Statistics
| Branch: | Revision:

root / hw / adb.c @ 99570a40

History | View | Annotate | Download (10.6 kB)

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