~ubuntu-branches/ubuntu/wily/qemu-kvm-spice/wily

« back to all changes in this revision

Viewing changes to hw/adb.c

  • Committer: Bazaar Package Importer
  • Author(s): Serge Hallyn
  • Date: 2011-10-19 10:44:56 UTC
  • Revision ID: james.westby@ubuntu.com-20111019104456-xgvskumk3sxi97f4
Tags: upstream-0.15.0+noroms
ImportĀ upstreamĀ versionĀ 0.15.0+noroms

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 "hw.h"
 
25
#include "ppc_mac.h"
 
26
#include "console.h"
 
27
 
 
28
/* debug ADB */
 
29
//#define DEBUG_ADB
 
30
 
 
31
#ifdef DEBUG_ADB
 
32
#define ADB_DPRINTF(fmt, ...) \
 
33
do { printf("ADB: " fmt , ## __VA_ARGS__); } while (0)
 
34
#else
 
35
#define ADB_DPRINTF(fmt, ...)
 
36
#endif
 
37
 
 
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
 
 
58
/* error codes */
 
59
#define ADB_RET_NOTPRESENT (-2)
 
60
 
 
61
int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
 
62
{
 
63
    ADBDevice *d;
 
64
    int devaddr, cmd, i;
 
65
 
 
66
    cmd = buf[0] & 0xf;
 
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;
 
75
    }
 
76
    devaddr = buf[0] >> 4;
 
77
    for(i = 0; i < s->nb_devices; i++) {
 
78
        d = &s->devices[i];
 
79
        if (d->devaddr == devaddr) {
 
80
            return d->devreq(d, obuf, buf, len);
 
81
        }
 
82
    }
 
83
    return ADB_RET_NOTPRESENT;
 
84
}
 
85
 
 
86
/* XXX: move that to cuda ? */
 
87
int adb_poll(ADBBusState *s, uint8_t *obuf)
 
88
{
 
89
    ADBDevice *d;
 
90
    int olen, i;
 
91
    uint8_t buf[1];
 
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];
 
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++;
 
104
            break;
 
105
        }
 
106
        s->poll_index++;
 
107
    }
 
108
    return olen;
 
109
}
 
110
 
 
111
ADBDevice *adb_register_device(ADBBusState *s, int devaddr,
 
112
                               ADBDeviceRequest *devreq,
 
113
                               ADBDeviceReset *devreset,
 
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;
 
122
    d->devreq = devreq;
 
123
    d->devreset = devreset;
 
124
    d->opaque = opaque;
 
125
    qemu_register_reset((QEMUResetHandler *)devreset, d);
 
126
    return d;
 
127
}
 
128
 
 
129
/***************************************************************/
 
130
/* Keyboard ADB device */
 
131
 
 
132
typedef struct KBDState {
 
133
    uint8_t data[128];
 
134
    int rptr, wptr, count;
 
135
} KBDState;
 
136
 
 
137
static 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,
 
143
 84, 85, 82, 65,  0,  0, 10,103,111,  0,  0,110, 81,  0,  0,  0,
 
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,
 
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,
 
152
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 
153
  0,  0,  0,  0,  0, 95,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 
154
};
 
155
 
 
156
static void adb_kbd_put_keycode(void *opaque, int keycode)
 
157
{
 
158
    ADBDevice *d = opaque;
 
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++;
 
166
    }
 
167
}
 
168
 
 
169
static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf)
 
170
{
 
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];
 
192
            obuf[0] = adb_keycode | (keycode & 0x80);
 
193
            /* NOTE: could put a second keycode if needed */
 
194
            obuf[1] = 0xff;
 
195
            olen = 2;
 
196
            ext_keycode = 0;
 
197
            break;
 
198
        }
 
199
    }
 
200
    return olen;
 
201
}
 
202
 
 
203
static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
 
204
                           const uint8_t *buf, int len)
 
205
{
 
206
    KBDState *s = d->opaque;
 
207
    int cmd, reg, olen;
 
208
 
 
209
    if ((buf[0] & 0x0f) == ADB_FLUSH) {
 
210
        /* flush keyboard fifo */
 
211
        s->wptr = s->rptr = s->count = 0;
 
212
        return 0;
 
213
    }
 
214
 
 
215
    cmd = buf[0] & 0xc;
 
216
    reg = buf[0] & 0x3;
 
217
    olen = 0;
 
218
    switch(cmd) {
 
219
    case ADB_WRITEREG:
 
220
        switch(reg) {
 
221
        case 2:
 
222
            /* LED status */
 
223
            break;
 
224
        case 3:
 
225
            switch(buf[2]) {
 
226
            case ADB_CMD_SELF_TEST:
 
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;
 
232
                break;
 
233
            default:
 
234
                /* XXX: check this */
 
235
                d->devaddr = buf[1] & 0xf;
 
236
                d->handler = buf[2];
 
237
                break;
 
238
            }
 
239
        }
 
240
        break;
 
241
    case ADB_READREG:
 
242
        switch(reg) {
 
243
        case 0:
 
244
            olen = adb_kbd_poll(d, obuf);
 
245
            break;
 
246
        case 1:
 
247
            break;
 
248
        case 2:
 
249
            obuf[0] = 0x00; /* XXX: check this */
 
250
            obuf[1] = 0x07; /* led status */
 
251
            olen = 2;
 
252
            break;
 
253
        case 3:
 
254
            obuf[0] = d->handler;
 
255
            obuf[1] = d->devaddr;
 
256
            olen = 2;
 
257
            break;
 
258
        }
 
259
        break;
 
260
    }
 
261
    return olen;
 
262
}
 
263
 
 
264
static 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
};
 
277
 
 
278
static 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
 
 
289
void adb_kbd_init(ADBBusState *bus)
 
290
{
 
291
    ADBDevice *d;
 
292
    KBDState *s;
 
293
    s = qemu_mallocz(sizeof(KBDState));
 
294
    d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request,
 
295
                            adb_kbd_reset, s);
 
296
    qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
 
297
    vmstate_register(NULL, -1, &vmstate_adb_kbd, s);
 
298
}
 
299
 
 
300
/***************************************************************/
 
301
/* Mouse ADB device */
 
302
 
 
303
typedef struct MouseState {
 
304
    int buttons_state, last_buttons_state;
 
305
    int dx, dy, dz;
 
306
} MouseState;
 
307
 
 
308
static void adb_mouse_event(void *opaque,
 
309
                            int dx1, int dy1, int dz1, int buttons_state)
 
310
{
 
311
    ADBDevice *d = opaque;
 
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
 
 
321
static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
 
322
{
 
323
    MouseState *s = d->opaque;
 
324
    int dx, dy;
 
325
 
 
326
    if (s->last_buttons_state == s->buttons_state &&
 
327
        s->dx == 0 && s->dy == 0)
 
328
        return 0;
 
329
 
 
330
    dx = s->dx;
 
331
    if (dx < -63)
 
332
        dx = -63;
 
333
    else if (dx > 63)
 
334
        dx = 63;
 
335
 
 
336
    dy = s->dy;
 
337
    if (dy < -63)
 
338
        dy = -63;
 
339
    else if (dy > 63)
 
340
        dy = 63;
 
341
 
 
342
    s->dx -= dx;
 
343
    s->dy -= dy;
 
344
    s->last_buttons_state = s->buttons_state;
 
345
 
 
346
    dx &= 0x7f;
 
347
    dy &= 0x7f;
 
348
 
 
349
    if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
 
350
        dy |= 0x80;
 
351
    if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
 
352
        dx |= 0x80;
 
353
 
 
354
    obuf[0] = dy;
 
355
    obuf[1] = dx;
 
356
    return 2;
 
357
}
 
358
 
 
359
static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
 
360
                             const uint8_t *buf, int len)
 
361
{
 
362
    MouseState *s = d->opaque;
 
363
    int cmd, reg, olen;
 
364
 
 
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;
 
372
    }
 
373
 
 
374
    cmd = buf[0] & 0xc;
 
375
    reg = buf[0] & 0x3;
 
376
    olen = 0;
 
377
    switch(cmd) {
 
378
    case ADB_WRITEREG:
 
379
        ADB_DPRINTF("write reg %d val 0x%2.2x\n", reg, buf[1]);
 
380
        switch(reg) {
 
381
        case 2:
 
382
            break;
 
383
        case 3:
 
384
            switch(buf[2]) {
 
385
            case ADB_CMD_SELF_TEST:
 
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;
 
391
                break;
 
392
            default:
 
393
                /* XXX: check this */
 
394
                d->devaddr = buf[1] & 0xf;
 
395
                break;
 
396
            }
 
397
        }
 
398
        break;
 
399
    case ADB_READREG:
 
400
        switch(reg) {
 
401
        case 0:
 
402
            olen = adb_mouse_poll(d, obuf);
 
403
            break;
 
404
        case 1:
 
405
            break;
 
406
        case 3:
 
407
            obuf[0] = d->handler;
 
408
            obuf[1] = d->devaddr;
 
409
            olen = 2;
 
410
            break;
 
411
        }
 
412
        ADB_DPRINTF("read reg %d obuf[0] 0x%2.2x obuf[1] 0x%2.2x\n", reg,
 
413
                    obuf[0], obuf[1]);
 
414
        break;
 
415
    }
 
416
    return olen;
 
417
}
 
418
 
 
419
static 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
 
 
430
static 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
};
 
444
 
 
445
void adb_mouse_init(ADBBusState *bus)
 
446
{
 
447
    ADBDevice *d;
 
448
    MouseState *s;
 
449
 
 
450
    s = qemu_mallocz(sizeof(MouseState));
 
451
    d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request,
 
452
                            adb_mouse_reset, s);
 
453
    qemu_add_mouse_event_handler(adb_mouse_event, d, 0, "QEMU ADB Mouse");
 
454
    vmstate_register(NULL, -1, &vmstate_adb_mouse, s);
 
455
}