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