source: trunk/packages/xen-3.1/xen-3.1/tools/ioemu/hw/adb.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 10.6 KB
Line 
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
49int 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 ? */
75int 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
99ADBDevice *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
119typedef struct KBDState {
120    uint8_t data[128];
121    int rptr, wptr, count;
122} KBDState;
123
124static 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
143static 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
156static 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
190static 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
251static 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
262void 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
276typedef struct MouseState {
277    int buttons_state, last_buttons_state;
278    int dx, dy, dz;
279} MouseState;
280
281static 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
294static 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
332static 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
389static 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
400void 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, 0);
410}
Note: See TracBrowser for help on using the repository browser.