Statistics
| Branch: | Revision:

root / hw / baum.c @ 6ee093c9

History | View | Annotate | Download (19.8 kB)

1
/*
2
 * QEMU Baum Braille Device
3
 *
4
 * Copyright (c) 2008 Samuel Thibault
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 "qemu-common.h"
25
#include "qemu-char.h"
26
#include "qemu-timer.h"
27
#include "usb.h"
28
#include "baum.h"
29
#include <brlapi.h>
30
#include <brlapi_constants.h>
31
#include <brlapi_keycodes.h>
32
#ifdef CONFIG_SDL
33
#include <SDL_syswm.h>
34
#endif
35

    
36
#if 0
37
#define DPRINTF(fmt, ...) \
38
        printf(fmt, ## __VA_ARGS__)
39
#else
40
#define DPRINTF(fmt, ...)
41
#endif
42

    
43
#define ESC 0x1B
44

    
45
#define BAUM_REQ_DisplayData                0x01
46
#define BAUM_REQ_GetVersionNumber        0x05
47
#define BAUM_REQ_GetKeys                0x08
48
#define BAUM_REQ_SetMode                0x12
49
#define BAUM_REQ_SetProtocol                0x15
50
#define BAUM_REQ_GetDeviceIdentity        0x84
51
#define BAUM_REQ_GetSerialNumber        0x8A
52

    
53
#define BAUM_RSP_CellCount                0x01
54
#define BAUM_RSP_VersionNumber                0x05
55
#define BAUM_RSP_ModeSetting                0x11
56
#define BAUM_RSP_CommunicationChannel        0x16
57
#define BAUM_RSP_PowerdownSignal        0x17
58
#define BAUM_RSP_HorizontalSensors        0x20
59
#define BAUM_RSP_VerticalSensors        0x21
60
#define BAUM_RSP_RoutingKeys                0x22
61
#define BAUM_RSP_Switches                0x23
62
#define BAUM_RSP_TopKeys                0x24
63
#define BAUM_RSP_HorizontalSensor        0x25
64
#define BAUM_RSP_VerticalSensor                0x26
65
#define BAUM_RSP_RoutingKey                0x27
66
#define BAUM_RSP_FrontKeys6                0x28
67
#define BAUM_RSP_BackKeys6                0x29
68
#define BAUM_RSP_CommandKeys                0x2B
69
#define BAUM_RSP_FrontKeys10                0x2C
70
#define BAUM_RSP_BackKeys10                0x2D
71
#define BAUM_RSP_EntryKeys                0x33
72
#define BAUM_RSP_JoyStick                0x34
73
#define BAUM_RSP_ErrorCode                0x40
74
#define BAUM_RSP_InfoBlock                0x42
75
#define BAUM_RSP_DeviceIdentity                0x84
76
#define BAUM_RSP_SerialNumber                0x8A
77
#define BAUM_RSP_BluetoothName                0x8C
78

    
79
#define BAUM_TL1 0x01
80
#define BAUM_TL2 0x02
81
#define BAUM_TL3 0x04
82
#define BAUM_TR1 0x08
83
#define BAUM_TR2 0x10
84
#define BAUM_TR3 0x20
85

    
86
#define BUF_SIZE 256
87

    
88
typedef struct {
89
    CharDriverState *chr;
90

    
91
    brlapi_handle_t *brlapi;
92
    int brlapi_fd;
93
    unsigned int x, y;
94

    
95
    uint8_t in_buf[BUF_SIZE];
96
    uint8_t in_buf_used;
97
    uint8_t out_buf[BUF_SIZE];
98
    uint8_t out_buf_used, out_buf_ptr;
99

    
100
    QEMUTimer *cellCount_timer;
101
} BaumDriverState;
102

    
103
/* Let's assume NABCC by default */
104
static const uint8_t nabcc_translation[256] = {
105
    [0] = ' ',
106
#ifndef BRLAPI_DOTS
107
#define BRLAPI_DOTS(d1,d2,d3,d4,d5,d6,d7,d8) \
108
    ((d1?BRLAPI_DOT1:0)|\
109
     (d2?BRLAPI_DOT2:0)|\
110
     (d3?BRLAPI_DOT3:0)|\
111
     (d4?BRLAPI_DOT4:0)|\
112
     (d5?BRLAPI_DOT5:0)|\
113
     (d6?BRLAPI_DOT6:0)|\
114
     (d7?BRLAPI_DOT7:0)|\
115
     (d8?BRLAPI_DOT8:0))
116
#endif
117
    [BRLAPI_DOTS(1,0,0,0,0,0,0,0)] = 'a',
118
    [BRLAPI_DOTS(1,1,0,0,0,0,0,0)] = 'b',
119
    [BRLAPI_DOTS(1,0,0,1,0,0,0,0)] = 'c',
120
    [BRLAPI_DOTS(1,0,0,1,1,0,0,0)] = 'd',
121
    [BRLAPI_DOTS(1,0,0,0,1,0,0,0)] = 'e',
122
    [BRLAPI_DOTS(1,1,0,1,0,0,0,0)] = 'f',
123
    [BRLAPI_DOTS(1,1,0,1,1,0,0,0)] = 'g',
124
    [BRLAPI_DOTS(1,1,0,0,1,0,0,0)] = 'h',
125
    [BRLAPI_DOTS(0,1,0,1,0,0,0,0)] = 'i',
126
    [BRLAPI_DOTS(0,1,0,1,1,0,0,0)] = 'j',
127
    [BRLAPI_DOTS(1,0,1,0,0,0,0,0)] = 'k',
128
    [BRLAPI_DOTS(1,1,1,0,0,0,0,0)] = 'l',
129
    [BRLAPI_DOTS(1,0,1,1,0,0,0,0)] = 'm',
130
    [BRLAPI_DOTS(1,0,1,1,1,0,0,0)] = 'n',
131
    [BRLAPI_DOTS(1,0,1,0,1,0,0,0)] = 'o',
132
    [BRLAPI_DOTS(1,1,1,1,0,0,0,0)] = 'p',
133
    [BRLAPI_DOTS(1,1,1,1,1,0,0,0)] = 'q',
134
    [BRLAPI_DOTS(1,1,1,0,1,0,0,0)] = 'r',
135
    [BRLAPI_DOTS(0,1,1,1,0,0,0,0)] = 's',
136
    [BRLAPI_DOTS(0,1,1,1,1,0,0,0)] = 't',
137
    [BRLAPI_DOTS(1,0,1,0,0,1,0,0)] = 'u',
138
    [BRLAPI_DOTS(1,1,1,0,0,1,0,0)] = 'v',
139
    [BRLAPI_DOTS(0,1,0,1,1,1,0,0)] = 'w',
140
    [BRLAPI_DOTS(1,0,1,1,0,1,0,0)] = 'x',
141
    [BRLAPI_DOTS(1,0,1,1,1,1,0,0)] = 'y',
142
    [BRLAPI_DOTS(1,0,1,0,1,1,0,0)] = 'z',
143

    
144
    [BRLAPI_DOTS(1,0,0,0,0,0,1,0)] = 'A',
145
    [BRLAPI_DOTS(1,1,0,0,0,0,1,0)] = 'B',
146
    [BRLAPI_DOTS(1,0,0,1,0,0,1,0)] = 'C',
147
    [BRLAPI_DOTS(1,0,0,1,1,0,1,0)] = 'D',
148
    [BRLAPI_DOTS(1,0,0,0,1,0,1,0)] = 'E',
149
    [BRLAPI_DOTS(1,1,0,1,0,0,1,0)] = 'F',
150
    [BRLAPI_DOTS(1,1,0,1,1,0,1,0)] = 'G',
151
    [BRLAPI_DOTS(1,1,0,0,1,0,1,0)] = 'H',
152
    [BRLAPI_DOTS(0,1,0,1,0,0,1,0)] = 'I',
153
    [BRLAPI_DOTS(0,1,0,1,1,0,1,0)] = 'J',
154
    [BRLAPI_DOTS(1,0,1,0,0,0,1,0)] = 'K',
155
    [BRLAPI_DOTS(1,1,1,0,0,0,1,0)] = 'L',
156
    [BRLAPI_DOTS(1,0,1,1,0,0,1,0)] = 'M',
157
    [BRLAPI_DOTS(1,0,1,1,1,0,1,0)] = 'N',
158
    [BRLAPI_DOTS(1,0,1,0,1,0,1,0)] = 'O',
159
    [BRLAPI_DOTS(1,1,1,1,0,0,1,0)] = 'P',
160
    [BRLAPI_DOTS(1,1,1,1,1,0,1,0)] = 'Q',
161
    [BRLAPI_DOTS(1,1,1,0,1,0,1,0)] = 'R',
162
    [BRLAPI_DOTS(0,1,1,1,0,0,1,0)] = 'S',
163
    [BRLAPI_DOTS(0,1,1,1,1,0,1,0)] = 'T',
164
    [BRLAPI_DOTS(1,0,1,0,0,1,1,0)] = 'U',
165
    [BRLAPI_DOTS(1,1,1,0,0,1,1,0)] = 'V',
166
    [BRLAPI_DOTS(0,1,0,1,1,1,1,0)] = 'W',
167
    [BRLAPI_DOTS(1,0,1,1,0,1,1,0)] = 'X',
168
    [BRLAPI_DOTS(1,0,1,1,1,1,1,0)] = 'Y',
169
    [BRLAPI_DOTS(1,0,1,0,1,1,1,0)] = 'Z',
170

    
171
    [BRLAPI_DOTS(0,0,1,0,1,1,0,0)] = '0',
172
    [BRLAPI_DOTS(0,1,0,0,0,0,0,0)] = '1',
173
    [BRLAPI_DOTS(0,1,1,0,0,0,0,0)] = '2',
174
    [BRLAPI_DOTS(0,1,0,0,1,0,0,0)] = '3',
175
    [BRLAPI_DOTS(0,1,0,0,1,1,0,0)] = '4',
176
    [BRLAPI_DOTS(0,1,0,0,0,1,0,0)] = '5',
177
    [BRLAPI_DOTS(0,1,1,0,1,0,0,0)] = '6',
178
    [BRLAPI_DOTS(0,1,1,0,1,1,0,0)] = '7',
179
    [BRLAPI_DOTS(0,1,1,0,0,1,0,0)] = '8',
180
    [BRLAPI_DOTS(0,0,1,0,1,0,0,0)] = '9',
181

    
182
    [BRLAPI_DOTS(0,0,0,1,0,1,0,0)] = '.',
183
    [BRLAPI_DOTS(0,0,1,1,0,1,0,0)] = '+',
184
    [BRLAPI_DOTS(0,0,1,0,0,1,0,0)] = '-',
185
    [BRLAPI_DOTS(1,0,0,0,0,1,0,0)] = '*',
186
    [BRLAPI_DOTS(0,0,1,1,0,0,0,0)] = '/',
187
    [BRLAPI_DOTS(1,1,1,0,1,1,0,0)] = '(',
188
    [BRLAPI_DOTS(0,1,1,1,1,1,0,0)] = ')',
189

    
190
    [BRLAPI_DOTS(1,1,1,1,0,1,0,0)] = '&',
191
    [BRLAPI_DOTS(0,0,1,1,1,1,0,0)] = '#',
192

    
193
    [BRLAPI_DOTS(0,0,0,0,0,1,0,0)] = ',',
194
    [BRLAPI_DOTS(0,0,0,0,1,1,0,0)] = ';',
195
    [BRLAPI_DOTS(1,0,0,0,1,1,0,0)] = ':',
196
    [BRLAPI_DOTS(0,1,1,1,0,1,0,0)] = '!',
197
    [BRLAPI_DOTS(1,0,0,1,1,1,0,0)] = '?',
198
    [BRLAPI_DOTS(0,0,0,0,1,0,0,0)] = '"',
199
    [BRLAPI_DOTS(0,0,1,0,0,0,0,0)] ='\'',
200
    [BRLAPI_DOTS(0,0,0,1,0,0,0,0)] = '`',
201
    [BRLAPI_DOTS(0,0,0,1,1,0,1,0)] = '^',
202
    [BRLAPI_DOTS(0,0,0,1,1,0,0,0)] = '~',
203
    [BRLAPI_DOTS(0,1,0,1,0,1,1,0)] = '[',
204
    [BRLAPI_DOTS(1,1,0,1,1,1,1,0)] = ']',
205
    [BRLAPI_DOTS(0,1,0,1,0,1,0,0)] = '{',
206
    [BRLAPI_DOTS(1,1,0,1,1,1,0,0)] = '}',
207
    [BRLAPI_DOTS(1,1,1,1,1,1,0,0)] = '=',
208
    [BRLAPI_DOTS(1,1,0,0,0,1,0,0)] = '<',
209
    [BRLAPI_DOTS(0,0,1,1,1,0,0,0)] = '>',
210
    [BRLAPI_DOTS(1,1,0,1,0,1,0,0)] = '$',
211
    [BRLAPI_DOTS(1,0,0,1,0,1,0,0)] = '%',
212
    [BRLAPI_DOTS(0,0,0,1,0,0,1,0)] = '@',
213
    [BRLAPI_DOTS(1,1,0,0,1,1,0,0)] = '|',
214
    [BRLAPI_DOTS(1,1,0,0,1,1,1,0)] ='\\',
215
    [BRLAPI_DOTS(0,0,0,1,1,1,0,0)] = '_',
216
};
217

    
218
/* The serial port can receive more of our data */
219
static void baum_accept_input(struct CharDriverState *chr)
220
{
221
    BaumDriverState *baum = chr->opaque;
222
    int room, first;
223

    
224
    if (!baum->out_buf_used)
225
        return;
226
    room = qemu_chr_can_read(chr);
227
    if (!room)
228
        return;
229
    if (room > baum->out_buf_used)
230
        room = baum->out_buf_used;
231

    
232
    first = BUF_SIZE - baum->out_buf_ptr;
233
    if (room > first) {
234
        qemu_chr_read(chr, baum->out_buf + baum->out_buf_ptr, first);
235
        baum->out_buf_ptr = 0;
236
        baum->out_buf_used -= first;
237
        room -= first;
238
    }
239
    qemu_chr_read(chr, baum->out_buf + baum->out_buf_ptr, room);
240
    baum->out_buf_ptr += room;
241
    baum->out_buf_used -= room;
242
}
243

    
244
/* We want to send a packet */
245
static void baum_write_packet(BaumDriverState *baum, const uint8_t *buf, int len)
246
{
247
    uint8_t io_buf[1 + 2 * len], *cur = io_buf;
248
    int room;
249
    *cur++ = ESC;
250
    while (len--)
251
        if ((*cur++ = *buf++) == ESC)
252
            *cur++ = ESC;
253
    room = qemu_chr_can_read(baum->chr);
254
    len = cur - io_buf;
255
    if (len <= room) {
256
        /* Fits */
257
        qemu_chr_read(baum->chr, io_buf, len);
258
    } else {
259
        int first;
260
        uint8_t out;
261
        /* Can't fit all, send what can be, and store the rest. */
262
        qemu_chr_read(baum->chr, io_buf, room);
263
        len -= room;
264
        cur = io_buf + room;
265
        if (len > BUF_SIZE - baum->out_buf_used) {
266
            /* Can't even store it, drop the previous data... */
267
            assert(len <= BUF_SIZE);
268
            baum->out_buf_used = 0;
269
            baum->out_buf_ptr = 0;
270
        }
271
        out = baum->out_buf_ptr;
272
        baum->out_buf_used += len;
273
        first = BUF_SIZE - baum->out_buf_ptr;
274
        if (len > first) {
275
            memcpy(baum->out_buf + out, cur, first);
276
            out = 0;
277
            len -= first;
278
            cur += first;
279
        }
280
        memcpy(baum->out_buf + out, cur, len);
281
    }
282
}
283

    
284
/* Called when the other end seems to have a wrong idea of our display size */
285
static void baum_cellCount_timer_cb(void *opaque)
286
{
287
    BaumDriverState *baum = opaque;
288
    uint8_t cell_count[] = { BAUM_RSP_CellCount, baum->x * baum->y };
289
    DPRINTF("Timeout waiting for DisplayData, sending cell count\n");
290
    baum_write_packet(baum, cell_count, sizeof(cell_count));
291
}
292

    
293
/* Try to interpret a whole incoming packet */
294
static int baum_eat_packet(BaumDriverState *baum, const uint8_t *buf, int len)
295
{
296
    const uint8_t *cur = buf;
297
    uint8_t req = 0;
298

    
299
    if (!len--)
300
        return 0;
301
    if (*cur++ != ESC) {
302
        while (*cur != ESC) {
303
            if (!len--)
304
                return 0;
305
            cur++;
306
        }
307
        DPRINTF("Dropped %d bytes!\n", cur - buf);
308
    }
309

    
310
#define EAT(c) do {\
311
    if (!len--) \
312
        return 0; \
313
    if ((c = *cur++) == ESC) { \
314
        if (!len--) \
315
            return 0; \
316
        if (*cur++ != ESC) { \
317
            DPRINTF("Broken packet %#2x, tossing\n", req); \
318
                if (qemu_timer_pending(baum->cellCount_timer)) { \
319
                qemu_del_timer(baum->cellCount_timer); \
320
                baum_cellCount_timer_cb(baum); \
321
            } \
322
            return (cur - 2 - buf); \
323
        } \
324
    } \
325
} while (0)
326

    
327
    EAT(req);
328
    switch (req) {
329
    case BAUM_REQ_DisplayData:
330
    {
331
        uint8_t cells[baum->x * baum->y], c;
332
        uint8_t text[baum->x * baum->y];
333
        uint8_t zero[baum->x * baum->y];
334
        int cursor = BRLAPI_CURSOR_OFF;
335
        int i;
336

    
337
        /* Allow 100ms to complete the DisplayData packet */
338
        qemu_mod_timer(baum->cellCount_timer, qemu_get_clock(vm_clock) +
339
                       get_ticks_per_sec() / 10);
340
        for (i = 0; i < baum->x * baum->y ; i++) {
341
            EAT(c);
342
            cells[i] = c;
343
            if ((c & (BRLAPI_DOT7|BRLAPI_DOT8))
344
                    == (BRLAPI_DOT7|BRLAPI_DOT8)) {
345
                cursor = i + 1;
346
                c &= ~(BRLAPI_DOT7|BRLAPI_DOT8);
347
            }
348
            if (!(c = nabcc_translation[c]))
349
                c = '?';
350
            text[i] = c;
351
        }
352
        qemu_del_timer(baum->cellCount_timer);
353

    
354
        memset(zero, 0, sizeof(zero));
355

    
356
        brlapi_writeArguments_t wa = {
357
            .displayNumber = BRLAPI_DISPLAY_DEFAULT,
358
            .regionBegin = 1,
359
            .regionSize = baum->x * baum->y,
360
            .text = (char *)text,
361
            .textSize = baum->x * baum->y,
362
            .andMask = zero,
363
            .orMask = cells,
364
            .cursor = cursor,
365
            .charset = (char *)"ISO-8859-1",
366
        };
367

    
368
        if (brlapi__write(baum->brlapi, &wa) == -1)
369
            brlapi_perror("baum brlapi_write");
370
        break;
371
    }
372
    case BAUM_REQ_SetMode:
373
    {
374
        uint8_t mode, setting;
375
        DPRINTF("SetMode\n");
376
        EAT(mode);
377
        EAT(setting);
378
        /* ignore */
379
        break;
380
    }
381
    case BAUM_REQ_SetProtocol:
382
    {
383
        uint8_t protocol;
384
        DPRINTF("SetProtocol\n");
385
        EAT(protocol);
386
        /* ignore */
387
        break;
388
    }
389
    case BAUM_REQ_GetDeviceIdentity:
390
    {
391
        uint8_t identity[17] = { BAUM_RSP_DeviceIdentity,
392
            'B','a','u','m',' ','V','a','r','i','o' };
393
        DPRINTF("GetDeviceIdentity\n");
394
        identity[11] = '0' + baum->x / 10;
395
        identity[12] = '0' + baum->x % 10;
396
        baum_write_packet(baum, identity, sizeof(identity));
397
        break;
398
    }
399
    case BAUM_REQ_GetVersionNumber:
400
    {
401
        uint8_t version[] = { BAUM_RSP_VersionNumber, 1 }; /* ? */
402
        DPRINTF("GetVersionNumber\n");
403
        baum_write_packet(baum, version, sizeof(version));
404
        break;
405
    }
406
    case BAUM_REQ_GetSerialNumber:
407
    {
408
        uint8_t serial[] = { BAUM_RSP_SerialNumber,
409
            '0','0','0','0','0','0','0','0' };
410
        DPRINTF("GetSerialNumber\n");
411
        baum_write_packet(baum, serial, sizeof(serial));
412
        break;
413
    }
414
    case BAUM_REQ_GetKeys:
415
    {
416
        DPRINTF("Get%0#2x\n", req);
417
        /* ignore */
418
        break;
419
    }
420
    default:
421
        DPRINTF("unrecognized request %0#2x\n", req);
422
        do
423
            if (!len--)
424
                return 0;
425
        while (*cur++ != ESC);
426
        cur--;
427
        break;
428
    }
429
    return cur - buf;
430
}
431

    
432
/* The other end is writing some data.  Store it and try to interpret */
433
static int baum_write(CharDriverState *chr, const uint8_t *buf, int len)
434
{
435
    BaumDriverState *baum = chr->opaque;
436
    int tocopy, cur, eaten, orig_len = len;
437

    
438
    if (!len)
439
        return 0;
440
    if (!baum->brlapi)
441
        return len;
442

    
443
    while (len) {
444
        /* Complete our buffer as much as possible */
445
        tocopy = len;
446
        if (tocopy > BUF_SIZE - baum->in_buf_used)
447
            tocopy = BUF_SIZE - baum->in_buf_used;
448

    
449
        memcpy(baum->in_buf + baum->in_buf_used, buf, tocopy);
450
        baum->in_buf_used += tocopy;
451
        buf += tocopy;
452
        len -= tocopy;
453

    
454
        /* Interpret it as much as possible */
455
        cur = 0;
456
        while (cur < baum->in_buf_used &&
457
                (eaten = baum_eat_packet(baum, baum->in_buf + cur, baum->in_buf_used - cur)))
458
            cur += eaten;
459

    
460
        /* Shift the remainder */
461
        if (cur) {
462
            memmove(baum->in_buf, baum->in_buf + cur, baum->in_buf_used - cur);
463
            baum->in_buf_used -= cur;
464
        }
465

    
466
        /* And continue if any data left */
467
    }
468
    return orig_len;
469
}
470

    
471
/* The other end sent us some event */
472
static void baum_send_event(CharDriverState *chr, int event)
473
{
474
    BaumDriverState *baum = chr->opaque;
475
    switch (event) {
476
    case CHR_EVENT_BREAK:
477
        break;
478
    case CHR_EVENT_RESET:
479
        /* Reset state */
480
        baum->in_buf_used = 0;
481
        break;
482
    }
483
}
484

    
485
/* Send the key code to the other end */
486
static void baum_send_key(BaumDriverState *baum, uint8_t type, uint8_t value) {
487
    uint8_t packet[] = { type, value };
488
    DPRINTF("writing key %x %x\n", type, value);
489
    baum_write_packet(baum, packet, sizeof(packet));
490
}
491

    
492
/* We got some data on the BrlAPI socket */
493
static void baum_chr_read(void *opaque)
494
{
495
    BaumDriverState *baum = opaque;
496
    brlapi_keyCode_t code;
497
    int ret;
498
    if (!baum->brlapi)
499
        return;
500
    while ((ret = brlapi__readKey(baum->brlapi, 0, &code)) == 1) {
501
        DPRINTF("got key %"BRLAPI_PRIxKEYCODE"\n", code);
502
        /* Emulate */
503
        switch (code & BRLAPI_KEY_TYPE_MASK) {
504
        case BRLAPI_KEY_TYPE_CMD:
505
            switch (code & BRLAPI_KEY_CMD_BLK_MASK) {
506
            case BRLAPI_KEY_CMD_ROUTE:
507
                baum_send_key(baum, BAUM_RSP_RoutingKey, (code & BRLAPI_KEY_CMD_ARG_MASK)+1);
508
                baum_send_key(baum, BAUM_RSP_RoutingKey, 0);
509
                break;
510
            case 0:
511
                switch (code & BRLAPI_KEY_CMD_ARG_MASK) {
512
                case BRLAPI_KEY_CMD_FWINLT:
513
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2);
514
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
515
                    break;
516
                case BRLAPI_KEY_CMD_FWINRT:
517
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR2);
518
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
519
                    break;
520
                case BRLAPI_KEY_CMD_LNUP:
521
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR1);
522
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
523
                    break;
524
                case BRLAPI_KEY_CMD_LNDN:
525
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR3);
526
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
527
                    break;
528
                case BRLAPI_KEY_CMD_TOP:
529
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL1|BAUM_TR1);
530
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
531
                    break;
532
                case BRLAPI_KEY_CMD_BOT:
533
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL3|BAUM_TR3);
534
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
535
                    break;
536
                case BRLAPI_KEY_CMD_TOP_LEFT:
537
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR1);
538
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
539
                    break;
540
                case BRLAPI_KEY_CMD_BOT_LEFT:
541
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR3);
542
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
543
                    break;
544
                case BRLAPI_KEY_CMD_HOME:
545
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR1|BAUM_TR3);
546
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
547
                    break;
548
                case BRLAPI_KEY_CMD_PREFMENU:
549
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL1|BAUM_TL3|BAUM_TR1);
550
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
551
                    break;
552
                }
553
            }
554
            break;
555
        case BRLAPI_KEY_TYPE_SYM:
556
            break;
557
        }
558
    }
559
    if (ret == -1 && (brlapi_errno != BRLAPI_ERROR_LIBCERR || errno != EINTR)) {
560
        brlapi_perror("baum: brlapi_readKey");
561
        brlapi__closeConnection(baum->brlapi);
562
        free(baum->brlapi);
563
        baum->brlapi = NULL;
564
    }
565
}
566

    
567
CharDriverState *chr_baum_init(QemuOpts *opts)
568
{
569
    BaumDriverState *baum;
570
    CharDriverState *chr;
571
    brlapi_handle_t *handle;
572
#ifdef CONFIG_SDL
573
    SDL_SysWMinfo info;
574
#endif
575
    int tty;
576

    
577
    baum = qemu_mallocz(sizeof(BaumDriverState));
578
    baum->chr = chr = qemu_mallocz(sizeof(CharDriverState));
579

    
580
    chr->opaque = baum;
581
    chr->chr_write = baum_write;
582
    chr->chr_send_event = baum_send_event;
583
    chr->chr_accept_input = baum_accept_input;
584

    
585
    handle = qemu_mallocz(brlapi_getHandleSize());
586
    baum->brlapi = handle;
587

    
588
    baum->brlapi_fd = brlapi__openConnection(handle, NULL, NULL);
589
    if (baum->brlapi_fd == -1) {
590
        brlapi_perror("baum_init: brlapi_openConnection");
591
        goto fail_handle;
592
    }
593

    
594
    baum->cellCount_timer = qemu_new_timer(vm_clock, baum_cellCount_timer_cb, baum);
595

    
596
    if (brlapi__getDisplaySize(handle, &baum->x, &baum->y) == -1) {
597
        brlapi_perror("baum_init: brlapi_getDisplaySize");
598
        goto fail;
599
    }
600

    
601
#ifdef CONFIG_SDL
602
    memset(&info, 0, sizeof(info));
603
    SDL_VERSION(&info.version);
604
    if (SDL_GetWMInfo(&info))
605
        tty = info.info.x11.wmwindow;
606
    else
607
#endif
608
        tty = BRLAPI_TTY_DEFAULT;
609

    
610
    if (brlapi__enterTtyMode(handle, tty, NULL) == -1) {
611
        brlapi_perror("baum_init: brlapi_enterTtyMode");
612
        goto fail;
613
    }
614

    
615
    qemu_set_fd_handler(baum->brlapi_fd, baum_chr_read, NULL, baum);
616

    
617
    qemu_chr_reset(chr);
618

    
619
    return chr;
620

    
621
fail:
622
    qemu_free_timer(baum->cellCount_timer);
623
    brlapi__closeConnection(handle);
624
fail_handle:
625
    free(handle);
626
    free(chr);
627
    free(baum);
628
    return NULL;
629
}
630

    
631
USBDevice *usb_baum_init(void)
632
{
633
    /* USB Product ID of Super Vario 40 */
634
    return usb_serial_init("productid=FE72:braille");
635
}