diff options
Diffstat (limited to 'hidd')
| -rw-r--r-- | hidd/Makefile.am | 22 | ||||
| -rw-r--r-- | hidd/fakehid.c | 669 | ||||
| -rw-r--r-- | hidd/fakehid.txt | 134 | ||||
| -rw-r--r-- | hidd/hidd.1 | 41 | ||||
| -rw-r--r-- | hidd/hidd.h | 34 | ||||
| -rw-r--r-- | hidd/main.c | 860 | ||||
| -rw-r--r-- | hidd/sdp.c | 352 | 
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; -} | 
