]> Git Repo - qemu.git/blob - hw/adb.c
Merge branch 'ppc-next' of git://repo.or.cz/qemu/agraf
[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 "adb.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 const VMStateDescription vmstate_adb_kbd = {
265     .name = "adb_kbd",
266     .version_id = 1,
267     .minimum_version_id = 1,
268     .minimum_version_id_old = 1,
269     .fields      = (VMStateField[]) {
270         VMSTATE_BUFFER(data, KBDState),
271         VMSTATE_INT32(rptr, KBDState),
272         VMSTATE_INT32(wptr, KBDState),
273         VMSTATE_INT32(count, KBDState),
274         VMSTATE_END_OF_LIST()
275     }
276 };
277
278 static int adb_kbd_reset(ADBDevice *d)
279 {
280     KBDState *s = d->opaque;
281
282     d->handler = 1;
283     d->devaddr = ADB_KEYBOARD;
284     memset(s, 0, sizeof(KBDState));
285
286     return 0;
287 }
288
289 void adb_kbd_init(ADBBusState *bus)
290 {
291     ADBDevice *d;
292     KBDState *s;
293     s = g_malloc0(sizeof(KBDState));
294     d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request,
295                             adb_kbd_reset, s);
296     qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
297     vmstate_register(NULL, -1, &vmstate_adb_kbd, s);
298 }
299
300 /***************************************************************/
301 /* Mouse ADB device */
302
303 typedef struct MouseState {
304     int buttons_state, last_buttons_state;
305     int dx, dy, dz;
306 } MouseState;
307
308 static void adb_mouse_event(void *opaque,
309                             int dx1, int dy1, int dz1, int buttons_state)
310 {
311     ADBDevice *d = opaque;
312     MouseState *s = d->opaque;
313
314     s->dx += dx1;
315     s->dy += dy1;
316     s->dz += dz1;
317     s->buttons_state = buttons_state;
318 }
319
320
321 static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
322 {
323     MouseState *s = d->opaque;
324     int dx, dy;
325
326     if (s->last_buttons_state == s->buttons_state &&
327         s->dx == 0 && s->dy == 0)
328         return 0;
329
330     dx = s->dx;
331     if (dx < -63)
332         dx = -63;
333     else if (dx > 63)
334         dx = 63;
335
336     dy = s->dy;
337     if (dy < -63)
338         dy = -63;
339     else if (dy > 63)
340         dy = 63;
341
342     s->dx -= dx;
343     s->dy -= dy;
344     s->last_buttons_state = s->buttons_state;
345
346     dx &= 0x7f;
347     dy &= 0x7f;
348
349     if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
350         dy |= 0x80;
351     if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
352         dx |= 0x80;
353
354     obuf[0] = dy;
355     obuf[1] = dx;
356     return 2;
357 }
358
359 static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
360                              const uint8_t *buf, int len)
361 {
362     MouseState *s = d->opaque;
363     int cmd, reg, olen;
364
365     if ((buf[0] & 0x0f) == ADB_FLUSH) {
366         /* flush mouse fifo */
367         s->buttons_state = s->last_buttons_state;
368         s->dx = 0;
369         s->dy = 0;
370         s->dz = 0;
371         return 0;
372     }
373
374     cmd = buf[0] & 0xc;
375     reg = buf[0] & 0x3;
376     olen = 0;
377     switch(cmd) {
378     case ADB_WRITEREG:
379         ADB_DPRINTF("write reg %d val 0x%2.2x\n", reg, buf[1]);
380         switch(reg) {
381         case 2:
382             break;
383         case 3:
384             switch(buf[2]) {
385             case ADB_CMD_SELF_TEST:
386                 break;
387             case ADB_CMD_CHANGE_ID:
388             case ADB_CMD_CHANGE_ID_AND_ACT:
389             case ADB_CMD_CHANGE_ID_AND_ENABLE:
390                 d->devaddr = buf[1] & 0xf;
391                 break;
392             default:
393                 /* XXX: check this */
394                 d->devaddr = buf[1] & 0xf;
395                 break;
396             }
397         }
398         break;
399     case ADB_READREG:
400         switch(reg) {
401         case 0:
402             olen = adb_mouse_poll(d, obuf);
403             break;
404         case 1:
405             break;
406         case 3:
407             obuf[0] = d->handler;
408             obuf[1] = d->devaddr;
409             olen = 2;
410             break;
411         }
412         ADB_DPRINTF("read reg %d obuf[0] 0x%2.2x obuf[1] 0x%2.2x\n", reg,
413                     obuf[0], obuf[1]);
414         break;
415     }
416     return olen;
417 }
418
419 static int adb_mouse_reset(ADBDevice *d)
420 {
421     MouseState *s = d->opaque;
422
423     d->handler = 2;
424     d->devaddr = ADB_MOUSE;
425     memset(s, 0, sizeof(MouseState));
426
427     return 0;
428 }
429
430 static const VMStateDescription vmstate_adb_mouse = {
431     .name = "adb_mouse",
432     .version_id = 1,
433     .minimum_version_id = 1,
434     .minimum_version_id_old = 1,
435     .fields      = (VMStateField[]) {
436         VMSTATE_INT32(buttons_state, MouseState),
437         VMSTATE_INT32(last_buttons_state, MouseState),
438         VMSTATE_INT32(dx, MouseState),
439         VMSTATE_INT32(dy, MouseState),
440         VMSTATE_INT32(dz, MouseState),
441         VMSTATE_END_OF_LIST()
442     }
443 };
444
445 void adb_mouse_init(ADBBusState *bus)
446 {
447     ADBDevice *d;
448     MouseState *s;
449
450     s = g_malloc0(sizeof(MouseState));
451     d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request,
452                             adb_mouse_reset, s);
453     qemu_add_mouse_event_handler(adb_mouse_event, d, 0, "QEMU ADB Mouse");
454     vmstate_register(NULL, -1, &vmstate_adb_mouse, s);
455 }
This page took 0.050519 seconds and 4 git commands to generate.