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

« back to all changes in this revision

Viewing changes to hw/baum.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 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_ns(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_OPENED:
 
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
        qemu_free(baum->brlapi);
 
563
        baum->brlapi = NULL;
 
564
    }
 
565
}
 
566
 
 
567
static void baum_close(struct CharDriverState *chr)
 
568
{
 
569
    BaumDriverState *baum = chr->opaque;
 
570
 
 
571
    qemu_free_timer(baum->cellCount_timer);
 
572
    if (baum->brlapi) {
 
573
        brlapi__closeConnection(baum->brlapi);
 
574
        qemu_free(baum->brlapi);
 
575
    }
 
576
    qemu_free(baum);
 
577
}
 
578
 
 
579
int chr_baum_init(QemuOpts *opts, CharDriverState **_chr)
 
580
{
 
581
    BaumDriverState *baum;
 
582
    CharDriverState *chr;
 
583
    brlapi_handle_t *handle;
 
584
#ifdef CONFIG_SDL
 
585
    SDL_SysWMinfo info;
 
586
#endif
 
587
    int tty;
 
588
 
 
589
    baum = qemu_mallocz(sizeof(BaumDriverState));
 
590
    baum->chr = chr = qemu_mallocz(sizeof(CharDriverState));
 
591
 
 
592
    chr->opaque = baum;
 
593
    chr->chr_write = baum_write;
 
594
    chr->chr_send_event = baum_send_event;
 
595
    chr->chr_accept_input = baum_accept_input;
 
596
    chr->chr_close = baum_close;
 
597
 
 
598
    handle = qemu_mallocz(brlapi_getHandleSize());
 
599
    baum->brlapi = handle;
 
600
 
 
601
    baum->brlapi_fd = brlapi__openConnection(handle, NULL, NULL);
 
602
    if (baum->brlapi_fd == -1) {
 
603
        brlapi_perror("baum_init: brlapi_openConnection");
 
604
        goto fail_handle;
 
605
    }
 
606
 
 
607
    baum->cellCount_timer = qemu_new_timer_ns(vm_clock, baum_cellCount_timer_cb, baum);
 
608
 
 
609
    if (brlapi__getDisplaySize(handle, &baum->x, &baum->y) == -1) {
 
610
        brlapi_perror("baum_init: brlapi_getDisplaySize");
 
611
        goto fail;
 
612
    }
 
613
 
 
614
#ifdef CONFIG_SDL
 
615
    memset(&info, 0, sizeof(info));
 
616
    SDL_VERSION(&info.version);
 
617
    if (SDL_GetWMInfo(&info))
 
618
        tty = info.info.x11.wmwindow;
 
619
    else
 
620
#endif
 
621
        tty = BRLAPI_TTY_DEFAULT;
 
622
 
 
623
    if (brlapi__enterTtyMode(handle, tty, NULL) == -1) {
 
624
        brlapi_perror("baum_init: brlapi_enterTtyMode");
 
625
        goto fail;
 
626
    }
 
627
 
 
628
    qemu_set_fd_handler(baum->brlapi_fd, baum_chr_read, NULL, baum);
 
629
 
 
630
    qemu_chr_generic_open(chr);
 
631
 
 
632
    *_chr = chr;
 
633
    return 0;
 
634
 
 
635
fail:
 
636
    qemu_free_timer(baum->cellCount_timer);
 
637
    brlapi__closeConnection(handle);
 
638
fail_handle:
 
639
    qemu_free(handle);
 
640
    qemu_free(chr);
 
641
    qemu_free(baum);
 
642
    return -EIO;
 
643
}