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
24 #include "qemu/osdep.h"
26 #include "hw/input/ps2.h"
27 #include "ui/console.h"
29 #include "sysemu/sysemu.h"
33 /* debug PC keyboard */
36 /* debug PC keyboard : only mouse */
39 /* Keyboard Commands */
40 #define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */
41 #define KBD_CMD_ECHO 0xEE
42 #define KBD_CMD_SCANCODE 0xF0 /* Get/set scancode set */
43 #define KBD_CMD_GET_ID 0xF2 /* get keyboard ID */
44 #define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */
45 #define KBD_CMD_ENABLE 0xF4 /* Enable scanning */
46 #define KBD_CMD_RESET_DISABLE 0xF5 /* reset and disable scanning */
47 #define KBD_CMD_RESET_ENABLE 0xF6 /* reset and enable scanning */
48 #define KBD_CMD_RESET 0xFF /* Reset */
50 /* Keyboard Replies */
51 #define KBD_REPLY_POR 0xAA /* Power on reset */
52 #define KBD_REPLY_ID 0xAB /* Keyboard ID */
53 #define KBD_REPLY_ACK 0xFA /* Command ACK */
54 #define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */
57 #define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */
58 #define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */
59 #define AUX_SET_RES 0xE8 /* Set resolution */
60 #define AUX_GET_SCALE 0xE9 /* Get scaling factor */
61 #define AUX_SET_STREAM 0xEA /* Set stream mode */
62 #define AUX_POLL 0xEB /* Poll */
63 #define AUX_RESET_WRAP 0xEC /* Reset wrap mode */
64 #define AUX_SET_WRAP 0xEE /* Set wrap mode */
65 #define AUX_SET_REMOTE 0xF0 /* Set remote mode */
66 #define AUX_GET_TYPE 0xF2 /* Get type */
67 #define AUX_SET_SAMPLE 0xF3 /* Set sample rate */
68 #define AUX_ENABLE_DEV 0xF4 /* Enable aux device */
69 #define AUX_DISABLE_DEV 0xF5 /* Disable aux device */
70 #define AUX_SET_DEFAULT 0xF6
71 #define AUX_RESET 0xFF /* Reset aux device */
72 #define AUX_ACK 0xFA /* Command byte ACK. */
74 #define MOUSE_STATUS_REMOTE 0x40
75 #define MOUSE_STATUS_ENABLED 0x20
76 #define MOUSE_STATUS_SCALE21 0x10
78 #define PS2_QUEUE_SIZE 16 /* Buffer size required by PS/2 protocol */
81 /* Keep the data array 256 bytes long, which compatibility
82 with older qemu versions. */
84 int rptr
, wptr
, count
;
90 void (*update_irq
)(void *, int);
97 /* QEMU uses translated PC scancodes internally. To avoid multiple
98 conversions we do the translation (if any) in the PS/2 emulation
99 not the keyboard controller. */
101 int scancode_set
; /* 1=XT, 2=AT, 3=PS/2 */
107 uint8_t mouse_status
;
108 uint8_t mouse_resolution
;
109 uint8_t mouse_sample_rate
;
111 uint8_t mouse_type
; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */
112 uint8_t mouse_detect_state
;
113 int mouse_dx
; /* current values, needed for 'poll' mode */
116 uint8_t mouse_buttons
;
119 /* Table to convert from PC scancodes to raw scancodes. */
120 static const unsigned char ps2_raw_keycode
[128] = {
121 0, 118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85, 102, 13,
122 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
123 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
124 50, 49, 58, 65, 73, 74, 89, 124, 17, 41, 88, 5, 6, 4, 12, 3,
125 11, 2, 10, 1, 9, 119, 126, 108, 117, 125, 123, 107, 115, 116, 121, 105,
126 114, 122, 112, 113, 127, 96, 97, 120, 7, 15, 23, 31, 39, 47, 55, 63,
127 71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87, 111,
128 19, 25, 57, 81, 83, 92, 95, 98, 99, 100, 101, 103, 104, 106, 109, 110
130 static const unsigned char ps2_raw_keycode_set3
[128] = {
131 0, 8, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85, 102, 13,
132 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 17, 28, 27,
133 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 92, 26, 34, 33, 42,
134 50, 49, 58, 65, 73, 74, 89, 126, 25, 41, 20, 7, 15, 23, 31, 39,
135 47, 2, 63, 71, 79, 118, 95, 108, 117, 125, 132, 107, 115, 116, 124, 105,
136 114, 122, 112, 113, 127, 96, 97, 86, 94, 15, 23, 31, 39, 47, 55, 63,
137 71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87, 111,
138 19, 25, 57, 81, 83, 92, 95, 98, 99, 100, 101, 103, 104, 106, 109, 110
141 void ps2_queue(void *opaque
, int b
)
143 PS2State
*s
= (PS2State
*)opaque
;
144 PS2Queue
*q
= &s
->queue
;
146 if (q
->count
>= PS2_QUEUE_SIZE
- 1)
148 q
->data
[q
->wptr
] = b
;
149 if (++q
->wptr
== PS2_QUEUE_SIZE
)
152 s
->update_irq(s
->update_arg
, 1);
156 keycode is expressed as follow:
157 bit 7 - 0 key pressed, 1 = key released
158 bits 6-0 - translated scancode set 2
160 static void ps2_put_keycode(void *opaque
, int keycode
)
162 PS2KbdState
*s
= opaque
;
164 trace_ps2_put_keycode(opaque
, keycode
);
165 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER
);
166 /* XXX: add support for scancode set 1 */
167 if (!s
->translate
&& keycode
< 0xe0 && s
->scancode_set
> 1) {
168 if (keycode
& 0x80) {
169 ps2_queue(&s
->common
, 0xf0);
171 if (s
->scancode_set
== 2) {
172 keycode
= ps2_raw_keycode
[keycode
& 0x7f];
173 } else if (s
->scancode_set
== 3) {
174 keycode
= ps2_raw_keycode_set3
[keycode
& 0x7f];
177 ps2_queue(&s
->common
, keycode
);
180 static void ps2_keyboard_event(DeviceState
*dev
, QemuConsole
*src
,
183 PS2KbdState
*s
= (PS2KbdState
*)dev
;
184 int scancodes
[3], i
, count
;
185 InputKeyEvent
*key
= evt
->u
.key
.data
;
187 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER
);
188 count
= qemu_input_key_value_to_scancode(key
->key
,
191 for (i
= 0; i
< count
; i
++) {
192 ps2_put_keycode(s
, scancodes
[i
]);
196 uint32_t ps2_read_data(void *opaque
)
198 PS2State
*s
= (PS2State
*)opaque
;
202 trace_ps2_read_data(opaque
);
205 /* NOTE: if no data left, we return the last keyboard one
206 (needed for EMM386) */
207 /* XXX: need a timer to do things correctly */
210 index
= PS2_QUEUE_SIZE
- 1;
211 val
= q
->data
[index
];
213 val
= q
->data
[q
->rptr
];
214 if (++q
->rptr
== PS2_QUEUE_SIZE
)
217 /* reading deasserts IRQ */
218 s
->update_irq(s
->update_arg
, 0);
219 /* reassert IRQs if data left */
220 s
->update_irq(s
->update_arg
, q
->count
!= 0);
225 static void ps2_set_ledstate(PS2KbdState
*s
, int ledstate
)
227 trace_ps2_set_ledstate(s
, ledstate
);
228 s
->ledstate
= ledstate
;
229 kbd_put_ledstate(ledstate
);
232 static void ps2_reset_keyboard(PS2KbdState
*s
)
234 trace_ps2_reset_keyboard(s
);
237 ps2_set_ledstate(s
, 0);
240 void ps2_write_keyboard(void *opaque
, int val
)
242 PS2KbdState
*s
= (PS2KbdState
*)opaque
;
244 trace_ps2_write_keyboard(opaque
, val
);
245 switch(s
->common
.write_cmd
) {
250 ps2_queue(&s
->common
, KBD_REPLY_ACK
);
253 ps2_queue(&s
->common
, KBD_REPLY_RESEND
);
256 ps2_queue(&s
->common
, KBD_REPLY_ACK
);
257 /* We emulate a MF2 AT keyboard here */
258 ps2_queue(&s
->common
, KBD_REPLY_ID
);
260 ps2_queue(&s
->common
, 0x41);
262 ps2_queue(&s
->common
, 0x83);
265 ps2_queue(&s
->common
, KBD_CMD_ECHO
);
269 ps2_queue(&s
->common
, KBD_REPLY_ACK
);
271 case KBD_CMD_SCANCODE
:
272 case KBD_CMD_SET_LEDS
:
273 case KBD_CMD_SET_RATE
:
274 s
->common
.write_cmd
= val
;
275 ps2_queue(&s
->common
, KBD_REPLY_ACK
);
277 case KBD_CMD_RESET_DISABLE
:
278 ps2_reset_keyboard(s
);
280 ps2_queue(&s
->common
, KBD_REPLY_ACK
);
282 case KBD_CMD_RESET_ENABLE
:
283 ps2_reset_keyboard(s
);
285 ps2_queue(&s
->common
, KBD_REPLY_ACK
);
288 ps2_reset_keyboard(s
);
289 ps2_queue(&s
->common
, KBD_REPLY_ACK
);
290 ps2_queue(&s
->common
, KBD_REPLY_POR
);
293 ps2_queue(&s
->common
, KBD_REPLY_ACK
);
297 case KBD_CMD_SCANCODE
:
299 if (s
->scancode_set
== 1)
300 ps2_put_keycode(s
, 0x43);
301 else if (s
->scancode_set
== 2)
302 ps2_put_keycode(s
, 0x41);
303 else if (s
->scancode_set
== 3)
304 ps2_put_keycode(s
, 0x3f);
306 if (val
>= 1 && val
<= 3)
307 s
->scancode_set
= val
;
308 ps2_queue(&s
->common
, KBD_REPLY_ACK
);
310 s
->common
.write_cmd
= -1;
312 case KBD_CMD_SET_LEDS
:
313 ps2_set_ledstate(s
, val
);
314 ps2_queue(&s
->common
, KBD_REPLY_ACK
);
315 s
->common
.write_cmd
= -1;
317 case KBD_CMD_SET_RATE
:
318 ps2_queue(&s
->common
, KBD_REPLY_ACK
);
319 s
->common
.write_cmd
= -1;
324 /* Set the scancode translation mode.
326 1 = translated scancodes (used by qemu internally). */
328 void ps2_keyboard_set_translation(void *opaque
, int mode
)
330 PS2KbdState
*s
= (PS2KbdState
*)opaque
;
331 trace_ps2_keyboard_set_translation(opaque
, mode
);
335 static void ps2_mouse_send_packet(PS2MouseState
*s
)
343 /* XXX: increase range to 8 bits ? */
352 b
= 0x08 | ((dx1
< 0) << 4) | ((dy1
< 0) << 5) | (s
->mouse_buttons
& 0x07);
353 ps2_queue(&s
->common
, b
);
354 ps2_queue(&s
->common
, dx1
& 0xff);
355 ps2_queue(&s
->common
, dy1
& 0xff);
356 /* extra byte for IMPS/2 or IMEX */
357 switch(s
->mouse_type
) {
365 ps2_queue(&s
->common
, dz1
& 0xff);
372 b
= (dz1
& 0x0f) | ((s
->mouse_buttons
& 0x18) << 1);
373 ps2_queue(&s
->common
, b
);
377 trace_ps2_mouse_send_packet(s
, dx1
, dy1
, dz1
, b
);
384 static void ps2_mouse_event(DeviceState
*dev
, QemuConsole
*src
,
387 static const int bmap
[INPUT_BUTTON__MAX
] = {
388 [INPUT_BUTTON_LEFT
] = MOUSE_EVENT_LBUTTON
,
389 [INPUT_BUTTON_MIDDLE
] = MOUSE_EVENT_MBUTTON
,
390 [INPUT_BUTTON_RIGHT
] = MOUSE_EVENT_RBUTTON
,
392 PS2MouseState
*s
= (PS2MouseState
*)dev
;
393 InputMoveEvent
*move
;
396 /* check if deltas are recorded when disabled */
397 if (!(s
->mouse_status
& MOUSE_STATUS_ENABLED
))
401 case INPUT_EVENT_KIND_REL
:
402 move
= evt
->u
.rel
.data
;
403 if (move
->axis
== INPUT_AXIS_X
) {
404 s
->mouse_dx
+= move
->value
;
405 } else if (move
->axis
== INPUT_AXIS_Y
) {
406 s
->mouse_dy
-= move
->value
;
410 case INPUT_EVENT_KIND_BTN
:
411 btn
= evt
->u
.btn
.data
;
413 s
->mouse_buttons
|= bmap
[btn
->button
];
414 if (btn
->button
== INPUT_BUTTON_WHEEL_UP
) {
416 } else if (btn
->button
== INPUT_BUTTON_WHEEL_DOWN
) {
420 s
->mouse_buttons
&= ~bmap
[btn
->button
];
430 static void ps2_mouse_sync(DeviceState
*dev
)
432 PS2MouseState
*s
= (PS2MouseState
*)dev
;
434 if (s
->mouse_buttons
) {
435 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER
);
437 if (!(s
->mouse_status
& MOUSE_STATUS_REMOTE
)) {
438 while (s
->common
.queue
.count
< PS2_QUEUE_SIZE
- 4) {
439 /* if not remote, send event. Multiple events are sent if
441 ps2_mouse_send_packet(s
);
442 if (s
->mouse_dx
== 0 && s
->mouse_dy
== 0 && s
->mouse_dz
== 0)
448 void ps2_mouse_fake_event(void *opaque
)
450 PS2MouseState
*s
= opaque
;
451 trace_ps2_mouse_fake_event(opaque
);
453 ps2_mouse_sync(opaque
);
456 void ps2_write_mouse(void *opaque
, int val
)
458 PS2MouseState
*s
= (PS2MouseState
*)opaque
;
460 trace_ps2_write_mouse(opaque
, val
);
462 printf("kbd: write mouse 0x%02x\n", val
);
464 switch(s
->common
.write_cmd
) {
469 if (val
== AUX_RESET_WRAP
) {
471 ps2_queue(&s
->common
, AUX_ACK
);
473 } else if (val
!= AUX_RESET
) {
474 ps2_queue(&s
->common
, val
);
479 case AUX_SET_SCALE11
:
480 s
->mouse_status
&= ~MOUSE_STATUS_SCALE21
;
481 ps2_queue(&s
->common
, AUX_ACK
);
483 case AUX_SET_SCALE21
:
484 s
->mouse_status
|= MOUSE_STATUS_SCALE21
;
485 ps2_queue(&s
->common
, AUX_ACK
);
488 s
->mouse_status
&= ~MOUSE_STATUS_REMOTE
;
489 ps2_queue(&s
->common
, AUX_ACK
);
493 ps2_queue(&s
->common
, AUX_ACK
);
496 s
->mouse_status
|= MOUSE_STATUS_REMOTE
;
497 ps2_queue(&s
->common
, AUX_ACK
);
500 ps2_queue(&s
->common
, AUX_ACK
);
501 ps2_queue(&s
->common
, s
->mouse_type
);
505 s
->common
.write_cmd
= val
;
506 ps2_queue(&s
->common
, AUX_ACK
);
509 ps2_queue(&s
->common
, AUX_ACK
);
510 ps2_queue(&s
->common
, s
->mouse_status
);
511 ps2_queue(&s
->common
, s
->mouse_resolution
);
512 ps2_queue(&s
->common
, s
->mouse_sample_rate
);
515 ps2_queue(&s
->common
, AUX_ACK
);
516 ps2_mouse_send_packet(s
);
519 s
->mouse_status
|= MOUSE_STATUS_ENABLED
;
520 ps2_queue(&s
->common
, AUX_ACK
);
522 case AUX_DISABLE_DEV
:
523 s
->mouse_status
&= ~MOUSE_STATUS_ENABLED
;
524 ps2_queue(&s
->common
, AUX_ACK
);
526 case AUX_SET_DEFAULT
:
527 s
->mouse_sample_rate
= 100;
528 s
->mouse_resolution
= 2;
530 ps2_queue(&s
->common
, AUX_ACK
);
533 s
->mouse_sample_rate
= 100;
534 s
->mouse_resolution
= 2;
537 ps2_queue(&s
->common
, AUX_ACK
);
538 ps2_queue(&s
->common
, 0xaa);
539 ps2_queue(&s
->common
, s
->mouse_type
);
546 s
->mouse_sample_rate
= val
;
547 /* detect IMPS/2 or IMEX */
548 switch(s
->mouse_detect_state
) {
552 s
->mouse_detect_state
= 1;
556 s
->mouse_detect_state
= 2;
558 s
->mouse_detect_state
= 3;
560 s
->mouse_detect_state
= 0;
564 s
->mouse_type
= 3; /* IMPS/2 */
565 s
->mouse_detect_state
= 0;
569 s
->mouse_type
= 4; /* IMEX */
570 s
->mouse_detect_state
= 0;
573 ps2_queue(&s
->common
, AUX_ACK
);
574 s
->common
.write_cmd
= -1;
577 s
->mouse_resolution
= val
;
578 ps2_queue(&s
->common
, AUX_ACK
);
579 s
->common
.write_cmd
= -1;
584 static void ps2_common_reset(PS2State
*s
)
592 s
->update_irq(s
->update_arg
, 0);
595 static void ps2_common_post_load(PS2State
*s
)
597 PS2Queue
*q
= &s
->queue
;
600 int tmp_data
[PS2_QUEUE_SIZE
];
602 /* set the useful data buffer queue size, < PS2_QUEUE_SIZE */
603 size
= q
->count
> PS2_QUEUE_SIZE
? 0 : q
->count
;
605 /* move the queue elements to the start of data array */
607 for (i
= 0; i
< size
; i
++) {
608 /* move the queue elements to the temporary buffer */
609 tmp_data
[i
] = q
->data
[q
->rptr
];
610 if (++q
->rptr
== 256) {
614 memcpy(q
->data
, tmp_data
, size
);
616 /* reset rptr/wptr/count */
620 s
->update_irq(s
->update_arg
, q
->count
!= 0);
623 static void ps2_kbd_reset(void *opaque
)
625 PS2KbdState
*s
= (PS2KbdState
*) opaque
;
627 trace_ps2_kbd_reset(opaque
);
628 ps2_common_reset(&s
->common
);
634 static void ps2_mouse_reset(void *opaque
)
636 PS2MouseState
*s
= (PS2MouseState
*) opaque
;
638 trace_ps2_mouse_reset(opaque
);
639 ps2_common_reset(&s
->common
);
641 s
->mouse_resolution
= 0;
642 s
->mouse_sample_rate
= 0;
645 s
->mouse_detect_state
= 0;
649 s
->mouse_buttons
= 0;
652 static const VMStateDescription vmstate_ps2_common
= {
653 .name
= "PS2 Common State",
655 .minimum_version_id
= 2,
656 .fields
= (VMStateField
[]) {
657 VMSTATE_INT32(write_cmd
, PS2State
),
658 VMSTATE_INT32(queue
.rptr
, PS2State
),
659 VMSTATE_INT32(queue
.wptr
, PS2State
),
660 VMSTATE_INT32(queue
.count
, PS2State
),
661 VMSTATE_BUFFER(queue
.data
, PS2State
),
662 VMSTATE_END_OF_LIST()
666 static bool ps2_keyboard_ledstate_needed(void *opaque
)
668 PS2KbdState
*s
= opaque
;
670 return s
->ledstate
!= 0; /* 0 is default state */
673 static int ps2_kbd_ledstate_post_load(void *opaque
, int version_id
)
675 PS2KbdState
*s
= opaque
;
677 kbd_put_ledstate(s
->ledstate
);
681 static const VMStateDescription vmstate_ps2_keyboard_ledstate
= {
682 .name
= "ps2kbd/ledstate",
684 .minimum_version_id
= 2,
685 .post_load
= ps2_kbd_ledstate_post_load
,
686 .needed
= ps2_keyboard_ledstate_needed
,
687 .fields
= (VMStateField
[]) {
688 VMSTATE_INT32(ledstate
, PS2KbdState
),
689 VMSTATE_END_OF_LIST()
693 static int ps2_kbd_post_load(void* opaque
, int version_id
)
695 PS2KbdState
*s
= (PS2KbdState
*)opaque
;
696 PS2State
*ps2
= &s
->common
;
701 ps2_common_post_load(ps2
);
706 static void ps2_kbd_pre_save(void *opaque
)
708 PS2KbdState
*s
= (PS2KbdState
*)opaque
;
709 PS2State
*ps2
= &s
->common
;
711 ps2_common_post_load(ps2
);
714 static const VMStateDescription vmstate_ps2_keyboard
= {
717 .minimum_version_id
= 2,
718 .post_load
= ps2_kbd_post_load
,
719 .pre_save
= ps2_kbd_pre_save
,
720 .fields
= (VMStateField
[]) {
721 VMSTATE_STRUCT(common
, PS2KbdState
, 0, vmstate_ps2_common
, PS2State
),
722 VMSTATE_INT32(scan_enabled
, PS2KbdState
),
723 VMSTATE_INT32(translate
, PS2KbdState
),
724 VMSTATE_INT32_V(scancode_set
, PS2KbdState
,3),
725 VMSTATE_END_OF_LIST()
727 .subsections
= (const VMStateDescription
*[]) {
728 &vmstate_ps2_keyboard_ledstate
,
733 static int ps2_mouse_post_load(void *opaque
, int version_id
)
735 PS2MouseState
*s
= (PS2MouseState
*)opaque
;
736 PS2State
*ps2
= &s
->common
;
738 ps2_common_post_load(ps2
);
743 static void ps2_mouse_pre_save(void *opaque
)
745 PS2MouseState
*s
= (PS2MouseState
*)opaque
;
746 PS2State
*ps2
= &s
->common
;
748 ps2_common_post_load(ps2
);
751 static const VMStateDescription vmstate_ps2_mouse
= {
754 .minimum_version_id
= 2,
755 .post_load
= ps2_mouse_post_load
,
756 .pre_save
= ps2_mouse_pre_save
,
757 .fields
= (VMStateField
[]) {
758 VMSTATE_STRUCT(common
, PS2MouseState
, 0, vmstate_ps2_common
, PS2State
),
759 VMSTATE_UINT8(mouse_status
, PS2MouseState
),
760 VMSTATE_UINT8(mouse_resolution
, PS2MouseState
),
761 VMSTATE_UINT8(mouse_sample_rate
, PS2MouseState
),
762 VMSTATE_UINT8(mouse_wrap
, PS2MouseState
),
763 VMSTATE_UINT8(mouse_type
, PS2MouseState
),
764 VMSTATE_UINT8(mouse_detect_state
, PS2MouseState
),
765 VMSTATE_INT32(mouse_dx
, PS2MouseState
),
766 VMSTATE_INT32(mouse_dy
, PS2MouseState
),
767 VMSTATE_INT32(mouse_dz
, PS2MouseState
),
768 VMSTATE_UINT8(mouse_buttons
, PS2MouseState
),
769 VMSTATE_END_OF_LIST()
773 static QemuInputHandler ps2_keyboard_handler
= {
774 .name
= "QEMU PS/2 Keyboard",
775 .mask
= INPUT_EVENT_MASK_KEY
,
776 .event
= ps2_keyboard_event
,
779 void *ps2_kbd_init(void (*update_irq
)(void *, int), void *update_arg
)
781 PS2KbdState
*s
= (PS2KbdState
*)g_malloc0(sizeof(PS2KbdState
));
783 trace_ps2_kbd_init(s
);
784 s
->common
.update_irq
= update_irq
;
785 s
->common
.update_arg
= update_arg
;
787 vmstate_register(NULL
, 0, &vmstate_ps2_keyboard
, s
);
788 qemu_input_handler_register((DeviceState
*)s
,
789 &ps2_keyboard_handler
);
790 qemu_register_reset(ps2_kbd_reset
, s
);
794 static QemuInputHandler ps2_mouse_handler
= {
795 .name
= "QEMU PS/2 Mouse",
796 .mask
= INPUT_EVENT_MASK_BTN
| INPUT_EVENT_MASK_REL
,
797 .event
= ps2_mouse_event
,
798 .sync
= ps2_mouse_sync
,
801 void *ps2_mouse_init(void (*update_irq
)(void *, int), void *update_arg
)
803 PS2MouseState
*s
= (PS2MouseState
*)g_malloc0(sizeof(PS2MouseState
));
805 trace_ps2_mouse_init(s
);
806 s
->common
.update_irq
= update_irq
;
807 s
->common
.update_arg
= update_arg
;
808 vmstate_register(NULL
, 0, &vmstate_ps2_mouse
, s
);
809 qemu_input_handler_register((DeviceState
*)s
,
811 qemu_register_reset(ps2_mouse_reset
, s
);