adb.c 10.6 KB
Newer Older
B
bellard 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
/*
 * QEMU ADB support
 * 
 * Copyright (c) 2004 Fabrice Bellard
 * 
 * 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.
 */
#include "vl.h"

/* 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

46 47 48
/* error codes */
#define ADB_RET_NOTPRESENT (-2)

B
bellard 已提交
49
int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
B
bellard 已提交
50 51 52 53
{
    ADBDevice *d;
    int devaddr, cmd, i;

B
bellard 已提交
54
    cmd = buf[0] & 0xf;
55 56 57 58 59 60 61 62
    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 已提交
63
    }
64
    devaddr = buf[0] >> 4;
B
bellard 已提交
65 66 67
    for(i = 0; i < s->nb_devices; i++) {
        d = &s->devices[i];
        if (d->devaddr == devaddr) {
B
bellard 已提交
68
            return d->devreq(d, obuf, buf, len);
B
bellard 已提交
69 70
        }
    }
71
    return ADB_RET_NOTPRESENT;
B
bellard 已提交
72 73
}

74
/* XXX: move that to cuda ? */
B
bellard 已提交
75 76 77 78
int adb_poll(ADBBusState *s, uint8_t *obuf)
{
    ADBDevice *d;
    int olen, i;
79
    uint8_t buf[1];
B
bellard 已提交
80 81 82 83 84 85

    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];
86 87 88 89 90 91
        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 已提交
92
            break;
93 94
        }
        s->poll_index++;
B
bellard 已提交
95 96
    }
    return olen;
B
bellard 已提交
97 98 99
}

ADBDevice *adb_register_device(ADBBusState *s, int devaddr, 
B
bellard 已提交
100
                               ADBDeviceRequest *devreq, 
101
                               ADBDeviceReset *devreset, 
B
bellard 已提交
102 103 104 105 106 107 108 109
                               void *opaque)
{
    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 已提交
110
    d->devreq = devreq;
111
    d->devreset = devreset;
B
bellard 已提交
112 113 114 115 116 117 118
    d->opaque = opaque;
    return d;
}

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

B
bellard 已提交
119 120 121 122 123
typedef struct KBDState {
    uint8_t data[128];
    int rptr, wptr, count;
} KBDState;

B
bellard 已提交
124 125 126 127 128 129
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 已提交
130
 84, 85, 82, 65,  0,  0, 10,103,111,  0,  0,110, 81,  0,  0,  0,
B
bellard 已提交
131 132
  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 已提交
133 134 135 136 137 138
  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 已提交
139
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
B
bellard 已提交
140
  0,  0,  0,  0,  0, 95,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
B
bellard 已提交
141 142 143 144 145
};

static void adb_kbd_put_keycode(void *opaque, int keycode)
{
    ADBDevice *d = opaque;
B
bellard 已提交
146 147 148 149 150 151 152
    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 已提交
153 154 155
    }
}

B
bellard 已提交
156
static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf)
B
bellard 已提交
157
{
B
bellard 已提交
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
    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];
179 180 181 182
            obuf[0] = adb_keycode | (keycode & 0x80);
            /* NOTE: could put a second keycode if needed */
            obuf[1] = 0xff;
            olen = 2;
B
bellard 已提交
183 184 185 186 187 188 189 190 191 192
            ext_keycode = 0;
            break;
        }
    }
    return olen;
}

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

196 197 198 199
    if ((buf[0] & 0x0f) == ADB_FLUSH) {
        /* flush keyboard fifo */
        s->wptr = s->rptr = s->count = 0;
        return 0;
B
bellard 已提交
200
    }
B
bellard 已提交
201 202 203

    cmd = buf[0] & 0xc;
    reg = buf[0] & 0x3;
B
bellard 已提交
204
    olen = 0;
B
bellard 已提交
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
    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) {
230 231 232
        case 0:
            olen = adb_kbd_poll(d, obuf);
            break;
B
bellard 已提交
233 234 235
        case 1:
            break;
        case 2:
B
bellard 已提交
236 237 238
            obuf[0] = 0x00; /* XXX: check this */
            obuf[1] = 0x07; /* led status */
            olen = 2;
B
bellard 已提交
239 240
            break;
        case 3:
B
bellard 已提交
241 242 243
            obuf[0] = d->handler;
            obuf[1] = d->devaddr;
            olen = 2;
B
bellard 已提交
244 245 246 247
            break;
        }
        break;
    }
B
bellard 已提交
248
    return olen;
B
bellard 已提交
249 250
}

B
bellard 已提交
251 252 253 254 255 256 257 258 259 260 261
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 已提交
262 263 264
void adb_kbd_init(ADBBusState *bus)
{
    ADBDevice *d;
B
bellard 已提交
265 266
    KBDState *s;
    s = qemu_mallocz(sizeof(KBDState));
B
bellard 已提交
267 268 269
    d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request,
                            adb_kbd_reset, s);
    adb_kbd_reset(d);
B
bellard 已提交
270 271 272 273 274 275
    qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
}

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

B
bellard 已提交
276 277 278 279 280
typedef struct MouseState {
    int buttons_state, last_buttons_state;
    int dx, dy, dz;
} MouseState;

B
bellard 已提交
281 282 283 284
static void adb_mouse_event(void *opaque,
                            int dx1, int dy1, int dz1, int buttons_state)
{
    ADBDevice *d = opaque;
B
bellard 已提交
285 286 287 288 289 290 291 292 293 294 295 296
    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 已提交
297 298
    int dx, dy;

B
bellard 已提交
299 300 301 302 303
    if (s->last_buttons_state == s->buttons_state &&
        s->dx == 0 && s->dy == 0)
        return 0;
        
    dx = s->dx;
B
bellard 已提交
304 305 306 307
    if (dx < -63)
        dx = -63;
    else if (dx > 63)
        dx = 63;
B
bellard 已提交
308 309
    
    dy = s->dy;
B
bellard 已提交
310 311 312 313
    if (dy < -63)
        dy = -63;
    else if (dy > 63)
        dy = 63;
B
bellard 已提交
314 315 316 317 318
    
    s->dx -= dx;
    s->dy -= dy;
    s->last_buttons_state = s->buttons_state;
    
B
bellard 已提交
319 320
    dx &= 0x7f;
    dy &= 0x7f;
B
bellard 已提交
321
    
322
    if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
B
bellard 已提交
323
        dy |= 0x80;
324
    if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
B
bellard 已提交
325
        dx |= 0x80;
B
bellard 已提交
326
    
327 328 329
    obuf[0] = dy;
    obuf[1] = dx;
    return 2;
B
bellard 已提交
330 331
}

B
bellard 已提交
332 333
static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
                             const uint8_t *buf, int len)
B
bellard 已提交
334
{
335
    MouseState *s = d->opaque;
B
bellard 已提交
336 337
    int cmd, reg, olen;
    
338 339 340 341 342 343 344
    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 已提交
345
    }
B
bellard 已提交
346 347 348

    cmd = buf[0] & 0xc;
    reg = buf[0] & 0x3;
B
bellard 已提交
349
    olen = 0;
B
bellard 已提交
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
    switch(cmd) {
    case ADB_WRITEREG:
        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) {
373 374 375
        case 0:
            olen = adb_mouse_poll(d, obuf);
            break;
B
bellard 已提交
376 377 378
        case 1:
            break;
        case 3:
B
bellard 已提交
379 380 381
            obuf[0] = d->handler;
            obuf[1] = d->devaddr;
            olen = 2;
B
bellard 已提交
382 383 384 385
            break;
        }
        break;
    }
B
bellard 已提交
386
    return olen;
B
bellard 已提交
387 388
}

B
bellard 已提交
389 390 391 392 393 394 395 396 397 398 399
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;
}

B
bellard 已提交
400 401 402
void adb_mouse_init(ADBBusState *bus)
{
    ADBDevice *d;
B
bellard 已提交
403
    MouseState *s;
B
bellard 已提交
404

B
bellard 已提交
405
    s = qemu_mallocz(sizeof(MouseState));
B
bellard 已提交
406 407 408
    d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request,
                            adb_mouse_reset, s);
    adb_mouse_reset(d);
B
bellard 已提交
409 410
    qemu_add_mouse_event_handler(adb_mouse_event, d);
}