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    .fields = (VMStateField[]) {
 307        VMSTATE_BUFFER(data, KBDState),
 308        VMSTATE_INT32(rptr, KBDState),
 309        VMSTATE_INT32(wptr, KBDState),
 310        VMSTATE_INT32(count, KBDState),
 311        VMSTATE_END_OF_LIST()
 312    }
 313};
 314
 315static void adb_kbd_reset(DeviceState *dev)
 316{
 317    ADBDevice *d = ADB_DEVICE(dev);
 318    KBDState *s = ADB_KEYBOARD(dev);
 319
 320    d->handler = 1;
 321    d->devaddr = ADB_DEVID_KEYBOARD;
 322    memset(s->data, 0, sizeof(s->data));
 323    s->rptr = 0;
 324    s->wptr = 0;
 325    s->count = 0;
 326}
 327
 328static void adb_kbd_realizefn(DeviceState *dev, Error **errp)
 329{
 330    ADBDevice *d = ADB_DEVICE(dev);
 331    ADBKeyboardClass *akc = ADB_KEYBOARD_GET_CLASS(dev);
 332
 333    akc->parent_realize(dev, errp);
 334
 335    qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
 336}
 337
 338static void adb_kbd_initfn(Object *obj)
 339{
 340    ADBDevice *d = ADB_DEVICE(obj);
 341
 342    d->devaddr = ADB_DEVID_KEYBOARD;
 343}
 344
 345static void adb_kbd_class_init(ObjectClass *oc, void *data)
 346{
 347    DeviceClass *dc = DEVICE_CLASS(oc);
 348    ADBDeviceClass *adc = ADB_DEVICE_CLASS(oc);
 349    ADBKeyboardClass *akc = ADB_KEYBOARD_CLASS(oc);
 350
 351    akc->parent_realize = dc->realize;
 352    dc->realize = adb_kbd_realizefn;
 353
 354    adc->devreq = adb_kbd_request;
 355    dc->reset = adb_kbd_reset;
 356    dc->vmsd = &vmstate_adb_kbd;
 357}
 358
 359static const TypeInfo adb_kbd_type_info = {
 360    .name = TYPE_ADB_KEYBOARD,
 361    .parent = TYPE_ADB_DEVICE,
 362    .instance_size = sizeof(KBDState),
 363    .instance_init = adb_kbd_initfn,
 364    .class_init = adb_kbd_class_init,
 365    .class_size = sizeof(ADBKeyboardClass),
 366};
 367
 368/***************************************************************/
 369/* Mouse ADB device */
 370
 371#define ADB_MOUSE(obj) OBJECT_CHECK(MouseState, (obj), TYPE_ADB_MOUSE)
 372
 373typedef struct MouseState {
 374    /*< public >*/
 375    ADBDevice parent_obj;
 376    /*< private >*/
 377
 378    int buttons_state, last_buttons_state;
 379    int dx, dy, dz;
 380} MouseState;
 381
 382#define ADB_MOUSE_CLASS(class) \
 383    OBJECT_CLASS_CHECK(ADBMouseClass, (class), TYPE_ADB_MOUSE)
 384#define ADB_MOUSE_GET_CLASS(obj) \
 385    OBJECT_GET_CLASS(ADBMouseClass, (obj), TYPE_ADB_MOUSE)
 386
 387typedef struct ADBMouseClass {
 388    /*< public >*/
 389    ADBDeviceClass parent_class;
 390    /*< private >*/
 391
 392    DeviceRealize parent_realize;
 393} ADBMouseClass;
 394
 395static void adb_mouse_event(void *opaque,
 396                            int dx1, int dy1, int dz1, int buttons_state)
 397{
 398    MouseState *s = opaque;
 399
 400    s->dx += dx1;
 401    s->dy += dy1;
 402    s->dz += dz1;
 403    s->buttons_state = buttons_state;
 404}
 405
 406
 407static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
 408{
 409    MouseState *s = ADB_MOUSE(d);
 410    int dx, dy;
 411
 412    if (s->last_buttons_state == s->buttons_state &&
 413        s->dx == 0 && s->dy == 0)
 414        return 0;
 415
 416    dx = s->dx;
 417    if (dx < -63)
 418        dx = -63;
 419    else if (dx > 63)
 420        dx = 63;
 421
 422    dy = s->dy;
 423    if (dy < -63)
 424        dy = -63;
 425    else if (dy > 63)
 426        dy = 63;
 427
 428    s->dx -= dx;
 429    s->dy -= dy;
 430    s->last_buttons_state = s->buttons_state;
 431
 432    dx &= 0x7f;
 433    dy &= 0x7f;
 434
 435    if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
 436        dy |= 0x80;
 437    if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
 438        dx |= 0x80;
 439
 440    obuf[0] = dy;
 441    obuf[1] = dx;
 442    return 2;
 443}
 444
 445static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
 446                             const uint8_t *buf, int len)
 447{
 448    MouseState *s = ADB_MOUSE(d);
 449    int cmd, reg, olen;
 450
 451    if ((buf[0] & 0x0f) == ADB_FLUSH) {
 452        /* flush mouse fifo */
 453        s->buttons_state = s->last_buttons_state;
 454        s->dx = 0;
 455        s->dy = 0;
 456        s->dz = 0;
 457        return 0;
 458    }
 459
 460    cmd = buf[0] & 0xc;
 461    reg = buf[0] & 0x3;
 462    olen = 0;
 463    switch(cmd) {
 464    case ADB_WRITEREG:
 465        ADB_DPRINTF("write reg %d val 0x%2.2x\n", reg, buf[1]);
 466        switch(reg) {
 467        case 2:
 468            break;
 469        case 3:
 470            switch(buf[2]) {
 471            case ADB_CMD_SELF_TEST:
 472                break;
 473            case ADB_CMD_CHANGE_ID:
 474            case ADB_CMD_CHANGE_ID_AND_ACT:
 475            case ADB_CMD_CHANGE_ID_AND_ENABLE:
 476                d->devaddr = buf[1] & 0xf;
 477                break;
 478            default:
 479                /* XXX: check this */
 480                d->devaddr = buf[1] & 0xf;
 481                break;
 482            }
 483        }
 484        break;
 485    case ADB_READREG:
 486        switch(reg) {
 487        case 0:
 488            olen = adb_mouse_poll(d, obuf);
 489            break;
 490        case 1:
 491            break;
 492        case 3:
 493            obuf[0] = d->handler;
 494            obuf[1] = d->devaddr;
 495            olen = 2;
 496            break;
 497        }
 498        ADB_DPRINTF("read reg %d obuf[0] 0x%2.2x obuf[1] 0x%2.2x\n", reg,
 499                    obuf[0], obuf[1]);
 500        break;
 501    }
 502    return olen;
 503}
 504
 505static void adb_mouse_reset(DeviceState *dev)
 506{
 507    ADBDevice *d = ADB_DEVICE(dev);
 508    MouseState *s = ADB_MOUSE(dev);
 509
 510    d->handler = 2;
 511    d->devaddr = ADB_DEVID_MOUSE;
 512    s->last_buttons_state = s->buttons_state = 0;
 513    s->dx = s->dy = s->dz = 0;
 514}
 515
 516static const VMStateDescription vmstate_adb_mouse = {
 517    .name = "adb_mouse",
 518    .version_id = 1,
 519    .minimum_version_id = 1,
 520    .fields = (VMStateField[]) {
 521        VMSTATE_INT32(buttons_state, MouseState),
 522        VMSTATE_INT32(last_buttons_state, MouseState),
 523        VMSTATE_INT32(dx, MouseState),
 524        VMSTATE_INT32(dy, MouseState),
 525        VMSTATE_INT32(dz, MouseState),
 526        VMSTATE_END_OF_LIST()
 527    }
 528};
 529
 530static void adb_mouse_realizefn(DeviceState *dev, Error **errp)
 531{
 532    MouseState *s = ADB_MOUSE(dev);
 533    ADBMouseClass *amc = ADB_MOUSE_GET_CLASS(dev);
 534
 535    amc->parent_realize(dev, errp);
 536
 537    qemu_add_mouse_event_handler(adb_mouse_event, s, 0, "QEMU ADB Mouse");
 538}
 539
 540static void adb_mouse_initfn(Object *obj)
 541{
 542    ADBDevice *d = ADB_DEVICE(obj);
 543
 544    d->devaddr = ADB_DEVID_MOUSE;
 545}
 546
 547static void adb_mouse_class_init(ObjectClass *oc, void *data)
 548{
 549    DeviceClass *dc = DEVICE_CLASS(oc);
 550    ADBDeviceClass *adc = ADB_DEVICE_CLASS(oc);
 551    ADBMouseClass *amc = ADB_MOUSE_CLASS(oc);
 552
 553    amc->parent_realize = dc->realize;
 554    dc->realize = adb_mouse_realizefn;
 555
 556    adc->devreq = adb_mouse_request;
 557    dc->reset = adb_mouse_reset;
 558    dc->vmsd = &vmstate_adb_mouse;
 559}
 560
 561static const TypeInfo adb_mouse_type_info = {
 562    .name = TYPE_ADB_MOUSE,
 563    .parent = TYPE_ADB_DEVICE,
 564    .instance_size = sizeof(MouseState),
 565    .instance_init = adb_mouse_initfn,
 566    .class_init = adb_mouse_class_init,
 567    .class_size = sizeof(ADBMouseClass),
 568};
 569
 570
 571static void adb_register_types(void)
 572{
 573    type_register_static(&adb_bus_type_info);
 574    type_register_static(&adb_device_type_info);
 575    type_register_static(&adb_kbd_type_info);
 576    type_register_static(&adb_mouse_type_info);
 577}
 578
 579type_init(adb_register_types)
 580