Annotation of qemu/hw/baum.c, revision 1.1.1.1

1.1       root        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:     baum->chr = chr = qemu_mallocz(sizeof(CharDriverState));
                    579: 
                    580:     chr->opaque = baum;
                    581:     chr->chr_write = baum_write;
                    582:     chr->chr_send_event = baum_send_event;
                    583:     chr->chr_accept_input = baum_accept_input;
                    584: 
                    585:     handle = qemu_mallocz(brlapi_getHandleSize());
                    586:     baum->brlapi = handle;
                    587: 
                    588:     baum->brlapi_fd = brlapi__openConnection(handle, NULL, NULL);
                    589:     if (baum->brlapi_fd == -1) {
                    590:         brlapi_perror("baum_init: brlapi_openConnection");
                    591:         goto fail_handle;
                    592:     }
                    593: 
                    594:     baum->cellCount_timer = qemu_new_timer(vm_clock, baum_cellCount_timer_cb, baum);
                    595: 
                    596:     if (brlapi__getDisplaySize(handle, &baum->x, &baum->y) == -1) {
                    597:         brlapi_perror("baum_init: brlapi_getDisplaySize");
                    598:         goto fail;
                    599:     }
                    600: 
                    601: #ifdef CONFIG_SDL
                    602:     memset(&info, 0, sizeof(info));
                    603:     SDL_VERSION(&info.version);
                    604:     if (SDL_GetWMInfo(&info))
                    605:         tty = info.info.x11.wmwindow;
                    606:     else
                    607: #endif
                    608:         tty = BRLAPI_TTY_DEFAULT;
                    609: 
                    610:     if (brlapi__enterTtyMode(handle, tty, NULL) == -1) {
                    611:         brlapi_perror("baum_init: brlapi_enterTtyMode");
                    612:         goto fail;
                    613:     }
                    614: 
                    615:     qemu_set_fd_handler(baum->brlapi_fd, baum_chr_read, NULL, baum);
                    616: 
                    617:     qemu_chr_reset(chr);
                    618: 
                    619:     return chr;
                    620: 
                    621: fail:
                    622:     qemu_free_timer(baum->cellCount_timer);
                    623:     brlapi__closeConnection(handle);
                    624: fail_handle:
                    625:     free(handle);
                    626:     free(chr);
                    627:     free(baum);
                    628:     return NULL;
                    629: }
                    630: 
                    631: USBDevice *usb_baum_init(void)
                    632: {
                    633:     /* USB Product ID of Super Vario 40 */
                    634:     return usb_serial_init("productid=FE72:braille");
                    635: }

unix.superglobalmegacorp.com