Blame view

hw/adb.c 12.4 KB
bellard authored
1
2
/*
 * QEMU ADB support
3
 *
bellard authored
4
 * Copyright (c) 2004 Fabrice Bellard
5
 *
bellard authored
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.
 */
pbrook authored
24
25
26
#include "hw.h"
#include "ppc_mac.h"
#include "console.h"
bellard authored
27
28
29
30
31
32
33
34
35
36
37
/* debug ADB */
//#define DEBUG_ADB

#ifdef DEBUG_ADB
#define ADB_DPRINTF(fmt, args...) \
do { printf("ADB: " fmt , ##args); } while (0)
#else
#define ADB_DPRINTF(fmt, args...)
#endif
bellard authored
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)
bellard authored
61
int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
bellard authored
62
63
64
65
{
    ADBDevice *d;
    int devaddr, cmd, i;
bellard authored
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;
bellard authored
75
    }
76
    devaddr = buf[0] >> 4;
bellard authored
77
78
79
    for(i = 0; i < s->nb_devices; i++) {
        d = &s->devices[i];
        if (d->devaddr == devaddr) {
bellard authored
80
            return d->devreq(d, obuf, buf, len);
bellard authored
81
82
        }
    }
83
    return ADB_RET_NOTPRESENT;
bellard authored
84
85
}
86
/* XXX: move that to cuda ? */
bellard authored
87
88
89
90
int adb_poll(ADBBusState *s, uint8_t *obuf)
{
    ADBDevice *d;
    int olen, i;
91
    uint8_t buf[1];
bellard authored
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++;
bellard authored
104
            break;
105
106
        }
        s->poll_index++;
bellard authored
107
108
    }
    return olen;
bellard authored
109
110
}
111
112
113
ADBDevice *adb_register_device(ADBBusState *s, int devaddr,
                               ADBDeviceRequest *devreq,
                               ADBDeviceReset *devreset,
bellard authored
114
115
116
117
118
119
120
121
                               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;
bellard authored
122
    d->devreq = devreq;
123
    d->devreset = devreset;
bellard authored
124
    d->opaque = opaque;
125
    qemu_register_reset((QEMUResetHandler *)devreset, d);
blueswir1 authored
126
    d->devreset(d);
bellard authored
127
128
129
130
131
132
    return d;
}

/***************************************************************/
/* Keyboard ADB device */
bellard authored
133
134
135
136
137
typedef struct KBDState {
    uint8_t data[128];
    int rptr, wptr, count;
} KBDState;
bellard authored
138
139
140
141
142
143
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,
bellard authored
144
 84, 85, 82, 65,  0,  0, 10,103,111,  0,  0,110, 81,  0,  0,  0,
bellard authored
145
146
  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,
bellard authored
147
148
149
150
151
152
  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,
bellard authored
153
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
bellard authored
154
  0,  0,  0,  0,  0, 95,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
bellard authored
155
156
157
158
159
};

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

static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
                           const uint8_t *buf, int len)
{
207
    KBDState *s = d->opaque;
bellard authored
208
209
    int cmd, reg, olen;
210
211
212
213
    if ((buf[0] & 0x0f) == ADB_FLUSH) {
        /* flush keyboard fifo */
        s->wptr = s->rptr = s->count = 0;
        return 0;
bellard authored
214
    }
bellard authored
215
216
217

    cmd = buf[0] & 0xc;
    reg = buf[0] & 0x3;
bellard authored
218
    olen = 0;
bellard authored
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
    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) {
244
245
246
        case 0:
            olen = adb_kbd_poll(d, obuf);
            break;
bellard authored
247
248
249
        case 1:
            break;
        case 2:
bellard authored
250
251
252
            obuf[0] = 0x00; /* XXX: check this */
            obuf[1] = 0x07; /* led status */
            olen = 2;
bellard authored
253
254
            break;
        case 3:
bellard authored
255
256
257
            obuf[0] = d->handler;
            obuf[1] = d->devaddr;
            olen = 2;
bellard authored
258
259
260
261
            break;
        }
        break;
    }
bellard authored
262
    return olen;
bellard authored
263
264
}
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
static void adb_kbd_save(QEMUFile *f, void *opaque)
{
    KBDState *s = (KBDState *)opaque;

    qemu_put_buffer(f, s->data, sizeof(s->data));
    qemu_put_sbe32s(f, &s->rptr);
    qemu_put_sbe32s(f, &s->wptr);
    qemu_put_sbe32s(f, &s->count);
}

static int adb_kbd_load(QEMUFile *f, void *opaque, int version_id)
{
    KBDState *s = (KBDState *)opaque;

    if (version_id != 1)
        return -EINVAL;

    qemu_get_buffer(f, s->data, sizeof(s->data));
    qemu_get_sbe32s(f, &s->rptr);
    qemu_get_sbe32s(f, &s->wptr);
    qemu_get_sbe32s(f, &s->count);

    return 0;
}
290
291
292
293
294
295
296
297
298
299
300
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;
}
bellard authored
301
302
303
void adb_kbd_init(ADBBusState *bus)
{
    ADBDevice *d;
bellard authored
304
305
    KBDState *s;
    s = qemu_mallocz(sizeof(KBDState));
306
307
    d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request,
                            adb_kbd_reset, s);
bellard authored
308
    qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
309
310
    register_savevm("adb_kbd", -1, 1, adb_kbd_save,
                    adb_kbd_load, s);
bellard authored
311
312
313
314
315
}

/***************************************************************/
/* Mouse ADB device */
bellard authored
316
317
318
319
320
typedef struct MouseState {
    int buttons_state, last_buttons_state;
    int dx, dy, dz;
} MouseState;
bellard authored
321
322
323
324
static void adb_mouse_event(void *opaque,
                            int dx1, int dy1, int dz1, int buttons_state)
{
    ADBDevice *d = opaque;
bellard authored
325
326
327
328
329
330
331
332
333
334
335
336
    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;
bellard authored
337
338
    int dx, dy;
bellard authored
339
340
341
    if (s->last_buttons_state == s->buttons_state &&
        s->dx == 0 && s->dy == 0)
        return 0;
342
bellard authored
343
    dx = s->dx;
bellard authored
344
345
346
347
    if (dx < -63)
        dx = -63;
    else if (dx > 63)
        dx = 63;
348
bellard authored
349
    dy = s->dy;
bellard authored
350
351
352
353
    if (dy < -63)
        dy = -63;
    else if (dy > 63)
        dy = 63;
354
bellard authored
355
356
357
    s->dx -= dx;
    s->dy -= dy;
    s->last_buttons_state = s->buttons_state;
358
bellard authored
359
360
    dx &= 0x7f;
    dy &= 0x7f;
361
362
    if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
bellard authored
363
        dy |= 0x80;
364
    if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
bellard authored
365
        dx |= 0x80;
366
367
368
369
    obuf[0] = dy;
    obuf[1] = dx;
    return 2;
bellard authored
370
371
}
bellard authored
372
373
static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
                             const uint8_t *buf, int len)
bellard authored
374
{
375
    MouseState *s = d->opaque;
bellard authored
376
    int cmd, reg, olen;
377
378
379
380
381
382
383
384
    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;
bellard authored
385
    }
bellard authored
386
387
388

    cmd = buf[0] & 0xc;
    reg = buf[0] & 0x3;
bellard authored
389
    olen = 0;
bellard authored
390
391
    switch(cmd) {
    case ADB_WRITEREG:
392
        ADB_DPRINTF("write reg %d val 0x%2.2x\n", reg, buf[1]);
bellard authored
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
        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) {
414
415
416
        case 0:
            olen = adb_mouse_poll(d, obuf);
            break;
bellard authored
417
418
419
        case 1:
            break;
        case 3:
bellard authored
420
421
422
            obuf[0] = d->handler;
            obuf[1] = d->devaddr;
            olen = 2;
bellard authored
423
424
            break;
        }
425
426
        ADB_DPRINTF("read reg %d obuf[0] 0x%2.2x obuf[1] 0x%2.2x\n", reg,
                    obuf[0], obuf[1]);
bellard authored
427
428
        break;
    }
bellard authored
429
    return olen;
bellard authored
430
431
}
432
433
434
435
436
437
438
439
440
441
442
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;
}
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
static void adb_mouse_save(QEMUFile *f, void *opaque)
{
    MouseState *s = (MouseState *)opaque;

    qemu_put_sbe32s(f, &s->buttons_state);
    qemu_put_sbe32s(f, &s->last_buttons_state);
    qemu_put_sbe32s(f, &s->dx);
    qemu_put_sbe32s(f, &s->dy);
    qemu_put_sbe32s(f, &s->dz);
}

static int adb_mouse_load(QEMUFile *f, void *opaque, int version_id)
{
    MouseState *s = (MouseState *)opaque;

    if (version_id != 1)
        return -EINVAL;

    qemu_get_sbe32s(f, &s->buttons_state);
    qemu_get_sbe32s(f, &s->last_buttons_state);
    qemu_get_sbe32s(f, &s->dx);
    qemu_get_sbe32s(f, &s->dy);
    qemu_get_sbe32s(f, &s->dz);

    return 0;
}
bellard authored
470
471
472
void adb_mouse_init(ADBBusState *bus)
{
    ADBDevice *d;
bellard authored
473
    MouseState *s;
bellard authored
474
bellard authored
475
    s = qemu_mallocz(sizeof(MouseState));
476
477
    d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request,
                            adb_mouse_reset, s);
478
    qemu_add_mouse_event_handler(adb_mouse_event, d, 0, "QEMU ADB Mouse");
479
480
    register_savevm("adb_mouse", -1, 1, adb_mouse_save,
                    adb_mouse_load, s);
bellard authored
481
}