]> git.ipfire.org Git - thirdparty/qemu.git/blame - hw/adb.c
find -type f | xargs sed -i 's/[\t ]$//g' # on most files
[thirdparty/qemu.git] / hw / 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 */
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
bec9d989
FB
46/* error codes */
47#define ADB_RET_NOTPRESENT (-2)
48
e2733d20 49int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
267002cd
FB
50{
51 ADBDevice *d;
52 int devaddr, cmd, i;
267002cd 53
819e712b 54 cmd = buf[0] & 0xf;
bec9d989
FB
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;
267002cd 63 }
bec9d989 64 devaddr = buf[0] >> 4;
267002cd
FB
65 for(i = 0; i < s->nb_devices; i++) {
66 d = &s->devices[i];
67 if (d->devaddr == devaddr) {
e2733d20 68 return d->devreq(d, obuf, buf, len);
267002cd
FB
69 }
70 }
bec9d989 71 return ADB_RET_NOTPRESENT;
e2733d20
FB
72}
73
bec9d989 74/* XXX: move that to cuda ? */
e2733d20
FB
75int adb_poll(ADBBusState *s, uint8_t *obuf)
76{
77 ADBDevice *d;
78 int olen, i;
bec9d989 79 uint8_t buf[1];
e2733d20
FB
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];
bec9d989
FB
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++;
e2733d20 92 break;
bec9d989
FB
93 }
94 s->poll_index++;
e2733d20
FB
95 }
96 return olen;
267002cd
FB
97}
98
5fafdf24
TS
99ADBDevice *adb_register_device(ADBBusState *s, int devaddr,
100 ADBDeviceRequest *devreq,
101 ADBDeviceReset *devreset,
267002cd
FB
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;
e2733d20 110 d->devreq = devreq;
bec9d989 111 d->devreset = devreset;
267002cd
FB
112 d->opaque = opaque;
113 return d;
114}
115
116/***************************************************************/
117/* Keyboard ADB device */
118
e2733d20
FB
119typedef struct KBDState {
120 uint8_t data[128];
121 int rptr, wptr, count;
122} KBDState;
123
267002cd
FB
124static 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,
e2733d20 130 84, 85, 82, 65, 0, 0, 10,103,111, 0, 0,110, 81, 0, 0, 0,
267002cd
FB
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,
e2733d20
FB
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,
267002cd 139 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
e2733d20 140 0, 0, 0, 0, 0, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
267002cd
FB
141};
142
143static void adb_kbd_put_keycode(void *opaque, int keycode)
144{
267002cd 145 ADBDevice *d = opaque;
e2733d20
FB
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++;
267002cd
FB
153 }
154}
155
e2733d20 156static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf)
267002cd 157{
e2733d20
FB
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];
bec9d989
FB
179 obuf[0] = adb_keycode | (keycode & 0x80);
180 /* NOTE: could put a second keycode if needed */
181 obuf[1] = 0xff;
182 olen = 2;
e2733d20
FB
183 ext_keycode = 0;
184 break;
185 }
186 }
187 return olen;
188}
189
190static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
191 const uint8_t *buf, int len)
192{
bec9d989 193 KBDState *s = d->opaque;
e2733d20
FB
194 int cmd, reg, olen;
195
bec9d989
FB
196 if ((buf[0] & 0x0f) == ADB_FLUSH) {
197 /* flush keyboard fifo */
198 s->wptr = s->rptr = s->count = 0;
199 return 0;
e2733d20 200 }
267002cd
FB
201
202 cmd = buf[0] & 0xc;
203 reg = buf[0] & 0x3;
e2733d20 204 olen = 0;
267002cd
FB
205 switch(cmd) {
206 case ADB_WRITEREG:
207 switch(reg) {
208 case 2:
209 /* LED status */
267002cd
FB
210 break;
211 case 3:
212 switch(buf[2]) {
213 case ADB_CMD_SELF_TEST:
267002cd
FB
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;
267002cd
FB
219 break;
220 default:
221 /* XXX: check this */
222 d->devaddr = buf[1] & 0xf;
223 d->handler = buf[2];
267002cd
FB
224 break;
225 }
226 }
227 break;
228 case ADB_READREG:
229 switch(reg) {
bec9d989
FB
230 case 0:
231 olen = adb_kbd_poll(d, obuf);
232 break;
267002cd 233 case 1:
267002cd
FB
234 break;
235 case 2:
e2733d20
FB
236 obuf[0] = 0x00; /* XXX: check this */
237 obuf[1] = 0x07; /* led status */
238 olen = 2;
267002cd
FB
239 break;
240 case 3:
e2733d20
FB
241 obuf[0] = d->handler;
242 obuf[1] = d->devaddr;
243 olen = 2;
267002cd
FB
244 break;
245 }
246 break;
247 }
e2733d20 248 return olen;
267002cd
FB
249}
250
3988e897
FB
251static 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
267002cd
FB
262void adb_kbd_init(ADBBusState *bus)
263{
264 ADBDevice *d;
e2733d20
FB
265 KBDState *s;
266 s = qemu_mallocz(sizeof(KBDState));
3988e897
FB
267 d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request,
268 adb_kbd_reset, s);
269 adb_kbd_reset(d);
267002cd
FB
270 qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
271}
272
273/***************************************************************/
274/* Mouse ADB device */
275
e2733d20
FB
276typedef struct MouseState {
277 int buttons_state, last_buttons_state;
278 int dx, dy, dz;
279} MouseState;
280
267002cd
FB
281static void adb_mouse_event(void *opaque,
282 int dx1, int dy1, int dz1, int buttons_state)
283{
284 ADBDevice *d = opaque;
e2733d20
FB
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
294static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
295{
296 MouseState *s = d->opaque;
267002cd
FB
297 int dx, dy;
298
e2733d20
FB
299 if (s->last_buttons_state == s->buttons_state &&
300 s->dx == 0 && s->dy == 0)
301 return 0;
5fafdf24 302
e2733d20 303 dx = s->dx;
267002cd
FB
304 if (dx < -63)
305 dx = -63;
306 else if (dx > 63)
307 dx = 63;
5fafdf24 308
e2733d20 309 dy = s->dy;
267002cd
FB
310 if (dy < -63)
311 dy = -63;
312 else if (dy > 63)
313 dy = 63;
5fafdf24 314
e2733d20
FB
315 s->dx -= dx;
316 s->dy -= dy;
317 s->last_buttons_state = s->buttons_state;
5fafdf24 318
267002cd
FB
319 dx &= 0x7f;
320 dy &= 0x7f;
5fafdf24 321
bec9d989 322 if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
267002cd 323 dy |= 0x80;
bec9d989 324 if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
267002cd 325 dx |= 0x80;
5fafdf24 326
bec9d989
FB
327 obuf[0] = dy;
328 obuf[1] = dx;
329 return 2;
267002cd
FB
330}
331
e2733d20
FB
332static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
333 const uint8_t *buf, int len)
267002cd 334{
bec9d989 335 MouseState *s = d->opaque;
e2733d20 336 int cmd, reg, olen;
5fafdf24 337
bec9d989
FB
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;
e2733d20 345 }
267002cd
FB
346
347 cmd = buf[0] & 0xc;
348 reg = buf[0] & 0x3;
e2733d20 349 olen = 0;
267002cd
FB
350 switch(cmd) {
351 case ADB_WRITEREG:
352 switch(reg) {
353 case 2:
267002cd
FB
354 break;
355 case 3:
356 switch(buf[2]) {
357 case ADB_CMD_SELF_TEST:
267002cd
FB
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;
267002cd
FB
363 break;
364 default:
365 /* XXX: check this */
366 d->devaddr = buf[1] & 0xf;
267002cd
FB
367 break;
368 }
369 }
370 break;
371 case ADB_READREG:
372 switch(reg) {
bec9d989
FB
373 case 0:
374 olen = adb_mouse_poll(d, obuf);
375 break;
267002cd 376 case 1:
267002cd
FB
377 break;
378 case 3:
e2733d20
FB
379 obuf[0] = d->handler;
380 obuf[1] = d->devaddr;
381 olen = 2;
267002cd
FB
382 break;
383 }
384 break;
385 }
e2733d20 386 return olen;
267002cd
FB
387}
388
3988e897
FB
389static 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
267002cd
FB
400void adb_mouse_init(ADBBusState *bus)
401{
402 ADBDevice *d;
e2733d20 403 MouseState *s;
267002cd 404
e2733d20 405 s = qemu_mallocz(sizeof(MouseState));
3988e897
FB
406 d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request,
407 adb_mouse_reset, s);
408 adb_mouse_reset(d);
455204eb 409 qemu_add_mouse_event_handler(adb_mouse_event, d, 0, "QEMU ADB Mouse");
267002cd 410}