Blame view

hw/adb.c 10.6 KB
bellard authored
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)
bellard authored
49
int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
bellard authored
50
51
52
53
{
    ADBDevice *d;
    int devaddr, cmd, i;
bellard authored
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;
bellard authored
63
    }
64
    devaddr = buf[0] >> 4;
bellard authored
65
66
67
    for(i = 0; i < s->nb_devices; i++) {
        d = &s->devices[i];
        if (d->devaddr == devaddr) {
bellard authored
68
            return d->devreq(d, obuf, buf, len);
bellard authored
69
70
        }
    }
71
    return ADB_RET_NOTPRESENT;
bellard authored
72
73
}
74
/* XXX: move that to cuda ? */
bellard authored
75
76
77
78
int adb_poll(ADBBusState *s, uint8_t *obuf)
{
    ADBDevice *d;
    int olen, i;
79
    uint8_t buf[1];
bellard authored
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++;
bellard authored
92
            break;
93
94
        }
        s->poll_index++;
bellard authored
95
96
    }
    return olen;
bellard authored
97
98
99
}

ADBDevice *adb_register_device(ADBBusState *s, int devaddr, 
bellard authored
100
                               ADBDeviceRequest *devreq, 
101
                               ADBDeviceReset *devreset, 
bellard authored
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;
bellard authored
110
    d->devreq = devreq;
111
    d->devreset = devreset;
bellard authored
112
113
114
115
116
117
118
    d->opaque = opaque;
    return d;
}

/***************************************************************/
/* Keyboard ADB device */
bellard authored
119
120
121
122
123
typedef struct KBDState {
    uint8_t data[128];
    int rptr, wptr, count;
} KBDState;
bellard authored
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,
bellard authored
130
 84, 85, 82, 65,  0,  0, 10,103,111,  0,  0,110, 81,  0,  0,  0,
bellard authored
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,
bellard authored
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,
bellard authored
139
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
bellard authored
140
  0,  0,  0,  0,  0, 95,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
bellard authored
141
142
143
144
145
};

static void adb_kbd_put_keycode(void *opaque, int keycode)
{
    ADBDevice *d = opaque;
bellard authored
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++;
bellard authored
153
154
155
    }
}
bellard authored
156
static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf)
bellard authored
157
{
bellard authored
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;
bellard authored
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;
bellard authored
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;
bellard authored
200
    }
bellard authored
201
202
203

    cmd = buf[0] & 0xc;
    reg = buf[0] & 0x3;
bellard authored
204
    olen = 0;
bellard authored
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;
bellard authored
233
234
235
        case 1:
            break;
        case 2:
bellard authored
236
237
238
            obuf[0] = 0x00; /* XXX: check this */
            obuf[1] = 0x07; /* led status */
            olen = 2;
bellard authored
239
240
            break;
        case 3:
bellard authored
241
242
243
            obuf[0] = d->handler;
            obuf[1] = d->devaddr;
            olen = 2;
bellard authored
244
245
246
247
            break;
        }
        break;
    }
bellard authored
248
    return olen;
bellard authored
249
250
}
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;
}
bellard authored
262
263
264
void adb_kbd_init(ADBBusState *bus)
{
    ADBDevice *d;
bellard authored
265
266
    KBDState *s;
    s = qemu_mallocz(sizeof(KBDState));
267
268
269
    d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request,
                            adb_kbd_reset, s);
    adb_kbd_reset(d);
bellard authored
270
271
272
273
274
275
    qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
}

/***************************************************************/
/* Mouse ADB device */
bellard authored
276
277
278
279
280
typedef struct MouseState {
    int buttons_state, last_buttons_state;
    int dx, dy, dz;
} MouseState;
bellard authored
281
282
283
284
static void adb_mouse_event(void *opaque,
                            int dx1, int dy1, int dz1, int buttons_state)
{
    ADBDevice *d = opaque;
bellard authored
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;
bellard authored
297
298
    int dx, dy;
bellard authored
299
300
301
302
303
    if (s->last_buttons_state == s->buttons_state &&
        s->dx == 0 && s->dy == 0)
        return 0;

    dx = s->dx;
bellard authored
304
305
306
307
    if (dx < -63)
        dx = -63;
    else if (dx > 63)
        dx = 63;
bellard authored
308
309

    dy = s->dy;
bellard authored
310
311
312
313
    if (dy < -63)
        dy = -63;
    else if (dy > 63)
        dy = 63;
bellard authored
314
315
316
317
318

    s->dx -= dx;
    s->dy -= dy;
    s->last_buttons_state = s->buttons_state;
bellard authored
319
320
    dx &= 0x7f;
    dy &= 0x7f;
bellard authored
321
322
    if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
bellard authored
323
        dy |= 0x80;
324
    if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
bellard authored
325
        dx |= 0x80;
bellard authored
326
327
328
329
    obuf[0] = dy;
    obuf[1] = dx;
    return 2;
bellard authored
330
331
}
bellard authored
332
333
static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
                             const uint8_t *buf, int len)
bellard authored
334
{
335
    MouseState *s = d->opaque;
bellard authored
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;
bellard authored
345
    }
bellard authored
346
347
348

    cmd = buf[0] & 0xc;
    reg = buf[0] & 0x3;
bellard authored
349
    olen = 0;
bellard authored
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;
bellard authored
376
377
378
        case 1:
            break;
        case 3:
bellard authored
379
380
381
            obuf[0] = d->handler;
            obuf[1] = d->devaddr;
            olen = 2;
bellard authored
382
383
384
385
            break;
        }
        break;
    }
bellard authored
386
    return olen;
bellard authored
387
388
}
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;
}
bellard authored
400
401
402
void adb_mouse_init(ADBBusState *bus)
{
    ADBDevice *d;
bellard authored
403
    MouseState *s;
bellard authored
404
bellard authored
405
    s = qemu_mallocz(sizeof(MouseState));
406
407
408
    d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request,
                            adb_mouse_reset, s);
    adb_mouse_reset(d);
409
    qemu_add_mouse_event_handler(adb_mouse_event, d, 0, "QEMU ADB Mouse");
bellard authored
410
}