target/mips: Remove XBurst Media eXtension Unit dead code
[qemu/ar7.git] / hw / input / ps2.c
blob72cdb80ae1cdd4d84d3b68e24c627476b5fad614
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.
25 #include "qemu/osdep.h"
26 #include "qemu/log.h"
27 #include "hw/input/ps2.h"
28 #include "migration/vmstate.h"
29 #include "ui/console.h"
30 #include "ui/input.h"
31 #include "sysemu/reset.h"
32 #include "sysemu/runstate.h"
34 #include "trace.h"
36 /* Keyboard Commands */
37 #define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */
38 #define KBD_CMD_ECHO 0xEE
39 #define KBD_CMD_SCANCODE 0xF0 /* Get/set scancode set */
40 #define KBD_CMD_GET_ID 0xF2 /* get keyboard ID */
41 #define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */
42 #define KBD_CMD_ENABLE 0xF4 /* Enable scanning */
43 #define KBD_CMD_RESET_DISABLE 0xF5 /* reset and disable scanning */
44 #define KBD_CMD_RESET_ENABLE 0xF6 /* reset and enable scanning */
45 #define KBD_CMD_RESET 0xFF /* Reset */
46 #define KBD_CMD_SET_MAKE_BREAK 0xFC /* Set Make and Break mode */
47 #define KBD_CMD_SET_TYPEMATIC 0xFA /* Set Typematic Make and Break mode */
49 /* Keyboard Replies */
50 #define KBD_REPLY_POR 0xAA /* Power on reset */
51 #define KBD_REPLY_ID 0xAB /* Keyboard ID */
52 #define KBD_REPLY_ACK 0xFA /* Command ACK */
53 #define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */
55 /* Mouse Commands */
56 #define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */
57 #define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */
58 #define AUX_SET_RES 0xE8 /* Set resolution */
59 #define AUX_GET_SCALE 0xE9 /* Get scaling factor */
60 #define AUX_SET_STREAM 0xEA /* Set stream mode */
61 #define AUX_POLL 0xEB /* Poll */
62 #define AUX_RESET_WRAP 0xEC /* Reset wrap mode */
63 #define AUX_SET_WRAP 0xEE /* Set wrap mode */
64 #define AUX_SET_REMOTE 0xF0 /* Set remote mode */
65 #define AUX_GET_TYPE 0xF2 /* Get type */
66 #define AUX_SET_SAMPLE 0xF3 /* Set sample rate */
67 #define AUX_ENABLE_DEV 0xF4 /* Enable aux device */
68 #define AUX_DISABLE_DEV 0xF5 /* Disable aux device */
69 #define AUX_SET_DEFAULT 0xF6
70 #define AUX_RESET 0xFF /* Reset aux device */
71 #define AUX_ACK 0xFA /* Command byte ACK. */
73 #define MOUSE_STATUS_REMOTE 0x40
74 #define MOUSE_STATUS_ENABLED 0x20
75 #define MOUSE_STATUS_SCALE21 0x10
77 #define PS2_QUEUE_SIZE 16 /* Buffer size required by PS/2 protocol */
79 /* Bits for 'modifiers' field in PS2KbdState */
80 #define MOD_CTRL_L (1 << 0)
81 #define MOD_SHIFT_L (1 << 1)
82 #define MOD_ALT_L (1 << 2)
83 #define MOD_CTRL_R (1 << 3)
84 #define MOD_SHIFT_R (1 << 4)
85 #define MOD_ALT_R (1 << 5)
87 typedef struct {
88 /* Keep the data array 256 bytes long, which compatibility
89 with older qemu versions. */
90 uint8_t data[256];
91 int rptr, wptr, count;
92 } PS2Queue;
94 struct PS2State {
95 PS2Queue queue;
96 int32_t write_cmd;
97 void (*update_irq)(void *, int);
98 void *update_arg;
101 typedef struct {
102 PS2State common;
103 int scan_enabled;
104 int translate;
105 int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */
106 int ledstate;
107 bool need_high_bit;
108 unsigned int modifiers; /* bitmask of MOD_* constants above */
109 } PS2KbdState;
111 typedef struct {
112 PS2State common;
113 uint8_t mouse_status;
114 uint8_t mouse_resolution;
115 uint8_t mouse_sample_rate;
116 uint8_t mouse_wrap;
117 uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */
118 uint8_t mouse_detect_state;
119 int mouse_dx; /* current values, needed for 'poll' mode */
120 int mouse_dy;
121 int mouse_dz;
122 uint8_t mouse_buttons;
123 } PS2MouseState;
125 static uint8_t translate_table[256] = {
126 0xff, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58,
127 0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59,
128 0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a,
129 0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b,
130 0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c,
131 0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d,
132 0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e,
133 0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f,
134 0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60,
135 0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61,
136 0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e,
137 0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76,
138 0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b,
139 0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f,
140 0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45,
141 0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54,
142 0x80, 0x81, 0x82, 0x41, 0x54, 0x85, 0x86, 0x87,
143 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
144 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
145 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
146 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
147 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
148 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
149 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
150 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
151 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
152 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
153 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
154 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
155 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
156 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
157 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
160 static unsigned int ps2_modifier_bit(QKeyCode key)
162 switch (key) {
163 case Q_KEY_CODE_CTRL:
164 return MOD_CTRL_L;
165 case Q_KEY_CODE_CTRL_R:
166 return MOD_CTRL_R;
167 case Q_KEY_CODE_SHIFT:
168 return MOD_SHIFT_L;
169 case Q_KEY_CODE_SHIFT_R:
170 return MOD_SHIFT_R;
171 case Q_KEY_CODE_ALT:
172 return MOD_ALT_L;
173 case Q_KEY_CODE_ALT_R:
174 return MOD_ALT_R;
175 default:
176 return 0;
180 static void ps2_reset_queue(PS2State *s)
182 PS2Queue *q = &s->queue;
184 q->rptr = 0;
185 q->wptr = 0;
186 q->count = 0;
189 int ps2_queue_empty(PS2State *s)
191 return s->queue.count == 0;
194 void ps2_queue_noirq(PS2State *s, int b)
196 PS2Queue *q = &s->queue;
198 if (q->count == PS2_QUEUE_SIZE) {
199 return;
202 q->data[q->wptr] = b;
203 if (++q->wptr == PS2_QUEUE_SIZE)
204 q->wptr = 0;
205 q->count++;
208 void ps2_raise_irq(PS2State *s)
210 s->update_irq(s->update_arg, 1);
213 void ps2_queue(PS2State *s, int b)
215 ps2_queue_noirq(s, b);
216 s->update_irq(s->update_arg, 1);
219 void ps2_queue_2(PS2State *s, int b1, int b2)
221 if (PS2_QUEUE_SIZE - s->queue.count < 2) {
222 return;
225 ps2_queue_noirq(s, b1);
226 ps2_queue_noirq(s, b2);
227 s->update_irq(s->update_arg, 1);
230 void ps2_queue_3(PS2State *s, int b1, int b2, int b3)
232 if (PS2_QUEUE_SIZE - s->queue.count < 3) {
233 return;
236 ps2_queue_noirq(s, b1);
237 ps2_queue_noirq(s, b2);
238 ps2_queue_noirq(s, b3);
239 s->update_irq(s->update_arg, 1);
242 void ps2_queue_4(PS2State *s, int b1, int b2, int b3, int b4)
244 if (PS2_QUEUE_SIZE - s->queue.count < 4) {
245 return;
248 ps2_queue_noirq(s, b1);
249 ps2_queue_noirq(s, b2);
250 ps2_queue_noirq(s, b3);
251 ps2_queue_noirq(s, b4);
252 s->update_irq(s->update_arg, 1);
255 /* keycode is the untranslated scancode in the current scancode set. */
256 static void ps2_put_keycode(void *opaque, int keycode)
258 PS2KbdState *s = opaque;
260 trace_ps2_put_keycode(opaque, keycode);
261 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL);
263 if (s->translate) {
264 if (keycode == 0xf0) {
265 s->need_high_bit = true;
266 } else if (s->need_high_bit) {
267 ps2_queue(&s->common, translate_table[keycode] | 0x80);
268 s->need_high_bit = false;
269 } else {
270 ps2_queue(&s->common, translate_table[keycode]);
272 } else {
273 ps2_queue(&s->common, keycode);
277 static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,
278 InputEvent *evt)
280 PS2KbdState *s = (PS2KbdState *)dev;
281 InputKeyEvent *key = evt->u.key.data;
282 int qcode;
283 uint16_t keycode = 0;
284 int mod;
286 /* do not process events while disabled to prevent stream corruption */
287 if (!s->scan_enabled) {
288 return;
291 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL);
292 assert(evt->type == INPUT_EVENT_KIND_KEY);
293 qcode = qemu_input_key_value_to_qcode(key->key);
295 mod = ps2_modifier_bit(qcode);
296 trace_ps2_keyboard_event(s, qcode, key->down, mod, s->modifiers);
297 if (key->down) {
298 s->modifiers |= mod;
299 } else {
300 s->modifiers &= ~mod;
303 if (s->scancode_set == 1) {
304 if (qcode == Q_KEY_CODE_PAUSE) {
305 if (s->modifiers & (MOD_CTRL_L | MOD_CTRL_R)) {
306 if (key->down) {
307 ps2_put_keycode(s, 0xe0);
308 ps2_put_keycode(s, 0x46);
309 ps2_put_keycode(s, 0xe0);
310 ps2_put_keycode(s, 0xc6);
312 } else {
313 if (key->down) {
314 ps2_put_keycode(s, 0xe1);
315 ps2_put_keycode(s, 0x1d);
316 ps2_put_keycode(s, 0x45);
317 ps2_put_keycode(s, 0xe1);
318 ps2_put_keycode(s, 0x9d);
319 ps2_put_keycode(s, 0xc5);
322 } else if (qcode == Q_KEY_CODE_PRINT) {
323 if (s->modifiers & MOD_ALT_L) {
324 if (key->down) {
325 ps2_put_keycode(s, 0xb8);
326 ps2_put_keycode(s, 0x38);
327 ps2_put_keycode(s, 0x54);
328 } else {
329 ps2_put_keycode(s, 0xd4);
330 ps2_put_keycode(s, 0xb8);
331 ps2_put_keycode(s, 0x38);
333 } else if (s->modifiers & MOD_ALT_R) {
334 if (key->down) {
335 ps2_put_keycode(s, 0xe0);
336 ps2_put_keycode(s, 0xb8);
337 ps2_put_keycode(s, 0xe0);
338 ps2_put_keycode(s, 0x38);
339 ps2_put_keycode(s, 0x54);
340 } else {
341 ps2_put_keycode(s, 0xd4);
342 ps2_put_keycode(s, 0xe0);
343 ps2_put_keycode(s, 0xb8);
344 ps2_put_keycode(s, 0xe0);
345 ps2_put_keycode(s, 0x38);
347 } else if (s->modifiers & (MOD_SHIFT_L | MOD_CTRL_L |
348 MOD_SHIFT_R | MOD_CTRL_R)) {
349 if (key->down) {
350 ps2_put_keycode(s, 0xe0);
351 ps2_put_keycode(s, 0x37);
352 } else {
353 ps2_put_keycode(s, 0xe0);
354 ps2_put_keycode(s, 0xb7);
356 } else {
357 if (key->down) {
358 ps2_put_keycode(s, 0xe0);
359 ps2_put_keycode(s, 0x2a);
360 ps2_put_keycode(s, 0xe0);
361 ps2_put_keycode(s, 0x37);
362 } else {
363 ps2_put_keycode(s, 0xe0);
364 ps2_put_keycode(s, 0xb7);
365 ps2_put_keycode(s, 0xe0);
366 ps2_put_keycode(s, 0xaa);
369 } else {
370 if (qcode < qemu_input_map_qcode_to_atset1_len)
371 keycode = qemu_input_map_qcode_to_atset1[qcode];
372 if (keycode) {
373 if (keycode & 0xff00) {
374 ps2_put_keycode(s, keycode >> 8);
376 if (!key->down) {
377 keycode |= 0x80;
379 ps2_put_keycode(s, keycode & 0xff);
380 } else {
381 qemu_log_mask(LOG_UNIMP,
382 "ps2: ignoring key with qcode %d\n", qcode);
385 } else if (s->scancode_set == 2) {
386 if (qcode == Q_KEY_CODE_PAUSE) {
387 if (s->modifiers & (MOD_CTRL_L | MOD_CTRL_R)) {
388 if (key->down) {
389 ps2_put_keycode(s, 0xe0);
390 ps2_put_keycode(s, 0x7e);
391 ps2_put_keycode(s, 0xe0);
392 ps2_put_keycode(s, 0xf0);
393 ps2_put_keycode(s, 0x7e);
395 } else {
396 if (key->down) {
397 ps2_put_keycode(s, 0xe1);
398 ps2_put_keycode(s, 0x14);
399 ps2_put_keycode(s, 0x77);
400 ps2_put_keycode(s, 0xe1);
401 ps2_put_keycode(s, 0xf0);
402 ps2_put_keycode(s, 0x14);
403 ps2_put_keycode(s, 0xf0);
404 ps2_put_keycode(s, 0x77);
407 } else if (qcode == Q_KEY_CODE_PRINT) {
408 if (s->modifiers & MOD_ALT_L) {
409 if (key->down) {
410 ps2_put_keycode(s, 0xf0);
411 ps2_put_keycode(s, 0x11);
412 ps2_put_keycode(s, 0x11);
413 ps2_put_keycode(s, 0x84);
414 } else {
415 ps2_put_keycode(s, 0xf0);
416 ps2_put_keycode(s, 0x84);
417 ps2_put_keycode(s, 0xf0);
418 ps2_put_keycode(s, 0x11);
419 ps2_put_keycode(s, 0x11);
421 } else if (s->modifiers & MOD_ALT_R) {
422 if (key->down) {
423 ps2_put_keycode(s, 0xe0);
424 ps2_put_keycode(s, 0xf0);
425 ps2_put_keycode(s, 0x11);
426 ps2_put_keycode(s, 0xe0);
427 ps2_put_keycode(s, 0x11);
428 ps2_put_keycode(s, 0x84);
429 } else {
430 ps2_put_keycode(s, 0xf0);
431 ps2_put_keycode(s, 0x84);
432 ps2_put_keycode(s, 0xe0);
433 ps2_put_keycode(s, 0xf0);
434 ps2_put_keycode(s, 0x11);
435 ps2_put_keycode(s, 0xe0);
436 ps2_put_keycode(s, 0x11);
438 } else if (s->modifiers & (MOD_SHIFT_L | MOD_CTRL_L |
439 MOD_SHIFT_R | MOD_CTRL_R)) {
440 if (key->down) {
441 ps2_put_keycode(s, 0xe0);
442 ps2_put_keycode(s, 0x7c);
443 } else {
444 ps2_put_keycode(s, 0xe0);
445 ps2_put_keycode(s, 0xf0);
446 ps2_put_keycode(s, 0x7c);
448 } else {
449 if (key->down) {
450 ps2_put_keycode(s, 0xe0);
451 ps2_put_keycode(s, 0x12);
452 ps2_put_keycode(s, 0xe0);
453 ps2_put_keycode(s, 0x7c);
454 } else {
455 ps2_put_keycode(s, 0xe0);
456 ps2_put_keycode(s, 0xf0);
457 ps2_put_keycode(s, 0x7c);
458 ps2_put_keycode(s, 0xe0);
459 ps2_put_keycode(s, 0xf0);
460 ps2_put_keycode(s, 0x12);
463 } else {
464 if (qcode < qemu_input_map_qcode_to_atset2_len)
465 keycode = qemu_input_map_qcode_to_atset2[qcode];
466 if (keycode) {
467 if (keycode & 0xff00) {
468 ps2_put_keycode(s, keycode >> 8);
470 if (!key->down) {
471 ps2_put_keycode(s, 0xf0);
473 ps2_put_keycode(s, keycode & 0xff);
474 } else {
475 qemu_log_mask(LOG_UNIMP,
476 "ps2: ignoring key with qcode %d\n", qcode);
479 } else if (s->scancode_set == 3) {
480 if (qcode < qemu_input_map_qcode_to_atset3_len)
481 keycode = qemu_input_map_qcode_to_atset3[qcode];
482 if (keycode) {
483 /* FIXME: break code should be configured on a key by key basis */
484 if (!key->down) {
485 ps2_put_keycode(s, 0xf0);
487 ps2_put_keycode(s, keycode);
488 } else {
489 qemu_log_mask(LOG_UNIMP,
490 "ps2: ignoring key with qcode %d\n", qcode);
495 uint32_t ps2_read_data(PS2State *s)
497 PS2Queue *q;
498 int val, index;
500 trace_ps2_read_data(s);
501 q = &s->queue;
502 if (q->count == 0) {
503 /* NOTE: if no data left, we return the last keyboard one
504 (needed for EMM386) */
505 /* XXX: need a timer to do things correctly */
506 index = q->rptr - 1;
507 if (index < 0)
508 index = PS2_QUEUE_SIZE - 1;
509 val = q->data[index];
510 } else {
511 val = q->data[q->rptr];
512 if (++q->rptr == PS2_QUEUE_SIZE)
513 q->rptr = 0;
514 q->count--;
515 /* reading deasserts IRQ */
516 s->update_irq(s->update_arg, 0);
517 /* reassert IRQs if data left */
518 s->update_irq(s->update_arg, q->count != 0);
520 return val;
523 static void ps2_set_ledstate(PS2KbdState *s, int ledstate)
525 trace_ps2_set_ledstate(s, ledstate);
526 s->ledstate = ledstate;
527 kbd_put_ledstate(ledstate);
530 static void ps2_reset_keyboard(PS2KbdState *s)
532 trace_ps2_reset_keyboard(s);
533 s->scan_enabled = 1;
534 s->scancode_set = 2;
535 ps2_reset_queue(&s->common);
536 ps2_set_ledstate(s, 0);
539 void ps2_write_keyboard(void *opaque, int val)
541 PS2KbdState *s = (PS2KbdState *)opaque;
543 trace_ps2_write_keyboard(opaque, val);
544 switch(s->common.write_cmd) {
545 default:
546 case -1:
547 switch(val) {
548 case 0x00:
549 ps2_queue(&s->common, KBD_REPLY_ACK);
550 break;
551 case 0x05:
552 ps2_queue(&s->common, KBD_REPLY_RESEND);
553 break;
554 case KBD_CMD_GET_ID:
555 /* We emulate a MF2 AT keyboard here */
556 if (s->translate)
557 ps2_queue_3(&s->common,
558 KBD_REPLY_ACK,
559 KBD_REPLY_ID,
560 0x41);
561 else
562 ps2_queue_3(&s->common,
563 KBD_REPLY_ACK,
564 KBD_REPLY_ID,
565 0x83);
566 break;
567 case KBD_CMD_ECHO:
568 ps2_queue(&s->common, KBD_CMD_ECHO);
569 break;
570 case KBD_CMD_ENABLE:
571 s->scan_enabled = 1;
572 ps2_queue(&s->common, KBD_REPLY_ACK);
573 break;
574 case KBD_CMD_SCANCODE:
575 case KBD_CMD_SET_LEDS:
576 case KBD_CMD_SET_RATE:
577 case KBD_CMD_SET_MAKE_BREAK:
578 s->common.write_cmd = val;
579 ps2_queue(&s->common, KBD_REPLY_ACK);
580 break;
581 case KBD_CMD_RESET_DISABLE:
582 ps2_reset_keyboard(s);
583 s->scan_enabled = 0;
584 ps2_queue(&s->common, KBD_REPLY_ACK);
585 break;
586 case KBD_CMD_RESET_ENABLE:
587 ps2_reset_keyboard(s);
588 s->scan_enabled = 1;
589 ps2_queue(&s->common, KBD_REPLY_ACK);
590 break;
591 case KBD_CMD_RESET:
592 ps2_reset_keyboard(s);
593 ps2_queue_2(&s->common,
594 KBD_REPLY_ACK,
595 KBD_REPLY_POR);
596 break;
597 case KBD_CMD_SET_TYPEMATIC:
598 ps2_queue(&s->common, KBD_REPLY_ACK);
599 break;
600 default:
601 ps2_queue(&s->common, KBD_REPLY_RESEND);
602 break;
604 break;
605 case KBD_CMD_SET_MAKE_BREAK:
606 ps2_queue(&s->common, KBD_REPLY_ACK);
607 s->common.write_cmd = -1;
608 break;
609 case KBD_CMD_SCANCODE:
610 if (val == 0) {
611 if (s->common.queue.count <= PS2_QUEUE_SIZE - 2) {
612 ps2_queue(&s->common, KBD_REPLY_ACK);
613 ps2_put_keycode(s, s->scancode_set);
615 } else if (val >= 1 && val <= 3) {
616 s->scancode_set = val;
617 ps2_queue(&s->common, KBD_REPLY_ACK);
618 } else {
619 ps2_queue(&s->common, KBD_REPLY_RESEND);
621 s->common.write_cmd = -1;
622 break;
623 case KBD_CMD_SET_LEDS:
624 ps2_set_ledstate(s, val);
625 ps2_queue(&s->common, KBD_REPLY_ACK);
626 s->common.write_cmd = -1;
627 break;
628 case KBD_CMD_SET_RATE:
629 ps2_queue(&s->common, KBD_REPLY_ACK);
630 s->common.write_cmd = -1;
631 break;
635 /* Set the scancode translation mode.
636 0 = raw scancodes.
637 1 = translated scancodes (used by qemu internally). */
639 void ps2_keyboard_set_translation(void *opaque, int mode)
641 PS2KbdState *s = (PS2KbdState *)opaque;
642 trace_ps2_keyboard_set_translation(opaque, mode);
643 s->translate = mode;
646 static int ps2_mouse_send_packet(PS2MouseState *s)
648 const int needed = 3 + (s->mouse_type - 2);
649 unsigned int b;
650 int dx1, dy1, dz1;
652 if (PS2_QUEUE_SIZE - s->common.queue.count < needed) {
653 return 0;
656 dx1 = s->mouse_dx;
657 dy1 = s->mouse_dy;
658 dz1 = s->mouse_dz;
659 /* XXX: increase range to 8 bits ? */
660 if (dx1 > 127)
661 dx1 = 127;
662 else if (dx1 < -127)
663 dx1 = -127;
664 if (dy1 > 127)
665 dy1 = 127;
666 else if (dy1 < -127)
667 dy1 = -127;
668 b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
669 ps2_queue_noirq(&s->common, b);
670 ps2_queue_noirq(&s->common, dx1 & 0xff);
671 ps2_queue_noirq(&s->common, dy1 & 0xff);
672 /* extra byte for IMPS/2 or IMEX */
673 switch(s->mouse_type) {
674 default:
675 break;
676 case 3:
677 if (dz1 > 127)
678 dz1 = 127;
679 else if (dz1 < -127)
680 dz1 = -127;
681 ps2_queue_noirq(&s->common, dz1 & 0xff);
682 break;
683 case 4:
684 if (dz1 > 7)
685 dz1 = 7;
686 else if (dz1 < -7)
687 dz1 = -7;
688 b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
689 ps2_queue_noirq(&s->common, b);
690 break;
693 ps2_raise_irq(&s->common);
695 trace_ps2_mouse_send_packet(s, dx1, dy1, dz1, b);
696 /* update deltas */
697 s->mouse_dx -= dx1;
698 s->mouse_dy -= dy1;
699 s->mouse_dz -= dz1;
701 return 1;
704 static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
705 InputEvent *evt)
707 static const int bmap[INPUT_BUTTON__MAX] = {
708 [INPUT_BUTTON_LEFT] = PS2_MOUSE_BUTTON_LEFT,
709 [INPUT_BUTTON_MIDDLE] = PS2_MOUSE_BUTTON_MIDDLE,
710 [INPUT_BUTTON_RIGHT] = PS2_MOUSE_BUTTON_RIGHT,
711 [INPUT_BUTTON_SIDE] = PS2_MOUSE_BUTTON_SIDE,
712 [INPUT_BUTTON_EXTRA] = PS2_MOUSE_BUTTON_EXTRA,
714 PS2MouseState *s = (PS2MouseState *)dev;
715 InputMoveEvent *move;
716 InputBtnEvent *btn;
718 /* check if deltas are recorded when disabled */
719 if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
720 return;
722 switch (evt->type) {
723 case INPUT_EVENT_KIND_REL:
724 move = evt->u.rel.data;
725 if (move->axis == INPUT_AXIS_X) {
726 s->mouse_dx += move->value;
727 } else if (move->axis == INPUT_AXIS_Y) {
728 s->mouse_dy -= move->value;
730 break;
732 case INPUT_EVENT_KIND_BTN:
733 btn = evt->u.btn.data;
734 if (btn->down) {
735 s->mouse_buttons |= bmap[btn->button];
736 if (btn->button == INPUT_BUTTON_WHEEL_UP) {
737 s->mouse_dz--;
738 } else if (btn->button == INPUT_BUTTON_WHEEL_DOWN) {
739 s->mouse_dz++;
741 } else {
742 s->mouse_buttons &= ~bmap[btn->button];
744 break;
746 default:
747 /* keep gcc happy */
748 break;
752 static void ps2_mouse_sync(DeviceState *dev)
754 PS2MouseState *s = (PS2MouseState *)dev;
756 /* do not sync while disabled to prevent stream corruption */
757 if (!(s->mouse_status & MOUSE_STATUS_ENABLED)) {
758 return;
761 if (s->mouse_buttons) {
762 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL);
764 if (!(s->mouse_status & MOUSE_STATUS_REMOTE)) {
765 /* if not remote, send event. Multiple events are sent if
766 too big deltas */
767 while (ps2_mouse_send_packet(s)) {
768 if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
769 break;
774 void ps2_mouse_fake_event(void *opaque)
776 PS2MouseState *s = opaque;
777 trace_ps2_mouse_fake_event(opaque);
778 s->mouse_dx++;
779 ps2_mouse_sync(opaque);
782 void ps2_write_mouse(void *opaque, int val)
784 PS2MouseState *s = (PS2MouseState *)opaque;
786 trace_ps2_write_mouse(opaque, val);
787 switch(s->common.write_cmd) {
788 default:
789 case -1:
790 /* mouse command */
791 if (s->mouse_wrap) {
792 if (val == AUX_RESET_WRAP) {
793 s->mouse_wrap = 0;
794 ps2_queue(&s->common, AUX_ACK);
795 return;
796 } else if (val != AUX_RESET) {
797 ps2_queue(&s->common, val);
798 return;
801 switch(val) {
802 case AUX_SET_SCALE11:
803 s->mouse_status &= ~MOUSE_STATUS_SCALE21;
804 ps2_queue(&s->common, AUX_ACK);
805 break;
806 case AUX_SET_SCALE21:
807 s->mouse_status |= MOUSE_STATUS_SCALE21;
808 ps2_queue(&s->common, AUX_ACK);
809 break;
810 case AUX_SET_STREAM:
811 s->mouse_status &= ~MOUSE_STATUS_REMOTE;
812 ps2_queue(&s->common, AUX_ACK);
813 break;
814 case AUX_SET_WRAP:
815 s->mouse_wrap = 1;
816 ps2_queue(&s->common, AUX_ACK);
817 break;
818 case AUX_SET_REMOTE:
819 s->mouse_status |= MOUSE_STATUS_REMOTE;
820 ps2_queue(&s->common, AUX_ACK);
821 break;
822 case AUX_GET_TYPE:
823 ps2_queue_2(&s->common,
824 AUX_ACK,
825 s->mouse_type);
826 break;
827 case AUX_SET_RES:
828 case AUX_SET_SAMPLE:
829 s->common.write_cmd = val;
830 ps2_queue(&s->common, AUX_ACK);
831 break;
832 case AUX_GET_SCALE:
833 ps2_queue_4(&s->common,
834 AUX_ACK,
835 s->mouse_status,
836 s->mouse_resolution,
837 s->mouse_sample_rate);
838 break;
839 case AUX_POLL:
840 ps2_queue(&s->common, AUX_ACK);
841 ps2_mouse_send_packet(s);
842 break;
843 case AUX_ENABLE_DEV:
844 s->mouse_status |= MOUSE_STATUS_ENABLED;
845 ps2_queue(&s->common, AUX_ACK);
846 break;
847 case AUX_DISABLE_DEV:
848 s->mouse_status &= ~MOUSE_STATUS_ENABLED;
849 ps2_queue(&s->common, AUX_ACK);
850 break;
851 case AUX_SET_DEFAULT:
852 s->mouse_sample_rate = 100;
853 s->mouse_resolution = 2;
854 s->mouse_status = 0;
855 ps2_queue(&s->common, AUX_ACK);
856 break;
857 case AUX_RESET:
858 s->mouse_sample_rate = 100;
859 s->mouse_resolution = 2;
860 s->mouse_status = 0;
861 s->mouse_type = 0;
862 ps2_reset_queue(&s->common);
863 ps2_queue_3(&s->common,
864 AUX_ACK,
865 0xaa,
866 s->mouse_type);
867 break;
868 default:
869 break;
871 break;
872 case AUX_SET_SAMPLE:
873 s->mouse_sample_rate = val;
874 /* detect IMPS/2 or IMEX */
875 switch(s->mouse_detect_state) {
876 default:
877 case 0:
878 if (val == 200)
879 s->mouse_detect_state = 1;
880 break;
881 case 1:
882 if (val == 100)
883 s->mouse_detect_state = 2;
884 else if (val == 200)
885 s->mouse_detect_state = 3;
886 else
887 s->mouse_detect_state = 0;
888 break;
889 case 2:
890 if (val == 80)
891 s->mouse_type = 3; /* IMPS/2 */
892 s->mouse_detect_state = 0;
893 break;
894 case 3:
895 if (val == 80)
896 s->mouse_type = 4; /* IMEX */
897 s->mouse_detect_state = 0;
898 break;
900 ps2_queue(&s->common, AUX_ACK);
901 s->common.write_cmd = -1;
902 break;
903 case AUX_SET_RES:
904 s->mouse_resolution = val;
905 ps2_queue(&s->common, AUX_ACK);
906 s->common.write_cmd = -1;
907 break;
911 static void ps2_common_reset(PS2State *s)
913 s->write_cmd = -1;
914 ps2_reset_queue(s);
915 s->update_irq(s->update_arg, 0);
918 static void ps2_common_post_load(PS2State *s)
920 PS2Queue *q = &s->queue;
921 uint8_t i, size;
922 uint8_t tmp_data[PS2_QUEUE_SIZE];
924 /* set the useful data buffer queue size, < PS2_QUEUE_SIZE */
925 size = q->count;
926 if (q->count < 0) {
927 size = 0;
928 } else if (q->count > PS2_QUEUE_SIZE) {
929 size = PS2_QUEUE_SIZE;
932 /* move the queue elements to the start of data array */
933 for (i = 0; i < size; i++) {
934 if (q->rptr < 0 || q->rptr >= sizeof(q->data)) {
935 q->rptr = 0;
937 tmp_data[i] = q->data[q->rptr++];
939 memcpy(q->data, tmp_data, size);
941 /* reset rptr/wptr/count */
942 q->rptr = 0;
943 q->wptr = (size == PS2_QUEUE_SIZE) ? 0 : size;
944 q->count = size;
947 static void ps2_kbd_reset(void *opaque)
949 PS2KbdState *s = (PS2KbdState *) opaque;
951 trace_ps2_kbd_reset(opaque);
952 ps2_common_reset(&s->common);
953 s->scan_enabled = 1;
954 s->translate = 0;
955 s->scancode_set = 2;
956 s->modifiers = 0;
959 static void ps2_mouse_reset(void *opaque)
961 PS2MouseState *s = (PS2MouseState *) opaque;
963 trace_ps2_mouse_reset(opaque);
964 ps2_common_reset(&s->common);
965 s->mouse_status = 0;
966 s->mouse_resolution = 0;
967 s->mouse_sample_rate = 0;
968 s->mouse_wrap = 0;
969 s->mouse_type = 0;
970 s->mouse_detect_state = 0;
971 s->mouse_dx = 0;
972 s->mouse_dy = 0;
973 s->mouse_dz = 0;
974 s->mouse_buttons = 0;
977 static const VMStateDescription vmstate_ps2_common = {
978 .name = "PS2 Common State",
979 .version_id = 3,
980 .minimum_version_id = 2,
981 .fields = (VMStateField[]) {
982 VMSTATE_INT32(write_cmd, PS2State),
983 VMSTATE_INT32(queue.rptr, PS2State),
984 VMSTATE_INT32(queue.wptr, PS2State),
985 VMSTATE_INT32(queue.count, PS2State),
986 VMSTATE_BUFFER(queue.data, PS2State),
987 VMSTATE_END_OF_LIST()
991 static bool ps2_keyboard_ledstate_needed(void *opaque)
993 PS2KbdState *s = opaque;
995 return s->ledstate != 0; /* 0 is default state */
998 static int ps2_kbd_ledstate_post_load(void *opaque, int version_id)
1000 PS2KbdState *s = opaque;
1002 kbd_put_ledstate(s->ledstate);
1003 return 0;
1006 static const VMStateDescription vmstate_ps2_keyboard_ledstate = {
1007 .name = "ps2kbd/ledstate",
1008 .version_id = 3,
1009 .minimum_version_id = 2,
1010 .post_load = ps2_kbd_ledstate_post_load,
1011 .needed = ps2_keyboard_ledstate_needed,
1012 .fields = (VMStateField[]) {
1013 VMSTATE_INT32(ledstate, PS2KbdState),
1014 VMSTATE_END_OF_LIST()
1018 static bool ps2_keyboard_need_high_bit_needed(void *opaque)
1020 PS2KbdState *s = opaque;
1021 return s->need_high_bit != 0; /* 0 is the usual state */
1024 static const VMStateDescription vmstate_ps2_keyboard_need_high_bit = {
1025 .name = "ps2kbd/need_high_bit",
1026 .version_id = 1,
1027 .minimum_version_id = 1,
1028 .needed = ps2_keyboard_need_high_bit_needed,
1029 .fields = (VMStateField[]) {
1030 VMSTATE_BOOL(need_high_bit, PS2KbdState),
1031 VMSTATE_END_OF_LIST()
1035 static int ps2_kbd_post_load(void* opaque, int version_id)
1037 PS2KbdState *s = (PS2KbdState*)opaque;
1038 PS2State *ps2 = &s->common;
1040 if (version_id == 2)
1041 s->scancode_set=2;
1043 ps2_common_post_load(ps2);
1045 return 0;
1048 static int ps2_kbd_pre_save(void *opaque)
1050 PS2KbdState *s = (PS2KbdState *)opaque;
1051 PS2State *ps2 = &s->common;
1053 ps2_common_post_load(ps2);
1055 return 0;
1058 static const VMStateDescription vmstate_ps2_keyboard = {
1059 .name = "ps2kbd",
1060 .version_id = 3,
1061 .minimum_version_id = 2,
1062 .post_load = ps2_kbd_post_load,
1063 .pre_save = ps2_kbd_pre_save,
1064 .fields = (VMStateField[]) {
1065 VMSTATE_STRUCT(common, PS2KbdState, 0, vmstate_ps2_common, PS2State),
1066 VMSTATE_INT32(scan_enabled, PS2KbdState),
1067 VMSTATE_INT32(translate, PS2KbdState),
1068 VMSTATE_INT32_V(scancode_set, PS2KbdState,3),
1069 VMSTATE_END_OF_LIST()
1071 .subsections = (const VMStateDescription*[]) {
1072 &vmstate_ps2_keyboard_ledstate,
1073 &vmstate_ps2_keyboard_need_high_bit,
1074 NULL
1078 static int ps2_mouse_post_load(void *opaque, int version_id)
1080 PS2MouseState *s = (PS2MouseState *)opaque;
1081 PS2State *ps2 = &s->common;
1083 ps2_common_post_load(ps2);
1085 return 0;
1088 static int ps2_mouse_pre_save(void *opaque)
1090 PS2MouseState *s = (PS2MouseState *)opaque;
1091 PS2State *ps2 = &s->common;
1093 ps2_common_post_load(ps2);
1095 return 0;
1098 static const VMStateDescription vmstate_ps2_mouse = {
1099 .name = "ps2mouse",
1100 .version_id = 2,
1101 .minimum_version_id = 2,
1102 .post_load = ps2_mouse_post_load,
1103 .pre_save = ps2_mouse_pre_save,
1104 .fields = (VMStateField[]) {
1105 VMSTATE_STRUCT(common, PS2MouseState, 0, vmstate_ps2_common, PS2State),
1106 VMSTATE_UINT8(mouse_status, PS2MouseState),
1107 VMSTATE_UINT8(mouse_resolution, PS2MouseState),
1108 VMSTATE_UINT8(mouse_sample_rate, PS2MouseState),
1109 VMSTATE_UINT8(mouse_wrap, PS2MouseState),
1110 VMSTATE_UINT8(mouse_type, PS2MouseState),
1111 VMSTATE_UINT8(mouse_detect_state, PS2MouseState),
1112 VMSTATE_INT32(mouse_dx, PS2MouseState),
1113 VMSTATE_INT32(mouse_dy, PS2MouseState),
1114 VMSTATE_INT32(mouse_dz, PS2MouseState),
1115 VMSTATE_UINT8(mouse_buttons, PS2MouseState),
1116 VMSTATE_END_OF_LIST()
1120 static QemuInputHandler ps2_keyboard_handler = {
1121 .name = "QEMU PS/2 Keyboard",
1122 .mask = INPUT_EVENT_MASK_KEY,
1123 .event = ps2_keyboard_event,
1126 void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
1128 PS2KbdState *s = (PS2KbdState *)g_malloc0(sizeof(PS2KbdState));
1130 trace_ps2_kbd_init(s);
1131 s->common.update_irq = update_irq;
1132 s->common.update_arg = update_arg;
1133 s->scancode_set = 2;
1134 vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s);
1135 qemu_input_handler_register((DeviceState *)s,
1136 &ps2_keyboard_handler);
1137 qemu_register_reset(ps2_kbd_reset, s);
1138 return s;
1141 static QemuInputHandler ps2_mouse_handler = {
1142 .name = "QEMU PS/2 Mouse",
1143 .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
1144 .event = ps2_mouse_event,
1145 .sync = ps2_mouse_sync,
1148 void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
1150 PS2MouseState *s = (PS2MouseState *)g_malloc0(sizeof(PS2MouseState));
1152 trace_ps2_mouse_init(s);
1153 s->common.update_irq = update_irq;
1154 s->common.update_arg = update_arg;
1155 vmstate_register(NULL, 0, &vmstate_ps2_mouse, s);
1156 qemu_input_handler_register((DeviceState *)s,
1157 &ps2_mouse_handler);
1158 qemu_register_reset(ps2_mouse_reset, s);
1159 return s;