|
|
1.1 root 1: /*
2: * QEMU PS/2 keyboard/mouse emulation
1.1.1.4 root 3: *
1.1 root 4: * Copyright (c) 2003 Fabrice Bellard
1.1.1.4 root 5: *
1.1 root 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: */
1.1.1.4 root 24: #include "hw.h"
25: #include "ps2.h"
26: #include "console.h"
1.1 root 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
1.1.1.5 ! root 37: #define KBD_CMD_SCANCODE 0xF0 /* Get/set scancode set */
1.1 root 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 */
1.1.1.5 ! root 47: #define KBD_REPLY_ID 0xAB /* Keyboard ID */
1.1 root 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:
75: typedef struct {
76: uint8_t data[PS2_QUEUE_SIZE];
77: int rptr, wptr, count;
78: } PS2Queue;
79:
80: typedef struct {
81: PS2Queue queue;
82: int32_t write_cmd;
83: void (*update_irq)(void *, int);
84: void *update_arg;
85: } PS2State;
86:
87: typedef struct {
88: PS2State common;
89: int scan_enabled;
1.1.1.2 root 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;
1.1.1.5 ! root 94: int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */
1.1 root 95: } PS2KbdState;
96:
97: typedef 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:
1.1.1.2 root 111: /* Table to convert from PC scancodes to raw scancodes. */
112: static const unsigned char ps2_raw_keycode[128] = {
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,
118: 114,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: };
122:
1.1 root 123: void ps2_queue(void *opaque, int b)
124: {
125: PS2State *s = (PS2State *)opaque;
126: PS2Queue *q = &s->queue;
127:
128: if (q->count >= PS2_QUEUE_SIZE)
129: return;
130: q->data[q->wptr] = b;
131: if (++q->wptr == PS2_QUEUE_SIZE)
132: q->wptr = 0;
133: q->count++;
134: s->update_irq(s->update_arg, 1);
135: }
136:
1.1.1.5 ! root 137: /*
! 138: keycode is expressed as follow:
! 139: bit 7 - 0 key pressed, 1 = key released
! 140: bits 6-0 - translated scancode set 2
! 141: */
1.1 root 142: static void ps2_put_keycode(void *opaque, int keycode)
143: {
1.1.1.2 root 144: PS2KbdState *s = opaque;
1.1.1.5 ! root 145:
! 146: /* XXX: add support for scancode sets 1 and 3 */
! 147: if (!s->translate && keycode < 0xe0 && s->scancode_set == 2)
1.1.1.2 root 148: {
149: if (keycode & 0x80)
150: ps2_queue(&s->common, 0xf0);
151: keycode = ps2_raw_keycode[keycode & 0x7f];
152: }
1.1 root 153: ps2_queue(&s->common, keycode);
154: }
155:
156: uint32_t ps2_read_data(void *opaque)
157: {
158: PS2State *s = (PS2State *)opaque;
159: PS2Queue *q;
160: int val, index;
1.1.1.4 root 161:
1.1 root 162: q = &s->queue;
163: if (q->count == 0) {
164: /* NOTE: if no data left, we return the last keyboard one
165: (needed for EMM386) */
166: /* XXX: need a timer to do things correctly */
167: index = q->rptr - 1;
168: if (index < 0)
169: index = PS2_QUEUE_SIZE - 1;
170: val = q->data[index];
171: } else {
172: val = q->data[q->rptr];
173: if (++q->rptr == PS2_QUEUE_SIZE)
174: q->rptr = 0;
175: q->count--;
176: /* reading deasserts IRQ */
177: s->update_irq(s->update_arg, 0);
178: /* reassert IRQs if data left */
179: s->update_irq(s->update_arg, q->count != 0);
180: }
181: return val;
182: }
183:
184: static void ps2_reset_keyboard(PS2KbdState *s)
185: {
186: s->scan_enabled = 1;
1.1.1.5 ! root 187: s->scancode_set = 2;
1.1 root 188: }
189:
190: void ps2_write_keyboard(void *opaque, int val)
191: {
192: PS2KbdState *s = (PS2KbdState *)opaque;
193:
194: switch(s->common.write_cmd) {
195: default:
196: case -1:
197: switch(val) {
198: case 0x00:
199: ps2_queue(&s->common, KBD_REPLY_ACK);
200: break;
201: case 0x05:
202: ps2_queue(&s->common, KBD_REPLY_RESEND);
203: break;
204: case KBD_CMD_GET_ID:
205: ps2_queue(&s->common, KBD_REPLY_ACK);
1.1.1.5 ! root 206: /* We emulate a MF2 AT keyboard here */
! 207: ps2_queue(&s->common, KBD_REPLY_ID);
! 208: if (s->translate)
! 209: ps2_queue(&s->common, 0x41);
! 210: else
! 211: ps2_queue(&s->common, 0x83);
1.1 root 212: break;
213: case KBD_CMD_ECHO:
214: ps2_queue(&s->common, KBD_CMD_ECHO);
215: break;
216: case KBD_CMD_ENABLE:
217: s->scan_enabled = 1;
218: ps2_queue(&s->common, KBD_REPLY_ACK);
219: break;
1.1.1.5 ! root 220: case KBD_CMD_SCANCODE:
1.1 root 221: case KBD_CMD_SET_LEDS:
222: case KBD_CMD_SET_RATE:
223: s->common.write_cmd = val;
224: ps2_queue(&s->common, KBD_REPLY_ACK);
225: break;
226: case KBD_CMD_RESET_DISABLE:
227: ps2_reset_keyboard(s);
228: s->scan_enabled = 0;
229: ps2_queue(&s->common, KBD_REPLY_ACK);
230: break;
231: case KBD_CMD_RESET_ENABLE:
232: ps2_reset_keyboard(s);
233: s->scan_enabled = 1;
234: ps2_queue(&s->common, KBD_REPLY_ACK);
235: break;
236: case KBD_CMD_RESET:
237: ps2_reset_keyboard(s);
238: ps2_queue(&s->common, KBD_REPLY_ACK);
239: ps2_queue(&s->common, KBD_REPLY_POR);
240: break;
241: default:
242: ps2_queue(&s->common, KBD_REPLY_ACK);
243: break;
244: }
245: break;
1.1.1.5 ! root 246: case KBD_CMD_SCANCODE:
! 247: if (val == 0) {
! 248: if (s->scancode_set == 1)
! 249: ps2_put_keycode(s, 0x43);
! 250: else if (s->scancode_set == 2)
! 251: ps2_put_keycode(s, 0x41);
! 252: else if (s->scancode_set == 3)
! 253: ps2_put_keycode(s, 0x3f);
! 254: } else {
! 255: if (val >= 1 && val <= 3)
! 256: s->scancode_set = val;
! 257: ps2_queue(&s->common, KBD_REPLY_ACK);
! 258: }
! 259: s->common.write_cmd = -1;
! 260: break;
1.1 root 261: case KBD_CMD_SET_LEDS:
262: ps2_queue(&s->common, KBD_REPLY_ACK);
263: s->common.write_cmd = -1;
264: break;
265: case KBD_CMD_SET_RATE:
266: ps2_queue(&s->common, KBD_REPLY_ACK);
267: s->common.write_cmd = -1;
268: break;
269: }
270: }
271:
1.1.1.2 root 272: /* Set the scancode translation mode.
273: 0 = raw scancodes.
274: 1 = translated scancodes (used by qemu internally). */
275:
276: void ps2_keyboard_set_translation(void *opaque, int mode)
277: {
278: PS2KbdState *s = (PS2KbdState *)opaque;
279: s->translate = mode;
280: }
281:
1.1 root 282: static void ps2_mouse_send_packet(PS2MouseState *s)
283: {
284: unsigned int b;
285: int dx1, dy1, dz1;
286:
287: dx1 = s->mouse_dx;
288: dy1 = s->mouse_dy;
289: dz1 = s->mouse_dz;
290: /* XXX: increase range to 8 bits ? */
291: if (dx1 > 127)
292: dx1 = 127;
293: else if (dx1 < -127)
294: dx1 = -127;
295: if (dy1 > 127)
296: dy1 = 127;
297: else if (dy1 < -127)
298: dy1 = -127;
299: b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
300: ps2_queue(&s->common, b);
301: ps2_queue(&s->common, dx1 & 0xff);
302: ps2_queue(&s->common, dy1 & 0xff);
303: /* extra byte for IMPS/2 or IMEX */
304: switch(s->mouse_type) {
305: default:
306: break;
307: case 3:
308: if (dz1 > 127)
309: dz1 = 127;
310: else if (dz1 < -127)
311: dz1 = -127;
312: ps2_queue(&s->common, dz1 & 0xff);
313: break;
314: case 4:
315: if (dz1 > 7)
316: dz1 = 7;
317: else if (dz1 < -7)
318: dz1 = -7;
319: b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
320: ps2_queue(&s->common, b);
321: break;
322: }
323:
324: /* update deltas */
325: s->mouse_dx -= dx1;
326: s->mouse_dy -= dy1;
327: s->mouse_dz -= dz1;
328: }
329:
1.1.1.4 root 330: static void ps2_mouse_event(void *opaque,
1.1 root 331: int dx, int dy, int dz, int buttons_state)
332: {
333: PS2MouseState *s = opaque;
334:
335: /* check if deltas are recorded when disabled */
336: if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
337: return;
338:
339: s->mouse_dx += dx;
340: s->mouse_dy -= dy;
341: s->mouse_dz += dz;
342: /* XXX: SDL sometimes generates nul events: we delete them */
343: if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0 &&
344: s->mouse_buttons == buttons_state)
345: return;
346: s->mouse_buttons = buttons_state;
1.1.1.4 root 347:
1.1 root 348: if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
349: (s->common.queue.count < (PS2_QUEUE_SIZE - 16))) {
350: for(;;) {
351: /* if not remote, send event. Multiple events are sent if
352: too big deltas */
353: ps2_mouse_send_packet(s);
354: if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
355: break;
356: }
357: }
358: }
359:
1.1.1.4 root 360: void ps2_mouse_fake_event(void *opaque)
361: {
362: ps2_mouse_event(opaque, 1, 0, 0, 0);
363: }
364:
1.1 root 365: void ps2_write_mouse(void *opaque, int val)
366: {
367: PS2MouseState *s = (PS2MouseState *)opaque;
368: #ifdef DEBUG_MOUSE
369: printf("kbd: write mouse 0x%02x\n", val);
370: #endif
371: switch(s->common.write_cmd) {
372: default:
373: case -1:
374: /* mouse command */
375: if (s->mouse_wrap) {
376: if (val == AUX_RESET_WRAP) {
377: s->mouse_wrap = 0;
378: ps2_queue(&s->common, AUX_ACK);
379: return;
380: } else if (val != AUX_RESET) {
381: ps2_queue(&s->common, val);
382: return;
383: }
384: }
385: switch(val) {
386: case AUX_SET_SCALE11:
387: s->mouse_status &= ~MOUSE_STATUS_SCALE21;
388: ps2_queue(&s->common, AUX_ACK);
389: break;
390: case AUX_SET_SCALE21:
391: s->mouse_status |= MOUSE_STATUS_SCALE21;
392: ps2_queue(&s->common, AUX_ACK);
393: break;
394: case AUX_SET_STREAM:
395: s->mouse_status &= ~MOUSE_STATUS_REMOTE;
396: ps2_queue(&s->common, AUX_ACK);
397: break;
398: case AUX_SET_WRAP:
399: s->mouse_wrap = 1;
400: ps2_queue(&s->common, AUX_ACK);
401: break;
402: case AUX_SET_REMOTE:
403: s->mouse_status |= MOUSE_STATUS_REMOTE;
404: ps2_queue(&s->common, AUX_ACK);
405: break;
406: case AUX_GET_TYPE:
407: ps2_queue(&s->common, AUX_ACK);
408: ps2_queue(&s->common, s->mouse_type);
409: break;
410: case AUX_SET_RES:
411: case AUX_SET_SAMPLE:
412: s->common.write_cmd = val;
413: ps2_queue(&s->common, AUX_ACK);
414: break;
415: case AUX_GET_SCALE:
416: ps2_queue(&s->common, AUX_ACK);
417: ps2_queue(&s->common, s->mouse_status);
418: ps2_queue(&s->common, s->mouse_resolution);
419: ps2_queue(&s->common, s->mouse_sample_rate);
420: break;
421: case AUX_POLL:
422: ps2_queue(&s->common, AUX_ACK);
423: ps2_mouse_send_packet(s);
424: break;
425: case AUX_ENABLE_DEV:
426: s->mouse_status |= MOUSE_STATUS_ENABLED;
427: ps2_queue(&s->common, AUX_ACK);
428: break;
429: case AUX_DISABLE_DEV:
430: s->mouse_status &= ~MOUSE_STATUS_ENABLED;
431: ps2_queue(&s->common, AUX_ACK);
432: break;
433: case AUX_SET_DEFAULT:
434: s->mouse_sample_rate = 100;
435: s->mouse_resolution = 2;
436: s->mouse_status = 0;
437: ps2_queue(&s->common, AUX_ACK);
438: break;
439: case AUX_RESET:
440: s->mouse_sample_rate = 100;
441: s->mouse_resolution = 2;
442: s->mouse_status = 0;
443: s->mouse_type = 0;
444: ps2_queue(&s->common, AUX_ACK);
445: ps2_queue(&s->common, 0xaa);
446: ps2_queue(&s->common, s->mouse_type);
447: break;
448: default:
449: break;
450: }
451: break;
452: case AUX_SET_SAMPLE:
453: s->mouse_sample_rate = val;
454: /* detect IMPS/2 or IMEX */
455: switch(s->mouse_detect_state) {
456: default:
457: case 0:
458: if (val == 200)
459: s->mouse_detect_state = 1;
460: break;
461: case 1:
462: if (val == 100)
463: s->mouse_detect_state = 2;
464: else if (val == 200)
465: s->mouse_detect_state = 3;
466: else
467: s->mouse_detect_state = 0;
468: break;
469: case 2:
1.1.1.4 root 470: if (val == 80)
1.1 root 471: s->mouse_type = 3; /* IMPS/2 */
472: s->mouse_detect_state = 0;
473: break;
474: case 3:
1.1.1.4 root 475: if (val == 80)
1.1 root 476: s->mouse_type = 4; /* IMEX */
477: s->mouse_detect_state = 0;
478: break;
479: }
480: ps2_queue(&s->common, AUX_ACK);
481: s->common.write_cmd = -1;
482: break;
483: case AUX_SET_RES:
484: s->mouse_resolution = val;
485: ps2_queue(&s->common, AUX_ACK);
486: s->common.write_cmd = -1;
487: break;
488: }
489: }
490:
491: static void ps2_reset(void *opaque)
492: {
493: PS2State *s = (PS2State *)opaque;
494: PS2Queue *q;
495: s->write_cmd = -1;
496: q = &s->queue;
497: q->rptr = 0;
498: q->wptr = 0;
499: q->count = 0;
1.1.1.5 ! root 500: s->update_irq(s->update_arg, 0);
1.1 root 501: }
502:
1.1.1.2 root 503: static void ps2_common_save (QEMUFile *f, PS2State *s)
504: {
1.1.1.4 root 505: qemu_put_be32 (f, s->write_cmd);
506: qemu_put_be32 (f, s->queue.rptr);
507: qemu_put_be32 (f, s->queue.wptr);
508: qemu_put_be32 (f, s->queue.count);
1.1.1.2 root 509: qemu_put_buffer (f, s->queue.data, sizeof (s->queue.data));
510: }
511:
512: static void ps2_common_load (QEMUFile *f, PS2State *s)
513: {
1.1.1.4 root 514: s->write_cmd=qemu_get_be32 (f);
515: s->queue.rptr=qemu_get_be32 (f);
516: s->queue.wptr=qemu_get_be32 (f);
517: s->queue.count=qemu_get_be32 (f);
1.1.1.2 root 518: qemu_get_buffer (f, s->queue.data, sizeof (s->queue.data));
519: }
520:
1.1 root 521: static void ps2_kbd_save(QEMUFile* f, void* opaque)
522: {
523: PS2KbdState *s = (PS2KbdState*)opaque;
1.1.1.2 root 524:
525: ps2_common_save (f, &s->common);
1.1.1.4 root 526: qemu_put_be32(f, s->scan_enabled);
527: qemu_put_be32(f, s->translate);
1.1.1.5 ! root 528: qemu_put_be32(f, s->scancode_set);
1.1 root 529: }
530:
531: static void ps2_mouse_save(QEMUFile* f, void* opaque)
532: {
533: PS2MouseState *s = (PS2MouseState*)opaque;
1.1.1.2 root 534:
535: ps2_common_save (f, &s->common);
1.1 root 536: qemu_put_8s(f, &s->mouse_status);
537: qemu_put_8s(f, &s->mouse_resolution);
538: qemu_put_8s(f, &s->mouse_sample_rate);
539: qemu_put_8s(f, &s->mouse_wrap);
540: qemu_put_8s(f, &s->mouse_type);
541: qemu_put_8s(f, &s->mouse_detect_state);
1.1.1.4 root 542: qemu_put_be32(f, s->mouse_dx);
543: qemu_put_be32(f, s->mouse_dy);
544: qemu_put_be32(f, s->mouse_dz);
1.1 root 545: qemu_put_8s(f, &s->mouse_buttons);
546: }
547:
548: static int ps2_kbd_load(QEMUFile* f, void* opaque, int version_id)
549: {
550: PS2KbdState *s = (PS2KbdState*)opaque;
1.1.1.2 root 551:
1.1.1.5 ! root 552: if (version_id != 2 && version_id != 3)
1.1 root 553: return -EINVAL;
1.1.1.2 root 554:
555: ps2_common_load (f, &s->common);
1.1.1.4 root 556: s->scan_enabled=qemu_get_be32(f);
557: s->translate=qemu_get_be32(f);
1.1.1.5 ! root 558: if (version_id == 3)
! 559: s->scancode_set=qemu_get_be32(f);
! 560: else
! 561: s->scancode_set=2;
1.1 root 562: return 0;
563: }
564:
565: static int ps2_mouse_load(QEMUFile* f, void* opaque, int version_id)
566: {
567: PS2MouseState *s = (PS2MouseState*)opaque;
1.1.1.2 root 568:
569: if (version_id != 2)
1.1 root 570: return -EINVAL;
1.1.1.2 root 571:
572: ps2_common_load (f, &s->common);
1.1 root 573: qemu_get_8s(f, &s->mouse_status);
574: qemu_get_8s(f, &s->mouse_resolution);
575: qemu_get_8s(f, &s->mouse_sample_rate);
576: qemu_get_8s(f, &s->mouse_wrap);
577: qemu_get_8s(f, &s->mouse_type);
578: qemu_get_8s(f, &s->mouse_detect_state);
1.1.1.4 root 579: s->mouse_dx=qemu_get_be32(f);
580: s->mouse_dy=qemu_get_be32(f);
581: s->mouse_dz=qemu_get_be32(f);
1.1 root 582: qemu_get_8s(f, &s->mouse_buttons);
583: return 0;
584: }
585:
586: void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
587: {
588: PS2KbdState *s = (PS2KbdState *)qemu_mallocz(sizeof(PS2KbdState));
589:
590: s->common.update_irq = update_irq;
591: s->common.update_arg = update_arg;
1.1.1.5 ! root 592: s->scancode_set = 2;
1.1 root 593: ps2_reset(&s->common);
1.1.1.5 ! root 594: register_savevm("ps2kbd", 0, 3, ps2_kbd_save, ps2_kbd_load, s);
1.1 root 595: qemu_add_kbd_event_handler(ps2_put_keycode, s);
596: qemu_register_reset(ps2_reset, &s->common);
597: return s;
598: }
599:
600: void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
601: {
602: PS2MouseState *s = (PS2MouseState *)qemu_mallocz(sizeof(PS2MouseState));
603:
604: s->common.update_irq = update_irq;
605: s->common.update_arg = update_arg;
606: ps2_reset(&s->common);
1.1.1.2 root 607: register_savevm("ps2mouse", 0, 2, ps2_mouse_save, ps2_mouse_load, s);
1.1.1.3 root 608: qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse");
1.1 root 609: qemu_register_reset(ps2_reset, &s->common);
610: return s;
611: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.