symbian-qemu-0.9.1-12/qemu-symbian-svp/hw/baum.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     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 <assert.h>
       
    30 #include <brlapi.h>
       
    31 #include <brlapi_constants.h>
       
    32 #include <brlapi_keycodes.h>
       
    33 #ifdef CONFIG_SDL
       
    34 #include <SDL/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     int x, y;
       
    95 
       
    96     uint8_t in_buf[BUF_SIZE];
       
    97     uint8_t in_buf_used;
       
    98     uint8_t out_buf[BUF_SIZE];
       
    99     uint8_t out_buf_used, out_buf_ptr;
       
   100 
       
   101     QEMUTimer *cellCount_timer;
       
   102 } BaumDriverState;
       
   103 
       
   104 /* Let's assume NABCC by default */
       
   105 static const uint8_t nabcc_translation[256] = {
       
   106     [0] = ' ',
       
   107 #ifndef BRLAPI_DOTS
       
   108 #define BRLAPI_DOTS(d1,d2,d3,d4,d5,d6,d7,d8) \
       
   109     ((d1?BRLAPI_DOT1:0)|\
       
   110      (d2?BRLAPI_DOT2:0)|\
       
   111      (d3?BRLAPI_DOT3:0)|\
       
   112      (d4?BRLAPI_DOT4:0)|\
       
   113      (d5?BRLAPI_DOT5:0)|\
       
   114      (d6?BRLAPI_DOT6:0)|\
       
   115      (d7?BRLAPI_DOT7:0)|\
       
   116      (d8?BRLAPI_DOT8:0))
       
   117 #endif
       
   118     [BRLAPI_DOTS(1,0,0,0,0,0,0,0)] = 'a',
       
   119     [BRLAPI_DOTS(1,1,0,0,0,0,0,0)] = 'b',
       
   120     [BRLAPI_DOTS(1,0,0,1,0,0,0,0)] = 'c',
       
   121     [BRLAPI_DOTS(1,0,0,1,1,0,0,0)] = 'd',
       
   122     [BRLAPI_DOTS(1,0,0,0,1,0,0,0)] = 'e',
       
   123     [BRLAPI_DOTS(1,1,0,1,0,0,0,0)] = 'f',
       
   124     [BRLAPI_DOTS(1,1,0,1,1,0,0,0)] = 'g',
       
   125     [BRLAPI_DOTS(1,1,0,0,1,0,0,0)] = 'h',
       
   126     [BRLAPI_DOTS(0,1,0,1,0,0,0,0)] = 'i',
       
   127     [BRLAPI_DOTS(0,1,0,1,1,0,0,0)] = 'j',
       
   128     [BRLAPI_DOTS(1,0,1,0,0,0,0,0)] = 'k',
       
   129     [BRLAPI_DOTS(1,1,1,0,0,0,0,0)] = 'l',
       
   130     [BRLAPI_DOTS(1,0,1,1,0,0,0,0)] = 'm',
       
   131     [BRLAPI_DOTS(1,0,1,1,1,0,0,0)] = 'n',
       
   132     [BRLAPI_DOTS(1,0,1,0,1,0,0,0)] = 'o',
       
   133     [BRLAPI_DOTS(1,1,1,1,0,0,0,0)] = 'p',
       
   134     [BRLAPI_DOTS(1,1,1,1,1,0,0,0)] = 'q',
       
   135     [BRLAPI_DOTS(1,1,1,0,1,0,0,0)] = 'r',
       
   136     [BRLAPI_DOTS(0,1,1,1,0,0,0,0)] = 's',
       
   137     [BRLAPI_DOTS(0,1,1,1,1,0,0,0)] = 't',
       
   138     [BRLAPI_DOTS(1,0,1,0,0,1,0,0)] = 'u',
       
   139     [BRLAPI_DOTS(1,1,1,0,0,1,0,0)] = 'v',
       
   140     [BRLAPI_DOTS(0,1,0,1,1,1,0,0)] = 'w',
       
   141     [BRLAPI_DOTS(1,0,1,1,0,1,0,0)] = 'x',
       
   142     [BRLAPI_DOTS(1,0,1,1,1,1,0,0)] = 'y',
       
   143     [BRLAPI_DOTS(1,0,1,0,1,1,0,0)] = 'z',
       
   144 
       
   145     [BRLAPI_DOTS(1,0,0,0,0,0,1,0)] = 'A',
       
   146     [BRLAPI_DOTS(1,1,0,0,0,0,1,0)] = 'B',
       
   147     [BRLAPI_DOTS(1,0,0,1,0,0,1,0)] = 'C',
       
   148     [BRLAPI_DOTS(1,0,0,1,1,0,1,0)] = 'D',
       
   149     [BRLAPI_DOTS(1,0,0,0,1,0,1,0)] = 'E',
       
   150     [BRLAPI_DOTS(1,1,0,1,0,0,1,0)] = 'F',
       
   151     [BRLAPI_DOTS(1,1,0,1,1,0,1,0)] = 'G',
       
   152     [BRLAPI_DOTS(1,1,0,0,1,0,1,0)] = 'H',
       
   153     [BRLAPI_DOTS(0,1,0,1,0,0,1,0)] = 'I',
       
   154     [BRLAPI_DOTS(0,1,0,1,1,0,1,0)] = 'J',
       
   155     [BRLAPI_DOTS(1,0,1,0,0,0,1,0)] = 'K',
       
   156     [BRLAPI_DOTS(1,1,1,0,0,0,1,0)] = 'L',
       
   157     [BRLAPI_DOTS(1,0,1,1,0,0,1,0)] = 'M',
       
   158     [BRLAPI_DOTS(1,0,1,1,1,0,1,0)] = 'N',
       
   159     [BRLAPI_DOTS(1,0,1,0,1,0,1,0)] = 'O',
       
   160     [BRLAPI_DOTS(1,1,1,1,0,0,1,0)] = 'P',
       
   161     [BRLAPI_DOTS(1,1,1,1,1,0,1,0)] = 'Q',
       
   162     [BRLAPI_DOTS(1,1,1,0,1,0,1,0)] = 'R',
       
   163     [BRLAPI_DOTS(0,1,1,1,0,0,1,0)] = 'S',
       
   164     [BRLAPI_DOTS(0,1,1,1,1,0,1,0)] = 'T',
       
   165     [BRLAPI_DOTS(1,0,1,0,0,1,1,0)] = 'U',
       
   166     [BRLAPI_DOTS(1,1,1,0,0,1,1,0)] = 'V',
       
   167     [BRLAPI_DOTS(0,1,0,1,1,1,1,0)] = 'W',
       
   168     [BRLAPI_DOTS(1,0,1,1,0,1,1,0)] = 'X',
       
   169     [BRLAPI_DOTS(1,0,1,1,1,1,1,0)] = 'Y',
       
   170     [BRLAPI_DOTS(1,0,1,0,1,1,1,0)] = 'Z',
       
   171 
       
   172     [BRLAPI_DOTS(0,0,1,0,1,1,0,0)] = '0',
       
   173     [BRLAPI_DOTS(0,1,0,0,0,0,0,0)] = '1',
       
   174     [BRLAPI_DOTS(0,1,1,0,0,0,0,0)] = '2',
       
   175     [BRLAPI_DOTS(0,1,0,0,1,0,0,0)] = '3',
       
   176     [BRLAPI_DOTS(0,1,0,0,1,1,0,0)] = '4',
       
   177     [BRLAPI_DOTS(0,1,0,0,0,1,0,0)] = '5',
       
   178     [BRLAPI_DOTS(0,1,1,0,1,0,0,0)] = '6',
       
   179     [BRLAPI_DOTS(0,1,1,0,1,1,0,0)] = '7',
       
   180     [BRLAPI_DOTS(0,1,1,0,0,1,0,0)] = '8',
       
   181     [BRLAPI_DOTS(0,0,1,0,1,0,0,0)] = '9',
       
   182 
       
   183     [BRLAPI_DOTS(0,0,0,1,0,1,0,0)] = '.',
       
   184     [BRLAPI_DOTS(0,0,1,1,0,1,0,0)] = '+',
       
   185     [BRLAPI_DOTS(0,0,1,0,0,1,0,0)] = '-',
       
   186     [BRLAPI_DOTS(1,0,0,0,0,1,0,0)] = '*',
       
   187     [BRLAPI_DOTS(0,0,1,1,0,0,0,0)] = '/',
       
   188     [BRLAPI_DOTS(1,1,1,0,1,1,0,0)] = '(',
       
   189     [BRLAPI_DOTS(0,1,1,1,1,1,0,0)] = ')',
       
   190 
       
   191     [BRLAPI_DOTS(1,1,1,1,0,1,0,0)] = '&',
       
   192     [BRLAPI_DOTS(0,0,1,1,1,1,0,0)] = '#',
       
   193 
       
   194     [BRLAPI_DOTS(0,0,0,0,0,1,0,0)] = ',',
       
   195     [BRLAPI_DOTS(0,0,0,0,1,1,0,0)] = ';',
       
   196     [BRLAPI_DOTS(1,0,0,0,1,1,0,0)] = ':',
       
   197     [BRLAPI_DOTS(0,1,1,1,0,1,0,0)] = '!',
       
   198     [BRLAPI_DOTS(1,0,0,1,1,1,0,0)] = '?',
       
   199     [BRLAPI_DOTS(0,0,0,0,1,0,0,0)] = '"',
       
   200     [BRLAPI_DOTS(0,0,1,0,0,0,0,0)] ='\'',
       
   201     [BRLAPI_DOTS(0,0,0,1,0,0,0,0)] = '`',
       
   202     [BRLAPI_DOTS(0,0,0,1,1,0,1,0)] = '^',
       
   203     [BRLAPI_DOTS(0,0,0,1,1,0,0,0)] = '~',
       
   204     [BRLAPI_DOTS(0,1,0,1,0,1,1,0)] = '[',
       
   205     [BRLAPI_DOTS(1,1,0,1,1,1,1,0)] = ']',
       
   206     [BRLAPI_DOTS(0,1,0,1,0,1,0,0)] = '{',
       
   207     [BRLAPI_DOTS(1,1,0,1,1,1,0,0)] = '}',
       
   208     [BRLAPI_DOTS(1,1,1,1,1,1,0,0)] = '=',
       
   209     [BRLAPI_DOTS(1,1,0,0,0,1,0,0)] = '<',
       
   210     [BRLAPI_DOTS(0,0,1,1,1,0,0,0)] = '>',
       
   211     [BRLAPI_DOTS(1,1,0,1,0,1,0,0)] = '$',
       
   212     [BRLAPI_DOTS(1,0,0,1,0,1,0,0)] = '%',
       
   213     [BRLAPI_DOTS(0,0,0,1,0,0,1,0)] = '@',
       
   214     [BRLAPI_DOTS(1,1,0,0,1,1,0,0)] = '|',
       
   215     [BRLAPI_DOTS(1,1,0,0,1,1,1,0)] ='\\',
       
   216     [BRLAPI_DOTS(0,0,0,1,1,1,0,0)] = '_',
       
   217 };
       
   218 
       
   219 /* The serial port can receive more of our data */
       
   220 static void baum_accept_input(struct CharDriverState *chr)
       
   221 {
       
   222     BaumDriverState *baum = chr->opaque;
       
   223     int room, first;
       
   224 
       
   225     if (!baum->out_buf_used)
       
   226         return;
       
   227     room = qemu_chr_can_read(chr);
       
   228     if (!room)
       
   229         return;
       
   230     if (room > baum->out_buf_used)
       
   231         room = baum->out_buf_used;
       
   232 
       
   233     first = BUF_SIZE - baum->out_buf_ptr;
       
   234     if (room > first) {
       
   235         qemu_chr_read(chr, baum->out_buf + baum->out_buf_ptr, first);
       
   236         baum->out_buf_ptr = 0;
       
   237         baum->out_buf_used -= first;
       
   238         room -= first;
       
   239     }
       
   240     qemu_chr_read(chr, baum->out_buf + baum->out_buf_ptr, room);
       
   241     baum->out_buf_ptr += room;
       
   242     baum->out_buf_used -= room;
       
   243 }
       
   244 
       
   245 /* We want to send a packet */
       
   246 static void baum_write_packet(BaumDriverState *baum, const uint8_t *buf, int len)
       
   247 {
       
   248     uint8_t io_buf[1 + 2 * len], *cur = io_buf;
       
   249     int room;
       
   250     *cur++ = ESC;
       
   251     while (len--)
       
   252         if ((*cur++ = *buf++) == ESC)
       
   253             *cur++ = ESC;
       
   254     room = qemu_chr_can_read(baum->chr);
       
   255     len = cur - io_buf;
       
   256     if (len <= room) {
       
   257         /* Fits */
       
   258         qemu_chr_read(baum->chr, io_buf, len);
       
   259     } else {
       
   260         int first;
       
   261         uint8_t out;
       
   262         /* Can't fit all, send what can be, and store the rest. */
       
   263         qemu_chr_read(baum->chr, io_buf, room);
       
   264         len -= room;
       
   265         cur = io_buf + room;
       
   266         if (len > BUF_SIZE - baum->out_buf_used) {
       
   267             /* Can't even store it, drop the previous data... */
       
   268             assert(len <= BUF_SIZE);
       
   269             baum->out_buf_used = 0;
       
   270             baum->out_buf_ptr = 0;
       
   271         }
       
   272         out = baum->out_buf_ptr;
       
   273         baum->out_buf_used += len;
       
   274         first = BUF_SIZE - baum->out_buf_ptr;
       
   275         if (len > first) {
       
   276             memcpy(baum->out_buf + out, cur, first);
       
   277             out = 0;
       
   278             len -= first;
       
   279             cur += first;
       
   280         }
       
   281         memcpy(baum->out_buf + out, cur, len);
       
   282     }
       
   283 }
       
   284 
       
   285 /* Called when the other end seems to have a wrong idea of our display size */
       
   286 static void baum_cellCount_timer_cb(void *opaque)
       
   287 {
       
   288     BaumDriverState *baum = opaque;
       
   289     uint8_t cell_count[] = { BAUM_RSP_CellCount, baum->x * baum->y };
       
   290     DPRINTF("Timeout waiting for DisplayData, sending cell count\n");
       
   291     baum_write_packet(baum, cell_count, sizeof(cell_count));
       
   292 }
       
   293 
       
   294 /* Try to interpret a whole incoming packet */
       
   295 static int baum_eat_packet(BaumDriverState *baum, const uint8_t *buf, int len)
       
   296 {
       
   297     const uint8_t *cur = buf;
       
   298     uint8_t req = 0;
       
   299 
       
   300     if (!len--)
       
   301         return 0;
       
   302     if (*cur++ != ESC) {
       
   303         while (*cur != ESC) {
       
   304             if (!len--)
       
   305                 return 0;
       
   306             cur++;
       
   307         }
       
   308         DPRINTF("Dropped %d bytes!\n", cur - buf);
       
   309     }
       
   310 
       
   311 #define EAT(c) do {\
       
   312     if (!len--) \
       
   313         return 0; \
       
   314     if ((c = *cur++) == ESC) { \
       
   315         if (!len--) \
       
   316             return 0; \
       
   317         if (*cur++ != ESC) { \
       
   318             DPRINTF("Broken packet %#2x, tossing\n", req); \
       
   319 		if (qemu_timer_pending(baum->cellCount_timer)) { \
       
   320                 qemu_del_timer(baum->cellCount_timer); \
       
   321                 baum_cellCount_timer_cb(baum); \
       
   322             } \
       
   323             return (cur - 2 - buf); \
       
   324         } \
       
   325     } \
       
   326 } while (0)
       
   327 
       
   328     EAT(req);
       
   329     switch (req) {
       
   330     case BAUM_REQ_DisplayData:
       
   331     {
       
   332         uint8_t cells[baum->x * baum->y], c;
       
   333         uint8_t text[baum->x * baum->y];
       
   334         uint8_t zero[baum->x * baum->y];
       
   335         int cursor = BRLAPI_CURSOR_OFF;
       
   336         int i;
       
   337 
       
   338         /* Allow 100ms to complete the DisplayData packet */
       
   339         qemu_mod_timer(baum->cellCount_timer, qemu_get_clock(vm_clock) + 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 = text,
       
   361             .textSize = baum->x * baum->y,
       
   362             .andMask = zero,
       
   363             .orMask = cells,
       
   364             .cursor = cursor,
       
   365             .charset = "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_RESET:
       
   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         free(baum->brlapi);
       
   563         baum->brlapi = NULL;
       
   564     }
       
   565 }
       
   566 
       
   567 CharDriverState *chr_baum_init(void)
       
   568 {
       
   569     BaumDriverState *baum;
       
   570     CharDriverState *chr;
       
   571     brlapi_handle_t *handle;
       
   572 #ifdef CONFIG_SDL
       
   573     SDL_SysWMinfo info;
       
   574 #endif
       
   575     int tty;
       
   576 
       
   577     baum = qemu_mallocz(sizeof(BaumDriverState));
       
   578     if (!baum)
       
   579         return NULL;
       
   580 
       
   581     baum->chr = chr = qemu_mallocz(sizeof(CharDriverState));
       
   582     if (!chr)
       
   583         goto fail_baum;
       
   584 
       
   585     chr->opaque = baum;
       
   586     chr->chr_write = baum_write;
       
   587     chr->chr_send_event = baum_send_event;
       
   588     chr->chr_accept_input = baum_accept_input;
       
   589 
       
   590     handle = qemu_mallocz(brlapi_getHandleSize());
       
   591     if (!handle)
       
   592         goto fail_chr;
       
   593     baum->brlapi = handle;
       
   594 
       
   595     baum->brlapi_fd = brlapi__openConnection(handle, NULL, NULL);
       
   596     if (baum->brlapi_fd == -1) {
       
   597         brlapi_perror("baum_init: brlapi_openConnection");
       
   598         goto fail_handle;
       
   599     }
       
   600 
       
   601     baum->cellCount_timer = qemu_new_timer(vm_clock, baum_cellCount_timer_cb, baum);
       
   602 
       
   603     if (brlapi__getDisplaySize(handle, &baum->x, &baum->y) == -1) {
       
   604         brlapi_perror("baum_init: brlapi_getDisplaySize");
       
   605         goto fail;
       
   606     }
       
   607 
       
   608 #ifdef CONFIG_SDL
       
   609     memset(&info, 0, sizeof(info));
       
   610     SDL_VERSION(&info.version);
       
   611     if (SDL_GetWMInfo(&info))
       
   612         tty = info.info.x11.wmwindow;
       
   613     else
       
   614 #endif
       
   615         tty = BRLAPI_TTY_DEFAULT;
       
   616 
       
   617     if (brlapi__enterTtyMode(handle, tty, NULL) == -1) {
       
   618         brlapi_perror("baum_init: brlapi_enterTtyMode");
       
   619         goto fail;
       
   620     }
       
   621 
       
   622     qemu_set_fd_handler(baum->brlapi_fd, baum_chr_read, NULL, baum);
       
   623 
       
   624     qemu_chr_reset(chr);
       
   625 
       
   626     return chr;
       
   627 
       
   628 fail:
       
   629     qemu_free_timer(baum->cellCount_timer);
       
   630     brlapi__closeConnection(handle);
       
   631 fail_handle:
       
   632     free(handle);
       
   633 fail_chr:
       
   634     free(chr);
       
   635 fail_baum:
       
   636     free(baum);
       
   637     return NULL;
       
   638 }
       
   639 
       
   640 USBDevice *usb_baum_init(void)
       
   641 {
       
   642     /* USB Product ID of Super Vario 40 */
       
   643     return usb_serial_init("productid=FE72:braille");
       
   644 }