summaryrefslogtreecommitdiffstats
path: root/hidd
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2008-08-04 20:58:34 +0200
committerMarcel Holtmann <marcel@holtmann.org>2008-08-04 20:58:34 +0200
commit40372f9dc3ab115870a10343124216a041e55d17 (patch)
treeef5bfa80e3f560cf6856fd7a0d5c27c75c2cefe0 /hidd
parent295eb0c879802eacff46cf3c962646363d81f6d3 (diff)
Move hidd pand and dund into compat directory
Diffstat (limited to 'hidd')
-rw-r--r--hidd/Makefile.am22
-rw-r--r--hidd/fakehid.c669
-rw-r--r--hidd/fakehid.txt134
-rw-r--r--hidd/hidd.141
-rw-r--r--hidd/hidd.h34
-rw-r--r--hidd/main.c860
-rw-r--r--hidd/sdp.c352
7 files changed, 0 insertions, 2112 deletions
diff --git a/hidd/Makefile.am b/hidd/Makefile.am
deleted file mode 100644
index 508372b4..00000000
--- a/hidd/Makefile.am
+++ /dev/null
@@ -1,22 +0,0 @@
-
-if HIDD
-bin_PROGRAMS = hidd
-
-hidd_SOURCES = main.c hidd.h sdp.c fakehid.c
-
-hidd_LDADD = @BLUEZ_LIBS@ -lm $(top_builddir)/common/libhelper.a
-endif
-
-AM_CFLAGS = @BLUEZ_CFLAGS@
-
-INCLUDES = -I$(top_srcdir)/common
-
-if HIDD
-if MANPAGES
-man_MANS = hidd.1
-endif
-endif
-
-EXTRA_DIST = hidd.1 fakehid.txt
-
-MAINTAINERCLEANFILES = Makefile.in
diff --git a/hidd/fakehid.c b/hidd/fakehid.c
deleted file mode 100644
index feefe2a6..00000000
--- a/hidd/fakehid.c
+++ /dev/null
@@ -1,669 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2003-2008 Marcel Holtmann <marcel@holtmann.org>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <sys/poll.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/rfcomm.h>
-#include <bluetooth/hidp.h>
-
-#include "hidd.h"
-#include "uinput.h"
-
-#include <math.h>
-
-#ifdef NEED_PPOLL
-#include "ppoll.h"
-#endif
-
-static volatile sig_atomic_t __io_canceled = 0;
-
-static void sig_hup(int sig)
-{
-}
-
-static void sig_term(int sig)
-{
- __io_canceled = 1;
-}
-
-static void send_event(int fd, uint16_t type, uint16_t code, int32_t value)
-{
- struct uinput_event event;
- int len;
-
- if (fd <= fileno(stderr))
- return;
-
- memset(&event, 0, sizeof(event));
- event.type = type;
- event.code = code;
- event.value = value;
-
- len = write(fd, &event, sizeof(event));
-}
-
-static int uinput_create(char *name, int keyboard, int mouse)
-{
- struct uinput_dev dev;
- int fd, aux;
-
- fd = open("/dev/uinput", O_RDWR);
- if (fd < 0) {
- fd = open("/dev/input/uinput", O_RDWR);
- if (fd < 0) {
- fd = open("/dev/misc/uinput", O_RDWR);
- if (fd < 0) {
- fprintf(stderr, "Can't open input device: %s (%d)\n",
- strerror(errno), errno);
- return -1;
- }
- }
- }
-
- memset(&dev, 0, sizeof(dev));
-
- if (name)
- strncpy(dev.name, name, UINPUT_MAX_NAME_SIZE);
-
- dev.id.bustype = BUS_BLUETOOTH;
- dev.id.vendor = 0x0000;
- dev.id.product = 0x0000;
- dev.id.version = 0x0000;
-
- if (write(fd, &dev, sizeof(dev)) < 0) {
- fprintf(stderr, "Can't write device information: %s (%d)\n",
- strerror(errno), errno);
- close(fd);
- return -1;
- }
-
- if (mouse) {
- ioctl(fd, UI_SET_EVBIT, EV_REL);
-
- for (aux = REL_X; aux <= REL_MISC; aux++)
- ioctl(fd, UI_SET_RELBIT, aux);
- }
-
- if (keyboard) {
- ioctl(fd, UI_SET_EVBIT, EV_KEY);
- ioctl(fd, UI_SET_EVBIT, EV_LED);
- ioctl(fd, UI_SET_EVBIT, EV_REP);
-
- for (aux = KEY_RESERVED; aux <= KEY_UNKNOWN; aux++)
- ioctl(fd, UI_SET_KEYBIT, aux);
-
- //for (aux = LED_NUML; aux <= LED_MISC; aux++)
- // ioctl(fd, UI_SET_LEDBIT, aux);
- }
-
- if (mouse) {
- ioctl(fd, UI_SET_EVBIT, EV_KEY);
-
- for (aux = BTN_LEFT; aux <= BTN_BACK; aux++)
- ioctl(fd, UI_SET_KEYBIT, aux);
- }
-
- ioctl(fd, UI_DEV_CREATE);
-
- return fd;
-}
-
-static int rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel)
-{
- struct sockaddr_rc addr;
- int sk;
-
- sk = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
- if (sk < 0) {
- fprintf(stderr, "Can't create socket: %s (%d)\n",
- strerror(errno), errno);
- return -1;
- }
-
- memset(&addr, 0, sizeof(addr));
- addr.rc_family = AF_BLUETOOTH;
- bacpy(&addr.rc_bdaddr, src);
-
- if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- fprintf(stderr, "Can't bind socket: %s (%d)\n",
- strerror(errno), errno);
- close(sk);
- return -1;
- }
-
- memset(&addr, 0, sizeof(addr));
- addr.rc_family = AF_BLUETOOTH;
- bacpy(&addr.rc_bdaddr, dst);
- addr.rc_channel = channel;
-
- if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- fprintf(stderr, "Can't connect: %s (%d)\n",
- strerror(errno), errno);
- close(sk);
- return -1;
- }
-
- return sk;
-}
-
-static void func(int fd)
-{
-}
-
-static void back(int fd)
-{
-}
-
-static void next(int fd)
-{
-}
-
-static void button(int fd, unsigned int button, int is_press)
-{
- switch (button) {
- case 1:
- send_event(fd, EV_KEY, BTN_LEFT, is_press);
- break;
- case 3:
- send_event(fd, EV_KEY, BTN_RIGHT, is_press);
- break;
- }
-
- send_event(fd, EV_SYN, SYN_REPORT, 0);
-}
-
-static void move(int fd, unsigned int direction)
-{
- double angle;
- int32_t x, y;
-
- angle = (direction * 22.5) * 3.1415926 / 180;
- x = (int) (sin(angle) * 8);
- y = (int) (cos(angle) * -8);
-
- send_event(fd, EV_REL, REL_X, x);
- send_event(fd, EV_REL, REL_Y, y);
-
- send_event(fd, EV_SYN, SYN_REPORT, 0);
-}
-
-static inline void epox_decode(int fd, unsigned char event)
-{
- switch (event) {
- case 48:
- func(fd); break;
- case 55:
- back(fd); break;
- case 56:
- next(fd); break;
- case 53:
- button(fd, 1, 1); break;
- case 121:
- button(fd, 1, 0); break;
- case 113:
- break;
- case 54:
- button(fd, 3, 1); break;
- case 120:
- button(fd, 3, 0); break;
- case 112:
- break;
- case 51:
- move(fd, 0); break;
- case 97:
- move(fd, 1); break;
- case 65:
- move(fd, 2); break;
- case 98:
- move(fd, 3); break;
- case 50:
- move(fd, 4); break;
- case 99:
- move(fd, 5); break;
- case 67:
- move(fd, 6); break;
- case 101:
- move(fd, 7); break;
- case 52:
- move(fd, 8); break;
- case 100:
- move(fd, 9); break;
- case 66:
- move(fd, 10); break;
- case 102:
- move(fd, 11); break;
- case 49:
- move(fd, 12); break;
- case 103:
- move(fd, 13); break;
- case 57:
- move(fd, 14); break;
- case 104:
- move(fd, 15); break;
- case 69:
- break;
- default:
- printf("Unknown event code %d\n", event);
- break;
- }
-}
-
-int epox_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel)
-{
- unsigned char buf[16];
- struct sigaction sa;
- struct pollfd p;
- sigset_t sigs;
- char addr[18];
- int i, fd, sk, len;
-
- sk = rfcomm_connect(src, dst, channel);
- if (sk < 0)
- return -1;
-
- fd = uinput_create("Bluetooth Presenter", 0, 1);
- if (fd < 0) {
- close(sk);
- return -1;
- }
-
- ba2str(dst, addr);
-
- printf("Connected to %s on channel %d\n", addr, channel);
- printf("Press CTRL-C for hangup\n");
-
- memset(&sa, 0, sizeof(sa));
- sa.sa_flags = SA_NOCLDSTOP;
- sa.sa_handler = SIG_IGN;
- sigaction(SIGCHLD, &sa, NULL);
- sigaction(SIGPIPE, &sa, NULL);
-
- sa.sa_handler = sig_term;
- sigaction(SIGTERM, &sa, NULL);
- sigaction(SIGINT, &sa, NULL);
-
- sa.sa_handler = sig_hup;
- sigaction(SIGHUP, &sa, NULL);
-
- sigfillset(&sigs);
- sigdelset(&sigs, SIGCHLD);
- sigdelset(&sigs, SIGPIPE);
- sigdelset(&sigs, SIGTERM);
- sigdelset(&sigs, SIGINT);
- sigdelset(&sigs, SIGHUP);
-
- p.fd = sk;
- p.events = POLLIN | POLLERR | POLLHUP;
-
- while (!__io_canceled) {
- p.revents = 0;
- if (ppoll(&p, 1, NULL, &sigs) < 1)
- continue;
-
- len = read(sk, buf, sizeof(buf));
- if (len < 0)
- break;
-
- for (i = 0; i < len; i++)
- epox_decode(fd, buf[i]);
- }
-
- printf("Disconnected\n");
-
- ioctl(fd, UI_DEV_DESTROY);
-
- close(fd);
- close(sk);
-
- return 0;
-}
-
-int headset_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel)
-{
- printf("Not implemented\n");
- return -1;
-}
-
-/* The strange meta key close to Ctrl has been assigned to Esc,
- Fn key to CtrlR and the left space to Alt*/
-
-static unsigned char jthree_keycodes[63] = {
- KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6,
- KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T,
- KEY_A, KEY_S, KEY_D, KEY_F, KEY_G,
- KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B,
- KEY_LEFTALT, KEY_TAB, KEY_CAPSLOCK, KEY_ESC,
- KEY_7, KEY_8, KEY_9, KEY_0, KEY_MINUS, KEY_EQUAL, KEY_BACKSPACE,
- KEY_Y, KEY_U, KEY_I, KEY_O, KEY_P, KEY_LEFTBRACE, KEY_RIGHTBRACE,
- KEY_H, KEY_J, KEY_K, KEY_L, KEY_SEMICOLON, KEY_APOSTROPHE, KEY_ENTER,
- KEY_N, KEY_M, KEY_COMMA, KEY_DOT, KEY_SLASH, KEY_UP,
- KEY_SPACE, KEY_COMPOSE, KEY_LEFT, KEY_DOWN, KEY_RIGHT,
- KEY_LEFTCTRL, KEY_RIGHTSHIFT, KEY_LEFTSHIFT, KEY_DELETE, KEY_RIGHTCTRL, KEY_RIGHTALT,
-};
-
-static inline void jthree_decode(int fd, unsigned char event)
-{
- if (event > 63)
- send_event(fd, EV_KEY, jthree_keycodes[event & 0x3f], 0);
- else
- send_event(fd, EV_KEY, jthree_keycodes[event - 1], 1);
-}
-
-int jthree_keyboard(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel)
-{
- unsigned char buf[16];
- struct sigaction sa;
- struct pollfd p;
- sigset_t sigs;
- char addr[18];
- int i, fd, sk, len;
-
- sk = rfcomm_connect(src, dst, channel);
- if (sk < 0)
- return -1;
-
- fd = uinput_create("J-Three Keyboard", 1, 0);
- if (fd < 0) {
- close(sk);
- return -1;
- }
-
- ba2str(dst, addr);
-
- printf("Connected to %s on channel %d\n", addr, channel);
- printf("Press CTRL-C for hangup\n");
-
- memset(&sa, 0, sizeof(sa));
- sa.sa_flags = SA_NOCLDSTOP;
- sa.sa_handler = SIG_IGN;
- sigaction(SIGCHLD, &sa, NULL);
- sigaction(SIGPIPE, &sa, NULL);
-
- sa.sa_handler = sig_term;
- sigaction(SIGTERM, &sa, NULL);
- sigaction(SIGINT, &sa, NULL);
-
- sa.sa_handler = sig_hup;
- sigaction(SIGHUP, &sa, NULL);
-
- sigfillset(&sigs);
- sigdelset(&sigs, SIGCHLD);
- sigdelset(&sigs, SIGPIPE);
- sigdelset(&sigs, SIGTERM);
- sigdelset(&sigs, SIGINT);
- sigdelset(&sigs, SIGHUP);
-
- p.fd = sk;
- p.events = POLLIN | POLLERR | POLLHUP;
-
- while (!__io_canceled) {
- p.revents = 0;
- if (ppoll(&p, 1, NULL, &sigs) < 1)
- continue;
-
- len = read(sk, buf, sizeof(buf));
- if (len < 0)
- break;
-
- for (i = 0; i < len; i++)
- jthree_decode(fd, buf[i]);
- }
-
- printf("Disconnected\n");
-
- ioctl(fd, UI_DEV_DESTROY);
-
- close(fd);
- close(sk);
-
- return 0;
-}
-
-static const int celluon_xlate_num[10] = {
- KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9
-};
-
-static const int celluon_xlate_char[26] = {
- KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J,
- KEY_K, KEY_L, KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T,
- KEY_U, KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z
-};
-
-static int celluon_xlate(int c)
-{
- if (c >= '0' && c <= '9')
- return celluon_xlate_num[c - '0'];
-
- if (c >= 'A' && c <= 'Z')
- return celluon_xlate_char[c - 'A'];
-
- switch (c) {
- case 0x08:
- return KEY_BACKSPACE;
- case 0x09:
- return KEY_TAB;
- case 0x0d:
- return KEY_ENTER;
- case 0x11:
- return KEY_LEFTCTRL;
- case 0x14:
- return KEY_CAPSLOCK;
- case 0x20:
- return KEY_SPACE;
- case 0x25:
- return KEY_LEFT;
- case 0x26:
- return KEY_UP;
- case 0x27:
- return KEY_RIGHT;
- case 0x28:
- return KEY_DOWN;
- case 0x2e:
- return KEY_DELETE;
- case 0x5b:
- return KEY_MENU;
- case 0xa1:
- return KEY_RIGHTSHIFT;
- case 0xa0:
- return KEY_LEFTSHIFT;
- case 0xba:
- return KEY_SEMICOLON;
- case 0xbd:
- return KEY_MINUS;
- case 0xbc:
- return KEY_COMMA;
- case 0xbb:
- return KEY_EQUAL;
- case 0xbe:
- return KEY_DOT;
- case 0xbf:
- return KEY_SLASH;
- case 0xc0:
- return KEY_GRAVE;
- case 0xdb:
- return KEY_LEFTBRACE;
- case 0xdc:
- return KEY_BACKSLASH;
- case 0xdd:
- return KEY_RIGHTBRACE;
- case 0xde:
- return KEY_APOSTROPHE;
- case 0xff03:
- return KEY_HOMEPAGE;
- case 0xff04:
- return KEY_TIME;
- case 0xff06:
- return KEY_OPEN;
- case 0xff07:
- return KEY_LIST;
- case 0xff08:
- return KEY_MAIL;
- case 0xff30:
- return KEY_CALC;
- case 0xff1a: /* Map FN to ALT */
- return KEY_LEFTALT;
- case 0xff2f:
- return KEY_INFO;
- default:
- printf("Unknown key %x\n", c);
- return c;
- }
-}
-
-struct celluon_state {
- int len; /* Expected length of current packet */
- int count; /* Number of bytes received */
- int action;
- int key;
-};
-
-static void celluon_decode(int fd, struct celluon_state *s, uint8_t c)
-{
- if (s->count < 2 && c != 0xa5) {
- /* Lost Sync */
- s->count = 0;
- return;
- }
-
- switch (s->count) {
- case 0:
- /* New packet - Reset state */
- s->len = 30;
- s->key = 0;
- break;
- case 1:
- break;
- case 6:
- s->action = c;
- break;
- case 28:
- s->key = c;
- if (c == 0xff)
- s->len = 31;
- break;
- case 29:
- case 30:
- if (s->count == s->len - 1) {
- /* TODO: Verify checksum */
- if (s->action < 2) {
- send_event(fd, EV_KEY, celluon_xlate(s->key),
- s->action);
- }
- s->count = -1;
- } else {
- s->key = (s->key << 8) | c;
- }
- break;
- }
-
- s->count++;
-
- return;
-}
-
-int celluon_keyboard(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel)
-{
- unsigned char buf[16];
- struct sigaction sa;
- struct pollfd p;
- sigset_t sigs;
- char addr[18];
- int i, fd, sk, len;
- struct celluon_state s;
-
- sk = rfcomm_connect(src, dst, channel);
- if (sk < 0)
- return -1;
-
- fd = uinput_create("Celluon Keyboard", 1, 0);
- if (fd < 0) {
- close(sk);
- return -1;
- }
-
- ba2str(dst, addr);
-
- printf("Connected to %s on channel %d\n", addr, channel);
- printf("Press CTRL-C for hangup\n");
-
- memset(&sa, 0, sizeof(sa));
- sa.sa_flags = SA_NOCLDSTOP;
- sa.sa_handler = SIG_IGN;
- sigaction(SIGCHLD, &sa, NULL);
- sigaction(SIGPIPE, &sa, NULL);
-
- sa.sa_handler = sig_term;
- sigaction(SIGTERM, &sa, NULL);
- sigaction(SIGINT, &sa, NULL);
-
- sa.sa_handler = sig_hup;
- sigaction(SIGHUP, &sa, NULL);
-
- sigfillset(&sigs);
- sigdelset(&sigs, SIGCHLD);
- sigdelset(&sigs, SIGPIPE);
- sigdelset(&sigs, SIGTERM);
- sigdelset(&sigs, SIGINT);
- sigdelset(&sigs, SIGHUP);
-
- p.fd = sk;
- p.events = POLLIN | POLLERR | POLLHUP;
-
- memset(&s, 0, sizeof(s));
-
- while (!__io_canceled) {
- p.revents = 0;
- if (ppoll(&p, 1, NULL, &sigs) < 1)
- continue;
-
- len = read(sk, buf, sizeof(buf));
- if (len < 0)
- break;
-
- for (i = 0; i < len; i++)
- celluon_decode(fd, &s, buf[i]);
- }
-
- printf("Disconnected\n");
-
- ioctl(fd, UI_DEV_DESTROY);
-
- close(fd);
- close(sk);
-
- return 0;
-}
diff --git a/hidd/fakehid.txt b/hidd/fakehid.txt
deleted file mode 100644
index 000d0ee2..00000000
--- a/hidd/fakehid.txt
+++ /dev/null
@@ -1,134 +0,0 @@
-EPox Presenter
-==============
-
-# hcitool inq
-Inquiring ...
- 00:04:61:aa:bb:cc clock offset: 0x1ded class: 0x004000
-
-# hcitool info 00:04:61:aa:bb:cc
-Requesting information ...
- BD Address: 00:04:61:aa:bb:cc
- OUI Company: EPOX Computer Co., Ltd. (00-04-61)
- Device Name: EPox BT-PM01B aabbcc
- LMP Version: 1.1 (0x1) LMP Subversion: 0xf78
- Manufacturer: Cambridge Silicon Radio (10)
- Features: 0xff 0xff 0x0f 0x00 0x00 0x00 0x00 0x00
- <3-slot packets> <5-slot packets> <encryption> <slot offset>
- <timing accuracy> <role switch> <hold mode> <sniff mode>
- <park state> <RSSI> <channel quality> <SCO link> <HV2 packets>
- <HV3 packets> <u-law log> <A-law log> <CVSD> <paging scheme>
- <power control> <transparent SCO>
-
-# sdptool records --raw 00:04:61:aa:bb:cc
-Sequence
- Attribute 0x0000 - ServiceRecordHandle
- UINT32 0x00010000
- Attribute 0x0001 - ServiceClassIDList
- Sequence
- UUID16 0x1101 - SerialPort
- Attribute 0x0004 - ProtocolDescriptorList
- Sequence
- Sequence
- UUID16 0x0100 - L2CAP
- Sequence
- UUID16 0x0003 - RFCOMM
- UINT8 0x01
- Attribute 0x0100
- String Cable Replacement
-
-
-J-Three Keyboard
-================
-
-# hcitool inq
-Inquiring ...
- 00:0A:3A:aa:bb:cc clock offset: 0x3039 class: 0x001f00
-
-# hcitool info 00:0A:3A:aa:bb:cc
-Password:
-Requesting information ...
- BD Address: 00:0A:3A:aa:bb:cc
- OUI Company: J-THREE INTERNATIONAL Holding Co., Ltd. (00-0A-3A)
- Device Name: KEYBOARD
- LMP Version: 1.1 (0x1) LMP Subversion: 0x2c2
- Manufacturer: Cambridge Silicon Radio (10)
- Features: 0xbc 0x06 0x07 0x00 0x00 0x00 0x00 0x00
- <encryption> <slot offset> <timing accuracy> <role switch>
- <sniff mode> <RSSI> <channel quality> <CVSD> <paging scheme>
- <power control>
-
-# sdptool records --raw 00:0A:3A:aa:bb:cc
-Sequence
- Attribute 0x0000 - ServiceRecordHandle
- UINT32 0x00010000
- Attribute 0x0001 - ServiceClassIDList
- Sequence
- UUID16 0x1101 - SerialPort
- Attribute 0x0004 - ProtocolDescriptorList
- Sequence
- Sequence
- UUID16 0x0100 - L2CAP
- Sequence
- UUID16 0x0003 - RFCOMM
- UINT8 0x01
- Attribute 0x0006 - LanguageBaseAttributeIDList
- Sequence
- UINT16 0x656e
- UINT16 0x006a
- UINT16 0x0100
- Attribute 0x0100
- String SPP slave
-
-
-Celluon Laserkey Keyboard
-=========================
-
-# hcitool inq
-Inquiring ...
- 00:0B:24:aa:bb:cc clock offset: 0x3ab6 class: 0x400210
-
-# hcitool info 00:0B:24:aa:bb:cc
-Requesting information ...
- BD Address: 00:0B:24:aa:bb:cc
- OUI Company: AirLogic (00-0B-24)
- Device Name: CL800BT
- LMP Version: 1.1 (0x1) LMP Subversion: 0x291
- Manufacturer: Cambridge Silicon Radio (10)
- Features: 0xff 0xff 0x0f 0x00 0x00 0x00 0x00 0x00
- <3-slot packets> <5-slot packets> <encryption> <slot offset>
- <timing accuracy> <role switch> <hold mode> <sniff mode>
- <park state> <RSSI> <channel quality> <SCO link> <HV2 packets>
- <HV3 packets> <u-law log> <A-law log> <CVSD> <paging scheme>
- <power control> <transparent SCO>
-
-# sdptool records --raw 00:0B:24:aa:bb:cc
-Sequence
- Attribute 0x0000 - ServiceRecordHandle
- UINT32 0x00010000
- Attribute 0x0001 - ServiceClassIDList
- Sequence
- UUID16 0x1101 - SerialPort
- Attribute 0x0004 - ProtocolDescriptorList
- Sequence
- Sequence
- UUID16 0x0100 - L2CAP
- Sequence
- UUID16 0x0003 - RFCOMM
- UINT8 0x01
- Attribute 0x0100
- String Serial Port
-
-Packet format is as follows (all fields little-endian):
- 0 uint16 magic # 0x5a5a
- 2 uint32 unknown # ???
- 6 uint8 action # 0 = keyup, 1 = keydown, 2 = repeat
- # 3, 4, 5, 6 = ??? (Mouse mode)
- 7 uint8 unknown[9] # ???
- 16 uint8 action2 # ??? same as action
- 17 uint16 x # Horizontal coordinate
- 19 uint16 y # Vertical coordinate
- 21 uint16 time # Some sort of timestamp
- 23 uint8 unknown[5] # ???
- 28 uint8 key[] # single byte keycode or 0xff byte
- # follwed by special keycode byte.
- Each packet followed by a checksum byte.
diff --git a/hidd/hidd.1 b/hidd/hidd.1
deleted file mode 100644
index b186ac24..00000000
--- a/hidd/hidd.1
+++ /dev/null
@@ -1,41 +0,0 @@
-.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.33.
-.TH HIDD "1" "May 2004" "hidd - Bluetooth HID daemon" "User Commands"
-.SH NAME
-hidd \- Bluetooth HID daemon
-.SH DESCRIPTION
-hidd - Bluetooth HID daemon
-.SS "Usage:"
-.IP
-hidd [options] [commands]
-.SH OPTIONS
-.TP
-\fB\-i\fR <hciX|bdaddr>
-Local HCI device or BD Address
-.TP
-\fB\-t\fR <timeout>
-Set idle timeout (in minutes)
-.TP
-\fB\-n\fR, \fB\-\-nodaemon\fR
-Don't fork daemon to background
-.TP
-\fB\-h\fR, \fB\-\-help\fR
-Display help
-.SS "Commands:"
-.TP
-\fB\-\-server\fR
-Start HID server
-.TP
-\fB\-\-search\fR
-Search for HID devices
-.TP
-\fB\-\-connect\fR <bdaddr>
-Connect remote HID device
-.TP
-\fB\-\-kill\fR <bdaddr>
-Terminate HID connection
-.TP
-\fB\-\-killall\fR
-Terminate all connections
-.TP
-\fB\-\-show\fR
-List current HID connections
diff --git a/hidd/hidd.h b/hidd/hidd.h
deleted file mode 100644
index 63e0cbbe..00000000
--- a/hidd/hidd.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2003-2008 Marcel Holtmann <marcel@holtmann.org>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#define L2CAP_PSM_HIDP_CTRL 0x11
-#define L2CAP_PSM_HIDP_INTR 0x13
-
-int get_stored_device_info(const bdaddr_t *src, const bdaddr_t *dst, struct hidp_connadd_req *req);
-int get_sdp_device_info(const bdaddr_t *src, const bdaddr_t *dst, struct hidp_connadd_req *req);
-int get_alternate_device_info(const bdaddr_t *src, const bdaddr_t *dst, uint16_t *uuid, uint8_t *channel, char *name, size_t len);
-
-int epox_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel);
-int headset_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel);
-int jthree_keyboard(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel);
-int celluon_keyboard(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel);
diff --git a/hidd/main.c b/hidd/main.c
deleted file mode 100644
index d0883b36..00000000
--- a/hidd/main.c
+++ /dev/null
@@ -1,860 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2003-2008 Marcel Holtmann <marcel@holtmann.org>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-#include <signal.h>
-#include <getopt.h>
-#include <sys/poll.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/hci.h>
-#include <bluetooth/hci_lib.h>
-#include <bluetooth/l2cap.h>
-#include <bluetooth/sdp.h>
-#include <bluetooth/hidp.h>
-
-#include "hidd.h"
-
-#ifdef NEED_PPOLL
-#include "ppoll.h"
-#endif
-
-enum {
- NONE,
- SHOW,
- SERVER,
- SEARCH,
- CONNECT,
- KILL
-};
-
-static volatile sig_atomic_t __io_canceled = 0;
-
-static void sig_hup(int sig)
-{
-}
-
-static void sig_term(int sig)
-{
- __io_canceled = 1;
-}
-
-static int l2cap_connect(bdaddr_t *src, bdaddr_t *dst, unsigned short psm)
-{
- struct sockaddr_l2 addr;
- struct l2cap_options opts;
- int sk;
-
- if ((sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) < 0)
- return -1;
-
- memset(&addr, 0, sizeof(addr));
- addr.l2_family = AF_BLUETOOTH;
- bacpy(&addr.l2_bdaddr, src);
-
- if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- close(sk);
- return -1;
- }
-
- memset(&opts, 0, sizeof(opts));
- opts.imtu = HIDP_DEFAULT_MTU;
- opts.omtu = HIDP_DEFAULT_MTU;
- opts.flush_to = 0xffff;
-
- setsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, sizeof(opts));
-
- memset(&addr, 0, sizeof(addr));
- addr.l2_family = AF_BLUETOOTH;
- bacpy(&addr.l2_bdaddr, dst);
- addr.l2_psm = htobs(psm);
-
- if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- close(sk);
- return -1;
- }
-
- return sk;
-}
-
-static int l2cap_listen(const bdaddr_t *bdaddr, unsigned short psm, int lm, int backlog)
-{
- struct sockaddr_l2 addr;
- struct l2cap_options opts;
- int sk;
-
- if ((sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) < 0)
- return -1;
-
- memset(&addr, 0, sizeof(addr));
- addr.l2_family = AF_BLUETOOTH;
- bacpy(&addr.l2_bdaddr, bdaddr);
- addr.l2_psm = htobs(psm);
-
- if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- close(sk);
- return -1;
- }
-
- setsockopt(sk, SOL_L2CAP, L2CAP_LM, &lm, sizeof(lm));
-
- memset(&opts, 0, sizeof(opts));
- opts.imtu = HIDP_DEFAULT_MTU;
- opts.omtu = HIDP_DEFAULT_MTU;
- opts.flush_to = 0xffff;
-
- setsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, sizeof(opts));
-
- if (listen(sk, backlog) < 0) {
- close(sk);
- return -1;
- }
-
- return sk;
-}
-
-static int l2cap_accept(int sk, bdaddr_t *bdaddr)
-{
- struct sockaddr_l2 addr;
- socklen_t addrlen;
- int nsk;
-
- memset(&addr, 0, sizeof(addr));
- addrlen = sizeof(addr);
-
- if ((nsk = accept(sk, (struct sockaddr *) &addr, &addrlen)) < 0)
- return -1;
-
- if (bdaddr)
- bacpy(bdaddr, &addr.l2_bdaddr);
-
- return nsk;
-}
-
-static int request_authentication(bdaddr_t *src, bdaddr_t *dst)
-{
- struct hci_conn_info_req *cr;
- char addr[18];
- int err, dd, dev_id;
-
- ba2str(src, addr);
- dev_id = hci_devid(addr);
- if (dev_id < 0)
- return dev_id;
-
- dd = hci_open_dev(dev_id);
- if (dd < 0)
- return dd;
-
- cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info));
- if (!cr)
- return -ENOMEM;
-
- bacpy(&cr->bdaddr, dst);
- cr->type = ACL_LINK;
- err = ioctl(dd, HCIGETCONNINFO, (unsigned long) cr);
- if (err < 0) {
- free(cr);
- hci_close_dev(dd);
- return err;
- }
-
- err = hci_authenticate_link(dd, htobs(cr->conn_info->handle), 25000);
-
- free(cr);
- hci_close_dev(dd);
-
- return err;
-}
-
-static int request_encryption(bdaddr_t *src, bdaddr_t *dst)
-{
- struct hci_conn_info_req *cr;
- char addr[18];
- int err, dd, dev_id;
-
- ba2str(src, addr);
- dev_id = hci_devid(addr);
- if (dev_id < 0)
- return dev_id;
-
- dd = hci_open_dev(dev_id);
- if (dd < 0)
- return dd;
-
- cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info));
- if (!cr)
- return -ENOMEM;
-
- bacpy(&cr->bdaddr, dst);
- cr->type = ACL_LINK;
- err = ioctl(dd, HCIGETCONNINFO, (unsigned long) cr);
- if (err < 0) {
- free(cr);
- hci_close_dev(dd);
- return err;
- }
-
- err = hci_encrypt_link(dd, htobs(cr->conn_info->handle), 1, 25000);
-
- free(cr);
- hci_close_dev(dd);
-
- return err;
-}
-
-static void enable_sixaxis(int csk)
-{
- const unsigned char buf[] = {
- 0x53 /*HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE*/,
- 0xf4, 0x42, 0x03, 0x00, 0x00 };
- int err;
-
- err = write(csk, buf, sizeof(buf));
-}
-
-static int create_device(int ctl, int csk, int isk, uint8_t subclass, int nosdp, int nocheck, int bootonly, int encrypt, int timeout)
-{
- struct hidp_connadd_req req;
- struct sockaddr_l2 addr;
- socklen_t addrlen;
- bdaddr_t src, dst;
- char bda[18];
- int err;
-
- memset(&addr, 0, sizeof(addr));
- addrlen = sizeof(addr);
-
- if (getsockname(csk, (struct sockaddr *) &addr, &addrlen) < 0)
- return -1;
-
- bacpy(&src, &addr.l2_bdaddr);
-
- memset(&addr, 0, sizeof(addr));
- addrlen = sizeof(addr);
-
- if (getpeername(csk, (struct sockaddr *) &addr, &addrlen) < 0)
- return -1;
-
- bacpy(&dst, &addr.l2_bdaddr);
-
- memset(&req, 0, sizeof(req));
- req.ctrl_sock = csk;
- req.intr_sock = isk;
- req.flags = 0;
- req.idle_to = timeout * 60;
-
- err = get_stored_device_info(&src, &dst, &req);
- if (!err)
- goto create;
-
- if (!nocheck) {
- ba2str(&dst, bda);
- syslog(LOG_ERR, "Rejected connection from unknown device %s", bda);
- /* Return no error to avoid run_server() complaining too */
- return 0;
- }
-
- if (!nosdp) {
- err = get_sdp_device_info(&src, &dst, &req);
- if (err < 0)
- goto error;
- } else {
- struct l2cap_conninfo conn;
- socklen_t size;
- uint8_t class[3];
-
- memset(&conn, 0, sizeof(conn));
- size = sizeof(conn);
- if (getsockopt(csk, SOL_L2CAP, L2CAP_CONNINFO, &conn, &size) < 0)
- memset(class, 0, 3);
- else
- memcpy(class, conn.dev_class, 3);
-
- if (class[1] == 0x25 && (class[2] == 0x00 || class[2] == 0x01))
- req.subclass = class[0];
- else
- req.subclass = 0xc0;
- }
-
-create:
- if (subclass != 0x00)
- req.subclass = subclass;
-
- ba2str(&dst, bda);
- syslog(LOG_INFO, "New HID device %s (%s)", bda, req.name);
-
- if (encrypt && (req.subclass & 0x40)) {
- err = request_authentication(&src, &dst);
- if (err < 0) {
- syslog(LOG_ERR, "Authentication for %s failed", bda);
- goto error;
- }
-
- err = request_encryption(&src, &dst);
- if (err < 0)
- syslog(LOG_ERR, "Encryption for %s failed", bda);
- }
-
- if (bootonly) {
- req.rd_size = 0;
- req.flags |= (1 << HIDP_BOOT_PROTOCOL_MODE);
- }
-
- if (req.vendor == 0x054c && req.product == 0x0268)
- enable_sixaxis(csk);
-
- err = ioctl(ctl, HIDPCONNADD, &req);
-
-error:
- if (req.rd_data)
- free(req.rd_data);
-
- return err;
-}
-
-static void run_server(int ctl, int csk, int isk, uint8_t subclass, int nosdp, int nocheck, int bootonly, int encrypt, int timeout)
-{
- struct pollfd p[2];
- sigset_t sigs;
- short events;
- int err, ncsk, nisk;
-
- sigfillset(&sigs);
- sigdelset(&sigs, SIGCHLD);
- sigdelset(&sigs, SIGPIPE);
- sigdelset(&sigs, SIGTERM);
- sigdelset(&sigs, SIGINT);
- sigdelset(&sigs, SIGHUP);
-
- p[0].fd = csk;
- p[0].events = POLLIN | POLLERR | POLLHUP;
-
- p[1].fd = isk;
- p[1].events = POLLIN | POLLERR | POLLHUP;
-
- while (!__io_canceled) {
- p[0].revents = 0;
- p[1].revents = 0;
-
- if (ppoll(p, 2, NULL, &sigs) < 1)
- continue;
-
- events = p[0].revents | p[1].revents;
-
- if (events & POLLIN) {
- ncsk = l2cap_accept(csk, NULL);
- nisk = l2cap_accept(isk, NULL);
-
- err = create_device(ctl, ncsk, nisk, subclass, nosdp, nocheck, bootonly, encrypt, timeout);
- if (err < 0)
- syslog(LOG_ERR, "HID create error %d (%s)",
- errno, strerror(errno));
-
- close(nisk);
- sleep(1);
- close(ncsk);
- }
- }
-}
-
-static char *hidp_state[] = {
- "unknown",
- "connected",
- "open",
- "bound",
- "listening",
- "connecting",
- "connecting",
- "config",
- "disconnecting",
- "closed"
-};
-
-static char *hidp_flagstostr(uint32_t flags)
-{
- static char str[100];
- str[0] = 0;
-
- strcat(str, "[");
-
- if (flags & (1 << HIDP_BOOT_PROTOCOL_MODE))
- strcat(str, "boot-protocol");
-
- strcat(str, "]");
-
- return str;
-}
-
-static void do_show(int ctl)
-{
- struct hidp_connlist_req req;
- struct hidp_conninfo ci[16];
- char addr[18];
- int i;
-
- req.cnum = 16;
- req.ci = ci;
-
- if (ioctl(ctl, HIDPGETCONNLIST, &req) < 0) {
- perror("Can't get connection list");
- close(ctl);
- exit(1);
- }
-
- for (i = 0; i < req.cnum; i++) {
- ba2str(&ci[i].bdaddr, addr);
- printf("%s %s [%04x:%04x] %s %s\n", addr, ci[i].name,
- ci[i].vendor, ci[i].product, hidp_state[ci[i].state],
- ci[i].flags ? hidp_flagstostr(ci[i].flags) : "");
- }
-}
-
-static void do_connect(int ctl, bdaddr_t *src, bdaddr_t *dst, uint8_t subclass, int fakehid, int bootonly, int encrypt, int timeout)
-{
- struct hidp_connadd_req req;
- uint16_t uuid = HID_SVCLASS_ID;
- uint8_t channel = 0;
- char name[256];
- int csk, isk, err;
-
- memset(&req, 0, sizeof(req));
-
- err = get_sdp_device_info(src, dst, &req);
- if (err < 0 && fakehid)
- err = get_alternate_device_info(src, dst,
- &uuid, &channel, name, sizeof(name) - 1);
-
- if (err < 0) {
- perror("Can't get device information");
- close(ctl);
- exit(1);
- }
-
- switch (uuid) {
- case HID_SVCLASS_ID:
- goto connect;
-
- case SERIAL_PORT_SVCLASS_ID:
- if (subclass == 0x40 || !strcmp(name, "Cable Replacement")) {
- if (epox_presenter(src, dst, channel) < 0) {
- close(ctl);
- exit(1);
- }
- break;
- }
- if (subclass == 0x1f || !strcmp(name, "SPP slave")) {
- if (jthree_keyboard(src, dst, channel) < 0) {
- close(ctl);
- exit(1);
- }
- break;
- }
- if (subclass == 0x02 || !strcmp(name, "Serial Port")) {
- if (celluon_keyboard(src, dst, channel) < 0) {
- close(ctl);
- exit(1);
- }
- break;
- }
- break;
-
- case HEADSET_SVCLASS_ID:
- case HANDSFREE_SVCLASS_ID:
- if (headset_presenter(src, dst, channel) < 0) {
- close(ctl);
- exit(1);
- }
- break;
- }
-
- return;
-
-connect:
- csk = l2cap_connect(src, dst, L2CAP_PSM_HIDP_CTRL);
- if (csk < 0) {
- perror("Can't create HID control channel");
- close(ctl);
- exit(1);
- }
-
- isk = l2cap_connect(src, dst, L2CAP_PSM_HIDP_INTR);
- if (isk < 0) {
- perror("Can't create HID interrupt channel");
- close(csk);
- close(ctl);
- exit(1);
- }
-
- err = create_device(ctl, csk, isk, subclass, 1, 1, bootonly, encrypt, timeout);
- if (err < 0) {
- fprintf(stderr, "HID create error %d (%s)\n",
- errno, strerror(errno));
- close(isk);
- sleep(1);
- close(csk);
- close(ctl);
- exit(1);
- }
-}
-
-static void do_search(int ctl, bdaddr_t *bdaddr, uint8_t subclass, int fakehid, int bootonly, int encrypt, int timeout)
-{
- inquiry_info *info = NULL;
- bdaddr_t src, dst;
- int i, dev_id, num_rsp, length, flags;
- char addr[18];
- uint8_t class[3];
-
- ba2str(bdaddr, addr);
- dev_id = hci_devid(addr);
- if (dev_id < 0) {
- dev_id = hci_get_route(NULL);
- hci_devba(dev_id, &src);
- } else
- bacpy(&src, bdaddr);
-
- length = 8; /* ~10 seconds */
- num_rsp = 0;
- flags = IREQ_CACHE_FLUSH;
-
- printf("Searching ...\n");
-
- num_rsp = hci_inquiry(dev_id, length, num_rsp, NULL, &info, flags);
-
- for (i = 0; i < num_rsp; i++) {
- memcpy(class, (info+i)->dev_class, 3);
- if (class[1] == 0x25 && (class[2] == 0x00 || class[2] == 0x01)) {
- bacpy(&dst, &(info+i)->bdaddr);
- ba2str(&dst, addr);
-
- printf("\tConnecting to device %s\n", addr);
- do_connect(ctl, &src, &dst, subclass, fakehid, bootonly, encrypt, timeout);
- }
- }
-
- if (!fakehid)
- goto done;
-
- for (i = 0; i < num_rsp; i++) {
- memcpy(class, (info+i)->dev_class, 3);
- if ((class[0] == 0x00 && class[2] == 0x00 &&
- (class[1] == 0x40 || class[1] == 0x1f)) ||
- (class[0] == 0x10 && class[1] == 0x02 && class[2] == 0x40)) {
- bacpy(&dst, &(info+i)->bdaddr);
- ba2str(&dst, addr);
-
- printf("\tConnecting to device %s\n", addr);
- do_connect(ctl, &src, &dst, subclass, 1, bootonly, 0, timeout);
- }
- }
-
-done:
- bt_free(info);
-
- if (!num_rsp) {
- fprintf(stderr, "\tNo devices in range or visible\n");
- close(ctl);
- exit(1);
- }
-}
-
-static void do_kill(int ctl, bdaddr_t *bdaddr, uint32_t flags)
-{
- struct hidp_conndel_req req;
- struct hidp_connlist_req cl;
- struct hidp_conninfo ci[16];
- int i;
-
- if (!bacmp(bdaddr, BDADDR_ALL)) {
- cl.cnum = 16;
- cl.ci = ci;
-
- if (ioctl(ctl, HIDPGETCONNLIST, &cl) < 0) {
- perror("Can't get connection list");
- close(ctl);
- exit(1);
- }
-
- for (i = 0; i < cl.cnum; i++) {
- bacpy(&req.bdaddr, &ci[i].bdaddr);
- req.flags = flags;
-
- if (ioctl(ctl, HIDPCONNDEL, &req) < 0) {
- perror("Can't release connection");
- close(ctl);
- exit(1);
- }
- }
-
- } else {
- bacpy(&req.bdaddr, bdaddr);
- req.flags = flags;
-
- if (ioctl(ctl, HIDPCONNDEL, &req) < 0) {
- perror("Can't release connection");
- close(ctl);
- exit(1);
- }
- }
-}
-
-static void usage(void)
-{
- printf("hidd - Bluetooth HID daemon version %s\n\n", VERSION);
-
- printf("Usage:\n"
- "\thidd [options] [commands]\n"
- "\n");
-
- printf("Options:\n"
- "\t-i <hciX|bdaddr> Local HCI device or BD Address\n"
- "\t-t <timeout> Set idle timeout (in minutes)\n"
- "\t-b <subclass> Overwrite the boot mode subclass\n"
- "\t-n, --nodaemon Don't fork daemon to background\n"
- "\t-h, --help Display help\n"
- "\n");
-
- printf("Commands:\n"
- "\t--server Start HID server\n"
- "\t--search Search for HID devices\n"
- "\t--connect <bdaddr> Connect remote HID device\n"
- "\t--unplug <bdaddr> Unplug the HID connection\n"
- "\t--kill <bdaddr> Terminate HID connection\n"
- "\t--killall Terminate all connections\n"
- "\t--show List current HID connections\n"
- "\n");
-}
-
-static struct option main_options[] = {
- { "help", 0, 0, 'h' },
- { "nodaemon", 0, 0, 'n' },
- { "subclass", 1, 0, 'b' },
- { "timeout", 1, 0, 't' },
- { "device", 1, 0, 'i' },
- { "master", 0, 0, 'M' },
- { "encrypt", 0, 0, 'E' },
- { "nosdp", 0, 0, 'D' },
- { "nocheck", 0, 0, 'Z' },
- { "bootonly", 0, 0, 'B' },
- { "hidonly", 0, 0, 'H' },
- { "show", 0, 0, 'l' },
- { "list", 0, 0, 'l' },
- { "server", 0, 0, 'd' },
- { "listen", 0, 0, 'd' },
- { "search", 0, 0, 's' },
- { "create", 1, 0, 'c' },
- { "connect", 1, 0, 'c' },
- { "disconnect", 1, 0, 'k' },
- { "terminate", 1, 0, 'k' },
- { "release", 1, 0, 'k' },
- { "kill", 1, 0, 'k' },
- { "killall", 0, 0, 'K' },
- { "unplug", 1, 0, 'u' },
- { 0, 0, 0, 0 }
-};
-
-int main(int argc, char *argv[])
-{
- struct sigaction sa;
- bdaddr_t bdaddr, dev;
- uint32_t flags = 0;
- uint8_t subclass = 0x00;
- char addr[18];
- int log_option = LOG_NDELAY | LOG_PID;
- int opt, ctl, csk, isk;
- int mode = SHOW, detach = 1, nosdp = 0, nocheck = 0, bootonly = 0;
- int fakehid = 1, encrypt = 0, timeout = 30, lm = 0;
-
- bacpy(&bdaddr, BDADDR_ANY);
-
- while ((opt = getopt_long(argc, argv, "+i:nt:b:MEDZBHldsc:k:Ku:h", main_options, NULL)) != -1) {
- switch(opt) {
- case 'i':
- if (!strncasecmp(optarg, "hci", 3))
- hci_devba(atoi(optarg + 3), &bdaddr);
- else
- str2ba(optarg, &bdaddr);
- break;
- case 'n':
- detach = 0;
- break;
- case 't':
- timeout = atoi(optarg);
- break;
- case 'b':
- if (!strncasecmp(optarg, "0x", 2))
- subclass = (uint8_t) strtol(optarg, NULL, 16);
- else
- subclass = atoi(optarg);
- break;
- case 'M':
- lm |= L2CAP_LM_MASTER;
- break;
- case 'E':
- encrypt = 1;
- break;
- case 'D':
- nosdp = 1;
- break;
- case 'Z':
- nocheck = 1;
- break;
- case 'B':
- bootonly = 1;
- break;
- case 'H':
- fakehid = 0;
- break;
- case 'l':
- mode = SHOW;
- break;
- case 'd':
- mode = SERVER;
- break;
- case 's':
- mode = SEARCH;
- break;
- case 'c':
- str2ba(optarg, &dev);
- mode = CONNECT;
- break;
- case 'k':
- str2ba(optarg, &dev);
- mode = KILL;
- break;
- case 'K':
- bacpy(&dev, BDADDR_ALL);
- mode = KILL;
- break;
- case 'u':
- str2ba(optarg, &dev);
- flags = (1 << HIDP_VIRTUAL_CABLE_UNPLUG);
- mode = KILL;
- break;
- case 'h':
- usage();
- exit(0);
- default:
- exit(0);
- }
- }
-
- ba2str(&bdaddr, addr);
-
- ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HIDP);
- if (ctl < 0) {
- perror("Can't open HIDP control socket");
- exit(1);
- }
-
- switch (mode) {
- case SERVER:
- csk = l2cap_listen(&bdaddr, L2CAP_PSM_HIDP_CTRL, lm, 10);
- if (csk < 0) {
- perror("Can't listen on HID control channel");
- close(ctl);
- exit(1);
- }
-
- isk = l2cap_listen(&bdaddr, L2CAP_PSM_HIDP_INTR, lm, 10);
- if (isk < 0) {
- perror("Can't listen on HID interrupt channel");
- close(ctl);
- close(csk);
- exit(1);
- }
- break;
-
- case SEARCH:
- do_search(ctl, &bdaddr, subclass, fakehid, bootonly, encrypt, timeout);
- close(ctl);
- exit(0);
-
- case CONNECT:
- do_connect(ctl, &bdaddr, &dev, subclass, fakehid, bootonly, encrypt, timeout);
- close(ctl);
- exit(0);
-
- case KILL:
- do_kill(ctl, &dev, flags);
- close(ctl);
- exit(0);
-
- default:
- do_show(ctl);
- close(ctl);
- exit(0);
- }
-
- if (detach) {
- if (daemon(0, 0)) {
- perror("Can't start daemon");
- exit(1);
- }
- } else
- log_option |= LOG_PERROR;
-
- openlog("hidd", log_option, LOG_DAEMON);
-
- if (bacmp(&bdaddr, BDADDR_ANY))
- syslog(LOG_INFO, "Bluetooth HID daemon (%s)", addr);
- else
- syslog(LOG_INFO, "Bluetooth HID daemon");
-
- memset(&sa, 0, sizeof(sa));
- sa.sa_flags = SA_NOCLDSTOP;
-
- sa.sa_handler = sig_term;
- sigaction(SIGTERM, &sa, NULL);
- sigaction(SIGINT, &sa, NULL);
- sa.sa_handler = sig_hup;
- sigaction(SIGHUP, &sa, NULL);
-
- sa.sa_handler = SIG_IGN;
- sigaction(SIGCHLD, &sa, NULL);
- sigaction(SIGPIPE, &sa, NULL);
-
- run_server(ctl, csk, isk, subclass, nosdp, nocheck, bootonly, encrypt, timeout);
-
- syslog(LOG_INFO, "Exit");
-
- close(csk);
- close(isk);
- close(ctl);
-
- return 0;
-}
diff --git a/hidd/sdp.c b/hidd/sdp.c
deleted file mode 100644
index eaf8c136..00000000
--- a/hidd/sdp.c
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2003-2008 Marcel Holtmann <marcel@holtmann.org>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/param.h>
-#include <sys/socket.h>
-
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/l2cap.h>
-#include <bluetooth/sdp.h>
-#include <bluetooth/sdp_lib.h>
-#include <bluetooth/hidp.h>
-
-#include "textfile.h"
-#include "hidd.h"
-
-static void epox_endian_quirk(unsigned char *data, int size)
-{
- /* USAGE_PAGE (Keyboard) 05 07
- * USAGE_MINIMUM (0) 19 00
- * USAGE_MAXIMUM (65280) 2A 00 FF <= must be FF 00
- * LOGICAL_MINIMUM (0) 15 00
- * LOGICAL_MAXIMUM (65280) 26 00 FF <= must be FF 00
- */
- unsigned char pattern[] = { 0x05, 0x07, 0x19, 0x00, 0x2a, 0x00, 0xff,
- 0x15, 0x00, 0x26, 0x00, 0xff };
- int i;
-
- if (!data)
- return;
-
- for (i = 0; i < size - sizeof(pattern); i++) {
- if (!memcmp(data + i, pattern, sizeof(pattern))) {
- data[i + 5] = 0xff;
- data[i + 6] = 0x00;
- data[i + 10] = 0xff;
- data[i + 11] = 0x00;
- }
- }
-}
-
-static int store_device_info(const bdaddr_t *src, const bdaddr_t *dst, struct hidp_connadd_req *req)
-{
- char filename[PATH_MAX + 1], addr[18], *str, *desc;
- int i, err, size;
-
- ba2str(src, addr);
- create_name(filename, PATH_MAX, STORAGEDIR, addr, "hidd");
-
- size = 15 + 3 + 3 + 5 + (req->rd_size * 2) + 1 + 9 + strlen(req->name) + 2;
- str = malloc(size);
- if (!str)
- return -ENOMEM;
-
- desc = malloc((req->rd_size * 2) + 1);
- if (!desc) {
- free(str);
- return -ENOMEM;
- }
-
- memset(desc, 0, (req->rd_size * 2) + 1);
- for (i = 0; i < req->rd_size; i++)
- sprintf(desc + (i * 2), "%2.2X", req->rd_data[i]);
-
- snprintf(str, size - 1, "%04X:%04X:%04X %02X %02X %04X %s %08X %s",
- req->vendor, req->product, req->version,
- req->subclass, req->country, req->parser, desc,
- req->flags, req->name);
-
- free(desc);
-
- create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
-
- ba2str(dst, addr);
- err = textfile_put(filename, addr, str);
-
- free(str);
-
- return err;
-}
-
-int get_stored_device_info(const bdaddr_t *src, const bdaddr_t *dst, struct hidp_connadd_req *req)
-{
- char filename[PATH_MAX + 1], addr[18], tmp[3], *str, *desc;
- unsigned int vendor, product, version, subclass, country, parser, pos;
- int i;
-
- desc = malloc(4096);
- if (!desc)
- return -ENOMEM;
-
- memset(desc, 0, 4096);
-
- ba2str(src, addr);
- create_name(filename, PATH_MAX, STORAGEDIR, addr, "hidd");
-
- ba2str(dst, addr);
- str = textfile_get(filename, addr);
- if (!str) {
- free(desc);
- return -EIO;
- }
-
- sscanf(str, "%04X:%04X:%04X %02X %02X %04X %4095s %08X %n",
- &vendor, &product, &version, &subclass, &country,
- &parser, desc, &req->flags, &pos);
-
- free(str);
-
- req->vendor = vendor;
- req->product = product;
- req->version = version;
- req->subclass = subclass;
- req->country = country;
- req->parser = parser;
-
- snprintf(req->name, 128, str + pos);
-
- req->rd_size = strlen(desc) / 2;
- req->rd_data = malloc(req->rd_size);
- if (!req->rd_data) {
- free(desc);
- return -ENOMEM;
- }
-
- memset(tmp, 0, sizeof(tmp));
- for (i = 0; i < req->rd_size; i++) {
- memcpy(tmp, desc + (i * 2), 2);
- req->rd_data[i] = (uint8_t) strtol(tmp, NULL, 16);
- }
-
- free(desc);
-
- return 0;
-}
-
-int get_sdp_device_info(const bdaddr_t *src, const bdaddr_t *dst, struct hidp_connadd_req *req)
-{
- struct sockaddr_l2 addr;
- socklen_t addrlen;
- bdaddr_t bdaddr;
- uint32_t range = 0x0000ffff;
- sdp_session_t *s;
- sdp_list_t *search, *attrid, *pnp_rsp, *hid_rsp;
- sdp_record_t *rec;
- sdp_data_t *pdlist, *pdlist2;
- uuid_t svclass;
- int err;
-
- s = sdp_connect(src, dst, SDP_RETRY_IF_BUSY | SDP_WAIT_ON_CLOSE);
- if (!s)
- return -1;
-
- sdp_uuid16_create(&svclass, PNP_INFO_SVCLASS_ID);
- search = sdp_list_append(NULL, &svclass);
- attrid = sdp_list_append(NULL, &range);
-
- err = sdp_service_search_attr_req(s, search,
- SDP_ATTR_REQ_RANGE, attrid, &pnp_rsp);
-
- sdp_list_free(search, NULL);
- sdp_list_free(attrid, NULL);
-
- sdp_uuid16_create(&svclass, HID_SVCLASS_ID);
- search = sdp_list_append(NULL, &svclass);
- attrid = sdp_list_append(NULL, &range);
-
- err = sdp_service_search_attr_req(s, search,
- SDP_ATTR_REQ_RANGE, attrid, &hid_rsp);
-
- sdp_list_free(search, NULL);
- sdp_list_free(attrid, NULL);
-
- memset(&addr, 0, sizeof(addr));
- addrlen = sizeof(addr);
-
- if (getsockname(s->sock, (struct sockaddr *) &addr, &addrlen) < 0)
- bacpy(&bdaddr, src);
- else
- bacpy(&bdaddr, &addr.l2_bdaddr);
-
- sdp_close(s);
-
- if (err || !hid_rsp)
- return -1;
-
- if (pnp_rsp) {
- rec = (sdp_record_t *) pnp_rsp->data;
-
- pdlist = sdp_data_get(rec, 0x0201);
- req->vendor = pdlist ? pdlist->val.uint16 : 0x0000;
-
- pdlist = sdp_data_get(rec, 0x0202);
- req->product = pdlist ? pdlist->val.uint16 : 0x0000;
-
- pdlist = sdp_data_get(rec, 0x0203);
- req->version = pdlist ? pdlist->val.uint16 : 0x0000;
-
- sdp_record_free(rec);
- }
-
- rec = (sdp_record_t *) hid_rsp->data;
-
- pdlist = sdp_data_get(rec, 0x0101);
- pdlist2 = sdp_data_get(rec, 0x0102);
- if (pdlist) {
- if (pdlist2) {
- if (strncmp(pdlist->val.str, pdlist2->val.str, 5)) {
- strncpy(req->name, pdlist2->val.str, sizeof(req->name) - 1);
- strcat(req->name, " ");
- }
- strncat(req->name, pdlist->val.str,
- sizeof(req->name) - strlen(req->name));
- } else
- strncpy(req->name, pdlist->val.str, sizeof(req->name));
- } else {
- pdlist2 = sdp_data_get(rec, 0x0100);
- if (pdlist2)
- strncpy(req->name, pdlist2->val.str, sizeof(req->name));
- }
-
- pdlist = sdp_data_get(rec, 0x0201);
- req->parser = pdlist ? pdlist->val.uint16 : 0x0100;
-
- pdlist = sdp_data_get(rec, 0x0202);
- req->subclass = pdlist ? pdlist->val.uint8 : 0;
-
- pdlist = sdp_data_get(rec, 0x0203);
- req->country = pdlist ? pdlist->val.uint8 : 0;
-
- pdlist = sdp_data_get(rec, 0x0206);
- if (pdlist) {
- pdlist = pdlist->val.dataseq;
- pdlist = pdlist->val.dataseq;
- pdlist = pdlist->next;
-
- req->rd_data = malloc(pdlist->unitSize);
- if (req->rd_data) {
- memcpy(req->rd_data, (unsigned char *) pdlist->val.str, pdlist->unitSize);
- req->rd_size = pdlist->unitSize;
- epox_endian_quirk(req->rd_data, req->rd_size);
- }
- }
-
- sdp_record_free(rec);
-
- if (bacmp(&bdaddr, BDADDR_ANY))
- store_device_info(&bdaddr, dst, req);
-
- return 0;
-}
-
-int get_alternate_device_info(const bdaddr_t *src, const bdaddr_t *dst, uint16_t *uuid, uint8_t *channel, char *name, size_t len)
-{
- uint16_t attr1 = SDP_ATTR_PROTO_DESC_LIST;
- uint16_t attr2 = SDP_ATTR_SVCNAME_PRIMARY;
- sdp_session_t *s;
- sdp_list_t *search, *attrid, *rsp;
- uuid_t svclass;
- int err;
-
- s = sdp_connect(src, dst, SDP_RETRY_IF_BUSY | SDP_WAIT_ON_CLOSE);
- if (!s)
- return -1;
-
- sdp_uuid16_create(&svclass, HEADSET_SVCLASS_ID);
- search = sdp_list_append(NULL, &svclass);
- attrid = sdp_list_append(NULL, &attr1);
- attrid = sdp_list_append(attrid, &attr2);
-
- err = sdp_service_search_attr_req(s, search,
- SDP_ATTR_REQ_INDIVIDUAL, attrid, &rsp);
-
- sdp_list_free(search, NULL);
- sdp_list_free(attrid, NULL);
-
- if (err <= 0) {
- sdp_uuid16_create(&svclass, SERIAL_PORT_SVCLASS_ID);
- search = sdp_list_append(NULL, &svclass);
- attrid = sdp_list_append(NULL, &attr1);
- attrid = sdp_list_append(attrid, &attr2);
-
- err = sdp_service_search_attr_req(s, search,
- SDP_ATTR_REQ_INDIVIDUAL, attrid, &rsp);
-
- sdp_list_free(search, NULL);
- sdp_list_free(attrid, NULL);
-
- if (err < 0) {
- sdp_close(s);
- return err;
- }
-
- if (uuid)
- *uuid = SERIAL_PORT_SVCLASS_ID;
- } else {
- if (uuid)
- *uuid = HEADSET_SVCLASS_ID;
- }
-
- sdp_close(s);
-
- for (; rsp; rsp = rsp->next) {
- sdp_record_t *rec = (sdp_record_t *) rsp->data;
- sdp_list_t *protos;
-
- sdp_get_service_name(rec, name, len);
-
- if (!sdp_get_access_protos(rec, &protos)) {
- uint8_t ch = sdp_get_proto_port(protos, RFCOMM_UUID);
- if (ch > 0) {
- if (channel)
- *channel = ch;
- return 0;
- }
- }
-
- sdp_record_free(rec);
- }
-
- return -EIO;
-}