etrax: Don't keep the passed irq pointer.
[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, ...) \
33 do { printf("ADB: " fmt , ## __VA_ARGS__); } while (0)
34 #else
35 #define ADB_DPRINTF(fmt, ...)
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 void adb_kbd_save(QEMUFile *f, void *opaque)
266 {
267     KBDState *s = (KBDState *)opaque;
268
269     qemu_put_buffer(f, s->data, sizeof(s->data));
270     qemu_put_sbe32s(f, &s->rptr);
271     qemu_put_sbe32s(f, &s->wptr);
272     qemu_put_sbe32s(f, &s->count);
273 }
274
275 static int adb_kbd_load(QEMUFile *f, void *opaque, int version_id)
276 {
277     KBDState *s = (KBDState *)opaque;
278
279     if (version_id != 1)
280         return -EINVAL;
281
282     qemu_get_buffer(f, s->data, sizeof(s->data));
283     qemu_get_sbe32s(f, &s->rptr);
284     qemu_get_sbe32s(f, &s->wptr);
285     qemu_get_sbe32s(f, &s->count);
286
287     return 0;
288 }
289
290 static int adb_kbd_reset(ADBDevice *d)
291 {
292     KBDState *s = d->opaque;
293
294     d->handler = 1;
295     d->devaddr = ADB_KEYBOARD;
296     memset(s, 0, sizeof(KBDState));
297
298     return 0;
299 }
300
301 void adb_kbd_init(ADBBusState *bus)
302 {
303     ADBDevice *d;
304     KBDState *s;
305     s = qemu_mallocz(sizeof(KBDState));
306     d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request,
307                             adb_kbd_reset, s);
308     qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
309     register_savevm("adb_kbd", -1, 1, adb_kbd_save,
310                     adb_kbd_load, s);
311 }
312
313 /***************************************************************/
314 /* Mouse ADB device */
315
316 typedef struct MouseState {
317     int buttons_state, last_buttons_state;
318     int dx, dy, dz;
319 } MouseState;
320
321 static void adb_mouse_event(void *opaque,
322                             int dx1, int dy1, int dz1, int buttons_state)
323 {
324     ADBDevice *d = opaque;
325     MouseState *s = d->opaque;
326
327     s->dx += dx1;
328     s->dy += dy1;
329     s->dz += dz1;
330     s->buttons_state = buttons_state;
331 }
332
333
334 static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
335 {
336     MouseState *s = d->opaque;
337     int dx, dy;
338
339     if (s->last_buttons_state == s->buttons_state &&
340         s->dx == 0 && s->dy == 0)
341         return 0;
342
343     dx = s->dx;
344     if (dx < -63)
345         dx = -63;
346     else if (dx > 63)
347         dx = 63;
348
349     dy = s->dy;
350     if (dy < -63)
351         dy = -63;
352     else if (dy > 63)
353         dy = 63;
354
355     s->dx -= dx;
356     s->dy -= dy;
357     s->last_buttons_state = s->buttons_state;
358
359     dx &= 0x7f;
360     dy &= 0x7f;
361
362     if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
363         dy |= 0x80;
364     if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
365         dx |= 0x80;
366
367     obuf[0] = dy;
368     obuf[1] = dx;
369     return 2;
370 }
371
372 static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
373                              const uint8_t *buf, int len)
374 {
375     MouseState *s = d->opaque;
376     int cmd, reg, olen;
377
378     if ((buf[0] & 0x0f) == ADB_FLUSH) {
379         /* flush mouse fifo */
380         s->buttons_state = s->last_buttons_state;
381         s->dx = 0;
382         s->dy = 0;
383         s->dz = 0;
384         return 0;
385     }
386
387     cmd = buf[0] & 0xc;
388     reg = buf[0] & 0x3;
389     olen = 0;
390     switch(cmd) {
391     case ADB_WRITEREG:
392         ADB_DPRINTF("write reg %d val 0x%2.2x\n", reg, buf[1]);
393         switch(reg) {
394         case 2:
395             break;
396         case 3:
397             switch(buf[2]) {
398             case ADB_CMD_SELF_TEST:
399                 break;
400             case ADB_CMD_CHANGE_ID:
401             case ADB_CMD_CHANGE_ID_AND_ACT:
402             case ADB_CMD_CHANGE_ID_AND_ENABLE:
403                 d->devaddr = buf[1] & 0xf;
404                 break;
405             default:
406                 /* XXX: check this */
407                 d->devaddr = buf[1] & 0xf;
408                 break;
409             }
410         }
411         break;
412     case ADB_READREG:
413         switch(reg) {
414         case 0:
415             olen = adb_mouse_poll(d, obuf);
416             break;
417         case 1:
418             break;
419         case 3:
420             obuf[0] = d->handler;
421             obuf[1] = d->devaddr;
422             olen = 2;
423             break;
424         }
425         ADB_DPRINTF("read reg %d obuf[0] 0x%2.2x obuf[1] 0x%2.2x\n", reg,
426                     obuf[0], obuf[1]);
427         break;
428     }
429     return olen;
430 }
431
432 static int adb_mouse_reset(ADBDevice *d)
433 {
434     MouseState *s = d->opaque;
435
436     d->handler = 2;
437     d->devaddr = ADB_MOUSE;
438     memset(s, 0, sizeof(MouseState));
439
440     return 0;
441 }
442
443 static void adb_mouse_save(QEMUFile *f, void *opaque)
444 {
445     MouseState *s = (MouseState *)opaque;
446
447     qemu_put_sbe32s(f, &s->buttons_state);
448     qemu_put_sbe32s(f, &s->last_buttons_state);
449     qemu_put_sbe32s(f, &s->dx);
450     qemu_put_sbe32s(f, &s->dy);
451     qemu_put_sbe32s(f, &s->dz);
452 }
453
454 static int adb_mouse_load(QEMUFile *f, void *opaque, int version_id)
455 {
456     MouseState *s = (MouseState *)opaque;
457
458     if (version_id != 1)
459         return -EINVAL;
460
461     qemu_get_sbe32s(f, &s->buttons_state);
462     qemu_get_sbe32s(f, &s->last_buttons_state);
463     qemu_get_sbe32s(f, &s->dx);
464     qemu_get_sbe32s(f, &s->dy);
465     qemu_get_sbe32s(f, &s->dz);
466
467     return 0;
468 }
469
470 void adb_mouse_init(ADBBusState *bus)
471 {
472     ADBDevice *d;
473     MouseState *s;
474
475     s = qemu_mallocz(sizeof(MouseState));
476     d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request,
477                             adb_mouse_reset, s);
478     qemu_add_mouse_event_handler(adb_mouse_event, d, 0, "QEMU ADB Mouse");
479     register_savevm("adb_mouse", -1, 1, adb_mouse_save,
480                     adb_mouse_load, s);
481 }