summaryrefslogtreecommitdiff
path: root/hidd
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2006-09-16 12:09:58 +0000
committerMarcel Holtmann <marcel@holtmann.org>2006-09-16 12:09:58 +0000
commit9f2da763372bb5b64840443b51a02c3861c66d57 (patch)
tree1caabfea978dc4f02af0a5eb54d62ef3e4f60685 /hidd
parent1531f5fad2b5f6c2c645914639df5afd66c999cd (diff)
Add support for the J-Three keyboard
Diffstat (limited to 'hidd')
-rw-r--r--hidd/fakehid.c303
-rw-r--r--hidd/hidd.h3
-rw-r--r--hidd/main.c20
-rw-r--r--hidd/sdp.c13
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;
diff --git a/hidd/sdp.c b/hidd/sdp.c
index 2c010f79..3a40182d 100644
--- a/hidd/sdp.c
+++ b/hidd/sdp.c
@@ -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) {