diff options
| -rw-r--r-- | hidd/fakehid.c | 303 | ||||
| -rw-r--r-- | hidd/hidd.h | 3 | ||||
| -rw-r--r-- | hidd/main.c | 20 | ||||
| -rw-r--r-- | hidd/sdp.c | 13 | 
4 files changed, 226 insertions, 113 deletions
| diff --git a/hidd/fakehid.c b/hidd/fakehid.c index be1f29b9..3a1c0d6e 100644 --- a/hidd/fakehid.c +++ b/hidd/fakehid.c @@ -49,7 +49,18 @@  #include "ppoll.h"  #endif -static void event(int fd, uint16_t type, uint16_t code, int32_t value) +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; @@ -65,6 +76,110 @@ static void event(int fd, uint16_t type, uint16_t code, int32_t 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)  {  } @@ -81,14 +196,14 @@ static void button(int fd, unsigned int button, int is_press)  {  	switch (button) {  	case 1: -		event(fd, EV_KEY, BTN_LEFT, is_press); +		send_event(fd, EV_KEY, BTN_LEFT, is_press);  		break;  	case 3: -		event(fd, EV_KEY, BTN_RIGHT, is_press); +		send_event(fd, EV_KEY, BTN_RIGHT, is_press);  		break;  	} -	event(fd, EV_SYN, SYN_REPORT, 0); +	send_event(fd, EV_SYN, SYN_REPORT, 0);  }  static void move(int fd, unsigned int direction) @@ -100,13 +215,13 @@ static void move(int fd, unsigned int direction)  	x = (int) (sin(angle) * 8);  	y = (int) (cos(angle) * -8); -	event(fd, EV_REL, REL_X, x); -	event(fd, EV_REL, REL_Y, y); +	send_event(fd, EV_REL, REL_X, x); +	send_event(fd, EV_REL, REL_Y, y); -	event(fd, EV_SYN, SYN_REPORT, 0); +	send_event(fd, EV_SYN, SYN_REPORT, 0);  } -static void epox_decode(int fd, unsigned char event) +static inline void epox_decode(int fd, unsigned char event)  {  	switch (event) {  	case 48: @@ -167,122 +282,108 @@ static void epox_decode(int fd, unsigned char event)  	}  } -static int uinput_create(char *name, int keyboard, int mouse) +int epox_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel)  { -	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)", -							strerror(errno), errno); -				return -1; -			} -		} -	} - -	memset(&dev, 0, sizeof(dev)); - -	if (name) -		strncpy(dev.name, name, UINPUT_MAX_NAME_SIZE); +	unsigned char buf[16]; +	struct sigaction sa; +	struct pollfd p; +	sigset_t sigs; +	char addr[18]; +	int i, fd, sk, len; -	dev.id.bustype = BUS_BLUETOOTH; -	dev.id.vendor  = 0x0000; -	dev.id.product = 0x0000; -	dev.id.version = 0x0000; +	sk = rfcomm_connect(src, dst, channel); +	if (sk < 0) +		return -1; -	if (write(fd, &dev, sizeof(dev)) < 0) { -		fprintf(stderr, "Can't write device information: %s (%d)", -							strerror(errno), errno); -		close(fd); +	fd = uinput_create("Bluetooth Presenter", 0, 1); +	if (fd < 0) { +		close(sk);  		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); -	} +	ba2str(dst, addr); -	if (keyboard) { -		ioctl(fd, UI_SET_EVBIT, EV_KEY); -		ioctl(fd, UI_SET_EVBIT, EV_LED); -		ioctl(fd, UI_SET_EVBIT, EV_REP); +	printf("Connected to %s on channel %d\n", addr, channel); +	printf("Press CTRL-C for hangup\n"); -		for (aux = KEY_RESERVED; aux <= KEY_UNKNOWN; aux++) -			ioctl(fd, UI_SET_KEYBIT, aux); +	memset(&sa, 0, sizeof(sa)); +	sa.sa_flags   = SA_NOCLDSTOP; +	sa.sa_handler = SIG_IGN; +	sigaction(SIGCHLD, &sa, NULL); +	sigaction(SIGPIPE, &sa, NULL); -		//for (aux = LED_NUML; aux <= LED_MISC; aux++) -		//	ioctl(fd, UI_SET_LEDBIT, aux); -	} +	sa.sa_handler = sig_term; +	sigaction(SIGTERM, &sa, NULL); +	sigaction(SIGINT,  &sa, NULL); -	if (mouse) { -		ioctl(fd, UI_SET_EVBIT, EV_KEY); +	sa.sa_handler = sig_hup; +	sigaction(SIGHUP, &sa, NULL); -		for (aux = BTN_LEFT; aux <= BTN_BACK; aux++) -			ioctl(fd, UI_SET_KEYBIT, aux); -	} +	sigfillset(&sigs); +	sigdelset(&sigs, SIGCHLD); +	sigdelset(&sigs, SIGPIPE); +	sigdelset(&sigs, SIGTERM); +	sigdelset(&sigs, SIGINT); +	sigdelset(&sigs, SIGHUP); -	ioctl(fd, UI_DEV_CREATE); +	p.fd = sk; +	p.events = POLLIN | POLLERR | POLLHUP; -	return fd; -} +	while (!__io_canceled) { +		p.revents = 0; +		if (ppoll(&p, 1, NULL, &sigs) < 1) +			continue; -static int rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel) -{ -	struct sockaddr_rc addr; -	int sk; +		len = read(sk, buf, sizeof(buf)); +		if (len < 0) +			break; -	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; +		for (i = 0; i < len; i++) +			epox_decode(fd, buf[i]);  	} -	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; -	} +	printf("Disconnected\n"); -	memset(&addr, 0, sizeof(addr)); -	addr.rc_family = AF_BLUETOOTH; -	bacpy(&addr.rc_bdaddr, dst); -	addr.rc_channel = channel; +	ioctl(fd, UI_DEV_DESTROY); -	if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { -		fprintf(stderr, "Can't connect: %s (%d)\n", -							strerror(errno), errno); -		close(sk); -		return -1; -	} +	close(fd); +	close(sk); -	return sk; +	return 0;  } -static volatile sig_atomic_t __io_canceled = 0; - -static void sig_hup(int sig) +int headset_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel)  { +	printf("Not implemented\n"); +	return -1;  } -static void sig_term(int sig) +/* 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)  { -	__io_canceled = 1; +	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 epox_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)  {  	unsigned char buf[16];  	struct sigaction sa; @@ -295,7 +396,7 @@ int epox_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel)  	if (sk < 0)  		return -1; -	fd = uinput_create("Bluetooth Presenter", 0, 1); +	fd = uinput_create("J-Three Keyboard", 1, 0);  	if (fd < 0) {  		close(sk);  		return -1; @@ -339,7 +440,7 @@ int epox_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel)  			break;  		for (i = 0; i < len; i++) -			epox_decode(fd, buf[i]); +			jthree_decode(fd, buf[i]);  	}  	printf("Disconnected\n"); @@ -351,9 +452,3 @@ int epox_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel)  	return 0;  } - -int headset_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel) -{ -	printf("Not implemented\n"); -	return -1; -} diff --git a/hidd/hidd.h b/hidd/hidd.h index afc65be1..bbbc952b 100644 --- a/hidd/hidd.h +++ b/hidd/hidd.h @@ -26,7 +26,8 @@  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); +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); diff --git a/hidd/main.c b/hidd/main.c index 7c478030..816c7ca6 100644 --- a/hidd/main.c +++ b/hidd/main.c @@ -431,13 +431,15 @@ static void do_connect(int ctl, bdaddr_t *src, bdaddr_t *dst, uint8_t subclass,  	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); +		err = get_alternate_device_info(src, dst, +				&uuid, &channel, name, sizeof(name) - 1);  	if (err < 0) {  		perror("Can't get device information"); @@ -450,9 +452,19 @@ static void do_connect(int ctl, bdaddr_t *src, bdaddr_t *dst, uint8_t subclass,  		goto connect;  	case SERIAL_PORT_SVCLASS_ID: -		if (epox_presenter(src, dst, channel) < 0) { -			close(ctl); -			exit(1); +		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;  		}  		break; @@ -271,9 +271,10 @@ int get_sdp_device_info(const bdaddr_t *src, const bdaddr_t *dst, struct hidp_co  	return 0;  } -int get_alternate_device_info(const bdaddr_t *src, const bdaddr_t *dst, uint16_t *uuid, uint8_t *channel) +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 attr = SDP_ATTR_PROTO_DESC_LIST; +	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; @@ -285,7 +286,8 @@ int get_alternate_device_info(const bdaddr_t *src, const bdaddr_t *dst, uint16_t  	sdp_uuid16_create(&svclass, HEADSET_SVCLASS_ID);  	search = sdp_list_append(NULL, &svclass); -	attrid = sdp_list_append(NULL, &attr); +	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); @@ -296,7 +298,8 @@ int get_alternate_device_info(const bdaddr_t *src, const bdaddr_t *dst, uint16_t  	if (err <= 0) {  		sdp_uuid16_create(&svclass, SERIAL_PORT_SVCLASS_ID);  		search = sdp_list_append(NULL, &svclass); -		attrid = sdp_list_append(NULL, &attr); +		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); @@ -322,6 +325,8 @@ int get_alternate_device_info(const bdaddr_t *src, const bdaddr_t *dst, uint16_t  		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) { | 
