|
|
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:
1.1.1.6 root 491: static void ps2_common_reset(PS2State *s)
1.1 root 492: {
493: PS2Queue *q;
494: s->write_cmd = -1;
495: q = &s->queue;
496: q->rptr = 0;
497: q->wptr = 0;
498: q->count = 0;
1.1.1.5 root 499: s->update_irq(s->update_arg, 0);
1.1 root 500: }
501:
1.1.1.6 root 502: static void ps2_kbd_reset(void *opaque)
503: {
504: PS2KbdState *s = (PS2KbdState *) opaque;
505:
506: ps2_common_reset(&s->common);
507: s->scan_enabled = 0;
508: s->translate = 0;
509: s->scancode_set = 0;
510: }
511:
512: static void ps2_mouse_reset(void *opaque)
513: {
514: PS2MouseState *s = (PS2MouseState *) opaque;
515:
516: ps2_common_reset(&s->common);
517: s->mouse_status = 0;
518: s->mouse_resolution = 0;
519: s->mouse_sample_rate = 0;
520: s->mouse_wrap = 0;
521: s->mouse_type = 0;
522: s->mouse_detect_state = 0;
523: s->mouse_dx = 0;
524: s->mouse_dy = 0;
525: s->mouse_dz = 0;
526: s->mouse_buttons = 0;
527: }
528:
1.1.1.7 ! root 529: static const VMStateDescription vmstate_ps2_common = {
! 530: .name = "PS2 Common State",
! 531: .version_id = 3,
! 532: .minimum_version_id = 2,
! 533: .minimum_version_id_old = 2,
! 534: .fields = (VMStateField []) {
! 535: VMSTATE_INT32(write_cmd, PS2State),
! 536: VMSTATE_INT32(queue.rptr, PS2State),
! 537: VMSTATE_INT32(queue.wptr, PS2State),
! 538: VMSTATE_INT32(queue.count, PS2State),
! 539: VMSTATE_BUFFER(queue.data, PS2State),
! 540: VMSTATE_END_OF_LIST()
! 541: }
! 542: };
1.1 root 543:
1.1.1.7 ! root 544: static int ps2_kbd_post_load(void* opaque, int version_id)
1.1 root 545: {
546: PS2KbdState *s = (PS2KbdState*)opaque;
1.1.1.2 root 547:
1.1.1.7 ! root 548: if (version_id == 2)
1.1.1.5 root 549: s->scancode_set=2;
1.1 root 550: return 0;
551: }
552:
1.1.1.7 ! root 553: static const VMStateDescription vmstate_ps2_keyboard = {
! 554: .name = "ps2kbd",
! 555: .version_id = 3,
! 556: .minimum_version_id = 2,
! 557: .minimum_version_id_old = 2,
! 558: .post_load = ps2_kbd_post_load,
! 559: .fields = (VMStateField []) {
! 560: VMSTATE_STRUCT(common, PS2KbdState, 0, vmstate_ps2_common, PS2State),
! 561: VMSTATE_INT32(scan_enabled, PS2KbdState),
! 562: VMSTATE_INT32(translate, PS2KbdState),
! 563: VMSTATE_INT32_V(scancode_set, PS2KbdState,3),
! 564: VMSTATE_END_OF_LIST()
! 565: }
! 566: };
! 567:
! 568: static const VMStateDescription vmstate_ps2_mouse = {
! 569: .name = "ps2mouse",
! 570: .version_id = 2,
! 571: .minimum_version_id = 2,
! 572: .minimum_version_id_old = 2,
! 573: .fields = (VMStateField []) {
! 574: VMSTATE_STRUCT(common, PS2MouseState, 0, vmstate_ps2_common, PS2State),
! 575: VMSTATE_UINT8(mouse_status, PS2MouseState),
! 576: VMSTATE_UINT8(mouse_resolution, PS2MouseState),
! 577: VMSTATE_UINT8(mouse_sample_rate, PS2MouseState),
! 578: VMSTATE_UINT8(mouse_wrap, PS2MouseState),
! 579: VMSTATE_UINT8(mouse_type, PS2MouseState),
! 580: VMSTATE_UINT8(mouse_detect_state, PS2MouseState),
! 581: VMSTATE_INT32(mouse_dx, PS2MouseState),
! 582: VMSTATE_INT32(mouse_dy, PS2MouseState),
! 583: VMSTATE_INT32(mouse_dz, PS2MouseState),
! 584: VMSTATE_UINT8(mouse_buttons, PS2MouseState),
! 585: VMSTATE_END_OF_LIST()
! 586: }
! 587: };
1.1 root 588:
589: void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
590: {
591: PS2KbdState *s = (PS2KbdState *)qemu_mallocz(sizeof(PS2KbdState));
592:
593: s->common.update_irq = update_irq;
594: s->common.update_arg = update_arg;
1.1.1.5 root 595: s->scancode_set = 2;
1.1.1.7 ! root 596: vmstate_register(0, &vmstate_ps2_keyboard, s);
1.1 root 597: qemu_add_kbd_event_handler(ps2_put_keycode, s);
1.1.1.6 root 598: qemu_register_reset(ps2_kbd_reset, s);
1.1 root 599: return s;
600: }
601:
602: void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
603: {
604: PS2MouseState *s = (PS2MouseState *)qemu_mallocz(sizeof(PS2MouseState));
605:
606: s->common.update_irq = update_irq;
607: s->common.update_arg = update_arg;
1.1.1.7 ! root 608: vmstate_register(0, &vmstate_ps2_mouse, s);
1.1.1.3 root 609: qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse");
1.1.1.6 root 610: qemu_register_reset(ps2_mouse_reset, s);
1.1 root 611: return s;
612: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.