2 * QEMU PS/2 keyboard/mouse emulation
4 * Copyright (c) 2003 Fabrice Bellard
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28 /* debug PC keyboard */
31 /* debug PC keyboard : only mouse */
34 /* Keyboard Commands */
35 #define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */
36 #define KBD_CMD_ECHO 0xEE
37 #define KBD_CMD_GET_ID 0xF2 /* get keyboard ID */
38 #define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */
39 #define KBD_CMD_ENABLE 0xF4 /* Enable scanning */
40 #define KBD_CMD_RESET_DISABLE 0xF5 /* reset and disable scanning */
41 #define KBD_CMD_RESET_ENABLE 0xF6 /* reset and enable scanning */
42 #define KBD_CMD_RESET 0xFF /* Reset */
44 /* Keyboard Replies */
45 #define KBD_REPLY_POR 0xAA /* Power on reset */
46 #define KBD_REPLY_ACK 0xFA /* Command ACK */
47 #define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */
50 #define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */
51 #define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */
52 #define AUX_SET_RES 0xE8 /* Set resolution */
53 #define AUX_GET_SCALE 0xE9 /* Get scaling factor */
54 #define AUX_SET_STREAM 0xEA /* Set stream mode */
55 #define AUX_POLL 0xEB /* Poll */
56 #define AUX_RESET_WRAP 0xEC /* Reset wrap mode */
57 #define AUX_SET_WRAP 0xEE /* Set wrap mode */
58 #define AUX_SET_REMOTE 0xF0 /* Set remote mode */
59 #define AUX_GET_TYPE 0xF2 /* Get type */
60 #define AUX_SET_SAMPLE 0xF3 /* Set sample rate */
61 #define AUX_ENABLE_DEV 0xF4 /* Enable aux device */
62 #define AUX_DISABLE_DEV 0xF5 /* Disable aux device */
63 #define AUX_SET_DEFAULT 0xF6
64 #define AUX_RESET 0xFF /* Reset aux device */
65 #define AUX_ACK 0xFA /* Command byte ACK. */
67 #define MOUSE_STATUS_REMOTE 0x40
68 #define MOUSE_STATUS_ENABLED 0x20
69 #define MOUSE_STATUS_SCALE21 0x10
71 #define PS2_QUEUE_SIZE 256
74 uint8_t data
[PS2_QUEUE_SIZE
];
75 int rptr
, wptr
, count
;
81 void (*update_irq
)(void *, int);
88 /* Qemu uses translated PC scancodes internally. To avoid multiple
89 conversions we do the translation (if any) in the PS/2 emulation
90 not the keyboard controller. */
97 uint8_t mouse_resolution
;
98 uint8_t mouse_sample_rate
;
100 uint8_t mouse_type
; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */
101 uint8_t mouse_detect_state
;
102 int mouse_dx
; /* current values, needed for 'poll' mode */
105 uint8_t mouse_buttons
;
108 /* Table to convert from PC scancodes to raw scancodes. */
109 static const unsigned char ps2_raw_keycode
[128] = {
110 0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
111 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
112 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
113 50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88, 5, 6, 4, 12, 3,
114 11, 2, 10, 1, 9,119,126,108,117,125,123,107,115,116,121,105,
115 114,122,112,113,127, 96, 97,120, 7, 15, 23, 31, 39, 47, 55, 63,
116 71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
117 19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
120 void ps2_queue(void *opaque
, int b
)
122 PS2State
*s
= (PS2State
*)opaque
;
123 PS2Queue
*q
= &s
->queue
;
125 if (q
->count
>= PS2_QUEUE_SIZE
)
127 q
->data
[q
->wptr
] = b
;
128 if (++q
->wptr
== PS2_QUEUE_SIZE
)
131 s
->update_irq(s
->update_arg
, 1);
134 static void ps2_put_keycode(void *opaque
, int keycode
)
136 PS2KbdState
*s
= opaque
;
137 if (!s
->translate
&& keycode
< 0xe0)
140 ps2_queue(&s
->common
, 0xf0);
141 keycode
= ps2_raw_keycode
[keycode
& 0x7f];
143 ps2_queue(&s
->common
, keycode
);
146 uint32_t ps2_read_data(void *opaque
)
148 PS2State
*s
= (PS2State
*)opaque
;
154 /* NOTE: if no data left, we return the last keyboard one
155 (needed for EMM386) */
156 /* XXX: need a timer to do things correctly */
159 index
= PS2_QUEUE_SIZE
- 1;
160 val
= q
->data
[index
];
162 val
= q
->data
[q
->rptr
];
163 if (++q
->rptr
== PS2_QUEUE_SIZE
)
166 /* reading deasserts IRQ */
167 s
->update_irq(s
->update_arg
, 0);
168 /* reassert IRQs if data left */
169 s
->update_irq(s
->update_arg
, q
->count
!= 0);
174 static void ps2_reset_keyboard(PS2KbdState
*s
)
179 void ps2_write_keyboard(void *opaque
, int val
)
181 PS2KbdState
*s
= (PS2KbdState
*)opaque
;
183 switch(s
->common
.write_cmd
) {
188 ps2_queue(&s
->common
, KBD_REPLY_ACK
);
191 ps2_queue(&s
->common
, KBD_REPLY_RESEND
);
194 ps2_queue(&s
->common
, KBD_REPLY_ACK
);
195 ps2_queue(&s
->common
, 0xab);
196 ps2_queue(&s
->common
, 0x83);
199 ps2_queue(&s
->common
, KBD_CMD_ECHO
);
203 ps2_queue(&s
->common
, KBD_REPLY_ACK
);
205 case KBD_CMD_SET_LEDS
:
206 case KBD_CMD_SET_RATE
:
207 s
->common
.write_cmd
= val
;
208 ps2_queue(&s
->common
, KBD_REPLY_ACK
);
210 case KBD_CMD_RESET_DISABLE
:
211 ps2_reset_keyboard(s
);
213 ps2_queue(&s
->common
, KBD_REPLY_ACK
);
215 case KBD_CMD_RESET_ENABLE
:
216 ps2_reset_keyboard(s
);
218 ps2_queue(&s
->common
, KBD_REPLY_ACK
);
221 ps2_reset_keyboard(s
);
222 ps2_queue(&s
->common
, KBD_REPLY_ACK
);
223 ps2_queue(&s
->common
, KBD_REPLY_POR
);
226 ps2_queue(&s
->common
, KBD_REPLY_ACK
);
230 case KBD_CMD_SET_LEDS
:
231 ps2_queue(&s
->common
, KBD_REPLY_ACK
);
232 s
->common
.write_cmd
= -1;
234 case KBD_CMD_SET_RATE
:
235 ps2_queue(&s
->common
, KBD_REPLY_ACK
);
236 s
->common
.write_cmd
= -1;
241 /* Set the scancode translation mode.
243 1 = translated scancodes (used by qemu internally). */
245 void ps2_keyboard_set_translation(void *opaque
, int mode
)
247 PS2KbdState
*s
= (PS2KbdState
*)opaque
;
251 static void ps2_mouse_send_packet(PS2MouseState
*s
)
259 /* XXX: increase range to 8 bits ? */
268 b
= 0x08 | ((dx1
< 0) << 4) | ((dy1
< 0) << 5) | (s
->mouse_buttons
& 0x07);
269 ps2_queue(&s
->common
, b
);
270 ps2_queue(&s
->common
, dx1
& 0xff);
271 ps2_queue(&s
->common
, dy1
& 0xff);
272 /* extra byte for IMPS/2 or IMEX */
273 switch(s
->mouse_type
) {
281 ps2_queue(&s
->common
, dz1
& 0xff);
288 b
= (dz1
& 0x0f) | ((s
->mouse_buttons
& 0x18) << 1);
289 ps2_queue(&s
->common
, b
);
299 static void ps2_mouse_event(void *opaque
,
300 int dx
, int dy
, int dz
, int buttons_state
)
302 PS2MouseState
*s
= opaque
;
304 /* check if deltas are recorded when disabled */
305 if (!(s
->mouse_status
& MOUSE_STATUS_ENABLED
))
311 /* XXX: SDL sometimes generates nul events: we delete them */
312 if (s
->mouse_dx
== 0 && s
->mouse_dy
== 0 && s
->mouse_dz
== 0 &&
313 s
->mouse_buttons
== buttons_state
)
315 s
->mouse_buttons
= buttons_state
;
317 if (!(s
->mouse_status
& MOUSE_STATUS_REMOTE
) &&
318 (s
->common
.queue
.count
< (PS2_QUEUE_SIZE
- 16))) {
320 /* if not remote, send event. Multiple events are sent if
322 ps2_mouse_send_packet(s
);
323 if (s
->mouse_dx
== 0 && s
->mouse_dy
== 0 && s
->mouse_dz
== 0)
329 void ps2_mouse_fake_event(void *opaque
)
331 ps2_mouse_event(opaque
, 1, 0, 0, 0);
334 void ps2_write_mouse(void *opaque
, int val
)
336 PS2MouseState
*s
= (PS2MouseState
*)opaque
;
338 printf("kbd: write mouse 0x%02x\n", val
);
340 switch(s
->common
.write_cmd
) {
345 if (val
== AUX_RESET_WRAP
) {
347 ps2_queue(&s
->common
, AUX_ACK
);
349 } else if (val
!= AUX_RESET
) {
350 ps2_queue(&s
->common
, val
);
355 case AUX_SET_SCALE11
:
356 s
->mouse_status
&= ~MOUSE_STATUS_SCALE21
;
357 ps2_queue(&s
->common
, AUX_ACK
);
359 case AUX_SET_SCALE21
:
360 s
->mouse_status
|= MOUSE_STATUS_SCALE21
;
361 ps2_queue(&s
->common
, AUX_ACK
);
364 s
->mouse_status
&= ~MOUSE_STATUS_REMOTE
;
365 ps2_queue(&s
->common
, AUX_ACK
);
369 ps2_queue(&s
->common
, AUX_ACK
);
372 s
->mouse_status
|= MOUSE_STATUS_REMOTE
;
373 ps2_queue(&s
->common
, AUX_ACK
);
376 ps2_queue(&s
->common
, AUX_ACK
);
377 ps2_queue(&s
->common
, s
->mouse_type
);
381 s
->common
.write_cmd
= val
;
382 ps2_queue(&s
->common
, AUX_ACK
);
385 ps2_queue(&s
->common
, AUX_ACK
);
386 ps2_queue(&s
->common
, s
->mouse_status
);
387 ps2_queue(&s
->common
, s
->mouse_resolution
);
388 ps2_queue(&s
->common
, s
->mouse_sample_rate
);
391 ps2_queue(&s
->common
, AUX_ACK
);
392 ps2_mouse_send_packet(s
);
395 s
->mouse_status
|= MOUSE_STATUS_ENABLED
;
396 ps2_queue(&s
->common
, AUX_ACK
);
398 case AUX_DISABLE_DEV
:
399 s
->mouse_status
&= ~MOUSE_STATUS_ENABLED
;
400 ps2_queue(&s
->common
, AUX_ACK
);
402 case AUX_SET_DEFAULT
:
403 s
->mouse_sample_rate
= 100;
404 s
->mouse_resolution
= 2;
406 ps2_queue(&s
->common
, AUX_ACK
);
409 s
->mouse_sample_rate
= 100;
410 s
->mouse_resolution
= 2;
413 ps2_queue(&s
->common
, AUX_ACK
);
414 ps2_queue(&s
->common
, 0xaa);
415 ps2_queue(&s
->common
, s
->mouse_type
);
422 s
->mouse_sample_rate
= val
;
423 /* detect IMPS/2 or IMEX */
424 switch(s
->mouse_detect_state
) {
428 s
->mouse_detect_state
= 1;
432 s
->mouse_detect_state
= 2;
434 s
->mouse_detect_state
= 3;
436 s
->mouse_detect_state
= 0;
440 s
->mouse_type
= 3; /* IMPS/2 */
441 s
->mouse_detect_state
= 0;
445 s
->mouse_type
= 4; /* IMEX */
446 s
->mouse_detect_state
= 0;
449 ps2_queue(&s
->common
, AUX_ACK
);
450 s
->common
.write_cmd
= -1;
453 s
->mouse_resolution
= val
;
454 ps2_queue(&s
->common
, AUX_ACK
);
455 s
->common
.write_cmd
= -1;
460 static void ps2_reset(void *opaque
)
462 PS2State
*s
= (PS2State
*)opaque
;
471 static void ps2_common_save (QEMUFile
*f
, PS2State
*s
)
473 qemu_put_be32s (f
, &s
->write_cmd
);
474 qemu_put_be32s (f
, &s
->queue
.rptr
);
475 qemu_put_be32s (f
, &s
->queue
.wptr
);
476 qemu_put_be32s (f
, &s
->queue
.count
);
477 qemu_put_buffer (f
, s
->queue
.data
, sizeof (s
->queue
.data
));
480 static void ps2_common_load (QEMUFile
*f
, PS2State
*s
)
482 qemu_get_be32s (f
, &s
->write_cmd
);
483 qemu_get_be32s (f
, &s
->queue
.rptr
);
484 qemu_get_be32s (f
, &s
->queue
.wptr
);
485 qemu_get_be32s (f
, &s
->queue
.count
);
486 qemu_get_buffer (f
, s
->queue
.data
, sizeof (s
->queue
.data
));
489 static void ps2_kbd_save(QEMUFile
* f
, void* opaque
)
491 PS2KbdState
*s
= (PS2KbdState
*)opaque
;
493 ps2_common_save (f
, &s
->common
);
494 qemu_put_be32s(f
, &s
->scan_enabled
);
495 qemu_put_be32s(f
, &s
->translate
);
498 static void ps2_mouse_save(QEMUFile
* f
, void* opaque
)
500 PS2MouseState
*s
= (PS2MouseState
*)opaque
;
502 ps2_common_save (f
, &s
->common
);
503 qemu_put_8s(f
, &s
->mouse_status
);
504 qemu_put_8s(f
, &s
->mouse_resolution
);
505 qemu_put_8s(f
, &s
->mouse_sample_rate
);
506 qemu_put_8s(f
, &s
->mouse_wrap
);
507 qemu_put_8s(f
, &s
->mouse_type
);
508 qemu_put_8s(f
, &s
->mouse_detect_state
);
509 qemu_put_be32s(f
, &s
->mouse_dx
);
510 qemu_put_be32s(f
, &s
->mouse_dy
);
511 qemu_put_be32s(f
, &s
->mouse_dz
);
512 qemu_put_8s(f
, &s
->mouse_buttons
);
515 static int ps2_kbd_load(QEMUFile
* f
, void* opaque
, int version_id
)
517 PS2KbdState
*s
= (PS2KbdState
*)opaque
;
522 ps2_common_load (f
, &s
->common
);
523 qemu_get_be32s(f
, &s
->scan_enabled
);
524 qemu_get_be32s(f
, &s
->translate
);
528 static int ps2_mouse_load(QEMUFile
* f
, void* opaque
, int version_id
)
530 PS2MouseState
*s
= (PS2MouseState
*)opaque
;
535 ps2_common_load (f
, &s
->common
);
536 qemu_get_8s(f
, &s
->mouse_status
);
537 qemu_get_8s(f
, &s
->mouse_resolution
);
538 qemu_get_8s(f
, &s
->mouse_sample_rate
);
539 qemu_get_8s(f
, &s
->mouse_wrap
);
540 qemu_get_8s(f
, &s
->mouse_type
);
541 qemu_get_8s(f
, &s
->mouse_detect_state
);
542 qemu_get_be32s(f
, &s
->mouse_dx
);
543 qemu_get_be32s(f
, &s
->mouse_dy
);
544 qemu_get_be32s(f
, &s
->mouse_dz
);
545 qemu_get_8s(f
, &s
->mouse_buttons
);
549 void *ps2_kbd_init(void (*update_irq
)(void *, int), void *update_arg
)
551 PS2KbdState
*s
= (PS2KbdState
*)qemu_mallocz(sizeof(PS2KbdState
));
553 s
->common
.update_irq
= update_irq
;
554 s
->common
.update_arg
= update_arg
;
555 ps2_reset(&s
->common
);
556 register_savevm("ps2kbd", 0, 2, ps2_kbd_save
, ps2_kbd_load
, s
);
557 qemu_add_kbd_event_handler(ps2_put_keycode
, s
);
558 qemu_register_reset(ps2_reset
, &s
->common
);
562 void *ps2_mouse_init(void (*update_irq
)(void *, int), void *update_arg
)
564 PS2MouseState
*s
= (PS2MouseState
*)qemu_mallocz(sizeof(PS2MouseState
));
566 s
->common
.update_irq
= update_irq
;
567 s
->common
.update_arg
= update_arg
;
568 ps2_reset(&s
->common
);
569 register_savevm("ps2mouse", 0, 2, ps2_mouse_save
, ps2_mouse_load
, s
);
570 qemu_add_mouse_event_handler(ps2_mouse_event
, s
, 0, "QEMU PS/2 Mouse");
571 qemu_register_reset(ps2_reset
, &s
->common
);