Statistics
| Branch: | Revision:

root / hw / adb.c @ bec9d989

History | View | Annotate | Download (10.1 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
void adb_kbd_init(ADBBusState *bus)
252
{
253
    ADBDevice *d;
254
    KBDState *s;
255
    s = qemu_mallocz(sizeof(KBDState));
256
    d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request, NULL, s);
257
    d->handler = 1;
258
    qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
259
}
260

    
261
/***************************************************************/
262
/* Mouse ADB device */
263

    
264
typedef struct MouseState {
265
    int buttons_state, last_buttons_state;
266
    int dx, dy, dz;
267
} MouseState;
268

    
269
static void adb_mouse_event(void *opaque,
270
                            int dx1, int dy1, int dz1, int buttons_state)
271
{
272
    ADBDevice *d = opaque;
273
    MouseState *s = d->opaque;
274

    
275
    s->dx += dx1;
276
    s->dy += dy1;
277
    s->dz += dz1;
278
    s->buttons_state = buttons_state;
279
}
280

    
281

    
282
static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
283
{
284
    MouseState *s = d->opaque;
285
    int dx, dy;
286

    
287
    if (s->last_buttons_state == s->buttons_state &&
288
        s->dx == 0 && s->dy == 0)
289
        return 0;
290
        
291
    dx = s->dx;
292
    if (dx < -63)
293
        dx = -63;
294
    else if (dx > 63)
295
        dx = 63;
296
    
297
    dy = s->dy;
298
    if (dy < -63)
299
        dy = -63;
300
    else if (dy > 63)
301
        dy = 63;
302
    
303
    s->dx -= dx;
304
    s->dy -= dy;
305
    s->last_buttons_state = s->buttons_state;
306
    
307
    dx &= 0x7f;
308
    dy &= 0x7f;
309
    
310
    if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
311
        dy |= 0x80;
312
    if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
313
        dx |= 0x80;
314
    
315
    obuf[0] = dy;
316
    obuf[1] = dx;
317
    return 2;
318
}
319

    
320
static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
321
                             const uint8_t *buf, int len)
322
{
323
    MouseState *s = d->opaque;
324
    int cmd, reg, olen;
325
    
326
    if ((buf[0] & 0x0f) == ADB_FLUSH) {
327
        /* flush mouse fifo */
328
        s->buttons_state = s->last_buttons_state;
329
        s->dx = 0;
330
        s->dy = 0;
331
        s->dz = 0;
332
        return 0;
333
    }
334

    
335
    cmd = buf[0] & 0xc;
336
    reg = buf[0] & 0x3;
337
    olen = 0;
338
    switch(cmd) {
339
    case ADB_WRITEREG:
340
        switch(reg) {
341
        case 2:
342
            break;
343
        case 3:
344
            switch(buf[2]) {
345
            case ADB_CMD_SELF_TEST:
346
                break;
347
            case ADB_CMD_CHANGE_ID:
348
            case ADB_CMD_CHANGE_ID_AND_ACT:
349
            case ADB_CMD_CHANGE_ID_AND_ENABLE:
350
                d->devaddr = buf[1] & 0xf;
351
                break;
352
            default:
353
                /* XXX: check this */
354
                d->devaddr = buf[1] & 0xf;
355
                break;
356
            }
357
        }
358
        break;
359
    case ADB_READREG:
360
        switch(reg) {
361
        case 0:
362
            olen = adb_mouse_poll(d, obuf);
363
            break;
364
        case 1:
365
            break;
366
        case 3:
367
            obuf[0] = d->handler;
368
            obuf[1] = d->devaddr;
369
            olen = 2;
370
            break;
371
        }
372
        break;
373
    }
374
    return olen;
375
}
376

    
377
void adb_mouse_init(ADBBusState *bus)
378
{
379
    ADBDevice *d;
380
    MouseState *s;
381

    
382
    s = qemu_mallocz(sizeof(MouseState));
383
    d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request, NULL, s);
384
    d->handler = 2;
385
    qemu_add_mouse_event_handler(adb_mouse_event, d);
386
}