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#define PS2_QUEUE_SIZE 16
78
79
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)
86
87typedef struct {
88
89
90 uint8_t data[256];
91 int rptr, wptr, count;
92} PS2Queue;
93
94struct PS2State {
95 PS2Queue queue;
96 int32_t write_cmd;
97 void (*update_irq)(void *, int);
98 void *update_arg;
99};
100
101typedef struct {
102 PS2State common;
103 int scan_enabled;
104 int translate;
105 int scancode_set;
106 int ledstate;
107 bool need_high_bit;
108 unsigned int modifiers;
109} PS2KbdState;
110
111typedef 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;
118 uint8_t mouse_detect_state;
119 int mouse_dx;
120 int mouse_dy;
121 int mouse_dz;
122 uint8_t mouse_buttons;
123} PS2MouseState;
124
125static 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,
158};
159
160static unsigned int ps2_modifier_bit(QKeyCode key)
161{
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;
177 }
178}
179
180static void ps2_reset_queue(PS2State *s)
181{
182 PS2Queue *q = &s->queue;
183
184 q->rptr = 0;
185 q->wptr = 0;
186 q->count = 0;
187}
188
189int ps2_queue_empty(PS2State *s)
190{
191 return s->queue.count == 0;
192}
193
194void ps2_queue_noirq(PS2State *s, int b)
195{
196 PS2Queue *q = &s->queue;
197
198 if (q->count == PS2_QUEUE_SIZE) {
199 return;
200 }
201
202 q->data[q->wptr] = b;
203 if (++q->wptr == PS2_QUEUE_SIZE)
204 q->wptr = 0;
205 q->count++;
206}
207
208void ps2_raise_irq(PS2State *s)
209{
210 s->update_irq(s->update_arg, 1);
211}
212
213void ps2_queue(PS2State *s, int b)
214{
215 if (PS2_QUEUE_SIZE - s->queue.count < 1) {
216 return;
217 }
218
219 ps2_queue_noirq(s, b);
220 ps2_raise_irq(s);
221}
222
223void ps2_queue_2(PS2State *s, int b1, int b2)
224{
225 if (PS2_QUEUE_SIZE - s->queue.count < 2) {
226 return;
227 }
228
229 ps2_queue_noirq(s, b1);
230 ps2_queue_noirq(s, b2);
231 ps2_raise_irq(s);
232}
233
234void ps2_queue_3(PS2State *s, int b1, int b2, int b3)
235{
236 if (PS2_QUEUE_SIZE - s->queue.count < 3) {
237 return;
238 }
239
240 ps2_queue_noirq(s, b1);
241 ps2_queue_noirq(s, b2);
242 ps2_queue_noirq(s, b3);
243 ps2_raise_irq(s);
244}
245
246void ps2_queue_4(PS2State *s, int b1, int b2, int b3, int b4)
247{
248 if (PS2_QUEUE_SIZE - s->queue.count < 4) {
249 return;
250 }
251
252 ps2_queue_noirq(s, b1);
253 ps2_queue_noirq(s, b2);
254 ps2_queue_noirq(s, b3);
255 ps2_queue_noirq(s, b4);
256 ps2_raise_irq(s);
257}
258
259
260static void ps2_put_keycode(void *opaque, int keycode)
261{
262 PS2KbdState *s = opaque;
263
264 trace_ps2_put_keycode(opaque, keycode);
265 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL);
266
267 if (s->translate) {
268 if (keycode == 0xf0) {
269 s->need_high_bit = true;
270 } else if (s->need_high_bit) {
271 ps2_queue(&s->common, translate_table[keycode] | 0x80);
272 s->need_high_bit = false;
273 } else {
274 ps2_queue(&s->common, translate_table[keycode]);
275 }
276 } else {
277 ps2_queue(&s->common, keycode);
278 }
279}
280
281static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,
282 InputEvent *evt)
283{
284 PS2KbdState *s = (PS2KbdState *)dev;
285 InputKeyEvent *key = evt->u.key.data;
286 int qcode;
287 uint16_t keycode = 0;
288 int mod;
289
290
291 if (!s->scan_enabled) {
292 return;
293 }
294
295 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL);
296 assert(evt->type == INPUT_EVENT_KIND_KEY);
297 qcode = qemu_input_key_value_to_qcode(key->key);
298
299 mod = ps2_modifier_bit(qcode);
300 trace_ps2_keyboard_event(s, qcode, key->down, mod,
301 s->modifiers, s->scancode_set, s->translate);
302 if (key->down) {
303 s->modifiers |= mod;
304 } else {
305 s->modifiers &= ~mod;
306 }
307
308 if (s->scancode_set == 1) {
309 if (qcode == Q_KEY_CODE_PAUSE) {
310 if (s->modifiers & (MOD_CTRL_L | MOD_CTRL_R)) {
311 if (key->down) {
312 ps2_put_keycode(s, 0xe0);
313 ps2_put_keycode(s, 0x46);
314 ps2_put_keycode(s, 0xe0);
315 ps2_put_keycode(s, 0xc6);
316 }
317 } else {
318 if (key->down) {
319 ps2_put_keycode(s, 0xe1);
320 ps2_put_keycode(s, 0x1d);
321 ps2_put_keycode(s, 0x45);
322 ps2_put_keycode(s, 0xe1);
323 ps2_put_keycode(s, 0x9d);
324 ps2_put_keycode(s, 0xc5);
325 }
326 }
327 } else if (qcode == Q_KEY_CODE_PRINT) {
328 if (s->modifiers & MOD_ALT_L) {
329 if (key->down) {
330 ps2_put_keycode(s, 0xb8);
331 ps2_put_keycode(s, 0x38);
332 ps2_put_keycode(s, 0x54);
333 } else {
334 ps2_put_keycode(s, 0xd4);
335 ps2_put_keycode(s, 0xb8);
336 ps2_put_keycode(s, 0x38);
337 }
338 } else if (s->modifiers & MOD_ALT_R) {
339 if (key->down) {
340 ps2_put_keycode(s, 0xe0);
341 ps2_put_keycode(s, 0xb8);
342 ps2_put_keycode(s, 0xe0);
343 ps2_put_keycode(s, 0x38);
344 ps2_put_keycode(s, 0x54);
345 } else {
346 ps2_put_keycode(s, 0xd4);
347 ps2_put_keycode(s, 0xe0);
348 ps2_put_keycode(s, 0xb8);
349 ps2_put_keycode(s, 0xe0);
350 ps2_put_keycode(s, 0x38);
351 }
352 } else if (s->modifiers & (MOD_SHIFT_L | MOD_CTRL_L |
353 MOD_SHIFT_R | MOD_CTRL_R)) {
354 if (key->down) {
355 ps2_put_keycode(s, 0xe0);
356 ps2_put_keycode(s, 0x37);
357 } else {
358 ps2_put_keycode(s, 0xe0);
359 ps2_put_keycode(s, 0xb7);
360 }
361 } else {
362 if (key->down) {
363 ps2_put_keycode(s, 0xe0);
364 ps2_put_keycode(s, 0x2a);
365 ps2_put_keycode(s, 0xe0);
366 ps2_put_keycode(s, 0x37);
367 } else {
368 ps2_put_keycode(s, 0xe0);
369 ps2_put_keycode(s, 0xb7);
370 ps2_put_keycode(s, 0xe0);
371 ps2_put_keycode(s, 0xaa);
372 }
373 }
374 } else {
375 if (qcode < qemu_input_map_qcode_to_atset1_len)
376 keycode = qemu_input_map_qcode_to_atset1[qcode];
377 if (keycode) {
378 if (keycode & 0xff00) {
379 ps2_put_keycode(s, keycode >> 8);
380 }
381 if (!key->down) {
382 keycode |= 0x80;
383 }
384 ps2_put_keycode(s, keycode & 0xff);
385 } else {
386 qemu_log_mask(LOG_UNIMP,
387 "ps2: ignoring key with qcode %d\n", qcode);
388 }
389 }
390 } else if (s->scancode_set == 2) {
391 if (qcode == Q_KEY_CODE_PAUSE) {
392 if (s->modifiers & (MOD_CTRL_L | MOD_CTRL_R)) {
393 if (key->down) {
394 ps2_put_keycode(s, 0xe0);
395 ps2_put_keycode(s, 0x7e);
396 ps2_put_keycode(s, 0xe0);
397 ps2_put_keycode(s, 0xf0);
398 ps2_put_keycode(s, 0x7e);
399 }
400 } else {
401 if (key->down) {
402 ps2_put_keycode(s, 0xe1);
403 ps2_put_keycode(s, 0x14);
404 ps2_put_keycode(s, 0x77);
405 ps2_put_keycode(s, 0xe1);
406 ps2_put_keycode(s, 0xf0);
407 ps2_put_keycode(s, 0x14);
408 ps2_put_keycode(s, 0xf0);
409 ps2_put_keycode(s, 0x77);
410 }
411 }
412 } else if (qcode == Q_KEY_CODE_PRINT) {
413 if (s->modifiers & MOD_ALT_L) {
414 if (key->down) {
415 ps2_put_keycode(s, 0xf0);
416 ps2_put_keycode(s, 0x11);
417 ps2_put_keycode(s, 0x11);
418 ps2_put_keycode(s, 0x84);
419 } else {
420 ps2_put_keycode(s, 0xf0);
421 ps2_put_keycode(s, 0x84);
422 ps2_put_keycode(s, 0xf0);
423 ps2_put_keycode(s, 0x11);
424 ps2_put_keycode(s, 0x11);
425 }
426 } else if (s->modifiers & MOD_ALT_R) {
427 if (key->down) {
428 ps2_put_keycode(s, 0xe0);
429 ps2_put_keycode(s, 0xf0);
430 ps2_put_keycode(s, 0x11);
431 ps2_put_keycode(s, 0xe0);
432 ps2_put_keycode(s, 0x11);
433 ps2_put_keycode(s, 0x84);
434 } else {
435 ps2_put_keycode(s, 0xf0);
436 ps2_put_keycode(s, 0x84);
437 ps2_put_keycode(s, 0xe0);
438 ps2_put_keycode(s, 0xf0);
439 ps2_put_keycode(s, 0x11);
440 ps2_put_keycode(s, 0xe0);
441 ps2_put_keycode(s, 0x11);
442 }
443 } else if (s->modifiers & (MOD_SHIFT_L | MOD_CTRL_L |
444 MOD_SHIFT_R | MOD_CTRL_R)) {
445 if (key->down) {
446 ps2_put_keycode(s, 0xe0);
447 ps2_put_keycode(s, 0x7c);
448 } else {
449 ps2_put_keycode(s, 0xe0);
450 ps2_put_keycode(s, 0xf0);
451 ps2_put_keycode(s, 0x7c);
452 }
453 } else {
454 if (key->down) {
455 ps2_put_keycode(s, 0xe0);
456 ps2_put_keycode(s, 0x12);
457 ps2_put_keycode(s, 0xe0);
458 ps2_put_keycode(s, 0x7c);
459 } else {
460 ps2_put_keycode(s, 0xe0);
461 ps2_put_keycode(s, 0xf0);
462 ps2_put_keycode(s, 0x7c);
463 ps2_put_keycode(s, 0xe0);
464 ps2_put_keycode(s, 0xf0);
465 ps2_put_keycode(s, 0x12);
466 }
467 }
468 } else {
469 if (qcode < qemu_input_map_qcode_to_atset2_len)
470 keycode = qemu_input_map_qcode_to_atset2[qcode];
471 if (keycode) {
472 if (keycode & 0xff00) {
473 ps2_put_keycode(s, keycode >> 8);
474 }
475 if (!key->down) {
476 ps2_put_keycode(s, 0xf0);
477 }
478 ps2_put_keycode(s, keycode & 0xff);
479 } else {
480 qemu_log_mask(LOG_UNIMP,
481 "ps2: ignoring key with qcode %d\n", qcode);
482 }
483 }
484 } else if (s->scancode_set == 3) {
485 if (qcode < qemu_input_map_qcode_to_atset3_len)
486 keycode = qemu_input_map_qcode_to_atset3[qcode];
487 if (keycode) {
488
489 if (!key->down) {
490 ps2_put_keycode(s, 0xf0);
491 }
492 ps2_put_keycode(s, keycode);
493 } else {
494 qemu_log_mask(LOG_UNIMP,
495 "ps2: ignoring key with qcode %d\n", qcode);
496 }
497 }
498}
499
500uint32_t ps2_read_data(PS2State *s)
501{
502 PS2Queue *q;
503 int val, index;
504
505 trace_ps2_read_data(s);
506 q = &s->queue;
507 if (q->count == 0) {
508
509
510
511 index = q->rptr - 1;
512 if (index < 0)
513 index = PS2_QUEUE_SIZE - 1;
514 val = q->data[index];
515 } else {
516 val = q->data[q->rptr];
517 if (++q->rptr == PS2_QUEUE_SIZE)
518 q->rptr = 0;
519 q->count--;
520
521 s->update_irq(s->update_arg, 0);
522
523 if (q->count) {
524 s->update_irq(s->update_arg, 1);
525 }
526 }
527 return val;
528}
529
530static void ps2_set_ledstate(PS2KbdState *s, int ledstate)
531{
532 trace_ps2_set_ledstate(s, ledstate);
533 s->ledstate = ledstate;
534 kbd_put_ledstate(ledstate);
535}
536
537static void ps2_reset_keyboard(PS2KbdState *s)
538{
539 trace_ps2_reset_keyboard(s);
540 s->scan_enabled = 1;
541 s->scancode_set = 2;
542 ps2_reset_queue(&s->common);
543 ps2_set_ledstate(s, 0);
544}
545
546void ps2_write_keyboard(void *opaque, int val)
547{
548 PS2KbdState *s = (PS2KbdState *)opaque;
549
550 trace_ps2_write_keyboard(opaque, val);
551 switch(s->common.write_cmd) {
552 default:
553 case -1:
554 switch(val) {
555 case 0x00:
556 ps2_queue(&s->common, KBD_REPLY_ACK);
557 break;
558 case 0x05:
559 ps2_queue(&s->common, KBD_REPLY_RESEND);
560 break;
561 case KBD_CMD_GET_ID:
562
563 if (s->translate)
564 ps2_queue_3(&s->common,
565 KBD_REPLY_ACK,
566 KBD_REPLY_ID,
567 0x41);
568 else
569 ps2_queue_3(&s->common,
570 KBD_REPLY_ACK,
571 KBD_REPLY_ID,
572 0x83);
573 break;
574 case KBD_CMD_ECHO:
575 ps2_queue(&s->common, KBD_CMD_ECHO);
576 break;
577 case KBD_CMD_ENABLE:
578 s->scan_enabled = 1;
579 ps2_queue(&s->common, KBD_REPLY_ACK);
580 break;
581 case KBD_CMD_SCANCODE:
582 case KBD_CMD_SET_LEDS:
583 case KBD_CMD_SET_RATE:
584 case KBD_CMD_SET_MAKE_BREAK:
585 s->common.write_cmd = val;
586 ps2_queue(&s->common, KBD_REPLY_ACK);
587 break;
588 case KBD_CMD_RESET_DISABLE:
589 ps2_reset_keyboard(s);
590 s->scan_enabled = 0;
591 ps2_queue(&s->common, KBD_REPLY_ACK);
592 break;
593 case KBD_CMD_RESET_ENABLE:
594 ps2_reset_keyboard(s);
595 s->scan_enabled = 1;
596 ps2_queue(&s->common, KBD_REPLY_ACK);
597 break;
598 case KBD_CMD_RESET:
599 ps2_reset_keyboard(s);
600 ps2_queue_2(&s->common,
601 KBD_REPLY_ACK,
602 KBD_REPLY_POR);
603 break;
604 case KBD_CMD_SET_TYPEMATIC:
605 ps2_queue(&s->common, KBD_REPLY_ACK);
606 break;
607 default:
608 ps2_queue(&s->common, KBD_REPLY_RESEND);
609 break;
610 }
611 break;
612 case KBD_CMD_SET_MAKE_BREAK:
613 ps2_queue(&s->common, KBD_REPLY_ACK);
614 s->common.write_cmd = -1;
615 break;
616 case KBD_CMD_SCANCODE:
617 if (val == 0) {
618 if (s->common.queue.count <= PS2_QUEUE_SIZE - 2) {
619 ps2_queue(&s->common, KBD_REPLY_ACK);
620 ps2_put_keycode(s, s->scancode_set);
621 }
622 } else if (val >= 1 && val <= 3) {
623 s->scancode_set = val;
624 ps2_queue(&s->common, KBD_REPLY_ACK);
625 } else {
626 ps2_queue(&s->common, KBD_REPLY_RESEND);
627 }
628 s->common.write_cmd = -1;
629 break;
630 case KBD_CMD_SET_LEDS:
631 ps2_set_ledstate(s, val);
632 ps2_queue(&s->common, KBD_REPLY_ACK);
633 s->common.write_cmd = -1;
634 break;
635 case KBD_CMD_SET_RATE:
636 ps2_queue(&s->common, KBD_REPLY_ACK);
637 s->common.write_cmd = -1;
638 break;
639 }
640}
641
642
643
644
645
646void ps2_keyboard_set_translation(void *opaque, int mode)
647{
648 PS2KbdState *s = (PS2KbdState *)opaque;
649 trace_ps2_keyboard_set_translation(opaque, mode);
650 s->translate = mode;
651}
652
653static int ps2_mouse_send_packet(PS2MouseState *s)
654{
655
656 const int needed = s->mouse_type ? 4 : 3;
657 unsigned int b;
658 int dx1, dy1, dz1;
659
660 if (PS2_QUEUE_SIZE - s->common.queue.count < needed) {
661 return 0;
662 }
663
664 dx1 = s->mouse_dx;
665 dy1 = s->mouse_dy;
666 dz1 = s->mouse_dz;
667
668 if (dx1 > 127)
669 dx1 = 127;
670 else if (dx1 < -127)
671 dx1 = -127;
672 if (dy1 > 127)
673 dy1 = 127;
674 else if (dy1 < -127)
675 dy1 = -127;
676 b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
677 ps2_queue_noirq(&s->common, b);
678 ps2_queue_noirq(&s->common, dx1 & 0xff);
679 ps2_queue_noirq(&s->common, dy1 & 0xff);
680
681 switch(s->mouse_type) {
682 default:
683 break;
684 case 3:
685 if (dz1 > 127)
686 dz1 = 127;
687 else if (dz1 < -127)
688 dz1 = -127;
689 ps2_queue_noirq(&s->common, dz1 & 0xff);
690 break;
691 case 4:
692 if (dz1 > 7)
693 dz1 = 7;
694 else if (dz1 < -7)
695 dz1 = -7;
696 b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
697 ps2_queue_noirq(&s->common, b);
698 break;
699 }
700
701 ps2_raise_irq(&s->common);
702
703 trace_ps2_mouse_send_packet(s, dx1, dy1, dz1, b);
704
705 s->mouse_dx -= dx1;
706 s->mouse_dy -= dy1;
707 s->mouse_dz -= dz1;
708
709 return 1;
710}
711
712static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
713 InputEvent *evt)
714{
715 static const int bmap[INPUT_BUTTON__MAX] = {
716 [INPUT_BUTTON_LEFT] = PS2_MOUSE_BUTTON_LEFT,
717 [INPUT_BUTTON_MIDDLE] = PS2_MOUSE_BUTTON_MIDDLE,
718 [INPUT_BUTTON_RIGHT] = PS2_MOUSE_BUTTON_RIGHT,
719 [INPUT_BUTTON_SIDE] = PS2_MOUSE_BUTTON_SIDE,
720 [INPUT_BUTTON_EXTRA] = PS2_MOUSE_BUTTON_EXTRA,
721 };
722 PS2MouseState *s = (PS2MouseState *)dev;
723 InputMoveEvent *move;
724 InputBtnEvent *btn;
725
726
727 if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
728 return;
729
730 switch (evt->type) {
731 case INPUT_EVENT_KIND_REL:
732 move = evt->u.rel.data;
733 if (move->axis == INPUT_AXIS_X) {
734 s->mouse_dx += move->value;
735 } else if (move->axis == INPUT_AXIS_Y) {
736 s->mouse_dy -= move->value;
737 }
738 break;
739
740 case INPUT_EVENT_KIND_BTN:
741 btn = evt->u.btn.data;
742 if (btn->down) {
743 s->mouse_buttons |= bmap[btn->button];
744 if (btn->button == INPUT_BUTTON_WHEEL_UP) {
745 s->mouse_dz--;
746 } else if (btn->button == INPUT_BUTTON_WHEEL_DOWN) {
747 s->mouse_dz++;
748 }
749 } else {
750 s->mouse_buttons &= ~bmap[btn->button];
751 }
752 break;
753
754 default:
755
756 break;
757 }
758}
759
760static void ps2_mouse_sync(DeviceState *dev)
761{
762 PS2MouseState *s = (PS2MouseState *)dev;
763
764
765 if (!(s->mouse_status & MOUSE_STATUS_ENABLED)) {
766 return;
767 }
768
769 if (s->mouse_buttons) {
770 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL);
771 }
772 if (!(s->mouse_status & MOUSE_STATUS_REMOTE)) {
773
774
775 while (ps2_mouse_send_packet(s)) {
776 if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
777 break;
778 }
779 }
780}
781
782void ps2_mouse_fake_event(void *opaque)
783{
784 PS2MouseState *s = opaque;
785 trace_ps2_mouse_fake_event(opaque);
786 s->mouse_dx++;
787 ps2_mouse_sync(opaque);
788}
789
790void ps2_write_mouse(void *opaque, int val)
791{
792 PS2MouseState *s = (PS2MouseState *)opaque;
793
794 trace_ps2_write_mouse(opaque, val);
795 switch(s->common.write_cmd) {
796 default:
797 case -1:
798
799 if (s->mouse_wrap) {
800 if (val == AUX_RESET_WRAP) {
801 s->mouse_wrap = 0;
802 ps2_queue(&s->common, AUX_ACK);
803 return;
804 } else if (val != AUX_RESET) {
805 ps2_queue(&s->common, val);
806 return;
807 }
808 }
809 switch(val) {
810 case AUX_SET_SCALE11:
811 s->mouse_status &= ~MOUSE_STATUS_SCALE21;
812 ps2_queue(&s->common, AUX_ACK);
813 break;
814 case AUX_SET_SCALE21:
815 s->mouse_status |= MOUSE_STATUS_SCALE21;
816 ps2_queue(&s->common, AUX_ACK);
817 break;
818 case AUX_SET_STREAM:
819 s->mouse_status &= ~MOUSE_STATUS_REMOTE;
820 ps2_queue(&s->common, AUX_ACK);
821 break;
822 case AUX_SET_WRAP:
823 s->mouse_wrap = 1;
824 ps2_queue(&s->common, AUX_ACK);
825 break;
826 case AUX_SET_REMOTE:
827 s->mouse_status |= MOUSE_STATUS_REMOTE;
828 ps2_queue(&s->common, AUX_ACK);
829 break;
830 case AUX_GET_TYPE:
831 ps2_queue_2(&s->common,
832 AUX_ACK,
833 s->mouse_type);
834 break;
835 case AUX_SET_RES:
836 case AUX_SET_SAMPLE:
837 s->common.write_cmd = val;
838 ps2_queue(&s->common, AUX_ACK);
839 break;
840 case AUX_GET_SCALE:
841 ps2_queue_4(&s->common,
842 AUX_ACK,
843 s->mouse_status,
844 s->mouse_resolution,
845 s->mouse_sample_rate);
846 break;
847 case AUX_POLL:
848 ps2_queue(&s->common, AUX_ACK);
849 ps2_mouse_send_packet(s);
850 break;
851 case AUX_ENABLE_DEV:
852 s->mouse_status |= MOUSE_STATUS_ENABLED;
853 ps2_queue(&s->common, AUX_ACK);
854 break;
855 case AUX_DISABLE_DEV:
856 s->mouse_status &= ~MOUSE_STATUS_ENABLED;
857 ps2_queue(&s->common, AUX_ACK);
858 break;
859 case AUX_SET_DEFAULT:
860 s->mouse_sample_rate = 100;
861 s->mouse_resolution = 2;
862 s->mouse_status = 0;
863 ps2_queue(&s->common, AUX_ACK);
864 break;
865 case AUX_RESET:
866 s->mouse_sample_rate = 100;
867 s->mouse_resolution = 2;
868 s->mouse_status = 0;
869 s->mouse_type = 0;
870 ps2_reset_queue(&s->common);
871 ps2_queue_3(&s->common,
872 AUX_ACK,
873 0xaa,
874 s->mouse_type);
875 break;
876 default:
877 break;
878 }
879 break;
880 case AUX_SET_SAMPLE:
881 s->mouse_sample_rate = val;
882
883 switch(s->mouse_detect_state) {
884 default:
885 case 0:
886 if (val == 200)
887 s->mouse_detect_state = 1;
888 break;
889 case 1:
890 if (val == 100)
891 s->mouse_detect_state = 2;
892 else if (val == 200)
893 s->mouse_detect_state = 3;
894 else
895 s->mouse_detect_state = 0;
896 break;
897 case 2:
898 if (val == 80)
899 s->mouse_type = 3;
900 s->mouse_detect_state = 0;
901 break;
902 case 3:
903 if (val == 80)
904 s->mouse_type = 4;
905 s->mouse_detect_state = 0;
906 break;
907 }
908 ps2_queue(&s->common, AUX_ACK);
909 s->common.write_cmd = -1;
910 break;
911 case AUX_SET_RES:
912 s->mouse_resolution = val;
913 ps2_queue(&s->common, AUX_ACK);
914 s->common.write_cmd = -1;
915 break;
916 }
917}
918
919static void ps2_common_reset(PS2State *s)
920{
921 s->write_cmd = -1;
922 ps2_reset_queue(s);
923 s->update_irq(s->update_arg, 0);
924}
925
926static void ps2_common_post_load(PS2State *s)
927{
928 PS2Queue *q = &s->queue;
929 uint8_t i, size;
930 uint8_t tmp_data[PS2_QUEUE_SIZE];
931
932
933 size = q->count;
934 if (q->count < 0) {
935 size = 0;
936 } else if (q->count > PS2_QUEUE_SIZE) {
937 size = PS2_QUEUE_SIZE;
938 }
939
940
941 for (i = 0; i < size; i++) {
942 if (q->rptr < 0 || q->rptr >= sizeof(q->data)) {
943 q->rptr = 0;
944 }
945 tmp_data[i] = q->data[q->rptr++];
946 }
947 memcpy(q->data, tmp_data, size);
948
949
950 q->rptr = 0;
951 q->wptr = (size == PS2_QUEUE_SIZE) ? 0 : size;
952 q->count = size;
953}
954
955static void ps2_kbd_reset(void *opaque)
956{
957 PS2KbdState *s = (PS2KbdState *) opaque;
958
959 trace_ps2_kbd_reset(opaque);
960 ps2_common_reset(&s->common);
961 s->scan_enabled = 1;
962 s->translate = 0;
963 s->scancode_set = 2;
964 s->modifiers = 0;
965}
966
967static void ps2_mouse_reset(void *opaque)
968{
969 PS2MouseState *s = (PS2MouseState *) opaque;
970
971 trace_ps2_mouse_reset(opaque);
972 ps2_common_reset(&s->common);
973 s->mouse_status = 0;
974 s->mouse_resolution = 0;
975 s->mouse_sample_rate = 0;
976 s->mouse_wrap = 0;
977 s->mouse_type = 0;
978 s->mouse_detect_state = 0;
979 s->mouse_dx = 0;
980 s->mouse_dy = 0;
981 s->mouse_dz = 0;
982 s->mouse_buttons = 0;
983}
984
985static const VMStateDescription vmstate_ps2_common = {
986 .name = "PS2 Common State",
987 .version_id = 3,
988 .minimum_version_id = 2,
989 .fields = (VMStateField[]) {
990 VMSTATE_INT32(write_cmd, PS2State),
991 VMSTATE_INT32(queue.rptr, PS2State),
992 VMSTATE_INT32(queue.wptr, PS2State),
993 VMSTATE_INT32(queue.count, PS2State),
994 VMSTATE_BUFFER(queue.data, PS2State),
995 VMSTATE_END_OF_LIST()
996 }
997};
998
999static bool ps2_keyboard_ledstate_needed(void *opaque)
1000{
1001 PS2KbdState *s = opaque;
1002
1003 return s->ledstate != 0;
1004}
1005
1006static int ps2_kbd_ledstate_post_load(void *opaque, int version_id)
1007{
1008 PS2KbdState *s = opaque;
1009
1010 kbd_put_ledstate(s->ledstate);
1011 return 0;
1012}
1013
1014static const VMStateDescription vmstate_ps2_keyboard_ledstate = {
1015 .name = "ps2kbd/ledstate",
1016 .version_id = 3,
1017 .minimum_version_id = 2,
1018 .post_load = ps2_kbd_ledstate_post_load,
1019 .needed = ps2_keyboard_ledstate_needed,
1020 .fields = (VMStateField[]) {
1021 VMSTATE_INT32(ledstate, PS2KbdState),
1022 VMSTATE_END_OF_LIST()
1023 }
1024};
1025
1026static bool ps2_keyboard_need_high_bit_needed(void *opaque)
1027{
1028 PS2KbdState *s = opaque;
1029 return s->need_high_bit != 0;
1030}
1031
1032static const VMStateDescription vmstate_ps2_keyboard_need_high_bit = {
1033 .name = "ps2kbd/need_high_bit",
1034 .version_id = 1,
1035 .minimum_version_id = 1,
1036 .needed = ps2_keyboard_need_high_bit_needed,
1037 .fields = (VMStateField[]) {
1038 VMSTATE_BOOL(need_high_bit, PS2KbdState),
1039 VMSTATE_END_OF_LIST()
1040 }
1041};
1042
1043static int ps2_kbd_post_load(void* opaque, int version_id)
1044{
1045 PS2KbdState *s = (PS2KbdState*)opaque;
1046 PS2State *ps2 = &s->common;
1047
1048 if (version_id == 2)
1049 s->scancode_set=2;
1050
1051 ps2_common_post_load(ps2);
1052
1053 return 0;
1054}
1055
1056static int ps2_kbd_pre_save(void *opaque)
1057{
1058 PS2KbdState *s = (PS2KbdState *)opaque;
1059 PS2State *ps2 = &s->common;
1060
1061 ps2_common_post_load(ps2);
1062
1063 return 0;
1064}
1065
1066static const VMStateDescription vmstate_ps2_keyboard = {
1067 .name = "ps2kbd",
1068 .version_id = 3,
1069 .minimum_version_id = 2,
1070 .post_load = ps2_kbd_post_load,
1071 .pre_save = ps2_kbd_pre_save,
1072 .fields = (VMStateField[]) {
1073 VMSTATE_STRUCT(common, PS2KbdState, 0, vmstate_ps2_common, PS2State),
1074 VMSTATE_INT32(scan_enabled, PS2KbdState),
1075 VMSTATE_INT32(translate, PS2KbdState),
1076 VMSTATE_INT32_V(scancode_set, PS2KbdState,3),
1077 VMSTATE_END_OF_LIST()
1078 },
1079 .subsections = (const VMStateDescription*[]) {
1080 &vmstate_ps2_keyboard_ledstate,
1081 &vmstate_ps2_keyboard_need_high_bit,
1082 NULL
1083 }
1084};
1085
1086static int ps2_mouse_post_load(void *opaque, int version_id)
1087{
1088 PS2MouseState *s = (PS2MouseState *)opaque;
1089 PS2State *ps2 = &s->common;
1090
1091 ps2_common_post_load(ps2);
1092
1093 return 0;
1094}
1095
1096static int ps2_mouse_pre_save(void *opaque)
1097{
1098 PS2MouseState *s = (PS2MouseState *)opaque;
1099 PS2State *ps2 = &s->common;
1100
1101 ps2_common_post_load(ps2);
1102
1103 return 0;
1104}
1105
1106static const VMStateDescription vmstate_ps2_mouse = {
1107 .name = "ps2mouse",
1108 .version_id = 2,
1109 .minimum_version_id = 2,
1110 .post_load = ps2_mouse_post_load,
1111 .pre_save = ps2_mouse_pre_save,
1112 .fields = (VMStateField[]) {
1113 VMSTATE_STRUCT(common, PS2MouseState, 0, vmstate_ps2_common, PS2State),
1114 VMSTATE_UINT8(mouse_status, PS2MouseState),
1115 VMSTATE_UINT8(mouse_resolution, PS2MouseState),
1116 VMSTATE_UINT8(mouse_sample_rate, PS2MouseState),
1117 VMSTATE_UINT8(mouse_wrap, PS2MouseState),
1118 VMSTATE_UINT8(mouse_type, PS2MouseState),
1119 VMSTATE_UINT8(mouse_detect_state, PS2MouseState),
1120 VMSTATE_INT32(mouse_dx, PS2MouseState),
1121 VMSTATE_INT32(mouse_dy, PS2MouseState),
1122 VMSTATE_INT32(mouse_dz, PS2MouseState),
1123 VMSTATE_UINT8(mouse_buttons, PS2MouseState),
1124 VMSTATE_END_OF_LIST()
1125 }
1126};
1127
1128static QemuInputHandler ps2_keyboard_handler = {
1129 .name = "QEMU PS/2 Keyboard",
1130 .mask = INPUT_EVENT_MASK_KEY,
1131 .event = ps2_keyboard_event,
1132};
1133
1134void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
1135{
1136 PS2KbdState *s = (PS2KbdState *)g_malloc0(sizeof(PS2KbdState));
1137
1138 trace_ps2_kbd_init(s);
1139 s->common.update_irq = update_irq;
1140 s->common.update_arg = update_arg;
1141 s->scancode_set = 2;
1142 vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s);
1143 qemu_input_handler_register((DeviceState *)s,
1144 &ps2_keyboard_handler);
1145 qemu_register_reset(ps2_kbd_reset, s);
1146 return s;
1147}
1148
1149static QemuInputHandler ps2_mouse_handler = {
1150 .name = "QEMU PS/2 Mouse",
1151 .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
1152 .event = ps2_mouse_event,
1153 .sync = ps2_mouse_sync,
1154};
1155
1156void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
1157{
1158 PS2MouseState *s = (PS2MouseState *)g_malloc0(sizeof(PS2MouseState));
1159
1160 trace_ps2_mouse_init(s);
1161 s->common.update_irq = update_irq;
1162 s->common.update_arg = update_arg;
1163 vmstate_register(NULL, 0, &vmstate_ps2_mouse, s);
1164 qemu_input_handler_register((DeviceState *)s,
1165 &ps2_mouse_handler);
1166 qemu_register_reset(ps2_mouse_reset, s);
1167 return s;
1168}
1169