From 3e9d510274d6560e026c76dc3ecf415db0dd7e68 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 14 Nov 2005 12:18:09 +0000 Subject: Add initial fake HID support --- hidd/fakehid.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 hidd/fakehid.c (limited to 'hidd/fakehid.c') diff --git a/hidd/fakehid.c b/hidd/fakehid.c new file mode 100644 index 00000000..1483f022 --- /dev/null +++ b/hidd/fakehid.c @@ -0,0 +1,49 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2003-2005 Marcel Holtmann + * + * + * 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 +#endif + +#include +#include +#include + +#include +#include +#include + +#include "hidd.h" + +#include +#include + +#include + +void epox_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel) +{ +} + +void headset_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel) +{ +} -- cgit From d7cde36719252eaab14fad2d2c094bb6e7003059 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 9 Dec 2005 11:43:09 +0000 Subject: Add support for the old RFCOMM based EPoX presenter --- hidd/fakehid.c | 296 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 293 insertions(+), 3 deletions(-) (limited to 'hidd/fakehid.c') diff --git a/hidd/fakehid.c b/hidd/fakehid.c index 1483f022..b9fbc200 100644 --- a/hidd/fakehid.c +++ b/hidd/fakehid.c @@ -27,6 +27,12 @@ #include #include +#include +#include +#include +#include +#include +#include #include #include @@ -34,16 +40,300 @@ #include #include "hidd.h" - -#include -#include +#include "uinput.h" #include +static void event(int fd, uint16_t type, uint16_t code, int32_t value) +{ + struct uinput_event event; + + if (fd <= fileno(stderr)) + return; + + memset(&event, 0, sizeof(event)); + event.type = type; + event.code = code; + event.value = value; + + write(fd, &event, sizeof(event)); +} + +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: + event(fd, EV_KEY, BTN_LEFT, is_press); + break; + case 3: + event(fd, EV_KEY, BTN_RIGHT, is_press); + break; + } + + 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); + + event(fd, EV_REL, REL_X, x); + event(fd, EV_REL, REL_Y, y); + + event(fd, EV_SYN, SYN_REPORT, 0); +} + +static 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; + } +} + +static int uinput_create(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)", + strerror(errno), errno); + return -1; + } + } + } + + memset(&dev, 0, sizeof(dev)); + strncpy(dev.name, "Bluetooth FakeHID", 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)", + 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 volatile sig_atomic_t __io_canceled = 0; + +static void sig_hup(int sig) +{ +} + +static void sig_term(int sig) +{ + __io_canceled = 1; +} + void epox_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel) { + unsigned char buf[16]; + struct sigaction sa; + struct pollfd p; + char addr[18]; + int i, fd, sk, len; + + sk = rfcomm_connect(src, dst, channel); + if (sk < 0) + return; + + fd = uinput_create(1, 1); + if (fd < 0) { + close(sk); + return; + } + + 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); + + p.fd = sk; + p.events = POLLIN | POLLERR | POLLHUP; + + while (!__io_canceled) { + p.revents = 0; + if (poll(&p, 1, 100) < 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); } void headset_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel) { + printf("Not implemented\n"); } -- cgit From 9f80ae2025e4d14059ac313b678e7457e5c506aa Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 9 Dec 2005 12:05:13 +0000 Subject: Support different device names --- hidd/fakehid.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'hidd/fakehid.c') diff --git a/hidd/fakehid.c b/hidd/fakehid.c index b9fbc200..61f33ce8 100644 --- a/hidd/fakehid.c +++ b/hidd/fakehid.c @@ -161,7 +161,7 @@ static void epox_decode(int fd, unsigned char event) } } -static int uinput_create(int keyboard, int mouse) +static int uinput_create(char *name, int keyboard, int mouse) { struct uinput_dev dev; int fd, aux; @@ -180,9 +180,12 @@ static int uinput_create(int keyboard, int mouse) } memset(&dev, 0, sizeof(dev)); - strncpy(dev.name, "Bluetooth FakeHID", UINPUT_MAX_NAME_SIZE); + + if (name) + strncpy(dev.name, name, UINPUT_MAX_NAME_SIZE); + dev.id.bustype = BUS_BLUETOOTH; - dev.id.vendor = 0x0000; + dev.id.vendor = 0x0000; dev.id.product = 0x0000; dev.id.version = 0x0000; @@ -285,7 +288,7 @@ void epox_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel) if (sk < 0) return; - fd = uinput_create(1, 1); + fd = uinput_create("Bluetooth Presenter", 0, 1); if (fd < 0) { close(sk); return; -- cgit From f2e48c44a7e4c9ee31b8ce2e302186f6047cfeab Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 3 Jan 2006 13:28:56 +0000 Subject: Update copyright information --- hidd/fakehid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'hidd/fakehid.c') diff --git a/hidd/fakehid.c b/hidd/fakehid.c index 61f33ce8..0d87335b 100644 --- a/hidd/fakehid.c +++ b/hidd/fakehid.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2003-2005 Marcel Holtmann + * Copyright (C) 2003-2006 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify -- cgit From b102348e988e4abc5d579ce13c067ce2c885aaf7 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 26 Jul 2006 13:32:44 +0000 Subject: Fix declared with attribute warn_unused_result errors --- hidd/fakehid.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'hidd/fakehid.c') diff --git a/hidd/fakehid.c b/hidd/fakehid.c index 0d87335b..138d2b48 100644 --- a/hidd/fakehid.c +++ b/hidd/fakehid.c @@ -47,6 +47,7 @@ static void event(int fd, uint16_t type, uint16_t code, int32_t value) { struct uinput_event event; + int len; if (fd <= fileno(stderr)) return; @@ -56,7 +57,7 @@ static void event(int fd, uint16_t type, uint16_t code, int32_t value) event.code = code; event.value = value; - write(fd, &event, sizeof(event)); + len = write(fd, &event, sizeof(event)); } static void func(int fd) -- cgit From 670e5ef72176dafc1bf2669d4c5c30e0db26dd71 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Tue, 1 Aug 2006 12:35:58 +0000 Subject: Exit with non-zero exit status if fakehid functions fail --- hidd/fakehid.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'hidd/fakehid.c') diff --git a/hidd/fakehid.c b/hidd/fakehid.c index 138d2b48..2699d3f5 100644 --- a/hidd/fakehid.c +++ b/hidd/fakehid.c @@ -277,7 +277,7 @@ static void sig_term(int sig) __io_canceled = 1; } -void epox_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel) +int epox_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel) { unsigned char buf[16]; struct sigaction sa; @@ -287,12 +287,12 @@ void epox_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel) sk = rfcomm_connect(src, dst, channel); if (sk < 0) - return; + return -1; fd = uinput_create("Bluetooth Presenter", 0, 1); if (fd < 0) { close(sk); - return; + return -1; } ba2str(dst, addr); @@ -335,9 +335,12 @@ void epox_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel) close(fd); close(sk); + + return 0; } -void headset_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) { printf("Not implemented\n"); + return -1; } -- cgit From 35e9349ffc53950c4b78fba9537a50cdb6e5fd7a Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 10 Aug 2006 10:20:59 +0000 Subject: Change default poll() timeout --- hidd/fakehid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'hidd/fakehid.c') diff --git a/hidd/fakehid.c b/hidd/fakehid.c index 2699d3f5..91a62fb3 100644 --- a/hidd/fakehid.c +++ b/hidd/fakehid.c @@ -318,7 +318,7 @@ int epox_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel) while (!__io_canceled) { p.revents = 0; - if (poll(&p, 1, 100) < 1) + if (poll(&p, 1, 500) < 1) continue; len = read(sk, buf, sizeof(buf)); -- cgit From a1bc48d15a5d6e78efe744eb7b27b6421cb7222f Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 16 Aug 2006 10:54:06 +0000 Subject: Convert to using ppoll() and pselect() --- hidd/fakehid.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'hidd/fakehid.c') diff --git a/hidd/fakehid.c b/hidd/fakehid.c index 91a62fb3..70eba3b4 100644 --- a/hidd/fakehid.c +++ b/hidd/fakehid.c @@ -25,6 +25,7 @@ #include #endif +#define _GNU_SOURCE #include #include #include @@ -44,6 +45,10 @@ #include +#ifdef NEED_PPOLL +#include "ppoll.h" +#endif + static void event(int fd, uint16_t type, uint16_t code, int32_t value) { struct uinput_event event; @@ -282,6 +287,7 @@ 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; @@ -313,12 +319,14 @@ int epox_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel) sa.sa_handler = sig_hup; sigaction(SIGHUP, &sa, NULL); + sigfillset(&sigs); + p.fd = sk; p.events = POLLIN | POLLERR | POLLHUP; while (!__io_canceled) { p.revents = 0; - if (poll(&p, 1, 500) < 1) + if (ppoll(&p, 1, NULL, &sigs) < 1) continue; len = read(sk, buf, sizeof(buf)); -- cgit From 73b9315e56f5f635eaf82a08271e8f462b731972 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 16 Aug 2006 11:44:52 +0000 Subject: Don't forget to unblock signals for ppoll() --- hidd/fakehid.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'hidd/fakehid.c') diff --git a/hidd/fakehid.c b/hidd/fakehid.c index 70eba3b4..be1f29b9 100644 --- a/hidd/fakehid.c +++ b/hidd/fakehid.c @@ -320,6 +320,11 @@ int epox_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel) 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; -- cgit From 9f2da763372bb5b64840443b51a02c3861c66d57 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 16 Sep 2006 12:09:58 +0000 Subject: Add support for the J-Three keyboard --- hidd/fakehid.c | 303 +++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 199 insertions(+), 104 deletions(-) (limited to 'hidd/fakehid.c') 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; -} -- cgit From 6d2c7e465e4a8e3e6bb9595ccfd0f471070eda69 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 29 Sep 2006 16:15:41 +0000 Subject: Add framework for Celluon keyboard --- hidd/fakehid.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'hidd/fakehid.c') diff --git a/hidd/fakehid.c b/hidd/fakehid.c index 3a1c0d6e..22349cbf 100644 --- a/hidd/fakehid.c +++ b/hidd/fakehid.c @@ -452,3 +452,70 @@ int jthree_keyboard(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel) return 0; } + +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 fd, sk, len; + + 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; + + while (!__io_canceled) { + p.revents = 0; + if (ppoll(&p, 1, NULL, &sigs) < 1) + continue; + + len = read(sk, buf, sizeof(buf)); + if (len < 0) + break; + } + + printf("Disconnected\n"); + + ioctl(fd, UI_DEV_DESTROY); + + close(fd); + close(sk); + + return 0; +} -- cgit From 607695ed109340f4b7a5628420e0a8e8aee34f4e Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 13 Jan 2007 17:48:12 +0000 Subject: Update copyright information --- hidd/fakehid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'hidd/fakehid.c') diff --git a/hidd/fakehid.c b/hidd/fakehid.c index 22349cbf..1a0cc33f 100644 --- a/hidd/fakehid.c +++ b/hidd/fakehid.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2003-2006 Marcel Holtmann + * Copyright (C) 2003-2007 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify -- cgit From 98ca10183bece1ed4798dda2131cbdde7e991869 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 12 Feb 2007 19:57:49 +0000 Subject: Add Celluon CL800BT decoding support --- hidd/fakehid.c | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 149 insertions(+), 1 deletion(-) (limited to 'hidd/fakehid.c') diff --git a/hidd/fakehid.c b/hidd/fakehid.c index 1a0cc33f..226dcef2 100644 --- a/hidd/fakehid.c +++ b/hidd/fakehid.c @@ -453,6 +453,148 @@ int jthree_keyboard(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel) 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]; @@ -460,7 +602,8 @@ int celluon_keyboard(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel) struct pollfd p; sigset_t sigs; char addr[18]; - int fd, sk, len; + int i, fd, sk, len; + struct celluon_state s; sk = rfcomm_connect(src, dst, channel); if (sk < 0) @@ -500,6 +643,8 @@ int celluon_keyboard(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel) 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) @@ -508,6 +653,9 @@ int celluon_keyboard(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel) 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"); -- cgit From e823c15e43a6f924779e466d434c51157002d9ee Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 2 Feb 2008 03:37:05 +0000 Subject: Update copyright information --- hidd/fakehid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'hidd/fakehid.c') diff --git a/hidd/fakehid.c b/hidd/fakehid.c index 226dcef2..feefe2a6 100644 --- a/hidd/fakehid.c +++ b/hidd/fakehid.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2003-2007 Marcel Holtmann + * Copyright (C) 2003-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify -- cgit