trace: dynamically allocate trace_dstate in CPUState
[qemu/ar7.git] / hw / input / ps2.c
blob0d14de08a62d97fca436b34489a04933f94b699c
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 typedef struct {
82 /* Keep the data array 256 bytes long, which compatibility
83 with older qemu versions. */
84 uint8_t data[256];
85 int rptr, wptr, count;
86 } PS2Queue;
88 typedef struct {
89 PS2Queue queue;
90 int32_t write_cmd;
91 void (*update_irq)(void *, int);
92 void *update_arg;
93 } PS2State;
95 typedef struct {
96 PS2State common;
97 int scan_enabled;
98 int translate;
99 int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */
100 int ledstate;
101 bool need_high_bit;
102 } PS2KbdState;
104 typedef struct {
105 PS2State common;
106 uint8_t mouse_status;
107 uint8_t mouse_resolution;
108 uint8_t mouse_sample_rate;
109 uint8_t mouse_wrap;
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 */
113 int mouse_dy;
114 int mouse_dz;
115 uint8_t mouse_buttons;
116 } PS2MouseState;
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,
227 #if 0
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,
250 #endif
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,
366 #if 0
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,
389 #endif
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)
550 return;
551 q->data[q->wptr] = b;
552 if (++q->wptr == PS2_QUEUE_SIZE)
553 q->wptr = 0;
554 q->count++;
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);
566 if (s->translate) {
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;
572 } else {
573 ps2_queue(&s->common, translate_table[keycode]);
575 } else {
576 ps2_queue(&s->common, keycode);
580 static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,
581 InputEvent *evt)
583 PS2KbdState *s = (PS2KbdState *)dev;
584 InputKeyEvent *key = evt->u.key.data;
585 int qcode;
586 uint16_t keycode;
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) {
594 if (key->down) {
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) {
603 if (key->down) {
604 ps2_put_keycode(s, 0xe0);
605 ps2_put_keycode(s, 0x2a);
606 ps2_put_keycode(s, 0xe0);
607 ps2_put_keycode(s, 0x37);
608 } else {
609 ps2_put_keycode(s, 0xe0);
610 ps2_put_keycode(s, 0xb7);
611 ps2_put_keycode(s, 0xe0);
612 ps2_put_keycode(s, 0xaa);
614 } else {
615 keycode = qcode_to_keycode_set1[qcode];
616 if (keycode) {
617 if (keycode & 0xff00) {
618 ps2_put_keycode(s, keycode >> 8);
620 if (!key->down) {
621 keycode |= 0x80;
623 ps2_put_keycode(s, keycode & 0xff);
624 } else {
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) {
631 if (key->down) {
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) {
642 if (key->down) {
643 ps2_put_keycode(s, 0xe0);
644 ps2_put_keycode(s, 0x12);
645 ps2_put_keycode(s, 0xe0);
646 ps2_put_keycode(s, 0x7c);
647 } else {
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);
655 } else {
656 keycode = qcode_to_keycode_set2[qcode];
657 if (keycode) {
658 if (keycode & 0xff00) {
659 ps2_put_keycode(s, keycode >> 8);
661 if (!key->down) {
662 ps2_put_keycode(s, 0xf0);
664 ps2_put_keycode(s, keycode & 0xff);
665 } else {
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];
672 if (keycode) {
673 /* FIXME: break code should be configured on a key by key basis */
674 if (!key->down) {
675 ps2_put_keycode(s, 0xf0);
677 ps2_put_keycode(s, keycode);
678 } else {
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;
688 PS2Queue *q;
689 int val, index;
691 trace_ps2_read_data(opaque);
692 q = &s->queue;
693 if (q->count == 0) {
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 */
697 index = q->rptr - 1;
698 if (index < 0)
699 index = PS2_QUEUE_SIZE - 1;
700 val = q->data[index];
701 } else {
702 val = q->data[q->rptr];
703 if (++q->rptr == PS2_QUEUE_SIZE)
704 q->rptr = 0;
705 q->count--;
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);
711 return val;
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);
724 s->scan_enabled = 1;
725 s->scancode_set = 2;
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) {
735 default:
736 case -1:
737 switch(val) {
738 case 0x00:
739 ps2_queue(&s->common, KBD_REPLY_ACK);
740 break;
741 case 0x05:
742 ps2_queue(&s->common, KBD_REPLY_RESEND);
743 break;
744 case KBD_CMD_GET_ID:
745 ps2_queue(&s->common, KBD_REPLY_ACK);
746 /* We emulate a MF2 AT keyboard here */
747 ps2_queue(&s->common, KBD_REPLY_ID);
748 if (s->translate)
749 ps2_queue(&s->common, 0x41);
750 else
751 ps2_queue(&s->common, 0x83);
752 break;
753 case KBD_CMD_ECHO:
754 ps2_queue(&s->common, KBD_CMD_ECHO);
755 break;
756 case KBD_CMD_ENABLE:
757 s->scan_enabled = 1;
758 ps2_queue(&s->common, KBD_REPLY_ACK);
759 break;
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);
765 break;
766 case KBD_CMD_RESET_DISABLE:
767 ps2_reset_keyboard(s);
768 s->scan_enabled = 0;
769 ps2_queue(&s->common, KBD_REPLY_ACK);
770 break;
771 case KBD_CMD_RESET_ENABLE:
772 ps2_reset_keyboard(s);
773 s->scan_enabled = 1;
774 ps2_queue(&s->common, KBD_REPLY_ACK);
775 break;
776 case KBD_CMD_RESET:
777 ps2_reset_keyboard(s);
778 ps2_queue(&s->common, KBD_REPLY_ACK);
779 ps2_queue(&s->common, KBD_REPLY_POR);
780 break;
781 default:
782 ps2_queue(&s->common, KBD_REPLY_RESEND);
783 break;
785 break;
786 case KBD_CMD_SCANCODE:
787 if (val == 0) {
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);
793 } else {
794 ps2_queue(&s->common, KBD_REPLY_RESEND);
796 s->common.write_cmd = -1;
797 break;
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;
802 break;
803 case KBD_CMD_SET_RATE:
804 ps2_queue(&s->common, KBD_REPLY_ACK);
805 s->common.write_cmd = -1;
806 break;
810 /* Set the scancode translation mode.
811 0 = raw scancodes.
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);
818 s->translate = mode;
821 static void ps2_mouse_send_packet(PS2MouseState *s)
823 unsigned int b;
824 int dx1, dy1, dz1;
826 dx1 = s->mouse_dx;
827 dy1 = s->mouse_dy;
828 dz1 = s->mouse_dz;
829 /* XXX: increase range to 8 bits ? */
830 if (dx1 > 127)
831 dx1 = 127;
832 else if (dx1 < -127)
833 dx1 = -127;
834 if (dy1 > 127)
835 dy1 = 127;
836 else if (dy1 < -127)
837 dy1 = -127;
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) {
844 default:
845 break;
846 case 3:
847 if (dz1 > 127)
848 dz1 = 127;
849 else if (dz1 < -127)
850 dz1 = -127;
851 ps2_queue(&s->common, dz1 & 0xff);
852 break;
853 case 4:
854 if (dz1 > 7)
855 dz1 = 7;
856 else if (dz1 < -7)
857 dz1 = -7;
858 b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
859 ps2_queue(&s->common, b);
860 break;
863 trace_ps2_mouse_send_packet(s, dx1, dy1, dz1, b);
864 /* update deltas */
865 s->mouse_dx -= dx1;
866 s->mouse_dy -= dy1;
867 s->mouse_dz -= dz1;
870 static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
871 InputEvent *evt)
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;
880 InputBtnEvent *btn;
882 /* check if deltas are recorded when disabled */
883 if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
884 return;
886 switch (evt->type) {
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;
894 break;
896 case INPUT_EVENT_KIND_BTN:
897 btn = evt->u.btn.data;
898 if (btn->down) {
899 s->mouse_buttons |= bmap[btn->button];
900 if (btn->button == INPUT_BUTTON_WHEEL_UP) {
901 s->mouse_dz--;
902 } else if (btn->button == INPUT_BUTTON_WHEEL_DOWN) {
903 s->mouse_dz++;
905 } else {
906 s->mouse_buttons &= ~bmap[btn->button];
908 break;
910 default:
911 /* keep gcc happy */
912 break;
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
926 too big deltas */
927 ps2_mouse_send_packet(s);
928 if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
929 break;
934 void ps2_mouse_fake_event(void *opaque)
936 PS2MouseState *s = opaque;
937 trace_ps2_mouse_fake_event(opaque);
938 s->mouse_dx++;
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);
947 #ifdef DEBUG_MOUSE
948 printf("kbd: write mouse 0x%02x\n", val);
949 #endif
950 switch(s->common.write_cmd) {
951 default:
952 case -1:
953 /* mouse command */
954 if (s->mouse_wrap) {
955 if (val == AUX_RESET_WRAP) {
956 s->mouse_wrap = 0;
957 ps2_queue(&s->common, AUX_ACK);
958 return;
959 } else if (val != AUX_RESET) {
960 ps2_queue(&s->common, val);
961 return;
964 switch(val) {
965 case AUX_SET_SCALE11:
966 s->mouse_status &= ~MOUSE_STATUS_SCALE21;
967 ps2_queue(&s->common, AUX_ACK);
968 break;
969 case AUX_SET_SCALE21:
970 s->mouse_status |= MOUSE_STATUS_SCALE21;
971 ps2_queue(&s->common, AUX_ACK);
972 break;
973 case AUX_SET_STREAM:
974 s->mouse_status &= ~MOUSE_STATUS_REMOTE;
975 ps2_queue(&s->common, AUX_ACK);
976 break;
977 case AUX_SET_WRAP:
978 s->mouse_wrap = 1;
979 ps2_queue(&s->common, AUX_ACK);
980 break;
981 case AUX_SET_REMOTE:
982 s->mouse_status |= MOUSE_STATUS_REMOTE;
983 ps2_queue(&s->common, AUX_ACK);
984 break;
985 case AUX_GET_TYPE:
986 ps2_queue(&s->common, AUX_ACK);
987 ps2_queue(&s->common, s->mouse_type);
988 break;
989 case AUX_SET_RES:
990 case AUX_SET_SAMPLE:
991 s->common.write_cmd = val;
992 ps2_queue(&s->common, AUX_ACK);
993 break;
994 case AUX_GET_SCALE:
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);
999 break;
1000 case AUX_POLL:
1001 ps2_queue(&s->common, AUX_ACK);
1002 ps2_mouse_send_packet(s);
1003 break;
1004 case AUX_ENABLE_DEV:
1005 s->mouse_status |= MOUSE_STATUS_ENABLED;
1006 ps2_queue(&s->common, AUX_ACK);
1007 break;
1008 case AUX_DISABLE_DEV:
1009 s->mouse_status &= ~MOUSE_STATUS_ENABLED;
1010 ps2_queue(&s->common, AUX_ACK);
1011 break;
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);
1017 break;
1018 case AUX_RESET:
1019 s->mouse_sample_rate = 100;
1020 s->mouse_resolution = 2;
1021 s->mouse_status = 0;
1022 s->mouse_type = 0;
1023 ps2_queue(&s->common, AUX_ACK);
1024 ps2_queue(&s->common, 0xaa);
1025 ps2_queue(&s->common, s->mouse_type);
1026 break;
1027 default:
1028 break;
1030 break;
1031 case AUX_SET_SAMPLE:
1032 s->mouse_sample_rate = val;
1033 /* detect IMPS/2 or IMEX */
1034 switch(s->mouse_detect_state) {
1035 default:
1036 case 0:
1037 if (val == 200)
1038 s->mouse_detect_state = 1;
1039 break;
1040 case 1:
1041 if (val == 100)
1042 s->mouse_detect_state = 2;
1043 else if (val == 200)
1044 s->mouse_detect_state = 3;
1045 else
1046 s->mouse_detect_state = 0;
1047 break;
1048 case 2:
1049 if (val == 80)
1050 s->mouse_type = 3; /* IMPS/2 */
1051 s->mouse_detect_state = 0;
1052 break;
1053 case 3:
1054 if (val == 80)
1055 s->mouse_type = 4; /* IMEX */
1056 s->mouse_detect_state = 0;
1057 break;
1059 ps2_queue(&s->common, AUX_ACK);
1060 s->common.write_cmd = -1;
1061 break;
1062 case AUX_SET_RES:
1063 s->mouse_resolution = val;
1064 ps2_queue(&s->common, AUX_ACK);
1065 s->common.write_cmd = -1;
1066 break;
1070 static void ps2_common_reset(PS2State *s)
1072 PS2Queue *q;
1073 s->write_cmd = -1;
1074 q = &s->queue;
1075 q->rptr = 0;
1076 q->wptr = 0;
1077 q->count = 0;
1078 s->update_irq(s->update_arg, 0);
1081 static void ps2_common_post_load(PS2State *s)
1083 PS2Queue *q = &s->queue;
1084 int size;
1085 int i;
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 */
1092 if (size > 0) {
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) {
1097 q->rptr = 0;
1100 memcpy(q->data, tmp_data, size);
1102 /* reset rptr/wptr/count */
1103 q->rptr = 0;
1104 q->wptr = size;
1105 q->count = size;
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;
1116 s->translate = 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;
1129 s->mouse_wrap = 0;
1130 s->mouse_type = 0;
1131 s->mouse_detect_state = 0;
1132 s->mouse_dx = 0;
1133 s->mouse_dy = 0;
1134 s->mouse_dz = 0;
1135 s->mouse_buttons = 0;
1138 static const VMStateDescription vmstate_ps2_common = {
1139 .name = "PS2 Common State",
1140 .version_id = 3,
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);
1164 return 0;
1167 static const VMStateDescription vmstate_ps2_keyboard_ledstate = {
1168 .name = "ps2kbd/ledstate",
1169 .version_id = 3,
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",
1187 .version_id = 1,
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)
1202 s->scancode_set=2;
1204 ps2_common_post_load(ps2);
1206 return 0;
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 = {
1218 .name = "ps2kbd",
1219 .version_id = 3,
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,
1233 NULL
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);
1244 return 0;
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 = {
1256 .name = "ps2mouse",
1257 .version_id = 2,
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);
1295 return 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);
1316 return s;