adb.c 11.9 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 51 52 53 54 55 56 57
/* 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) */
#define ADB_DONGLE	1
#define ADB_KEYBOARD	2
#define ADB_MOUSE	3
#define ADB_TABLET	4
#define ADB_MODEM	5
#define ADB_MISC	7

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

B
bellard 已提交
61
int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
B
bellard 已提交
62 63 64 65
{
    ADBDevice *d;
    int devaddr, cmd, i;

B
bellard 已提交
66
    cmd = buf[0] & 0xf;
67 68 69 70 71 72 73 74
    if (cmd == ADB_BUSRESET) {
        for(i = 0; i < s->nb_devices; i++) {
            d = &s->devices[i];
            if (d->devreset) {
                d->devreset(d);
            }
        }
        return 0;
B
bellard 已提交
75
    }
76
    devaddr = buf[0] >> 4;
B
bellard 已提交
77 78 79
    for(i = 0; i < s->nb_devices; i++) {
        d = &s->devices[i];
        if (d->devaddr == devaddr) {
B
bellard 已提交
80
            return d->devreq(d, obuf, buf, len);
B
bellard 已提交
81 82
        }
    }
83
    return ADB_RET_NOTPRESENT;
B
bellard 已提交
84 85
}

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

    olen = 0;
    for(i = 0; i < s->nb_devices; i++) {
        if (s->poll_index >= s->nb_devices)
            s->poll_index = 0;
        d = &s->devices[s->poll_index];
98 99 100 101 102 103
        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 已提交
104
            break;
105 106
        }
        s->poll_index++;
B
bellard 已提交
107 108
    }
    return olen;
B
bellard 已提交
109 110
}

B
Blue Swirl 已提交
111 112 113 114
static ADBDevice *adb_register_device(ADBBusState *s, int devaddr,
                                      ADBDeviceRequest *devreq,
                                      ADBDeviceReset *devreset,
                                      void *opaque)
B
bellard 已提交
115 116 117 118 119 120 121
{
    ADBDevice *d;
    if (s->nb_devices >= MAX_ADB_DEVICES)
        return NULL;
    d = &s->devices[s->nb_devices++];
    d->bus = s;
    d->devaddr = devaddr;
B
bellard 已提交
122
    d->devreq = devreq;
123
    d->devreset = devreset;
B
bellard 已提交
124
    d->opaque = opaque;
125
    qemu_register_reset((QEMUResetHandler *)devreset, d);
B
bellard 已提交
126 127 128 129 130 131
    return d;
}

/***************************************************************/
/* Keyboard ADB device */

B
bellard 已提交
132 133 134 135 136
typedef struct KBDState {
    uint8_t data[128];
    int rptr, wptr, count;
} KBDState;

B
bellard 已提交
137 138 139 140 141 142
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 已提交
143
 84, 85, 82, 65,  0,  0, 10,103,111,  0,  0,110, 81,  0,  0,  0,
B
bellard 已提交
144 145
  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 已提交
146 147 148 149 150 151
  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 已提交
152
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
B
bellard 已提交
153
  0,  0,  0,  0,  0, 95,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
B
bellard 已提交
154 155 156 157 158
};

static void adb_kbd_put_keycode(void *opaque, int keycode)
{
    ADBDevice *d = opaque;
B
bellard 已提交
159 160 161 162 163 164 165
    KBDState *s = d->opaque;

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

B
bellard 已提交
169
static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf)
B
bellard 已提交
170
{
B
bellard 已提交
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
    static int ext_keycode;
    KBDState *s = d->opaque;
    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];
192 193 194 195
            obuf[0] = adb_keycode | (keycode & 0x80);
            /* NOTE: could put a second keycode if needed */
            obuf[1] = 0xff;
            olen = 2;
B
bellard 已提交
196 197 198 199 200 201 202 203 204 205
            ext_keycode = 0;
            break;
        }
    }
    return olen;
}

static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
                           const uint8_t *buf, int len)
{
206
    KBDState *s = d->opaque;
B
bellard 已提交
207 208
    int cmd, reg, olen;

209 210 211 212
    if ((buf[0] & 0x0f) == ADB_FLUSH) {
        /* flush keyboard fifo */
        s->wptr = s->rptr = s->count = 0;
        return 0;
B
bellard 已提交
213
    }
B
bellard 已提交
214 215 216

    cmd = buf[0] & 0xc;
    reg = buf[0] & 0x3;
B
bellard 已提交
217
    olen = 0;
B
bellard 已提交
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
    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) {
243 244 245
        case 0:
            olen = adb_kbd_poll(d, obuf);
            break;
B
bellard 已提交
246 247 248
        case 1:
            break;
        case 2:
B
bellard 已提交
249 250 251
            obuf[0] = 0x00; /* XXX: check this */
            obuf[1] = 0x07; /* led status */
            olen = 2;
B
bellard 已提交
252 253
            break;
        case 3:
B
bellard 已提交
254 255 256
            obuf[0] = d->handler;
            obuf[1] = d->devaddr;
            olen = 2;
B
bellard 已提交
257 258 259 260
            break;
        }
        break;
    }
B
bellard 已提交
261
    return olen;
B
bellard 已提交
262 263
}

J
Juan Quintela 已提交
264 265 266 267 268 269 270 271 272 273 274 275 276
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 已提交
277

B
bellard 已提交
278 279 280 281 282 283 284 285 286 287 288
static int adb_kbd_reset(ADBDevice *d)
{
    KBDState *s = d->opaque;

    d->handler = 1;
    d->devaddr = ADB_KEYBOARD;
    memset(s, 0, sizeof(KBDState));

    return 0;
}

B
bellard 已提交
289 290 291
void adb_kbd_init(ADBBusState *bus)
{
    ADBDevice *d;
B
bellard 已提交
292
    KBDState *s;
293
    s = g_malloc0(sizeof(KBDState));
B
bellard 已提交
294 295
    d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request,
                            adb_kbd_reset, s);
B
bellard 已提交
296
    qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
J
Juan Quintela 已提交
297
    vmstate_register(NULL, -1, &vmstate_adb_kbd, s);
B
bellard 已提交
298 299 300 301 302
}

/***************************************************************/
/* Mouse ADB device */

B
bellard 已提交
303 304 305 306 307
typedef struct MouseState {
    int buttons_state, last_buttons_state;
    int dx, dy, dz;
} MouseState;

B
bellard 已提交
308 309 310 311
static void adb_mouse_event(void *opaque,
                            int dx1, int dy1, int dz1, int buttons_state)
{
    ADBDevice *d = opaque;
B
bellard 已提交
312 313 314 315 316 317 318 319 320 321 322 323
    MouseState *s = d->opaque;

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


static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
{
    MouseState *s = d->opaque;
B
bellard 已提交
324 325
    int dx, dy;

B
bellard 已提交
326 327 328
    if (s->last_buttons_state == s->buttons_state &&
        s->dx == 0 && s->dy == 0)
        return 0;
329

B
bellard 已提交
330
    dx = s->dx;
B
bellard 已提交
331 332 333 334
    if (dx < -63)
        dx = -63;
    else if (dx > 63)
        dx = 63;
335

B
bellard 已提交
336
    dy = s->dy;
B
bellard 已提交
337 338 339 340
    if (dy < -63)
        dy = -63;
    else if (dy > 63)
        dy = 63;
341

B
bellard 已提交
342 343 344
    s->dx -= dx;
    s->dy -= dy;
    s->last_buttons_state = s->buttons_state;
345

B
bellard 已提交
346 347
    dx &= 0x7f;
    dy &= 0x7f;
348

349
    if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
B
bellard 已提交
350
        dy |= 0x80;
351
    if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
B
bellard 已提交
352
        dx |= 0x80;
353

354 355 356
    obuf[0] = dy;
    obuf[1] = dx;
    return 2;
B
bellard 已提交
357 358
}

B
bellard 已提交
359 360
static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
                             const uint8_t *buf, int len)
B
bellard 已提交
361
{
362
    MouseState *s = d->opaque;
B
bellard 已提交
363
    int cmd, reg, olen;
364

365 366 367 368 369 370 371
    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 已提交
372
    }
B
bellard 已提交
373 374 375

    cmd = buf[0] & 0xc;
    reg = buf[0] & 0x3;
B
bellard 已提交
376
    olen = 0;
B
bellard 已提交
377 378
    switch(cmd) {
    case ADB_WRITEREG:
B
blueswir1 已提交
379
        ADB_DPRINTF("write reg %d val 0x%2.2x\n", reg, buf[1]);
B
bellard 已提交
380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400
        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) {
401 402 403
        case 0:
            olen = adb_mouse_poll(d, obuf);
            break;
B
bellard 已提交
404 405 406
        case 1:
            break;
        case 3:
B
bellard 已提交
407 408 409
            obuf[0] = d->handler;
            obuf[1] = d->devaddr;
            olen = 2;
B
bellard 已提交
410 411
            break;
        }
B
blueswir1 已提交
412 413
        ADB_DPRINTF("read reg %d obuf[0] 0x%2.2x obuf[1] 0x%2.2x\n", reg,
                    obuf[0], obuf[1]);
B
bellard 已提交
414 415
        break;
    }
B
bellard 已提交
416
    return olen;
B
bellard 已提交
417 418
}

B
bellard 已提交
419 420 421 422 423 424 425 426 427 428 429
static int adb_mouse_reset(ADBDevice *d)
{
    MouseState *s = d->opaque;

    d->handler = 2;
    d->devaddr = ADB_MOUSE;
    memset(s, 0, sizeof(MouseState));

    return 0;
}

J
Juan Quintela 已提交
430 431 432 433 434 435 436 437 438 439 440 441 442 443
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 已提交
444

B
bellard 已提交
445 446 447
void adb_mouse_init(ADBBusState *bus)
{
    ADBDevice *d;
B
bellard 已提交
448
    MouseState *s;
B
bellard 已提交
449

450
    s = g_malloc0(sizeof(MouseState));
B
bellard 已提交
451 452
    d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request,
                            adb_mouse_reset, s);
453
    qemu_add_mouse_event_handler(adb_mouse_event, d, 0, "QEMU ADB Mouse");
J
Juan Quintela 已提交
454
    vmstate_register(NULL, -1, &vmstate_adb_mouse, s);
B
bellard 已提交
455
}