File:  [Qemu by Fabrice Bellard] / qemu / hw / baum.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 18:29:45 2018 UTC (2 years, 3 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu0150, qemu0141, qemu0140, qemu0130, HEAD
qemu 0.13.0

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

unix.superglobalmegacorp.com