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