ia64/xen-unstable

view tools/ioemu/hw/adb.c @ 6946:e703abaf6e3d

Add behaviour to the remove methods to remove the transaction's path itself. This allows us to write Remove(path) to remove the specified path rather than having to slice the path ourselves.
author emellor@ewan
date Sun Sep 18 14:42:13 2005 +0100 (2005-09-18)
parents 8e5fc5fe636c
children f7b43e5c42b9
line source
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"
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)
50 {
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);
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 }
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];
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 }
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 }
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,
141 };
143 static void adb_kbd_put_keycode(void *opaque, int keycode)
144 {
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++;
153 }
154 }
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;
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;
185 }
186 }
187 return olen;
188 }
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;
196 if ((buf[0] & 0x0f) == ADB_FLUSH) {
197 /* flush keyboard fifo */
198 s->wptr = s->rptr = s->count = 0;
199 return 0;
200 }
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 }
251 void adb_kbd_init(ADBBusState *bus)
252 {
253 ADBDevice *d;
254 KBDState *s;
255 s = qemu_mallocz(sizeof(KBDState));
256 d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request, NULL, s);
257 d->handler = 1;
258 qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
259 }
261 /***************************************************************/
262 /* Mouse ADB device */
264 typedef struct MouseState {
265 int buttons_state, last_buttons_state;
266 int dx, dy, dz;
267 } MouseState;
269 static void adb_mouse_event(void *opaque,
270 int dx1, int dy1, int dz1, int buttons_state)
271 {
272 ADBDevice *d = opaque;
273 MouseState *s = d->opaque;
275 s->dx += dx1;
276 s->dy += dy1;
277 s->dz += dz1;
278 s->buttons_state = buttons_state;
279 }
282 static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
283 {
284 MouseState *s = d->opaque;
285 int dx, dy;
287 if (s->last_buttons_state == s->buttons_state &&
288 s->dx == 0 && s->dy == 0)
289 return 0;
291 dx = s->dx;
292 if (dx < -63)
293 dx = -63;
294 else if (dx > 63)
295 dx = 63;
297 dy = s->dy;
298 if (dy < -63)
299 dy = -63;
300 else if (dy > 63)
301 dy = 63;
303 s->dx -= dx;
304 s->dy -= dy;
305 s->last_buttons_state = s->buttons_state;
307 dx &= 0x7f;
308 dy &= 0x7f;
310 if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
311 dy |= 0x80;
312 if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
313 dx |= 0x80;
315 obuf[0] = dy;
316 obuf[1] = dx;
317 return 2;
318 }
320 static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
321 const uint8_t *buf, int len)
322 {
323 MouseState *s = d->opaque;
324 int cmd, reg, olen;
326 if ((buf[0] & 0x0f) == ADB_FLUSH) {
327 /* flush mouse fifo */
328 s->buttons_state = s->last_buttons_state;
329 s->dx = 0;
330 s->dy = 0;
331 s->dz = 0;
332 return 0;
333 }
335 cmd = buf[0] & 0xc;
336 reg = buf[0] & 0x3;
337 olen = 0;
338 switch(cmd) {
339 case ADB_WRITEREG:
340 switch(reg) {
341 case 2:
342 break;
343 case 3:
344 switch(buf[2]) {
345 case ADB_CMD_SELF_TEST:
346 break;
347 case ADB_CMD_CHANGE_ID:
348 case ADB_CMD_CHANGE_ID_AND_ACT:
349 case ADB_CMD_CHANGE_ID_AND_ENABLE:
350 d->devaddr = buf[1] & 0xf;
351 break;
352 default:
353 /* XXX: check this */
354 d->devaddr = buf[1] & 0xf;
355 break;
356 }
357 }
358 break;
359 case ADB_READREG:
360 switch(reg) {
361 case 0:
362 olen = adb_mouse_poll(d, obuf);
363 break;
364 case 1:
365 break;
366 case 3:
367 obuf[0] = d->handler;
368 obuf[1] = d->devaddr;
369 olen = 2;
370 break;
371 }
372 break;
373 }
374 return olen;
375 }
377 void adb_mouse_init(ADBBusState *bus)
378 {
379 ADBDevice *d;
380 MouseState *s;
382 s = qemu_mallocz(sizeof(MouseState));
383 d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request, NULL, s);
384 d->handler = 2;
385 qemu_add_mouse_event_handler(adb_mouse_event, d);
386 }