OSDN Git Service

qcow2: Don't strand clusters near 2G intervals during commit
[qmiga/qemu.git] / backends / baum.c
1 /*
2  * QEMU Baum Braille Device
3  *
4  * Copyright (c) 2008, 2010-2011, 2016 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/osdep.h"
25 #include "qapi/error.h"
26 #include "qemu-common.h"
27 #include "sysemu/char.h"
28 #include "qemu/timer.h"
29 #include "hw/usb.h"
30 #include <brlapi.h>
31 #include <brlapi_constants.h>
32 #include <brlapi_keycodes.h>
33 #ifdef CONFIG_SDL
34 #include <SDL_syswm.h>
35 #endif
36
37 #if 0
38 #define DPRINTF(fmt, ...) \
39         printf(fmt, ## __VA_ARGS__)
40 #else
41 #define DPRINTF(fmt, ...)
42 #endif
43
44 #define ESC 0x1B
45
46 #define BAUM_REQ_DisplayData            0x01
47 #define BAUM_REQ_GetVersionNumber       0x05
48 #define BAUM_REQ_GetKeys                0x08
49 #define BAUM_REQ_SetMode                0x12
50 #define BAUM_REQ_SetProtocol            0x15
51 #define BAUM_REQ_GetDeviceIdentity      0x84
52 #define BAUM_REQ_GetSerialNumber        0x8A
53
54 #define BAUM_RSP_CellCount              0x01
55 #define BAUM_RSP_VersionNumber          0x05
56 #define BAUM_RSP_ModeSetting            0x11
57 #define BAUM_RSP_CommunicationChannel   0x16
58 #define BAUM_RSP_PowerdownSignal        0x17
59 #define BAUM_RSP_HorizontalSensors      0x20
60 #define BAUM_RSP_VerticalSensors        0x21
61 #define BAUM_RSP_RoutingKeys            0x22
62 #define BAUM_RSP_Switches               0x23
63 #define BAUM_RSP_TopKeys                0x24
64 #define BAUM_RSP_HorizontalSensor       0x25
65 #define BAUM_RSP_VerticalSensor         0x26
66 #define BAUM_RSP_RoutingKey             0x27
67 #define BAUM_RSP_FrontKeys6             0x28
68 #define BAUM_RSP_BackKeys6              0x29
69 #define BAUM_RSP_CommandKeys            0x2B
70 #define BAUM_RSP_FrontKeys10            0x2C
71 #define BAUM_RSP_BackKeys10             0x2D
72 #define BAUM_RSP_EntryKeys              0x33
73 #define BAUM_RSP_JoyStick               0x34
74 #define BAUM_RSP_ErrorCode              0x40
75 #define BAUM_RSP_InfoBlock              0x42
76 #define BAUM_RSP_DeviceIdentity         0x84
77 #define BAUM_RSP_SerialNumber           0x8A
78 #define BAUM_RSP_BluetoothName          0x8C
79
80 #define BAUM_TL1 0x01
81 #define BAUM_TL2 0x02
82 #define BAUM_TL3 0x04
83 #define BAUM_TR1 0x08
84 #define BAUM_TR2 0x10
85 #define BAUM_TR3 0x20
86
87 #define BUF_SIZE 256
88
89 typedef struct {
90     CharDriverState *chr;
91
92     brlapi_handle_t *brlapi;
93     int brlapi_fd;
94     unsigned int x, y;
95     bool deferred_init;
96
97     uint8_t in_buf[BUF_SIZE];
98     uint8_t in_buf_used;
99     uint8_t out_buf[BUF_SIZE];
100     uint8_t out_buf_used, out_buf_ptr;
101
102     QEMUTimer *cellCount_timer;
103 } BaumDriverState;
104
105 /* Let's assume NABCC by default */
106 enum way {
107     DOTS2ASCII,
108     ASCII2DOTS
109 };
110 static const uint8_t nabcc_translation[2][256] = {
111 #ifndef BRLAPI_DOTS
112 #define BRLAPI_DOTS(d1,d2,d3,d4,d5,d6,d7,d8) \
113     ((d1?BRLAPI_DOT1:0)|\
114      (d2?BRLAPI_DOT2:0)|\
115      (d3?BRLAPI_DOT3:0)|\
116      (d4?BRLAPI_DOT4:0)|\
117      (d5?BRLAPI_DOT5:0)|\
118      (d6?BRLAPI_DOT6:0)|\
119      (d7?BRLAPI_DOT7:0)|\
120      (d8?BRLAPI_DOT8:0))
121 #endif
122 #define DO(dots, ascii) \
123     [DOTS2ASCII][dots] = ascii, \
124     [ASCII2DOTS][ascii] = dots
125     DO(0, ' '),
126     DO(BRLAPI_DOTS(1, 0, 0, 0, 0, 0, 0, 0), 'a'),
127     DO(BRLAPI_DOTS(1, 1, 0, 0, 0, 0, 0, 0), 'b'),
128     DO(BRLAPI_DOTS(1, 0, 0, 1, 0, 0, 0, 0), 'c'),
129     DO(BRLAPI_DOTS(1, 0, 0, 1, 1, 0, 0, 0), 'd'),
130     DO(BRLAPI_DOTS(1, 0, 0, 0, 1, 0, 0, 0), 'e'),
131     DO(BRLAPI_DOTS(1, 1, 0, 1, 0, 0, 0, 0), 'f'),
132     DO(BRLAPI_DOTS(1, 1, 0, 1, 1, 0, 0, 0), 'g'),
133     DO(BRLAPI_DOTS(1, 1, 0, 0, 1, 0, 0, 0), 'h'),
134     DO(BRLAPI_DOTS(0, 1, 0, 1, 0, 0, 0, 0), 'i'),
135     DO(BRLAPI_DOTS(0, 1, 0, 1, 1, 0, 0, 0), 'j'),
136     DO(BRLAPI_DOTS(1, 0, 1, 0, 0, 0, 0, 0), 'k'),
137     DO(BRLAPI_DOTS(1, 1, 1, 0, 0, 0, 0, 0), 'l'),
138     DO(BRLAPI_DOTS(1, 0, 1, 1, 0, 0, 0, 0), 'm'),
139     DO(BRLAPI_DOTS(1, 0, 1, 1, 1, 0, 0, 0), 'n'),
140     DO(BRLAPI_DOTS(1, 0, 1, 0, 1, 0, 0, 0), 'o'),
141     DO(BRLAPI_DOTS(1, 1, 1, 1, 0, 0, 0, 0), 'p'),
142     DO(BRLAPI_DOTS(1, 1, 1, 1, 1, 0, 0, 0), 'q'),
143     DO(BRLAPI_DOTS(1, 1, 1, 0, 1, 0, 0, 0), 'r'),
144     DO(BRLAPI_DOTS(0, 1, 1, 1, 0, 0, 0, 0), 's'),
145     DO(BRLAPI_DOTS(0, 1, 1, 1, 1, 0, 0, 0), 't'),
146     DO(BRLAPI_DOTS(1, 0, 1, 0, 0, 1, 0, 0), 'u'),
147     DO(BRLAPI_DOTS(1, 1, 1, 0, 0, 1, 0, 0), 'v'),
148     DO(BRLAPI_DOTS(0, 1, 0, 1, 1, 1, 0, 0), 'w'),
149     DO(BRLAPI_DOTS(1, 0, 1, 1, 0, 1, 0, 0), 'x'),
150     DO(BRLAPI_DOTS(1, 0, 1, 1, 1, 1, 0, 0), 'y'),
151     DO(BRLAPI_DOTS(1, 0, 1, 0, 1, 1, 0, 0), 'z'),
152
153     DO(BRLAPI_DOTS(1, 0, 0, 0, 0, 0, 1, 0), 'A'),
154     DO(BRLAPI_DOTS(1, 1, 0, 0, 0, 0, 1, 0), 'B'),
155     DO(BRLAPI_DOTS(1, 0, 0, 1, 0, 0, 1, 0), 'C'),
156     DO(BRLAPI_DOTS(1, 0, 0, 1, 1, 0, 1, 0), 'D'),
157     DO(BRLAPI_DOTS(1, 0, 0, 0, 1, 0, 1, 0), 'E'),
158     DO(BRLAPI_DOTS(1, 1, 0, 1, 0, 0, 1, 0), 'F'),
159     DO(BRLAPI_DOTS(1, 1, 0, 1, 1, 0, 1, 0), 'G'),
160     DO(BRLAPI_DOTS(1, 1, 0, 0, 1, 0, 1, 0), 'H'),
161     DO(BRLAPI_DOTS(0, 1, 0, 1, 0, 0, 1, 0), 'I'),
162     DO(BRLAPI_DOTS(0, 1, 0, 1, 1, 0, 1, 0), 'J'),
163     DO(BRLAPI_DOTS(1, 0, 1, 0, 0, 0, 1, 0), 'K'),
164     DO(BRLAPI_DOTS(1, 1, 1, 0, 0, 0, 1, 0), 'L'),
165     DO(BRLAPI_DOTS(1, 0, 1, 1, 0, 0, 1, 0), 'M'),
166     DO(BRLAPI_DOTS(1, 0, 1, 1, 1, 0, 1, 0), 'N'),
167     DO(BRLAPI_DOTS(1, 0, 1, 0, 1, 0, 1, 0), 'O'),
168     DO(BRLAPI_DOTS(1, 1, 1, 1, 0, 0, 1, 0), 'P'),
169     DO(BRLAPI_DOTS(1, 1, 1, 1, 1, 0, 1, 0), 'Q'),
170     DO(BRLAPI_DOTS(1, 1, 1, 0, 1, 0, 1, 0), 'R'),
171     DO(BRLAPI_DOTS(0, 1, 1, 1, 0, 0, 1, 0), 'S'),
172     DO(BRLAPI_DOTS(0, 1, 1, 1, 1, 0, 1, 0), 'T'),
173     DO(BRLAPI_DOTS(1, 0, 1, 0, 0, 1, 1, 0), 'U'),
174     DO(BRLAPI_DOTS(1, 1, 1, 0, 0, 1, 1, 0), 'V'),
175     DO(BRLAPI_DOTS(0, 1, 0, 1, 1, 1, 1, 0), 'W'),
176     DO(BRLAPI_DOTS(1, 0, 1, 1, 0, 1, 1, 0), 'X'),
177     DO(BRLAPI_DOTS(1, 0, 1, 1, 1, 1, 1, 0), 'Y'),
178     DO(BRLAPI_DOTS(1, 0, 1, 0, 1, 1, 1, 0), 'Z'),
179
180     DO(BRLAPI_DOTS(0, 0, 1, 0, 1, 1, 0, 0), '0'),
181     DO(BRLAPI_DOTS(0, 1, 0, 0, 0, 0, 0, 0), '1'),
182     DO(BRLAPI_DOTS(0, 1, 1, 0, 0, 0, 0, 0), '2'),
183     DO(BRLAPI_DOTS(0, 1, 0, 0, 1, 0, 0, 0), '3'),
184     DO(BRLAPI_DOTS(0, 1, 0, 0, 1, 1, 0, 0), '4'),
185     DO(BRLAPI_DOTS(0, 1, 0, 0, 0, 1, 0, 0), '5'),
186     DO(BRLAPI_DOTS(0, 1, 1, 0, 1, 0, 0, 0), '6'),
187     DO(BRLAPI_DOTS(0, 1, 1, 0, 1, 1, 0, 0), '7'),
188     DO(BRLAPI_DOTS(0, 1, 1, 0, 0, 1, 0, 0), '8'),
189     DO(BRLAPI_DOTS(0, 0, 1, 0, 1, 0, 0, 0), '9'),
190
191     DO(BRLAPI_DOTS(0, 0, 0, 1, 0, 1, 0, 0), '.'),
192     DO(BRLAPI_DOTS(0, 0, 1, 1, 0, 1, 0, 0), '+'),
193     DO(BRLAPI_DOTS(0, 0, 1, 0, 0, 1, 0, 0), '-'),
194     DO(BRLAPI_DOTS(1, 0, 0, 0, 0, 1, 0, 0), '*'),
195     DO(BRLAPI_DOTS(0, 0, 1, 1, 0, 0, 0, 0), '/'),
196     DO(BRLAPI_DOTS(1, 1, 1, 0, 1, 1, 0, 0), '('),
197     DO(BRLAPI_DOTS(0, 1, 1, 1, 1, 1, 0, 0), ')'),
198
199     DO(BRLAPI_DOTS(1, 1, 1, 1, 0, 1, 0, 0), '&'),
200     DO(BRLAPI_DOTS(0, 0, 1, 1, 1, 1, 0, 0), '#'),
201
202     DO(BRLAPI_DOTS(0, 0, 0, 0, 0, 1, 0, 0), ','),
203     DO(BRLAPI_DOTS(0, 0, 0, 0, 1, 1, 0, 0), ';'),
204     DO(BRLAPI_DOTS(1, 0, 0, 0, 1, 1, 0, 0), ':'),
205     DO(BRLAPI_DOTS(0, 1, 1, 1, 0, 1, 0, 0), '!'),
206     DO(BRLAPI_DOTS(1, 0, 0, 1, 1, 1, 0, 0), '?'),
207     DO(BRLAPI_DOTS(0, 0, 0, 0, 1, 0, 0, 0), '"'),
208     DO(BRLAPI_DOTS(0, 0, 1, 0, 0, 0, 0, 0), '\''),
209     DO(BRLAPI_DOTS(0, 0, 0, 1, 0, 0, 0, 0), '`'),
210     DO(BRLAPI_DOTS(0, 0, 0, 1, 1, 0, 1, 0), '^'),
211     DO(BRLAPI_DOTS(0, 0, 0, 1, 1, 0, 0, 0), '~'),
212     DO(BRLAPI_DOTS(0, 1, 0, 1, 0, 1, 1, 0), '['),
213     DO(BRLAPI_DOTS(1, 1, 0, 1, 1, 1, 1, 0), ']'),
214     DO(BRLAPI_DOTS(0, 1, 0, 1, 0, 1, 0, 0), '{'),
215     DO(BRLAPI_DOTS(1, 1, 0, 1, 1, 1, 0, 0), '}'),
216     DO(BRLAPI_DOTS(1, 1, 1, 1, 1, 1, 0, 0), '='),
217     DO(BRLAPI_DOTS(1, 1, 0, 0, 0, 1, 0, 0), '<'),
218     DO(BRLAPI_DOTS(0, 0, 1, 1, 1, 0, 0, 0), '>'),
219     DO(BRLAPI_DOTS(1, 1, 0, 1, 0, 1, 0, 0), '$'),
220     DO(BRLAPI_DOTS(1, 0, 0, 1, 0, 1, 0, 0), '%'),
221     DO(BRLAPI_DOTS(0, 0, 0, 1, 0, 0, 1, 0), '@'),
222     DO(BRLAPI_DOTS(1, 1, 0, 0, 1, 1, 0, 0), '|'),
223     DO(BRLAPI_DOTS(1, 1, 0, 0, 1, 1, 1, 0), '\\'),
224     DO(BRLAPI_DOTS(0, 0, 0, 1, 1, 1, 0, 0), '_'),
225 };
226
227 /* The guest OS has started discussing with us, finish initializing BrlAPI */
228 static int baum_deferred_init(BaumDriverState *baum)
229 {
230 #if defined(CONFIG_SDL)
231 #if SDL_COMPILEDVERSION < SDL_VERSIONNUM(2, 0, 0)
232     SDL_SysWMinfo info;
233 #endif
234 #endif
235     int tty;
236
237     if (baum->deferred_init) {
238         return 1;
239     }
240
241     if (brlapi__getDisplaySize(baum->brlapi, &baum->x, &baum->y) == -1) {
242         brlapi_perror("baum: brlapi__getDisplaySize");
243         return 0;
244     }
245
246 #if defined(CONFIG_SDL)
247 #if SDL_COMPILEDVERSION < SDL_VERSIONNUM(2, 0, 0)
248     memset(&info, 0, sizeof(info));
249     SDL_VERSION(&info.version);
250     if (SDL_GetWMInfo(&info)) {
251         tty = info.info.x11.wmwindow;
252     } else {
253 #endif
254 #endif
255         tty = BRLAPI_TTY_DEFAULT;
256 #if defined(CONFIG_SDL)
257 #if SDL_COMPILEDVERSION < SDL_VERSIONNUM(2, 0, 0)
258     }
259 #endif
260 #endif
261
262     if (brlapi__enterTtyMode(baum->brlapi, tty, NULL) == -1) {
263         brlapi_perror("baum: brlapi__enterTtyMode");
264         return 0;
265     }
266     baum->deferred_init = 1;
267     return 1;
268 }
269
270 /* The serial port can receive more of our data */
271 static void baum_accept_input(struct CharDriverState *chr)
272 {
273     BaumDriverState *baum = chr->opaque;
274     int room, first;
275
276     if (!baum->out_buf_used)
277         return;
278     room = qemu_chr_be_can_write(chr);
279     if (!room)
280         return;
281     if (room > baum->out_buf_used)
282         room = baum->out_buf_used;
283
284     first = BUF_SIZE - baum->out_buf_ptr;
285     if (room > first) {
286         qemu_chr_be_write(chr, baum->out_buf + baum->out_buf_ptr, first);
287         baum->out_buf_ptr = 0;
288         baum->out_buf_used -= first;
289         room -= first;
290     }
291     qemu_chr_be_write(chr, baum->out_buf + baum->out_buf_ptr, room);
292     baum->out_buf_ptr += room;
293     baum->out_buf_used -= room;
294 }
295
296 /* We want to send a packet */
297 static void baum_write_packet(BaumDriverState *baum, const uint8_t *buf, int len)
298 {
299     uint8_t io_buf[1 + 2 * len], *cur = io_buf;
300     int room;
301     *cur++ = ESC;
302     while (len--)
303         if ((*cur++ = *buf++) == ESC)
304             *cur++ = ESC;
305     room = qemu_chr_be_can_write(baum->chr);
306     len = cur - io_buf;
307     if (len <= room) {
308         /* Fits */
309         qemu_chr_be_write(baum->chr, io_buf, len);
310     } else {
311         int first;
312         uint8_t out;
313         /* Can't fit all, send what can be, and store the rest. */
314         qemu_chr_be_write(baum->chr, io_buf, room);
315         len -= room;
316         cur = io_buf + room;
317         if (len > BUF_SIZE - baum->out_buf_used) {
318             /* Can't even store it, drop the previous data... */
319             assert(len <= BUF_SIZE);
320             baum->out_buf_used = 0;
321             baum->out_buf_ptr = 0;
322         }
323         out = baum->out_buf_ptr;
324         baum->out_buf_used += len;
325         first = BUF_SIZE - baum->out_buf_ptr;
326         if (len > first) {
327             memcpy(baum->out_buf + out, cur, first);
328             out = 0;
329             len -= first;
330             cur += first;
331         }
332         memcpy(baum->out_buf + out, cur, len);
333     }
334 }
335
336 /* Called when the other end seems to have a wrong idea of our display size */
337 static void baum_cellCount_timer_cb(void *opaque)
338 {
339     BaumDriverState *baum = opaque;
340     uint8_t cell_count[] = { BAUM_RSP_CellCount, baum->x * baum->y };
341     DPRINTF("Timeout waiting for DisplayData, sending cell count\n");
342     baum_write_packet(baum, cell_count, sizeof(cell_count));
343 }
344
345 /* Try to interpret a whole incoming packet */
346 static int baum_eat_packet(BaumDriverState *baum, const uint8_t *buf, int len)
347 {
348     const uint8_t *cur = buf;
349     uint8_t req = 0;
350
351     if (!len--)
352         return 0;
353     if (*cur++ != ESC) {
354         while (*cur != ESC) {
355             if (!len--)
356                 return 0;
357             cur++;
358         }
359         DPRINTF("Dropped %td bytes!\n", cur - buf);
360     }
361
362 #define EAT(c) do {\
363     if (!len--) \
364         return 0; \
365     if ((c = *cur++) == ESC) { \
366         if (!len--) \
367             return 0; \
368         if (*cur++ != ESC) { \
369             DPRINTF("Broken packet %#2x, tossing\n", req); \
370             if (timer_pending(baum->cellCount_timer)) {    \
371                 timer_del(baum->cellCount_timer);     \
372                 baum_cellCount_timer_cb(baum);             \
373             } \
374             return (cur - 2 - buf); \
375         } \
376     } \
377 } while (0)
378
379     EAT(req);
380     switch (req) {
381     case BAUM_REQ_DisplayData:
382     {
383         uint8_t cells[baum->x * baum->y], c;
384         uint8_t text[baum->x * baum->y];
385         uint8_t zero[baum->x * baum->y];
386         int cursor = BRLAPI_CURSOR_OFF;
387         int i;
388
389         /* Allow 100ms to complete the DisplayData packet */
390         timer_mod(baum->cellCount_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
391                        NANOSECONDS_PER_SECOND / 10);
392         for (i = 0; i < baum->x * baum->y ; i++) {
393             EAT(c);
394             cells[i] = c;
395             if ((c & (BRLAPI_DOT7|BRLAPI_DOT8))
396                     == (BRLAPI_DOT7|BRLAPI_DOT8)) {
397                 cursor = i + 1;
398                 c &= ~(BRLAPI_DOT7|BRLAPI_DOT8);
399             }
400             c = nabcc_translation[DOTS2ASCII][c];
401             if (!c) {
402                 c = '?';
403             }
404             text[i] = c;
405         }
406         timer_del(baum->cellCount_timer);
407
408         memset(zero, 0, sizeof(zero));
409
410         brlapi_writeArguments_t wa = {
411             .displayNumber = BRLAPI_DISPLAY_DEFAULT,
412             .regionBegin = 1,
413             .regionSize = baum->x * baum->y,
414             .text = (char *)text,
415             .textSize = baum->x * baum->y,
416             .andMask = zero,
417             .orMask = cells,
418             .cursor = cursor,
419             .charset = (char *)"ISO-8859-1",
420         };
421
422         if (brlapi__write(baum->brlapi, &wa) == -1)
423             brlapi_perror("baum brlapi_write");
424         break;
425     }
426     case BAUM_REQ_SetMode:
427     {
428         uint8_t mode, setting;
429         DPRINTF("SetMode\n");
430         EAT(mode);
431         EAT(setting);
432         /* ignore */
433         break;
434     }
435     case BAUM_REQ_SetProtocol:
436     {
437         uint8_t protocol;
438         DPRINTF("SetProtocol\n");
439         EAT(protocol);
440         /* ignore */
441         break;
442     }
443     case BAUM_REQ_GetDeviceIdentity:
444     {
445         uint8_t identity[17] = { BAUM_RSP_DeviceIdentity,
446             'B','a','u','m',' ','V','a','r','i','o' };
447         DPRINTF("GetDeviceIdentity\n");
448         identity[11] = '0' + baum->x / 10;
449         identity[12] = '0' + baum->x % 10;
450         baum_write_packet(baum, identity, sizeof(identity));
451         break;
452     }
453     case BAUM_REQ_GetVersionNumber:
454     {
455         uint8_t version[] = { BAUM_RSP_VersionNumber, 1 }; /* ? */
456         DPRINTF("GetVersionNumber\n");
457         baum_write_packet(baum, version, sizeof(version));
458         break;
459     }
460     case BAUM_REQ_GetSerialNumber:
461     {
462         uint8_t serial[] = { BAUM_RSP_SerialNumber,
463             '0','0','0','0','0','0','0','0' };
464         DPRINTF("GetSerialNumber\n");
465         baum_write_packet(baum, serial, sizeof(serial));
466         break;
467     }
468     case BAUM_REQ_GetKeys:
469     {
470         DPRINTF("Get%0#2x\n", req);
471         /* ignore */
472         break;
473     }
474     default:
475         DPRINTF("unrecognized request %0#2x\n", req);
476         do
477             if (!len--)
478                 return 0;
479         while (*cur++ != ESC);
480         cur--;
481         break;
482     }
483     return cur - buf;
484 }
485
486 /* The other end is writing some data.  Store it and try to interpret */
487 static int baum_write(CharDriverState *chr, const uint8_t *buf, int len)
488 {
489     BaumDriverState *baum = chr->opaque;
490     int tocopy, cur, eaten, orig_len = len;
491
492     if (!len)
493         return 0;
494     if (!baum->brlapi)
495         return len;
496     if (!baum_deferred_init(baum))
497         return len;
498
499     while (len) {
500         /* Complete our buffer as much as possible */
501         tocopy = len;
502         if (tocopy > BUF_SIZE - baum->in_buf_used)
503             tocopy = BUF_SIZE - baum->in_buf_used;
504
505         memcpy(baum->in_buf + baum->in_buf_used, buf, tocopy);
506         baum->in_buf_used += tocopy;
507         buf += tocopy;
508         len -= tocopy;
509
510         /* Interpret it as much as possible */
511         cur = 0;
512         while (cur < baum->in_buf_used &&
513                 (eaten = baum_eat_packet(baum, baum->in_buf + cur, baum->in_buf_used - cur)))
514             cur += eaten;
515
516         /* Shift the remainder */
517         if (cur) {
518             memmove(baum->in_buf, baum->in_buf + cur, baum->in_buf_used - cur);
519             baum->in_buf_used -= cur;
520         }
521
522         /* And continue if any data left */
523     }
524     return orig_len;
525 }
526
527 /* Send the key code to the other end */
528 static void baum_send_key(BaumDriverState *baum, uint8_t type, uint8_t value) {
529     uint8_t packet[] = { type, value };
530     DPRINTF("writing key %x %x\n", type, value);
531     baum_write_packet(baum, packet, sizeof(packet));
532 }
533
534 static void baum_send_key2(BaumDriverState *baum, uint8_t type, uint8_t value,
535                            uint8_t value2) {
536     uint8_t packet[] = { type, value, value2 };
537     DPRINTF("writing key %x %x\n", type, value);
538     baum_write_packet(baum, packet, sizeof(packet));
539 }
540
541 /* We got some data on the BrlAPI socket */
542 static void baum_chr_read(void *opaque)
543 {
544     BaumDriverState *baum = opaque;
545     brlapi_keyCode_t code;
546     int ret;
547     if (!baum->brlapi)
548         return;
549     if (!baum_deferred_init(baum))
550         return;
551     while ((ret = brlapi__readKey(baum->brlapi, 0, &code)) == 1) {
552         DPRINTF("got key %"BRLAPI_PRIxKEYCODE"\n", code);
553         /* Emulate */
554         switch (code & BRLAPI_KEY_TYPE_MASK) {
555         case BRLAPI_KEY_TYPE_CMD:
556             switch (code & BRLAPI_KEY_CMD_BLK_MASK) {
557             case BRLAPI_KEY_CMD_ROUTE:
558                 baum_send_key(baum, BAUM_RSP_RoutingKey, (code & BRLAPI_KEY_CMD_ARG_MASK)+1);
559                 baum_send_key(baum, BAUM_RSP_RoutingKey, 0);
560                 break;
561             case 0:
562                 switch (code & BRLAPI_KEY_CMD_ARG_MASK) {
563                 case BRLAPI_KEY_CMD_FWINLT:
564                     baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2);
565                     baum_send_key(baum, BAUM_RSP_TopKeys, 0);
566                     break;
567                 case BRLAPI_KEY_CMD_FWINRT:
568                     baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR2);
569                     baum_send_key(baum, BAUM_RSP_TopKeys, 0);
570                     break;
571                 case BRLAPI_KEY_CMD_LNUP:
572                     baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR1);
573                     baum_send_key(baum, BAUM_RSP_TopKeys, 0);
574                     break;
575                 case BRLAPI_KEY_CMD_LNDN:
576                     baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR3);
577                     baum_send_key(baum, BAUM_RSP_TopKeys, 0);
578                     break;
579                 case BRLAPI_KEY_CMD_TOP:
580                     baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL1|BAUM_TR1);
581                     baum_send_key(baum, BAUM_RSP_TopKeys, 0);
582                     break;
583                 case BRLAPI_KEY_CMD_BOT:
584                     baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL3|BAUM_TR3);
585                     baum_send_key(baum, BAUM_RSP_TopKeys, 0);
586                     break;
587                 case BRLAPI_KEY_CMD_TOP_LEFT:
588                     baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR1);
589                     baum_send_key(baum, BAUM_RSP_TopKeys, 0);
590                     break;
591                 case BRLAPI_KEY_CMD_BOT_LEFT:
592                     baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR3);
593                     baum_send_key(baum, BAUM_RSP_TopKeys, 0);
594                     break;
595                 case BRLAPI_KEY_CMD_HOME:
596                     baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR1|BAUM_TR3);
597                     baum_send_key(baum, BAUM_RSP_TopKeys, 0);
598                     break;
599                 case BRLAPI_KEY_CMD_PREFMENU:
600                     baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL1|BAUM_TL3|BAUM_TR1);
601                     baum_send_key(baum, BAUM_RSP_TopKeys, 0);
602                     break;
603                 }
604             }
605             break;
606         case BRLAPI_KEY_TYPE_SYM:
607             {
608                 brlapi_keyCode_t keysym = code & BRLAPI_KEY_CODE_MASK;
609                 if (keysym < 0x100) {
610                     uint8_t dots = nabcc_translation[ASCII2DOTS][keysym];
611                     if (dots) {
612                         baum_send_key2(baum, BAUM_RSP_EntryKeys, 0, dots);
613                         baum_send_key2(baum, BAUM_RSP_EntryKeys, 0, 0);
614                     }
615                 }
616                 break;
617             }
618         }
619     }
620     if (ret == -1 && (brlapi_errno != BRLAPI_ERROR_LIBCERR || errno != EINTR)) {
621         brlapi_perror("baum: brlapi_readKey");
622         brlapi__closeConnection(baum->brlapi);
623         g_free(baum->brlapi);
624         baum->brlapi = NULL;
625     }
626 }
627
628 static void baum_free(struct CharDriverState *chr)
629 {
630     BaumDriverState *baum = chr->opaque;
631
632     timer_free(baum->cellCount_timer);
633     if (baum->brlapi) {
634         brlapi__closeConnection(baum->brlapi);
635         g_free(baum->brlapi);
636     }
637     g_free(baum);
638 }
639
640 static CharDriverState *chr_baum_init(const char *id,
641                                       ChardevBackend *backend,
642                                       ChardevReturn *ret,
643                                       bool *be_opened,
644                                       Error **errp)
645 {
646     ChardevCommon *common = backend->u.braille.data;
647     BaumDriverState *baum;
648     CharDriverState *chr;
649     brlapi_handle_t *handle;
650
651     chr = qemu_chr_alloc(common, errp);
652     if (!chr) {
653         return NULL;
654     }
655     baum = g_malloc0(sizeof(BaumDriverState));
656     baum->chr = chr;
657
658     chr->opaque = baum;
659     chr->chr_write = baum_write;
660     chr->chr_accept_input = baum_accept_input;
661     chr->chr_free = baum_free;
662
663     handle = g_malloc0(brlapi_getHandleSize());
664     baum->brlapi = handle;
665
666     baum->brlapi_fd = brlapi__openConnection(handle, NULL, NULL);
667     if (baum->brlapi_fd == -1) {
668         error_setg(errp, "brlapi__openConnection: %s",
669                    brlapi_strerror(brlapi_error_location()));
670         goto fail_handle;
671     }
672     baum->deferred_init = 0;
673
674     baum->cellCount_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, baum_cellCount_timer_cb, baum);
675
676     qemu_set_fd_handler(baum->brlapi_fd, baum_chr_read, NULL, baum);
677
678     return chr;
679
680 fail_handle:
681     g_free(handle);
682     g_free(chr);
683     g_free(baum);
684     return NULL;
685 }
686
687 static void register_types(void)
688 {
689     register_char_driver("braille", CHARDEV_BACKEND_KIND_BRAILLE, NULL,
690                          chr_baum_init);
691 }
692
693 type_init(register_types);