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