summaryrefslogtreecommitdiffstats
path: root/hidd/fakehid.c
diff options
context:
space:
mode:
Diffstat (limited to 'hidd/fakehid.c')
-rw-r--r--hidd/fakehid.c296
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");
}