~vcs-imports/qemu/git

« back to all changes in this revision

Viewing changes to hw/baum.c

  • Committer: blueswir1
  • Date: 2007-09-25 17:28:42 UTC
  • Revision ID: git-v1:c2efc95d45fd4c76d4650a34a2a2676b87a93ac4
 Fix monitor expressions


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3238 c046a42c-6fe2-441c-8c8c-71466251a162

Show diffs side-by-side

added added

removed removed

Lines of Context:
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 <assert.h>
29
 
#include <brlapi.h>
30
 
#include <brlapi_constants.h>
31
 
#include <brlapi_keycodes.h>
32
 
#ifdef CONFIG_SDL
33
 
#include <SDL/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
 
    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) + ticks_per_sec / 10);
339
 
        for (i = 0; i < baum->x * baum->y ; i++) {
340
 
            EAT(c);
341
 
            cells[i] = c;
342
 
            if ((c & (BRLAPI_DOT7|BRLAPI_DOT8))
343
 
                    == (BRLAPI_DOT7|BRLAPI_DOT8)) {
344
 
                cursor = i + 1;
345
 
                c &= ~(BRLAPI_DOT7|BRLAPI_DOT8);
346
 
            }
347
 
            if (!(c = nabcc_translation[c]))
348
 
                c = '?';
349
 
            text[i] = c;
350
 
        }
351
 
        qemu_del_timer(baum->cellCount_timer);
352
 
 
353
 
        memset(zero, 0, sizeof(zero));
354
 
 
355
 
        brlapi_writeArguments_t wa = {
356
 
            .displayNumber = BRLAPI_DISPLAY_DEFAULT,
357
 
            .regionBegin = 1,
358
 
            .regionSize = baum->x * baum->y,
359
 
            .text = text,
360
 
            .textSize = baum->x * baum->y,
361
 
            .andMask = zero,
362
 
            .orMask = cells,
363
 
            .cursor = cursor,
364
 
            .charset = "ISO-8859-1",
365
 
        };
366
 
 
367
 
        if (brlapi__write(baum->brlapi, &wa) == -1)
368
 
            brlapi_perror("baum brlapi_write");
369
 
        break;
370
 
    }
371
 
    case BAUM_REQ_SetMode:
372
 
    {
373
 
        uint8_t mode, setting;
374
 
        DPRINTF("SetMode\n");
375
 
        EAT(mode);
376
 
        EAT(setting);
377
 
        /* ignore */
378
 
        break;
379
 
    }
380
 
    case BAUM_REQ_SetProtocol:
381
 
    {
382
 
        uint8_t protocol;
383
 
        DPRINTF("SetProtocol\n");
384
 
        EAT(protocol);
385
 
        /* ignore */
386
 
        break;
387
 
    }
388
 
    case BAUM_REQ_GetDeviceIdentity:
389
 
    {
390
 
        uint8_t identity[17] = { BAUM_RSP_DeviceIdentity,
391
 
            'B','a','u','m',' ','V','a','r','i','o' };
392
 
        DPRINTF("GetDeviceIdentity\n");
393
 
        identity[11] = '0' + baum->x / 10;
394
 
        identity[12] = '0' + baum->x % 10;
395
 
        baum_write_packet(baum, identity, sizeof(identity));
396
 
        break;
397
 
    }
398
 
    case BAUM_REQ_GetVersionNumber:
399
 
    {
400
 
        uint8_t version[] = { BAUM_RSP_VersionNumber, 1 }; /* ? */
401
 
        DPRINTF("GetVersionNumber\n");
402
 
        baum_write_packet(baum, version, sizeof(version));
403
 
        break;
404
 
    }
405
 
    case BAUM_REQ_GetSerialNumber:
406
 
    {
407
 
        uint8_t serial[] = { BAUM_RSP_SerialNumber,
408
 
            '0','0','0','0','0','0','0','0' };
409
 
        DPRINTF("GetSerialNumber\n");
410
 
        baum_write_packet(baum, serial, sizeof(serial));
411
 
        break;
412
 
    }
413
 
    case BAUM_REQ_GetKeys:
414
 
    {
415
 
        DPRINTF("Get%0#2x\n", req);
416
 
        /* ignore */
417
 
        break;
418
 
    }
419
 
    default:
420
 
        DPRINTF("unrecognized request %0#2x\n", req);
421
 
        do
422
 
            if (!len--)
423
 
                return 0;
424
 
        while (*cur++ != ESC);
425
 
        cur--;
426
 
        break;
427
 
    }
428
 
    return cur - buf;
429
 
}
430
 
 
431
 
/* The other end is writing some data.  Store it and try to interpret */
432
 
static int baum_write(CharDriverState *chr, const uint8_t *buf, int len)
433
 
{
434
 
    BaumDriverState *baum = chr->opaque;
435
 
    int tocopy, cur, eaten, orig_len = len;
436
 
 
437
 
    if (!len)
438
 
        return 0;
439
 
    if (!baum->brlapi)
440
 
        return len;
441
 
 
442
 
    while (len) {
443
 
        /* Complete our buffer as much as possible */
444
 
        tocopy = len;
445
 
        if (tocopy > BUF_SIZE - baum->in_buf_used)
446
 
            tocopy = BUF_SIZE - baum->in_buf_used;
447
 
 
448
 
        memcpy(baum->in_buf + baum->in_buf_used, buf, tocopy);
449
 
        baum->in_buf_used += tocopy;
450
 
        buf += tocopy;
451
 
        len -= tocopy;
452
 
 
453
 
        /* Interpret it as much as possible */
454
 
        cur = 0;
455
 
        while (cur < baum->in_buf_used &&
456
 
                (eaten = baum_eat_packet(baum, baum->in_buf + cur, baum->in_buf_used - cur)))
457
 
            cur += eaten;
458
 
 
459
 
        /* Shift the remainder */
460
 
        if (cur) {
461
 
            memmove(baum->in_buf, baum->in_buf + cur, baum->in_buf_used - cur);
462
 
            baum->in_buf_used -= cur;
463
 
        }
464
 
 
465
 
        /* And continue if any data left */
466
 
    }
467
 
    return orig_len;
468
 
}
469
 
 
470
 
/* The other end sent us some event */
471
 
static void baum_send_event(CharDriverState *chr, int event)
472
 
{
473
 
    BaumDriverState *baum = chr->opaque;
474
 
    switch (event) {
475
 
    case CHR_EVENT_BREAK:
476
 
        break;
477
 
    case CHR_EVENT_RESET:
478
 
        /* Reset state */
479
 
        baum->in_buf_used = 0;
480
 
        break;
481
 
    }
482
 
}
483
 
 
484
 
/* Send the key code to the other end */
485
 
static void baum_send_key(BaumDriverState *baum, uint8_t type, uint8_t value) {
486
 
    uint8_t packet[] = { type, value };
487
 
    DPRINTF("writing key %x %x\n", type, value);
488
 
    baum_write_packet(baum, packet, sizeof(packet));
489
 
}
490
 
 
491
 
/* We got some data on the BrlAPI socket */
492
 
static void baum_chr_read(void *opaque)
493
 
{
494
 
    BaumDriverState *baum = opaque;
495
 
    brlapi_keyCode_t code;
496
 
    int ret;
497
 
    if (!baum->brlapi)
498
 
        return;
499
 
    while ((ret = brlapi__readKey(baum->brlapi, 0, &code)) == 1) {
500
 
        DPRINTF("got key %"BRLAPI_PRIxKEYCODE"\n", code);
501
 
        /* Emulate */
502
 
        switch (code & BRLAPI_KEY_TYPE_MASK) {
503
 
        case BRLAPI_KEY_TYPE_CMD:
504
 
            switch (code & BRLAPI_KEY_CMD_BLK_MASK) {
505
 
            case BRLAPI_KEY_CMD_ROUTE:
506
 
                baum_send_key(baum, BAUM_RSP_RoutingKey, (code & BRLAPI_KEY_CMD_ARG_MASK)+1);
507
 
                baum_send_key(baum, BAUM_RSP_RoutingKey, 0);
508
 
                break;
509
 
            case 0:
510
 
                switch (code & BRLAPI_KEY_CMD_ARG_MASK) {
511
 
                case BRLAPI_KEY_CMD_FWINLT:
512
 
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2);
513
 
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
514
 
                    break;
515
 
                case BRLAPI_KEY_CMD_FWINRT:
516
 
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR2);
517
 
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
518
 
                    break;
519
 
                case BRLAPI_KEY_CMD_LNUP:
520
 
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR1);
521
 
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
522
 
                    break;
523
 
                case BRLAPI_KEY_CMD_LNDN:
524
 
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR3);
525
 
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
526
 
                    break;
527
 
                case BRLAPI_KEY_CMD_TOP:
528
 
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL1|BAUM_TR1);
529
 
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
530
 
                    break;
531
 
                case BRLAPI_KEY_CMD_BOT:
532
 
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL3|BAUM_TR3);
533
 
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
534
 
                    break;
535
 
                case BRLAPI_KEY_CMD_TOP_LEFT:
536
 
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR1);
537
 
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
538
 
                    break;
539
 
                case BRLAPI_KEY_CMD_BOT_LEFT:
540
 
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR3);
541
 
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
542
 
                    break;
543
 
                case BRLAPI_KEY_CMD_HOME:
544
 
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR1|BAUM_TR3);
545
 
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
546
 
                    break;
547
 
                case BRLAPI_KEY_CMD_PREFMENU:
548
 
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL1|BAUM_TL3|BAUM_TR1);
549
 
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
550
 
                    break;
551
 
                }
552
 
            }
553
 
            break;
554
 
        case BRLAPI_KEY_TYPE_SYM:
555
 
            break;
556
 
        }
557
 
    }
558
 
    if (ret == -1 && (brlapi_errno != BRLAPI_ERROR_LIBCERR || errno != EINTR)) {
559
 
        brlapi_perror("baum: brlapi_readKey");
560
 
        brlapi__closeConnection(baum->brlapi);
561
 
        free(baum->brlapi);
562
 
        baum->brlapi = NULL;
563
 
    }
564
 
}
565
 
 
566
 
CharDriverState *chr_baum_init(void)
567
 
{
568
 
    BaumDriverState *baum;
569
 
    CharDriverState *chr;
570
 
    brlapi_handle_t *handle;
571
 
#ifdef CONFIG_SDL
572
 
    SDL_SysWMinfo info;
573
 
#endif
574
 
    int tty;
575
 
 
576
 
    baum = qemu_mallocz(sizeof(BaumDriverState));
577
 
    if (!baum)
578
 
        return NULL;
579
 
 
580
 
    baum->chr = chr = qemu_mallocz(sizeof(CharDriverState));
581
 
    if (!chr)
582
 
        goto fail_baum;
583
 
 
584
 
    chr->opaque = baum;
585
 
    chr->chr_write = baum_write;
586
 
    chr->chr_send_event = baum_send_event;
587
 
    chr->chr_accept_input = baum_accept_input;
588
 
 
589
 
    handle = qemu_mallocz(brlapi_getHandleSize());
590
 
    if (!handle)
591
 
        goto fail_chr;
592
 
    baum->brlapi = handle;
593
 
 
594
 
    baum->brlapi_fd = brlapi__openConnection(handle, NULL, NULL);
595
 
    if (baum->brlapi_fd == -1) {
596
 
        brlapi_perror("baum_init: brlapi_openConnection");
597
 
        goto fail_handle;
598
 
    }
599
 
 
600
 
    baum->cellCount_timer = qemu_new_timer(vm_clock, baum_cellCount_timer_cb, baum);
601
 
 
602
 
    if (brlapi__getDisplaySize(handle, &baum->x, &baum->y) == -1) {
603
 
        brlapi_perror("baum_init: brlapi_getDisplaySize");
604
 
        goto fail;
605
 
    }
606
 
 
607
 
#ifdef CONFIG_SDL
608
 
    memset(&info, 0, sizeof(info));
609
 
    SDL_VERSION(&info.version);
610
 
    if (SDL_GetWMInfo(&info))
611
 
        tty = info.info.x11.wmwindow;
612
 
    else
613
 
#endif
614
 
        tty = BRLAPI_TTY_DEFAULT;
615
 
 
616
 
    if (brlapi__enterTtyMode(handle, tty, NULL) == -1) {
617
 
        brlapi_perror("baum_init: brlapi_enterTtyMode");
618
 
        goto fail;
619
 
    }
620
 
 
621
 
    qemu_set_fd_handler(baum->brlapi_fd, baum_chr_read, NULL, baum);
622
 
 
623
 
    qemu_chr_reset(chr);
624
 
 
625
 
    return chr;
626
 
 
627
 
fail:
628
 
    qemu_free_timer(baum->cellCount_timer);
629
 
    brlapi__closeConnection(handle);
630
 
fail_handle:
631
 
    free(handle);
632
 
fail_chr:
633
 
    free(chr);
634
 
fail_baum:
635
 
    free(baum);
636
 
    return NULL;
637
 
}
638
 
 
639
 
USBDevice *usb_baum_init(void)
640
 
{
641
 
    /* USB Product ID of Super Vario 40 */
642
 
    return usb_serial_init("productid=FE72:braille");
643
 
}