Statistics
| Branch: | Revision:

root / hw / adb.c @ 09b26c5e

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 "vl.h"
25

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

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

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

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

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

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

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

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

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

    
116
/***************************************************************/
117
/* Keyboard ADB device */
118

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

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

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

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

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

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

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

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

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

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

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

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

    
259
    return 0;
260
}
261

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

    
273
/***************************************************************/
274
/* Mouse ADB device */
275

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

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

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

    
293

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

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

    
332
static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
333
                             const uint8_t *buf, int len)
334
{
335
    MouseState *s = d->opaque;
336
    int cmd, reg, olen;
337
    
338
    if ((buf[0] & 0x0f) == ADB_FLUSH) {
339
        /* flush mouse fifo */
340
        s->buttons_state = s->last_buttons_state;
341
        s->dx = 0;
342
        s->dy = 0;
343
        s->dz = 0;
344
        return 0;
345
    }
346

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

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

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

    
397
    return 0;
398
}
399

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

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