ps2: fix scancodes sent for Alt-Print key combination (aka SysRq)
[qemu/ar7.git] / hw / input / ps2.c
blob1e6f6ae9b6450fa00dfe75e26519cdf2229897f6
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.
24 #include "qemu/osdep.h"
25 #include "qemu/log.h"
26 #include "hw/hw.h"
27 #include "hw/input/ps2.h"
28 #include "ui/console.h"
29 #include "ui/input.h"
30 #include "sysemu/sysemu.h"
32 #include "trace.h"
34 /* debug PC keyboard */
35 //#define DEBUG_KBD
37 /* debug PC keyboard : only mouse */
38 //#define DEBUG_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 */
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. */
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 */
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)
89 typedef struct {
90 /* Keep the data array 256 bytes long, which compatibility
91 with older qemu versions. */
92 uint8_t data[256];
93 int rptr, wptr, count;
94 } PS2Queue;
96 struct PS2State {
97 PS2Queue queue;
98 int32_t write_cmd;
99 void (*update_irq)(void *, int);
100 void *update_arg;
103 typedef struct {
104 PS2State common;
105 int scan_enabled;
106 int translate;
107 int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */
108 int ledstate;
109 bool need_high_bit;
110 unsigned int modifiers; /* bitmask of MOD_* constants above */
111 } PS2KbdState;
113 typedef 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;
127 /* Table to convert from QEMU codes to scancodes. */
128 static const uint16_t qcode_to_keycode_set1[Q_KEY_CODE__MAX] = {
129 [0 ... Q_KEY_CODE__MAX - 1] = 0,
131 [Q_KEY_CODE_A] = 0x1e,
132 [Q_KEY_CODE_B] = 0x30,
133 [Q_KEY_CODE_C] = 0x2e,
134 [Q_KEY_CODE_D] = 0x20,
135 [Q_KEY_CODE_E] = 0x12,
136 [Q_KEY_CODE_F] = 0x21,
137 [Q_KEY_CODE_G] = 0x22,
138 [Q_KEY_CODE_H] = 0x23,
139 [Q_KEY_CODE_I] = 0x17,
140 [Q_KEY_CODE_J] = 0x24,
141 [Q_KEY_CODE_K] = 0x25,
142 [Q_KEY_CODE_L] = 0x26,
143 [Q_KEY_CODE_M] = 0x32,
144 [Q_KEY_CODE_N] = 0x31,
145 [Q_KEY_CODE_O] = 0x18,
146 [Q_KEY_CODE_P] = 0x19,
147 [Q_KEY_CODE_Q] = 0x10,
148 [Q_KEY_CODE_R] = 0x13,
149 [Q_KEY_CODE_S] = 0x1f,
150 [Q_KEY_CODE_T] = 0x14,
151 [Q_KEY_CODE_U] = 0x16,
152 [Q_KEY_CODE_V] = 0x2f,
153 [Q_KEY_CODE_W] = 0x11,
154 [Q_KEY_CODE_X] = 0x2d,
155 [Q_KEY_CODE_Y] = 0x15,
156 [Q_KEY_CODE_Z] = 0x2c,
157 [Q_KEY_CODE_0] = 0x0b,
158 [Q_KEY_CODE_1] = 0x02,
159 [Q_KEY_CODE_2] = 0x03,
160 [Q_KEY_CODE_3] = 0x04,
161 [Q_KEY_CODE_4] = 0x05,
162 [Q_KEY_CODE_5] = 0x06,
163 [Q_KEY_CODE_6] = 0x07,
164 [Q_KEY_CODE_7] = 0x08,
165 [Q_KEY_CODE_8] = 0x09,
166 [Q_KEY_CODE_9] = 0x0a,
167 [Q_KEY_CODE_GRAVE_ACCENT] = 0x29,
168 [Q_KEY_CODE_MINUS] = 0x0c,
169 [Q_KEY_CODE_EQUAL] = 0x0d,
170 [Q_KEY_CODE_BACKSLASH] = 0x2b,
171 [Q_KEY_CODE_BACKSPACE] = 0x0e,
172 [Q_KEY_CODE_SPC] = 0x39,
173 [Q_KEY_CODE_TAB] = 0x0f,
174 [Q_KEY_CODE_CAPS_LOCK] = 0x3a,
175 [Q_KEY_CODE_SHIFT] = 0x2a,
176 [Q_KEY_CODE_CTRL] = 0x1d,
177 [Q_KEY_CODE_META_L] = 0xe05b,
178 [Q_KEY_CODE_ALT] = 0x38,
179 [Q_KEY_CODE_SHIFT_R] = 0x36,
180 [Q_KEY_CODE_CTRL_R] = 0xe01d,
181 [Q_KEY_CODE_META_R] = 0xe05c,
182 [Q_KEY_CODE_ALT_R] = 0xe038,
183 [Q_KEY_CODE_MENU] = 0xe05d,
184 [Q_KEY_CODE_RET] = 0x1c,
185 [Q_KEY_CODE_ESC] = 0x01,
186 [Q_KEY_CODE_F1] = 0x3b,
187 [Q_KEY_CODE_F2] = 0x3c,
188 [Q_KEY_CODE_F3] = 0x3d,
189 [Q_KEY_CODE_F4] = 0x3e,
190 [Q_KEY_CODE_F5] = 0x3f,
191 [Q_KEY_CODE_F6] = 0x40,
192 [Q_KEY_CODE_F7] = 0x41,
193 [Q_KEY_CODE_F8] = 0x42,
194 [Q_KEY_CODE_F9] = 0x43,
195 [Q_KEY_CODE_F10] = 0x44,
196 [Q_KEY_CODE_F11] = 0x57,
197 [Q_KEY_CODE_F12] = 0x58,
198 /* special handling for Q_KEY_CODE_PRINT */
199 [Q_KEY_CODE_SCROLL_LOCK] = 0x46,
200 /* special handling for Q_KEY_CODE_PAUSE */
201 [Q_KEY_CODE_BRACKET_LEFT] = 0x1a,
202 [Q_KEY_CODE_INSERT] = 0xe052,
203 [Q_KEY_CODE_HOME] = 0xe047,
204 [Q_KEY_CODE_PGUP] = 0xe049,
205 [Q_KEY_CODE_DELETE] = 0xe053,
206 [Q_KEY_CODE_END] = 0xe04f,
207 [Q_KEY_CODE_PGDN] = 0xe051,
208 [Q_KEY_CODE_UP] = 0xe048,
209 [Q_KEY_CODE_LEFT] = 0xe04b,
210 [Q_KEY_CODE_DOWN] = 0xe050,
211 [Q_KEY_CODE_RIGHT] = 0xe04d,
212 [Q_KEY_CODE_NUM_LOCK] = 0x45,
213 [Q_KEY_CODE_KP_DIVIDE] = 0xe035,
214 [Q_KEY_CODE_KP_MULTIPLY] = 0x37,
215 [Q_KEY_CODE_KP_SUBTRACT] = 0x4a,
216 [Q_KEY_CODE_KP_ADD] = 0x4e,
217 [Q_KEY_CODE_KP_ENTER] = 0xe01c,
218 [Q_KEY_CODE_KP_DECIMAL] = 0x53,
219 [Q_KEY_CODE_KP_0] = 0x52,
220 [Q_KEY_CODE_KP_1] = 0x4f,
221 [Q_KEY_CODE_KP_2] = 0x50,
222 [Q_KEY_CODE_KP_3] = 0x51,
223 [Q_KEY_CODE_KP_4] = 0x4b,
224 [Q_KEY_CODE_KP_5] = 0x4c,
225 [Q_KEY_CODE_KP_6] = 0x4d,
226 [Q_KEY_CODE_KP_7] = 0x47,
227 [Q_KEY_CODE_KP_8] = 0x48,
228 [Q_KEY_CODE_KP_9] = 0x49,
229 [Q_KEY_CODE_BRACKET_RIGHT] = 0x1b,
230 [Q_KEY_CODE_SEMICOLON] = 0x27,
231 [Q_KEY_CODE_APOSTROPHE] = 0x28,
232 [Q_KEY_CODE_COMMA] = 0x33,
233 [Q_KEY_CODE_DOT] = 0x34,
234 [Q_KEY_CODE_SLASH] = 0x35,
236 [Q_KEY_CODE_POWER] = 0x0e5e,
237 [Q_KEY_CODE_SLEEP] = 0x0e5f,
238 [Q_KEY_CODE_WAKE] = 0x0e63,
240 [Q_KEY_CODE_AUDIONEXT] = 0xe019,
241 [Q_KEY_CODE_AUDIOPREV] = 0xe010,
242 [Q_KEY_CODE_AUDIOSTOP] = 0xe024,
243 [Q_KEY_CODE_AUDIOPLAY] = 0xe022,
244 [Q_KEY_CODE_AUDIOMUTE] = 0xe020,
245 [Q_KEY_CODE_VOLUMEUP] = 0xe030,
246 [Q_KEY_CODE_VOLUMEDOWN] = 0xe02e,
247 [Q_KEY_CODE_MEDIASELECT] = 0xe06d,
248 [Q_KEY_CODE_MAIL] = 0xe06c,
249 [Q_KEY_CODE_CALCULATOR] = 0xe021,
250 [Q_KEY_CODE_COMPUTER] = 0xe06b,
251 [Q_KEY_CODE_FIND] = 0xe065,
252 [Q_KEY_CODE_AC_HOME] = 0xe032,
253 [Q_KEY_CODE_AC_BACK] = 0xe06a,
254 [Q_KEY_CODE_AC_FORWARD] = 0xe069,
255 [Q_KEY_CODE_STOP] = 0xe068,
256 [Q_KEY_CODE_AC_REFRESH] = 0xe067,
257 [Q_KEY_CODE_AC_BOOKMARKS] = 0xe066,
259 [Q_KEY_CODE_ASTERISK] = 0x37,
260 [Q_KEY_CODE_LESS] = 0x56,
261 [Q_KEY_CODE_RO] = 0x73,
262 [Q_KEY_CODE_HIRAGANA] = 0x70,
263 [Q_KEY_CODE_HENKAN] = 0x79,
264 [Q_KEY_CODE_YEN] = 0x7d,
265 [Q_KEY_CODE_KP_COMMA] = 0x7e,
268 static const uint16_t qcode_to_keycode_set2[Q_KEY_CODE__MAX] = {
269 [0 ... Q_KEY_CODE__MAX - 1] = 0,
271 [Q_KEY_CODE_A] = 0x1c,
272 [Q_KEY_CODE_B] = 0x32,
273 [Q_KEY_CODE_C] = 0x21,
274 [Q_KEY_CODE_D] = 0x23,
275 [Q_KEY_CODE_E] = 0x24,
276 [Q_KEY_CODE_F] = 0x2b,
277 [Q_KEY_CODE_G] = 0x34,
278 [Q_KEY_CODE_H] = 0x33,
279 [Q_KEY_CODE_I] = 0x43,
280 [Q_KEY_CODE_J] = 0x3b,
281 [Q_KEY_CODE_K] = 0x42,
282 [Q_KEY_CODE_L] = 0x4b,
283 [Q_KEY_CODE_M] = 0x3a,
284 [Q_KEY_CODE_N] = 0x31,
285 [Q_KEY_CODE_O] = 0x44,
286 [Q_KEY_CODE_P] = 0x4d,
287 [Q_KEY_CODE_Q] = 0x15,
288 [Q_KEY_CODE_R] = 0x2d,
289 [Q_KEY_CODE_S] = 0x1b,
290 [Q_KEY_CODE_T] = 0x2c,
291 [Q_KEY_CODE_U] = 0x3c,
292 [Q_KEY_CODE_V] = 0x2a,
293 [Q_KEY_CODE_W] = 0x1d,
294 [Q_KEY_CODE_X] = 0x22,
295 [Q_KEY_CODE_Y] = 0x35,
296 [Q_KEY_CODE_Z] = 0x1a,
297 [Q_KEY_CODE_0] = 0x45,
298 [Q_KEY_CODE_1] = 0x16,
299 [Q_KEY_CODE_2] = 0x1e,
300 [Q_KEY_CODE_3] = 0x26,
301 [Q_KEY_CODE_4] = 0x25,
302 [Q_KEY_CODE_5] = 0x2e,
303 [Q_KEY_CODE_6] = 0x36,
304 [Q_KEY_CODE_7] = 0x3d,
305 [Q_KEY_CODE_8] = 0x3e,
306 [Q_KEY_CODE_9] = 0x46,
307 [Q_KEY_CODE_GRAVE_ACCENT] = 0x0e,
308 [Q_KEY_CODE_MINUS] = 0x4e,
309 [Q_KEY_CODE_EQUAL] = 0x55,
310 [Q_KEY_CODE_BACKSLASH] = 0x5d,
311 [Q_KEY_CODE_BACKSPACE] = 0x66,
312 [Q_KEY_CODE_SPC] = 0x29,
313 [Q_KEY_CODE_TAB] = 0x0d,
314 [Q_KEY_CODE_CAPS_LOCK] = 0x58,
315 [Q_KEY_CODE_SHIFT] = 0x12,
316 [Q_KEY_CODE_CTRL] = 0x14,
317 [Q_KEY_CODE_META_L] = 0xe01f,
318 [Q_KEY_CODE_ALT] = 0x11,
319 [Q_KEY_CODE_SHIFT_R] = 0x59,
320 [Q_KEY_CODE_CTRL_R] = 0xe014,
321 [Q_KEY_CODE_META_R] = 0xe027,
322 [Q_KEY_CODE_ALT_R] = 0xe011,
323 [Q_KEY_CODE_MENU] = 0xe02f,
324 [Q_KEY_CODE_RET] = 0x5a,
325 [Q_KEY_CODE_ESC] = 0x76,
326 [Q_KEY_CODE_F1] = 0x05,
327 [Q_KEY_CODE_F2] = 0x06,
328 [Q_KEY_CODE_F3] = 0x04,
329 [Q_KEY_CODE_F4] = 0x0c,
330 [Q_KEY_CODE_F5] = 0x03,
331 [Q_KEY_CODE_F6] = 0x0b,
332 [Q_KEY_CODE_F7] = 0x83,
333 [Q_KEY_CODE_F8] = 0x0a,
334 [Q_KEY_CODE_F9] = 0x01,
335 [Q_KEY_CODE_F10] = 0x09,
336 [Q_KEY_CODE_F11] = 0x78,
337 [Q_KEY_CODE_F12] = 0x07,
338 /* special handling for Q_KEY_CODE_PRINT */
339 [Q_KEY_CODE_SCROLL_LOCK] = 0x7e,
340 /* special handling for Q_KEY_CODE_PAUSE */
341 [Q_KEY_CODE_BRACKET_LEFT] = 0x54,
342 [Q_KEY_CODE_INSERT] = 0xe070,
343 [Q_KEY_CODE_HOME] = 0xe06c,
344 [Q_KEY_CODE_PGUP] = 0xe07d,
345 [Q_KEY_CODE_DELETE] = 0xe071,
346 [Q_KEY_CODE_END] = 0xe069,
347 [Q_KEY_CODE_PGDN] = 0xe07a,
348 [Q_KEY_CODE_UP] = 0xe075,
349 [Q_KEY_CODE_LEFT] = 0xe06b,
350 [Q_KEY_CODE_DOWN] = 0xe072,
351 [Q_KEY_CODE_RIGHT] = 0xe074,
352 [Q_KEY_CODE_NUM_LOCK] = 0x77,
353 [Q_KEY_CODE_KP_DIVIDE] = 0xe04a,
354 [Q_KEY_CODE_KP_MULTIPLY] = 0x7c,
355 [Q_KEY_CODE_KP_SUBTRACT] = 0x7b,
356 [Q_KEY_CODE_KP_ADD] = 0x79,
357 [Q_KEY_CODE_KP_ENTER] = 0xe05a,
358 [Q_KEY_CODE_KP_DECIMAL] = 0x71,
359 [Q_KEY_CODE_KP_0] = 0x70,
360 [Q_KEY_CODE_KP_1] = 0x69,
361 [Q_KEY_CODE_KP_2] = 0x72,
362 [Q_KEY_CODE_KP_3] = 0x7a,
363 [Q_KEY_CODE_KP_4] = 0x6b,
364 [Q_KEY_CODE_KP_5] = 0x73,
365 [Q_KEY_CODE_KP_6] = 0x74,
366 [Q_KEY_CODE_KP_7] = 0x6c,
367 [Q_KEY_CODE_KP_8] = 0x75,
368 [Q_KEY_CODE_KP_9] = 0x7d,
369 [Q_KEY_CODE_BRACKET_RIGHT] = 0x5b,
370 [Q_KEY_CODE_SEMICOLON] = 0x4c,
371 [Q_KEY_CODE_APOSTROPHE] = 0x52,
372 [Q_KEY_CODE_COMMA] = 0x41,
373 [Q_KEY_CODE_DOT] = 0x49,
374 [Q_KEY_CODE_SLASH] = 0x4a,
376 [Q_KEY_CODE_POWER] = 0x0e37,
377 [Q_KEY_CODE_SLEEP] = 0x0e3f,
378 [Q_KEY_CODE_WAKE] = 0x0e5e,
380 [Q_KEY_CODE_AUDIONEXT] = 0xe04d,
381 [Q_KEY_CODE_AUDIOPREV] = 0xe015,
382 [Q_KEY_CODE_AUDIOSTOP] = 0xe03b,
383 [Q_KEY_CODE_AUDIOPLAY] = 0xe034,
384 [Q_KEY_CODE_AUDIOMUTE] = 0xe023,
385 [Q_KEY_CODE_VOLUMEUP] = 0xe032,
386 [Q_KEY_CODE_VOLUMEDOWN] = 0xe021,
387 [Q_KEY_CODE_MEDIASELECT] = 0xe050,
388 [Q_KEY_CODE_MAIL] = 0xe048,
389 [Q_KEY_CODE_CALCULATOR] = 0xe02b,
390 [Q_KEY_CODE_COMPUTER] = 0xe040,
391 [Q_KEY_CODE_FIND] = 0xe010,
392 [Q_KEY_CODE_AC_HOME] = 0xe03a,
393 [Q_KEY_CODE_AC_BACK] = 0xe038,
394 [Q_KEY_CODE_AC_FORWARD] = 0xe030,
395 [Q_KEY_CODE_STOP] = 0xe028,
396 [Q_KEY_CODE_AC_REFRESH] = 0xe020,
397 [Q_KEY_CODE_AC_BOOKMARKS] = 0xe018,
399 [Q_KEY_CODE_ASTERISK] = 0x7c,
400 [Q_KEY_CODE_LESS] = 0x61,
401 [Q_KEY_CODE_SYSRQ] = 0x7f,
402 [Q_KEY_CODE_RO] = 0x51,
403 [Q_KEY_CODE_HIRAGANA] = 0x13,
404 [Q_KEY_CODE_HENKAN] = 0x64,
405 [Q_KEY_CODE_YEN] = 0x6a,
406 [Q_KEY_CODE_KP_COMMA] = 0x6d,
409 static const uint16_t qcode_to_keycode_set3[Q_KEY_CODE__MAX] = {
410 [0 ... Q_KEY_CODE__MAX - 1] = 0,
412 [Q_KEY_CODE_A] = 0x1c,
413 [Q_KEY_CODE_B] = 0x32,
414 [Q_KEY_CODE_C] = 0x21,
415 [Q_KEY_CODE_D] = 0x23,
416 [Q_KEY_CODE_E] = 0x24,
417 [Q_KEY_CODE_F] = 0x2b,
418 [Q_KEY_CODE_G] = 0x34,
419 [Q_KEY_CODE_H] = 0x33,
420 [Q_KEY_CODE_I] = 0x43,
421 [Q_KEY_CODE_J] = 0x3b,
422 [Q_KEY_CODE_K] = 0x42,
423 [Q_KEY_CODE_L] = 0x4b,
424 [Q_KEY_CODE_M] = 0x3a,
425 [Q_KEY_CODE_N] = 0x31,
426 [Q_KEY_CODE_O] = 0x44,
427 [Q_KEY_CODE_P] = 0x4d,
428 [Q_KEY_CODE_Q] = 0x15,
429 [Q_KEY_CODE_R] = 0x2d,
430 [Q_KEY_CODE_S] = 0x1b,
431 [Q_KEY_CODE_T] = 0x2c,
432 [Q_KEY_CODE_U] = 0x3c,
433 [Q_KEY_CODE_V] = 0x2a,
434 [Q_KEY_CODE_W] = 0x1d,
435 [Q_KEY_CODE_X] = 0x22,
436 [Q_KEY_CODE_Y] = 0x35,
437 [Q_KEY_CODE_Z] = 0x1a,
438 [Q_KEY_CODE_0] = 0x45,
439 [Q_KEY_CODE_1] = 0x16,
440 [Q_KEY_CODE_2] = 0x1e,
441 [Q_KEY_CODE_3] = 0x26,
442 [Q_KEY_CODE_4] = 0x25,
443 [Q_KEY_CODE_5] = 0x2e,
444 [Q_KEY_CODE_6] = 0x36,
445 [Q_KEY_CODE_7] = 0x3d,
446 [Q_KEY_CODE_8] = 0x3e,
447 [Q_KEY_CODE_9] = 0x46,
448 [Q_KEY_CODE_GRAVE_ACCENT] = 0x0e,
449 [Q_KEY_CODE_MINUS] = 0x4e,
450 [Q_KEY_CODE_EQUAL] = 0x55,
451 [Q_KEY_CODE_BACKSLASH] = 0x5c,
452 [Q_KEY_CODE_BACKSPACE] = 0x66,
453 [Q_KEY_CODE_SPC] = 0x29,
454 [Q_KEY_CODE_TAB] = 0x0d,
455 [Q_KEY_CODE_CAPS_LOCK] = 0x14,
456 [Q_KEY_CODE_SHIFT] = 0x12,
457 [Q_KEY_CODE_CTRL] = 0x11,
458 [Q_KEY_CODE_META_L] = 0x8b,
459 [Q_KEY_CODE_ALT] = 0x19,
460 [Q_KEY_CODE_SHIFT_R] = 0x59,
461 [Q_KEY_CODE_CTRL_R] = 0x58,
462 [Q_KEY_CODE_META_R] = 0x8c,
463 [Q_KEY_CODE_ALT_R] = 0x39,
464 [Q_KEY_CODE_MENU] = 0x8d,
465 [Q_KEY_CODE_RET] = 0x5a,
466 [Q_KEY_CODE_ESC] = 0x08,
467 [Q_KEY_CODE_F1] = 0x07,
468 [Q_KEY_CODE_F2] = 0x0f,
469 [Q_KEY_CODE_F3] = 0x17,
470 [Q_KEY_CODE_F4] = 0x1f,
471 [Q_KEY_CODE_F5] = 0x27,
472 [Q_KEY_CODE_F6] = 0x2f,
473 [Q_KEY_CODE_F7] = 0x37,
474 [Q_KEY_CODE_F8] = 0x3f,
475 [Q_KEY_CODE_F9] = 0x47,
476 [Q_KEY_CODE_F10] = 0x4f,
477 [Q_KEY_CODE_F11] = 0x56,
478 [Q_KEY_CODE_F12] = 0x5e,
479 [Q_KEY_CODE_PRINT] = 0x57,
480 [Q_KEY_CODE_SCROLL_LOCK] = 0x5f,
481 [Q_KEY_CODE_PAUSE] = 0x62,
482 [Q_KEY_CODE_BRACKET_LEFT] = 0x54,
483 [Q_KEY_CODE_INSERT] = 0x67,
484 [Q_KEY_CODE_HOME] = 0x6e,
485 [Q_KEY_CODE_PGUP] = 0x6f,
486 [Q_KEY_CODE_DELETE] = 0x64,
487 [Q_KEY_CODE_END] = 0x65,
488 [Q_KEY_CODE_PGDN] = 0x6d,
489 [Q_KEY_CODE_UP] = 0x63,
490 [Q_KEY_CODE_LEFT] = 0x61,
491 [Q_KEY_CODE_DOWN] = 0x60,
492 [Q_KEY_CODE_RIGHT] = 0x6a,
493 [Q_KEY_CODE_NUM_LOCK] = 0x76,
494 [Q_KEY_CODE_KP_DIVIDE] = 0x4a,
495 [Q_KEY_CODE_KP_MULTIPLY] = 0x7e,
496 [Q_KEY_CODE_KP_SUBTRACT] = 0x4e,
497 [Q_KEY_CODE_KP_ADD] = 0x7c,
498 [Q_KEY_CODE_KP_ENTER] = 0x79,
499 [Q_KEY_CODE_KP_DECIMAL] = 0x71,
500 [Q_KEY_CODE_KP_0] = 0x70,
501 [Q_KEY_CODE_KP_1] = 0x69,
502 [Q_KEY_CODE_KP_2] = 0x72,
503 [Q_KEY_CODE_KP_3] = 0x7a,
504 [Q_KEY_CODE_KP_4] = 0x6b,
505 [Q_KEY_CODE_KP_5] = 0x73,
506 [Q_KEY_CODE_KP_6] = 0x74,
507 [Q_KEY_CODE_KP_7] = 0x6c,
508 [Q_KEY_CODE_KP_8] = 0x75,
509 [Q_KEY_CODE_KP_9] = 0x7d,
510 [Q_KEY_CODE_BRACKET_RIGHT] = 0x5b,
511 [Q_KEY_CODE_SEMICOLON] = 0x4c,
512 [Q_KEY_CODE_APOSTROPHE] = 0x52,
513 [Q_KEY_CODE_COMMA] = 0x41,
514 [Q_KEY_CODE_DOT] = 0x49,
515 [Q_KEY_CODE_SLASH] = 0x4a,
517 [Q_KEY_CODE_HIRAGANA] = 0x87,
518 [Q_KEY_CODE_HENKAN] = 0x86,
519 [Q_KEY_CODE_YEN] = 0x5d,
522 static uint8_t translate_table[256] = {
523 0xff, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58,
524 0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59,
525 0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a,
526 0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b,
527 0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c,
528 0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d,
529 0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e,
530 0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f,
531 0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60,
532 0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61,
533 0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e,
534 0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76,
535 0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b,
536 0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f,
537 0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45,
538 0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54,
539 0x80, 0x81, 0x82, 0x41, 0x54, 0x85, 0x86, 0x87,
540 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
541 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
542 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
543 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
544 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
545 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
546 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
547 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
548 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
549 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
550 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
551 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
552 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
553 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
554 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
557 static unsigned int ps2_modifier_bit(QKeyCode key)
559 switch (key) {
560 case Q_KEY_CODE_CTRL:
561 return MOD_CTRL_L;
562 case Q_KEY_CODE_CTRL_R:
563 return MOD_CTRL_R;
564 case Q_KEY_CODE_SHIFT:
565 return MOD_SHIFT_L;
566 case Q_KEY_CODE_SHIFT_R:
567 return MOD_SHIFT_R;
568 case Q_KEY_CODE_ALT:
569 return MOD_ALT_L;
570 case Q_KEY_CODE_ALT_R:
571 return MOD_ALT_R;
572 default:
573 return 0;
577 static void ps2_reset_queue(PS2State *s)
579 PS2Queue *q = &s->queue;
581 q->rptr = 0;
582 q->wptr = 0;
583 q->count = 0;
586 void ps2_queue(PS2State *s, int b)
588 PS2Queue *q = &s->queue;
590 if (q->count >= PS2_QUEUE_SIZE - 1)
591 return;
592 q->data[q->wptr] = b;
593 if (++q->wptr == PS2_QUEUE_SIZE)
594 q->wptr = 0;
595 q->count++;
596 s->update_irq(s->update_arg, 1);
599 /* keycode is the untranslated scancode in the current scancode set. */
600 static void ps2_put_keycode(void *opaque, int keycode)
602 PS2KbdState *s = opaque;
604 trace_ps2_put_keycode(opaque, keycode);
605 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
607 if (s->translate) {
608 if (keycode == 0xf0) {
609 s->need_high_bit = true;
610 } else if (s->need_high_bit) {
611 ps2_queue(&s->common, translate_table[keycode] | 0x80);
612 s->need_high_bit = false;
613 } else {
614 ps2_queue(&s->common, translate_table[keycode]);
616 } else {
617 ps2_queue(&s->common, keycode);
621 static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,
622 InputEvent *evt)
624 PS2KbdState *s = (PS2KbdState *)dev;
625 InputKeyEvent *key = evt->u.key.data;
626 int qcode;
627 uint16_t keycode;
628 int mod;
630 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
631 assert(evt->type == INPUT_EVENT_KIND_KEY);
632 qcode = qemu_input_key_value_to_qcode(key->key);
634 mod = ps2_modifier_bit(qcode);
635 trace_ps2_keyboard_event(s, qcode, key->down, mod, s->modifiers);
636 if (key->down) {
637 s->modifiers |= mod;
638 } else {
639 s->modifiers &= ~mod;
642 if (s->scancode_set == 1) {
643 if (qcode == Q_KEY_CODE_PAUSE) {
644 if (key->down) {
645 ps2_put_keycode(s, 0xe1);
646 ps2_put_keycode(s, 0x1d);
647 ps2_put_keycode(s, 0x45);
648 ps2_put_keycode(s, 0x91);
649 ps2_put_keycode(s, 0x9d);
650 ps2_put_keycode(s, 0xc5);
652 } else if (qcode == Q_KEY_CODE_PRINT) {
653 if (s->modifiers & MOD_ALT_L) {
654 if (key->down) {
655 ps2_put_keycode(s, 0xb8);
656 ps2_put_keycode(s, 0x38);
657 ps2_put_keycode(s, 0x54);
658 } else {
659 ps2_put_keycode(s, 0xd4);
660 ps2_put_keycode(s, 0xb8);
661 ps2_put_keycode(s, 0x38);
663 } else if (s->modifiers & MOD_ALT_R) {
664 if (key->down) {
665 ps2_put_keycode(s, 0xe0);
666 ps2_put_keycode(s, 0xb8);
667 ps2_put_keycode(s, 0xe0);
668 ps2_put_keycode(s, 0x38);
669 ps2_put_keycode(s, 0x54);
670 } else {
671 ps2_put_keycode(s, 0xd4);
672 ps2_put_keycode(s, 0xe0);
673 ps2_put_keycode(s, 0xb8);
674 ps2_put_keycode(s, 0xe0);
675 ps2_put_keycode(s, 0x38);
677 } else {
678 if (key->down) {
679 ps2_put_keycode(s, 0xe0);
680 ps2_put_keycode(s, 0x2a);
681 ps2_put_keycode(s, 0xe0);
682 ps2_put_keycode(s, 0x37);
683 } else {
684 ps2_put_keycode(s, 0xe0);
685 ps2_put_keycode(s, 0xb7);
686 ps2_put_keycode(s, 0xe0);
687 ps2_put_keycode(s, 0xaa);
690 } else {
691 keycode = qcode_to_keycode_set1[qcode];
692 if (keycode) {
693 if (keycode & 0xff00) {
694 ps2_put_keycode(s, keycode >> 8);
696 if (!key->down) {
697 keycode |= 0x80;
699 ps2_put_keycode(s, keycode & 0xff);
700 } else {
701 qemu_log_mask(LOG_UNIMP,
702 "ps2: ignoring key with qcode %d\n", qcode);
705 } else if (s->scancode_set == 2) {
706 if (qcode == Q_KEY_CODE_PAUSE) {
707 if (key->down) {
708 ps2_put_keycode(s, 0xe1);
709 ps2_put_keycode(s, 0x14);
710 ps2_put_keycode(s, 0x77);
711 ps2_put_keycode(s, 0xe1);
712 ps2_put_keycode(s, 0xf0);
713 ps2_put_keycode(s, 0x14);
714 ps2_put_keycode(s, 0xf0);
715 ps2_put_keycode(s, 0x77);
717 } else if (qcode == Q_KEY_CODE_PRINT) {
718 if (s->modifiers & MOD_ALT_L) {
719 if (key->down) {
720 ps2_put_keycode(s, 0xf0);
721 ps2_put_keycode(s, 0x11);
722 ps2_put_keycode(s, 0x11);
723 ps2_put_keycode(s, 0x84);
724 } else {
725 ps2_put_keycode(s, 0xf0);
726 ps2_put_keycode(s, 0x84);
727 ps2_put_keycode(s, 0xf0);
728 ps2_put_keycode(s, 0x11);
729 ps2_put_keycode(s, 0x11);
731 } else if (s->modifiers & MOD_ALT_R) {
732 if (key->down) {
733 ps2_put_keycode(s, 0xe0);
734 ps2_put_keycode(s, 0xf0);
735 ps2_put_keycode(s, 0x11);
736 ps2_put_keycode(s, 0xe0);
737 ps2_put_keycode(s, 0x11);
738 ps2_put_keycode(s, 0x84);
739 } else {
740 ps2_put_keycode(s, 0xf0);
741 ps2_put_keycode(s, 0x84);
742 ps2_put_keycode(s, 0xe0);
743 ps2_put_keycode(s, 0xf0);
744 ps2_put_keycode(s, 0x11);
745 ps2_put_keycode(s, 0xe0);
746 ps2_put_keycode(s, 0x11);
748 } else {
749 if (key->down) {
750 ps2_put_keycode(s, 0xe0);
751 ps2_put_keycode(s, 0x12);
752 ps2_put_keycode(s, 0xe0);
753 ps2_put_keycode(s, 0x7c);
754 } else {
755 ps2_put_keycode(s, 0xe0);
756 ps2_put_keycode(s, 0xf0);
757 ps2_put_keycode(s, 0x7c);
758 ps2_put_keycode(s, 0xe0);
759 ps2_put_keycode(s, 0xf0);
760 ps2_put_keycode(s, 0x12);
763 } else {
764 keycode = qcode_to_keycode_set2[qcode];
765 if (keycode) {
766 if (keycode & 0xff00) {
767 ps2_put_keycode(s, keycode >> 8);
769 if (!key->down) {
770 ps2_put_keycode(s, 0xf0);
772 ps2_put_keycode(s, keycode & 0xff);
773 } else {
774 qemu_log_mask(LOG_UNIMP,
775 "ps2: ignoring key with qcode %d\n", qcode);
778 } else if (s->scancode_set == 3) {
779 keycode = qcode_to_keycode_set3[qcode];
780 if (keycode) {
781 /* FIXME: break code should be configured on a key by key basis */
782 if (!key->down) {
783 ps2_put_keycode(s, 0xf0);
785 ps2_put_keycode(s, keycode);
786 } else {
787 qemu_log_mask(LOG_UNIMP,
788 "ps2: ignoring key with qcode %d\n", qcode);
793 uint32_t ps2_read_data(PS2State *s)
795 PS2Queue *q;
796 int val, index;
798 trace_ps2_read_data(s);
799 q = &s->queue;
800 if (q->count == 0) {
801 /* NOTE: if no data left, we return the last keyboard one
802 (needed for EMM386) */
803 /* XXX: need a timer to do things correctly */
804 index = q->rptr - 1;
805 if (index < 0)
806 index = PS2_QUEUE_SIZE - 1;
807 val = q->data[index];
808 } else {
809 val = q->data[q->rptr];
810 if (++q->rptr == PS2_QUEUE_SIZE)
811 q->rptr = 0;
812 q->count--;
813 /* reading deasserts IRQ */
814 s->update_irq(s->update_arg, 0);
815 /* reassert IRQs if data left */
816 s->update_irq(s->update_arg, q->count != 0);
818 return val;
821 static void ps2_set_ledstate(PS2KbdState *s, int ledstate)
823 trace_ps2_set_ledstate(s, ledstate);
824 s->ledstate = ledstate;
825 kbd_put_ledstate(ledstate);
828 static void ps2_reset_keyboard(PS2KbdState *s)
830 trace_ps2_reset_keyboard(s);
831 s->scan_enabled = 1;
832 s->scancode_set = 2;
833 ps2_reset_queue(&s->common);
834 ps2_set_ledstate(s, 0);
837 void ps2_write_keyboard(void *opaque, int val)
839 PS2KbdState *s = (PS2KbdState *)opaque;
841 trace_ps2_write_keyboard(opaque, val);
842 switch(s->common.write_cmd) {
843 default:
844 case -1:
845 switch(val) {
846 case 0x00:
847 ps2_queue(&s->common, KBD_REPLY_ACK);
848 break;
849 case 0x05:
850 ps2_queue(&s->common, KBD_REPLY_RESEND);
851 break;
852 case KBD_CMD_GET_ID:
853 ps2_queue(&s->common, KBD_REPLY_ACK);
854 /* We emulate a MF2 AT keyboard here */
855 ps2_queue(&s->common, KBD_REPLY_ID);
856 if (s->translate)
857 ps2_queue(&s->common, 0x41);
858 else
859 ps2_queue(&s->common, 0x83);
860 break;
861 case KBD_CMD_ECHO:
862 ps2_queue(&s->common, KBD_CMD_ECHO);
863 break;
864 case KBD_CMD_ENABLE:
865 s->scan_enabled = 1;
866 ps2_queue(&s->common, KBD_REPLY_ACK);
867 break;
868 case KBD_CMD_SCANCODE:
869 case KBD_CMD_SET_LEDS:
870 case KBD_CMD_SET_RATE:
871 s->common.write_cmd = val;
872 ps2_queue(&s->common, KBD_REPLY_ACK);
873 break;
874 case KBD_CMD_RESET_DISABLE:
875 ps2_reset_keyboard(s);
876 s->scan_enabled = 0;
877 ps2_queue(&s->common, KBD_REPLY_ACK);
878 break;
879 case KBD_CMD_RESET_ENABLE:
880 ps2_reset_keyboard(s);
881 s->scan_enabled = 1;
882 ps2_queue(&s->common, KBD_REPLY_ACK);
883 break;
884 case KBD_CMD_RESET:
885 ps2_reset_keyboard(s);
886 ps2_queue(&s->common, KBD_REPLY_ACK);
887 ps2_queue(&s->common, KBD_REPLY_POR);
888 break;
889 default:
890 ps2_queue(&s->common, KBD_REPLY_RESEND);
891 break;
893 break;
894 case KBD_CMD_SCANCODE:
895 if (val == 0) {
896 ps2_queue(&s->common, KBD_REPLY_ACK);
897 ps2_put_keycode(s, s->scancode_set);
898 } else if (val >= 1 && val <= 3) {
899 s->scancode_set = val;
900 ps2_queue(&s->common, KBD_REPLY_ACK);
901 } else {
902 ps2_queue(&s->common, KBD_REPLY_RESEND);
904 s->common.write_cmd = -1;
905 break;
906 case KBD_CMD_SET_LEDS:
907 ps2_set_ledstate(s, val);
908 ps2_queue(&s->common, KBD_REPLY_ACK);
909 s->common.write_cmd = -1;
910 break;
911 case KBD_CMD_SET_RATE:
912 ps2_queue(&s->common, KBD_REPLY_ACK);
913 s->common.write_cmd = -1;
914 break;
918 /* Set the scancode translation mode.
919 0 = raw scancodes.
920 1 = translated scancodes (used by qemu internally). */
922 void ps2_keyboard_set_translation(void *opaque, int mode)
924 PS2KbdState *s = (PS2KbdState *)opaque;
925 trace_ps2_keyboard_set_translation(opaque, mode);
926 s->translate = mode;
929 static void ps2_mouse_send_packet(PS2MouseState *s)
931 unsigned int b;
932 int dx1, dy1, dz1;
934 dx1 = s->mouse_dx;
935 dy1 = s->mouse_dy;
936 dz1 = s->mouse_dz;
937 /* XXX: increase range to 8 bits ? */
938 if (dx1 > 127)
939 dx1 = 127;
940 else if (dx1 < -127)
941 dx1 = -127;
942 if (dy1 > 127)
943 dy1 = 127;
944 else if (dy1 < -127)
945 dy1 = -127;
946 b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
947 ps2_queue(&s->common, b);
948 ps2_queue(&s->common, dx1 & 0xff);
949 ps2_queue(&s->common, dy1 & 0xff);
950 /* extra byte for IMPS/2 or IMEX */
951 switch(s->mouse_type) {
952 default:
953 break;
954 case 3:
955 if (dz1 > 127)
956 dz1 = 127;
957 else if (dz1 < -127)
958 dz1 = -127;
959 ps2_queue(&s->common, dz1 & 0xff);
960 break;
961 case 4:
962 if (dz1 > 7)
963 dz1 = 7;
964 else if (dz1 < -7)
965 dz1 = -7;
966 b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
967 ps2_queue(&s->common, b);
968 break;
971 trace_ps2_mouse_send_packet(s, dx1, dy1, dz1, b);
972 /* update deltas */
973 s->mouse_dx -= dx1;
974 s->mouse_dy -= dy1;
975 s->mouse_dz -= dz1;
978 static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
979 InputEvent *evt)
981 static const int bmap[INPUT_BUTTON__MAX] = {
982 [INPUT_BUTTON_LEFT] = PS2_MOUSE_BUTTON_LEFT,
983 [INPUT_BUTTON_MIDDLE] = PS2_MOUSE_BUTTON_MIDDLE,
984 [INPUT_BUTTON_RIGHT] = PS2_MOUSE_BUTTON_RIGHT,
985 [INPUT_BUTTON_SIDE] = PS2_MOUSE_BUTTON_SIDE,
986 [INPUT_BUTTON_EXTRA] = PS2_MOUSE_BUTTON_EXTRA,
988 PS2MouseState *s = (PS2MouseState *)dev;
989 InputMoveEvent *move;
990 InputBtnEvent *btn;
992 /* check if deltas are recorded when disabled */
993 if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
994 return;
996 switch (evt->type) {
997 case INPUT_EVENT_KIND_REL:
998 move = evt->u.rel.data;
999 if (move->axis == INPUT_AXIS_X) {
1000 s->mouse_dx += move->value;
1001 } else if (move->axis == INPUT_AXIS_Y) {
1002 s->mouse_dy -= move->value;
1004 break;
1006 case INPUT_EVENT_KIND_BTN:
1007 btn = evt->u.btn.data;
1008 if (btn->down) {
1009 s->mouse_buttons |= bmap[btn->button];
1010 if (btn->button == INPUT_BUTTON_WHEEL_UP) {
1011 s->mouse_dz--;
1012 } else if (btn->button == INPUT_BUTTON_WHEEL_DOWN) {
1013 s->mouse_dz++;
1015 } else {
1016 s->mouse_buttons &= ~bmap[btn->button];
1018 break;
1020 default:
1021 /* keep gcc happy */
1022 break;
1026 static void ps2_mouse_sync(DeviceState *dev)
1028 PS2MouseState *s = (PS2MouseState *)dev;
1030 if (s->mouse_buttons) {
1031 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
1033 if (!(s->mouse_status & MOUSE_STATUS_REMOTE)) {
1034 while (s->common.queue.count < PS2_QUEUE_SIZE - 4) {
1035 /* if not remote, send event. Multiple events are sent if
1036 too big deltas */
1037 ps2_mouse_send_packet(s);
1038 if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
1039 break;
1044 void ps2_mouse_fake_event(void *opaque)
1046 PS2MouseState *s = opaque;
1047 trace_ps2_mouse_fake_event(opaque);
1048 s->mouse_dx++;
1049 ps2_mouse_sync(opaque);
1052 void ps2_write_mouse(void *opaque, int val)
1054 PS2MouseState *s = (PS2MouseState *)opaque;
1056 trace_ps2_write_mouse(opaque, val);
1057 #ifdef DEBUG_MOUSE
1058 printf("kbd: write mouse 0x%02x\n", val);
1059 #endif
1060 switch(s->common.write_cmd) {
1061 default:
1062 case -1:
1063 /* mouse command */
1064 if (s->mouse_wrap) {
1065 if (val == AUX_RESET_WRAP) {
1066 s->mouse_wrap = 0;
1067 ps2_queue(&s->common, AUX_ACK);
1068 return;
1069 } else if (val != AUX_RESET) {
1070 ps2_queue(&s->common, val);
1071 return;
1074 switch(val) {
1075 case AUX_SET_SCALE11:
1076 s->mouse_status &= ~MOUSE_STATUS_SCALE21;
1077 ps2_queue(&s->common, AUX_ACK);
1078 break;
1079 case AUX_SET_SCALE21:
1080 s->mouse_status |= MOUSE_STATUS_SCALE21;
1081 ps2_queue(&s->common, AUX_ACK);
1082 break;
1083 case AUX_SET_STREAM:
1084 s->mouse_status &= ~MOUSE_STATUS_REMOTE;
1085 ps2_queue(&s->common, AUX_ACK);
1086 break;
1087 case AUX_SET_WRAP:
1088 s->mouse_wrap = 1;
1089 ps2_queue(&s->common, AUX_ACK);
1090 break;
1091 case AUX_SET_REMOTE:
1092 s->mouse_status |= MOUSE_STATUS_REMOTE;
1093 ps2_queue(&s->common, AUX_ACK);
1094 break;
1095 case AUX_GET_TYPE:
1096 ps2_queue(&s->common, AUX_ACK);
1097 ps2_queue(&s->common, s->mouse_type);
1098 break;
1099 case AUX_SET_RES:
1100 case AUX_SET_SAMPLE:
1101 s->common.write_cmd = val;
1102 ps2_queue(&s->common, AUX_ACK);
1103 break;
1104 case AUX_GET_SCALE:
1105 ps2_queue(&s->common, AUX_ACK);
1106 ps2_queue(&s->common, s->mouse_status);
1107 ps2_queue(&s->common, s->mouse_resolution);
1108 ps2_queue(&s->common, s->mouse_sample_rate);
1109 break;
1110 case AUX_POLL:
1111 ps2_queue(&s->common, AUX_ACK);
1112 ps2_mouse_send_packet(s);
1113 break;
1114 case AUX_ENABLE_DEV:
1115 s->mouse_status |= MOUSE_STATUS_ENABLED;
1116 ps2_queue(&s->common, AUX_ACK);
1117 break;
1118 case AUX_DISABLE_DEV:
1119 s->mouse_status &= ~MOUSE_STATUS_ENABLED;
1120 ps2_queue(&s->common, AUX_ACK);
1121 break;
1122 case AUX_SET_DEFAULT:
1123 s->mouse_sample_rate = 100;
1124 s->mouse_resolution = 2;
1125 s->mouse_status = 0;
1126 ps2_queue(&s->common, AUX_ACK);
1127 break;
1128 case AUX_RESET:
1129 s->mouse_sample_rate = 100;
1130 s->mouse_resolution = 2;
1131 s->mouse_status = 0;
1132 s->mouse_type = 0;
1133 ps2_queue(&s->common, AUX_ACK);
1134 ps2_queue(&s->common, 0xaa);
1135 ps2_queue(&s->common, s->mouse_type);
1136 break;
1137 default:
1138 break;
1140 break;
1141 case AUX_SET_SAMPLE:
1142 s->mouse_sample_rate = val;
1143 /* detect IMPS/2 or IMEX */
1144 switch(s->mouse_detect_state) {
1145 default:
1146 case 0:
1147 if (val == 200)
1148 s->mouse_detect_state = 1;
1149 break;
1150 case 1:
1151 if (val == 100)
1152 s->mouse_detect_state = 2;
1153 else if (val == 200)
1154 s->mouse_detect_state = 3;
1155 else
1156 s->mouse_detect_state = 0;
1157 break;
1158 case 2:
1159 if (val == 80)
1160 s->mouse_type = 3; /* IMPS/2 */
1161 s->mouse_detect_state = 0;
1162 break;
1163 case 3:
1164 if (val == 80)
1165 s->mouse_type = 4; /* IMEX */
1166 s->mouse_detect_state = 0;
1167 break;
1169 ps2_queue(&s->common, AUX_ACK);
1170 s->common.write_cmd = -1;
1171 break;
1172 case AUX_SET_RES:
1173 s->mouse_resolution = val;
1174 ps2_queue(&s->common, AUX_ACK);
1175 s->common.write_cmd = -1;
1176 break;
1180 static void ps2_common_reset(PS2State *s)
1182 s->write_cmd = -1;
1183 ps2_reset_queue(s);
1184 s->update_irq(s->update_arg, 0);
1187 static void ps2_common_post_load(PS2State *s)
1189 PS2Queue *q = &s->queue;
1190 int size;
1191 int i;
1192 int tmp_data[PS2_QUEUE_SIZE];
1194 /* set the useful data buffer queue size, < PS2_QUEUE_SIZE */
1195 size = q->count > PS2_QUEUE_SIZE ? 0 : q->count;
1197 /* move the queue elements to the start of data array */
1198 if (size > 0) {
1199 for (i = 0; i < size; i++) {
1200 /* move the queue elements to the temporary buffer */
1201 tmp_data[i] = q->data[q->rptr];
1202 if (++q->rptr == 256) {
1203 q->rptr = 0;
1206 memcpy(q->data, tmp_data, size);
1208 /* reset rptr/wptr/count */
1209 q->rptr = 0;
1210 q->wptr = size;
1211 q->count = size;
1212 s->update_irq(s->update_arg, q->count != 0);
1215 static void ps2_kbd_reset(void *opaque)
1217 PS2KbdState *s = (PS2KbdState *) opaque;
1219 trace_ps2_kbd_reset(opaque);
1220 ps2_common_reset(&s->common);
1221 s->scan_enabled = 0;
1222 s->translate = 0;
1223 s->scancode_set = 2;
1224 s->modifiers = 0;
1227 static void ps2_mouse_reset(void *opaque)
1229 PS2MouseState *s = (PS2MouseState *) opaque;
1231 trace_ps2_mouse_reset(opaque);
1232 ps2_common_reset(&s->common);
1233 s->mouse_status = 0;
1234 s->mouse_resolution = 0;
1235 s->mouse_sample_rate = 0;
1236 s->mouse_wrap = 0;
1237 s->mouse_type = 0;
1238 s->mouse_detect_state = 0;
1239 s->mouse_dx = 0;
1240 s->mouse_dy = 0;
1241 s->mouse_dz = 0;
1242 s->mouse_buttons = 0;
1245 static const VMStateDescription vmstate_ps2_common = {
1246 .name = "PS2 Common State",
1247 .version_id = 3,
1248 .minimum_version_id = 2,
1249 .fields = (VMStateField[]) {
1250 VMSTATE_INT32(write_cmd, PS2State),
1251 VMSTATE_INT32(queue.rptr, PS2State),
1252 VMSTATE_INT32(queue.wptr, PS2State),
1253 VMSTATE_INT32(queue.count, PS2State),
1254 VMSTATE_BUFFER(queue.data, PS2State),
1255 VMSTATE_END_OF_LIST()
1259 static bool ps2_keyboard_ledstate_needed(void *opaque)
1261 PS2KbdState *s = opaque;
1263 return s->ledstate != 0; /* 0 is default state */
1266 static int ps2_kbd_ledstate_post_load(void *opaque, int version_id)
1268 PS2KbdState *s = opaque;
1270 kbd_put_ledstate(s->ledstate);
1271 return 0;
1274 static const VMStateDescription vmstate_ps2_keyboard_ledstate = {
1275 .name = "ps2kbd/ledstate",
1276 .version_id = 3,
1277 .minimum_version_id = 2,
1278 .post_load = ps2_kbd_ledstate_post_load,
1279 .needed = ps2_keyboard_ledstate_needed,
1280 .fields = (VMStateField[]) {
1281 VMSTATE_INT32(ledstate, PS2KbdState),
1282 VMSTATE_END_OF_LIST()
1286 static bool ps2_keyboard_need_high_bit_needed(void *opaque)
1288 PS2KbdState *s = opaque;
1289 return s->need_high_bit != 0; /* 0 is the usual state */
1292 static const VMStateDescription vmstate_ps2_keyboard_need_high_bit = {
1293 .name = "ps2kbd/need_high_bit",
1294 .version_id = 1,
1295 .minimum_version_id = 1,
1296 .needed = ps2_keyboard_need_high_bit_needed,
1297 .fields = (VMStateField[]) {
1298 VMSTATE_BOOL(need_high_bit, PS2KbdState),
1299 VMSTATE_END_OF_LIST()
1303 static int ps2_kbd_post_load(void* opaque, int version_id)
1305 PS2KbdState *s = (PS2KbdState*)opaque;
1306 PS2State *ps2 = &s->common;
1308 if (version_id == 2)
1309 s->scancode_set=2;
1311 ps2_common_post_load(ps2);
1313 return 0;
1316 static int ps2_kbd_pre_save(void *opaque)
1318 PS2KbdState *s = (PS2KbdState *)opaque;
1319 PS2State *ps2 = &s->common;
1321 ps2_common_post_load(ps2);
1323 return 0;
1326 static const VMStateDescription vmstate_ps2_keyboard = {
1327 .name = "ps2kbd",
1328 .version_id = 3,
1329 .minimum_version_id = 2,
1330 .post_load = ps2_kbd_post_load,
1331 .pre_save = ps2_kbd_pre_save,
1332 .fields = (VMStateField[]) {
1333 VMSTATE_STRUCT(common, PS2KbdState, 0, vmstate_ps2_common, PS2State),
1334 VMSTATE_INT32(scan_enabled, PS2KbdState),
1335 VMSTATE_INT32(translate, PS2KbdState),
1336 VMSTATE_INT32_V(scancode_set, PS2KbdState,3),
1337 VMSTATE_END_OF_LIST()
1339 .subsections = (const VMStateDescription*[]) {
1340 &vmstate_ps2_keyboard_ledstate,
1341 &vmstate_ps2_keyboard_need_high_bit,
1342 NULL
1346 static int ps2_mouse_post_load(void *opaque, int version_id)
1348 PS2MouseState *s = (PS2MouseState *)opaque;
1349 PS2State *ps2 = &s->common;
1351 ps2_common_post_load(ps2);
1353 return 0;
1356 static int ps2_mouse_pre_save(void *opaque)
1358 PS2MouseState *s = (PS2MouseState *)opaque;
1359 PS2State *ps2 = &s->common;
1361 ps2_common_post_load(ps2);
1363 return 0;
1366 static const VMStateDescription vmstate_ps2_mouse = {
1367 .name = "ps2mouse",
1368 .version_id = 2,
1369 .minimum_version_id = 2,
1370 .post_load = ps2_mouse_post_load,
1371 .pre_save = ps2_mouse_pre_save,
1372 .fields = (VMStateField[]) {
1373 VMSTATE_STRUCT(common, PS2MouseState, 0, vmstate_ps2_common, PS2State),
1374 VMSTATE_UINT8(mouse_status, PS2MouseState),
1375 VMSTATE_UINT8(mouse_resolution, PS2MouseState),
1376 VMSTATE_UINT8(mouse_sample_rate, PS2MouseState),
1377 VMSTATE_UINT8(mouse_wrap, PS2MouseState),
1378 VMSTATE_UINT8(mouse_type, PS2MouseState),
1379 VMSTATE_UINT8(mouse_detect_state, PS2MouseState),
1380 VMSTATE_INT32(mouse_dx, PS2MouseState),
1381 VMSTATE_INT32(mouse_dy, PS2MouseState),
1382 VMSTATE_INT32(mouse_dz, PS2MouseState),
1383 VMSTATE_UINT8(mouse_buttons, PS2MouseState),
1384 VMSTATE_END_OF_LIST()
1388 static QemuInputHandler ps2_keyboard_handler = {
1389 .name = "QEMU PS/2 Keyboard",
1390 .mask = INPUT_EVENT_MASK_KEY,
1391 .event = ps2_keyboard_event,
1394 void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
1396 PS2KbdState *s = (PS2KbdState *)g_malloc0(sizeof(PS2KbdState));
1398 trace_ps2_kbd_init(s);
1399 s->common.update_irq = update_irq;
1400 s->common.update_arg = update_arg;
1401 s->scancode_set = 2;
1402 vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s);
1403 qemu_input_handler_register((DeviceState *)s,
1404 &ps2_keyboard_handler);
1405 qemu_register_reset(ps2_kbd_reset, s);
1406 return s;
1409 static QemuInputHandler ps2_mouse_handler = {
1410 .name = "QEMU PS/2 Mouse",
1411 .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
1412 .event = ps2_mouse_event,
1413 .sync = ps2_mouse_sync,
1416 void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
1418 PS2MouseState *s = (PS2MouseState *)g_malloc0(sizeof(PS2MouseState));
1420 trace_ps2_mouse_init(s);
1421 s->common.update_irq = update_irq;
1422 s->common.update_arg = update_arg;
1423 vmstate_register(NULL, 0, &vmstate_ps2_mouse, s);
1424 qemu_input_handler_register((DeviceState *)s,
1425 &ps2_mouse_handler);
1426 qemu_register_reset(ps2_mouse_reset, s);
1427 return s;