]> Git Repo - qemu.git/blame - hw/input/ps2.c
ps2: fix scancodes sent for Alt-Print key combination (aka SysRq)
[qemu.git] / hw / input / ps2.c
CommitLineData
0e43e99c
FB
1/*
2 * QEMU PS/2 keyboard/mouse emulation
5fafdf24 3 *
0e43e99c 4 * Copyright (c) 2003 Fabrice Bellard
5fafdf24 5 *
0e43e99c
FB
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:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
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.
23 */
0430891c 24#include "qemu/osdep.h"
ec044a80 25#include "qemu/log.h"
83c9f4ca 26#include "hw/hw.h"
0d09e41a 27#include "hw/input/ps2.h"
28ecbaee 28#include "ui/console.h"
66e6536e 29#include "ui/input.h"
9c17d615 30#include "sysemu/sysemu.h"
0e43e99c 31
5edab03d
DK
32#include "trace.h"
33
0e43e99c
FB
34/* debug PC keyboard */
35//#define DEBUG_KBD
36
37/* debug PC keyboard : only mouse */
38//#define DEBUG_MOUSE
39
40/* Keyboard Commands */
41#define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */
42#define KBD_CMD_ECHO 0xEE
e7d93956 43#define KBD_CMD_SCANCODE 0xF0 /* Get/set scancode set */
0e43e99c
FB
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 */
50
51/* Keyboard Replies */
52#define KBD_REPLY_POR 0xAA /* Power on reset */
35c4d671 53#define KBD_REPLY_ID 0xAB /* Keyboard ID */
0e43e99c
FB
54#define KBD_REPLY_ACK 0xFA /* Command ACK */
55#define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */
56
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. */
74
75#define MOUSE_STATUS_REMOTE 0x40
76#define MOUSE_STATUS_ENABLED 0x20
77#define MOUSE_STATUS_SCALE21 0x10
78
2858ab09 79#define PS2_QUEUE_SIZE 16 /* Buffer size required by PS/2 protocol */
0e43e99c 80
620775d1
DB
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)
88
0e43e99c 89typedef struct {
2858ab09
GA
90 /* Keep the data array 256 bytes long, which compatibility
91 with older qemu versions. */
92 uint8_t data[256];
0e43e99c
FB
93 int rptr, wptr, count;
94} PS2Queue;
95
8498bb8d 96struct PS2State {
0e43e99c
FB
97 PS2Queue queue;
98 int32_t write_cmd;
99 void (*update_irq)(void *, int);
100 void *update_arg;
8498bb8d 101};
0e43e99c
FB
102
103typedef struct {
104 PS2State common;
105 int scan_enabled;
f94f5d71 106 int translate;
e7d93956 107 int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */
7f540ab5 108 int ledstate;
57d5c005 109 bool need_high_bit;
620775d1 110 unsigned int modifiers; /* bitmask of MOD_* constants above */
0e43e99c
FB
111} PS2KbdState;
112
113typedef 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;
126
8c10e0ba
HP
127/* Table to convert from QEMU codes to scancodes. */
128static const uint16_t qcode_to_keycode_set1[Q_KEY_CODE__MAX] = {
129 [0 ... Q_KEY_CODE__MAX - 1] = 0,
130
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,
235
8c10e0ba
HP
236 [Q_KEY_CODE_POWER] = 0x0e5e,
237 [Q_KEY_CODE_SLEEP] = 0x0e5f,
238 [Q_KEY_CODE_WAKE] = 0x0e63,
239
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,
103dce8f 251 [Q_KEY_CODE_FIND] = 0xe065,
8c10e0ba
HP
252 [Q_KEY_CODE_AC_HOME] = 0xe032,
253 [Q_KEY_CODE_AC_BACK] = 0xe06a,
254 [Q_KEY_CODE_AC_FORWARD] = 0xe069,
103dce8f 255 [Q_KEY_CODE_STOP] = 0xe068,
8c10e0ba
HP
256 [Q_KEY_CODE_AC_REFRESH] = 0xe067,
257 [Q_KEY_CODE_AC_BOOKMARKS] = 0xe066,
8c10e0ba
HP
258
259 [Q_KEY_CODE_ASTERISK] = 0x37,
260 [Q_KEY_CODE_LESS] = 0x56,
261 [Q_KEY_CODE_RO] = 0x73,
e9346441
OH
262 [Q_KEY_CODE_HIRAGANA] = 0x70,
263 [Q_KEY_CODE_HENKAN] = 0x79,
264 [Q_KEY_CODE_YEN] = 0x7d,
8c10e0ba
HP
265 [Q_KEY_CODE_KP_COMMA] = 0x7e,
266};
267
268static const uint16_t qcode_to_keycode_set2[Q_KEY_CODE__MAX] = {
269 [0 ... Q_KEY_CODE__MAX - 1] = 0,
270
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,
375
8c10e0ba
HP
376 [Q_KEY_CODE_POWER] = 0x0e37,
377 [Q_KEY_CODE_SLEEP] = 0x0e3f,
378 [Q_KEY_CODE_WAKE] = 0x0e5e,
379
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,
103dce8f 391 [Q_KEY_CODE_FIND] = 0xe010,
8c10e0ba
HP
392 [Q_KEY_CODE_AC_HOME] = 0xe03a,
393 [Q_KEY_CODE_AC_BACK] = 0xe038,
394 [Q_KEY_CODE_AC_FORWARD] = 0xe030,
103dce8f 395 [Q_KEY_CODE_STOP] = 0xe028,
8c10e0ba
HP
396 [Q_KEY_CODE_AC_REFRESH] = 0xe020,
397 [Q_KEY_CODE_AC_BOOKMARKS] = 0xe018,
8c10e0ba 398
8c10e0ba
HP
399 [Q_KEY_CODE_ASTERISK] = 0x7c,
400 [Q_KEY_CODE_LESS] = 0x61,
401 [Q_KEY_CODE_SYSRQ] = 0x7f,
402 [Q_KEY_CODE_RO] = 0x51,
e9346441
OH
403 [Q_KEY_CODE_HIRAGANA] = 0x13,
404 [Q_KEY_CODE_HENKAN] = 0x64,
405 [Q_KEY_CODE_YEN] = 0x6a,
8c10e0ba 406 [Q_KEY_CODE_KP_COMMA] = 0x6d,
7096a96d 407};
8c10e0ba
HP
408
409static const uint16_t qcode_to_keycode_set3[Q_KEY_CODE__MAX] = {
410 [0 ... Q_KEY_CODE__MAX - 1] = 0,
411
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,
e9346441
OH
516
517 [Q_KEY_CODE_HIRAGANA] = 0x87,
518 [Q_KEY_CODE_HENKAN] = 0x86,
519 [Q_KEY_CODE_YEN] = 0x5d,
f94f5d71
PB
520};
521
57d5c005
HP
522static 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,
555};
556
620775d1
DB
557static unsigned int ps2_modifier_bit(QKeyCode key)
558{
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;
574 }
575}
576
954ee55b
GH
577static void ps2_reset_queue(PS2State *s)
578{
579 PS2Queue *q = &s->queue;
580
581 q->rptr = 0;
582 q->wptr = 0;
583 q->count = 0;
584}
585
8498bb8d 586void ps2_queue(PS2State *s, int b)
0e43e99c 587{
0e43e99c
FB
588 PS2Queue *q = &s->queue;
589
2858ab09 590 if (q->count >= PS2_QUEUE_SIZE - 1)
0e43e99c
FB
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);
597}
598
57d5c005 599/* keycode is the untranslated scancode in the current scancode set. */
0e43e99c
FB
600static void ps2_put_keycode(void *opaque, int keycode)
601{
f94f5d71 602 PS2KbdState *s = opaque;
e7d93956 603
5edab03d 604 trace_ps2_put_keycode(opaque, keycode);
fd214d18 605 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
57d5c005
HP
606
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]);
7096a96d 615 }
57d5c005
HP
616 } else {
617 ps2_queue(&s->common, keycode);
618 }
0e43e99c
FB
619}
620
66e6536e
GH
621static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,
622 InputEvent *evt)
623{
624 PS2KbdState *s = (PS2KbdState *)dev;
32bafa8f 625 InputKeyEvent *key = evt->u.key.data;
8c10e0ba
HP
626 int qcode;
627 uint16_t keycode;
620775d1 628 int mod;
66e6536e
GH
629
630 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
8c10e0ba
HP
631 assert(evt->type == INPUT_EVENT_KIND_KEY);
632 qcode = qemu_input_key_value_to_qcode(key->key);
57d5c005 633
620775d1
DB
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;
640 }
641
8c10e0ba
HP
642 if (s->scancode_set == 1) {
643 if (qcode == Q_KEY_CODE_PAUSE) {
644 if (key->down) {
645 ps2_put_keycode(s, 0xe1);
646 ps2_put_keycode(s, 0x1d);
647 ps2_put_keycode(s, 0x45);
648 ps2_put_keycode(s, 0x91);
649 ps2_put_keycode(s, 0x9d);
650 ps2_put_keycode(s, 0xc5);
651 }
652 } else if (qcode == Q_KEY_CODE_PRINT) {
620775d1
DB
653 if (s->modifiers & MOD_ALT_L) {
654 if (key->down) {
655 ps2_put_keycode(s, 0xb8);
656 ps2_put_keycode(s, 0x38);
657 ps2_put_keycode(s, 0x54);
658 } else {
659 ps2_put_keycode(s, 0xd4);
660 ps2_put_keycode(s, 0xb8);
661 ps2_put_keycode(s, 0x38);
662 }
663 } else if (s->modifiers & MOD_ALT_R) {
664 if (key->down) {
665 ps2_put_keycode(s, 0xe0);
666 ps2_put_keycode(s, 0xb8);
667 ps2_put_keycode(s, 0xe0);
668 ps2_put_keycode(s, 0x38);
669 ps2_put_keycode(s, 0x54);
670 } else {
671 ps2_put_keycode(s, 0xd4);
672 ps2_put_keycode(s, 0xe0);
673 ps2_put_keycode(s, 0xb8);
674 ps2_put_keycode(s, 0xe0);
675 ps2_put_keycode(s, 0x38);
676 }
8c10e0ba 677 } else {
620775d1
DB
678 if (key->down) {
679 ps2_put_keycode(s, 0xe0);
680 ps2_put_keycode(s, 0x2a);
681 ps2_put_keycode(s, 0xe0);
682 ps2_put_keycode(s, 0x37);
683 } else {
684 ps2_put_keycode(s, 0xe0);
685 ps2_put_keycode(s, 0xb7);
686 ps2_put_keycode(s, 0xe0);
687 ps2_put_keycode(s, 0xaa);
688 }
8c10e0ba 689 }
57d5c005 690 } else {
8c10e0ba
HP
691 keycode = qcode_to_keycode_set1[qcode];
692 if (keycode) {
693 if (keycode & 0xff00) {
694 ps2_put_keycode(s, keycode >> 8);
695 }
696 if (!key->down) {
697 keycode |= 0x80;
698 }
699 ps2_put_keycode(s, keycode & 0xff);
700 } else {
ec044a80
HP
701 qemu_log_mask(LOG_UNIMP,
702 "ps2: ignoring key with qcode %d\n", qcode);
8c10e0ba 703 }
57d5c005 704 }
8c10e0ba
HP
705 } else if (s->scancode_set == 2) {
706 if (qcode == Q_KEY_CODE_PAUSE) {
707 if (key->down) {
708 ps2_put_keycode(s, 0xe1);
709 ps2_put_keycode(s, 0x14);
710 ps2_put_keycode(s, 0x77);
711 ps2_put_keycode(s, 0xe1);
712 ps2_put_keycode(s, 0xf0);
713 ps2_put_keycode(s, 0x14);
714 ps2_put_keycode(s, 0xf0);
715 ps2_put_keycode(s, 0x77);
57d5c005 716 }
8c10e0ba 717 } else if (qcode == Q_KEY_CODE_PRINT) {
620775d1
DB
718 if (s->modifiers & MOD_ALT_L) {
719 if (key->down) {
720 ps2_put_keycode(s, 0xf0);
721 ps2_put_keycode(s, 0x11);
722 ps2_put_keycode(s, 0x11);
723 ps2_put_keycode(s, 0x84);
724 } else {
725 ps2_put_keycode(s, 0xf0);
726 ps2_put_keycode(s, 0x84);
727 ps2_put_keycode(s, 0xf0);
728 ps2_put_keycode(s, 0x11);
729 ps2_put_keycode(s, 0x11);
730 }
731 } else if (s->modifiers & MOD_ALT_R) {
732 if (key->down) {
733 ps2_put_keycode(s, 0xe0);
734 ps2_put_keycode(s, 0xf0);
735 ps2_put_keycode(s, 0x11);
736 ps2_put_keycode(s, 0xe0);
737 ps2_put_keycode(s, 0x11);
738 ps2_put_keycode(s, 0x84);
739 } else {
740 ps2_put_keycode(s, 0xf0);
741 ps2_put_keycode(s, 0x84);
742 ps2_put_keycode(s, 0xe0);
743 ps2_put_keycode(s, 0xf0);
744 ps2_put_keycode(s, 0x11);
745 ps2_put_keycode(s, 0xe0);
746 ps2_put_keycode(s, 0x11);
747 }
8c10e0ba 748 } else {
620775d1
DB
749 if (key->down) {
750 ps2_put_keycode(s, 0xe0);
751 ps2_put_keycode(s, 0x12);
752 ps2_put_keycode(s, 0xe0);
753 ps2_put_keycode(s, 0x7c);
754 } else {
755 ps2_put_keycode(s, 0xe0);
756 ps2_put_keycode(s, 0xf0);
757 ps2_put_keycode(s, 0x7c);
758 ps2_put_keycode(s, 0xe0);
759 ps2_put_keycode(s, 0xf0);
760 ps2_put_keycode(s, 0x12);
761 }
8c10e0ba
HP
762 }
763 } else {
764 keycode = qcode_to_keycode_set2[qcode];
765 if (keycode) {
766 if (keycode & 0xff00) {
767 ps2_put_keycode(s, keycode >> 8);
768 }
769 if (!key->down) {
770 ps2_put_keycode(s, 0xf0);
771 }
772 ps2_put_keycode(s, keycode & 0xff);
8c10e0ba 773 } else {
ec044a80
HP
774 qemu_log_mask(LOG_UNIMP,
775 "ps2: ignoring key with qcode %d\n", qcode);
57d5c005
HP
776 }
777 }
8c10e0ba
HP
778 } else if (s->scancode_set == 3) {
779 keycode = qcode_to_keycode_set3[qcode];
780 if (keycode) {
781 /* FIXME: break code should be configured on a key by key basis */
782 if (!key->down) {
783 ps2_put_keycode(s, 0xf0);
784 }
785 ps2_put_keycode(s, keycode);
8c10e0ba 786 } else {
ec044a80
HP
787 qemu_log_mask(LOG_UNIMP,
788 "ps2: ignoring key with qcode %d\n", qcode);
8c10e0ba 789 }
66e6536e
GH
790 }
791}
792
8498bb8d 793uint32_t ps2_read_data(PS2State *s)
0e43e99c 794{
0e43e99c
FB
795 PS2Queue *q;
796 int val, index;
3b46e624 797
8498bb8d 798 trace_ps2_read_data(s);
0e43e99c
FB
799 q = &s->queue;
800 if (q->count == 0) {
801 /* NOTE: if no data left, we return the last keyboard one
802 (needed for EMM386) */
803 /* XXX: need a timer to do things correctly */
804 index = q->rptr - 1;
805 if (index < 0)
806 index = PS2_QUEUE_SIZE - 1;
807 val = q->data[index];
808 } else {
809 val = q->data[q->rptr];
810 if (++q->rptr == PS2_QUEUE_SIZE)
811 q->rptr = 0;
812 q->count--;
813 /* reading deasserts IRQ */
814 s->update_irq(s->update_arg, 0);
815 /* reassert IRQs if data left */
816 s->update_irq(s->update_arg, q->count != 0);
817 }
818 return val;
819}
820
7f540ab5
CF
821static void ps2_set_ledstate(PS2KbdState *s, int ledstate)
822{
5edab03d 823 trace_ps2_set_ledstate(s, ledstate);
7f540ab5
CF
824 s->ledstate = ledstate;
825 kbd_put_ledstate(ledstate);
826}
827
0e43e99c
FB
828static void ps2_reset_keyboard(PS2KbdState *s)
829{
5edab03d 830 trace_ps2_reset_keyboard(s);
0e43e99c 831 s->scan_enabled = 1;
e7d93956 832 s->scancode_set = 2;
6e24ee0c 833 ps2_reset_queue(&s->common);
7f540ab5 834 ps2_set_ledstate(s, 0);
0e43e99c
FB
835}
836
837void ps2_write_keyboard(void *opaque, int val)
838{
839 PS2KbdState *s = (PS2KbdState *)opaque;
840
5edab03d 841 trace_ps2_write_keyboard(opaque, val);
0e43e99c
FB
842 switch(s->common.write_cmd) {
843 default:
844 case -1:
845 switch(val) {
846 case 0x00:
847 ps2_queue(&s->common, KBD_REPLY_ACK);
848 break;
849 case 0x05:
850 ps2_queue(&s->common, KBD_REPLY_RESEND);
851 break;
852 case KBD_CMD_GET_ID:
853 ps2_queue(&s->common, KBD_REPLY_ACK);
e7d93956 854 /* We emulate a MF2 AT keyboard here */
35c4d671
AJ
855 ps2_queue(&s->common, KBD_REPLY_ID);
856 if (s->translate)
857 ps2_queue(&s->common, 0x41);
858 else
859 ps2_queue(&s->common, 0x83);
0e43e99c
FB
860 break;
861 case KBD_CMD_ECHO:
862 ps2_queue(&s->common, KBD_CMD_ECHO);
863 break;
864 case KBD_CMD_ENABLE:
865 s->scan_enabled = 1;
866 ps2_queue(&s->common, KBD_REPLY_ACK);
867 break;
e7d93956 868 case KBD_CMD_SCANCODE:
0e43e99c
FB
869 case KBD_CMD_SET_LEDS:
870 case KBD_CMD_SET_RATE:
871 s->common.write_cmd = val;
872 ps2_queue(&s->common, KBD_REPLY_ACK);
873 break;
874 case KBD_CMD_RESET_DISABLE:
875 ps2_reset_keyboard(s);
876 s->scan_enabled = 0;
877 ps2_queue(&s->common, KBD_REPLY_ACK);
878 break;
879 case KBD_CMD_RESET_ENABLE:
880 ps2_reset_keyboard(s);
881 s->scan_enabled = 1;
882 ps2_queue(&s->common, KBD_REPLY_ACK);
883 break;
884 case KBD_CMD_RESET:
885 ps2_reset_keyboard(s);
886 ps2_queue(&s->common, KBD_REPLY_ACK);
887 ps2_queue(&s->common, KBD_REPLY_POR);
888 break;
889 default:
06b3611f 890 ps2_queue(&s->common, KBD_REPLY_RESEND);
0e43e99c
FB
891 break;
892 }
893 break;
e7d93956
AJ
894 case KBD_CMD_SCANCODE:
895 if (val == 0) {
4df23b64 896 ps2_queue(&s->common, KBD_REPLY_ACK);
57d5c005 897 ps2_put_keycode(s, s->scancode_set);
4df23b64
HP
898 } else if (val >= 1 && val <= 3) {
899 s->scancode_set = val;
e7d93956 900 ps2_queue(&s->common, KBD_REPLY_ACK);
4df23b64
HP
901 } else {
902 ps2_queue(&s->common, KBD_REPLY_RESEND);
e7d93956
AJ
903 }
904 s->common.write_cmd = -1;
905 break;
0e43e99c 906 case KBD_CMD_SET_LEDS:
7f540ab5 907 ps2_set_ledstate(s, val);
0e43e99c
FB
908 ps2_queue(&s->common, KBD_REPLY_ACK);
909 s->common.write_cmd = -1;
910 break;
911 case KBD_CMD_SET_RATE:
912 ps2_queue(&s->common, KBD_REPLY_ACK);
913 s->common.write_cmd = -1;
914 break;
915 }
916}
917
f94f5d71
PB
918/* Set the scancode translation mode.
919 0 = raw scancodes.
920 1 = translated scancodes (used by qemu internally). */
921
922void ps2_keyboard_set_translation(void *opaque, int mode)
923{
924 PS2KbdState *s = (PS2KbdState *)opaque;
5edab03d 925 trace_ps2_keyboard_set_translation(opaque, mode);
f94f5d71
PB
926 s->translate = mode;
927}
928
0e43e99c
FB
929static void ps2_mouse_send_packet(PS2MouseState *s)
930{
931 unsigned int b;
932 int dx1, dy1, dz1;
933
934 dx1 = s->mouse_dx;
935 dy1 = s->mouse_dy;
936 dz1 = s->mouse_dz;
937 /* XXX: increase range to 8 bits ? */
938 if (dx1 > 127)
939 dx1 = 127;
940 else if (dx1 < -127)
941 dx1 = -127;
942 if (dy1 > 127)
943 dy1 = 127;
944 else if (dy1 < -127)
945 dy1 = -127;
946 b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
947 ps2_queue(&s->common, b);
948 ps2_queue(&s->common, dx1 & 0xff);
949 ps2_queue(&s->common, dy1 & 0xff);
950 /* extra byte for IMPS/2 or IMEX */
951 switch(s->mouse_type) {
952 default:
953 break;
954 case 3:
955 if (dz1 > 127)
956 dz1 = 127;
957 else if (dz1 < -127)
958 dz1 = -127;
959 ps2_queue(&s->common, dz1 & 0xff);
960 break;
961 case 4:
962 if (dz1 > 7)
963 dz1 = 7;
964 else if (dz1 < -7)
965 dz1 = -7;
966 b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
967 ps2_queue(&s->common, b);
968 break;
969 }
970
5edab03d 971 trace_ps2_mouse_send_packet(s, dx1, dy1, dz1, b);
0e43e99c
FB
972 /* update deltas */
973 s->mouse_dx -= dx1;
974 s->mouse_dy -= dy1;
975 s->mouse_dz -= dz1;
976}
977
2a766d29
GH
978static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
979 InputEvent *evt)
0e43e99c 980{
7fb1cf16 981 static const int bmap[INPUT_BUTTON__MAX] = {
8b0caab0
FL
982 [INPUT_BUTTON_LEFT] = PS2_MOUSE_BUTTON_LEFT,
983 [INPUT_BUTTON_MIDDLE] = PS2_MOUSE_BUTTON_MIDDLE,
984 [INPUT_BUTTON_RIGHT] = PS2_MOUSE_BUTTON_RIGHT,
985 [INPUT_BUTTON_SIDE] = PS2_MOUSE_BUTTON_SIDE,
986 [INPUT_BUTTON_EXTRA] = PS2_MOUSE_BUTTON_EXTRA,
2a766d29
GH
987 };
988 PS2MouseState *s = (PS2MouseState *)dev;
b5a1b443
EB
989 InputMoveEvent *move;
990 InputBtnEvent *btn;
0e43e99c
FB
991
992 /* check if deltas are recorded when disabled */
993 if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
994 return;
995
568c73a4 996 switch (evt->type) {
2a766d29 997 case INPUT_EVENT_KIND_REL:
32bafa8f 998 move = evt->u.rel.data;
b5a1b443
EB
999 if (move->axis == INPUT_AXIS_X) {
1000 s->mouse_dx += move->value;
1001 } else if (move->axis == INPUT_AXIS_Y) {
1002 s->mouse_dy -= move->value;
2a766d29
GH
1003 }
1004 break;
3b46e624 1005
2a766d29 1006 case INPUT_EVENT_KIND_BTN:
32bafa8f 1007 btn = evt->u.btn.data;
b5a1b443
EB
1008 if (btn->down) {
1009 s->mouse_buttons |= bmap[btn->button];
1010 if (btn->button == INPUT_BUTTON_WHEEL_UP) {
2a766d29 1011 s->mouse_dz--;
b5a1b443 1012 } else if (btn->button == INPUT_BUTTON_WHEEL_DOWN) {
2a766d29
GH
1013 s->mouse_dz++;
1014 }
1015 } else {
b5a1b443 1016 s->mouse_buttons &= ~bmap[btn->button];
2a766d29
GH
1017 }
1018 break;
1019
1020 default:
1021 /* keep gcc happy */
1022 break;
fd214d18 1023 }
2a766d29 1024}
fd214d18 1025
2a766d29
GH
1026static void ps2_mouse_sync(DeviceState *dev)
1027{
1028 PS2MouseState *s = (PS2MouseState *)dev;
1029
1030 if (s->mouse_buttons) {
1031 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
1032 }
2858ab09
GA
1033 if (!(s->mouse_status & MOUSE_STATUS_REMOTE)) {
1034 while (s->common.queue.count < PS2_QUEUE_SIZE - 4) {
0e43e99c
FB
1035 /* if not remote, send event. Multiple events are sent if
1036 too big deltas */
1037 ps2_mouse_send_packet(s);
1038 if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
1039 break;
1040 }
1041 }
1042}
1043
548df2ac
TS
1044void ps2_mouse_fake_event(void *opaque)
1045{
2a766d29 1046 PS2MouseState *s = opaque;
5edab03d 1047 trace_ps2_mouse_fake_event(opaque);
2a766d29
GH
1048 s->mouse_dx++;
1049 ps2_mouse_sync(opaque);
548df2ac
TS
1050}
1051
0e43e99c
FB
1052void ps2_write_mouse(void *opaque, int val)
1053{
1054 PS2MouseState *s = (PS2MouseState *)opaque;
5edab03d
DK
1055
1056 trace_ps2_write_mouse(opaque, val);
0e43e99c
FB
1057#ifdef DEBUG_MOUSE
1058 printf("kbd: write mouse 0x%02x\n", val);
1059#endif
1060 switch(s->common.write_cmd) {
1061 default:
1062 case -1:
1063 /* mouse command */
1064 if (s->mouse_wrap) {
1065 if (val == AUX_RESET_WRAP) {
1066 s->mouse_wrap = 0;
1067 ps2_queue(&s->common, AUX_ACK);
1068 return;
1069 } else if (val != AUX_RESET) {
1070 ps2_queue(&s->common, val);
1071 return;
1072 }
1073 }
1074 switch(val) {
1075 case AUX_SET_SCALE11:
1076 s->mouse_status &= ~MOUSE_STATUS_SCALE21;
1077 ps2_queue(&s->common, AUX_ACK);
1078 break;
1079 case AUX_SET_SCALE21:
1080 s->mouse_status |= MOUSE_STATUS_SCALE21;
1081 ps2_queue(&s->common, AUX_ACK);
1082 break;
1083 case AUX_SET_STREAM:
1084 s->mouse_status &= ~MOUSE_STATUS_REMOTE;
1085 ps2_queue(&s->common, AUX_ACK);
1086 break;
1087 case AUX_SET_WRAP:
1088 s->mouse_wrap = 1;
1089 ps2_queue(&s->common, AUX_ACK);
1090 break;
1091 case AUX_SET_REMOTE:
1092 s->mouse_status |= MOUSE_STATUS_REMOTE;
1093 ps2_queue(&s->common, AUX_ACK);
1094 break;
1095 case AUX_GET_TYPE:
1096 ps2_queue(&s->common, AUX_ACK);
1097 ps2_queue(&s->common, s->mouse_type);
1098 break;
1099 case AUX_SET_RES:
1100 case AUX_SET_SAMPLE:
1101 s->common.write_cmd = val;
1102 ps2_queue(&s->common, AUX_ACK);
1103 break;
1104 case AUX_GET_SCALE:
1105 ps2_queue(&s->common, AUX_ACK);
1106 ps2_queue(&s->common, s->mouse_status);
1107 ps2_queue(&s->common, s->mouse_resolution);
1108 ps2_queue(&s->common, s->mouse_sample_rate);
1109 break;
1110 case AUX_POLL:
1111 ps2_queue(&s->common, AUX_ACK);
1112 ps2_mouse_send_packet(s);
1113 break;
1114 case AUX_ENABLE_DEV:
1115 s->mouse_status |= MOUSE_STATUS_ENABLED;
1116 ps2_queue(&s->common, AUX_ACK);
1117 break;
1118 case AUX_DISABLE_DEV:
1119 s->mouse_status &= ~MOUSE_STATUS_ENABLED;
1120 ps2_queue(&s->common, AUX_ACK);
1121 break;
1122 case AUX_SET_DEFAULT:
1123 s->mouse_sample_rate = 100;
1124 s->mouse_resolution = 2;
1125 s->mouse_status = 0;
1126 ps2_queue(&s->common, AUX_ACK);
1127 break;
1128 case AUX_RESET:
1129 s->mouse_sample_rate = 100;
1130 s->mouse_resolution = 2;
1131 s->mouse_status = 0;
1132 s->mouse_type = 0;
1133 ps2_queue(&s->common, AUX_ACK);
1134 ps2_queue(&s->common, 0xaa);
1135 ps2_queue(&s->common, s->mouse_type);
1136 break;
1137 default:
1138 break;
1139 }
1140 break;
1141 case AUX_SET_SAMPLE:
1142 s->mouse_sample_rate = val;
1143 /* detect IMPS/2 or IMEX */
1144 switch(s->mouse_detect_state) {
1145 default:
1146 case 0:
1147 if (val == 200)
1148 s->mouse_detect_state = 1;
1149 break;
1150 case 1:
1151 if (val == 100)
1152 s->mouse_detect_state = 2;
1153 else if (val == 200)
1154 s->mouse_detect_state = 3;
1155 else
1156 s->mouse_detect_state = 0;
1157 break;
1158 case 2:
5fafdf24 1159 if (val == 80)
0e43e99c
FB
1160 s->mouse_type = 3; /* IMPS/2 */
1161 s->mouse_detect_state = 0;
1162 break;
1163 case 3:
5fafdf24 1164 if (val == 80)
0e43e99c
FB
1165 s->mouse_type = 4; /* IMEX */
1166 s->mouse_detect_state = 0;
1167 break;
1168 }
1169 ps2_queue(&s->common, AUX_ACK);
1170 s->common.write_cmd = -1;
1171 break;
1172 case AUX_SET_RES:
1173 s->mouse_resolution = val;
1174 ps2_queue(&s->common, AUX_ACK);
1175 s->common.write_cmd = -1;
1176 break;
1177 }
1178}
1179
ef74679a 1180static void ps2_common_reset(PS2State *s)
0e43e99c 1181{
0e43e99c 1182 s->write_cmd = -1;
954ee55b 1183 ps2_reset_queue(s);
deeccef3 1184 s->update_irq(s->update_arg, 0);
0e43e99c
FB
1185}
1186
2858ab09
GA
1187static void ps2_common_post_load(PS2State *s)
1188{
1189 PS2Queue *q = &s->queue;
1190 int size;
1191 int i;
1192 int tmp_data[PS2_QUEUE_SIZE];
1193
1194 /* set the useful data buffer queue size, < PS2_QUEUE_SIZE */
1195 size = q->count > PS2_QUEUE_SIZE ? 0 : q->count;
1196
1197 /* move the queue elements to the start of data array */
1198 if (size > 0) {
1199 for (i = 0; i < size; i++) {
1200 /* move the queue elements to the temporary buffer */
1201 tmp_data[i] = q->data[q->rptr];
1202 if (++q->rptr == 256) {
1203 q->rptr = 0;
1204 }
1205 }
1206 memcpy(q->data, tmp_data, size);
1207 }
1208 /* reset rptr/wptr/count */
1209 q->rptr = 0;
1210 q->wptr = size;
1211 q->count = size;
1212 s->update_irq(s->update_arg, q->count != 0);
1213}
1214
ef74679a
DS
1215static void ps2_kbd_reset(void *opaque)
1216{
1217 PS2KbdState *s = (PS2KbdState *) opaque;
1218
5edab03d 1219 trace_ps2_kbd_reset(opaque);
ef74679a
DS
1220 ps2_common_reset(&s->common);
1221 s->scan_enabled = 0;
1222 s->translate = 0;
089adafd 1223 s->scancode_set = 2;
620775d1 1224 s->modifiers = 0;
ef74679a
DS
1225}
1226
1227static void ps2_mouse_reset(void *opaque)
1228{
1229 PS2MouseState *s = (PS2MouseState *) opaque;
1230
5edab03d 1231 trace_ps2_mouse_reset(opaque);
ef74679a
DS
1232 ps2_common_reset(&s->common);
1233 s->mouse_status = 0;
1234 s->mouse_resolution = 0;
1235 s->mouse_sample_rate = 0;
1236 s->mouse_wrap = 0;
1237 s->mouse_type = 0;
1238 s->mouse_detect_state = 0;
1239 s->mouse_dx = 0;
1240 s->mouse_dy = 0;
1241 s->mouse_dz = 0;
1242 s->mouse_buttons = 0;
1243}
1244
b31442c3
JQ
1245static const VMStateDescription vmstate_ps2_common = {
1246 .name = "PS2 Common State",
1247 .version_id = 3,
1248 .minimum_version_id = 2,
d49805ae 1249 .fields = (VMStateField[]) {
b31442c3
JQ
1250 VMSTATE_INT32(write_cmd, PS2State),
1251 VMSTATE_INT32(queue.rptr, PS2State),
1252 VMSTATE_INT32(queue.wptr, PS2State),
1253 VMSTATE_INT32(queue.count, PS2State),
1254 VMSTATE_BUFFER(queue.data, PS2State),
1255 VMSTATE_END_OF_LIST()
1256 }
1257};
0e43e99c 1258
7f540ab5
CF
1259static bool ps2_keyboard_ledstate_needed(void *opaque)
1260{
1261 PS2KbdState *s = opaque;
1262
1263 return s->ledstate != 0; /* 0 is default state */
1264}
1265
1266static int ps2_kbd_ledstate_post_load(void *opaque, int version_id)
1267{
1268 PS2KbdState *s = opaque;
1269
1270 kbd_put_ledstate(s->ledstate);
1271 return 0;
1272}
1273
1274static const VMStateDescription vmstate_ps2_keyboard_ledstate = {
1275 .name = "ps2kbd/ledstate",
1276 .version_id = 3,
1277 .minimum_version_id = 2,
7f540ab5 1278 .post_load = ps2_kbd_ledstate_post_load,
5cd8cada 1279 .needed = ps2_keyboard_ledstate_needed,
d49805ae 1280 .fields = (VMStateField[]) {
7f540ab5
CF
1281 VMSTATE_INT32(ledstate, PS2KbdState),
1282 VMSTATE_END_OF_LIST()
1283 }
1284};
1285
57d5c005
HP
1286static bool ps2_keyboard_need_high_bit_needed(void *opaque)
1287{
1288 PS2KbdState *s = opaque;
1289 return s->need_high_bit != 0; /* 0 is the usual state */
1290}
1291
1292static const VMStateDescription vmstate_ps2_keyboard_need_high_bit = {
1293 .name = "ps2kbd/need_high_bit",
1294 .version_id = 1,
1295 .minimum_version_id = 1,
1296 .needed = ps2_keyboard_need_high_bit_needed,
1297 .fields = (VMStateField[]) {
1298 VMSTATE_BOOL(need_high_bit, PS2KbdState),
1299 VMSTATE_END_OF_LIST()
1300 }
1301};
1302
db596c53 1303static int ps2_kbd_post_load(void* opaque, int version_id)
0e43e99c
FB
1304{
1305 PS2KbdState *s = (PS2KbdState*)opaque;
2858ab09 1306 PS2State *ps2 = &s->common;
7783e9f0 1307
db596c53 1308 if (version_id == 2)
e7d93956 1309 s->scancode_set=2;
2858ab09
GA
1310
1311 ps2_common_post_load(ps2);
1312
0e43e99c
FB
1313 return 0;
1314}
1315
44b1ff31 1316static int ps2_kbd_pre_save(void *opaque)
2858ab09
GA
1317{
1318 PS2KbdState *s = (PS2KbdState *)opaque;
1319 PS2State *ps2 = &s->common;
1320
1321 ps2_common_post_load(ps2);
44b1ff31
DDAG
1322
1323 return 0;
2858ab09
GA
1324}
1325
b31442c3
JQ
1326static const VMStateDescription vmstate_ps2_keyboard = {
1327 .name = "ps2kbd",
1328 .version_id = 3,
db596c53 1329 .minimum_version_id = 2,
db596c53 1330 .post_load = ps2_kbd_post_load,
2858ab09 1331 .pre_save = ps2_kbd_pre_save,
d49805ae 1332 .fields = (VMStateField[]) {
b31442c3
JQ
1333 VMSTATE_STRUCT(common, PS2KbdState, 0, vmstate_ps2_common, PS2State),
1334 VMSTATE_INT32(scan_enabled, PS2KbdState),
1335 VMSTATE_INT32(translate, PS2KbdState),
1336 VMSTATE_INT32_V(scancode_set, PS2KbdState,3),
1337 VMSTATE_END_OF_LIST()
7f540ab5 1338 },
5cd8cada
JQ
1339 .subsections = (const VMStateDescription*[]) {
1340 &vmstate_ps2_keyboard_ledstate,
57d5c005 1341 &vmstate_ps2_keyboard_need_high_bit,
5cd8cada 1342 NULL
b31442c3
JQ
1343 }
1344};
7783e9f0 1345
2858ab09
GA
1346static int ps2_mouse_post_load(void *opaque, int version_id)
1347{
1348 PS2MouseState *s = (PS2MouseState *)opaque;
1349 PS2State *ps2 = &s->common;
1350
1351 ps2_common_post_load(ps2);
1352
1353 return 0;
1354}
1355
44b1ff31 1356static int ps2_mouse_pre_save(void *opaque)
2858ab09
GA
1357{
1358 PS2MouseState *s = (PS2MouseState *)opaque;
1359 PS2State *ps2 = &s->common;
1360
1361 ps2_common_post_load(ps2);
44b1ff31
DDAG
1362
1363 return 0;
2858ab09
GA
1364}
1365
b31442c3
JQ
1366static const VMStateDescription vmstate_ps2_mouse = {
1367 .name = "ps2mouse",
1368 .version_id = 2,
1369 .minimum_version_id = 2,
2858ab09
GA
1370 .post_load = ps2_mouse_post_load,
1371 .pre_save = ps2_mouse_pre_save,
d49805ae 1372 .fields = (VMStateField[]) {
b31442c3
JQ
1373 VMSTATE_STRUCT(common, PS2MouseState, 0, vmstate_ps2_common, PS2State),
1374 VMSTATE_UINT8(mouse_status, PS2MouseState),
1375 VMSTATE_UINT8(mouse_resolution, PS2MouseState),
1376 VMSTATE_UINT8(mouse_sample_rate, PS2MouseState),
1377 VMSTATE_UINT8(mouse_wrap, PS2MouseState),
1378 VMSTATE_UINT8(mouse_type, PS2MouseState),
1379 VMSTATE_UINT8(mouse_detect_state, PS2MouseState),
1380 VMSTATE_INT32(mouse_dx, PS2MouseState),
1381 VMSTATE_INT32(mouse_dy, PS2MouseState),
1382 VMSTATE_INT32(mouse_dz, PS2MouseState),
1383 VMSTATE_UINT8(mouse_buttons, PS2MouseState),
1384 VMSTATE_END_OF_LIST()
1385 }
1386};
0e43e99c 1387
66e6536e
GH
1388static QemuInputHandler ps2_keyboard_handler = {
1389 .name = "QEMU PS/2 Keyboard",
1390 .mask = INPUT_EVENT_MASK_KEY,
1391 .event = ps2_keyboard_event,
1392};
1393
0e43e99c
FB
1394void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
1395{
7267c094 1396 PS2KbdState *s = (PS2KbdState *)g_malloc0(sizeof(PS2KbdState));
0e43e99c 1397
5edab03d 1398 trace_ps2_kbd_init(s);
0e43e99c
FB
1399 s->common.update_irq = update_irq;
1400 s->common.update_arg = update_arg;
e7d93956 1401 s->scancode_set = 2;
0be71e32 1402 vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s);
66e6536e
GH
1403 qemu_input_handler_register((DeviceState *)s,
1404 &ps2_keyboard_handler);
ef74679a 1405 qemu_register_reset(ps2_kbd_reset, s);
0e43e99c
FB
1406 return s;
1407}
1408
2a766d29
GH
1409static QemuInputHandler ps2_mouse_handler = {
1410 .name = "QEMU PS/2 Mouse",
1411 .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
1412 .event = ps2_mouse_event,
1413 .sync = ps2_mouse_sync,
1414};
1415
0e43e99c
FB
1416void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
1417{
7267c094 1418 PS2MouseState *s = (PS2MouseState *)g_malloc0(sizeof(PS2MouseState));
0e43e99c 1419
5edab03d 1420 trace_ps2_mouse_init(s);
0e43e99c
FB
1421 s->common.update_irq = update_irq;
1422 s->common.update_arg = update_arg;
0be71e32 1423 vmstate_register(NULL, 0, &vmstate_ps2_mouse, s);
2a766d29
GH
1424 qemu_input_handler_register((DeviceState *)s,
1425 &ps2_mouse_handler);
ef74679a 1426 qemu_register_reset(ps2_mouse_reset, s);
0e43e99c
FB
1427 return s;
1428}
This page took 1.112237 seconds and 4 git commands to generate.