3
* BlueZ - Bluetooth protocol stack for Linux
5
* Copyright (C) 2003-2008 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 void send_event(int fd, uint16_t type, uint16_t code, int32_t value)
65
struct uinput_event event;
68
if (fd <= fileno(stderr))
71
memset(&event, 0, sizeof(event));
76
len = write(fd, &event, sizeof(event));
79
static int uinput_create(char *name, int keyboard, int mouse)
81
struct uinput_dev dev;
84
fd = open("/dev/uinput", O_RDWR);
86
fd = open("/dev/input/uinput", O_RDWR);
88
fd = open("/dev/misc/uinput", O_RDWR);
90
fprintf(stderr, "Can't open input device: %s (%d)\n",
91
strerror(errno), errno);
97
memset(&dev, 0, sizeof(dev));
100
strncpy(dev.name, name, UINPUT_MAX_NAME_SIZE);
102
dev.id.bustype = BUS_BLUETOOTH;
103
dev.id.vendor = 0x0000;
104
dev.id.product = 0x0000;
105
dev.id.version = 0x0000;
107
if (write(fd, &dev, sizeof(dev)) < 0) {
108
fprintf(stderr, "Can't write device information: %s (%d)\n",
109
strerror(errno), errno);
115
ioctl(fd, UI_SET_EVBIT, EV_REL);
117
for (aux = REL_X; aux <= REL_MISC; aux++)
118
ioctl(fd, UI_SET_RELBIT, aux);
122
ioctl(fd, UI_SET_EVBIT, EV_KEY);
123
ioctl(fd, UI_SET_EVBIT, EV_LED);
124
ioctl(fd, UI_SET_EVBIT, EV_REP);
126
for (aux = KEY_RESERVED; aux <= KEY_UNKNOWN; aux++)
127
ioctl(fd, UI_SET_KEYBIT, aux);
129
//for (aux = LED_NUML; aux <= LED_MISC; aux++)
130
// 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);