]> git.proxmox.com Git - qemu.git/blame - hw/adb.c
tcg-sparc: Use TCG_TARGET_REG_BITS in conditional compilation.
[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 */
87ecb68b
PB
24#include "hw.h"
25#include "ppc_mac.h"
26#include "console.h"
267002cd 27
ea026b2f
BS
28/* debug ADB */
29//#define DEBUG_ADB
30
31#ifdef DEBUG_ADB
001faf32
BS
32#define ADB_DPRINTF(fmt, ...) \
33do { printf("ADB: " fmt , ## __VA_ARGS__); } while (0)
ea026b2f 34#else
001faf32 35#define ADB_DPRINTF(fmt, ...)
ea026b2f
BS
36#endif
37
267002cd
FB
38/* 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) */
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
57
bec9d989
FB
58/* error codes */
59#define ADB_RET_NOTPRESENT (-2)
60
e2733d20 61int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
267002cd
FB
62{
63 ADBDevice *d;
64 int devaddr, cmd, i;
267002cd 65
819e712b 66 cmd = buf[0] & 0xf;
bec9d989
FB
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);
72 }
73 }
74 return 0;
267002cd 75 }
bec9d989 76 devaddr = buf[0] >> 4;
267002cd
FB
77 for(i = 0; i < s->nb_devices; i++) {
78 d = &s->devices[i];
79 if (d->devaddr == devaddr) {
e2733d20 80 return d->devreq(d, obuf, buf, len);
267002cd
FB
81 }
82 }
bec9d989 83 return ADB_RET_NOTPRESENT;
e2733d20
FB
84}
85
bec9d989 86/* XXX: move that to cuda ? */
e2733d20
FB
87int adb_poll(ADBBusState *s, uint8_t *obuf)
88{
89 ADBDevice *d;
90 int olen, i;
bec9d989 91 uint8_t buf[1];
e2733d20
FB
92
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];
bec9d989
FB
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++;
e2733d20 104 break;
bec9d989
FB
105 }
106 s->poll_index++;
e2733d20
FB
107 }
108 return olen;
267002cd
FB
109}
110
5fafdf24
TS
111ADBDevice *adb_register_device(ADBBusState *s, int devaddr,
112 ADBDeviceRequest *devreq,
113 ADBDeviceReset *devreset,
267002cd
FB
114 void *opaque)
115{
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;
e2733d20 122 d->devreq = devreq;
bec9d989 123 d->devreset = devreset;
267002cd 124 d->opaque = opaque;
a08d4367 125 qemu_register_reset((QEMUResetHandler *)devreset, d);
267002cd
FB
126 return d;
127}
128
129/***************************************************************/
130/* Keyboard ADB device */
131
e2733d20
FB
132typedef struct KBDState {
133 uint8_t data[128];
134 int rptr, wptr, count;
135} KBDState;
136
267002cd
FB
137static 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,
e2733d20 143 84, 85, 82, 65, 0, 0, 10,103,111, 0, 0,110, 81, 0, 0, 0,
267002cd
FB
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,
e2733d20
FB
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,
267002cd 152 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
e2733d20 153 0, 0, 0, 0, 0, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
267002cd
FB
154};
155
156static void adb_kbd_put_keycode(void *opaque, int keycode)
157{
267002cd 158 ADBDevice *d = opaque;
e2733d20
FB
159 KBDState *s = d->opaque;
160
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++;
267002cd
FB
166 }
167}
168
e2733d20 169static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf)
267002cd 170{
e2733d20
FB
171 static int ext_keycode;
172 KBDState *s = d->opaque;
173 int adb_keycode, keycode;
174 int olen;
175
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--;
184
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];
bec9d989
FB
192 obuf[0] = adb_keycode | (keycode & 0x80);
193 /* NOTE: could put a second keycode if needed */
194 obuf[1] = 0xff;
195 olen = 2;
e2733d20
FB
196 ext_keycode = 0;
197 break;
198 }
199 }
200 return olen;
201}
202
203static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
204 const uint8_t *buf, int len)
205{
bec9d989 206 KBDState *s = d->opaque;
e2733d20
FB
207 int cmd, reg, olen;
208
bec9d989
FB
209 if ((buf[0] & 0x0f) == ADB_FLUSH) {
210 /* flush keyboard fifo */
211 s->wptr = s->rptr = s->count = 0;
212 return 0;
e2733d20 213 }
267002cd
FB
214
215 cmd = buf[0] & 0xc;
216 reg = buf[0] & 0x3;
e2733d20 217 olen = 0;
267002cd
FB
218 switch(cmd) {
219 case ADB_WRITEREG:
220 switch(reg) {
221 case 2:
222 /* LED status */
267002cd
FB
223 break;
224 case 3:
225 switch(buf[2]) {
226 case ADB_CMD_SELF_TEST:
267002cd
FB
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;
267002cd
FB
232 break;
233 default:
234 /* XXX: check this */
235 d->devaddr = buf[1] & 0xf;
236 d->handler = buf[2];
267002cd
FB
237 break;
238 }
239 }
240 break;
241 case ADB_READREG:
242 switch(reg) {
bec9d989
FB
243 case 0:
244 olen = adb_kbd_poll(d, obuf);
245 break;
267002cd 246 case 1:
267002cd
FB
247 break;
248 case 2:
e2733d20
FB
249 obuf[0] = 0x00; /* XXX: check this */
250 obuf[1] = 0x07; /* led status */
251 olen = 2;
267002cd
FB
252 break;
253 case 3:
e2733d20
FB
254 obuf[0] = d->handler;
255 obuf[1] = d->devaddr;
256 olen = 2;
267002cd
FB
257 break;
258 }
259 break;
260 }
e2733d20 261 return olen;
267002cd
FB
262}
263
9b64997f
BS
264static void adb_kbd_save(QEMUFile *f, void *opaque)
265{
266 KBDState *s = (KBDState *)opaque;
267
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);
272}
273
274static int adb_kbd_load(QEMUFile *f, void *opaque, int version_id)
275{
276 KBDState *s = (KBDState *)opaque;
277
278 if (version_id != 1)
279 return -EINVAL;
280
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);
285
286 return 0;
287}
288
3988e897
FB
289static int adb_kbd_reset(ADBDevice *d)
290{
291 KBDState *s = d->opaque;
292
293 d->handler = 1;
294 d->devaddr = ADB_KEYBOARD;
295 memset(s, 0, sizeof(KBDState));
296
297 return 0;
298}
299
267002cd
FB
300void adb_kbd_init(ADBBusState *bus)
301{
302 ADBDevice *d;
e2733d20
FB
303 KBDState *s;
304 s = qemu_mallocz(sizeof(KBDState));
3988e897
FB
305 d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request,
306 adb_kbd_reset, s);
267002cd 307 qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
9b64997f
BS
308 register_savevm("adb_kbd", -1, 1, adb_kbd_save,
309 adb_kbd_load, s);
267002cd
FB
310}
311
312/***************************************************************/
313/* Mouse ADB device */
314
e2733d20
FB
315typedef struct MouseState {
316 int buttons_state, last_buttons_state;
317 int dx, dy, dz;
318} MouseState;
319
267002cd
FB
320static void adb_mouse_event(void *opaque,
321 int dx1, int dy1, int dz1, int buttons_state)
322{
323 ADBDevice *d = opaque;
e2733d20
FB
324 MouseState *s = d->opaque;
325
326 s->dx += dx1;
327 s->dy += dy1;
328 s->dz += dz1;
329 s->buttons_state = buttons_state;
330}
331
332
333static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
334{
335 MouseState *s = d->opaque;
267002cd
FB
336 int dx, dy;
337
e2733d20
FB
338 if (s->last_buttons_state == s->buttons_state &&
339 s->dx == 0 && s->dy == 0)
340 return 0;
3b46e624 341
e2733d20 342 dx = s->dx;
267002cd
FB
343 if (dx < -63)
344 dx = -63;
345 else if (dx > 63)
346 dx = 63;
3b46e624 347
e2733d20 348 dy = s->dy;
267002cd
FB
349 if (dy < -63)
350 dy = -63;
351 else if (dy > 63)
352 dy = 63;
3b46e624 353
e2733d20
FB
354 s->dx -= dx;
355 s->dy -= dy;
356 s->last_buttons_state = s->buttons_state;
3b46e624 357
267002cd
FB
358 dx &= 0x7f;
359 dy &= 0x7f;
3b46e624 360
bec9d989 361 if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
267002cd 362 dy |= 0x80;
bec9d989 363 if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
267002cd 364 dx |= 0x80;
3b46e624 365
bec9d989
FB
366 obuf[0] = dy;
367 obuf[1] = dx;
368 return 2;
267002cd
FB
369}
370
e2733d20
FB
371static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
372 const uint8_t *buf, int len)
267002cd 373{
bec9d989 374 MouseState *s = d->opaque;
e2733d20 375 int cmd, reg, olen;
3b46e624 376
bec9d989
FB
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;
e2733d20 384 }
267002cd
FB
385
386 cmd = buf[0] & 0xc;
387 reg = buf[0] & 0x3;
e2733d20 388 olen = 0;
267002cd
FB
389 switch(cmd) {
390 case ADB_WRITEREG:
ea026b2f 391 ADB_DPRINTF("write reg %d val 0x%2.2x\n", reg, buf[1]);
267002cd
FB
392 switch(reg) {
393 case 2:
267002cd
FB
394 break;
395 case 3:
396 switch(buf[2]) {
397 case ADB_CMD_SELF_TEST:
267002cd
FB
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;
267002cd
FB
403 break;
404 default:
405 /* XXX: check this */
406 d->devaddr = buf[1] & 0xf;
267002cd
FB
407 break;
408 }
409 }
410 break;
411 case ADB_READREG:
412 switch(reg) {
bec9d989
FB
413 case 0:
414 olen = adb_mouse_poll(d, obuf);
415 break;
267002cd 416 case 1:
267002cd
FB
417 break;
418 case 3:
e2733d20
FB
419 obuf[0] = d->handler;
420 obuf[1] = d->devaddr;
421 olen = 2;
267002cd
FB
422 break;
423 }
ea026b2f
BS
424 ADB_DPRINTF("read reg %d obuf[0] 0x%2.2x obuf[1] 0x%2.2x\n", reg,
425 obuf[0], obuf[1]);
267002cd
FB
426 break;
427 }
e2733d20 428 return olen;
267002cd
FB
429}
430
3988e897
FB
431static int adb_mouse_reset(ADBDevice *d)
432{
433 MouseState *s = d->opaque;
434
435 d->handler = 2;
436 d->devaddr = ADB_MOUSE;
437 memset(s, 0, sizeof(MouseState));
438
439 return 0;
440}
441
9b64997f
BS
442static void adb_mouse_save(QEMUFile *f, void *opaque)
443{
444 MouseState *s = (MouseState *)opaque;
445
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);
451}
452
453static int adb_mouse_load(QEMUFile *f, void *opaque, int version_id)
454{
455 MouseState *s = (MouseState *)opaque;
456
457 if (version_id != 1)
458 return -EINVAL;
459
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);
465
466 return 0;
467}
468
267002cd
FB
469void adb_mouse_init(ADBBusState *bus)
470{
471 ADBDevice *d;
e2733d20 472 MouseState *s;
267002cd 473
e2733d20 474 s = qemu_mallocz(sizeof(MouseState));
3988e897
FB
475 d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request,
476 adb_mouse_reset, s);
455204eb 477 qemu_add_mouse_event_handler(adb_mouse_event, d, 0, "QEMU ADB Mouse");
9b64997f
BS
478 register_savevm("adb_mouse", -1, 1, adb_mouse_save,
479 adb_mouse_load, s);
267002cd 480}