Statistics
| Branch: | Revision:

root / hw / adb.c @ 4e3e9d0b

History | View | Annotate | Download (8.7 kB)

1 267002cd bellard
/*
2 267002cd bellard
 * QEMU ADB support
3 267002cd bellard
 * 
4 267002cd bellard
 * Copyright (c) 2004 Fabrice Bellard
5 267002cd bellard
 * 
6 267002cd bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 267002cd bellard
 * of this software and associated documentation files (the "Software"), to deal
8 267002cd bellard
 * in the Software without restriction, including without limitation the rights
9 267002cd bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 267002cd bellard
 * copies of the Software, and to permit persons to whom the Software is
11 267002cd bellard
 * furnished to do so, subject to the following conditions:
12 267002cd bellard
 *
13 267002cd bellard
 * The above copyright notice and this permission notice shall be included in
14 267002cd bellard
 * all copies or substantial portions of the Software.
15 267002cd bellard
 *
16 267002cd bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 267002cd bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 267002cd bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 267002cd bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 267002cd bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 267002cd bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 267002cd bellard
 * THE SOFTWARE.
23 267002cd bellard
 */
24 267002cd bellard
#include "vl.h"
25 267002cd bellard
26 267002cd bellard
/* ADB commands */
27 267002cd bellard
#define ADB_BUSRESET                0x00
28 267002cd bellard
#define ADB_FLUSH               0x01
29 267002cd bellard
#define ADB_WRITEREG                0x08
30 267002cd bellard
#define ADB_READREG                0x0c
31 267002cd bellard
32 267002cd bellard
/* ADB device commands */
33 267002cd bellard
#define ADB_CMD_SELF_TEST                0xff
34 267002cd bellard
#define ADB_CMD_CHANGE_ID                0xfe
35 267002cd bellard
#define ADB_CMD_CHANGE_ID_AND_ACT        0xfd
36 267002cd bellard
#define ADB_CMD_CHANGE_ID_AND_ENABLE        0x00
37 267002cd bellard
38 267002cd bellard
/* ADB default device IDs (upper 4 bits of ADB command byte) */
39 267002cd bellard
#define ADB_DONGLE        1
40 267002cd bellard
#define ADB_KEYBOARD        2
41 267002cd bellard
#define ADB_MOUSE        3
42 267002cd bellard
#define ADB_TABLET        4
43 267002cd bellard
#define ADB_MODEM        5
44 267002cd bellard
#define ADB_MISC        7
45 267002cd bellard
46 267002cd bellard
#define ADB_RET_OK                        0
47 267002cd bellard
#define ADB_RET_INUSE                        1
48 267002cd bellard
#define ADB_RET_NOTPRESENT                2
49 267002cd bellard
#define ADB_RET_TIMEOUT                        3
50 267002cd bellard
#define ADB_RET_UNEXPECTED_RESULT        4
51 267002cd bellard
#define ADB_RET_REQUEST_ERROR                5
52 267002cd bellard
#define ADB_RET_BUS_ERROR                6
53 267002cd bellard
54 267002cd bellard
55 267002cd bellard
static void adb_send_packet1(ADBBusState *s, uint8_t reply)
56 267002cd bellard
{
57 267002cd bellard
    adb_send_packet(s, &reply, 1);
58 267002cd bellard
}
59 267002cd bellard
60 267002cd bellard
void adb_receive_packet(ADBBusState *s, const uint8_t *buf, int len)
61 267002cd bellard
{
62 267002cd bellard
    ADBDevice *d;
63 267002cd bellard
    int devaddr, cmd, i;
64 267002cd bellard
    uint8_t obuf[4];
65 267002cd bellard
66 267002cd bellard
    cmd = buf[1] & 0xf;
67 267002cd bellard
    devaddr = buf[1] >> 4;
68 267002cd bellard
    if (buf[1] == ADB_BUSRESET) {
69 267002cd bellard
        obuf[0] = 0x00;
70 267002cd bellard
        obuf[1] = 0x00;
71 267002cd bellard
        adb_send_packet(s, obuf, 2);
72 267002cd bellard
        return;
73 267002cd bellard
    }
74 267002cd bellard
    if (cmd == ADB_FLUSH) {
75 267002cd bellard
        obuf[0] = 0x00;
76 267002cd bellard
        obuf[1] = 0x00;
77 267002cd bellard
        adb_send_packet(s, obuf, 2);
78 267002cd bellard
        return;
79 267002cd bellard
    }
80 267002cd bellard
81 267002cd bellard
    for(i = 0; i < s->nb_devices; i++) {
82 267002cd bellard
        d = &s->devices[i];
83 267002cd bellard
        if (d->devaddr == devaddr) {
84 267002cd bellard
            d->receive_packet(d, buf, len);
85 267002cd bellard
            return;
86 267002cd bellard
        }
87 267002cd bellard
    }
88 267002cd bellard
    adb_send_packet1(s, ADB_RET_NOTPRESENT);
89 267002cd bellard
}
90 267002cd bellard
91 267002cd bellard
ADBDevice *adb_register_device(ADBBusState *s, int devaddr, 
92 267002cd bellard
                               ADBDeviceReceivePacket *receive_packet, 
93 267002cd bellard
                               void *opaque)
94 267002cd bellard
{
95 267002cd bellard
    ADBDevice *d;
96 267002cd bellard
    if (s->nb_devices >= MAX_ADB_DEVICES)
97 267002cd bellard
        return NULL;
98 267002cd bellard
    d = &s->devices[s->nb_devices++];
99 267002cd bellard
    d->bus = s;
100 267002cd bellard
    d->devaddr = devaddr;
101 267002cd bellard
    d->receive_packet = receive_packet;
102 267002cd bellard
    d->opaque = opaque;
103 267002cd bellard
    return d;
104 267002cd bellard
}
105 267002cd bellard
106 267002cd bellard
/***************************************************************/
107 267002cd bellard
/* Keyboard ADB device */
108 267002cd bellard
109 267002cd bellard
static const uint8_t pc_to_adb_keycode[256] = {
110 267002cd bellard
  0, 53, 18, 19, 20, 21, 23, 22, 26, 28, 25, 29, 27, 24, 51, 48,
111 267002cd bellard
 12, 13, 14, 15, 17, 16, 32, 34, 31, 35, 33, 30, 36, 54,  0,  1,
112 267002cd bellard
  2,  3,  5,  4, 38, 40, 37, 41, 39, 50, 56, 42,  6,  7,  8,  9,
113 267002cd bellard
 11, 45, 46, 43, 47, 44,123, 67, 58, 49, 57,122,120, 99,118, 96,
114 267002cd bellard
 97, 98,100,101,109, 71,107, 89, 91, 92, 78, 86, 87, 88, 69, 83,
115 267002cd bellard
 84, 85, 82, 65,  0,  0, 10,103,111,  0,  0,  0,  0,  0,  0,  0,
116 267002cd bellard
 76,125, 75,105,124,110,115, 62,116, 59, 60,119, 61,121,114,117,
117 267002cd bellard
  0,  0,  0,  0,127, 81,  0,113,  0,  0,  0,  0, 95, 55,  0,  0,
118 267002cd bellard
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
119 267002cd bellard
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
120 267002cd bellard
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
121 267002cd bellard
  0,  0,  0,  0,  0, 94,  0, 93,  0,  0,  0,  0,  0,  0,104,102,
122 267002cd bellard
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
123 267002cd bellard
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
124 267002cd bellard
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
125 267002cd bellard
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
126 267002cd bellard
};
127 267002cd bellard
128 267002cd bellard
static void adb_kbd_put_keycode(void *opaque, int keycode)
129 267002cd bellard
{
130 267002cd bellard
    static int ext_keycode;
131 267002cd bellard
    ADBDevice *d = opaque;
132 267002cd bellard
    uint8_t buf[4];
133 267002cd bellard
    int adb_keycode;
134 267002cd bellard
    
135 267002cd bellard
    if (keycode == 0xe0) {
136 267002cd bellard
        ext_keycode = 1;
137 267002cd bellard
    } else {
138 267002cd bellard
        
139 267002cd bellard
        if (ext_keycode)
140 267002cd bellard
            adb_keycode =  pc_to_adb_keycode[keycode | 0x80];
141 267002cd bellard
        else
142 267002cd bellard
            adb_keycode =  pc_to_adb_keycode[keycode & 0x7f];
143 267002cd bellard
            
144 267002cd bellard
        buf[0] = 0x40;
145 267002cd bellard
        buf[1] = (d->devaddr << 4) | 0x0c;
146 267002cd bellard
        buf[2] = adb_keycode | (keycode & 0x80);
147 267002cd bellard
        buf[3] = 0xff;
148 267002cd bellard
        adb_send_packet(d->bus, buf, 4);
149 267002cd bellard
        ext_keycode = 0;
150 267002cd bellard
    }
151 267002cd bellard
}
152 267002cd bellard
153 267002cd bellard
static void adb_kbd_receive_packet(ADBDevice *d, const uint8_t *buf, int len)
154 267002cd bellard
{
155 267002cd bellard
    int cmd, reg;
156 267002cd bellard
    uint8_t obuf[4];
157 267002cd bellard
158 267002cd bellard
    cmd = buf[0] & 0xc;
159 267002cd bellard
    reg = buf[0] & 0x3;
160 267002cd bellard
    switch(cmd) {
161 267002cd bellard
    case ADB_WRITEREG:
162 267002cd bellard
        switch(reg) {
163 267002cd bellard
        case 2:
164 267002cd bellard
            /* LED status */
165 267002cd bellard
            adb_send_packet1(d->bus, ADB_RET_OK);
166 267002cd bellard
            break;
167 267002cd bellard
        case 3:
168 267002cd bellard
            switch(buf[2]) {
169 267002cd bellard
            case ADB_CMD_SELF_TEST:
170 267002cd bellard
                adb_send_packet1(d->bus, ADB_RET_OK);
171 267002cd bellard
                break;
172 267002cd bellard
            case ADB_CMD_CHANGE_ID:
173 267002cd bellard
            case ADB_CMD_CHANGE_ID_AND_ACT:
174 267002cd bellard
            case ADB_CMD_CHANGE_ID_AND_ENABLE:
175 267002cd bellard
                d->devaddr = buf[1] & 0xf;
176 267002cd bellard
                adb_send_packet1(d->bus, ADB_RET_OK);
177 267002cd bellard
                break;
178 267002cd bellard
            default:
179 267002cd bellard
                /* XXX: check this */
180 267002cd bellard
                d->devaddr = buf[1] & 0xf;
181 267002cd bellard
                d->handler = buf[2];
182 267002cd bellard
                adb_send_packet1(d->bus, ADB_RET_OK);
183 267002cd bellard
                break;
184 267002cd bellard
            }
185 267002cd bellard
        }
186 267002cd bellard
        break;
187 267002cd bellard
    case ADB_READREG:
188 267002cd bellard
        switch(reg) {
189 267002cd bellard
        case 1:
190 267002cd bellard
            adb_send_packet1(d->bus, ADB_RET_OK);
191 267002cd bellard
            break;
192 267002cd bellard
        case 2:
193 267002cd bellard
            obuf[0] = ADB_RET_OK;
194 267002cd bellard
            obuf[1] = 0x00; /* XXX: check this */
195 267002cd bellard
            obuf[2] = 0x07; /* led status */
196 267002cd bellard
            adb_send_packet(d->bus, obuf, 3);
197 267002cd bellard
            break;
198 267002cd bellard
        case 3:
199 267002cd bellard
            obuf[0] = ADB_RET_OK;
200 267002cd bellard
            obuf[1] = d->handler;
201 267002cd bellard
            obuf[2] = d->devaddr;
202 267002cd bellard
            adb_send_packet(d->bus, obuf, 3);
203 267002cd bellard
            break;
204 267002cd bellard
        }
205 267002cd bellard
        break;
206 267002cd bellard
    }
207 267002cd bellard
}
208 267002cd bellard
209 267002cd bellard
void adb_kbd_init(ADBBusState *bus)
210 267002cd bellard
{
211 267002cd bellard
    ADBDevice *d;
212 267002cd bellard
213 267002cd bellard
    d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_receive_packet, NULL);
214 267002cd bellard
    qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
215 267002cd bellard
}
216 267002cd bellard
217 267002cd bellard
/***************************************************************/
218 267002cd bellard
/* Mouse ADB device */
219 267002cd bellard
220 267002cd bellard
static void adb_mouse_event(void *opaque,
221 267002cd bellard
                            int dx1, int dy1, int dz1, int buttons_state)
222 267002cd bellard
{
223 267002cd bellard
    ADBDevice *d = opaque;
224 267002cd bellard
    uint8_t buf[4];
225 267002cd bellard
    int dx, dy;
226 267002cd bellard
227 267002cd bellard
    dx = dx1;
228 267002cd bellard
    if (dx < -63)
229 267002cd bellard
        dx = -63;
230 267002cd bellard
    else if (dx > 63)
231 267002cd bellard
        dx = 63;
232 267002cd bellard
233 267002cd bellard
    dy = dy1;
234 267002cd bellard
    if (dy < -63)
235 267002cd bellard
        dy = -63;
236 267002cd bellard
    else if (dy > 63)
237 267002cd bellard
        dy = 63;
238 267002cd bellard
239 267002cd bellard
    dx &= 0x7f;
240 267002cd bellard
    dy &= 0x7f;
241 267002cd bellard
242 267002cd bellard
    if (buttons_state & MOUSE_EVENT_LBUTTON)
243 267002cd bellard
        dy |= 0x80;
244 267002cd bellard
    if (buttons_state & MOUSE_EVENT_RBUTTON)
245 267002cd bellard
        dx |= 0x80;
246 267002cd bellard
247 267002cd bellard
    buf[0] = 0x40;
248 267002cd bellard
    buf[1] = (d->devaddr << 4) | 0x0c;
249 267002cd bellard
    buf[2] = dy;
250 267002cd bellard
    buf[3] = dx;
251 267002cd bellard
    adb_send_packet(d->bus, buf, 4);
252 267002cd bellard
}
253 267002cd bellard
254 267002cd bellard
static void adb_mouse_receive_packet(ADBDevice *d, const uint8_t *buf, int len)
255 267002cd bellard
{
256 267002cd bellard
    int cmd, reg;
257 267002cd bellard
    uint8_t obuf[4];
258 267002cd bellard
259 267002cd bellard
    cmd = buf[0] & 0xc;
260 267002cd bellard
    reg = buf[0] & 0x3;
261 267002cd bellard
    switch(cmd) {
262 267002cd bellard
    case ADB_WRITEREG:
263 267002cd bellard
        switch(reg) {
264 267002cd bellard
        case 2:
265 267002cd bellard
            adb_send_packet1(d->bus, ADB_RET_OK);
266 267002cd bellard
            break;
267 267002cd bellard
        case 3:
268 267002cd bellard
            switch(buf[2]) {
269 267002cd bellard
            case ADB_CMD_SELF_TEST:
270 267002cd bellard
                adb_send_packet1(d->bus, ADB_RET_OK);
271 267002cd bellard
                break;
272 267002cd bellard
            case ADB_CMD_CHANGE_ID:
273 267002cd bellard
            case ADB_CMD_CHANGE_ID_AND_ACT:
274 267002cd bellard
            case ADB_CMD_CHANGE_ID_AND_ENABLE:
275 267002cd bellard
                d->devaddr = buf[1] & 0xf;
276 267002cd bellard
                adb_send_packet1(d->bus, ADB_RET_OK);
277 267002cd bellard
                break;
278 267002cd bellard
            default:
279 267002cd bellard
                /* XXX: check this */
280 267002cd bellard
                d->devaddr = buf[1] & 0xf;
281 267002cd bellard
                adb_send_packet1(d->bus, ADB_RET_OK);
282 267002cd bellard
                break;
283 267002cd bellard
            }
284 267002cd bellard
        }
285 267002cd bellard
        break;
286 267002cd bellard
    case ADB_READREG:
287 267002cd bellard
        switch(reg) {
288 267002cd bellard
        case 1:
289 267002cd bellard
            adb_send_packet1(d->bus, ADB_RET_OK);
290 267002cd bellard
            break;
291 267002cd bellard
        case 3:
292 267002cd bellard
            obuf[0] = ADB_RET_OK;
293 267002cd bellard
            obuf[1] = d->handler;
294 267002cd bellard
            obuf[2] = d->devaddr;
295 267002cd bellard
            adb_send_packet(d->bus, obuf, 3);
296 267002cd bellard
            break;
297 267002cd bellard
        }
298 267002cd bellard
        break;
299 267002cd bellard
    }
300 267002cd bellard
}
301 267002cd bellard
302 267002cd bellard
void adb_mouse_init(ADBBusState *bus)
303 267002cd bellard
{
304 267002cd bellard
    ADBDevice *d;
305 267002cd bellard
306 267002cd bellard
    d = adb_register_device(bus, ADB_MOUSE, adb_mouse_receive_packet, NULL);
307 267002cd bellard
    qemu_add_mouse_event_handler(adb_mouse_event, d);
308 267002cd bellard
}