qcow2: refactor decompress_buffer
[qemu/ar7.git] / hw / input / ps2.c
blobeb33ee9b6f0d294e8f165e1550dca8366707ba5c
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 "qemu/log.h"
26 #include "hw/hw.h"
27 #include "hw/input/ps2.h"
28 #include "ui/console.h"
29 #include "ui/input.h"
30 #include "sysemu/sysemu.h"
32 #include "trace.h"
34 /* debug PC keyboard */
35 //#define DEBUG_KBD
37 /* debug PC keyboard : only mouse */
38 //#define DEBUG_MOUSE
40 /* Keyboard Commands */
41 #define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */
42 #define KBD_CMD_ECHO 0xEE
43 #define KBD_CMD_SCANCODE 0xF0 /* Get/set scancode set */
44 #define KBD_CMD_GET_ID 0xF2 /* get keyboard ID */
45 #define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */
46 #define KBD_CMD_ENABLE 0xF4 /* Enable scanning */
47 #define KBD_CMD_RESET_DISABLE 0xF5 /* reset and disable scanning */
48 #define KBD_CMD_RESET_ENABLE 0xF6 /* reset and enable scanning */
49 #define KBD_CMD_RESET 0xFF /* Reset */
51 /* Keyboard Replies */
52 #define KBD_REPLY_POR 0xAA /* Power on reset */
53 #define KBD_REPLY_ID 0xAB /* Keyboard ID */
54 #define KBD_REPLY_ACK 0xFA /* Command ACK */
55 #define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */
57 /* Mouse Commands */
58 #define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */
59 #define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */
60 #define AUX_SET_RES 0xE8 /* Set resolution */
61 #define AUX_GET_SCALE 0xE9 /* Get scaling factor */
62 #define AUX_SET_STREAM 0xEA /* Set stream mode */
63 #define AUX_POLL 0xEB /* Poll */
64 #define AUX_RESET_WRAP 0xEC /* Reset wrap mode */
65 #define AUX_SET_WRAP 0xEE /* Set wrap mode */
66 #define AUX_SET_REMOTE 0xF0 /* Set remote mode */
67 #define AUX_GET_TYPE 0xF2 /* Get type */
68 #define AUX_SET_SAMPLE 0xF3 /* Set sample rate */
69 #define AUX_ENABLE_DEV 0xF4 /* Enable aux device */
70 #define AUX_DISABLE_DEV 0xF5 /* Disable aux device */
71 #define AUX_SET_DEFAULT 0xF6
72 #define AUX_RESET 0xFF /* Reset aux device */
73 #define AUX_ACK 0xFA /* Command byte ACK. */
75 #define MOUSE_STATUS_REMOTE 0x40
76 #define MOUSE_STATUS_ENABLED 0x20
77 #define MOUSE_STATUS_SCALE21 0x10
79 #define PS2_QUEUE_SIZE 16 /* Buffer size required by PS/2 protocol */
81 /* Bits for 'modifiers' field in PS2KbdState */
82 #define MOD_CTRL_L (1 << 0)
83 #define MOD_SHIFT_L (1 << 1)
84 #define MOD_ALT_L (1 << 2)
85 #define MOD_CTRL_R (1 << 3)
86 #define MOD_SHIFT_R (1 << 4)
87 #define MOD_ALT_R (1 << 5)
89 typedef struct {
90 /* Keep the data array 256 bytes long, which compatibility
91 with older qemu versions. */
92 uint8_t data[256];
93 int rptr, wptr, count;
94 } PS2Queue;
96 struct PS2State {
97 PS2Queue queue;
98 int32_t write_cmd;
99 void (*update_irq)(void *, int);
100 void *update_arg;
103 typedef struct {
104 PS2State common;
105 int scan_enabled;
106 int translate;
107 int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */
108 int ledstate;
109 bool need_high_bit;
110 unsigned int modifiers; /* bitmask of MOD_* constants above */
111 } PS2KbdState;
113 typedef struct {
114 PS2State common;
115 uint8_t mouse_status;
116 uint8_t mouse_resolution;
117 uint8_t mouse_sample_rate;
118 uint8_t mouse_wrap;
119 uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */
120 uint8_t mouse_detect_state;
121 int mouse_dx; /* current values, needed for 'poll' mode */
122 int mouse_dy;
123 int mouse_dz;
124 uint8_t mouse_buttons;
125 } PS2MouseState;
127 static uint8_t translate_table[256] = {
128 0xff, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58,
129 0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59,
130 0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a,
131 0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b,
132 0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c,
133 0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d,
134 0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e,
135 0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f,
136 0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60,
137 0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61,
138 0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e,
139 0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76,
140 0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b,
141 0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f,
142 0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45,
143 0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54,
144 0x80, 0x81, 0x82, 0x41, 0x54, 0x85, 0x86, 0x87,
145 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
146 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
147 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
148 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
149 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
150 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
151 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
152 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
153 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
154 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
155 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
156 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
157 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
158 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
159 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
162 static unsigned int ps2_modifier_bit(QKeyCode key)
164 switch (key) {
165 case Q_KEY_CODE_CTRL:
166 return MOD_CTRL_L;
167 case Q_KEY_CODE_CTRL_R:
168 return MOD_CTRL_R;
169 case Q_KEY_CODE_SHIFT:
170 return MOD_SHIFT_L;
171 case Q_KEY_CODE_SHIFT_R:
172 return MOD_SHIFT_R;
173 case Q_KEY_CODE_ALT:
174 return MOD_ALT_L;
175 case Q_KEY_CODE_ALT_R:
176 return MOD_ALT_R;
177 default:
178 return 0;
182 static void ps2_reset_queue(PS2State *s)
184 PS2Queue *q = &s->queue;
186 q->rptr = 0;
187 q->wptr = 0;
188 q->count = 0;
191 void ps2_queue_noirq(PS2State *s, int b)
193 PS2Queue *q = &s->queue;
195 if (q->count == PS2_QUEUE_SIZE) {
196 return;
199 q->data[q->wptr] = b;
200 if (++q->wptr == PS2_QUEUE_SIZE)
201 q->wptr = 0;
202 q->count++;
205 void ps2_raise_irq(PS2State *s)
207 s->update_irq(s->update_arg, 1);
210 void ps2_queue(PS2State *s, int b)
212 ps2_queue_noirq(s, b);
213 s->update_irq(s->update_arg, 1);
216 void ps2_queue_2(PS2State *s, int b1, int b2)
218 if (PS2_QUEUE_SIZE - s->queue.count < 2) {
219 return;
222 ps2_queue_noirq(s, b1);
223 ps2_queue_noirq(s, b2);
224 s->update_irq(s->update_arg, 1);
227 void ps2_queue_3(PS2State *s, int b1, int b2, int b3)
229 if (PS2_QUEUE_SIZE - s->queue.count < 3) {
230 return;
233 ps2_queue_noirq(s, b1);
234 ps2_queue_noirq(s, b2);
235 ps2_queue_noirq(s, b3);
236 s->update_irq(s->update_arg, 1);
239 void ps2_queue_4(PS2State *s, int b1, int b2, int b3, int b4)
241 if (PS2_QUEUE_SIZE - s->queue.count < 4) {
242 return;
245 ps2_queue_noirq(s, b1);
246 ps2_queue_noirq(s, b2);
247 ps2_queue_noirq(s, b3);
248 ps2_queue_noirq(s, b4);
249 s->update_irq(s->update_arg, 1);
252 /* keycode is the untranslated scancode in the current scancode set. */
253 static void ps2_put_keycode(void *opaque, int keycode)
255 PS2KbdState *s = opaque;
257 trace_ps2_put_keycode(opaque, keycode);
258 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
260 if (s->translate) {
261 if (keycode == 0xf0) {
262 s->need_high_bit = true;
263 } else if (s->need_high_bit) {
264 ps2_queue(&s->common, translate_table[keycode] | 0x80);
265 s->need_high_bit = false;
266 } else {
267 ps2_queue(&s->common, translate_table[keycode]);
269 } else {
270 ps2_queue(&s->common, keycode);
274 static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,
275 InputEvent *evt)
277 PS2KbdState *s = (PS2KbdState *)dev;
278 InputKeyEvent *key = evt->u.key.data;
279 int qcode;
280 uint16_t keycode = 0;
281 int mod;
283 /* do not process events while disabled to prevent stream corruption */
284 if (!s->scan_enabled) {
285 return;
288 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
289 assert(evt->type == INPUT_EVENT_KIND_KEY);
290 qcode = qemu_input_key_value_to_qcode(key->key);
292 mod = ps2_modifier_bit(qcode);
293 trace_ps2_keyboard_event(s, qcode, key->down, mod, s->modifiers);
294 if (key->down) {
295 s->modifiers |= mod;
296 } else {
297 s->modifiers &= ~mod;
300 if (s->scancode_set == 1) {
301 if (qcode == Q_KEY_CODE_PAUSE) {
302 if (s->modifiers & (MOD_CTRL_L | MOD_CTRL_R)) {
303 if (key->down) {
304 ps2_put_keycode(s, 0xe0);
305 ps2_put_keycode(s, 0x46);
306 ps2_put_keycode(s, 0xe0);
307 ps2_put_keycode(s, 0xc6);
309 } else {
310 if (key->down) {
311 ps2_put_keycode(s, 0xe1);
312 ps2_put_keycode(s, 0x1d);
313 ps2_put_keycode(s, 0x45);
314 ps2_put_keycode(s, 0xe1);
315 ps2_put_keycode(s, 0x9d);
316 ps2_put_keycode(s, 0xc5);
319 } else if (qcode == Q_KEY_CODE_PRINT) {
320 if (s->modifiers & MOD_ALT_L) {
321 if (key->down) {
322 ps2_put_keycode(s, 0xb8);
323 ps2_put_keycode(s, 0x38);
324 ps2_put_keycode(s, 0x54);
325 } else {
326 ps2_put_keycode(s, 0xd4);
327 ps2_put_keycode(s, 0xb8);
328 ps2_put_keycode(s, 0x38);
330 } else if (s->modifiers & MOD_ALT_R) {
331 if (key->down) {
332 ps2_put_keycode(s, 0xe0);
333 ps2_put_keycode(s, 0xb8);
334 ps2_put_keycode(s, 0xe0);
335 ps2_put_keycode(s, 0x38);
336 ps2_put_keycode(s, 0x54);
337 } else {
338 ps2_put_keycode(s, 0xd4);
339 ps2_put_keycode(s, 0xe0);
340 ps2_put_keycode(s, 0xb8);
341 ps2_put_keycode(s, 0xe0);
342 ps2_put_keycode(s, 0x38);
344 } else if (s->modifiers & (MOD_SHIFT_L | MOD_CTRL_L |
345 MOD_SHIFT_R | MOD_CTRL_R)) {
346 if (key->down) {
347 ps2_put_keycode(s, 0xe0);
348 ps2_put_keycode(s, 0x37);
349 } else {
350 ps2_put_keycode(s, 0xe0);
351 ps2_put_keycode(s, 0xb7);
353 } else {
354 if (key->down) {
355 ps2_put_keycode(s, 0xe0);
356 ps2_put_keycode(s, 0x2a);
357 ps2_put_keycode(s, 0xe0);
358 ps2_put_keycode(s, 0x37);
359 } else {
360 ps2_put_keycode(s, 0xe0);
361 ps2_put_keycode(s, 0xb7);
362 ps2_put_keycode(s, 0xe0);
363 ps2_put_keycode(s, 0xaa);
366 } else {
367 if (qcode < qemu_input_map_qcode_to_atset1_len)
368 keycode = qemu_input_map_qcode_to_atset1[qcode];
369 if (keycode) {
370 if (keycode & 0xff00) {
371 ps2_put_keycode(s, keycode >> 8);
373 if (!key->down) {
374 keycode |= 0x80;
376 ps2_put_keycode(s, keycode & 0xff);
377 } else {
378 qemu_log_mask(LOG_UNIMP,
379 "ps2: ignoring key with qcode %d\n", qcode);
382 } else if (s->scancode_set == 2) {
383 if (qcode == Q_KEY_CODE_PAUSE) {
384 if (s->modifiers & (MOD_CTRL_L | MOD_CTRL_R)) {
385 if (key->down) {
386 ps2_put_keycode(s, 0xe0);
387 ps2_put_keycode(s, 0x7e);
388 ps2_put_keycode(s, 0xe0);
389 ps2_put_keycode(s, 0xf0);
390 ps2_put_keycode(s, 0x7e);
392 } else {
393 if (key->down) {
394 ps2_put_keycode(s, 0xe1);
395 ps2_put_keycode(s, 0x14);
396 ps2_put_keycode(s, 0x77);
397 ps2_put_keycode(s, 0xe1);
398 ps2_put_keycode(s, 0xf0);
399 ps2_put_keycode(s, 0x14);
400 ps2_put_keycode(s, 0xf0);
401 ps2_put_keycode(s, 0x77);
404 } else if (qcode == Q_KEY_CODE_PRINT) {
405 if (s->modifiers & MOD_ALT_L) {
406 if (key->down) {
407 ps2_put_keycode(s, 0xf0);
408 ps2_put_keycode(s, 0x11);
409 ps2_put_keycode(s, 0x11);
410 ps2_put_keycode(s, 0x84);
411 } else {
412 ps2_put_keycode(s, 0xf0);
413 ps2_put_keycode(s, 0x84);
414 ps2_put_keycode(s, 0xf0);
415 ps2_put_keycode(s, 0x11);
416 ps2_put_keycode(s, 0x11);
418 } else if (s->modifiers & MOD_ALT_R) {
419 if (key->down) {
420 ps2_put_keycode(s, 0xe0);
421 ps2_put_keycode(s, 0xf0);
422 ps2_put_keycode(s, 0x11);
423 ps2_put_keycode(s, 0xe0);
424 ps2_put_keycode(s, 0x11);
425 ps2_put_keycode(s, 0x84);
426 } else {
427 ps2_put_keycode(s, 0xf0);
428 ps2_put_keycode(s, 0x84);
429 ps2_put_keycode(s, 0xe0);
430 ps2_put_keycode(s, 0xf0);
431 ps2_put_keycode(s, 0x11);
432 ps2_put_keycode(s, 0xe0);
433 ps2_put_keycode(s, 0x11);
435 } else if (s->modifiers & (MOD_SHIFT_L | MOD_CTRL_L |
436 MOD_SHIFT_R | MOD_CTRL_R)) {
437 if (key->down) {
438 ps2_put_keycode(s, 0xe0);
439 ps2_put_keycode(s, 0x7c);
440 } else {
441 ps2_put_keycode(s, 0xe0);
442 ps2_put_keycode(s, 0xf0);
443 ps2_put_keycode(s, 0x7c);
445 } else {
446 if (key->down) {
447 ps2_put_keycode(s, 0xe0);
448 ps2_put_keycode(s, 0x12);
449 ps2_put_keycode(s, 0xe0);
450 ps2_put_keycode(s, 0x7c);
451 } else {
452 ps2_put_keycode(s, 0xe0);
453 ps2_put_keycode(s, 0xf0);
454 ps2_put_keycode(s, 0x7c);
455 ps2_put_keycode(s, 0xe0);
456 ps2_put_keycode(s, 0xf0);
457 ps2_put_keycode(s, 0x12);
460 } else {
461 if (qcode < qemu_input_map_qcode_to_atset2_len)
462 keycode = qemu_input_map_qcode_to_atset2[qcode];
463 if (keycode) {
464 if (keycode & 0xff00) {
465 ps2_put_keycode(s, keycode >> 8);
467 if (!key->down) {
468 ps2_put_keycode(s, 0xf0);
470 ps2_put_keycode(s, keycode & 0xff);
471 } else {
472 qemu_log_mask(LOG_UNIMP,
473 "ps2: ignoring key with qcode %d\n", qcode);
476 } else if (s->scancode_set == 3) {
477 if (qcode < qemu_input_map_qcode_to_atset3_len)
478 keycode = qemu_input_map_qcode_to_atset3[qcode];
479 if (keycode) {
480 /* FIXME: break code should be configured on a key by key basis */
481 if (!key->down) {
482 ps2_put_keycode(s, 0xf0);
484 ps2_put_keycode(s, keycode);
485 } else {
486 qemu_log_mask(LOG_UNIMP,
487 "ps2: ignoring key with qcode %d\n", qcode);
492 uint32_t ps2_read_data(PS2State *s)
494 PS2Queue *q;
495 int val, index;
497 trace_ps2_read_data(s);
498 q = &s->queue;
499 if (q->count == 0) {
500 /* NOTE: if no data left, we return the last keyboard one
501 (needed for EMM386) */
502 /* XXX: need a timer to do things correctly */
503 index = q->rptr - 1;
504 if (index < 0)
505 index = PS2_QUEUE_SIZE - 1;
506 val = q->data[index];
507 } else {
508 val = q->data[q->rptr];
509 if (++q->rptr == PS2_QUEUE_SIZE)
510 q->rptr = 0;
511 q->count--;
512 /* reading deasserts IRQ */
513 s->update_irq(s->update_arg, 0);
514 /* reassert IRQs if data left */
515 s->update_irq(s->update_arg, q->count != 0);
517 return val;
520 static void ps2_set_ledstate(PS2KbdState *s, int ledstate)
522 trace_ps2_set_ledstate(s, ledstate);
523 s->ledstate = ledstate;
524 kbd_put_ledstate(ledstate);
527 static void ps2_reset_keyboard(PS2KbdState *s)
529 trace_ps2_reset_keyboard(s);
530 s->scan_enabled = 1;
531 s->scancode_set = 2;
532 ps2_reset_queue(&s->common);
533 ps2_set_ledstate(s, 0);
536 void ps2_write_keyboard(void *opaque, int val)
538 PS2KbdState *s = (PS2KbdState *)opaque;
540 trace_ps2_write_keyboard(opaque, val);
541 switch(s->common.write_cmd) {
542 default:
543 case -1:
544 switch(val) {
545 case 0x00:
546 ps2_queue(&s->common, KBD_REPLY_ACK);
547 break;
548 case 0x05:
549 ps2_queue(&s->common, KBD_REPLY_RESEND);
550 break;
551 case KBD_CMD_GET_ID:
552 /* We emulate a MF2 AT keyboard here */
553 if (s->translate)
554 ps2_queue_3(&s->common,
555 KBD_REPLY_ACK,
556 KBD_REPLY_ID,
557 0x41);
558 else
559 ps2_queue_3(&s->common,
560 KBD_REPLY_ACK,
561 KBD_REPLY_ID,
562 0x83);
563 break;
564 case KBD_CMD_ECHO:
565 ps2_queue(&s->common, KBD_CMD_ECHO);
566 break;
567 case KBD_CMD_ENABLE:
568 s->scan_enabled = 1;
569 ps2_queue(&s->common, KBD_REPLY_ACK);
570 break;
571 case KBD_CMD_SCANCODE:
572 case KBD_CMD_SET_LEDS:
573 case KBD_CMD_SET_RATE:
574 s->common.write_cmd = val;
575 ps2_queue(&s->common, KBD_REPLY_ACK);
576 break;
577 case KBD_CMD_RESET_DISABLE:
578 ps2_reset_keyboard(s);
579 s->scan_enabled = 0;
580 ps2_queue(&s->common, KBD_REPLY_ACK);
581 break;
582 case KBD_CMD_RESET_ENABLE:
583 ps2_reset_keyboard(s);
584 s->scan_enabled = 1;
585 ps2_queue(&s->common, KBD_REPLY_ACK);
586 break;
587 case KBD_CMD_RESET:
588 ps2_reset_keyboard(s);
589 ps2_queue_2(&s->common,
590 KBD_REPLY_ACK,
591 KBD_REPLY_POR);
592 break;
593 default:
594 ps2_queue(&s->common, KBD_REPLY_RESEND);
595 break;
597 break;
598 case KBD_CMD_SCANCODE:
599 if (val == 0) {
600 if (s->common.queue.count <= PS2_QUEUE_SIZE - 2) {
601 ps2_queue(&s->common, KBD_REPLY_ACK);
602 ps2_put_keycode(s, s->scancode_set);
604 } else if (val >= 1 && val <= 3) {
605 s->scancode_set = val;
606 ps2_queue(&s->common, KBD_REPLY_ACK);
607 } else {
608 ps2_queue(&s->common, KBD_REPLY_RESEND);
610 s->common.write_cmd = -1;
611 break;
612 case KBD_CMD_SET_LEDS:
613 ps2_set_ledstate(s, val);
614 ps2_queue(&s->common, KBD_REPLY_ACK);
615 s->common.write_cmd = -1;
616 break;
617 case KBD_CMD_SET_RATE:
618 ps2_queue(&s->common, KBD_REPLY_ACK);
619 s->common.write_cmd = -1;
620 break;
624 /* Set the scancode translation mode.
625 0 = raw scancodes.
626 1 = translated scancodes (used by qemu internally). */
628 void ps2_keyboard_set_translation(void *opaque, int mode)
630 PS2KbdState *s = (PS2KbdState *)opaque;
631 trace_ps2_keyboard_set_translation(opaque, mode);
632 s->translate = mode;
635 static int ps2_mouse_send_packet(PS2MouseState *s)
637 const int needed = 3 + (s->mouse_type - 2);
638 unsigned int b;
639 int dx1, dy1, dz1;
641 if (PS2_QUEUE_SIZE - s->common.queue.count < needed) {
642 return 0;
645 dx1 = s->mouse_dx;
646 dy1 = s->mouse_dy;
647 dz1 = s->mouse_dz;
648 /* XXX: increase range to 8 bits ? */
649 if (dx1 > 127)
650 dx1 = 127;
651 else if (dx1 < -127)
652 dx1 = -127;
653 if (dy1 > 127)
654 dy1 = 127;
655 else if (dy1 < -127)
656 dy1 = -127;
657 b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
658 ps2_queue_noirq(&s->common, b);
659 ps2_queue_noirq(&s->common, dx1 & 0xff);
660 ps2_queue_noirq(&s->common, dy1 & 0xff);
661 /* extra byte for IMPS/2 or IMEX */
662 switch(s->mouse_type) {
663 default:
664 break;
665 case 3:
666 if (dz1 > 127)
667 dz1 = 127;
668 else if (dz1 < -127)
669 dz1 = -127;
670 ps2_queue_noirq(&s->common, dz1 & 0xff);
671 break;
672 case 4:
673 if (dz1 > 7)
674 dz1 = 7;
675 else if (dz1 < -7)
676 dz1 = -7;
677 b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
678 ps2_queue_noirq(&s->common, b);
679 break;
682 ps2_raise_irq(&s->common);
684 trace_ps2_mouse_send_packet(s, dx1, dy1, dz1, b);
685 /* update deltas */
686 s->mouse_dx -= dx1;
687 s->mouse_dy -= dy1;
688 s->mouse_dz -= dz1;
690 return 1;
693 static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
694 InputEvent *evt)
696 static const int bmap[INPUT_BUTTON__MAX] = {
697 [INPUT_BUTTON_LEFT] = PS2_MOUSE_BUTTON_LEFT,
698 [INPUT_BUTTON_MIDDLE] = PS2_MOUSE_BUTTON_MIDDLE,
699 [INPUT_BUTTON_RIGHT] = PS2_MOUSE_BUTTON_RIGHT,
700 [INPUT_BUTTON_SIDE] = PS2_MOUSE_BUTTON_SIDE,
701 [INPUT_BUTTON_EXTRA] = PS2_MOUSE_BUTTON_EXTRA,
703 PS2MouseState *s = (PS2MouseState *)dev;
704 InputMoveEvent *move;
705 InputBtnEvent *btn;
707 /* check if deltas are recorded when disabled */
708 if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
709 return;
711 switch (evt->type) {
712 case INPUT_EVENT_KIND_REL:
713 move = evt->u.rel.data;
714 if (move->axis == INPUT_AXIS_X) {
715 s->mouse_dx += move->value;
716 } else if (move->axis == INPUT_AXIS_Y) {
717 s->mouse_dy -= move->value;
719 break;
721 case INPUT_EVENT_KIND_BTN:
722 btn = evt->u.btn.data;
723 if (btn->down) {
724 s->mouse_buttons |= bmap[btn->button];
725 if (btn->button == INPUT_BUTTON_WHEEL_UP) {
726 s->mouse_dz--;
727 } else if (btn->button == INPUT_BUTTON_WHEEL_DOWN) {
728 s->mouse_dz++;
730 } else {
731 s->mouse_buttons &= ~bmap[btn->button];
733 break;
735 default:
736 /* keep gcc happy */
737 break;
741 static void ps2_mouse_sync(DeviceState *dev)
743 PS2MouseState *s = (PS2MouseState *)dev;
745 /* do not sync while disabled to prevent stream corruption */
746 if (!(s->mouse_status & MOUSE_STATUS_ENABLED)) {
747 return;
750 if (s->mouse_buttons) {
751 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
753 if (!(s->mouse_status & MOUSE_STATUS_REMOTE)) {
754 /* if not remote, send event. Multiple events are sent if
755 too big deltas */
756 while (ps2_mouse_send_packet(s)) {
757 if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
758 break;
763 void ps2_mouse_fake_event(void *opaque)
765 PS2MouseState *s = opaque;
766 trace_ps2_mouse_fake_event(opaque);
767 s->mouse_dx++;
768 ps2_mouse_sync(opaque);
771 void ps2_write_mouse(void *opaque, int val)
773 PS2MouseState *s = (PS2MouseState *)opaque;
775 trace_ps2_write_mouse(opaque, val);
776 #ifdef DEBUG_MOUSE
777 printf("kbd: write mouse 0x%02x\n", val);
778 #endif
779 switch(s->common.write_cmd) {
780 default:
781 case -1:
782 /* mouse command */
783 if (s->mouse_wrap) {
784 if (val == AUX_RESET_WRAP) {
785 s->mouse_wrap = 0;
786 ps2_queue(&s->common, AUX_ACK);
787 return;
788 } else if (val != AUX_RESET) {
789 ps2_queue(&s->common, val);
790 return;
793 switch(val) {
794 case AUX_SET_SCALE11:
795 s->mouse_status &= ~MOUSE_STATUS_SCALE21;
796 ps2_queue(&s->common, AUX_ACK);
797 break;
798 case AUX_SET_SCALE21:
799 s->mouse_status |= MOUSE_STATUS_SCALE21;
800 ps2_queue(&s->common, AUX_ACK);
801 break;
802 case AUX_SET_STREAM:
803 s->mouse_status &= ~MOUSE_STATUS_REMOTE;
804 ps2_queue(&s->common, AUX_ACK);
805 break;
806 case AUX_SET_WRAP:
807 s->mouse_wrap = 1;
808 ps2_queue(&s->common, AUX_ACK);
809 break;
810 case AUX_SET_REMOTE:
811 s->mouse_status |= MOUSE_STATUS_REMOTE;
812 ps2_queue(&s->common, AUX_ACK);
813 break;
814 case AUX_GET_TYPE:
815 ps2_queue_2(&s->common,
816 AUX_ACK,
817 s->mouse_type);
818 break;
819 case AUX_SET_RES:
820 case AUX_SET_SAMPLE:
821 s->common.write_cmd = val;
822 ps2_queue(&s->common, AUX_ACK);
823 break;
824 case AUX_GET_SCALE:
825 ps2_queue_4(&s->common,
826 AUX_ACK,
827 s->mouse_status,
828 s->mouse_resolution,
829 s->mouse_sample_rate);
830 break;
831 case AUX_POLL:
832 ps2_queue(&s->common, AUX_ACK);
833 ps2_mouse_send_packet(s);
834 break;
835 case AUX_ENABLE_DEV:
836 s->mouse_status |= MOUSE_STATUS_ENABLED;
837 ps2_queue(&s->common, AUX_ACK);
838 break;
839 case AUX_DISABLE_DEV:
840 s->mouse_status &= ~MOUSE_STATUS_ENABLED;
841 ps2_queue(&s->common, AUX_ACK);
842 break;
843 case AUX_SET_DEFAULT:
844 s->mouse_sample_rate = 100;
845 s->mouse_resolution = 2;
846 s->mouse_status = 0;
847 ps2_queue(&s->common, AUX_ACK);
848 break;
849 case AUX_RESET:
850 s->mouse_sample_rate = 100;
851 s->mouse_resolution = 2;
852 s->mouse_status = 0;
853 s->mouse_type = 0;
854 ps2_reset_queue(&s->common);
855 ps2_queue_3(&s->common,
856 AUX_ACK,
857 0xaa,
858 s->mouse_type);
859 break;
860 default:
861 break;
863 break;
864 case AUX_SET_SAMPLE:
865 s->mouse_sample_rate = val;
866 /* detect IMPS/2 or IMEX */
867 switch(s->mouse_detect_state) {
868 default:
869 case 0:
870 if (val == 200)
871 s->mouse_detect_state = 1;
872 break;
873 case 1:
874 if (val == 100)
875 s->mouse_detect_state = 2;
876 else if (val == 200)
877 s->mouse_detect_state = 3;
878 else
879 s->mouse_detect_state = 0;
880 break;
881 case 2:
882 if (val == 80)
883 s->mouse_type = 3; /* IMPS/2 */
884 s->mouse_detect_state = 0;
885 break;
886 case 3:
887 if (val == 80)
888 s->mouse_type = 4; /* IMEX */
889 s->mouse_detect_state = 0;
890 break;
892 ps2_queue(&s->common, AUX_ACK);
893 s->common.write_cmd = -1;
894 break;
895 case AUX_SET_RES:
896 s->mouse_resolution = val;
897 ps2_queue(&s->common, AUX_ACK);
898 s->common.write_cmd = -1;
899 break;
903 static void ps2_common_reset(PS2State *s)
905 s->write_cmd = -1;
906 ps2_reset_queue(s);
907 s->update_irq(s->update_arg, 0);
910 static void ps2_common_post_load(PS2State *s)
912 PS2Queue *q = &s->queue;
913 uint8_t i, size;
914 uint8_t tmp_data[PS2_QUEUE_SIZE];
916 /* set the useful data buffer queue size, < PS2_QUEUE_SIZE */
917 size = q->count;
918 if (q->count < 0) {
919 size = 0;
920 } else if (q->count > PS2_QUEUE_SIZE) {
921 size = PS2_QUEUE_SIZE;
924 /* move the queue elements to the start of data array */
925 for (i = 0; i < size; i++) {
926 if (q->rptr < 0 || q->rptr >= sizeof(q->data)) {
927 q->rptr = 0;
929 tmp_data[i] = q->data[q->rptr++];
931 memcpy(q->data, tmp_data, size);
933 /* reset rptr/wptr/count */
934 q->rptr = 0;
935 q->wptr = (size == PS2_QUEUE_SIZE) ? 0 : size;
936 q->count = size;
939 static void ps2_kbd_reset(void *opaque)
941 PS2KbdState *s = (PS2KbdState *) opaque;
943 trace_ps2_kbd_reset(opaque);
944 ps2_common_reset(&s->common);
945 s->scan_enabled = 1;
946 s->translate = 0;
947 s->scancode_set = 2;
948 s->modifiers = 0;
951 static void ps2_mouse_reset(void *opaque)
953 PS2MouseState *s = (PS2MouseState *) opaque;
955 trace_ps2_mouse_reset(opaque);
956 ps2_common_reset(&s->common);
957 s->mouse_status = 0;
958 s->mouse_resolution = 0;
959 s->mouse_sample_rate = 0;
960 s->mouse_wrap = 0;
961 s->mouse_type = 0;
962 s->mouse_detect_state = 0;
963 s->mouse_dx = 0;
964 s->mouse_dy = 0;
965 s->mouse_dz = 0;
966 s->mouse_buttons = 0;
969 static const VMStateDescription vmstate_ps2_common = {
970 .name = "PS2 Common State",
971 .version_id = 3,
972 .minimum_version_id = 2,
973 .fields = (VMStateField[]) {
974 VMSTATE_INT32(write_cmd, PS2State),
975 VMSTATE_INT32(queue.rptr, PS2State),
976 VMSTATE_INT32(queue.wptr, PS2State),
977 VMSTATE_INT32(queue.count, PS2State),
978 VMSTATE_BUFFER(queue.data, PS2State),
979 VMSTATE_END_OF_LIST()
983 static bool ps2_keyboard_ledstate_needed(void *opaque)
985 PS2KbdState *s = opaque;
987 return s->ledstate != 0; /* 0 is default state */
990 static int ps2_kbd_ledstate_post_load(void *opaque, int version_id)
992 PS2KbdState *s = opaque;
994 kbd_put_ledstate(s->ledstate);
995 return 0;
998 static const VMStateDescription vmstate_ps2_keyboard_ledstate = {
999 .name = "ps2kbd/ledstate",
1000 .version_id = 3,
1001 .minimum_version_id = 2,
1002 .post_load = ps2_kbd_ledstate_post_load,
1003 .needed = ps2_keyboard_ledstate_needed,
1004 .fields = (VMStateField[]) {
1005 VMSTATE_INT32(ledstate, PS2KbdState),
1006 VMSTATE_END_OF_LIST()
1010 static bool ps2_keyboard_need_high_bit_needed(void *opaque)
1012 PS2KbdState *s = opaque;
1013 return s->need_high_bit != 0; /* 0 is the usual state */
1016 static const VMStateDescription vmstate_ps2_keyboard_need_high_bit = {
1017 .name = "ps2kbd/need_high_bit",
1018 .version_id = 1,
1019 .minimum_version_id = 1,
1020 .needed = ps2_keyboard_need_high_bit_needed,
1021 .fields = (VMStateField[]) {
1022 VMSTATE_BOOL(need_high_bit, PS2KbdState),
1023 VMSTATE_END_OF_LIST()
1027 static int ps2_kbd_post_load(void* opaque, int version_id)
1029 PS2KbdState *s = (PS2KbdState*)opaque;
1030 PS2State *ps2 = &s->common;
1032 if (version_id == 2)
1033 s->scancode_set=2;
1035 ps2_common_post_load(ps2);
1037 return 0;
1040 static int ps2_kbd_pre_save(void *opaque)
1042 PS2KbdState *s = (PS2KbdState *)opaque;
1043 PS2State *ps2 = &s->common;
1045 ps2_common_post_load(ps2);
1047 return 0;
1050 static const VMStateDescription vmstate_ps2_keyboard = {
1051 .name = "ps2kbd",
1052 .version_id = 3,
1053 .minimum_version_id = 2,
1054 .post_load = ps2_kbd_post_load,
1055 .pre_save = ps2_kbd_pre_save,
1056 .fields = (VMStateField[]) {
1057 VMSTATE_STRUCT(common, PS2KbdState, 0, vmstate_ps2_common, PS2State),
1058 VMSTATE_INT32(scan_enabled, PS2KbdState),
1059 VMSTATE_INT32(translate, PS2KbdState),
1060 VMSTATE_INT32_V(scancode_set, PS2KbdState,3),
1061 VMSTATE_END_OF_LIST()
1063 .subsections = (const VMStateDescription*[]) {
1064 &vmstate_ps2_keyboard_ledstate,
1065 &vmstate_ps2_keyboard_need_high_bit,
1066 NULL
1070 static int ps2_mouse_post_load(void *opaque, int version_id)
1072 PS2MouseState *s = (PS2MouseState *)opaque;
1073 PS2State *ps2 = &s->common;
1075 ps2_common_post_load(ps2);
1077 return 0;
1080 static int ps2_mouse_pre_save(void *opaque)
1082 PS2MouseState *s = (PS2MouseState *)opaque;
1083 PS2State *ps2 = &s->common;
1085 ps2_common_post_load(ps2);
1087 return 0;
1090 static const VMStateDescription vmstate_ps2_mouse = {
1091 .name = "ps2mouse",
1092 .version_id = 2,
1093 .minimum_version_id = 2,
1094 .post_load = ps2_mouse_post_load,
1095 .pre_save = ps2_mouse_pre_save,
1096 .fields = (VMStateField[]) {
1097 VMSTATE_STRUCT(common, PS2MouseState, 0, vmstate_ps2_common, PS2State),
1098 VMSTATE_UINT8(mouse_status, PS2MouseState),
1099 VMSTATE_UINT8(mouse_resolution, PS2MouseState),
1100 VMSTATE_UINT8(mouse_sample_rate, PS2MouseState),
1101 VMSTATE_UINT8(mouse_wrap, PS2MouseState),
1102 VMSTATE_UINT8(mouse_type, PS2MouseState),
1103 VMSTATE_UINT8(mouse_detect_state, PS2MouseState),
1104 VMSTATE_INT32(mouse_dx, PS2MouseState),
1105 VMSTATE_INT32(mouse_dy, PS2MouseState),
1106 VMSTATE_INT32(mouse_dz, PS2MouseState),
1107 VMSTATE_UINT8(mouse_buttons, PS2MouseState),
1108 VMSTATE_END_OF_LIST()
1112 static QemuInputHandler ps2_keyboard_handler = {
1113 .name = "QEMU PS/2 Keyboard",
1114 .mask = INPUT_EVENT_MASK_KEY,
1115 .event = ps2_keyboard_event,
1118 void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
1120 PS2KbdState *s = (PS2KbdState *)g_malloc0(sizeof(PS2KbdState));
1122 trace_ps2_kbd_init(s);
1123 s->common.update_irq = update_irq;
1124 s->common.update_arg = update_arg;
1125 s->scancode_set = 2;
1126 vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s);
1127 qemu_input_handler_register((DeviceState *)s,
1128 &ps2_keyboard_handler);
1129 qemu_register_reset(ps2_kbd_reset, s);
1130 return s;
1133 static QemuInputHandler ps2_mouse_handler = {
1134 .name = "QEMU PS/2 Mouse",
1135 .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
1136 .event = ps2_mouse_event,
1137 .sync = ps2_mouse_sync,
1140 void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
1142 PS2MouseState *s = (PS2MouseState *)g_malloc0(sizeof(PS2MouseState));
1144 trace_ps2_mouse_init(s);
1145 s->common.update_irq = update_irq;
1146 s->common.update_arg = update_arg;
1147 vmstate_register(NULL, 0, &vmstate_ps2_mouse, s);
1148 qemu_input_handler_register((DeviceState *)s,
1149 &ps2_mouse_handler);
1150 qemu_register_reset(ps2_mouse_reset, s);
1151 return s;