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) { |