qemu/hw/input/ps2.c
<<
>>
Prefs
   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
  80typedef 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
  87typedef struct {
  88    PS2Queue queue;
  89    int32_t write_cmd;
  90    void (*update_irq)(void *, int);
  91    void *update_arg;
  92} PS2State;
  93
  94typedef 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
 105typedef 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.  */
 120static 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,
 126114, 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};
 130static 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,
 136114, 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
 141void 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 */
 160static 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
 180static 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
 196uint32_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
 225static 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
 232static 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
 240void 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_ACK);
 294            break;
 295        }
 296        break;
 297    case KBD_CMD_SCANCODE:
 298        if (val == 0) {
 299            if (s->scancode_set == 1)
 300                ps2_put_keycode(s, 0x43);
 301            else if (s->scancode_set == 2)
 302                ps2_put_keycode(s, 0x41);
 303            else if (s->scancode_set == 3)
 304                ps2_put_keycode(s, 0x3f);
 305        } else {
 306            if (val >= 1 && val <= 3)
 307                s->scancode_set = val;
 308            ps2_queue(&s->common, KBD_REPLY_ACK);
 309        }
 310        s->common.write_cmd = -1;
 311        break;
 312    case KBD_CMD_SET_LEDS:
 313        ps2_set_ledstate(s, val);
 314        ps2_queue(&s->common, KBD_REPLY_ACK);
 315        s->common.write_cmd = -1;
 316        break;
 317    case KBD_CMD_SET_RATE:
 318        ps2_queue(&s->common, KBD_REPLY_ACK);
 319        s->common.write_cmd = -1;
 320        break;
 321    }
 322}
 323
 324/* Set the scancode translation mode.
 325   0 = raw scancodes.
 326   1 = translated scancodes (used by qemu internally).  */
 327
 328void ps2_keyboard_set_translation(void *opaque, int mode)
 329{
 330    PS2KbdState *s = (PS2KbdState *)opaque;
 331    trace_ps2_keyboard_set_translation(opaque, mode);
 332    s->translate = mode;
 333}
 334
 335static void ps2_mouse_send_packet(PS2MouseState *s)
 336{
 337    unsigned int b;
 338    int dx1, dy1, dz1;
 339
 340    dx1 = s->mouse_dx;
 341    dy1 = s->mouse_dy;
 342    dz1 = s->mouse_dz;
 343    /* XXX: increase range to 8 bits ? */
 344    if (dx1 > 127)
 345        dx1 = 127;
 346    else if (dx1 < -127)
 347        dx1 = -127;
 348    if (dy1 > 127)
 349        dy1 = 127;
 350    else if (dy1 < -127)
 351        dy1 = -127;
 352    b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
 353    ps2_queue(&s->common, b);
 354    ps2_queue(&s->common, dx1 & 0xff);
 355    ps2_queue(&s->common, dy1 & 0xff);
 356    /* extra byte for IMPS/2 or IMEX */
 357    switch(s->mouse_type) {
 358    default:
 359        break;
 360    case 3:
 361        if (dz1 > 127)
 362            dz1 = 127;
 363        else if (dz1 < -127)
 364                dz1 = -127;
 365        ps2_queue(&s->common, dz1 & 0xff);
 366        break;
 367    case 4:
 368        if (dz1 > 7)
 369            dz1 = 7;
 370        else if (dz1 < -7)
 371            dz1 = -7;
 372        b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
 373        ps2_queue(&s->common, b);
 374        break;
 375    }
 376
 377    trace_ps2_mouse_send_packet(s, dx1, dy1, dz1, b);
 378    /* update deltas */
 379    s->mouse_dx -= dx1;
 380    s->mouse_dy -= dy1;
 381    s->mouse_dz -= dz1;
 382}
 383
 384static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
 385                            InputEvent *evt)
 386{
 387    static const int bmap[INPUT_BUTTON__MAX] = {
 388        [INPUT_BUTTON_LEFT]   = MOUSE_EVENT_LBUTTON,
 389        [INPUT_BUTTON_MIDDLE] = MOUSE_EVENT_MBUTTON,
 390        [INPUT_BUTTON_RIGHT]  = MOUSE_EVENT_RBUTTON,
 391    };
 392    PS2MouseState *s = (PS2MouseState *)dev;
 393    InputMoveEvent *move;
 394    InputBtnEvent *btn;
 395
 396    /* check if deltas are recorded when disabled */
 397    if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
 398        return;
 399
 400    switch (evt->type) {
 401    case INPUT_EVENT_KIND_REL:
 402        move = evt->u.rel.data;
 403        if (move->axis == INPUT_AXIS_X) {
 404            s->mouse_dx += move->value;
 405        } else if (move->axis == INPUT_AXIS_Y) {
 406            s->mouse_dy -= move->value;
 407        }
 408        break;
 409
 410    case INPUT_EVENT_KIND_BTN:
 411        btn = evt->u.btn.data;
 412        if (btn->down) {
 413            s->mouse_buttons |= bmap[btn->button];
 414            if (btn->button == INPUT_BUTTON_WHEEL_UP) {
 415                s->mouse_dz--;
 416            } else if (btn->button == INPUT_BUTTON_WHEEL_DOWN) {
 417                s->mouse_dz++;
 418            }
 419        } else {
 420            s->mouse_buttons &= ~bmap[btn->button];
 421        }
 422        break;
 423
 424    default:
 425        /* keep gcc happy */
 426        break;
 427    }
 428}
 429
 430static void ps2_mouse_sync(DeviceState *dev)
 431{
 432    PS2MouseState *s = (PS2MouseState *)dev;
 433
 434    if (s->mouse_buttons) {
 435        qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
 436    }
 437    if (!(s->mouse_status & MOUSE_STATUS_REMOTE)) {
 438        while (s->common.queue.count < PS2_QUEUE_SIZE - 4) {
 439            /* if not remote, send event. Multiple events are sent if
 440               too big deltas */
 441            ps2_mouse_send_packet(s);
 442            if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
 443                break;
 444        }
 445    }
 446}
 447
 448void ps2_mouse_fake_event(void *opaque)
 449{
 450    PS2MouseState *s = opaque;
 451    trace_ps2_mouse_fake_event(opaque);
 452    s->mouse_dx++;
 453    ps2_mouse_sync(opaque);
 454}
 455
 456void ps2_write_mouse(void *opaque, int val)
 457{
 458    PS2MouseState *s = (PS2MouseState *)opaque;
 459
 460    trace_ps2_write_mouse(opaque, val);
 461#ifdef DEBUG_MOUSE
 462    printf("kbd: write mouse 0x%02x\n", val);
 463#endif
 464    switch(s->common.write_cmd) {
 465    default:
 466    case -1:
 467        /* mouse command */
 468        if (s->mouse_wrap) {
 469            if (val == AUX_RESET_WRAP) {
 470                s->mouse_wrap = 0;
 471                ps2_queue(&s->common, AUX_ACK);
 472                return;
 473            } else if (val != AUX_RESET) {
 474                ps2_queue(&s->common, val);
 475                return;
 476            }
 477        }
 478        switch(val) {
 479        case AUX_SET_SCALE11:
 480            s->mouse_status &= ~MOUSE_STATUS_SCALE21;
 481            ps2_queue(&s->common, AUX_ACK);
 482            break;
 483        case AUX_SET_SCALE21:
 484            s->mouse_status |= MOUSE_STATUS_SCALE21;
 485            ps2_queue(&s->common, AUX_ACK);
 486            break;
 487        case AUX_SET_STREAM:
 488            s->mouse_status &= ~MOUSE_STATUS_REMOTE;
 489            ps2_queue(&s->common, AUX_ACK);
 490            break;
 491        case AUX_SET_WRAP:
 492            s->mouse_wrap = 1;
 493            ps2_queue(&s->common, AUX_ACK);
 494            break;
 495        case AUX_SET_REMOTE:
 496            s->mouse_status |= MOUSE_STATUS_REMOTE;
 497            ps2_queue(&s->common, AUX_ACK);
 498            break;
 499        case AUX_GET_TYPE:
 500            ps2_queue(&s->common, AUX_ACK);
 501            ps2_queue(&s->common, s->mouse_type);
 502            break;
 503        case AUX_SET_RES:
 504        case AUX_SET_SAMPLE:
 505            s->common.write_cmd = val;
 506            ps2_queue(&s->common, AUX_ACK);
 507            break;
 508        case AUX_GET_SCALE:
 509            ps2_queue(&s->common, AUX_ACK);
 510            ps2_queue(&s->common, s->mouse_status);
 511            ps2_queue(&s->common, s->mouse_resolution);
 512            ps2_queue(&s->common, s->mouse_sample_rate);
 513            break;
 514        case AUX_POLL:
 515            ps2_queue(&s->common, AUX_ACK);
 516            ps2_mouse_send_packet(s);
 517            break;
 518        case AUX_ENABLE_DEV:
 519            s->mouse_status |= MOUSE_STATUS_ENABLED;
 520            ps2_queue(&s->common, AUX_ACK);
 521            break;
 522        case AUX_DISABLE_DEV:
 523            s->mouse_status &= ~MOUSE_STATUS_ENABLED;
 524            ps2_queue(&s->common, AUX_ACK);
 525            break;
 526        case AUX_SET_DEFAULT:
 527            s->mouse_sample_rate = 100;
 528            s->mouse_resolution = 2;
 529            s->mouse_status = 0;
 530            ps2_queue(&s->common, AUX_ACK);
 531            break;
 532        case AUX_RESET:
 533            s->mouse_sample_rate = 100;
 534            s->mouse_resolution = 2;
 535            s->mouse_status = 0;
 536            s->mouse_type = 0;
 537            ps2_queue(&s->common, AUX_ACK);
 538            ps2_queue(&s->common, 0xaa);
 539            ps2_queue(&s->common, s->mouse_type);
 540            break;
 541        default:
 542            break;
 543        }
 544        break;
 545    case AUX_SET_SAMPLE:
 546        s->mouse_sample_rate = val;
 547        /* detect IMPS/2 or IMEX */
 548        switch(s->mouse_detect_state) {
 549        default:
 550        case 0:
 551            if (val == 200)
 552                s->mouse_detect_state = 1;
 553            break;
 554        case 1:
 555            if (val == 100)
 556                s->mouse_detect_state = 2;
 557            else if (val == 200)
 558                s->mouse_detect_state = 3;
 559            else
 560                s->mouse_detect_state = 0;
 561            break;
 562        case 2:
 563            if (val == 80)
 564                s->mouse_type = 3; /* IMPS/2 */
 565            s->mouse_detect_state = 0;
 566            break;
 567        case 3:
 568            if (val == 80)
 569                s->mouse_type = 4; /* IMEX */
 570            s->mouse_detect_state = 0;
 571            break;
 572        }
 573        ps2_queue(&s->common, AUX_ACK);
 574        s->common.write_cmd = -1;
 575        break;
 576    case AUX_SET_RES:
 577        s->mouse_resolution = val;
 578        ps2_queue(&s->common, AUX_ACK);
 579        s->common.write_cmd = -1;
 580        break;
 581    }
 582}
 583
 584static void ps2_common_reset(PS2State *s)
 585{
 586    PS2Queue *q;
 587    s->write_cmd = -1;
 588    q = &s->queue;
 589    q->rptr = 0;
 590    q->wptr = 0;
 591    q->count = 0;
 592    s->update_irq(s->update_arg, 0);
 593}
 594
 595static void ps2_common_post_load(PS2State *s)
 596{
 597    PS2Queue *q = &s->queue;
 598    int size;
 599    int i;
 600    int tmp_data[PS2_QUEUE_SIZE];
 601
 602    /* set the useful data buffer queue size, < PS2_QUEUE_SIZE */
 603    size = q->count > PS2_QUEUE_SIZE ? 0 : q->count;
 604
 605    /* move the queue elements to the start of data array */
 606    if (size > 0) {
 607        for (i = 0; i < size; i++) {
 608            /* move the queue elements to the temporary buffer */
 609            tmp_data[i] = q->data[q->rptr];
 610            if (++q->rptr == 256) {
 611                q->rptr = 0;
 612            }
 613        }
 614        memcpy(q->data, tmp_data, size);
 615    }
 616    /* reset rptr/wptr/count */
 617    q->rptr = 0;
 618    q->wptr = size;
 619    q->count = size;
 620    s->update_irq(s->update_arg, q->count != 0);
 621}
 622
 623static void ps2_kbd_reset(void *opaque)
 624{
 625    PS2KbdState *s = (PS2KbdState *) opaque;
 626
 627    trace_ps2_kbd_reset(opaque);
 628    ps2_common_reset(&s->common);
 629    s->scan_enabled = 0;
 630    s->translate = 0;
 631    s->scancode_set = 2;
 632}
 633
 634static void ps2_mouse_reset(void *opaque)
 635{
 636    PS2MouseState *s = (PS2MouseState *) opaque;
 637
 638    trace_ps2_mouse_reset(opaque);
 639    ps2_common_reset(&s->common);
 640    s->mouse_status = 0;
 641    s->mouse_resolution = 0;
 642    s->mouse_sample_rate = 0;
 643    s->mouse_wrap = 0;
 644    s->mouse_type = 0;
 645    s->mouse_detect_state = 0;
 646    s->mouse_dx = 0;
 647    s->mouse_dy = 0;
 648    s->mouse_dz = 0;
 649    s->mouse_buttons = 0;
 650}
 651
 652static const VMStateDescription vmstate_ps2_common = {
 653    .name = "PS2 Common State",
 654    .version_id = 3,
 655    .minimum_version_id = 2,
 656    .fields = (VMStateField[]) {
 657        VMSTATE_INT32(write_cmd, PS2State),
 658        VMSTATE_INT32(queue.rptr, PS2State),
 659        VMSTATE_INT32(queue.wptr, PS2State),
 660        VMSTATE_INT32(queue.count, PS2State),
 661        VMSTATE_BUFFER(queue.data, PS2State),
 662        VMSTATE_END_OF_LIST()
 663    }
 664};
 665
 666static bool ps2_keyboard_ledstate_needed(void *opaque)
 667{
 668    PS2KbdState *s = opaque;
 669
 670    return s->ledstate != 0; /* 0 is default state */
 671}
 672
 673static int ps2_kbd_ledstate_post_load(void *opaque, int version_id)
 674{
 675    PS2KbdState *s = opaque;
 676
 677    kbd_put_ledstate(s->ledstate);
 678    return 0;
 679}
 680
 681static const VMStateDescription vmstate_ps2_keyboard_ledstate = {
 682    .name = "ps2kbd/ledstate",
 683    .version_id = 3,
 684    .minimum_version_id = 2,
 685    .post_load = ps2_kbd_ledstate_post_load,
 686    .needed = ps2_keyboard_ledstate_needed,
 687    .fields = (VMStateField[]) {
 688        VMSTATE_INT32(ledstate, PS2KbdState),
 689        VMSTATE_END_OF_LIST()
 690    }
 691};
 692
 693static int ps2_kbd_post_load(void* opaque, int version_id)
 694{
 695    PS2KbdState *s = (PS2KbdState*)opaque;
 696    PS2State *ps2 = &s->common;
 697
 698    if (version_id == 2)
 699        s->scancode_set=2;
 700
 701    ps2_common_post_load(ps2);
 702
 703    return 0;
 704}
 705
 706static void ps2_kbd_pre_save(void *opaque)
 707{
 708    PS2KbdState *s = (PS2KbdState *)opaque;
 709    PS2State *ps2 = &s->common;
 710
 711    ps2_common_post_load(ps2);
 712}
 713
 714static const VMStateDescription vmstate_ps2_keyboard = {
 715    .name = "ps2kbd",
 716    .version_id = 3,
 717    .minimum_version_id = 2,
 718    .post_load = ps2_kbd_post_load,
 719    .pre_save = ps2_kbd_pre_save,
 720    .fields = (VMStateField[]) {
 721        VMSTATE_STRUCT(common, PS2KbdState, 0, vmstate_ps2_common, PS2State),
 722        VMSTATE_INT32(scan_enabled, PS2KbdState),
 723        VMSTATE_INT32(translate, PS2KbdState),
 724        VMSTATE_INT32_V(scancode_set, PS2KbdState,3),
 725        VMSTATE_END_OF_LIST()
 726    },
 727    .subsections = (const VMStateDescription*[]) {
 728        &vmstate_ps2_keyboard_ledstate,
 729        NULL
 730    }
 731};
 732
 733static int ps2_mouse_post_load(void *opaque, int version_id)
 734{
 735    PS2MouseState *s = (PS2MouseState *)opaque;
 736    PS2State *ps2 = &s->common;
 737
 738    ps2_common_post_load(ps2);
 739
 740    return 0;
 741}
 742
 743static void ps2_mouse_pre_save(void *opaque)
 744{
 745    PS2MouseState *s = (PS2MouseState *)opaque;
 746    PS2State *ps2 = &s->common;
 747
 748    ps2_common_post_load(ps2);
 749}
 750
 751static const VMStateDescription vmstate_ps2_mouse = {
 752    .name = "ps2mouse",
 753    .version_id = 2,
 754    .minimum_version_id = 2,
 755    .post_load = ps2_mouse_post_load,
 756    .pre_save = ps2_mouse_pre_save,
 757    .fields = (VMStateField[]) {
 758        VMSTATE_STRUCT(common, PS2MouseState, 0, vmstate_ps2_common, PS2State),
 759        VMSTATE_UINT8(mouse_status, PS2MouseState),
 760        VMSTATE_UINT8(mouse_resolution, PS2MouseState),
 761        VMSTATE_UINT8(mouse_sample_rate, PS2MouseState),
 762        VMSTATE_UINT8(mouse_wrap, PS2MouseState),
 763        VMSTATE_UINT8(mouse_type, PS2MouseState),
 764        VMSTATE_UINT8(mouse_detect_state, PS2MouseState),
 765        VMSTATE_INT32(mouse_dx, PS2MouseState),
 766        VMSTATE_INT32(mouse_dy, PS2MouseState),
 767        VMSTATE_INT32(mouse_dz, PS2MouseState),
 768        VMSTATE_UINT8(mouse_buttons, PS2MouseState),
 769        VMSTATE_END_OF_LIST()
 770    }
 771};
 772
 773static QemuInputHandler ps2_keyboard_handler = {
 774    .name  = "QEMU PS/2 Keyboard",
 775    .mask  = INPUT_EVENT_MASK_KEY,
 776    .event = ps2_keyboard_event,
 777};
 778
 779void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
 780{
 781    PS2KbdState *s = (PS2KbdState *)g_malloc0(sizeof(PS2KbdState));
 782
 783    trace_ps2_kbd_init(s);
 784    s->common.update_irq = update_irq;
 785    s->common.update_arg = update_arg;
 786    s->scancode_set = 2;
 787    vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s);
 788    qemu_input_handler_register((DeviceState *)s,
 789                                &ps2_keyboard_handler);
 790    qemu_register_reset(ps2_kbd_reset, s);
 791    return s;
 792}
 793
 794static QemuInputHandler ps2_mouse_handler = {
 795    .name  = "QEMU PS/2 Mouse",
 796    .mask  = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
 797    .event = ps2_mouse_event,
 798    .sync  = ps2_mouse_sync,
 799};
 800
 801void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
 802{
 803    PS2MouseState *s = (PS2MouseState *)g_malloc0(sizeof(PS2MouseState));
 804
 805    trace_ps2_mouse_init(s);
 806    s->common.update_irq = update_irq;
 807    s->common.update_arg = update_arg;
 808    vmstate_register(NULL, 0, &vmstate_ps2_mouse, s);
 809    qemu_input_handler_register((DeviceState *)s,
 810                                &ps2_mouse_handler);
 811    qemu_register_reset(ps2_mouse_reset, s);
 812    return s;
 813}
 814