]> Git Repo - qemu.git/blame - hw/input/ps2.c
Merge remote-tracking branch 'remotes/stefanha/tags/tracing-pull-request' into staging
[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
FB
80
81typedef struct {
2858ab09
GA
82 /* Keep the data array 256 bytes long, which compatibility
83 with older qemu versions. */
84 uint8_t data[256];
0e43e99c
FB
85 int rptr, wptr, count;
86} PS2Queue;
87
88typedef struct {
89 PS2Queue queue;
90 int32_t write_cmd;
91 void (*update_irq)(void *, int);
92 void *update_arg;
93} PS2State;
94
95typedef struct {
96 PS2State common;
97 int scan_enabled;
f94f5d71 98 int translate;
e7d93956 99 int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */
7f540ab5 100 int ledstate;
57d5c005 101 bool need_high_bit;
0e43e99c
FB
102} PS2KbdState;
103
104typedef 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;
117
8c10e0ba
HP
118/* Table to convert from QEMU codes to scancodes. */
119static const uint16_t qcode_to_keycode_set1[Q_KEY_CODE__MAX] = {
120 [0 ... Q_KEY_CODE__MAX - 1] = 0,
121
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,
226
227#if 0
228 [Q_KEY_CODE_POWER] = 0x0e5e,
229 [Q_KEY_CODE_SLEEP] = 0x0e5f,
230 [Q_KEY_CODE_WAKE] = 0x0e63,
231
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
251
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,
256};
257
258static const uint16_t qcode_to_keycode_set2[Q_KEY_CODE__MAX] = {
259 [0 ... Q_KEY_CODE__MAX - 1] = 0,
260
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,
365
366#if 0
367 [Q_KEY_CODE_POWER] = 0x0e37,
368 [Q_KEY_CODE_SLEEP] = 0x0e3f,
369 [Q_KEY_CODE_WAKE] = 0x0e5e,
370
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
390
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,
7096a96d 398};
8c10e0ba
HP
399
400static const uint16_t qcode_to_keycode_set3[Q_KEY_CODE__MAX] = {
401 [0 ... Q_KEY_CODE__MAX - 1] = 0,
402
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,
f94f5d71
PB
507};
508
57d5c005
HP
509static 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,
542};
543
0e43e99c
FB
544void ps2_queue(void *opaque, int b)
545{
546 PS2State *s = (PS2State *)opaque;
547 PS2Queue *q = &s->queue;
548
2858ab09 549 if (q->count >= PS2_QUEUE_SIZE - 1)
0e43e99c
FB
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);
556}
557
57d5c005 558/* keycode is the untranslated scancode in the current scancode set. */
0e43e99c
FB
559static void ps2_put_keycode(void *opaque, int keycode)
560{
f94f5d71 561 PS2KbdState *s = opaque;
e7d93956 562
5edab03d 563 trace_ps2_put_keycode(opaque, keycode);
fd214d18 564 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
57d5c005
HP
565
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]);
7096a96d 574 }
57d5c005
HP
575 } else {
576 ps2_queue(&s->common, keycode);
577 }
0e43e99c
FB
578}
579
66e6536e
GH
580static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,
581 InputEvent *evt)
582{
583 PS2KbdState *s = (PS2KbdState *)dev;
32bafa8f 584 InputKeyEvent *key = evt->u.key.data;
8c10e0ba
HP
585 int qcode;
586 uint16_t keycode;
66e6536e
GH
587
588 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
8c10e0ba
HP
589 assert(evt->type == INPUT_EVENT_KIND_KEY);
590 qcode = qemu_input_key_value_to_qcode(key->key);
57d5c005 591
8c10e0ba
HP
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);
601 }
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);
613 }
57d5c005 614 } else {
8c10e0ba
HP
615 keycode = qcode_to_keycode_set1[qcode];
616 if (keycode) {
617 if (keycode & 0xff00) {
618 ps2_put_keycode(s, keycode >> 8);
619 }
620 if (!key->down) {
621 keycode |= 0x80;
622 }
623 ps2_put_keycode(s, keycode & 0xff);
624 } else {
ec044a80
HP
625 qemu_log_mask(LOG_UNIMP,
626 "ps2: ignoring key with qcode %d\n", qcode);
8c10e0ba 627 }
57d5c005 628 }
8c10e0ba
HP
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);
57d5c005 640 }
8c10e0ba
HP
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);
654 }
655 } else {
656 keycode = qcode_to_keycode_set2[qcode];
657 if (keycode) {
658 if (keycode & 0xff00) {
659 ps2_put_keycode(s, keycode >> 8);
660 }
661 if (!key->down) {
662 ps2_put_keycode(s, 0xf0);
663 }
664 ps2_put_keycode(s, keycode & 0xff);
8c10e0ba 665 } else {
ec044a80
HP
666 qemu_log_mask(LOG_UNIMP,
667 "ps2: ignoring key with qcode %d\n", qcode);
57d5c005
HP
668 }
669 }
8c10e0ba
HP
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);
676 }
677 ps2_put_keycode(s, keycode);
8c10e0ba 678 } else {
ec044a80
HP
679 qemu_log_mask(LOG_UNIMP,
680 "ps2: ignoring key with qcode %d\n", qcode);
8c10e0ba 681 }
66e6536e
GH
682 }
683}
684
0e43e99c
FB
685uint32_t ps2_read_data(void *opaque)
686{
687 PS2State *s = (PS2State *)opaque;
688 PS2Queue *q;
689 int val, index;
3b46e624 690
5edab03d 691 trace_ps2_read_data(opaque);
0e43e99c
FB
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);
710 }
711 return val;
712}
713
7f540ab5
CF
714static void ps2_set_ledstate(PS2KbdState *s, int ledstate)
715{
5edab03d 716 trace_ps2_set_ledstate(s, ledstate);
7f540ab5
CF
717 s->ledstate = ledstate;
718 kbd_put_ledstate(ledstate);
719}
720
0e43e99c
FB
721static void ps2_reset_keyboard(PS2KbdState *s)
722{
5edab03d 723 trace_ps2_reset_keyboard(s);
0e43e99c 724 s->scan_enabled = 1;
e7d93956 725 s->scancode_set = 2;
7f540ab5 726 ps2_set_ledstate(s, 0);
0e43e99c
FB
727}
728
729void ps2_write_keyboard(void *opaque, int val)
730{
731 PS2KbdState *s = (PS2KbdState *)opaque;
732
5edab03d 733 trace_ps2_write_keyboard(opaque, val);
0e43e99c
FB
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);
e7d93956 746 /* We emulate a MF2 AT keyboard here */
35c4d671
AJ
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);
0e43e99c
FB
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;
e7d93956 760 case KBD_CMD_SCANCODE:
0e43e99c
FB
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:
06b3611f 782 ps2_queue(&s->common, KBD_REPLY_RESEND);
0e43e99c
FB
783 break;
784 }
785 break;
e7d93956
AJ
786 case KBD_CMD_SCANCODE:
787 if (val == 0) {
4df23b64 788 ps2_queue(&s->common, KBD_REPLY_ACK);
57d5c005 789 ps2_put_keycode(s, s->scancode_set);
4df23b64
HP
790 } else if (val >= 1 && val <= 3) {
791 s->scancode_set = val;
e7d93956 792 ps2_queue(&s->common, KBD_REPLY_ACK);
4df23b64
HP
793 } else {
794 ps2_queue(&s->common, KBD_REPLY_RESEND);
e7d93956
AJ
795 }
796 s->common.write_cmd = -1;
797 break;
0e43e99c 798 case KBD_CMD_SET_LEDS:
7f540ab5 799 ps2_set_ledstate(s, val);
0e43e99c
FB
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;
807 }
808}
809
f94f5d71
PB
810/* Set the scancode translation mode.
811 0 = raw scancodes.
812 1 = translated scancodes (used by qemu internally). */
813
814void ps2_keyboard_set_translation(void *opaque, int mode)
815{
816 PS2KbdState *s = (PS2KbdState *)opaque;
5edab03d 817 trace_ps2_keyboard_set_translation(opaque, mode);
f94f5d71
PB
818 s->translate = mode;
819}
820
0e43e99c
FB
821static void ps2_mouse_send_packet(PS2MouseState *s)
822{
823 unsigned int b;
824 int dx1, dy1, dz1;
825
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;
861 }
862
5edab03d 863 trace_ps2_mouse_send_packet(s, dx1, dy1, dz1, b);
0e43e99c
FB
864 /* update deltas */
865 s->mouse_dx -= dx1;
866 s->mouse_dy -= dy1;
867 s->mouse_dz -= dz1;
868}
869
2a766d29
GH
870static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
871 InputEvent *evt)
0e43e99c 872{
7fb1cf16 873 static const int bmap[INPUT_BUTTON__MAX] = {
2a766d29
GH
874 [INPUT_BUTTON_LEFT] = MOUSE_EVENT_LBUTTON,
875 [INPUT_BUTTON_MIDDLE] = MOUSE_EVENT_MBUTTON,
876 [INPUT_BUTTON_RIGHT] = MOUSE_EVENT_RBUTTON,
877 };
878 PS2MouseState *s = (PS2MouseState *)dev;
b5a1b443
EB
879 InputMoveEvent *move;
880 InputBtnEvent *btn;
0e43e99c
FB
881
882 /* check if deltas are recorded when disabled */
883 if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
884 return;
885
568c73a4 886 switch (evt->type) {
2a766d29 887 case INPUT_EVENT_KIND_REL:
32bafa8f 888 move = evt->u.rel.data;
b5a1b443
EB
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;
2a766d29
GH
893 }
894 break;
3b46e624 895
2a766d29 896 case INPUT_EVENT_KIND_BTN:
32bafa8f 897 btn = evt->u.btn.data;
b5a1b443
EB
898 if (btn->down) {
899 s->mouse_buttons |= bmap[btn->button];
900 if (btn->button == INPUT_BUTTON_WHEEL_UP) {
2a766d29 901 s->mouse_dz--;
b5a1b443 902 } else if (btn->button == INPUT_BUTTON_WHEEL_DOWN) {
2a766d29
GH
903 s->mouse_dz++;
904 }
905 } else {
b5a1b443 906 s->mouse_buttons &= ~bmap[btn->button];
2a766d29
GH
907 }
908 break;
909
910 default:
911 /* keep gcc happy */
912 break;
fd214d18 913 }
2a766d29 914}
fd214d18 915
2a766d29
GH
916static void ps2_mouse_sync(DeviceState *dev)
917{
918 PS2MouseState *s = (PS2MouseState *)dev;
919
920 if (s->mouse_buttons) {
921 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
922 }
2858ab09
GA
923 if (!(s->mouse_status & MOUSE_STATUS_REMOTE)) {
924 while (s->common.queue.count < PS2_QUEUE_SIZE - 4) {
0e43e99c
FB
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;
930 }
931 }
932}
933
548df2ac
TS
934void ps2_mouse_fake_event(void *opaque)
935{
2a766d29 936 PS2MouseState *s = opaque;
5edab03d 937 trace_ps2_mouse_fake_event(opaque);
2a766d29
GH
938 s->mouse_dx++;
939 ps2_mouse_sync(opaque);
548df2ac
TS
940}
941
0e43e99c
FB
942void ps2_write_mouse(void *opaque, int val)
943{
944 PS2MouseState *s = (PS2MouseState *)opaque;
5edab03d
DK
945
946 trace_ps2_write_mouse(opaque, val);
0e43e99c
FB
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;
962 }
963 }
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;
1029 }
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:
5fafdf24 1049 if (val == 80)
0e43e99c
FB
1050 s->mouse_type = 3; /* IMPS/2 */
1051 s->mouse_detect_state = 0;
1052 break;
1053 case 3:
5fafdf24 1054 if (val == 80)
0e43e99c
FB
1055 s->mouse_type = 4; /* IMEX */
1056 s->mouse_detect_state = 0;
1057 break;
1058 }
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;
1067 }
1068}
1069
ef74679a 1070static void ps2_common_reset(PS2State *s)
0e43e99c 1071{
0e43e99c
FB
1072 PS2Queue *q;
1073 s->write_cmd = -1;
1074 q = &s->queue;
1075 q->rptr = 0;
1076 q->wptr = 0;
1077 q->count = 0;
deeccef3 1078 s->update_irq(s->update_arg, 0);
0e43e99c
FB
1079}
1080
2858ab09
GA
1081static void ps2_common_post_load(PS2State *s)
1082{
1083 PS2Queue *q = &s->queue;
1084 int size;
1085 int i;
1086 int tmp_data[PS2_QUEUE_SIZE];
1087
1088 /* set the useful data buffer queue size, < PS2_QUEUE_SIZE */
1089 size = q->count > PS2_QUEUE_SIZE ? 0 : q->count;
1090
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;
1098 }
1099 }
1100 memcpy(q->data, tmp_data, size);
1101 }
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);
1107}
1108
ef74679a
DS
1109static void ps2_kbd_reset(void *opaque)
1110{
1111 PS2KbdState *s = (PS2KbdState *) opaque;
1112
5edab03d 1113 trace_ps2_kbd_reset(opaque);
ef74679a
DS
1114 ps2_common_reset(&s->common);
1115 s->scan_enabled = 0;
1116 s->translate = 0;
089adafd 1117 s->scancode_set = 2;
ef74679a
DS
1118}
1119
1120static void ps2_mouse_reset(void *opaque)
1121{
1122 PS2MouseState *s = (PS2MouseState *) opaque;
1123
5edab03d 1124 trace_ps2_mouse_reset(opaque);
ef74679a
DS
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;
1136}
1137
b31442c3
JQ
1138static const VMStateDescription vmstate_ps2_common = {
1139 .name = "PS2 Common State",
1140 .version_id = 3,
1141 .minimum_version_id = 2,
d49805ae 1142 .fields = (VMStateField[]) {
b31442c3
JQ
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()
1149 }
1150};
0e43e99c 1151
7f540ab5
CF
1152static bool ps2_keyboard_ledstate_needed(void *opaque)
1153{
1154 PS2KbdState *s = opaque;
1155
1156 return s->ledstate != 0; /* 0 is default state */
1157}
1158
1159static int ps2_kbd_ledstate_post_load(void *opaque, int version_id)
1160{
1161 PS2KbdState *s = opaque;
1162
1163 kbd_put_ledstate(s->ledstate);
1164 return 0;
1165}
1166
1167static const VMStateDescription vmstate_ps2_keyboard_ledstate = {
1168 .name = "ps2kbd/ledstate",
1169 .version_id = 3,
1170 .minimum_version_id = 2,
7f540ab5 1171 .post_load = ps2_kbd_ledstate_post_load,
5cd8cada 1172 .needed = ps2_keyboard_ledstate_needed,
d49805ae 1173 .fields = (VMStateField[]) {
7f540ab5
CF
1174 VMSTATE_INT32(ledstate, PS2KbdState),
1175 VMSTATE_END_OF_LIST()
1176 }
1177};
1178
57d5c005
HP
1179static bool ps2_keyboard_need_high_bit_needed(void *opaque)
1180{
1181 PS2KbdState *s = opaque;
1182 return s->need_high_bit != 0; /* 0 is the usual state */
1183}
1184
1185static 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()
1193 }
1194};
1195
db596c53 1196static int ps2_kbd_post_load(void* opaque, int version_id)
0e43e99c
FB
1197{
1198 PS2KbdState *s = (PS2KbdState*)opaque;
2858ab09 1199 PS2State *ps2 = &s->common;
7783e9f0 1200
db596c53 1201 if (version_id == 2)
e7d93956 1202 s->scancode_set=2;
2858ab09
GA
1203
1204 ps2_common_post_load(ps2);
1205
0e43e99c
FB
1206 return 0;
1207}
1208
2858ab09
GA
1209static void ps2_kbd_pre_save(void *opaque)
1210{
1211 PS2KbdState *s = (PS2KbdState *)opaque;
1212 PS2State *ps2 = &s->common;
1213
1214 ps2_common_post_load(ps2);
1215}
1216
b31442c3
JQ
1217static const VMStateDescription vmstate_ps2_keyboard = {
1218 .name = "ps2kbd",
1219 .version_id = 3,
db596c53 1220 .minimum_version_id = 2,
db596c53 1221 .post_load = ps2_kbd_post_load,
2858ab09 1222 .pre_save = ps2_kbd_pre_save,
d49805ae 1223 .fields = (VMStateField[]) {
b31442c3
JQ
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()
7f540ab5 1229 },
5cd8cada
JQ
1230 .subsections = (const VMStateDescription*[]) {
1231 &vmstate_ps2_keyboard_ledstate,
57d5c005 1232 &vmstate_ps2_keyboard_need_high_bit,
5cd8cada 1233 NULL
b31442c3
JQ
1234 }
1235};
7783e9f0 1236
2858ab09
GA
1237static int ps2_mouse_post_load(void *opaque, int version_id)
1238{
1239 PS2MouseState *s = (PS2MouseState *)opaque;
1240 PS2State *ps2 = &s->common;
1241
1242 ps2_common_post_load(ps2);
1243
1244 return 0;
1245}
1246
1247static void ps2_mouse_pre_save(void *opaque)
1248{
1249 PS2MouseState *s = (PS2MouseState *)opaque;
1250 PS2State *ps2 = &s->common;
1251
1252 ps2_common_post_load(ps2);
1253}
1254
b31442c3
JQ
1255static const VMStateDescription vmstate_ps2_mouse = {
1256 .name = "ps2mouse",
1257 .version_id = 2,
1258 .minimum_version_id = 2,
2858ab09
GA
1259 .post_load = ps2_mouse_post_load,
1260 .pre_save = ps2_mouse_pre_save,
d49805ae 1261 .fields = (VMStateField[]) {
b31442c3
JQ
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()
1274 }
1275};
0e43e99c 1276
66e6536e
GH
1277static QemuInputHandler ps2_keyboard_handler = {
1278 .name = "QEMU PS/2 Keyboard",
1279 .mask = INPUT_EVENT_MASK_KEY,
1280 .event = ps2_keyboard_event,
1281};
1282
0e43e99c
FB
1283void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
1284{
7267c094 1285 PS2KbdState *s = (PS2KbdState *)g_malloc0(sizeof(PS2KbdState));
0e43e99c 1286
5edab03d 1287 trace_ps2_kbd_init(s);
0e43e99c
FB
1288 s->common.update_irq = update_irq;
1289 s->common.update_arg = update_arg;
e7d93956 1290 s->scancode_set = 2;
0be71e32 1291 vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s);
66e6536e
GH
1292 qemu_input_handler_register((DeviceState *)s,
1293 &ps2_keyboard_handler);
ef74679a 1294 qemu_register_reset(ps2_kbd_reset, s);
0e43e99c
FB
1295 return s;
1296}
1297
2a766d29
GH
1298static 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,
1303};
1304
0e43e99c
FB
1305void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
1306{
7267c094 1307 PS2MouseState *s = (PS2MouseState *)g_malloc0(sizeof(PS2MouseState));
0e43e99c 1308
5edab03d 1309 trace_ps2_mouse_init(s);
0e43e99c
FB
1310 s->common.update_irq = update_irq;
1311 s->common.update_arg = update_arg;
0be71e32 1312 vmstate_register(NULL, 0, &vmstate_ps2_mouse, s);
2a766d29
GH
1313 qemu_input_handler_register((DeviceState *)s,
1314 &ps2_mouse_handler);
ef74679a 1315 qemu_register_reset(ps2_mouse_reset, s);
0e43e99c
FB
1316 return s;
1317}
This page took 1.007729 seconds and 4 git commands to generate.