1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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"
33
34#include "trace.h"
35
36
37#define KBD_CMD_SET_LEDS 0xED
38#define KBD_CMD_ECHO 0xEE
39#define KBD_CMD_SCANCODE 0xF0
40#define KBD_CMD_GET_ID 0xF2
41#define KBD_CMD_SET_RATE 0xF3
42#define KBD_CMD_ENABLE 0xF4
43#define KBD_CMD_RESET_DISABLE 0xF5
44#define KBD_CMD_RESET_ENABLE 0xF6
45#define KBD_CMD_RESET 0xFF
46#define KBD_CMD_SET_MAKE_BREAK 0xFC
47#define KBD_CMD_SET_TYPEMATIC 0xFA
48
49
50#define KBD_REPLY_POR 0xAA
51#define KBD_REPLY_ID 0xAB
52#define KBD_REPLY_ACK 0xFA
53#define KBD_REPLY_RESEND 0xFE
54
55
56#define AUX_SET_SCALE11 0xE6
57#define AUX_SET_SCALE21 0xE7
58#define AUX_SET_RES 0xE8
59#define AUX_GET_SCALE 0xE9
60#define AUX_SET_STREAM 0xEA
61#define AUX_POLL 0xEB
62#define AUX_RESET_WRAP 0xEC
63#define AUX_SET_WRAP 0xEE
64#define AUX_SET_REMOTE 0xF0
65#define AUX_GET_TYPE 0xF2
66#define AUX_SET_SAMPLE 0xF3
67#define AUX_ENABLE_DEV 0xF4
68#define AUX_DISABLE_DEV 0xF5
69#define AUX_SET_DEFAULT 0xF6
70#define AUX_RESET 0xFF
71#define AUX_ACK 0xFA
72
73#define MOUSE_STATUS_REMOTE 0x40
74#define MOUSE_STATUS_ENABLED 0x20
75#define MOUSE_STATUS_SCALE21 0x10
76
77
78
79
80
81#define PS2_BUFFER_SIZE 256
82#define PS2_QUEUE_SIZE 16
83#define PS2_QUEUE_HEADROOM 8
84
85
86#define MOD_CTRL_L (1 << 0)
87#define MOD_SHIFT_L (1 << 1)
88#define MOD_ALT_L (1 << 2)
89#define MOD_CTRL_R (1 << 3)
90#define MOD_SHIFT_R (1 << 4)
91#define MOD_ALT_R (1 << 5)
92
93typedef struct {
94 uint8_t data[PS2_BUFFER_SIZE];
95 int rptr, wptr, cwptr, count;
96} PS2Queue;
97
98struct PS2State {
99 PS2Queue queue;
100 int32_t write_cmd;
101 void (*update_irq)(void *, int);
102 void *update_arg;
103};
104
105typedef struct {
106 PS2State common;
107 int scan_enabled;
108 int translate;
109 int scancode_set;
110 int ledstate;
111 bool need_high_bit;
112 unsigned int modifiers;
113} PS2KbdState;
114
115typedef struct {
116 PS2State common;
117 uint8_t mouse_status;
118 uint8_t mouse_resolution;
119 uint8_t mouse_sample_rate;
120 uint8_t mouse_wrap;
121 uint8_t mouse_type;
122 uint8_t mouse_detect_state;
123 int mouse_dx;
124 int mouse_dy;
125 int mouse_dz;
126 uint8_t mouse_buttons;
127} PS2MouseState;
128
129static uint8_t translate_table[256] = {
130 0xff, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58,
131 0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59,
132 0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a,
133 0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b,
134 0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c,
135 0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d,
136 0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e,
137 0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f,
138 0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60,
139 0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61,
140 0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e,
141 0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76,
142 0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b,
143 0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f,
144 0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45,
145 0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54,
146 0x80, 0x81, 0x82, 0x41, 0x54, 0x85, 0x86, 0x87,
147 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
148 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
149 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
150 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
151 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
152 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
153 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
154 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
155 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
156 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
157 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
158 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
159 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
160 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
161 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
162};
163
164static unsigned int ps2_modifier_bit(QKeyCode key)
165{
166 switch (key) {
167 case Q_KEY_CODE_CTRL:
168 return MOD_CTRL_L;
169 case Q_KEY_CODE_CTRL_R:
170 return MOD_CTRL_R;
171 case Q_KEY_CODE_SHIFT:
172 return MOD_SHIFT_L;
173 case Q_KEY_CODE_SHIFT_R:
174 return MOD_SHIFT_R;
175 case Q_KEY_CODE_ALT:
176 return MOD_ALT_L;
177 case Q_KEY_CODE_ALT_R:
178 return MOD_ALT_R;
179 default:
180 return 0;
181 }
182}
183
184static void ps2_reset_queue(PS2State *s)
185{
186 PS2Queue *q = &s->queue;
187
188 q->rptr = 0;
189 q->wptr = 0;
190 q->cwptr = -1;
191 q->count = 0;
192}
193
194int ps2_queue_empty(PS2State *s)
195{
196 return s->queue.count == 0;
197}
198
199void ps2_queue_noirq(PS2State *s, int b)
200{
201 PS2Queue *q = &s->queue;
202
203 if (q->count >= PS2_QUEUE_SIZE) {
204 return;
205 }
206
207 q->data[q->wptr] = b;
208 if (++q->wptr == PS2_BUFFER_SIZE) {
209 q->wptr = 0;
210 }
211 q->count++;
212}
213
214void ps2_raise_irq(PS2State *s)
215{
216 s->update_irq(s->update_arg, 1);
217}
218
219void ps2_queue(PS2State *s, int b)
220{
221 if (PS2_QUEUE_SIZE - s->queue.count < 1) {
222 return;
223 }
224
225 ps2_queue_noirq(s, b);
226 ps2_raise_irq(s);
227}
228
229void ps2_queue_2(PS2State *s, int b1, int b2)
230{
231 if (PS2_QUEUE_SIZE - s->queue.count < 2) {
232 return;
233 }
234
235 ps2_queue_noirq(s, b1);
236 ps2_queue_noirq(s, b2);
237 ps2_raise_irq(s);
238}
239
240void ps2_queue_3(PS2State *s, int b1, int b2, int b3)
241{
242 if (PS2_QUEUE_SIZE - s->queue.count < 3) {
243 return;
244 }
245
246 ps2_queue_noirq(s, b1);
247 ps2_queue_noirq(s, b2);
248 ps2_queue_noirq(s, b3);
249 ps2_raise_irq(s);
250}
251
252void ps2_queue_4(PS2State *s, int b1, int b2, int b3, int b4)
253{
254 if (PS2_QUEUE_SIZE - s->queue.count < 4) {
255 return;
256 }
257
258 ps2_queue_noirq(s, b1);
259 ps2_queue_noirq(s, b2);
260 ps2_queue_noirq(s, b3);
261 ps2_queue_noirq(s, b4);
262 ps2_raise_irq(s);
263}
264
265static void ps2_cqueue_data(PS2Queue *q, int b)
266{
267 q->data[q->cwptr] = b;
268 if (++q->cwptr >= PS2_BUFFER_SIZE) {
269 q->cwptr = 0;
270 }
271 q->count++;
272}
273
274static void ps2_cqueue_1(PS2State *s, int b1)
275{
276 PS2Queue *q = &s->queue;
277
278 q->rptr = (q->rptr - 1) & (PS2_BUFFER_SIZE - 1);
279 q->cwptr = q->rptr;
280 ps2_cqueue_data(q, b1);
281 ps2_raise_irq(s);
282}
283
284static void ps2_cqueue_2(PS2State *s, int b1, int b2)
285{
286 PS2Queue *q = &s->queue;
287
288 q->rptr = (q->rptr - 2) & (PS2_BUFFER_SIZE - 1);
289 q->cwptr = q->rptr;
290 ps2_cqueue_data(q, b1);
291 ps2_cqueue_data(q, b2);
292 ps2_raise_irq(s);
293}
294
295static void ps2_cqueue_3(PS2State *s, int b1, int b2, int b3)
296{
297 PS2Queue *q = &s->queue;
298
299 q->rptr = (q->rptr - 3) & (PS2_BUFFER_SIZE - 1);
300 q->cwptr = q->rptr;
301 ps2_cqueue_data(q, b1);
302 ps2_cqueue_data(q, b2);
303 ps2_cqueue_data(q, b3);
304 ps2_raise_irq(s);
305}
306
307static void ps2_cqueue_reset(PS2State *s)
308{
309 PS2Queue *q = &s->queue;
310 int ccount;
311
312 if (q->cwptr == -1) {
313 return;
314 }
315
316 ccount = (q->cwptr - q->rptr) & (PS2_BUFFER_SIZE - 1);
317 q->count -= ccount;
318 q->rptr = q->cwptr;
319 q->cwptr = -1;
320}
321
322
323static void ps2_put_keycode(void *opaque, int keycode)
324{
325 PS2KbdState *s = opaque;
326
327 trace_ps2_put_keycode(opaque, keycode);
328 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL);
329
330 if (s->translate) {
331 if (keycode == 0xf0) {
332 s->need_high_bit = true;
333 } else if (s->need_high_bit) {
334 ps2_queue(&s->common, translate_table[keycode] | 0x80);
335 s->need_high_bit = false;
336 } else {
337 ps2_queue(&s->common, translate_table[keycode]);
338 }
339 } else {
340 ps2_queue(&s->common, keycode);
341 }
342}
343
344static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,
345 InputEvent *evt)
346{
347 PS2KbdState *s = (PS2KbdState *)dev;
348 InputKeyEvent *key = evt->u.key.data;
349 int qcode;
350 uint16_t keycode = 0;
351 int mod;
352
353
354 if (!s->scan_enabled) {
355 return;
356 }
357
358 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL);
359 assert(evt->type == INPUT_EVENT_KIND_KEY);
360 qcode = qemu_input_key_value_to_qcode(key->key);
361
362 mod = ps2_modifier_bit(qcode);
363 trace_ps2_keyboard_event(s, qcode, key->down, mod,
364 s->modifiers, s->scancode_set, s->translate);
365 if (key->down) {
366 s->modifiers |= mod;
367 } else {
368 s->modifiers &= ~mod;
369 }
370
371 if (s->scancode_set == 1) {
372 if (qcode == Q_KEY_CODE_PAUSE) {
373 if (s->modifiers & (MOD_CTRL_L | MOD_CTRL_R)) {
374 if (key->down) {
375 ps2_put_keycode(s, 0xe0);
376 ps2_put_keycode(s, 0x46);
377 ps2_put_keycode(s, 0xe0);
378 ps2_put_keycode(s, 0xc6);
379 }
380 } else {
381 if (key->down) {
382 ps2_put_keycode(s, 0xe1);
383 ps2_put_keycode(s, 0x1d);
384 ps2_put_keycode(s, 0x45);
385 ps2_put_keycode(s, 0xe1);
386 ps2_put_keycode(s, 0x9d);
387 ps2_put_keycode(s, 0xc5);
388 }
389 }
390 } else if (qcode == Q_KEY_CODE_PRINT) {
391 if (s->modifiers & MOD_ALT_L) {
392 if (key->down) {
393 ps2_put_keycode(s, 0xb8);
394 ps2_put_keycode(s, 0x38);
395 ps2_put_keycode(s, 0x54);
396 } else {
397 ps2_put_keycode(s, 0xd4);
398 ps2_put_keycode(s, 0xb8);
399 ps2_put_keycode(s, 0x38);
400 }
401 } else if (s->modifiers & MOD_ALT_R) {
402 if (key->down) {
403 ps2_put_keycode(s, 0xe0);
404 ps2_put_keycode(s, 0xb8);
405 ps2_put_keycode(s, 0xe0);
406 ps2_put_keycode(s, 0x38);
407 ps2_put_keycode(s, 0x54);
408 } else {
409 ps2_put_keycode(s, 0xd4);
410 ps2_put_keycode(s, 0xe0);
411 ps2_put_keycode(s, 0xb8);
412 ps2_put_keycode(s, 0xe0);
413 ps2_put_keycode(s, 0x38);
414 }
415 } else if (s->modifiers & (MOD_SHIFT_L | MOD_CTRL_L |
416 MOD_SHIFT_R | MOD_CTRL_R)) {
417 if (key->down) {
418 ps2_put_keycode(s, 0xe0);
419 ps2_put_keycode(s, 0x37);
420 } else {
421 ps2_put_keycode(s, 0xe0);
422 ps2_put_keycode(s, 0xb7);
423 }
424 } else {
425 if (key->down) {
426 ps2_put_keycode(s, 0xe0);
427 ps2_put_keycode(s, 0x2a);
428 ps2_put_keycode(s, 0xe0);
429 ps2_put_keycode(s, 0x37);
430 } else {
431 ps2_put_keycode(s, 0xe0);
432 ps2_put_keycode(s, 0xb7);
433 ps2_put_keycode(s, 0xe0);
434 ps2_put_keycode(s, 0xaa);
435 }
436 }
437 } else {
438 if (qcode < qemu_input_map_qcode_to_atset1_len)
439 keycode = qemu_input_map_qcode_to_atset1[qcode];
440 if (keycode) {
441 if (keycode & 0xff00) {
442 ps2_put_keycode(s, keycode >> 8);
443 }
444 if (!key->down) {
445 keycode |= 0x80;
446 }
447 ps2_put_keycode(s, keycode & 0xff);
448 } else {
449 qemu_log_mask(LOG_UNIMP,
450 "ps2: ignoring key with qcode %d\n", qcode);
451 }
452 }
453 } else if (s->scancode_set == 2) {
454 if (qcode == Q_KEY_CODE_PAUSE) {
455 if (s->modifiers & (MOD_CTRL_L | MOD_CTRL_R)) {
456 if (key->down) {
457 ps2_put_keycode(s, 0xe0);
458 ps2_put_keycode(s, 0x7e);
459 ps2_put_keycode(s, 0xe0);
460 ps2_put_keycode(s, 0xf0);
461 ps2_put_keycode(s, 0x7e);
462 }
463 } else {
464 if (key->down) {
465 ps2_put_keycode(s, 0xe1);
466 ps2_put_keycode(s, 0x14);
467 ps2_put_keycode(s, 0x77);
468 ps2_put_keycode(s, 0xe1);
469 ps2_put_keycode(s, 0xf0);
470 ps2_put_keycode(s, 0x14);
471 ps2_put_keycode(s, 0xf0);
472 ps2_put_keycode(s, 0x77);
473 }
474 }
475 } else if (qcode == Q_KEY_CODE_PRINT) {
476 if (s->modifiers & MOD_ALT_L) {
477 if (key->down) {
478 ps2_put_keycode(s, 0xf0);
479 ps2_put_keycode(s, 0x11);
480 ps2_put_keycode(s, 0x11);
481 ps2_put_keycode(s, 0x84);
482 } else {
483 ps2_put_keycode(s, 0xf0);
484 ps2_put_keycode(s, 0x84);
485 ps2_put_keycode(s, 0xf0);
486 ps2_put_keycode(s, 0x11);
487 ps2_put_keycode(s, 0x11);
488 }
489 } else if (s->modifiers & MOD_ALT_R) {
490 if (key->down) {
491 ps2_put_keycode(s, 0xe0);
492 ps2_put_keycode(s, 0xf0);
493 ps2_put_keycode(s, 0x11);
494 ps2_put_keycode(s, 0xe0);
495 ps2_put_keycode(s, 0x11);
496 ps2_put_keycode(s, 0x84);
497 } else {
498 ps2_put_keycode(s, 0xf0);
499 ps2_put_keycode(s, 0x84);
500 ps2_put_keycode(s, 0xe0);
501 ps2_put_keycode(s, 0xf0);
502 ps2_put_keycode(s, 0x11);
503 ps2_put_keycode(s, 0xe0);
504 ps2_put_keycode(s, 0x11);
505 }
506 } else if (s->modifiers & (MOD_SHIFT_L | MOD_CTRL_L |
507 MOD_SHIFT_R | MOD_CTRL_R)) {
508 if (key->down) {
509 ps2_put_keycode(s, 0xe0);
510 ps2_put_keycode(s, 0x7c);
511 } else {
512 ps2_put_keycode(s, 0xe0);
513 ps2_put_keycode(s, 0xf0);
514 ps2_put_keycode(s, 0x7c);
515 }
516 } else {
517 if (key->down) {
518 ps2_put_keycode(s, 0xe0);
519 ps2_put_keycode(s, 0x12);
520 ps2_put_keycode(s, 0xe0);
521 ps2_put_keycode(s, 0x7c);
522 } else {
523 ps2_put_keycode(s, 0xe0);
524 ps2_put_keycode(s, 0xf0);
525 ps2_put_keycode(s, 0x7c);
526 ps2_put_keycode(s, 0xe0);
527 ps2_put_keycode(s, 0xf0);
528 ps2_put_keycode(s, 0x12);
529 }
530 }
531 } else {
532 if (qcode < qemu_input_map_qcode_to_atset2_len)
533 keycode = qemu_input_map_qcode_to_atset2[qcode];
534 if (keycode) {
535 if (keycode & 0xff00) {
536 ps2_put_keycode(s, keycode >> 8);
537 }
538 if (!key->down) {
539 ps2_put_keycode(s, 0xf0);
540 }
541 ps2_put_keycode(s, keycode & 0xff);
542 } else {
543 qemu_log_mask(LOG_UNIMP,
544 "ps2: ignoring key with qcode %d\n", qcode);
545 }
546 }
547 } else if (s->scancode_set == 3) {
548 if (qcode < qemu_input_map_qcode_to_atset3_len)
549 keycode = qemu_input_map_qcode_to_atset3[qcode];
550 if (keycode) {
551
552 if (!key->down) {
553 ps2_put_keycode(s, 0xf0);
554 }
555 ps2_put_keycode(s, keycode);
556 } else {
557 qemu_log_mask(LOG_UNIMP,
558 "ps2: ignoring key with qcode %d\n", qcode);
559 }
560 }
561}
562
563uint32_t ps2_read_data(PS2State *s)
564{
565 PS2Queue *q;
566 int val, index;
567
568 trace_ps2_read_data(s);
569 q = &s->queue;
570 if (q->count == 0) {
571
572
573
574 index = q->rptr - 1;
575 if (index < 0) {
576 index = PS2_BUFFER_SIZE - 1;
577 }
578 val = q->data[index];
579 } else {
580 val = q->data[q->rptr];
581 if (++q->rptr == PS2_BUFFER_SIZE) {
582 q->rptr = 0;
583 }
584 q->count--;
585 if (q->rptr == q->cwptr) {
586
587 q->cwptr = -1;
588 }
589
590 s->update_irq(s->update_arg, 0);
591
592 if (q->count) {
593 s->update_irq(s->update_arg, 1);
594 }
595 }
596 return val;
597}
598
599static void ps2_set_ledstate(PS2KbdState *s, int ledstate)
600{
601 trace_ps2_set_ledstate(s, ledstate);
602 s->ledstate = ledstate;
603 kbd_put_ledstate(ledstate);
604}
605
606static void ps2_reset_keyboard(PS2KbdState *s)
607{
608 trace_ps2_reset_keyboard(s);
609 s->scan_enabled = 1;
610 s->scancode_set = 2;
611 ps2_reset_queue(&s->common);
612 ps2_set_ledstate(s, 0);
613}
614
615void ps2_write_keyboard(void *opaque, int val)
616{
617 PS2KbdState *s = (PS2KbdState *)opaque;
618
619 trace_ps2_write_keyboard(opaque, val);
620 ps2_cqueue_reset(&s->common);
621 switch(s->common.write_cmd) {
622 default:
623 case -1:
624 switch(val) {
625 case 0x00:
626 ps2_cqueue_1(&s->common, KBD_REPLY_ACK);
627 break;
628 case 0x05:
629 ps2_cqueue_1(&s->common, KBD_REPLY_RESEND);
630 break;
631 case KBD_CMD_GET_ID:
632
633 ps2_cqueue_3(&s->common, KBD_REPLY_ACK, KBD_REPLY_ID,
634 s->translate ? 0x41 : 0x83);
635 break;
636 case KBD_CMD_ECHO:
637 ps2_cqueue_1(&s->common, KBD_CMD_ECHO);
638 break;
639 case KBD_CMD_ENABLE:
640 s->scan_enabled = 1;
641 ps2_cqueue_1(&s->common, KBD_REPLY_ACK);
642 break;
643 case KBD_CMD_SCANCODE:
644 case KBD_CMD_SET_LEDS:
645 case KBD_CMD_SET_RATE:
646 case KBD_CMD_SET_MAKE_BREAK:
647 s->common.write_cmd = val;
648 ps2_cqueue_1(&s->common, KBD_REPLY_ACK);
649 break;
650 case KBD_CMD_RESET_DISABLE:
651 ps2_reset_keyboard(s);
652 s->scan_enabled = 0;
653 ps2_cqueue_1(&s->common, KBD_REPLY_ACK);
654 break;
655 case KBD_CMD_RESET_ENABLE:
656 ps2_reset_keyboard(s);
657 s->scan_enabled = 1;
658 ps2_cqueue_1(&s->common, KBD_REPLY_ACK);
659 break;
660 case KBD_CMD_RESET:
661 ps2_reset_keyboard(s);
662 ps2_cqueue_2(&s->common,
663 KBD_REPLY_ACK,
664 KBD_REPLY_POR);
665 break;
666 case KBD_CMD_SET_TYPEMATIC:
667 ps2_cqueue_1(&s->common, KBD_REPLY_ACK);
668 break;
669 default:
670 ps2_cqueue_1(&s->common, KBD_REPLY_RESEND);
671 break;
672 }
673 break;
674 case KBD_CMD_SET_MAKE_BREAK:
675 ps2_cqueue_1(&s->common, KBD_REPLY_ACK);
676 s->common.write_cmd = -1;
677 break;
678 case KBD_CMD_SCANCODE:
679 if (val == 0) {
680 ps2_cqueue_2(&s->common, KBD_REPLY_ACK, s->translate ?
681 translate_table[s->scancode_set] : s->scancode_set);
682 } else if (val >= 1 && val <= 3) {
683 s->scancode_set = val;
684 ps2_cqueue_1(&s->common, KBD_REPLY_ACK);
685 } else {
686 ps2_cqueue_1(&s->common, KBD_REPLY_RESEND);
687 }
688 s->common.write_cmd = -1;
689 break;
690 case KBD_CMD_SET_LEDS:
691 ps2_set_ledstate(s, val);
692 ps2_cqueue_1(&s->common, KBD_REPLY_ACK);
693 s->common.write_cmd = -1;
694 break;
695 case KBD_CMD_SET_RATE:
696 ps2_cqueue_1(&s->common, KBD_REPLY_ACK);
697 s->common.write_cmd = -1;
698 break;
699 }
700}
701
702
703
704
705
706void ps2_keyboard_set_translation(void *opaque, int mode)
707{
708 PS2KbdState *s = (PS2KbdState *)opaque;
709 trace_ps2_keyboard_set_translation(opaque, mode);
710 s->translate = mode;
711}
712
713static int ps2_mouse_send_packet(PS2MouseState *s)
714{
715
716 const int needed = s->mouse_type ? 4 : 3;
717 unsigned int b;
718 int dx1, dy1, dz1;
719
720 if (PS2_QUEUE_SIZE - s->common.queue.count < needed) {
721 return 0;
722 }
723
724 dx1 = s->mouse_dx;
725 dy1 = s->mouse_dy;
726 dz1 = s->mouse_dz;
727
728 if (dx1 > 127)
729 dx1 = 127;
730 else if (dx1 < -127)
731 dx1 = -127;
732 if (dy1 > 127)
733 dy1 = 127;
734 else if (dy1 < -127)
735 dy1 = -127;
736 b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
737 ps2_queue_noirq(&s->common, b);
738 ps2_queue_noirq(&s->common, dx1 & 0xff);
739 ps2_queue_noirq(&s->common, dy1 & 0xff);
740
741 switch(s->mouse_type) {
742 default:
743 break;
744 case 3:
745 if (dz1 > 127)
746 dz1 = 127;
747 else if (dz1 < -127)
748 dz1 = -127;
749 ps2_queue_noirq(&s->common, dz1 & 0xff);
750 break;
751 case 4:
752 if (dz1 > 7)
753 dz1 = 7;
754 else if (dz1 < -7)
755 dz1 = -7;
756 b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
757 ps2_queue_noirq(&s->common, b);
758 break;
759 }
760
761 ps2_raise_irq(&s->common);
762
763 trace_ps2_mouse_send_packet(s, dx1, dy1, dz1, b);
764
765 s->mouse_dx -= dx1;
766 s->mouse_dy -= dy1;
767 s->mouse_dz -= dz1;
768
769 return 1;
770}
771
772static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
773 InputEvent *evt)
774{
775 static const int bmap[INPUT_BUTTON__MAX] = {
776 [INPUT_BUTTON_LEFT] = PS2_MOUSE_BUTTON_LEFT,
777 [INPUT_BUTTON_MIDDLE] = PS2_MOUSE_BUTTON_MIDDLE,
778 [INPUT_BUTTON_RIGHT] = PS2_MOUSE_BUTTON_RIGHT,
779 [INPUT_BUTTON_SIDE] = PS2_MOUSE_BUTTON_SIDE,
780 [INPUT_BUTTON_EXTRA] = PS2_MOUSE_BUTTON_EXTRA,
781 };
782 PS2MouseState *s = (PS2MouseState *)dev;
783 InputMoveEvent *move;
784 InputBtnEvent *btn;
785
786
787 if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
788 return;
789
790 switch (evt->type) {
791 case INPUT_EVENT_KIND_REL:
792 move = evt->u.rel.data;
793 if (move->axis == INPUT_AXIS_X) {
794 s->mouse_dx += move->value;
795 } else if (move->axis == INPUT_AXIS_Y) {
796 s->mouse_dy -= move->value;
797 }
798 break;
799
800 case INPUT_EVENT_KIND_BTN:
801 btn = evt->u.btn.data;
802 if (btn->down) {
803 s->mouse_buttons |= bmap[btn->button];
804 if (btn->button == INPUT_BUTTON_WHEEL_UP) {
805 s->mouse_dz--;
806 } else if (btn->button == INPUT_BUTTON_WHEEL_DOWN) {
807 s->mouse_dz++;
808 }
809 } else {
810 s->mouse_buttons &= ~bmap[btn->button];
811 }
812 break;
813
814 default:
815
816 break;
817 }
818}
819
820static void ps2_mouse_sync(DeviceState *dev)
821{
822 PS2MouseState *s = (PS2MouseState *)dev;
823
824
825 if (!(s->mouse_status & MOUSE_STATUS_ENABLED)) {
826 return;
827 }
828
829 if (s->mouse_buttons) {
830 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL);
831 }
832 if (!(s->mouse_status & MOUSE_STATUS_REMOTE)) {
833
834
835 while (ps2_mouse_send_packet(s)) {
836 if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
837 break;
838 }
839 }
840}
841
842void ps2_mouse_fake_event(void *opaque)
843{
844 PS2MouseState *s = opaque;
845 trace_ps2_mouse_fake_event(opaque);
846 s->mouse_dx++;
847 ps2_mouse_sync(opaque);
848}
849
850void ps2_write_mouse(void *opaque, int val)
851{
852 PS2MouseState *s = (PS2MouseState *)opaque;
853
854 trace_ps2_write_mouse(opaque, val);
855 switch(s->common.write_cmd) {
856 default:
857 case -1:
858
859 if (s->mouse_wrap) {
860 if (val == AUX_RESET_WRAP) {
861 s->mouse_wrap = 0;
862 ps2_queue(&s->common, AUX_ACK);
863 return;
864 } else if (val != AUX_RESET) {
865 ps2_queue(&s->common, val);
866 return;
867 }
868 }
869 switch(val) {
870 case AUX_SET_SCALE11:
871 s->mouse_status &= ~MOUSE_STATUS_SCALE21;
872 ps2_queue(&s->common, AUX_ACK);
873 break;
874 case AUX_SET_SCALE21:
875 s->mouse_status |= MOUSE_STATUS_SCALE21;
876 ps2_queue(&s->common, AUX_ACK);
877 break;
878 case AUX_SET_STREAM:
879 s->mouse_status &= ~MOUSE_STATUS_REMOTE;
880 ps2_queue(&s->common, AUX_ACK);
881 break;
882 case AUX_SET_WRAP:
883 s->mouse_wrap = 1;
884 ps2_queue(&s->common, AUX_ACK);
885 break;
886 case AUX_SET_REMOTE:
887 s->mouse_status |= MOUSE_STATUS_REMOTE;
888 ps2_queue(&s->common, AUX_ACK);
889 break;
890 case AUX_GET_TYPE:
891 ps2_queue_2(&s->common,
892 AUX_ACK,
893 s->mouse_type);
894 break;
895 case AUX_SET_RES:
896 case AUX_SET_SAMPLE:
897 s->common.write_cmd = val;
898 ps2_queue(&s->common, AUX_ACK);
899 break;
900 case AUX_GET_SCALE:
901 ps2_queue_4(&s->common,
902 AUX_ACK,
903 s->mouse_status,
904 s->mouse_resolution,
905 s->mouse_sample_rate);
906 break;
907 case AUX_POLL:
908 ps2_queue(&s->common, AUX_ACK);
909 ps2_mouse_send_packet(s);
910 break;
911 case AUX_ENABLE_DEV:
912 s->mouse_status |= MOUSE_STATUS_ENABLED;
913 ps2_queue(&s->common, AUX_ACK);
914 break;
915 case AUX_DISABLE_DEV:
916 s->mouse_status &= ~MOUSE_STATUS_ENABLED;
917 ps2_queue(&s->common, AUX_ACK);
918 break;
919 case AUX_SET_DEFAULT:
920 s->mouse_sample_rate = 100;
921 s->mouse_resolution = 2;
922 s->mouse_status = 0;
923 ps2_queue(&s->common, AUX_ACK);
924 break;
925 case AUX_RESET:
926 s->mouse_sample_rate = 100;
927 s->mouse_resolution = 2;
928 s->mouse_status = 0;
929 s->mouse_type = 0;
930 ps2_reset_queue(&s->common);
931 ps2_queue_3(&s->common,
932 AUX_ACK,
933 0xaa,
934 s->mouse_type);
935 break;
936 default:
937 break;
938 }
939 break;
940 case AUX_SET_SAMPLE:
941 s->mouse_sample_rate = val;
942
943 switch(s->mouse_detect_state) {
944 default:
945 case 0:
946 if (val == 200)
947 s->mouse_detect_state = 1;
948 break;
949 case 1:
950 if (val == 100)
951 s->mouse_detect_state = 2;
952 else if (val == 200)
953 s->mouse_detect_state = 3;
954 else
955 s->mouse_detect_state = 0;
956 break;
957 case 2:
958 if (val == 80)
959 s->mouse_type = 3;
960 s->mouse_detect_state = 0;
961 break;
962 case 3:
963 if (val == 80)
964 s->mouse_type = 4;
965 s->mouse_detect_state = 0;
966 break;
967 }
968 ps2_queue(&s->common, AUX_ACK);
969 s->common.write_cmd = -1;
970 break;
971 case AUX_SET_RES:
972 s->mouse_resolution = val;
973 ps2_queue(&s->common, AUX_ACK);
974 s->common.write_cmd = -1;
975 break;
976 }
977}
978
979static void ps2_common_reset(PS2State *s)
980{
981 s->write_cmd = -1;
982 ps2_reset_queue(s);
983 s->update_irq(s->update_arg, 0);
984}
985
986static void ps2_common_post_load(PS2State *s)
987{
988 PS2Queue *q = &s->queue;
989 int ccount = 0;
990
991
992 if (q->cwptr != -1) {
993 ccount = (q->cwptr - q->rptr) & (PS2_BUFFER_SIZE - 1);
994 if (ccount > PS2_QUEUE_HEADROOM) {
995 ccount = PS2_QUEUE_HEADROOM;
996 }
997 }
998
999
1000 if (q->count < ccount) {
1001 q->count = ccount;
1002 } else if (q->count > ccount + PS2_QUEUE_SIZE) {
1003 q->count = ccount + PS2_QUEUE_SIZE;
1004 }
1005
1006
1007 q->rptr = q->rptr & (PS2_BUFFER_SIZE - 1);
1008 q->wptr = (q->rptr + q->count) & (PS2_BUFFER_SIZE - 1);
1009 q->cwptr = ccount ? (q->rptr + ccount) & (PS2_BUFFER_SIZE - 1) : -1;
1010}
1011
1012static void ps2_kbd_reset(void *opaque)
1013{
1014 PS2KbdState *s = (PS2KbdState *) opaque;
1015
1016 trace_ps2_kbd_reset(opaque);
1017 ps2_common_reset(&s->common);
1018 s->scan_enabled = 1;
1019 s->translate = 0;
1020 s->scancode_set = 2;
1021 s->modifiers = 0;
1022}
1023
1024static void ps2_mouse_reset(void *opaque)
1025{
1026 PS2MouseState *s = (PS2MouseState *) opaque;
1027
1028 trace_ps2_mouse_reset(opaque);
1029 ps2_common_reset(&s->common);
1030 s->mouse_status = 0;
1031 s->mouse_resolution = 0;
1032 s->mouse_sample_rate = 0;
1033 s->mouse_wrap = 0;
1034 s->mouse_type = 0;
1035 s->mouse_detect_state = 0;
1036 s->mouse_dx = 0;
1037 s->mouse_dy = 0;
1038 s->mouse_dz = 0;
1039 s->mouse_buttons = 0;
1040}
1041
1042static const VMStateDescription vmstate_ps2_common = {
1043 .name = "PS2 Common State",
1044 .version_id = 3,
1045 .minimum_version_id = 2,
1046 .fields = (VMStateField[]) {
1047 VMSTATE_INT32(write_cmd, PS2State),
1048 VMSTATE_INT32(queue.rptr, PS2State),
1049 VMSTATE_INT32(queue.wptr, PS2State),
1050 VMSTATE_INT32(queue.count, PS2State),
1051 VMSTATE_BUFFER(queue.data, PS2State),
1052 VMSTATE_END_OF_LIST()
1053 }
1054};
1055
1056static bool ps2_keyboard_ledstate_needed(void *opaque)
1057{
1058 PS2KbdState *s = opaque;
1059
1060 return s->ledstate != 0;
1061}
1062
1063static int ps2_kbd_ledstate_post_load(void *opaque, int version_id)
1064{
1065 PS2KbdState *s = opaque;
1066
1067 kbd_put_ledstate(s->ledstate);
1068 return 0;
1069}
1070
1071static const VMStateDescription vmstate_ps2_keyboard_ledstate = {
1072 .name = "ps2kbd/ledstate",
1073 .version_id = 3,
1074 .minimum_version_id = 2,
1075 .post_load = ps2_kbd_ledstate_post_load,
1076 .needed = ps2_keyboard_ledstate_needed,
1077 .fields = (VMStateField[]) {
1078 VMSTATE_INT32(ledstate, PS2KbdState),
1079 VMSTATE_END_OF_LIST()
1080 }
1081};
1082
1083static bool ps2_keyboard_need_high_bit_needed(void *opaque)
1084{
1085 PS2KbdState *s = opaque;
1086 return s->need_high_bit != 0;
1087}
1088
1089static const VMStateDescription vmstate_ps2_keyboard_need_high_bit = {
1090 .name = "ps2kbd/need_high_bit",
1091 .version_id = 1,
1092 .minimum_version_id = 1,
1093 .needed = ps2_keyboard_need_high_bit_needed,
1094 .fields = (VMStateField[]) {
1095 VMSTATE_BOOL(need_high_bit, PS2KbdState),
1096 VMSTATE_END_OF_LIST()
1097 }
1098};
1099
1100static bool ps2_keyboard_cqueue_needed(void *opaque)
1101{
1102 PS2KbdState *s = opaque;
1103
1104 return s->common.queue.cwptr != -1;
1105}
1106
1107static const VMStateDescription vmstate_ps2_keyboard_cqueue = {
1108 .name = "ps2kbd/command_reply_queue",
1109 .needed = ps2_keyboard_cqueue_needed,
1110 .fields = (VMStateField[]) {
1111 VMSTATE_INT32(common.queue.cwptr, PS2KbdState),
1112 VMSTATE_END_OF_LIST()
1113 }
1114};
1115
1116static int ps2_kbd_post_load(void* opaque, int version_id)
1117{
1118 PS2KbdState *s = (PS2KbdState*)opaque;
1119 PS2State *ps2 = &s->common;
1120
1121 if (version_id == 2)
1122 s->scancode_set=2;
1123
1124 ps2_common_post_load(ps2);
1125
1126 return 0;
1127}
1128
1129static const VMStateDescription vmstate_ps2_keyboard = {
1130 .name = "ps2kbd",
1131 .version_id = 3,
1132 .minimum_version_id = 2,
1133 .post_load = ps2_kbd_post_load,
1134 .fields = (VMStateField[]) {
1135 VMSTATE_STRUCT(common, PS2KbdState, 0, vmstate_ps2_common, PS2State),
1136 VMSTATE_INT32(scan_enabled, PS2KbdState),
1137 VMSTATE_INT32(translate, PS2KbdState),
1138 VMSTATE_INT32_V(scancode_set, PS2KbdState,3),
1139 VMSTATE_END_OF_LIST()
1140 },
1141 .subsections = (const VMStateDescription*[]) {
1142 &vmstate_ps2_keyboard_ledstate,
1143 &vmstate_ps2_keyboard_need_high_bit,
1144 &vmstate_ps2_keyboard_cqueue,
1145 NULL
1146 }
1147};
1148
1149static int ps2_mouse_post_load(void *opaque, int version_id)
1150{
1151 PS2MouseState *s = (PS2MouseState *)opaque;
1152 PS2State *ps2 = &s->common;
1153
1154 ps2_common_post_load(ps2);
1155
1156 return 0;
1157}
1158
1159static const VMStateDescription vmstate_ps2_mouse = {
1160 .name = "ps2mouse",
1161 .version_id = 2,
1162 .minimum_version_id = 2,
1163 .post_load = ps2_mouse_post_load,
1164 .fields = (VMStateField[]) {
1165 VMSTATE_STRUCT(common, PS2MouseState, 0, vmstate_ps2_common, PS2State),
1166 VMSTATE_UINT8(mouse_status, PS2MouseState),
1167 VMSTATE_UINT8(mouse_resolution, PS2MouseState),
1168 VMSTATE_UINT8(mouse_sample_rate, PS2MouseState),
1169 VMSTATE_UINT8(mouse_wrap, PS2MouseState),
1170 VMSTATE_UINT8(mouse_type, PS2MouseState),
1171 VMSTATE_UINT8(mouse_detect_state, PS2MouseState),
1172 VMSTATE_INT32(mouse_dx, PS2MouseState),
1173 VMSTATE_INT32(mouse_dy, PS2MouseState),
1174 VMSTATE_INT32(mouse_dz, PS2MouseState),
1175 VMSTATE_UINT8(mouse_buttons, PS2MouseState),
1176 VMSTATE_END_OF_LIST()
1177 }
1178};
1179
1180static QemuInputHandler ps2_keyboard_handler = {
1181 .name = "QEMU PS/2 Keyboard",
1182 .mask = INPUT_EVENT_MASK_KEY,
1183 .event = ps2_keyboard_event,
1184};
1185
1186void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
1187{
1188 PS2KbdState *s = (PS2KbdState *)g_malloc0(sizeof(PS2KbdState));
1189
1190 trace_ps2_kbd_init(s);
1191 s->common.update_irq = update_irq;
1192 s->common.update_arg = update_arg;
1193 s->scancode_set = 2;
1194 vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s);
1195 qemu_input_handler_register((DeviceState *)s,
1196 &ps2_keyboard_handler);
1197 qemu_register_reset(ps2_kbd_reset, s);
1198 return s;
1199}
1200
1201static QemuInputHandler ps2_mouse_handler = {
1202 .name = "QEMU PS/2 Mouse",
1203 .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
1204 .event = ps2_mouse_event,
1205 .sync = ps2_mouse_sync,
1206};
1207
1208void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
1209{
1210 PS2MouseState *s = (PS2MouseState *)g_malloc0(sizeof(PS2MouseState));
1211
1212 trace_ps2_mouse_init(s);
1213 s->common.update_irq = update_irq;
1214 s->common.update_arg = update_arg;
1215 vmstate_register(NULL, 0, &vmstate_ps2_mouse, s);
1216 qemu_input_handler_register((DeviceState *)s,
1217 &ps2_mouse_handler);
1218 qemu_register_reset(ps2_mouse_reset, s);
1219 return s;
1220}
1221