1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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"
31
32#include "trace.h"
33
34
35
36
37
38
39
40
41#define KBD_CMD_SET_LEDS 0xED
42#define KBD_CMD_ECHO 0xEE
43#define KBD_CMD_SCANCODE 0xF0
44#define KBD_CMD_GET_ID 0xF2
45#define KBD_CMD_SET_RATE 0xF3
46#define KBD_CMD_ENABLE 0xF4
47#define KBD_CMD_RESET_DISABLE 0xF5
48#define KBD_CMD_RESET_ENABLE 0xF6
49#define KBD_CMD_RESET 0xFF
50
51
52#define KBD_REPLY_POR 0xAA
53#define KBD_REPLY_ID 0xAB
54#define KBD_REPLY_ACK 0xFA
55#define KBD_REPLY_RESEND 0xFE
56
57
58#define AUX_SET_SCALE11 0xE6
59#define AUX_SET_SCALE21 0xE7
60#define AUX_SET_RES 0xE8
61#define AUX_GET_SCALE 0xE9
62#define AUX_SET_STREAM 0xEA
63#define AUX_POLL 0xEB
64#define AUX_RESET_WRAP 0xEC
65#define AUX_SET_WRAP 0xEE
66#define AUX_SET_REMOTE 0xF0
67#define AUX_GET_TYPE 0xF2
68#define AUX_SET_SAMPLE 0xF3
69#define AUX_ENABLE_DEV 0xF4
70#define AUX_DISABLE_DEV 0xF5
71#define AUX_SET_DEFAULT 0xF6
72#define AUX_RESET 0xFF
73#define AUX_ACK 0xFA
74
75#define MOUSE_STATUS_REMOTE 0x40
76#define MOUSE_STATUS_ENABLED 0x20
77#define MOUSE_STATUS_SCALE21 0x10
78
79#define PS2_QUEUE_SIZE 16
80
81
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)
88
89typedef struct {
90
91
92 uint8_t data[256];
93 int rptr, wptr, count;
94} PS2Queue;
95
96struct PS2State {
97 PS2Queue queue;
98 int32_t write_cmd;
99 void (*update_irq)(void *, int);
100 void *update_arg;
101};
102
103typedef struct {
104 PS2State common;
105 int scan_enabled;
106 int translate;
107 int scancode_set;
108 int ledstate;
109 bool need_high_bit;
110 unsigned int modifiers;
111} PS2KbdState;
112
113typedef 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;
120 uint8_t mouse_detect_state;
121 int mouse_dx;
122 int mouse_dy;
123 int mouse_dz;
124 uint8_t mouse_buttons;
125} PS2MouseState;
126
127static 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,
160};
161
162static unsigned int ps2_modifier_bit(QKeyCode key)
163{
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;
179 }
180}
181
182static void ps2_reset_queue(PS2State *s)
183{
184 PS2Queue *q = &s->queue;
185
186 q->rptr = 0;
187 q->wptr = 0;
188 q->count = 0;
189}
190
191void ps2_queue_noirq(PS2State *s, int b)
192{
193 PS2Queue *q = &s->queue;
194
195 if (q->count == PS2_QUEUE_SIZE) {
196 return;
197 }
198
199 q->data[q->wptr] = b;
200 if (++q->wptr == PS2_QUEUE_SIZE)
201 q->wptr = 0;
202 q->count++;
203}
204
205void ps2_raise_irq(PS2State *s)
206{
207 s->update_irq(s->update_arg, 1);
208}
209
210void ps2_queue(PS2State *s, int b)
211{
212 ps2_queue_noirq(s, b);
213 s->update_irq(s->update_arg, 1);
214}
215
216void ps2_queue_2(PS2State *s, int b1, int b2)
217{
218 if (PS2_QUEUE_SIZE - s->queue.count < 2) {
219 return;
220 }
221
222 ps2_queue_noirq(s, b1);
223 ps2_queue_noirq(s, b2);
224 s->update_irq(s->update_arg, 1);
225}
226
227void ps2_queue_3(PS2State *s, int b1, int b2, int b3)
228{
229 if (PS2_QUEUE_SIZE - s->queue.count < 3) {
230 return;
231 }
232
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);
237}
238
239void ps2_queue_4(PS2State *s, int b1, int b2, int b3, int b4)
240{
241 if (PS2_QUEUE_SIZE - s->queue.count < 4) {
242 return;
243 }
244
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);
250}
251
252
253static void ps2_put_keycode(void *opaque, int keycode)
254{
255 PS2KbdState *s = opaque;
256
257 trace_ps2_put_keycode(opaque, keycode);
258 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
259
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]);
268 }
269 } else {
270 ps2_queue(&s->common, keycode);
271 }
272}
273
274static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,
275 InputEvent *evt)
276{
277 PS2KbdState *s = (PS2KbdState *)dev;
278 InputKeyEvent *key = evt->u.key.data;
279 int qcode;
280 uint16_t keycode = 0;
281 int mod;
282
283
284 if (!s->scan_enabled) {
285 return;
286 }
287
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);
291
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;
298 }
299
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);
308 }
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);
317 }
318 }
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);
329 }
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);
343 }
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);
352 }
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);
364 }
365 }
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);
372 }
373 if (!key->down) {
374 keycode |= 0x80;
375 }
376 ps2_put_keycode(s, keycode & 0xff);
377 } else {
378 qemu_log_mask(LOG_UNIMP,
379 "ps2: ignoring key with qcode %d\n", qcode);
380 }
381 }
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);
391 }
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);
402 }
403 }
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);
417 }
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);
434 }
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);
444 }
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);
458 }
459 }
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);
466 }
467 if (!key->down) {
468 ps2_put_keycode(s, 0xf0);
469 }
470 ps2_put_keycode(s, keycode & 0xff);
471 } else {
472 qemu_log_mask(LOG_UNIMP,
473 "ps2: ignoring key with qcode %d\n", qcode);
474 }
475 }
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
481 if (!key->down) {
482 ps2_put_keycode(s, 0xf0);
483 }
484 ps2_put_keycode(s, keycode);
485 } else {
486 qemu_log_mask(LOG_UNIMP,
487 "ps2: ignoring key with qcode %d\n", qcode);
488 }
489 }
490}
491
492uint32_t ps2_read_data(PS2State *s)
493{
494 PS2Queue *q;
495 int val, index;
496
497 trace_ps2_read_data(s);
498 q = &s->queue;
499 if (q->count == 0) {
500
501
502
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
513 s->update_irq(s->update_arg, 0);
514
515 s->update_irq(s->update_arg, q->count != 0);
516 }
517 return val;
518}
519
520static void ps2_set_ledstate(PS2KbdState *s, int ledstate)
521{
522 trace_ps2_set_ledstate(s, ledstate);
523 s->ledstate = ledstate;
524 kbd_put_ledstate(ledstate);
525}
526
527static void ps2_reset_keyboard(PS2KbdState *s)
528{
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);
534}
535
536void ps2_write_keyboard(void *opaque, int val)
537{
538 PS2KbdState *s = (PS2KbdState *)opaque;
539
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
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;
596 }
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);
603 }
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);
609 }
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;
621 }
622}
623
624
625
626
627
628void ps2_keyboard_set_translation(void *opaque, int mode)
629{
630 PS2KbdState *s = (PS2KbdState *)opaque;
631 trace_ps2_keyboard_set_translation(opaque, mode);
632 s->translate = mode;
633}
634
635static int ps2_mouse_send_packet(PS2MouseState *s)
636{
637 const int needed = 3 + (s->mouse_type - 2);
638 unsigned int b;
639 int dx1, dy1, dz1;
640
641 if (PS2_QUEUE_SIZE - s->common.queue.count < needed) {
642 return 0;
643 }
644
645 dx1 = s->mouse_dx;
646 dy1 = s->mouse_dy;
647 dz1 = s->mouse_dz;
648
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
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;
680 }
681
682 ps2_raise_irq(&s->common);
683
684 trace_ps2_mouse_send_packet(s, dx1, dy1, dz1, b);
685
686 s->mouse_dx -= dx1;
687 s->mouse_dy -= dy1;
688 s->mouse_dz -= dz1;
689
690 return 1;
691}
692
693static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
694 InputEvent *evt)
695{
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,
702 };
703 PS2MouseState *s = (PS2MouseState *)dev;
704 InputMoveEvent *move;
705 InputBtnEvent *btn;
706
707
708 if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
709 return;
710
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;
718 }
719 break;
720
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++;
729 }
730 } else {
731 s->mouse_buttons &= ~bmap[btn->button];
732 }
733 break;
734
735 default:
736
737 break;
738 }
739}
740
741static void ps2_mouse_sync(DeviceState *dev)
742{
743 PS2MouseState *s = (PS2MouseState *)dev;
744
745
746 if (!(s->mouse_status & MOUSE_STATUS_ENABLED)) {
747 return;
748 }
749
750 if (s->mouse_buttons) {
751 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
752 }
753 if (!(s->mouse_status & MOUSE_STATUS_REMOTE)) {
754
755
756 while (ps2_mouse_send_packet(s)) {
757 if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
758 break;
759 }
760 }
761}
762
763void ps2_mouse_fake_event(void *opaque)
764{
765 PS2MouseState *s = opaque;
766 trace_ps2_mouse_fake_event(opaque);
767 s->mouse_dx++;
768 ps2_mouse_sync(opaque);
769}
770
771void ps2_write_mouse(void *opaque, int val)
772{
773 PS2MouseState *s = (PS2MouseState *)opaque;
774
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
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;
791 }
792 }
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;
862 }
863 break;
864 case AUX_SET_SAMPLE:
865 s->mouse_sample_rate = val;
866
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;
884 s->mouse_detect_state = 0;
885 break;
886 case 3:
887 if (val == 80)
888 s->mouse_type = 4;
889 s->mouse_detect_state = 0;
890 break;
891 }
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;
900 }
901}
902
903static void ps2_common_reset(PS2State *s)
904{
905 s->write_cmd = -1;
906 ps2_reset_queue(s);
907 s->update_irq(s->update_arg, 0);
908}
909
910static void ps2_common_post_load(PS2State *s)
911{
912 PS2Queue *q = &s->queue;
913 uint8_t i, size;
914 uint8_t tmp_data[PS2_QUEUE_SIZE];
915
916
917 size = (q->count < 0 || q->count > PS2_QUEUE_SIZE) ? 0 : q->count;
918
919
920 for (i = 0; i < size; i++) {
921 if (q->rptr < 0 || q->rptr >= sizeof(q->data)) {
922 q->rptr = 0;
923 }
924 tmp_data[i] = q->data[q->rptr++];
925 }
926 memcpy(q->data, tmp_data, size);
927
928
929 q->rptr = 0;
930 q->wptr = (size == PS2_QUEUE_SIZE) ? 0 : size;
931 q->count = size;
932 s->update_irq(s->update_arg, q->count != 0);
933}
934
935static void ps2_kbd_reset(void *opaque)
936{
937 PS2KbdState *s = (PS2KbdState *) opaque;
938
939 trace_ps2_kbd_reset(opaque);
940 ps2_common_reset(&s->common);
941 s->scan_enabled = 0;
942 s->translate = 0;
943 s->scancode_set = 2;
944 s->modifiers = 0;
945}
946
947static void ps2_mouse_reset(void *opaque)
948{
949 PS2MouseState *s = (PS2MouseState *) opaque;
950
951 trace_ps2_mouse_reset(opaque);
952 ps2_common_reset(&s->common);
953 s->mouse_status = 0;
954 s->mouse_resolution = 0;
955 s->mouse_sample_rate = 0;
956 s->mouse_wrap = 0;
957 s->mouse_type = 0;
958 s->mouse_detect_state = 0;
959 s->mouse_dx = 0;
960 s->mouse_dy = 0;
961 s->mouse_dz = 0;
962 s->mouse_buttons = 0;
963}
964
965static const VMStateDescription vmstate_ps2_common = {
966 .name = "PS2 Common State",
967 .version_id = 3,
968 .minimum_version_id = 2,
969 .fields = (VMStateField[]) {
970 VMSTATE_INT32(write_cmd, PS2State),
971 VMSTATE_INT32(queue.rptr, PS2State),
972 VMSTATE_INT32(queue.wptr, PS2State),
973 VMSTATE_INT32(queue.count, PS2State),
974 VMSTATE_BUFFER(queue.data, PS2State),
975 VMSTATE_END_OF_LIST()
976 }
977};
978
979static bool ps2_keyboard_ledstate_needed(void *opaque)
980{
981 PS2KbdState *s = opaque;
982
983 return s->ledstate != 0;
984}
985
986static int ps2_kbd_ledstate_post_load(void *opaque, int version_id)
987{
988 PS2KbdState *s = opaque;
989
990 kbd_put_ledstate(s->ledstate);
991 return 0;
992}
993
994static const VMStateDescription vmstate_ps2_keyboard_ledstate = {
995 .name = "ps2kbd/ledstate",
996 .version_id = 3,
997 .minimum_version_id = 2,
998 .post_load = ps2_kbd_ledstate_post_load,
999 .needed = ps2_keyboard_ledstate_needed,
1000 .fields = (VMStateField[]) {
1001 VMSTATE_INT32(ledstate, PS2KbdState),
1002 VMSTATE_END_OF_LIST()
1003 }
1004};
1005
1006static bool ps2_keyboard_need_high_bit_needed(void *opaque)
1007{
1008 PS2KbdState *s = opaque;
1009 return s->need_high_bit != 0;
1010}
1011
1012static const VMStateDescription vmstate_ps2_keyboard_need_high_bit = {
1013 .name = "ps2kbd/need_high_bit",
1014 .version_id = 1,
1015 .minimum_version_id = 1,
1016 .needed = ps2_keyboard_need_high_bit_needed,
1017 .fields = (VMStateField[]) {
1018 VMSTATE_BOOL(need_high_bit, PS2KbdState),
1019 VMSTATE_END_OF_LIST()
1020 }
1021};
1022
1023static int ps2_kbd_post_load(void* opaque, int version_id)
1024{
1025 PS2KbdState *s = (PS2KbdState*)opaque;
1026 PS2State *ps2 = &s->common;
1027
1028 if (version_id == 2)
1029 s->scancode_set=2;
1030
1031 ps2_common_post_load(ps2);
1032
1033 return 0;
1034}
1035
1036static int ps2_kbd_pre_save(void *opaque)
1037{
1038 PS2KbdState *s = (PS2KbdState *)opaque;
1039 PS2State *ps2 = &s->common;
1040
1041 ps2_common_post_load(ps2);
1042
1043 return 0;
1044}
1045
1046static const VMStateDescription vmstate_ps2_keyboard = {
1047 .name = "ps2kbd",
1048 .version_id = 3,
1049 .minimum_version_id = 2,
1050 .post_load = ps2_kbd_post_load,
1051 .pre_save = ps2_kbd_pre_save,
1052 .fields = (VMStateField[]) {
1053 VMSTATE_STRUCT(common, PS2KbdState, 0, vmstate_ps2_common, PS2State),
1054 VMSTATE_INT32(scan_enabled, PS2KbdState),
1055 VMSTATE_INT32(translate, PS2KbdState),
1056 VMSTATE_INT32_V(scancode_set, PS2KbdState,3),
1057 VMSTATE_END_OF_LIST()
1058 },
1059 .subsections = (const VMStateDescription*[]) {
1060 &vmstate_ps2_keyboard_ledstate,
1061 &vmstate_ps2_keyboard_need_high_bit,
1062 NULL
1063 }
1064};
1065
1066static int ps2_mouse_post_load(void *opaque, int version_id)
1067{
1068 PS2MouseState *s = (PS2MouseState *)opaque;
1069 PS2State *ps2 = &s->common;
1070
1071 ps2_common_post_load(ps2);
1072
1073 return 0;
1074}
1075
1076static int ps2_mouse_pre_save(void *opaque)
1077{
1078 PS2MouseState *s = (PS2MouseState *)opaque;
1079 PS2State *ps2 = &s->common;
1080
1081 ps2_common_post_load(ps2);
1082
1083 return 0;
1084}
1085
1086static const VMStateDescription vmstate_ps2_mouse = {
1087 .name = "ps2mouse",
1088 .version_id = 2,
1089 .minimum_version_id = 2,
1090 .post_load = ps2_mouse_post_load,
1091 .pre_save = ps2_mouse_pre_save,
1092 .fields = (VMStateField[]) {
1093 VMSTATE_STRUCT(common, PS2MouseState, 0, vmstate_ps2_common, PS2State),
1094 VMSTATE_UINT8(mouse_status, PS2MouseState),
1095 VMSTATE_UINT8(mouse_resolution, PS2MouseState),
1096 VMSTATE_UINT8(mouse_sample_rate, PS2MouseState),
1097 VMSTATE_UINT8(mouse_wrap, PS2MouseState),
1098 VMSTATE_UINT8(mouse_type, PS2MouseState),
1099 VMSTATE_UINT8(mouse_detect_state, PS2MouseState),
1100 VMSTATE_INT32(mouse_dx, PS2MouseState),
1101 VMSTATE_INT32(mouse_dy, PS2MouseState),
1102 VMSTATE_INT32(mouse_dz, PS2MouseState),
1103 VMSTATE_UINT8(mouse_buttons, PS2MouseState),
1104 VMSTATE_END_OF_LIST()
1105 }
1106};
1107
1108static QemuInputHandler ps2_keyboard_handler = {
1109 .name = "QEMU PS/2 Keyboard",
1110 .mask = INPUT_EVENT_MASK_KEY,
1111 .event = ps2_keyboard_event,
1112};
1113
1114void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
1115{
1116 PS2KbdState *s = (PS2KbdState *)g_malloc0(sizeof(PS2KbdState));
1117
1118 trace_ps2_kbd_init(s);
1119 s->common.update_irq = update_irq;
1120 s->common.update_arg = update_arg;
1121 s->scancode_set = 2;
1122 vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s);
1123 qemu_input_handler_register((DeviceState *)s,
1124 &ps2_keyboard_handler);
1125 qemu_register_reset(ps2_kbd_reset, s);
1126 return s;
1127}
1128
1129static QemuInputHandler ps2_mouse_handler = {
1130 .name = "QEMU PS/2 Mouse",
1131 .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
1132 .event = ps2_mouse_event,
1133 .sync = ps2_mouse_sync,
1134};
1135
1136void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
1137{
1138 PS2MouseState *s = (PS2MouseState *)g_malloc0(sizeof(PS2MouseState));
1139
1140 trace_ps2_mouse_init(s);
1141 s->common.update_irq = update_irq;
1142 s->common.update_arg = update_arg;
1143 vmstate_register(NULL, 0, &vmstate_ps2_mouse, s);
1144 qemu_input_handler_register((DeviceState *)s,
1145 &ps2_mouse_handler);
1146 qemu_register_reset(ps2_mouse_reset, s);
1147 return s;
1148}
1149