3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2003-2010 Marcel Holtmann <marcel@holtmann.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
36 #include <sys/ioctl.h>
37 #include <sys/socket.h>
39 #include <bluetooth/bluetooth.h>
40 #include <bluetooth/rfcomm.h>
41 #include <bluetooth/hidp.h>
52 static volatile sig_atomic_t __io_canceled = 0;
54 static void sig_hup(int sig)
58 static void sig_term(int sig)
63 static int send_event(int fd, uint16_t type, uint16_t code, int32_t value)
65 struct uinput_event event;
67 if (fd <= fileno(stderr))
70 memset(&event, 0, sizeof(event));
75 return write(fd, &event, sizeof(event));
78 static int uinput_create(char *name, int keyboard, int mouse)
80 struct uinput_dev dev;
83 fd = open("/dev/uinput", O_RDWR);
85 fd = open("/dev/input/uinput", O_RDWR);
87 fd = open("/dev/misc/uinput", O_RDWR);
89 fprintf(stderr, "Can't open input device: %s (%d)\n",
90 strerror(errno), errno);
96 memset(&dev, 0, sizeof(dev));
99 strncpy(dev.name, name, UINPUT_MAX_NAME_SIZE - 1);
101 dev.id.bustype = BUS_BLUETOOTH;
102 dev.id.vendor = 0x0000;
103 dev.id.product = 0x0000;
104 dev.id.version = 0x0000;
106 if (write(fd, &dev, sizeof(dev)) < 0) {
107 fprintf(stderr, "Can't write device information: %s (%d)\n",
108 strerror(errno), errno);
114 ioctl(fd, UI_SET_EVBIT, EV_REL);
116 for (aux = REL_X; aux <= REL_MISC; aux++)
117 ioctl(fd, UI_SET_RELBIT, aux);
121 ioctl(fd, UI_SET_EVBIT, EV_KEY);
122 ioctl(fd, UI_SET_EVBIT, EV_LED);
123 ioctl(fd, UI_SET_EVBIT, EV_REP);
125 for (aux = KEY_RESERVED; aux <= KEY_UNKNOWN; aux++)
126 ioctl(fd, UI_SET_KEYBIT, aux);
128 *for (aux = LED_NUML; aux <= LED_MISC; aux++)
129 * ioctl(fd, UI_SET_LEDBIT, aux);
134 ioctl(fd, UI_SET_EVBIT, EV_KEY);
136 for (aux = BTN_LEFT; aux <= BTN_BACK; aux++)
137 ioctl(fd, UI_SET_KEYBIT, aux);
140 ioctl(fd, UI_DEV_CREATE);
145 static int rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel)
147 struct sockaddr_rc addr;
150 sk = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
152 fprintf(stderr, "Can't create socket: %s (%d)\n",
153 strerror(errno), errno);
157 memset(&addr, 0, sizeof(addr));
158 addr.rc_family = AF_BLUETOOTH;
159 bacpy(&addr.rc_bdaddr, src);
161 if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
162 fprintf(stderr, "Can't bind socket: %s (%d)\n",
163 strerror(errno), errno);
168 memset(&addr, 0, sizeof(addr));
169 addr.rc_family = AF_BLUETOOTH;
170 bacpy(&addr.rc_bdaddr, dst);
171 addr.rc_channel = channel;
173 if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
174 fprintf(stderr, "Can't connect: %s (%d)\n",
175 strerror(errno), errno);
183 static void func(int fd)
187 static void back(int fd)
191 static void next(int fd)
195 static void button(int fd, unsigned int button, int is_press)
199 send_event(fd, EV_KEY, BTN_LEFT, is_press);
202 send_event(fd, EV_KEY, BTN_RIGHT, is_press);
206 send_event(fd, EV_SYN, SYN_REPORT, 0);
209 static void move(int fd, unsigned int direction)
214 angle = (direction * 22.5) * 3.1415926 / 180;
215 x = (int) (sin(angle) * 8);
216 y = (int) (cos(angle) * -8);
218 send_event(fd, EV_REL, REL_X, x);
219 send_event(fd, EV_REL, REL_Y, y);
221 send_event(fd, EV_SYN, SYN_REPORT, 0);
224 static inline void epox_decode(int fd, unsigned char event)
234 button(fd, 1, 1); break;
236 button(fd, 1, 0); break;
240 button(fd, 3, 1); break;
242 button(fd, 3, 0); break;
280 printf("Unknown event code %d\n", event);
285 int epox_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel)
287 unsigned char buf[16];
294 sk = rfcomm_connect(src, dst, channel);
298 fd = uinput_create("Bluetooth Presenter", 0, 1);
306 printf("Connected to %s on channel %d\n", addr, channel);
307 printf("Press CTRL-C for hangup\n");
309 memset(&sa, 0, sizeof(sa));
310 sa.sa_flags = SA_NOCLDSTOP;
311 sa.sa_handler = SIG_IGN;
312 sigaction(SIGCHLD, &sa, NULL);
313 sigaction(SIGPIPE, &sa, NULL);
315 sa.sa_handler = sig_term;
316 sigaction(SIGTERM, &sa, NULL);
317 sigaction(SIGINT, &sa, NULL);
319 sa.sa_handler = sig_hup;
320 sigaction(SIGHUP, &sa, NULL);
323 sigdelset(&sigs, SIGCHLD);
324 sigdelset(&sigs, SIGPIPE);
325 sigdelset(&sigs, SIGTERM);
326 sigdelset(&sigs, SIGINT);
327 sigdelset(&sigs, SIGHUP);
330 p.events = POLLIN | POLLERR | POLLHUP;
332 while (!__io_canceled) {
334 if (ppoll(&p, 1, NULL, &sigs) < 1)
337 len = read(sk, buf, sizeof(buf));
341 for (i = 0; i < len; i++)
342 epox_decode(fd, buf[i]);
345 printf("Disconnected\n");
347 ioctl(fd, UI_DEV_DESTROY);
355 int headset_presenter(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel)
357 printf("Not implemented\n");
361 /* The strange meta key close to Ctrl has been assigned to Esc,
362 Fn key to CtrlR and the left space to Alt*/
364 static unsigned char jthree_keycodes[63] = {
365 KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6,
366 KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T,
367 KEY_A, KEY_S, KEY_D, KEY_F, KEY_G,
368 KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B,
369 KEY_LEFTALT, KEY_TAB, KEY_CAPSLOCK, KEY_ESC,
370 KEY_7, KEY_8, KEY_9, KEY_0, KEY_MINUS, KEY_EQUAL, KEY_BACKSPACE,
371 KEY_Y, KEY_U, KEY_I, KEY_O, KEY_P, KEY_LEFTBRACE, KEY_RIGHTBRACE,
372 KEY_H, KEY_J, KEY_K, KEY_L, KEY_SEMICOLON, KEY_APOSTROPHE, KEY_ENTER,
373 KEY_N, KEY_M, KEY_COMMA, KEY_DOT, KEY_SLASH, KEY_UP,
374 KEY_SPACE, KEY_COMPOSE, KEY_LEFT, KEY_DOWN, KEY_RIGHT,
375 KEY_LEFTCTRL, KEY_RIGHTSHIFT, KEY_LEFTSHIFT, KEY_DELETE, KEY_RIGHTCTRL, KEY_RIGHTALT,
378 static inline void jthree_decode(int fd, unsigned char event)
381 send_event(fd, EV_KEY, jthree_keycodes[event & 0x3f], 0);
383 send_event(fd, EV_KEY, jthree_keycodes[event - 1], 1);
386 int jthree_keyboard(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel)
388 unsigned char buf[16];
395 sk = rfcomm_connect(src, dst, channel);
399 fd = uinput_create("J-Three Keyboard", 1, 0);
407 printf("Connected to %s on channel %d\n", addr, channel);
408 printf("Press CTRL-C for hangup\n");
410 memset(&sa, 0, sizeof(sa));
411 sa.sa_flags = SA_NOCLDSTOP;
412 sa.sa_handler = SIG_IGN;
413 sigaction(SIGCHLD, &sa, NULL);
414 sigaction(SIGPIPE, &sa, NULL);
416 sa.sa_handler = sig_term;
417 sigaction(SIGTERM, &sa, NULL);
418 sigaction(SIGINT, &sa, NULL);
420 sa.sa_handler = sig_hup;
421 sigaction(SIGHUP, &sa, NULL);
424 sigdelset(&sigs, SIGCHLD);
425 sigdelset(&sigs, SIGPIPE);
426 sigdelset(&sigs, SIGTERM);
427 sigdelset(&sigs, SIGINT);
428 sigdelset(&sigs, SIGHUP);
431 p.events = POLLIN | POLLERR | POLLHUP;
433 while (!__io_canceled) {
435 if (ppoll(&p, 1, NULL, &sigs) < 1)
438 len = read(sk, buf, sizeof(buf));
442 for (i = 0; i < len; i++)
443 jthree_decode(fd, buf[i]);
446 printf("Disconnected\n");
448 ioctl(fd, UI_DEV_DESTROY);
456 static const int celluon_xlate_num[10] = {
457 KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9
460 static const int celluon_xlate_char[26] = {
461 KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J,
462 KEY_K, KEY_L, KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T,
463 KEY_U, KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z
466 static int celluon_xlate(int c)
468 if (c >= '0' && c <= '9')
469 return celluon_xlate_num[c - '0'];
471 if (c >= 'A' && c <= 'Z')
472 return celluon_xlate_char[c - 'A'];
476 return KEY_BACKSPACE;
500 return KEY_RIGHTSHIFT;
502 return KEY_LEFTSHIFT;
504 return KEY_SEMICOLON;
518 return KEY_LEFTBRACE;
520 return KEY_BACKSLASH;
522 return KEY_RIGHTBRACE;
524 return KEY_APOSTROPHE;
537 case 0xff1a: /* Map FN to ALT */
542 printf("Unknown key %x\n", c);
547 struct celluon_state {
548 int len; /* Expected length of current packet */
549 int count; /* Number of bytes received */
554 static void celluon_decode(int fd, struct celluon_state *s, uint8_t c)
556 if (s->count < 2 && c != 0xa5) {
564 /* New packet - Reset state */
580 if (s->count == s->len - 1) {
581 /* TODO: Verify checksum */
583 send_event(fd, EV_KEY, celluon_xlate(s->key),
588 s->key = (s->key << 8) | c;
598 int celluon_keyboard(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel)
600 unsigned char buf[16];
606 struct celluon_state s;
608 sk = rfcomm_connect(src, dst, channel);
612 fd = uinput_create("Celluon Keyboard", 1, 0);
620 printf("Connected to %s on channel %d\n", addr, channel);
621 printf("Press CTRL-C for hangup\n");
623 memset(&sa, 0, sizeof(sa));
624 sa.sa_flags = SA_NOCLDSTOP;
625 sa.sa_handler = SIG_IGN;
626 sigaction(SIGCHLD, &sa, NULL);
627 sigaction(SIGPIPE, &sa, NULL);
629 sa.sa_handler = sig_term;
630 sigaction(SIGTERM, &sa, NULL);
631 sigaction(SIGINT, &sa, NULL);
633 sa.sa_handler = sig_hup;
634 sigaction(SIGHUP, &sa, NULL);
637 sigdelset(&sigs, SIGCHLD);
638 sigdelset(&sigs, SIGPIPE);
639 sigdelset(&sigs, SIGTERM);
640 sigdelset(&sigs, SIGINT);
641 sigdelset(&sigs, SIGHUP);
644 p.events = POLLIN | POLLERR | POLLHUP;
646 memset(&s, 0, sizeof(s));
648 while (!__io_canceled) {
650 if (ppoll(&p, 1, NULL, &sigs) < 1)
653 len = read(sk, buf, sizeof(buf));
657 for (i = 0; i < len; i++)
658 celluon_decode(fd, &s, buf[i]);
661 printf("Disconnected\n");
663 ioctl(fd, UI_DEV_DESTROY);