]> git.proxmox.com Git - qemu.git/blame - hw/adb.c
Use glib memory allocation and free functions
[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
1f1f0600
JQ
264static const VMStateDescription vmstate_adb_kbd = {
265 .name = "adb_kbd",
266 .version_id = 1,
267 .minimum_version_id = 1,
268 .minimum_version_id_old = 1,
269 .fields = (VMStateField[]) {
270 VMSTATE_BUFFER(data, KBDState),
271 VMSTATE_INT32(rptr, KBDState),
272 VMSTATE_INT32(wptr, KBDState),
273 VMSTATE_INT32(count, KBDState),
274 VMSTATE_END_OF_LIST()
275 }
276};
9b64997f 277
3988e897
FB
278static int adb_kbd_reset(ADBDevice *d)
279{
280 KBDState *s = d->opaque;
281
282 d->handler = 1;
283 d->devaddr = ADB_KEYBOARD;
284 memset(s, 0, sizeof(KBDState));
285
286 return 0;
287}
288
267002cd
FB
289void adb_kbd_init(ADBBusState *bus)
290{
291 ADBDevice *d;
e2733d20 292 KBDState *s;
7267c094 293 s = g_malloc0(sizeof(KBDState));
3988e897
FB
294 d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request,
295 adb_kbd_reset, s);
267002cd 296 qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
1f1f0600 297 vmstate_register(NULL, -1, &vmstate_adb_kbd, s);
267002cd
FB
298}
299
300/***************************************************************/
301/* Mouse ADB device */
302
e2733d20
FB
303typedef struct MouseState {
304 int buttons_state, last_buttons_state;
305 int dx, dy, dz;
306} MouseState;
307
267002cd
FB
308static void adb_mouse_event(void *opaque,
309 int dx1, int dy1, int dz1, int buttons_state)
310{
311 ADBDevice *d = opaque;
e2733d20
FB
312 MouseState *s = d->opaque;
313
314 s->dx += dx1;
315 s->dy += dy1;
316 s->dz += dz1;
317 s->buttons_state = buttons_state;
318}
319
320
321static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
322{
323 MouseState *s = d->opaque;
267002cd
FB
324 int dx, dy;
325
e2733d20
FB
326 if (s->last_buttons_state == s->buttons_state &&
327 s->dx == 0 && s->dy == 0)
328 return 0;
3b46e624 329
e2733d20 330 dx = s->dx;
267002cd
FB
331 if (dx < -63)
332 dx = -63;
333 else if (dx > 63)
334 dx = 63;
3b46e624 335
e2733d20 336 dy = s->dy;
267002cd
FB
337 if (dy < -63)
338 dy = -63;
339 else if (dy > 63)
340 dy = 63;
3b46e624 341
e2733d20
FB
342 s->dx -= dx;
343 s->dy -= dy;
344 s->last_buttons_state = s->buttons_state;
3b46e624 345
267002cd
FB
346 dx &= 0x7f;
347 dy &= 0x7f;
3b46e624 348
bec9d989 349 if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
267002cd 350 dy |= 0x80;
bec9d989 351 if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
267002cd 352 dx |= 0x80;
3b46e624 353
bec9d989
FB
354 obuf[0] = dy;
355 obuf[1] = dx;
356 return 2;
267002cd
FB
357}
358
e2733d20
FB
359static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
360 const uint8_t *buf, int len)
267002cd 361{
bec9d989 362 MouseState *s = d->opaque;
e2733d20 363 int cmd, reg, olen;
3b46e624 364
bec9d989
FB
365 if ((buf[0] & 0x0f) == ADB_FLUSH) {
366 /* flush mouse fifo */
367 s->buttons_state = s->last_buttons_state;
368 s->dx = 0;
369 s->dy = 0;
370 s->dz = 0;
371 return 0;
e2733d20 372 }
267002cd
FB
373
374 cmd = buf[0] & 0xc;
375 reg = buf[0] & 0x3;
e2733d20 376 olen = 0;
267002cd
FB
377 switch(cmd) {
378 case ADB_WRITEREG:
ea026b2f 379 ADB_DPRINTF("write reg %d val 0x%2.2x\n", reg, buf[1]);
267002cd
FB
380 switch(reg) {
381 case 2:
267002cd
FB
382 break;
383 case 3:
384 switch(buf[2]) {
385 case ADB_CMD_SELF_TEST:
267002cd
FB
386 break;
387 case ADB_CMD_CHANGE_ID:
388 case ADB_CMD_CHANGE_ID_AND_ACT:
389 case ADB_CMD_CHANGE_ID_AND_ENABLE:
390 d->devaddr = buf[1] & 0xf;
267002cd
FB
391 break;
392 default:
393 /* XXX: check this */
394 d->devaddr = buf[1] & 0xf;
267002cd
FB
395 break;
396 }
397 }
398 break;
399 case ADB_READREG:
400 switch(reg) {
bec9d989
FB
401 case 0:
402 olen = adb_mouse_poll(d, obuf);
403 break;
267002cd 404 case 1:
267002cd
FB
405 break;
406 case 3:
e2733d20
FB
407 obuf[0] = d->handler;
408 obuf[1] = d->devaddr;
409 olen = 2;
267002cd
FB
410 break;
411 }
ea026b2f
BS
412 ADB_DPRINTF("read reg %d obuf[0] 0x%2.2x obuf[1] 0x%2.2x\n", reg,
413 obuf[0], obuf[1]);
267002cd
FB
414 break;
415 }
e2733d20 416 return olen;
267002cd
FB
417}
418
3988e897
FB
419static int adb_mouse_reset(ADBDevice *d)
420{
421 MouseState *s = d->opaque;
422
423 d->handler = 2;
424 d->devaddr = ADB_MOUSE;
425 memset(s, 0, sizeof(MouseState));
426
427 return 0;
428}
429
2b2cd592
JQ
430static const VMStateDescription vmstate_adb_mouse = {
431 .name = "adb_mouse",
432 .version_id = 1,
433 .minimum_version_id = 1,
434 .minimum_version_id_old = 1,
435 .fields = (VMStateField[]) {
436 VMSTATE_INT32(buttons_state, MouseState),
437 VMSTATE_INT32(last_buttons_state, MouseState),
438 VMSTATE_INT32(dx, MouseState),
439 VMSTATE_INT32(dy, MouseState),
440 VMSTATE_INT32(dz, MouseState),
441 VMSTATE_END_OF_LIST()
442 }
443};
9b64997f 444
267002cd
FB
445void adb_mouse_init(ADBBusState *bus)
446{
447 ADBDevice *d;
e2733d20 448 MouseState *s;
267002cd 449
7267c094 450 s = g_malloc0(sizeof(MouseState));
3988e897
FB
451 d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request,
452 adb_mouse_reset, s);
455204eb 453 qemu_add_mouse_event_handler(adb_mouse_event, d, 0, "QEMU ADB Mouse");
2b2cd592 454 vmstate_register(NULL, -1, &vmstate_adb_mouse, s);
267002cd 455}