ps2: use QEMU qcodes instead of scancodes
[qemu/kevin.git] / hw / input / ps2.c
blob98da984384f5fef2f59b0272cfc539a921d491c6
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 "hw/hw.h"
26 #include "hw/input/ps2.h"
27 #include "ui/console.h"
28 #include "ui/input.h"
29 #include "sysemu/sysemu.h"
31 #include "trace.h"
33 /* debug PC keyboard */
34 //#define DEBUG_KBD
36 /* debug PC keyboard : only mouse */
37 //#define DEBUG_MOUSE
39 /* Keyboard Commands */
40 #define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */
41 #define KBD_CMD_ECHO 0xEE
42 #define KBD_CMD_SCANCODE 0xF0 /* Get/set scancode set */
43 #define KBD_CMD_GET_ID 0xF2 /* get keyboard ID */
44 #define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */
45 #define KBD_CMD_ENABLE 0xF4 /* Enable scanning */
46 #define KBD_CMD_RESET_DISABLE 0xF5 /* reset and disable scanning */
47 #define KBD_CMD_RESET_ENABLE 0xF6 /* reset and enable scanning */
48 #define KBD_CMD_RESET 0xFF /* Reset */
50 /* Keyboard Replies */
51 #define KBD_REPLY_POR 0xAA /* Power on reset */
52 #define KBD_REPLY_ID 0xAB /* Keyboard ID */
53 #define KBD_REPLY_ACK 0xFA /* Command ACK */
54 #define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */
56 /* Mouse Commands */
57 #define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */
58 #define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */
59 #define AUX_SET_RES 0xE8 /* Set resolution */
60 #define AUX_GET_SCALE 0xE9 /* Get scaling factor */
61 #define AUX_SET_STREAM 0xEA /* Set stream mode */
62 #define AUX_POLL 0xEB /* Poll */
63 #define AUX_RESET_WRAP 0xEC /* Reset wrap mode */
64 #define AUX_SET_WRAP 0xEE /* Set wrap mode */
65 #define AUX_SET_REMOTE 0xF0 /* Set remote mode */
66 #define AUX_GET_TYPE 0xF2 /* Get type */
67 #define AUX_SET_SAMPLE 0xF3 /* Set sample rate */
68 #define AUX_ENABLE_DEV 0xF4 /* Enable aux device */
69 #define AUX_DISABLE_DEV 0xF5 /* Disable aux device */
70 #define AUX_SET_DEFAULT 0xF6
71 #define AUX_RESET 0xFF /* Reset aux device */
72 #define AUX_ACK 0xFA /* Command byte ACK. */
74 #define MOUSE_STATUS_REMOTE 0x40
75 #define MOUSE_STATUS_ENABLED 0x20
76 #define MOUSE_STATUS_SCALE21 0x10
78 #define PS2_QUEUE_SIZE 16 /* Buffer size required by PS/2 protocol */
80 typedef struct {
81 /* Keep the data array 256 bytes long, which compatibility
82 with older qemu versions. */
83 uint8_t data[256];
84 int rptr, wptr, count;
85 } PS2Queue;
87 typedef struct {
88 PS2Queue queue;
89 int32_t write_cmd;
90 void (*update_irq)(void *, int);
91 void *update_arg;
92 } PS2State;
94 typedef struct {
95 PS2State common;
96 int scan_enabled;
97 int translate;
98 int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */
99 int ledstate;
100 bool need_high_bit;
101 } PS2KbdState;
103 typedef struct {
104 PS2State common;
105 uint8_t mouse_status;
106 uint8_t mouse_resolution;
107 uint8_t mouse_sample_rate;
108 uint8_t mouse_wrap;
109 uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */
110 uint8_t mouse_detect_state;
111 int mouse_dx; /* current values, needed for 'poll' mode */
112 int mouse_dy;
113 int mouse_dz;
114 uint8_t mouse_buttons;
115 } PS2MouseState;
117 /* Table to convert from QEMU codes to scancodes. */
118 static const uint16_t qcode_to_keycode_set1[Q_KEY_CODE__MAX] = {
119 [0 ... Q_KEY_CODE__MAX - 1] = 0,
121 [Q_KEY_CODE_A] = 0x1e,
122 [Q_KEY_CODE_B] = 0x30,
123 [Q_KEY_CODE_C] = 0x2e,
124 [Q_KEY_CODE_D] = 0x20,
125 [Q_KEY_CODE_E] = 0x12,
126 [Q_KEY_CODE_F] = 0x21,
127 [Q_KEY_CODE_G] = 0x22,
128 [Q_KEY_CODE_H] = 0x23,
129 [Q_KEY_CODE_I] = 0x17,
130 [Q_KEY_CODE_J] = 0x24,
131 [Q_KEY_CODE_K] = 0x25,
132 [Q_KEY_CODE_L] = 0x26,
133 [Q_KEY_CODE_M] = 0x32,
134 [Q_KEY_CODE_N] = 0x31,
135 [Q_KEY_CODE_O] = 0x18,
136 [Q_KEY_CODE_P] = 0x19,
137 [Q_KEY_CODE_Q] = 0x10,
138 [Q_KEY_CODE_R] = 0x13,
139 [Q_KEY_CODE_S] = 0x1f,
140 [Q_KEY_CODE_T] = 0x14,
141 [Q_KEY_CODE_U] = 0x16,
142 [Q_KEY_CODE_V] = 0x2f,
143 [Q_KEY_CODE_W] = 0x11,
144 [Q_KEY_CODE_X] = 0x2d,
145 [Q_KEY_CODE_Y] = 0x15,
146 [Q_KEY_CODE_Z] = 0x2c,
147 [Q_KEY_CODE_0] = 0x0b,
148 [Q_KEY_CODE_1] = 0x02,
149 [Q_KEY_CODE_2] = 0x03,
150 [Q_KEY_CODE_3] = 0x04,
151 [Q_KEY_CODE_4] = 0x05,
152 [Q_KEY_CODE_5] = 0x06,
153 [Q_KEY_CODE_6] = 0x07,
154 [Q_KEY_CODE_7] = 0x08,
155 [Q_KEY_CODE_8] = 0x09,
156 [Q_KEY_CODE_9] = 0x0a,
157 [Q_KEY_CODE_GRAVE_ACCENT] = 0x29,
158 [Q_KEY_CODE_MINUS] = 0x0c,
159 [Q_KEY_CODE_EQUAL] = 0x0d,
160 [Q_KEY_CODE_BACKSLASH] = 0x2b,
161 [Q_KEY_CODE_BACKSPACE] = 0x0e,
162 [Q_KEY_CODE_SPC] = 0x39,
163 [Q_KEY_CODE_TAB] = 0x0f,
164 [Q_KEY_CODE_CAPS_LOCK] = 0x3a,
165 [Q_KEY_CODE_SHIFT] = 0x2a,
166 [Q_KEY_CODE_CTRL] = 0x1d,
167 [Q_KEY_CODE_META_L] = 0xe05b,
168 [Q_KEY_CODE_ALT] = 0x38,
169 [Q_KEY_CODE_SHIFT_R] = 0x36,
170 [Q_KEY_CODE_CTRL_R] = 0xe01d,
171 [Q_KEY_CODE_META_R] = 0xe05c,
172 [Q_KEY_CODE_ALT_R] = 0xe038,
173 [Q_KEY_CODE_MENU] = 0xe05d,
174 [Q_KEY_CODE_RET] = 0x1c,
175 [Q_KEY_CODE_ESC] = 0x01,
176 [Q_KEY_CODE_F1] = 0x3b,
177 [Q_KEY_CODE_F2] = 0x3c,
178 [Q_KEY_CODE_F3] = 0x3d,
179 [Q_KEY_CODE_F4] = 0x3e,
180 [Q_KEY_CODE_F5] = 0x3f,
181 [Q_KEY_CODE_F6] = 0x40,
182 [Q_KEY_CODE_F7] = 0x41,
183 [Q_KEY_CODE_F8] = 0x42,
184 [Q_KEY_CODE_F9] = 0x43,
185 [Q_KEY_CODE_F10] = 0x44,
186 [Q_KEY_CODE_F11] = 0x57,
187 [Q_KEY_CODE_F12] = 0x58,
188 /* special handling for Q_KEY_CODE_PRINT */
189 [Q_KEY_CODE_SCROLL_LOCK] = 0x46,
190 /* special handling for Q_KEY_CODE_PAUSE */
191 [Q_KEY_CODE_BRACKET_LEFT] = 0x1a,
192 [Q_KEY_CODE_INSERT] = 0xe052,
193 [Q_KEY_CODE_HOME] = 0xe047,
194 [Q_KEY_CODE_PGUP] = 0xe049,
195 [Q_KEY_CODE_DELETE] = 0xe053,
196 [Q_KEY_CODE_END] = 0xe04f,
197 [Q_KEY_CODE_PGDN] = 0xe051,
198 [Q_KEY_CODE_UP] = 0xe048,
199 [Q_KEY_CODE_LEFT] = 0xe04b,
200 [Q_KEY_CODE_DOWN] = 0xe050,
201 [Q_KEY_CODE_RIGHT] = 0xe04d,
202 [Q_KEY_CODE_NUM_LOCK] = 0x45,
203 [Q_KEY_CODE_KP_DIVIDE] = 0xe035,
204 [Q_KEY_CODE_KP_MULTIPLY] = 0x37,
205 [Q_KEY_CODE_KP_SUBTRACT] = 0x4a,
206 [Q_KEY_CODE_KP_ADD] = 0x4e,
207 [Q_KEY_CODE_KP_ENTER] = 0xe01c,
208 [Q_KEY_CODE_KP_DECIMAL] = 0x53,
209 [Q_KEY_CODE_KP_0] = 0x52,
210 [Q_KEY_CODE_KP_1] = 0x4f,
211 [Q_KEY_CODE_KP_2] = 0x50,
212 [Q_KEY_CODE_KP_3] = 0x51,
213 [Q_KEY_CODE_KP_4] = 0x4b,
214 [Q_KEY_CODE_KP_5] = 0x4c,
215 [Q_KEY_CODE_KP_6] = 0x4d,
216 [Q_KEY_CODE_KP_7] = 0x47,
217 [Q_KEY_CODE_KP_8] = 0x48,
218 [Q_KEY_CODE_KP_9] = 0x49,
219 [Q_KEY_CODE_BRACKET_RIGHT] = 0x1b,
220 [Q_KEY_CODE_SEMICOLON] = 0x27,
221 [Q_KEY_CODE_APOSTROPHE] = 0x28,
222 [Q_KEY_CODE_COMMA] = 0x33,
223 [Q_KEY_CODE_DOT] = 0x34,
224 [Q_KEY_CODE_SLASH] = 0x35,
226 #if 0
227 [Q_KEY_CODE_POWER] = 0x0e5e,
228 [Q_KEY_CODE_SLEEP] = 0x0e5f,
229 [Q_KEY_CODE_WAKE] = 0x0e63,
231 [Q_KEY_CODE_AUDIONEXT] = 0xe019,
232 [Q_KEY_CODE_AUDIOPREV] = 0xe010,
233 [Q_KEY_CODE_AUDIOSTOP] = 0xe024,
234 [Q_KEY_CODE_AUDIOPLAY] = 0xe022,
235 [Q_KEY_CODE_AUDIOMUTE] = 0xe020,
236 [Q_KEY_CODE_VOLUMEUP] = 0xe030,
237 [Q_KEY_CODE_VOLUMEDOWN] = 0xe02e,
238 [Q_KEY_CODE_MEDIASELECT] = 0xe06d,
239 [Q_KEY_CODE_MAIL] = 0xe06c,
240 [Q_KEY_CODE_CALCULATOR] = 0xe021,
241 [Q_KEY_CODE_COMPUTER] = 0xe06b,
242 [Q_KEY_CODE_AC_SEARCH] = 0xe065,
243 [Q_KEY_CODE_AC_HOME] = 0xe032,
244 [Q_KEY_CODE_AC_BACK] = 0xe06a,
245 [Q_KEY_CODE_AC_FORWARD] = 0xe069,
246 [Q_KEY_CODE_AC_STOP] = 0xe068,
247 [Q_KEY_CODE_AC_REFRESH] = 0xe067,
248 [Q_KEY_CODE_AC_BOOKMARKS] = 0xe066,
249 #endif
251 [Q_KEY_CODE_ASTERISK] = 0x37,
252 [Q_KEY_CODE_LESS] = 0x56,
253 [Q_KEY_CODE_RO] = 0x73,
254 [Q_KEY_CODE_KP_COMMA] = 0x7e,
257 static const uint16_t qcode_to_keycode_set2[Q_KEY_CODE__MAX] = {
258 [0 ... Q_KEY_CODE__MAX - 1] = 0,
260 [Q_KEY_CODE_A] = 0x1c,
261 [Q_KEY_CODE_B] = 0x32,
262 [Q_KEY_CODE_C] = 0x21,
263 [Q_KEY_CODE_D] = 0x23,
264 [Q_KEY_CODE_E] = 0x24,
265 [Q_KEY_CODE_F] = 0x2b,
266 [Q_KEY_CODE_G] = 0x34,
267 [Q_KEY_CODE_H] = 0x33,
268 [Q_KEY_CODE_I] = 0x43,
269 [Q_KEY_CODE_J] = 0x3b,
270 [Q_KEY_CODE_K] = 0x42,
271 [Q_KEY_CODE_L] = 0x4b,
272 [Q_KEY_CODE_M] = 0x3a,
273 [Q_KEY_CODE_N] = 0x31,
274 [Q_KEY_CODE_O] = 0x44,
275 [Q_KEY_CODE_P] = 0x4d,
276 [Q_KEY_CODE_Q] = 0x15,
277 [Q_KEY_CODE_R] = 0x2d,
278 [Q_KEY_CODE_S] = 0x1b,
279 [Q_KEY_CODE_T] = 0x2c,
280 [Q_KEY_CODE_U] = 0x3c,
281 [Q_KEY_CODE_V] = 0x2a,
282 [Q_KEY_CODE_W] = 0x1d,
283 [Q_KEY_CODE_X] = 0x22,
284 [Q_KEY_CODE_Y] = 0x35,
285 [Q_KEY_CODE_Z] = 0x1a,
286 [Q_KEY_CODE_0] = 0x45,
287 [Q_KEY_CODE_1] = 0x16,
288 [Q_KEY_CODE_2] = 0x1e,
289 [Q_KEY_CODE_3] = 0x26,
290 [Q_KEY_CODE_4] = 0x25,
291 [Q_KEY_CODE_5] = 0x2e,
292 [Q_KEY_CODE_6] = 0x36,
293 [Q_KEY_CODE_7] = 0x3d,
294 [Q_KEY_CODE_8] = 0x3e,
295 [Q_KEY_CODE_9] = 0x46,
296 [Q_KEY_CODE_GRAVE_ACCENT] = 0x0e,
297 [Q_KEY_CODE_MINUS] = 0x4e,
298 [Q_KEY_CODE_EQUAL] = 0x55,
299 [Q_KEY_CODE_BACKSLASH] = 0x5d,
300 [Q_KEY_CODE_BACKSPACE] = 0x66,
301 [Q_KEY_CODE_SPC] = 0x29,
302 [Q_KEY_CODE_TAB] = 0x0d,
303 [Q_KEY_CODE_CAPS_LOCK] = 0x58,
304 [Q_KEY_CODE_SHIFT] = 0x12,
305 [Q_KEY_CODE_CTRL] = 0x14,
306 [Q_KEY_CODE_META_L] = 0xe01f,
307 [Q_KEY_CODE_ALT] = 0x11,
308 [Q_KEY_CODE_SHIFT_R] = 0x59,
309 [Q_KEY_CODE_CTRL_R] = 0xe014,
310 [Q_KEY_CODE_META_R] = 0xe027,
311 [Q_KEY_CODE_ALT_R] = 0xe011,
312 [Q_KEY_CODE_MENU] = 0xe02f,
313 [Q_KEY_CODE_RET] = 0x5a,
314 [Q_KEY_CODE_ESC] = 0x76,
315 [Q_KEY_CODE_F1] = 0x05,
316 [Q_KEY_CODE_F2] = 0x06,
317 [Q_KEY_CODE_F3] = 0x04,
318 [Q_KEY_CODE_F4] = 0x0c,
319 [Q_KEY_CODE_F5] = 0x03,
320 [Q_KEY_CODE_F6] = 0x0b,
321 [Q_KEY_CODE_F7] = 0x83,
322 [Q_KEY_CODE_F8] = 0x0a,
323 [Q_KEY_CODE_F9] = 0x01,
324 [Q_KEY_CODE_F10] = 0x09,
325 [Q_KEY_CODE_F11] = 0x78,
326 [Q_KEY_CODE_F12] = 0x07,
327 /* special handling for Q_KEY_CODE_PRINT */
328 [Q_KEY_CODE_SCROLL_LOCK] = 0x7e,
329 /* special handling for Q_KEY_CODE_PAUSE */
330 [Q_KEY_CODE_BRACKET_LEFT] = 0x54,
331 [Q_KEY_CODE_INSERT] = 0xe070,
332 [Q_KEY_CODE_HOME] = 0xe06c,
333 [Q_KEY_CODE_PGUP] = 0xe07d,
334 [Q_KEY_CODE_DELETE] = 0xe071,
335 [Q_KEY_CODE_END] = 0xe069,
336 [Q_KEY_CODE_PGDN] = 0xe07a,
337 [Q_KEY_CODE_UP] = 0xe075,
338 [Q_KEY_CODE_LEFT] = 0xe06b,
339 [Q_KEY_CODE_DOWN] = 0xe072,
340 [Q_KEY_CODE_RIGHT] = 0xe074,
341 [Q_KEY_CODE_NUM_LOCK] = 0x77,
342 [Q_KEY_CODE_KP_DIVIDE] = 0xe04a,
343 [Q_KEY_CODE_KP_MULTIPLY] = 0x7c,
344 [Q_KEY_CODE_KP_SUBTRACT] = 0x7b,
345 [Q_KEY_CODE_KP_ADD] = 0x79,
346 [Q_KEY_CODE_KP_ENTER] = 0xe05a,
347 [Q_KEY_CODE_KP_DECIMAL] = 0x71,
348 [Q_KEY_CODE_KP_0] = 0x70,
349 [Q_KEY_CODE_KP_1] = 0x69,
350 [Q_KEY_CODE_KP_2] = 0x72,
351 [Q_KEY_CODE_KP_3] = 0x7a,
352 [Q_KEY_CODE_KP_4] = 0x6b,
353 [Q_KEY_CODE_KP_5] = 0x73,
354 [Q_KEY_CODE_KP_6] = 0x74,
355 [Q_KEY_CODE_KP_7] = 0x6c,
356 [Q_KEY_CODE_KP_8] = 0x75,
357 [Q_KEY_CODE_KP_9] = 0x7d,
358 [Q_KEY_CODE_BRACKET_RIGHT] = 0x5b,
359 [Q_KEY_CODE_SEMICOLON] = 0x4c,
360 [Q_KEY_CODE_APOSTROPHE] = 0x52,
361 [Q_KEY_CODE_COMMA] = 0x41,
362 [Q_KEY_CODE_DOT] = 0x49,
363 [Q_KEY_CODE_SLASH] = 0x4a,
365 #if 0
366 [Q_KEY_CODE_POWER] = 0x0e37,
367 [Q_KEY_CODE_SLEEP] = 0x0e3f,
368 [Q_KEY_CODE_WAKE] = 0x0e5e,
370 [Q_KEY_CODE_AUDIONEXT] = 0xe04d,
371 [Q_KEY_CODE_AUDIOPREV] = 0xe015,
372 [Q_KEY_CODE_AUDIOSTOP] = 0xe03b,
373 [Q_KEY_CODE_AUDIOPLAY] = 0xe034,
374 [Q_KEY_CODE_AUDIOMUTE] = 0xe023,
375 [Q_KEY_CODE_VOLUMEUP] = 0xe032,
376 [Q_KEY_CODE_VOLUMEDOWN] = 0xe021,
377 [Q_KEY_CODE_MEDIASELECT] = 0xe050,
378 [Q_KEY_CODE_MAIL] = 0xe048,
379 [Q_KEY_CODE_CALCULATOR] = 0xe02b,
380 [Q_KEY_CODE_COMPUTER] = 0xe040,
381 [Q_KEY_CODE_AC_SEARCH] = 0xe010,
382 [Q_KEY_CODE_AC_HOME] = 0xe03a,
383 [Q_KEY_CODE_AC_BACK] = 0xe038,
384 [Q_KEY_CODE_AC_FORWARD] = 0xe030,
385 [Q_KEY_CODE_AC_STOP] = 0xe028,
386 [Q_KEY_CODE_AC_REFRESH] = 0xe020,
387 [Q_KEY_CODE_AC_BOOKMARKS] = 0xe018,
388 #endif
390 [Q_KEY_CODE_ALTGR] = 0x08,
391 [Q_KEY_CODE_ALTGR_R] = 0xe008,
392 [Q_KEY_CODE_ASTERISK] = 0x7c,
393 [Q_KEY_CODE_LESS] = 0x61,
394 [Q_KEY_CODE_SYSRQ] = 0x7f,
395 [Q_KEY_CODE_RO] = 0x51,
396 [Q_KEY_CODE_KP_COMMA] = 0x6d,
399 static const uint16_t qcode_to_keycode_set3[Q_KEY_CODE__MAX] = {
400 [0 ... Q_KEY_CODE__MAX - 1] = 0,
402 [Q_KEY_CODE_A] = 0x1c,
403 [Q_KEY_CODE_B] = 0x32,
404 [Q_KEY_CODE_C] = 0x21,
405 [Q_KEY_CODE_D] = 0x23,
406 [Q_KEY_CODE_E] = 0x24,
407 [Q_KEY_CODE_F] = 0x2b,
408 [Q_KEY_CODE_G] = 0x34,
409 [Q_KEY_CODE_H] = 0x33,
410 [Q_KEY_CODE_I] = 0x43,
411 [Q_KEY_CODE_J] = 0x3b,
412 [Q_KEY_CODE_K] = 0x42,
413 [Q_KEY_CODE_L] = 0x4b,
414 [Q_KEY_CODE_M] = 0x3a,
415 [Q_KEY_CODE_N] = 0x31,
416 [Q_KEY_CODE_O] = 0x44,
417 [Q_KEY_CODE_P] = 0x4d,
418 [Q_KEY_CODE_Q] = 0x15,
419 [Q_KEY_CODE_R] = 0x2d,
420 [Q_KEY_CODE_S] = 0x1b,
421 [Q_KEY_CODE_T] = 0x2c,
422 [Q_KEY_CODE_U] = 0x3c,
423 [Q_KEY_CODE_V] = 0x2a,
424 [Q_KEY_CODE_W] = 0x1d,
425 [Q_KEY_CODE_X] = 0x22,
426 [Q_KEY_CODE_Y] = 0x35,
427 [Q_KEY_CODE_Z] = 0x1a,
428 [Q_KEY_CODE_0] = 0x45,
429 [Q_KEY_CODE_1] = 0x16,
430 [Q_KEY_CODE_2] = 0x1e,
431 [Q_KEY_CODE_3] = 0x26,
432 [Q_KEY_CODE_4] = 0x25,
433 [Q_KEY_CODE_5] = 0x2e,
434 [Q_KEY_CODE_6] = 0x36,
435 [Q_KEY_CODE_7] = 0x3d,
436 [Q_KEY_CODE_8] = 0x3e,
437 [Q_KEY_CODE_9] = 0x46,
438 [Q_KEY_CODE_GRAVE_ACCENT] = 0x0e,
439 [Q_KEY_CODE_MINUS] = 0x4e,
440 [Q_KEY_CODE_EQUAL] = 0x55,
441 [Q_KEY_CODE_BACKSLASH] = 0x5c,
442 [Q_KEY_CODE_BACKSPACE] = 0x66,
443 [Q_KEY_CODE_SPC] = 0x29,
444 [Q_KEY_CODE_TAB] = 0x0d,
445 [Q_KEY_CODE_CAPS_LOCK] = 0x14,
446 [Q_KEY_CODE_SHIFT] = 0x12,
447 [Q_KEY_CODE_CTRL] = 0x11,
448 [Q_KEY_CODE_META_L] = 0x8b,
449 [Q_KEY_CODE_ALT] = 0x19,
450 [Q_KEY_CODE_SHIFT_R] = 0x59,
451 [Q_KEY_CODE_CTRL_R] = 0x58,
452 [Q_KEY_CODE_META_R] = 0x8c,
453 [Q_KEY_CODE_ALT_R] = 0x39,
454 [Q_KEY_CODE_MENU] = 0x8d,
455 [Q_KEY_CODE_RET] = 0x5a,
456 [Q_KEY_CODE_ESC] = 0x08,
457 [Q_KEY_CODE_F1] = 0x07,
458 [Q_KEY_CODE_F2] = 0x0f,
459 [Q_KEY_CODE_F3] = 0x17,
460 [Q_KEY_CODE_F4] = 0x1f,
461 [Q_KEY_CODE_F5] = 0x27,
462 [Q_KEY_CODE_F6] = 0x2f,
463 [Q_KEY_CODE_F7] = 0x37,
464 [Q_KEY_CODE_F8] = 0x3f,
465 [Q_KEY_CODE_F9] = 0x47,
466 [Q_KEY_CODE_F10] = 0x4f,
467 [Q_KEY_CODE_F11] = 0x56,
468 [Q_KEY_CODE_F12] = 0x5e,
469 [Q_KEY_CODE_PRINT] = 0x57,
470 [Q_KEY_CODE_SCROLL_LOCK] = 0x5f,
471 [Q_KEY_CODE_PAUSE] = 0x62,
472 [Q_KEY_CODE_BRACKET_LEFT] = 0x54,
473 [Q_KEY_CODE_INSERT] = 0x67,
474 [Q_KEY_CODE_HOME] = 0x6e,
475 [Q_KEY_CODE_PGUP] = 0x6f,
476 [Q_KEY_CODE_DELETE] = 0x64,
477 [Q_KEY_CODE_END] = 0x65,
478 [Q_KEY_CODE_PGDN] = 0x6d,
479 [Q_KEY_CODE_UP] = 0x63,
480 [Q_KEY_CODE_LEFT] = 0x61,
481 [Q_KEY_CODE_DOWN] = 0x60,
482 [Q_KEY_CODE_RIGHT] = 0x6a,
483 [Q_KEY_CODE_NUM_LOCK] = 0x76,
484 [Q_KEY_CODE_KP_DIVIDE] = 0x4a,
485 [Q_KEY_CODE_KP_MULTIPLY] = 0x7e,
486 [Q_KEY_CODE_KP_SUBTRACT] = 0x4e,
487 [Q_KEY_CODE_KP_ADD] = 0x7c,
488 [Q_KEY_CODE_KP_ENTER] = 0x79,
489 [Q_KEY_CODE_KP_DECIMAL] = 0x71,
490 [Q_KEY_CODE_KP_0] = 0x70,
491 [Q_KEY_CODE_KP_1] = 0x69,
492 [Q_KEY_CODE_KP_2] = 0x72,
493 [Q_KEY_CODE_KP_3] = 0x7a,
494 [Q_KEY_CODE_KP_4] = 0x6b,
495 [Q_KEY_CODE_KP_5] = 0x73,
496 [Q_KEY_CODE_KP_6] = 0x74,
497 [Q_KEY_CODE_KP_7] = 0x6c,
498 [Q_KEY_CODE_KP_8] = 0x75,
499 [Q_KEY_CODE_KP_9] = 0x7d,
500 [Q_KEY_CODE_BRACKET_RIGHT] = 0x5b,
501 [Q_KEY_CODE_SEMICOLON] = 0x4c,
502 [Q_KEY_CODE_APOSTROPHE] = 0x52,
503 [Q_KEY_CODE_COMMA] = 0x41,
504 [Q_KEY_CODE_DOT] = 0x49,
505 [Q_KEY_CODE_SLASH] = 0x4a,
508 static uint8_t translate_table[256] = {
509 0xff, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58,
510 0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59,
511 0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a,
512 0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b,
513 0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c,
514 0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d,
515 0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e,
516 0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f,
517 0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60,
518 0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61,
519 0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e,
520 0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76,
521 0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b,
522 0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f,
523 0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45,
524 0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54,
525 0x80, 0x81, 0x82, 0x41, 0x54, 0x85, 0x86, 0x87,
526 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
527 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
528 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
529 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
530 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
531 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
532 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
533 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
534 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
535 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
536 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
537 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
538 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
539 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
540 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
543 void ps2_queue(void *opaque, int b)
545 PS2State *s = (PS2State *)opaque;
546 PS2Queue *q = &s->queue;
548 if (q->count >= PS2_QUEUE_SIZE - 1)
549 return;
550 q->data[q->wptr] = b;
551 if (++q->wptr == PS2_QUEUE_SIZE)
552 q->wptr = 0;
553 q->count++;
554 s->update_irq(s->update_arg, 1);
557 /* keycode is the untranslated scancode in the current scancode set. */
558 static void ps2_put_keycode(void *opaque, int keycode)
560 PS2KbdState *s = opaque;
562 trace_ps2_put_keycode(opaque, keycode);
563 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
565 if (s->translate) {
566 if (keycode == 0xf0) {
567 s->need_high_bit = true;
568 } else if (s->need_high_bit) {
569 ps2_queue(&s->common, translate_table[keycode] | 0x80);
570 s->need_high_bit = false;
571 } else {
572 ps2_queue(&s->common, translate_table[keycode]);
574 } else {
575 ps2_queue(&s->common, keycode);
579 static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,
580 InputEvent *evt)
582 PS2KbdState *s = (PS2KbdState *)dev;
583 InputKeyEvent *key = evt->u.key.data;
584 int qcode;
585 uint16_t keycode;
587 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
588 assert(evt->type == INPUT_EVENT_KIND_KEY);
589 qcode = qemu_input_key_value_to_qcode(key->key);
591 if (s->scancode_set == 1) {
592 if (qcode == Q_KEY_CODE_PAUSE) {
593 if (key->down) {
594 ps2_put_keycode(s, 0xe1);
595 ps2_put_keycode(s, 0x1d);
596 ps2_put_keycode(s, 0x45);
597 ps2_put_keycode(s, 0x91);
598 ps2_put_keycode(s, 0x9d);
599 ps2_put_keycode(s, 0xc5);
601 } else if (qcode == Q_KEY_CODE_PRINT) {
602 if (key->down) {
603 ps2_put_keycode(s, 0xe0);
604 ps2_put_keycode(s, 0x2a);
605 ps2_put_keycode(s, 0xe0);
606 ps2_put_keycode(s, 0x37);
607 } else {
608 ps2_put_keycode(s, 0xe0);
609 ps2_put_keycode(s, 0xb7);
610 ps2_put_keycode(s, 0xe0);
611 ps2_put_keycode(s, 0xaa);
613 } else {
614 keycode = qcode_to_keycode_set1[qcode];
615 if (keycode) {
616 if (keycode & 0xff00) {
617 ps2_put_keycode(s, keycode >> 8);
619 if (!key->down) {
620 keycode |= 0x80;
622 ps2_put_keycode(s, keycode & 0xff);
623 } else {
624 ps2_queue(&s->common, key->down ? 0x00 : 0x80);
627 } else if (s->scancode_set == 2) {
628 if (qcode == Q_KEY_CODE_PAUSE) {
629 if (key->down) {
630 ps2_put_keycode(s, 0xe1);
631 ps2_put_keycode(s, 0x14);
632 ps2_put_keycode(s, 0x77);
633 ps2_put_keycode(s, 0xe1);
634 ps2_put_keycode(s, 0xf0);
635 ps2_put_keycode(s, 0x14);
636 ps2_put_keycode(s, 0xf0);
637 ps2_put_keycode(s, 0x77);
639 } else if (qcode == Q_KEY_CODE_PRINT) {
640 if (key->down) {
641 ps2_put_keycode(s, 0xe0);
642 ps2_put_keycode(s, 0x12);
643 ps2_put_keycode(s, 0xe0);
644 ps2_put_keycode(s, 0x7c);
645 } else {
646 ps2_put_keycode(s, 0xe0);
647 ps2_put_keycode(s, 0xf0);
648 ps2_put_keycode(s, 0x7c);
649 ps2_put_keycode(s, 0xe0);
650 ps2_put_keycode(s, 0xf0);
651 ps2_put_keycode(s, 0x12);
653 } else {
654 keycode = qcode_to_keycode_set2[qcode];
655 if (keycode) {
656 if (keycode & 0xff00) {
657 ps2_put_keycode(s, keycode >> 8);
659 if (!key->down) {
660 ps2_put_keycode(s, 0xf0);
662 ps2_put_keycode(s, keycode & 0xff);
663 } else if (key->down) {
664 ps2_queue(&s->common, 0x00);
665 } else if (s->translate) {
666 ps2_queue(&s->common, 0x80);
667 } else {
668 ps2_queue(&s->common, 0xf0);
669 ps2_queue(&s->common, 0x00);
672 } else if (s->scancode_set == 3) {
673 keycode = qcode_to_keycode_set3[qcode];
674 if (keycode) {
675 /* FIXME: break code should be configured on a key by key basis */
676 if (!key->down) {
677 ps2_put_keycode(s, 0xf0);
679 ps2_put_keycode(s, keycode);
680 } else if (key->down) {
681 ps2_queue(&s->common, 0x00);
682 } else if (s->translate) {
683 ps2_queue(&s->common, 0x80);
684 } else {
685 ps2_queue(&s->common, 0xf0);
686 ps2_queue(&s->common, 0x00);
691 uint32_t ps2_read_data(void *opaque)
693 PS2State *s = (PS2State *)opaque;
694 PS2Queue *q;
695 int val, index;
697 trace_ps2_read_data(opaque);
698 q = &s->queue;
699 if (q->count == 0) {
700 /* NOTE: if no data left, we return the last keyboard one
701 (needed for EMM386) */
702 /* XXX: need a timer to do things correctly */
703 index = q->rptr - 1;
704 if (index < 0)
705 index = PS2_QUEUE_SIZE - 1;
706 val = q->data[index];
707 } else {
708 val = q->data[q->rptr];
709 if (++q->rptr == PS2_QUEUE_SIZE)
710 q->rptr = 0;
711 q->count--;
712 /* reading deasserts IRQ */
713 s->update_irq(s->update_arg, 0);
714 /* reassert IRQs if data left */
715 s->update_irq(s->update_arg, q->count != 0);
717 return val;
720 static void ps2_set_ledstate(PS2KbdState *s, int ledstate)
722 trace_ps2_set_ledstate(s, ledstate);
723 s->ledstate = ledstate;
724 kbd_put_ledstate(ledstate);
727 static void ps2_reset_keyboard(PS2KbdState *s)
729 trace_ps2_reset_keyboard(s);
730 s->scan_enabled = 1;
731 s->scancode_set = 2;
732 ps2_set_ledstate(s, 0);
735 void ps2_write_keyboard(void *opaque, int val)
737 PS2KbdState *s = (PS2KbdState *)opaque;
739 trace_ps2_write_keyboard(opaque, val);
740 switch(s->common.write_cmd) {
741 default:
742 case -1:
743 switch(val) {
744 case 0x00:
745 ps2_queue(&s->common, KBD_REPLY_ACK);
746 break;
747 case 0x05:
748 ps2_queue(&s->common, KBD_REPLY_RESEND);
749 break;
750 case KBD_CMD_GET_ID:
751 ps2_queue(&s->common, KBD_REPLY_ACK);
752 /* We emulate a MF2 AT keyboard here */
753 ps2_queue(&s->common, KBD_REPLY_ID);
754 if (s->translate)
755 ps2_queue(&s->common, 0x41);
756 else
757 ps2_queue(&s->common, 0x83);
758 break;
759 case KBD_CMD_ECHO:
760 ps2_queue(&s->common, KBD_CMD_ECHO);
761 break;
762 case KBD_CMD_ENABLE:
763 s->scan_enabled = 1;
764 ps2_queue(&s->common, KBD_REPLY_ACK);
765 break;
766 case KBD_CMD_SCANCODE:
767 case KBD_CMD_SET_LEDS:
768 case KBD_CMD_SET_RATE:
769 s->common.write_cmd = val;
770 ps2_queue(&s->common, KBD_REPLY_ACK);
771 break;
772 case KBD_CMD_RESET_DISABLE:
773 ps2_reset_keyboard(s);
774 s->scan_enabled = 0;
775 ps2_queue(&s->common, KBD_REPLY_ACK);
776 break;
777 case KBD_CMD_RESET_ENABLE:
778 ps2_reset_keyboard(s);
779 s->scan_enabled = 1;
780 ps2_queue(&s->common, KBD_REPLY_ACK);
781 break;
782 case KBD_CMD_RESET:
783 ps2_reset_keyboard(s);
784 ps2_queue(&s->common, KBD_REPLY_ACK);
785 ps2_queue(&s->common, KBD_REPLY_POR);
786 break;
787 default:
788 ps2_queue(&s->common, KBD_REPLY_RESEND);
789 break;
791 break;
792 case KBD_CMD_SCANCODE:
793 if (val == 0) {
794 ps2_queue(&s->common, KBD_REPLY_ACK);
795 ps2_put_keycode(s, s->scancode_set);
796 } else if (val >= 1 && val <= 3) {
797 s->scancode_set = val;
798 ps2_queue(&s->common, KBD_REPLY_ACK);
799 } else {
800 ps2_queue(&s->common, KBD_REPLY_RESEND);
802 s->common.write_cmd = -1;
803 break;
804 case KBD_CMD_SET_LEDS:
805 ps2_set_ledstate(s, val);
806 ps2_queue(&s->common, KBD_REPLY_ACK);
807 s->common.write_cmd = -1;
808 break;
809 case KBD_CMD_SET_RATE:
810 ps2_queue(&s->common, KBD_REPLY_ACK);
811 s->common.write_cmd = -1;
812 break;
816 /* Set the scancode translation mode.
817 0 = raw scancodes.
818 1 = translated scancodes (used by qemu internally). */
820 void ps2_keyboard_set_translation(void *opaque, int mode)
822 PS2KbdState *s = (PS2KbdState *)opaque;
823 trace_ps2_keyboard_set_translation(opaque, mode);
824 s->translate = mode;
827 static void ps2_mouse_send_packet(PS2MouseState *s)
829 unsigned int b;
830 int dx1, dy1, dz1;
832 dx1 = s->mouse_dx;
833 dy1 = s->mouse_dy;
834 dz1 = s->mouse_dz;
835 /* XXX: increase range to 8 bits ? */
836 if (dx1 > 127)
837 dx1 = 127;
838 else if (dx1 < -127)
839 dx1 = -127;
840 if (dy1 > 127)
841 dy1 = 127;
842 else if (dy1 < -127)
843 dy1 = -127;
844 b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
845 ps2_queue(&s->common, b);
846 ps2_queue(&s->common, dx1 & 0xff);
847 ps2_queue(&s->common, dy1 & 0xff);
848 /* extra byte for IMPS/2 or IMEX */
849 switch(s->mouse_type) {
850 default:
851 break;
852 case 3:
853 if (dz1 > 127)
854 dz1 = 127;
855 else if (dz1 < -127)
856 dz1 = -127;
857 ps2_queue(&s->common, dz1 & 0xff);
858 break;
859 case 4:
860 if (dz1 > 7)
861 dz1 = 7;
862 else if (dz1 < -7)
863 dz1 = -7;
864 b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
865 ps2_queue(&s->common, b);
866 break;
869 trace_ps2_mouse_send_packet(s, dx1, dy1, dz1, b);
870 /* update deltas */
871 s->mouse_dx -= dx1;
872 s->mouse_dy -= dy1;
873 s->mouse_dz -= dz1;
876 static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
877 InputEvent *evt)
879 static const int bmap[INPUT_BUTTON__MAX] = {
880 [INPUT_BUTTON_LEFT] = MOUSE_EVENT_LBUTTON,
881 [INPUT_BUTTON_MIDDLE] = MOUSE_EVENT_MBUTTON,
882 [INPUT_BUTTON_RIGHT] = MOUSE_EVENT_RBUTTON,
884 PS2MouseState *s = (PS2MouseState *)dev;
885 InputMoveEvent *move;
886 InputBtnEvent *btn;
888 /* check if deltas are recorded when disabled */
889 if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
890 return;
892 switch (evt->type) {
893 case INPUT_EVENT_KIND_REL:
894 move = evt->u.rel.data;
895 if (move->axis == INPUT_AXIS_X) {
896 s->mouse_dx += move->value;
897 } else if (move->axis == INPUT_AXIS_Y) {
898 s->mouse_dy -= move->value;
900 break;
902 case INPUT_EVENT_KIND_BTN:
903 btn = evt->u.btn.data;
904 if (btn->down) {
905 s->mouse_buttons |= bmap[btn->button];
906 if (btn->button == INPUT_BUTTON_WHEEL_UP) {
907 s->mouse_dz--;
908 } else if (btn->button == INPUT_BUTTON_WHEEL_DOWN) {
909 s->mouse_dz++;
911 } else {
912 s->mouse_buttons &= ~bmap[btn->button];
914 break;
916 default:
917 /* keep gcc happy */
918 break;
922 static void ps2_mouse_sync(DeviceState *dev)
924 PS2MouseState *s = (PS2MouseState *)dev;
926 if (s->mouse_buttons) {
927 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
929 if (!(s->mouse_status & MOUSE_STATUS_REMOTE)) {
930 while (s->common.queue.count < PS2_QUEUE_SIZE - 4) {
931 /* if not remote, send event. Multiple events are sent if
932 too big deltas */
933 ps2_mouse_send_packet(s);
934 if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
935 break;
940 void ps2_mouse_fake_event(void *opaque)
942 PS2MouseState *s = opaque;
943 trace_ps2_mouse_fake_event(opaque);
944 s->mouse_dx++;
945 ps2_mouse_sync(opaque);
948 void ps2_write_mouse(void *opaque, int val)
950 PS2MouseState *s = (PS2MouseState *)opaque;
952 trace_ps2_write_mouse(opaque, val);
953 #ifdef DEBUG_MOUSE
954 printf("kbd: write mouse 0x%02x\n", val);
955 #endif
956 switch(s->common.write_cmd) {
957 default:
958 case -1:
959 /* mouse command */
960 if (s->mouse_wrap) {
961 if (val == AUX_RESET_WRAP) {
962 s->mouse_wrap = 0;
963 ps2_queue(&s->common, AUX_ACK);
964 return;
965 } else if (val != AUX_RESET) {
966 ps2_queue(&s->common, val);
967 return;
970 switch(val) {
971 case AUX_SET_SCALE11:
972 s->mouse_status &= ~MOUSE_STATUS_SCALE21;
973 ps2_queue(&s->common, AUX_ACK);
974 break;
975 case AUX_SET_SCALE21:
976 s->mouse_status |= MOUSE_STATUS_SCALE21;
977 ps2_queue(&s->common, AUX_ACK);
978 break;
979 case AUX_SET_STREAM:
980 s->mouse_status &= ~MOUSE_STATUS_REMOTE;
981 ps2_queue(&s->common, AUX_ACK);
982 break;
983 case AUX_SET_WRAP:
984 s->mouse_wrap = 1;
985 ps2_queue(&s->common, AUX_ACK);
986 break;
987 case AUX_SET_REMOTE:
988 s->mouse_status |= MOUSE_STATUS_REMOTE;
989 ps2_queue(&s->common, AUX_ACK);
990 break;
991 case AUX_GET_TYPE:
992 ps2_queue(&s->common, AUX_ACK);
993 ps2_queue(&s->common, s->mouse_type);
994 break;
995 case AUX_SET_RES:
996 case AUX_SET_SAMPLE:
997 s->common.write_cmd = val;
998 ps2_queue(&s->common, AUX_ACK);
999 break;
1000 case AUX_GET_SCALE:
1001 ps2_queue(&s->common, AUX_ACK);
1002 ps2_queue(&s->common, s->mouse_status);
1003 ps2_queue(&s->common, s->mouse_resolution);
1004 ps2_queue(&s->common, s->mouse_sample_rate);
1005 break;
1006 case AUX_POLL:
1007 ps2_queue(&s->common, AUX_ACK);
1008 ps2_mouse_send_packet(s);
1009 break;
1010 case AUX_ENABLE_DEV:
1011 s->mouse_status |= MOUSE_STATUS_ENABLED;
1012 ps2_queue(&s->common, AUX_ACK);
1013 break;
1014 case AUX_DISABLE_DEV:
1015 s->mouse_status &= ~MOUSE_STATUS_ENABLED;
1016 ps2_queue(&s->common, AUX_ACK);
1017 break;
1018 case AUX_SET_DEFAULT:
1019 s->mouse_sample_rate = 100;
1020 s->mouse_resolution = 2;
1021 s->mouse_status = 0;
1022 ps2_queue(&s->common, AUX_ACK);
1023 break;
1024 case AUX_RESET:
1025 s->mouse_sample_rate = 100;
1026 s->mouse_resolution = 2;
1027 s->mouse_status = 0;
1028 s->mouse_type = 0;
1029 ps2_queue(&s->common, AUX_ACK);
1030 ps2_queue(&s->common, 0xaa);
1031 ps2_queue(&s->common, s->mouse_type);
1032 break;
1033 default:
1034 break;
1036 break;
1037 case AUX_SET_SAMPLE:
1038 s->mouse_sample_rate = val;
1039 /* detect IMPS/2 or IMEX */
1040 switch(s->mouse_detect_state) {
1041 default:
1042 case 0:
1043 if (val == 200)
1044 s->mouse_detect_state = 1;
1045 break;
1046 case 1:
1047 if (val == 100)
1048 s->mouse_detect_state = 2;
1049 else if (val == 200)
1050 s->mouse_detect_state = 3;
1051 else
1052 s->mouse_detect_state = 0;
1053 break;
1054 case 2:
1055 if (val == 80)
1056 s->mouse_type = 3; /* IMPS/2 */
1057 s->mouse_detect_state = 0;
1058 break;
1059 case 3:
1060 if (val == 80)
1061 s->mouse_type = 4; /* IMEX */
1062 s->mouse_detect_state = 0;
1063 break;
1065 ps2_queue(&s->common, AUX_ACK);
1066 s->common.write_cmd = -1;
1067 break;
1068 case AUX_SET_RES:
1069 s->mouse_resolution = val;
1070 ps2_queue(&s->common, AUX_ACK);
1071 s->common.write_cmd = -1;
1072 break;
1076 static void ps2_common_reset(PS2State *s)
1078 PS2Queue *q;
1079 s->write_cmd = -1;
1080 q = &s->queue;
1081 q->rptr = 0;
1082 q->wptr = 0;
1083 q->count = 0;
1084 s->update_irq(s->update_arg, 0);
1087 static void ps2_common_post_load(PS2State *s)
1089 PS2Queue *q = &s->queue;
1090 int size;
1091 int i;
1092 int tmp_data[PS2_QUEUE_SIZE];
1094 /* set the useful data buffer queue size, < PS2_QUEUE_SIZE */
1095 size = q->count > PS2_QUEUE_SIZE ? 0 : q->count;
1097 /* move the queue elements to the start of data array */
1098 if (size > 0) {
1099 for (i = 0; i < size; i++) {
1100 /* move the queue elements to the temporary buffer */
1101 tmp_data[i] = q->data[q->rptr];
1102 if (++q->rptr == 256) {
1103 q->rptr = 0;
1106 memcpy(q->data, tmp_data, size);
1108 /* reset rptr/wptr/count */
1109 q->rptr = 0;
1110 q->wptr = size;
1111 q->count = size;
1112 s->update_irq(s->update_arg, q->count != 0);
1115 static void ps2_kbd_reset(void *opaque)
1117 PS2KbdState *s = (PS2KbdState *) opaque;
1119 trace_ps2_kbd_reset(opaque);
1120 ps2_common_reset(&s->common);
1121 s->scan_enabled = 0;
1122 s->translate = 0;
1123 s->scancode_set = 2;
1126 static void ps2_mouse_reset(void *opaque)
1128 PS2MouseState *s = (PS2MouseState *) opaque;
1130 trace_ps2_mouse_reset(opaque);
1131 ps2_common_reset(&s->common);
1132 s->mouse_status = 0;
1133 s->mouse_resolution = 0;
1134 s->mouse_sample_rate = 0;
1135 s->mouse_wrap = 0;
1136 s->mouse_type = 0;
1137 s->mouse_detect_state = 0;
1138 s->mouse_dx = 0;
1139 s->mouse_dy = 0;
1140 s->mouse_dz = 0;
1141 s->mouse_buttons = 0;
1144 static const VMStateDescription vmstate_ps2_common = {
1145 .name = "PS2 Common State",
1146 .version_id = 3,
1147 .minimum_version_id = 2,
1148 .fields = (VMStateField[]) {
1149 VMSTATE_INT32(write_cmd, PS2State),
1150 VMSTATE_INT32(queue.rptr, PS2State),
1151 VMSTATE_INT32(queue.wptr, PS2State),
1152 VMSTATE_INT32(queue.count, PS2State),
1153 VMSTATE_BUFFER(queue.data, PS2State),
1154 VMSTATE_END_OF_LIST()
1158 static bool ps2_keyboard_ledstate_needed(void *opaque)
1160 PS2KbdState *s = opaque;
1162 return s->ledstate != 0; /* 0 is default state */
1165 static int ps2_kbd_ledstate_post_load(void *opaque, int version_id)
1167 PS2KbdState *s = opaque;
1169 kbd_put_ledstate(s->ledstate);
1170 return 0;
1173 static const VMStateDescription vmstate_ps2_keyboard_ledstate = {
1174 .name = "ps2kbd/ledstate",
1175 .version_id = 3,
1176 .minimum_version_id = 2,
1177 .post_load = ps2_kbd_ledstate_post_load,
1178 .needed = ps2_keyboard_ledstate_needed,
1179 .fields = (VMStateField[]) {
1180 VMSTATE_INT32(ledstate, PS2KbdState),
1181 VMSTATE_END_OF_LIST()
1185 static bool ps2_keyboard_need_high_bit_needed(void *opaque)
1187 PS2KbdState *s = opaque;
1188 return s->need_high_bit != 0; /* 0 is the usual state */
1191 static const VMStateDescription vmstate_ps2_keyboard_need_high_bit = {
1192 .name = "ps2kbd/need_high_bit",
1193 .version_id = 1,
1194 .minimum_version_id = 1,
1195 .needed = ps2_keyboard_need_high_bit_needed,
1196 .fields = (VMStateField[]) {
1197 VMSTATE_BOOL(need_high_bit, PS2KbdState),
1198 VMSTATE_END_OF_LIST()
1202 static int ps2_kbd_post_load(void* opaque, int version_id)
1204 PS2KbdState *s = (PS2KbdState*)opaque;
1205 PS2State *ps2 = &s->common;
1207 if (version_id == 2)
1208 s->scancode_set=2;
1210 ps2_common_post_load(ps2);
1212 return 0;
1215 static void ps2_kbd_pre_save(void *opaque)
1217 PS2KbdState *s = (PS2KbdState *)opaque;
1218 PS2State *ps2 = &s->common;
1220 ps2_common_post_load(ps2);
1223 static const VMStateDescription vmstate_ps2_keyboard = {
1224 .name = "ps2kbd",
1225 .version_id = 3,
1226 .minimum_version_id = 2,
1227 .post_load = ps2_kbd_post_load,
1228 .pre_save = ps2_kbd_pre_save,
1229 .fields = (VMStateField[]) {
1230 VMSTATE_STRUCT(common, PS2KbdState, 0, vmstate_ps2_common, PS2State),
1231 VMSTATE_INT32(scan_enabled, PS2KbdState),
1232 VMSTATE_INT32(translate, PS2KbdState),
1233 VMSTATE_INT32_V(scancode_set, PS2KbdState,3),
1234 VMSTATE_END_OF_LIST()
1236 .subsections = (const VMStateDescription*[]) {
1237 &vmstate_ps2_keyboard_ledstate,
1238 &vmstate_ps2_keyboard_need_high_bit,
1239 NULL
1243 static int ps2_mouse_post_load(void *opaque, int version_id)
1245 PS2MouseState *s = (PS2MouseState *)opaque;
1246 PS2State *ps2 = &s->common;
1248 ps2_common_post_load(ps2);
1250 return 0;
1253 static void ps2_mouse_pre_save(void *opaque)
1255 PS2MouseState *s = (PS2MouseState *)opaque;
1256 PS2State *ps2 = &s->common;
1258 ps2_common_post_load(ps2);
1261 static const VMStateDescription vmstate_ps2_mouse = {
1262 .name = "ps2mouse",
1263 .version_id = 2,
1264 .minimum_version_id = 2,
1265 .post_load = ps2_mouse_post_load,
1266 .pre_save = ps2_mouse_pre_save,
1267 .fields = (VMStateField[]) {
1268 VMSTATE_STRUCT(common, PS2MouseState, 0, vmstate_ps2_common, PS2State),
1269 VMSTATE_UINT8(mouse_status, PS2MouseState),
1270 VMSTATE_UINT8(mouse_resolution, PS2MouseState),
1271 VMSTATE_UINT8(mouse_sample_rate, PS2MouseState),
1272 VMSTATE_UINT8(mouse_wrap, PS2MouseState),
1273 VMSTATE_UINT8(mouse_type, PS2MouseState),
1274 VMSTATE_UINT8(mouse_detect_state, PS2MouseState),
1275 VMSTATE_INT32(mouse_dx, PS2MouseState),
1276 VMSTATE_INT32(mouse_dy, PS2MouseState),
1277 VMSTATE_INT32(mouse_dz, PS2MouseState),
1278 VMSTATE_UINT8(mouse_buttons, PS2MouseState),
1279 VMSTATE_END_OF_LIST()
1283 static QemuInputHandler ps2_keyboard_handler = {
1284 .name = "QEMU PS/2 Keyboard",
1285 .mask = INPUT_EVENT_MASK_KEY,
1286 .event = ps2_keyboard_event,
1289 void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
1291 PS2KbdState *s = (PS2KbdState *)g_malloc0(sizeof(PS2KbdState));
1293 trace_ps2_kbd_init(s);
1294 s->common.update_irq = update_irq;
1295 s->common.update_arg = update_arg;
1296 s->scancode_set = 2;
1297 vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s);
1298 qemu_input_handler_register((DeviceState *)s,
1299 &ps2_keyboard_handler);
1300 qemu_register_reset(ps2_kbd_reset, s);
1301 return s;
1304 static QemuInputHandler ps2_mouse_handler = {
1305 .name = "QEMU PS/2 Mouse",
1306 .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
1307 .event = ps2_mouse_event,
1308 .sync = ps2_mouse_sync,
1311 void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
1313 PS2MouseState *s = (PS2MouseState *)g_malloc0(sizeof(PS2MouseState));
1315 trace_ps2_mouse_init(s);
1316 s->common.update_irq = update_irq;
1317 s->common.update_arg = update_arg;
1318 vmstate_register(NULL, 0, &vmstate_ps2_mouse, s);
1319 qemu_input_handler_register((DeviceState *)s,
1320 &ps2_mouse_handler);
1321 qemu_register_reset(ps2_mouse_reset, s);
1322 return s;