Blame view

hw/adb.c 10.6 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
38
39
40
41
42
43
44
45
46
47

/* 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
48
49
50
/* error codes */
#define ADB_RET_NOTPRESENT (-2)
bellard authored
51
int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
bellard authored
52
53
54
55
{
    ADBDevice *d;
    int devaddr, cmd, i;
bellard authored
56
    cmd = buf[0] & 0xf;
57
58
59
60
61
62
63
64
    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
65
    }
66
    devaddr = buf[0] >> 4;
bellard authored
67
68
69
    for(i = 0; i < s->nb_devices; i++) {
        d = &s->devices[i];
        if (d->devaddr == devaddr) {
bellard authored
70
            return d->devreq(d, obuf, buf, len);
bellard authored
71
72
        }
    }
73
    return ADB_RET_NOTPRESENT;
bellard authored
74
75
}
76
/* XXX: move that to cuda ? */
bellard authored
77
78
79
80
int adb_poll(ADBBusState *s, uint8_t *obuf)
{
    ADBDevice *d;
    int olen, i;
81
    uint8_t buf[1];
bellard authored
82
83
84
85
86
87

    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];
88
89
90
91
92
93
        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
94
            break;
95
96
        }
        s->poll_index++;
bellard authored
97
98
    }
    return olen;
bellard authored
99
100
}
101
102
103
ADBDevice *adb_register_device(ADBBusState *s, int devaddr,
                               ADBDeviceRequest *devreq,
                               ADBDeviceReset *devreset,
bellard authored
104
105
106
107
108
109
110
111
                               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
112
    d->devreq = devreq;
113
    d->devreset = devreset;
bellard authored
114
115
116
117
118
119
120
    d->opaque = opaque;
    return d;
}

/***************************************************************/
/* Keyboard ADB device */
bellard authored
121
122
123
124
125
typedef struct KBDState {
    uint8_t data[128];
    int rptr, wptr, count;
} KBDState;
bellard authored
126
127
128
129
130
131
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
132
 84, 85, 82, 65,  0,  0, 10,103,111,  0,  0,110, 81,  0,  0,  0,
bellard authored
133
134
  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
135
136
137
138
139
140
  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
141
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
bellard authored
142
  0,  0,  0,  0,  0, 95,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
bellard authored
143
144
145
146
147
};

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

static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
                           const uint8_t *buf, int len)
{
195
    KBDState *s = d->opaque;
bellard authored
196
197
    int cmd, reg, olen;
198
199
200
201
    if ((buf[0] & 0x0f) == ADB_FLUSH) {
        /* flush keyboard fifo */
        s->wptr = s->rptr = s->count = 0;
        return 0;
bellard authored
202
    }
bellard authored
203
204
205

    cmd = buf[0] & 0xc;
    reg = buf[0] & 0x3;
bellard authored
206
    olen = 0;
bellard authored
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
    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) {
232
233
234
        case 0:
            olen = adb_kbd_poll(d, obuf);
            break;
bellard authored
235
236
237
        case 1:
            break;
        case 2:
bellard authored
238
239
240
            obuf[0] = 0x00; /* XXX: check this */
            obuf[1] = 0x07; /* led status */
            olen = 2;
bellard authored
241
242
            break;
        case 3:
bellard authored
243
244
245
            obuf[0] = d->handler;
            obuf[1] = d->devaddr;
            olen = 2;
bellard authored
246
247
248
249
            break;
        }
        break;
    }
bellard authored
250
    return olen;
bellard authored
251
252
}
253
254
255
256
257
258
259
260
261
262
263
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
264
265
266
void adb_kbd_init(ADBBusState *bus)
{
    ADBDevice *d;
bellard authored
267
268
    KBDState *s;
    s = qemu_mallocz(sizeof(KBDState));
269
270
271
    d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request,
                            adb_kbd_reset, s);
    adb_kbd_reset(d);
bellard authored
272
273
274
275
276
277
    qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
}

/***************************************************************/
/* Mouse ADB device */
bellard authored
278
279
280
281
282
typedef struct MouseState {
    int buttons_state, last_buttons_state;
    int dx, dy, dz;
} MouseState;
bellard authored
283
284
285
286
static void adb_mouse_event(void *opaque,
                            int dx1, int dy1, int dz1, int buttons_state)
{
    ADBDevice *d = opaque;
bellard authored
287
288
289
290
291
292
293
294
295
296
297
298
    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
299
300
    int dx, dy;
bellard authored
301
302
303
    if (s->last_buttons_state == s->buttons_state &&
        s->dx == 0 && s->dy == 0)
        return 0;
304
bellard authored
305
    dx = s->dx;
bellard authored
306
307
308
309
    if (dx < -63)
        dx = -63;
    else if (dx > 63)
        dx = 63;
310
bellard authored
311
    dy = s->dy;
bellard authored
312
313
314
315
    if (dy < -63)
        dy = -63;
    else if (dy > 63)
        dy = 63;
316
bellard authored
317
318
319
    s->dx -= dx;
    s->dy -= dy;
    s->last_buttons_state = s->buttons_state;
320
bellard authored
321
322
    dx &= 0x7f;
    dy &= 0x7f;
323
324
    if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
bellard authored
325
        dy |= 0x80;
326
    if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
bellard authored
327
        dx |= 0x80;
328
329
330
331
    obuf[0] = dy;
    obuf[1] = dx;
    return 2;
bellard authored
332
333
}
bellard authored
334
335
static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
                             const uint8_t *buf, int len)
bellard authored
336
{
337
    MouseState *s = d->opaque;
bellard authored
338
    int cmd, reg, olen;
339
340
341
342
343
344
345
346
    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
347
    }
bellard authored
348
349
350

    cmd = buf[0] & 0xc;
    reg = buf[0] & 0x3;
bellard authored
351
    olen = 0;
bellard authored
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
    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) {
375
376
377
        case 0:
            olen = adb_mouse_poll(d, obuf);
            break;
bellard authored
378
379
380
        case 1:
            break;
        case 3:
bellard authored
381
382
383
            obuf[0] = d->handler;
            obuf[1] = d->devaddr;
            olen = 2;
bellard authored
384
385
386
387
            break;
        }
        break;
    }
bellard authored
388
    return olen;
bellard authored
389
390
}
391
392
393
394
395
396
397
398
399
400
401
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;
}
bellard authored
402
403
404
void adb_mouse_init(ADBBusState *bus)
{
    ADBDevice *d;
bellard authored
405
    MouseState *s;
bellard authored
406
bellard authored
407
    s = qemu_mallocz(sizeof(MouseState));
408
409
410
    d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request,
                            adb_mouse_reset, s);
    adb_mouse_reset(d);
411
    qemu_add_mouse_event_handler(adb_mouse_event, d, 0, "QEMU ADB Mouse");
bellard authored
412
}