qemu/hw/input/adb.c
<<
>>
Prefs
   1/*
   2 * QEMU ADB support
   3 *
   4 * Copyright (c) 2004 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/adb.h"
  26#include "ui/console.h"
  27
  28/* debug ADB */
  29//#define DEBUG_ADB
  30
  31#ifdef DEBUG_ADB
  32#define ADB_DPRINTF(fmt, ...) \
  33do { printf("ADB: " fmt , ## __VA_ARGS__); } while (0)
  34#else
  35#define ADB_DPRINTF(fmt, ...)
  36#endif
  37
  38/* ADB commands */
  39#define ADB_BUSRESET            0x00
  40#define ADB_FLUSH               0x01
  41#define ADB_WRITEREG            0x08
  42#define ADB_READREG             0x0c
  43
  44/* ADB device commands */
  45#define ADB_CMD_SELF_TEST               0xff
  46#define ADB_CMD_CHANGE_ID               0xfe
  47#define ADB_CMD_CHANGE_ID_AND_ACT       0xfd
  48#define ADB_CMD_CHANGE_ID_AND_ENABLE    0x00
  49
  50/* ADB default device IDs (upper 4 bits of ADB command byte) */
  51#define ADB_DEVID_DONGLE   1
  52#define ADB_DEVID_KEYBOARD 2
  53#define ADB_DEVID_MOUSE    3
  54#define ADB_DEVID_TABLET   4
  55#define ADB_DEVID_MODEM    5
  56#define ADB_DEVID_MISC     7
  57
  58/* error codes */
  59#define ADB_RET_NOTPRESENT (-2)
  60
  61static void adb_device_reset(ADBDevice *d)
  62{
  63    qdev_reset_all(DEVICE(d));
  64}
  65
  66int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
  67{
  68    ADBDevice *d;
  69    int devaddr, cmd, i;
  70
  71    cmd = buf[0] & 0xf;
  72    if (cmd == ADB_BUSRESET) {
  73        for(i = 0; i < s->nb_devices; i++) {
  74            d = s->devices[i];
  75            adb_device_reset(d);
  76        }
  77        return 0;
  78    }
  79    devaddr = buf[0] >> 4;
  80    for(i = 0; i < s->nb_devices; i++) {
  81        d = s->devices[i];
  82        if (d->devaddr == devaddr) {
  83            ADBDeviceClass *adc = ADB_DEVICE_GET_CLASS(d);
  84            return adc->devreq(d, obuf, buf, len);
  85        }
  86    }
  87    return ADB_RET_NOTPRESENT;
  88}
  89
  90/* XXX: move that to cuda ? */
  91int adb_poll(ADBBusState *s, uint8_t *obuf)
  92{
  93    ADBDevice *d;
  94    int olen, i;
  95    uint8_t buf[1];
  96
  97    olen = 0;
  98    for(i = 0; i < s->nb_devices; i++) {
  99        if (s->poll_index >= s->nb_devices)
 100            s->poll_index = 0;
 101        d = s->devices[s->poll_index];
 102        buf[0] = ADB_READREG | (d->devaddr << 4);
 103        olen = adb_request(s, obuf + 1, buf, 1);
 104        /* if there is data, we poll again the same device */
 105        if (olen > 0) {
 106            obuf[0] = buf[0];
 107            olen++;
 108            break;
 109        }
 110        s->poll_index++;
 111    }
 112    return olen;
 113}
 114
 115static const TypeInfo adb_bus_type_info = {
 116    .name = TYPE_ADB_BUS,
 117    .parent = TYPE_BUS,
 118    .instance_size = sizeof(ADBBusState),
 119};
 120
 121static void adb_device_realizefn(DeviceState *dev, Error **errp)
 122{
 123    ADBDevice *d = ADB_DEVICE(dev);
 124    ADBBusState *bus = ADB_BUS(qdev_get_parent_bus(dev));
 125
 126    if (bus->nb_devices >= MAX_ADB_DEVICES) {
 127        return;
 128    }
 129
 130    bus->devices[bus->nb_devices++] = d;
 131}
 132
 133static void adb_device_class_init(ObjectClass *oc, void *data)
 134{
 135    DeviceClass *dc = DEVICE_CLASS(oc);
 136
 137    dc->realize = adb_device_realizefn;
 138    dc->bus_type = TYPE_ADB_BUS;
 139}
 140
 141static const TypeInfo adb_device_type_info = {
 142    .name = TYPE_ADB_DEVICE,
 143    .parent = TYPE_DEVICE,
 144    .instance_size = sizeof(ADBDevice),
 145    .abstract = true,
 146    .class_init = adb_device_class_init,
 147};
 148
 149/***************************************************************/
 150/* Keyboard ADB device */
 151
 152#define ADB_KEYBOARD(obj) OBJECT_CHECK(KBDState, (obj), TYPE_ADB_KEYBOARD)
 153
 154typedef struct KBDState {
 155    /*< private >*/
 156    ADBDevice parent_obj;
 157    /*< public >*/
 158
 159    uint8_t data[128];
 160    int rptr, wptr, count;
 161} KBDState;
 162
 163#define ADB_KEYBOARD_CLASS(class) \
 164    OBJECT_CLASS_CHECK(ADBKeyboardClass, (class), TYPE_ADB_KEYBOARD)
 165#define ADB_KEYBOARD_GET_CLASS(obj) \
 166    OBJECT_GET_CLASS(ADBKeyboardClass, (obj), TYPE_ADB_KEYBOARD)
 167
 168typedef struct ADBKeyboardClass {
 169    /*< private >*/
 170    ADBDeviceClass parent_class;
 171    /*< public >*/
 172
 173    DeviceRealize parent_realize;
 174} ADBKeyboardClass;
 175
 176static const uint8_t pc_to_adb_keycode[256] = {
 177  0, 53, 18, 19, 20, 21, 23, 22, 26, 28, 25, 29, 27, 24, 51, 48,
 178 12, 13, 14, 15, 17, 16, 32, 34, 31, 35, 33, 30, 36, 54,  0,  1,
 179  2,  3,  5,  4, 38, 40, 37, 41, 39, 50, 56, 42,  6,  7,  8,  9,
 180 11, 45, 46, 43, 47, 44,123, 67, 58, 49, 57,122,120, 99,118, 96,
 181 97, 98,100,101,109, 71,107, 89, 91, 92, 78, 86, 87, 88, 69, 83,
 182 84, 85, 82, 65,  0,  0, 10,103,111,  0,  0,110, 81,  0,  0,  0,
 183  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 184  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 185  0,  0,  0, 94,  0, 93,  0,  0,  0,  0,  0,  0,104,102,  0,  0,
 186  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 76,125,  0,  0,
 187  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,105,  0,  0,  0,  0,  0,
 188  0,  0,  0,  0,  0, 75,  0,  0,124,  0,  0,  0,  0,  0,  0,  0,
 189  0,  0,  0,  0,  0,  0,  0,115, 62,116,  0, 59,  0, 60,  0,119,
 190 61,121,114,117,  0,  0,  0,  0,  0,  0,  0, 55,126,  0,127,  0,
 191  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 192  0,  0,  0,  0,  0, 95,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 193};
 194
 195static void adb_kbd_put_keycode(void *opaque, int keycode)
 196{
 197    KBDState *s = opaque;
 198
 199    if (s->count < sizeof(s->data)) {
 200        s->data[s->wptr] = keycode;
 201        if (++s->wptr == sizeof(s->data))
 202            s->wptr = 0;
 203        s->count++;
 204    }
 205}
 206
 207static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf)
 208{
 209    static int ext_keycode;
 210    KBDState *s = ADB_KEYBOARD(d);
 211    int adb_keycode, keycode;
 212    int olen;
 213
 214    olen = 0;
 215    for(;;) {
 216        if (s->count == 0)
 217            break;
 218        keycode = s->data[s->rptr];
 219        if (++s->rptr == sizeof(s->data))
 220            s->rptr = 0;
 221        s->count--;
 222
 223        if (keycode == 0xe0) {
 224            ext_keycode = 1;
 225        } else {
 226            if (ext_keycode)
 227                adb_keycode =  pc_to_adb_keycode[keycode | 0x80];
 228            else
 229                adb_keycode =  pc_to_adb_keycode[keycode & 0x7f];
 230            obuf[0] = adb_keycode | (keycode & 0x80);
 231            /* NOTE: could put a second keycode if needed */
 232            obuf[1] = 0xff;
 233            olen = 2;
 234            ext_keycode = 0;
 235            break;
 236        }
 237    }
 238    return olen;
 239}
 240
 241static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
 242                           const uint8_t *buf, int len)
 243{
 244    KBDState *s = ADB_KEYBOARD(d);
 245    int cmd, reg, olen;
 246
 247    if ((buf[0] & 0x0f) == ADB_FLUSH) {
 248        /* flush keyboard fifo */
 249        s->wptr = s->rptr = s->count = 0;
 250        return 0;
 251    }
 252
 253    cmd = buf[0] & 0xc;
 254    reg = buf[0] & 0x3;
 255    olen = 0;
 256    switch(cmd) {
 257    case ADB_WRITEREG:
 258        switch(reg) {
 259        case 2:
 260            /* LED status */
 261            break;
 262        case 3:
 263            switch(buf[2]) {
 264            case ADB_CMD_SELF_TEST:
 265                break;
 266            case ADB_CMD_CHANGE_ID:
 267            case ADB_CMD_CHANGE_ID_AND_ACT:
 268            case ADB_CMD_CHANGE_ID_AND_ENABLE:
 269                d->devaddr = buf[1] & 0xf;
 270                break;
 271            default:
 272                /* XXX: check this */
 273                d->devaddr = buf[1] & 0xf;
 274                d->handler = buf[2];
 275                break;
 276            }
 277        }
 278        break;
 279    case ADB_READREG:
 280        switch(reg) {
 281        case 0:
 282            olen = adb_kbd_poll(d, obuf);
 283            break;
 284        case 1:
 285            break;
 286        case 2:
 287            obuf[0] = 0x00; /* XXX: check this */
 288            obuf[1] = 0x07; /* led status */
 289            olen = 2;
 290            break;
 291        case 3:
 292            obuf[0] = d->handler;
 293            obuf[1] = d->devaddr;
 294            olen = 2;
 295            break;
 296        }
 297        break;
 298    }
 299    return olen;
 300}
 301
 302static const VMStateDescription vmstate_adb_kbd = {
 303    .name = "adb_kbd",
 304    .version_id = 1,
 305    .minimum_version_id = 1,
 306    .minimum_version_id_old = 1,
 307    .fields      = (VMStateField[]) {
 308        VMSTATE_BUFFER(data, KBDState),
 309        VMSTATE_INT32(rptr, KBDState),
 310        VMSTATE_INT32(wptr, KBDState),
 311        VMSTATE_INT32(count, KBDState),
 312        VMSTATE_END_OF_LIST()
 313    }
 314};
 315
 316static void adb_kbd_reset(DeviceState *dev)
 317{
 318    ADBDevice *d = ADB_DEVICE(dev);
 319    KBDState *s = ADB_KEYBOARD(dev);
 320
 321    d->handler = 1;
 322    d->devaddr = ADB_DEVID_KEYBOARD;
 323    memset(s->data, 0, sizeof(s->data));
 324    s->rptr = 0;
 325    s->wptr = 0;
 326    s->count = 0;
 327}
 328
 329static void adb_kbd_realizefn(DeviceState *dev, Error **errp)
 330{
 331    ADBDevice *d = ADB_DEVICE(dev);
 332    ADBKeyboardClass *akc = ADB_KEYBOARD_GET_CLASS(dev);
 333
 334    akc->parent_realize(dev, errp);
 335
 336    qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
 337}
 338
 339static void adb_kbd_initfn(Object *obj)
 340{
 341    ADBDevice *d = ADB_DEVICE(obj);
 342
 343    d->devaddr = ADB_DEVID_KEYBOARD;
 344}
 345
 346static void adb_kbd_class_init(ObjectClass *oc, void *data)
 347{
 348    DeviceClass *dc = DEVICE_CLASS(oc);
 349    ADBDeviceClass *adc = ADB_DEVICE_CLASS(oc);
 350    ADBKeyboardClass *akc = ADB_KEYBOARD_CLASS(oc);
 351
 352    akc->parent_realize = dc->realize;
 353    dc->realize = adb_kbd_realizefn;
 354
 355    adc->devreq = adb_kbd_request;
 356    dc->reset = adb_kbd_reset;
 357    dc->vmsd = &vmstate_adb_kbd;
 358}
 359
 360static const TypeInfo adb_kbd_type_info = {
 361    .name = TYPE_ADB_KEYBOARD,
 362    .parent = TYPE_ADB_DEVICE,
 363    .instance_size = sizeof(KBDState),
 364    .instance_init = adb_kbd_initfn,
 365    .class_init = adb_kbd_class_init,
 366    .class_size = sizeof(ADBKeyboardClass),
 367};
 368
 369/***************************************************************/
 370/* Mouse ADB device */
 371
 372#define ADB_MOUSE(obj) OBJECT_CHECK(MouseState, (obj), TYPE_ADB_MOUSE)
 373
 374typedef struct MouseState {
 375    /*< public >*/
 376    ADBDevice parent_obj;
 377    /*< private >*/
 378
 379    int buttons_state, last_buttons_state;
 380    int dx, dy, dz;
 381} MouseState;
 382
 383#define ADB_MOUSE_CLASS(class) \
 384    OBJECT_CLASS_CHECK(ADBMouseClass, (class), TYPE_ADB_MOUSE)
 385#define ADB_MOUSE_GET_CLASS(obj) \
 386    OBJECT_GET_CLASS(ADBMouseClass, (obj), TYPE_ADB_MOUSE)
 387
 388typedef struct ADBMouseClass {
 389    /*< public >*/
 390    ADBDeviceClass parent_class;
 391    /*< private >*/
 392
 393    DeviceRealize parent_realize;
 394} ADBMouseClass;
 395
 396static void adb_mouse_event(void *opaque,
 397                            int dx1, int dy1, int dz1, int buttons_state)
 398{
 399    MouseState *s = opaque;
 400
 401    s->dx += dx1;
 402    s->dy += dy1;
 403    s->dz += dz1;
 404    s->buttons_state = buttons_state;
 405}
 406
 407
 408static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
 409{
 410    MouseState *s = ADB_MOUSE(d);
 411    int dx, dy;
 412
 413    if (s->last_buttons_state == s->buttons_state &&
 414        s->dx == 0 && s->dy == 0)
 415        return 0;
 416
 417    dx = s->dx;
 418    if (dx < -63)
 419        dx = -63;
 420    else if (dx > 63)
 421        dx = 63;
 422
 423    dy = s->dy;
 424    if (dy < -63)
 425        dy = -63;
 426    else if (dy > 63)
 427        dy = 63;
 428
 429    s->dx -= dx;
 430    s->dy -= dy;
 431    s->last_buttons_state = s->buttons_state;
 432
 433    dx &= 0x7f;
 434    dy &= 0x7f;
 435
 436    if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
 437        dy |= 0x80;
 438    if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
 439        dx |= 0x80;
 440
 441    obuf[0] = dy;
 442    obuf[1] = dx;
 443    return 2;
 444}
 445
 446static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
 447                             const uint8_t *buf, int len)
 448{
 449    MouseState *s = ADB_MOUSE(d);
 450    int cmd, reg, olen;
 451
 452    if ((buf[0] & 0x0f) == ADB_FLUSH) {
 453        /* flush mouse fifo */
 454        s->buttons_state = s->last_buttons_state;
 455        s->dx = 0;
 456        s->dy = 0;
 457        s->dz = 0;
 458        return 0;
 459    }
 460
 461    cmd = buf[0] & 0xc;
 462    reg = buf[0] & 0x3;
 463    olen = 0;
 464    switch(cmd) {
 465    case ADB_WRITEREG:
 466        ADB_DPRINTF("write reg %d val 0x%2.2x\n", reg, buf[1]);
 467        switch(reg) {
 468        case 2:
 469            break;
 470        case 3:
 471            switch(buf[2]) {
 472            case ADB_CMD_SELF_TEST:
 473                break;
 474            case ADB_CMD_CHANGE_ID:
 475            case ADB_CMD_CHANGE_ID_AND_ACT:
 476            case ADB_CMD_CHANGE_ID_AND_ENABLE:
 477                d->devaddr = buf[1] & 0xf;
 478                break;
 479            default:
 480                /* XXX: check this */
 481                d->devaddr = buf[1] & 0xf;
 482                break;
 483            }
 484        }
 485        break;
 486    case ADB_READREG:
 487        switch(reg) {
 488        case 0:
 489            olen = adb_mouse_poll(d, obuf);
 490            break;
 491        case 1:
 492            break;
 493        case 3:
 494            obuf[0] = d->handler;
 495            obuf[1] = d->devaddr;
 496            olen = 2;
 497            break;
 498        }
 499        ADB_DPRINTF("read reg %d obuf[0] 0x%2.2x obuf[1] 0x%2.2x\n", reg,
 500                    obuf[0], obuf[1]);
 501        break;
 502    }
 503    return olen;
 504}
 505
 506static void adb_mouse_reset(DeviceState *dev)
 507{
 508    ADBDevice *d = ADB_DEVICE(dev);
 509    MouseState *s = ADB_MOUSE(dev);
 510
 511    d->handler = 2;
 512    d->devaddr = ADB_DEVID_MOUSE;
 513    s->last_buttons_state = s->buttons_state = 0;
 514    s->dx = s->dy = s->dz = 0;
 515}
 516
 517static const VMStateDescription vmstate_adb_mouse = {
 518    .name = "adb_mouse",
 519    .version_id = 1,
 520    .minimum_version_id = 1,
 521    .minimum_version_id_old = 1,
 522    .fields      = (VMStateField[]) {
 523        VMSTATE_INT32(buttons_state, MouseState),
 524        VMSTATE_INT32(last_buttons_state, MouseState),
 525        VMSTATE_INT32(dx, MouseState),
 526        VMSTATE_INT32(dy, MouseState),
 527        VMSTATE_INT32(dz, MouseState),
 528        VMSTATE_END_OF_LIST()
 529    }
 530};
 531
 532static void adb_mouse_realizefn(DeviceState *dev, Error **errp)
 533{
 534    MouseState *s = ADB_MOUSE(dev);
 535    ADBMouseClass *amc = ADB_MOUSE_GET_CLASS(dev);
 536
 537    amc->parent_realize(dev, errp);
 538
 539    qemu_add_mouse_event_handler(adb_mouse_event, s, 0, "QEMU ADB Mouse");
 540}
 541
 542static void adb_mouse_initfn(Object *obj)
 543{
 544    ADBDevice *d = ADB_DEVICE(obj);
 545
 546    d->devaddr = ADB_DEVID_MOUSE;
 547}
 548
 549static void adb_mouse_class_init(ObjectClass *oc, void *data)
 550{
 551    DeviceClass *dc = DEVICE_CLASS(oc);
 552    ADBDeviceClass *adc = ADB_DEVICE_CLASS(oc);
 553    ADBMouseClass *amc = ADB_MOUSE_CLASS(oc);
 554
 555    amc->parent_realize = dc->realize;
 556    dc->realize = adb_mouse_realizefn;
 557
 558    adc->devreq = adb_mouse_request;
 559    dc->reset = adb_mouse_reset;
 560    dc->vmsd = &vmstate_adb_mouse;
 561}
 562
 563static const TypeInfo adb_mouse_type_info = {
 564    .name = TYPE_ADB_MOUSE,
 565    .parent = TYPE_ADB_DEVICE,
 566    .instance_size = sizeof(MouseState),
 567    .instance_init = adb_mouse_initfn,
 568    .class_init = adb_mouse_class_init,
 569    .class_size = sizeof(ADBMouseClass),
 570};
 571
 572
 573static void adb_register_types(void)
 574{
 575    type_register_static(&adb_bus_type_info);
 576    type_register_static(&adb_device_type_info);
 577    type_register_static(&adb_kbd_type_info);
 578    type_register_static(&adb_mouse_type_info);
 579}
 580
 581type_init(adb_register_types)
 582