ARMv7 support.
[qemu/mini2440.git] / hw / adb.c
blob1e43792b5a3ed718e47333b46459d712be032a0d
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 "vl.h"
26 /* ADB commands */
27 #define ADB_BUSRESET 0x00
28 #define ADB_FLUSH 0x01
29 #define ADB_WRITEREG 0x08
30 #define ADB_READREG 0x0c
32 /* ADB device commands */
33 #define ADB_CMD_SELF_TEST 0xff
34 #define ADB_CMD_CHANGE_ID 0xfe
35 #define ADB_CMD_CHANGE_ID_AND_ACT 0xfd
36 #define ADB_CMD_CHANGE_ID_AND_ENABLE 0x00
38 /* ADB default device IDs (upper 4 bits of ADB command byte) */
39 #define ADB_DONGLE 1
40 #define ADB_KEYBOARD 2
41 #define ADB_MOUSE 3
42 #define ADB_TABLET 4
43 #define ADB_MODEM 5
44 #define ADB_MISC 7
46 /* error codes */
47 #define ADB_RET_NOTPRESENT (-2)
49 int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
51 ADBDevice *d;
52 int devaddr, cmd, i;
54 cmd = buf[0] & 0xf;
55 if (cmd == ADB_BUSRESET) {
56 for(i = 0; i < s->nb_devices; i++) {
57 d = &s->devices[i];
58 if (d->devreset) {
59 d->devreset(d);
62 return 0;
64 devaddr = buf[0] >> 4;
65 for(i = 0; i < s->nb_devices; i++) {
66 d = &s->devices[i];
67 if (d->devaddr == devaddr) {
68 return d->devreq(d, obuf, buf, len);
71 return ADB_RET_NOTPRESENT;
74 /* XXX: move that to cuda ? */
75 int adb_poll(ADBBusState *s, uint8_t *obuf)
77 ADBDevice *d;
78 int olen, i;
79 uint8_t buf[1];
81 olen = 0;
82 for(i = 0; i < s->nb_devices; i++) {
83 if (s->poll_index >= s->nb_devices)
84 s->poll_index = 0;
85 d = &s->devices[s->poll_index];
86 buf[0] = ADB_READREG | (d->devaddr << 4);
87 olen = adb_request(s, obuf + 1, buf, 1);
88 /* if there is data, we poll again the same device */
89 if (olen > 0) {
90 obuf[0] = buf[0];
91 olen++;
92 break;
94 s->poll_index++;
96 return olen;
99 ADBDevice *adb_register_device(ADBBusState *s, int devaddr,
100 ADBDeviceRequest *devreq,
101 ADBDeviceReset *devreset,
102 void *opaque)
104 ADBDevice *d;
105 if (s->nb_devices >= MAX_ADB_DEVICES)
106 return NULL;
107 d = &s->devices[s->nb_devices++];
108 d->bus = s;
109 d->devaddr = devaddr;
110 d->devreq = devreq;
111 d->devreset = devreset;
112 d->opaque = opaque;
113 return d;
116 /***************************************************************/
117 /* Keyboard ADB device */
119 typedef struct KBDState {
120 uint8_t data[128];
121 int rptr, wptr, count;
122 } KBDState;
124 static const uint8_t pc_to_adb_keycode[256] = {
125 0, 53, 18, 19, 20, 21, 23, 22, 26, 28, 25, 29, 27, 24, 51, 48,
126 12, 13, 14, 15, 17, 16, 32, 34, 31, 35, 33, 30, 36, 54, 0, 1,
127 2, 3, 5, 4, 38, 40, 37, 41, 39, 50, 56, 42, 6, 7, 8, 9,
128 11, 45, 46, 43, 47, 44,123, 67, 58, 49, 57,122,120, 99,118, 96,
129 97, 98,100,101,109, 71,107, 89, 91, 92, 78, 86, 87, 88, 69, 83,
130 84, 85, 82, 65, 0, 0, 10,103,111, 0, 0,110, 81, 0, 0, 0,
131 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
132 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
133 0, 0, 0, 94, 0, 93, 0, 0, 0, 0, 0, 0,104,102, 0, 0,
134 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76,125, 0, 0,
135 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,105, 0, 0, 0, 0, 0,
136 0, 0, 0, 0, 0, 75, 0, 0,124, 0, 0, 0, 0, 0, 0, 0,
137 0, 0, 0, 0, 0, 0, 0,115, 62,116, 0, 59, 0, 60, 0,119,
138 61,121,114,117, 0, 0, 0, 0, 0, 0, 0, 55,126, 0,127, 0,
139 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
140 0, 0, 0, 0, 0, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
143 static void adb_kbd_put_keycode(void *opaque, int keycode)
145 ADBDevice *d = opaque;
146 KBDState *s = d->opaque;
148 if (s->count < sizeof(s->data)) {
149 s->data[s->wptr] = keycode;
150 if (++s->wptr == sizeof(s->data))
151 s->wptr = 0;
152 s->count++;
156 static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf)
158 static int ext_keycode;
159 KBDState *s = d->opaque;
160 int adb_keycode, keycode;
161 int olen;
163 olen = 0;
164 for(;;) {
165 if (s->count == 0)
166 break;
167 keycode = s->data[s->rptr];
168 if (++s->rptr == sizeof(s->data))
169 s->rptr = 0;
170 s->count--;
172 if (keycode == 0xe0) {
173 ext_keycode = 1;
174 } else {
175 if (ext_keycode)
176 adb_keycode = pc_to_adb_keycode[keycode | 0x80];
177 else
178 adb_keycode = pc_to_adb_keycode[keycode & 0x7f];
179 obuf[0] = adb_keycode | (keycode & 0x80);
180 /* NOTE: could put a second keycode if needed */
181 obuf[1] = 0xff;
182 olen = 2;
183 ext_keycode = 0;
184 break;
187 return olen;
190 static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
191 const uint8_t *buf, int len)
193 KBDState *s = d->opaque;
194 int cmd, reg, olen;
196 if ((buf[0] & 0x0f) == ADB_FLUSH) {
197 /* flush keyboard fifo */
198 s->wptr = s->rptr = s->count = 0;
199 return 0;
202 cmd = buf[0] & 0xc;
203 reg = buf[0] & 0x3;
204 olen = 0;
205 switch(cmd) {
206 case ADB_WRITEREG:
207 switch(reg) {
208 case 2:
209 /* LED status */
210 break;
211 case 3:
212 switch(buf[2]) {
213 case ADB_CMD_SELF_TEST:
214 break;
215 case ADB_CMD_CHANGE_ID:
216 case ADB_CMD_CHANGE_ID_AND_ACT:
217 case ADB_CMD_CHANGE_ID_AND_ENABLE:
218 d->devaddr = buf[1] & 0xf;
219 break;
220 default:
221 /* XXX: check this */
222 d->devaddr = buf[1] & 0xf;
223 d->handler = buf[2];
224 break;
227 break;
228 case ADB_READREG:
229 switch(reg) {
230 case 0:
231 olen = adb_kbd_poll(d, obuf);
232 break;
233 case 1:
234 break;
235 case 2:
236 obuf[0] = 0x00; /* XXX: check this */
237 obuf[1] = 0x07; /* led status */
238 olen = 2;
239 break;
240 case 3:
241 obuf[0] = d->handler;
242 obuf[1] = d->devaddr;
243 olen = 2;
244 break;
246 break;
248 return olen;
251 static int adb_kbd_reset(ADBDevice *d)
253 KBDState *s = d->opaque;
255 d->handler = 1;
256 d->devaddr = ADB_KEYBOARD;
257 memset(s, 0, sizeof(KBDState));
259 return 0;
262 void adb_kbd_init(ADBBusState *bus)
264 ADBDevice *d;
265 KBDState *s;
266 s = qemu_mallocz(sizeof(KBDState));
267 d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request,
268 adb_kbd_reset, s);
269 adb_kbd_reset(d);
270 qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
273 /***************************************************************/
274 /* Mouse ADB device */
276 typedef struct MouseState {
277 int buttons_state, last_buttons_state;
278 int dx, dy, dz;
279 } MouseState;
281 static void adb_mouse_event(void *opaque,
282 int dx1, int dy1, int dz1, int buttons_state)
284 ADBDevice *d = opaque;
285 MouseState *s = d->opaque;
287 s->dx += dx1;
288 s->dy += dy1;
289 s->dz += dz1;
290 s->buttons_state = buttons_state;
294 static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
296 MouseState *s = d->opaque;
297 int dx, dy;
299 if (s->last_buttons_state == s->buttons_state &&
300 s->dx == 0 && s->dy == 0)
301 return 0;
303 dx = s->dx;
304 if (dx < -63)
305 dx = -63;
306 else if (dx > 63)
307 dx = 63;
309 dy = s->dy;
310 if (dy < -63)
311 dy = -63;
312 else if (dy > 63)
313 dy = 63;
315 s->dx -= dx;
316 s->dy -= dy;
317 s->last_buttons_state = s->buttons_state;
319 dx &= 0x7f;
320 dy &= 0x7f;
322 if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
323 dy |= 0x80;
324 if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
325 dx |= 0x80;
327 obuf[0] = dy;
328 obuf[1] = dx;
329 return 2;
332 static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
333 const uint8_t *buf, int len)
335 MouseState *s = d->opaque;
336 int cmd, reg, olen;
338 if ((buf[0] & 0x0f) == ADB_FLUSH) {
339 /* flush mouse fifo */
340 s->buttons_state = s->last_buttons_state;
341 s->dx = 0;
342 s->dy = 0;
343 s->dz = 0;
344 return 0;
347 cmd = buf[0] & 0xc;
348 reg = buf[0] & 0x3;
349 olen = 0;
350 switch(cmd) {
351 case ADB_WRITEREG:
352 switch(reg) {
353 case 2:
354 break;
355 case 3:
356 switch(buf[2]) {
357 case ADB_CMD_SELF_TEST:
358 break;
359 case ADB_CMD_CHANGE_ID:
360 case ADB_CMD_CHANGE_ID_AND_ACT:
361 case ADB_CMD_CHANGE_ID_AND_ENABLE:
362 d->devaddr = buf[1] & 0xf;
363 break;
364 default:
365 /* XXX: check this */
366 d->devaddr = buf[1] & 0xf;
367 break;
370 break;
371 case ADB_READREG:
372 switch(reg) {
373 case 0:
374 olen = adb_mouse_poll(d, obuf);
375 break;
376 case 1:
377 break;
378 case 3:
379 obuf[0] = d->handler;
380 obuf[1] = d->devaddr;
381 olen = 2;
382 break;
384 break;
386 return olen;
389 static int adb_mouse_reset(ADBDevice *d)
391 MouseState *s = d->opaque;
393 d->handler = 2;
394 d->devaddr = ADB_MOUSE;
395 memset(s, 0, sizeof(MouseState));
397 return 0;
400 void adb_mouse_init(ADBBusState *bus)
402 ADBDevice *d;
403 MouseState *s;
405 s = qemu_mallocz(sizeof(MouseState));
406 d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request,
407 adb_mouse_reset, s);
408 adb_mouse_reset(d);
409 qemu_add_mouse_event_handler(adb_mouse_event, d, 0, "QEMU ADB Mouse");