]> git.proxmox.com Git - mirror_qemu.git/blob - hw/adb.c
find -type f | xargs sed -i 's/[\t ]*$//g' # Yes, again. Note the star in the regex.
[mirror_qemu.git] / hw / adb.c
1 /*
2 * QEMU ADB support
3 *
4 * Copyright (c) 2004 Fabrice Bellard
5 *
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 */
24 #include "vl.h"
25
26 /* ADB commands */
27 #define ADB_BUSRESET 0x00
28 #define ADB_FLUSH 0x01
29 #define ADB_WRITEREG 0x08
30 #define ADB_READREG 0x0c
31
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
37
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
45
46 /* error codes */
47 #define ADB_RET_NOTPRESENT (-2)
48
49 int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
50 {
51 ADBDevice *d;
52 int devaddr, cmd, i;
53
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);
60 }
61 }
62 return 0;
63 }
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);
69 }
70 }
71 return ADB_RET_NOTPRESENT;
72 }
73
74 /* XXX: move that to cuda ? */
75 int adb_poll(ADBBusState *s, uint8_t *obuf)
76 {
77 ADBDevice *d;
78 int olen, i;
79 uint8_t buf[1];
80
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;
93 }
94 s->poll_index++;
95 }
96 return olen;
97 }
98
99 ADBDevice *adb_register_device(ADBBusState *s, int devaddr,
100 ADBDeviceRequest *devreq,
101 ADBDeviceReset *devreset,
102 void *opaque)
103 {
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;
114 }
115
116 /***************************************************************/
117 /* Keyboard ADB device */
118
119 typedef struct KBDState {
120 uint8_t data[128];
121 int rptr, wptr, count;
122 } KBDState;
123
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,
141 };
142
143 static void adb_kbd_put_keycode(void *opaque, int keycode)
144 {
145 ADBDevice *d = opaque;
146 KBDState *s = d->opaque;
147
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++;
153 }
154 }
155
156 static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf)
157 {
158 static int ext_keycode;
159 KBDState *s = d->opaque;
160 int adb_keycode, keycode;
161 int olen;
162
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--;
171
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;
185 }
186 }
187 return olen;
188 }
189
190 static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
191 const uint8_t *buf, int len)
192 {
193 KBDState *s = d->opaque;
194 int cmd, reg, olen;
195
196 if ((buf[0] & 0x0f) == ADB_FLUSH) {
197 /* flush keyboard fifo */
198 s->wptr = s->rptr = s->count = 0;
199 return 0;
200 }
201
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;
225 }
226 }
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;
245 }
246 break;
247 }
248 return olen;
249 }
250
251 static int adb_kbd_reset(ADBDevice *d)
252 {
253 KBDState *s = d->opaque;
254
255 d->handler = 1;
256 d->devaddr = ADB_KEYBOARD;
257 memset(s, 0, sizeof(KBDState));
258
259 return 0;
260 }
261
262 void adb_kbd_init(ADBBusState *bus)
263 {
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);
271 }
272
273 /***************************************************************/
274 /* Mouse ADB device */
275
276 typedef struct MouseState {
277 int buttons_state, last_buttons_state;
278 int dx, dy, dz;
279 } MouseState;
280
281 static void adb_mouse_event(void *opaque,
282 int dx1, int dy1, int dz1, int buttons_state)
283 {
284 ADBDevice *d = opaque;
285 MouseState *s = d->opaque;
286
287 s->dx += dx1;
288 s->dy += dy1;
289 s->dz += dz1;
290 s->buttons_state = buttons_state;
291 }
292
293
294 static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
295 {
296 MouseState *s = d->opaque;
297 int dx, dy;
298
299 if (s->last_buttons_state == s->buttons_state &&
300 s->dx == 0 && s->dy == 0)
301 return 0;
302
303 dx = s->dx;
304 if (dx < -63)
305 dx = -63;
306 else if (dx > 63)
307 dx = 63;
308
309 dy = s->dy;
310 if (dy < -63)
311 dy = -63;
312 else if (dy > 63)
313 dy = 63;
314
315 s->dx -= dx;
316 s->dy -= dy;
317 s->last_buttons_state = s->buttons_state;
318
319 dx &= 0x7f;
320 dy &= 0x7f;
321
322 if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
323 dy |= 0x80;
324 if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
325 dx |= 0x80;
326
327 obuf[0] = dy;
328 obuf[1] = dx;
329 return 2;
330 }
331
332 static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
333 const uint8_t *buf, int len)
334 {
335 MouseState *s = d->opaque;
336 int cmd, reg, olen;
337
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;
345 }
346
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;
368 }
369 }
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;
383 }
384 break;
385 }
386 return olen;
387 }
388
389 static int adb_mouse_reset(ADBDevice *d)
390 {
391 MouseState *s = d->opaque;
392
393 d->handler = 2;
394 d->devaddr = ADB_MOUSE;
395 memset(s, 0, sizeof(MouseState));
396
397 return 0;
398 }
399
400 void adb_mouse_init(ADBBusState *bus)
401 {
402 ADBDevice *d;
403 MouseState *s;
404
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");
410 }