Statistics
| Branch: | Revision:

root / hw / ps2.c @ 0d09e41a

History | View | Annotate | Download (20.4 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/hw.h"
25
#include "hw/input/ps2.h"
26
#include "ui/console.h"
27
#include "sysemu/sysemu.h"
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
38
#define KBD_CMD_SCANCODE        0xF0        /* Get/set scancode set */
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 */
48
#define KBD_REPLY_ID                0xAB        /* Keyboard ID */
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;
91
    /* QEMU uses translated PC scancodes internally.  To avoid multiple
92
       conversions we do the translation (if any) in the PS/2 emulation
93
       not the keyboard controller.  */
94
    int translate;
95
    int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */
96
    int ledstate;
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

    
113
/* Table to convert from PC scancodes to raw scancodes.  */
114
static const unsigned char ps2_raw_keycode[128] = {
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
133
};
134

    
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

    
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
 */
154
static void ps2_put_keycode(void *opaque, int keycode)
155
{
156
    PS2KbdState *s = opaque;
157

    
158
    qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
159
    /* XXX: add support for scancode set 1 */
160
    if (!s->translate && keycode < 0xe0 && s->scancode_set > 1) {
161
        if (keycode & 0x80) {
162
            ps2_queue(&s->common, 0xf0);
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
        }
169
      }
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;
178

    
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

    
201
static void ps2_set_ledstate(PS2KbdState *s, int ledstate)
202
{
203
    s->ledstate = ledstate;
204
    kbd_put_ledstate(ledstate);
205
}
206

    
207
static void ps2_reset_keyboard(PS2KbdState *s)
208
{
209
    s->scan_enabled = 1;
210
    s->scancode_set = 2;
211
    ps2_set_ledstate(s, 0);
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);
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);
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;
244
        case KBD_CMD_SCANCODE:
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;
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;
285
    case KBD_CMD_SET_LEDS:
286
        ps2_set_ledstate(s, val);
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

    
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

    
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

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

    
373
    if (buttons_state) {
374
        qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
375
    }
376

    
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

    
389
void ps2_mouse_fake_event(void *opaque)
390
{
391
    ps2_mouse_event(opaque, 1, 0, 0, 0);
392
}
393

    
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:
499
            if (val == 80)
500
                s->mouse_type = 3; /* IMPS/2 */
501
            s->mouse_detect_state = 0;
502
            break;
503
        case 3:
504
            if (val == 80)
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

    
520
static void ps2_common_reset(PS2State *s)
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;
528
    s->update_irq(s->update_arg, 0);
529
}
530

    
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

    
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
};
572

    
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

    
600
static int ps2_kbd_post_load(void* opaque, int version_id)
601
{
602
    PS2KbdState *s = (PS2KbdState*)opaque;
603

    
604
    if (version_id == 2)
605
        s->scancode_set=2;
606
    return 0;
607
}
608

    
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()
621
    },
622
    .subsections = (VMStateSubsection []) {
623
        {
624
            .vmsd = &vmstate_ps2_keyboard_ledstate,
625
            .needed = ps2_keyboard_ledstate_needed,
626
        }, {
627
            /* empty */
628
        }
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
};
652

    
653
void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
654
{
655
    PS2KbdState *s = (PS2KbdState *)g_malloc0(sizeof(PS2KbdState));
656

    
657
    s->common.update_irq = update_irq;
658
    s->common.update_arg = update_arg;
659
    s->scancode_set = 2;
660
    vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s);
661
    qemu_add_kbd_event_handler(ps2_put_keycode, s);
662
    qemu_register_reset(ps2_kbd_reset, s);
663
    return s;
664
}
665

    
666
void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
667
{
668
    PS2MouseState *s = (PS2MouseState *)g_malloc0(sizeof(PS2MouseState));
669

    
670
    s->common.update_irq = update_irq;
671
    s->common.update_arg = update_arg;
672
    vmstate_register(NULL, 0, &vmstate_ps2_mouse, s);
673
    qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse");
674
    qemu_register_reset(ps2_mouse_reset, s);
675
    return s;
676
}