Statistics
| Branch: | Revision:

root / hw / adb.c @ 87ecb68b

History | View | Annotate | Download (10.6 kB)

1
/*
2
 * QEMU ADB support
3
 *
4
 * Copyright (c) 2004 Fabrice Bellard
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include "hw.h"
25
#include "ppc_mac.h"
26
#include "console.h"
27

    
28
/* ADB commands */
29
#define ADB_BUSRESET                0x00
30
#define ADB_FLUSH               0x01
31
#define ADB_WRITEREG                0x08
32
#define ADB_READREG                0x0c
33

    
34
/* ADB device commands */
35
#define ADB_CMD_SELF_TEST                0xff
36
#define ADB_CMD_CHANGE_ID                0xfe
37
#define ADB_CMD_CHANGE_ID_AND_ACT        0xfd
38
#define ADB_CMD_CHANGE_ID_AND_ENABLE        0x00
39

    
40
/* ADB default device IDs (upper 4 bits of ADB command byte) */
41
#define ADB_DONGLE        1
42
#define ADB_KEYBOARD        2
43
#define ADB_MOUSE        3
44
#define ADB_TABLET        4
45
#define ADB_MODEM        5
46
#define ADB_MISC        7
47

    
48
/* error codes */
49
#define ADB_RET_NOTPRESENT (-2)
50

    
51
int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
52
{
53
    ADBDevice *d;
54
    int devaddr, cmd, i;
55

    
56
    cmd = buf[0] & 0xf;
57
    if (cmd == ADB_BUSRESET) {
58
        for(i = 0; i < s->nb_devices; i++) {
59
            d = &s->devices[i];
60
            if (d->devreset) {
61
                d->devreset(d);
62
            }
63
        }
64
        return 0;
65
    }
66
    devaddr = buf[0] >> 4;
67
    for(i = 0; i < s->nb_devices; i++) {
68
        d = &s->devices[i];
69
        if (d->devaddr == devaddr) {
70
            return d->devreq(d, obuf, buf, len);
71
        }
72
    }
73
    return ADB_RET_NOTPRESENT;
74
}
75

    
76
/* XXX: move that to cuda ? */
77
int adb_poll(ADBBusState *s, uint8_t *obuf)
78
{
79
    ADBDevice *d;
80
    int olen, i;
81
    uint8_t buf[1];
82

    
83
    olen = 0;
84
    for(i = 0; i < s->nb_devices; i++) {
85
        if (s->poll_index >= s->nb_devices)
86
            s->poll_index = 0;
87
        d = &s->devices[s->poll_index];
88
        buf[0] = ADB_READREG | (d->devaddr << 4);
89
        olen = adb_request(s, obuf + 1, buf, 1);
90
        /* if there is data, we poll again the same device */
91
        if (olen > 0) {
92
            obuf[0] = buf[0];
93
            olen++;
94
            break;
95
        }
96
        s->poll_index++;
97
    }
98
    return olen;
99
}
100

    
101
ADBDevice *adb_register_device(ADBBusState *s, int devaddr,
102
                               ADBDeviceRequest *devreq,
103
                               ADBDeviceReset *devreset,
104
                               void *opaque)
105
{
106
    ADBDevice *d;
107
    if (s->nb_devices >= MAX_ADB_DEVICES)
108
        return NULL;
109
    d = &s->devices[s->nb_devices++];
110
    d->bus = s;
111
    d->devaddr = devaddr;
112
    d->devreq = devreq;
113
    d->devreset = devreset;
114
    d->opaque = opaque;
115
    return d;
116
}
117

    
118
/***************************************************************/
119
/* Keyboard ADB device */
120

    
121
typedef struct KBDState {
122
    uint8_t data[128];
123
    int rptr, wptr, count;
124
} KBDState;
125

    
126
static const uint8_t pc_to_adb_keycode[256] = {
127
  0, 53, 18, 19, 20, 21, 23, 22, 26, 28, 25, 29, 27, 24, 51, 48,
128
 12, 13, 14, 15, 17, 16, 32, 34, 31, 35, 33, 30, 36, 54,  0,  1,
129
  2,  3,  5,  4, 38, 40, 37, 41, 39, 50, 56, 42,  6,  7,  8,  9,
130
 11, 45, 46, 43, 47, 44,123, 67, 58, 49, 57,122,120, 99,118, 96,
131
 97, 98,100,101,109, 71,107, 89, 91, 92, 78, 86, 87, 88, 69, 83,
132
 84, 85, 82, 65,  0,  0, 10,103,111,  0,  0,110, 81,  0,  0,  0,
133
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
134
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
135
  0,  0,  0, 94,  0, 93,  0,  0,  0,  0,  0,  0,104,102,  0,  0,
136
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 76,125,  0,  0,
137
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,105,  0,  0,  0,  0,  0,
138
  0,  0,  0,  0,  0, 75,  0,  0,124,  0,  0,  0,  0,  0,  0,  0,
139
  0,  0,  0,  0,  0,  0,  0,115, 62,116,  0, 59,  0, 60,  0,119,
140
 61,121,114,117,  0,  0,  0,  0,  0,  0,  0, 55,126,  0,127,  0,
141
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
142
  0,  0,  0,  0,  0, 95,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
143
};
144

    
145
static void adb_kbd_put_keycode(void *opaque, int keycode)
146
{
147
    ADBDevice *d = opaque;
148
    KBDState *s = d->opaque;
149

    
150
    if (s->count < sizeof(s->data)) {
151
        s->data[s->wptr] = keycode;
152
        if (++s->wptr == sizeof(s->data))
153
            s->wptr = 0;
154
        s->count++;
155
    }
156
}
157

    
158
static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf)
159
{
160
    static int ext_keycode;
161
    KBDState *s = d->opaque;
162
    int adb_keycode, keycode;
163
    int olen;
164

    
165
    olen = 0;
166
    for(;;) {
167
        if (s->count == 0)
168
            break;
169
        keycode = s->data[s->rptr];
170
        if (++s->rptr == sizeof(s->data))
171
            s->rptr = 0;
172
        s->count--;
173

    
174
        if (keycode == 0xe0) {
175
            ext_keycode = 1;
176
        } else {
177
            if (ext_keycode)
178
                adb_keycode =  pc_to_adb_keycode[keycode | 0x80];
179
            else
180
                adb_keycode =  pc_to_adb_keycode[keycode & 0x7f];
181
            obuf[0] = adb_keycode | (keycode & 0x80);
182
            /* NOTE: could put a second keycode if needed */
183
            obuf[1] = 0xff;
184
            olen = 2;
185
            ext_keycode = 0;
186
            break;
187
        }
188
    }
189
    return olen;
190
}
191

    
192
static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
193
                           const uint8_t *buf, int len)
194
{
195
    KBDState *s = d->opaque;
196
    int cmd, reg, olen;
197

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

    
204
    cmd = buf[0] & 0xc;
205
    reg = buf[0] & 0x3;
206
    olen = 0;
207
    switch(cmd) {
208
    case ADB_WRITEREG:
209
        switch(reg) {
210
        case 2:
211
            /* LED status */
212
            break;
213
        case 3:
214
            switch(buf[2]) {
215
            case ADB_CMD_SELF_TEST:
216
                break;
217
            case ADB_CMD_CHANGE_ID:
218
            case ADB_CMD_CHANGE_ID_AND_ACT:
219
            case ADB_CMD_CHANGE_ID_AND_ENABLE:
220
                d->devaddr = buf[1] & 0xf;
221
                break;
222
            default:
223
                /* XXX: check this */
224
                d->devaddr = buf[1] & 0xf;
225
                d->handler = buf[2];
226
                break;
227
            }
228
        }
229
        break;
230
    case ADB_READREG:
231
        switch(reg) {
232
        case 0:
233
            olen = adb_kbd_poll(d, obuf);
234
            break;
235
        case 1:
236
            break;
237
        case 2:
238
            obuf[0] = 0x00; /* XXX: check this */
239
            obuf[1] = 0x07; /* led status */
240
            olen = 2;
241
            break;
242
        case 3:
243
            obuf[0] = d->handler;
244
            obuf[1] = d->devaddr;
245
            olen = 2;
246
            break;
247
        }
248
        break;
249
    }
250
    return olen;
251
}
252

    
253
static int adb_kbd_reset(ADBDevice *d)
254
{
255
    KBDState *s = d->opaque;
256

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

    
261
    return 0;
262
}
263

    
264
void adb_kbd_init(ADBBusState *bus)
265
{
266
    ADBDevice *d;
267
    KBDState *s;
268
    s = qemu_mallocz(sizeof(KBDState));
269
    d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request,
270
                            adb_kbd_reset, s);
271
    adb_kbd_reset(d);
272
    qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
273
}
274

    
275
/***************************************************************/
276
/* Mouse ADB device */
277

    
278
typedef struct MouseState {
279
    int buttons_state, last_buttons_state;
280
    int dx, dy, dz;
281
} MouseState;
282

    
283
static void adb_mouse_event(void *opaque,
284
                            int dx1, int dy1, int dz1, int buttons_state)
285
{
286
    ADBDevice *d = opaque;
287
    MouseState *s = d->opaque;
288

    
289
    s->dx += dx1;
290
    s->dy += dy1;
291
    s->dz += dz1;
292
    s->buttons_state = buttons_state;
293
}
294

    
295

    
296
static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
297
{
298
    MouseState *s = d->opaque;
299
    int dx, dy;
300

    
301
    if (s->last_buttons_state == s->buttons_state &&
302
        s->dx == 0 && s->dy == 0)
303
        return 0;
304

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

    
311
    dy = s->dy;
312
    if (dy < -63)
313
        dy = -63;
314
    else if (dy > 63)
315
        dy = 63;
316

    
317
    s->dx -= dx;
318
    s->dy -= dy;
319
    s->last_buttons_state = s->buttons_state;
320

    
321
    dx &= 0x7f;
322
    dy &= 0x7f;
323

    
324
    if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
325
        dy |= 0x80;
326
    if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
327
        dx |= 0x80;
328

    
329
    obuf[0] = dy;
330
    obuf[1] = dx;
331
    return 2;
332
}
333

    
334
static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
335
                             const uint8_t *buf, int len)
336
{
337
    MouseState *s = d->opaque;
338
    int cmd, reg, olen;
339

    
340
    if ((buf[0] & 0x0f) == ADB_FLUSH) {
341
        /* flush mouse fifo */
342
        s->buttons_state = s->last_buttons_state;
343
        s->dx = 0;
344
        s->dy = 0;
345
        s->dz = 0;
346
        return 0;
347
    }
348

    
349
    cmd = buf[0] & 0xc;
350
    reg = buf[0] & 0x3;
351
    olen = 0;
352
    switch(cmd) {
353
    case ADB_WRITEREG:
354
        switch(reg) {
355
        case 2:
356
            break;
357
        case 3:
358
            switch(buf[2]) {
359
            case ADB_CMD_SELF_TEST:
360
                break;
361
            case ADB_CMD_CHANGE_ID:
362
            case ADB_CMD_CHANGE_ID_AND_ACT:
363
            case ADB_CMD_CHANGE_ID_AND_ENABLE:
364
                d->devaddr = buf[1] & 0xf;
365
                break;
366
            default:
367
                /* XXX: check this */
368
                d->devaddr = buf[1] & 0xf;
369
                break;
370
            }
371
        }
372
        break;
373
    case ADB_READREG:
374
        switch(reg) {
375
        case 0:
376
            olen = adb_mouse_poll(d, obuf);
377
            break;
378
        case 1:
379
            break;
380
        case 3:
381
            obuf[0] = d->handler;
382
            obuf[1] = d->devaddr;
383
            olen = 2;
384
            break;
385
        }
386
        break;
387
    }
388
    return olen;
389
}
390

    
391
static int adb_mouse_reset(ADBDevice *d)
392
{
393
    MouseState *s = d->opaque;
394

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

    
399
    return 0;
400
}
401

    
402
void adb_mouse_init(ADBBusState *bus)
403
{
404
    ADBDevice *d;
405
    MouseState *s;
406

    
407
    s = qemu_mallocz(sizeof(MouseState));
408
    d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request,
409
                            adb_mouse_reset, s);
410
    adb_mouse_reset(d);
411
    qemu_add_mouse_event_handler(adb_mouse_event, d, 0, "QEMU ADB Mouse");
412
}