]> git.proxmox.com Git - mirror_qemu.git/blame - hw/input/ps2.c
qmp hmp: Make system_wakeup check wake-up support and run state
[mirror_qemu.git] / hw / input / ps2.c
CommitLineData
0e43e99c
FB
1/*
2 * QEMU PS/2 keyboard/mouse emulation
5fafdf24 3 *
0e43e99c 4 * Copyright (c) 2003 Fabrice Bellard
5fafdf24 5 *
0e43e99c
FB
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:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
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.
23 */
0430891c 24#include "qemu/osdep.h"
ec044a80 25#include "qemu/log.h"
83c9f4ca 26#include "hw/hw.h"
0d09e41a 27#include "hw/input/ps2.h"
28ecbaee 28#include "ui/console.h"
66e6536e 29#include "ui/input.h"
9c17d615 30#include "sysemu/sysemu.h"
0e43e99c 31
5edab03d
DK
32#include "trace.h"
33
0e43e99c
FB
34/* debug PC keyboard */
35//#define DEBUG_KBD
36
37/* debug PC keyboard : only mouse */
38//#define DEBUG_MOUSE
39
40/* Keyboard Commands */
41#define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */
42#define KBD_CMD_ECHO 0xEE
e7d93956 43#define KBD_CMD_SCANCODE 0xF0 /* Get/set scancode set */
0e43e99c
FB
44#define KBD_CMD_GET_ID 0xF2 /* get keyboard ID */
45#define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */
46#define KBD_CMD_ENABLE 0xF4 /* Enable scanning */
47#define KBD_CMD_RESET_DISABLE 0xF5 /* reset and disable scanning */
48#define KBD_CMD_RESET_ENABLE 0xF6 /* reset and enable scanning */
49#define KBD_CMD_RESET 0xFF /* Reset */
50
51/* Keyboard Replies */
52#define KBD_REPLY_POR 0xAA /* Power on reset */
35c4d671 53#define KBD_REPLY_ID 0xAB /* Keyboard ID */
0e43e99c
FB
54#define KBD_REPLY_ACK 0xFA /* Command ACK */
55#define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */
56
57/* Mouse Commands */
58#define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */
59#define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */
60#define AUX_SET_RES 0xE8 /* Set resolution */
61#define AUX_GET_SCALE 0xE9 /* Get scaling factor */
62#define AUX_SET_STREAM 0xEA /* Set stream mode */
63#define AUX_POLL 0xEB /* Poll */
64#define AUX_RESET_WRAP 0xEC /* Reset wrap mode */
65#define AUX_SET_WRAP 0xEE /* Set wrap mode */
66#define AUX_SET_REMOTE 0xF0 /* Set remote mode */
67#define AUX_GET_TYPE 0xF2 /* Get type */
68#define AUX_SET_SAMPLE 0xF3 /* Set sample rate */
69#define AUX_ENABLE_DEV 0xF4 /* Enable aux device */
70#define AUX_DISABLE_DEV 0xF5 /* Disable aux device */
71#define AUX_SET_DEFAULT 0xF6
72#define AUX_RESET 0xFF /* Reset aux device */
73#define AUX_ACK 0xFA /* Command byte ACK. */
74
75#define MOUSE_STATUS_REMOTE 0x40
76#define MOUSE_STATUS_ENABLED 0x20
77#define MOUSE_STATUS_SCALE21 0x10
78
2858ab09 79#define PS2_QUEUE_SIZE 16 /* Buffer size required by PS/2 protocol */
0e43e99c 80
620775d1
DB
81/* Bits for 'modifiers' field in PS2KbdState */
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
0e43e99c 89typedef struct {
2858ab09
GA
90 /* Keep the data array 256 bytes long, which compatibility
91 with older qemu versions. */
92 uint8_t data[256];
0e43e99c
FB
93 int rptr, wptr, count;
94} PS2Queue;
95
8498bb8d 96struct PS2State {
0e43e99c
FB
97 PS2Queue queue;
98 int32_t write_cmd;
99 void (*update_irq)(void *, int);
100 void *update_arg;
8498bb8d 101};
0e43e99c
FB
102
103typedef struct {
104 PS2State common;
105 int scan_enabled;
f94f5d71 106 int translate;
e7d93956 107 int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */
7f540ab5 108 int ledstate;
57d5c005 109 bool need_high_bit;
620775d1 110 unsigned int modifiers; /* bitmask of MOD_* constants above */
0e43e99c
FB
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; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */
120 uint8_t mouse_detect_state;
121 int mouse_dx; /* current values, needed for 'poll' mode */
122 int mouse_dy;
123 int mouse_dz;
124 uint8_t mouse_buttons;
125} PS2MouseState;
126
57d5c005
HP
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
620775d1
DB
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
954ee55b
GH
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
7abe7eb2 191void ps2_queue_noirq(PS2State *s, int b)
0e43e99c 192{
0e43e99c
FB
193 PS2Queue *q = &s->queue;
194
7abe7eb2 195 if (q->count == PS2_QUEUE_SIZE) {
0e43e99c 196 return;
7abe7eb2
GM
197 }
198
0e43e99c
FB
199 q->data[q->wptr] = b;
200 if (++q->wptr == PS2_QUEUE_SIZE)
201 q->wptr = 0;
202 q->count++;
7abe7eb2
GM
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);
0e43e99c
FB
249 s->update_irq(s->update_arg, 1);
250}
251
57d5c005 252/* keycode is the untranslated scancode in the current scancode set. */
0e43e99c
FB
253static void ps2_put_keycode(void *opaque, int keycode)
254{
f94f5d71 255 PS2KbdState *s = opaque;
e7d93956 256
5edab03d 257 trace_ps2_put_keycode(opaque, keycode);
fb064112 258 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL);
57d5c005
HP
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]);
7096a96d 268 }
57d5c005
HP
269 } else {
270 ps2_queue(&s->common, keycode);
271 }
0e43e99c
FB
272}
273
66e6536e
GH
274static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,
275 InputEvent *evt)
276{
277 PS2KbdState *s = (PS2KbdState *)dev;
32bafa8f 278 InputKeyEvent *key = evt->u.key.data;
8c10e0ba 279 int qcode;
ab8f9d49 280 uint16_t keycode = 0;
620775d1 281 int mod;
66e6536e 282
143c04c7
GM
283 /* do not process events while disabled to prevent stream corruption */
284 if (!s->scan_enabled) {
285 return;
286 }
287
fb064112 288 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL);
8c10e0ba
HP
289 assert(evt->type == INPUT_EVENT_KIND_KEY);
290 qcode = qemu_input_key_value_to_qcode(key->key);
57d5c005 291
620775d1
DB
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
8c10e0ba
HP
300 if (s->scancode_set == 1) {
301 if (qcode == Q_KEY_CODE_PAUSE) {
29fd23a5
DB
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 }
8c10e0ba
HP
318 }
319 } else if (qcode == Q_KEY_CODE_PRINT) {
620775d1
DB
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 }
8f63458f
DB
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 }
8c10e0ba 353 } else {
620775d1
DB
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 }
8c10e0ba 365 }
57d5c005 366 } else {
ab8f9d49
DB
367 if (qcode < qemu_input_map_qcode_to_atset1_len)
368 keycode = qemu_input_map_qcode_to_atset1[qcode];
8c10e0ba
HP
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 {
ec044a80
HP
378 qemu_log_mask(LOG_UNIMP,
379 "ps2: ignoring key with qcode %d\n", qcode);
8c10e0ba 380 }
57d5c005 381 }
8c10e0ba
HP
382 } else if (s->scancode_set == 2) {
383 if (qcode == Q_KEY_CODE_PAUSE) {
29fd23a5
DB
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 }
57d5c005 403 }
8c10e0ba 404 } else if (qcode == Q_KEY_CODE_PRINT) {
620775d1
DB
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 }
8f63458f
DB
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 }
8c10e0ba 445 } else {
620775d1
DB
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 }
8c10e0ba
HP
459 }
460 } else {
ab8f9d49
DB
461 if (qcode < qemu_input_map_qcode_to_atset2_len)
462 keycode = qemu_input_map_qcode_to_atset2[qcode];
8c10e0ba
HP
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);
8c10e0ba 471 } else {
ec044a80
HP
472 qemu_log_mask(LOG_UNIMP,
473 "ps2: ignoring key with qcode %d\n", qcode);
57d5c005
HP
474 }
475 }
8c10e0ba 476 } else if (s->scancode_set == 3) {
ab8f9d49
DB
477 if (qcode < qemu_input_map_qcode_to_atset3_len)
478 keycode = qemu_input_map_qcode_to_atset3[qcode];
8c10e0ba
HP
479 if (keycode) {
480 /* FIXME: break code should be configured on a key by key basis */
481 if (!key->down) {
482 ps2_put_keycode(s, 0xf0);
483 }
484 ps2_put_keycode(s, keycode);
8c10e0ba 485 } else {
ec044a80
HP
486 qemu_log_mask(LOG_UNIMP,
487 "ps2: ignoring key with qcode %d\n", qcode);
8c10e0ba 488 }
66e6536e
GH
489 }
490}
491
8498bb8d 492uint32_t ps2_read_data(PS2State *s)
0e43e99c 493{
0e43e99c
FB
494 PS2Queue *q;
495 int val, index;
3b46e624 496
8498bb8d 497 trace_ps2_read_data(s);
0e43e99c
FB
498 q = &s->queue;
499 if (q->count == 0) {
500 /* NOTE: if no data left, we return the last keyboard one
501 (needed for EMM386) */
502 /* XXX: need a timer to do things correctly */
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 /* reading deasserts IRQ */
513 s->update_irq(s->update_arg, 0);
514 /* reassert IRQs if data left */
515 s->update_irq(s->update_arg, q->count != 0);
516 }
517 return val;
518}
519
7f540ab5
CF
520static void ps2_set_ledstate(PS2KbdState *s, int ledstate)
521{
5edab03d 522 trace_ps2_set_ledstate(s, ledstate);
7f540ab5
CF
523 s->ledstate = ledstate;
524 kbd_put_ledstate(ledstate);
525}
526
0e43e99c
FB
527static void ps2_reset_keyboard(PS2KbdState *s)
528{
5edab03d 529 trace_ps2_reset_keyboard(s);
0e43e99c 530 s->scan_enabled = 1;
e7d93956 531 s->scancode_set = 2;
6e24ee0c 532 ps2_reset_queue(&s->common);
7f540ab5 533 ps2_set_ledstate(s, 0);
0e43e99c
FB
534}
535
536void ps2_write_keyboard(void *opaque, int val)
537{
538 PS2KbdState *s = (PS2KbdState *)opaque;
539
5edab03d 540 trace_ps2_write_keyboard(opaque, val);
0e43e99c
FB
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:
e7d93956 552 /* We emulate a MF2 AT keyboard here */
35c4d671 553 if (s->translate)
7abe7eb2
GM
554 ps2_queue_3(&s->common,
555 KBD_REPLY_ACK,
556 KBD_REPLY_ID,
557 0x41);
35c4d671 558 else
7abe7eb2
GM
559 ps2_queue_3(&s->common,
560 KBD_REPLY_ACK,
561 KBD_REPLY_ID,
562 0x83);
0e43e99c
FB
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;
e7d93956 571 case KBD_CMD_SCANCODE:
0e43e99c
FB
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);
7abe7eb2
GM
589 ps2_queue_2(&s->common,
590 KBD_REPLY_ACK,
591 KBD_REPLY_POR);
0e43e99c
FB
592 break;
593 default:
06b3611f 594 ps2_queue(&s->common, KBD_REPLY_RESEND);
0e43e99c
FB
595 break;
596 }
597 break;
e7d93956
AJ
598 case KBD_CMD_SCANCODE:
599 if (val == 0) {
7abe7eb2
GM
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 }
4df23b64
HP
604 } else if (val >= 1 && val <= 3) {
605 s->scancode_set = val;
e7d93956 606 ps2_queue(&s->common, KBD_REPLY_ACK);
4df23b64
HP
607 } else {
608 ps2_queue(&s->common, KBD_REPLY_RESEND);
e7d93956
AJ
609 }
610 s->common.write_cmd = -1;
611 break;
0e43e99c 612 case KBD_CMD_SET_LEDS:
7f540ab5 613 ps2_set_ledstate(s, val);
0e43e99c
FB
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
f94f5d71
PB
624/* Set the scancode translation mode.
625 0 = raw scancodes.
626 1 = translated scancodes (used by qemu internally). */
627
628void ps2_keyboard_set_translation(void *opaque, int mode)
629{
630 PS2KbdState *s = (PS2KbdState *)opaque;
5edab03d 631 trace_ps2_keyboard_set_translation(opaque, mode);
f94f5d71
PB
632 s->translate = mode;
633}
634
7abe7eb2 635static int ps2_mouse_send_packet(PS2MouseState *s)
0e43e99c 636{
7abe7eb2 637 const int needed = 3 + (s->mouse_type - 2);
0e43e99c
FB
638 unsigned int b;
639 int dx1, dy1, dz1;
640
7abe7eb2
GM
641 if (PS2_QUEUE_SIZE - s->common.queue.count < needed) {
642 return 0;
643 }
644
0e43e99c
FB
645 dx1 = s->mouse_dx;
646 dy1 = s->mouse_dy;
647 dz1 = s->mouse_dz;
648 /* XXX: increase range to 8 bits ? */
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);
7abe7eb2
GM
658 ps2_queue_noirq(&s->common, b);
659 ps2_queue_noirq(&s->common, dx1 & 0xff);
660 ps2_queue_noirq(&s->common, dy1 & 0xff);
0e43e99c
FB
661 /* extra byte for IMPS/2 or IMEX */
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;
7abe7eb2 670 ps2_queue_noirq(&s->common, dz1 & 0xff);
0e43e99c
FB
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);
7abe7eb2 678 ps2_queue_noirq(&s->common, b);
0e43e99c
FB
679 break;
680 }
681
7abe7eb2
GM
682 ps2_raise_irq(&s->common);
683
5edab03d 684 trace_ps2_mouse_send_packet(s, dx1, dy1, dz1, b);
0e43e99c
FB
685 /* update deltas */
686 s->mouse_dx -= dx1;
687 s->mouse_dy -= dy1;
688 s->mouse_dz -= dz1;
7abe7eb2
GM
689
690 return 1;
0e43e99c
FB
691}
692
2a766d29
GH
693static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
694 InputEvent *evt)
0e43e99c 695{
7fb1cf16 696 static const int bmap[INPUT_BUTTON__MAX] = {
8b0caab0
FL
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,
2a766d29
GH
702 };
703 PS2MouseState *s = (PS2MouseState *)dev;
b5a1b443
EB
704 InputMoveEvent *move;
705 InputBtnEvent *btn;
0e43e99c
FB
706
707 /* check if deltas are recorded when disabled */
708 if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
709 return;
710
568c73a4 711 switch (evt->type) {
2a766d29 712 case INPUT_EVENT_KIND_REL:
32bafa8f 713 move = evt->u.rel.data;
b5a1b443
EB
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;
2a766d29
GH
718 }
719 break;
3b46e624 720
2a766d29 721 case INPUT_EVENT_KIND_BTN:
32bafa8f 722 btn = evt->u.btn.data;
b5a1b443
EB
723 if (btn->down) {
724 s->mouse_buttons |= bmap[btn->button];
725 if (btn->button == INPUT_BUTTON_WHEEL_UP) {
2a766d29 726 s->mouse_dz--;
b5a1b443 727 } else if (btn->button == INPUT_BUTTON_WHEEL_DOWN) {
2a766d29
GH
728 s->mouse_dz++;
729 }
730 } else {
b5a1b443 731 s->mouse_buttons &= ~bmap[btn->button];
2a766d29
GH
732 }
733 break;
734
735 default:
736 /* keep gcc happy */
737 break;
fd214d18 738 }
2a766d29 739}
fd214d18 740
2a766d29
GH
741static void ps2_mouse_sync(DeviceState *dev)
742{
743 PS2MouseState *s = (PS2MouseState *)dev;
744
143c04c7
GM
745 /* do not sync while disabled to prevent stream corruption */
746 if (!(s->mouse_status & MOUSE_STATUS_ENABLED)) {
747 return;
748 }
749
2a766d29 750 if (s->mouse_buttons) {
fb064112 751 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL);
2a766d29 752 }
2858ab09 753 if (!(s->mouse_status & MOUSE_STATUS_REMOTE)) {
7abe7eb2
GM
754 /* if not remote, send event. Multiple events are sent if
755 too big deltas */
756 while (ps2_mouse_send_packet(s)) {
0e43e99c
FB
757 if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
758 break;
759 }
760 }
761}
762
548df2ac
TS
763void ps2_mouse_fake_event(void *opaque)
764{
2a766d29 765 PS2MouseState *s = opaque;
5edab03d 766 trace_ps2_mouse_fake_event(opaque);
2a766d29
GH
767 s->mouse_dx++;
768 ps2_mouse_sync(opaque);
548df2ac
TS
769}
770
0e43e99c
FB
771void ps2_write_mouse(void *opaque, int val)
772{
773 PS2MouseState *s = (PS2MouseState *)opaque;
5edab03d
DK
774
775 trace_ps2_write_mouse(opaque, val);
0e43e99c
FB
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 /* mouse command */
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:
7abe7eb2
GM
815 ps2_queue_2(&s->common,
816 AUX_ACK,
817 s->mouse_type);
0e43e99c
FB
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:
7abe7eb2
GM
825 ps2_queue_4(&s->common,
826 AUX_ACK,
827 s->mouse_status,
828 s->mouse_resolution,
829 s->mouse_sample_rate);
0e43e99c
FB
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;
143c04c7 854 ps2_reset_queue(&s->common);
7abe7eb2
GM
855 ps2_queue_3(&s->common,
856 AUX_ACK,
857 0xaa,
858 s->mouse_type);
0e43e99c
FB
859 break;
860 default:
861 break;
862 }
863 break;
864 case AUX_SET_SAMPLE:
865 s->mouse_sample_rate = val;
866 /* detect IMPS/2 or IMEX */
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:
5fafdf24 882 if (val == 80)
0e43e99c
FB
883 s->mouse_type = 3; /* IMPS/2 */
884 s->mouse_detect_state = 0;
885 break;
886 case 3:
5fafdf24 887 if (val == 80)
0e43e99c
FB
888 s->mouse_type = 4; /* IMEX */
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
ef74679a 903static void ps2_common_reset(PS2State *s)
0e43e99c 904{
0e43e99c 905 s->write_cmd = -1;
954ee55b 906 ps2_reset_queue(s);
deeccef3 907 s->update_irq(s->update_arg, 0);
0e43e99c
FB
908}
909
2858ab09
GA
910static void ps2_common_post_load(PS2State *s)
911{
912 PS2Queue *q = &s->queue;
802cbcb7
PP
913 uint8_t i, size;
914 uint8_t tmp_data[PS2_QUEUE_SIZE];
2858ab09
GA
915
916 /* set the useful data buffer queue size, < PS2_QUEUE_SIZE */
a1f2ed2a
PD
917 size = q->count;
918 if (q->count < 0) {
919 size = 0;
920 } else if (q->count > PS2_QUEUE_SIZE) {
921 size = PS2_QUEUE_SIZE;
922 }
2858ab09
GA
923
924 /* move the queue elements to the start of data array */
802cbcb7
PP
925 for (i = 0; i < size; i++) {
926 if (q->rptr < 0 || q->rptr >= sizeof(q->data)) {
927 q->rptr = 0;
2858ab09 928 }
802cbcb7 929 tmp_data[i] = q->data[q->rptr++];
2858ab09 930 }
802cbcb7
PP
931 memcpy(q->data, tmp_data, size);
932
2858ab09
GA
933 /* reset rptr/wptr/count */
934 q->rptr = 0;
b55a06df 935 q->wptr = (size == PS2_QUEUE_SIZE) ? 0 : size;
2858ab09 936 q->count = size;
2858ab09
GA
937}
938
ef74679a
DS
939static void ps2_kbd_reset(void *opaque)
940{
941 PS2KbdState *s = (PS2KbdState *) opaque;
942
5edab03d 943 trace_ps2_kbd_reset(opaque);
ef74679a 944 ps2_common_reset(&s->common);
d2e550a8 945 s->scan_enabled = 1;
ef74679a 946 s->translate = 0;
089adafd 947 s->scancode_set = 2;
620775d1 948 s->modifiers = 0;
ef74679a
DS
949}
950
951static void ps2_mouse_reset(void *opaque)
952{
953 PS2MouseState *s = (PS2MouseState *) opaque;
954
5edab03d 955 trace_ps2_mouse_reset(opaque);
ef74679a
DS
956 ps2_common_reset(&s->common);
957 s->mouse_status = 0;
958 s->mouse_resolution = 0;
959 s->mouse_sample_rate = 0;
960 s->mouse_wrap = 0;
961 s->mouse_type = 0;
962 s->mouse_detect_state = 0;
963 s->mouse_dx = 0;
964 s->mouse_dy = 0;
965 s->mouse_dz = 0;
966 s->mouse_buttons = 0;
967}
968
b31442c3
JQ
969static const VMStateDescription vmstate_ps2_common = {
970 .name = "PS2 Common State",
971 .version_id = 3,
972 .minimum_version_id = 2,
d49805ae 973 .fields = (VMStateField[]) {
b31442c3
JQ
974 VMSTATE_INT32(write_cmd, PS2State),
975 VMSTATE_INT32(queue.rptr, PS2State),
976 VMSTATE_INT32(queue.wptr, PS2State),
977 VMSTATE_INT32(queue.count, PS2State),
978 VMSTATE_BUFFER(queue.data, PS2State),
979 VMSTATE_END_OF_LIST()
980 }
981};
0e43e99c 982
7f540ab5
CF
983static bool ps2_keyboard_ledstate_needed(void *opaque)
984{
985 PS2KbdState *s = opaque;
986
987 return s->ledstate != 0; /* 0 is default state */
988}
989
990static int ps2_kbd_ledstate_post_load(void *opaque, int version_id)
991{
992 PS2KbdState *s = opaque;
993
994 kbd_put_ledstate(s->ledstate);
995 return 0;
996}
997
998static const VMStateDescription vmstate_ps2_keyboard_ledstate = {
999 .name = "ps2kbd/ledstate",
1000 .version_id = 3,
1001 .minimum_version_id = 2,
7f540ab5 1002 .post_load = ps2_kbd_ledstate_post_load,
5cd8cada 1003 .needed = ps2_keyboard_ledstate_needed,
d49805ae 1004 .fields = (VMStateField[]) {
7f540ab5
CF
1005 VMSTATE_INT32(ledstate, PS2KbdState),
1006 VMSTATE_END_OF_LIST()
1007 }
1008};
1009
57d5c005
HP
1010static bool ps2_keyboard_need_high_bit_needed(void *opaque)
1011{
1012 PS2KbdState *s = opaque;
1013 return s->need_high_bit != 0; /* 0 is the usual state */
1014}
1015
1016static const VMStateDescription vmstate_ps2_keyboard_need_high_bit = {
1017 .name = "ps2kbd/need_high_bit",
1018 .version_id = 1,
1019 .minimum_version_id = 1,
1020 .needed = ps2_keyboard_need_high_bit_needed,
1021 .fields = (VMStateField[]) {
1022 VMSTATE_BOOL(need_high_bit, PS2KbdState),
1023 VMSTATE_END_OF_LIST()
1024 }
1025};
1026
db596c53 1027static int ps2_kbd_post_load(void* opaque, int version_id)
0e43e99c
FB
1028{
1029 PS2KbdState *s = (PS2KbdState*)opaque;
2858ab09 1030 PS2State *ps2 = &s->common;
7783e9f0 1031
db596c53 1032 if (version_id == 2)
e7d93956 1033 s->scancode_set=2;
2858ab09
GA
1034
1035 ps2_common_post_load(ps2);
1036
0e43e99c
FB
1037 return 0;
1038}
1039
44b1ff31 1040static int ps2_kbd_pre_save(void *opaque)
2858ab09
GA
1041{
1042 PS2KbdState *s = (PS2KbdState *)opaque;
1043 PS2State *ps2 = &s->common;
1044
1045 ps2_common_post_load(ps2);
44b1ff31
DDAG
1046
1047 return 0;
2858ab09
GA
1048}
1049
b31442c3
JQ
1050static const VMStateDescription vmstate_ps2_keyboard = {
1051 .name = "ps2kbd",
1052 .version_id = 3,
db596c53 1053 .minimum_version_id = 2,
db596c53 1054 .post_load = ps2_kbd_post_load,
2858ab09 1055 .pre_save = ps2_kbd_pre_save,
d49805ae 1056 .fields = (VMStateField[]) {
b31442c3
JQ
1057 VMSTATE_STRUCT(common, PS2KbdState, 0, vmstate_ps2_common, PS2State),
1058 VMSTATE_INT32(scan_enabled, PS2KbdState),
1059 VMSTATE_INT32(translate, PS2KbdState),
1060 VMSTATE_INT32_V(scancode_set, PS2KbdState,3),
1061 VMSTATE_END_OF_LIST()
7f540ab5 1062 },
5cd8cada
JQ
1063 .subsections = (const VMStateDescription*[]) {
1064 &vmstate_ps2_keyboard_ledstate,
57d5c005 1065 &vmstate_ps2_keyboard_need_high_bit,
5cd8cada 1066 NULL
b31442c3
JQ
1067 }
1068};
7783e9f0 1069
2858ab09
GA
1070static int ps2_mouse_post_load(void *opaque, int version_id)
1071{
1072 PS2MouseState *s = (PS2MouseState *)opaque;
1073 PS2State *ps2 = &s->common;
1074
1075 ps2_common_post_load(ps2);
1076
1077 return 0;
1078}
1079
44b1ff31 1080static int ps2_mouse_pre_save(void *opaque)
2858ab09
GA
1081{
1082 PS2MouseState *s = (PS2MouseState *)opaque;
1083 PS2State *ps2 = &s->common;
1084
1085 ps2_common_post_load(ps2);
44b1ff31
DDAG
1086
1087 return 0;
2858ab09
GA
1088}
1089
b31442c3
JQ
1090static const VMStateDescription vmstate_ps2_mouse = {
1091 .name = "ps2mouse",
1092 .version_id = 2,
1093 .minimum_version_id = 2,
2858ab09
GA
1094 .post_load = ps2_mouse_post_load,
1095 .pre_save = ps2_mouse_pre_save,
d49805ae 1096 .fields = (VMStateField[]) {
b31442c3
JQ
1097 VMSTATE_STRUCT(common, PS2MouseState, 0, vmstate_ps2_common, PS2State),
1098 VMSTATE_UINT8(mouse_status, PS2MouseState),
1099 VMSTATE_UINT8(mouse_resolution, PS2MouseState),
1100 VMSTATE_UINT8(mouse_sample_rate, PS2MouseState),
1101 VMSTATE_UINT8(mouse_wrap, PS2MouseState),
1102 VMSTATE_UINT8(mouse_type, PS2MouseState),
1103 VMSTATE_UINT8(mouse_detect_state, PS2MouseState),
1104 VMSTATE_INT32(mouse_dx, PS2MouseState),
1105 VMSTATE_INT32(mouse_dy, PS2MouseState),
1106 VMSTATE_INT32(mouse_dz, PS2MouseState),
1107 VMSTATE_UINT8(mouse_buttons, PS2MouseState),
1108 VMSTATE_END_OF_LIST()
1109 }
1110};
0e43e99c 1111
66e6536e
GH
1112static QemuInputHandler ps2_keyboard_handler = {
1113 .name = "QEMU PS/2 Keyboard",
1114 .mask = INPUT_EVENT_MASK_KEY,
1115 .event = ps2_keyboard_event,
1116};
1117
0e43e99c
FB
1118void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
1119{
7267c094 1120 PS2KbdState *s = (PS2KbdState *)g_malloc0(sizeof(PS2KbdState));
0e43e99c 1121
5edab03d 1122 trace_ps2_kbd_init(s);
0e43e99c
FB
1123 s->common.update_irq = update_irq;
1124 s->common.update_arg = update_arg;
e7d93956 1125 s->scancode_set = 2;
0be71e32 1126 vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s);
66e6536e
GH
1127 qemu_input_handler_register((DeviceState *)s,
1128 &ps2_keyboard_handler);
ef74679a 1129 qemu_register_reset(ps2_kbd_reset, s);
0e43e99c
FB
1130 return s;
1131}
1132
2a766d29
GH
1133static QemuInputHandler ps2_mouse_handler = {
1134 .name = "QEMU PS/2 Mouse",
1135 .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
1136 .event = ps2_mouse_event,
1137 .sync = ps2_mouse_sync,
1138};
1139
0e43e99c
FB
1140void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
1141{
7267c094 1142 PS2MouseState *s = (PS2MouseState *)g_malloc0(sizeof(PS2MouseState));
0e43e99c 1143
5edab03d 1144 trace_ps2_mouse_init(s);
0e43e99c
FB
1145 s->common.update_irq = update_irq;
1146 s->common.update_arg = update_arg;
0be71e32 1147 vmstate_register(NULL, 0, &vmstate_ps2_mouse, s);
2a766d29
GH
1148 qemu_input_handler_register((DeviceState *)s,
1149 &ps2_mouse_handler);
ef74679a 1150 qemu_register_reset(ps2_mouse_reset, s);
0e43e99c
FB
1151 return s;
1152}