ps2: allow keycode translation for all scancode sets
[qemu.git] / hw / input / ps2.c
blob3636dfb686f7df50bf715004090ad8c9a576b6df
1 /*
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
22 * THE SOFTWARE.
24 #include "qemu/osdep.h"
25 #include "hw/hw.h"
26 #include "hw/input/ps2.h"
27 #include "ui/console.h"
28 #include "ui/input.h"
29 #include "sysemu/sysemu.h"
31 #include "trace.h"
33 /* debug PC keyboard */
34 //#define DEBUG_KBD
36 /* debug PC keyboard : only mouse */
37 //#define DEBUG_MOUSE
39 /* Keyboard Commands */
40 #define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */
41 #define KBD_CMD_ECHO 0xEE
42 #define KBD_CMD_SCANCODE 0xF0 /* Get/set scancode set */
43 #define KBD_CMD_GET_ID 0xF2 /* get keyboard ID */
44 #define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */
45 #define KBD_CMD_ENABLE 0xF4 /* Enable scanning */
46 #define KBD_CMD_RESET_DISABLE 0xF5 /* reset and disable scanning */
47 #define KBD_CMD_RESET_ENABLE 0xF6 /* reset and enable scanning */
48 #define KBD_CMD_RESET 0xFF /* Reset */
50 /* Keyboard Replies */
51 #define KBD_REPLY_POR 0xAA /* Power on reset */
52 #define KBD_REPLY_ID 0xAB /* Keyboard ID */
53 #define KBD_REPLY_ACK 0xFA /* Command ACK */
54 #define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */
56 /* Mouse Commands */
57 #define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */
58 #define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */
59 #define AUX_SET_RES 0xE8 /* Set resolution */
60 #define AUX_GET_SCALE 0xE9 /* Get scaling factor */
61 #define AUX_SET_STREAM 0xEA /* Set stream mode */
62 #define AUX_POLL 0xEB /* Poll */
63 #define AUX_RESET_WRAP 0xEC /* Reset wrap mode */
64 #define AUX_SET_WRAP 0xEE /* Set wrap mode */
65 #define AUX_SET_REMOTE 0xF0 /* Set remote mode */
66 #define AUX_GET_TYPE 0xF2 /* Get type */
67 #define AUX_SET_SAMPLE 0xF3 /* Set sample rate */
68 #define AUX_ENABLE_DEV 0xF4 /* Enable aux device */
69 #define AUX_DISABLE_DEV 0xF5 /* Disable aux device */
70 #define AUX_SET_DEFAULT 0xF6
71 #define AUX_RESET 0xFF /* Reset aux device */
72 #define AUX_ACK 0xFA /* Command byte ACK. */
74 #define MOUSE_STATUS_REMOTE 0x40
75 #define MOUSE_STATUS_ENABLED 0x20
76 #define MOUSE_STATUS_SCALE21 0x10
78 #define PS2_QUEUE_SIZE 16 /* Buffer size required by PS/2 protocol */
80 typedef struct {
81 /* Keep the data array 256 bytes long, which compatibility
82 with older qemu versions. */
83 uint8_t data[256];
84 int rptr, wptr, count;
85 } PS2Queue;
87 typedef struct {
88 PS2Queue queue;
89 int32_t write_cmd;
90 void (*update_irq)(void *, int);
91 void *update_arg;
92 } PS2State;
94 typedef struct {
95 PS2State common;
96 int scan_enabled;
97 int translate;
98 int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */
99 int ledstate;
100 bool need_high_bit;
101 } PS2KbdState;
103 typedef struct {
104 PS2State common;
105 uint8_t mouse_status;
106 uint8_t mouse_resolution;
107 uint8_t mouse_sample_rate;
108 uint8_t mouse_wrap;
109 uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */
110 uint8_t mouse_detect_state;
111 int mouse_dx; /* current values, needed for 'poll' mode */
112 int mouse_dy;
113 int mouse_dz;
114 uint8_t mouse_buttons;
115 } PS2MouseState;
117 /* Table to convert from PC scancodes to raw scancodes. */
118 static const unsigned char ps2_raw_keycode[128] = {
119 0, 118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85, 102, 13,
120 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
121 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
122 50, 49, 58, 65, 73, 74, 89, 124, 17, 41, 88, 5, 6, 4, 12, 3,
123 11, 2, 10, 1, 9, 119, 126, 108, 117, 125, 123, 107, 115, 116, 121, 105,
124 114, 122, 112, 113, 127, 96, 97, 120, 7, 15, 23, 31, 39, 47, 55, 63,
125 71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87, 111,
126 19, 25, 57, 81, 83, 92, 95, 98, 99, 100, 101, 103, 104, 106, 109, 110
128 static const unsigned char ps2_raw_keycode_set3[128] = {
129 0, 8, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85, 102, 13,
130 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 17, 28, 27,
131 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 92, 26, 34, 33, 42,
132 50, 49, 58, 65, 73, 74, 89, 126, 25, 41, 20, 7, 15, 23, 31, 39,
133 47, 2, 63, 71, 79, 118, 95, 108, 117, 125, 132, 107, 115, 116, 124, 105,
134 114, 122, 112, 113, 127, 96, 97, 86, 94, 15, 23, 31, 39, 47, 55, 63,
135 71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87, 111,
136 19, 25, 57, 81, 83, 92, 95, 98, 99, 100, 101, 103, 104, 106, 109, 110
139 static uint8_t translate_table[256] = {
140 0xff, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58,
141 0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59,
142 0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a,
143 0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b,
144 0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c,
145 0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d,
146 0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e,
147 0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f,
148 0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60,
149 0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61,
150 0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e,
151 0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76,
152 0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b,
153 0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f,
154 0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45,
155 0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54,
156 0x80, 0x81, 0x82, 0x41, 0x54, 0x85, 0x86, 0x87,
157 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
158 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
159 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
160 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
161 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
162 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
163 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
164 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
165 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
166 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
167 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
168 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
169 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
170 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
171 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
174 void ps2_queue(void *opaque, int b)
176 PS2State *s = (PS2State *)opaque;
177 PS2Queue *q = &s->queue;
179 if (q->count >= PS2_QUEUE_SIZE - 1)
180 return;
181 q->data[q->wptr] = b;
182 if (++q->wptr == PS2_QUEUE_SIZE)
183 q->wptr = 0;
184 q->count++;
185 s->update_irq(s->update_arg, 1);
188 /* keycode is the untranslated scancode in the current scancode set. */
189 static void ps2_put_keycode(void *opaque, int keycode)
191 PS2KbdState *s = opaque;
193 trace_ps2_put_keycode(opaque, keycode);
194 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
196 if (s->translate) {
197 if (keycode == 0xf0) {
198 s->need_high_bit = true;
199 } else if (s->need_high_bit) {
200 ps2_queue(&s->common, translate_table[keycode] | 0x80);
201 s->need_high_bit = false;
202 } else {
203 ps2_queue(&s->common, translate_table[keycode]);
205 } else {
206 ps2_queue(&s->common, keycode);
210 static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,
211 InputEvent *evt)
213 PS2KbdState *s = (PS2KbdState *)dev;
214 int scancodes[3], i, count;
215 InputKeyEvent *key = evt->u.key.data;
216 int keycode;
218 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
219 count = qemu_input_key_value_to_scancode(key->key,
220 key->down,
221 scancodes);
223 /* handle invalid key */
224 if (count == 1 && scancodes[0] == 0x00) {
225 ps2_queue(&s->common, 0x00);
226 return;
227 } else if (count == 1 && scancodes[0] == 0x80) {
228 if (s->translate || s->scancode_set == 1) {
229 ps2_queue(&s->common, 0x80);
230 } else {
231 ps2_queue(&s->common, 0xf0);
232 ps2_queue(&s->common, 0x00);
234 return;
237 for (i = 0; i < count; i++) {
238 /* XXX: add support for scancode set 1 */
239 keycode = scancodes[i];
240 if (keycode < 0xe0 && (s->scancode_set > 1 || s->translate)) {
241 if (keycode & 0x80) {
242 ps2_put_keycode(&s->common, 0xf0);
244 if (s->scancode_set == 1 || s->scancode_set == 2) {
245 keycode = ps2_raw_keycode[keycode & 0x7f];
246 } else if (s->scancode_set == 3) {
247 keycode = ps2_raw_keycode_set3[keycode & 0x7f];
250 ps2_put_keycode(s, keycode);
254 uint32_t ps2_read_data(void *opaque)
256 PS2State *s = (PS2State *)opaque;
257 PS2Queue *q;
258 int val, index;
260 trace_ps2_read_data(opaque);
261 q = &s->queue;
262 if (q->count == 0) {
263 /* NOTE: if no data left, we return the last keyboard one
264 (needed for EMM386) */
265 /* XXX: need a timer to do things correctly */
266 index = q->rptr - 1;
267 if (index < 0)
268 index = PS2_QUEUE_SIZE - 1;
269 val = q->data[index];
270 } else {
271 val = q->data[q->rptr];
272 if (++q->rptr == PS2_QUEUE_SIZE)
273 q->rptr = 0;
274 q->count--;
275 /* reading deasserts IRQ */
276 s->update_irq(s->update_arg, 0);
277 /* reassert IRQs if data left */
278 s->update_irq(s->update_arg, q->count != 0);
280 return val;
283 static void ps2_set_ledstate(PS2KbdState *s, int ledstate)
285 trace_ps2_set_ledstate(s, ledstate);
286 s->ledstate = ledstate;
287 kbd_put_ledstate(ledstate);
290 static void ps2_reset_keyboard(PS2KbdState *s)
292 trace_ps2_reset_keyboard(s);
293 s->scan_enabled = 1;
294 s->scancode_set = 2;
295 ps2_set_ledstate(s, 0);
298 void ps2_write_keyboard(void *opaque, int val)
300 PS2KbdState *s = (PS2KbdState *)opaque;
302 trace_ps2_write_keyboard(opaque, val);
303 switch(s->common.write_cmd) {
304 default:
305 case -1:
306 switch(val) {
307 case 0x00:
308 ps2_queue(&s->common, KBD_REPLY_ACK);
309 break;
310 case 0x05:
311 ps2_queue(&s->common, KBD_REPLY_RESEND);
312 break;
313 case KBD_CMD_GET_ID:
314 ps2_queue(&s->common, KBD_REPLY_ACK);
315 /* We emulate a MF2 AT keyboard here */
316 ps2_queue(&s->common, KBD_REPLY_ID);
317 if (s->translate)
318 ps2_queue(&s->common, 0x41);
319 else
320 ps2_queue(&s->common, 0x83);
321 break;
322 case KBD_CMD_ECHO:
323 ps2_queue(&s->common, KBD_CMD_ECHO);
324 break;
325 case KBD_CMD_ENABLE:
326 s->scan_enabled = 1;
327 ps2_queue(&s->common, KBD_REPLY_ACK);
328 break;
329 case KBD_CMD_SCANCODE:
330 case KBD_CMD_SET_LEDS:
331 case KBD_CMD_SET_RATE:
332 s->common.write_cmd = val;
333 ps2_queue(&s->common, KBD_REPLY_ACK);
334 break;
335 case KBD_CMD_RESET_DISABLE:
336 ps2_reset_keyboard(s);
337 s->scan_enabled = 0;
338 ps2_queue(&s->common, KBD_REPLY_ACK);
339 break;
340 case KBD_CMD_RESET_ENABLE:
341 ps2_reset_keyboard(s);
342 s->scan_enabled = 1;
343 ps2_queue(&s->common, KBD_REPLY_ACK);
344 break;
345 case KBD_CMD_RESET:
346 ps2_reset_keyboard(s);
347 ps2_queue(&s->common, KBD_REPLY_ACK);
348 ps2_queue(&s->common, KBD_REPLY_POR);
349 break;
350 default:
351 ps2_queue(&s->common, KBD_REPLY_RESEND);
352 break;
354 break;
355 case KBD_CMD_SCANCODE:
356 if (val == 0) {
357 ps2_queue(&s->common, KBD_REPLY_ACK);
358 ps2_put_keycode(s, s->scancode_set);
359 } else if (val >= 1 && val <= 3) {
360 s->scancode_set = val;
361 ps2_queue(&s->common, KBD_REPLY_ACK);
362 } else {
363 ps2_queue(&s->common, KBD_REPLY_RESEND);
365 s->common.write_cmd = -1;
366 break;
367 case KBD_CMD_SET_LEDS:
368 ps2_set_ledstate(s, val);
369 ps2_queue(&s->common, KBD_REPLY_ACK);
370 s->common.write_cmd = -1;
371 break;
372 case KBD_CMD_SET_RATE:
373 ps2_queue(&s->common, KBD_REPLY_ACK);
374 s->common.write_cmd = -1;
375 break;
379 /* Set the scancode translation mode.
380 0 = raw scancodes.
381 1 = translated scancodes (used by qemu internally). */
383 void ps2_keyboard_set_translation(void *opaque, int mode)
385 PS2KbdState *s = (PS2KbdState *)opaque;
386 trace_ps2_keyboard_set_translation(opaque, mode);
387 s->translate = mode;
390 static void ps2_mouse_send_packet(PS2MouseState *s)
392 unsigned int b;
393 int dx1, dy1, dz1;
395 dx1 = s->mouse_dx;
396 dy1 = s->mouse_dy;
397 dz1 = s->mouse_dz;
398 /* XXX: increase range to 8 bits ? */
399 if (dx1 > 127)
400 dx1 = 127;
401 else if (dx1 < -127)
402 dx1 = -127;
403 if (dy1 > 127)
404 dy1 = 127;
405 else if (dy1 < -127)
406 dy1 = -127;
407 b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
408 ps2_queue(&s->common, b);
409 ps2_queue(&s->common, dx1 & 0xff);
410 ps2_queue(&s->common, dy1 & 0xff);
411 /* extra byte for IMPS/2 or IMEX */
412 switch(s->mouse_type) {
413 default:
414 break;
415 case 3:
416 if (dz1 > 127)
417 dz1 = 127;
418 else if (dz1 < -127)
419 dz1 = -127;
420 ps2_queue(&s->common, dz1 & 0xff);
421 break;
422 case 4:
423 if (dz1 > 7)
424 dz1 = 7;
425 else if (dz1 < -7)
426 dz1 = -7;
427 b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
428 ps2_queue(&s->common, b);
429 break;
432 trace_ps2_mouse_send_packet(s, dx1, dy1, dz1, b);
433 /* update deltas */
434 s->mouse_dx -= dx1;
435 s->mouse_dy -= dy1;
436 s->mouse_dz -= dz1;
439 static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
440 InputEvent *evt)
442 static const int bmap[INPUT_BUTTON__MAX] = {
443 [INPUT_BUTTON_LEFT] = MOUSE_EVENT_LBUTTON,
444 [INPUT_BUTTON_MIDDLE] = MOUSE_EVENT_MBUTTON,
445 [INPUT_BUTTON_RIGHT] = MOUSE_EVENT_RBUTTON,
447 PS2MouseState *s = (PS2MouseState *)dev;
448 InputMoveEvent *move;
449 InputBtnEvent *btn;
451 /* check if deltas are recorded when disabled */
452 if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
453 return;
455 switch (evt->type) {
456 case INPUT_EVENT_KIND_REL:
457 move = evt->u.rel.data;
458 if (move->axis == INPUT_AXIS_X) {
459 s->mouse_dx += move->value;
460 } else if (move->axis == INPUT_AXIS_Y) {
461 s->mouse_dy -= move->value;
463 break;
465 case INPUT_EVENT_KIND_BTN:
466 btn = evt->u.btn.data;
467 if (btn->down) {
468 s->mouse_buttons |= bmap[btn->button];
469 if (btn->button == INPUT_BUTTON_WHEEL_UP) {
470 s->mouse_dz--;
471 } else if (btn->button == INPUT_BUTTON_WHEEL_DOWN) {
472 s->mouse_dz++;
474 } else {
475 s->mouse_buttons &= ~bmap[btn->button];
477 break;
479 default:
480 /* keep gcc happy */
481 break;
485 static void ps2_mouse_sync(DeviceState *dev)
487 PS2MouseState *s = (PS2MouseState *)dev;
489 if (s->mouse_buttons) {
490 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
492 if (!(s->mouse_status & MOUSE_STATUS_REMOTE)) {
493 while (s->common.queue.count < PS2_QUEUE_SIZE - 4) {
494 /* if not remote, send event. Multiple events are sent if
495 too big deltas */
496 ps2_mouse_send_packet(s);
497 if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
498 break;
503 void ps2_mouse_fake_event(void *opaque)
505 PS2MouseState *s = opaque;
506 trace_ps2_mouse_fake_event(opaque);
507 s->mouse_dx++;
508 ps2_mouse_sync(opaque);
511 void ps2_write_mouse(void *opaque, int val)
513 PS2MouseState *s = (PS2MouseState *)opaque;
515 trace_ps2_write_mouse(opaque, val);
516 #ifdef DEBUG_MOUSE
517 printf("kbd: write mouse 0x%02x\n", val);
518 #endif
519 switch(s->common.write_cmd) {
520 default:
521 case -1:
522 /* mouse command */
523 if (s->mouse_wrap) {
524 if (val == AUX_RESET_WRAP) {
525 s->mouse_wrap = 0;
526 ps2_queue(&s->common, AUX_ACK);
527 return;
528 } else if (val != AUX_RESET) {
529 ps2_queue(&s->common, val);
530 return;
533 switch(val) {
534 case AUX_SET_SCALE11:
535 s->mouse_status &= ~MOUSE_STATUS_SCALE21;
536 ps2_queue(&s->common, AUX_ACK);
537 break;
538 case AUX_SET_SCALE21:
539 s->mouse_status |= MOUSE_STATUS_SCALE21;
540 ps2_queue(&s->common, AUX_ACK);
541 break;
542 case AUX_SET_STREAM:
543 s->mouse_status &= ~MOUSE_STATUS_REMOTE;
544 ps2_queue(&s->common, AUX_ACK);
545 break;
546 case AUX_SET_WRAP:
547 s->mouse_wrap = 1;
548 ps2_queue(&s->common, AUX_ACK);
549 break;
550 case AUX_SET_REMOTE:
551 s->mouse_status |= MOUSE_STATUS_REMOTE;
552 ps2_queue(&s->common, AUX_ACK);
553 break;
554 case AUX_GET_TYPE:
555 ps2_queue(&s->common, AUX_ACK);
556 ps2_queue(&s->common, s->mouse_type);
557 break;
558 case AUX_SET_RES:
559 case AUX_SET_SAMPLE:
560 s->common.write_cmd = val;
561 ps2_queue(&s->common, AUX_ACK);
562 break;
563 case AUX_GET_SCALE:
564 ps2_queue(&s->common, AUX_ACK);
565 ps2_queue(&s->common, s->mouse_status);
566 ps2_queue(&s->common, s->mouse_resolution);
567 ps2_queue(&s->common, s->mouse_sample_rate);
568 break;
569 case AUX_POLL:
570 ps2_queue(&s->common, AUX_ACK);
571 ps2_mouse_send_packet(s);
572 break;
573 case AUX_ENABLE_DEV:
574 s->mouse_status |= MOUSE_STATUS_ENABLED;
575 ps2_queue(&s->common, AUX_ACK);
576 break;
577 case AUX_DISABLE_DEV:
578 s->mouse_status &= ~MOUSE_STATUS_ENABLED;
579 ps2_queue(&s->common, AUX_ACK);
580 break;
581 case AUX_SET_DEFAULT:
582 s->mouse_sample_rate = 100;
583 s->mouse_resolution = 2;
584 s->mouse_status = 0;
585 ps2_queue(&s->common, AUX_ACK);
586 break;
587 case AUX_RESET:
588 s->mouse_sample_rate = 100;
589 s->mouse_resolution = 2;
590 s->mouse_status = 0;
591 s->mouse_type = 0;
592 ps2_queue(&s->common, AUX_ACK);
593 ps2_queue(&s->common, 0xaa);
594 ps2_queue(&s->common, s->mouse_type);
595 break;
596 default:
597 break;
599 break;
600 case AUX_SET_SAMPLE:
601 s->mouse_sample_rate = val;
602 /* detect IMPS/2 or IMEX */
603 switch(s->mouse_detect_state) {
604 default:
605 case 0:
606 if (val == 200)
607 s->mouse_detect_state = 1;
608 break;
609 case 1:
610 if (val == 100)
611 s->mouse_detect_state = 2;
612 else if (val == 200)
613 s->mouse_detect_state = 3;
614 else
615 s->mouse_detect_state = 0;
616 break;
617 case 2:
618 if (val == 80)
619 s->mouse_type = 3; /* IMPS/2 */
620 s->mouse_detect_state = 0;
621 break;
622 case 3:
623 if (val == 80)
624 s->mouse_type = 4; /* IMEX */
625 s->mouse_detect_state = 0;
626 break;
628 ps2_queue(&s->common, AUX_ACK);
629 s->common.write_cmd = -1;
630 break;
631 case AUX_SET_RES:
632 s->mouse_resolution = val;
633 ps2_queue(&s->common, AUX_ACK);
634 s->common.write_cmd = -1;
635 break;
639 static void ps2_common_reset(PS2State *s)
641 PS2Queue *q;
642 s->write_cmd = -1;
643 q = &s->queue;
644 q->rptr = 0;
645 q->wptr = 0;
646 q->count = 0;
647 s->update_irq(s->update_arg, 0);
650 static void ps2_common_post_load(PS2State *s)
652 PS2Queue *q = &s->queue;
653 int size;
654 int i;
655 int tmp_data[PS2_QUEUE_SIZE];
657 /* set the useful data buffer queue size, < PS2_QUEUE_SIZE */
658 size = q->count > PS2_QUEUE_SIZE ? 0 : q->count;
660 /* move the queue elements to the start of data array */
661 if (size > 0) {
662 for (i = 0; i < size; i++) {
663 /* move the queue elements to the temporary buffer */
664 tmp_data[i] = q->data[q->rptr];
665 if (++q->rptr == 256) {
666 q->rptr = 0;
669 memcpy(q->data, tmp_data, size);
671 /* reset rptr/wptr/count */
672 q->rptr = 0;
673 q->wptr = size;
674 q->count = size;
675 s->update_irq(s->update_arg, q->count != 0);
678 static void ps2_kbd_reset(void *opaque)
680 PS2KbdState *s = (PS2KbdState *) opaque;
682 trace_ps2_kbd_reset(opaque);
683 ps2_common_reset(&s->common);
684 s->scan_enabled = 0;
685 s->translate = 0;
686 s->scancode_set = 2;
689 static void ps2_mouse_reset(void *opaque)
691 PS2MouseState *s = (PS2MouseState *) opaque;
693 trace_ps2_mouse_reset(opaque);
694 ps2_common_reset(&s->common);
695 s->mouse_status = 0;
696 s->mouse_resolution = 0;
697 s->mouse_sample_rate = 0;
698 s->mouse_wrap = 0;
699 s->mouse_type = 0;
700 s->mouse_detect_state = 0;
701 s->mouse_dx = 0;
702 s->mouse_dy = 0;
703 s->mouse_dz = 0;
704 s->mouse_buttons = 0;
707 static const VMStateDescription vmstate_ps2_common = {
708 .name = "PS2 Common State",
709 .version_id = 3,
710 .minimum_version_id = 2,
711 .fields = (VMStateField[]) {
712 VMSTATE_INT32(write_cmd, PS2State),
713 VMSTATE_INT32(queue.rptr, PS2State),
714 VMSTATE_INT32(queue.wptr, PS2State),
715 VMSTATE_INT32(queue.count, PS2State),
716 VMSTATE_BUFFER(queue.data, PS2State),
717 VMSTATE_END_OF_LIST()
721 static bool ps2_keyboard_ledstate_needed(void *opaque)
723 PS2KbdState *s = opaque;
725 return s->ledstate != 0; /* 0 is default state */
728 static int ps2_kbd_ledstate_post_load(void *opaque, int version_id)
730 PS2KbdState *s = opaque;
732 kbd_put_ledstate(s->ledstate);
733 return 0;
736 static const VMStateDescription vmstate_ps2_keyboard_ledstate = {
737 .name = "ps2kbd/ledstate",
738 .version_id = 3,
739 .minimum_version_id = 2,
740 .post_load = ps2_kbd_ledstate_post_load,
741 .needed = ps2_keyboard_ledstate_needed,
742 .fields = (VMStateField[]) {
743 VMSTATE_INT32(ledstate, PS2KbdState),
744 VMSTATE_END_OF_LIST()
748 static bool ps2_keyboard_need_high_bit_needed(void *opaque)
750 PS2KbdState *s = opaque;
751 return s->need_high_bit != 0; /* 0 is the usual state */
754 static const VMStateDescription vmstate_ps2_keyboard_need_high_bit = {
755 .name = "ps2kbd/need_high_bit",
756 .version_id = 1,
757 .minimum_version_id = 1,
758 .needed = ps2_keyboard_need_high_bit_needed,
759 .fields = (VMStateField[]) {
760 VMSTATE_BOOL(need_high_bit, PS2KbdState),
761 VMSTATE_END_OF_LIST()
765 static int ps2_kbd_post_load(void* opaque, int version_id)
767 PS2KbdState *s = (PS2KbdState*)opaque;
768 PS2State *ps2 = &s->common;
770 if (version_id == 2)
771 s->scancode_set=2;
773 ps2_common_post_load(ps2);
775 return 0;
778 static void ps2_kbd_pre_save(void *opaque)
780 PS2KbdState *s = (PS2KbdState *)opaque;
781 PS2State *ps2 = &s->common;
783 ps2_common_post_load(ps2);
786 static const VMStateDescription vmstate_ps2_keyboard = {
787 .name = "ps2kbd",
788 .version_id = 3,
789 .minimum_version_id = 2,
790 .post_load = ps2_kbd_post_load,
791 .pre_save = ps2_kbd_pre_save,
792 .fields = (VMStateField[]) {
793 VMSTATE_STRUCT(common, PS2KbdState, 0, vmstate_ps2_common, PS2State),
794 VMSTATE_INT32(scan_enabled, PS2KbdState),
795 VMSTATE_INT32(translate, PS2KbdState),
796 VMSTATE_INT32_V(scancode_set, PS2KbdState,3),
797 VMSTATE_END_OF_LIST()
799 .subsections = (const VMStateDescription*[]) {
800 &vmstate_ps2_keyboard_ledstate,
801 &vmstate_ps2_keyboard_need_high_bit,
802 NULL
806 static int ps2_mouse_post_load(void *opaque, int version_id)
808 PS2MouseState *s = (PS2MouseState *)opaque;
809 PS2State *ps2 = &s->common;
811 ps2_common_post_load(ps2);
813 return 0;
816 static void ps2_mouse_pre_save(void *opaque)
818 PS2MouseState *s = (PS2MouseState *)opaque;
819 PS2State *ps2 = &s->common;
821 ps2_common_post_load(ps2);
824 static const VMStateDescription vmstate_ps2_mouse = {
825 .name = "ps2mouse",
826 .version_id = 2,
827 .minimum_version_id = 2,
828 .post_load = ps2_mouse_post_load,
829 .pre_save = ps2_mouse_pre_save,
830 .fields = (VMStateField[]) {
831 VMSTATE_STRUCT(common, PS2MouseState, 0, vmstate_ps2_common, PS2State),
832 VMSTATE_UINT8(mouse_status, PS2MouseState),
833 VMSTATE_UINT8(mouse_resolution, PS2MouseState),
834 VMSTATE_UINT8(mouse_sample_rate, PS2MouseState),
835 VMSTATE_UINT8(mouse_wrap, PS2MouseState),
836 VMSTATE_UINT8(mouse_type, PS2MouseState),
837 VMSTATE_UINT8(mouse_detect_state, PS2MouseState),
838 VMSTATE_INT32(mouse_dx, PS2MouseState),
839 VMSTATE_INT32(mouse_dy, PS2MouseState),
840 VMSTATE_INT32(mouse_dz, PS2MouseState),
841 VMSTATE_UINT8(mouse_buttons, PS2MouseState),
842 VMSTATE_END_OF_LIST()
846 static QemuInputHandler ps2_keyboard_handler = {
847 .name = "QEMU PS/2 Keyboard",
848 .mask = INPUT_EVENT_MASK_KEY,
849 .event = ps2_keyboard_event,
852 void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
854 PS2KbdState *s = (PS2KbdState *)g_malloc0(sizeof(PS2KbdState));
856 trace_ps2_kbd_init(s);
857 s->common.update_irq = update_irq;
858 s->common.update_arg = update_arg;
859 s->scancode_set = 2;
860 vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s);
861 qemu_input_handler_register((DeviceState *)s,
862 &ps2_keyboard_handler);
863 qemu_register_reset(ps2_kbd_reset, s);
864 return s;
867 static QemuInputHandler ps2_mouse_handler = {
868 .name = "QEMU PS/2 Mouse",
869 .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
870 .event = ps2_mouse_event,
871 .sync = ps2_mouse_sync,
874 void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
876 PS2MouseState *s = (PS2MouseState *)g_malloc0(sizeof(PS2MouseState));
878 trace_ps2_mouse_init(s);
879 s->common.update_irq = update_irq;
880 s->common.update_arg = update_arg;
881 vmstate_register(NULL, 0, &vmstate_ps2_mouse, s);
882 qemu_input_handler_register((DeviceState *)s,
883 &ps2_mouse_handler);
884 qemu_register_reset(ps2_mouse_reset, s);
885 return s;