HACKING: Add a section on error handling and reporting
[qemu/ar7.git] / hw / input / adb.c
blobc384856c13fa795489ff47f0ab167b4284617ca0
1 /*
2 * QEMU ADB support
4 * Copyright (c) 2004 Fabrice Bellard
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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.
24 #include "qemu/osdep.h"
25 #include "hw/hw.h"
26 #include "hw/input/adb.h"
27 #include "ui/console.h"
29 /* debug ADB */
30 //#define DEBUG_ADB
32 #ifdef DEBUG_ADB
33 #define ADB_DPRINTF(fmt, ...) \
34 do { printf("ADB: " fmt , ## __VA_ARGS__); } while (0)
35 #else
36 #define ADB_DPRINTF(fmt, ...)
37 #endif
39 /* ADB commands */
40 #define ADB_BUSRESET 0x00
41 #define ADB_FLUSH 0x01
42 #define ADB_WRITEREG 0x08
43 #define ADB_READREG 0x0c
45 /* ADB device commands */
46 #define ADB_CMD_SELF_TEST 0xff
47 #define ADB_CMD_CHANGE_ID 0xfe
48 #define ADB_CMD_CHANGE_ID_AND_ACT 0xfd
49 #define ADB_CMD_CHANGE_ID_AND_ENABLE 0x00
51 /* ADB default device IDs (upper 4 bits of ADB command byte) */
52 #define ADB_DEVID_DONGLE 1
53 #define ADB_DEVID_KEYBOARD 2
54 #define ADB_DEVID_MOUSE 3
55 #define ADB_DEVID_TABLET 4
56 #define ADB_DEVID_MODEM 5
57 #define ADB_DEVID_MISC 7
59 /* error codes */
60 #define ADB_RET_NOTPRESENT (-2)
62 static void adb_device_reset(ADBDevice *d)
64 qdev_reset_all(DEVICE(d));
67 int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
69 ADBDevice *d;
70 int devaddr, cmd, i;
72 cmd = buf[0] & 0xf;
73 if (cmd == ADB_BUSRESET) {
74 for(i = 0; i < s->nb_devices; i++) {
75 d = s->devices[i];
76 adb_device_reset(d);
78 return 0;
80 devaddr = buf[0] >> 4;
81 for(i = 0; i < s->nb_devices; i++) {
82 d = s->devices[i];
83 if (d->devaddr == devaddr) {
84 ADBDeviceClass *adc = ADB_DEVICE_GET_CLASS(d);
85 return adc->devreq(d, obuf, buf, len);
88 return ADB_RET_NOTPRESENT;
91 /* XXX: move that to cuda ? */
92 int adb_poll(ADBBusState *s, uint8_t *obuf)
94 ADBDevice *d;
95 int olen, i;
96 uint8_t buf[1];
98 olen = 0;
99 for(i = 0; i < s->nb_devices; i++) {
100 if (s->poll_index >= s->nb_devices)
101 s->poll_index = 0;
102 d = s->devices[s->poll_index];
103 buf[0] = ADB_READREG | (d->devaddr << 4);
104 olen = adb_request(s, obuf + 1, buf, 1);
105 /* if there is data, we poll again the same device */
106 if (olen > 0) {
107 obuf[0] = buf[0];
108 olen++;
109 break;
111 s->poll_index++;
113 return olen;
116 static const TypeInfo adb_bus_type_info = {
117 .name = TYPE_ADB_BUS,
118 .parent = TYPE_BUS,
119 .instance_size = sizeof(ADBBusState),
122 static const VMStateDescription vmstate_adb_device = {
123 .name = "adb_device",
124 .version_id = 0,
125 .minimum_version_id = 0,
126 .fields = (VMStateField[]) {
127 VMSTATE_INT32(devaddr, ADBDevice),
128 VMSTATE_INT32(handler, ADBDevice),
129 VMSTATE_END_OF_LIST()
133 static void adb_device_realizefn(DeviceState *dev, Error **errp)
135 ADBDevice *d = ADB_DEVICE(dev);
136 ADBBusState *bus = ADB_BUS(qdev_get_parent_bus(dev));
138 if (bus->nb_devices >= MAX_ADB_DEVICES) {
139 return;
142 bus->devices[bus->nb_devices++] = d;
145 static void adb_device_class_init(ObjectClass *oc, void *data)
147 DeviceClass *dc = DEVICE_CLASS(oc);
149 dc->realize = adb_device_realizefn;
150 dc->bus_type = TYPE_ADB_BUS;
153 static const TypeInfo adb_device_type_info = {
154 .name = TYPE_ADB_DEVICE,
155 .parent = TYPE_DEVICE,
156 .instance_size = sizeof(ADBDevice),
157 .abstract = true,
158 .class_init = adb_device_class_init,
161 /***************************************************************/
162 /* Keyboard ADB device */
164 #define ADB_KEYBOARD(obj) OBJECT_CHECK(KBDState, (obj), TYPE_ADB_KEYBOARD)
166 typedef struct KBDState {
167 /*< private >*/
168 ADBDevice parent_obj;
169 /*< public >*/
171 uint8_t data[128];
172 int rptr, wptr, count;
173 } KBDState;
175 #define ADB_KEYBOARD_CLASS(class) \
176 OBJECT_CLASS_CHECK(ADBKeyboardClass, (class), TYPE_ADB_KEYBOARD)
177 #define ADB_KEYBOARD_GET_CLASS(obj) \
178 OBJECT_GET_CLASS(ADBKeyboardClass, (obj), TYPE_ADB_KEYBOARD)
180 typedef struct ADBKeyboardClass {
181 /*< private >*/
182 ADBDeviceClass parent_class;
183 /*< public >*/
185 DeviceRealize parent_realize;
186 } ADBKeyboardClass;
188 static const uint8_t pc_to_adb_keycode[256] = {
189 0, 53, 18, 19, 20, 21, 23, 22, 26, 28, 25, 29, 27, 24, 51, 48,
190 12, 13, 14, 15, 17, 16, 32, 34, 31, 35, 33, 30, 36, 54, 0, 1,
191 2, 3, 5, 4, 38, 40, 37, 41, 39, 50, 56, 42, 6, 7, 8, 9,
192 11, 45, 46, 43, 47, 44,123, 67, 58, 49, 57,122,120, 99,118, 96,
193 97, 98,100,101,109, 71,107, 89, 91, 92, 78, 86, 87, 88, 69, 83,
194 84, 85, 82, 65, 0, 0, 10,103,111, 0, 0,110, 81, 0, 0, 0,
195 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
196 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
197 0, 0, 0, 94, 0, 93, 0, 0, 0, 0, 0, 0,104,102, 0, 0,
198 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76,125, 0, 0,
199 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,105, 0, 0, 0, 0, 0,
200 0, 0, 0, 0, 0, 75, 0, 0,124, 0, 0, 0, 0, 0, 0, 0,
201 0, 0, 0, 0, 0, 0, 0,115, 62,116, 0, 59, 0, 60, 0,119,
202 61,121,114,117, 0, 0, 0, 0, 0, 0, 0, 55,126, 0,127, 0,
203 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
204 0, 0, 0, 0, 0, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207 static void adb_kbd_put_keycode(void *opaque, int keycode)
209 KBDState *s = opaque;
211 if (s->count < sizeof(s->data)) {
212 s->data[s->wptr] = keycode;
213 if (++s->wptr == sizeof(s->data))
214 s->wptr = 0;
215 s->count++;
219 static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf)
221 static int ext_keycode;
222 KBDState *s = ADB_KEYBOARD(d);
223 int adb_keycode, keycode;
224 int olen;
226 olen = 0;
227 for(;;) {
228 if (s->count == 0)
229 break;
230 keycode = s->data[s->rptr];
231 if (++s->rptr == sizeof(s->data))
232 s->rptr = 0;
233 s->count--;
235 if (keycode == 0xe0) {
236 ext_keycode = 1;
237 } else {
238 if (ext_keycode)
239 adb_keycode = pc_to_adb_keycode[keycode | 0x80];
240 else
241 adb_keycode = pc_to_adb_keycode[keycode & 0x7f];
242 obuf[0] = adb_keycode | (keycode & 0x80);
243 /* NOTE: could put a second keycode if needed */
244 obuf[1] = 0xff;
245 olen = 2;
246 ext_keycode = 0;
247 break;
250 return olen;
253 static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
254 const uint8_t *buf, int len)
256 KBDState *s = ADB_KEYBOARD(d);
257 int cmd, reg, olen;
259 if ((buf[0] & 0x0f) == ADB_FLUSH) {
260 /* flush keyboard fifo */
261 s->wptr = s->rptr = s->count = 0;
262 return 0;
265 cmd = buf[0] & 0xc;
266 reg = buf[0] & 0x3;
267 olen = 0;
268 switch(cmd) {
269 case ADB_WRITEREG:
270 switch(reg) {
271 case 2:
272 /* LED status */
273 break;
274 case 3:
275 switch(buf[2]) {
276 case ADB_CMD_SELF_TEST:
277 break;
278 case ADB_CMD_CHANGE_ID:
279 case ADB_CMD_CHANGE_ID_AND_ACT:
280 case ADB_CMD_CHANGE_ID_AND_ENABLE:
281 d->devaddr = buf[1] & 0xf;
282 break;
283 default:
284 /* XXX: check this */
285 d->devaddr = buf[1] & 0xf;
286 d->handler = buf[2];
287 break;
290 break;
291 case ADB_READREG:
292 switch(reg) {
293 case 0:
294 olen = adb_kbd_poll(d, obuf);
295 break;
296 case 1:
297 break;
298 case 2:
299 obuf[0] = 0x00; /* XXX: check this */
300 obuf[1] = 0x07; /* led status */
301 olen = 2;
302 break;
303 case 3:
304 obuf[0] = d->handler;
305 obuf[1] = d->devaddr;
306 olen = 2;
307 break;
309 break;
311 return olen;
314 static const VMStateDescription vmstate_adb_kbd = {
315 .name = "adb_kbd",
316 .version_id = 2,
317 .minimum_version_id = 2,
318 .fields = (VMStateField[]) {
319 VMSTATE_STRUCT(parent_obj, KBDState, 0, vmstate_adb_device, ADBDevice),
320 VMSTATE_BUFFER(data, KBDState),
321 VMSTATE_INT32(rptr, KBDState),
322 VMSTATE_INT32(wptr, KBDState),
323 VMSTATE_INT32(count, KBDState),
324 VMSTATE_END_OF_LIST()
328 static void adb_kbd_reset(DeviceState *dev)
330 ADBDevice *d = ADB_DEVICE(dev);
331 KBDState *s = ADB_KEYBOARD(dev);
333 d->handler = 1;
334 d->devaddr = ADB_DEVID_KEYBOARD;
335 memset(s->data, 0, sizeof(s->data));
336 s->rptr = 0;
337 s->wptr = 0;
338 s->count = 0;
341 static void adb_kbd_realizefn(DeviceState *dev, Error **errp)
343 ADBDevice *d = ADB_DEVICE(dev);
344 ADBKeyboardClass *akc = ADB_KEYBOARD_GET_CLASS(dev);
346 akc->parent_realize(dev, errp);
348 qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
351 static void adb_kbd_initfn(Object *obj)
353 ADBDevice *d = ADB_DEVICE(obj);
355 d->devaddr = ADB_DEVID_KEYBOARD;
358 static void adb_kbd_class_init(ObjectClass *oc, void *data)
360 DeviceClass *dc = DEVICE_CLASS(oc);
361 ADBDeviceClass *adc = ADB_DEVICE_CLASS(oc);
362 ADBKeyboardClass *akc = ADB_KEYBOARD_CLASS(oc);
364 akc->parent_realize = dc->realize;
365 dc->realize = adb_kbd_realizefn;
366 set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
368 adc->devreq = adb_kbd_request;
369 dc->reset = adb_kbd_reset;
370 dc->vmsd = &vmstate_adb_kbd;
373 static const TypeInfo adb_kbd_type_info = {
374 .name = TYPE_ADB_KEYBOARD,
375 .parent = TYPE_ADB_DEVICE,
376 .instance_size = sizeof(KBDState),
377 .instance_init = adb_kbd_initfn,
378 .class_init = adb_kbd_class_init,
379 .class_size = sizeof(ADBKeyboardClass),
382 /***************************************************************/
383 /* Mouse ADB device */
385 #define ADB_MOUSE(obj) OBJECT_CHECK(MouseState, (obj), TYPE_ADB_MOUSE)
387 typedef struct MouseState {
388 /*< public >*/
389 ADBDevice parent_obj;
390 /*< private >*/
392 int buttons_state, last_buttons_state;
393 int dx, dy, dz;
394 } MouseState;
396 #define ADB_MOUSE_CLASS(class) \
397 OBJECT_CLASS_CHECK(ADBMouseClass, (class), TYPE_ADB_MOUSE)
398 #define ADB_MOUSE_GET_CLASS(obj) \
399 OBJECT_GET_CLASS(ADBMouseClass, (obj), TYPE_ADB_MOUSE)
401 typedef struct ADBMouseClass {
402 /*< public >*/
403 ADBDeviceClass parent_class;
404 /*< private >*/
406 DeviceRealize parent_realize;
407 } ADBMouseClass;
409 static void adb_mouse_event(void *opaque,
410 int dx1, int dy1, int dz1, int buttons_state)
412 MouseState *s = opaque;
414 s->dx += dx1;
415 s->dy += dy1;
416 s->dz += dz1;
417 s->buttons_state = buttons_state;
421 static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
423 MouseState *s = ADB_MOUSE(d);
424 int dx, dy;
426 if (s->last_buttons_state == s->buttons_state &&
427 s->dx == 0 && s->dy == 0)
428 return 0;
430 dx = s->dx;
431 if (dx < -63)
432 dx = -63;
433 else if (dx > 63)
434 dx = 63;
436 dy = s->dy;
437 if (dy < -63)
438 dy = -63;
439 else if (dy > 63)
440 dy = 63;
442 s->dx -= dx;
443 s->dy -= dy;
444 s->last_buttons_state = s->buttons_state;
446 dx &= 0x7f;
447 dy &= 0x7f;
449 if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
450 dy |= 0x80;
451 if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
452 dx |= 0x80;
454 obuf[0] = dy;
455 obuf[1] = dx;
456 return 2;
459 static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
460 const uint8_t *buf, int len)
462 MouseState *s = ADB_MOUSE(d);
463 int cmd, reg, olen;
465 if ((buf[0] & 0x0f) == ADB_FLUSH) {
466 /* flush mouse fifo */
467 s->buttons_state = s->last_buttons_state;
468 s->dx = 0;
469 s->dy = 0;
470 s->dz = 0;
471 return 0;
474 cmd = buf[0] & 0xc;
475 reg = buf[0] & 0x3;
476 olen = 0;
477 switch(cmd) {
478 case ADB_WRITEREG:
479 ADB_DPRINTF("write reg %d val 0x%2.2x\n", reg, buf[1]);
480 switch(reg) {
481 case 2:
482 break;
483 case 3:
484 switch(buf[2]) {
485 case ADB_CMD_SELF_TEST:
486 break;
487 case ADB_CMD_CHANGE_ID:
488 case ADB_CMD_CHANGE_ID_AND_ACT:
489 case ADB_CMD_CHANGE_ID_AND_ENABLE:
490 d->devaddr = buf[1] & 0xf;
491 break;
492 default:
493 /* XXX: check this */
494 d->devaddr = buf[1] & 0xf;
495 break;
498 break;
499 case ADB_READREG:
500 switch(reg) {
501 case 0:
502 olen = adb_mouse_poll(d, obuf);
503 break;
504 case 1:
505 break;
506 case 3:
507 obuf[0] = d->handler;
508 obuf[1] = d->devaddr;
509 olen = 2;
510 break;
512 ADB_DPRINTF("read reg %d obuf[0] 0x%2.2x obuf[1] 0x%2.2x\n", reg,
513 obuf[0], obuf[1]);
514 break;
516 return olen;
519 static void adb_mouse_reset(DeviceState *dev)
521 ADBDevice *d = ADB_DEVICE(dev);
522 MouseState *s = ADB_MOUSE(dev);
524 d->handler = 2;
525 d->devaddr = ADB_DEVID_MOUSE;
526 s->last_buttons_state = s->buttons_state = 0;
527 s->dx = s->dy = s->dz = 0;
530 static const VMStateDescription vmstate_adb_mouse = {
531 .name = "adb_mouse",
532 .version_id = 2,
533 .minimum_version_id = 2,
534 .fields = (VMStateField[]) {
535 VMSTATE_STRUCT(parent_obj, MouseState, 0, vmstate_adb_device,
536 ADBDevice),
537 VMSTATE_INT32(buttons_state, MouseState),
538 VMSTATE_INT32(last_buttons_state, MouseState),
539 VMSTATE_INT32(dx, MouseState),
540 VMSTATE_INT32(dy, MouseState),
541 VMSTATE_INT32(dz, MouseState),
542 VMSTATE_END_OF_LIST()
546 static void adb_mouse_realizefn(DeviceState *dev, Error **errp)
548 MouseState *s = ADB_MOUSE(dev);
549 ADBMouseClass *amc = ADB_MOUSE_GET_CLASS(dev);
551 amc->parent_realize(dev, errp);
553 qemu_add_mouse_event_handler(adb_mouse_event, s, 0, "QEMU ADB Mouse");
556 static void adb_mouse_initfn(Object *obj)
558 ADBDevice *d = ADB_DEVICE(obj);
560 d->devaddr = ADB_DEVID_MOUSE;
563 static void adb_mouse_class_init(ObjectClass *oc, void *data)
565 DeviceClass *dc = DEVICE_CLASS(oc);
566 ADBDeviceClass *adc = ADB_DEVICE_CLASS(oc);
567 ADBMouseClass *amc = ADB_MOUSE_CLASS(oc);
569 amc->parent_realize = dc->realize;
570 dc->realize = adb_mouse_realizefn;
571 set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
573 adc->devreq = adb_mouse_request;
574 dc->reset = adb_mouse_reset;
575 dc->vmsd = &vmstate_adb_mouse;
578 static const TypeInfo adb_mouse_type_info = {
579 .name = TYPE_ADB_MOUSE,
580 .parent = TYPE_ADB_DEVICE,
581 .instance_size = sizeof(MouseState),
582 .instance_init = adb_mouse_initfn,
583 .class_init = adb_mouse_class_init,
584 .class_size = sizeof(ADBMouseClass),
588 static void adb_register_types(void)
590 type_register_static(&adb_bus_type_info);
591 type_register_static(&adb_device_type_info);
592 type_register_static(&adb_kbd_type_info);
593 type_register_static(&adb_mouse_type_info);
596 type_init(adb_register_types)