Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging
[qemu/ar7.git] / hw / input / ps2.c
blob45af76a8378f20c9f48341b5922a0c81c12acbc5
1 /*
2 * QEMU PS/2 keyboard/mouse emulation
4 * Copyright (c) 2003 Fabrice Bellard
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
25 #include "qemu/osdep.h"
26 #include "qemu/log.h"
27 #include "hw/irq.h"
28 #include "hw/sysbus.h"
29 #include "hw/input/ps2.h"
30 #include "migration/vmstate.h"
31 #include "ui/console.h"
32 #include "ui/input.h"
33 #include "sysemu/reset.h"
34 #include "sysemu/runstate.h"
35 #include "qapi/error.h"
37 #include "trace.h"
39 /* Keyboard Commands */
40 #define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */
41 #define KBD_CMD_ECHO 0xEE
42 #define KBD_CMD_SCANCODE 0xF0 /* Get/set scancode set */
43 #define KBD_CMD_GET_ID 0xF2 /* get keyboard ID */
44 #define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */
45 #define KBD_CMD_ENABLE 0xF4 /* Enable scanning */
46 #define KBD_CMD_RESET_DISABLE 0xF5 /* reset and disable scanning */
47 #define KBD_CMD_RESET_ENABLE 0xF6 /* reset and enable scanning */
48 #define KBD_CMD_RESET 0xFF /* Reset */
49 #define KBD_CMD_SET_MAKE_BREAK 0xFC /* Set Make and Break mode */
50 #define KBD_CMD_SET_TYPEMATIC 0xFA /* Set Typematic Make and Break mode */
52 /* Keyboard Replies */
53 #define KBD_REPLY_POR 0xAA /* Power on reset */
54 #define KBD_REPLY_ID 0xAB /* Keyboard ID */
55 #define KBD_REPLY_ACK 0xFA /* Command ACK */
56 #define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */
58 /* Mouse Commands */
59 #define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */
60 #define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */
61 #define AUX_SET_RES 0xE8 /* Set resolution */
62 #define AUX_GET_SCALE 0xE9 /* Get scaling factor */
63 #define AUX_SET_STREAM 0xEA /* Set stream mode */
64 #define AUX_POLL 0xEB /* Poll */
65 #define AUX_RESET_WRAP 0xEC /* Reset wrap mode */
66 #define AUX_SET_WRAP 0xEE /* Set wrap mode */
67 #define AUX_SET_REMOTE 0xF0 /* Set remote mode */
68 #define AUX_GET_TYPE 0xF2 /* Get type */
69 #define AUX_SET_SAMPLE 0xF3 /* Set sample rate */
70 #define AUX_ENABLE_DEV 0xF4 /* Enable aux device */
71 #define AUX_DISABLE_DEV 0xF5 /* Disable aux device */
72 #define AUX_SET_DEFAULT 0xF6
73 #define AUX_RESET 0xFF /* Reset aux device */
74 #define AUX_ACK 0xFA /* Command byte ACK. */
76 #define MOUSE_STATUS_REMOTE 0x40
77 #define MOUSE_STATUS_ENABLED 0x20
78 #define MOUSE_STATUS_SCALE21 0x10
80 #define PS2_QUEUE_SIZE 16 /* Queue size required by PS/2 protocol */
81 #define PS2_QUEUE_HEADROOM 8 /* Queue size for keyboard command replies */
83 /* Bits for 'modifiers' field in PS2KbdState */
84 #define MOD_CTRL_L (1 << 0)
85 #define MOD_SHIFT_L (1 << 1)
86 #define MOD_ALT_L (1 << 2)
87 #define MOD_CTRL_R (1 << 3)
88 #define MOD_SHIFT_R (1 << 4)
89 #define MOD_ALT_R (1 << 5)
91 static uint8_t translate_table[256] = {
92 0xff, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58,
93 0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59,
94 0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a,
95 0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b,
96 0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c,
97 0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d,
98 0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e,
99 0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f,
100 0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60,
101 0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61,
102 0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e,
103 0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76,
104 0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b,
105 0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f,
106 0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45,
107 0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54,
108 0x80, 0x81, 0x82, 0x41, 0x54, 0x85, 0x86, 0x87,
109 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
110 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
111 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
112 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
113 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
114 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
115 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
116 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
117 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
118 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
119 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
120 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
121 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
122 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
123 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
126 static unsigned int ps2_modifier_bit(QKeyCode key)
128 switch (key) {
129 case Q_KEY_CODE_CTRL:
130 return MOD_CTRL_L;
131 case Q_KEY_CODE_CTRL_R:
132 return MOD_CTRL_R;
133 case Q_KEY_CODE_SHIFT:
134 return MOD_SHIFT_L;
135 case Q_KEY_CODE_SHIFT_R:
136 return MOD_SHIFT_R;
137 case Q_KEY_CODE_ALT:
138 return MOD_ALT_L;
139 case Q_KEY_CODE_ALT_R:
140 return MOD_ALT_R;
141 default:
142 return 0;
146 static void ps2_reset_queue(PS2State *s)
148 PS2Queue *q = &s->queue;
150 q->rptr = 0;
151 q->wptr = 0;
152 q->cwptr = -1;
153 q->count = 0;
156 int ps2_queue_empty(PS2State *s)
158 return s->queue.count == 0;
161 void ps2_queue_noirq(PS2State *s, int b)
163 PS2Queue *q = &s->queue;
165 if (q->count >= PS2_QUEUE_SIZE) {
166 return;
169 q->data[q->wptr] = b;
170 if (++q->wptr == PS2_BUFFER_SIZE) {
171 q->wptr = 0;
173 q->count++;
176 static void ps2_raise_irq(PS2State *s)
178 qemu_set_irq(s->irq, 1);
181 static void ps2_lower_irq(PS2State *s)
183 qemu_set_irq(s->irq, 0);
186 void ps2_queue(PS2State *s, int b)
188 if (PS2_QUEUE_SIZE - s->queue.count < 1) {
189 return;
192 ps2_queue_noirq(s, b);
193 ps2_raise_irq(s);
196 void ps2_queue_2(PS2State *s, int b1, int b2)
198 if (PS2_QUEUE_SIZE - s->queue.count < 2) {
199 return;
202 ps2_queue_noirq(s, b1);
203 ps2_queue_noirq(s, b2);
204 ps2_raise_irq(s);
207 void ps2_queue_3(PS2State *s, int b1, int b2, int b3)
209 if (PS2_QUEUE_SIZE - s->queue.count < 3) {
210 return;
213 ps2_queue_noirq(s, b1);
214 ps2_queue_noirq(s, b2);
215 ps2_queue_noirq(s, b3);
216 ps2_raise_irq(s);
219 void ps2_queue_4(PS2State *s, int b1, int b2, int b3, int b4)
221 if (PS2_QUEUE_SIZE - s->queue.count < 4) {
222 return;
225 ps2_queue_noirq(s, b1);
226 ps2_queue_noirq(s, b2);
227 ps2_queue_noirq(s, b3);
228 ps2_queue_noirq(s, b4);
229 ps2_raise_irq(s);
232 static void ps2_cqueue_data(PS2Queue *q, int b)
234 q->data[q->cwptr] = b;
235 if (++q->cwptr >= PS2_BUFFER_SIZE) {
236 q->cwptr = 0;
238 q->count++;
241 static void ps2_cqueue_1(PS2State *s, int b1)
243 PS2Queue *q = &s->queue;
245 q->rptr = (q->rptr - 1) & (PS2_BUFFER_SIZE - 1);
246 q->cwptr = q->rptr;
247 ps2_cqueue_data(q, b1);
248 ps2_raise_irq(s);
251 static void ps2_cqueue_2(PS2State *s, int b1, int b2)
253 PS2Queue *q = &s->queue;
255 q->rptr = (q->rptr - 2) & (PS2_BUFFER_SIZE - 1);
256 q->cwptr = q->rptr;
257 ps2_cqueue_data(q, b1);
258 ps2_cqueue_data(q, b2);
259 ps2_raise_irq(s);
262 static void ps2_cqueue_3(PS2State *s, int b1, int b2, int b3)
264 PS2Queue *q = &s->queue;
266 q->rptr = (q->rptr - 3) & (PS2_BUFFER_SIZE - 1);
267 q->cwptr = q->rptr;
268 ps2_cqueue_data(q, b1);
269 ps2_cqueue_data(q, b2);
270 ps2_cqueue_data(q, b3);
271 ps2_raise_irq(s);
274 static void ps2_cqueue_reset(PS2State *s)
276 PS2Queue *q = &s->queue;
277 int ccount;
279 if (q->cwptr == -1) {
280 return;
283 ccount = (q->cwptr - q->rptr) & (PS2_BUFFER_SIZE - 1);
284 q->count -= ccount;
285 q->rptr = q->cwptr;
286 q->cwptr = -1;
289 /* keycode is the untranslated scancode in the current scancode set. */
290 static void ps2_put_keycode(void *opaque, int keycode)
292 PS2KbdState *s = opaque;
293 PS2State *ps = PS2_DEVICE(s);
295 trace_ps2_put_keycode(opaque, keycode);
296 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL);
298 if (s->translate) {
299 if (keycode == 0xf0) {
300 s->need_high_bit = true;
301 } else if (s->need_high_bit) {
302 ps2_queue(ps, translate_table[keycode] | 0x80);
303 s->need_high_bit = false;
304 } else {
305 ps2_queue(ps, translate_table[keycode]);
307 } else {
308 ps2_queue(ps, keycode);
312 static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,
313 InputEvent *evt)
315 PS2KbdState *s = (PS2KbdState *)dev;
316 InputKeyEvent *key = evt->u.key.data;
317 int qcode;
318 uint16_t keycode = 0;
319 int mod;
321 /* do not process events while disabled to prevent stream corruption */
322 if (!s->scan_enabled) {
323 return;
326 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL);
327 assert(evt->type == INPUT_EVENT_KIND_KEY);
328 qcode = qemu_input_key_value_to_qcode(key->key);
330 mod = ps2_modifier_bit(qcode);
331 trace_ps2_keyboard_event(s, qcode, key->down, mod,
332 s->modifiers, s->scancode_set, s->translate);
333 if (key->down) {
334 s->modifiers |= mod;
335 } else {
336 s->modifiers &= ~mod;
339 if (s->scancode_set == 1) {
340 if (qcode == Q_KEY_CODE_PAUSE) {
341 if (s->modifiers & (MOD_CTRL_L | MOD_CTRL_R)) {
342 if (key->down) {
343 ps2_put_keycode(s, 0xe0);
344 ps2_put_keycode(s, 0x46);
345 ps2_put_keycode(s, 0xe0);
346 ps2_put_keycode(s, 0xc6);
348 } else {
349 if (key->down) {
350 ps2_put_keycode(s, 0xe1);
351 ps2_put_keycode(s, 0x1d);
352 ps2_put_keycode(s, 0x45);
353 ps2_put_keycode(s, 0xe1);
354 ps2_put_keycode(s, 0x9d);
355 ps2_put_keycode(s, 0xc5);
358 } else if (qcode == Q_KEY_CODE_PRINT) {
359 if (s->modifiers & MOD_ALT_L) {
360 if (key->down) {
361 ps2_put_keycode(s, 0xb8);
362 ps2_put_keycode(s, 0x38);
363 ps2_put_keycode(s, 0x54);
364 } else {
365 ps2_put_keycode(s, 0xd4);
366 ps2_put_keycode(s, 0xb8);
367 ps2_put_keycode(s, 0x38);
369 } else if (s->modifiers & MOD_ALT_R) {
370 if (key->down) {
371 ps2_put_keycode(s, 0xe0);
372 ps2_put_keycode(s, 0xb8);
373 ps2_put_keycode(s, 0xe0);
374 ps2_put_keycode(s, 0x38);
375 ps2_put_keycode(s, 0x54);
376 } else {
377 ps2_put_keycode(s, 0xd4);
378 ps2_put_keycode(s, 0xe0);
379 ps2_put_keycode(s, 0xb8);
380 ps2_put_keycode(s, 0xe0);
381 ps2_put_keycode(s, 0x38);
383 } else if (s->modifiers & (MOD_SHIFT_L | MOD_CTRL_L |
384 MOD_SHIFT_R | MOD_CTRL_R)) {
385 if (key->down) {
386 ps2_put_keycode(s, 0xe0);
387 ps2_put_keycode(s, 0x37);
388 } else {
389 ps2_put_keycode(s, 0xe0);
390 ps2_put_keycode(s, 0xb7);
392 } else {
393 if (key->down) {
394 ps2_put_keycode(s, 0xe0);
395 ps2_put_keycode(s, 0x2a);
396 ps2_put_keycode(s, 0xe0);
397 ps2_put_keycode(s, 0x37);
398 } else {
399 ps2_put_keycode(s, 0xe0);
400 ps2_put_keycode(s, 0xb7);
401 ps2_put_keycode(s, 0xe0);
402 ps2_put_keycode(s, 0xaa);
405 } else if ((qcode == Q_KEY_CODE_LANG1 || qcode == Q_KEY_CODE_LANG2)
406 && !key->down) {
407 /* Ignore release for these keys */
408 } else {
409 if (qcode < qemu_input_map_qcode_to_atset1_len) {
410 keycode = qemu_input_map_qcode_to_atset1[qcode];
412 if (keycode) {
413 if (keycode & 0xff00) {
414 ps2_put_keycode(s, keycode >> 8);
416 if (!key->down) {
417 keycode |= 0x80;
419 ps2_put_keycode(s, keycode & 0xff);
420 } else {
421 qemu_log_mask(LOG_UNIMP,
422 "ps2: ignoring key with qcode %d\n", qcode);
425 } else if (s->scancode_set == 2) {
426 if (qcode == Q_KEY_CODE_PAUSE) {
427 if (s->modifiers & (MOD_CTRL_L | MOD_CTRL_R)) {
428 if (key->down) {
429 ps2_put_keycode(s, 0xe0);
430 ps2_put_keycode(s, 0x7e);
431 ps2_put_keycode(s, 0xe0);
432 ps2_put_keycode(s, 0xf0);
433 ps2_put_keycode(s, 0x7e);
435 } else {
436 if (key->down) {
437 ps2_put_keycode(s, 0xe1);
438 ps2_put_keycode(s, 0x14);
439 ps2_put_keycode(s, 0x77);
440 ps2_put_keycode(s, 0xe1);
441 ps2_put_keycode(s, 0xf0);
442 ps2_put_keycode(s, 0x14);
443 ps2_put_keycode(s, 0xf0);
444 ps2_put_keycode(s, 0x77);
447 } else if (qcode == Q_KEY_CODE_PRINT) {
448 if (s->modifiers & MOD_ALT_L) {
449 if (key->down) {
450 ps2_put_keycode(s, 0xf0);
451 ps2_put_keycode(s, 0x11);
452 ps2_put_keycode(s, 0x11);
453 ps2_put_keycode(s, 0x84);
454 } else {
455 ps2_put_keycode(s, 0xf0);
456 ps2_put_keycode(s, 0x84);
457 ps2_put_keycode(s, 0xf0);
458 ps2_put_keycode(s, 0x11);
459 ps2_put_keycode(s, 0x11);
461 } else if (s->modifiers & MOD_ALT_R) {
462 if (key->down) {
463 ps2_put_keycode(s, 0xe0);
464 ps2_put_keycode(s, 0xf0);
465 ps2_put_keycode(s, 0x11);
466 ps2_put_keycode(s, 0xe0);
467 ps2_put_keycode(s, 0x11);
468 ps2_put_keycode(s, 0x84);
469 } else {
470 ps2_put_keycode(s, 0xf0);
471 ps2_put_keycode(s, 0x84);
472 ps2_put_keycode(s, 0xe0);
473 ps2_put_keycode(s, 0xf0);
474 ps2_put_keycode(s, 0x11);
475 ps2_put_keycode(s, 0xe0);
476 ps2_put_keycode(s, 0x11);
478 } else if (s->modifiers & (MOD_SHIFT_L | MOD_CTRL_L |
479 MOD_SHIFT_R | MOD_CTRL_R)) {
480 if (key->down) {
481 ps2_put_keycode(s, 0xe0);
482 ps2_put_keycode(s, 0x7c);
483 } else {
484 ps2_put_keycode(s, 0xe0);
485 ps2_put_keycode(s, 0xf0);
486 ps2_put_keycode(s, 0x7c);
488 } else {
489 if (key->down) {
490 ps2_put_keycode(s, 0xe0);
491 ps2_put_keycode(s, 0x12);
492 ps2_put_keycode(s, 0xe0);
493 ps2_put_keycode(s, 0x7c);
494 } else {
495 ps2_put_keycode(s, 0xe0);
496 ps2_put_keycode(s, 0xf0);
497 ps2_put_keycode(s, 0x7c);
498 ps2_put_keycode(s, 0xe0);
499 ps2_put_keycode(s, 0xf0);
500 ps2_put_keycode(s, 0x12);
503 } else if ((qcode == Q_KEY_CODE_LANG1 || qcode == Q_KEY_CODE_LANG2) &&
504 !key->down) {
505 /* Ignore release for these keys */
506 } else {
507 if (qcode < qemu_input_map_qcode_to_atset2_len) {
508 keycode = qemu_input_map_qcode_to_atset2[qcode];
510 if (keycode) {
511 if (keycode & 0xff00) {
512 ps2_put_keycode(s, keycode >> 8);
514 if (!key->down) {
515 ps2_put_keycode(s, 0xf0);
517 ps2_put_keycode(s, keycode & 0xff);
518 } else {
519 qemu_log_mask(LOG_UNIMP,
520 "ps2: ignoring key with qcode %d\n", qcode);
523 } else if (s->scancode_set == 3) {
524 if (qcode < qemu_input_map_qcode_to_atset3_len) {
525 keycode = qemu_input_map_qcode_to_atset3[qcode];
527 if (keycode) {
528 /* FIXME: break code should be configured on a key by key basis */
529 if (!key->down) {
530 ps2_put_keycode(s, 0xf0);
532 ps2_put_keycode(s, keycode);
533 } else {
534 qemu_log_mask(LOG_UNIMP,
535 "ps2: ignoring key with qcode %d\n", qcode);
540 uint32_t ps2_read_data(PS2State *s)
542 PS2Queue *q;
543 int val, index;
545 trace_ps2_read_data(s);
546 q = &s->queue;
547 if (q->count == 0) {
549 * NOTE: if no data left, we return the last keyboard one
550 * (needed for EMM386)
552 /* XXX: need a timer to do things correctly */
553 index = q->rptr - 1;
554 if (index < 0) {
555 index = PS2_BUFFER_SIZE - 1;
557 val = q->data[index];
558 } else {
559 val = q->data[q->rptr];
560 if (++q->rptr == PS2_BUFFER_SIZE) {
561 q->rptr = 0;
563 q->count--;
564 if (q->rptr == q->cwptr) {
565 /* command reply queue is empty */
566 q->cwptr = -1;
568 /* reading deasserts IRQ */
569 ps2_lower_irq(s);
570 /* reassert IRQs if data left */
571 if (q->count) {
572 ps2_raise_irq(s);
575 return val;
578 static void ps2_set_ledstate(PS2KbdState *s, int ledstate)
580 trace_ps2_set_ledstate(s, ledstate);
581 s->ledstate = ledstate;
582 kbd_put_ledstate(ledstate);
585 static void ps2_reset_keyboard(PS2KbdState *s)
587 PS2State *ps2 = PS2_DEVICE(s);
589 trace_ps2_reset_keyboard(s);
590 s->scan_enabled = 1;
591 s->scancode_set = 2;
592 ps2_reset_queue(ps2);
593 ps2_set_ledstate(s, 0);
596 void ps2_write_keyboard(PS2KbdState *s, int val)
598 PS2State *ps2 = PS2_DEVICE(s);
600 trace_ps2_write_keyboard(s, val);
601 ps2_cqueue_reset(ps2);
602 switch (ps2->write_cmd) {
603 default:
604 case -1:
605 switch (val) {
606 case 0x00:
607 ps2_cqueue_1(ps2, KBD_REPLY_ACK);
608 break;
609 case 0x05:
610 ps2_cqueue_1(ps2, KBD_REPLY_RESEND);
611 break;
612 case KBD_CMD_GET_ID:
613 /* We emulate a MF2 AT keyboard here */
614 ps2_cqueue_3(ps2, KBD_REPLY_ACK, KBD_REPLY_ID,
615 s->translate ? 0x41 : 0x83);
616 break;
617 case KBD_CMD_ECHO:
618 ps2_cqueue_1(ps2, KBD_CMD_ECHO);
619 break;
620 case KBD_CMD_ENABLE:
621 s->scan_enabled = 1;
622 ps2_cqueue_1(ps2, KBD_REPLY_ACK);
623 break;
624 case KBD_CMD_SCANCODE:
625 case KBD_CMD_SET_LEDS:
626 case KBD_CMD_SET_RATE:
627 case KBD_CMD_SET_MAKE_BREAK:
628 ps2->write_cmd = val;
629 ps2_cqueue_1(ps2, KBD_REPLY_ACK);
630 break;
631 case KBD_CMD_RESET_DISABLE:
632 ps2_reset_keyboard(s);
633 s->scan_enabled = 0;
634 ps2_cqueue_1(ps2, KBD_REPLY_ACK);
635 break;
636 case KBD_CMD_RESET_ENABLE:
637 ps2_reset_keyboard(s);
638 s->scan_enabled = 1;
639 ps2_cqueue_1(ps2, KBD_REPLY_ACK);
640 break;
641 case KBD_CMD_RESET:
642 ps2_reset_keyboard(s);
643 ps2_cqueue_2(ps2,
644 KBD_REPLY_ACK,
645 KBD_REPLY_POR);
646 break;
647 case KBD_CMD_SET_TYPEMATIC:
648 ps2_cqueue_1(ps2, KBD_REPLY_ACK);
649 break;
650 default:
651 ps2_cqueue_1(ps2, KBD_REPLY_RESEND);
652 break;
654 break;
655 case KBD_CMD_SET_MAKE_BREAK:
656 ps2_cqueue_1(ps2, KBD_REPLY_ACK);
657 ps2->write_cmd = -1;
658 break;
659 case KBD_CMD_SCANCODE:
660 if (val == 0) {
661 ps2_cqueue_2(ps2, KBD_REPLY_ACK, s->translate ?
662 translate_table[s->scancode_set] : s->scancode_set);
663 } else if (val >= 1 && val <= 3) {
664 s->scancode_set = val;
665 ps2_cqueue_1(ps2, KBD_REPLY_ACK);
666 } else {
667 ps2_cqueue_1(ps2, KBD_REPLY_RESEND);
669 ps2->write_cmd = -1;
670 break;
671 case KBD_CMD_SET_LEDS:
672 ps2_set_ledstate(s, val);
673 ps2_cqueue_1(ps2, KBD_REPLY_ACK);
674 ps2->write_cmd = -1;
675 break;
676 case KBD_CMD_SET_RATE:
677 ps2_cqueue_1(ps2, KBD_REPLY_ACK);
678 ps2->write_cmd = -1;
679 break;
684 * Set the scancode translation mode.
685 * 0 = raw scancodes.
686 * 1 = translated scancodes (used by qemu internally).
689 void ps2_keyboard_set_translation(PS2KbdState *s, int mode)
691 trace_ps2_keyboard_set_translation(s, mode);
692 s->translate = mode;
695 static int ps2_mouse_send_packet(PS2MouseState *s)
697 PS2State *ps2 = PS2_DEVICE(s);
698 /* IMPS/2 and IMEX send 4 bytes, PS2 sends 3 bytes */
699 const int needed = s->mouse_type ? 4 : 3;
700 unsigned int b;
701 int dx1, dy1, dz1, dw1;
703 if (PS2_QUEUE_SIZE - ps2->queue.count < needed) {
704 return 0;
707 dx1 = s->mouse_dx;
708 dy1 = s->mouse_dy;
709 dz1 = s->mouse_dz;
710 dw1 = s->mouse_dw;
711 /* XXX: increase range to 8 bits ? */
712 if (dx1 > 127) {
713 dx1 = 127;
714 } else if (dx1 < -127) {
715 dx1 = -127;
717 if (dy1 > 127) {
718 dy1 = 127;
719 } else if (dy1 < -127) {
720 dy1 = -127;
722 b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
723 ps2_queue_noirq(ps2, b);
724 ps2_queue_noirq(ps2, dx1 & 0xff);
725 ps2_queue_noirq(ps2, dy1 & 0xff);
726 /* extra byte for IMPS/2 or IMEX */
727 switch (s->mouse_type) {
728 default:
729 /* Just ignore the wheels if not supported */
730 s->mouse_dz = 0;
731 s->mouse_dw = 0;
732 break;
733 case 3:
734 if (dz1 > 127) {
735 dz1 = 127;
736 } else if (dz1 < -127) {
737 dz1 = -127;
739 ps2_queue_noirq(ps2, dz1 & 0xff);
740 s->mouse_dz -= dz1;
741 s->mouse_dw = 0;
742 break;
743 case 4:
745 * This matches what the Linux kernel expects for exps/2 in
746 * drivers/input/mouse/psmouse-base.c. Note, if you happen to
747 * press/release the 4th or 5th buttons at the same moment as a
748 * horizontal wheel scroll, those button presses will get lost. I'm not
749 * sure what to do about that, since by this point we don't know
750 * whether those buttons actually changed state.
752 if (dw1 != 0) {
753 if (dw1 > 31) {
754 dw1 = 31;
755 } else if (dw1 < -31) {
756 dw1 = -31;
760 * linux kernel expects first 6 bits to represent the value
761 * for horizontal scroll
763 b = (dw1 & 0x3f) | 0x40;
764 s->mouse_dw -= dw1;
765 } else {
766 if (dz1 > 7) {
767 dz1 = 7;
768 } else if (dz1 < -7) {
769 dz1 = -7;
772 b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
773 s->mouse_dz -= dz1;
775 ps2_queue_noirq(ps2, b);
776 break;
779 ps2_raise_irq(ps2);
781 trace_ps2_mouse_send_packet(s, dx1, dy1, dz1, b);
782 /* update deltas */
783 s->mouse_dx -= dx1;
784 s->mouse_dy -= dy1;
786 return 1;
789 static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
790 InputEvent *evt)
792 static const int bmap[INPUT_BUTTON__MAX] = {
793 [INPUT_BUTTON_LEFT] = PS2_MOUSE_BUTTON_LEFT,
794 [INPUT_BUTTON_MIDDLE] = PS2_MOUSE_BUTTON_MIDDLE,
795 [INPUT_BUTTON_RIGHT] = PS2_MOUSE_BUTTON_RIGHT,
796 [INPUT_BUTTON_SIDE] = PS2_MOUSE_BUTTON_SIDE,
797 [INPUT_BUTTON_EXTRA] = PS2_MOUSE_BUTTON_EXTRA,
799 PS2MouseState *s = (PS2MouseState *)dev;
800 InputMoveEvent *move;
801 InputBtnEvent *btn;
803 /* check if deltas are recorded when disabled */
804 if (!(s->mouse_status & MOUSE_STATUS_ENABLED)) {
805 return;
808 switch (evt->type) {
809 case INPUT_EVENT_KIND_REL:
810 move = evt->u.rel.data;
811 if (move->axis == INPUT_AXIS_X) {
812 s->mouse_dx += move->value;
813 } else if (move->axis == INPUT_AXIS_Y) {
814 s->mouse_dy -= move->value;
816 break;
818 case INPUT_EVENT_KIND_BTN:
819 btn = evt->u.btn.data;
820 if (btn->down) {
821 s->mouse_buttons |= bmap[btn->button];
822 if (btn->button == INPUT_BUTTON_WHEEL_UP) {
823 s->mouse_dz--;
824 } else if (btn->button == INPUT_BUTTON_WHEEL_DOWN) {
825 s->mouse_dz++;
828 if (btn->button == INPUT_BUTTON_WHEEL_RIGHT) {
829 s->mouse_dw--;
830 } else if (btn->button == INPUT_BUTTON_WHEEL_LEFT) {
831 s->mouse_dw++;
833 } else {
834 s->mouse_buttons &= ~bmap[btn->button];
836 break;
838 default:
839 /* keep gcc happy */
840 break;
844 static void ps2_mouse_sync(DeviceState *dev)
846 PS2MouseState *s = (PS2MouseState *)dev;
848 /* do not sync while disabled to prevent stream corruption */
849 if (!(s->mouse_status & MOUSE_STATUS_ENABLED)) {
850 return;
853 if (s->mouse_buttons) {
854 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL);
856 if (!(s->mouse_status & MOUSE_STATUS_REMOTE)) {
858 * if not remote, send event. Multiple events are sent if
859 * too big deltas
861 while (ps2_mouse_send_packet(s)) {
862 if (s->mouse_dx == 0 && s->mouse_dy == 0
863 && s->mouse_dz == 0 && s->mouse_dw == 0) {
864 break;
870 void ps2_mouse_fake_event(PS2MouseState *s)
872 trace_ps2_mouse_fake_event(s);
873 s->mouse_dx++;
874 ps2_mouse_sync(DEVICE(s));
877 void ps2_write_mouse(PS2MouseState *s, int val)
879 PS2State *ps2 = PS2_DEVICE(s);
881 trace_ps2_write_mouse(s, val);
882 switch (ps2->write_cmd) {
883 default:
884 case -1:
885 /* mouse command */
886 if (s->mouse_wrap) {
887 if (val == AUX_RESET_WRAP) {
888 s->mouse_wrap = 0;
889 ps2_queue(ps2, AUX_ACK);
890 return;
891 } else if (val != AUX_RESET) {
892 ps2_queue(ps2, val);
893 return;
896 switch (val) {
897 case AUX_SET_SCALE11:
898 s->mouse_status &= ~MOUSE_STATUS_SCALE21;
899 ps2_queue(ps2, AUX_ACK);
900 break;
901 case AUX_SET_SCALE21:
902 s->mouse_status |= MOUSE_STATUS_SCALE21;
903 ps2_queue(ps2, AUX_ACK);
904 break;
905 case AUX_SET_STREAM:
906 s->mouse_status &= ~MOUSE_STATUS_REMOTE;
907 ps2_queue(ps2, AUX_ACK);
908 break;
909 case AUX_SET_WRAP:
910 s->mouse_wrap = 1;
911 ps2_queue(ps2, AUX_ACK);
912 break;
913 case AUX_SET_REMOTE:
914 s->mouse_status |= MOUSE_STATUS_REMOTE;
915 ps2_queue(ps2, AUX_ACK);
916 break;
917 case AUX_GET_TYPE:
918 ps2_queue_2(ps2,
919 AUX_ACK,
920 s->mouse_type);
921 break;
922 case AUX_SET_RES:
923 case AUX_SET_SAMPLE:
924 ps2->write_cmd = val;
925 ps2_queue(ps2, AUX_ACK);
926 break;
927 case AUX_GET_SCALE:
928 ps2_queue_4(ps2,
929 AUX_ACK,
930 s->mouse_status,
931 s->mouse_resolution,
932 s->mouse_sample_rate);
933 break;
934 case AUX_POLL:
935 ps2_queue(ps2, AUX_ACK);
936 ps2_mouse_send_packet(s);
937 break;
938 case AUX_ENABLE_DEV:
939 s->mouse_status |= MOUSE_STATUS_ENABLED;
940 ps2_queue(ps2, AUX_ACK);
941 break;
942 case AUX_DISABLE_DEV:
943 s->mouse_status &= ~MOUSE_STATUS_ENABLED;
944 ps2_queue(ps2, AUX_ACK);
945 break;
946 case AUX_SET_DEFAULT:
947 s->mouse_sample_rate = 100;
948 s->mouse_resolution = 2;
949 s->mouse_status = 0;
950 ps2_queue(ps2, AUX_ACK);
951 break;
952 case AUX_RESET:
953 s->mouse_sample_rate = 100;
954 s->mouse_resolution = 2;
955 s->mouse_status = 0;
956 s->mouse_type = 0;
957 ps2_reset_queue(ps2);
958 ps2_queue_3(ps2,
959 AUX_ACK,
960 0xaa,
961 s->mouse_type);
962 break;
963 default:
964 break;
966 break;
967 case AUX_SET_SAMPLE:
968 s->mouse_sample_rate = val;
969 /* detect IMPS/2 or IMEX */
970 switch (s->mouse_detect_state) {
971 default:
972 case 0:
973 if (val == 200) {
974 s->mouse_detect_state = 1;
976 break;
977 case 1:
978 if (val == 100) {
979 s->mouse_detect_state = 2;
980 } else if (val == 200) {
981 s->mouse_detect_state = 3;
982 } else {
983 s->mouse_detect_state = 0;
985 break;
986 case 2:
987 if (val == 80) {
988 s->mouse_type = 3; /* IMPS/2 */
990 s->mouse_detect_state = 0;
991 break;
992 case 3:
993 if (val == 80) {
994 s->mouse_type = 4; /* IMEX */
996 s->mouse_detect_state = 0;
997 break;
999 ps2_queue(ps2, AUX_ACK);
1000 ps2->write_cmd = -1;
1001 break;
1002 case AUX_SET_RES:
1003 s->mouse_resolution = val;
1004 ps2_queue(ps2, AUX_ACK);
1005 ps2->write_cmd = -1;
1006 break;
1010 static void ps2_reset_hold(Object *obj)
1012 PS2State *s = PS2_DEVICE(obj);
1014 s->write_cmd = -1;
1015 ps2_reset_queue(s);
1018 static void ps2_reset_exit(Object *obj)
1020 PS2State *s = PS2_DEVICE(obj);
1022 ps2_lower_irq(s);
1025 static void ps2_common_post_load(PS2State *s)
1027 PS2Queue *q = &s->queue;
1028 int ccount = 0;
1030 /* limit the number of queued command replies to PS2_QUEUE_HEADROOM */
1031 if (q->cwptr != -1) {
1032 ccount = (q->cwptr - q->rptr) & (PS2_BUFFER_SIZE - 1);
1033 if (ccount > PS2_QUEUE_HEADROOM) {
1034 ccount = PS2_QUEUE_HEADROOM;
1038 /* limit the scancode queue size to PS2_QUEUE_SIZE */
1039 if (q->count < ccount) {
1040 q->count = ccount;
1041 } else if (q->count > ccount + PS2_QUEUE_SIZE) {
1042 q->count = ccount + PS2_QUEUE_SIZE;
1045 /* sanitize rptr and recalculate wptr and cwptr */
1046 q->rptr = q->rptr & (PS2_BUFFER_SIZE - 1);
1047 q->wptr = (q->rptr + q->count) & (PS2_BUFFER_SIZE - 1);
1048 q->cwptr = ccount ? (q->rptr + ccount) & (PS2_BUFFER_SIZE - 1) : -1;
1051 static void ps2_kbd_reset_hold(Object *obj)
1053 PS2DeviceClass *ps2dc = PS2_DEVICE_GET_CLASS(obj);
1054 PS2KbdState *s = PS2_KBD_DEVICE(obj);
1056 trace_ps2_kbd_reset(s);
1058 if (ps2dc->parent_phases.hold) {
1059 ps2dc->parent_phases.hold(obj);
1062 s->scan_enabled = 1;
1063 s->translate = 0;
1064 s->scancode_set = 2;
1065 s->modifiers = 0;
1068 static void ps2_mouse_reset_hold(Object *obj)
1070 PS2DeviceClass *ps2dc = PS2_DEVICE_GET_CLASS(obj);
1071 PS2MouseState *s = PS2_MOUSE_DEVICE(obj);
1073 trace_ps2_mouse_reset(s);
1075 if (ps2dc->parent_phases.hold) {
1076 ps2dc->parent_phases.hold(obj);
1079 s->mouse_status = 0;
1080 s->mouse_resolution = 0;
1081 s->mouse_sample_rate = 0;
1082 s->mouse_wrap = 0;
1083 s->mouse_type = 0;
1084 s->mouse_detect_state = 0;
1085 s->mouse_dx = 0;
1086 s->mouse_dy = 0;
1087 s->mouse_dz = 0;
1088 s->mouse_dw = 0;
1089 s->mouse_buttons = 0;
1092 static const VMStateDescription vmstate_ps2_common = {
1093 .name = "PS2 Common State",
1094 .version_id = 3,
1095 .minimum_version_id = 2,
1096 .fields = (VMStateField[]) {
1097 VMSTATE_INT32(write_cmd, PS2State),
1098 VMSTATE_INT32(queue.rptr, PS2State),
1099 VMSTATE_INT32(queue.wptr, PS2State),
1100 VMSTATE_INT32(queue.count, PS2State),
1101 VMSTATE_BUFFER(queue.data, PS2State),
1102 VMSTATE_END_OF_LIST()
1106 static bool ps2_keyboard_ledstate_needed(void *opaque)
1108 PS2KbdState *s = opaque;
1110 return s->ledstate != 0; /* 0 is default state */
1113 static int ps2_kbd_ledstate_post_load(void *opaque, int version_id)
1115 PS2KbdState *s = opaque;
1117 kbd_put_ledstate(s->ledstate);
1118 return 0;
1121 static const VMStateDescription vmstate_ps2_keyboard_ledstate = {
1122 .name = "ps2kbd/ledstate",
1123 .version_id = 3,
1124 .minimum_version_id = 2,
1125 .post_load = ps2_kbd_ledstate_post_load,
1126 .needed = ps2_keyboard_ledstate_needed,
1127 .fields = (VMStateField[]) {
1128 VMSTATE_INT32(ledstate, PS2KbdState),
1129 VMSTATE_END_OF_LIST()
1133 static bool ps2_keyboard_need_high_bit_needed(void *opaque)
1135 PS2KbdState *s = opaque;
1136 return s->need_high_bit != 0; /* 0 is the usual state */
1139 static const VMStateDescription vmstate_ps2_keyboard_need_high_bit = {
1140 .name = "ps2kbd/need_high_bit",
1141 .version_id = 1,
1142 .minimum_version_id = 1,
1143 .needed = ps2_keyboard_need_high_bit_needed,
1144 .fields = (VMStateField[]) {
1145 VMSTATE_BOOL(need_high_bit, PS2KbdState),
1146 VMSTATE_END_OF_LIST()
1150 static bool ps2_keyboard_cqueue_needed(void *opaque)
1152 PS2KbdState *s = opaque;
1153 PS2State *ps2 = PS2_DEVICE(s);
1155 return ps2->queue.cwptr != -1; /* the queue is mostly empty */
1158 static const VMStateDescription vmstate_ps2_keyboard_cqueue = {
1159 .name = "ps2kbd/command_reply_queue",
1160 .needed = ps2_keyboard_cqueue_needed,
1161 .fields = (VMStateField[]) {
1162 VMSTATE_INT32(parent_obj.queue.cwptr, PS2KbdState),
1163 VMSTATE_END_OF_LIST()
1167 static int ps2_kbd_post_load(void *opaque, int version_id)
1169 PS2KbdState *s = (PS2KbdState *)opaque;
1170 PS2State *ps2 = PS2_DEVICE(s);
1172 if (version_id == 2) {
1173 s->scancode_set = 2;
1176 ps2_common_post_load(ps2);
1178 return 0;
1181 static const VMStateDescription vmstate_ps2_keyboard = {
1182 .name = "ps2kbd",
1183 .version_id = 3,
1184 .minimum_version_id = 2,
1185 .post_load = ps2_kbd_post_load,
1186 .fields = (VMStateField[]) {
1187 VMSTATE_STRUCT(parent_obj, PS2KbdState, 0, vmstate_ps2_common,
1188 PS2State),
1189 VMSTATE_INT32(scan_enabled, PS2KbdState),
1190 VMSTATE_INT32(translate, PS2KbdState),
1191 VMSTATE_INT32_V(scancode_set, PS2KbdState, 3),
1192 VMSTATE_END_OF_LIST()
1194 .subsections = (const VMStateDescription * []) {
1195 &vmstate_ps2_keyboard_ledstate,
1196 &vmstate_ps2_keyboard_need_high_bit,
1197 &vmstate_ps2_keyboard_cqueue,
1198 NULL
1202 static int ps2_mouse_post_load(void *opaque, int version_id)
1204 PS2MouseState *s = (PS2MouseState *)opaque;
1205 PS2State *ps2 = PS2_DEVICE(s);
1207 ps2_common_post_load(ps2);
1209 return 0;
1212 static const VMStateDescription vmstate_ps2_mouse = {
1213 .name = "ps2mouse",
1214 .version_id = 2,
1215 .minimum_version_id = 2,
1216 .post_load = ps2_mouse_post_load,
1217 .fields = (VMStateField[]) {
1218 VMSTATE_STRUCT(parent_obj, PS2MouseState, 0, vmstate_ps2_common,
1219 PS2State),
1220 VMSTATE_UINT8(mouse_status, PS2MouseState),
1221 VMSTATE_UINT8(mouse_resolution, PS2MouseState),
1222 VMSTATE_UINT8(mouse_sample_rate, PS2MouseState),
1223 VMSTATE_UINT8(mouse_wrap, PS2MouseState),
1224 VMSTATE_UINT8(mouse_type, PS2MouseState),
1225 VMSTATE_UINT8(mouse_detect_state, PS2MouseState),
1226 VMSTATE_INT32(mouse_dx, PS2MouseState),
1227 VMSTATE_INT32(mouse_dy, PS2MouseState),
1228 VMSTATE_INT32(mouse_dz, PS2MouseState),
1229 VMSTATE_UINT8(mouse_buttons, PS2MouseState),
1230 VMSTATE_END_OF_LIST()
1234 static QemuInputHandler ps2_keyboard_handler = {
1235 .name = "QEMU PS/2 Keyboard",
1236 .mask = INPUT_EVENT_MASK_KEY,
1237 .event = ps2_keyboard_event,
1240 static void ps2_kbd_realize(DeviceState *dev, Error **errp)
1242 qemu_input_handler_register(dev, &ps2_keyboard_handler);
1245 static QemuInputHandler ps2_mouse_handler = {
1246 .name = "QEMU PS/2 Mouse",
1247 .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
1248 .event = ps2_mouse_event,
1249 .sync = ps2_mouse_sync,
1252 static void ps2_mouse_realize(DeviceState *dev, Error **errp)
1254 qemu_input_handler_register(dev, &ps2_mouse_handler);
1257 static void ps2_kbd_class_init(ObjectClass *klass, void *data)
1259 DeviceClass *dc = DEVICE_CLASS(klass);
1260 ResettableClass *rc = RESETTABLE_CLASS(klass);
1261 PS2DeviceClass *ps2dc = PS2_DEVICE_CLASS(klass);
1263 dc->realize = ps2_kbd_realize;
1264 resettable_class_set_parent_phases(rc, NULL, ps2_kbd_reset_hold, NULL,
1265 &ps2dc->parent_phases);
1266 dc->vmsd = &vmstate_ps2_keyboard;
1269 static const TypeInfo ps2_kbd_info = {
1270 .name = TYPE_PS2_KBD_DEVICE,
1271 .parent = TYPE_PS2_DEVICE,
1272 .instance_size = sizeof(PS2KbdState),
1273 .class_init = ps2_kbd_class_init
1276 static void ps2_mouse_class_init(ObjectClass *klass, void *data)
1278 DeviceClass *dc = DEVICE_CLASS(klass);
1279 ResettableClass *rc = RESETTABLE_CLASS(klass);
1280 PS2DeviceClass *ps2dc = PS2_DEVICE_CLASS(klass);
1282 dc->realize = ps2_mouse_realize;
1283 resettable_class_set_parent_phases(rc, NULL, ps2_mouse_reset_hold, NULL,
1284 &ps2dc->parent_phases);
1285 dc->vmsd = &vmstate_ps2_mouse;
1288 static const TypeInfo ps2_mouse_info = {
1289 .name = TYPE_PS2_MOUSE_DEVICE,
1290 .parent = TYPE_PS2_DEVICE,
1291 .instance_size = sizeof(PS2MouseState),
1292 .class_init = ps2_mouse_class_init
1295 static void ps2_init(Object *obj)
1297 PS2State *s = PS2_DEVICE(obj);
1299 qdev_init_gpio_out(DEVICE(obj), &s->irq, 1);
1302 static void ps2_class_init(ObjectClass *klass, void *data)
1304 DeviceClass *dc = DEVICE_CLASS(klass);
1305 ResettableClass *rc = RESETTABLE_CLASS(klass);
1307 rc->phases.hold = ps2_reset_hold;
1308 rc->phases.exit = ps2_reset_exit;
1309 set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
1312 static const TypeInfo ps2_info = {
1313 .name = TYPE_PS2_DEVICE,
1314 .parent = TYPE_SYS_BUS_DEVICE,
1315 .instance_init = ps2_init,
1316 .instance_size = sizeof(PS2State),
1317 .class_init = ps2_class_init,
1318 .class_size = sizeof(PS2DeviceClass),
1319 .abstract = true
1322 static void ps2_register_types(void)
1324 type_register_static(&ps2_info);
1325 type_register_static(&ps2_kbd_info);
1326 type_register_static(&ps2_mouse_info);
1329 type_init(ps2_register_types)