]> Git Repo - qemu.git/blame - hw/input/adb.c
hw: Fix qemu_allocate_irqs() leaks
[qemu.git] / hw / input / adb.c
CommitLineData
267002cd
FB
1/*
2 * QEMU ADB support
5fafdf24 3 *
267002cd 4 * Copyright (c) 2004 Fabrice Bellard
5fafdf24 5 *
267002cd
FB
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 */
83c9f4ca 24#include "hw/hw.h"
0d09e41a 25#include "hw/input/adb.h"
28ecbaee 26#include "ui/console.h"
267002cd 27
ea026b2f
BS
28/* debug ADB */
29//#define DEBUG_ADB
30
31#ifdef DEBUG_ADB
001faf32
BS
32#define ADB_DPRINTF(fmt, ...) \
33do { printf("ADB: " fmt , ## __VA_ARGS__); } while (0)
ea026b2f 34#else
001faf32 35#define ADB_DPRINTF(fmt, ...)
ea026b2f
BS
36#endif
37
267002cd
FB
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) */
2e4a7c9c
AF
51#define ADB_DEVID_DONGLE 1
52#define ADB_DEVID_KEYBOARD 2
53#define ADB_DEVID_MOUSE 3
54#define ADB_DEVID_TABLET 4
55#define ADB_DEVID_MODEM 5
56#define ADB_DEVID_MISC 7
267002cd 57
bec9d989
FB
58/* error codes */
59#define ADB_RET_NOTPRESENT (-2)
60
2e4a7c9c
AF
61static void adb_device_reset(ADBDevice *d)
62{
63 qdev_reset_all(DEVICE(d));
64}
65
e2733d20 66int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
267002cd
FB
67{
68 ADBDevice *d;
69 int devaddr, cmd, i;
267002cd 70
819e712b 71 cmd = buf[0] & 0xf;
bec9d989
FB
72 if (cmd == ADB_BUSRESET) {
73 for(i = 0; i < s->nb_devices; i++) {
2e4a7c9c
AF
74 d = s->devices[i];
75 adb_device_reset(d);
bec9d989
FB
76 }
77 return 0;
267002cd 78 }
bec9d989 79 devaddr = buf[0] >> 4;
267002cd 80 for(i = 0; i < s->nb_devices; i++) {
2e4a7c9c 81 d = s->devices[i];
267002cd 82 if (d->devaddr == devaddr) {
2e4a7c9c
AF
83 ADBDeviceClass *adc = ADB_DEVICE_GET_CLASS(d);
84 return adc->devreq(d, obuf, buf, len);
267002cd
FB
85 }
86 }
bec9d989 87 return ADB_RET_NOTPRESENT;
e2733d20
FB
88}
89
bec9d989 90/* XXX: move that to cuda ? */
e2733d20
FB
91int adb_poll(ADBBusState *s, uint8_t *obuf)
92{
93 ADBDevice *d;
94 int olen, i;
bec9d989 95 uint8_t buf[1];
e2733d20
FB
96
97 olen = 0;
98 for(i = 0; i < s->nb_devices; i++) {
99 if (s->poll_index >= s->nb_devices)
100 s->poll_index = 0;
2e4a7c9c 101 d = s->devices[s->poll_index];
bec9d989
FB
102 buf[0] = ADB_READREG | (d->devaddr << 4);
103 olen = adb_request(s, obuf + 1, buf, 1);
104 /* if there is data, we poll again the same device */
105 if (olen > 0) {
106 obuf[0] = buf[0];
107 olen++;
e2733d20 108 break;
bec9d989
FB
109 }
110 s->poll_index++;
e2733d20
FB
111 }
112 return olen;
267002cd
FB
113}
114
84ede329
AF
115static const TypeInfo adb_bus_type_info = {
116 .name = TYPE_ADB_BUS,
117 .parent = TYPE_BUS,
118 .instance_size = sizeof(ADBBusState),
119};
120
2e4a7c9c
AF
121static void adb_device_realizefn(DeviceState *dev, Error **errp)
122{
123 ADBDevice *d = ADB_DEVICE(dev);
124 ADBBusState *bus = ADB_BUS(qdev_get_parent_bus(dev));
125
126 if (bus->nb_devices >= MAX_ADB_DEVICES) {
127 return;
128 }
129
130 bus->devices[bus->nb_devices++] = d;
131}
132
133static void adb_device_class_init(ObjectClass *oc, void *data)
134{
135 DeviceClass *dc = DEVICE_CLASS(oc);
136
137 dc->realize = adb_device_realizefn;
138 dc->bus_type = TYPE_ADB_BUS;
139}
140
141static const TypeInfo adb_device_type_info = {
142 .name = TYPE_ADB_DEVICE,
143 .parent = TYPE_DEVICE,
144 .instance_size = sizeof(ADBDevice),
145 .abstract = true,
146 .class_init = adb_device_class_init,
147};
148
267002cd
FB
149/***************************************************************/
150/* Keyboard ADB device */
151
2e4a7c9c
AF
152#define ADB_KEYBOARD(obj) OBJECT_CHECK(KBDState, (obj), TYPE_ADB_KEYBOARD)
153
e2733d20 154typedef struct KBDState {
2e4a7c9c
AF
155 /*< private >*/
156 ADBDevice parent_obj;
157 /*< public >*/
158
e2733d20
FB
159 uint8_t data[128];
160 int rptr, wptr, count;
161} KBDState;
162
2e4a7c9c
AF
163#define ADB_KEYBOARD_CLASS(class) \
164 OBJECT_CLASS_CHECK(ADBKeyboardClass, (class), TYPE_ADB_KEYBOARD)
165#define ADB_KEYBOARD_GET_CLASS(obj) \
166 OBJECT_GET_CLASS(ADBKeyboardClass, (obj), TYPE_ADB_KEYBOARD)
167
168typedef struct ADBKeyboardClass {
169 /*< private >*/
170 ADBDeviceClass parent_class;
171 /*< public >*/
172
173 DeviceRealize parent_realize;
174} ADBKeyboardClass;
175
267002cd
FB
176static const uint8_t pc_to_adb_keycode[256] = {
177 0, 53, 18, 19, 20, 21, 23, 22, 26, 28, 25, 29, 27, 24, 51, 48,
178 12, 13, 14, 15, 17, 16, 32, 34, 31, 35, 33, 30, 36, 54, 0, 1,
179 2, 3, 5, 4, 38, 40, 37, 41, 39, 50, 56, 42, 6, 7, 8, 9,
180 11, 45, 46, 43, 47, 44,123, 67, 58, 49, 57,122,120, 99,118, 96,
181 97, 98,100,101,109, 71,107, 89, 91, 92, 78, 86, 87, 88, 69, 83,
e2733d20 182 84, 85, 82, 65, 0, 0, 10,103,111, 0, 0,110, 81, 0, 0, 0,
267002cd
FB
183 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
184 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
e2733d20
FB
185 0, 0, 0, 94, 0, 93, 0, 0, 0, 0, 0, 0,104,102, 0, 0,
186 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76,125, 0, 0,
187 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,105, 0, 0, 0, 0, 0,
188 0, 0, 0, 0, 0, 75, 0, 0,124, 0, 0, 0, 0, 0, 0, 0,
189 0, 0, 0, 0, 0, 0, 0,115, 62,116, 0, 59, 0, 60, 0,119,
190 61,121,114,117, 0, 0, 0, 0, 0, 0, 0, 55,126, 0,127, 0,
267002cd 191 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
e2733d20 192 0, 0, 0, 0, 0, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
267002cd
FB
193};
194
195static void adb_kbd_put_keycode(void *opaque, int keycode)
196{
2e4a7c9c 197 KBDState *s = opaque;
e2733d20
FB
198
199 if (s->count < sizeof(s->data)) {
200 s->data[s->wptr] = keycode;
201 if (++s->wptr == sizeof(s->data))
202 s->wptr = 0;
203 s->count++;
267002cd
FB
204 }
205}
206
e2733d20 207static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf)
267002cd 208{
e2733d20 209 static int ext_keycode;
2e4a7c9c 210 KBDState *s = ADB_KEYBOARD(d);
e2733d20
FB
211 int adb_keycode, keycode;
212 int olen;
213
214 olen = 0;
215 for(;;) {
216 if (s->count == 0)
217 break;
218 keycode = s->data[s->rptr];
219 if (++s->rptr == sizeof(s->data))
220 s->rptr = 0;
221 s->count--;
222
223 if (keycode == 0xe0) {
224 ext_keycode = 1;
225 } else {
226 if (ext_keycode)
227 adb_keycode = pc_to_adb_keycode[keycode | 0x80];
228 else
229 adb_keycode = pc_to_adb_keycode[keycode & 0x7f];
bec9d989
FB
230 obuf[0] = adb_keycode | (keycode & 0x80);
231 /* NOTE: could put a second keycode if needed */
232 obuf[1] = 0xff;
233 olen = 2;
e2733d20
FB
234 ext_keycode = 0;
235 break;
236 }
237 }
238 return olen;
239}
240
241static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
242 const uint8_t *buf, int len)
243{
2e4a7c9c 244 KBDState *s = ADB_KEYBOARD(d);
e2733d20
FB
245 int cmd, reg, olen;
246
bec9d989
FB
247 if ((buf[0] & 0x0f) == ADB_FLUSH) {
248 /* flush keyboard fifo */
249 s->wptr = s->rptr = s->count = 0;
250 return 0;
e2733d20 251 }
267002cd
FB
252
253 cmd = buf[0] & 0xc;
254 reg = buf[0] & 0x3;
e2733d20 255 olen = 0;
267002cd
FB
256 switch(cmd) {
257 case ADB_WRITEREG:
258 switch(reg) {
259 case 2:
260 /* LED status */
267002cd
FB
261 break;
262 case 3:
263 switch(buf[2]) {
264 case ADB_CMD_SELF_TEST:
267002cd
FB
265 break;
266 case ADB_CMD_CHANGE_ID:
267 case ADB_CMD_CHANGE_ID_AND_ACT:
268 case ADB_CMD_CHANGE_ID_AND_ENABLE:
269 d->devaddr = buf[1] & 0xf;
267002cd
FB
270 break;
271 default:
272 /* XXX: check this */
273 d->devaddr = buf[1] & 0xf;
274 d->handler = buf[2];
267002cd
FB
275 break;
276 }
277 }
278 break;
279 case ADB_READREG:
280 switch(reg) {
bec9d989
FB
281 case 0:
282 olen = adb_kbd_poll(d, obuf);
283 break;
267002cd 284 case 1:
267002cd
FB
285 break;
286 case 2:
e2733d20
FB
287 obuf[0] = 0x00; /* XXX: check this */
288 obuf[1] = 0x07; /* led status */
289 olen = 2;
267002cd
FB
290 break;
291 case 3:
e2733d20
FB
292 obuf[0] = d->handler;
293 obuf[1] = d->devaddr;
294 olen = 2;
267002cd
FB
295 break;
296 }
297 break;
298 }
e2733d20 299 return olen;
267002cd
FB
300}
301
1f1f0600
JQ
302static const VMStateDescription vmstate_adb_kbd = {
303 .name = "adb_kbd",
304 .version_id = 1,
305 .minimum_version_id = 1,
35d08458 306 .fields = (VMStateField[]) {
1f1f0600
JQ
307 VMSTATE_BUFFER(data, KBDState),
308 VMSTATE_INT32(rptr, KBDState),
309 VMSTATE_INT32(wptr, KBDState),
310 VMSTATE_INT32(count, KBDState),
311 VMSTATE_END_OF_LIST()
312 }
313};
9b64997f 314
2e4a7c9c 315static void adb_kbd_reset(DeviceState *dev)
3988e897 316{
2e4a7c9c
AF
317 ADBDevice *d = ADB_DEVICE(dev);
318 KBDState *s = ADB_KEYBOARD(dev);
3988e897
FB
319
320 d->handler = 1;
2e4a7c9c
AF
321 d->devaddr = ADB_DEVID_KEYBOARD;
322 memset(s->data, 0, sizeof(s->data));
323 s->rptr = 0;
324 s->wptr = 0;
325 s->count = 0;
3988e897
FB
326}
327
2e4a7c9c 328static void adb_kbd_realizefn(DeviceState *dev, Error **errp)
267002cd 329{
2e4a7c9c
AF
330 ADBDevice *d = ADB_DEVICE(dev);
331 ADBKeyboardClass *akc = ADB_KEYBOARD_GET_CLASS(dev);
332
333 akc->parent_realize(dev, errp);
334
267002cd
FB
335 qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
336}
337
2e4a7c9c
AF
338static void adb_kbd_initfn(Object *obj)
339{
340 ADBDevice *d = ADB_DEVICE(obj);
341
342 d->devaddr = ADB_DEVID_KEYBOARD;
343}
344
345static void adb_kbd_class_init(ObjectClass *oc, void *data)
346{
347 DeviceClass *dc = DEVICE_CLASS(oc);
348 ADBDeviceClass *adc = ADB_DEVICE_CLASS(oc);
349 ADBKeyboardClass *akc = ADB_KEYBOARD_CLASS(oc);
350
351 akc->parent_realize = dc->realize;
352 dc->realize = adb_kbd_realizefn;
353
354 adc->devreq = adb_kbd_request;
355 dc->reset = adb_kbd_reset;
356 dc->vmsd = &vmstate_adb_kbd;
357}
358
359static const TypeInfo adb_kbd_type_info = {
360 .name = TYPE_ADB_KEYBOARD,
361 .parent = TYPE_ADB_DEVICE,
362 .instance_size = sizeof(KBDState),
363 .instance_init = adb_kbd_initfn,
364 .class_init = adb_kbd_class_init,
365 .class_size = sizeof(ADBKeyboardClass),
366};
367
267002cd
FB
368/***************************************************************/
369/* Mouse ADB device */
370
2e4a7c9c
AF
371#define ADB_MOUSE(obj) OBJECT_CHECK(MouseState, (obj), TYPE_ADB_MOUSE)
372
e2733d20 373typedef struct MouseState {
2e4a7c9c
AF
374 /*< public >*/
375 ADBDevice parent_obj;
376 /*< private >*/
377
e2733d20
FB
378 int buttons_state, last_buttons_state;
379 int dx, dy, dz;
380} MouseState;
381
2e4a7c9c
AF
382#define ADB_MOUSE_CLASS(class) \
383 OBJECT_CLASS_CHECK(ADBMouseClass, (class), TYPE_ADB_MOUSE)
384#define ADB_MOUSE_GET_CLASS(obj) \
385 OBJECT_GET_CLASS(ADBMouseClass, (obj), TYPE_ADB_MOUSE)
386
387typedef struct ADBMouseClass {
388 /*< public >*/
389 ADBDeviceClass parent_class;
390 /*< private >*/
391
392 DeviceRealize parent_realize;
393} ADBMouseClass;
394
267002cd
FB
395static void adb_mouse_event(void *opaque,
396 int dx1, int dy1, int dz1, int buttons_state)
397{
2e4a7c9c 398 MouseState *s = opaque;
e2733d20
FB
399
400 s->dx += dx1;
401 s->dy += dy1;
402 s->dz += dz1;
403 s->buttons_state = buttons_state;
404}
405
406
407static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
408{
2e4a7c9c 409 MouseState *s = ADB_MOUSE(d);
267002cd
FB
410 int dx, dy;
411
e2733d20
FB
412 if (s->last_buttons_state == s->buttons_state &&
413 s->dx == 0 && s->dy == 0)
414 return 0;
3b46e624 415
e2733d20 416 dx = s->dx;
267002cd
FB
417 if (dx < -63)
418 dx = -63;
419 else if (dx > 63)
420 dx = 63;
3b46e624 421
e2733d20 422 dy = s->dy;
267002cd
FB
423 if (dy < -63)
424 dy = -63;
425 else if (dy > 63)
426 dy = 63;
3b46e624 427
e2733d20
FB
428 s->dx -= dx;
429 s->dy -= dy;
430 s->last_buttons_state = s->buttons_state;
3b46e624 431
267002cd
FB
432 dx &= 0x7f;
433 dy &= 0x7f;
3b46e624 434
bec9d989 435 if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
267002cd 436 dy |= 0x80;
bec9d989 437 if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
267002cd 438 dx |= 0x80;
3b46e624 439
bec9d989
FB
440 obuf[0] = dy;
441 obuf[1] = dx;
442 return 2;
267002cd
FB
443}
444
e2733d20
FB
445static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
446 const uint8_t *buf, int len)
267002cd 447{
2e4a7c9c 448 MouseState *s = ADB_MOUSE(d);
e2733d20 449 int cmd, reg, olen;
3b46e624 450
bec9d989
FB
451 if ((buf[0] & 0x0f) == ADB_FLUSH) {
452 /* flush mouse fifo */
453 s->buttons_state = s->last_buttons_state;
454 s->dx = 0;
455 s->dy = 0;
456 s->dz = 0;
457 return 0;
e2733d20 458 }
267002cd
FB
459
460 cmd = buf[0] & 0xc;
461 reg = buf[0] & 0x3;
e2733d20 462 olen = 0;
267002cd
FB
463 switch(cmd) {
464 case ADB_WRITEREG:
ea026b2f 465 ADB_DPRINTF("write reg %d val 0x%2.2x\n", reg, buf[1]);
267002cd
FB
466 switch(reg) {
467 case 2:
267002cd
FB
468 break;
469 case 3:
470 switch(buf[2]) {
471 case ADB_CMD_SELF_TEST:
267002cd
FB
472 break;
473 case ADB_CMD_CHANGE_ID:
474 case ADB_CMD_CHANGE_ID_AND_ACT:
475 case ADB_CMD_CHANGE_ID_AND_ENABLE:
476 d->devaddr = buf[1] & 0xf;
267002cd
FB
477 break;
478 default:
479 /* XXX: check this */
480 d->devaddr = buf[1] & 0xf;
267002cd
FB
481 break;
482 }
483 }
484 break;
485 case ADB_READREG:
486 switch(reg) {
bec9d989
FB
487 case 0:
488 olen = adb_mouse_poll(d, obuf);
489 break;
267002cd 490 case 1:
267002cd
FB
491 break;
492 case 3:
e2733d20
FB
493 obuf[0] = d->handler;
494 obuf[1] = d->devaddr;
495 olen = 2;
267002cd
FB
496 break;
497 }
ea026b2f
BS
498 ADB_DPRINTF("read reg %d obuf[0] 0x%2.2x obuf[1] 0x%2.2x\n", reg,
499 obuf[0], obuf[1]);
267002cd
FB
500 break;
501 }
e2733d20 502 return olen;
267002cd
FB
503}
504
2e4a7c9c 505static void adb_mouse_reset(DeviceState *dev)
3988e897 506{
2e4a7c9c
AF
507 ADBDevice *d = ADB_DEVICE(dev);
508 MouseState *s = ADB_MOUSE(dev);
3988e897
FB
509
510 d->handler = 2;
2e4a7c9c
AF
511 d->devaddr = ADB_DEVID_MOUSE;
512 s->last_buttons_state = s->buttons_state = 0;
513 s->dx = s->dy = s->dz = 0;
3988e897
FB
514}
515
2b2cd592
JQ
516static const VMStateDescription vmstate_adb_mouse = {
517 .name = "adb_mouse",
518 .version_id = 1,
519 .minimum_version_id = 1,
35d08458 520 .fields = (VMStateField[]) {
2b2cd592
JQ
521 VMSTATE_INT32(buttons_state, MouseState),
522 VMSTATE_INT32(last_buttons_state, MouseState),
523 VMSTATE_INT32(dx, MouseState),
524 VMSTATE_INT32(dy, MouseState),
525 VMSTATE_INT32(dz, MouseState),
526 VMSTATE_END_OF_LIST()
527 }
528};
9b64997f 529
2e4a7c9c 530static void adb_mouse_realizefn(DeviceState *dev, Error **errp)
267002cd 531{
2e4a7c9c
AF
532 MouseState *s = ADB_MOUSE(dev);
533 ADBMouseClass *amc = ADB_MOUSE_GET_CLASS(dev);
534
535 amc->parent_realize(dev, errp);
536
537 qemu_add_mouse_event_handler(adb_mouse_event, s, 0, "QEMU ADB Mouse");
538}
539
540static void adb_mouse_initfn(Object *obj)
541{
542 ADBDevice *d = ADB_DEVICE(obj);
267002cd 543
2e4a7c9c 544 d->devaddr = ADB_DEVID_MOUSE;
267002cd 545}
84ede329 546
2e4a7c9c
AF
547static void adb_mouse_class_init(ObjectClass *oc, void *data)
548{
549 DeviceClass *dc = DEVICE_CLASS(oc);
550 ADBDeviceClass *adc = ADB_DEVICE_CLASS(oc);
551 ADBMouseClass *amc = ADB_MOUSE_CLASS(oc);
552
553 amc->parent_realize = dc->realize;
554 dc->realize = adb_mouse_realizefn;
555
556 adc->devreq = adb_mouse_request;
557 dc->reset = adb_mouse_reset;
558 dc->vmsd = &vmstate_adb_mouse;
559}
560
561static const TypeInfo adb_mouse_type_info = {
562 .name = TYPE_ADB_MOUSE,
563 .parent = TYPE_ADB_DEVICE,
564 .instance_size = sizeof(MouseState),
565 .instance_init = adb_mouse_initfn,
566 .class_init = adb_mouse_class_init,
567 .class_size = sizeof(ADBMouseClass),
568};
569
84ede329
AF
570
571static void adb_register_types(void)
572{
573 type_register_static(&adb_bus_type_info);
2e4a7c9c
AF
574 type_register_static(&adb_device_type_info);
575 type_register_static(&adb_kbd_type_info);
576 type_register_static(&adb_mouse_type_info);
84ede329
AF
577}
578
579type_init(adb_register_types)
This page took 0.738423 seconds and 4 git commands to generate.