Check in updated bthidd(8). This is still work in progress.
This commit is contained in:
parent
75ad04b4f6
commit
3adfd74adb
@ -1,12 +1,15 @@
|
||||
# $Id: Makefile,v 1.2 2004/02/13 21:46:20 max Exp $
|
||||
# $Id: Makefile,v 1.3 2004/08/17 21:49:46 max Exp $
|
||||
# $FreeBSD$
|
||||
|
||||
PROG= bthidd
|
||||
#MAN= bthidd.8 bthidd.conf.5
|
||||
NOMAN=
|
||||
SRCS= bthidd.c client.c hid.c lexer.l parser.y server.c session.c
|
||||
WARNS?= 1
|
||||
NOMAN= 1
|
||||
SRCS= bthidd.c client.c hid.c kbd.c lexer.l parser.y server.c \
|
||||
session.c
|
||||
|
||||
CFLAGS+= -I${.CURDIR}
|
||||
WARNS?= 2
|
||||
DEBUG_FLAGS= -g
|
||||
|
||||
DPADD= ${LIBBLUETOOTH} ${LIBSDP}
|
||||
LDADD= -lbluetooth -lusbhid
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: bthidd.c,v 1.4 2004/02/26 21:48:44 max Exp $
|
||||
* $Id: bthidd.c,v 1.7 2004/11/17 21:59:42 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -62,14 +62,16 @@ main(int argc, char *argv[])
|
||||
{
|
||||
struct bthid_server srv;
|
||||
struct sigaction sa;
|
||||
char const *pid_file = BTHIDD_PIDFILE;
|
||||
char const *pid_file = BTHIDD_PIDFILE, *ep = NULL;
|
||||
int opt, detach, tval;
|
||||
|
||||
memset(&srv, 0, sizeof(srv));
|
||||
memcpy(&srv.bdaddr, NG_HCI_BDADDR_ANY, sizeof(srv.bdaddr));
|
||||
srv.windex = -1;
|
||||
detach = 1;
|
||||
tval = 10; /* sec */
|
||||
|
||||
while ((opt = getopt(argc, argv, "a:c:dH:hp:t:")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "a:c:dH:hp:s:t:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'a': /* BDADDR */
|
||||
if (!bt_aton(optarg, &srv.bdaddr)) {
|
||||
@ -98,13 +100,21 @@ main(int argc, char *argv[])
|
||||
pid_file = optarg;
|
||||
break;
|
||||
|
||||
case 't': { /* rescan interval */
|
||||
char *ep = NULL;
|
||||
case 's': /* switch script */
|
||||
srv.script = optarg;
|
||||
break;
|
||||
|
||||
tval = strtol(optarg, &ep, 10);
|
||||
case 't': /* rescan interval */
|
||||
tval = strtol(optarg, (char **) &ep, 10);
|
||||
if (*ep != '\0' || tval <= 0)
|
||||
usage();
|
||||
} break;
|
||||
break;
|
||||
|
||||
case 'u': /* wired keyboard index */
|
||||
srv.windex = strtol(optarg, (char **) &ep, 10);
|
||||
if (*ep != '\0' || srv.windex < 0)
|
||||
usage();
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
default:
|
||||
@ -141,6 +151,14 @@ main(int argc, char *argv[])
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sa.sa_handler = SIG_IGN;
|
||||
sa.sa_flags = SA_NOCLDSTOP|SA_NOCLDWAIT;
|
||||
if (sigaction(SIGCHLD, &sa, NULL) < 0) {
|
||||
syslog(LOG_CRIT, "Could not install signal handlers. %s (%d)",
|
||||
strerror(errno), errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (read_config_file() < 0 || read_hids_file() < 0 ||
|
||||
server_init(&srv) < 0 || write_pid_file(pid_file) < 0)
|
||||
exit(1);
|
||||
@ -249,7 +267,9 @@ usage(void)
|
||||
" -H file specify known HIDs file name\n" \
|
||||
" -h display this message\n" \
|
||||
" -p file specify PID file name\n" \
|
||||
" -t tval client rescan interval (sec)\n" \
|
||||
" -s script specify keyboard switching script\n" \
|
||||
" -t tval specify client rescan interval (sec)\n" \
|
||||
" -u unit specify wired keyboard unit\n" \
|
||||
"", BTHIDD_IDENT);
|
||||
exit(255);
|
||||
}
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: bthidd.h,v 1.4 2004/02/26 21:44:20 max Exp $
|
||||
* $Id: bthidd.h,v 1.6 2004/11/17 21:59:42 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -39,14 +39,18 @@ struct bthid_session;
|
||||
|
||||
struct bthid_server
|
||||
{
|
||||
bdaddr_t bdaddr; /* local bdaddr */
|
||||
int cons; /* /dev/consolectl */
|
||||
int ctrl; /* control channel (listen) */
|
||||
int intr; /* interrupt channel (listen) */
|
||||
int maxfd; /* max fd in sets */
|
||||
fd_set rfdset; /* read descriptor set */
|
||||
fd_set wfdset; /* write descriptor set */
|
||||
LIST_HEAD(, bthid_session) sessions;
|
||||
bdaddr_t bdaddr; /* local bdaddr */
|
||||
int cons; /* /dev/consolectl */
|
||||
int vkbd; /* /dev/vkbdctl */
|
||||
char const *script; /* keyboard switching script */
|
||||
int windex; /* wired keyboard index */
|
||||
bitstr_t *keys; /* pressed keys map */
|
||||
int ctrl; /* control channel (listen) */
|
||||
int intr; /* intr. channel (listen) */
|
||||
int maxfd; /* max fd in sets */
|
||||
fd_set rfdset; /* read descriptor set */
|
||||
fd_set wfdset; /* write descriptor set */
|
||||
LIST_HEAD(, bthid_session) sessions;
|
||||
};
|
||||
|
||||
typedef struct bthid_server bthid_server_t;
|
||||
@ -54,16 +58,17 @@ typedef struct bthid_server * bthid_server_p;
|
||||
|
||||
struct bthid_session
|
||||
{
|
||||
bthid_server_p srv; /* pointer back to server */
|
||||
int ctrl; /* control channel */
|
||||
int intr; /* interrupt channel */
|
||||
bdaddr_t bdaddr; /* remote bdaddr */
|
||||
short state; /* session state */
|
||||
bthid_server_p srv; /* pointer back to server */
|
||||
int ctrl; /* control channel */
|
||||
int intr; /* interrupt channel */
|
||||
bdaddr_t bdaddr;/* remote bdaddr */
|
||||
short state; /* session state */
|
||||
#define CLOSED 0
|
||||
#define W4CTRL 1
|
||||
#define W4INTR 2
|
||||
#define OPEN 3
|
||||
LIST_ENTRY(bthid_session) next; /* link to next */
|
||||
bitstr_t *keys; /* pressed keys map */
|
||||
LIST_ENTRY(bthid_session) next; /* link to next */
|
||||
};
|
||||
|
||||
typedef struct bthid_session bthid_session_t;
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: hid.c,v 1.3 2004/02/26 21:47:35 max Exp $
|
||||
* $Id: hid.c,v 1.4 2004/11/17 21:59:42 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -40,13 +40,18 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include <usbhid.h>
|
||||
#include "bthidd.h"
|
||||
#include "bthid_config.h"
|
||||
#include "kbd.h"
|
||||
|
||||
#undef min
|
||||
#define min(x, y) (((x) < (y))? (x) : (y))
|
||||
|
||||
#undef ASIZE
|
||||
#define ASIZE(a) (sizeof(a)/sizeof(a[0]))
|
||||
|
||||
/*
|
||||
* Process data from control channel
|
||||
*/
|
||||
@ -123,9 +128,10 @@ hid_interrupt(bthid_session_p s, char *data, int len)
|
||||
hid_item_t h;
|
||||
int report_id, usage, page, val,
|
||||
mouse_x, mouse_y, mouse_z, mouse_butt,
|
||||
nkeys, keys[32]; /* XXX how big keys[] should be? */
|
||||
mevents, kevents;
|
||||
|
||||
assert(s != NULL);
|
||||
assert(s->srv != NULL);
|
||||
assert(data != NULL);
|
||||
|
||||
if (len < 3) {
|
||||
@ -148,7 +154,7 @@ hid_interrupt(bthid_session_p s, char *data, int len)
|
||||
hid_device = get_hid_device(&s->bdaddr);
|
||||
assert(hid_device != NULL);
|
||||
|
||||
mouse_x = mouse_y = mouse_z = mouse_butt = nkeys = 0;
|
||||
mouse_x = mouse_y = mouse_z = mouse_butt = mevents = kevents = 0;
|
||||
|
||||
for (d = hid_start_parse(hid_device->desc, 1 << hid_input, -1);
|
||||
hid_get_item(d, &h) > 0; ) {
|
||||
@ -164,14 +170,17 @@ hid_interrupt(bthid_session_p s, char *data, int len)
|
||||
switch (usage) {
|
||||
case HUG_X:
|
||||
mouse_x = val;
|
||||
mevents ++;
|
||||
break;
|
||||
|
||||
case HUG_Y:
|
||||
mouse_y = val;
|
||||
mevents ++;
|
||||
break;
|
||||
|
||||
case HUG_WHEEL:
|
||||
mouse_z = -val;
|
||||
mevents ++;
|
||||
break;
|
||||
|
||||
case HUG_SYSTEM_SLEEP:
|
||||
@ -182,20 +191,24 @@ hid_interrupt(bthid_session_p s, char *data, int len)
|
||||
break;
|
||||
|
||||
case HUP_KEYBOARD:
|
||||
kevents ++;
|
||||
|
||||
if (h.flags & HIO_VARIABLE) {
|
||||
if (val && nkeys < sizeof(keys))
|
||||
keys[nkeys ++] = usage;
|
||||
if (val && usage < kbd_maxkey())
|
||||
bit_set(s->srv->keys, usage);
|
||||
} else {
|
||||
if (val && nkeys < sizeof(keys))
|
||||
keys[nkeys ++] = val;
|
||||
if (val && val < kbd_maxkey())
|
||||
bit_set(s->srv->keys, val);
|
||||
|
||||
data ++;
|
||||
len --;
|
||||
|
||||
len = min(len, h.report_size);
|
||||
while (len > 0) {
|
||||
val = hid_get_data(data, &h);
|
||||
if (val && nkeys < sizeof(keys))
|
||||
keys[nkeys ++] = val;
|
||||
if (val && val < kbd_maxkey())
|
||||
bit_set(s->srv->keys, val);
|
||||
|
||||
data ++;
|
||||
len --;
|
||||
}
|
||||
@ -204,6 +217,97 @@ hid_interrupt(bthid_session_p s, char *data, int len)
|
||||
|
||||
case HUP_BUTTON:
|
||||
mouse_butt |= (val << (usage - 1));
|
||||
mevents ++;
|
||||
break;
|
||||
|
||||
case HUP_CONSUMER:
|
||||
if (!val)
|
||||
break;
|
||||
|
||||
switch (usage) {
|
||||
case 0xb5: /* Scan Next Track */
|
||||
val = 0x19;
|
||||
break;
|
||||
|
||||
case 0xb6: /* Scan Previous Track */
|
||||
val = 0x10;
|
||||
break;
|
||||
|
||||
case 0xb7: /* Stop */
|
||||
val = 0x24;
|
||||
break;
|
||||
|
||||
case 0xcd: /* Play/Pause */
|
||||
val = 0x22;
|
||||
break;
|
||||
|
||||
case 0xe2: /* Mute */
|
||||
val = 0x20;
|
||||
break;
|
||||
|
||||
case 0xe9: /* Volume Up */
|
||||
val = 0x30;
|
||||
break;
|
||||
|
||||
case 0xea: /* Volume Down */
|
||||
val = 0x2E;
|
||||
break;
|
||||
|
||||
case 0x183: /* Media Select */
|
||||
val = 0x6D;
|
||||
break;
|
||||
|
||||
case 0x018a: /* Mail */
|
||||
val = 0x6C;
|
||||
break;
|
||||
|
||||
case 0x192: /* Calculator */
|
||||
val = 0x21;
|
||||
break;
|
||||
|
||||
case 0x194: /* My Computer */
|
||||
val = 0x6B;
|
||||
break;
|
||||
|
||||
case 0x221: /* WWW Search */
|
||||
val = 0x65;
|
||||
break;
|
||||
|
||||
case 0x223: /* WWW Home */
|
||||
val = 0x32;
|
||||
break;
|
||||
|
||||
case 0x224: /* WWW Back */
|
||||
val = 0x6A;
|
||||
break;
|
||||
|
||||
case 0x225: /* WWW Forward */
|
||||
val = 0x69;
|
||||
break;
|
||||
|
||||
case 0x226: /* WWW Stop */
|
||||
val = 0x68;
|
||||
break;
|
||||
|
||||
case 0227: /* WWW Refresh */
|
||||
val = 0x67;
|
||||
break;
|
||||
|
||||
case 0x22a: /* WWW Favorites */
|
||||
val = 0x66;
|
||||
break;
|
||||
|
||||
default:
|
||||
val = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* XXX FIXME - UGLY HACK */
|
||||
if (val != 0) {
|
||||
int buf[4] = { 0xe0, val, 0xe0, val|0x80 };
|
||||
|
||||
write(s->srv->vkbd, buf, sizeof(buf));
|
||||
}
|
||||
break;
|
||||
|
||||
case HUP_MICROSOFT:
|
||||
@ -236,13 +340,17 @@ hid_interrupt(bthid_session_p s, char *data, int len)
|
||||
}
|
||||
hid_end_parse(d);
|
||||
|
||||
/* Feed keyboard events into kernel */
|
||||
if (kevents > 0)
|
||||
kbd_process_keys(s);
|
||||
|
||||
/*
|
||||
* XXX FIXME Feed mouse and keyboard events into kernel
|
||||
* The code block below works, but it is not
|
||||
* good enough
|
||||
* XXX FIXME Feed mouse events into kernel.
|
||||
* The code block below works, but it is not good enough.
|
||||
* Need to track double-clicks etc.
|
||||
*/
|
||||
|
||||
if (mouse_x != 0 || mouse_y != 0 || mouse_z != 0 || mouse_butt != 0) {
|
||||
if (mevents > 0) {
|
||||
struct mouse_info mi;
|
||||
|
||||
mi.operation = MOUSE_ACTION;
|
||||
|
592
usr.sbin/bluetooth/bthidd/kbd.c
Normal file
592
usr.sbin/bluetooth/bthidd/kbd.c
Normal file
@ -0,0 +1,592 @@
|
||||
/*
|
||||
* kbd.c
|
||||
*
|
||||
* Copyright (c) 2004 Maksim Yevmenkin <m_evmenkin@yahoo.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: kbd.c,v 1.2 2004/11/17 21:59:42 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/consio.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/kbio.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/wait.h>
|
||||
#include <assert.h>
|
||||
#include <bluetooth.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include "bthidd.h"
|
||||
#include "kbd.h"
|
||||
|
||||
static void kbd_write(bitstr_t *m, int fb, int make, int fd);
|
||||
static int kbd_xlate(int code, int make, int *b, int const *eob);
|
||||
|
||||
/*
|
||||
* HID code to PS/2 set 1 code translation table.
|
||||
*
|
||||
* http://www.microsoft.com/whdc/device/input/Scancode.mspx
|
||||
*
|
||||
* The table only contains "make" (key pressed) codes.
|
||||
* The "break" (key released) code is generated as "make" | 0x80
|
||||
*/
|
||||
|
||||
#define E0PREFIX (1 << 31)
|
||||
#define NOBREAK (1 << 30)
|
||||
#define CODEMASK (~(E0PREFIX|NOBREAK))
|
||||
|
||||
static int const x[] =
|
||||
{
|
||||
/*==================================================*/
|
||||
/* Name HID code Make Break*/
|
||||
/*==================================================*/
|
||||
/* No Event 00 */ -1, /* None */
|
||||
/* Overrun Error 01 */ NOBREAK|0xFF, /* None */
|
||||
/* POST Fail 02 */ NOBREAK|0xFC, /* None */
|
||||
/* ErrorUndefined 03 */ -1, /* Unassigned */
|
||||
/* a A 04 */ 0x1E, /* 9E */
|
||||
/* b B 05 */ 0x30, /* B0 */
|
||||
/* c C 06 */ 0x2E, /* AE */
|
||||
/* d D 07 */ 0x20, /* A0 */
|
||||
/* e E 08 */ 0x12, /* 92 */
|
||||
/* f F 09 */ 0x21, /* A1 */
|
||||
/* g G 0A */ 0x22, /* A2 */
|
||||
/* h H 0B */ 0x23, /* A3 */
|
||||
/* i I 0C */ 0x17, /* 97 */
|
||||
/* j J 0D */ 0x24, /* A4 */
|
||||
/* k K 0E */ 0x25, /* A5 */
|
||||
/* l L 0F */ 0x26, /* A6 */
|
||||
/* m M 10 */ 0x32, /* B2 */
|
||||
/* n N 11 */ 0x31, /* B1 */
|
||||
/* o O 12 */ 0x18, /* 98 */
|
||||
/* p P 13 */ 0x19, /* 99 */
|
||||
/* q Q 14 */ 0x10, /* 90 */
|
||||
/* r R 15 */ 0x13, /* 93 */
|
||||
/* s S 16 */ 0x1F, /* 9F */
|
||||
/* t T 17 */ 0x14, /* 94 */
|
||||
/* u U 18 */ 0x16, /* 96 */
|
||||
/* v V 19 */ 0x2F, /* AF */
|
||||
/* w W 1A */ 0x11, /* 91 */
|
||||
/* x X 1B */ 0x2D, /* AD */
|
||||
/* y Y 1C */ 0x15, /* 95 */
|
||||
/* z Z 1D */ 0x2C, /* AC */
|
||||
/* 1 ! 1E */ 0x02, /* 82 */
|
||||
/* 2 @ 1F */ 0x03, /* 83 */
|
||||
/* 3 # 20 */ 0x04, /* 84 */
|
||||
/* 4 $ 21 */ 0x05, /* 85 */
|
||||
/* 5 % 22 */ 0x06, /* 86 */
|
||||
/* 6 ^ 23 */ 0x07, /* 87 */
|
||||
/* 7 & 24 */ 0x08, /* 88 */
|
||||
/* 8 * 25 */ 0x09, /* 89 */
|
||||
/* 9 ( 26 */ 0x0A, /* 8A */
|
||||
/* 0 ) 27 */ 0x0B, /* 8B */
|
||||
/* Return 28 */ 0x1C, /* 9C */
|
||||
/* Escape 29 */ 0x01, /* 81 */
|
||||
/* Backspace 2A */ 0x0E, /* 8E */
|
||||
/* Tab 2B */ 0x0F, /* 8F */
|
||||
/* Space 2C */ 0x39, /* B9 */
|
||||
/* - _ 2D */ 0x0C, /* 8C */
|
||||
/* = + 2E */ 0x0D, /* 8D */
|
||||
/* [ { 2F */ 0x1A, /* 9A */
|
||||
/* ] } 30 */ 0x1B, /* 9B */
|
||||
/* \ | 31 */ 0x2B, /* AB */
|
||||
/* Europe 1 32 */ 0x2B, /* AB */
|
||||
/* ; : 33 */ 0x27, /* A7 */
|
||||
/* " ' 34 */ 0x28, /* A8 */
|
||||
/* ` ~ 35 */ 0x29, /* A9 */
|
||||
/* comma < 36 */ 0x33, /* B3 */
|
||||
/* . > 37 */ 0x34, /* B4 */
|
||||
/* / ? 38 */ 0x35, /* B5 */
|
||||
/* Caps Lock 39 */ 0x3A, /* BA */
|
||||
/* F1 3A */ 0x3B, /* BB */
|
||||
/* F2 3B */ 0x3C, /* BC */
|
||||
/* F3 3C */ 0x3D, /* BD */
|
||||
/* F4 3D */ 0x3E, /* BE */
|
||||
/* F5 3E */ 0x3F, /* BF */
|
||||
/* F6 3F */ 0x40, /* C0 */
|
||||
/* F7 40 */ 0x41, /* C1 */
|
||||
/* F8 41 */ 0x42, /* C2 */
|
||||
/* F9 42 */ 0x43, /* C3 */
|
||||
/* F10 43 */ 0x44, /* C4 */
|
||||
/* F11 44 */ 0x57, /* D7 */
|
||||
/* F12 45 */ 0x58, /* D8 */
|
||||
/* Print Screen 46 */ E0PREFIX|37, /* E0 B7 */
|
||||
/* Scroll Lock 47 */ 0x46, /* C6 */
|
||||
#if 0
|
||||
/* Break (Ctrl-Pause) 48 */ E0 46 E0 C6, /* None */
|
||||
/* Pause 48 */ E1 1D 45 E1 9D C5, /* None */
|
||||
#else
|
||||
/* Break (Ctrl-Pause)/Pause 48 */ NOBREAK /* Special case */, /* None */
|
||||
#endif
|
||||
/* Insert 49 */ E0PREFIX|0x52, /* E0 D2 */
|
||||
/* Home 4A */ E0PREFIX|0x47, /* E0 C7 */
|
||||
/* Page Up 4B */ E0PREFIX|0x49, /* E0 C9 */
|
||||
/* Delete 4C */ E0PREFIX|0x53, /* E0 D3 */
|
||||
/* End 4D */ E0PREFIX|0x4F, /* E0 CF */
|
||||
/* Page Down 4E */ E0PREFIX|0x51, /* E0 D1 */
|
||||
/* Right Arrow 4F */ E0PREFIX|0x4D, /* E0 CD */
|
||||
/* Left Arrow 50 */ E0PREFIX|0x4B, /* E0 CB */
|
||||
/* Down Arrow 51 */ E0PREFIX|0x50, /* E0 D0 */
|
||||
/* Up Arrow 52 */ E0PREFIX|0x48, /* E0 C8 */
|
||||
/* Num Lock 53 */ 0x45, /* C5 */
|
||||
/* Keypad / 54 */ E0PREFIX|0x35, /* E0 B5 */
|
||||
/* Keypad * 55 */ 0x37, /* B7 */
|
||||
/* Keypad - 56 */ 0x4A, /* CA */
|
||||
/* Keypad + 57 */ 0x4E, /* CE */
|
||||
/* Keypad Enter 58 */ E0PREFIX|0x1C, /* E0 9C */
|
||||
/* Keypad 1 End 59 */ 0x4F, /* CF */
|
||||
/* Keypad 2 Down 5A */ 0x50, /* D0 */
|
||||
/* Keypad 3 PageDn 5B */ 0x51, /* D1 */
|
||||
/* Keypad 4 Left 5C */ 0x4B, /* CB */
|
||||
/* Keypad 5 5D */ 0x4C, /* CC */
|
||||
/* Keypad 6 Right 5E */ 0x4D, /* CD */
|
||||
/* Keypad 7 Home 5F */ 0x47, /* C7 */
|
||||
/* Keypad 8 Up 60 */ 0x48, /* C8 */
|
||||
/* Keypad 9 PageUp 61 */ 0x49, /* C9 */
|
||||
/* Keypad 0 Insert 62 */ 0x52, /* D2 */
|
||||
/* Keypad . Delete 63 */ 0x53, /* D3 */
|
||||
/* Europe 2 64 */ 0x56, /* D6 */
|
||||
/* App 65 */ E0PREFIX|0x5D, /* E0 DD */
|
||||
/* Keyboard Power 66 */ E0PREFIX|0x5E, /* E0 DE */
|
||||
/* Keypad = 67 */ 0x59, /* D9 */
|
||||
/* F13 68 */ 0x64, /* E4 */
|
||||
/* F14 69 */ 0x65, /* E5 */
|
||||
/* F15 6A */ 0x66, /* E6 */
|
||||
/* F16 6B */ 0x67, /* E7 */
|
||||
/* F17 6C */ 0x68, /* E8 */
|
||||
/* F18 6D */ 0x69, /* E9 */
|
||||
/* F19 6E */ 0x6A, /* EA */
|
||||
/* F20 6F */ 0x6B, /* EB */
|
||||
/* F21 70 */ 0x6C, /* EC */
|
||||
/* F22 71 */ 0x6D, /* ED */
|
||||
/* F23 72 */ 0x6E, /* EE */
|
||||
/* F24 73 */ 0x76, /* F6 */
|
||||
/* Keyboard Execute 74 */ -1, /* Unassigned */
|
||||
/* Keyboard Help 75 */ -1, /* Unassigned */
|
||||
/* Keyboard Menu 76 */ -1, /* Unassigned */
|
||||
/* Keyboard Select 77 */ -1, /* Unassigned */
|
||||
/* Keyboard Stop 78 */ -1, /* Unassigned */
|
||||
/* Keyboard Again 79 */ -1, /* Unassigned */
|
||||
/* Keyboard Undo 7A */ -1, /* Unassigned */
|
||||
/* Keyboard Cut 7B */ -1, /* Unassigned */
|
||||
/* Keyboard Copy 7C */ -1, /* Unassigned */
|
||||
/* Keyboard Paste 7D */ -1, /* Unassigned */
|
||||
/* Keyboard Find 7E */ -1, /* Unassigned */
|
||||
/* Keyboard Mute 7F */ -1, /* Unassigned */
|
||||
/* Keyboard Volume Up 80 */ -1, /* Unassigned */
|
||||
/* Keyboard Volume Dn 81 */ -1, /* Unassigned */
|
||||
/* Keyboard Locking Caps Lock 82 */ -1, /* Unassigned */
|
||||
/* Keyboard Locking Num Lock 83 */ -1, /* Unassigned */
|
||||
/* Keyboard Locking Scroll Lock 84 */ -1, /* Unassigned */
|
||||
/* Keypad comma 85 */ 0x7E, /* FE */
|
||||
/* Keyboard Equal Sign 86 */ -1, /* Unassigned */
|
||||
/* Keyboard Int'l 1 87 */ 0x73, /* F3 */
|
||||
/* Keyboard Int'l 2 88 */ 0x70, /* F0 */
|
||||
/* Keyboard Int'l 2 89 */ 0x7D, /* FD */
|
||||
/* Keyboard Int'l 4 8A */ 0x79, /* F9 */
|
||||
/* Keyboard Int'l 5 8B */ 0x7B, /* FB */
|
||||
/* Keyboard Int'l 6 8C */ 0x5C, /* DC */
|
||||
/* Keyboard Int'l 7 8D */ -1, /* Unassigned */
|
||||
/* Keyboard Int'l 8 8E */ -1, /* Unassigned */
|
||||
/* Keyboard Int'l 9 8F */ -1, /* Unassigned */
|
||||
/* Keyboard Lang 1 90 */ NOBREAK|0xF2, /* None */
|
||||
/* Keyboard Lang 2 91 */ NOBREAK|0xF1, /* None */
|
||||
/* Keyboard Lang 3 92 */ 0x78, /* F8 */
|
||||
/* Keyboard Lang 4 93 */ 0x77, /* F7 */
|
||||
/* Keyboard Lang 5 94 */ 0x76, /* F6 */
|
||||
/* Keyboard Lang 6 95 */ -1, /* Unassigned */
|
||||
/* Keyboard Lang 7 96 */ -1, /* Unassigned */
|
||||
/* Keyboard Lang 8 97 */ -1, /* Unassigned */
|
||||
/* Keyboard Lang 9 98 */ -1, /* Unassigned */
|
||||
/* Keyboard Alternate Erase 99 */ -1, /* Unassigned */
|
||||
/* Keyboard SysReq/Attention 9A */ -1, /* Unassigned */
|
||||
/* Keyboard Cancel 9B */ -1, /* Unassigned */
|
||||
/* Keyboard Clear 9C */ -1, /* Unassigned */
|
||||
/* Keyboard Prior 9D */ -1, /* Unassigned */
|
||||
/* Keyboard Return 9E */ -1, /* Unassigned */
|
||||
/* Keyboard Separator 9F */ -1, /* Unassigned */
|
||||
/* Keyboard Out A0 */ -1, /* Unassigned */
|
||||
/* Keyboard Oper A1 */ -1, /* Unassigned */
|
||||
/* Keyboard Clear/Again A2 */ -1, /* Unassigned */
|
||||
/* Keyboard CrSel/Props A3 */ -1, /* Unassigned */
|
||||
/* Keyboard ExSel A4 */ -1, /* Unassigned */
|
||||
/* Reserved A5 */ -1, /* Reserved */
|
||||
/* Reserved A6 */ -1, /* Reserved */
|
||||
/* Reserved A7 */ -1, /* Reserved */
|
||||
/* Reserved A8 */ -1, /* Reserved */
|
||||
/* Reserved A9 */ -1, /* Reserved */
|
||||
/* Reserved AA */ -1, /* Reserved */
|
||||
/* Reserved AB */ -1, /* Reserved */
|
||||
/* Reserved AC */ -1, /* Reserved */
|
||||
/* Reserved AD */ -1, /* Reserved */
|
||||
/* Reserved AE */ -1, /* Reserved */
|
||||
/* Reserved AF */ -1, /* Reserved */
|
||||
/* Reserved B0 */ -1, /* Reserved */
|
||||
/* Reserved B1 */ -1, /* Reserved */
|
||||
/* Reserved B2 */ -1, /* Reserved */
|
||||
/* Reserved B3 */ -1, /* Reserved */
|
||||
/* Reserved B4 */ -1, /* Reserved */
|
||||
/* Reserved B5 */ -1, /* Reserved */
|
||||
/* Reserved B6 */ -1, /* Reserved */
|
||||
/* Reserved B7 */ -1, /* Reserved */
|
||||
/* Reserved B8 */ -1, /* Reserved */
|
||||
/* Reserved B9 */ -1, /* Reserved */
|
||||
/* Reserved BA */ -1, /* Reserved */
|
||||
/* Reserved BB */ -1, /* Reserved */
|
||||
/* Reserved BC */ -1, /* Reserved */
|
||||
/* Reserved BD */ -1, /* Reserved */
|
||||
/* Reserved BE */ -1, /* Reserved */
|
||||
/* Reserved BF */ -1, /* Reserved */
|
||||
/* Reserved C0 */ -1, /* Reserved */
|
||||
/* Reserved C1 */ -1, /* Reserved */
|
||||
/* Reserved C2 */ -1, /* Reserved */
|
||||
/* Reserved C3 */ -1, /* Reserved */
|
||||
/* Reserved C4 */ -1, /* Reserved */
|
||||
/* Reserved C5 */ -1, /* Reserved */
|
||||
/* Reserved C6 */ -1, /* Reserved */
|
||||
/* Reserved C8 */ -1, /* Reserved */
|
||||
/* Reserved C9 */ -1, /* Reserved */
|
||||
/* Reserved CA */ -1, /* Reserved */
|
||||
/* Reserved CB */ -1, /* Reserved */
|
||||
/* Reserved CC */ -1, /* Reserved */
|
||||
/* Reserved CD */ -1, /* Reserved */
|
||||
/* Reserved CE */ -1, /* Reserved */
|
||||
/* Reserved CF */ -1, /* Reserved */
|
||||
/* Reserved D0 */ -1, /* Reserved */
|
||||
/* Reserved D1 */ -1, /* Reserved */
|
||||
/* Reserved D2 */ -1, /* Reserved */
|
||||
/* Reserved D3 */ -1, /* Reserved */
|
||||
/* Reserved D4 */ -1, /* Reserved */
|
||||
/* Reserved D5 */ -1, /* Reserved */
|
||||
/* Reserved D6 */ -1, /* Reserved */
|
||||
/* Reserved D8 */ -1, /* Reserved */
|
||||
/* Reserved D9 */ -1, /* Reserved */
|
||||
/* Reserved DA */ -1, /* Reserved */
|
||||
/* Reserved DB */ -1, /* Reserved */
|
||||
/* Reserved DC */ -1, /* Reserved */
|
||||
/* Reserved DD */ -1, /* Reserved */
|
||||
/* Reserved DE */ -1, /* Reserved */
|
||||
/* Reserved DF */ -1, /* Reserved */
|
||||
/* Left Control E0 */ 0x1D, /* 9D */
|
||||
/* Left Control E0 */ 0x1D, /* 9D */
|
||||
/* Left Shift E1 */ 0x2A, /* AA */
|
||||
/* Left Alt E2 */ 0x38, /* B8 */
|
||||
/* Left GUI E3 */ E0PREFIX|0x5B, /* E0 DB */
|
||||
/* Right Control E4 */ E0PREFIX|0x1D, /* E0 9D */
|
||||
/* Right Shift E5 */ 0x36, /* B6 */
|
||||
/* Right Alt E6 */ E0PREFIX|0x38, /* E0 B8 */
|
||||
/* Right GUI E7 */ E0PREFIX|0x5C /* E0 DC */
|
||||
};
|
||||
|
||||
#define xsize (sizeof(x)/sizeof(x[0]))
|
||||
|
||||
/*
|
||||
* Get a max HID keycode (aligned)
|
||||
*/
|
||||
|
||||
int
|
||||
kbd_maxkey(void)
|
||||
{
|
||||
return (xsize);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process keys
|
||||
*/
|
||||
|
||||
int
|
||||
kbd_process_keys(bthid_session_p s)
|
||||
{
|
||||
bitstr_t r[bitstr_size(xsize)];
|
||||
int f0, f1, i;
|
||||
|
||||
assert(s != NULL);
|
||||
assert(s->srv != NULL);
|
||||
|
||||
bit_ffs(s->srv->keys, xsize, &f0);
|
||||
bit_ffs(s->keys, xsize, &f1);
|
||||
|
||||
if (f0 == -1) {
|
||||
/* all keys are released, no keys pressed */
|
||||
if (f1 != -1) {
|
||||
kbd_write(s->keys, f1, 0, s->srv->vkbd);
|
||||
memset(s->keys, 0, bitstr_size(xsize));
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (f1 == -1) {
|
||||
/* some keys got pressed, no keys released */
|
||||
if (f0 != -1) {
|
||||
memcpy(s->keys, s->srv->keys, bitstr_size(xsize));
|
||||
kbd_write(s->keys, f0, 1, s->srv->vkbd);
|
||||
memset(s->srv->keys, 0, bitstr_size(xsize));
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* some keys got pressed, some keys got released */
|
||||
memset(r, 0, bitstr_size(xsize));
|
||||
|
||||
for (i = f1; i < xsize; i++) {
|
||||
if (bit_test(s->keys, i)) {
|
||||
if (!bit_test(s->srv->keys, i)) {
|
||||
bit_clear(s->keys, i);
|
||||
bit_set(r, i);
|
||||
} else
|
||||
bit_clear(s->srv->keys, i);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = f0; i < xsize; i++) {
|
||||
if (bit_test(s->srv->keys, i)) {
|
||||
if (!bit_test(s->keys, i))
|
||||
bit_set(s->keys, i);
|
||||
else
|
||||
bit_clear(s->srv->keys, i);
|
||||
}
|
||||
}
|
||||
|
||||
bit_ffs(r, xsize, &f0);
|
||||
bit_ffs(s->srv->keys, xsize, &f1);
|
||||
|
||||
if (f0 > 0)
|
||||
kbd_write(r, f0, 0, s->srv->vkbd);
|
||||
|
||||
if (f1 > 0) {
|
||||
kbd_write(s->srv->keys, f1, 1, s->srv->vkbd);
|
||||
memset(s->srv->keys, 0, bitstr_size(xsize));
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get current keyboard index (fd version)
|
||||
*/
|
||||
|
||||
int
|
||||
kbd_get_index_fd(int fd)
|
||||
{
|
||||
keyboard_info_t info;
|
||||
|
||||
return ((ioctl(fd, KDGKBINFO, &info) < 0)? -1 : info.kb_index);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get current keyboard index (device node version)
|
||||
*/
|
||||
|
||||
int
|
||||
kbd_get_index(char const *device)
|
||||
{
|
||||
int fd, index;
|
||||
|
||||
fd = open(device, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return (-1);
|
||||
|
||||
index = kbd_get_index_fd(fd);
|
||||
|
||||
close(fd);
|
||||
|
||||
return (index);
|
||||
}
|
||||
|
||||
/*
|
||||
* Switch keyboards. Execute external script to switch keyboards. The keyboard
|
||||
* index will be passed to the script in the first argument (argv[1]). We use
|
||||
* external script here to allow user to customize his/her wireless keyboard,
|
||||
* i.e. set mapping etc. In theory, all parameters could be picked up from the
|
||||
* rc.conf.
|
||||
*/
|
||||
|
||||
int
|
||||
kbd_switch(char const *script, int index)
|
||||
{
|
||||
pid_t pid;
|
||||
int status;
|
||||
|
||||
if (script == NULL) {
|
||||
syslog(LOG_NOTICE, "Could not switch keyboards. " \
|
||||
"Switch script is not defined");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (access(script, X_OK) < 0) {
|
||||
syslog(LOG_ERR, "The %s is not executable. %s (%d)",
|
||||
script, strerror(errno), errno);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
|
||||
if (pid == (pid_t) -1) {
|
||||
syslog(LOG_ERR, "Could not create process for %s. %s (%d)",
|
||||
script, strerror(errno), errno);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
char arg[16];
|
||||
char *argv[3] = { (char *) script, arg, NULL };
|
||||
|
||||
snprintf(arg, sizeof(arg), "%d", index);
|
||||
execv(script, argv);
|
||||
|
||||
syslog(LOG_ERR, "Could not execute '%s %d'. %s (%d)",
|
||||
script, index, strerror(errno), errno);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (waitpid(pid, &status, 0) < 0) {
|
||||
syslog(LOG_ERR, "Could not waitpid for %s. %s (%d)",
|
||||
script, strerror(errno), errno);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (WIFEXITED(status) && WEXITSTATUS(status)) {
|
||||
syslog(LOG_ERR, "External command '%s %d' failed, exit code %d",
|
||||
script, index, WEXITSTATUS(status));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Translate given keymap and write keyscodes
|
||||
*/
|
||||
|
||||
static void
|
||||
kbd_write(bitstr_t *m, int fb, int make, int fd)
|
||||
{
|
||||
int i, *b, *eob, n, buf[64];
|
||||
|
||||
b = buf;
|
||||
eob = b + sizeof(buf)/sizeof(buf[0]);
|
||||
i = fb;
|
||||
|
||||
while (i < xsize) {
|
||||
if (bit_test(m, i)) {
|
||||
n = kbd_xlate(i, make, b, eob);
|
||||
if (n == -1) {
|
||||
write(fd, buf, (b - buf) * sizeof(buf[0]));
|
||||
b = buf;
|
||||
continue;
|
||||
}
|
||||
|
||||
b += n;
|
||||
}
|
||||
|
||||
i ++;
|
||||
}
|
||||
|
||||
if (b != buf)
|
||||
write(fd, buf, (b - buf) * sizeof(buf[0]));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Translate HID code into PS/2 code and put codes into buffer b.
|
||||
* Returns the number of codes put in b. Return -1 if buffer has not
|
||||
* enough space.
|
||||
*/
|
||||
|
||||
#undef PUT
|
||||
#define PUT(c, n, b, eob) \
|
||||
do { \
|
||||
if ((b) >= (eob)) \
|
||||
return (-1); \
|
||||
*(b) = (c); \
|
||||
(b) ++; \
|
||||
(n) ++; \
|
||||
} while (0)
|
||||
|
||||
static int
|
||||
kbd_xlate(int code, int make, int *b, int const *eob)
|
||||
{
|
||||
int c, n;
|
||||
|
||||
n = 0;
|
||||
|
||||
if (code >= xsize)
|
||||
return (0); /* HID code is not in the table */
|
||||
|
||||
/* Handle special case - Pause/Break */
|
||||
if (code == 0x48) {
|
||||
if (!make)
|
||||
return (0); /* No break code */
|
||||
|
||||
#if 0
|
||||
XXX FIXME
|
||||
if (ctrl_is_pressed) {
|
||||
/* Break (Ctrl-Pause) */
|
||||
PUT(0xe0, n, b, eob);
|
||||
PUT(0x46, n, b, eob);
|
||||
PUT(0xe0, n, b, eob);
|
||||
PUT(0xc6, n, b, eob);
|
||||
} else {
|
||||
/* Pause */
|
||||
PUT(0xe1, n, b, eob);
|
||||
PUT(0x1d, n, b, eob);
|
||||
PUT(0x45, n, b, eob);
|
||||
PUT(0xe1, n, b, eob);
|
||||
PUT(0x9d, n, b, eob);
|
||||
PUT(0xc5, n, b, eob);
|
||||
}
|
||||
#endif
|
||||
|
||||
return (n);
|
||||
}
|
||||
|
||||
if ((c = x[code]) == -1)
|
||||
return (0); /* HID code translation is not defined */
|
||||
|
||||
if (make) {
|
||||
if (c & E0PREFIX)
|
||||
PUT(0xe0, n, b, eob);
|
||||
|
||||
PUT((c & CODEMASK), n, b, eob);
|
||||
} else if (!(c & NOBREAK)) {
|
||||
if (c & E0PREFIX)
|
||||
PUT(0xe0, n, b, eob);
|
||||
|
||||
PUT((0x80|(c & CODEMASK)), n, b, eob);
|
||||
}
|
||||
|
||||
return (n);
|
||||
}
|
||||
|
41
usr.sbin/bluetooth/bthidd/kbd.h
Normal file
41
usr.sbin/bluetooth/bthidd/kbd.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* kbd.h
|
||||
*
|
||||
* Copyright (c) 2004 Maksim Yevmenkin <m_evmenkin@yahoo.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: kbd.h,v 1.2 2004/11/17 21:59:42 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _KBD_H_
|
||||
#define _KBD_H_
|
||||
|
||||
int kbd_maxkey (void);
|
||||
int kbd_process_keys(bthid_session_p s);
|
||||
int kbd_get_index_fd(int fd);
|
||||
int kbd_get_index (char const *device);
|
||||
int kbd_switch (char const *script, int index);
|
||||
|
||||
#endif /* ndef _KBD_H_ */
|
@ -26,18 +26,18 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: parser.y,v 1.3 2004/02/13 21:46:21 max Exp $
|
||||
* $Id: parser.y,v 1.4 2004/11/17 21:59:42 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/queue.h>
|
||||
#include <bluetooth.h>
|
||||
#include <errno.h>
|
||||
#include <libusbhid.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <usbhid.h>
|
||||
|
||||
#ifndef BTHIDCONTROL
|
||||
#include <stdarg.h>
|
||||
@ -52,7 +52,7 @@
|
||||
#define LOGCRIT stderr
|
||||
#define LOGERR stderr
|
||||
#define LOGWARNING stderr
|
||||
#define EOL "\n"
|
||||
#define EOL "\n"
|
||||
#endif /* ndef BTHIDCONTROL */
|
||||
|
||||
#include "bthid_config.h"
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: server.c,v 1.5 2004/02/26 21:43:36 max Exp $
|
||||
* $Id: server.c,v 1.7 2004/11/17 21:59:42 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -42,6 +42,7 @@
|
||||
#include <usbhid.h>
|
||||
#include "bthidd.h"
|
||||
#include "bthid_config.h"
|
||||
#include "kbd.h"
|
||||
|
||||
#undef max
|
||||
#define max(x, y) (((x) > (y))? (x) : (y))
|
||||
@ -65,6 +66,25 @@ server_init(bthid_server_p srv)
|
||||
FD_ZERO(&srv->wfdset);
|
||||
LIST_INIT(&srv->sessions);
|
||||
|
||||
/* Allocate HID keycodes buffer */
|
||||
srv->keys = bit_alloc(kbd_maxkey());
|
||||
if (srv->keys == NULL) {
|
||||
syslog(LOG_ERR, "Could not allocate HID keys buffer");
|
||||
return (-1);
|
||||
}
|
||||
memset(srv->keys, 0, bitstr_size(kbd_maxkey()));
|
||||
|
||||
/* Get wired keyboard index (if was not specified) */
|
||||
if (srv->windex == -1) {
|
||||
srv->windex = kbd_get_index("/dev/console");
|
||||
if (srv->windex < 0) {
|
||||
syslog(LOG_ERR, "Could not open get wired keyboard " \
|
||||
"index. %s (%d)", strerror(errno), errno);
|
||||
free(srv->keys);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Open /dev/consolectl */
|
||||
srv->cons = open("/dev/consolectl", O_RDWR);
|
||||
if (srv->cons < 0) {
|
||||
@ -73,12 +93,24 @@ server_init(bthid_server_p srv)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Open /dev/vkbdctl */
|
||||
srv->vkbd = open("/dev/vkbdctl", O_RDWR);
|
||||
if (srv->vkbd < 0) {
|
||||
syslog(LOG_ERR, "Could not open /dev/vkbdctl. %s (%d)",
|
||||
strerror(errno), errno);
|
||||
close(srv->cons);
|
||||
free(srv->keys);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Create control socket */
|
||||
srv->ctrl = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BLUETOOTH_PROTO_L2CAP);
|
||||
if (srv->ctrl < 0) {
|
||||
syslog(LOG_ERR, "Could not create control L2CAP socket. " \
|
||||
"%s (%d)", strerror(errno), errno);
|
||||
close(srv->vkbd);
|
||||
close(srv->cons);
|
||||
free(srv->keys);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
@ -90,14 +122,20 @@ server_init(bthid_server_p srv)
|
||||
if (bind(srv->ctrl, (struct sockaddr *) &l2addr, sizeof(l2addr)) < 0) {
|
||||
syslog(LOG_ERR, "Could not bind control L2CAP socket. " \
|
||||
"%s (%d)", strerror(errno), errno);
|
||||
close(srv->ctrl);
|
||||
close(srv->vkbd);
|
||||
close(srv->cons);
|
||||
free(srv->keys);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (listen(srv->ctrl, 10) < 0) {
|
||||
syslog(LOG_ERR, "Could not listen on control L2CAP socket. " \
|
||||
"%s (%d)", strerror(errno), errno);
|
||||
close(srv->ctrl);
|
||||
close(srv->vkbd);
|
||||
close(srv->cons);
|
||||
free(srv->keys);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
@ -107,7 +145,9 @@ server_init(bthid_server_p srv)
|
||||
syslog(LOG_ERR, "Could not create interrupt L2CAP socket. " \
|
||||
"%s (%d)", strerror(errno), errno);
|
||||
close(srv->ctrl);
|
||||
close(srv->vkbd);
|
||||
close(srv->cons);
|
||||
free(srv->keys);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
@ -116,16 +156,22 @@ server_init(bthid_server_p srv)
|
||||
if (bind(srv->intr, (struct sockaddr *) &l2addr, sizeof(l2addr)) < 0) {
|
||||
syslog(LOG_ERR, "Could not bind interrupt L2CAP socket. " \
|
||||
"%s (%d)", strerror(errno), errno);
|
||||
close(srv->intr);
|
||||
close(srv->ctrl);
|
||||
close(srv->vkbd);
|
||||
close(srv->cons);
|
||||
free(srv->keys);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (listen(srv->intr, 10) < 0) {
|
||||
syslog(LOG_ERR, "Could not listen on interrupt L2CAP socket. "\
|
||||
"%s (%d)", strerror(errno), errno);
|
||||
close(srv->intr);
|
||||
close(srv->ctrl);
|
||||
close(srv->vkbd);
|
||||
close(srv->cons);
|
||||
free(srv->keys);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
@ -146,12 +192,15 @@ server_shutdown(bthid_server_p srv)
|
||||
assert(srv != NULL);
|
||||
|
||||
close(srv->cons);
|
||||
close(srv->vkbd);
|
||||
close(srv->ctrl);
|
||||
close(srv->intr);
|
||||
|
||||
while (!LIST_EMPTY(&srv->sessions))
|
||||
session_close(LIST_FIRST(&srv->sessions));
|
||||
|
||||
free(srv->keys);
|
||||
|
||||
memset(srv, 0, sizeof(*srv));
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: session.c,v 1.1 2004/02/12 22:46:59 max Exp $
|
||||
* $Id: session.c,v 1.2 2004/11/17 21:59:42 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -37,6 +37,7 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "bthidd.h"
|
||||
#include "kbd.h"
|
||||
|
||||
/*
|
||||
* Create new session
|
||||
@ -53,10 +54,15 @@ session_open(bthid_server_p srv, bdaddr_p bdaddr)
|
||||
if ((s = (bthid_session_p) malloc(sizeof(*s))) != NULL) {
|
||||
s->srv = srv;
|
||||
memcpy(&s->bdaddr, bdaddr, sizeof(s->bdaddr));
|
||||
s->ctrl = s->intr = -1;
|
||||
s->ctrl = -1;
|
||||
s->intr = -1;
|
||||
s->state = CLOSED;
|
||||
|
||||
LIST_INSERT_HEAD(&srv->sessions, s, next);
|
||||
s->keys = bit_alloc(kbd_maxkey());
|
||||
if (s->keys == NULL) {
|
||||
free(s);
|
||||
s = NULL;
|
||||
} else
|
||||
LIST_INSERT_HEAD(&srv->sessions, s, next);
|
||||
}
|
||||
|
||||
return (s);
|
||||
@ -130,6 +136,8 @@ session_close(bthid_session_p s)
|
||||
s->srv->maxfd --;
|
||||
}
|
||||
|
||||
free(s->keys);
|
||||
|
||||
memset(s, 0, sizeof(*s));
|
||||
free(s);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user