]> git.proxmox.com Git - qemu.git/blame - hw/ps2.c
user: Restore debug usage message for '-d ?' in user mode emulation
[qemu.git] / hw / ps2.c
CommitLineData
0e43e99c
FB
1/*
2 * QEMU PS/2 keyboard/mouse emulation
5fafdf24 3 *
0e43e99c 4 * Copyright (c) 2003 Fabrice Bellard
5fafdf24 5 *
0e43e99c
FB
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:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
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
22 * THE SOFTWARE.
23 */
87ecb68b
PB
24#include "hw.h"
25#include "ps2.h"
26#include "console.h"
0e43e99c
FB
27
28/* debug PC keyboard */
29//#define DEBUG_KBD
30
31/* debug PC keyboard : only mouse */
32//#define DEBUG_MOUSE
33
34/* Keyboard Commands */
35#define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */
36#define KBD_CMD_ECHO 0xEE
e7d93956 37#define KBD_CMD_SCANCODE 0xF0 /* Get/set scancode set */
0e43e99c
FB
38#define KBD_CMD_GET_ID 0xF2 /* get keyboard ID */
39#define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */
40#define KBD_CMD_ENABLE 0xF4 /* Enable scanning */
41#define KBD_CMD_RESET_DISABLE 0xF5 /* reset and disable scanning */
42#define KBD_CMD_RESET_ENABLE 0xF6 /* reset and enable scanning */
43#define KBD_CMD_RESET 0xFF /* Reset */
44
45/* Keyboard Replies */
46#define KBD_REPLY_POR 0xAA /* Power on reset */
35c4d671 47#define KBD_REPLY_ID 0xAB /* Keyboard ID */
0e43e99c
FB
48#define KBD_REPLY_ACK 0xFA /* Command ACK */
49#define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */
50
51/* Mouse Commands */
52#define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */
53#define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */
54#define AUX_SET_RES 0xE8 /* Set resolution */
55#define AUX_GET_SCALE 0xE9 /* Get scaling factor */
56#define AUX_SET_STREAM 0xEA /* Set stream mode */
57#define AUX_POLL 0xEB /* Poll */
58#define AUX_RESET_WRAP 0xEC /* Reset wrap mode */
59#define AUX_SET_WRAP 0xEE /* Set wrap mode */
60#define AUX_SET_REMOTE 0xF0 /* Set remote mode */
61#define AUX_GET_TYPE 0xF2 /* Get type */
62#define AUX_SET_SAMPLE 0xF3 /* Set sample rate */
63#define AUX_ENABLE_DEV 0xF4 /* Enable aux device */
64#define AUX_DISABLE_DEV 0xF5 /* Disable aux device */
65#define AUX_SET_DEFAULT 0xF6
66#define AUX_RESET 0xFF /* Reset aux device */
67#define AUX_ACK 0xFA /* Command byte ACK. */
68
69#define MOUSE_STATUS_REMOTE 0x40
70#define MOUSE_STATUS_ENABLED 0x20
71#define MOUSE_STATUS_SCALE21 0x10
72
73#define PS2_QUEUE_SIZE 256
74
75typedef struct {
76 uint8_t data[PS2_QUEUE_SIZE];
77 int rptr, wptr, count;
78} PS2Queue;
79
80typedef struct {
81 PS2Queue queue;
82 int32_t write_cmd;
83 void (*update_irq)(void *, int);
84 void *update_arg;
85} PS2State;
86
87typedef struct {
88 PS2State common;
89 int scan_enabled;
f94f5d71
PB
90 /* Qemu uses translated PC scancodes internally. To avoid multiple
91 conversions we do the translation (if any) in the PS/2 emulation
92 not the keyboard controller. */
93 int translate;
e7d93956 94 int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */
0e43e99c
FB
95} PS2KbdState;
96
97typedef struct {
98 PS2State common;
99 uint8_t mouse_status;
100 uint8_t mouse_resolution;
101 uint8_t mouse_sample_rate;
102 uint8_t mouse_wrap;
103 uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */
104 uint8_t mouse_detect_state;
105 int mouse_dx; /* current values, needed for 'poll' mode */
106 int mouse_dy;
107 int mouse_dz;
108 uint8_t mouse_buttons;
109} PS2MouseState;
110
f94f5d71
PB
111/* Table to convert from PC scancodes to raw scancodes. */
112static const unsigned char ps2_raw_keycode[128] = {
7096a96d
RT
113 0, 118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85, 102, 13,
114 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
115 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
116 50, 49, 58, 65, 73, 74, 89, 124, 17, 41, 88, 5, 6, 4, 12, 3,
117 11, 2, 10, 1, 9, 119, 126, 108, 117, 125, 123, 107, 115, 116, 121, 105,
118114, 122, 112, 113, 127, 96, 97, 120, 7, 15, 23, 31, 39, 47, 55, 63,
119 71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87, 111,
120 19, 25, 57, 81, 83, 92, 95, 98, 99, 100, 101, 103, 104, 106, 109, 110
121};
122static const unsigned char ps2_raw_keycode_set3[128] = {
123 0, 8, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85, 102, 13,
124 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 17, 28, 27,
125 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 92, 26, 34, 33, 42,
126 50, 49, 58, 65, 73, 74, 89, 126, 25, 41, 20, 7, 15, 23, 31, 39,
127 47, 2, 63, 71, 79, 118, 95, 108, 117, 125, 132, 107, 115, 116, 124, 105,
128114, 122, 112, 113, 127, 96, 97, 86, 94, 15, 23, 31, 39, 47, 55, 63,
129 71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87, 111,
130 19, 25, 57, 81, 83, 92, 95, 98, 99, 100, 101, 103, 104, 106, 109, 110
f94f5d71
PB
131};
132
0e43e99c
FB
133void ps2_queue(void *opaque, int b)
134{
135 PS2State *s = (PS2State *)opaque;
136 PS2Queue *q = &s->queue;
137
138 if (q->count >= PS2_QUEUE_SIZE)
139 return;
140 q->data[q->wptr] = b;
141 if (++q->wptr == PS2_QUEUE_SIZE)
142 q->wptr = 0;
143 q->count++;
144 s->update_irq(s->update_arg, 1);
145}
146
35c4d671
AJ
147/*
148 keycode is expressed as follow:
149 bit 7 - 0 key pressed, 1 = key released
150 bits 6-0 - translated scancode set 2
151 */
0e43e99c
FB
152static void ps2_put_keycode(void *opaque, int keycode)
153{
f94f5d71 154 PS2KbdState *s = opaque;
e7d93956 155
7096a96d
RT
156 /* XXX: add support for scancode set 1 */
157 if (!s->translate && keycode < 0xe0 && s->scancode_set > 1) {
158 if (keycode & 0x80) {
f94f5d71 159 ps2_queue(&s->common, 0xf0);
7096a96d
RT
160 }
161 if (s->scancode_set == 2) {
162 keycode = ps2_raw_keycode[keycode & 0x7f];
163 } else if (s->scancode_set == 3) {
164 keycode = ps2_raw_keycode_set3[keycode & 0x7f];
165 }
f94f5d71 166 }
0e43e99c
FB
167 ps2_queue(&s->common, keycode);
168}
169
170uint32_t ps2_read_data(void *opaque)
171{
172 PS2State *s = (PS2State *)opaque;
173 PS2Queue *q;
174 int val, index;
3b46e624 175
0e43e99c
FB
176 q = &s->queue;
177 if (q->count == 0) {
178 /* NOTE: if no data left, we return the last keyboard one
179 (needed for EMM386) */
180 /* XXX: need a timer to do things correctly */
181 index = q->rptr - 1;
182 if (index < 0)
183 index = PS2_QUEUE_SIZE - 1;
184 val = q->data[index];
185 } else {
186 val = q->data[q->rptr];
187 if (++q->rptr == PS2_QUEUE_SIZE)
188 q->rptr = 0;
189 q->count--;
190 /* reading deasserts IRQ */
191 s->update_irq(s->update_arg, 0);
192 /* reassert IRQs if data left */
193 s->update_irq(s->update_arg, q->count != 0);
194 }
195 return val;
196}
197
198static void ps2_reset_keyboard(PS2KbdState *s)
199{
200 s->scan_enabled = 1;
e7d93956 201 s->scancode_set = 2;
6937b376 202 kbd_put_ledstate(0);
0e43e99c
FB
203}
204
205void ps2_write_keyboard(void *opaque, int val)
206{
207 PS2KbdState *s = (PS2KbdState *)opaque;
208
209 switch(s->common.write_cmd) {
210 default:
211 case -1:
212 switch(val) {
213 case 0x00:
214 ps2_queue(&s->common, KBD_REPLY_ACK);
215 break;
216 case 0x05:
217 ps2_queue(&s->common, KBD_REPLY_RESEND);
218 break;
219 case KBD_CMD_GET_ID:
220 ps2_queue(&s->common, KBD_REPLY_ACK);
e7d93956 221 /* We emulate a MF2 AT keyboard here */
35c4d671
AJ
222 ps2_queue(&s->common, KBD_REPLY_ID);
223 if (s->translate)
224 ps2_queue(&s->common, 0x41);
225 else
226 ps2_queue(&s->common, 0x83);
0e43e99c
FB
227 break;
228 case KBD_CMD_ECHO:
229 ps2_queue(&s->common, KBD_CMD_ECHO);
230 break;
231 case KBD_CMD_ENABLE:
232 s->scan_enabled = 1;
233 ps2_queue(&s->common, KBD_REPLY_ACK);
234 break;
e7d93956 235 case KBD_CMD_SCANCODE:
0e43e99c
FB
236 case KBD_CMD_SET_LEDS:
237 case KBD_CMD_SET_RATE:
238 s->common.write_cmd = val;
239 ps2_queue(&s->common, KBD_REPLY_ACK);
240 break;
241 case KBD_CMD_RESET_DISABLE:
242 ps2_reset_keyboard(s);
243 s->scan_enabled = 0;
244 ps2_queue(&s->common, KBD_REPLY_ACK);
245 break;
246 case KBD_CMD_RESET_ENABLE:
247 ps2_reset_keyboard(s);
248 s->scan_enabled = 1;
249 ps2_queue(&s->common, KBD_REPLY_ACK);
250 break;
251 case KBD_CMD_RESET:
252 ps2_reset_keyboard(s);
253 ps2_queue(&s->common, KBD_REPLY_ACK);
254 ps2_queue(&s->common, KBD_REPLY_POR);
255 break;
256 default:
257 ps2_queue(&s->common, KBD_REPLY_ACK);
258 break;
259 }
260 break;
e7d93956
AJ
261 case KBD_CMD_SCANCODE:
262 if (val == 0) {
263 if (s->scancode_set == 1)
264 ps2_put_keycode(s, 0x43);
265 else if (s->scancode_set == 2)
266 ps2_put_keycode(s, 0x41);
267 else if (s->scancode_set == 3)
268 ps2_put_keycode(s, 0x3f);
269 } else {
270 if (val >= 1 && val <= 3)
271 s->scancode_set = val;
272 ps2_queue(&s->common, KBD_REPLY_ACK);
273 }
274 s->common.write_cmd = -1;
275 break;
0e43e99c 276 case KBD_CMD_SET_LEDS:
6937b376 277 kbd_put_ledstate(val);
0e43e99c
FB
278 ps2_queue(&s->common, KBD_REPLY_ACK);
279 s->common.write_cmd = -1;
280 break;
281 case KBD_CMD_SET_RATE:
282 ps2_queue(&s->common, KBD_REPLY_ACK);
283 s->common.write_cmd = -1;
284 break;
285 }
286}
287
f94f5d71
PB
288/* Set the scancode translation mode.
289 0 = raw scancodes.
290 1 = translated scancodes (used by qemu internally). */
291
292void ps2_keyboard_set_translation(void *opaque, int mode)
293{
294 PS2KbdState *s = (PS2KbdState *)opaque;
295 s->translate = mode;
296}
297
0e43e99c
FB
298static void ps2_mouse_send_packet(PS2MouseState *s)
299{
300 unsigned int b;
301 int dx1, dy1, dz1;
302
303 dx1 = s->mouse_dx;
304 dy1 = s->mouse_dy;
305 dz1 = s->mouse_dz;
306 /* XXX: increase range to 8 bits ? */
307 if (dx1 > 127)
308 dx1 = 127;
309 else if (dx1 < -127)
310 dx1 = -127;
311 if (dy1 > 127)
312 dy1 = 127;
313 else if (dy1 < -127)
314 dy1 = -127;
315 b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
316 ps2_queue(&s->common, b);
317 ps2_queue(&s->common, dx1 & 0xff);
318 ps2_queue(&s->common, dy1 & 0xff);
319 /* extra byte for IMPS/2 or IMEX */
320 switch(s->mouse_type) {
321 default:
322 break;
323 case 3:
324 if (dz1 > 127)
325 dz1 = 127;
326 else if (dz1 < -127)
327 dz1 = -127;
328 ps2_queue(&s->common, dz1 & 0xff);
329 break;
330 case 4:
331 if (dz1 > 7)
332 dz1 = 7;
333 else if (dz1 < -7)
334 dz1 = -7;
335 b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
336 ps2_queue(&s->common, b);
337 break;
338 }
339
340 /* update deltas */
341 s->mouse_dx -= dx1;
342 s->mouse_dy -= dy1;
343 s->mouse_dz -= dz1;
344}
345
5fafdf24 346static void ps2_mouse_event(void *opaque,
0e43e99c
FB
347 int dx, int dy, int dz, int buttons_state)
348{
349 PS2MouseState *s = opaque;
350
351 /* check if deltas are recorded when disabled */
352 if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
353 return;
354
355 s->mouse_dx += dx;
356 s->mouse_dy -= dy;
357 s->mouse_dz += dz;
358 /* XXX: SDL sometimes generates nul events: we delete them */
359 if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0 &&
360 s->mouse_buttons == buttons_state)
361 return;
362 s->mouse_buttons = buttons_state;
3b46e624 363
0e43e99c
FB
364 if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
365 (s->common.queue.count < (PS2_QUEUE_SIZE - 16))) {
366 for(;;) {
367 /* if not remote, send event. Multiple events are sent if
368 too big deltas */
369 ps2_mouse_send_packet(s);
370 if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
371 break;
372 }
373 }
374}
375
548df2ac
TS
376void ps2_mouse_fake_event(void *opaque)
377{
378 ps2_mouse_event(opaque, 1, 0, 0, 0);
379}
380
0e43e99c
FB
381void ps2_write_mouse(void *opaque, int val)
382{
383 PS2MouseState *s = (PS2MouseState *)opaque;
384#ifdef DEBUG_MOUSE
385 printf("kbd: write mouse 0x%02x\n", val);
386#endif
387 switch(s->common.write_cmd) {
388 default:
389 case -1:
390 /* mouse command */
391 if (s->mouse_wrap) {
392 if (val == AUX_RESET_WRAP) {
393 s->mouse_wrap = 0;
394 ps2_queue(&s->common, AUX_ACK);
395 return;
396 } else if (val != AUX_RESET) {
397 ps2_queue(&s->common, val);
398 return;
399 }
400 }
401 switch(val) {
402 case AUX_SET_SCALE11:
403 s->mouse_status &= ~MOUSE_STATUS_SCALE21;
404 ps2_queue(&s->common, AUX_ACK);
405 break;
406 case AUX_SET_SCALE21:
407 s->mouse_status |= MOUSE_STATUS_SCALE21;
408 ps2_queue(&s->common, AUX_ACK);
409 break;
410 case AUX_SET_STREAM:
411 s->mouse_status &= ~MOUSE_STATUS_REMOTE;
412 ps2_queue(&s->common, AUX_ACK);
413 break;
414 case AUX_SET_WRAP:
415 s->mouse_wrap = 1;
416 ps2_queue(&s->common, AUX_ACK);
417 break;
418 case AUX_SET_REMOTE:
419 s->mouse_status |= MOUSE_STATUS_REMOTE;
420 ps2_queue(&s->common, AUX_ACK);
421 break;
422 case AUX_GET_TYPE:
423 ps2_queue(&s->common, AUX_ACK);
424 ps2_queue(&s->common, s->mouse_type);
425 break;
426 case AUX_SET_RES:
427 case AUX_SET_SAMPLE:
428 s->common.write_cmd = val;
429 ps2_queue(&s->common, AUX_ACK);
430 break;
431 case AUX_GET_SCALE:
432 ps2_queue(&s->common, AUX_ACK);
433 ps2_queue(&s->common, s->mouse_status);
434 ps2_queue(&s->common, s->mouse_resolution);
435 ps2_queue(&s->common, s->mouse_sample_rate);
436 break;
437 case AUX_POLL:
438 ps2_queue(&s->common, AUX_ACK);
439 ps2_mouse_send_packet(s);
440 break;
441 case AUX_ENABLE_DEV:
442 s->mouse_status |= MOUSE_STATUS_ENABLED;
443 ps2_queue(&s->common, AUX_ACK);
444 break;
445 case AUX_DISABLE_DEV:
446 s->mouse_status &= ~MOUSE_STATUS_ENABLED;
447 ps2_queue(&s->common, AUX_ACK);
448 break;
449 case AUX_SET_DEFAULT:
450 s->mouse_sample_rate = 100;
451 s->mouse_resolution = 2;
452 s->mouse_status = 0;
453 ps2_queue(&s->common, AUX_ACK);
454 break;
455 case AUX_RESET:
456 s->mouse_sample_rate = 100;
457 s->mouse_resolution = 2;
458 s->mouse_status = 0;
459 s->mouse_type = 0;
460 ps2_queue(&s->common, AUX_ACK);
461 ps2_queue(&s->common, 0xaa);
462 ps2_queue(&s->common, s->mouse_type);
463 break;
464 default:
465 break;
466 }
467 break;
468 case AUX_SET_SAMPLE:
469 s->mouse_sample_rate = val;
470 /* detect IMPS/2 or IMEX */
471 switch(s->mouse_detect_state) {
472 default:
473 case 0:
474 if (val == 200)
475 s->mouse_detect_state = 1;
476 break;
477 case 1:
478 if (val == 100)
479 s->mouse_detect_state = 2;
480 else if (val == 200)
481 s->mouse_detect_state = 3;
482 else
483 s->mouse_detect_state = 0;
484 break;
485 case 2:
5fafdf24 486 if (val == 80)
0e43e99c
FB
487 s->mouse_type = 3; /* IMPS/2 */
488 s->mouse_detect_state = 0;
489 break;
490 case 3:
5fafdf24 491 if (val == 80)
0e43e99c
FB
492 s->mouse_type = 4; /* IMEX */
493 s->mouse_detect_state = 0;
494 break;
495 }
496 ps2_queue(&s->common, AUX_ACK);
497 s->common.write_cmd = -1;
498 break;
499 case AUX_SET_RES:
500 s->mouse_resolution = val;
501 ps2_queue(&s->common, AUX_ACK);
502 s->common.write_cmd = -1;
503 break;
504 }
505}
506
ef74679a 507static void ps2_common_reset(PS2State *s)
0e43e99c 508{
0e43e99c
FB
509 PS2Queue *q;
510 s->write_cmd = -1;
511 q = &s->queue;
512 q->rptr = 0;
513 q->wptr = 0;
514 q->count = 0;
deeccef3 515 s->update_irq(s->update_arg, 0);
0e43e99c
FB
516}
517
ef74679a
DS
518static void ps2_kbd_reset(void *opaque)
519{
520 PS2KbdState *s = (PS2KbdState *) opaque;
521
522 ps2_common_reset(&s->common);
523 s->scan_enabled = 0;
524 s->translate = 0;
525 s->scancode_set = 0;
526}
527
528static void ps2_mouse_reset(void *opaque)
529{
530 PS2MouseState *s = (PS2MouseState *) opaque;
531
532 ps2_common_reset(&s->common);
533 s->mouse_status = 0;
534 s->mouse_resolution = 0;
535 s->mouse_sample_rate = 0;
536 s->mouse_wrap = 0;
537 s->mouse_type = 0;
538 s->mouse_detect_state = 0;
539 s->mouse_dx = 0;
540 s->mouse_dy = 0;
541 s->mouse_dz = 0;
542 s->mouse_buttons = 0;
543}
544
b31442c3
JQ
545static const VMStateDescription vmstate_ps2_common = {
546 .name = "PS2 Common State",
547 .version_id = 3,
548 .minimum_version_id = 2,
549 .minimum_version_id_old = 2,
550 .fields = (VMStateField []) {
551 VMSTATE_INT32(write_cmd, PS2State),
552 VMSTATE_INT32(queue.rptr, PS2State),
553 VMSTATE_INT32(queue.wptr, PS2State),
554 VMSTATE_INT32(queue.count, PS2State),
555 VMSTATE_BUFFER(queue.data, PS2State),
556 VMSTATE_END_OF_LIST()
557 }
558};
0e43e99c 559
db596c53 560static int ps2_kbd_post_load(void* opaque, int version_id)
0e43e99c
FB
561{
562 PS2KbdState *s = (PS2KbdState*)opaque;
7783e9f0 563
db596c53 564 if (version_id == 2)
e7d93956 565 s->scancode_set=2;
0e43e99c
FB
566 return 0;
567}
568
b31442c3
JQ
569static const VMStateDescription vmstate_ps2_keyboard = {
570 .name = "ps2kbd",
571 .version_id = 3,
db596c53 572 .minimum_version_id = 2,
b31442c3 573 .minimum_version_id_old = 2,
db596c53 574 .post_load = ps2_kbd_post_load,
b31442c3
JQ
575 .fields = (VMStateField []) {
576 VMSTATE_STRUCT(common, PS2KbdState, 0, vmstate_ps2_common, PS2State),
577 VMSTATE_INT32(scan_enabled, PS2KbdState),
578 VMSTATE_INT32(translate, PS2KbdState),
579 VMSTATE_INT32_V(scancode_set, PS2KbdState,3),
580 VMSTATE_END_OF_LIST()
581 }
582};
7783e9f0 583
b31442c3
JQ
584static const VMStateDescription vmstate_ps2_mouse = {
585 .name = "ps2mouse",
586 .version_id = 2,
587 .minimum_version_id = 2,
588 .minimum_version_id_old = 2,
589 .fields = (VMStateField []) {
590 VMSTATE_STRUCT(common, PS2MouseState, 0, vmstate_ps2_common, PS2State),
591 VMSTATE_UINT8(mouse_status, PS2MouseState),
592 VMSTATE_UINT8(mouse_resolution, PS2MouseState),
593 VMSTATE_UINT8(mouse_sample_rate, PS2MouseState),
594 VMSTATE_UINT8(mouse_wrap, PS2MouseState),
595 VMSTATE_UINT8(mouse_type, PS2MouseState),
596 VMSTATE_UINT8(mouse_detect_state, PS2MouseState),
597 VMSTATE_INT32(mouse_dx, PS2MouseState),
598 VMSTATE_INT32(mouse_dy, PS2MouseState),
599 VMSTATE_INT32(mouse_dz, PS2MouseState),
600 VMSTATE_UINT8(mouse_buttons, PS2MouseState),
601 VMSTATE_END_OF_LIST()
602 }
603};
0e43e99c
FB
604
605void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
606{
607 PS2KbdState *s = (PS2KbdState *)qemu_mallocz(sizeof(PS2KbdState));
608
609 s->common.update_irq = update_irq;
610 s->common.update_arg = update_arg;
e7d93956 611 s->scancode_set = 2;
0be71e32 612 vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s);
0e43e99c 613 qemu_add_kbd_event_handler(ps2_put_keycode, s);
ef74679a 614 qemu_register_reset(ps2_kbd_reset, s);
0e43e99c
FB
615 return s;
616}
617
618void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
619{
620 PS2MouseState *s = (PS2MouseState *)qemu_mallocz(sizeof(PS2MouseState));
621
622 s->common.update_irq = update_irq;
623 s->common.update_arg = update_arg;
0be71e32 624 vmstate_register(NULL, 0, &vmstate_ps2_mouse, s);
455204eb 625 qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse");
ef74679a 626 qemu_register_reset(ps2_mouse_reset, s);
0e43e99c
FB
627 return s;
628}