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