~jderose/ubuntu/raring/qemu/vde-again

« back to all changes in this revision

Viewing changes to hw/ps2.c

  • Committer: Bazaar Package Importer
  • Author(s): Aurelien Jarno, Aurelien Jarno
  • Date: 2008-08-25 04:38:35 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20080825043835-8e3tftavy8bujdch
Tags: 0.9.1-6
[ Aurelien Jarno ]
* debian/control: 
  - Update list of supported targets (Closes: bug#488339).
* debian/qemu-make-debian-root:
  - Use mktemp instead of $$ to create temporary directories (Closes: 
    bug#496394).
* debian/links:
  - Add missing links to manpages.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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_GET_ID          0xF2    /* get keyboard ID */
 
38
#define KBD_CMD_SET_RATE        0xF3    /* Set typematic rate */
 
39
#define KBD_CMD_ENABLE          0xF4    /* Enable scanning */
 
40
#define KBD_CMD_RESET_DISABLE   0xF5    /* reset and disable scanning */
 
41
#define KBD_CMD_RESET_ENABLE    0xF6    /* reset and enable scanning */
 
42
#define KBD_CMD_RESET           0xFF    /* Reset */
 
43
 
 
44
/* Keyboard Replies */
 
45
#define KBD_REPLY_POR           0xAA    /* Power on reset */
 
46
#define KBD_REPLY_ACK           0xFA    /* Command ACK */
 
47
#define KBD_REPLY_RESEND        0xFE    /* Command NACK, send the cmd again */
 
48
 
 
49
/* Mouse Commands */
 
50
#define AUX_SET_SCALE11         0xE6    /* Set 1:1 scaling */
 
51
#define AUX_SET_SCALE21         0xE7    /* Set 2:1 scaling */
 
52
#define AUX_SET_RES             0xE8    /* Set resolution */
 
53
#define AUX_GET_SCALE           0xE9    /* Get scaling factor */
 
54
#define AUX_SET_STREAM          0xEA    /* Set stream mode */
 
55
#define AUX_POLL                0xEB    /* Poll */
 
56
#define AUX_RESET_WRAP          0xEC    /* Reset wrap mode */
 
57
#define AUX_SET_WRAP            0xEE    /* Set wrap mode */
 
58
#define AUX_SET_REMOTE          0xF0    /* Set remote mode */
 
59
#define AUX_GET_TYPE            0xF2    /* Get type */
 
60
#define AUX_SET_SAMPLE          0xF3    /* Set sample rate */
 
61
#define AUX_ENABLE_DEV          0xF4    /* Enable aux device */
 
62
#define AUX_DISABLE_DEV         0xF5    /* Disable aux device */
 
63
#define AUX_SET_DEFAULT         0xF6
 
64
#define AUX_RESET               0xFF    /* Reset aux device */
 
65
#define AUX_ACK                 0xFA    /* Command byte ACK. */
 
66
 
 
67
#define MOUSE_STATUS_REMOTE     0x40
 
68
#define MOUSE_STATUS_ENABLED    0x20
 
69
#define MOUSE_STATUS_SCALE21    0x10
 
70
 
 
71
#define PS2_QUEUE_SIZE 256
 
72
 
 
73
typedef struct {
 
74
    uint8_t data[PS2_QUEUE_SIZE];
 
75
    int rptr, wptr, count;
 
76
} PS2Queue;
 
77
 
 
78
typedef struct {
 
79
    PS2Queue queue;
 
80
    int32_t write_cmd;
 
81
    void (*update_irq)(void *, int);
 
82
    void *update_arg;
 
83
} PS2State;
 
84
 
 
85
typedef struct {
 
86
    PS2State common;
 
87
    int scan_enabled;
 
88
    /* Qemu uses translated PC scancodes internally.  To avoid multiple
 
89
       conversions we do the translation (if any) in the PS/2 emulation
 
90
       not the keyboard controller.  */
 
91
    int translate;
 
92
} PS2KbdState;
 
93
 
 
94
typedef struct {
 
95
    PS2State common;
 
96
    uint8_t mouse_status;
 
97
    uint8_t mouse_resolution;
 
98
    uint8_t mouse_sample_rate;
 
99
    uint8_t mouse_wrap;
 
100
    uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */
 
101
    uint8_t mouse_detect_state;
 
102
    int mouse_dx; /* current values, needed for 'poll' mode */
 
103
    int mouse_dy;
 
104
    int mouse_dz;
 
105
    uint8_t mouse_buttons;
 
106
} PS2MouseState;
 
107
 
 
108
/* Table to convert from PC scancodes to raw scancodes.  */
 
109
static const unsigned char ps2_raw_keycode[128] = {
 
110
          0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
 
111
         21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
 
112
         35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
 
113
         50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88,  5,  6,  4, 12,  3,
 
114
         11,  2, 10,  1,  9,119,126,108,117,125,123,107,115,116,121,105,
 
115
        114,122,112,113,127, 96, 97,120,  7, 15, 23, 31, 39, 47, 55, 63,
 
116
         71, 79, 86, 94,  8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
 
117
         19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
 
118
};
 
119
 
 
120
void ps2_queue(void *opaque, int b)
 
121
{
 
122
    PS2State *s = (PS2State *)opaque;
 
123
    PS2Queue *q = &s->queue;
 
124
 
 
125
    if (q->count >= PS2_QUEUE_SIZE)
 
126
        return;
 
127
    q->data[q->wptr] = b;
 
128
    if (++q->wptr == PS2_QUEUE_SIZE)
 
129
        q->wptr = 0;
 
130
    q->count++;
 
131
    s->update_irq(s->update_arg, 1);
 
132
}
 
133
 
 
134
static void ps2_put_keycode(void *opaque, int keycode)
 
135
{
 
136
    PS2KbdState *s = opaque;
 
137
    if (!s->translate && keycode < 0xe0)
 
138
      {
 
139
        if (keycode & 0x80)
 
140
            ps2_queue(&s->common, 0xf0);
 
141
        keycode = ps2_raw_keycode[keycode & 0x7f];
 
142
      }
 
143
    ps2_queue(&s->common, keycode);
 
144
}
 
145
 
 
146
uint32_t ps2_read_data(void *opaque)
 
147
{
 
148
    PS2State *s = (PS2State *)opaque;
 
149
    PS2Queue *q;
 
150
    int val, index;
 
151
 
 
152
    q = &s->queue;
 
153
    if (q->count == 0) {
 
154
        /* NOTE: if no data left, we return the last keyboard one
 
155
           (needed for EMM386) */
 
156
        /* XXX: need a timer to do things correctly */
 
157
        index = q->rptr - 1;
 
158
        if (index < 0)
 
159
            index = PS2_QUEUE_SIZE - 1;
 
160
        val = q->data[index];
 
161
    } else {
 
162
        val = q->data[q->rptr];
 
163
        if (++q->rptr == PS2_QUEUE_SIZE)
 
164
            q->rptr = 0;
 
165
        q->count--;
 
166
        /* reading deasserts IRQ */
 
167
        s->update_irq(s->update_arg, 0);
 
168
        /* reassert IRQs if data left */
 
169
        s->update_irq(s->update_arg, q->count != 0);
 
170
    }
 
171
    return val;
 
172
}
 
173
 
 
174
static void ps2_reset_keyboard(PS2KbdState *s)
 
175
{
 
176
    s->scan_enabled = 1;
 
177
}
 
178
 
 
179
void ps2_write_keyboard(void *opaque, int val)
 
180
{
 
181
    PS2KbdState *s = (PS2KbdState *)opaque;
 
182
 
 
183
    switch(s->common.write_cmd) {
 
184
    default:
 
185
    case -1:
 
186
        switch(val) {
 
187
        case 0x00:
 
188
            ps2_queue(&s->common, KBD_REPLY_ACK);
 
189
            break;
 
190
        case 0x05:
 
191
            ps2_queue(&s->common, KBD_REPLY_RESEND);
 
192
            break;
 
193
        case KBD_CMD_GET_ID:
 
194
            ps2_queue(&s->common, KBD_REPLY_ACK);
 
195
            ps2_queue(&s->common, 0xab);
 
196
            ps2_queue(&s->common, 0x83);
 
197
            break;
 
198
        case KBD_CMD_ECHO:
 
199
            ps2_queue(&s->common, KBD_CMD_ECHO);
 
200
            break;
 
201
        case KBD_CMD_ENABLE:
 
202
            s->scan_enabled = 1;
 
203
            ps2_queue(&s->common, KBD_REPLY_ACK);
 
204
            break;
 
205
        case KBD_CMD_SET_LEDS:
 
206
        case KBD_CMD_SET_RATE:
 
207
            s->common.write_cmd = val;
 
208
            ps2_queue(&s->common, KBD_REPLY_ACK);
 
209
            break;
 
210
        case KBD_CMD_RESET_DISABLE:
 
211
            ps2_reset_keyboard(s);
 
212
            s->scan_enabled = 0;
 
213
            ps2_queue(&s->common, KBD_REPLY_ACK);
 
214
            break;
 
215
        case KBD_CMD_RESET_ENABLE:
 
216
            ps2_reset_keyboard(s);
 
217
            s->scan_enabled = 1;
 
218
            ps2_queue(&s->common, KBD_REPLY_ACK);
 
219
            break;
 
220
        case KBD_CMD_RESET:
 
221
            ps2_reset_keyboard(s);
 
222
            ps2_queue(&s->common, KBD_REPLY_ACK);
 
223
            ps2_queue(&s->common, KBD_REPLY_POR);
 
224
            break;
 
225
        default:
 
226
            ps2_queue(&s->common, KBD_REPLY_ACK);
 
227
            break;
 
228
        }
 
229
        break;
 
230
    case KBD_CMD_SET_LEDS:
 
231
        ps2_queue(&s->common, KBD_REPLY_ACK);
 
232
        s->common.write_cmd = -1;
 
233
        break;
 
234
    case KBD_CMD_SET_RATE:
 
235
        ps2_queue(&s->common, KBD_REPLY_ACK);
 
236
        s->common.write_cmd = -1;
 
237
        break;
 
238
    }
 
239
}
 
240
 
 
241
/* Set the scancode translation mode.
 
242
   0 = raw scancodes.
 
243
   1 = translated scancodes (used by qemu internally).  */
 
244
 
 
245
void ps2_keyboard_set_translation(void *opaque, int mode)
 
246
{
 
247
    PS2KbdState *s = (PS2KbdState *)opaque;
 
248
    s->translate = mode;
 
249
}
 
250
 
 
251
static void ps2_mouse_send_packet(PS2MouseState *s)
 
252
{
 
253
    unsigned int b;
 
254
    int dx1, dy1, dz1;
 
255
 
 
256
    dx1 = s->mouse_dx;
 
257
    dy1 = s->mouse_dy;
 
258
    dz1 = s->mouse_dz;
 
259
    /* XXX: increase range to 8 bits ? */
 
260
    if (dx1 > 127)
 
261
        dx1 = 127;
 
262
    else if (dx1 < -127)
 
263
        dx1 = -127;
 
264
    if (dy1 > 127)
 
265
        dy1 = 127;
 
266
    else if (dy1 < -127)
 
267
        dy1 = -127;
 
268
    b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
 
269
    ps2_queue(&s->common, b);
 
270
    ps2_queue(&s->common, dx1 & 0xff);
 
271
    ps2_queue(&s->common, dy1 & 0xff);
 
272
    /* extra byte for IMPS/2 or IMEX */
 
273
    switch(s->mouse_type) {
 
274
    default:
 
275
        break;
 
276
    case 3:
 
277
        if (dz1 > 127)
 
278
            dz1 = 127;
 
279
        else if (dz1 < -127)
 
280
                dz1 = -127;
 
281
        ps2_queue(&s->common, dz1 & 0xff);
 
282
        break;
 
283
    case 4:
 
284
        if (dz1 > 7)
 
285
            dz1 = 7;
 
286
        else if (dz1 < -7)
 
287
            dz1 = -7;
 
288
        b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
 
289
        ps2_queue(&s->common, b);
 
290
        break;
 
291
    }
 
292
 
 
293
    /* update deltas */
 
294
    s->mouse_dx -= dx1;
 
295
    s->mouse_dy -= dy1;
 
296
    s->mouse_dz -= dz1;
 
297
}
 
298
 
 
299
static void ps2_mouse_event(void *opaque,
 
300
                            int dx, int dy, int dz, int buttons_state)
 
301
{
 
302
    PS2MouseState *s = opaque;
 
303
 
 
304
    /* check if deltas are recorded when disabled */
 
305
    if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
 
306
        return;
 
307
 
 
308
    s->mouse_dx += dx;
 
309
    s->mouse_dy -= dy;
 
310
    s->mouse_dz += dz;
 
311
    /* XXX: SDL sometimes generates nul events: we delete them */
 
312
    if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0 &&
 
313
        s->mouse_buttons == buttons_state)
 
314
        return;
 
315
    s->mouse_buttons = buttons_state;
 
316
 
 
317
    if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
 
318
        (s->common.queue.count < (PS2_QUEUE_SIZE - 16))) {
 
319
        for(;;) {
 
320
            /* if not remote, send event. Multiple events are sent if
 
321
               too big deltas */
 
322
            ps2_mouse_send_packet(s);
 
323
            if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
 
324
                break;
 
325
        }
 
326
    }
 
327
}
 
328
 
 
329
void ps2_mouse_fake_event(void *opaque)
 
330
{
 
331
    ps2_mouse_event(opaque, 1, 0, 0, 0);
 
332
}
 
333
 
 
334
void ps2_write_mouse(void *opaque, int val)
 
335
{
 
336
    PS2MouseState *s = (PS2MouseState *)opaque;
 
337
#ifdef DEBUG_MOUSE
 
338
    printf("kbd: write mouse 0x%02x\n", val);
 
339
#endif
 
340
    switch(s->common.write_cmd) {
 
341
    default:
 
342
    case -1:
 
343
        /* mouse command */
 
344
        if (s->mouse_wrap) {
 
345
            if (val == AUX_RESET_WRAP) {
 
346
                s->mouse_wrap = 0;
 
347
                ps2_queue(&s->common, AUX_ACK);
 
348
                return;
 
349
            } else if (val != AUX_RESET) {
 
350
                ps2_queue(&s->common, val);
 
351
                return;
 
352
            }
 
353
        }
 
354
        switch(val) {
 
355
        case AUX_SET_SCALE11:
 
356
            s->mouse_status &= ~MOUSE_STATUS_SCALE21;
 
357
            ps2_queue(&s->common, AUX_ACK);
 
358
            break;
 
359
        case AUX_SET_SCALE21:
 
360
            s->mouse_status |= MOUSE_STATUS_SCALE21;
 
361
            ps2_queue(&s->common, AUX_ACK);
 
362
            break;
 
363
        case AUX_SET_STREAM:
 
364
            s->mouse_status &= ~MOUSE_STATUS_REMOTE;
 
365
            ps2_queue(&s->common, AUX_ACK);
 
366
            break;
 
367
        case AUX_SET_WRAP:
 
368
            s->mouse_wrap = 1;
 
369
            ps2_queue(&s->common, AUX_ACK);
 
370
            break;
 
371
        case AUX_SET_REMOTE:
 
372
            s->mouse_status |= MOUSE_STATUS_REMOTE;
 
373
            ps2_queue(&s->common, AUX_ACK);
 
374
            break;
 
375
        case AUX_GET_TYPE:
 
376
            ps2_queue(&s->common, AUX_ACK);
 
377
            ps2_queue(&s->common, s->mouse_type);
 
378
            break;
 
379
        case AUX_SET_RES:
 
380
        case AUX_SET_SAMPLE:
 
381
            s->common.write_cmd = val;
 
382
            ps2_queue(&s->common, AUX_ACK);
 
383
            break;
 
384
        case AUX_GET_SCALE:
 
385
            ps2_queue(&s->common, AUX_ACK);
 
386
            ps2_queue(&s->common, s->mouse_status);
 
387
            ps2_queue(&s->common, s->mouse_resolution);
 
388
            ps2_queue(&s->common, s->mouse_sample_rate);
 
389
            break;
 
390
        case AUX_POLL:
 
391
            ps2_queue(&s->common, AUX_ACK);
 
392
            ps2_mouse_send_packet(s);
 
393
            break;
 
394
        case AUX_ENABLE_DEV:
 
395
            s->mouse_status |= MOUSE_STATUS_ENABLED;
 
396
            ps2_queue(&s->common, AUX_ACK);
 
397
            break;
 
398
        case AUX_DISABLE_DEV:
 
399
            s->mouse_status &= ~MOUSE_STATUS_ENABLED;
 
400
            ps2_queue(&s->common, AUX_ACK);
 
401
            break;
 
402
        case AUX_SET_DEFAULT:
 
403
            s->mouse_sample_rate = 100;
 
404
            s->mouse_resolution = 2;
 
405
            s->mouse_status = 0;
 
406
            ps2_queue(&s->common, AUX_ACK);
 
407
            break;
 
408
        case AUX_RESET:
 
409
            s->mouse_sample_rate = 100;
 
410
            s->mouse_resolution = 2;
 
411
            s->mouse_status = 0;
 
412
            s->mouse_type = 0;
 
413
            ps2_queue(&s->common, AUX_ACK);
 
414
            ps2_queue(&s->common, 0xaa);
 
415
            ps2_queue(&s->common, s->mouse_type);
 
416
            break;
 
417
        default:
 
418
            break;
 
419
        }
 
420
        break;
 
421
    case AUX_SET_SAMPLE:
 
422
        s->mouse_sample_rate = val;
 
423
        /* detect IMPS/2 or IMEX */
 
424
        switch(s->mouse_detect_state) {
 
425
        default:
 
426
        case 0:
 
427
            if (val == 200)
 
428
                s->mouse_detect_state = 1;
 
429
            break;
 
430
        case 1:
 
431
            if (val == 100)
 
432
                s->mouse_detect_state = 2;
 
433
            else if (val == 200)
 
434
                s->mouse_detect_state = 3;
 
435
            else
 
436
                s->mouse_detect_state = 0;
 
437
            break;
 
438
        case 2:
 
439
            if (val == 80)
 
440
                s->mouse_type = 3; /* IMPS/2 */
 
441
            s->mouse_detect_state = 0;
 
442
            break;
 
443
        case 3:
 
444
            if (val == 80)
 
445
                s->mouse_type = 4; /* IMEX */
 
446
            s->mouse_detect_state = 0;
 
447
            break;
 
448
        }
 
449
        ps2_queue(&s->common, AUX_ACK);
 
450
        s->common.write_cmd = -1;
 
451
        break;
 
452
    case AUX_SET_RES:
 
453
        s->mouse_resolution = val;
 
454
        ps2_queue(&s->common, AUX_ACK);
 
455
        s->common.write_cmd = -1;
 
456
        break;
 
457
    }
 
458
}
 
459
 
 
460
static void ps2_reset(void *opaque)
 
461
{
 
462
    PS2State *s = (PS2State *)opaque;
 
463
    PS2Queue *q;
 
464
    s->write_cmd = -1;
 
465
    q = &s->queue;
 
466
    q->rptr = 0;
 
467
    q->wptr = 0;
 
468
    q->count = 0;
 
469
}
 
470
 
 
471
static void ps2_common_save (QEMUFile *f, PS2State *s)
 
472
{
 
473
    qemu_put_be32 (f, s->write_cmd);
 
474
    qemu_put_be32 (f, s->queue.rptr);
 
475
    qemu_put_be32 (f, s->queue.wptr);
 
476
    qemu_put_be32 (f, s->queue.count);
 
477
    qemu_put_buffer (f, s->queue.data, sizeof (s->queue.data));
 
478
}
 
479
 
 
480
static void ps2_common_load (QEMUFile *f, PS2State *s)
 
481
{
 
482
    s->write_cmd=qemu_get_be32 (f);
 
483
    s->queue.rptr=qemu_get_be32 (f);
 
484
    s->queue.wptr=qemu_get_be32 (f);
 
485
    s->queue.count=qemu_get_be32 (f);
 
486
    qemu_get_buffer (f, s->queue.data, sizeof (s->queue.data));
 
487
}
 
488
 
 
489
static void ps2_kbd_save(QEMUFile* f, void* opaque)
 
490
{
 
491
    PS2KbdState *s = (PS2KbdState*)opaque;
 
492
 
 
493
    ps2_common_save (f, &s->common);
 
494
    qemu_put_be32(f, s->scan_enabled);
 
495
    qemu_put_be32(f, s->translate);
 
496
}
 
497
 
 
498
static void ps2_mouse_save(QEMUFile* f, void* opaque)
 
499
{
 
500
    PS2MouseState *s = (PS2MouseState*)opaque;
 
501
 
 
502
    ps2_common_save (f, &s->common);
 
503
    qemu_put_8s(f, &s->mouse_status);
 
504
    qemu_put_8s(f, &s->mouse_resolution);
 
505
    qemu_put_8s(f, &s->mouse_sample_rate);
 
506
    qemu_put_8s(f, &s->mouse_wrap);
 
507
    qemu_put_8s(f, &s->mouse_type);
 
508
    qemu_put_8s(f, &s->mouse_detect_state);
 
509
    qemu_put_be32(f, s->mouse_dx);
 
510
    qemu_put_be32(f, s->mouse_dy);
 
511
    qemu_put_be32(f, s->mouse_dz);
 
512
    qemu_put_8s(f, &s->mouse_buttons);
 
513
}
 
514
 
 
515
static int ps2_kbd_load(QEMUFile* f, void* opaque, int version_id)
 
516
{
 
517
    PS2KbdState *s = (PS2KbdState*)opaque;
 
518
 
 
519
    if (version_id != 2)
 
520
        return -EINVAL;
 
521
 
 
522
    ps2_common_load (f, &s->common);
 
523
    s->scan_enabled=qemu_get_be32(f);
 
524
    s->translate=qemu_get_be32(f);
 
525
    return 0;
 
526
}
 
527
 
 
528
static int ps2_mouse_load(QEMUFile* f, void* opaque, int version_id)
 
529
{
 
530
    PS2MouseState *s = (PS2MouseState*)opaque;
 
531
 
 
532
    if (version_id != 2)
 
533
        return -EINVAL;
 
534
 
 
535
    ps2_common_load (f, &s->common);
 
536
    qemu_get_8s(f, &s->mouse_status);
 
537
    qemu_get_8s(f, &s->mouse_resolution);
 
538
    qemu_get_8s(f, &s->mouse_sample_rate);
 
539
    qemu_get_8s(f, &s->mouse_wrap);
 
540
    qemu_get_8s(f, &s->mouse_type);
 
541
    qemu_get_8s(f, &s->mouse_detect_state);
 
542
    s->mouse_dx=qemu_get_be32(f);
 
543
    s->mouse_dy=qemu_get_be32(f);
 
544
    s->mouse_dz=qemu_get_be32(f);
 
545
    qemu_get_8s(f, &s->mouse_buttons);
 
546
    return 0;
 
547
}
 
548
 
 
549
void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
 
550
{
 
551
    PS2KbdState *s = (PS2KbdState *)qemu_mallocz(sizeof(PS2KbdState));
 
552
 
 
553
    s->common.update_irq = update_irq;
 
554
    s->common.update_arg = update_arg;
 
555
    ps2_reset(&s->common);
 
556
    register_savevm("ps2kbd", 0, 2, ps2_kbd_save, ps2_kbd_load, s);
 
557
    qemu_add_kbd_event_handler(ps2_put_keycode, s);
 
558
    qemu_register_reset(ps2_reset, &s->common);
 
559
    return s;
 
560
}
 
561
 
 
562
void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
 
563
{
 
564
    PS2MouseState *s = (PS2MouseState *)qemu_mallocz(sizeof(PS2MouseState));
 
565
 
 
566
    s->common.update_irq = update_irq;
 
567
    s->common.update_arg = update_arg;
 
568
    ps2_reset(&s->common);
 
569
    register_savevm("ps2mouse", 0, 2, ps2_mouse_save, ps2_mouse_load, s);
 
570
    qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse");
 
571
    qemu_register_reset(ps2_reset, &s->common);
 
572
    return s;
 
573
}