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