]> Git Repo - qemu.git/blob - hw/ps2.c
Merge remote-tracking branch 'kraxel/usb.29' into staging
[qemu.git] / hw / ps2.c
1 /*
2  * QEMU PS/2 keyboard/mouse emulation
3  *
4  * Copyright (c) 2003 Fabrice Bellard
5  *
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  */
24 #include "hw.h"
25 #include "ps2.h"
26 #include "console.h"
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
37 #define KBD_CMD_SCANCODE        0xF0    /* Get/set scancode set */
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 */
47 #define KBD_REPLY_ID            0xAB    /* Keyboard ID */
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;
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;
94     int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */
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
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 static 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,
128 114, 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
131 };
132
133 void 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
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  */
152 static void ps2_put_keycode(void *opaque, int keycode)
153 {
154     PS2KbdState *s = opaque;
155
156     /* XXX: add support for scancode set 1 */
157     if (!s->translate && keycode < 0xe0 && s->scancode_set > 1) {
158         if (keycode & 0x80) {
159             ps2_queue(&s->common, 0xf0);
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         }
166       }
167     ps2_queue(&s->common, keycode);
168 }
169
170 uint32_t ps2_read_data(void *opaque)
171 {
172     PS2State *s = (PS2State *)opaque;
173     PS2Queue *q;
174     int val, index;
175
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
198 static void ps2_reset_keyboard(PS2KbdState *s)
199 {
200     s->scan_enabled = 1;
201     s->scancode_set = 2;
202     kbd_put_ledstate(0);
203 }
204
205 void 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);
221             /* We emulate a MF2 AT keyboard here */
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);
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;
235         case KBD_CMD_SCANCODE:
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;
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;
276     case KBD_CMD_SET_LEDS:
277         kbd_put_ledstate(val);
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
288 /* Set the scancode translation mode.
289    0 = raw scancodes.
290    1 = translated scancodes (used by qemu internally).  */
291
292 void ps2_keyboard_set_translation(void *opaque, int mode)
293 {
294     PS2KbdState *s = (PS2KbdState *)opaque;
295     s->translate = mode;
296 }
297
298 static 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
346 static void ps2_mouse_event(void *opaque,
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;
363
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
376 void ps2_mouse_fake_event(void *opaque)
377 {
378     ps2_mouse_event(opaque, 1, 0, 0, 0);
379 }
380
381 void 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:
486             if (val == 80)
487                 s->mouse_type = 3; /* IMPS/2 */
488             s->mouse_detect_state = 0;
489             break;
490         case 3:
491             if (val == 80)
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
507 static void ps2_common_reset(PS2State *s)
508 {
509     PS2Queue *q;
510     s->write_cmd = -1;
511     q = &s->queue;
512     q->rptr = 0;
513     q->wptr = 0;
514     q->count = 0;
515     s->update_irq(s->update_arg, 0);
516 }
517
518 static 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
528 static 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
545 static 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 };
559
560 static int ps2_kbd_post_load(void* opaque, int version_id)
561 {
562     PS2KbdState *s = (PS2KbdState*)opaque;
563
564     if (version_id == 2)
565         s->scancode_set=2;
566     return 0;
567 }
568
569 static const VMStateDescription vmstate_ps2_keyboard = {
570     .name = "ps2kbd",
571     .version_id = 3,
572     .minimum_version_id = 2,
573     .minimum_version_id_old = 2,
574     .post_load = ps2_kbd_post_load,
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 };
583
584 static 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 };
604
605 void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
606 {
607     PS2KbdState *s = (PS2KbdState *)g_malloc0(sizeof(PS2KbdState));
608
609     s->common.update_irq = update_irq;
610     s->common.update_arg = update_arg;
611     s->scancode_set = 2;
612     vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s);
613     qemu_add_kbd_event_handler(ps2_put_keycode, s);
614     qemu_register_reset(ps2_kbd_reset, s);
615     return s;
616 }
617
618 void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
619 {
620     PS2MouseState *s = (PS2MouseState *)g_malloc0(sizeof(PS2MouseState));
621
622     s->common.update_irq = update_irq;
623     s->common.update_arg = update_arg;
624     vmstate_register(NULL, 0, &vmstate_ps2_mouse, s);
625     qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse");
626     qemu_register_reset(ps2_mouse_reset, s);
627     return s;
628 }
This page took 0.059627 seconds and 4 git commands to generate.