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
24 #include "qemu/osdep.h"
27 #include "hw/input/ps2.h"
28 #include "ui/console.h"
30 #include "sysemu/sysemu.h"
34 /* debug PC keyboard */
37 /* debug PC keyboard : only mouse */
40 /* Keyboard Commands */
41 #define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */
42 #define KBD_CMD_ECHO 0xEE
43 #define KBD_CMD_SCANCODE 0xF0 /* Get/set scancode set */
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 */
51 /* Keyboard Replies */
52 #define KBD_REPLY_POR 0xAA /* Power on reset */
53 #define KBD_REPLY_ID 0xAB /* Keyboard ID */
54 #define KBD_REPLY_ACK 0xFA /* Command ACK */
55 #define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */
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. */
75 #define MOUSE_STATUS_REMOTE 0x40
76 #define MOUSE_STATUS_ENABLED 0x20
77 #define MOUSE_STATUS_SCALE21 0x10
79 #define PS2_QUEUE_SIZE 16 /* Buffer size required by PS/2 protocol */
82 /* Keep the data array 256 bytes long, which compatibility
83 with older qemu versions. */
85 int rptr, wptr, count;
91 void (*update_irq)(void *, int);
99 int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */
106 uint8_t mouse_status;
107 uint8_t mouse_resolution;
108 uint8_t mouse_sample_rate;
110 uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */
111 uint8_t mouse_detect_state;
112 int mouse_dx; /* current values, needed for 'poll' mode */
115 uint8_t mouse_buttons;
118 /* Table to convert from QEMU codes to scancodes. */
119 static const uint16_t qcode_to_keycode_set1[Q_KEY_CODE__MAX] = {
120 [0 ... Q_KEY_CODE__MAX - 1] = 0,
122 [Q_KEY_CODE_A] = 0x1e,
123 [Q_KEY_CODE_B] = 0x30,
124 [Q_KEY_CODE_C] = 0x2e,
125 [Q_KEY_CODE_D] = 0x20,
126 [Q_KEY_CODE_E] = 0x12,
127 [Q_KEY_CODE_F] = 0x21,
128 [Q_KEY_CODE_G] = 0x22,
129 [Q_KEY_CODE_H] = 0x23,
130 [Q_KEY_CODE_I] = 0x17,
131 [Q_KEY_CODE_J] = 0x24,
132 [Q_KEY_CODE_K] = 0x25,
133 [Q_KEY_CODE_L] = 0x26,
134 [Q_KEY_CODE_M] = 0x32,
135 [Q_KEY_CODE_N] = 0x31,
136 [Q_KEY_CODE_O] = 0x18,
137 [Q_KEY_CODE_P] = 0x19,
138 [Q_KEY_CODE_Q] = 0x10,
139 [Q_KEY_CODE_R] = 0x13,
140 [Q_KEY_CODE_S] = 0x1f,
141 [Q_KEY_CODE_T] = 0x14,
142 [Q_KEY_CODE_U] = 0x16,
143 [Q_KEY_CODE_V] = 0x2f,
144 [Q_KEY_CODE_W] = 0x11,
145 [Q_KEY_CODE_X] = 0x2d,
146 [Q_KEY_CODE_Y] = 0x15,
147 [Q_KEY_CODE_Z] = 0x2c,
148 [Q_KEY_CODE_0] = 0x0b,
149 [Q_KEY_CODE_1] = 0x02,
150 [Q_KEY_CODE_2] = 0x03,
151 [Q_KEY_CODE_3] = 0x04,
152 [Q_KEY_CODE_4] = 0x05,
153 [Q_KEY_CODE_5] = 0x06,
154 [Q_KEY_CODE_6] = 0x07,
155 [Q_KEY_CODE_7] = 0x08,
156 [Q_KEY_CODE_8] = 0x09,
157 [Q_KEY_CODE_9] = 0x0a,
158 [Q_KEY_CODE_GRAVE_ACCENT] = 0x29,
159 [Q_KEY_CODE_MINUS] = 0x0c,
160 [Q_KEY_CODE_EQUAL] = 0x0d,
161 [Q_KEY_CODE_BACKSLASH] = 0x2b,
162 [Q_KEY_CODE_BACKSPACE] = 0x0e,
163 [Q_KEY_CODE_SPC] = 0x39,
164 [Q_KEY_CODE_TAB] = 0x0f,
165 [Q_KEY_CODE_CAPS_LOCK] = 0x3a,
166 [Q_KEY_CODE_SHIFT] = 0x2a,
167 [Q_KEY_CODE_CTRL] = 0x1d,
168 [Q_KEY_CODE_META_L] = 0xe05b,
169 [Q_KEY_CODE_ALT] = 0x38,
170 [Q_KEY_CODE_SHIFT_R] = 0x36,
171 [Q_KEY_CODE_CTRL_R] = 0xe01d,
172 [Q_KEY_CODE_META_R] = 0xe05c,
173 [Q_KEY_CODE_ALT_R] = 0xe038,
174 [Q_KEY_CODE_MENU] = 0xe05d,
175 [Q_KEY_CODE_RET] = 0x1c,
176 [Q_KEY_CODE_ESC] = 0x01,
177 [Q_KEY_CODE_F1] = 0x3b,
178 [Q_KEY_CODE_F2] = 0x3c,
179 [Q_KEY_CODE_F3] = 0x3d,
180 [Q_KEY_CODE_F4] = 0x3e,
181 [Q_KEY_CODE_F5] = 0x3f,
182 [Q_KEY_CODE_F6] = 0x40,
183 [Q_KEY_CODE_F7] = 0x41,
184 [Q_KEY_CODE_F8] = 0x42,
185 [Q_KEY_CODE_F9] = 0x43,
186 [Q_KEY_CODE_F10] = 0x44,
187 [Q_KEY_CODE_F11] = 0x57,
188 [Q_KEY_CODE_F12] = 0x58,
189 /* special handling for Q_KEY_CODE_PRINT */
190 [Q_KEY_CODE_SCROLL_LOCK] = 0x46,
191 /* special handling for Q_KEY_CODE_PAUSE */
192 [Q_KEY_CODE_BRACKET_LEFT] = 0x1a,
193 [Q_KEY_CODE_INSERT] = 0xe052,
194 [Q_KEY_CODE_HOME] = 0xe047,
195 [Q_KEY_CODE_PGUP] = 0xe049,
196 [Q_KEY_CODE_DELETE] = 0xe053,
197 [Q_KEY_CODE_END] = 0xe04f,
198 [Q_KEY_CODE_PGDN] = 0xe051,
199 [Q_KEY_CODE_UP] = 0xe048,
200 [Q_KEY_CODE_LEFT] = 0xe04b,
201 [Q_KEY_CODE_DOWN] = 0xe050,
202 [Q_KEY_CODE_RIGHT] = 0xe04d,
203 [Q_KEY_CODE_NUM_LOCK] = 0x45,
204 [Q_KEY_CODE_KP_DIVIDE] = 0xe035,
205 [Q_KEY_CODE_KP_MULTIPLY] = 0x37,
206 [Q_KEY_CODE_KP_SUBTRACT] = 0x4a,
207 [Q_KEY_CODE_KP_ADD] = 0x4e,
208 [Q_KEY_CODE_KP_ENTER] = 0xe01c,
209 [Q_KEY_CODE_KP_DECIMAL] = 0x53,
210 [Q_KEY_CODE_KP_0] = 0x52,
211 [Q_KEY_CODE_KP_1] = 0x4f,
212 [Q_KEY_CODE_KP_2] = 0x50,
213 [Q_KEY_CODE_KP_3] = 0x51,
214 [Q_KEY_CODE_KP_4] = 0x4b,
215 [Q_KEY_CODE_KP_5] = 0x4c,
216 [Q_KEY_CODE_KP_6] = 0x4d,
217 [Q_KEY_CODE_KP_7] = 0x47,
218 [Q_KEY_CODE_KP_8] = 0x48,
219 [Q_KEY_CODE_KP_9] = 0x49,
220 [Q_KEY_CODE_BRACKET_RIGHT] = 0x1b,
221 [Q_KEY_CODE_SEMICOLON] = 0x27,
222 [Q_KEY_CODE_APOSTROPHE] = 0x28,
223 [Q_KEY_CODE_COMMA] = 0x33,
224 [Q_KEY_CODE_DOT] = 0x34,
225 [Q_KEY_CODE_SLASH] = 0x35,
228 [Q_KEY_CODE_POWER] = 0x0e5e,
229 [Q_KEY_CODE_SLEEP] = 0x0e5f,
230 [Q_KEY_CODE_WAKE] = 0x0e63,
232 [Q_KEY_CODE_AUDIONEXT] = 0xe019,
233 [Q_KEY_CODE_AUDIOPREV] = 0xe010,
234 [Q_KEY_CODE_AUDIOSTOP] = 0xe024,
235 [Q_KEY_CODE_AUDIOPLAY] = 0xe022,
236 [Q_KEY_CODE_AUDIOMUTE] = 0xe020,
237 [Q_KEY_CODE_VOLUMEUP] = 0xe030,
238 [Q_KEY_CODE_VOLUMEDOWN] = 0xe02e,
239 [Q_KEY_CODE_MEDIASELECT] = 0xe06d,
240 [Q_KEY_CODE_MAIL] = 0xe06c,
241 [Q_KEY_CODE_CALCULATOR] = 0xe021,
242 [Q_KEY_CODE_COMPUTER] = 0xe06b,
243 [Q_KEY_CODE_AC_SEARCH] = 0xe065,
244 [Q_KEY_CODE_AC_HOME] = 0xe032,
245 [Q_KEY_CODE_AC_BACK] = 0xe06a,
246 [Q_KEY_CODE_AC_FORWARD] = 0xe069,
247 [Q_KEY_CODE_AC_STOP] = 0xe068,
248 [Q_KEY_CODE_AC_REFRESH] = 0xe067,
249 [Q_KEY_CODE_AC_BOOKMARKS] = 0xe066,
252 [Q_KEY_CODE_ASTERISK] = 0x37,
253 [Q_KEY_CODE_LESS] = 0x56,
254 [Q_KEY_CODE_RO] = 0x73,
255 [Q_KEY_CODE_KP_COMMA] = 0x7e,
258 static const uint16_t qcode_to_keycode_set2[Q_KEY_CODE__MAX] = {
259 [0 ... Q_KEY_CODE__MAX - 1] = 0,
261 [Q_KEY_CODE_A] = 0x1c,
262 [Q_KEY_CODE_B] = 0x32,
263 [Q_KEY_CODE_C] = 0x21,
264 [Q_KEY_CODE_D] = 0x23,
265 [Q_KEY_CODE_E] = 0x24,
266 [Q_KEY_CODE_F] = 0x2b,
267 [Q_KEY_CODE_G] = 0x34,
268 [Q_KEY_CODE_H] = 0x33,
269 [Q_KEY_CODE_I] = 0x43,
270 [Q_KEY_CODE_J] = 0x3b,
271 [Q_KEY_CODE_K] = 0x42,
272 [Q_KEY_CODE_L] = 0x4b,
273 [Q_KEY_CODE_M] = 0x3a,
274 [Q_KEY_CODE_N] = 0x31,
275 [Q_KEY_CODE_O] = 0x44,
276 [Q_KEY_CODE_P] = 0x4d,
277 [Q_KEY_CODE_Q] = 0x15,
278 [Q_KEY_CODE_R] = 0x2d,
279 [Q_KEY_CODE_S] = 0x1b,
280 [Q_KEY_CODE_T] = 0x2c,
281 [Q_KEY_CODE_U] = 0x3c,
282 [Q_KEY_CODE_V] = 0x2a,
283 [Q_KEY_CODE_W] = 0x1d,
284 [Q_KEY_CODE_X] = 0x22,
285 [Q_KEY_CODE_Y] = 0x35,
286 [Q_KEY_CODE_Z] = 0x1a,
287 [Q_KEY_CODE_0] = 0x45,
288 [Q_KEY_CODE_1] = 0x16,
289 [Q_KEY_CODE_2] = 0x1e,
290 [Q_KEY_CODE_3] = 0x26,
291 [Q_KEY_CODE_4] = 0x25,
292 [Q_KEY_CODE_5] = 0x2e,
293 [Q_KEY_CODE_6] = 0x36,
294 [Q_KEY_CODE_7] = 0x3d,
295 [Q_KEY_CODE_8] = 0x3e,
296 [Q_KEY_CODE_9] = 0x46,
297 [Q_KEY_CODE_GRAVE_ACCENT] = 0x0e,
298 [Q_KEY_CODE_MINUS] = 0x4e,
299 [Q_KEY_CODE_EQUAL] = 0x55,
300 [Q_KEY_CODE_BACKSLASH] = 0x5d,
301 [Q_KEY_CODE_BACKSPACE] = 0x66,
302 [Q_KEY_CODE_SPC] = 0x29,
303 [Q_KEY_CODE_TAB] = 0x0d,
304 [Q_KEY_CODE_CAPS_LOCK] = 0x58,
305 [Q_KEY_CODE_SHIFT] = 0x12,
306 [Q_KEY_CODE_CTRL] = 0x14,
307 [Q_KEY_CODE_META_L] = 0xe01f,
308 [Q_KEY_CODE_ALT] = 0x11,
309 [Q_KEY_CODE_SHIFT_R] = 0x59,
310 [Q_KEY_CODE_CTRL_R] = 0xe014,
311 [Q_KEY_CODE_META_R] = 0xe027,
312 [Q_KEY_CODE_ALT_R] = 0xe011,
313 [Q_KEY_CODE_MENU] = 0xe02f,
314 [Q_KEY_CODE_RET] = 0x5a,
315 [Q_KEY_CODE_ESC] = 0x76,
316 [Q_KEY_CODE_F1] = 0x05,
317 [Q_KEY_CODE_F2] = 0x06,
318 [Q_KEY_CODE_F3] = 0x04,
319 [Q_KEY_CODE_F4] = 0x0c,
320 [Q_KEY_CODE_F5] = 0x03,
321 [Q_KEY_CODE_F6] = 0x0b,
322 [Q_KEY_CODE_F7] = 0x83,
323 [Q_KEY_CODE_F8] = 0x0a,
324 [Q_KEY_CODE_F9] = 0x01,
325 [Q_KEY_CODE_F10] = 0x09,
326 [Q_KEY_CODE_F11] = 0x78,
327 [Q_KEY_CODE_F12] = 0x07,
328 /* special handling for Q_KEY_CODE_PRINT */
329 [Q_KEY_CODE_SCROLL_LOCK] = 0x7e,
330 /* special handling for Q_KEY_CODE_PAUSE */
331 [Q_KEY_CODE_BRACKET_LEFT] = 0x54,
332 [Q_KEY_CODE_INSERT] = 0xe070,
333 [Q_KEY_CODE_HOME] = 0xe06c,
334 [Q_KEY_CODE_PGUP] = 0xe07d,
335 [Q_KEY_CODE_DELETE] = 0xe071,
336 [Q_KEY_CODE_END] = 0xe069,
337 [Q_KEY_CODE_PGDN] = 0xe07a,
338 [Q_KEY_CODE_UP] = 0xe075,
339 [Q_KEY_CODE_LEFT] = 0xe06b,
340 [Q_KEY_CODE_DOWN] = 0xe072,
341 [Q_KEY_CODE_RIGHT] = 0xe074,
342 [Q_KEY_CODE_NUM_LOCK] = 0x77,
343 [Q_KEY_CODE_KP_DIVIDE] = 0xe04a,
344 [Q_KEY_CODE_KP_MULTIPLY] = 0x7c,
345 [Q_KEY_CODE_KP_SUBTRACT] = 0x7b,
346 [Q_KEY_CODE_KP_ADD] = 0x79,
347 [Q_KEY_CODE_KP_ENTER] = 0xe05a,
348 [Q_KEY_CODE_KP_DECIMAL] = 0x71,
349 [Q_KEY_CODE_KP_0] = 0x70,
350 [Q_KEY_CODE_KP_1] = 0x69,
351 [Q_KEY_CODE_KP_2] = 0x72,
352 [Q_KEY_CODE_KP_3] = 0x7a,
353 [Q_KEY_CODE_KP_4] = 0x6b,
354 [Q_KEY_CODE_KP_5] = 0x73,
355 [Q_KEY_CODE_KP_6] = 0x74,
356 [Q_KEY_CODE_KP_7] = 0x6c,
357 [Q_KEY_CODE_KP_8] = 0x75,
358 [Q_KEY_CODE_KP_9] = 0x7d,
359 [Q_KEY_CODE_BRACKET_RIGHT] = 0x5b,
360 [Q_KEY_CODE_SEMICOLON] = 0x4c,
361 [Q_KEY_CODE_APOSTROPHE] = 0x52,
362 [Q_KEY_CODE_COMMA] = 0x41,
363 [Q_KEY_CODE_DOT] = 0x49,
364 [Q_KEY_CODE_SLASH] = 0x4a,
367 [Q_KEY_CODE_POWER] = 0x0e37,
368 [Q_KEY_CODE_SLEEP] = 0x0e3f,
369 [Q_KEY_CODE_WAKE] = 0x0e5e,
371 [Q_KEY_CODE_AUDIONEXT] = 0xe04d,
372 [Q_KEY_CODE_AUDIOPREV] = 0xe015,
373 [Q_KEY_CODE_AUDIOSTOP] = 0xe03b,
374 [Q_KEY_CODE_AUDIOPLAY] = 0xe034,
375 [Q_KEY_CODE_AUDIOMUTE] = 0xe023,
376 [Q_KEY_CODE_VOLUMEUP] = 0xe032,
377 [Q_KEY_CODE_VOLUMEDOWN] = 0xe021,
378 [Q_KEY_CODE_MEDIASELECT] = 0xe050,
379 [Q_KEY_CODE_MAIL] = 0xe048,
380 [Q_KEY_CODE_CALCULATOR] = 0xe02b,
381 [Q_KEY_CODE_COMPUTER] = 0xe040,
382 [Q_KEY_CODE_AC_SEARCH] = 0xe010,
383 [Q_KEY_CODE_AC_HOME] = 0xe03a,
384 [Q_KEY_CODE_AC_BACK] = 0xe038,
385 [Q_KEY_CODE_AC_FORWARD] = 0xe030,
386 [Q_KEY_CODE_AC_STOP] = 0xe028,
387 [Q_KEY_CODE_AC_REFRESH] = 0xe020,
388 [Q_KEY_CODE_AC_BOOKMARKS] = 0xe018,
391 [Q_KEY_CODE_ALTGR] = 0x08,
392 [Q_KEY_CODE_ALTGR_R] = 0xe008,
393 [Q_KEY_CODE_ASTERISK] = 0x7c,
394 [Q_KEY_CODE_LESS] = 0x61,
395 [Q_KEY_CODE_SYSRQ] = 0x7f,
396 [Q_KEY_CODE_RO] = 0x51,
397 [Q_KEY_CODE_KP_COMMA] = 0x6d,
400 static const uint16_t qcode_to_keycode_set3[Q_KEY_CODE__MAX] = {
401 [0 ... Q_KEY_CODE__MAX - 1] = 0,
403 [Q_KEY_CODE_A] = 0x1c,
404 [Q_KEY_CODE_B] = 0x32,
405 [Q_KEY_CODE_C] = 0x21,
406 [Q_KEY_CODE_D] = 0x23,
407 [Q_KEY_CODE_E] = 0x24,
408 [Q_KEY_CODE_F] = 0x2b,
409 [Q_KEY_CODE_G] = 0x34,
410 [Q_KEY_CODE_H] = 0x33,
411 [Q_KEY_CODE_I] = 0x43,
412 [Q_KEY_CODE_J] = 0x3b,
413 [Q_KEY_CODE_K] = 0x42,
414 [Q_KEY_CODE_L] = 0x4b,
415 [Q_KEY_CODE_M] = 0x3a,
416 [Q_KEY_CODE_N] = 0x31,
417 [Q_KEY_CODE_O] = 0x44,
418 [Q_KEY_CODE_P] = 0x4d,
419 [Q_KEY_CODE_Q] = 0x15,
420 [Q_KEY_CODE_R] = 0x2d,
421 [Q_KEY_CODE_S] = 0x1b,
422 [Q_KEY_CODE_T] = 0x2c,
423 [Q_KEY_CODE_U] = 0x3c,
424 [Q_KEY_CODE_V] = 0x2a,
425 [Q_KEY_CODE_W] = 0x1d,
426 [Q_KEY_CODE_X] = 0x22,
427 [Q_KEY_CODE_Y] = 0x35,
428 [Q_KEY_CODE_Z] = 0x1a,
429 [Q_KEY_CODE_0] = 0x45,
430 [Q_KEY_CODE_1] = 0x16,
431 [Q_KEY_CODE_2] = 0x1e,
432 [Q_KEY_CODE_3] = 0x26,
433 [Q_KEY_CODE_4] = 0x25,
434 [Q_KEY_CODE_5] = 0x2e,
435 [Q_KEY_CODE_6] = 0x36,
436 [Q_KEY_CODE_7] = 0x3d,
437 [Q_KEY_CODE_8] = 0x3e,
438 [Q_KEY_CODE_9] = 0x46,
439 [Q_KEY_CODE_GRAVE_ACCENT] = 0x0e,
440 [Q_KEY_CODE_MINUS] = 0x4e,
441 [Q_KEY_CODE_EQUAL] = 0x55,
442 [Q_KEY_CODE_BACKSLASH] = 0x5c,
443 [Q_KEY_CODE_BACKSPACE] = 0x66,
444 [Q_KEY_CODE_SPC] = 0x29,
445 [Q_KEY_CODE_TAB] = 0x0d,
446 [Q_KEY_CODE_CAPS_LOCK] = 0x14,
447 [Q_KEY_CODE_SHIFT] = 0x12,
448 [Q_KEY_CODE_CTRL] = 0x11,
449 [Q_KEY_CODE_META_L] = 0x8b,
450 [Q_KEY_CODE_ALT] = 0x19,
451 [Q_KEY_CODE_SHIFT_R] = 0x59,
452 [Q_KEY_CODE_CTRL_R] = 0x58,
453 [Q_KEY_CODE_META_R] = 0x8c,
454 [Q_KEY_CODE_ALT_R] = 0x39,
455 [Q_KEY_CODE_MENU] = 0x8d,
456 [Q_KEY_CODE_RET] = 0x5a,
457 [Q_KEY_CODE_ESC] = 0x08,
458 [Q_KEY_CODE_F1] = 0x07,
459 [Q_KEY_CODE_F2] = 0x0f,
460 [Q_KEY_CODE_F3] = 0x17,
461 [Q_KEY_CODE_F4] = 0x1f,
462 [Q_KEY_CODE_F5] = 0x27,
463 [Q_KEY_CODE_F6] = 0x2f,
464 [Q_KEY_CODE_F7] = 0x37,
465 [Q_KEY_CODE_F8] = 0x3f,
466 [Q_KEY_CODE_F9] = 0x47,
467 [Q_KEY_CODE_F10] = 0x4f,
468 [Q_KEY_CODE_F11] = 0x56,
469 [Q_KEY_CODE_F12] = 0x5e,
470 [Q_KEY_CODE_PRINT] = 0x57,
471 [Q_KEY_CODE_SCROLL_LOCK] = 0x5f,
472 [Q_KEY_CODE_PAUSE] = 0x62,
473 [Q_KEY_CODE_BRACKET_LEFT] = 0x54,
474 [Q_KEY_CODE_INSERT] = 0x67,
475 [Q_KEY_CODE_HOME] = 0x6e,
476 [Q_KEY_CODE_PGUP] = 0x6f,
477 [Q_KEY_CODE_DELETE] = 0x64,
478 [Q_KEY_CODE_END] = 0x65,
479 [Q_KEY_CODE_PGDN] = 0x6d,
480 [Q_KEY_CODE_UP] = 0x63,
481 [Q_KEY_CODE_LEFT] = 0x61,
482 [Q_KEY_CODE_DOWN] = 0x60,
483 [Q_KEY_CODE_RIGHT] = 0x6a,
484 [Q_KEY_CODE_NUM_LOCK] = 0x76,
485 [Q_KEY_CODE_KP_DIVIDE] = 0x4a,
486 [Q_KEY_CODE_KP_MULTIPLY] = 0x7e,
487 [Q_KEY_CODE_KP_SUBTRACT] = 0x4e,
488 [Q_KEY_CODE_KP_ADD] = 0x7c,
489 [Q_KEY_CODE_KP_ENTER] = 0x79,
490 [Q_KEY_CODE_KP_DECIMAL] = 0x71,
491 [Q_KEY_CODE_KP_0] = 0x70,
492 [Q_KEY_CODE_KP_1] = 0x69,
493 [Q_KEY_CODE_KP_2] = 0x72,
494 [Q_KEY_CODE_KP_3] = 0x7a,
495 [Q_KEY_CODE_KP_4] = 0x6b,
496 [Q_KEY_CODE_KP_5] = 0x73,
497 [Q_KEY_CODE_KP_6] = 0x74,
498 [Q_KEY_CODE_KP_7] = 0x6c,
499 [Q_KEY_CODE_KP_8] = 0x75,
500 [Q_KEY_CODE_KP_9] = 0x7d,
501 [Q_KEY_CODE_BRACKET_RIGHT] = 0x5b,
502 [Q_KEY_CODE_SEMICOLON] = 0x4c,
503 [Q_KEY_CODE_APOSTROPHE] = 0x52,
504 [Q_KEY_CODE_COMMA] = 0x41,
505 [Q_KEY_CODE_DOT] = 0x49,
506 [Q_KEY_CODE_SLASH] = 0x4a,
509 static uint8_t translate_table[256] = {
510 0xff, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58,
511 0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59,
512 0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a,
513 0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b,
514 0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c,
515 0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d,
516 0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e,
517 0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f,
518 0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60,
519 0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61,
520 0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e,
521 0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76,
522 0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b,
523 0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f,
524 0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45,
525 0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54,
526 0x80, 0x81, 0x82, 0x41, 0x54, 0x85, 0x86, 0x87,
527 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
528 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
529 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
530 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
531 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
532 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
533 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
534 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
535 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
536 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
537 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
538 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
539 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
540 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
541 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
544 void ps2_queue(void *opaque, int b)
546 PS2State *s = (PS2State *)opaque;
547 PS2Queue *q = &s->queue;
549 if (q->count >= PS2_QUEUE_SIZE - 1)
551 q->data[q->wptr] = b;
552 if (++q->wptr == PS2_QUEUE_SIZE)
555 s->update_irq(s->update_arg, 1);
558 /* keycode is the untranslated scancode in the current scancode set. */
559 static void ps2_put_keycode(void *opaque, int keycode)
561 PS2KbdState *s = opaque;
563 trace_ps2_put_keycode(opaque, keycode);
564 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
567 if (keycode == 0xf0) {
568 s->need_high_bit = true;
569 } else if (s->need_high_bit) {
570 ps2_queue(&s->common, translate_table[keycode] | 0x80);
571 s->need_high_bit = false;
573 ps2_queue(&s->common, translate_table[keycode]);
576 ps2_queue(&s->common, keycode);
580 static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,
583 PS2KbdState *s = (PS2KbdState *)dev;
584 InputKeyEvent *key = evt->u.key.data;
588 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
589 assert(evt->type == INPUT_EVENT_KIND_KEY);
590 qcode = qemu_input_key_value_to_qcode(key->key);
592 if (s->scancode_set == 1) {
593 if (qcode == Q_KEY_CODE_PAUSE) {
595 ps2_put_keycode(s, 0xe1);
596 ps2_put_keycode(s, 0x1d);
597 ps2_put_keycode(s, 0x45);
598 ps2_put_keycode(s, 0x91);
599 ps2_put_keycode(s, 0x9d);
600 ps2_put_keycode(s, 0xc5);
602 } else if (qcode == Q_KEY_CODE_PRINT) {
604 ps2_put_keycode(s, 0xe0);
605 ps2_put_keycode(s, 0x2a);
606 ps2_put_keycode(s, 0xe0);
607 ps2_put_keycode(s, 0x37);
609 ps2_put_keycode(s, 0xe0);
610 ps2_put_keycode(s, 0xb7);
611 ps2_put_keycode(s, 0xe0);
612 ps2_put_keycode(s, 0xaa);
615 keycode = qcode_to_keycode_set1[qcode];
617 if (keycode & 0xff00) {
618 ps2_put_keycode(s, keycode >> 8);
623 ps2_put_keycode(s, keycode & 0xff);
625 qemu_log_mask(LOG_UNIMP,
626 "ps2: ignoring key with qcode %d\n", qcode);
629 } else if (s->scancode_set == 2) {
630 if (qcode == Q_KEY_CODE_PAUSE) {
632 ps2_put_keycode(s, 0xe1);
633 ps2_put_keycode(s, 0x14);
634 ps2_put_keycode(s, 0x77);
635 ps2_put_keycode(s, 0xe1);
636 ps2_put_keycode(s, 0xf0);
637 ps2_put_keycode(s, 0x14);
638 ps2_put_keycode(s, 0xf0);
639 ps2_put_keycode(s, 0x77);
641 } else if (qcode == Q_KEY_CODE_PRINT) {
643 ps2_put_keycode(s, 0xe0);
644 ps2_put_keycode(s, 0x12);
645 ps2_put_keycode(s, 0xe0);
646 ps2_put_keycode(s, 0x7c);
648 ps2_put_keycode(s, 0xe0);
649 ps2_put_keycode(s, 0xf0);
650 ps2_put_keycode(s, 0x7c);
651 ps2_put_keycode(s, 0xe0);
652 ps2_put_keycode(s, 0xf0);
653 ps2_put_keycode(s, 0x12);
656 keycode = qcode_to_keycode_set2[qcode];
658 if (keycode & 0xff00) {
659 ps2_put_keycode(s, keycode >> 8);
662 ps2_put_keycode(s, 0xf0);
664 ps2_put_keycode(s, keycode & 0xff);
666 qemu_log_mask(LOG_UNIMP,
667 "ps2: ignoring key with qcode %d\n", qcode);
670 } else if (s->scancode_set == 3) {
671 keycode = qcode_to_keycode_set3[qcode];
673 /* FIXME: break code should be configured on a key by key basis */
675 ps2_put_keycode(s, 0xf0);
677 ps2_put_keycode(s, keycode);
679 qemu_log_mask(LOG_UNIMP,
680 "ps2: ignoring key with qcode %d\n", qcode);
685 uint32_t ps2_read_data(void *opaque)
687 PS2State *s = (PS2State *)opaque;
691 trace_ps2_read_data(opaque);
694 /* NOTE: if no data left, we return the last keyboard one
695 (needed for EMM386) */
696 /* XXX: need a timer to do things correctly */
699 index = PS2_QUEUE_SIZE - 1;
700 val = q->data[index];
702 val = q->data[q->rptr];
703 if (++q->rptr == PS2_QUEUE_SIZE)
706 /* reading deasserts IRQ */
707 s->update_irq(s->update_arg, 0);
708 /* reassert IRQs if data left */
709 s->update_irq(s->update_arg, q->count != 0);
714 static void ps2_set_ledstate(PS2KbdState *s, int ledstate)
716 trace_ps2_set_ledstate(s, ledstate);
717 s->ledstate = ledstate;
718 kbd_put_ledstate(ledstate);
721 static void ps2_reset_keyboard(PS2KbdState *s)
723 trace_ps2_reset_keyboard(s);
726 ps2_set_ledstate(s, 0);
729 void ps2_write_keyboard(void *opaque, int val)
731 PS2KbdState *s = (PS2KbdState *)opaque;
733 trace_ps2_write_keyboard(opaque, val);
734 switch(s->common.write_cmd) {
739 ps2_queue(&s->common, KBD_REPLY_ACK);
742 ps2_queue(&s->common, KBD_REPLY_RESEND);
745 ps2_queue(&s->common, KBD_REPLY_ACK);
746 /* We emulate a MF2 AT keyboard here */
747 ps2_queue(&s->common, KBD_REPLY_ID);
749 ps2_queue(&s->common, 0x41);
751 ps2_queue(&s->common, 0x83);
754 ps2_queue(&s->common, KBD_CMD_ECHO);
758 ps2_queue(&s->common, KBD_REPLY_ACK);
760 case KBD_CMD_SCANCODE:
761 case KBD_CMD_SET_LEDS:
762 case KBD_CMD_SET_RATE:
763 s->common.write_cmd = val;
764 ps2_queue(&s->common, KBD_REPLY_ACK);
766 case KBD_CMD_RESET_DISABLE:
767 ps2_reset_keyboard(s);
769 ps2_queue(&s->common, KBD_REPLY_ACK);
771 case KBD_CMD_RESET_ENABLE:
772 ps2_reset_keyboard(s);
774 ps2_queue(&s->common, KBD_REPLY_ACK);
777 ps2_reset_keyboard(s);
778 ps2_queue(&s->common, KBD_REPLY_ACK);
779 ps2_queue(&s->common, KBD_REPLY_POR);
782 ps2_queue(&s->common, KBD_REPLY_RESEND);
786 case KBD_CMD_SCANCODE:
788 ps2_queue(&s->common, KBD_REPLY_ACK);
789 ps2_put_keycode(s, s->scancode_set);
790 } else if (val >= 1 && val <= 3) {
791 s->scancode_set = val;
792 ps2_queue(&s->common, KBD_REPLY_ACK);
794 ps2_queue(&s->common, KBD_REPLY_RESEND);
796 s->common.write_cmd = -1;
798 case KBD_CMD_SET_LEDS:
799 ps2_set_ledstate(s, val);
800 ps2_queue(&s->common, KBD_REPLY_ACK);
801 s->common.write_cmd = -1;
803 case KBD_CMD_SET_RATE:
804 ps2_queue(&s->common, KBD_REPLY_ACK);
805 s->common.write_cmd = -1;
810 /* Set the scancode translation mode.
812 1 = translated scancodes (used by qemu internally). */
814 void ps2_keyboard_set_translation(void *opaque, int mode)
816 PS2KbdState *s = (PS2KbdState *)opaque;
817 trace_ps2_keyboard_set_translation(opaque, mode);
821 static void ps2_mouse_send_packet(PS2MouseState *s)
829 /* XXX: increase range to 8 bits ? */
838 b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
839 ps2_queue(&s->common, b);
840 ps2_queue(&s->common, dx1 & 0xff);
841 ps2_queue(&s->common, dy1 & 0xff);
842 /* extra byte for IMPS/2 or IMEX */
843 switch(s->mouse_type) {
851 ps2_queue(&s->common, dz1 & 0xff);
858 b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
859 ps2_queue(&s->common, b);
863 trace_ps2_mouse_send_packet(s, dx1, dy1, dz1, b);
870 static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
873 static const int bmap[INPUT_BUTTON__MAX] = {
874 [INPUT_BUTTON_LEFT] = MOUSE_EVENT_LBUTTON,
875 [INPUT_BUTTON_MIDDLE] = MOUSE_EVENT_MBUTTON,
876 [INPUT_BUTTON_RIGHT] = MOUSE_EVENT_RBUTTON,
878 PS2MouseState *s = (PS2MouseState *)dev;
879 InputMoveEvent *move;
882 /* check if deltas are recorded when disabled */
883 if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
887 case INPUT_EVENT_KIND_REL:
888 move = evt->u.rel.data;
889 if (move->axis == INPUT_AXIS_X) {
890 s->mouse_dx += move->value;
891 } else if (move->axis == INPUT_AXIS_Y) {
892 s->mouse_dy -= move->value;
896 case INPUT_EVENT_KIND_BTN:
897 btn = evt->u.btn.data;
899 s->mouse_buttons |= bmap[btn->button];
900 if (btn->button == INPUT_BUTTON_WHEEL_UP) {
902 } else if (btn->button == INPUT_BUTTON_WHEEL_DOWN) {
906 s->mouse_buttons &= ~bmap[btn->button];
916 static void ps2_mouse_sync(DeviceState *dev)
918 PS2MouseState *s = (PS2MouseState *)dev;
920 if (s->mouse_buttons) {
921 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
923 if (!(s->mouse_status & MOUSE_STATUS_REMOTE)) {
924 while (s->common.queue.count < PS2_QUEUE_SIZE - 4) {
925 /* if not remote, send event. Multiple events are sent if
927 ps2_mouse_send_packet(s);
928 if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
934 void ps2_mouse_fake_event(void *opaque)
936 PS2MouseState *s = opaque;
937 trace_ps2_mouse_fake_event(opaque);
939 ps2_mouse_sync(opaque);
942 void ps2_write_mouse(void *opaque, int val)
944 PS2MouseState *s = (PS2MouseState *)opaque;
946 trace_ps2_write_mouse(opaque, val);
948 printf("kbd: write mouse 0x%02x\n", val);
950 switch(s->common.write_cmd) {
955 if (val == AUX_RESET_WRAP) {
957 ps2_queue(&s->common, AUX_ACK);
959 } else if (val != AUX_RESET) {
960 ps2_queue(&s->common, val);
965 case AUX_SET_SCALE11:
966 s->mouse_status &= ~MOUSE_STATUS_SCALE21;
967 ps2_queue(&s->common, AUX_ACK);
969 case AUX_SET_SCALE21:
970 s->mouse_status |= MOUSE_STATUS_SCALE21;
971 ps2_queue(&s->common, AUX_ACK);
974 s->mouse_status &= ~MOUSE_STATUS_REMOTE;
975 ps2_queue(&s->common, AUX_ACK);
979 ps2_queue(&s->common, AUX_ACK);
982 s->mouse_status |= MOUSE_STATUS_REMOTE;
983 ps2_queue(&s->common, AUX_ACK);
986 ps2_queue(&s->common, AUX_ACK);
987 ps2_queue(&s->common, s->mouse_type);
991 s->common.write_cmd = val;
992 ps2_queue(&s->common, AUX_ACK);
995 ps2_queue(&s->common, AUX_ACK);
996 ps2_queue(&s->common, s->mouse_status);
997 ps2_queue(&s->common, s->mouse_resolution);
998 ps2_queue(&s->common, s->mouse_sample_rate);
1001 ps2_queue(&s->common, AUX_ACK);
1002 ps2_mouse_send_packet(s);
1004 case AUX_ENABLE_DEV:
1005 s->mouse_status |= MOUSE_STATUS_ENABLED;
1006 ps2_queue(&s->common, AUX_ACK);
1008 case AUX_DISABLE_DEV:
1009 s->mouse_status &= ~MOUSE_STATUS_ENABLED;
1010 ps2_queue(&s->common, AUX_ACK);
1012 case AUX_SET_DEFAULT:
1013 s->mouse_sample_rate = 100;
1014 s->mouse_resolution = 2;
1015 s->mouse_status = 0;
1016 ps2_queue(&s->common, AUX_ACK);
1019 s->mouse_sample_rate = 100;
1020 s->mouse_resolution = 2;
1021 s->mouse_status = 0;
1023 ps2_queue(&s->common, AUX_ACK);
1024 ps2_queue(&s->common, 0xaa);
1025 ps2_queue(&s->common, s->mouse_type);
1031 case AUX_SET_SAMPLE:
1032 s->mouse_sample_rate = val;
1033 /* detect IMPS/2 or IMEX */
1034 switch(s->mouse_detect_state) {
1038 s->mouse_detect_state = 1;
1042 s->mouse_detect_state = 2;
1043 else if (val == 200)
1044 s->mouse_detect_state = 3;
1046 s->mouse_detect_state = 0;
1050 s->mouse_type = 3; /* IMPS/2 */
1051 s->mouse_detect_state = 0;
1055 s->mouse_type = 4; /* IMEX */
1056 s->mouse_detect_state = 0;
1059 ps2_queue(&s->common, AUX_ACK);
1060 s->common.write_cmd = -1;
1063 s->mouse_resolution = val;
1064 ps2_queue(&s->common, AUX_ACK);
1065 s->common.write_cmd = -1;
1070 static void ps2_common_reset(PS2State *s)
1078 s->update_irq(s->update_arg, 0);
1081 static void ps2_common_post_load(PS2State *s)
1083 PS2Queue *q = &s->queue;
1086 int tmp_data[PS2_QUEUE_SIZE];
1088 /* set the useful data buffer queue size, < PS2_QUEUE_SIZE */
1089 size = q->count > PS2_QUEUE_SIZE ? 0 : q->count;
1091 /* move the queue elements to the start of data array */
1093 for (i = 0; i < size; i++) {
1094 /* move the queue elements to the temporary buffer */
1095 tmp_data[i] = q->data[q->rptr];
1096 if (++q->rptr == 256) {
1100 memcpy(q->data, tmp_data, size);
1102 /* reset rptr/wptr/count */
1106 s->update_irq(s->update_arg, q->count != 0);
1109 static void ps2_kbd_reset(void *opaque)
1111 PS2KbdState *s = (PS2KbdState *) opaque;
1113 trace_ps2_kbd_reset(opaque);
1114 ps2_common_reset(&s->common);
1115 s->scan_enabled = 0;
1117 s->scancode_set = 2;
1120 static void ps2_mouse_reset(void *opaque)
1122 PS2MouseState *s = (PS2MouseState *) opaque;
1124 trace_ps2_mouse_reset(opaque);
1125 ps2_common_reset(&s->common);
1126 s->mouse_status = 0;
1127 s->mouse_resolution = 0;
1128 s->mouse_sample_rate = 0;
1131 s->mouse_detect_state = 0;
1135 s->mouse_buttons = 0;
1138 static const VMStateDescription vmstate_ps2_common = {
1139 .name = "PS2 Common State",
1141 .minimum_version_id = 2,
1142 .fields = (VMStateField[]) {
1143 VMSTATE_INT32(write_cmd, PS2State),
1144 VMSTATE_INT32(queue.rptr, PS2State),
1145 VMSTATE_INT32(queue.wptr, PS2State),
1146 VMSTATE_INT32(queue.count, PS2State),
1147 VMSTATE_BUFFER(queue.data, PS2State),
1148 VMSTATE_END_OF_LIST()
1152 static bool ps2_keyboard_ledstate_needed(void *opaque)
1154 PS2KbdState *s = opaque;
1156 return s->ledstate != 0; /* 0 is default state */
1159 static int ps2_kbd_ledstate_post_load(void *opaque, int version_id)
1161 PS2KbdState *s = opaque;
1163 kbd_put_ledstate(s->ledstate);
1167 static const VMStateDescription vmstate_ps2_keyboard_ledstate = {
1168 .name = "ps2kbd/ledstate",
1170 .minimum_version_id = 2,
1171 .post_load = ps2_kbd_ledstate_post_load,
1172 .needed = ps2_keyboard_ledstate_needed,
1173 .fields = (VMStateField[]) {
1174 VMSTATE_INT32(ledstate, PS2KbdState),
1175 VMSTATE_END_OF_LIST()
1179 static bool ps2_keyboard_need_high_bit_needed(void *opaque)
1181 PS2KbdState *s = opaque;
1182 return s->need_high_bit != 0; /* 0 is the usual state */
1185 static const VMStateDescription vmstate_ps2_keyboard_need_high_bit = {
1186 .name = "ps2kbd/need_high_bit",
1188 .minimum_version_id = 1,
1189 .needed = ps2_keyboard_need_high_bit_needed,
1190 .fields = (VMStateField[]) {
1191 VMSTATE_BOOL(need_high_bit, PS2KbdState),
1192 VMSTATE_END_OF_LIST()
1196 static int ps2_kbd_post_load(void* opaque, int version_id)
1198 PS2KbdState *s = (PS2KbdState*)opaque;
1199 PS2State *ps2 = &s->common;
1201 if (version_id == 2)
1204 ps2_common_post_load(ps2);
1209 static void ps2_kbd_pre_save(void *opaque)
1211 PS2KbdState *s = (PS2KbdState *)opaque;
1212 PS2State *ps2 = &s->common;
1214 ps2_common_post_load(ps2);
1217 static const VMStateDescription vmstate_ps2_keyboard = {
1220 .minimum_version_id = 2,
1221 .post_load = ps2_kbd_post_load,
1222 .pre_save = ps2_kbd_pre_save,
1223 .fields = (VMStateField[]) {
1224 VMSTATE_STRUCT(common, PS2KbdState, 0, vmstate_ps2_common, PS2State),
1225 VMSTATE_INT32(scan_enabled, PS2KbdState),
1226 VMSTATE_INT32(translate, PS2KbdState),
1227 VMSTATE_INT32_V(scancode_set, PS2KbdState,3),
1228 VMSTATE_END_OF_LIST()
1230 .subsections = (const VMStateDescription*[]) {
1231 &vmstate_ps2_keyboard_ledstate,
1232 &vmstate_ps2_keyboard_need_high_bit,
1237 static int ps2_mouse_post_load(void *opaque, int version_id)
1239 PS2MouseState *s = (PS2MouseState *)opaque;
1240 PS2State *ps2 = &s->common;
1242 ps2_common_post_load(ps2);
1247 static void ps2_mouse_pre_save(void *opaque)
1249 PS2MouseState *s = (PS2MouseState *)opaque;
1250 PS2State *ps2 = &s->common;
1252 ps2_common_post_load(ps2);
1255 static const VMStateDescription vmstate_ps2_mouse = {
1258 .minimum_version_id = 2,
1259 .post_load = ps2_mouse_post_load,
1260 .pre_save = ps2_mouse_pre_save,
1261 .fields = (VMStateField[]) {
1262 VMSTATE_STRUCT(common, PS2MouseState, 0, vmstate_ps2_common, PS2State),
1263 VMSTATE_UINT8(mouse_status, PS2MouseState),
1264 VMSTATE_UINT8(mouse_resolution, PS2MouseState),
1265 VMSTATE_UINT8(mouse_sample_rate, PS2MouseState),
1266 VMSTATE_UINT8(mouse_wrap, PS2MouseState),
1267 VMSTATE_UINT8(mouse_type, PS2MouseState),
1268 VMSTATE_UINT8(mouse_detect_state, PS2MouseState),
1269 VMSTATE_INT32(mouse_dx, PS2MouseState),
1270 VMSTATE_INT32(mouse_dy, PS2MouseState),
1271 VMSTATE_INT32(mouse_dz, PS2MouseState),
1272 VMSTATE_UINT8(mouse_buttons, PS2MouseState),
1273 VMSTATE_END_OF_LIST()
1277 static QemuInputHandler ps2_keyboard_handler = {
1278 .name = "QEMU PS/2 Keyboard",
1279 .mask = INPUT_EVENT_MASK_KEY,
1280 .event = ps2_keyboard_event,
1283 void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
1285 PS2KbdState *s = (PS2KbdState *)g_malloc0(sizeof(PS2KbdState));
1287 trace_ps2_kbd_init(s);
1288 s->common.update_irq = update_irq;
1289 s->common.update_arg = update_arg;
1290 s->scancode_set = 2;
1291 vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s);
1292 qemu_input_handler_register((DeviceState *)s,
1293 &ps2_keyboard_handler);
1294 qemu_register_reset(ps2_kbd_reset, s);
1298 static QemuInputHandler ps2_mouse_handler = {
1299 .name = "QEMU PS/2 Mouse",
1300 .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
1301 .event = ps2_mouse_event,
1302 .sync = ps2_mouse_sync,
1305 void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
1307 PS2MouseState *s = (PS2MouseState *)g_malloc0(sizeof(PS2MouseState));
1309 trace_ps2_mouse_init(s);
1310 s->common.update_irq = update_irq;
1311 s->common.update_arg = update_arg;
1312 vmstate_register(NULL, 0, &vmstate_ps2_mouse, s);
1313 qemu_input_handler_register((DeviceState *)s,
1314 &ps2_mouse_handler);
1315 qemu_register_reset(ps2_mouse_reset, s);