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