Statistics
| Branch: | Revision:

root / hw / ps2.c @ 35c4d671

History | View | Annotate | Download (18.2 kB)

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

    
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

    
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
 */
142
static void ps2_put_keycode(void *opaque, int keycode)
143
{
144
    PS2KbdState *s = opaque;
145

    
146
    /* XXX: add support for scancode sets 1 and 3 */
147
    if (!s->translate && keycode < 0xe0 && s->scancode_set == 2)
148
      {
149
        if (keycode & 0x80)
150
            ps2_queue(&s->common, 0xf0);
151
        keycode = ps2_raw_keycode[keycode & 0x7f];
152
      }
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;
161

    
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;
187
    s->scancode_set = 2;
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);
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);
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;
220
        case KBD_CMD_SCANCODE:
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;
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;
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

    
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

    
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

    
330
static void ps2_mouse_event(void *opaque,
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;
347

    
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

    
360
void ps2_mouse_fake_event(void *opaque)
361
{
362
    ps2_mouse_event(opaque, 1, 0, 0, 0);
363
}
364

    
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:
470
            if (val == 80)
471
                s->mouse_type = 3; /* IMPS/2 */
472
            s->mouse_detect_state = 0;
473
            break;
474
        case 3:
475
            if (val == 80)
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;
500
}
501

    
502
static void ps2_common_save (QEMUFile *f, PS2State *s)
503
{
504
    qemu_put_be32 (f, s->write_cmd);
505
    qemu_put_be32 (f, s->queue.rptr);
506
    qemu_put_be32 (f, s->queue.wptr);
507
    qemu_put_be32 (f, s->queue.count);
508
    qemu_put_buffer (f, s->queue.data, sizeof (s->queue.data));
509
}
510

    
511
static void ps2_common_load (QEMUFile *f, PS2State *s)
512
{
513
    s->write_cmd=qemu_get_be32 (f);
514
    s->queue.rptr=qemu_get_be32 (f);
515
    s->queue.wptr=qemu_get_be32 (f);
516
    s->queue.count=qemu_get_be32 (f);
517
    qemu_get_buffer (f, s->queue.data, sizeof (s->queue.data));
518
}
519

    
520
static void ps2_kbd_save(QEMUFile* f, void* opaque)
521
{
522
    PS2KbdState *s = (PS2KbdState*)opaque;
523

    
524
    ps2_common_save (f, &s->common);
525
    qemu_put_be32(f, s->scan_enabled);
526
    qemu_put_be32(f, s->translate);
527
    qemu_put_be32(f, s->scancode_set);
528
}
529

    
530
static void ps2_mouse_save(QEMUFile* f, void* opaque)
531
{
532
    PS2MouseState *s = (PS2MouseState*)opaque;
533

    
534
    ps2_common_save (f, &s->common);
535
    qemu_put_8s(f, &s->mouse_status);
536
    qemu_put_8s(f, &s->mouse_resolution);
537
    qemu_put_8s(f, &s->mouse_sample_rate);
538
    qemu_put_8s(f, &s->mouse_wrap);
539
    qemu_put_8s(f, &s->mouse_type);
540
    qemu_put_8s(f, &s->mouse_detect_state);
541
    qemu_put_be32(f, s->mouse_dx);
542
    qemu_put_be32(f, s->mouse_dy);
543
    qemu_put_be32(f, s->mouse_dz);
544
    qemu_put_8s(f, &s->mouse_buttons);
545
}
546

    
547
static int ps2_kbd_load(QEMUFile* f, void* opaque, int version_id)
548
{
549
    PS2KbdState *s = (PS2KbdState*)opaque;
550

    
551
    if (version_id != 2 && version_id != 3)
552
        return -EINVAL;
553

    
554
    ps2_common_load (f, &s->common);
555
    s->scan_enabled=qemu_get_be32(f);
556
    s->translate=qemu_get_be32(f);
557
    if (version_id == 3)
558
        s->scancode_set=qemu_get_be32(f);
559
    else
560
        s->scancode_set=2;
561
    return 0;
562
}
563

    
564
static int ps2_mouse_load(QEMUFile* f, void* opaque, int version_id)
565
{
566
    PS2MouseState *s = (PS2MouseState*)opaque;
567

    
568
    if (version_id != 2)
569
        return -EINVAL;
570

    
571
    ps2_common_load (f, &s->common);
572
    qemu_get_8s(f, &s->mouse_status);
573
    qemu_get_8s(f, &s->mouse_resolution);
574
    qemu_get_8s(f, &s->mouse_sample_rate);
575
    qemu_get_8s(f, &s->mouse_wrap);
576
    qemu_get_8s(f, &s->mouse_type);
577
    qemu_get_8s(f, &s->mouse_detect_state);
578
    s->mouse_dx=qemu_get_be32(f);
579
    s->mouse_dy=qemu_get_be32(f);
580
    s->mouse_dz=qemu_get_be32(f);
581
    qemu_get_8s(f, &s->mouse_buttons);
582
    return 0;
583
}
584

    
585
void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
586
{
587
    PS2KbdState *s = (PS2KbdState *)qemu_mallocz(sizeof(PS2KbdState));
588

    
589
    s->common.update_irq = update_irq;
590
    s->common.update_arg = update_arg;
591
    s->scancode_set = 2;
592
    ps2_reset(&s->common);
593
    register_savevm("ps2kbd", 0, 3, ps2_kbd_save, ps2_kbd_load, s);
594
    qemu_add_kbd_event_handler(ps2_put_keycode, s);
595
    qemu_register_reset(ps2_reset, &s->common);
596
    return s;
597
}
598

    
599
void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
600
{
601
    PS2MouseState *s = (PS2MouseState *)qemu_mallocz(sizeof(PS2MouseState));
602

    
603
    s->common.update_irq = update_irq;
604
    s->common.update_arg = update_arg;
605
    ps2_reset(&s->common);
606
    register_savevm("ps2mouse", 0, 2, ps2_mouse_save, ps2_mouse_load, s);
607
    qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse");
608
    qemu_register_reset(ps2_reset, &s->common);
609
    return s;
610
}