]> Git Repo - qemu.git/blob - hw/adb.c
sparc64: interrupt trap handling
[qemu.git] / 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     return d;
127 }
128
129 /***************************************************************/
130 /* Keyboard ADB device */
131
132 typedef struct KBDState {
133     uint8_t data[128];
134     int rptr, wptr, count;
135 } KBDState;
136
137 static const uint8_t pc_to_adb_keycode[256] = {
138   0, 53, 18, 19, 20, 21, 23, 22, 26, 28, 25, 29, 27, 24, 51, 48,
139  12, 13, 14, 15, 17, 16, 32, 34, 31, 35, 33, 30, 36, 54,  0,  1,
140   2,  3,  5,  4, 38, 40, 37, 41, 39, 50, 56, 42,  6,  7,  8,  9,
141  11, 45, 46, 43, 47, 44,123, 67, 58, 49, 57,122,120, 99,118, 96,
142  97, 98,100,101,109, 71,107, 89, 91, 92, 78, 86, 87, 88, 69, 83,
143  84, 85, 82, 65,  0,  0, 10,103,111,  0,  0,110, 81,  0,  0,  0,
144   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
145   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
146   0,  0,  0, 94,  0, 93,  0,  0,  0,  0,  0,  0,104,102,  0,  0,
147   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 76,125,  0,  0,
148   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,105,  0,  0,  0,  0,  0,
149   0,  0,  0,  0,  0, 75,  0,  0,124,  0,  0,  0,  0,  0,  0,  0,
150   0,  0,  0,  0,  0,  0,  0,115, 62,116,  0, 59,  0, 60,  0,119,
151  61,121,114,117,  0,  0,  0,  0,  0,  0,  0, 55,126,  0,127,  0,
152   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
153   0,  0,  0,  0,  0, 95,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
154 };
155
156 static void adb_kbd_put_keycode(void *opaque, int keycode)
157 {
158     ADBDevice *d = opaque;
159     KBDState *s = d->opaque;
160
161     if (s->count < sizeof(s->data)) {
162         s->data[s->wptr] = keycode;
163         if (++s->wptr == sizeof(s->data))
164             s->wptr = 0;
165         s->count++;
166     }
167 }
168
169 static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf)
170 {
171     static int ext_keycode;
172     KBDState *s = d->opaque;
173     int adb_keycode, keycode;
174     int olen;
175
176     olen = 0;
177     for(;;) {
178         if (s->count == 0)
179             break;
180         keycode = s->data[s->rptr];
181         if (++s->rptr == sizeof(s->data))
182             s->rptr = 0;
183         s->count--;
184
185         if (keycode == 0xe0) {
186             ext_keycode = 1;
187         } else {
188             if (ext_keycode)
189                 adb_keycode =  pc_to_adb_keycode[keycode | 0x80];
190             else
191                 adb_keycode =  pc_to_adb_keycode[keycode & 0x7f];
192             obuf[0] = adb_keycode | (keycode & 0x80);
193             /* NOTE: could put a second keycode if needed */
194             obuf[1] = 0xff;
195             olen = 2;
196             ext_keycode = 0;
197             break;
198         }
199     }
200     return olen;
201 }
202
203 static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
204                            const uint8_t *buf, int len)
205 {
206     KBDState *s = d->opaque;
207     int cmd, reg, olen;
208
209     if ((buf[0] & 0x0f) == ADB_FLUSH) {
210         /* flush keyboard fifo */
211         s->wptr = s->rptr = s->count = 0;
212         return 0;
213     }
214
215     cmd = buf[0] & 0xc;
216     reg = buf[0] & 0x3;
217     olen = 0;
218     switch(cmd) {
219     case ADB_WRITEREG:
220         switch(reg) {
221         case 2:
222             /* LED status */
223             break;
224         case 3:
225             switch(buf[2]) {
226             case ADB_CMD_SELF_TEST:
227                 break;
228             case ADB_CMD_CHANGE_ID:
229             case ADB_CMD_CHANGE_ID_AND_ACT:
230             case ADB_CMD_CHANGE_ID_AND_ENABLE:
231                 d->devaddr = buf[1] & 0xf;
232                 break;
233             default:
234                 /* XXX: check this */
235                 d->devaddr = buf[1] & 0xf;
236                 d->handler = buf[2];
237                 break;
238             }
239         }
240         break;
241     case ADB_READREG:
242         switch(reg) {
243         case 0:
244             olen = adb_kbd_poll(d, obuf);
245             break;
246         case 1:
247             break;
248         case 2:
249             obuf[0] = 0x00; /* XXX: check this */
250             obuf[1] = 0x07; /* led status */
251             olen = 2;
252             break;
253         case 3:
254             obuf[0] = d->handler;
255             obuf[1] = d->devaddr;
256             olen = 2;
257             break;
258         }
259         break;
260     }
261     return olen;
262 }
263
264 static void adb_kbd_save(QEMUFile *f, void *opaque)
265 {
266     KBDState *s = (KBDState *)opaque;
267
268     qemu_put_buffer(f, s->data, sizeof(s->data));
269     qemu_put_sbe32s(f, &s->rptr);
270     qemu_put_sbe32s(f, &s->wptr);
271     qemu_put_sbe32s(f, &s->count);
272 }
273
274 static int adb_kbd_load(QEMUFile *f, void *opaque, int version_id)
275 {
276     KBDState *s = (KBDState *)opaque;
277
278     if (version_id != 1)
279         return -EINVAL;
280
281     qemu_get_buffer(f, s->data, sizeof(s->data));
282     qemu_get_sbe32s(f, &s->rptr);
283     qemu_get_sbe32s(f, &s->wptr);
284     qemu_get_sbe32s(f, &s->count);
285
286     return 0;
287 }
288
289 static int adb_kbd_reset(ADBDevice *d)
290 {
291     KBDState *s = d->opaque;
292
293     d->handler = 1;
294     d->devaddr = ADB_KEYBOARD;
295     memset(s, 0, sizeof(KBDState));
296
297     return 0;
298 }
299
300 void adb_kbd_init(ADBBusState *bus)
301 {
302     ADBDevice *d;
303     KBDState *s;
304     s = qemu_mallocz(sizeof(KBDState));
305     d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request,
306                             adb_kbd_reset, s);
307     qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
308     register_savevm("adb_kbd", -1, 1, adb_kbd_save,
309                     adb_kbd_load, s);
310 }
311
312 /***************************************************************/
313 /* Mouse ADB device */
314
315 typedef struct MouseState {
316     int buttons_state, last_buttons_state;
317     int dx, dy, dz;
318 } MouseState;
319
320 static void adb_mouse_event(void *opaque,
321                             int dx1, int dy1, int dz1, int buttons_state)
322 {
323     ADBDevice *d = opaque;
324     MouseState *s = d->opaque;
325
326     s->dx += dx1;
327     s->dy += dy1;
328     s->dz += dz1;
329     s->buttons_state = buttons_state;
330 }
331
332
333 static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
334 {
335     MouseState *s = d->opaque;
336     int dx, dy;
337
338     if (s->last_buttons_state == s->buttons_state &&
339         s->dx == 0 && s->dy == 0)
340         return 0;
341
342     dx = s->dx;
343     if (dx < -63)
344         dx = -63;
345     else if (dx > 63)
346         dx = 63;
347
348     dy = s->dy;
349     if (dy < -63)
350         dy = -63;
351     else if (dy > 63)
352         dy = 63;
353
354     s->dx -= dx;
355     s->dy -= dy;
356     s->last_buttons_state = s->buttons_state;
357
358     dx &= 0x7f;
359     dy &= 0x7f;
360
361     if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
362         dy |= 0x80;
363     if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
364         dx |= 0x80;
365
366     obuf[0] = dy;
367     obuf[1] = dx;
368     return 2;
369 }
370
371 static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
372                              const uint8_t *buf, int len)
373 {
374     MouseState *s = d->opaque;
375     int cmd, reg, olen;
376
377     if ((buf[0] & 0x0f) == ADB_FLUSH) {
378         /* flush mouse fifo */
379         s->buttons_state = s->last_buttons_state;
380         s->dx = 0;
381         s->dy = 0;
382         s->dz = 0;
383         return 0;
384     }
385
386     cmd = buf[0] & 0xc;
387     reg = buf[0] & 0x3;
388     olen = 0;
389     switch(cmd) {
390     case ADB_WRITEREG:
391         ADB_DPRINTF("write reg %d val 0x%2.2x\n", reg, buf[1]);
392         switch(reg) {
393         case 2:
394             break;
395         case 3:
396             switch(buf[2]) {
397             case ADB_CMD_SELF_TEST:
398                 break;
399             case ADB_CMD_CHANGE_ID:
400             case ADB_CMD_CHANGE_ID_AND_ACT:
401             case ADB_CMD_CHANGE_ID_AND_ENABLE:
402                 d->devaddr = buf[1] & 0xf;
403                 break;
404             default:
405                 /* XXX: check this */
406                 d->devaddr = buf[1] & 0xf;
407                 break;
408             }
409         }
410         break;
411     case ADB_READREG:
412         switch(reg) {
413         case 0:
414             olen = adb_mouse_poll(d, obuf);
415             break;
416         case 1:
417             break;
418         case 3:
419             obuf[0] = d->handler;
420             obuf[1] = d->devaddr;
421             olen = 2;
422             break;
423         }
424         ADB_DPRINTF("read reg %d obuf[0] 0x%2.2x obuf[1] 0x%2.2x\n", reg,
425                     obuf[0], obuf[1]);
426         break;
427     }
428     return olen;
429 }
430
431 static int adb_mouse_reset(ADBDevice *d)
432 {
433     MouseState *s = d->opaque;
434
435     d->handler = 2;
436     d->devaddr = ADB_MOUSE;
437     memset(s, 0, sizeof(MouseState));
438
439     return 0;
440 }
441
442 static void adb_mouse_save(QEMUFile *f, void *opaque)
443 {
444     MouseState *s = (MouseState *)opaque;
445
446     qemu_put_sbe32s(f, &s->buttons_state);
447     qemu_put_sbe32s(f, &s->last_buttons_state);
448     qemu_put_sbe32s(f, &s->dx);
449     qemu_put_sbe32s(f, &s->dy);
450     qemu_put_sbe32s(f, &s->dz);
451 }
452
453 static int adb_mouse_load(QEMUFile *f, void *opaque, int version_id)
454 {
455     MouseState *s = (MouseState *)opaque;
456
457     if (version_id != 1)
458         return -EINVAL;
459
460     qemu_get_sbe32s(f, &s->buttons_state);
461     qemu_get_sbe32s(f, &s->last_buttons_state);
462     qemu_get_sbe32s(f, &s->dx);
463     qemu_get_sbe32s(f, &s->dy);
464     qemu_get_sbe32s(f, &s->dz);
465
466     return 0;
467 }
468
469 void adb_mouse_init(ADBBusState *bus)
470 {
471     ADBDevice *d;
472     MouseState *s;
473
474     s = qemu_mallocz(sizeof(MouseState));
475     d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request,
476                             adb_mouse_reset, s);
477     qemu_add_mouse_event_handler(adb_mouse_event, d, 0, "QEMU ADB Mouse");
478     register_savevm("adb_mouse", -1, 1, adb_mouse_save,
479                     adb_mouse_load, s);
480 }
This page took 0.050367 seconds and 4 git commands to generate.