ps2: check PS2Queue pointers in post_load routine
[qemu/ar7.git] / hw / input / ps2.c
blobde171a28dd205a2caf7dcc921d43a157786a410d
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 (s->modifiers & (MOD_CTRL_L | MOD_CTRL_R)) {
645 if (key->down) {
646 ps2_put_keycode(s, 0xe0);
647 ps2_put_keycode(s, 0x46);
648 ps2_put_keycode(s, 0xe0);
649 ps2_put_keycode(s, 0xc6);
651 } else {
652 if (key->down) {
653 ps2_put_keycode(s, 0xe1);
654 ps2_put_keycode(s, 0x1d);
655 ps2_put_keycode(s, 0x45);
656 ps2_put_keycode(s, 0xe1);
657 ps2_put_keycode(s, 0x9d);
658 ps2_put_keycode(s, 0xc5);
661 } else if (qcode == Q_KEY_CODE_PRINT) {
662 if (s->modifiers & MOD_ALT_L) {
663 if (key->down) {
664 ps2_put_keycode(s, 0xb8);
665 ps2_put_keycode(s, 0x38);
666 ps2_put_keycode(s, 0x54);
667 } else {
668 ps2_put_keycode(s, 0xd4);
669 ps2_put_keycode(s, 0xb8);
670 ps2_put_keycode(s, 0x38);
672 } else if (s->modifiers & MOD_ALT_R) {
673 if (key->down) {
674 ps2_put_keycode(s, 0xe0);
675 ps2_put_keycode(s, 0xb8);
676 ps2_put_keycode(s, 0xe0);
677 ps2_put_keycode(s, 0x38);
678 ps2_put_keycode(s, 0x54);
679 } else {
680 ps2_put_keycode(s, 0xd4);
681 ps2_put_keycode(s, 0xe0);
682 ps2_put_keycode(s, 0xb8);
683 ps2_put_keycode(s, 0xe0);
684 ps2_put_keycode(s, 0x38);
686 } else if (s->modifiers & (MOD_SHIFT_L | MOD_CTRL_L |
687 MOD_SHIFT_R | MOD_CTRL_R)) {
688 if (key->down) {
689 ps2_put_keycode(s, 0xe0);
690 ps2_put_keycode(s, 0x37);
691 } else {
692 ps2_put_keycode(s, 0xe0);
693 ps2_put_keycode(s, 0xb7);
695 } else {
696 if (key->down) {
697 ps2_put_keycode(s, 0xe0);
698 ps2_put_keycode(s, 0x2a);
699 ps2_put_keycode(s, 0xe0);
700 ps2_put_keycode(s, 0x37);
701 } else {
702 ps2_put_keycode(s, 0xe0);
703 ps2_put_keycode(s, 0xb7);
704 ps2_put_keycode(s, 0xe0);
705 ps2_put_keycode(s, 0xaa);
708 } else {
709 keycode = qcode_to_keycode_set1[qcode];
710 if (keycode) {
711 if (keycode & 0xff00) {
712 ps2_put_keycode(s, keycode >> 8);
714 if (!key->down) {
715 keycode |= 0x80;
717 ps2_put_keycode(s, keycode & 0xff);
718 } else {
719 qemu_log_mask(LOG_UNIMP,
720 "ps2: ignoring key with qcode %d\n", qcode);
723 } else if (s->scancode_set == 2) {
724 if (qcode == Q_KEY_CODE_PAUSE) {
725 if (s->modifiers & (MOD_CTRL_L | MOD_CTRL_R)) {
726 if (key->down) {
727 ps2_put_keycode(s, 0xe0);
728 ps2_put_keycode(s, 0x7e);
729 ps2_put_keycode(s, 0xe0);
730 ps2_put_keycode(s, 0xf0);
731 ps2_put_keycode(s, 0x7e);
733 } else {
734 if (key->down) {
735 ps2_put_keycode(s, 0xe1);
736 ps2_put_keycode(s, 0x14);
737 ps2_put_keycode(s, 0x77);
738 ps2_put_keycode(s, 0xe1);
739 ps2_put_keycode(s, 0xf0);
740 ps2_put_keycode(s, 0x14);
741 ps2_put_keycode(s, 0xf0);
742 ps2_put_keycode(s, 0x77);
745 } else if (qcode == Q_KEY_CODE_PRINT) {
746 if (s->modifiers & MOD_ALT_L) {
747 if (key->down) {
748 ps2_put_keycode(s, 0xf0);
749 ps2_put_keycode(s, 0x11);
750 ps2_put_keycode(s, 0x11);
751 ps2_put_keycode(s, 0x84);
752 } else {
753 ps2_put_keycode(s, 0xf0);
754 ps2_put_keycode(s, 0x84);
755 ps2_put_keycode(s, 0xf0);
756 ps2_put_keycode(s, 0x11);
757 ps2_put_keycode(s, 0x11);
759 } else if (s->modifiers & MOD_ALT_R) {
760 if (key->down) {
761 ps2_put_keycode(s, 0xe0);
762 ps2_put_keycode(s, 0xf0);
763 ps2_put_keycode(s, 0x11);
764 ps2_put_keycode(s, 0xe0);
765 ps2_put_keycode(s, 0x11);
766 ps2_put_keycode(s, 0x84);
767 } else {
768 ps2_put_keycode(s, 0xf0);
769 ps2_put_keycode(s, 0x84);
770 ps2_put_keycode(s, 0xe0);
771 ps2_put_keycode(s, 0xf0);
772 ps2_put_keycode(s, 0x11);
773 ps2_put_keycode(s, 0xe0);
774 ps2_put_keycode(s, 0x11);
776 } else if (s->modifiers & (MOD_SHIFT_L | MOD_CTRL_L |
777 MOD_SHIFT_R | MOD_CTRL_R)) {
778 if (key->down) {
779 ps2_put_keycode(s, 0xe0);
780 ps2_put_keycode(s, 0x7c);
781 } else {
782 ps2_put_keycode(s, 0xe0);
783 ps2_put_keycode(s, 0xf0);
784 ps2_put_keycode(s, 0x7c);
786 } else {
787 if (key->down) {
788 ps2_put_keycode(s, 0xe0);
789 ps2_put_keycode(s, 0x12);
790 ps2_put_keycode(s, 0xe0);
791 ps2_put_keycode(s, 0x7c);
792 } else {
793 ps2_put_keycode(s, 0xe0);
794 ps2_put_keycode(s, 0xf0);
795 ps2_put_keycode(s, 0x7c);
796 ps2_put_keycode(s, 0xe0);
797 ps2_put_keycode(s, 0xf0);
798 ps2_put_keycode(s, 0x12);
801 } else {
802 keycode = qcode_to_keycode_set2[qcode];
803 if (keycode) {
804 if (keycode & 0xff00) {
805 ps2_put_keycode(s, keycode >> 8);
807 if (!key->down) {
808 ps2_put_keycode(s, 0xf0);
810 ps2_put_keycode(s, keycode & 0xff);
811 } else {
812 qemu_log_mask(LOG_UNIMP,
813 "ps2: ignoring key with qcode %d\n", qcode);
816 } else if (s->scancode_set == 3) {
817 keycode = qcode_to_keycode_set3[qcode];
818 if (keycode) {
819 /* FIXME: break code should be configured on a key by key basis */
820 if (!key->down) {
821 ps2_put_keycode(s, 0xf0);
823 ps2_put_keycode(s, keycode);
824 } else {
825 qemu_log_mask(LOG_UNIMP,
826 "ps2: ignoring key with qcode %d\n", qcode);
831 uint32_t ps2_read_data(PS2State *s)
833 PS2Queue *q;
834 int val, index;
836 trace_ps2_read_data(s);
837 q = &s->queue;
838 if (q->count == 0) {
839 /* NOTE: if no data left, we return the last keyboard one
840 (needed for EMM386) */
841 /* XXX: need a timer to do things correctly */
842 index = q->rptr - 1;
843 if (index < 0)
844 index = PS2_QUEUE_SIZE - 1;
845 val = q->data[index];
846 } else {
847 val = q->data[q->rptr];
848 if (++q->rptr == PS2_QUEUE_SIZE)
849 q->rptr = 0;
850 q->count--;
851 /* reading deasserts IRQ */
852 s->update_irq(s->update_arg, 0);
853 /* reassert IRQs if data left */
854 s->update_irq(s->update_arg, q->count != 0);
856 return val;
859 static void ps2_set_ledstate(PS2KbdState *s, int ledstate)
861 trace_ps2_set_ledstate(s, ledstate);
862 s->ledstate = ledstate;
863 kbd_put_ledstate(ledstate);
866 static void ps2_reset_keyboard(PS2KbdState *s)
868 trace_ps2_reset_keyboard(s);
869 s->scan_enabled = 1;
870 s->scancode_set = 2;
871 ps2_reset_queue(&s->common);
872 ps2_set_ledstate(s, 0);
875 void ps2_write_keyboard(void *opaque, int val)
877 PS2KbdState *s = (PS2KbdState *)opaque;
879 trace_ps2_write_keyboard(opaque, val);
880 switch(s->common.write_cmd) {
881 default:
882 case -1:
883 switch(val) {
884 case 0x00:
885 ps2_queue(&s->common, KBD_REPLY_ACK);
886 break;
887 case 0x05:
888 ps2_queue(&s->common, KBD_REPLY_RESEND);
889 break;
890 case KBD_CMD_GET_ID:
891 ps2_queue(&s->common, KBD_REPLY_ACK);
892 /* We emulate a MF2 AT keyboard here */
893 ps2_queue(&s->common, KBD_REPLY_ID);
894 if (s->translate)
895 ps2_queue(&s->common, 0x41);
896 else
897 ps2_queue(&s->common, 0x83);
898 break;
899 case KBD_CMD_ECHO:
900 ps2_queue(&s->common, KBD_CMD_ECHO);
901 break;
902 case KBD_CMD_ENABLE:
903 s->scan_enabled = 1;
904 ps2_queue(&s->common, KBD_REPLY_ACK);
905 break;
906 case KBD_CMD_SCANCODE:
907 case KBD_CMD_SET_LEDS:
908 case KBD_CMD_SET_RATE:
909 s->common.write_cmd = val;
910 ps2_queue(&s->common, KBD_REPLY_ACK);
911 break;
912 case KBD_CMD_RESET_DISABLE:
913 ps2_reset_keyboard(s);
914 s->scan_enabled = 0;
915 ps2_queue(&s->common, KBD_REPLY_ACK);
916 break;
917 case KBD_CMD_RESET_ENABLE:
918 ps2_reset_keyboard(s);
919 s->scan_enabled = 1;
920 ps2_queue(&s->common, KBD_REPLY_ACK);
921 break;
922 case KBD_CMD_RESET:
923 ps2_reset_keyboard(s);
924 ps2_queue(&s->common, KBD_REPLY_ACK);
925 ps2_queue(&s->common, KBD_REPLY_POR);
926 break;
927 default:
928 ps2_queue(&s->common, KBD_REPLY_RESEND);
929 break;
931 break;
932 case KBD_CMD_SCANCODE:
933 if (val == 0) {
934 ps2_queue(&s->common, KBD_REPLY_ACK);
935 ps2_put_keycode(s, s->scancode_set);
936 } else if (val >= 1 && val <= 3) {
937 s->scancode_set = val;
938 ps2_queue(&s->common, KBD_REPLY_ACK);
939 } else {
940 ps2_queue(&s->common, KBD_REPLY_RESEND);
942 s->common.write_cmd = -1;
943 break;
944 case KBD_CMD_SET_LEDS:
945 ps2_set_ledstate(s, val);
946 ps2_queue(&s->common, KBD_REPLY_ACK);
947 s->common.write_cmd = -1;
948 break;
949 case KBD_CMD_SET_RATE:
950 ps2_queue(&s->common, KBD_REPLY_ACK);
951 s->common.write_cmd = -1;
952 break;
956 /* Set the scancode translation mode.
957 0 = raw scancodes.
958 1 = translated scancodes (used by qemu internally). */
960 void ps2_keyboard_set_translation(void *opaque, int mode)
962 PS2KbdState *s = (PS2KbdState *)opaque;
963 trace_ps2_keyboard_set_translation(opaque, mode);
964 s->translate = mode;
967 static void ps2_mouse_send_packet(PS2MouseState *s)
969 unsigned int b;
970 int dx1, dy1, dz1;
972 dx1 = s->mouse_dx;
973 dy1 = s->mouse_dy;
974 dz1 = s->mouse_dz;
975 /* XXX: increase range to 8 bits ? */
976 if (dx1 > 127)
977 dx1 = 127;
978 else if (dx1 < -127)
979 dx1 = -127;
980 if (dy1 > 127)
981 dy1 = 127;
982 else if (dy1 < -127)
983 dy1 = -127;
984 b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
985 ps2_queue(&s->common, b);
986 ps2_queue(&s->common, dx1 & 0xff);
987 ps2_queue(&s->common, dy1 & 0xff);
988 /* extra byte for IMPS/2 or IMEX */
989 switch(s->mouse_type) {
990 default:
991 break;
992 case 3:
993 if (dz1 > 127)
994 dz1 = 127;
995 else if (dz1 < -127)
996 dz1 = -127;
997 ps2_queue(&s->common, dz1 & 0xff);
998 break;
999 case 4:
1000 if (dz1 > 7)
1001 dz1 = 7;
1002 else if (dz1 < -7)
1003 dz1 = -7;
1004 b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
1005 ps2_queue(&s->common, b);
1006 break;
1009 trace_ps2_mouse_send_packet(s, dx1, dy1, dz1, b);
1010 /* update deltas */
1011 s->mouse_dx -= dx1;
1012 s->mouse_dy -= dy1;
1013 s->mouse_dz -= dz1;
1016 static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
1017 InputEvent *evt)
1019 static const int bmap[INPUT_BUTTON__MAX] = {
1020 [INPUT_BUTTON_LEFT] = PS2_MOUSE_BUTTON_LEFT,
1021 [INPUT_BUTTON_MIDDLE] = PS2_MOUSE_BUTTON_MIDDLE,
1022 [INPUT_BUTTON_RIGHT] = PS2_MOUSE_BUTTON_RIGHT,
1023 [INPUT_BUTTON_SIDE] = PS2_MOUSE_BUTTON_SIDE,
1024 [INPUT_BUTTON_EXTRA] = PS2_MOUSE_BUTTON_EXTRA,
1026 PS2MouseState *s = (PS2MouseState *)dev;
1027 InputMoveEvent *move;
1028 InputBtnEvent *btn;
1030 /* check if deltas are recorded when disabled */
1031 if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
1032 return;
1034 switch (evt->type) {
1035 case INPUT_EVENT_KIND_REL:
1036 move = evt->u.rel.data;
1037 if (move->axis == INPUT_AXIS_X) {
1038 s->mouse_dx += move->value;
1039 } else if (move->axis == INPUT_AXIS_Y) {
1040 s->mouse_dy -= move->value;
1042 break;
1044 case INPUT_EVENT_KIND_BTN:
1045 btn = evt->u.btn.data;
1046 if (btn->down) {
1047 s->mouse_buttons |= bmap[btn->button];
1048 if (btn->button == INPUT_BUTTON_WHEEL_UP) {
1049 s->mouse_dz--;
1050 } else if (btn->button == INPUT_BUTTON_WHEEL_DOWN) {
1051 s->mouse_dz++;
1053 } else {
1054 s->mouse_buttons &= ~bmap[btn->button];
1056 break;
1058 default:
1059 /* keep gcc happy */
1060 break;
1064 static void ps2_mouse_sync(DeviceState *dev)
1066 PS2MouseState *s = (PS2MouseState *)dev;
1068 if (s->mouse_buttons) {
1069 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
1071 if (!(s->mouse_status & MOUSE_STATUS_REMOTE)) {
1072 while (s->common.queue.count < PS2_QUEUE_SIZE - 4) {
1073 /* if not remote, send event. Multiple events are sent if
1074 too big deltas */
1075 ps2_mouse_send_packet(s);
1076 if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
1077 break;
1082 void ps2_mouse_fake_event(void *opaque)
1084 PS2MouseState *s = opaque;
1085 trace_ps2_mouse_fake_event(opaque);
1086 s->mouse_dx++;
1087 ps2_mouse_sync(opaque);
1090 void ps2_write_mouse(void *opaque, int val)
1092 PS2MouseState *s = (PS2MouseState *)opaque;
1094 trace_ps2_write_mouse(opaque, val);
1095 #ifdef DEBUG_MOUSE
1096 printf("kbd: write mouse 0x%02x\n", val);
1097 #endif
1098 switch(s->common.write_cmd) {
1099 default:
1100 case -1:
1101 /* mouse command */
1102 if (s->mouse_wrap) {
1103 if (val == AUX_RESET_WRAP) {
1104 s->mouse_wrap = 0;
1105 ps2_queue(&s->common, AUX_ACK);
1106 return;
1107 } else if (val != AUX_RESET) {
1108 ps2_queue(&s->common, val);
1109 return;
1112 switch(val) {
1113 case AUX_SET_SCALE11:
1114 s->mouse_status &= ~MOUSE_STATUS_SCALE21;
1115 ps2_queue(&s->common, AUX_ACK);
1116 break;
1117 case AUX_SET_SCALE21:
1118 s->mouse_status |= MOUSE_STATUS_SCALE21;
1119 ps2_queue(&s->common, AUX_ACK);
1120 break;
1121 case AUX_SET_STREAM:
1122 s->mouse_status &= ~MOUSE_STATUS_REMOTE;
1123 ps2_queue(&s->common, AUX_ACK);
1124 break;
1125 case AUX_SET_WRAP:
1126 s->mouse_wrap = 1;
1127 ps2_queue(&s->common, AUX_ACK);
1128 break;
1129 case AUX_SET_REMOTE:
1130 s->mouse_status |= MOUSE_STATUS_REMOTE;
1131 ps2_queue(&s->common, AUX_ACK);
1132 break;
1133 case AUX_GET_TYPE:
1134 ps2_queue(&s->common, AUX_ACK);
1135 ps2_queue(&s->common, s->mouse_type);
1136 break;
1137 case AUX_SET_RES:
1138 case AUX_SET_SAMPLE:
1139 s->common.write_cmd = val;
1140 ps2_queue(&s->common, AUX_ACK);
1141 break;
1142 case AUX_GET_SCALE:
1143 ps2_queue(&s->common, AUX_ACK);
1144 ps2_queue(&s->common, s->mouse_status);
1145 ps2_queue(&s->common, s->mouse_resolution);
1146 ps2_queue(&s->common, s->mouse_sample_rate);
1147 break;
1148 case AUX_POLL:
1149 ps2_queue(&s->common, AUX_ACK);
1150 ps2_mouse_send_packet(s);
1151 break;
1152 case AUX_ENABLE_DEV:
1153 s->mouse_status |= MOUSE_STATUS_ENABLED;
1154 ps2_queue(&s->common, AUX_ACK);
1155 break;
1156 case AUX_DISABLE_DEV:
1157 s->mouse_status &= ~MOUSE_STATUS_ENABLED;
1158 ps2_queue(&s->common, AUX_ACK);
1159 break;
1160 case AUX_SET_DEFAULT:
1161 s->mouse_sample_rate = 100;
1162 s->mouse_resolution = 2;
1163 s->mouse_status = 0;
1164 ps2_queue(&s->common, AUX_ACK);
1165 break;
1166 case AUX_RESET:
1167 s->mouse_sample_rate = 100;
1168 s->mouse_resolution = 2;
1169 s->mouse_status = 0;
1170 s->mouse_type = 0;
1171 ps2_queue(&s->common, AUX_ACK);
1172 ps2_queue(&s->common, 0xaa);
1173 ps2_queue(&s->common, s->mouse_type);
1174 break;
1175 default:
1176 break;
1178 break;
1179 case AUX_SET_SAMPLE:
1180 s->mouse_sample_rate = val;
1181 /* detect IMPS/2 or IMEX */
1182 switch(s->mouse_detect_state) {
1183 default:
1184 case 0:
1185 if (val == 200)
1186 s->mouse_detect_state = 1;
1187 break;
1188 case 1:
1189 if (val == 100)
1190 s->mouse_detect_state = 2;
1191 else if (val == 200)
1192 s->mouse_detect_state = 3;
1193 else
1194 s->mouse_detect_state = 0;
1195 break;
1196 case 2:
1197 if (val == 80)
1198 s->mouse_type = 3; /* IMPS/2 */
1199 s->mouse_detect_state = 0;
1200 break;
1201 case 3:
1202 if (val == 80)
1203 s->mouse_type = 4; /* IMEX */
1204 s->mouse_detect_state = 0;
1205 break;
1207 ps2_queue(&s->common, AUX_ACK);
1208 s->common.write_cmd = -1;
1209 break;
1210 case AUX_SET_RES:
1211 s->mouse_resolution = val;
1212 ps2_queue(&s->common, AUX_ACK);
1213 s->common.write_cmd = -1;
1214 break;
1218 static void ps2_common_reset(PS2State *s)
1220 s->write_cmd = -1;
1221 ps2_reset_queue(s);
1222 s->update_irq(s->update_arg, 0);
1225 static void ps2_common_post_load(PS2State *s)
1227 PS2Queue *q = &s->queue;
1228 uint8_t i, size;
1229 uint8_t tmp_data[PS2_QUEUE_SIZE];
1231 /* set the useful data buffer queue size, < PS2_QUEUE_SIZE */
1232 size = (q->count < 0 || q->count > PS2_QUEUE_SIZE) ? 0 : q->count;
1234 /* move the queue elements to the start of data array */
1235 for (i = 0; i < size; i++) {
1236 if (q->rptr < 0 || q->rptr >= sizeof(q->data)) {
1237 q->rptr = 0;
1239 tmp_data[i] = q->data[q->rptr++];
1241 memcpy(q->data, tmp_data, size);
1243 /* reset rptr/wptr/count */
1244 q->rptr = 0;
1245 q->wptr = size;
1246 q->count = size;
1247 s->update_irq(s->update_arg, q->count != 0);
1250 static void ps2_kbd_reset(void *opaque)
1252 PS2KbdState *s = (PS2KbdState *) opaque;
1254 trace_ps2_kbd_reset(opaque);
1255 ps2_common_reset(&s->common);
1256 s->scan_enabled = 0;
1257 s->translate = 0;
1258 s->scancode_set = 2;
1259 s->modifiers = 0;
1262 static void ps2_mouse_reset(void *opaque)
1264 PS2MouseState *s = (PS2MouseState *) opaque;
1266 trace_ps2_mouse_reset(opaque);
1267 ps2_common_reset(&s->common);
1268 s->mouse_status = 0;
1269 s->mouse_resolution = 0;
1270 s->mouse_sample_rate = 0;
1271 s->mouse_wrap = 0;
1272 s->mouse_type = 0;
1273 s->mouse_detect_state = 0;
1274 s->mouse_dx = 0;
1275 s->mouse_dy = 0;
1276 s->mouse_dz = 0;
1277 s->mouse_buttons = 0;
1280 static const VMStateDescription vmstate_ps2_common = {
1281 .name = "PS2 Common State",
1282 .version_id = 3,
1283 .minimum_version_id = 2,
1284 .fields = (VMStateField[]) {
1285 VMSTATE_INT32(write_cmd, PS2State),
1286 VMSTATE_INT32(queue.rptr, PS2State),
1287 VMSTATE_INT32(queue.wptr, PS2State),
1288 VMSTATE_INT32(queue.count, PS2State),
1289 VMSTATE_BUFFER(queue.data, PS2State),
1290 VMSTATE_END_OF_LIST()
1294 static bool ps2_keyboard_ledstate_needed(void *opaque)
1296 PS2KbdState *s = opaque;
1298 return s->ledstate != 0; /* 0 is default state */
1301 static int ps2_kbd_ledstate_post_load(void *opaque, int version_id)
1303 PS2KbdState *s = opaque;
1305 kbd_put_ledstate(s->ledstate);
1306 return 0;
1309 static const VMStateDescription vmstate_ps2_keyboard_ledstate = {
1310 .name = "ps2kbd/ledstate",
1311 .version_id = 3,
1312 .minimum_version_id = 2,
1313 .post_load = ps2_kbd_ledstate_post_load,
1314 .needed = ps2_keyboard_ledstate_needed,
1315 .fields = (VMStateField[]) {
1316 VMSTATE_INT32(ledstate, PS2KbdState),
1317 VMSTATE_END_OF_LIST()
1321 static bool ps2_keyboard_need_high_bit_needed(void *opaque)
1323 PS2KbdState *s = opaque;
1324 return s->need_high_bit != 0; /* 0 is the usual state */
1327 static const VMStateDescription vmstate_ps2_keyboard_need_high_bit = {
1328 .name = "ps2kbd/need_high_bit",
1329 .version_id = 1,
1330 .minimum_version_id = 1,
1331 .needed = ps2_keyboard_need_high_bit_needed,
1332 .fields = (VMStateField[]) {
1333 VMSTATE_BOOL(need_high_bit, PS2KbdState),
1334 VMSTATE_END_OF_LIST()
1338 static int ps2_kbd_post_load(void* opaque, int version_id)
1340 PS2KbdState *s = (PS2KbdState*)opaque;
1341 PS2State *ps2 = &s->common;
1343 if (version_id == 2)
1344 s->scancode_set=2;
1346 ps2_common_post_load(ps2);
1348 return 0;
1351 static int ps2_kbd_pre_save(void *opaque)
1353 PS2KbdState *s = (PS2KbdState *)opaque;
1354 PS2State *ps2 = &s->common;
1356 ps2_common_post_load(ps2);
1358 return 0;
1361 static const VMStateDescription vmstate_ps2_keyboard = {
1362 .name = "ps2kbd",
1363 .version_id = 3,
1364 .minimum_version_id = 2,
1365 .post_load = ps2_kbd_post_load,
1366 .pre_save = ps2_kbd_pre_save,
1367 .fields = (VMStateField[]) {
1368 VMSTATE_STRUCT(common, PS2KbdState, 0, vmstate_ps2_common, PS2State),
1369 VMSTATE_INT32(scan_enabled, PS2KbdState),
1370 VMSTATE_INT32(translate, PS2KbdState),
1371 VMSTATE_INT32_V(scancode_set, PS2KbdState,3),
1372 VMSTATE_END_OF_LIST()
1374 .subsections = (const VMStateDescription*[]) {
1375 &vmstate_ps2_keyboard_ledstate,
1376 &vmstate_ps2_keyboard_need_high_bit,
1377 NULL
1381 static int ps2_mouse_post_load(void *opaque, int version_id)
1383 PS2MouseState *s = (PS2MouseState *)opaque;
1384 PS2State *ps2 = &s->common;
1386 ps2_common_post_load(ps2);
1388 return 0;
1391 static int ps2_mouse_pre_save(void *opaque)
1393 PS2MouseState *s = (PS2MouseState *)opaque;
1394 PS2State *ps2 = &s->common;
1396 ps2_common_post_load(ps2);
1398 return 0;
1401 static const VMStateDescription vmstate_ps2_mouse = {
1402 .name = "ps2mouse",
1403 .version_id = 2,
1404 .minimum_version_id = 2,
1405 .post_load = ps2_mouse_post_load,
1406 .pre_save = ps2_mouse_pre_save,
1407 .fields = (VMStateField[]) {
1408 VMSTATE_STRUCT(common, PS2MouseState, 0, vmstate_ps2_common, PS2State),
1409 VMSTATE_UINT8(mouse_status, PS2MouseState),
1410 VMSTATE_UINT8(mouse_resolution, PS2MouseState),
1411 VMSTATE_UINT8(mouse_sample_rate, PS2MouseState),
1412 VMSTATE_UINT8(mouse_wrap, PS2MouseState),
1413 VMSTATE_UINT8(mouse_type, PS2MouseState),
1414 VMSTATE_UINT8(mouse_detect_state, PS2MouseState),
1415 VMSTATE_INT32(mouse_dx, PS2MouseState),
1416 VMSTATE_INT32(mouse_dy, PS2MouseState),
1417 VMSTATE_INT32(mouse_dz, PS2MouseState),
1418 VMSTATE_UINT8(mouse_buttons, PS2MouseState),
1419 VMSTATE_END_OF_LIST()
1423 static QemuInputHandler ps2_keyboard_handler = {
1424 .name = "QEMU PS/2 Keyboard",
1425 .mask = INPUT_EVENT_MASK_KEY,
1426 .event = ps2_keyboard_event,
1429 void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
1431 PS2KbdState *s = (PS2KbdState *)g_malloc0(sizeof(PS2KbdState));
1433 trace_ps2_kbd_init(s);
1434 s->common.update_irq = update_irq;
1435 s->common.update_arg = update_arg;
1436 s->scancode_set = 2;
1437 vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s);
1438 qemu_input_handler_register((DeviceState *)s,
1439 &ps2_keyboard_handler);
1440 qemu_register_reset(ps2_kbd_reset, s);
1441 return s;
1444 static QemuInputHandler ps2_mouse_handler = {
1445 .name = "QEMU PS/2 Mouse",
1446 .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
1447 .event = ps2_mouse_event,
1448 .sync = ps2_mouse_sync,
1451 void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
1453 PS2MouseState *s = (PS2MouseState *)g_malloc0(sizeof(PS2MouseState));
1455 trace_ps2_mouse_init(s);
1456 s->common.update_irq = update_irq;
1457 s->common.update_arg = update_arg;
1458 vmstate_register(NULL, 0, &vmstate_ps2_mouse, s);
1459 qemu_input_handler_register((DeviceState *)s,
1460 &ps2_mouse_handler);
1461 qemu_register_reset(ps2_mouse_reset, s);
1462 return s;