Fix zero-length write(2).
[qemu/agraf.git] / hw / adb.c
blob4fb7a624178ec51c05a653eaf91ab1a8e2956322
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 "hw.h"
25 #include "ppc_mac.h"
26 #include "console.h"
28 /* debug ADB */
29 //#define DEBUG_ADB
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
38 /* ADB commands */
39 #define ADB_BUSRESET 0x00
40 #define ADB_FLUSH 0x01
41 #define ADB_WRITEREG 0x08
42 #define ADB_READREG 0x0c
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
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
58 /* error codes */
59 #define ADB_RET_NOTPRESENT (-2)
61 int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
63 ADBDevice *d;
64 int devaddr, cmd, i;
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);
74 return 0;
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);
83 return ADB_RET_NOTPRESENT;
86 /* XXX: move that to cuda ? */
87 int adb_poll(ADBBusState *s, uint8_t *obuf)
89 ADBDevice *d;
90 int olen, i;
91 uint8_t buf[1];
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;
106 s->poll_index++;
108 return olen;
111 ADBDevice *adb_register_device(ADBBusState *s, int devaddr,
112 ADBDeviceRequest *devreq,
113 ADBDeviceReset *devreset,
114 void *opaque)
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;
129 /***************************************************************/
130 /* Keyboard ADB device */
132 typedef struct KBDState {
133 uint8_t data[128];
134 int rptr, wptr, count;
135 } KBDState;
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,
156 static void adb_kbd_put_keycode(void *opaque, int keycode)
158 ADBDevice *d = opaque;
159 KBDState *s = d->opaque;
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++;
169 static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf)
171 static int ext_keycode;
172 KBDState *s = d->opaque;
173 int adb_keycode, keycode;
174 int olen;
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--;
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;
200 return olen;
203 static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
204 const uint8_t *buf, int len)
206 KBDState *s = d->opaque;
207 int cmd, reg, olen;
209 if ((buf[0] & 0x0f) == ADB_FLUSH) {
210 /* flush keyboard fifo */
211 s->wptr = s->rptr = s->count = 0;
212 return 0;
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;
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;
259 break;
261 return olen;
264 static void adb_kbd_save(QEMUFile *f, void *opaque)
266 KBDState *s = (KBDState *)opaque;
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);
274 static int adb_kbd_load(QEMUFile *f, void *opaque, int version_id)
276 KBDState *s = (KBDState *)opaque;
278 if (version_id != 1)
279 return -EINVAL;
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);
286 return 0;
289 static int adb_kbd_reset(ADBDevice *d)
291 KBDState *s = d->opaque;
293 d->handler = 1;
294 d->devaddr = ADB_KEYBOARD;
295 memset(s, 0, sizeof(KBDState));
297 return 0;
300 void adb_kbd_init(ADBBusState *bus)
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("adb_kbd", -1, 1, adb_kbd_save,
309 adb_kbd_load, s);
312 /***************************************************************/
313 /* Mouse ADB device */
315 typedef struct MouseState {
316 int buttons_state, last_buttons_state;
317 int dx, dy, dz;
318 } MouseState;
320 static void adb_mouse_event(void *opaque,
321 int dx1, int dy1, int dz1, int buttons_state)
323 ADBDevice *d = opaque;
324 MouseState *s = d->opaque;
326 s->dx += dx1;
327 s->dy += dy1;
328 s->dz += dz1;
329 s->buttons_state = buttons_state;
333 static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
335 MouseState *s = d->opaque;
336 int dx, dy;
338 if (s->last_buttons_state == s->buttons_state &&
339 s->dx == 0 && s->dy == 0)
340 return 0;
342 dx = s->dx;
343 if (dx < -63)
344 dx = -63;
345 else if (dx > 63)
346 dx = 63;
348 dy = s->dy;
349 if (dy < -63)
350 dy = -63;
351 else if (dy > 63)
352 dy = 63;
354 s->dx -= dx;
355 s->dy -= dy;
356 s->last_buttons_state = s->buttons_state;
358 dx &= 0x7f;
359 dy &= 0x7f;
361 if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
362 dy |= 0x80;
363 if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
364 dx |= 0x80;
366 obuf[0] = dy;
367 obuf[1] = dx;
368 return 2;
371 static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
372 const uint8_t *buf, int len)
374 MouseState *s = d->opaque;
375 int cmd, reg, olen;
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;
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;
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;
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;
428 return olen;
431 static int adb_mouse_reset(ADBDevice *d)
433 MouseState *s = d->opaque;
435 d->handler = 2;
436 d->devaddr = ADB_MOUSE;
437 memset(s, 0, sizeof(MouseState));
439 return 0;
442 static void adb_mouse_save(QEMUFile *f, void *opaque)
444 MouseState *s = (MouseState *)opaque;
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);
453 static int adb_mouse_load(QEMUFile *f, void *opaque, int version_id)
455 MouseState *s = (MouseState *)opaque;
457 if (version_id != 1)
458 return -EINVAL;
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);
466 return 0;
469 void adb_mouse_init(ADBBusState *bus)
471 ADBDevice *d;
472 MouseState *s;
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("adb_mouse", -1, 1, adb_mouse_save,
479 adb_mouse_load, s);