diff options
Diffstat (limited to 'hidd/fakehid.c')
-rw-r--r-- | hidd/fakehid.c | 296 |
1 files changed, 293 insertions, 3 deletions
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 <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> @@ -34,16 +40,300 @@ #include <bluetooth/hidp.h> #include "hidd.h" - -#include <X11/Xlib.h> -#include <X11/extensions/XTest.h> +#include "uinput.h" #include <math.h> +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"); } |