~qermit/qemu/usbredir

« back to all changes in this revision

Viewing changes to backends/baum.c

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2013-05-28 08:18:30 UTC
  • mfrom: (1.8.2) (10.1.37 sid)
  • Revision ID: package-import@ubuntu.com-20130528081830-87xl2z9fq516a814
Tags: 1.5.0+dfsg-2ubuntu1
* Merge 1.5.0+dfs-2 from debian unstable.  Remaining changes:
  - debian/control
    * update maintainer
    * remove libiscsi, usb-redir, vde, vnc-jpeg, and libssh2-1-dev
      from build-deps
    * enable rbd
    * add qemu-system and qemu-common B/R to qemu-keymaps
    * add D:udev, R:qemu, R:qemu-common and B:qemu-common to
      qemu-system-common
    * qemu-system-arm, qemu-system-ppc, qemu-system-sparc:
      - add qemu-kvm to Provides
      - add qemu-common, qemu-kvm, kvm to B/R
      - remove openbios-sparc from qemu-system-sparc D
    * qemu-system-x86:
      - add qemu-common to Breaks/Replaces.
      - add cpu-checker to Recommends.
    * qemu-user: add B/R:qemu-kvm
    * qemu-kvm:
      - add armhf armel powerpc sparc to Architecture
      - C/R/P: qemu-kvm-spice
    * add qemu-common package
    * drop qemu-slof which is not packaged in ubuntu
  - add qemu-system-common.links for tap ifup/down scripts and OVMF link.
  - qemu-system-x86.links:
    * remove pxe rom links which are in kvm-ipxe
    * add symlink for kvm.1 manpage
  - debian/rules
    * add kvm-spice symlink to qemu-kvm
    * call dh_installmodules for qemu-system-x86
    * update dh_installinit to install upstart script
    * run dh_installman (Closes: #709241) (cherrypicked from 1.5.0+dfsg-2)
  - Add qemu-utils.links for kvm-* symlinks.
  - Add qemu-system-x86.qemu-kvm.upstart and .default
  - Add qemu-system-x86.modprobe to set nesting=1
  - Add qemu-system-common.preinst to add kvm group
  - qemu-system-common.postinst: remove bad group acl if there, then have
    udev relabel /dev/kvm.
  - Dropped patches:
    * 0001-fix-wrong-output-with-info-chardev-for-tcp-socket.patch
  - Kept patches:
    * expose_vms_qemu64cpu.patch - updated
    * gridcentric patch - updated
    * linaro arm patches from qemu-linaro rebasing branch

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 "sysemu/char.h"
 
26
#include "qemu/timer.h"
 
27
#include "hw/usb.h"
 
28
#include <brlapi.h>
 
29
#include <brlapi_constants.h>
 
30
#include <brlapi_keycodes.h>
 
31
#ifdef CONFIG_SDL
 
32
#include <SDL_syswm.h>
 
33
#endif
 
34
 
 
35
#if 0
 
36
#define DPRINTF(fmt, ...) \
 
37
        printf(fmt, ## __VA_ARGS__)
 
38
#else
 
39
#define DPRINTF(fmt, ...)
 
40
#endif
 
41
 
 
42
#define ESC 0x1B
 
43
 
 
44
#define BAUM_REQ_DisplayData            0x01
 
45
#define BAUM_REQ_GetVersionNumber       0x05
 
46
#define BAUM_REQ_GetKeys                0x08
 
47
#define BAUM_REQ_SetMode                0x12
 
48
#define BAUM_REQ_SetProtocol            0x15
 
49
#define BAUM_REQ_GetDeviceIdentity      0x84
 
50
#define BAUM_REQ_GetSerialNumber        0x8A
 
51
 
 
52
#define BAUM_RSP_CellCount              0x01
 
53
#define BAUM_RSP_VersionNumber          0x05
 
54
#define BAUM_RSP_ModeSetting            0x11
 
55
#define BAUM_RSP_CommunicationChannel   0x16
 
56
#define BAUM_RSP_PowerdownSignal        0x17
 
57
#define BAUM_RSP_HorizontalSensors      0x20
 
58
#define BAUM_RSP_VerticalSensors        0x21
 
59
#define BAUM_RSP_RoutingKeys            0x22
 
60
#define BAUM_RSP_Switches               0x23
 
61
#define BAUM_RSP_TopKeys                0x24
 
62
#define BAUM_RSP_HorizontalSensor       0x25
 
63
#define BAUM_RSP_VerticalSensor         0x26
 
64
#define BAUM_RSP_RoutingKey             0x27
 
65
#define BAUM_RSP_FrontKeys6             0x28
 
66
#define BAUM_RSP_BackKeys6              0x29
 
67
#define BAUM_RSP_CommandKeys            0x2B
 
68
#define BAUM_RSP_FrontKeys10            0x2C
 
69
#define BAUM_RSP_BackKeys10             0x2D
 
70
#define BAUM_RSP_EntryKeys              0x33
 
71
#define BAUM_RSP_JoyStick               0x34
 
72
#define BAUM_RSP_ErrorCode              0x40
 
73
#define BAUM_RSP_InfoBlock              0x42
 
74
#define BAUM_RSP_DeviceIdentity         0x84
 
75
#define BAUM_RSP_SerialNumber           0x8A
 
76
#define BAUM_RSP_BluetoothName          0x8C
 
77
 
 
78
#define BAUM_TL1 0x01
 
79
#define BAUM_TL2 0x02
 
80
#define BAUM_TL3 0x04
 
81
#define BAUM_TR1 0x08
 
82
#define BAUM_TR2 0x10
 
83
#define BAUM_TR3 0x20
 
84
 
 
85
#define BUF_SIZE 256
 
86
 
 
87
typedef struct {
 
88
    CharDriverState *chr;
 
89
 
 
90
    brlapi_handle_t *brlapi;
 
91
    int brlapi_fd;
 
92
    unsigned int x, y;
 
93
 
 
94
    uint8_t in_buf[BUF_SIZE];
 
95
    uint8_t in_buf_used;
 
96
    uint8_t out_buf[BUF_SIZE];
 
97
    uint8_t out_buf_used, out_buf_ptr;
 
98
 
 
99
    QEMUTimer *cellCount_timer;
 
100
} BaumDriverState;
 
101
 
 
102
/* Let's assume NABCC by default */
 
103
static const uint8_t nabcc_translation[256] = {
 
104
    [0] = ' ',
 
105
#ifndef BRLAPI_DOTS
 
106
#define BRLAPI_DOTS(d1,d2,d3,d4,d5,d6,d7,d8) \
 
107
    ((d1?BRLAPI_DOT1:0)|\
 
108
     (d2?BRLAPI_DOT2:0)|\
 
109
     (d3?BRLAPI_DOT3:0)|\
 
110
     (d4?BRLAPI_DOT4:0)|\
 
111
     (d5?BRLAPI_DOT5:0)|\
 
112
     (d6?BRLAPI_DOT6:0)|\
 
113
     (d7?BRLAPI_DOT7:0)|\
 
114
     (d8?BRLAPI_DOT8:0))
 
115
#endif
 
116
    [BRLAPI_DOTS(1,0,0,0,0,0,0,0)] = 'a',
 
117
    [BRLAPI_DOTS(1,1,0,0,0,0,0,0)] = 'b',
 
118
    [BRLAPI_DOTS(1,0,0,1,0,0,0,0)] = 'c',
 
119
    [BRLAPI_DOTS(1,0,0,1,1,0,0,0)] = 'd',
 
120
    [BRLAPI_DOTS(1,0,0,0,1,0,0,0)] = 'e',
 
121
    [BRLAPI_DOTS(1,1,0,1,0,0,0,0)] = 'f',
 
122
    [BRLAPI_DOTS(1,1,0,1,1,0,0,0)] = 'g',
 
123
    [BRLAPI_DOTS(1,1,0,0,1,0,0,0)] = 'h',
 
124
    [BRLAPI_DOTS(0,1,0,1,0,0,0,0)] = 'i',
 
125
    [BRLAPI_DOTS(0,1,0,1,1,0,0,0)] = 'j',
 
126
    [BRLAPI_DOTS(1,0,1,0,0,0,0,0)] = 'k',
 
127
    [BRLAPI_DOTS(1,1,1,0,0,0,0,0)] = 'l',
 
128
    [BRLAPI_DOTS(1,0,1,1,0,0,0,0)] = 'm',
 
129
    [BRLAPI_DOTS(1,0,1,1,1,0,0,0)] = 'n',
 
130
    [BRLAPI_DOTS(1,0,1,0,1,0,0,0)] = 'o',
 
131
    [BRLAPI_DOTS(1,1,1,1,0,0,0,0)] = 'p',
 
132
    [BRLAPI_DOTS(1,1,1,1,1,0,0,0)] = 'q',
 
133
    [BRLAPI_DOTS(1,1,1,0,1,0,0,0)] = 'r',
 
134
    [BRLAPI_DOTS(0,1,1,1,0,0,0,0)] = 's',
 
135
    [BRLAPI_DOTS(0,1,1,1,1,0,0,0)] = 't',
 
136
    [BRLAPI_DOTS(1,0,1,0,0,1,0,0)] = 'u',
 
137
    [BRLAPI_DOTS(1,1,1,0,0,1,0,0)] = 'v',
 
138
    [BRLAPI_DOTS(0,1,0,1,1,1,0,0)] = 'w',
 
139
    [BRLAPI_DOTS(1,0,1,1,0,1,0,0)] = 'x',
 
140
    [BRLAPI_DOTS(1,0,1,1,1,1,0,0)] = 'y',
 
141
    [BRLAPI_DOTS(1,0,1,0,1,1,0,0)] = 'z',
 
142
 
 
143
    [BRLAPI_DOTS(1,0,0,0,0,0,1,0)] = 'A',
 
144
    [BRLAPI_DOTS(1,1,0,0,0,0,1,0)] = 'B',
 
145
    [BRLAPI_DOTS(1,0,0,1,0,0,1,0)] = 'C',
 
146
    [BRLAPI_DOTS(1,0,0,1,1,0,1,0)] = 'D',
 
147
    [BRLAPI_DOTS(1,0,0,0,1,0,1,0)] = 'E',
 
148
    [BRLAPI_DOTS(1,1,0,1,0,0,1,0)] = 'F',
 
149
    [BRLAPI_DOTS(1,1,0,1,1,0,1,0)] = 'G',
 
150
    [BRLAPI_DOTS(1,1,0,0,1,0,1,0)] = 'H',
 
151
    [BRLAPI_DOTS(0,1,0,1,0,0,1,0)] = 'I',
 
152
    [BRLAPI_DOTS(0,1,0,1,1,0,1,0)] = 'J',
 
153
    [BRLAPI_DOTS(1,0,1,0,0,0,1,0)] = 'K',
 
154
    [BRLAPI_DOTS(1,1,1,0,0,0,1,0)] = 'L',
 
155
    [BRLAPI_DOTS(1,0,1,1,0,0,1,0)] = 'M',
 
156
    [BRLAPI_DOTS(1,0,1,1,1,0,1,0)] = 'N',
 
157
    [BRLAPI_DOTS(1,0,1,0,1,0,1,0)] = 'O',
 
158
    [BRLAPI_DOTS(1,1,1,1,0,0,1,0)] = 'P',
 
159
    [BRLAPI_DOTS(1,1,1,1,1,0,1,0)] = 'Q',
 
160
    [BRLAPI_DOTS(1,1,1,0,1,0,1,0)] = 'R',
 
161
    [BRLAPI_DOTS(0,1,1,1,0,0,1,0)] = 'S',
 
162
    [BRLAPI_DOTS(0,1,1,1,1,0,1,0)] = 'T',
 
163
    [BRLAPI_DOTS(1,0,1,0,0,1,1,0)] = 'U',
 
164
    [BRLAPI_DOTS(1,1,1,0,0,1,1,0)] = 'V',
 
165
    [BRLAPI_DOTS(0,1,0,1,1,1,1,0)] = 'W',
 
166
    [BRLAPI_DOTS(1,0,1,1,0,1,1,0)] = 'X',
 
167
    [BRLAPI_DOTS(1,0,1,1,1,1,1,0)] = 'Y',
 
168
    [BRLAPI_DOTS(1,0,1,0,1,1,1,0)] = 'Z',
 
169
 
 
170
    [BRLAPI_DOTS(0,0,1,0,1,1,0,0)] = '0',
 
171
    [BRLAPI_DOTS(0,1,0,0,0,0,0,0)] = '1',
 
172
    [BRLAPI_DOTS(0,1,1,0,0,0,0,0)] = '2',
 
173
    [BRLAPI_DOTS(0,1,0,0,1,0,0,0)] = '3',
 
174
    [BRLAPI_DOTS(0,1,0,0,1,1,0,0)] = '4',
 
175
    [BRLAPI_DOTS(0,1,0,0,0,1,0,0)] = '5',
 
176
    [BRLAPI_DOTS(0,1,1,0,1,0,0,0)] = '6',
 
177
    [BRLAPI_DOTS(0,1,1,0,1,1,0,0)] = '7',
 
178
    [BRLAPI_DOTS(0,1,1,0,0,1,0,0)] = '8',
 
179
    [BRLAPI_DOTS(0,0,1,0,1,0,0,0)] = '9',
 
180
 
 
181
    [BRLAPI_DOTS(0,0,0,1,0,1,0,0)] = '.',
 
182
    [BRLAPI_DOTS(0,0,1,1,0,1,0,0)] = '+',
 
183
    [BRLAPI_DOTS(0,0,1,0,0,1,0,0)] = '-',
 
184
    [BRLAPI_DOTS(1,0,0,0,0,1,0,0)] = '*',
 
185
    [BRLAPI_DOTS(0,0,1,1,0,0,0,0)] = '/',
 
186
    [BRLAPI_DOTS(1,1,1,0,1,1,0,0)] = '(',
 
187
    [BRLAPI_DOTS(0,1,1,1,1,1,0,0)] = ')',
 
188
 
 
189
    [BRLAPI_DOTS(1,1,1,1,0,1,0,0)] = '&',
 
190
    [BRLAPI_DOTS(0,0,1,1,1,1,0,0)] = '#',
 
191
 
 
192
    [BRLAPI_DOTS(0,0,0,0,0,1,0,0)] = ',',
 
193
    [BRLAPI_DOTS(0,0,0,0,1,1,0,0)] = ';',
 
194
    [BRLAPI_DOTS(1,0,0,0,1,1,0,0)] = ':',
 
195
    [BRLAPI_DOTS(0,1,1,1,0,1,0,0)] = '!',
 
196
    [BRLAPI_DOTS(1,0,0,1,1,1,0,0)] = '?',
 
197
    [BRLAPI_DOTS(0,0,0,0,1,0,0,0)] = '"',
 
198
    [BRLAPI_DOTS(0,0,1,0,0,0,0,0)] ='\'',
 
199
    [BRLAPI_DOTS(0,0,0,1,0,0,0,0)] = '`',
 
200
    [BRLAPI_DOTS(0,0,0,1,1,0,1,0)] = '^',
 
201
    [BRLAPI_DOTS(0,0,0,1,1,0,0,0)] = '~',
 
202
    [BRLAPI_DOTS(0,1,0,1,0,1,1,0)] = '[',
 
203
    [BRLAPI_DOTS(1,1,0,1,1,1,1,0)] = ']',
 
204
    [BRLAPI_DOTS(0,1,0,1,0,1,0,0)] = '{',
 
205
    [BRLAPI_DOTS(1,1,0,1,1,1,0,0)] = '}',
 
206
    [BRLAPI_DOTS(1,1,1,1,1,1,0,0)] = '=',
 
207
    [BRLAPI_DOTS(1,1,0,0,0,1,0,0)] = '<',
 
208
    [BRLAPI_DOTS(0,0,1,1,1,0,0,0)] = '>',
 
209
    [BRLAPI_DOTS(1,1,0,1,0,1,0,0)] = '$',
 
210
    [BRLAPI_DOTS(1,0,0,1,0,1,0,0)] = '%',
 
211
    [BRLAPI_DOTS(0,0,0,1,0,0,1,0)] = '@',
 
212
    [BRLAPI_DOTS(1,1,0,0,1,1,0,0)] = '|',
 
213
    [BRLAPI_DOTS(1,1,0,0,1,1,1,0)] ='\\',
 
214
    [BRLAPI_DOTS(0,0,0,1,1,1,0,0)] = '_',
 
215
};
 
216
 
 
217
/* The serial port can receive more of our data */
 
218
static void baum_accept_input(struct CharDriverState *chr)
 
219
{
 
220
    BaumDriverState *baum = chr->opaque;
 
221
    int room, first;
 
222
 
 
223
    if (!baum->out_buf_used)
 
224
        return;
 
225
    room = qemu_chr_be_can_write(chr);
 
226
    if (!room)
 
227
        return;
 
228
    if (room > baum->out_buf_used)
 
229
        room = baum->out_buf_used;
 
230
 
 
231
    first = BUF_SIZE - baum->out_buf_ptr;
 
232
    if (room > first) {
 
233
        qemu_chr_be_write(chr, baum->out_buf + baum->out_buf_ptr, first);
 
234
        baum->out_buf_ptr = 0;
 
235
        baum->out_buf_used -= first;
 
236
        room -= first;
 
237
    }
 
238
    qemu_chr_be_write(chr, baum->out_buf + baum->out_buf_ptr, room);
 
239
    baum->out_buf_ptr += room;
 
240
    baum->out_buf_used -= room;
 
241
}
 
242
 
 
243
/* We want to send a packet */
 
244
static void baum_write_packet(BaumDriverState *baum, const uint8_t *buf, int len)
 
245
{
 
246
    uint8_t io_buf[1 + 2 * len], *cur = io_buf;
 
247
    int room;
 
248
    *cur++ = ESC;
 
249
    while (len--)
 
250
        if ((*cur++ = *buf++) == ESC)
 
251
            *cur++ = ESC;
 
252
    room = qemu_chr_be_can_write(baum->chr);
 
253
    len = cur - io_buf;
 
254
    if (len <= room) {
 
255
        /* Fits */
 
256
        qemu_chr_be_write(baum->chr, io_buf, len);
 
257
    } else {
 
258
        int first;
 
259
        uint8_t out;
 
260
        /* Can't fit all, send what can be, and store the rest. */
 
261
        qemu_chr_be_write(baum->chr, io_buf, room);
 
262
        len -= room;
 
263
        cur = io_buf + room;
 
264
        if (len > BUF_SIZE - baum->out_buf_used) {
 
265
            /* Can't even store it, drop the previous data... */
 
266
            assert(len <= BUF_SIZE);
 
267
            baum->out_buf_used = 0;
 
268
            baum->out_buf_ptr = 0;
 
269
        }
 
270
        out = baum->out_buf_ptr;
 
271
        baum->out_buf_used += len;
 
272
        first = BUF_SIZE - baum->out_buf_ptr;
 
273
        if (len > first) {
 
274
            memcpy(baum->out_buf + out, cur, first);
 
275
            out = 0;
 
276
            len -= first;
 
277
            cur += first;
 
278
        }
 
279
        memcpy(baum->out_buf + out, cur, len);
 
280
    }
 
281
}
 
282
 
 
283
/* Called when the other end seems to have a wrong idea of our display size */
 
284
static void baum_cellCount_timer_cb(void *opaque)
 
285
{
 
286
    BaumDriverState *baum = opaque;
 
287
    uint8_t cell_count[] = { BAUM_RSP_CellCount, baum->x * baum->y };
 
288
    DPRINTF("Timeout waiting for DisplayData, sending cell count\n");
 
289
    baum_write_packet(baum, cell_count, sizeof(cell_count));
 
290
}
 
291
 
 
292
/* Try to interpret a whole incoming packet */
 
293
static int baum_eat_packet(BaumDriverState *baum, const uint8_t *buf, int len)
 
294
{
 
295
    const uint8_t *cur = buf;
 
296
    uint8_t req = 0;
 
297
 
 
298
    if (!len--)
 
299
        return 0;
 
300
    if (*cur++ != ESC) {
 
301
        while (*cur != ESC) {
 
302
            if (!len--)
 
303
                return 0;
 
304
            cur++;
 
305
        }
 
306
        DPRINTF("Dropped %d bytes!\n", cur - buf);
 
307
    }
 
308
 
 
309
#define EAT(c) do {\
 
310
    if (!len--) \
 
311
        return 0; \
 
312
    if ((c = *cur++) == ESC) { \
 
313
        if (!len--) \
 
314
            return 0; \
 
315
        if (*cur++ != ESC) { \
 
316
            DPRINTF("Broken packet %#2x, tossing\n", req); \
 
317
                if (qemu_timer_pending(baum->cellCount_timer)) { \
 
318
                qemu_del_timer(baum->cellCount_timer); \
 
319
                baum_cellCount_timer_cb(baum); \
 
320
            } \
 
321
            return (cur - 2 - buf); \
 
322
        } \
 
323
    } \
 
324
} while (0)
 
325
 
 
326
    EAT(req);
 
327
    switch (req) {
 
328
    case BAUM_REQ_DisplayData:
 
329
    {
 
330
        uint8_t cells[baum->x * baum->y], c;
 
331
        uint8_t text[baum->x * baum->y];
 
332
        uint8_t zero[baum->x * baum->y];
 
333
        int cursor = BRLAPI_CURSOR_OFF;
 
334
        int i;
 
335
 
 
336
        /* Allow 100ms to complete the DisplayData packet */
 
337
        qemu_mod_timer(baum->cellCount_timer, qemu_get_clock_ns(vm_clock) +
 
338
                       get_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 = (char *)text,
 
360
            .textSize = baum->x * baum->y,
 
361
            .andMask = zero,
 
362
            .orMask = cells,
 
363
            .cursor = cursor,
 
364
            .charset = (char *)"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
/* Send the key code to the other end */
 
471
static void baum_send_key(BaumDriverState *baum, uint8_t type, uint8_t value) {
 
472
    uint8_t packet[] = { type, value };
 
473
    DPRINTF("writing key %x %x\n", type, value);
 
474
    baum_write_packet(baum, packet, sizeof(packet));
 
475
}
 
476
 
 
477
/* We got some data on the BrlAPI socket */
 
478
static void baum_chr_read(void *opaque)
 
479
{
 
480
    BaumDriverState *baum = opaque;
 
481
    brlapi_keyCode_t code;
 
482
    int ret;
 
483
    if (!baum->brlapi)
 
484
        return;
 
485
    while ((ret = brlapi__readKey(baum->brlapi, 0, &code)) == 1) {
 
486
        DPRINTF("got key %"BRLAPI_PRIxKEYCODE"\n", code);
 
487
        /* Emulate */
 
488
        switch (code & BRLAPI_KEY_TYPE_MASK) {
 
489
        case BRLAPI_KEY_TYPE_CMD:
 
490
            switch (code & BRLAPI_KEY_CMD_BLK_MASK) {
 
491
            case BRLAPI_KEY_CMD_ROUTE:
 
492
                baum_send_key(baum, BAUM_RSP_RoutingKey, (code & BRLAPI_KEY_CMD_ARG_MASK)+1);
 
493
                baum_send_key(baum, BAUM_RSP_RoutingKey, 0);
 
494
                break;
 
495
            case 0:
 
496
                switch (code & BRLAPI_KEY_CMD_ARG_MASK) {
 
497
                case BRLAPI_KEY_CMD_FWINLT:
 
498
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2);
 
499
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
 
500
                    break;
 
501
                case BRLAPI_KEY_CMD_FWINRT:
 
502
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR2);
 
503
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
 
504
                    break;
 
505
                case BRLAPI_KEY_CMD_LNUP:
 
506
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR1);
 
507
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
 
508
                    break;
 
509
                case BRLAPI_KEY_CMD_LNDN:
 
510
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR3);
 
511
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
 
512
                    break;
 
513
                case BRLAPI_KEY_CMD_TOP:
 
514
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL1|BAUM_TR1);
 
515
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
 
516
                    break;
 
517
                case BRLAPI_KEY_CMD_BOT:
 
518
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL3|BAUM_TR3);
 
519
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
 
520
                    break;
 
521
                case BRLAPI_KEY_CMD_TOP_LEFT:
 
522
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR1);
 
523
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
 
524
                    break;
 
525
                case BRLAPI_KEY_CMD_BOT_LEFT:
 
526
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR3);
 
527
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
 
528
                    break;
 
529
                case BRLAPI_KEY_CMD_HOME:
 
530
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR1|BAUM_TR3);
 
531
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
 
532
                    break;
 
533
                case BRLAPI_KEY_CMD_PREFMENU:
 
534
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL1|BAUM_TL3|BAUM_TR1);
 
535
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
 
536
                    break;
 
537
                }
 
538
            }
 
539
            break;
 
540
        case BRLAPI_KEY_TYPE_SYM:
 
541
            break;
 
542
        }
 
543
    }
 
544
    if (ret == -1 && (brlapi_errno != BRLAPI_ERROR_LIBCERR || errno != EINTR)) {
 
545
        brlapi_perror("baum: brlapi_readKey");
 
546
        brlapi__closeConnection(baum->brlapi);
 
547
        g_free(baum->brlapi);
 
548
        baum->brlapi = NULL;
 
549
    }
 
550
}
 
551
 
 
552
static void baum_close(struct CharDriverState *chr)
 
553
{
 
554
    BaumDriverState *baum = chr->opaque;
 
555
 
 
556
    qemu_free_timer(baum->cellCount_timer);
 
557
    if (baum->brlapi) {
 
558
        brlapi__closeConnection(baum->brlapi);
 
559
        g_free(baum->brlapi);
 
560
    }
 
561
    g_free(baum);
 
562
}
 
563
 
 
564
CharDriverState *chr_baum_init(void)
 
565
{
 
566
    BaumDriverState *baum;
 
567
    CharDriverState *chr;
 
568
    brlapi_handle_t *handle;
 
569
#ifdef CONFIG_SDL
 
570
    SDL_SysWMinfo info;
 
571
#endif
 
572
    int tty;
 
573
 
 
574
    baum = g_malloc0(sizeof(BaumDriverState));
 
575
    baum->chr = chr = g_malloc0(sizeof(CharDriverState));
 
576
 
 
577
    chr->opaque = baum;
 
578
    chr->chr_write = baum_write;
 
579
    chr->chr_accept_input = baum_accept_input;
 
580
    chr->chr_close = baum_close;
 
581
 
 
582
    handle = g_malloc0(brlapi_getHandleSize());
 
583
    baum->brlapi = handle;
 
584
 
 
585
    baum->brlapi_fd = brlapi__openConnection(handle, NULL, NULL);
 
586
    if (baum->brlapi_fd == -1) {
 
587
        brlapi_perror("baum_init: brlapi_openConnection");
 
588
        goto fail_handle;
 
589
    }
 
590
 
 
591
    baum->cellCount_timer = qemu_new_timer_ns(vm_clock, baum_cellCount_timer_cb, baum);
 
592
 
 
593
    if (brlapi__getDisplaySize(handle, &baum->x, &baum->y) == -1) {
 
594
        brlapi_perror("baum_init: brlapi_getDisplaySize");
 
595
        goto fail;
 
596
    }
 
597
 
 
598
#ifdef CONFIG_SDL
 
599
    memset(&info, 0, sizeof(info));
 
600
    SDL_VERSION(&info.version);
 
601
    if (SDL_GetWMInfo(&info))
 
602
        tty = info.info.x11.wmwindow;
 
603
    else
 
604
#endif
 
605
        tty = BRLAPI_TTY_DEFAULT;
 
606
 
 
607
    if (brlapi__enterTtyMode(handle, tty, NULL) == -1) {
 
608
        brlapi_perror("baum_init: brlapi_enterTtyMode");
 
609
        goto fail;
 
610
    }
 
611
 
 
612
    qemu_set_fd_handler(baum->brlapi_fd, baum_chr_read, NULL, baum);
 
613
 
 
614
    qemu_chr_be_generic_open(chr);
 
615
 
 
616
    return chr;
 
617
 
 
618
fail:
 
619
    qemu_free_timer(baum->cellCount_timer);
 
620
    brlapi__closeConnection(handle);
 
621
fail_handle:
 
622
    g_free(handle);
 
623
    g_free(chr);
 
624
    g_free(baum);
 
625
    return NULL;
 
626
}
 
627
 
 
628
static void register_types(void)
 
629
{
 
630
    register_char_driver_qapi("braille", CHARDEV_BACKEND_KIND_BRAILLE, NULL);
 
631
}
 
632
 
 
633
type_init(register_types);