adb.c 15.0 KB
Newer Older
B
bellard 已提交
1 2
/*
 * QEMU ADB support
3
 *
B
bellard 已提交
4
 * Copyright (c) 2004 Fabrice Bellard
5
 *
B
bellard 已提交
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
P
pbrook 已提交
24
#include "hw.h"
25
#include "adb.h"
26
#include "ui/console.h"
B
bellard 已提交
27

B
blueswir1 已提交
28 29 30 31
/* debug ADB */
//#define DEBUG_ADB

#ifdef DEBUG_ADB
32 33
#define ADB_DPRINTF(fmt, ...) \
do { printf("ADB: " fmt , ## __VA_ARGS__); } while (0)
B
blueswir1 已提交
34
#else
35
#define ADB_DPRINTF(fmt, ...)
B
blueswir1 已提交
36 37
#endif

B
bellard 已提交
38 39 40 41 42 43 44 45 46 47 48 49 50
/* ADB commands */
#define ADB_BUSRESET		0x00
#define ADB_FLUSH               0x01
#define ADB_WRITEREG		0x08
#define ADB_READREG		0x0c

/* ADB device commands */
#define ADB_CMD_SELF_TEST		0xff
#define ADB_CMD_CHANGE_ID		0xfe
#define ADB_CMD_CHANGE_ID_AND_ACT	0xfd
#define ADB_CMD_CHANGE_ID_AND_ENABLE	0x00

/* ADB default device IDs (upper 4 bits of ADB command byte) */
A
Andreas Färber 已提交
51 52 53 54 55 56
#define ADB_DEVID_DONGLE   1
#define ADB_DEVID_KEYBOARD 2
#define ADB_DEVID_MOUSE    3
#define ADB_DEVID_TABLET   4
#define ADB_DEVID_MODEM    5
#define ADB_DEVID_MISC     7
B
bellard 已提交
57

58 59 60
/* error codes */
#define ADB_RET_NOTPRESENT (-2)

A
Andreas Färber 已提交
61 62 63 64 65
static void adb_device_reset(ADBDevice *d)
{
    qdev_reset_all(DEVICE(d));
}

B
bellard 已提交
66
int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
B
bellard 已提交
67 68 69 70
{
    ADBDevice *d;
    int devaddr, cmd, i;

B
bellard 已提交
71
    cmd = buf[0] & 0xf;
72 73
    if (cmd == ADB_BUSRESET) {
        for(i = 0; i < s->nb_devices; i++) {
A
Andreas Färber 已提交
74 75
            d = s->devices[i];
            adb_device_reset(d);
76 77
        }
        return 0;
B
bellard 已提交
78
    }
79
    devaddr = buf[0] >> 4;
B
bellard 已提交
80
    for(i = 0; i < s->nb_devices; i++) {
A
Andreas Färber 已提交
81
        d = s->devices[i];
B
bellard 已提交
82
        if (d->devaddr == devaddr) {
A
Andreas Färber 已提交
83 84
            ADBDeviceClass *adc = ADB_DEVICE_GET_CLASS(d);
            return adc->devreq(d, obuf, buf, len);
B
bellard 已提交
85 86
        }
    }
87
    return ADB_RET_NOTPRESENT;
B
bellard 已提交
88 89
}

90
/* XXX: move that to cuda ? */
B
bellard 已提交
91 92 93 94
int adb_poll(ADBBusState *s, uint8_t *obuf)
{
    ADBDevice *d;
    int olen, i;
95
    uint8_t buf[1];
B
bellard 已提交
96 97 98 99 100

    olen = 0;
    for(i = 0; i < s->nb_devices; i++) {
        if (s->poll_index >= s->nb_devices)
            s->poll_index = 0;
A
Andreas Färber 已提交
101
        d = s->devices[s->poll_index];
102 103 104 105 106 107
        buf[0] = ADB_READREG | (d->devaddr << 4);
        olen = adb_request(s, obuf + 1, buf, 1);
        /* if there is data, we poll again the same device */
        if (olen > 0) {
            obuf[0] = buf[0];
            olen++;
B
bellard 已提交
108
            break;
109 110
        }
        s->poll_index++;
B
bellard 已提交
111 112
    }
    return olen;
B
bellard 已提交
113 114
}

A
Andreas Färber 已提交
115 116 117 118 119 120
static const TypeInfo adb_bus_type_info = {
    .name = TYPE_ADB_BUS,
    .parent = TYPE_BUS,
    .instance_size = sizeof(ADBBusState),
};

A
Andreas Färber 已提交
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
static void adb_device_realizefn(DeviceState *dev, Error **errp)
{
    ADBDevice *d = ADB_DEVICE(dev);
    ADBBusState *bus = ADB_BUS(qdev_get_parent_bus(dev));

    if (bus->nb_devices >= MAX_ADB_DEVICES) {
        return;
    }

    bus->devices[bus->nb_devices++] = d;
}

static void adb_device_class_init(ObjectClass *oc, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(oc);

    dc->realize = adb_device_realizefn;
    dc->bus_type = TYPE_ADB_BUS;
}

static const TypeInfo adb_device_type_info = {
    .name = TYPE_ADB_DEVICE,
    .parent = TYPE_DEVICE,
    .instance_size = sizeof(ADBDevice),
    .abstract = true,
    .class_init = adb_device_class_init,
};

B
bellard 已提交
149 150 151
/***************************************************************/
/* Keyboard ADB device */

A
Andreas Färber 已提交
152 153
#define ADB_KEYBOARD(obj) OBJECT_CHECK(KBDState, (obj), TYPE_ADB_KEYBOARD)

B
bellard 已提交
154
typedef struct KBDState {
A
Andreas Färber 已提交
155 156 157 158
    /*< private >*/
    ADBDevice parent_obj;
    /*< public >*/

B
bellard 已提交
159 160 161 162
    uint8_t data[128];
    int rptr, wptr, count;
} KBDState;

A
Andreas Färber 已提交
163 164 165 166 167 168 169 170 171 172 173 174 175
#define ADB_KEYBOARD_CLASS(class) \
    OBJECT_CLASS_CHECK(ADBKeyboardClass, (class), TYPE_ADB_KEYBOARD)
#define ADB_KEYBOARD_GET_CLASS(obj) \
    OBJECT_GET_CLASS(ADBKeyboardClass, (obj), TYPE_ADB_KEYBOARD)

typedef struct ADBKeyboardClass {
    /*< private >*/
    ADBDeviceClass parent_class;
    /*< public >*/

    DeviceRealize parent_realize;
} ADBKeyboardClass;

B
bellard 已提交
176 177 178 179 180 181
static const uint8_t pc_to_adb_keycode[256] = {
  0, 53, 18, 19, 20, 21, 23, 22, 26, 28, 25, 29, 27, 24, 51, 48,
 12, 13, 14, 15, 17, 16, 32, 34, 31, 35, 33, 30, 36, 54,  0,  1,
  2,  3,  5,  4, 38, 40, 37, 41, 39, 50, 56, 42,  6,  7,  8,  9,
 11, 45, 46, 43, 47, 44,123, 67, 58, 49, 57,122,120, 99,118, 96,
 97, 98,100,101,109, 71,107, 89, 91, 92, 78, 86, 87, 88, 69, 83,
B
bellard 已提交
182
 84, 85, 82, 65,  0,  0, 10,103,111,  0,  0,110, 81,  0,  0,  0,
B
bellard 已提交
183 184
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
B
bellard 已提交
185 186 187 188 189 190
  0,  0,  0, 94,  0, 93,  0,  0,  0,  0,  0,  0,104,102,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 76,125,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,105,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0, 75,  0,  0,124,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,115, 62,116,  0, 59,  0, 60,  0,119,
 61,121,114,117,  0,  0,  0,  0,  0,  0,  0, 55,126,  0,127,  0,
B
bellard 已提交
191
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
B
bellard 已提交
192
  0,  0,  0,  0,  0, 95,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
B
bellard 已提交
193 194 195 196
};

static void adb_kbd_put_keycode(void *opaque, int keycode)
{
A
Andreas Färber 已提交
197
    KBDState *s = opaque;
B
bellard 已提交
198 199 200 201 202 203

    if (s->count < sizeof(s->data)) {
        s->data[s->wptr] = keycode;
        if (++s->wptr == sizeof(s->data))
            s->wptr = 0;
        s->count++;
B
bellard 已提交
204 205 206
    }
}

B
bellard 已提交
207
static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf)
B
bellard 已提交
208
{
B
bellard 已提交
209
    static int ext_keycode;
A
Andreas Färber 已提交
210
    KBDState *s = ADB_KEYBOARD(d);
B
bellard 已提交
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
    int adb_keycode, keycode;
    int olen;

    olen = 0;
    for(;;) {
        if (s->count == 0)
            break;
        keycode = s->data[s->rptr];
        if (++s->rptr == sizeof(s->data))
            s->rptr = 0;
        s->count--;

        if (keycode == 0xe0) {
            ext_keycode = 1;
        } else {
            if (ext_keycode)
                adb_keycode =  pc_to_adb_keycode[keycode | 0x80];
            else
                adb_keycode =  pc_to_adb_keycode[keycode & 0x7f];
230 231 232 233
            obuf[0] = adb_keycode | (keycode & 0x80);
            /* NOTE: could put a second keycode if needed */
            obuf[1] = 0xff;
            olen = 2;
B
bellard 已提交
234 235 236 237 238 239 240 241 242 243
            ext_keycode = 0;
            break;
        }
    }
    return olen;
}

static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
                           const uint8_t *buf, int len)
{
A
Andreas Färber 已提交
244
    KBDState *s = ADB_KEYBOARD(d);
B
bellard 已提交
245 246
    int cmd, reg, olen;

247 248 249 250
    if ((buf[0] & 0x0f) == ADB_FLUSH) {
        /* flush keyboard fifo */
        s->wptr = s->rptr = s->count = 0;
        return 0;
B
bellard 已提交
251
    }
B
bellard 已提交
252 253 254

    cmd = buf[0] & 0xc;
    reg = buf[0] & 0x3;
B
bellard 已提交
255
    olen = 0;
B
bellard 已提交
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
    switch(cmd) {
    case ADB_WRITEREG:
        switch(reg) {
        case 2:
            /* LED status */
            break;
        case 3:
            switch(buf[2]) {
            case ADB_CMD_SELF_TEST:
                break;
            case ADB_CMD_CHANGE_ID:
            case ADB_CMD_CHANGE_ID_AND_ACT:
            case ADB_CMD_CHANGE_ID_AND_ENABLE:
                d->devaddr = buf[1] & 0xf;
                break;
            default:
                /* XXX: check this */
                d->devaddr = buf[1] & 0xf;
                d->handler = buf[2];
                break;
            }
        }
        break;
    case ADB_READREG:
        switch(reg) {
281 282 283
        case 0:
            olen = adb_kbd_poll(d, obuf);
            break;
B
bellard 已提交
284 285 286
        case 1:
            break;
        case 2:
B
bellard 已提交
287 288 289
            obuf[0] = 0x00; /* XXX: check this */
            obuf[1] = 0x07; /* led status */
            olen = 2;
B
bellard 已提交
290 291
            break;
        case 3:
B
bellard 已提交
292 293 294
            obuf[0] = d->handler;
            obuf[1] = d->devaddr;
            olen = 2;
B
bellard 已提交
295 296 297 298
            break;
        }
        break;
    }
B
bellard 已提交
299
    return olen;
B
bellard 已提交
300 301
}

J
Juan Quintela 已提交
302 303 304 305 306 307 308 309 310 311 312 313 314
static const VMStateDescription vmstate_adb_kbd = {
    .name = "adb_kbd",
    .version_id = 1,
    .minimum_version_id = 1,
    .minimum_version_id_old = 1,
    .fields      = (VMStateField[]) {
        VMSTATE_BUFFER(data, KBDState),
        VMSTATE_INT32(rptr, KBDState),
        VMSTATE_INT32(wptr, KBDState),
        VMSTATE_INT32(count, KBDState),
        VMSTATE_END_OF_LIST()
    }
};
B
blueswir1 已提交
315

A
Andreas Färber 已提交
316
static void adb_kbd_reset(DeviceState *dev)
B
bellard 已提交
317
{
A
Andreas Färber 已提交
318 319
    ADBDevice *d = ADB_DEVICE(dev);
    KBDState *s = ADB_KEYBOARD(dev);
B
bellard 已提交
320 321

    d->handler = 1;
A
Andreas Färber 已提交
322 323 324 325 326
    d->devaddr = ADB_DEVID_KEYBOARD;
    memset(s->data, 0, sizeof(s->data));
    s->rptr = 0;
    s->wptr = 0;
    s->count = 0;
B
bellard 已提交
327 328
}

A
Andreas Färber 已提交
329
static void adb_kbd_realizefn(DeviceState *dev, Error **errp)
B
bellard 已提交
330
{
A
Andreas Färber 已提交
331 332 333 334 335
    ADBDevice *d = ADB_DEVICE(dev);
    ADBKeyboardClass *akc = ADB_KEYBOARD_GET_CLASS(dev);

    akc->parent_realize(dev, errp);

B
bellard 已提交
336 337 338
    qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
}

A
Andreas Färber 已提交
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368
static void adb_kbd_initfn(Object *obj)
{
    ADBDevice *d = ADB_DEVICE(obj);

    d->devaddr = ADB_DEVID_KEYBOARD;
}

static void adb_kbd_class_init(ObjectClass *oc, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(oc);
    ADBDeviceClass *adc = ADB_DEVICE_CLASS(oc);
    ADBKeyboardClass *akc = ADB_KEYBOARD_CLASS(oc);

    akc->parent_realize = dc->realize;
    dc->realize = adb_kbd_realizefn;

    adc->devreq = adb_kbd_request;
    dc->reset = adb_kbd_reset;
    dc->vmsd = &vmstate_adb_kbd;
}

static const TypeInfo adb_kbd_type_info = {
    .name = TYPE_ADB_KEYBOARD,
    .parent = TYPE_ADB_DEVICE,
    .instance_size = sizeof(KBDState),
    .instance_init = adb_kbd_initfn,
    .class_init = adb_kbd_class_init,
    .class_size = sizeof(ADBKeyboardClass),
};

B
bellard 已提交
369 370 371
/***************************************************************/
/* Mouse ADB device */

A
Andreas Färber 已提交
372 373
#define ADB_MOUSE(obj) OBJECT_CHECK(MouseState, (obj), TYPE_ADB_MOUSE)

B
bellard 已提交
374
typedef struct MouseState {
A
Andreas Färber 已提交
375 376 377 378
    /*< public >*/
    ADBDevice parent_obj;
    /*< private >*/

B
bellard 已提交
379 380 381 382
    int buttons_state, last_buttons_state;
    int dx, dy, dz;
} MouseState;

A
Andreas Färber 已提交
383 384 385 386 387 388 389 390 391 392 393 394 395
#define ADB_MOUSE_CLASS(class) \
    OBJECT_CLASS_CHECK(ADBMouseClass, (class), TYPE_ADB_MOUSE)
#define ADB_MOUSE_GET_CLASS(obj) \
    OBJECT_GET_CLASS(ADBMouseClass, (obj), TYPE_ADB_MOUSE)

typedef struct ADBMouseClass {
    /*< public >*/
    ADBDeviceClass parent_class;
    /*< private >*/

    DeviceRealize parent_realize;
} ADBMouseClass;

B
bellard 已提交
396 397 398
static void adb_mouse_event(void *opaque,
                            int dx1, int dy1, int dz1, int buttons_state)
{
A
Andreas Färber 已提交
399
    MouseState *s = opaque;
B
bellard 已提交
400 401 402 403 404 405 406 407 408 409

    s->dx += dx1;
    s->dy += dy1;
    s->dz += dz1;
    s->buttons_state = buttons_state;
}


static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
{
A
Andreas Färber 已提交
410
    MouseState *s = ADB_MOUSE(d);
B
bellard 已提交
411 412
    int dx, dy;

B
bellard 已提交
413 414 415
    if (s->last_buttons_state == s->buttons_state &&
        s->dx == 0 && s->dy == 0)
        return 0;
416

B
bellard 已提交
417
    dx = s->dx;
B
bellard 已提交
418 419 420 421
    if (dx < -63)
        dx = -63;
    else if (dx > 63)
        dx = 63;
422

B
bellard 已提交
423
    dy = s->dy;
B
bellard 已提交
424 425 426 427
    if (dy < -63)
        dy = -63;
    else if (dy > 63)
        dy = 63;
428

B
bellard 已提交
429 430 431
    s->dx -= dx;
    s->dy -= dy;
    s->last_buttons_state = s->buttons_state;
432

B
bellard 已提交
433 434
    dx &= 0x7f;
    dy &= 0x7f;
435

436
    if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
B
bellard 已提交
437
        dy |= 0x80;
438
    if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
B
bellard 已提交
439
        dx |= 0x80;
440

441 442 443
    obuf[0] = dy;
    obuf[1] = dx;
    return 2;
B
bellard 已提交
444 445
}

B
bellard 已提交
446 447
static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
                             const uint8_t *buf, int len)
B
bellard 已提交
448
{
A
Andreas Färber 已提交
449
    MouseState *s = ADB_MOUSE(d);
B
bellard 已提交
450
    int cmd, reg, olen;
451

452 453 454 455 456 457 458
    if ((buf[0] & 0x0f) == ADB_FLUSH) {
        /* flush mouse fifo */
        s->buttons_state = s->last_buttons_state;
        s->dx = 0;
        s->dy = 0;
        s->dz = 0;
        return 0;
B
bellard 已提交
459
    }
B
bellard 已提交
460 461 462

    cmd = buf[0] & 0xc;
    reg = buf[0] & 0x3;
B
bellard 已提交
463
    olen = 0;
B
bellard 已提交
464 465
    switch(cmd) {
    case ADB_WRITEREG:
B
blueswir1 已提交
466
        ADB_DPRINTF("write reg %d val 0x%2.2x\n", reg, buf[1]);
B
bellard 已提交
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487
        switch(reg) {
        case 2:
            break;
        case 3:
            switch(buf[2]) {
            case ADB_CMD_SELF_TEST:
                break;
            case ADB_CMD_CHANGE_ID:
            case ADB_CMD_CHANGE_ID_AND_ACT:
            case ADB_CMD_CHANGE_ID_AND_ENABLE:
                d->devaddr = buf[1] & 0xf;
                break;
            default:
                /* XXX: check this */
                d->devaddr = buf[1] & 0xf;
                break;
            }
        }
        break;
    case ADB_READREG:
        switch(reg) {
488 489 490
        case 0:
            olen = adb_mouse_poll(d, obuf);
            break;
B
bellard 已提交
491 492 493
        case 1:
            break;
        case 3:
B
bellard 已提交
494 495 496
            obuf[0] = d->handler;
            obuf[1] = d->devaddr;
            olen = 2;
B
bellard 已提交
497 498
            break;
        }
B
blueswir1 已提交
499 500
        ADB_DPRINTF("read reg %d obuf[0] 0x%2.2x obuf[1] 0x%2.2x\n", reg,
                    obuf[0], obuf[1]);
B
bellard 已提交
501 502
        break;
    }
B
bellard 已提交
503
    return olen;
B
bellard 已提交
504 505
}

A
Andreas Färber 已提交
506
static void adb_mouse_reset(DeviceState *dev)
B
bellard 已提交
507
{
A
Andreas Färber 已提交
508 509
    ADBDevice *d = ADB_DEVICE(dev);
    MouseState *s = ADB_MOUSE(dev);
B
bellard 已提交
510 511

    d->handler = 2;
A
Andreas Färber 已提交
512 513 514
    d->devaddr = ADB_DEVID_MOUSE;
    s->last_buttons_state = s->buttons_state = 0;
    s->dx = s->dy = s->dz = 0;
B
bellard 已提交
515 516
}

J
Juan Quintela 已提交
517 518 519 520 521 522 523 524 525 526 527 528 529 530
static const VMStateDescription vmstate_adb_mouse = {
    .name = "adb_mouse",
    .version_id = 1,
    .minimum_version_id = 1,
    .minimum_version_id_old = 1,
    .fields      = (VMStateField[]) {
        VMSTATE_INT32(buttons_state, MouseState),
        VMSTATE_INT32(last_buttons_state, MouseState),
        VMSTATE_INT32(dx, MouseState),
        VMSTATE_INT32(dy, MouseState),
        VMSTATE_INT32(dz, MouseState),
        VMSTATE_END_OF_LIST()
    }
};
B
blueswir1 已提交
531

A
Andreas Färber 已提交
532
static void adb_mouse_realizefn(DeviceState *dev, Error **errp)
B
bellard 已提交
533
{
A
Andreas Färber 已提交
534 535 536 537 538 539 540 541 542 543 544
    MouseState *s = ADB_MOUSE(dev);
    ADBMouseClass *amc = ADB_MOUSE_GET_CLASS(dev);

    amc->parent_realize(dev, errp);

    qemu_add_mouse_event_handler(adb_mouse_event, s, 0, "QEMU ADB Mouse");
}

static void adb_mouse_initfn(Object *obj)
{
    ADBDevice *d = ADB_DEVICE(obj);
B
bellard 已提交
545

A
Andreas Färber 已提交
546
    d->devaddr = ADB_DEVID_MOUSE;
B
bellard 已提交
547
}
A
Andreas Färber 已提交
548

A
Andreas Färber 已提交
549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571
static void adb_mouse_class_init(ObjectClass *oc, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(oc);
    ADBDeviceClass *adc = ADB_DEVICE_CLASS(oc);
    ADBMouseClass *amc = ADB_MOUSE_CLASS(oc);

    amc->parent_realize = dc->realize;
    dc->realize = adb_mouse_realizefn;

    adc->devreq = adb_mouse_request;
    dc->reset = adb_mouse_reset;
    dc->vmsd = &vmstate_adb_mouse;
}

static const TypeInfo adb_mouse_type_info = {
    .name = TYPE_ADB_MOUSE,
    .parent = TYPE_ADB_DEVICE,
    .instance_size = sizeof(MouseState),
    .instance_init = adb_mouse_initfn,
    .class_init = adb_mouse_class_init,
    .class_size = sizeof(ADBMouseClass),
};

A
Andreas Färber 已提交
572 573 574 575

static void adb_register_types(void)
{
    type_register_static(&adb_bus_type_info);
A
Andreas Färber 已提交
576 577 578
    type_register_static(&adb_device_type_info);
    type_register_static(&adb_kbd_type_info);
    type_register_static(&adb_mouse_type_info);
A
Andreas Färber 已提交
579 580 581
}

type_init(adb_register_types)