1 /* 2 * QEMU PS/2 keyboard/mouse emulation 3 * 4 * Copyright (c) 2003 Fabrice Bellard 5 * 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 */ 24 #include "qemu/osdep.h" 25 #include "hw/hw.h" 26 #include "hw/input/ps2.h" 27 #include "ui/console.h" 28 #include "ui/input.h" 29 #include "sysemu/sysemu.h" 30 31 #include "trace.h" 32 33 /* debug PC keyboard */ 34 //#define DEBUG_KBD 35 36 /* debug PC keyboard : only mouse */ 37 //#define DEBUG_MOUSE 38 39 /* Keyboard Commands */ 40 #define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */ 41 #define KBD_CMD_ECHO 0xEE 42 #define KBD_CMD_SCANCODE 0xF0 /* Get/set scancode set */ 43 #define KBD_CMD_GET_ID 0xF2 /* get keyboard ID */ 44 #define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */ 45 #define KBD_CMD_ENABLE 0xF4 /* Enable scanning */ 46 #define KBD_CMD_RESET_DISABLE 0xF5 /* reset and disable scanning */ 47 #define KBD_CMD_RESET_ENABLE 0xF6 /* reset and enable scanning */ 48 #define KBD_CMD_RESET 0xFF /* Reset */ 49 50 /* Keyboard Replies */ 51 #define KBD_REPLY_POR 0xAA /* Power on reset */ 52 #define KBD_REPLY_ID 0xAB /* Keyboard ID */ 53 #define KBD_REPLY_ACK 0xFA /* Command ACK */ 54 #define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */ 55 56 /* Mouse Commands */ 57 #define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */ 58 #define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */ 59 #define AUX_SET_RES 0xE8 /* Set resolution */ 60 #define AUX_GET_SCALE 0xE9 /* Get scaling factor */ 61 #define AUX_SET_STREAM 0xEA /* Set stream mode */ 62 #define AUX_POLL 0xEB /* Poll */ 63 #define AUX_RESET_WRAP 0xEC /* Reset wrap mode */ 64 #define AUX_SET_WRAP 0xEE /* Set wrap mode */ 65 #define AUX_SET_REMOTE 0xF0 /* Set remote mode */ 66 #define AUX_GET_TYPE 0xF2 /* Get type */ 67 #define AUX_SET_SAMPLE 0xF3 /* Set sample rate */ 68 #define AUX_ENABLE_DEV 0xF4 /* Enable aux device */ 69 #define AUX_DISABLE_DEV 0xF5 /* Disable aux device */ 70 #define AUX_SET_DEFAULT 0xF6 71 #define AUX_RESET 0xFF /* Reset aux device */ 72 #define AUX_ACK 0xFA /* Command byte ACK. */ 73 74 #define MOUSE_STATUS_REMOTE 0x40 75 #define MOUSE_STATUS_ENABLED 0x20 76 #define MOUSE_STATUS_SCALE21 0x10 77 78 #define PS2_QUEUE_SIZE 16 /* Buffer size required by PS/2 protocol */ 79 80 typedef struct { 81 /* Keep the data array 256 bytes long, which compatibility 82 with older qemu versions. */ 83 uint8_t data[256]; 84 int rptr, wptr, count; 85 } PS2Queue; 86 87 typedef struct { 88 PS2Queue queue; 89 int32_t write_cmd; 90 void (*update_irq)(void *, int); 91 void *update_arg; 92 } PS2State; 93 94 typedef struct { 95 PS2State common; 96 int scan_enabled; 97 /* QEMU uses translated PC scancodes internally. To avoid multiple 98 conversions we do the translation (if any) in the PS/2 emulation 99 not the keyboard controller. */ 100 int translate; 101 int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */ 102 int ledstate; 103 } PS2KbdState; 104 105 typedef struct { 106 PS2State common; 107 uint8_t mouse_status; 108 uint8_t mouse_resolution; 109 uint8_t mouse_sample_rate; 110 uint8_t mouse_wrap; 111 uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */ 112 uint8_t mouse_detect_state; 113 int mouse_dx; /* current values, needed for 'poll' mode */ 114 int mouse_dy; 115 int mouse_dz; 116 uint8_t mouse_buttons; 117 } PS2MouseState; 118 119 /* Table to convert from PC scancodes to raw scancodes. */ 120 static const unsigned char ps2_raw_keycode[128] = { 121 0, 118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85, 102, 13, 122 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27, 123 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42, 124 50, 49, 58, 65, 73, 74, 89, 124, 17, 41, 88, 5, 6, 4, 12, 3, 125 11, 2, 10, 1, 9, 119, 126, 108, 117, 125, 123, 107, 115, 116, 121, 105, 126 114, 122, 112, 113, 127, 96, 97, 120, 7, 15, 23, 31, 39, 47, 55, 63, 127 71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87, 111, 128 19, 25, 57, 81, 83, 92, 95, 98, 99, 100, 101, 103, 104, 106, 109, 110 129 }; 130 static const unsigned char ps2_raw_keycode_set3[128] = { 131 0, 8, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85, 102, 13, 132 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 17, 28, 27, 133 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 92, 26, 34, 33, 42, 134 50, 49, 58, 65, 73, 74, 89, 126, 25, 41, 20, 7, 15, 23, 31, 39, 135 47, 2, 63, 71, 79, 118, 95, 108, 117, 125, 132, 107, 115, 116, 124, 105, 136 114, 122, 112, 113, 127, 96, 97, 86, 94, 15, 23, 31, 39, 47, 55, 63, 137 71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87, 111, 138 19, 25, 57, 81, 83, 92, 95, 98, 99, 100, 101, 103, 104, 106, 109, 110 139 }; 140 141 void ps2_queue(void *opaque, int b) 142 { 143 PS2State *s = (PS2State *)opaque; 144 PS2Queue *q = &s->queue; 145 146 if (q->count >= PS2_QUEUE_SIZE - 1) 147 return; 148 q->data[q->wptr] = b; 149 if (++q->wptr == PS2_QUEUE_SIZE) 150 q->wptr = 0; 151 q->count++; 152 s->update_irq(s->update_arg, 1); 153 } 154 155 /* 156 keycode is expressed as follow: 157 bit 7 - 0 key pressed, 1 = key released 158 bits 6-0 - translated scancode set 2 159 */ 160 static void ps2_put_keycode(void *opaque, int keycode) 161 { 162 PS2KbdState *s = opaque; 163 164 trace_ps2_put_keycode(opaque, keycode); 165 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); 166 /* XXX: add support for scancode set 1 */ 167 if (!s->translate && keycode < 0xe0 && s->scancode_set > 1) { 168 if (keycode & 0x80) { 169 ps2_queue(&s->common, 0xf0); 170 } 171 if (s->scancode_set == 2) { 172 keycode = ps2_raw_keycode[keycode & 0x7f]; 173 } else if (s->scancode_set == 3) { 174 keycode = ps2_raw_keycode_set3[keycode & 0x7f]; 175 } 176 } 177 ps2_queue(&s->common, keycode); 178 } 179 180 static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src, 181 InputEvent *evt) 182 { 183 PS2KbdState *s = (PS2KbdState *)dev; 184 int scancodes[3], i, count; 185 InputKeyEvent *key = evt->u.key.data; 186 187 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); 188 count = qemu_input_key_value_to_scancode(key->key, 189 key->down, 190 scancodes); 191 for (i = 0; i < count; i++) { 192 ps2_put_keycode(s, scancodes[i]); 193 } 194 } 195 196 uint32_t ps2_read_data(void *opaque) 197 { 198 PS2State *s = (PS2State *)opaque; 199 PS2Queue *q; 200 int val, index; 201 202 trace_ps2_read_data(opaque); 203 q = &s->queue; 204 if (q->count == 0) { 205 /* NOTE: if no data left, we return the last keyboard one 206 (needed for EMM386) */ 207 /* XXX: need a timer to do things correctly */ 208 index = q->rptr - 1; 209 if (index < 0) 210 index = PS2_QUEUE_SIZE - 1; 211 val = q->data[index]; 212 } else { 213 val = q->data[q->rptr]; 214 if (++q->rptr == PS2_QUEUE_SIZE) 215 q->rptr = 0; 216 q->count--; 217 /* reading deasserts IRQ */ 218 s->update_irq(s->update_arg, 0); 219 /* reassert IRQs if data left */ 220 s->update_irq(s->update_arg, q->count != 0); 221 } 222 return val; 223 } 224 225 static void ps2_set_ledstate(PS2KbdState *s, int ledstate) 226 { 227 trace_ps2_set_ledstate(s, ledstate); 228 s->ledstate = ledstate; 229 kbd_put_ledstate(ledstate); 230 } 231 232 static void ps2_reset_keyboard(PS2KbdState *s) 233 { 234 trace_ps2_reset_keyboard(s); 235 s->scan_enabled = 1; 236 s->scancode_set = 2; 237 ps2_set_ledstate(s, 0); 238 } 239 240 void ps2_write_keyboard(void *opaque, int val) 241 { 242 PS2KbdState *s = (PS2KbdState *)opaque; 243 244 trace_ps2_write_keyboard(opaque, val); 245 switch(s->common.write_cmd) { 246 default: 247 case -1: 248 switch(val) { 249 case 0x00: 250 ps2_queue(&s->common, KBD_REPLY_ACK); 251 break; 252 case 0x05: 253 ps2_queue(&s->common, KBD_REPLY_RESEND); 254 break; 255 case KBD_CMD_GET_ID: 256 ps2_queue(&s->common, KBD_REPLY_ACK); 257 /* We emulate a MF2 AT keyboard here */ 258 ps2_queue(&s->common, KBD_REPLY_ID); 259 if (s->translate) 260 ps2_queue(&s->common, 0x41); 261 else 262 ps2_queue(&s->common, 0x83); 263 break; 264 case KBD_CMD_ECHO: 265 ps2_queue(&s->common, KBD_CMD_ECHO); 266 break; 267 case KBD_CMD_ENABLE: 268 s->scan_enabled = 1; 269 ps2_queue(&s->common, KBD_REPLY_ACK); 270 break; 271 case KBD_CMD_SCANCODE: 272 case KBD_CMD_SET_LEDS: 273 case KBD_CMD_SET_RATE: 274 s->common.write_cmd = val; 275 ps2_queue(&s->common, KBD_REPLY_ACK); 276 break; 277 case KBD_CMD_RESET_DISABLE: 278 ps2_reset_keyboard(s); 279 s->scan_enabled = 0; 280 ps2_queue(&s->common, KBD_REPLY_ACK); 281 break; 282 case KBD_CMD_RESET_ENABLE: 283 ps2_reset_keyboard(s); 284 s->scan_enabled = 1; 285 ps2_queue(&s->common, KBD_REPLY_ACK); 286 break; 287 case KBD_CMD_RESET: 288 ps2_reset_keyboard(s); 289 ps2_queue(&s->common, KBD_REPLY_ACK); 290 ps2_queue(&s->common, KBD_REPLY_POR); 291 break; 292 default: 293 ps2_queue(&s->common, KBD_REPLY_RESEND); 294 break; 295 } 296 break; 297 case KBD_CMD_SCANCODE: 298 if (val == 0) { 299 ps2_queue(&s->common, KBD_REPLY_ACK); 300 if (s->scancode_set == 1) 301 ps2_put_keycode(s, 0x43); 302 else if (s->scancode_set == 2) 303 ps2_put_keycode(s, 0x41); 304 else if (s->scancode_set == 3) 305 ps2_put_keycode(s, 0x3f); 306 } else if (val >= 1 && val <= 3) { 307 s->scancode_set = val; 308 ps2_queue(&s->common, KBD_REPLY_ACK); 309 } else { 310 ps2_queue(&s->common, KBD_REPLY_RESEND); 311 } 312 s->common.write_cmd = -1; 313 break; 314 case KBD_CMD_SET_LEDS: 315 ps2_set_ledstate(s, val); 316 ps2_queue(&s->common, KBD_REPLY_ACK); 317 s->common.write_cmd = -1; 318 break; 319 case KBD_CMD_SET_RATE: 320 ps2_queue(&s->common, KBD_REPLY_ACK); 321 s->common.write_cmd = -1; 322 break; 323 } 324 } 325 326 /* Set the scancode translation mode. 327 0 = raw scancodes. 328 1 = translated scancodes (used by qemu internally). */ 329 330 void ps2_keyboard_set_translation(void *opaque, int mode) 331 { 332 PS2KbdState *s = (PS2KbdState *)opaque; 333 trace_ps2_keyboard_set_translation(opaque, mode); 334 s->translate = mode; 335 } 336 337 static void ps2_mouse_send_packet(PS2MouseState *s) 338 { 339 unsigned int b; 340 int dx1, dy1, dz1; 341 342 dx1 = s->mouse_dx; 343 dy1 = s->mouse_dy; 344 dz1 = s->mouse_dz; 345 /* XXX: increase range to 8 bits ? */ 346 if (dx1 > 127) 347 dx1 = 127; 348 else if (dx1 < -127) 349 dx1 = -127; 350 if (dy1 > 127) 351 dy1 = 127; 352 else if (dy1 < -127) 353 dy1 = -127; 354 b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07); 355 ps2_queue(&s->common, b); 356 ps2_queue(&s->common, dx1 & 0xff); 357 ps2_queue(&s->common, dy1 & 0xff); 358 /* extra byte for IMPS/2 or IMEX */ 359 switch(s->mouse_type) { 360 default: 361 break; 362 case 3: 363 if (dz1 > 127) 364 dz1 = 127; 365 else if (dz1 < -127) 366 dz1 = -127; 367 ps2_queue(&s->common, dz1 & 0xff); 368 break; 369 case 4: 370 if (dz1 > 7) 371 dz1 = 7; 372 else if (dz1 < -7) 373 dz1 = -7; 374 b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1); 375 ps2_queue(&s->common, b); 376 break; 377 } 378 379 trace_ps2_mouse_send_packet(s, dx1, dy1, dz1, b); 380 /* update deltas */ 381 s->mouse_dx -= dx1; 382 s->mouse_dy -= dy1; 383 s->mouse_dz -= dz1; 384 } 385 386 static void ps2_mouse_event(DeviceState *dev, QemuConsole *src, 387 InputEvent *evt) 388 { 389 static const int bmap[INPUT_BUTTON__MAX] = { 390 [INPUT_BUTTON_LEFT] = MOUSE_EVENT_LBUTTON, 391 [INPUT_BUTTON_MIDDLE] = MOUSE_EVENT_MBUTTON, 392 [INPUT_BUTTON_RIGHT] = MOUSE_EVENT_RBUTTON, 393 }; 394 PS2MouseState *s = (PS2MouseState *)dev; 395 InputMoveEvent *move; 396 InputBtnEvent *btn; 397 398 /* check if deltas are recorded when disabled */ 399 if (!(s->mouse_status & MOUSE_STATUS_ENABLED)) 400 return; 401 402 switch (evt->type) { 403 case INPUT_EVENT_KIND_REL: 404 move = evt->u.rel.data; 405 if (move->axis == INPUT_AXIS_X) { 406 s->mouse_dx += move->value; 407 } else if (move->axis == INPUT_AXIS_Y) { 408 s->mouse_dy -= move->value; 409 } 410 break; 411 412 case INPUT_EVENT_KIND_BTN: 413 btn = evt->u.btn.data; 414 if (btn->down) { 415 s->mouse_buttons |= bmap[btn->button]; 416 if (btn->button == INPUT_BUTTON_WHEEL_UP) { 417 s->mouse_dz--; 418 } else if (btn->button == INPUT_BUTTON_WHEEL_DOWN) { 419 s->mouse_dz++; 420 } 421 } else { 422 s->mouse_buttons &= ~bmap[btn->button]; 423 } 424 break; 425 426 default: 427 /* keep gcc happy */ 428 break; 429 } 430 } 431 432 static void ps2_mouse_sync(DeviceState *dev) 433 { 434 PS2MouseState *s = (PS2MouseState *)dev; 435 436 if (s->mouse_buttons) { 437 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); 438 } 439 if (!(s->mouse_status & MOUSE_STATUS_REMOTE)) { 440 while (s->common.queue.count < PS2_QUEUE_SIZE - 4) { 441 /* if not remote, send event. Multiple events are sent if 442 too big deltas */ 443 ps2_mouse_send_packet(s); 444 if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0) 445 break; 446 } 447 } 448 } 449 450 void ps2_mouse_fake_event(void *opaque) 451 { 452 PS2MouseState *s = opaque; 453 trace_ps2_mouse_fake_event(opaque); 454 s->mouse_dx++; 455 ps2_mouse_sync(opaque); 456 } 457 458 void ps2_write_mouse(void *opaque, int val) 459 { 460 PS2MouseState *s = (PS2MouseState *)opaque; 461 462 trace_ps2_write_mouse(opaque, val); 463 #ifdef DEBUG_MOUSE 464 printf("kbd: write mouse 0x%02x\n", val); 465 #endif 466 switch(s->common.write_cmd) { 467 default: 468 case -1: 469 /* mouse command */ 470 if (s->mouse_wrap) { 471 if (val == AUX_RESET_WRAP) { 472 s->mouse_wrap = 0; 473 ps2_queue(&s->common, AUX_ACK); 474 return; 475 } else if (val != AUX_RESET) { 476 ps2_queue(&s->common, val); 477 return; 478 } 479 } 480 switch(val) { 481 case AUX_SET_SCALE11: 482 s->mouse_status &= ~MOUSE_STATUS_SCALE21; 483 ps2_queue(&s->common, AUX_ACK); 484 break; 485 case AUX_SET_SCALE21: 486 s->mouse_status |= MOUSE_STATUS_SCALE21; 487 ps2_queue(&s->common, AUX_ACK); 488 break; 489 case AUX_SET_STREAM: 490 s->mouse_status &= ~MOUSE_STATUS_REMOTE; 491 ps2_queue(&s->common, AUX_ACK); 492 break; 493 case AUX_SET_WRAP: 494 s->mouse_wrap = 1; 495 ps2_queue(&s->common, AUX_ACK); 496 break; 497 case AUX_SET_REMOTE: 498 s->mouse_status |= MOUSE_STATUS_REMOTE; 499 ps2_queue(&s->common, AUX_ACK); 500 break; 501 case AUX_GET_TYPE: 502 ps2_queue(&s->common, AUX_ACK); 503 ps2_queue(&s->common, s->mouse_type); 504 break; 505 case AUX_SET_RES: 506 case AUX_SET_SAMPLE: 507 s->common.write_cmd = val; 508 ps2_queue(&s->common, AUX_ACK); 509 break; 510 case AUX_GET_SCALE: 511 ps2_queue(&s->common, AUX_ACK); 512 ps2_queue(&s->common, s->mouse_status); 513 ps2_queue(&s->common, s->mouse_resolution); 514 ps2_queue(&s->common, s->mouse_sample_rate); 515 break; 516 case AUX_POLL: 517 ps2_queue(&s->common, AUX_ACK); 518 ps2_mouse_send_packet(s); 519 break; 520 case AUX_ENABLE_DEV: 521 s->mouse_status |= MOUSE_STATUS_ENABLED; 522 ps2_queue(&s->common, AUX_ACK); 523 break; 524 case AUX_DISABLE_DEV: 525 s->mouse_status &= ~MOUSE_STATUS_ENABLED; 526 ps2_queue(&s->common, AUX_ACK); 527 break; 528 case AUX_SET_DEFAULT: 529 s->mouse_sample_rate = 100; 530 s->mouse_resolution = 2; 531 s->mouse_status = 0; 532 ps2_queue(&s->common, AUX_ACK); 533 break; 534 case AUX_RESET: 535 s->mouse_sample_rate = 100; 536 s->mouse_resolution = 2; 537 s->mouse_status = 0; 538 s->mouse_type = 0; 539 ps2_queue(&s->common, AUX_ACK); 540 ps2_queue(&s->common, 0xaa); 541 ps2_queue(&s->common, s->mouse_type); 542 break; 543 default: 544 break; 545 } 546 break; 547 case AUX_SET_SAMPLE: 548 s->mouse_sample_rate = val; 549 /* detect IMPS/2 or IMEX */ 550 switch(s->mouse_detect_state) { 551 default: 552 case 0: 553 if (val == 200) 554 s->mouse_detect_state = 1; 555 break; 556 case 1: 557 if (val == 100) 558 s->mouse_detect_state = 2; 559 else if (val == 200) 560 s->mouse_detect_state = 3; 561 else 562 s->mouse_detect_state = 0; 563 break; 564 case 2: 565 if (val == 80) 566 s->mouse_type = 3; /* IMPS/2 */ 567 s->mouse_detect_state = 0; 568 break; 569 case 3: 570 if (val == 80) 571 s->mouse_type = 4; /* IMEX */ 572 s->mouse_detect_state = 0; 573 break; 574 } 575 ps2_queue(&s->common, AUX_ACK); 576 s->common.write_cmd = -1; 577 break; 578 case AUX_SET_RES: 579 s->mouse_resolution = val; 580 ps2_queue(&s->common, AUX_ACK); 581 s->common.write_cmd = -1; 582 break; 583 } 584 } 585 586 static void ps2_common_reset(PS2State *s) 587 { 588 PS2Queue *q; 589 s->write_cmd = -1; 590 q = &s->queue; 591 q->rptr = 0; 592 q->wptr = 0; 593 q->count = 0; 594 s->update_irq(s->update_arg, 0); 595 } 596 597 static void ps2_common_post_load(PS2State *s) 598 { 599 PS2Queue *q = &s->queue; 600 int size; 601 int i; 602 int tmp_data[PS2_QUEUE_SIZE]; 603 604 /* set the useful data buffer queue size, < PS2_QUEUE_SIZE */ 605 size = q->count > PS2_QUEUE_SIZE ? 0 : q->count; 606 607 /* move the queue elements to the start of data array */ 608 if (size > 0) { 609 for (i = 0; i < size; i++) { 610 /* move the queue elements to the temporary buffer */ 611 tmp_data[i] = q->data[q->rptr]; 612 if (++q->rptr == 256) { 613 q->rptr = 0; 614 } 615 } 616 memcpy(q->data, tmp_data, size); 617 } 618 /* reset rptr/wptr/count */ 619 q->rptr = 0; 620 q->wptr = size; 621 q->count = size; 622 s->update_irq(s->update_arg, q->count != 0); 623 } 624 625 static void ps2_kbd_reset(void *opaque) 626 { 627 PS2KbdState *s = (PS2KbdState *) opaque; 628 629 trace_ps2_kbd_reset(opaque); 630 ps2_common_reset(&s->common); 631 s->scan_enabled = 0; 632 s->translate = 0; 633 s->scancode_set = 2; 634 } 635 636 static void ps2_mouse_reset(void *opaque) 637 { 638 PS2MouseState *s = (PS2MouseState *) opaque; 639 640 trace_ps2_mouse_reset(opaque); 641 ps2_common_reset(&s->common); 642 s->mouse_status = 0; 643 s->mouse_resolution = 0; 644 s->mouse_sample_rate = 0; 645 s->mouse_wrap = 0; 646 s->mouse_type = 0; 647 s->mouse_detect_state = 0; 648 s->mouse_dx = 0; 649 s->mouse_dy = 0; 650 s->mouse_dz = 0; 651 s->mouse_buttons = 0; 652 } 653 654 static const VMStateDescription vmstate_ps2_common = { 655 .name = "PS2 Common State", 656 .version_id = 3, 657 .minimum_version_id = 2, 658 .fields = (VMStateField[]) { 659 VMSTATE_INT32(write_cmd, PS2State), 660 VMSTATE_INT32(queue.rptr, PS2State), 661 VMSTATE_INT32(queue.wptr, PS2State), 662 VMSTATE_INT32(queue.count, PS2State), 663 VMSTATE_BUFFER(queue.data, PS2State), 664 VMSTATE_END_OF_LIST() 665 } 666 }; 667 668 static bool ps2_keyboard_ledstate_needed(void *opaque) 669 { 670 PS2KbdState *s = opaque; 671 672 return s->ledstate != 0; /* 0 is default state */ 673 } 674 675 static int ps2_kbd_ledstate_post_load(void *opaque, int version_id) 676 { 677 PS2KbdState *s = opaque; 678 679 kbd_put_ledstate(s->ledstate); 680 return 0; 681 } 682 683 static const VMStateDescription vmstate_ps2_keyboard_ledstate = { 684 .name = "ps2kbd/ledstate", 685 .version_id = 3, 686 .minimum_version_id = 2, 687 .post_load = ps2_kbd_ledstate_post_load, 688 .needed = ps2_keyboard_ledstate_needed, 689 .fields = (VMStateField[]) { 690 VMSTATE_INT32(ledstate, PS2KbdState), 691 VMSTATE_END_OF_LIST() 692 } 693 }; 694 695 static int ps2_kbd_post_load(void* opaque, int version_id) 696 { 697 PS2KbdState *s = (PS2KbdState*)opaque; 698 PS2State *ps2 = &s->common; 699 700 if (version_id == 2) 701 s->scancode_set=2; 702 703 ps2_common_post_load(ps2); 704 705 return 0; 706 } 707 708 static void ps2_kbd_pre_save(void *opaque) 709 { 710 PS2KbdState *s = (PS2KbdState *)opaque; 711 PS2State *ps2 = &s->common; 712 713 ps2_common_post_load(ps2); 714 } 715 716 static const VMStateDescription vmstate_ps2_keyboard = { 717 .name = "ps2kbd", 718 .version_id = 3, 719 .minimum_version_id = 2, 720 .post_load = ps2_kbd_post_load, 721 .pre_save = ps2_kbd_pre_save, 722 .fields = (VMStateField[]) { 723 VMSTATE_STRUCT(common, PS2KbdState, 0, vmstate_ps2_common, PS2State), 724 VMSTATE_INT32(scan_enabled, PS2KbdState), 725 VMSTATE_INT32(translate, PS2KbdState), 726 VMSTATE_INT32_V(scancode_set, PS2KbdState,3), 727 VMSTATE_END_OF_LIST() 728 }, 729 .subsections = (const VMStateDescription*[]) { 730 &vmstate_ps2_keyboard_ledstate, 731 NULL 732 } 733 }; 734 735 static int ps2_mouse_post_load(void *opaque, int version_id) 736 { 737 PS2MouseState *s = (PS2MouseState *)opaque; 738 PS2State *ps2 = &s->common; 739 740 ps2_common_post_load(ps2); 741 742 return 0; 743 } 744 745 static void ps2_mouse_pre_save(void *opaque) 746 { 747 PS2MouseState *s = (PS2MouseState *)opaque; 748 PS2State *ps2 = &s->common; 749 750 ps2_common_post_load(ps2); 751 } 752 753 static const VMStateDescription vmstate_ps2_mouse = { 754 .name = "ps2mouse", 755 .version_id = 2, 756 .minimum_version_id = 2, 757 .post_load = ps2_mouse_post_load, 758 .pre_save = ps2_mouse_pre_save, 759 .fields = (VMStateField[]) { 760 VMSTATE_STRUCT(common, PS2MouseState, 0, vmstate_ps2_common, PS2State), 761 VMSTATE_UINT8(mouse_status, PS2MouseState), 762 VMSTATE_UINT8(mouse_resolution, PS2MouseState), 763 VMSTATE_UINT8(mouse_sample_rate, PS2MouseState), 764 VMSTATE_UINT8(mouse_wrap, PS2MouseState), 765 VMSTATE_UINT8(mouse_type, PS2MouseState), 766 VMSTATE_UINT8(mouse_detect_state, PS2MouseState), 767 VMSTATE_INT32(mouse_dx, PS2MouseState), 768 VMSTATE_INT32(mouse_dy, PS2MouseState), 769 VMSTATE_INT32(mouse_dz, PS2MouseState), 770 VMSTATE_UINT8(mouse_buttons, PS2MouseState), 771 VMSTATE_END_OF_LIST() 772 } 773 }; 774 775 static QemuInputHandler ps2_keyboard_handler = { 776 .name = "QEMU PS/2 Keyboard", 777 .mask = INPUT_EVENT_MASK_KEY, 778 .event = ps2_keyboard_event, 779 }; 780 781 void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg) 782 { 783 PS2KbdState *s = (PS2KbdState *)g_malloc0(sizeof(PS2KbdState)); 784 785 trace_ps2_kbd_init(s); 786 s->common.update_irq = update_irq; 787 s->common.update_arg = update_arg; 788 s->scancode_set = 2; 789 vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s); 790 qemu_input_handler_register((DeviceState *)s, 791 &ps2_keyboard_handler); 792 qemu_register_reset(ps2_kbd_reset, s); 793 return s; 794 } 795 796 static QemuInputHandler ps2_mouse_handler = { 797 .name = "QEMU PS/2 Mouse", 798 .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL, 799 .event = ps2_mouse_event, 800 .sync = ps2_mouse_sync, 801 }; 802 803 void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg) 804 { 805 PS2MouseState *s = (PS2MouseState *)g_malloc0(sizeof(PS2MouseState)); 806 807 trace_ps2_mouse_init(s); 808 s->common.update_irq = update_irq; 809 s->common.update_arg = update_arg; 810 vmstate_register(NULL, 0, &vmstate_ps2_mouse, s); 811 qemu_input_handler_register((DeviceState *)s, 812 &ps2_mouse_handler); 813 qemu_register_reset(ps2_mouse_reset, s); 814 return s; 815 } 816