Statistics
| Branch: | Revision:

root / hw / baum.c @ d78f3995

History | View | Annotate | Download (19.7 kB)

1 2e4d9fb1 aurel32
/*
2 2e4d9fb1 aurel32
 * QEMU Baum Braille Device
3 2e4d9fb1 aurel32
 *
4 2e4d9fb1 aurel32
 * Copyright (c) 2008 Samuel Thibault
5 2e4d9fb1 aurel32
 *
6 2e4d9fb1 aurel32
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 2e4d9fb1 aurel32
 * of this software and associated documentation files (the "Software"), to deal
8 2e4d9fb1 aurel32
 * in the Software without restriction, including without limitation the rights
9 2e4d9fb1 aurel32
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 2e4d9fb1 aurel32
 * copies of the Software, and to permit persons to whom the Software is
11 2e4d9fb1 aurel32
 * furnished to do so, subject to the following conditions:
12 2e4d9fb1 aurel32
 *
13 2e4d9fb1 aurel32
 * The above copyright notice and this permission notice shall be included in
14 2e4d9fb1 aurel32
 * all copies or substantial portions of the Software.
15 2e4d9fb1 aurel32
 *
16 2e4d9fb1 aurel32
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 2e4d9fb1 aurel32
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 2e4d9fb1 aurel32
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 2e4d9fb1 aurel32
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 2e4d9fb1 aurel32
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 2e4d9fb1 aurel32
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 2e4d9fb1 aurel32
 * THE SOFTWARE.
23 2e4d9fb1 aurel32
 */
24 2e4d9fb1 aurel32
#include "qemu-common.h"
25 2e4d9fb1 aurel32
#include "qemu-char.h"
26 2e4d9fb1 aurel32
#include "qemu-timer.h"
27 2e4d9fb1 aurel32
#include "usb.h"
28 c78eae61 aurel32
#include "baum.h"
29 2e4d9fb1 aurel32
#include <assert.h>
30 2e4d9fb1 aurel32
#include <brlapi.h>
31 2e4d9fb1 aurel32
#include <brlapi_constants.h>
32 2e4d9fb1 aurel32
#include <brlapi_keycodes.h>
33 2e4d9fb1 aurel32
#ifdef CONFIG_SDL
34 2e4d9fb1 aurel32
#include <SDL/SDL_syswm.h>
35 2e4d9fb1 aurel32
#endif
36 2e4d9fb1 aurel32
37 2e4d9fb1 aurel32
#if 0
38 2e4d9fb1 aurel32
#define DPRINTF(fmt, ...) \
39 2e4d9fb1 aurel32
        printf(fmt, ## __VA_ARGS__)
40 2e4d9fb1 aurel32
#else
41 2e4d9fb1 aurel32
#define DPRINTF(fmt, ...)
42 2e4d9fb1 aurel32
#endif
43 2e4d9fb1 aurel32
44 2e4d9fb1 aurel32
#define ESC 0x1B
45 2e4d9fb1 aurel32
46 2e4d9fb1 aurel32
#define BAUM_REQ_DisplayData                0x01
47 2e4d9fb1 aurel32
#define BAUM_REQ_GetVersionNumber        0x05
48 2e4d9fb1 aurel32
#define BAUM_REQ_GetKeys                0x08
49 2e4d9fb1 aurel32
#define BAUM_REQ_SetMode                0x12
50 2e4d9fb1 aurel32
#define BAUM_REQ_SetProtocol                0x15
51 2e4d9fb1 aurel32
#define BAUM_REQ_GetDeviceIdentity        0x84
52 2e4d9fb1 aurel32
#define BAUM_REQ_GetSerialNumber        0x8A
53 2e4d9fb1 aurel32
54 2e4d9fb1 aurel32
#define BAUM_RSP_CellCount                0x01
55 2e4d9fb1 aurel32
#define BAUM_RSP_VersionNumber                0x05
56 2e4d9fb1 aurel32
#define BAUM_RSP_ModeSetting                0x11
57 2e4d9fb1 aurel32
#define BAUM_RSP_CommunicationChannel        0x16
58 2e4d9fb1 aurel32
#define BAUM_RSP_PowerdownSignal        0x17
59 2e4d9fb1 aurel32
#define BAUM_RSP_HorizontalSensors        0x20
60 2e4d9fb1 aurel32
#define BAUM_RSP_VerticalSensors        0x21
61 2e4d9fb1 aurel32
#define BAUM_RSP_RoutingKeys                0x22
62 2e4d9fb1 aurel32
#define BAUM_RSP_Switches                0x23
63 2e4d9fb1 aurel32
#define BAUM_RSP_TopKeys                0x24
64 2e4d9fb1 aurel32
#define BAUM_RSP_HorizontalSensor        0x25
65 2e4d9fb1 aurel32
#define BAUM_RSP_VerticalSensor                0x26
66 2e4d9fb1 aurel32
#define BAUM_RSP_RoutingKey                0x27
67 2e4d9fb1 aurel32
#define BAUM_RSP_FrontKeys6                0x28
68 2e4d9fb1 aurel32
#define BAUM_RSP_BackKeys6                0x29
69 2e4d9fb1 aurel32
#define BAUM_RSP_CommandKeys                0x2B
70 2e4d9fb1 aurel32
#define BAUM_RSP_FrontKeys10                0x2C
71 2e4d9fb1 aurel32
#define BAUM_RSP_BackKeys10                0x2D
72 2e4d9fb1 aurel32
#define BAUM_RSP_EntryKeys                0x33
73 2e4d9fb1 aurel32
#define BAUM_RSP_JoyStick                0x34
74 2e4d9fb1 aurel32
#define BAUM_RSP_ErrorCode                0x40
75 2e4d9fb1 aurel32
#define BAUM_RSP_InfoBlock                0x42
76 2e4d9fb1 aurel32
#define BAUM_RSP_DeviceIdentity                0x84
77 2e4d9fb1 aurel32
#define BAUM_RSP_SerialNumber                0x8A
78 2e4d9fb1 aurel32
#define BAUM_RSP_BluetoothName                0x8C
79 2e4d9fb1 aurel32
80 2e4d9fb1 aurel32
#define BAUM_TL1 0x01
81 2e4d9fb1 aurel32
#define BAUM_TL2 0x02
82 2e4d9fb1 aurel32
#define BAUM_TL3 0x04
83 2e4d9fb1 aurel32
#define BAUM_TR1 0x08
84 2e4d9fb1 aurel32
#define BAUM_TR2 0x10
85 2e4d9fb1 aurel32
#define BAUM_TR3 0x20
86 2e4d9fb1 aurel32
87 2e4d9fb1 aurel32
#define BUF_SIZE 256
88 2e4d9fb1 aurel32
89 2e4d9fb1 aurel32
typedef struct {
90 2e4d9fb1 aurel32
    CharDriverState *chr;
91 2e4d9fb1 aurel32
92 2e4d9fb1 aurel32
    brlapi_handle_t *brlapi;
93 2e4d9fb1 aurel32
    int brlapi_fd;
94 2e4d9fb1 aurel32
    int x, y;
95 2e4d9fb1 aurel32
96 2e4d9fb1 aurel32
    uint8_t in_buf[BUF_SIZE];
97 2e4d9fb1 aurel32
    uint8_t in_buf_used;
98 2e4d9fb1 aurel32
    uint8_t out_buf[BUF_SIZE];
99 2e4d9fb1 aurel32
    uint8_t out_buf_used, out_buf_ptr;
100 2e4d9fb1 aurel32
101 2e4d9fb1 aurel32
    QEMUTimer *cellCount_timer;
102 2e4d9fb1 aurel32
} BaumDriverState;
103 2e4d9fb1 aurel32
104 2e4d9fb1 aurel32
/* Let's assume NABCC by default */
105 2e4d9fb1 aurel32
static const uint8_t nabcc_translation[256] = {
106 2e4d9fb1 aurel32
    [0] = ' ',
107 2e4d9fb1 aurel32
#ifndef BRLAPI_DOTS
108 2e4d9fb1 aurel32
#define BRLAPI_DOTS(d1,d2,d3,d4,d5,d6,d7,d8) \
109 2e4d9fb1 aurel32
    ((d1?BRLAPI_DOT1:0)|\
110 2e4d9fb1 aurel32
     (d2?BRLAPI_DOT2:0)|\
111 2e4d9fb1 aurel32
     (d3?BRLAPI_DOT3:0)|\
112 2e4d9fb1 aurel32
     (d4?BRLAPI_DOT4:0)|\
113 2e4d9fb1 aurel32
     (d5?BRLAPI_DOT5:0)|\
114 2e4d9fb1 aurel32
     (d6?BRLAPI_DOT6:0)|\
115 2e4d9fb1 aurel32
     (d7?BRLAPI_DOT7:0)|\
116 2e4d9fb1 aurel32
     (d8?BRLAPI_DOT8:0))
117 2e4d9fb1 aurel32
#endif
118 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,0,0,0,0,0,0,0)] = 'a',
119 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,1,0,0,0,0,0,0)] = 'b',
120 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,0,0,1,0,0,0,0)] = 'c',
121 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,0,0,1,1,0,0,0)] = 'd',
122 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,0,0,0,1,0,0,0)] = 'e',
123 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,1,0,1,0,0,0,0)] = 'f',
124 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,1,0,1,1,0,0,0)] = 'g',
125 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,1,0,0,1,0,0,0)] = 'h',
126 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,1,0,1,0,0,0,0)] = 'i',
127 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,1,0,1,1,0,0,0)] = 'j',
128 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,0,1,0,0,0,0,0)] = 'k',
129 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,1,1,0,0,0,0,0)] = 'l',
130 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,0,1,1,0,0,0,0)] = 'm',
131 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,0,1,1,1,0,0,0)] = 'n',
132 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,0,1,0,1,0,0,0)] = 'o',
133 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,1,1,1,0,0,0,0)] = 'p',
134 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,1,1,1,1,0,0,0)] = 'q',
135 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,1,1,0,1,0,0,0)] = 'r',
136 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,1,1,1,0,0,0,0)] = 's',
137 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,1,1,1,1,0,0,0)] = 't',
138 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,0,1,0,0,1,0,0)] = 'u',
139 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,1,1,0,0,1,0,0)] = 'v',
140 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,1,0,1,1,1,0,0)] = 'w',
141 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,0,1,1,0,1,0,0)] = 'x',
142 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,0,1,1,1,1,0,0)] = 'y',
143 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,0,1,0,1,1,0,0)] = 'z',
144 2e4d9fb1 aurel32
145 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,0,0,0,0,0,1,0)] = 'A',
146 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,1,0,0,0,0,1,0)] = 'B',
147 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,0,0,1,0,0,1,0)] = 'C',
148 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,0,0,1,1,0,1,0)] = 'D',
149 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,0,0,0,1,0,1,0)] = 'E',
150 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,1,0,1,0,0,1,0)] = 'F',
151 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,1,0,1,1,0,1,0)] = 'G',
152 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,1,0,0,1,0,1,0)] = 'H',
153 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,1,0,1,0,0,1,0)] = 'I',
154 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,1,0,1,1,0,1,0)] = 'J',
155 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,0,1,0,0,0,1,0)] = 'K',
156 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,1,1,0,0,0,1,0)] = 'L',
157 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,0,1,1,0,0,1,0)] = 'M',
158 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,0,1,1,1,0,1,0)] = 'N',
159 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,0,1,0,1,0,1,0)] = 'O',
160 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,1,1,1,0,0,1,0)] = 'P',
161 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,1,1,1,1,0,1,0)] = 'Q',
162 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,1,1,0,1,0,1,0)] = 'R',
163 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,1,1,1,0,0,1,0)] = 'S',
164 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,1,1,1,1,0,1,0)] = 'T',
165 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,0,1,0,0,1,1,0)] = 'U',
166 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,1,1,0,0,1,1,0)] = 'V',
167 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,1,0,1,1,1,1,0)] = 'W',
168 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,0,1,1,0,1,1,0)] = 'X',
169 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,0,1,1,1,1,1,0)] = 'Y',
170 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,0,1,0,1,1,1,0)] = 'Z',
171 2e4d9fb1 aurel32
172 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,0,1,0,1,1,0,0)] = '0',
173 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,1,0,0,0,0,0,0)] = '1',
174 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,1,1,0,0,0,0,0)] = '2',
175 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,1,0,0,1,0,0,0)] = '3',
176 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,1,0,0,1,1,0,0)] = '4',
177 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,1,0,0,0,1,0,0)] = '5',
178 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,1,1,0,1,0,0,0)] = '6',
179 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,1,1,0,1,1,0,0)] = '7',
180 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,1,1,0,0,1,0,0)] = '8',
181 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,0,1,0,1,0,0,0)] = '9',
182 2e4d9fb1 aurel32
183 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,0,0,1,0,1,0,0)] = '.',
184 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,0,1,1,0,1,0,0)] = '+',
185 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,0,1,0,0,1,0,0)] = '-',
186 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,0,0,0,0,1,0,0)] = '*',
187 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,0,1,1,0,0,0,0)] = '/',
188 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,1,1,0,1,1,0,0)] = '(',
189 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,1,1,1,1,1,0,0)] = ')',
190 2e4d9fb1 aurel32
191 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,1,1,1,0,1,0,0)] = '&',
192 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,0,1,1,1,1,0,0)] = '#',
193 2e4d9fb1 aurel32
194 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,0,0,0,0,1,0,0)] = ',',
195 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,0,0,0,1,1,0,0)] = ';',
196 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,0,0,0,1,1,0,0)] = ':',
197 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,1,1,1,0,1,0,0)] = '!',
198 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,0,0,1,1,1,0,0)] = '?',
199 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,0,0,0,1,0,0,0)] = '"',
200 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,0,1,0,0,0,0,0)] ='\'',
201 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,0,0,1,0,0,0,0)] = '`',
202 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,0,0,1,1,0,1,0)] = '^',
203 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,0,0,1,1,0,0,0)] = '~',
204 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,1,0,1,0,1,1,0)] = '[',
205 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,1,0,1,1,1,1,0)] = ']',
206 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,1,0,1,0,1,0,0)] = '{',
207 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,1,0,1,1,1,0,0)] = '}',
208 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,1,1,1,1,1,0,0)] = '=',
209 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,1,0,0,0,1,0,0)] = '<',
210 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,0,1,1,1,0,0,0)] = '>',
211 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,1,0,1,0,1,0,0)] = '$',
212 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,0,0,1,0,1,0,0)] = '%',
213 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,0,0,1,0,0,1,0)] = '@',
214 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,1,0,0,1,1,0,0)] = '|',
215 2e4d9fb1 aurel32
    [BRLAPI_DOTS(1,1,0,0,1,1,1,0)] ='\\',
216 2e4d9fb1 aurel32
    [BRLAPI_DOTS(0,0,0,1,1,1,0,0)] = '_',
217 2e4d9fb1 aurel32
};
218 2e4d9fb1 aurel32
219 2e4d9fb1 aurel32
/* The serial port can receive more of our data */
220 2e4d9fb1 aurel32
static void baum_accept_input(struct CharDriverState *chr)
221 2e4d9fb1 aurel32
{
222 2e4d9fb1 aurel32
    BaumDriverState *baum = chr->opaque;
223 2e4d9fb1 aurel32
    int room, first;
224 2e4d9fb1 aurel32
225 2e4d9fb1 aurel32
    if (!baum->out_buf_used)
226 2e4d9fb1 aurel32
        return;
227 2e4d9fb1 aurel32
    room = qemu_chr_can_read(chr);
228 2e4d9fb1 aurel32
    if (!room)
229 2e4d9fb1 aurel32
        return;
230 2e4d9fb1 aurel32
    if (room > baum->out_buf_used)
231 2e4d9fb1 aurel32
        room = baum->out_buf_used;
232 2e4d9fb1 aurel32
233 2e4d9fb1 aurel32
    first = BUF_SIZE - baum->out_buf_ptr;
234 2e4d9fb1 aurel32
    if (room > first) {
235 2e4d9fb1 aurel32
        qemu_chr_read(chr, baum->out_buf + baum->out_buf_ptr, first);
236 2e4d9fb1 aurel32
        baum->out_buf_ptr = 0;
237 2e4d9fb1 aurel32
        baum->out_buf_used -= first;
238 2e4d9fb1 aurel32
        room -= first;
239 2e4d9fb1 aurel32
    }
240 2e4d9fb1 aurel32
    qemu_chr_read(chr, baum->out_buf + baum->out_buf_ptr, room);
241 2e4d9fb1 aurel32
    baum->out_buf_ptr += room;
242 2e4d9fb1 aurel32
    baum->out_buf_used -= room;
243 2e4d9fb1 aurel32
}
244 2e4d9fb1 aurel32
245 2e4d9fb1 aurel32
/* We want to send a packet */
246 2e4d9fb1 aurel32
static void baum_write_packet(BaumDriverState *baum, const uint8_t *buf, int len)
247 2e4d9fb1 aurel32
{
248 2e4d9fb1 aurel32
    uint8_t io_buf[1 + 2 * len], *cur = io_buf;
249 2e4d9fb1 aurel32
    int room;
250 2e4d9fb1 aurel32
    *cur++ = ESC;
251 2e4d9fb1 aurel32
    while (len--)
252 2e4d9fb1 aurel32
        if ((*cur++ = *buf++) == ESC)
253 2e4d9fb1 aurel32
            *cur++ = ESC;
254 2e4d9fb1 aurel32
    room = qemu_chr_can_read(baum->chr);
255 2e4d9fb1 aurel32
    len = cur - io_buf;
256 2e4d9fb1 aurel32
    if (len <= room) {
257 2e4d9fb1 aurel32
        /* Fits */
258 2e4d9fb1 aurel32
        qemu_chr_read(baum->chr, io_buf, len);
259 2e4d9fb1 aurel32
    } else {
260 2e4d9fb1 aurel32
        int first;
261 2e4d9fb1 aurel32
        uint8_t out;
262 2e4d9fb1 aurel32
        /* Can't fit all, send what can be, and store the rest. */
263 2e4d9fb1 aurel32
        qemu_chr_read(baum->chr, io_buf, room);
264 2e4d9fb1 aurel32
        len -= room;
265 2e4d9fb1 aurel32
        cur = io_buf + room;
266 2e4d9fb1 aurel32
        if (len > BUF_SIZE - baum->out_buf_used) {
267 2e4d9fb1 aurel32
            /* Can't even store it, drop the previous data... */
268 2e4d9fb1 aurel32
            assert(len <= BUF_SIZE);
269 2e4d9fb1 aurel32
            baum->out_buf_used = 0;
270 2e4d9fb1 aurel32
            baum->out_buf_ptr = 0;
271 2e4d9fb1 aurel32
        }
272 2e4d9fb1 aurel32
        out = baum->out_buf_ptr;
273 2e4d9fb1 aurel32
        baum->out_buf_used += len;
274 2e4d9fb1 aurel32
        first = BUF_SIZE - baum->out_buf_ptr;
275 2e4d9fb1 aurel32
        if (len > first) {
276 2e4d9fb1 aurel32
            memcpy(baum->out_buf + out, cur, first);
277 2e4d9fb1 aurel32
            out = 0;
278 2e4d9fb1 aurel32
            len -= first;
279 2e4d9fb1 aurel32
            cur += first;
280 2e4d9fb1 aurel32
        }
281 2e4d9fb1 aurel32
        memcpy(baum->out_buf + out, cur, len);
282 2e4d9fb1 aurel32
    }
283 2e4d9fb1 aurel32
}
284 2e4d9fb1 aurel32
285 2e4d9fb1 aurel32
/* Called when the other end seems to have a wrong idea of our display size */
286 2e4d9fb1 aurel32
static void baum_cellCount_timer_cb(void *opaque)
287 2e4d9fb1 aurel32
{
288 2e4d9fb1 aurel32
    BaumDriverState *baum = opaque;
289 2e4d9fb1 aurel32
    uint8_t cell_count[] = { BAUM_RSP_CellCount, baum->x * baum->y };
290 2e4d9fb1 aurel32
    DPRINTF("Timeout waiting for DisplayData, sending cell count\n");
291 2e4d9fb1 aurel32
    baum_write_packet(baum, cell_count, sizeof(cell_count));
292 2e4d9fb1 aurel32
}
293 2e4d9fb1 aurel32
294 2e4d9fb1 aurel32
/* Try to interpret a whole incoming packet */
295 2e4d9fb1 aurel32
static int baum_eat_packet(BaumDriverState *baum, const uint8_t *buf, int len)
296 2e4d9fb1 aurel32
{
297 2e4d9fb1 aurel32
    const uint8_t *cur = buf;
298 2e4d9fb1 aurel32
    uint8_t req = 0;
299 2e4d9fb1 aurel32
300 2e4d9fb1 aurel32
    if (!len--)
301 2e4d9fb1 aurel32
        return 0;
302 2e4d9fb1 aurel32
    if (*cur++ != ESC) {
303 2e4d9fb1 aurel32
        while (*cur != ESC) {
304 2e4d9fb1 aurel32
            if (!len--)
305 2e4d9fb1 aurel32
                return 0;
306 2e4d9fb1 aurel32
            cur++;
307 2e4d9fb1 aurel32
        }
308 2e4d9fb1 aurel32
        DPRINTF("Dropped %d bytes!\n", cur - buf);
309 2e4d9fb1 aurel32
    }
310 2e4d9fb1 aurel32
311 2e4d9fb1 aurel32
#define EAT(c) do {\
312 2e4d9fb1 aurel32
    if (!len--) \
313 2e4d9fb1 aurel32
        return 0; \
314 2e4d9fb1 aurel32
    if ((c = *cur++) == ESC) { \
315 2e4d9fb1 aurel32
        if (!len--) \
316 2e4d9fb1 aurel32
            return 0; \
317 2e4d9fb1 aurel32
        if (*cur++ != ESC) { \
318 2e4d9fb1 aurel32
            DPRINTF("Broken packet %#2x, tossing\n", req); \
319 2e4d9fb1 aurel32
                if (qemu_timer_pending(baum->cellCount_timer)) { \
320 2e4d9fb1 aurel32
                qemu_del_timer(baum->cellCount_timer); \
321 2e4d9fb1 aurel32
                baum_cellCount_timer_cb(baum); \
322 2e4d9fb1 aurel32
            } \
323 2e4d9fb1 aurel32
            return (cur - 2 - buf); \
324 2e4d9fb1 aurel32
        } \
325 2e4d9fb1 aurel32
    } \
326 2e4d9fb1 aurel32
} while (0)
327 2e4d9fb1 aurel32
328 2e4d9fb1 aurel32
    EAT(req);
329 2e4d9fb1 aurel32
    switch (req) {
330 2e4d9fb1 aurel32
    case BAUM_REQ_DisplayData:
331 2e4d9fb1 aurel32
    {
332 2e4d9fb1 aurel32
        uint8_t cells[baum->x * baum->y], c;
333 2e4d9fb1 aurel32
        uint8_t text[baum->x * baum->y];
334 2e4d9fb1 aurel32
        uint8_t zero[baum->x * baum->y];
335 2e4d9fb1 aurel32
        int cursor = BRLAPI_CURSOR_OFF;
336 2e4d9fb1 aurel32
        int i;
337 2e4d9fb1 aurel32
338 2e4d9fb1 aurel32
        /* Allow 100ms to complete the DisplayData packet */
339 2e4d9fb1 aurel32
        qemu_mod_timer(baum->cellCount_timer, qemu_get_clock(vm_clock) + ticks_per_sec / 10);
340 2e4d9fb1 aurel32
        for (i = 0; i < baum->x * baum->y ; i++) {
341 2e4d9fb1 aurel32
            EAT(c);
342 2e4d9fb1 aurel32
            cells[i] = c;
343 2e4d9fb1 aurel32
            if ((c & (BRLAPI_DOT7|BRLAPI_DOT8))
344 2e4d9fb1 aurel32
                    == (BRLAPI_DOT7|BRLAPI_DOT8)) {
345 2e4d9fb1 aurel32
                cursor = i + 1;
346 2e4d9fb1 aurel32
                c &= ~(BRLAPI_DOT7|BRLAPI_DOT8);
347 2e4d9fb1 aurel32
            }
348 2e4d9fb1 aurel32
            if (!(c = nabcc_translation[c]))
349 2e4d9fb1 aurel32
                c = '?';
350 2e4d9fb1 aurel32
            text[i] = c;
351 2e4d9fb1 aurel32
        }
352 2e4d9fb1 aurel32
        qemu_del_timer(baum->cellCount_timer);
353 2e4d9fb1 aurel32
354 2e4d9fb1 aurel32
        memset(zero, 0, sizeof(zero));
355 2e4d9fb1 aurel32
356 2e4d9fb1 aurel32
        brlapi_writeArguments_t wa = {
357 2e4d9fb1 aurel32
            .displayNumber = BRLAPI_DISPLAY_DEFAULT,
358 2e4d9fb1 aurel32
            .regionBegin = 1,
359 2e4d9fb1 aurel32
            .regionSize = baum->x * baum->y,
360 2e4d9fb1 aurel32
            .text = text,
361 2e4d9fb1 aurel32
            .textSize = baum->x * baum->y,
362 2e4d9fb1 aurel32
            .andMask = zero,
363 2e4d9fb1 aurel32
            .orMask = cells,
364 2e4d9fb1 aurel32
            .cursor = cursor,
365 2e4d9fb1 aurel32
            .charset = "ISO-8859-1",
366 2e4d9fb1 aurel32
        };
367 2e4d9fb1 aurel32
368 2e4d9fb1 aurel32
        if (brlapi__write(baum->brlapi, &wa) == -1)
369 2e4d9fb1 aurel32
            brlapi_perror("baum brlapi_write");
370 2e4d9fb1 aurel32
        break;
371 2e4d9fb1 aurel32
    }
372 2e4d9fb1 aurel32
    case BAUM_REQ_SetMode:
373 2e4d9fb1 aurel32
    {
374 2e4d9fb1 aurel32
        uint8_t mode, setting;
375 2e4d9fb1 aurel32
        DPRINTF("SetMode\n");
376 2e4d9fb1 aurel32
        EAT(mode);
377 2e4d9fb1 aurel32
        EAT(setting);
378 2e4d9fb1 aurel32
        /* ignore */
379 2e4d9fb1 aurel32
        break;
380 2e4d9fb1 aurel32
    }
381 2e4d9fb1 aurel32
    case BAUM_REQ_SetProtocol:
382 2e4d9fb1 aurel32
    {
383 2e4d9fb1 aurel32
        uint8_t protocol;
384 2e4d9fb1 aurel32
        DPRINTF("SetProtocol\n");
385 2e4d9fb1 aurel32
        EAT(protocol);
386 2e4d9fb1 aurel32
        /* ignore */
387 2e4d9fb1 aurel32
        break;
388 2e4d9fb1 aurel32
    }
389 2e4d9fb1 aurel32
    case BAUM_REQ_GetDeviceIdentity:
390 2e4d9fb1 aurel32
    {
391 2e4d9fb1 aurel32
        uint8_t identity[17] = { BAUM_RSP_DeviceIdentity,
392 2e4d9fb1 aurel32
            'B','a','u','m',' ','V','a','r','i','o' };
393 2e4d9fb1 aurel32
        DPRINTF("GetDeviceIdentity\n");
394 2e4d9fb1 aurel32
        identity[11] = '0' + baum->x / 10;
395 2e4d9fb1 aurel32
        identity[12] = '0' + baum->x % 10;
396 2e4d9fb1 aurel32
        baum_write_packet(baum, identity, sizeof(identity));
397 2e4d9fb1 aurel32
        break;
398 2e4d9fb1 aurel32
    }
399 2e4d9fb1 aurel32
    case BAUM_REQ_GetVersionNumber:
400 2e4d9fb1 aurel32
    {
401 2e4d9fb1 aurel32
        uint8_t version[] = { BAUM_RSP_VersionNumber, 1 }; /* ? */
402 2e4d9fb1 aurel32
        DPRINTF("GetVersionNumber\n");
403 2e4d9fb1 aurel32
        baum_write_packet(baum, version, sizeof(version));
404 2e4d9fb1 aurel32
        break;
405 2e4d9fb1 aurel32
    }
406 2e4d9fb1 aurel32
    case BAUM_REQ_GetSerialNumber:
407 2e4d9fb1 aurel32
    {
408 2e4d9fb1 aurel32
        uint8_t serial[] = { BAUM_RSP_SerialNumber,
409 2e4d9fb1 aurel32
            '0','0','0','0','0','0','0','0' };
410 2e4d9fb1 aurel32
        DPRINTF("GetSerialNumber\n");
411 2e4d9fb1 aurel32
        baum_write_packet(baum, serial, sizeof(serial));
412 2e4d9fb1 aurel32
        break;
413 2e4d9fb1 aurel32
    }
414 2e4d9fb1 aurel32
    case BAUM_REQ_GetKeys:
415 2e4d9fb1 aurel32
    {
416 2e4d9fb1 aurel32
        DPRINTF("Get%0#2x\n", req);
417 2e4d9fb1 aurel32
        /* ignore */
418 2e4d9fb1 aurel32
        break;
419 2e4d9fb1 aurel32
    }
420 2e4d9fb1 aurel32
    default:
421 2e4d9fb1 aurel32
        DPRINTF("unrecognized request %0#2x\n", req);
422 2e4d9fb1 aurel32
        do
423 2e4d9fb1 aurel32
            if (!len--)
424 2e4d9fb1 aurel32
                return 0;
425 2e4d9fb1 aurel32
        while (*cur++ != ESC);
426 2e4d9fb1 aurel32
        cur--;
427 2e4d9fb1 aurel32
        break;
428 2e4d9fb1 aurel32
    }
429 2e4d9fb1 aurel32
    return cur - buf;
430 2e4d9fb1 aurel32
}
431 2e4d9fb1 aurel32
432 2e4d9fb1 aurel32
/* The other end is writing some data.  Store it and try to interpret */
433 2e4d9fb1 aurel32
static int baum_write(CharDriverState *chr, const uint8_t *buf, int len)
434 2e4d9fb1 aurel32
{
435 2e4d9fb1 aurel32
    BaumDriverState *baum = chr->opaque;
436 2e4d9fb1 aurel32
    int tocopy, cur, eaten, orig_len = len;
437 2e4d9fb1 aurel32
438 2e4d9fb1 aurel32
    if (!len)
439 2e4d9fb1 aurel32
        return 0;
440 2e4d9fb1 aurel32
    if (!baum->brlapi)
441 2e4d9fb1 aurel32
        return len;
442 2e4d9fb1 aurel32
443 2e4d9fb1 aurel32
    while (len) {
444 2e4d9fb1 aurel32
        /* Complete our buffer as much as possible */
445 2e4d9fb1 aurel32
        tocopy = len;
446 2e4d9fb1 aurel32
        if (tocopy > BUF_SIZE - baum->in_buf_used)
447 2e4d9fb1 aurel32
            tocopy = BUF_SIZE - baum->in_buf_used;
448 2e4d9fb1 aurel32
449 2e4d9fb1 aurel32
        memcpy(baum->in_buf + baum->in_buf_used, buf, tocopy);
450 2e4d9fb1 aurel32
        baum->in_buf_used += tocopy;
451 2e4d9fb1 aurel32
        buf += tocopy;
452 2e4d9fb1 aurel32
        len -= tocopy;
453 2e4d9fb1 aurel32
454 2e4d9fb1 aurel32
        /* Interpret it as much as possible */
455 2e4d9fb1 aurel32
        cur = 0;
456 2e4d9fb1 aurel32
        while (cur < baum->in_buf_used &&
457 2e4d9fb1 aurel32
                (eaten = baum_eat_packet(baum, baum->in_buf + cur, baum->in_buf_used - cur)))
458 2e4d9fb1 aurel32
            cur += eaten;
459 2e4d9fb1 aurel32
460 2e4d9fb1 aurel32
        /* Shift the remainder */
461 2e4d9fb1 aurel32
        if (cur) {
462 2e4d9fb1 aurel32
            memmove(baum->in_buf, baum->in_buf + cur, baum->in_buf_used - cur);
463 2e4d9fb1 aurel32
            baum->in_buf_used -= cur;
464 2e4d9fb1 aurel32
        }
465 2e4d9fb1 aurel32
466 2e4d9fb1 aurel32
        /* And continue if any data left */
467 2e4d9fb1 aurel32
    }
468 2e4d9fb1 aurel32
    return orig_len;
469 2e4d9fb1 aurel32
}
470 2e4d9fb1 aurel32
471 2e4d9fb1 aurel32
/* The other end sent us some event */
472 2e4d9fb1 aurel32
static void baum_send_event(CharDriverState *chr, int event)
473 2e4d9fb1 aurel32
{
474 2e4d9fb1 aurel32
    BaumDriverState *baum = chr->opaque;
475 2e4d9fb1 aurel32
    switch (event) {
476 2e4d9fb1 aurel32
    case CHR_EVENT_BREAK:
477 2e4d9fb1 aurel32
        break;
478 2e4d9fb1 aurel32
    case CHR_EVENT_RESET:
479 2e4d9fb1 aurel32
        /* Reset state */
480 2e4d9fb1 aurel32
        baum->in_buf_used = 0;
481 2e4d9fb1 aurel32
        break;
482 2e4d9fb1 aurel32
    }
483 2e4d9fb1 aurel32
}
484 2e4d9fb1 aurel32
485 2e4d9fb1 aurel32
/* Send the key code to the other end */
486 2e4d9fb1 aurel32
static void baum_send_key(BaumDriverState *baum, uint8_t type, uint8_t value) {
487 2e4d9fb1 aurel32
    uint8_t packet[] = { type, value };
488 2e4d9fb1 aurel32
    DPRINTF("writing key %x %x\n", type, value);
489 2e4d9fb1 aurel32
    baum_write_packet(baum, packet, sizeof(packet));
490 2e4d9fb1 aurel32
}
491 2e4d9fb1 aurel32
492 2e4d9fb1 aurel32
/* We got some data on the BrlAPI socket */
493 2e4d9fb1 aurel32
static void baum_chr_read(void *opaque)
494 2e4d9fb1 aurel32
{
495 2e4d9fb1 aurel32
    BaumDriverState *baum = opaque;
496 2e4d9fb1 aurel32
    brlapi_keyCode_t code;
497 2e4d9fb1 aurel32
    int ret;
498 2e4d9fb1 aurel32
    if (!baum->brlapi)
499 2e4d9fb1 aurel32
        return;
500 2e4d9fb1 aurel32
    while ((ret = brlapi__readKey(baum->brlapi, 0, &code)) == 1) {
501 2e4d9fb1 aurel32
        DPRINTF("got key %"BRLAPI_PRIxKEYCODE"\n", code);
502 2e4d9fb1 aurel32
        /* Emulate */
503 2e4d9fb1 aurel32
        switch (code & BRLAPI_KEY_TYPE_MASK) {
504 2e4d9fb1 aurel32
        case BRLAPI_KEY_TYPE_CMD:
505 2e4d9fb1 aurel32
            switch (code & BRLAPI_KEY_CMD_BLK_MASK) {
506 2e4d9fb1 aurel32
            case BRLAPI_KEY_CMD_ROUTE:
507 2e4d9fb1 aurel32
                baum_send_key(baum, BAUM_RSP_RoutingKey, (code & BRLAPI_KEY_CMD_ARG_MASK)+1);
508 2e4d9fb1 aurel32
                baum_send_key(baum, BAUM_RSP_RoutingKey, 0);
509 2e4d9fb1 aurel32
                break;
510 2e4d9fb1 aurel32
            case 0:
511 2e4d9fb1 aurel32
                switch (code & BRLAPI_KEY_CMD_ARG_MASK) {
512 2e4d9fb1 aurel32
                case BRLAPI_KEY_CMD_FWINLT:
513 2e4d9fb1 aurel32
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2);
514 2e4d9fb1 aurel32
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
515 2e4d9fb1 aurel32
                    break;
516 2e4d9fb1 aurel32
                case BRLAPI_KEY_CMD_FWINRT:
517 2e4d9fb1 aurel32
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR2);
518 2e4d9fb1 aurel32
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
519 2e4d9fb1 aurel32
                    break;
520 2e4d9fb1 aurel32
                case BRLAPI_KEY_CMD_LNUP:
521 2e4d9fb1 aurel32
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR1);
522 2e4d9fb1 aurel32
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
523 2e4d9fb1 aurel32
                    break;
524 2e4d9fb1 aurel32
                case BRLAPI_KEY_CMD_LNDN:
525 2e4d9fb1 aurel32
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR3);
526 2e4d9fb1 aurel32
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
527 2e4d9fb1 aurel32
                    break;
528 2e4d9fb1 aurel32
                case BRLAPI_KEY_CMD_TOP:
529 2e4d9fb1 aurel32
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL1|BAUM_TR1);
530 2e4d9fb1 aurel32
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
531 2e4d9fb1 aurel32
                    break;
532 2e4d9fb1 aurel32
                case BRLAPI_KEY_CMD_BOT:
533 2e4d9fb1 aurel32
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL3|BAUM_TR3);
534 2e4d9fb1 aurel32
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
535 2e4d9fb1 aurel32
                    break;
536 2e4d9fb1 aurel32
                case BRLAPI_KEY_CMD_TOP_LEFT:
537 2e4d9fb1 aurel32
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR1);
538 2e4d9fb1 aurel32
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
539 2e4d9fb1 aurel32
                    break;
540 2e4d9fb1 aurel32
                case BRLAPI_KEY_CMD_BOT_LEFT:
541 2e4d9fb1 aurel32
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR3);
542 2e4d9fb1 aurel32
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
543 2e4d9fb1 aurel32
                    break;
544 2e4d9fb1 aurel32
                case BRLAPI_KEY_CMD_HOME:
545 2e4d9fb1 aurel32
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR1|BAUM_TR3);
546 2e4d9fb1 aurel32
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
547 2e4d9fb1 aurel32
                    break;
548 2e4d9fb1 aurel32
                case BRLAPI_KEY_CMD_PREFMENU:
549 2e4d9fb1 aurel32
                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL1|BAUM_TL3|BAUM_TR1);
550 2e4d9fb1 aurel32
                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
551 2e4d9fb1 aurel32
                    break;
552 2e4d9fb1 aurel32
                }
553 2e4d9fb1 aurel32
            }
554 2e4d9fb1 aurel32
            break;
555 2e4d9fb1 aurel32
        case BRLAPI_KEY_TYPE_SYM:
556 2e4d9fb1 aurel32
            break;
557 2e4d9fb1 aurel32
        }
558 2e4d9fb1 aurel32
    }
559 2e4d9fb1 aurel32
    if (ret == -1 && (brlapi_errno != BRLAPI_ERROR_LIBCERR || errno != EINTR)) {
560 2e4d9fb1 aurel32
        brlapi_perror("baum: brlapi_readKey");
561 2e4d9fb1 aurel32
        brlapi__closeConnection(baum->brlapi);
562 2e4d9fb1 aurel32
        free(baum->brlapi);
563 2e4d9fb1 aurel32
        baum->brlapi = NULL;
564 2e4d9fb1 aurel32
    }
565 2e4d9fb1 aurel32
}
566 2e4d9fb1 aurel32
567 2e4d9fb1 aurel32
CharDriverState *chr_baum_init(void)
568 2e4d9fb1 aurel32
{
569 2e4d9fb1 aurel32
    BaumDriverState *baum;
570 2e4d9fb1 aurel32
    CharDriverState *chr;
571 2e4d9fb1 aurel32
    brlapi_handle_t *handle;
572 2e4d9fb1 aurel32
#ifdef CONFIG_SDL
573 2e4d9fb1 aurel32
    SDL_SysWMinfo info;
574 2e4d9fb1 aurel32
#endif
575 2e4d9fb1 aurel32
    int tty;
576 2e4d9fb1 aurel32
577 2e4d9fb1 aurel32
    baum = qemu_mallocz(sizeof(BaumDriverState));
578 2e4d9fb1 aurel32
    baum->chr = chr = qemu_mallocz(sizeof(CharDriverState));
579 2e4d9fb1 aurel32
580 2e4d9fb1 aurel32
    chr->opaque = baum;
581 2e4d9fb1 aurel32
    chr->chr_write = baum_write;
582 2e4d9fb1 aurel32
    chr->chr_send_event = baum_send_event;
583 2e4d9fb1 aurel32
    chr->chr_accept_input = baum_accept_input;
584 2e4d9fb1 aurel32
585 2e4d9fb1 aurel32
    handle = qemu_mallocz(brlapi_getHandleSize());
586 2e4d9fb1 aurel32
    baum->brlapi = handle;
587 2e4d9fb1 aurel32
588 2e4d9fb1 aurel32
    baum->brlapi_fd = brlapi__openConnection(handle, NULL, NULL);
589 2e4d9fb1 aurel32
    if (baum->brlapi_fd == -1) {
590 2e4d9fb1 aurel32
        brlapi_perror("baum_init: brlapi_openConnection");
591 2e4d9fb1 aurel32
        goto fail_handle;
592 2e4d9fb1 aurel32
    }
593 2e4d9fb1 aurel32
594 2e4d9fb1 aurel32
    baum->cellCount_timer = qemu_new_timer(vm_clock, baum_cellCount_timer_cb, baum);
595 2e4d9fb1 aurel32
596 2e4d9fb1 aurel32
    if (brlapi__getDisplaySize(handle, &baum->x, &baum->y) == -1) {
597 2e4d9fb1 aurel32
        brlapi_perror("baum_init: brlapi_getDisplaySize");
598 2e4d9fb1 aurel32
        goto fail;
599 2e4d9fb1 aurel32
    }
600 2e4d9fb1 aurel32
601 2e4d9fb1 aurel32
#ifdef CONFIG_SDL
602 2e4d9fb1 aurel32
    memset(&info, 0, sizeof(info));
603 2e4d9fb1 aurel32
    SDL_VERSION(&info.version);
604 2e4d9fb1 aurel32
    if (SDL_GetWMInfo(&info))
605 2e4d9fb1 aurel32
        tty = info.info.x11.wmwindow;
606 2e4d9fb1 aurel32
    else
607 2e4d9fb1 aurel32
#endif
608 2e4d9fb1 aurel32
        tty = BRLAPI_TTY_DEFAULT;
609 2e4d9fb1 aurel32
610 2e4d9fb1 aurel32
    if (brlapi__enterTtyMode(handle, tty, NULL) == -1) {
611 2e4d9fb1 aurel32
        brlapi_perror("baum_init: brlapi_enterTtyMode");
612 2e4d9fb1 aurel32
        goto fail;
613 2e4d9fb1 aurel32
    }
614 2e4d9fb1 aurel32
615 2e4d9fb1 aurel32
    qemu_set_fd_handler(baum->brlapi_fd, baum_chr_read, NULL, baum);
616 2e4d9fb1 aurel32
617 2e4d9fb1 aurel32
    qemu_chr_reset(chr);
618 2e4d9fb1 aurel32
619 2e4d9fb1 aurel32
    return chr;
620 2e4d9fb1 aurel32
621 2e4d9fb1 aurel32
fail:
622 2e4d9fb1 aurel32
    qemu_free_timer(baum->cellCount_timer);
623 2e4d9fb1 aurel32
    brlapi__closeConnection(handle);
624 260cfc43 aurel32
fail_handle:
625 2e4d9fb1 aurel32
    free(handle);
626 2e4d9fb1 aurel32
    free(chr);
627 2e4d9fb1 aurel32
    free(baum);
628 2e4d9fb1 aurel32
    return NULL;
629 2e4d9fb1 aurel32
}
630 2e4d9fb1 aurel32
631 2e4d9fb1 aurel32
USBDevice *usb_baum_init(void)
632 2e4d9fb1 aurel32
{
633 2e4d9fb1 aurel32
    /* USB Product ID of Super Vario 40 */
634 2e4d9fb1 aurel32
    return usb_serial_init("productid=FE72:braille");
635 2e4d9fb1 aurel32
}