From 159b6e9f144c7afdf3ad95c29d1fede9626fa8b1 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sun, 3 Feb 2013 20:21:00 +0100 Subject: hw: move char backends to backends/ Braille and msmouse support is in hw/, but it is not hardware. Move it to the backends/ directory. Signed-off-by: Paolo Bonzini --- backends/Makefile.objs | 4 + backends/baum.c | 627 +++++++++++++++++++++++++++++++++++++++++++++++++ backends/msmouse.c | 78 ++++++ hw/Makefile.objs | 4 +- hw/baum.c | 627 ------------------------------------------------- hw/baum.h | 30 --- hw/msmouse.c | 78 ------ hw/msmouse.h | 7 - include/char/baum.h | 30 +++ include/char/msmouse.h | 7 + qemu-char.c | 4 +- vl.c | 2 +- 12 files changed, 750 insertions(+), 748 deletions(-) create mode 100644 backends/baum.c create mode 100644 backends/msmouse.c delete mode 100644 hw/baum.c delete mode 100644 hw/baum.h delete mode 100644 hw/msmouse.c delete mode 100644 hw/msmouse.h create mode 100644 include/char/baum.h create mode 100644 include/char/msmouse.h diff --git a/backends/Makefile.objs b/backends/Makefile.objs index 8836761..464bc3e 100644 --- a/backends/Makefile.objs +++ b/backends/Makefile.objs @@ -1,2 +1,6 @@ common-obj-y += rng.o rng-egd.o common-obj-$(CONFIG_POSIX) += rng-random.o + +common-obj-y += msmouse.o +common-obj-$(CONFIG_BRLAPI) += baum.o +$(obj)/baum.o: QEMU_CFLAGS += $(SDL_CFLAGS) diff --git a/backends/baum.c b/backends/baum.c new file mode 100644 index 0000000..37ccca8 --- /dev/null +++ b/backends/baum.c @@ -0,0 +1,627 @@ +/* + * QEMU Baum Braille Device + * + * Copyright (c) 2008 Samuel Thibault + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "qemu-common.h" +#include "char/char.h" +#include "qemu/timer.h" +#include "hw/usb.h" +#include "char/baum.h" +#include +#include +#include +#ifdef CONFIG_SDL +#include +#endif + +#if 0 +#define DPRINTF(fmt, ...) \ + printf(fmt, ## __VA_ARGS__) +#else +#define DPRINTF(fmt, ...) +#endif + +#define ESC 0x1B + +#define BAUM_REQ_DisplayData 0x01 +#define BAUM_REQ_GetVersionNumber 0x05 +#define BAUM_REQ_GetKeys 0x08 +#define BAUM_REQ_SetMode 0x12 +#define BAUM_REQ_SetProtocol 0x15 +#define BAUM_REQ_GetDeviceIdentity 0x84 +#define BAUM_REQ_GetSerialNumber 0x8A + +#define BAUM_RSP_CellCount 0x01 +#define BAUM_RSP_VersionNumber 0x05 +#define BAUM_RSP_ModeSetting 0x11 +#define BAUM_RSP_CommunicationChannel 0x16 +#define BAUM_RSP_PowerdownSignal 0x17 +#define BAUM_RSP_HorizontalSensors 0x20 +#define BAUM_RSP_VerticalSensors 0x21 +#define BAUM_RSP_RoutingKeys 0x22 +#define BAUM_RSP_Switches 0x23 +#define BAUM_RSP_TopKeys 0x24 +#define BAUM_RSP_HorizontalSensor 0x25 +#define BAUM_RSP_VerticalSensor 0x26 +#define BAUM_RSP_RoutingKey 0x27 +#define BAUM_RSP_FrontKeys6 0x28 +#define BAUM_RSP_BackKeys6 0x29 +#define BAUM_RSP_CommandKeys 0x2B +#define BAUM_RSP_FrontKeys10 0x2C +#define BAUM_RSP_BackKeys10 0x2D +#define BAUM_RSP_EntryKeys 0x33 +#define BAUM_RSP_JoyStick 0x34 +#define BAUM_RSP_ErrorCode 0x40 +#define BAUM_RSP_InfoBlock 0x42 +#define BAUM_RSP_DeviceIdentity 0x84 +#define BAUM_RSP_SerialNumber 0x8A +#define BAUM_RSP_BluetoothName 0x8C + +#define BAUM_TL1 0x01 +#define BAUM_TL2 0x02 +#define BAUM_TL3 0x04 +#define BAUM_TR1 0x08 +#define BAUM_TR2 0x10 +#define BAUM_TR3 0x20 + +#define BUF_SIZE 256 + +typedef struct { + CharDriverState *chr; + + brlapi_handle_t *brlapi; + int brlapi_fd; + unsigned int x, y; + + uint8_t in_buf[BUF_SIZE]; + uint8_t in_buf_used; + uint8_t out_buf[BUF_SIZE]; + uint8_t out_buf_used, out_buf_ptr; + + QEMUTimer *cellCount_timer; +} BaumDriverState; + +/* Let's assume NABCC by default */ +static const uint8_t nabcc_translation[256] = { + [0] = ' ', +#ifndef BRLAPI_DOTS +#define BRLAPI_DOTS(d1,d2,d3,d4,d5,d6,d7,d8) \ + ((d1?BRLAPI_DOT1:0)|\ + (d2?BRLAPI_DOT2:0)|\ + (d3?BRLAPI_DOT3:0)|\ + (d4?BRLAPI_DOT4:0)|\ + (d5?BRLAPI_DOT5:0)|\ + (d6?BRLAPI_DOT6:0)|\ + (d7?BRLAPI_DOT7:0)|\ + (d8?BRLAPI_DOT8:0)) +#endif + [BRLAPI_DOTS(1,0,0,0,0,0,0,0)] = 'a', + [BRLAPI_DOTS(1,1,0,0,0,0,0,0)] = 'b', + [BRLAPI_DOTS(1,0,0,1,0,0,0,0)] = 'c', + [BRLAPI_DOTS(1,0,0,1,1,0,0,0)] = 'd', + [BRLAPI_DOTS(1,0,0,0,1,0,0,0)] = 'e', + [BRLAPI_DOTS(1,1,0,1,0,0,0,0)] = 'f', + [BRLAPI_DOTS(1,1,0,1,1,0,0,0)] = 'g', + [BRLAPI_DOTS(1,1,0,0,1,0,0,0)] = 'h', + [BRLAPI_DOTS(0,1,0,1,0,0,0,0)] = 'i', + [BRLAPI_DOTS(0,1,0,1,1,0,0,0)] = 'j', + [BRLAPI_DOTS(1,0,1,0,0,0,0,0)] = 'k', + [BRLAPI_DOTS(1,1,1,0,0,0,0,0)] = 'l', + [BRLAPI_DOTS(1,0,1,1,0,0,0,0)] = 'm', + [BRLAPI_DOTS(1,0,1,1,1,0,0,0)] = 'n', + [BRLAPI_DOTS(1,0,1,0,1,0,0,0)] = 'o', + [BRLAPI_DOTS(1,1,1,1,0,0,0,0)] = 'p', + [BRLAPI_DOTS(1,1,1,1,1,0,0,0)] = 'q', + [BRLAPI_DOTS(1,1,1,0,1,0,0,0)] = 'r', + [BRLAPI_DOTS(0,1,1,1,0,0,0,0)] = 's', + [BRLAPI_DOTS(0,1,1,1,1,0,0,0)] = 't', + [BRLAPI_DOTS(1,0,1,0,0,1,0,0)] = 'u', + [BRLAPI_DOTS(1,1,1,0,0,1,0,0)] = 'v', + [BRLAPI_DOTS(0,1,0,1,1,1,0,0)] = 'w', + [BRLAPI_DOTS(1,0,1,1,0,1,0,0)] = 'x', + [BRLAPI_DOTS(1,0,1,1,1,1,0,0)] = 'y', + [BRLAPI_DOTS(1,0,1,0,1,1,0,0)] = 'z', + + [BRLAPI_DOTS(1,0,0,0,0,0,1,0)] = 'A', + [BRLAPI_DOTS(1,1,0,0,0,0,1,0)] = 'B', + [BRLAPI_DOTS(1,0,0,1,0,0,1,0)] = 'C', + [BRLAPI_DOTS(1,0,0,1,1,0,1,0)] = 'D', + [BRLAPI_DOTS(1,0,0,0,1,0,1,0)] = 'E', + [BRLAPI_DOTS(1,1,0,1,0,0,1,0)] = 'F', + [BRLAPI_DOTS(1,1,0,1,1,0,1,0)] = 'G', + [BRLAPI_DOTS(1,1,0,0,1,0,1,0)] = 'H', + [BRLAPI_DOTS(0,1,0,1,0,0,1,0)] = 'I', + [BRLAPI_DOTS(0,1,0,1,1,0,1,0)] = 'J', + [BRLAPI_DOTS(1,0,1,0,0,0,1,0)] = 'K', + [BRLAPI_DOTS(1,1,1,0,0,0,1,0)] = 'L', + [BRLAPI_DOTS(1,0,1,1,0,0,1,0)] = 'M', + [BRLAPI_DOTS(1,0,1,1,1,0,1,0)] = 'N', + [BRLAPI_DOTS(1,0,1,0,1,0,1,0)] = 'O', + [BRLAPI_DOTS(1,1,1,1,0,0,1,0)] = 'P', + [BRLAPI_DOTS(1,1,1,1,1,0,1,0)] = 'Q', + [BRLAPI_DOTS(1,1,1,0,1,0,1,0)] = 'R', + [BRLAPI_DOTS(0,1,1,1,0,0,1,0)] = 'S', + [BRLAPI_DOTS(0,1,1,1,1,0,1,0)] = 'T', + [BRLAPI_DOTS(1,0,1,0,0,1,1,0)] = 'U', + [BRLAPI_DOTS(1,1,1,0,0,1,1,0)] = 'V', + [BRLAPI_DOTS(0,1,0,1,1,1,1,0)] = 'W', + [BRLAPI_DOTS(1,0,1,1,0,1,1,0)] = 'X', + [BRLAPI_DOTS(1,0,1,1,1,1,1,0)] = 'Y', + [BRLAPI_DOTS(1,0,1,0,1,1,1,0)] = 'Z', + + [BRLAPI_DOTS(0,0,1,0,1,1,0,0)] = '0', + [BRLAPI_DOTS(0,1,0,0,0,0,0,0)] = '1', + [BRLAPI_DOTS(0,1,1,0,0,0,0,0)] = '2', + [BRLAPI_DOTS(0,1,0,0,1,0,0,0)] = '3', + [BRLAPI_DOTS(0,1,0,0,1,1,0,0)] = '4', + [BRLAPI_DOTS(0,1,0,0,0,1,0,0)] = '5', + [BRLAPI_DOTS(0,1,1,0,1,0,0,0)] = '6', + [BRLAPI_DOTS(0,1,1,0,1,1,0,0)] = '7', + [BRLAPI_DOTS(0,1,1,0,0,1,0,0)] = '8', + [BRLAPI_DOTS(0,0,1,0,1,0,0,0)] = '9', + + [BRLAPI_DOTS(0,0,0,1,0,1,0,0)] = '.', + [BRLAPI_DOTS(0,0,1,1,0,1,0,0)] = '+', + [BRLAPI_DOTS(0,0,1,0,0,1,0,0)] = '-', + [BRLAPI_DOTS(1,0,0,0,0,1,0,0)] = '*', + [BRLAPI_DOTS(0,0,1,1,0,0,0,0)] = '/', + [BRLAPI_DOTS(1,1,1,0,1,1,0,0)] = '(', + [BRLAPI_DOTS(0,1,1,1,1,1,0,0)] = ')', + + [BRLAPI_DOTS(1,1,1,1,0,1,0,0)] = '&', + [BRLAPI_DOTS(0,0,1,1,1,1,0,0)] = '#', + + [BRLAPI_DOTS(0,0,0,0,0,1,0,0)] = ',', + [BRLAPI_DOTS(0,0,0,0,1,1,0,0)] = ';', + [BRLAPI_DOTS(1,0,0,0,1,1,0,0)] = ':', + [BRLAPI_DOTS(0,1,1,1,0,1,0,0)] = '!', + [BRLAPI_DOTS(1,0,0,1,1,1,0,0)] = '?', + [BRLAPI_DOTS(0,0,0,0,1,0,0,0)] = '"', + [BRLAPI_DOTS(0,0,1,0,0,0,0,0)] ='\'', + [BRLAPI_DOTS(0,0,0,1,0,0,0,0)] = '`', + [BRLAPI_DOTS(0,0,0,1,1,0,1,0)] = '^', + [BRLAPI_DOTS(0,0,0,1,1,0,0,0)] = '~', + [BRLAPI_DOTS(0,1,0,1,0,1,1,0)] = '[', + [BRLAPI_DOTS(1,1,0,1,1,1,1,0)] = ']', + [BRLAPI_DOTS(0,1,0,1,0,1,0,0)] = '{', + [BRLAPI_DOTS(1,1,0,1,1,1,0,0)] = '}', + [BRLAPI_DOTS(1,1,1,1,1,1,0,0)] = '=', + [BRLAPI_DOTS(1,1,0,0,0,1,0,0)] = '<', + [BRLAPI_DOTS(0,0,1,1,1,0,0,0)] = '>', + [BRLAPI_DOTS(1,1,0,1,0,1,0,0)] = '$', + [BRLAPI_DOTS(1,0,0,1,0,1,0,0)] = '%', + [BRLAPI_DOTS(0,0,0,1,0,0,1,0)] = '@', + [BRLAPI_DOTS(1,1,0,0,1,1,0,0)] = '|', + [BRLAPI_DOTS(1,1,0,0,1,1,1,0)] ='\\', + [BRLAPI_DOTS(0,0,0,1,1,1,0,0)] = '_', +}; + +/* The serial port can receive more of our data */ +static void baum_accept_input(struct CharDriverState *chr) +{ + BaumDriverState *baum = chr->opaque; + int room, first; + + if (!baum->out_buf_used) + return; + room = qemu_chr_be_can_write(chr); + if (!room) + return; + if (room > baum->out_buf_used) + room = baum->out_buf_used; + + first = BUF_SIZE - baum->out_buf_ptr; + if (room > first) { + qemu_chr_be_write(chr, baum->out_buf + baum->out_buf_ptr, first); + baum->out_buf_ptr = 0; + baum->out_buf_used -= first; + room -= first; + } + qemu_chr_be_write(chr, baum->out_buf + baum->out_buf_ptr, room); + baum->out_buf_ptr += room; + baum->out_buf_used -= room; +} + +/* We want to send a packet */ +static void baum_write_packet(BaumDriverState *baum, const uint8_t *buf, int len) +{ + uint8_t io_buf[1 + 2 * len], *cur = io_buf; + int room; + *cur++ = ESC; + while (len--) + if ((*cur++ = *buf++) == ESC) + *cur++ = ESC; + room = qemu_chr_be_can_write(baum->chr); + len = cur - io_buf; + if (len <= room) { + /* Fits */ + qemu_chr_be_write(baum->chr, io_buf, len); + } else { + int first; + uint8_t out; + /* Can't fit all, send what can be, and store the rest. */ + qemu_chr_be_write(baum->chr, io_buf, room); + len -= room; + cur = io_buf + room; + if (len > BUF_SIZE - baum->out_buf_used) { + /* Can't even store it, drop the previous data... */ + assert(len <= BUF_SIZE); + baum->out_buf_used = 0; + baum->out_buf_ptr = 0; + } + out = baum->out_buf_ptr; + baum->out_buf_used += len; + first = BUF_SIZE - baum->out_buf_ptr; + if (len > first) { + memcpy(baum->out_buf + out, cur, first); + out = 0; + len -= first; + cur += first; + } + memcpy(baum->out_buf + out, cur, len); + } +} + +/* Called when the other end seems to have a wrong idea of our display size */ +static void baum_cellCount_timer_cb(void *opaque) +{ + BaumDriverState *baum = opaque; + uint8_t cell_count[] = { BAUM_RSP_CellCount, baum->x * baum->y }; + DPRINTF("Timeout waiting for DisplayData, sending cell count\n"); + baum_write_packet(baum, cell_count, sizeof(cell_count)); +} + +/* Try to interpret a whole incoming packet */ +static int baum_eat_packet(BaumDriverState *baum, const uint8_t *buf, int len) +{ + const uint8_t *cur = buf; + uint8_t req = 0; + + if (!len--) + return 0; + if (*cur++ != ESC) { + while (*cur != ESC) { + if (!len--) + return 0; + cur++; + } + DPRINTF("Dropped %d bytes!\n", cur - buf); + } + +#define EAT(c) do {\ + if (!len--) \ + return 0; \ + if ((c = *cur++) == ESC) { \ + if (!len--) \ + return 0; \ + if (*cur++ != ESC) { \ + DPRINTF("Broken packet %#2x, tossing\n", req); \ + if (qemu_timer_pending(baum->cellCount_timer)) { \ + qemu_del_timer(baum->cellCount_timer); \ + baum_cellCount_timer_cb(baum); \ + } \ + return (cur - 2 - buf); \ + } \ + } \ +} while (0) + + EAT(req); + switch (req) { + case BAUM_REQ_DisplayData: + { + uint8_t cells[baum->x * baum->y], c; + uint8_t text[baum->x * baum->y]; + uint8_t zero[baum->x * baum->y]; + int cursor = BRLAPI_CURSOR_OFF; + int i; + + /* Allow 100ms to complete the DisplayData packet */ + qemu_mod_timer(baum->cellCount_timer, qemu_get_clock_ns(vm_clock) + + get_ticks_per_sec() / 10); + for (i = 0; i < baum->x * baum->y ; i++) { + EAT(c); + cells[i] = c; + if ((c & (BRLAPI_DOT7|BRLAPI_DOT8)) + == (BRLAPI_DOT7|BRLAPI_DOT8)) { + cursor = i + 1; + c &= ~(BRLAPI_DOT7|BRLAPI_DOT8); + } + if (!(c = nabcc_translation[c])) + c = '?'; + text[i] = c; + } + qemu_del_timer(baum->cellCount_timer); + + memset(zero, 0, sizeof(zero)); + + brlapi_writeArguments_t wa = { + .displayNumber = BRLAPI_DISPLAY_DEFAULT, + .regionBegin = 1, + .regionSize = baum->x * baum->y, + .text = (char *)text, + .textSize = baum->x * baum->y, + .andMask = zero, + .orMask = cells, + .cursor = cursor, + .charset = (char *)"ISO-8859-1", + }; + + if (brlapi__write(baum->brlapi, &wa) == -1) + brlapi_perror("baum brlapi_write"); + break; + } + case BAUM_REQ_SetMode: + { + uint8_t mode, setting; + DPRINTF("SetMode\n"); + EAT(mode); + EAT(setting); + /* ignore */ + break; + } + case BAUM_REQ_SetProtocol: + { + uint8_t protocol; + DPRINTF("SetProtocol\n"); + EAT(protocol); + /* ignore */ + break; + } + case BAUM_REQ_GetDeviceIdentity: + { + uint8_t identity[17] = { BAUM_RSP_DeviceIdentity, + 'B','a','u','m',' ','V','a','r','i','o' }; + DPRINTF("GetDeviceIdentity\n"); + identity[11] = '0' + baum->x / 10; + identity[12] = '0' + baum->x % 10; + baum_write_packet(baum, identity, sizeof(identity)); + break; + } + case BAUM_REQ_GetVersionNumber: + { + uint8_t version[] = { BAUM_RSP_VersionNumber, 1 }; /* ? */ + DPRINTF("GetVersionNumber\n"); + baum_write_packet(baum, version, sizeof(version)); + break; + } + case BAUM_REQ_GetSerialNumber: + { + uint8_t serial[] = { BAUM_RSP_SerialNumber, + '0','0','0','0','0','0','0','0' }; + DPRINTF("GetSerialNumber\n"); + baum_write_packet(baum, serial, sizeof(serial)); + break; + } + case BAUM_REQ_GetKeys: + { + DPRINTF("Get%0#2x\n", req); + /* ignore */ + break; + } + default: + DPRINTF("unrecognized request %0#2x\n", req); + do + if (!len--) + return 0; + while (*cur++ != ESC); + cur--; + break; + } + return cur - buf; +} + +/* The other end is writing some data. Store it and try to interpret */ +static int baum_write(CharDriverState *chr, const uint8_t *buf, int len) +{ + BaumDriverState *baum = chr->opaque; + int tocopy, cur, eaten, orig_len = len; + + if (!len) + return 0; + if (!baum->brlapi) + return len; + + while (len) { + /* Complete our buffer as much as possible */ + tocopy = len; + if (tocopy > BUF_SIZE - baum->in_buf_used) + tocopy = BUF_SIZE - baum->in_buf_used; + + memcpy(baum->in_buf + baum->in_buf_used, buf, tocopy); + baum->in_buf_used += tocopy; + buf += tocopy; + len -= tocopy; + + /* Interpret it as much as possible */ + cur = 0; + while (cur < baum->in_buf_used && + (eaten = baum_eat_packet(baum, baum->in_buf + cur, baum->in_buf_used - cur))) + cur += eaten; + + /* Shift the remainder */ + if (cur) { + memmove(baum->in_buf, baum->in_buf + cur, baum->in_buf_used - cur); + baum->in_buf_used -= cur; + } + + /* And continue if any data left */ + } + return orig_len; +} + +/* Send the key code to the other end */ +static void baum_send_key(BaumDriverState *baum, uint8_t type, uint8_t value) { + uint8_t packet[] = { type, value }; + DPRINTF("writing key %x %x\n", type, value); + baum_write_packet(baum, packet, sizeof(packet)); +} + +/* We got some data on the BrlAPI socket */ +static void baum_chr_read(void *opaque) +{ + BaumDriverState *baum = opaque; + brlapi_keyCode_t code; + int ret; + if (!baum->brlapi) + return; + while ((ret = brlapi__readKey(baum->brlapi, 0, &code)) == 1) { + DPRINTF("got key %"BRLAPI_PRIxKEYCODE"\n", code); + /* Emulate */ + switch (code & BRLAPI_KEY_TYPE_MASK) { + case BRLAPI_KEY_TYPE_CMD: + switch (code & BRLAPI_KEY_CMD_BLK_MASK) { + case BRLAPI_KEY_CMD_ROUTE: + baum_send_key(baum, BAUM_RSP_RoutingKey, (code & BRLAPI_KEY_CMD_ARG_MASK)+1); + baum_send_key(baum, BAUM_RSP_RoutingKey, 0); + break; + case 0: + switch (code & BRLAPI_KEY_CMD_ARG_MASK) { + case BRLAPI_KEY_CMD_FWINLT: + baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2); + baum_send_key(baum, BAUM_RSP_TopKeys, 0); + break; + case BRLAPI_KEY_CMD_FWINRT: + baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR2); + baum_send_key(baum, BAUM_RSP_TopKeys, 0); + break; + case BRLAPI_KEY_CMD_LNUP: + baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR1); + baum_send_key(baum, BAUM_RSP_TopKeys, 0); + break; + case BRLAPI_KEY_CMD_LNDN: + baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR3); + baum_send_key(baum, BAUM_RSP_TopKeys, 0); + break; + case BRLAPI_KEY_CMD_TOP: + baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL1|BAUM_TR1); + baum_send_key(baum, BAUM_RSP_TopKeys, 0); + break; + case BRLAPI_KEY_CMD_BOT: + baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL3|BAUM_TR3); + baum_send_key(baum, BAUM_RSP_TopKeys, 0); + break; + case BRLAPI_KEY_CMD_TOP_LEFT: + baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR1); + baum_send_key(baum, BAUM_RSP_TopKeys, 0); + break; + case BRLAPI_KEY_CMD_BOT_LEFT: + baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR3); + baum_send_key(baum, BAUM_RSP_TopKeys, 0); + break; + case BRLAPI_KEY_CMD_HOME: + baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR1|BAUM_TR3); + baum_send_key(baum, BAUM_RSP_TopKeys, 0); + break; + case BRLAPI_KEY_CMD_PREFMENU: + baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL1|BAUM_TL3|BAUM_TR1); + baum_send_key(baum, BAUM_RSP_TopKeys, 0); + break; + } + } + break; + case BRLAPI_KEY_TYPE_SYM: + break; + } + } + if (ret == -1 && (brlapi_errno != BRLAPI_ERROR_LIBCERR || errno != EINTR)) { + brlapi_perror("baum: brlapi_readKey"); + brlapi__closeConnection(baum->brlapi); + g_free(baum->brlapi); + baum->brlapi = NULL; + } +} + +static void baum_close(struct CharDriverState *chr) +{ + BaumDriverState *baum = chr->opaque; + + qemu_free_timer(baum->cellCount_timer); + if (baum->brlapi) { + brlapi__closeConnection(baum->brlapi); + g_free(baum->brlapi); + } + g_free(baum); +} + +CharDriverState *chr_baum_init(QemuOpts *opts) +{ + BaumDriverState *baum; + CharDriverState *chr; + brlapi_handle_t *handle; +#ifdef CONFIG_SDL + SDL_SysWMinfo info; +#endif + int tty; + + baum = g_malloc0(sizeof(BaumDriverState)); + baum->chr = chr = g_malloc0(sizeof(CharDriverState)); + + chr->opaque = baum; + chr->chr_write = baum_write; + chr->chr_accept_input = baum_accept_input; + chr->chr_close = baum_close; + + handle = g_malloc0(brlapi_getHandleSize()); + baum->brlapi = handle; + + baum->brlapi_fd = brlapi__openConnection(handle, NULL, NULL); + if (baum->brlapi_fd == -1) { + brlapi_perror("baum_init: brlapi_openConnection"); + goto fail_handle; + } + + baum->cellCount_timer = qemu_new_timer_ns(vm_clock, baum_cellCount_timer_cb, baum); + + if (brlapi__getDisplaySize(handle, &baum->x, &baum->y) == -1) { + brlapi_perror("baum_init: brlapi_getDisplaySize"); + goto fail; + } + +#ifdef CONFIG_SDL + memset(&info, 0, sizeof(info)); + SDL_VERSION(&info.version); + if (SDL_GetWMInfo(&info)) + tty = info.info.x11.wmwindow; + else +#endif + tty = BRLAPI_TTY_DEFAULT; + + if (brlapi__enterTtyMode(handle, tty, NULL) == -1) { + brlapi_perror("baum_init: brlapi_enterTtyMode"); + goto fail; + } + + qemu_set_fd_handler(baum->brlapi_fd, baum_chr_read, NULL, baum); + + qemu_chr_generic_open(chr); + + return chr; + +fail: + qemu_free_timer(baum->cellCount_timer); + brlapi__closeConnection(handle); +fail_handle: + g_free(handle); + g_free(chr); + g_free(baum); + return NULL; +} diff --git a/backends/msmouse.c b/backends/msmouse.c new file mode 100644 index 0000000..bf2ff2a --- /dev/null +++ b/backends/msmouse.c @@ -0,0 +1,78 @@ +/* + * QEMU Microsoft serial mouse emulation + * + * Copyright (c) 2008 Lubomir Rintel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include +#include "qemu-common.h" +#include "char/char.h" +#include "ui/console.h" +#include "char/msmouse.h" + +#define MSMOUSE_LO6(n) ((n) & 0x3f) +#define MSMOUSE_HI2(n) (((n) & 0xc0) >> 6) + +static void msmouse_event(void *opaque, + int dx, int dy, int dz, int buttons_state) +{ + CharDriverState *chr = (CharDriverState *)opaque; + + unsigned char bytes[4] = { 0x40, 0x00, 0x00, 0x00 }; + + /* Movement deltas */ + bytes[0] |= (MSMOUSE_HI2(dy) << 2) | MSMOUSE_HI2(dx); + bytes[1] |= MSMOUSE_LO6(dx); + bytes[2] |= MSMOUSE_LO6(dy); + + /* Buttons */ + bytes[0] |= (buttons_state & 0x01 ? 0x20 : 0x00); + bytes[0] |= (buttons_state & 0x02 ? 0x10 : 0x00); + bytes[3] |= (buttons_state & 0x04 ? 0x20 : 0x00); + + /* We always send the packet of, so that we do not have to keep track + of previous state of the middle button. This can potentially confuse + some very old drivers for two button mice though. */ + qemu_chr_be_write(chr, bytes, 4); +} + +static int msmouse_chr_write (struct CharDriverState *s, const uint8_t *buf, int len) +{ + /* Ignore writes to mouse port */ + return len; +} + +static void msmouse_chr_close (struct CharDriverState *chr) +{ + g_free (chr); +} + +CharDriverState *qemu_chr_open_msmouse(QemuOpts *opts) +{ + CharDriverState *chr; + + chr = g_malloc0(sizeof(CharDriverState)); + chr->chr_write = msmouse_chr_write; + chr->chr_close = msmouse_chr_close; + + qemu_add_mouse_event_handler(msmouse_event, chr, 0, "QEMU Microsoft Mouse"); + + return chr; +} diff --git a/hw/Makefile.objs b/hw/Makefile.objs index 40ebe46..5750332 100644 --- a/hw/Makefile.objs +++ b/hw/Makefile.objs @@ -190,10 +190,9 @@ common-obj-$(CONFIG_SSI_SD) += ssi-sd.o common-obj-$(CONFIG_SD) += sd.o common-obj-y += bt.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o common-obj-y += bt-hci-csr.o -common-obj-y += msmouse.o ps2.o +common-obj-y += ps2.o common-obj-y += qdev-monitor.o common-obj-y += qdev-properties-system.o -common-obj-$(CONFIG_BRLAPI) += baum.o # xen backend driver support common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o xen_devconfig.o @@ -218,5 +217,4 @@ obj-$(CONFIG_KVM) += ivshmem.o obj-$(CONFIG_LINUX) += vfio_pci.o endif -$(obj)/baum.o: QEMU_CFLAGS += $(SDL_CFLAGS) endif diff --git a/hw/baum.c b/hw/baum.c deleted file mode 100644 index 09dcb9c..0000000 --- a/hw/baum.c +++ /dev/null @@ -1,627 +0,0 @@ -/* - * QEMU Baum Braille Device - * - * Copyright (c) 2008 Samuel Thibault - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include "qemu-common.h" -#include "char/char.h" -#include "qemu/timer.h" -#include "usb.h" -#include "baum.h" -#include -#include -#include -#ifdef CONFIG_SDL -#include -#endif - -#if 0 -#define DPRINTF(fmt, ...) \ - printf(fmt, ## __VA_ARGS__) -#else -#define DPRINTF(fmt, ...) -#endif - -#define ESC 0x1B - -#define BAUM_REQ_DisplayData 0x01 -#define BAUM_REQ_GetVersionNumber 0x05 -#define BAUM_REQ_GetKeys 0x08 -#define BAUM_REQ_SetMode 0x12 -#define BAUM_REQ_SetProtocol 0x15 -#define BAUM_REQ_GetDeviceIdentity 0x84 -#define BAUM_REQ_GetSerialNumber 0x8A - -#define BAUM_RSP_CellCount 0x01 -#define BAUM_RSP_VersionNumber 0x05 -#define BAUM_RSP_ModeSetting 0x11 -#define BAUM_RSP_CommunicationChannel 0x16 -#define BAUM_RSP_PowerdownSignal 0x17 -#define BAUM_RSP_HorizontalSensors 0x20 -#define BAUM_RSP_VerticalSensors 0x21 -#define BAUM_RSP_RoutingKeys 0x22 -#define BAUM_RSP_Switches 0x23 -#define BAUM_RSP_TopKeys 0x24 -#define BAUM_RSP_HorizontalSensor 0x25 -#define BAUM_RSP_VerticalSensor 0x26 -#define BAUM_RSP_RoutingKey 0x27 -#define BAUM_RSP_FrontKeys6 0x28 -#define BAUM_RSP_BackKeys6 0x29 -#define BAUM_RSP_CommandKeys 0x2B -#define BAUM_RSP_FrontKeys10 0x2C -#define BAUM_RSP_BackKeys10 0x2D -#define BAUM_RSP_EntryKeys 0x33 -#define BAUM_RSP_JoyStick 0x34 -#define BAUM_RSP_ErrorCode 0x40 -#define BAUM_RSP_InfoBlock 0x42 -#define BAUM_RSP_DeviceIdentity 0x84 -#define BAUM_RSP_SerialNumber 0x8A -#define BAUM_RSP_BluetoothName 0x8C - -#define BAUM_TL1 0x01 -#define BAUM_TL2 0x02 -#define BAUM_TL3 0x04 -#define BAUM_TR1 0x08 -#define BAUM_TR2 0x10 -#define BAUM_TR3 0x20 - -#define BUF_SIZE 256 - -typedef struct { - CharDriverState *chr; - - brlapi_handle_t *brlapi; - int brlapi_fd; - unsigned int x, y; - - uint8_t in_buf[BUF_SIZE]; - uint8_t in_buf_used; - uint8_t out_buf[BUF_SIZE]; - uint8_t out_buf_used, out_buf_ptr; - - QEMUTimer *cellCount_timer; -} BaumDriverState; - -/* Let's assume NABCC by default */ -static const uint8_t nabcc_translation[256] = { - [0] = ' ', -#ifndef BRLAPI_DOTS -#define BRLAPI_DOTS(d1,d2,d3,d4,d5,d6,d7,d8) \ - ((d1?BRLAPI_DOT1:0)|\ - (d2?BRLAPI_DOT2:0)|\ - (d3?BRLAPI_DOT3:0)|\ - (d4?BRLAPI_DOT4:0)|\ - (d5?BRLAPI_DOT5:0)|\ - (d6?BRLAPI_DOT6:0)|\ - (d7?BRLAPI_DOT7:0)|\ - (d8?BRLAPI_DOT8:0)) -#endif - [BRLAPI_DOTS(1,0,0,0,0,0,0,0)] = 'a', - [BRLAPI_DOTS(1,1,0,0,0,0,0,0)] = 'b', - [BRLAPI_DOTS(1,0,0,1,0,0,0,0)] = 'c', - [BRLAPI_DOTS(1,0,0,1,1,0,0,0)] = 'd', - [BRLAPI_DOTS(1,0,0,0,1,0,0,0)] = 'e', - [BRLAPI_DOTS(1,1,0,1,0,0,0,0)] = 'f', - [BRLAPI_DOTS(1,1,0,1,1,0,0,0)] = 'g', - [BRLAPI_DOTS(1,1,0,0,1,0,0,0)] = 'h', - [BRLAPI_DOTS(0,1,0,1,0,0,0,0)] = 'i', - [BRLAPI_DOTS(0,1,0,1,1,0,0,0)] = 'j', - [BRLAPI_DOTS(1,0,1,0,0,0,0,0)] = 'k', - [BRLAPI_DOTS(1,1,1,0,0,0,0,0)] = 'l', - [BRLAPI_DOTS(1,0,1,1,0,0,0,0)] = 'm', - [BRLAPI_DOTS(1,0,1,1,1,0,0,0)] = 'n', - [BRLAPI_DOTS(1,0,1,0,1,0,0,0)] = 'o', - [BRLAPI_DOTS(1,1,1,1,0,0,0,0)] = 'p', - [BRLAPI_DOTS(1,1,1,1,1,0,0,0)] = 'q', - [BRLAPI_DOTS(1,1,1,0,1,0,0,0)] = 'r', - [BRLAPI_DOTS(0,1,1,1,0,0,0,0)] = 's', - [BRLAPI_DOTS(0,1,1,1,1,0,0,0)] = 't', - [BRLAPI_DOTS(1,0,1,0,0,1,0,0)] = 'u', - [BRLAPI_DOTS(1,1,1,0,0,1,0,0)] = 'v', - [BRLAPI_DOTS(0,1,0,1,1,1,0,0)] = 'w', - [BRLAPI_DOTS(1,0,1,1,0,1,0,0)] = 'x', - [BRLAPI_DOTS(1,0,1,1,1,1,0,0)] = 'y', - [BRLAPI_DOTS(1,0,1,0,1,1,0,0)] = 'z', - - [BRLAPI_DOTS(1,0,0,0,0,0,1,0)] = 'A', - [BRLAPI_DOTS(1,1,0,0,0,0,1,0)] = 'B', - [BRLAPI_DOTS(1,0,0,1,0,0,1,0)] = 'C', - [BRLAPI_DOTS(1,0,0,1,1,0,1,0)] = 'D', - [BRLAPI_DOTS(1,0,0,0,1,0,1,0)] = 'E', - [BRLAPI_DOTS(1,1,0,1,0,0,1,0)] = 'F', - [BRLAPI_DOTS(1,1,0,1,1,0,1,0)] = 'G', - [BRLAPI_DOTS(1,1,0,0,1,0,1,0)] = 'H', - [BRLAPI_DOTS(0,1,0,1,0,0,1,0)] = 'I', - [BRLAPI_DOTS(0,1,0,1,1,0,1,0)] = 'J', - [BRLAPI_DOTS(1,0,1,0,0,0,1,0)] = 'K', - [BRLAPI_DOTS(1,1,1,0,0,0,1,0)] = 'L', - [BRLAPI_DOTS(1,0,1,1,0,0,1,0)] = 'M', - [BRLAPI_DOTS(1,0,1,1,1,0,1,0)] = 'N', - [BRLAPI_DOTS(1,0,1,0,1,0,1,0)] = 'O', - [BRLAPI_DOTS(1,1,1,1,0,0,1,0)] = 'P', - [BRLAPI_DOTS(1,1,1,1,1,0,1,0)] = 'Q', - [BRLAPI_DOTS(1,1,1,0,1,0,1,0)] = 'R', - [BRLAPI_DOTS(0,1,1,1,0,0,1,0)] = 'S', - [BRLAPI_DOTS(0,1,1,1,1,0,1,0)] = 'T', - [BRLAPI_DOTS(1,0,1,0,0,1,1,0)] = 'U', - [BRLAPI_DOTS(1,1,1,0,0,1,1,0)] = 'V', - [BRLAPI_DOTS(0,1,0,1,1,1,1,0)] = 'W', - [BRLAPI_DOTS(1,0,1,1,0,1,1,0)] = 'X', - [BRLAPI_DOTS(1,0,1,1,1,1,1,0)] = 'Y', - [BRLAPI_DOTS(1,0,1,0,1,1,1,0)] = 'Z', - - [BRLAPI_DOTS(0,0,1,0,1,1,0,0)] = '0', - [BRLAPI_DOTS(0,1,0,0,0,0,0,0)] = '1', - [BRLAPI_DOTS(0,1,1,0,0,0,0,0)] = '2', - [BRLAPI_DOTS(0,1,0,0,1,0,0,0)] = '3', - [BRLAPI_DOTS(0,1,0,0,1,1,0,0)] = '4', - [BRLAPI_DOTS(0,1,0,0,0,1,0,0)] = '5', - [BRLAPI_DOTS(0,1,1,0,1,0,0,0)] = '6', - [BRLAPI_DOTS(0,1,1,0,1,1,0,0)] = '7', - [BRLAPI_DOTS(0,1,1,0,0,1,0,0)] = '8', - [BRLAPI_DOTS(0,0,1,0,1,0,0,0)] = '9', - - [BRLAPI_DOTS(0,0,0,1,0,1,0,0)] = '.', - [BRLAPI_DOTS(0,0,1,1,0,1,0,0)] = '+', - [BRLAPI_DOTS(0,0,1,0,0,1,0,0)] = '-', - [BRLAPI_DOTS(1,0,0,0,0,1,0,0)] = '*', - [BRLAPI_DOTS(0,0,1,1,0,0,0,0)] = '/', - [BRLAPI_DOTS(1,1,1,0,1,1,0,0)] = '(', - [BRLAPI_DOTS(0,1,1,1,1,1,0,0)] = ')', - - [BRLAPI_DOTS(1,1,1,1,0,1,0,0)] = '&', - [BRLAPI_DOTS(0,0,1,1,1,1,0,0)] = '#', - - [BRLAPI_DOTS(0,0,0,0,0,1,0,0)] = ',', - [BRLAPI_DOTS(0,0,0,0,1,1,0,0)] = ';', - [BRLAPI_DOTS(1,0,0,0,1,1,0,0)] = ':', - [BRLAPI_DOTS(0,1,1,1,0,1,0,0)] = '!', - [BRLAPI_DOTS(1,0,0,1,1,1,0,0)] = '?', - [BRLAPI_DOTS(0,0,0,0,1,0,0,0)] = '"', - [BRLAPI_DOTS(0,0,1,0,0,0,0,0)] ='\'', - [BRLAPI_DOTS(0,0,0,1,0,0,0,0)] = '`', - [BRLAPI_DOTS(0,0,0,1,1,0,1,0)] = '^', - [BRLAPI_DOTS(0,0,0,1,1,0,0,0)] = '~', - [BRLAPI_DOTS(0,1,0,1,0,1,1,0)] = '[', - [BRLAPI_DOTS(1,1,0,1,1,1,1,0)] = ']', - [BRLAPI_DOTS(0,1,0,1,0,1,0,0)] = '{', - [BRLAPI_DOTS(1,1,0,1,1,1,0,0)] = '}', - [BRLAPI_DOTS(1,1,1,1,1,1,0,0)] = '=', - [BRLAPI_DOTS(1,1,0,0,0,1,0,0)] = '<', - [BRLAPI_DOTS(0,0,1,1,1,0,0,0)] = '>', - [BRLAPI_DOTS(1,1,0,1,0,1,0,0)] = '$', - [BRLAPI_DOTS(1,0,0,1,0,1,0,0)] = '%', - [BRLAPI_DOTS(0,0,0,1,0,0,1,0)] = '@', - [BRLAPI_DOTS(1,1,0,0,1,1,0,0)] = '|', - [BRLAPI_DOTS(1,1,0,0,1,1,1,0)] ='\\', - [BRLAPI_DOTS(0,0,0,1,1,1,0,0)] = '_', -}; - -/* The serial port can receive more of our data */ -static void baum_accept_input(struct CharDriverState *chr) -{ - BaumDriverState *baum = chr->opaque; - int room, first; - - if (!baum->out_buf_used) - return; - room = qemu_chr_be_can_write(chr); - if (!room) - return; - if (room > baum->out_buf_used) - room = baum->out_buf_used; - - first = BUF_SIZE - baum->out_buf_ptr; - if (room > first) { - qemu_chr_be_write(chr, baum->out_buf + baum->out_buf_ptr, first); - baum->out_buf_ptr = 0; - baum->out_buf_used -= first; - room -= first; - } - qemu_chr_be_write(chr, baum->out_buf + baum->out_buf_ptr, room); - baum->out_buf_ptr += room; - baum->out_buf_used -= room; -} - -/* We want to send a packet */ -static void baum_write_packet(BaumDriverState *baum, const uint8_t *buf, int len) -{ - uint8_t io_buf[1 + 2 * len], *cur = io_buf; - int room; - *cur++ = ESC; - while (len--) - if ((*cur++ = *buf++) == ESC) - *cur++ = ESC; - room = qemu_chr_be_can_write(baum->chr); - len = cur - io_buf; - if (len <= room) { - /* Fits */ - qemu_chr_be_write(baum->chr, io_buf, len); - } else { - int first; - uint8_t out; - /* Can't fit all, send what can be, and store the rest. */ - qemu_chr_be_write(baum->chr, io_buf, room); - len -= room; - cur = io_buf + room; - if (len > BUF_SIZE - baum->out_buf_used) { - /* Can't even store it, drop the previous data... */ - assert(len <= BUF_SIZE); - baum->out_buf_used = 0; - baum->out_buf_ptr = 0; - } - out = baum->out_buf_ptr; - baum->out_buf_used += len; - first = BUF_SIZE - baum->out_buf_ptr; - if (len > first) { - memcpy(baum->out_buf + out, cur, first); - out = 0; - len -= first; - cur += first; - } - memcpy(baum->out_buf + out, cur, len); - } -} - -/* Called when the other end seems to have a wrong idea of our display size */ -static void baum_cellCount_timer_cb(void *opaque) -{ - BaumDriverState *baum = opaque; - uint8_t cell_count[] = { BAUM_RSP_CellCount, baum->x * baum->y }; - DPRINTF("Timeout waiting for DisplayData, sending cell count\n"); - baum_write_packet(baum, cell_count, sizeof(cell_count)); -} - -/* Try to interpret a whole incoming packet */ -static int baum_eat_packet(BaumDriverState *baum, const uint8_t *buf, int len) -{ - const uint8_t *cur = buf; - uint8_t req = 0; - - if (!len--) - return 0; - if (*cur++ != ESC) { - while (*cur != ESC) { - if (!len--) - return 0; - cur++; - } - DPRINTF("Dropped %d bytes!\n", cur - buf); - } - -#define EAT(c) do {\ - if (!len--) \ - return 0; \ - if ((c = *cur++) == ESC) { \ - if (!len--) \ - return 0; \ - if (*cur++ != ESC) { \ - DPRINTF("Broken packet %#2x, tossing\n", req); \ - if (qemu_timer_pending(baum->cellCount_timer)) { \ - qemu_del_timer(baum->cellCount_timer); \ - baum_cellCount_timer_cb(baum); \ - } \ - return (cur - 2 - buf); \ - } \ - } \ -} while (0) - - EAT(req); - switch (req) { - case BAUM_REQ_DisplayData: - { - uint8_t cells[baum->x * baum->y], c; - uint8_t text[baum->x * baum->y]; - uint8_t zero[baum->x * baum->y]; - int cursor = BRLAPI_CURSOR_OFF; - int i; - - /* Allow 100ms to complete the DisplayData packet */ - qemu_mod_timer(baum->cellCount_timer, qemu_get_clock_ns(vm_clock) + - get_ticks_per_sec() / 10); - for (i = 0; i < baum->x * baum->y ; i++) { - EAT(c); - cells[i] = c; - if ((c & (BRLAPI_DOT7|BRLAPI_DOT8)) - == (BRLAPI_DOT7|BRLAPI_DOT8)) { - cursor = i + 1; - c &= ~(BRLAPI_DOT7|BRLAPI_DOT8); - } - if (!(c = nabcc_translation[c])) - c = '?'; - text[i] = c; - } - qemu_del_timer(baum->cellCount_timer); - - memset(zero, 0, sizeof(zero)); - - brlapi_writeArguments_t wa = { - .displayNumber = BRLAPI_DISPLAY_DEFAULT, - .regionBegin = 1, - .regionSize = baum->x * baum->y, - .text = (char *)text, - .textSize = baum->x * baum->y, - .andMask = zero, - .orMask = cells, - .cursor = cursor, - .charset = (char *)"ISO-8859-1", - }; - - if (brlapi__write(baum->brlapi, &wa) == -1) - brlapi_perror("baum brlapi_write"); - break; - } - case BAUM_REQ_SetMode: - { - uint8_t mode, setting; - DPRINTF("SetMode\n"); - EAT(mode); - EAT(setting); - /* ignore */ - break; - } - case BAUM_REQ_SetProtocol: - { - uint8_t protocol; - DPRINTF("SetProtocol\n"); - EAT(protocol); - /* ignore */ - break; - } - case BAUM_REQ_GetDeviceIdentity: - { - uint8_t identity[17] = { BAUM_RSP_DeviceIdentity, - 'B','a','u','m',' ','V','a','r','i','o' }; - DPRINTF("GetDeviceIdentity\n"); - identity[11] = '0' + baum->x / 10; - identity[12] = '0' + baum->x % 10; - baum_write_packet(baum, identity, sizeof(identity)); - break; - } - case BAUM_REQ_GetVersionNumber: - { - uint8_t version[] = { BAUM_RSP_VersionNumber, 1 }; /* ? */ - DPRINTF("GetVersionNumber\n"); - baum_write_packet(baum, version, sizeof(version)); - break; - } - case BAUM_REQ_GetSerialNumber: - { - uint8_t serial[] = { BAUM_RSP_SerialNumber, - '0','0','0','0','0','0','0','0' }; - DPRINTF("GetSerialNumber\n"); - baum_write_packet(baum, serial, sizeof(serial)); - break; - } - case BAUM_REQ_GetKeys: - { - DPRINTF("Get%0#2x\n", req); - /* ignore */ - break; - } - default: - DPRINTF("unrecognized request %0#2x\n", req); - do - if (!len--) - return 0; - while (*cur++ != ESC); - cur--; - break; - } - return cur - buf; -} - -/* The other end is writing some data. Store it and try to interpret */ -static int baum_write(CharDriverState *chr, const uint8_t *buf, int len) -{ - BaumDriverState *baum = chr->opaque; - int tocopy, cur, eaten, orig_len = len; - - if (!len) - return 0; - if (!baum->brlapi) - return len; - - while (len) { - /* Complete our buffer as much as possible */ - tocopy = len; - if (tocopy > BUF_SIZE - baum->in_buf_used) - tocopy = BUF_SIZE - baum->in_buf_used; - - memcpy(baum->in_buf + baum->in_buf_used, buf, tocopy); - baum->in_buf_used += tocopy; - buf += tocopy; - len -= tocopy; - - /* Interpret it as much as possible */ - cur = 0; - while (cur < baum->in_buf_used && - (eaten = baum_eat_packet(baum, baum->in_buf + cur, baum->in_buf_used - cur))) - cur += eaten; - - /* Shift the remainder */ - if (cur) { - memmove(baum->in_buf, baum->in_buf + cur, baum->in_buf_used - cur); - baum->in_buf_used -= cur; - } - - /* And continue if any data left */ - } - return orig_len; -} - -/* Send the key code to the other end */ -static void baum_send_key(BaumDriverState *baum, uint8_t type, uint8_t value) { - uint8_t packet[] = { type, value }; - DPRINTF("writing key %x %x\n", type, value); - baum_write_packet(baum, packet, sizeof(packet)); -} - -/* We got some data on the BrlAPI socket */ -static void baum_chr_read(void *opaque) -{ - BaumDriverState *baum = opaque; - brlapi_keyCode_t code; - int ret; - if (!baum->brlapi) - return; - while ((ret = brlapi__readKey(baum->brlapi, 0, &code)) == 1) { - DPRINTF("got key %"BRLAPI_PRIxKEYCODE"\n", code); - /* Emulate */ - switch (code & BRLAPI_KEY_TYPE_MASK) { - case BRLAPI_KEY_TYPE_CMD: - switch (code & BRLAPI_KEY_CMD_BLK_MASK) { - case BRLAPI_KEY_CMD_ROUTE: - baum_send_key(baum, BAUM_RSP_RoutingKey, (code & BRLAPI_KEY_CMD_ARG_MASK)+1); - baum_send_key(baum, BAUM_RSP_RoutingKey, 0); - break; - case 0: - switch (code & BRLAPI_KEY_CMD_ARG_MASK) { - case BRLAPI_KEY_CMD_FWINLT: - baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2); - baum_send_key(baum, BAUM_RSP_TopKeys, 0); - break; - case BRLAPI_KEY_CMD_FWINRT: - baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR2); - baum_send_key(baum, BAUM_RSP_TopKeys, 0); - break; - case BRLAPI_KEY_CMD_LNUP: - baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR1); - baum_send_key(baum, BAUM_RSP_TopKeys, 0); - break; - case BRLAPI_KEY_CMD_LNDN: - baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR3); - baum_send_key(baum, BAUM_RSP_TopKeys, 0); - break; - case BRLAPI_KEY_CMD_TOP: - baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL1|BAUM_TR1); - baum_send_key(baum, BAUM_RSP_TopKeys, 0); - break; - case BRLAPI_KEY_CMD_BOT: - baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL3|BAUM_TR3); - baum_send_key(baum, BAUM_RSP_TopKeys, 0); - break; - case BRLAPI_KEY_CMD_TOP_LEFT: - baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR1); - baum_send_key(baum, BAUM_RSP_TopKeys, 0); - break; - case BRLAPI_KEY_CMD_BOT_LEFT: - baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR3); - baum_send_key(baum, BAUM_RSP_TopKeys, 0); - break; - case BRLAPI_KEY_CMD_HOME: - baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR1|BAUM_TR3); - baum_send_key(baum, BAUM_RSP_TopKeys, 0); - break; - case BRLAPI_KEY_CMD_PREFMENU: - baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL1|BAUM_TL3|BAUM_TR1); - baum_send_key(baum, BAUM_RSP_TopKeys, 0); - break; - } - } - break; - case BRLAPI_KEY_TYPE_SYM: - break; - } - } - if (ret == -1 && (brlapi_errno != BRLAPI_ERROR_LIBCERR || errno != EINTR)) { - brlapi_perror("baum: brlapi_readKey"); - brlapi__closeConnection(baum->brlapi); - g_free(baum->brlapi); - baum->brlapi = NULL; - } -} - -static void baum_close(struct CharDriverState *chr) -{ - BaumDriverState *baum = chr->opaque; - - qemu_free_timer(baum->cellCount_timer); - if (baum->brlapi) { - brlapi__closeConnection(baum->brlapi); - g_free(baum->brlapi); - } - g_free(baum); -} - -CharDriverState *chr_baum_init(QemuOpts *opts) -{ - BaumDriverState *baum; - CharDriverState *chr; - brlapi_handle_t *handle; -#ifdef CONFIG_SDL - SDL_SysWMinfo info; -#endif - int tty; - - baum = g_malloc0(sizeof(BaumDriverState)); - baum->chr = chr = g_malloc0(sizeof(CharDriverState)); - - chr->opaque = baum; - chr->chr_write = baum_write; - chr->chr_accept_input = baum_accept_input; - chr->chr_close = baum_close; - - handle = g_malloc0(brlapi_getHandleSize()); - baum->brlapi = handle; - - baum->brlapi_fd = brlapi__openConnection(handle, NULL, NULL); - if (baum->brlapi_fd == -1) { - brlapi_perror("baum_init: brlapi_openConnection"); - goto fail_handle; - } - - baum->cellCount_timer = qemu_new_timer_ns(vm_clock, baum_cellCount_timer_cb, baum); - - if (brlapi__getDisplaySize(handle, &baum->x, &baum->y) == -1) { - brlapi_perror("baum_init: brlapi_getDisplaySize"); - goto fail; - } - -#ifdef CONFIG_SDL - memset(&info, 0, sizeof(info)); - SDL_VERSION(&info.version); - if (SDL_GetWMInfo(&info)) - tty = info.info.x11.wmwindow; - else -#endif - tty = BRLAPI_TTY_DEFAULT; - - if (brlapi__enterTtyMode(handle, tty, NULL) == -1) { - brlapi_perror("baum_init: brlapi_enterTtyMode"); - goto fail; - } - - qemu_set_fd_handler(baum->brlapi_fd, baum_chr_read, NULL, baum); - - qemu_chr_generic_open(chr); - - return chr; - -fail: - qemu_free_timer(baum->cellCount_timer); - brlapi__closeConnection(handle); -fail_handle: - g_free(handle); - g_free(chr); - g_free(baum); - return NULL; -} diff --git a/hw/baum.h b/hw/baum.h deleted file mode 100644 index 7635884..0000000 --- a/hw/baum.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * QEMU Baum - * - * Copyright (c) 2008 Samuel Thibault - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef HW_BAUM_H -#define HW_BAUM_H 1 - -/* char device */ -CharDriverState *chr_baum_init(QemuOpts *opts); - -#endif diff --git a/hw/msmouse.c b/hw/msmouse.c deleted file mode 100644 index ef47aed..0000000 --- a/hw/msmouse.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * QEMU Microsoft serial mouse emulation - * - * Copyright (c) 2008 Lubomir Rintel - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include -#include "qemu-common.h" -#include "char/char.h" -#include "ui/console.h" -#include "msmouse.h" - -#define MSMOUSE_LO6(n) ((n) & 0x3f) -#define MSMOUSE_HI2(n) (((n) & 0xc0) >> 6) - -static void msmouse_event(void *opaque, - int dx, int dy, int dz, int buttons_state) -{ - CharDriverState *chr = (CharDriverState *)opaque; - - unsigned char bytes[4] = { 0x40, 0x00, 0x00, 0x00 }; - - /* Movement deltas */ - bytes[0] |= (MSMOUSE_HI2(dy) << 2) | MSMOUSE_HI2(dx); - bytes[1] |= MSMOUSE_LO6(dx); - bytes[2] |= MSMOUSE_LO6(dy); - - /* Buttons */ - bytes[0] |= (buttons_state & 0x01 ? 0x20 : 0x00); - bytes[0] |= (buttons_state & 0x02 ? 0x10 : 0x00); - bytes[3] |= (buttons_state & 0x04 ? 0x20 : 0x00); - - /* We always send the packet of, so that we do not have to keep track - of previous state of the middle button. This can potentially confuse - some very old drivers for two button mice though. */ - qemu_chr_be_write(chr, bytes, 4); -} - -static int msmouse_chr_write (struct CharDriverState *s, const uint8_t *buf, int len) -{ - /* Ignore writes to mouse port */ - return len; -} - -static void msmouse_chr_close (struct CharDriverState *chr) -{ - g_free (chr); -} - -CharDriverState *qemu_chr_open_msmouse(QemuOpts *opts) -{ - CharDriverState *chr; - - chr = g_malloc0(sizeof(CharDriverState)); - chr->chr_write = msmouse_chr_write; - chr->chr_close = msmouse_chr_close; - - qemu_add_mouse_event_handler(msmouse_event, chr, 0, "QEMU Microsoft Mouse"); - - return chr; -} diff --git a/hw/msmouse.h b/hw/msmouse.h deleted file mode 100644 index 8cff3a7..0000000 --- a/hw/msmouse.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef HW_MSMOUSE_H -#define HW_MSMOUSE_H 1 - -/* msmouse.c */ -CharDriverState *qemu_chr_open_msmouse(QemuOpts *opts); - -#endif diff --git a/include/char/baum.h b/include/char/baum.h new file mode 100644 index 0000000..7635884 --- /dev/null +++ b/include/char/baum.h @@ -0,0 +1,30 @@ +/* + * QEMU Baum + * + * Copyright (c) 2008 Samuel Thibault + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef HW_BAUM_H +#define HW_BAUM_H 1 + +/* char device */ +CharDriverState *chr_baum_init(QemuOpts *opts); + +#endif diff --git a/include/char/msmouse.h b/include/char/msmouse.h new file mode 100644 index 0000000..8cff3a7 --- /dev/null +++ b/include/char/msmouse.h @@ -0,0 +1,7 @@ +#ifndef HW_MSMOUSE_H +#define HW_MSMOUSE_H 1 + +/* msmouse.c */ +CharDriverState *qemu_chr_open_msmouse(QemuOpts *opts); + +#endif diff --git a/qemu-char.c b/qemu-char.c index 160decc..6dc1474 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -28,8 +28,8 @@ #include "qemu/timer.h" #include "char/char.h" #include "hw/usb.h" -#include "hw/baum.h" -#include "hw/msmouse.h" +#include "char/baum.h" +#include "char/msmouse.h" #include "qmp-commands.h" #include diff --git a/vl.c b/vl.c index c03edf1..e0a8eeb 100644 --- a/vl.c +++ b/vl.c @@ -119,7 +119,7 @@ int main(int argc, char **argv) #include "hw/pcmcia.h" #include "hw/pc.h" #include "hw/isa.h" -#include "hw/baum.h" +#include "char/baum.h" #include "hw/bt.h" #include "hw/watchdog.h" #include "hw/smbios.h" -- cgit v1.1