blob: fd9052c16b04571b6198d42e07e28b91031abbeb [file] [log] [blame]
bellard267002c2004-06-03 18:46:20 +00001/*
2 * QEMU ADB support
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard267002c2004-06-03 18:46:20 +00004 * Copyright (c) 2004 Fabrice Bellard
ths5fafdf22007-09-16 21:08:06 +00005 *
bellard267002c2004-06-03 18:46:20 +00006 * 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 */
Paolo Bonzini83c9f4c2013-02-04 15:40:22 +010024#include "hw/hw.h"
25#include "hw/adb.h"
Paolo Bonzini28ecbae2012-11-28 12:06:30 +010026#include "ui/console.h"
bellard267002c2004-06-03 18:46:20 +000027
blueswir1ea026b22008-12-24 09:38:16 +000028/* debug ADB */
29//#define DEBUG_ADB
30
31#ifdef DEBUG_ADB
Blue Swirl001faf32009-05-13 17:53:17 +000032#define ADB_DPRINTF(fmt, ...) \
33do { printf("ADB: " fmt , ## __VA_ARGS__); } while (0)
blueswir1ea026b22008-12-24 09:38:16 +000034#else
Blue Swirl001faf32009-05-13 17:53:17 +000035#define ADB_DPRINTF(fmt, ...)
blueswir1ea026b22008-12-24 09:38:16 +000036#endif
37
bellard267002c2004-06-03 18:46:20 +000038/* 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) */
Andreas Färber2e4a7c92013-01-23 23:04:04 +000051#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
bellard267002c2004-06-03 18:46:20 +000057
bellardbec9d982004-07-12 20:15:26 +000058/* error codes */
59#define ADB_RET_NOTPRESENT (-2)
60
Andreas Färber2e4a7c92013-01-23 23:04:04 +000061static void adb_device_reset(ADBDevice *d)
62{
63 qdev_reset_all(DEVICE(d));
64}
65
bellarde2733d22004-06-21 22:46:10 +000066int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
bellard267002c2004-06-03 18:46:20 +000067{
68 ADBDevice *d;
69 int devaddr, cmd, i;
bellard267002c2004-06-03 18:46:20 +000070
bellard819e7122004-06-21 16:47:13 +000071 cmd = buf[0] & 0xf;
bellardbec9d982004-07-12 20:15:26 +000072 if (cmd == ADB_BUSRESET) {
73 for(i = 0; i < s->nb_devices; i++) {
Andreas Färber2e4a7c92013-01-23 23:04:04 +000074 d = s->devices[i];
75 adb_device_reset(d);
bellardbec9d982004-07-12 20:15:26 +000076 }
77 return 0;
78 }
bellard819e7122004-06-21 16:47:13 +000079 devaddr = buf[0] >> 4;
bellard267002c2004-06-03 18:46:20 +000080 for(i = 0; i < s->nb_devices; i++) {
Andreas Färber2e4a7c92013-01-23 23:04:04 +000081 d = s->devices[i];
bellard267002c2004-06-03 18:46:20 +000082 if (d->devaddr == devaddr) {
Andreas Färber2e4a7c92013-01-23 23:04:04 +000083 ADBDeviceClass *adc = ADB_DEVICE_GET_CLASS(d);
84 return adc->devreq(d, obuf, buf, len);
bellard267002c2004-06-03 18:46:20 +000085 }
86 }
bellardbec9d982004-07-12 20:15:26 +000087 return ADB_RET_NOTPRESENT;
bellarde2733d22004-06-21 22:46:10 +000088}
89
bellardbec9d982004-07-12 20:15:26 +000090/* XXX: move that to cuda ? */
bellarde2733d22004-06-21 22:46:10 +000091int adb_poll(ADBBusState *s, uint8_t *obuf)
92{
93 ADBDevice *d;
94 int olen, i;
bellardbec9d982004-07-12 20:15:26 +000095 uint8_t buf[1];
bellarde2733d22004-06-21 22:46:10 +000096
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;
Andreas Färber2e4a7c92013-01-23 23:04:04 +0000101 d = s->devices[s->poll_index];
bellardbec9d982004-07-12 20:15:26 +0000102 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++;
bellarde2733d22004-06-21 22:46:10 +0000108 break;
bellardbec9d982004-07-12 20:15:26 +0000109 }
110 s->poll_index++;
bellarde2733d22004-06-21 22:46:10 +0000111 }
112 return olen;
bellard267002c2004-06-03 18:46:20 +0000113}
114
Andreas Färber84ede322013-01-23 23:04:03 +0000115static const TypeInfo adb_bus_type_info = {
116 .name = TYPE_ADB_BUS,
117 .parent = TYPE_BUS,
118 .instance_size = sizeof(ADBBusState),
119};
120
Andreas Färber2e4a7c92013-01-23 23:04:04 +0000121static 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
bellard267002c2004-06-03 18:46:20 +0000149/***************************************************************/
150/* Keyboard ADB device */
151
Andreas Färber2e4a7c92013-01-23 23:04:04 +0000152#define ADB_KEYBOARD(obj) OBJECT_CHECK(KBDState, (obj), TYPE_ADB_KEYBOARD)
153
bellarde2733d22004-06-21 22:46:10 +0000154typedef struct KBDState {
Andreas Färber2e4a7c92013-01-23 23:04:04 +0000155 /*< private >*/
156 ADBDevice parent_obj;
157 /*< public >*/
158
bellarde2733d22004-06-21 22:46:10 +0000159 uint8_t data[128];
160 int rptr, wptr, count;
161} KBDState;
162
Andreas Färber2e4a7c92013-01-23 23:04:04 +0000163#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
bellard267002c2004-06-03 18:46:20 +0000176static 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,
bellarde2733d22004-06-21 22:46:10 +0000182 84, 85, 82, 65, 0, 0, 10,103,111, 0, 0,110, 81, 0, 0, 0,
bellard267002c2004-06-03 18:46:20 +0000183 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,
bellarde2733d22004-06-21 22:46:10 +0000185 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,
bellard267002c2004-06-03 18:46:20 +0000191 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
bellarde2733d22004-06-21 22:46:10 +0000192 0, 0, 0, 0, 0, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
bellard267002c2004-06-03 18:46:20 +0000193};
194
195static void adb_kbd_put_keycode(void *opaque, int keycode)
196{
Andreas Färber2e4a7c92013-01-23 23:04:04 +0000197 KBDState *s = opaque;
bellarde2733d22004-06-21 22:46:10 +0000198
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++;
bellard267002c2004-06-03 18:46:20 +0000204 }
205}
206
bellarde2733d22004-06-21 22:46:10 +0000207static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf)
bellard267002c2004-06-03 18:46:20 +0000208{
bellarde2733d22004-06-21 22:46:10 +0000209 static int ext_keycode;
Andreas Färber2e4a7c92013-01-23 23:04:04 +0000210 KBDState *s = ADB_KEYBOARD(d);
bellarde2733d22004-06-21 22:46:10 +0000211 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];
bellardbec9d982004-07-12 20:15:26 +0000230 obuf[0] = adb_keycode | (keycode & 0x80);
231 /* NOTE: could put a second keycode if needed */
232 obuf[1] = 0xff;
233 olen = 2;
bellarde2733d22004-06-21 22:46:10 +0000234 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{
Andreas Färber2e4a7c92013-01-23 23:04:04 +0000244 KBDState *s = ADB_KEYBOARD(d);
bellarde2733d22004-06-21 22:46:10 +0000245 int cmd, reg, olen;
246
bellardbec9d982004-07-12 20:15:26 +0000247 if ((buf[0] & 0x0f) == ADB_FLUSH) {
248 /* flush keyboard fifo */
249 s->wptr = s->rptr = s->count = 0;
250 return 0;
bellarde2733d22004-06-21 22:46:10 +0000251 }
bellard267002c2004-06-03 18:46:20 +0000252
253 cmd = buf[0] & 0xc;
254 reg = buf[0] & 0x3;
bellarde2733d22004-06-21 22:46:10 +0000255 olen = 0;
bellard267002c2004-06-03 18:46:20 +0000256 switch(cmd) {
257 case ADB_WRITEREG:
258 switch(reg) {
259 case 2:
260 /* LED status */
bellard267002c2004-06-03 18:46:20 +0000261 break;
262 case 3:
263 switch(buf[2]) {
264 case ADB_CMD_SELF_TEST:
bellard267002c2004-06-03 18:46:20 +0000265 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;
bellard267002c2004-06-03 18:46:20 +0000270 break;
271 default:
272 /* XXX: check this */
273 d->devaddr = buf[1] & 0xf;
274 d->handler = buf[2];
bellard267002c2004-06-03 18:46:20 +0000275 break;
276 }
277 }
278 break;
279 case ADB_READREG:
280 switch(reg) {
bellardbec9d982004-07-12 20:15:26 +0000281 case 0:
282 olen = adb_kbd_poll(d, obuf);
283 break;
bellard267002c2004-06-03 18:46:20 +0000284 case 1:
bellard267002c2004-06-03 18:46:20 +0000285 break;
286 case 2:
bellarde2733d22004-06-21 22:46:10 +0000287 obuf[0] = 0x00; /* XXX: check this */
288 obuf[1] = 0x07; /* led status */
289 olen = 2;
bellard267002c2004-06-03 18:46:20 +0000290 break;
291 case 3:
bellarde2733d22004-06-21 22:46:10 +0000292 obuf[0] = d->handler;
293 obuf[1] = d->devaddr;
294 olen = 2;
bellard267002c2004-06-03 18:46:20 +0000295 break;
296 }
297 break;
298 }
bellarde2733d22004-06-21 22:46:10 +0000299 return olen;
bellard267002c2004-06-03 18:46:20 +0000300}
301
Juan Quintela1f1f0602010-12-01 21:54:04 +0100302static const VMStateDescription vmstate_adb_kbd = {
303 .name = "adb_kbd",
304 .version_id = 1,
305 .minimum_version_id = 1,
306 .minimum_version_id_old = 1,
307 .fields = (VMStateField[]) {
308 VMSTATE_BUFFER(data, KBDState),
309 VMSTATE_INT32(rptr, KBDState),
310 VMSTATE_INT32(wptr, KBDState),
311 VMSTATE_INT32(count, KBDState),
312 VMSTATE_END_OF_LIST()
313 }
314};
blueswir19b649972008-12-30 19:01:19 +0000315
Andreas Färber2e4a7c92013-01-23 23:04:04 +0000316static void adb_kbd_reset(DeviceState *dev)
bellard3988e892005-02-15 22:58:51 +0000317{
Andreas Färber2e4a7c92013-01-23 23:04:04 +0000318 ADBDevice *d = ADB_DEVICE(dev);
319 KBDState *s = ADB_KEYBOARD(dev);
bellard3988e892005-02-15 22:58:51 +0000320
321 d->handler = 1;
Andreas Färber2e4a7c92013-01-23 23:04:04 +0000322 d->devaddr = ADB_DEVID_KEYBOARD;
323 memset(s->data, 0, sizeof(s->data));
324 s->rptr = 0;
325 s->wptr = 0;
326 s->count = 0;
bellard3988e892005-02-15 22:58:51 +0000327}
328
Andreas Färber2e4a7c92013-01-23 23:04:04 +0000329static void adb_kbd_realizefn(DeviceState *dev, Error **errp)
bellard267002c2004-06-03 18:46:20 +0000330{
Andreas Färber2e4a7c92013-01-23 23:04:04 +0000331 ADBDevice *d = ADB_DEVICE(dev);
332 ADBKeyboardClass *akc = ADB_KEYBOARD_GET_CLASS(dev);
333
334 akc->parent_realize(dev, errp);
335
bellard267002c2004-06-03 18:46:20 +0000336 qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
337}
338
Andreas Färber2e4a7c92013-01-23 23:04:04 +0000339static void adb_kbd_initfn(Object *obj)
340{
341 ADBDevice *d = ADB_DEVICE(obj);
342
343 d->devaddr = ADB_DEVID_KEYBOARD;
344}
345
346static void adb_kbd_class_init(ObjectClass *oc, void *data)
347{
348 DeviceClass *dc = DEVICE_CLASS(oc);
349 ADBDeviceClass *adc = ADB_DEVICE_CLASS(oc);
350 ADBKeyboardClass *akc = ADB_KEYBOARD_CLASS(oc);
351
352 akc->parent_realize = dc->realize;
353 dc->realize = adb_kbd_realizefn;
354
355 adc->devreq = adb_kbd_request;
356 dc->reset = adb_kbd_reset;
357 dc->vmsd = &vmstate_adb_kbd;
358}
359
360static const TypeInfo adb_kbd_type_info = {
361 .name = TYPE_ADB_KEYBOARD,
362 .parent = TYPE_ADB_DEVICE,
363 .instance_size = sizeof(KBDState),
364 .instance_init = adb_kbd_initfn,
365 .class_init = adb_kbd_class_init,
366 .class_size = sizeof(ADBKeyboardClass),
367};
368
bellard267002c2004-06-03 18:46:20 +0000369/***************************************************************/
370/* Mouse ADB device */
371
Andreas Färber2e4a7c92013-01-23 23:04:04 +0000372#define ADB_MOUSE(obj) OBJECT_CHECK(MouseState, (obj), TYPE_ADB_MOUSE)
373
bellarde2733d22004-06-21 22:46:10 +0000374typedef struct MouseState {
Andreas Färber2e4a7c92013-01-23 23:04:04 +0000375 /*< public >*/
376 ADBDevice parent_obj;
377 /*< private >*/
378
bellarde2733d22004-06-21 22:46:10 +0000379 int buttons_state, last_buttons_state;
380 int dx, dy, dz;
381} MouseState;
382
Andreas Färber2e4a7c92013-01-23 23:04:04 +0000383#define ADB_MOUSE_CLASS(class) \
384 OBJECT_CLASS_CHECK(ADBMouseClass, (class), TYPE_ADB_MOUSE)
385#define ADB_MOUSE_GET_CLASS(obj) \
386 OBJECT_GET_CLASS(ADBMouseClass, (obj), TYPE_ADB_MOUSE)
387
388typedef struct ADBMouseClass {
389 /*< public >*/
390 ADBDeviceClass parent_class;
391 /*< private >*/
392
393 DeviceRealize parent_realize;
394} ADBMouseClass;
395
bellard267002c2004-06-03 18:46:20 +0000396static void adb_mouse_event(void *opaque,
397 int dx1, int dy1, int dz1, int buttons_state)
398{
Andreas Färber2e4a7c92013-01-23 23:04:04 +0000399 MouseState *s = opaque;
bellarde2733d22004-06-21 22:46:10 +0000400
401 s->dx += dx1;
402 s->dy += dy1;
403 s->dz += dz1;
404 s->buttons_state = buttons_state;
405}
406
407
408static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
409{
Andreas Färber2e4a7c92013-01-23 23:04:04 +0000410 MouseState *s = ADB_MOUSE(d);
bellard267002c2004-06-03 18:46:20 +0000411 int dx, dy;
412
bellarde2733d22004-06-21 22:46:10 +0000413 if (s->last_buttons_state == s->buttons_state &&
414 s->dx == 0 && s->dy == 0)
415 return 0;
ths3b46e622007-09-17 08:09:54 +0000416
bellarde2733d22004-06-21 22:46:10 +0000417 dx = s->dx;
bellard267002c2004-06-03 18:46:20 +0000418 if (dx < -63)
419 dx = -63;
420 else if (dx > 63)
421 dx = 63;
ths3b46e622007-09-17 08:09:54 +0000422
bellarde2733d22004-06-21 22:46:10 +0000423 dy = s->dy;
bellard267002c2004-06-03 18:46:20 +0000424 if (dy < -63)
425 dy = -63;
426 else if (dy > 63)
427 dy = 63;
ths3b46e622007-09-17 08:09:54 +0000428
bellarde2733d22004-06-21 22:46:10 +0000429 s->dx -= dx;
430 s->dy -= dy;
431 s->last_buttons_state = s->buttons_state;
ths3b46e622007-09-17 08:09:54 +0000432
bellard267002c2004-06-03 18:46:20 +0000433 dx &= 0x7f;
434 dy &= 0x7f;
ths3b46e622007-09-17 08:09:54 +0000435
bellardbec9d982004-07-12 20:15:26 +0000436 if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
bellard267002c2004-06-03 18:46:20 +0000437 dy |= 0x80;
bellardbec9d982004-07-12 20:15:26 +0000438 if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
bellard267002c2004-06-03 18:46:20 +0000439 dx |= 0x80;
ths3b46e622007-09-17 08:09:54 +0000440
bellardbec9d982004-07-12 20:15:26 +0000441 obuf[0] = dy;
442 obuf[1] = dx;
443 return 2;
bellard267002c2004-06-03 18:46:20 +0000444}
445
bellarde2733d22004-06-21 22:46:10 +0000446static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
447 const uint8_t *buf, int len)
bellard267002c2004-06-03 18:46:20 +0000448{
Andreas Färber2e4a7c92013-01-23 23:04:04 +0000449 MouseState *s = ADB_MOUSE(d);
bellarde2733d22004-06-21 22:46:10 +0000450 int cmd, reg, olen;
ths3b46e622007-09-17 08:09:54 +0000451
bellardbec9d982004-07-12 20:15:26 +0000452 if ((buf[0] & 0x0f) == ADB_FLUSH) {
453 /* flush mouse fifo */
454 s->buttons_state = s->last_buttons_state;
455 s->dx = 0;
456 s->dy = 0;
457 s->dz = 0;
458 return 0;
bellarde2733d22004-06-21 22:46:10 +0000459 }
bellard267002c2004-06-03 18:46:20 +0000460
461 cmd = buf[0] & 0xc;
462 reg = buf[0] & 0x3;
bellarde2733d22004-06-21 22:46:10 +0000463 olen = 0;
bellard267002c2004-06-03 18:46:20 +0000464 switch(cmd) {
465 case ADB_WRITEREG:
blueswir1ea026b22008-12-24 09:38:16 +0000466 ADB_DPRINTF("write reg %d val 0x%2.2x\n", reg, buf[1]);
bellard267002c2004-06-03 18:46:20 +0000467 switch(reg) {
468 case 2:
bellard267002c2004-06-03 18:46:20 +0000469 break;
470 case 3:
471 switch(buf[2]) {
472 case ADB_CMD_SELF_TEST:
bellard267002c2004-06-03 18:46:20 +0000473 break;
474 case ADB_CMD_CHANGE_ID:
475 case ADB_CMD_CHANGE_ID_AND_ACT:
476 case ADB_CMD_CHANGE_ID_AND_ENABLE:
477 d->devaddr = buf[1] & 0xf;
bellard267002c2004-06-03 18:46:20 +0000478 break;
479 default:
480 /* XXX: check this */
481 d->devaddr = buf[1] & 0xf;
bellard267002c2004-06-03 18:46:20 +0000482 break;
483 }
484 }
485 break;
486 case ADB_READREG:
487 switch(reg) {
bellardbec9d982004-07-12 20:15:26 +0000488 case 0:
489 olen = adb_mouse_poll(d, obuf);
490 break;
bellard267002c2004-06-03 18:46:20 +0000491 case 1:
bellard267002c2004-06-03 18:46:20 +0000492 break;
493 case 3:
bellarde2733d22004-06-21 22:46:10 +0000494 obuf[0] = d->handler;
495 obuf[1] = d->devaddr;
496 olen = 2;
bellard267002c2004-06-03 18:46:20 +0000497 break;
498 }
blueswir1ea026b22008-12-24 09:38:16 +0000499 ADB_DPRINTF("read reg %d obuf[0] 0x%2.2x obuf[1] 0x%2.2x\n", reg,
500 obuf[0], obuf[1]);
bellard267002c2004-06-03 18:46:20 +0000501 break;
502 }
bellarde2733d22004-06-21 22:46:10 +0000503 return olen;
bellard267002c2004-06-03 18:46:20 +0000504}
505
Andreas Färber2e4a7c92013-01-23 23:04:04 +0000506static void adb_mouse_reset(DeviceState *dev)
bellard3988e892005-02-15 22:58:51 +0000507{
Andreas Färber2e4a7c92013-01-23 23:04:04 +0000508 ADBDevice *d = ADB_DEVICE(dev);
509 MouseState *s = ADB_MOUSE(dev);
bellard3988e892005-02-15 22:58:51 +0000510
511 d->handler = 2;
Andreas Färber2e4a7c92013-01-23 23:04:04 +0000512 d->devaddr = ADB_DEVID_MOUSE;
513 s->last_buttons_state = s->buttons_state = 0;
514 s->dx = s->dy = s->dz = 0;
bellard3988e892005-02-15 22:58:51 +0000515}
516
Juan Quintela2b2cd592010-12-01 21:56:35 +0100517static const VMStateDescription vmstate_adb_mouse = {
518 .name = "adb_mouse",
519 .version_id = 1,
520 .minimum_version_id = 1,
521 .minimum_version_id_old = 1,
522 .fields = (VMStateField[]) {
523 VMSTATE_INT32(buttons_state, MouseState),
524 VMSTATE_INT32(last_buttons_state, MouseState),
525 VMSTATE_INT32(dx, MouseState),
526 VMSTATE_INT32(dy, MouseState),
527 VMSTATE_INT32(dz, MouseState),
528 VMSTATE_END_OF_LIST()
529 }
530};
blueswir19b649972008-12-30 19:01:19 +0000531
Andreas Färber2e4a7c92013-01-23 23:04:04 +0000532static void adb_mouse_realizefn(DeviceState *dev, Error **errp)
bellard267002c2004-06-03 18:46:20 +0000533{
Andreas Färber2e4a7c92013-01-23 23:04:04 +0000534 MouseState *s = ADB_MOUSE(dev);
535 ADBMouseClass *amc = ADB_MOUSE_GET_CLASS(dev);
bellard267002c2004-06-03 18:46:20 +0000536
Andreas Färber2e4a7c92013-01-23 23:04:04 +0000537 amc->parent_realize(dev, errp);
538
539 qemu_add_mouse_event_handler(adb_mouse_event, s, 0, "QEMU ADB Mouse");
bellard267002c2004-06-03 18:46:20 +0000540}
Andreas Färber84ede322013-01-23 23:04:03 +0000541
Andreas Färber2e4a7c92013-01-23 23:04:04 +0000542static void adb_mouse_initfn(Object *obj)
543{
544 ADBDevice *d = ADB_DEVICE(obj);
545
546 d->devaddr = ADB_DEVID_MOUSE;
547}
548
549static void adb_mouse_class_init(ObjectClass *oc, void *data)
550{
551 DeviceClass *dc = DEVICE_CLASS(oc);
552 ADBDeviceClass *adc = ADB_DEVICE_CLASS(oc);
553 ADBMouseClass *amc = ADB_MOUSE_CLASS(oc);
554
555 amc->parent_realize = dc->realize;
556 dc->realize = adb_mouse_realizefn;
557
558 adc->devreq = adb_mouse_request;
559 dc->reset = adb_mouse_reset;
560 dc->vmsd = &vmstate_adb_mouse;
561}
562
563static const TypeInfo adb_mouse_type_info = {
564 .name = TYPE_ADB_MOUSE,
565 .parent = TYPE_ADB_DEVICE,
566 .instance_size = sizeof(MouseState),
567 .instance_init = adb_mouse_initfn,
568 .class_init = adb_mouse_class_init,
569 .class_size = sizeof(ADBMouseClass),
570};
571
Andreas Färber84ede322013-01-23 23:04:03 +0000572
573static void adb_register_types(void)
574{
575 type_register_static(&adb_bus_type_info);
Andreas Färber2e4a7c92013-01-23 23:04:04 +0000576 type_register_static(&adb_device_type_info);
577 type_register_static(&adb_kbd_type_info);
578 type_register_static(&adb_mouse_type_info);
Andreas Färber84ede322013-01-23 23:04:03 +0000579}
580
581type_init(adb_register_types)