2
* QEMU PS/2 keyboard/mouse emulation
4
* Copyright (c) 2003 Fabrice Bellard
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:
13
* The above copyright notice and this permission notice shall be included in
14
* all copies or substantial portions of the Software.
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
28
/* debug PC keyboard */
31
/* debug PC keyboard : only mouse */
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 */
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 */
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. */
67
#define MOUSE_STATUS_REMOTE 0x40
68
#define MOUSE_STATUS_ENABLED 0x20
69
#define MOUSE_STATUS_SCALE21 0x10
71
#define PS2_QUEUE_SIZE 256
74
uint8_t data[PS2_QUEUE_SIZE];
75
int rptr, wptr, count;
81
void (*update_irq)(void *, int);
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. */
97
uint8_t mouse_resolution;
98
uint8_t mouse_sample_rate;
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 */
105
uint8_t mouse_buttons;
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
120
void ps2_queue(void *opaque, int b)
122
PS2State *s = (PS2State *)opaque;
123
PS2Queue *q = &s->queue;
125
if (q->count >= PS2_QUEUE_SIZE)
127
q->data[q->wptr] = b;
128
if (++q->wptr == PS2_QUEUE_SIZE)
131
s->update_irq(s->update_arg, 1);
134
static void ps2_put_keycode(void *opaque, int keycode)
136
PS2KbdState *s = opaque;
137
if (!s->translate && keycode < 0xe0)
140
ps2_queue(&s->common, 0xf0);
141
keycode = ps2_raw_keycode[keycode & 0x7f];
143
ps2_queue(&s->common, keycode);
146
uint32_t ps2_read_data(void *opaque)
148
PS2State *s = (PS2State *)opaque;
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 */
159
index = PS2_QUEUE_SIZE - 1;
160
val = q->data[index];
162
val = q->data[q->rptr];
163
if (++q->rptr == PS2_QUEUE_SIZE)
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);
174
static void ps2_reset_keyboard(PS2KbdState *s)
179
void ps2_write_keyboard(void *opaque, int val)
181
PS2KbdState *s = (PS2KbdState *)opaque;
183
switch(s->common.write_cmd) {
188
ps2_queue(&s->common, KBD_REPLY_ACK);
191
ps2_queue(&s->common, KBD_REPLY_RESEND);
194
ps2_queue(&s->common, KBD_REPLY_ACK);
195
ps2_queue(&s->common, 0xab);
196
ps2_queue(&s->common, 0x83);
199
ps2_queue(&s->common, KBD_CMD_ECHO);
203
ps2_queue(&s->common, KBD_REPLY_ACK);
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);
210
case KBD_CMD_RESET_DISABLE:
211
ps2_reset_keyboard(s);
213
ps2_queue(&s->common, KBD_REPLY_ACK);
215
case KBD_CMD_RESET_ENABLE:
216
ps2_reset_keyboard(s);
218
ps2_queue(&s->common, KBD_REPLY_ACK);
221
ps2_reset_keyboard(s);
222
ps2_queue(&s->common, KBD_REPLY_ACK);
223
ps2_queue(&s->common, KBD_REPLY_POR);
226
ps2_queue(&s->common, KBD_REPLY_ACK);
230
case KBD_CMD_SET_LEDS:
231
ps2_queue(&s->common, KBD_REPLY_ACK);
232
s->common.write_cmd = -1;
234
case KBD_CMD_SET_RATE:
235
ps2_queue(&s->common, KBD_REPLY_ACK);
236
s->common.write_cmd = -1;
241
/* Set the scancode translation mode.
243
1 = translated scancodes (used by qemu internally). */
245
void ps2_keyboard_set_translation(void *opaque, int mode)
247
PS2KbdState *s = (PS2KbdState *)opaque;
251
static void ps2_mouse_send_packet(PS2MouseState *s)
259
/* XXX: increase range to 8 bits ? */
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) {
281
ps2_queue(&s->common, dz1 & 0xff);
288
b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
289
ps2_queue(&s->common, b);
299
static void ps2_mouse_event(void *opaque,
300
int dx, int dy, int dz, int buttons_state)
302
PS2MouseState *s = opaque;
304
/* check if deltas are recorded when disabled */
305
if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
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)
315
s->mouse_buttons = buttons_state;
317
if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
318
(s->common.queue.count < (PS2_QUEUE_SIZE - 16))) {
320
/* if not remote, send event. Multiple events are sent if
322
ps2_mouse_send_packet(s);
323
if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
329
void ps2_mouse_fake_event(void *opaque)
331
ps2_mouse_event(opaque, 1, 0, 0, 0);
334
void ps2_write_mouse(void *opaque, int val)
336
PS2MouseState *s = (PS2MouseState *)opaque;
338
printf("kbd: write mouse 0x%02x\n", val);
340
switch(s->common.write_cmd) {
345
if (val == AUX_RESET_WRAP) {
347
ps2_queue(&s->common, AUX_ACK);
349
} else if (val != AUX_RESET) {
350
ps2_queue(&s->common, val);
355
case AUX_SET_SCALE11:
356
s->mouse_status &= ~MOUSE_STATUS_SCALE21;
357
ps2_queue(&s->common, AUX_ACK);
359
case AUX_SET_SCALE21:
360
s->mouse_status |= MOUSE_STATUS_SCALE21;
361
ps2_queue(&s->common, AUX_ACK);
364
s->mouse_status &= ~MOUSE_STATUS_REMOTE;
365
ps2_queue(&s->common, AUX_ACK);
369
ps2_queue(&s->common, AUX_ACK);
372
s->mouse_status |= MOUSE_STATUS_REMOTE;
373
ps2_queue(&s->common, AUX_ACK);
376
ps2_queue(&s->common, AUX_ACK);
377
ps2_queue(&s->common, s->mouse_type);
381
s->common.write_cmd = val;
382
ps2_queue(&s->common, AUX_ACK);
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);
391
ps2_queue(&s->common, AUX_ACK);
392
ps2_mouse_send_packet(s);
395
s->mouse_status |= MOUSE_STATUS_ENABLED;
396
ps2_queue(&s->common, AUX_ACK);
398
case AUX_DISABLE_DEV:
399
s->mouse_status &= ~MOUSE_STATUS_ENABLED;
400
ps2_queue(&s->common, AUX_ACK);
402
case AUX_SET_DEFAULT:
403
s->mouse_sample_rate = 100;
404
s->mouse_resolution = 2;
406
ps2_queue(&s->common, AUX_ACK);
409
s->mouse_sample_rate = 100;
410
s->mouse_resolution = 2;
413
ps2_queue(&s->common, AUX_ACK);
414
ps2_queue(&s->common, 0xaa);
415
ps2_queue(&s->common, s->mouse_type);
422
s->mouse_sample_rate = val;
423
/* detect IMPS/2 or IMEX */
424
switch(s->mouse_detect_state) {
428
s->mouse_detect_state = 1;
432
s->mouse_detect_state = 2;
434
s->mouse_detect_state = 3;
436
s->mouse_detect_state = 0;
440
s->mouse_type = 3; /* IMPS/2 */
441
s->mouse_detect_state = 0;
445
s->mouse_type = 4; /* IMEX */
446
s->mouse_detect_state = 0;
449
ps2_queue(&s->common, AUX_ACK);
450
s->common.write_cmd = -1;
453
s->mouse_resolution = val;
454
ps2_queue(&s->common, AUX_ACK);
455
s->common.write_cmd = -1;
460
static void ps2_reset(void *opaque)
462
PS2State *s = (PS2State *)opaque;
471
static void ps2_common_save (QEMUFile *f, PS2State *s)
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));
480
static void ps2_common_load (QEMUFile *f, PS2State *s)
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));
489
static void ps2_kbd_save(QEMUFile* f, void* opaque)
491
PS2KbdState *s = (PS2KbdState*)opaque;
493
ps2_common_save (f, &s->common);
494
qemu_put_be32(f, s->scan_enabled);
495
qemu_put_be32(f, s->translate);
498
static void ps2_mouse_save(QEMUFile* f, void* opaque)
500
PS2MouseState *s = (PS2MouseState*)opaque;
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);
515
static int ps2_kbd_load(QEMUFile* f, void* opaque, int version_id)
517
PS2KbdState *s = (PS2KbdState*)opaque;
522
ps2_common_load (f, &s->common);
523
s->scan_enabled=qemu_get_be32(f);
524
s->translate=qemu_get_be32(f);
528
static int ps2_mouse_load(QEMUFile* f, void* opaque, int version_id)
530
PS2MouseState *s = (PS2MouseState*)opaque;
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);
549
void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
551
PS2KbdState *s = (PS2KbdState *)qemu_mallocz(sizeof(PS2KbdState));
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);
562
void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
564
PS2MouseState *s = (PS2MouseState *)qemu_mallocz(sizeof(PS2MouseState));
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);