xref: /illumos-kvm-cmd/hw/adb.c (revision 68396ea9)
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 
adb_request(ADBBusState * s,uint8_t * obuf,const uint8_t * buf,int len)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 ? */
adb_poll(ADBBusState * s,uint8_t * obuf)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 
adb_register_device(ADBBusState * s,int devaddr,ADBDeviceRequest * devreq,ADBDeviceReset * devreset,void * opaque)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 
adb_kbd_put_keycode(void * opaque,int keycode)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 
adb_kbd_poll(ADBDevice * d,uint8_t * obuf)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 
adb_kbd_request(ADBDevice * d,uint8_t * obuf,const uint8_t * buf,int len)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 
adb_kbd_save(QEMUFile * f,void * opaque)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 
adb_kbd_load(QEMUFile * f,void * opaque,int version_id)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 
adb_kbd_reset(ADBDevice * d)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 
adb_kbd_init(ADBBusState * bus)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(NULL, "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 
adb_mouse_event(void * opaque,int dx1,int dy1,int dz1,int buttons_state)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 
adb_mouse_poll(ADBDevice * d,uint8_t * obuf)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 
adb_mouse_request(ADBDevice * d,uint8_t * obuf,const uint8_t * buf,int len)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 
adb_mouse_reset(ADBDevice * d)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 
adb_mouse_save(QEMUFile * f,void * opaque)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 
adb_mouse_load(QEMUFile * f,void * opaque,int version_id)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 
adb_mouse_init(ADBBusState * bus)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(NULL, "adb_mouse", -1, 1, adb_mouse_save,
479                     adb_mouse_load, s);
480 }
481