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