Statistics
| Branch: | Revision:

root / hw / input / adb.c @ a8aec295

History | View | Annotate | Download (15 kB)

1 267002cd bellard
/*
2 267002cd bellard
 * QEMU ADB support
3 5fafdf24 ths
 *
4 267002cd bellard
 * Copyright (c) 2004 Fabrice Bellard
5 5fafdf24 ths
 *
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 83c9f4ca Paolo Bonzini
#include "hw/hw.h"
25 0d09e41a Paolo Bonzini
#include "hw/input/adb.h"
26 28ecbaee Paolo Bonzini
#include "ui/console.h"
27 267002cd bellard
28 ea026b2f blueswir1
/* debug ADB */
29 ea026b2f blueswir1
//#define DEBUG_ADB
30 ea026b2f blueswir1
31 ea026b2f blueswir1
#ifdef DEBUG_ADB
32 001faf32 Blue Swirl
#define ADB_DPRINTF(fmt, ...) \
33 001faf32 Blue Swirl
do { printf("ADB: " fmt , ## __VA_ARGS__); } while (0)
34 ea026b2f blueswir1
#else
35 001faf32 Blue Swirl
#define ADB_DPRINTF(fmt, ...)
36 ea026b2f blueswir1
#endif
37 ea026b2f blueswir1
38 267002cd bellard
/* ADB commands */
39 267002cd bellard
#define ADB_BUSRESET                0x00
40 267002cd bellard
#define ADB_FLUSH               0x01
41 267002cd bellard
#define ADB_WRITEREG                0x08
42 267002cd bellard
#define ADB_READREG                0x0c
43 267002cd bellard
44 267002cd bellard
/* ADB device commands */
45 267002cd bellard
#define ADB_CMD_SELF_TEST                0xff
46 267002cd bellard
#define ADB_CMD_CHANGE_ID                0xfe
47 267002cd bellard
#define ADB_CMD_CHANGE_ID_AND_ACT        0xfd
48 267002cd bellard
#define ADB_CMD_CHANGE_ID_AND_ENABLE        0x00
49 267002cd bellard
50 267002cd bellard
/* ADB default device IDs (upper 4 bits of ADB command byte) */
51 2e4a7c9c Andreas Färber
#define ADB_DEVID_DONGLE   1
52 2e4a7c9c Andreas Färber
#define ADB_DEVID_KEYBOARD 2
53 2e4a7c9c Andreas Färber
#define ADB_DEVID_MOUSE    3
54 2e4a7c9c Andreas Färber
#define ADB_DEVID_TABLET   4
55 2e4a7c9c Andreas Färber
#define ADB_DEVID_MODEM    5
56 2e4a7c9c Andreas Färber
#define ADB_DEVID_MISC     7
57 267002cd bellard
58 bec9d989 bellard
/* error codes */
59 bec9d989 bellard
#define ADB_RET_NOTPRESENT (-2)
60 bec9d989 bellard
61 2e4a7c9c Andreas Färber
static void adb_device_reset(ADBDevice *d)
62 2e4a7c9c Andreas Färber
{
63 2e4a7c9c Andreas Färber
    qdev_reset_all(DEVICE(d));
64 2e4a7c9c Andreas Färber
}
65 2e4a7c9c Andreas Färber
66 e2733d20 bellard
int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
67 267002cd bellard
{
68 267002cd bellard
    ADBDevice *d;
69 267002cd bellard
    int devaddr, cmd, i;
70 267002cd bellard
71 819e712b bellard
    cmd = buf[0] & 0xf;
72 bec9d989 bellard
    if (cmd == ADB_BUSRESET) {
73 bec9d989 bellard
        for(i = 0; i < s->nb_devices; i++) {
74 2e4a7c9c Andreas Färber
            d = s->devices[i];
75 2e4a7c9c Andreas Färber
            adb_device_reset(d);
76 bec9d989 bellard
        }
77 bec9d989 bellard
        return 0;
78 267002cd bellard
    }
79 bec9d989 bellard
    devaddr = buf[0] >> 4;
80 267002cd bellard
    for(i = 0; i < s->nb_devices; i++) {
81 2e4a7c9c Andreas Färber
        d = s->devices[i];
82 267002cd bellard
        if (d->devaddr == devaddr) {
83 2e4a7c9c Andreas Färber
            ADBDeviceClass *adc = ADB_DEVICE_GET_CLASS(d);
84 2e4a7c9c Andreas Färber
            return adc->devreq(d, obuf, buf, len);
85 267002cd bellard
        }
86 267002cd bellard
    }
87 bec9d989 bellard
    return ADB_RET_NOTPRESENT;
88 e2733d20 bellard
}
89 e2733d20 bellard
90 bec9d989 bellard
/* XXX: move that to cuda ? */
91 e2733d20 bellard
int adb_poll(ADBBusState *s, uint8_t *obuf)
92 e2733d20 bellard
{
93 e2733d20 bellard
    ADBDevice *d;
94 e2733d20 bellard
    int olen, i;
95 bec9d989 bellard
    uint8_t buf[1];
96 e2733d20 bellard
97 e2733d20 bellard
    olen = 0;
98 e2733d20 bellard
    for(i = 0; i < s->nb_devices; i++) {
99 e2733d20 bellard
        if (s->poll_index >= s->nb_devices)
100 e2733d20 bellard
            s->poll_index = 0;
101 2e4a7c9c Andreas Färber
        d = s->devices[s->poll_index];
102 bec9d989 bellard
        buf[0] = ADB_READREG | (d->devaddr << 4);
103 bec9d989 bellard
        olen = adb_request(s, obuf + 1, buf, 1);
104 bec9d989 bellard
        /* if there is data, we poll again the same device */
105 bec9d989 bellard
        if (olen > 0) {
106 bec9d989 bellard
            obuf[0] = buf[0];
107 bec9d989 bellard
            olen++;
108 e2733d20 bellard
            break;
109 bec9d989 bellard
        }
110 bec9d989 bellard
        s->poll_index++;
111 e2733d20 bellard
    }
112 e2733d20 bellard
    return olen;
113 267002cd bellard
}
114 267002cd bellard
115 84ede329 Andreas Färber
static const TypeInfo adb_bus_type_info = {
116 84ede329 Andreas Färber
    .name = TYPE_ADB_BUS,
117 84ede329 Andreas Färber
    .parent = TYPE_BUS,
118 84ede329 Andreas Färber
    .instance_size = sizeof(ADBBusState),
119 84ede329 Andreas Färber
};
120 84ede329 Andreas Färber
121 2e4a7c9c Andreas Färber
static void adb_device_realizefn(DeviceState *dev, Error **errp)
122 2e4a7c9c Andreas Färber
{
123 2e4a7c9c Andreas Färber
    ADBDevice *d = ADB_DEVICE(dev);
124 2e4a7c9c Andreas Färber
    ADBBusState *bus = ADB_BUS(qdev_get_parent_bus(dev));
125 2e4a7c9c Andreas Färber
126 2e4a7c9c Andreas Färber
    if (bus->nb_devices >= MAX_ADB_DEVICES) {
127 2e4a7c9c Andreas Färber
        return;
128 2e4a7c9c Andreas Färber
    }
129 2e4a7c9c Andreas Färber
130 2e4a7c9c Andreas Färber
    bus->devices[bus->nb_devices++] = d;
131 2e4a7c9c Andreas Färber
}
132 2e4a7c9c Andreas Färber
133 2e4a7c9c Andreas Färber
static void adb_device_class_init(ObjectClass *oc, void *data)
134 2e4a7c9c Andreas Färber
{
135 2e4a7c9c Andreas Färber
    DeviceClass *dc = DEVICE_CLASS(oc);
136 2e4a7c9c Andreas Färber
137 2e4a7c9c Andreas Färber
    dc->realize = adb_device_realizefn;
138 2e4a7c9c Andreas Färber
    dc->bus_type = TYPE_ADB_BUS;
139 2e4a7c9c Andreas Färber
}
140 2e4a7c9c Andreas Färber
141 2e4a7c9c Andreas Färber
static const TypeInfo adb_device_type_info = {
142 2e4a7c9c Andreas Färber
    .name = TYPE_ADB_DEVICE,
143 2e4a7c9c Andreas Färber
    .parent = TYPE_DEVICE,
144 2e4a7c9c Andreas Färber
    .instance_size = sizeof(ADBDevice),
145 2e4a7c9c Andreas Färber
    .abstract = true,
146 2e4a7c9c Andreas Färber
    .class_init = adb_device_class_init,
147 2e4a7c9c Andreas Färber
};
148 2e4a7c9c Andreas Färber
149 267002cd bellard
/***************************************************************/
150 267002cd bellard
/* Keyboard ADB device */
151 267002cd bellard
152 2e4a7c9c Andreas Färber
#define ADB_KEYBOARD(obj) OBJECT_CHECK(KBDState, (obj), TYPE_ADB_KEYBOARD)
153 2e4a7c9c Andreas Färber
154 e2733d20 bellard
typedef struct KBDState {
155 2e4a7c9c Andreas Färber
    /*< private >*/
156 2e4a7c9c Andreas Färber
    ADBDevice parent_obj;
157 2e4a7c9c Andreas Färber
    /*< public >*/
158 2e4a7c9c Andreas Färber
159 e2733d20 bellard
    uint8_t data[128];
160 e2733d20 bellard
    int rptr, wptr, count;
161 e2733d20 bellard
} KBDState;
162 e2733d20 bellard
163 2e4a7c9c Andreas Färber
#define ADB_KEYBOARD_CLASS(class) \
164 2e4a7c9c Andreas Färber
    OBJECT_CLASS_CHECK(ADBKeyboardClass, (class), TYPE_ADB_KEYBOARD)
165 2e4a7c9c Andreas Färber
#define ADB_KEYBOARD_GET_CLASS(obj) \
166 2e4a7c9c Andreas Färber
    OBJECT_GET_CLASS(ADBKeyboardClass, (obj), TYPE_ADB_KEYBOARD)
167 2e4a7c9c Andreas Färber
168 2e4a7c9c Andreas Färber
typedef struct ADBKeyboardClass {
169 2e4a7c9c Andreas Färber
    /*< private >*/
170 2e4a7c9c Andreas Färber
    ADBDeviceClass parent_class;
171 2e4a7c9c Andreas Färber
    /*< public >*/
172 2e4a7c9c Andreas Färber
173 2e4a7c9c Andreas Färber
    DeviceRealize parent_realize;
174 2e4a7c9c Andreas Färber
} ADBKeyboardClass;
175 2e4a7c9c Andreas Färber
176 267002cd bellard
static const uint8_t pc_to_adb_keycode[256] = {
177 267002cd bellard
  0, 53, 18, 19, 20, 21, 23, 22, 26, 28, 25, 29, 27, 24, 51, 48,
178 267002cd bellard
 12, 13, 14, 15, 17, 16, 32, 34, 31, 35, 33, 30, 36, 54,  0,  1,
179 267002cd bellard
  2,  3,  5,  4, 38, 40, 37, 41, 39, 50, 56, 42,  6,  7,  8,  9,
180 267002cd bellard
 11, 45, 46, 43, 47, 44,123, 67, 58, 49, 57,122,120, 99,118, 96,
181 267002cd bellard
 97, 98,100,101,109, 71,107, 89, 91, 92, 78, 86, 87, 88, 69, 83,
182 e2733d20 bellard
 84, 85, 82, 65,  0,  0, 10,103,111,  0,  0,110, 81,  0,  0,  0,
183 267002cd bellard
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
184 267002cd bellard
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
185 e2733d20 bellard
  0,  0,  0, 94,  0, 93,  0,  0,  0,  0,  0,  0,104,102,  0,  0,
186 e2733d20 bellard
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 76,125,  0,  0,
187 e2733d20 bellard
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,105,  0,  0,  0,  0,  0,
188 e2733d20 bellard
  0,  0,  0,  0,  0, 75,  0,  0,124,  0,  0,  0,  0,  0,  0,  0,
189 e2733d20 bellard
  0,  0,  0,  0,  0,  0,  0,115, 62,116,  0, 59,  0, 60,  0,119,
190 e2733d20 bellard
 61,121,114,117,  0,  0,  0,  0,  0,  0,  0, 55,126,  0,127,  0,
191 267002cd bellard
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
192 e2733d20 bellard
  0,  0,  0,  0,  0, 95,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
193 267002cd bellard
};
194 267002cd bellard
195 267002cd bellard
static void adb_kbd_put_keycode(void *opaque, int keycode)
196 267002cd bellard
{
197 2e4a7c9c Andreas Färber
    KBDState *s = opaque;
198 e2733d20 bellard
199 e2733d20 bellard
    if (s->count < sizeof(s->data)) {
200 e2733d20 bellard
        s->data[s->wptr] = keycode;
201 e2733d20 bellard
        if (++s->wptr == sizeof(s->data))
202 e2733d20 bellard
            s->wptr = 0;
203 e2733d20 bellard
        s->count++;
204 267002cd bellard
    }
205 267002cd bellard
}
206 267002cd bellard
207 e2733d20 bellard
static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf)
208 267002cd bellard
{
209 e2733d20 bellard
    static int ext_keycode;
210 2e4a7c9c Andreas Färber
    KBDState *s = ADB_KEYBOARD(d);
211 e2733d20 bellard
    int adb_keycode, keycode;
212 e2733d20 bellard
    int olen;
213 e2733d20 bellard
214 e2733d20 bellard
    olen = 0;
215 e2733d20 bellard
    for(;;) {
216 e2733d20 bellard
        if (s->count == 0)
217 e2733d20 bellard
            break;
218 e2733d20 bellard
        keycode = s->data[s->rptr];
219 e2733d20 bellard
        if (++s->rptr == sizeof(s->data))
220 e2733d20 bellard
            s->rptr = 0;
221 e2733d20 bellard
        s->count--;
222 e2733d20 bellard
223 e2733d20 bellard
        if (keycode == 0xe0) {
224 e2733d20 bellard
            ext_keycode = 1;
225 e2733d20 bellard
        } else {
226 e2733d20 bellard
            if (ext_keycode)
227 e2733d20 bellard
                adb_keycode =  pc_to_adb_keycode[keycode | 0x80];
228 e2733d20 bellard
            else
229 e2733d20 bellard
                adb_keycode =  pc_to_adb_keycode[keycode & 0x7f];
230 bec9d989 bellard
            obuf[0] = adb_keycode | (keycode & 0x80);
231 bec9d989 bellard
            /* NOTE: could put a second keycode if needed */
232 bec9d989 bellard
            obuf[1] = 0xff;
233 bec9d989 bellard
            olen = 2;
234 e2733d20 bellard
            ext_keycode = 0;
235 e2733d20 bellard
            break;
236 e2733d20 bellard
        }
237 e2733d20 bellard
    }
238 e2733d20 bellard
    return olen;
239 e2733d20 bellard
}
240 e2733d20 bellard
241 e2733d20 bellard
static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
242 e2733d20 bellard
                           const uint8_t *buf, int len)
243 e2733d20 bellard
{
244 2e4a7c9c Andreas Färber
    KBDState *s = ADB_KEYBOARD(d);
245 e2733d20 bellard
    int cmd, reg, olen;
246 e2733d20 bellard
247 bec9d989 bellard
    if ((buf[0] & 0x0f) == ADB_FLUSH) {
248 bec9d989 bellard
        /* flush keyboard fifo */
249 bec9d989 bellard
        s->wptr = s->rptr = s->count = 0;
250 bec9d989 bellard
        return 0;
251 e2733d20 bellard
    }
252 267002cd bellard
253 267002cd bellard
    cmd = buf[0] & 0xc;
254 267002cd bellard
    reg = buf[0] & 0x3;
255 e2733d20 bellard
    olen = 0;
256 267002cd bellard
    switch(cmd) {
257 267002cd bellard
    case ADB_WRITEREG:
258 267002cd bellard
        switch(reg) {
259 267002cd bellard
        case 2:
260 267002cd bellard
            /* LED status */
261 267002cd bellard
            break;
262 267002cd bellard
        case 3:
263 267002cd bellard
            switch(buf[2]) {
264 267002cd bellard
            case ADB_CMD_SELF_TEST:
265 267002cd bellard
                break;
266 267002cd bellard
            case ADB_CMD_CHANGE_ID:
267 267002cd bellard
            case ADB_CMD_CHANGE_ID_AND_ACT:
268 267002cd bellard
            case ADB_CMD_CHANGE_ID_AND_ENABLE:
269 267002cd bellard
                d->devaddr = buf[1] & 0xf;
270 267002cd bellard
                break;
271 267002cd bellard
            default:
272 267002cd bellard
                /* XXX: check this */
273 267002cd bellard
                d->devaddr = buf[1] & 0xf;
274 267002cd bellard
                d->handler = buf[2];
275 267002cd bellard
                break;
276 267002cd bellard
            }
277 267002cd bellard
        }
278 267002cd bellard
        break;
279 267002cd bellard
    case ADB_READREG:
280 267002cd bellard
        switch(reg) {
281 bec9d989 bellard
        case 0:
282 bec9d989 bellard
            olen = adb_kbd_poll(d, obuf);
283 bec9d989 bellard
            break;
284 267002cd bellard
        case 1:
285 267002cd bellard
            break;
286 267002cd bellard
        case 2:
287 e2733d20 bellard
            obuf[0] = 0x00; /* XXX: check this */
288 e2733d20 bellard
            obuf[1] = 0x07; /* led status */
289 e2733d20 bellard
            olen = 2;
290 267002cd bellard
            break;
291 267002cd bellard
        case 3:
292 e2733d20 bellard
            obuf[0] = d->handler;
293 e2733d20 bellard
            obuf[1] = d->devaddr;
294 e2733d20 bellard
            olen = 2;
295 267002cd bellard
            break;
296 267002cd bellard
        }
297 267002cd bellard
        break;
298 267002cd bellard
    }
299 e2733d20 bellard
    return olen;
300 267002cd bellard
}
301 267002cd bellard
302 1f1f0600 Juan Quintela
static const VMStateDescription vmstate_adb_kbd = {
303 1f1f0600 Juan Quintela
    .name = "adb_kbd",
304 1f1f0600 Juan Quintela
    .version_id = 1,
305 1f1f0600 Juan Quintela
    .minimum_version_id = 1,
306 1f1f0600 Juan Quintela
    .minimum_version_id_old = 1,
307 1f1f0600 Juan Quintela
    .fields      = (VMStateField[]) {
308 1f1f0600 Juan Quintela
        VMSTATE_BUFFER(data, KBDState),
309 1f1f0600 Juan Quintela
        VMSTATE_INT32(rptr, KBDState),
310 1f1f0600 Juan Quintela
        VMSTATE_INT32(wptr, KBDState),
311 1f1f0600 Juan Quintela
        VMSTATE_INT32(count, KBDState),
312 1f1f0600 Juan Quintela
        VMSTATE_END_OF_LIST()
313 1f1f0600 Juan Quintela
    }
314 1f1f0600 Juan Quintela
};
315 9b64997f blueswir1
316 2e4a7c9c Andreas Färber
static void adb_kbd_reset(DeviceState *dev)
317 3988e897 bellard
{
318 2e4a7c9c Andreas Färber
    ADBDevice *d = ADB_DEVICE(dev);
319 2e4a7c9c Andreas Färber
    KBDState *s = ADB_KEYBOARD(dev);
320 3988e897 bellard
321 3988e897 bellard
    d->handler = 1;
322 2e4a7c9c Andreas Färber
    d->devaddr = ADB_DEVID_KEYBOARD;
323 2e4a7c9c Andreas Färber
    memset(s->data, 0, sizeof(s->data));
324 2e4a7c9c Andreas Färber
    s->rptr = 0;
325 2e4a7c9c Andreas Färber
    s->wptr = 0;
326 2e4a7c9c Andreas Färber
    s->count = 0;
327 3988e897 bellard
}
328 3988e897 bellard
329 2e4a7c9c Andreas Färber
static void adb_kbd_realizefn(DeviceState *dev, Error **errp)
330 267002cd bellard
{
331 2e4a7c9c Andreas Färber
    ADBDevice *d = ADB_DEVICE(dev);
332 2e4a7c9c Andreas Färber
    ADBKeyboardClass *akc = ADB_KEYBOARD_GET_CLASS(dev);
333 2e4a7c9c Andreas Färber
334 2e4a7c9c Andreas Färber
    akc->parent_realize(dev, errp);
335 2e4a7c9c Andreas Färber
336 267002cd bellard
    qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
337 267002cd bellard
}
338 267002cd bellard
339 2e4a7c9c Andreas Färber
static void adb_kbd_initfn(Object *obj)
340 2e4a7c9c Andreas Färber
{
341 2e4a7c9c Andreas Färber
    ADBDevice *d = ADB_DEVICE(obj);
342 2e4a7c9c Andreas Färber
343 2e4a7c9c Andreas Färber
    d->devaddr = ADB_DEVID_KEYBOARD;
344 2e4a7c9c Andreas Färber
}
345 2e4a7c9c Andreas Färber
346 2e4a7c9c Andreas Färber
static void adb_kbd_class_init(ObjectClass *oc, void *data)
347 2e4a7c9c Andreas Färber
{
348 2e4a7c9c Andreas Färber
    DeviceClass *dc = DEVICE_CLASS(oc);
349 2e4a7c9c Andreas Färber
    ADBDeviceClass *adc = ADB_DEVICE_CLASS(oc);
350 2e4a7c9c Andreas Färber
    ADBKeyboardClass *akc = ADB_KEYBOARD_CLASS(oc);
351 2e4a7c9c Andreas Färber
352 2e4a7c9c Andreas Färber
    akc->parent_realize = dc->realize;
353 2e4a7c9c Andreas Färber
    dc->realize = adb_kbd_realizefn;
354 2e4a7c9c Andreas Färber
355 2e4a7c9c Andreas Färber
    adc->devreq = adb_kbd_request;
356 2e4a7c9c Andreas Färber
    dc->reset = adb_kbd_reset;
357 2e4a7c9c Andreas Färber
    dc->vmsd = &vmstate_adb_kbd;
358 2e4a7c9c Andreas Färber
}
359 2e4a7c9c Andreas Färber
360 2e4a7c9c Andreas Färber
static const TypeInfo adb_kbd_type_info = {
361 2e4a7c9c Andreas Färber
    .name = TYPE_ADB_KEYBOARD,
362 2e4a7c9c Andreas Färber
    .parent = TYPE_ADB_DEVICE,
363 2e4a7c9c Andreas Färber
    .instance_size = sizeof(KBDState),
364 2e4a7c9c Andreas Färber
    .instance_init = adb_kbd_initfn,
365 2e4a7c9c Andreas Färber
    .class_init = adb_kbd_class_init,
366 2e4a7c9c Andreas Färber
    .class_size = sizeof(ADBKeyboardClass),
367 2e4a7c9c Andreas Färber
};
368 2e4a7c9c Andreas Färber
369 267002cd bellard
/***************************************************************/
370 267002cd bellard
/* Mouse ADB device */
371 267002cd bellard
372 2e4a7c9c Andreas Färber
#define ADB_MOUSE(obj) OBJECT_CHECK(MouseState, (obj), TYPE_ADB_MOUSE)
373 2e4a7c9c Andreas Färber
374 e2733d20 bellard
typedef struct MouseState {
375 2e4a7c9c Andreas Färber
    /*< public >*/
376 2e4a7c9c Andreas Färber
    ADBDevice parent_obj;
377 2e4a7c9c Andreas Färber
    /*< private >*/
378 2e4a7c9c Andreas Färber
379 e2733d20 bellard
    int buttons_state, last_buttons_state;
380 e2733d20 bellard
    int dx, dy, dz;
381 e2733d20 bellard
} MouseState;
382 e2733d20 bellard
383 2e4a7c9c Andreas Färber
#define ADB_MOUSE_CLASS(class) \
384 2e4a7c9c Andreas Färber
    OBJECT_CLASS_CHECK(ADBMouseClass, (class), TYPE_ADB_MOUSE)
385 2e4a7c9c Andreas Färber
#define ADB_MOUSE_GET_CLASS(obj) \
386 2e4a7c9c Andreas Färber
    OBJECT_GET_CLASS(ADBMouseClass, (obj), TYPE_ADB_MOUSE)
387 2e4a7c9c Andreas Färber
388 2e4a7c9c Andreas Färber
typedef struct ADBMouseClass {
389 2e4a7c9c Andreas Färber
    /*< public >*/
390 2e4a7c9c Andreas Färber
    ADBDeviceClass parent_class;
391 2e4a7c9c Andreas Färber
    /*< private >*/
392 2e4a7c9c Andreas Färber
393 2e4a7c9c Andreas Färber
    DeviceRealize parent_realize;
394 2e4a7c9c Andreas Färber
} ADBMouseClass;
395 2e4a7c9c Andreas Färber
396 267002cd bellard
static void adb_mouse_event(void *opaque,
397 267002cd bellard
                            int dx1, int dy1, int dz1, int buttons_state)
398 267002cd bellard
{
399 2e4a7c9c Andreas Färber
    MouseState *s = opaque;
400 e2733d20 bellard
401 e2733d20 bellard
    s->dx += dx1;
402 e2733d20 bellard
    s->dy += dy1;
403 e2733d20 bellard
    s->dz += dz1;
404 e2733d20 bellard
    s->buttons_state = buttons_state;
405 e2733d20 bellard
}
406 e2733d20 bellard
407 e2733d20 bellard
408 e2733d20 bellard
static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
409 e2733d20 bellard
{
410 2e4a7c9c Andreas Färber
    MouseState *s = ADB_MOUSE(d);
411 267002cd bellard
    int dx, dy;
412 267002cd bellard
413 e2733d20 bellard
    if (s->last_buttons_state == s->buttons_state &&
414 e2733d20 bellard
        s->dx == 0 && s->dy == 0)
415 e2733d20 bellard
        return 0;
416 3b46e624 ths
417 e2733d20 bellard
    dx = s->dx;
418 267002cd bellard
    if (dx < -63)
419 267002cd bellard
        dx = -63;
420 267002cd bellard
    else if (dx > 63)
421 267002cd bellard
        dx = 63;
422 3b46e624 ths
423 e2733d20 bellard
    dy = s->dy;
424 267002cd bellard
    if (dy < -63)
425 267002cd bellard
        dy = -63;
426 267002cd bellard
    else if (dy > 63)
427 267002cd bellard
        dy = 63;
428 3b46e624 ths
429 e2733d20 bellard
    s->dx -= dx;
430 e2733d20 bellard
    s->dy -= dy;
431 e2733d20 bellard
    s->last_buttons_state = s->buttons_state;
432 3b46e624 ths
433 267002cd bellard
    dx &= 0x7f;
434 267002cd bellard
    dy &= 0x7f;
435 3b46e624 ths
436 bec9d989 bellard
    if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
437 267002cd bellard
        dy |= 0x80;
438 bec9d989 bellard
    if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
439 267002cd bellard
        dx |= 0x80;
440 3b46e624 ths
441 bec9d989 bellard
    obuf[0] = dy;
442 bec9d989 bellard
    obuf[1] = dx;
443 bec9d989 bellard
    return 2;
444 267002cd bellard
}
445 267002cd bellard
446 e2733d20 bellard
static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
447 e2733d20 bellard
                             const uint8_t *buf, int len)
448 267002cd bellard
{
449 2e4a7c9c Andreas Färber
    MouseState *s = ADB_MOUSE(d);
450 e2733d20 bellard
    int cmd, reg, olen;
451 3b46e624 ths
452 bec9d989 bellard
    if ((buf[0] & 0x0f) == ADB_FLUSH) {
453 bec9d989 bellard
        /* flush mouse fifo */
454 bec9d989 bellard
        s->buttons_state = s->last_buttons_state;
455 bec9d989 bellard
        s->dx = 0;
456 bec9d989 bellard
        s->dy = 0;
457 bec9d989 bellard
        s->dz = 0;
458 bec9d989 bellard
        return 0;
459 e2733d20 bellard
    }
460 267002cd bellard
461 267002cd bellard
    cmd = buf[0] & 0xc;
462 267002cd bellard
    reg = buf[0] & 0x3;
463 e2733d20 bellard
    olen = 0;
464 267002cd bellard
    switch(cmd) {
465 267002cd bellard
    case ADB_WRITEREG:
466 ea026b2f blueswir1
        ADB_DPRINTF("write reg %d val 0x%2.2x\n", reg, buf[1]);
467 267002cd bellard
        switch(reg) {
468 267002cd bellard
        case 2:
469 267002cd bellard
            break;
470 267002cd bellard
        case 3:
471 267002cd bellard
            switch(buf[2]) {
472 267002cd bellard
            case ADB_CMD_SELF_TEST:
473 267002cd bellard
                break;
474 267002cd bellard
            case ADB_CMD_CHANGE_ID:
475 267002cd bellard
            case ADB_CMD_CHANGE_ID_AND_ACT:
476 267002cd bellard
            case ADB_CMD_CHANGE_ID_AND_ENABLE:
477 267002cd bellard
                d->devaddr = buf[1] & 0xf;
478 267002cd bellard
                break;
479 267002cd bellard
            default:
480 267002cd bellard
                /* XXX: check this */
481 267002cd bellard
                d->devaddr = buf[1] & 0xf;
482 267002cd bellard
                break;
483 267002cd bellard
            }
484 267002cd bellard
        }
485 267002cd bellard
        break;
486 267002cd bellard
    case ADB_READREG:
487 267002cd bellard
        switch(reg) {
488 bec9d989 bellard
        case 0:
489 bec9d989 bellard
            olen = adb_mouse_poll(d, obuf);
490 bec9d989 bellard
            break;
491 267002cd bellard
        case 1:
492 267002cd bellard
            break;
493 267002cd bellard
        case 3:
494 e2733d20 bellard
            obuf[0] = d->handler;
495 e2733d20 bellard
            obuf[1] = d->devaddr;
496 e2733d20 bellard
            olen = 2;
497 267002cd bellard
            break;
498 267002cd bellard
        }
499 ea026b2f blueswir1
        ADB_DPRINTF("read reg %d obuf[0] 0x%2.2x obuf[1] 0x%2.2x\n", reg,
500 ea026b2f blueswir1
                    obuf[0], obuf[1]);
501 267002cd bellard
        break;
502 267002cd bellard
    }
503 e2733d20 bellard
    return olen;
504 267002cd bellard
}
505 267002cd bellard
506 2e4a7c9c Andreas Färber
static void adb_mouse_reset(DeviceState *dev)
507 3988e897 bellard
{
508 2e4a7c9c Andreas Färber
    ADBDevice *d = ADB_DEVICE(dev);
509 2e4a7c9c Andreas Färber
    MouseState *s = ADB_MOUSE(dev);
510 3988e897 bellard
511 3988e897 bellard
    d->handler = 2;
512 2e4a7c9c Andreas Färber
    d->devaddr = ADB_DEVID_MOUSE;
513 2e4a7c9c Andreas Färber
    s->last_buttons_state = s->buttons_state = 0;
514 2e4a7c9c Andreas Färber
    s->dx = s->dy = s->dz = 0;
515 3988e897 bellard
}
516 3988e897 bellard
517 2b2cd592 Juan Quintela
static const VMStateDescription vmstate_adb_mouse = {
518 2b2cd592 Juan Quintela
    .name = "adb_mouse",
519 2b2cd592 Juan Quintela
    .version_id = 1,
520 2b2cd592 Juan Quintela
    .minimum_version_id = 1,
521 2b2cd592 Juan Quintela
    .minimum_version_id_old = 1,
522 2b2cd592 Juan Quintela
    .fields      = (VMStateField[]) {
523 2b2cd592 Juan Quintela
        VMSTATE_INT32(buttons_state, MouseState),
524 2b2cd592 Juan Quintela
        VMSTATE_INT32(last_buttons_state, MouseState),
525 2b2cd592 Juan Quintela
        VMSTATE_INT32(dx, MouseState),
526 2b2cd592 Juan Quintela
        VMSTATE_INT32(dy, MouseState),
527 2b2cd592 Juan Quintela
        VMSTATE_INT32(dz, MouseState),
528 2b2cd592 Juan Quintela
        VMSTATE_END_OF_LIST()
529 2b2cd592 Juan Quintela
    }
530 2b2cd592 Juan Quintela
};
531 9b64997f blueswir1
532 2e4a7c9c Andreas Färber
static void adb_mouse_realizefn(DeviceState *dev, Error **errp)
533 267002cd bellard
{
534 2e4a7c9c Andreas Färber
    MouseState *s = ADB_MOUSE(dev);
535 2e4a7c9c Andreas Färber
    ADBMouseClass *amc = ADB_MOUSE_GET_CLASS(dev);
536 2e4a7c9c Andreas Färber
537 2e4a7c9c Andreas Färber
    amc->parent_realize(dev, errp);
538 2e4a7c9c Andreas Färber
539 2e4a7c9c Andreas Färber
    qemu_add_mouse_event_handler(adb_mouse_event, s, 0, "QEMU ADB Mouse");
540 2e4a7c9c Andreas Färber
}
541 2e4a7c9c Andreas Färber
542 2e4a7c9c Andreas Färber
static void adb_mouse_initfn(Object *obj)
543 2e4a7c9c Andreas Färber
{
544 2e4a7c9c Andreas Färber
    ADBDevice *d = ADB_DEVICE(obj);
545 267002cd bellard
546 2e4a7c9c Andreas Färber
    d->devaddr = ADB_DEVID_MOUSE;
547 267002cd bellard
}
548 84ede329 Andreas Färber
549 2e4a7c9c Andreas Färber
static void adb_mouse_class_init(ObjectClass *oc, void *data)
550 2e4a7c9c Andreas Färber
{
551 2e4a7c9c Andreas Färber
    DeviceClass *dc = DEVICE_CLASS(oc);
552 2e4a7c9c Andreas Färber
    ADBDeviceClass *adc = ADB_DEVICE_CLASS(oc);
553 2e4a7c9c Andreas Färber
    ADBMouseClass *amc = ADB_MOUSE_CLASS(oc);
554 2e4a7c9c Andreas Färber
555 2e4a7c9c Andreas Färber
    amc->parent_realize = dc->realize;
556 2e4a7c9c Andreas Färber
    dc->realize = adb_mouse_realizefn;
557 2e4a7c9c Andreas Färber
558 2e4a7c9c Andreas Färber
    adc->devreq = adb_mouse_request;
559 2e4a7c9c Andreas Färber
    dc->reset = adb_mouse_reset;
560 2e4a7c9c Andreas Färber
    dc->vmsd = &vmstate_adb_mouse;
561 2e4a7c9c Andreas Färber
}
562 2e4a7c9c Andreas Färber
563 2e4a7c9c Andreas Färber
static const TypeInfo adb_mouse_type_info = {
564 2e4a7c9c Andreas Färber
    .name = TYPE_ADB_MOUSE,
565 2e4a7c9c Andreas Färber
    .parent = TYPE_ADB_DEVICE,
566 2e4a7c9c Andreas Färber
    .instance_size = sizeof(MouseState),
567 2e4a7c9c Andreas Färber
    .instance_init = adb_mouse_initfn,
568 2e4a7c9c Andreas Färber
    .class_init = adb_mouse_class_init,
569 2e4a7c9c Andreas Färber
    .class_size = sizeof(ADBMouseClass),
570 2e4a7c9c Andreas Färber
};
571 2e4a7c9c Andreas Färber
572 84ede329 Andreas Färber
573 84ede329 Andreas Färber
static void adb_register_types(void)
574 84ede329 Andreas Färber
{
575 84ede329 Andreas Färber
    type_register_static(&adb_bus_type_info);
576 2e4a7c9c Andreas Färber
    type_register_static(&adb_device_type_info);
577 2e4a7c9c Andreas Färber
    type_register_static(&adb_kbd_type_info);
578 2e4a7c9c Andreas Färber
    type_register_static(&adb_mouse_type_info);
579 84ede329 Andreas Färber
}
580 84ede329 Andreas Färber
581 84ede329 Andreas Färber
type_init(adb_register_types)