Statistics
| Branch: | Revision:

root / hw / adb.c @ 09b26c5e

History | View | Annotate | Download (10.6 kB)

1 267002cd bellard
/*
2 267002cd bellard
 * QEMU ADB support
3 267002cd bellard
 * 
4 267002cd bellard
 * Copyright (c) 2004 Fabrice Bellard
5 267002cd bellard
 * 
6 267002cd bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 267002cd bellard
 * of this software and associated documentation files (the "Software"), to deal
8 267002cd bellard
 * in the Software without restriction, including without limitation the rights
9 267002cd bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 267002cd bellard
 * copies of the Software, and to permit persons to whom the Software is
11 267002cd bellard
 * furnished to do so, subject to the following conditions:
12 267002cd bellard
 *
13 267002cd bellard
 * The above copyright notice and this permission notice shall be included in
14 267002cd bellard
 * all copies or substantial portions of the Software.
15 267002cd bellard
 *
16 267002cd bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 267002cd bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 267002cd bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 267002cd bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 267002cd bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 267002cd bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 267002cd bellard
 * THE SOFTWARE.
23 267002cd bellard
 */
24 267002cd bellard
#include "vl.h"
25 267002cd bellard
26 267002cd bellard
/* ADB commands */
27 267002cd bellard
#define ADB_BUSRESET                0x00
28 267002cd bellard
#define ADB_FLUSH               0x01
29 267002cd bellard
#define ADB_WRITEREG                0x08
30 267002cd bellard
#define ADB_READREG                0x0c
31 267002cd bellard
32 267002cd bellard
/* ADB device commands */
33 267002cd bellard
#define ADB_CMD_SELF_TEST                0xff
34 267002cd bellard
#define ADB_CMD_CHANGE_ID                0xfe
35 267002cd bellard
#define ADB_CMD_CHANGE_ID_AND_ACT        0xfd
36 267002cd bellard
#define ADB_CMD_CHANGE_ID_AND_ENABLE        0x00
37 267002cd bellard
38 267002cd bellard
/* ADB default device IDs (upper 4 bits of ADB command byte) */
39 267002cd bellard
#define ADB_DONGLE        1
40 267002cd bellard
#define ADB_KEYBOARD        2
41 267002cd bellard
#define ADB_MOUSE        3
42 267002cd bellard
#define ADB_TABLET        4
43 267002cd bellard
#define ADB_MODEM        5
44 267002cd bellard
#define ADB_MISC        7
45 267002cd bellard
46 bec9d989 bellard
/* error codes */
47 bec9d989 bellard
#define ADB_RET_NOTPRESENT (-2)
48 bec9d989 bellard
49 e2733d20 bellard
int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
50 267002cd bellard
{
51 267002cd bellard
    ADBDevice *d;
52 267002cd bellard
    int devaddr, cmd, i;
53 267002cd bellard
54 819e712b bellard
    cmd = buf[0] & 0xf;
55 bec9d989 bellard
    if (cmd == ADB_BUSRESET) {
56 bec9d989 bellard
        for(i = 0; i < s->nb_devices; i++) {
57 bec9d989 bellard
            d = &s->devices[i];
58 bec9d989 bellard
            if (d->devreset) {
59 bec9d989 bellard
                d->devreset(d);
60 bec9d989 bellard
            }
61 bec9d989 bellard
        }
62 bec9d989 bellard
        return 0;
63 267002cd bellard
    }
64 bec9d989 bellard
    devaddr = buf[0] >> 4;
65 267002cd bellard
    for(i = 0; i < s->nb_devices; i++) {
66 267002cd bellard
        d = &s->devices[i];
67 267002cd bellard
        if (d->devaddr == devaddr) {
68 e2733d20 bellard
            return d->devreq(d, obuf, buf, len);
69 267002cd bellard
        }
70 267002cd bellard
    }
71 bec9d989 bellard
    return ADB_RET_NOTPRESENT;
72 e2733d20 bellard
}
73 e2733d20 bellard
74 bec9d989 bellard
/* XXX: move that to cuda ? */
75 e2733d20 bellard
int adb_poll(ADBBusState *s, uint8_t *obuf)
76 e2733d20 bellard
{
77 e2733d20 bellard
    ADBDevice *d;
78 e2733d20 bellard
    int olen, i;
79 bec9d989 bellard
    uint8_t buf[1];
80 e2733d20 bellard
81 e2733d20 bellard
    olen = 0;
82 e2733d20 bellard
    for(i = 0; i < s->nb_devices; i++) {
83 e2733d20 bellard
        if (s->poll_index >= s->nb_devices)
84 e2733d20 bellard
            s->poll_index = 0;
85 e2733d20 bellard
        d = &s->devices[s->poll_index];
86 bec9d989 bellard
        buf[0] = ADB_READREG | (d->devaddr << 4);
87 bec9d989 bellard
        olen = adb_request(s, obuf + 1, buf, 1);
88 bec9d989 bellard
        /* if there is data, we poll again the same device */
89 bec9d989 bellard
        if (olen > 0) {
90 bec9d989 bellard
            obuf[0] = buf[0];
91 bec9d989 bellard
            olen++;
92 e2733d20 bellard
            break;
93 bec9d989 bellard
        }
94 bec9d989 bellard
        s->poll_index++;
95 e2733d20 bellard
    }
96 e2733d20 bellard
    return olen;
97 267002cd bellard
}
98 267002cd bellard
99 267002cd bellard
ADBDevice *adb_register_device(ADBBusState *s, int devaddr, 
100 e2733d20 bellard
                               ADBDeviceRequest *devreq, 
101 bec9d989 bellard
                               ADBDeviceReset *devreset, 
102 267002cd bellard
                               void *opaque)
103 267002cd bellard
{
104 267002cd bellard
    ADBDevice *d;
105 267002cd bellard
    if (s->nb_devices >= MAX_ADB_DEVICES)
106 267002cd bellard
        return NULL;
107 267002cd bellard
    d = &s->devices[s->nb_devices++];
108 267002cd bellard
    d->bus = s;
109 267002cd bellard
    d->devaddr = devaddr;
110 e2733d20 bellard
    d->devreq = devreq;
111 bec9d989 bellard
    d->devreset = devreset;
112 267002cd bellard
    d->opaque = opaque;
113 267002cd bellard
    return d;
114 267002cd bellard
}
115 267002cd bellard
116 267002cd bellard
/***************************************************************/
117 267002cd bellard
/* Keyboard ADB device */
118 267002cd bellard
119 e2733d20 bellard
typedef struct KBDState {
120 e2733d20 bellard
    uint8_t data[128];
121 e2733d20 bellard
    int rptr, wptr, count;
122 e2733d20 bellard
} KBDState;
123 e2733d20 bellard
124 267002cd bellard
static const uint8_t pc_to_adb_keycode[256] = {
125 267002cd bellard
  0, 53, 18, 19, 20, 21, 23, 22, 26, 28, 25, 29, 27, 24, 51, 48,
126 267002cd bellard
 12, 13, 14, 15, 17, 16, 32, 34, 31, 35, 33, 30, 36, 54,  0,  1,
127 267002cd bellard
  2,  3,  5,  4, 38, 40, 37, 41, 39, 50, 56, 42,  6,  7,  8,  9,
128 267002cd bellard
 11, 45, 46, 43, 47, 44,123, 67, 58, 49, 57,122,120, 99,118, 96,
129 267002cd bellard
 97, 98,100,101,109, 71,107, 89, 91, 92, 78, 86, 87, 88, 69, 83,
130 e2733d20 bellard
 84, 85, 82, 65,  0,  0, 10,103,111,  0,  0,110, 81,  0,  0,  0,
131 267002cd bellard
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
132 267002cd bellard
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
133 e2733d20 bellard
  0,  0,  0, 94,  0, 93,  0,  0,  0,  0,  0,  0,104,102,  0,  0,
134 e2733d20 bellard
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 76,125,  0,  0,
135 e2733d20 bellard
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,105,  0,  0,  0,  0,  0,
136 e2733d20 bellard
  0,  0,  0,  0,  0, 75,  0,  0,124,  0,  0,  0,  0,  0,  0,  0,
137 e2733d20 bellard
  0,  0,  0,  0,  0,  0,  0,115, 62,116,  0, 59,  0, 60,  0,119,
138 e2733d20 bellard
 61,121,114,117,  0,  0,  0,  0,  0,  0,  0, 55,126,  0,127,  0,
139 267002cd bellard
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
140 e2733d20 bellard
  0,  0,  0,  0,  0, 95,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
141 267002cd bellard
};
142 267002cd bellard
143 267002cd bellard
static void adb_kbd_put_keycode(void *opaque, int keycode)
144 267002cd bellard
{
145 267002cd bellard
    ADBDevice *d = opaque;
146 e2733d20 bellard
    KBDState *s = d->opaque;
147 e2733d20 bellard
148 e2733d20 bellard
    if (s->count < sizeof(s->data)) {
149 e2733d20 bellard
        s->data[s->wptr] = keycode;
150 e2733d20 bellard
        if (++s->wptr == sizeof(s->data))
151 e2733d20 bellard
            s->wptr = 0;
152 e2733d20 bellard
        s->count++;
153 267002cd bellard
    }
154 267002cd bellard
}
155 267002cd bellard
156 e2733d20 bellard
static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf)
157 267002cd bellard
{
158 e2733d20 bellard
    static int ext_keycode;
159 e2733d20 bellard
    KBDState *s = d->opaque;
160 e2733d20 bellard
    int adb_keycode, keycode;
161 e2733d20 bellard
    int olen;
162 e2733d20 bellard
163 e2733d20 bellard
    olen = 0;
164 e2733d20 bellard
    for(;;) {
165 e2733d20 bellard
        if (s->count == 0)
166 e2733d20 bellard
            break;
167 e2733d20 bellard
        keycode = s->data[s->rptr];
168 e2733d20 bellard
        if (++s->rptr == sizeof(s->data))
169 e2733d20 bellard
            s->rptr = 0;
170 e2733d20 bellard
        s->count--;
171 e2733d20 bellard
172 e2733d20 bellard
        if (keycode == 0xe0) {
173 e2733d20 bellard
            ext_keycode = 1;
174 e2733d20 bellard
        } else {
175 e2733d20 bellard
            if (ext_keycode)
176 e2733d20 bellard
                adb_keycode =  pc_to_adb_keycode[keycode | 0x80];
177 e2733d20 bellard
            else
178 e2733d20 bellard
                adb_keycode =  pc_to_adb_keycode[keycode & 0x7f];
179 bec9d989 bellard
            obuf[0] = adb_keycode | (keycode & 0x80);
180 bec9d989 bellard
            /* NOTE: could put a second keycode if needed */
181 bec9d989 bellard
            obuf[1] = 0xff;
182 bec9d989 bellard
            olen = 2;
183 e2733d20 bellard
            ext_keycode = 0;
184 e2733d20 bellard
            break;
185 e2733d20 bellard
        }
186 e2733d20 bellard
    }
187 e2733d20 bellard
    return olen;
188 e2733d20 bellard
}
189 e2733d20 bellard
190 e2733d20 bellard
static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
191 e2733d20 bellard
                           const uint8_t *buf, int len)
192 e2733d20 bellard
{
193 bec9d989 bellard
    KBDState *s = d->opaque;
194 e2733d20 bellard
    int cmd, reg, olen;
195 e2733d20 bellard
196 bec9d989 bellard
    if ((buf[0] & 0x0f) == ADB_FLUSH) {
197 bec9d989 bellard
        /* flush keyboard fifo */
198 bec9d989 bellard
        s->wptr = s->rptr = s->count = 0;
199 bec9d989 bellard
        return 0;
200 e2733d20 bellard
    }
201 267002cd bellard
202 267002cd bellard
    cmd = buf[0] & 0xc;
203 267002cd bellard
    reg = buf[0] & 0x3;
204 e2733d20 bellard
    olen = 0;
205 267002cd bellard
    switch(cmd) {
206 267002cd bellard
    case ADB_WRITEREG:
207 267002cd bellard
        switch(reg) {
208 267002cd bellard
        case 2:
209 267002cd bellard
            /* LED status */
210 267002cd bellard
            break;
211 267002cd bellard
        case 3:
212 267002cd bellard
            switch(buf[2]) {
213 267002cd bellard
            case ADB_CMD_SELF_TEST:
214 267002cd bellard
                break;
215 267002cd bellard
            case ADB_CMD_CHANGE_ID:
216 267002cd bellard
            case ADB_CMD_CHANGE_ID_AND_ACT:
217 267002cd bellard
            case ADB_CMD_CHANGE_ID_AND_ENABLE:
218 267002cd bellard
                d->devaddr = buf[1] & 0xf;
219 267002cd bellard
                break;
220 267002cd bellard
            default:
221 267002cd bellard
                /* XXX: check this */
222 267002cd bellard
                d->devaddr = buf[1] & 0xf;
223 267002cd bellard
                d->handler = buf[2];
224 267002cd bellard
                break;
225 267002cd bellard
            }
226 267002cd bellard
        }
227 267002cd bellard
        break;
228 267002cd bellard
    case ADB_READREG:
229 267002cd bellard
        switch(reg) {
230 bec9d989 bellard
        case 0:
231 bec9d989 bellard
            olen = adb_kbd_poll(d, obuf);
232 bec9d989 bellard
            break;
233 267002cd bellard
        case 1:
234 267002cd bellard
            break;
235 267002cd bellard
        case 2:
236 e2733d20 bellard
            obuf[0] = 0x00; /* XXX: check this */
237 e2733d20 bellard
            obuf[1] = 0x07; /* led status */
238 e2733d20 bellard
            olen = 2;
239 267002cd bellard
            break;
240 267002cd bellard
        case 3:
241 e2733d20 bellard
            obuf[0] = d->handler;
242 e2733d20 bellard
            obuf[1] = d->devaddr;
243 e2733d20 bellard
            olen = 2;
244 267002cd bellard
            break;
245 267002cd bellard
        }
246 267002cd bellard
        break;
247 267002cd bellard
    }
248 e2733d20 bellard
    return olen;
249 267002cd bellard
}
250 267002cd bellard
251 3988e897 bellard
static int adb_kbd_reset(ADBDevice *d)
252 3988e897 bellard
{
253 3988e897 bellard
    KBDState *s = d->opaque;
254 3988e897 bellard
255 3988e897 bellard
    d->handler = 1;
256 3988e897 bellard
    d->devaddr = ADB_KEYBOARD;
257 3988e897 bellard
    memset(s, 0, sizeof(KBDState));
258 3988e897 bellard
259 3988e897 bellard
    return 0;
260 3988e897 bellard
}
261 3988e897 bellard
262 267002cd bellard
void adb_kbd_init(ADBBusState *bus)
263 267002cd bellard
{
264 267002cd bellard
    ADBDevice *d;
265 e2733d20 bellard
    KBDState *s;
266 e2733d20 bellard
    s = qemu_mallocz(sizeof(KBDState));
267 3988e897 bellard
    d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request,
268 3988e897 bellard
                            adb_kbd_reset, s);
269 3988e897 bellard
    adb_kbd_reset(d);
270 267002cd bellard
    qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
271 267002cd bellard
}
272 267002cd bellard
273 267002cd bellard
/***************************************************************/
274 267002cd bellard
/* Mouse ADB device */
275 267002cd bellard
276 e2733d20 bellard
typedef struct MouseState {
277 e2733d20 bellard
    int buttons_state, last_buttons_state;
278 e2733d20 bellard
    int dx, dy, dz;
279 e2733d20 bellard
} MouseState;
280 e2733d20 bellard
281 267002cd bellard
static void adb_mouse_event(void *opaque,
282 267002cd bellard
                            int dx1, int dy1, int dz1, int buttons_state)
283 267002cd bellard
{
284 267002cd bellard
    ADBDevice *d = opaque;
285 e2733d20 bellard
    MouseState *s = d->opaque;
286 e2733d20 bellard
287 e2733d20 bellard
    s->dx += dx1;
288 e2733d20 bellard
    s->dy += dy1;
289 e2733d20 bellard
    s->dz += dz1;
290 e2733d20 bellard
    s->buttons_state = buttons_state;
291 e2733d20 bellard
}
292 e2733d20 bellard
293 e2733d20 bellard
294 e2733d20 bellard
static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
295 e2733d20 bellard
{
296 e2733d20 bellard
    MouseState *s = d->opaque;
297 267002cd bellard
    int dx, dy;
298 267002cd bellard
299 e2733d20 bellard
    if (s->last_buttons_state == s->buttons_state &&
300 e2733d20 bellard
        s->dx == 0 && s->dy == 0)
301 e2733d20 bellard
        return 0;
302 e2733d20 bellard
        
303 e2733d20 bellard
    dx = s->dx;
304 267002cd bellard
    if (dx < -63)
305 267002cd bellard
        dx = -63;
306 267002cd bellard
    else if (dx > 63)
307 267002cd bellard
        dx = 63;
308 e2733d20 bellard
    
309 e2733d20 bellard
    dy = s->dy;
310 267002cd bellard
    if (dy < -63)
311 267002cd bellard
        dy = -63;
312 267002cd bellard
    else if (dy > 63)
313 267002cd bellard
        dy = 63;
314 e2733d20 bellard
    
315 e2733d20 bellard
    s->dx -= dx;
316 e2733d20 bellard
    s->dy -= dy;
317 e2733d20 bellard
    s->last_buttons_state = s->buttons_state;
318 e2733d20 bellard
    
319 267002cd bellard
    dx &= 0x7f;
320 267002cd bellard
    dy &= 0x7f;
321 e2733d20 bellard
    
322 bec9d989 bellard
    if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
323 267002cd bellard
        dy |= 0x80;
324 bec9d989 bellard
    if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
325 267002cd bellard
        dx |= 0x80;
326 e2733d20 bellard
    
327 bec9d989 bellard
    obuf[0] = dy;
328 bec9d989 bellard
    obuf[1] = dx;
329 bec9d989 bellard
    return 2;
330 267002cd bellard
}
331 267002cd bellard
332 e2733d20 bellard
static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
333 e2733d20 bellard
                             const uint8_t *buf, int len)
334 267002cd bellard
{
335 bec9d989 bellard
    MouseState *s = d->opaque;
336 e2733d20 bellard
    int cmd, reg, olen;
337 e2733d20 bellard
    
338 bec9d989 bellard
    if ((buf[0] & 0x0f) == ADB_FLUSH) {
339 bec9d989 bellard
        /* flush mouse fifo */
340 bec9d989 bellard
        s->buttons_state = s->last_buttons_state;
341 bec9d989 bellard
        s->dx = 0;
342 bec9d989 bellard
        s->dy = 0;
343 bec9d989 bellard
        s->dz = 0;
344 bec9d989 bellard
        return 0;
345 e2733d20 bellard
    }
346 267002cd bellard
347 267002cd bellard
    cmd = buf[0] & 0xc;
348 267002cd bellard
    reg = buf[0] & 0x3;
349 e2733d20 bellard
    olen = 0;
350 267002cd bellard
    switch(cmd) {
351 267002cd bellard
    case ADB_WRITEREG:
352 267002cd bellard
        switch(reg) {
353 267002cd bellard
        case 2:
354 267002cd bellard
            break;
355 267002cd bellard
        case 3:
356 267002cd bellard
            switch(buf[2]) {
357 267002cd bellard
            case ADB_CMD_SELF_TEST:
358 267002cd bellard
                break;
359 267002cd bellard
            case ADB_CMD_CHANGE_ID:
360 267002cd bellard
            case ADB_CMD_CHANGE_ID_AND_ACT:
361 267002cd bellard
            case ADB_CMD_CHANGE_ID_AND_ENABLE:
362 267002cd bellard
                d->devaddr = buf[1] & 0xf;
363 267002cd bellard
                break;
364 267002cd bellard
            default:
365 267002cd bellard
                /* XXX: check this */
366 267002cd bellard
                d->devaddr = buf[1] & 0xf;
367 267002cd bellard
                break;
368 267002cd bellard
            }
369 267002cd bellard
        }
370 267002cd bellard
        break;
371 267002cd bellard
    case ADB_READREG:
372 267002cd bellard
        switch(reg) {
373 bec9d989 bellard
        case 0:
374 bec9d989 bellard
            olen = adb_mouse_poll(d, obuf);
375 bec9d989 bellard
            break;
376 267002cd bellard
        case 1:
377 267002cd bellard
            break;
378 267002cd bellard
        case 3:
379 e2733d20 bellard
            obuf[0] = d->handler;
380 e2733d20 bellard
            obuf[1] = d->devaddr;
381 e2733d20 bellard
            olen = 2;
382 267002cd bellard
            break;
383 267002cd bellard
        }
384 267002cd bellard
        break;
385 267002cd bellard
    }
386 e2733d20 bellard
    return olen;
387 267002cd bellard
}
388 267002cd bellard
389 3988e897 bellard
static int adb_mouse_reset(ADBDevice *d)
390 3988e897 bellard
{
391 3988e897 bellard
    MouseState *s = d->opaque;
392 3988e897 bellard
393 3988e897 bellard
    d->handler = 2;
394 3988e897 bellard
    d->devaddr = ADB_MOUSE;
395 3988e897 bellard
    memset(s, 0, sizeof(MouseState));
396 3988e897 bellard
397 3988e897 bellard
    return 0;
398 3988e897 bellard
}
399 3988e897 bellard
400 267002cd bellard
void adb_mouse_init(ADBBusState *bus)
401 267002cd bellard
{
402 267002cd bellard
    ADBDevice *d;
403 e2733d20 bellard
    MouseState *s;
404 267002cd bellard
405 e2733d20 bellard
    s = qemu_mallocz(sizeof(MouseState));
406 3988e897 bellard
    d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request,
407 3988e897 bellard
                            adb_mouse_reset, s);
408 3988e897 bellard
    adb_mouse_reset(d);
409 267002cd bellard
    qemu_add_mouse_event_handler(adb_mouse_event, d);
410 267002cd bellard
}