blob: 2cf98ceabcc75a2e3e1932a93f50d55970994a66 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 HIDP implementation for Linux Bluetooth stack (BlueZ).
3 Copyright (C) 2003-2004 Marcel Holtmann <marcel@holtmann.org>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License version 2 as
7 published by the Free Software Foundation;
8
9 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
10 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
12 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
13 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
18 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
19 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
20 SOFTWARE IS DISCLAIMED.
21*/
22
23#include <linux/config.h>
24#include <linux/module.h>
25
26#include <linux/types.h>
27#include <linux/errno.h>
28#include <linux/kernel.h>
29#include <linux/major.h>
30#include <linux/sched.h>
31#include <linux/slab.h>
32#include <linux/poll.h>
33#include <linux/fcntl.h>
34#include <linux/skbuff.h>
35#include <linux/socket.h>
36#include <linux/ioctl.h>
37#include <linux/file.h>
38#include <linux/init.h>
39#include <linux/wait.h>
40#include <net/sock.h>
41
42#include <linux/input.h>
43
44#include <net/bluetooth/bluetooth.h>
45#include <net/bluetooth/l2cap.h>
46
47#include "hidp.h"
48
49#ifndef CONFIG_BT_HIDP_DEBUG
50#undef BT_DBG
51#define BT_DBG(D...)
52#endif
53
54#define VERSION "1.1"
55
56static DECLARE_RWSEM(hidp_session_sem);
57static LIST_HEAD(hidp_session_list);
58
59static unsigned char hidp_keycode[256] = {
60 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
61 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3,
62 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26,
63 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
64 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
65 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
66 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
67 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
68 115,114, 0, 0, 0,121, 0, 89, 93,124, 92, 94, 95, 0, 0, 0,
69 122,123, 90, 91, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
70 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
71 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
72 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
73 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
74 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
75 150,158,159,128,136,177,178,176,142,152,173,140
76};
77
78static unsigned char hidp_mkeyspat[] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 };
79
80static struct hidp_session *__hidp_get_session(bdaddr_t *bdaddr)
81{
82 struct hidp_session *session;
83 struct list_head *p;
84
85 BT_DBG("");
86
87 list_for_each(p, &hidp_session_list) {
88 session = list_entry(p, struct hidp_session, list);
89 if (!bacmp(bdaddr, &session->bdaddr))
90 return session;
91 }
92 return NULL;
93}
94
95static void __hidp_link_session(struct hidp_session *session)
96{
97 __module_get(THIS_MODULE);
98 list_add(&session->list, &hidp_session_list);
99}
100
101static void __hidp_unlink_session(struct hidp_session *session)
102{
103 list_del(&session->list);
104 module_put(THIS_MODULE);
105}
106
107static void __hidp_copy_session(struct hidp_session *session, struct hidp_conninfo *ci)
108{
109 bacpy(&ci->bdaddr, &session->bdaddr);
110
111 ci->flags = session->flags;
112 ci->state = session->state;
113
114 ci->vendor = 0x0000;
115 ci->product = 0x0000;
116 ci->version = 0x0000;
117 memset(ci->name, 0, 128);
118
119 if (session->input) {
120 ci->vendor = session->input->id.vendor;
121 ci->product = session->input->id.product;
122 ci->version = session->input->id.version;
123 if (session->input->name)
124 strncpy(ci->name, session->input->name, 128);
125 else
126 strncpy(ci->name, "HID Boot Device", 128);
127 }
128}
129
130static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
131{
132 struct hidp_session *session = dev->private;
133 struct sk_buff *skb;
134 unsigned char newleds;
135
136 BT_DBG("input %p type %d code %d value %d", dev, type, code, value);
137
138 if (type != EV_LED)
139 return -1;
140
141 newleds = (!!test_bit(LED_KANA, dev->led) << 3) |
142 (!!test_bit(LED_COMPOSE, dev->led) << 3) |
143 (!!test_bit(LED_SCROLLL, dev->led) << 2) |
144 (!!test_bit(LED_CAPSL, dev->led) << 1) |
145 (!!test_bit(LED_NUML, dev->led));
146
147 if (session->leds == newleds)
148 return 0;
149
150 session->leds = newleds;
151
152 if (!(skb = alloc_skb(3, GFP_ATOMIC))) {
153 BT_ERR("Can't allocate memory for new frame");
154 return -ENOMEM;
155 }
156
157 *skb_put(skb, 1) = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
158 *skb_put(skb, 1) = 0x01;
159 *skb_put(skb, 1) = newleds;
160
161 skb_queue_tail(&session->intr_transmit, skb);
162
163 hidp_schedule(session);
164
165 return 0;
166}
167
168static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
169{
170 struct input_dev *dev = session->input;
171 unsigned char *keys = session->keys;
172 unsigned char *udata = skb->data + 1;
173 signed char *sdata = skb->data + 1;
174 int i, size = skb->len - 1;
175
176 switch (skb->data[0]) {
177 case 0x01: /* Keyboard report */
178 for (i = 0; i < 8; i++)
179 input_report_key(dev, hidp_keycode[i + 224], (udata[0] >> i) & 1);
180
181 /* If all the key codes have been set to 0x01, it means
182 * too many keys were pressed at the same time. */
183 if (!memcmp(udata + 2, hidp_mkeyspat, 6))
184 break;
185
186 for (i = 2; i < 8; i++) {
187 if (keys[i] > 3 && memscan(udata + 2, keys[i], 6) == udata + 8) {
188 if (hidp_keycode[keys[i]])
189 input_report_key(dev, hidp_keycode[keys[i]], 0);
190 else
191 BT_ERR("Unknown key (scancode %#x) released.", keys[i]);
192 }
193
194 if (udata[i] > 3 && memscan(keys + 2, udata[i], 6) == keys + 8) {
195 if (hidp_keycode[udata[i]])
196 input_report_key(dev, hidp_keycode[udata[i]], 1);
197 else
198 BT_ERR("Unknown key (scancode %#x) pressed.", udata[i]);
199 }
200 }
201
202 memcpy(keys, udata, 8);
203 break;
204
205 case 0x02: /* Mouse report */
206 input_report_key(dev, BTN_LEFT, sdata[0] & 0x01);
207 input_report_key(dev, BTN_RIGHT, sdata[0] & 0x02);
208 input_report_key(dev, BTN_MIDDLE, sdata[0] & 0x04);
209 input_report_key(dev, BTN_SIDE, sdata[0] & 0x08);
210 input_report_key(dev, BTN_EXTRA, sdata[0] & 0x10);
211
212 input_report_rel(dev, REL_X, sdata[1]);
213 input_report_rel(dev, REL_Y, sdata[2]);
214
215 if (size > 3)
216 input_report_rel(dev, REL_WHEEL, sdata[3]);
217 break;
218 }
219
220 input_sync(dev);
221}
222
223static void hidp_idle_timeout(unsigned long arg)
224{
225 struct hidp_session *session = (struct hidp_session *) arg;
226
227 atomic_inc(&session->terminate);
228 hidp_schedule(session);
229}
230
231static inline void hidp_set_timer(struct hidp_session *session)
232{
233 if (session->idle_to > 0)
234 mod_timer(&session->timer, jiffies + HZ * session->idle_to);
235}
236
237static inline void hidp_del_timer(struct hidp_session *session)
238{
239 if (session->idle_to > 0)
240 del_timer(&session->timer);
241}
242
243static int __hidp_send_ctrl_message(struct hidp_session *session,
244 unsigned char hdr, unsigned char *data, int size)
245{
246 struct sk_buff *skb;
247
248 BT_DBG("session %p data %p size %d", session, data, size);
249
250 if (!(skb = alloc_skb(size + 1, GFP_ATOMIC))) {
251 BT_ERR("Can't allocate memory for new frame");
252 return -ENOMEM;
253 }
254
255 *skb_put(skb, 1) = hdr;
256 if (data && size > 0)
257 memcpy(skb_put(skb, size), data, size);
258
259 skb_queue_tail(&session->ctrl_transmit, skb);
260
261 return 0;
262}
263
264static int inline hidp_send_ctrl_message(struct hidp_session *session,
265 unsigned char hdr, unsigned char *data, int size)
266{
267 int err;
268
269 err = __hidp_send_ctrl_message(session, hdr, data, size);
270
271 hidp_schedule(session);
272
273 return err;
274}
275
276static inline void hidp_process_handshake(struct hidp_session *session, unsigned char param)
277{
278 BT_DBG("session %p param 0x%02x", session, param);
279
280 switch (param) {
281 case HIDP_HSHK_SUCCESSFUL:
282 /* FIXME: Call into SET_ GET_ handlers here */
283 break;
284
285 case HIDP_HSHK_NOT_READY:
286 case HIDP_HSHK_ERR_INVALID_REPORT_ID:
287 case HIDP_HSHK_ERR_UNSUPPORTED_REQUEST:
288 case HIDP_HSHK_ERR_INVALID_PARAMETER:
289 /* FIXME: Call into SET_ GET_ handlers here */
290 break;
291
292 case HIDP_HSHK_ERR_UNKNOWN:
293 break;
294
295 case HIDP_HSHK_ERR_FATAL:
296 /* Device requests a reboot, as this is the only way this error
297 * can be recovered. */
298 __hidp_send_ctrl_message(session,
299 HIDP_TRANS_HID_CONTROL | HIDP_CTRL_SOFT_RESET, NULL, 0);
300 break;
301
302 default:
303 __hidp_send_ctrl_message(session,
304 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
305 break;
306 }
307}
308
309static inline void hidp_process_hid_control(struct hidp_session *session, unsigned char param)
310{
311 BT_DBG("session %p param 0x%02x", session, param);
312
313 switch (param) {
314 case HIDP_CTRL_NOP:
315 break;
316
317 case HIDP_CTRL_VIRTUAL_CABLE_UNPLUG:
318 /* Flush the transmit queues */
319 skb_queue_purge(&session->ctrl_transmit);
320 skb_queue_purge(&session->intr_transmit);
321
322 /* Kill session thread */
323 atomic_inc(&session->terminate);
324 break;
325
326 case HIDP_CTRL_HARD_RESET:
327 case HIDP_CTRL_SOFT_RESET:
328 case HIDP_CTRL_SUSPEND:
329 case HIDP_CTRL_EXIT_SUSPEND:
330 /* FIXME: We have to parse these and return no error */
331 break;
332
333 default:
334 __hidp_send_ctrl_message(session,
335 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
336 break;
337 }
338}
339
340static inline void hidp_process_data(struct hidp_session *session, struct sk_buff *skb, unsigned char param)
341{
342 BT_DBG("session %p skb %p len %d param 0x%02x", session, skb, skb->len, param);
343
344 switch (param) {
345 case HIDP_DATA_RTYPE_INPUT:
346 hidp_set_timer(session);
347
348 if (session->input)
349 hidp_input_report(session, skb);
350 break;
351
352 case HIDP_DATA_RTYPE_OTHER:
353 case HIDP_DATA_RTYPE_OUPUT:
354 case HIDP_DATA_RTYPE_FEATURE:
355 break;
356
357 default:
358 __hidp_send_ctrl_message(session,
359 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
360 }
361}
362
363static inline void hidp_recv_ctrl_frame(struct hidp_session *session, struct sk_buff *skb)
364{
365 unsigned char hdr, type, param;
366
367 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
368
369 hdr = skb->data[0];
370 skb_pull(skb, 1);
371
372 type = hdr & HIDP_HEADER_TRANS_MASK;
373 param = hdr & HIDP_HEADER_PARAM_MASK;
374
375 switch (type) {
376 case HIDP_TRANS_HANDSHAKE:
377 hidp_process_handshake(session, param);
378 break;
379
380 case HIDP_TRANS_HID_CONTROL:
381 hidp_process_hid_control(session, param);
382 break;
383
384 case HIDP_TRANS_DATA:
385 hidp_process_data(session, skb, param);
386 break;
387
388 default:
389 __hidp_send_ctrl_message(session,
390 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_UNSUPPORTED_REQUEST, NULL, 0);
391 break;
392 }
393
394 kfree_skb(skb);
395}
396
397static inline void hidp_recv_intr_frame(struct hidp_session *session, struct sk_buff *skb)
398{
399 unsigned char hdr;
400
401 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
402
403 hdr = skb->data[0];
404 skb_pull(skb, 1);
405
406 if (hdr == (HIDP_TRANS_DATA | HIDP_DATA_RTYPE_INPUT)) {
407 hidp_set_timer(session);
408 if (session->input)
409 hidp_input_report(session, skb);
410 } else {
411 BT_DBG("Unsupported protocol header 0x%02x", hdr);
412 }
413
414 kfree_skb(skb);
415}
416
417static int hidp_send_frame(struct socket *sock, unsigned char *data, int len)
418{
419 struct kvec iv = { data, len };
420 struct msghdr msg;
421
422 BT_DBG("sock %p data %p len %d", sock, data, len);
423
424 if (!len)
425 return 0;
426
427 memset(&msg, 0, sizeof(msg));
428
429 return kernel_sendmsg(sock, &msg, &iv, 1, len);
430}
431
432static int hidp_process_transmit(struct hidp_session *session)
433{
434 struct sk_buff *skb;
435
436 BT_DBG("session %p", session);
437
438 while ((skb = skb_dequeue(&session->ctrl_transmit))) {
439 if (hidp_send_frame(session->ctrl_sock, skb->data, skb->len) < 0) {
440 skb_queue_head(&session->ctrl_transmit, skb);
441 break;
442 }
443
444 hidp_set_timer(session);
445 kfree_skb(skb);
446 }
447
448 while ((skb = skb_dequeue(&session->intr_transmit))) {
449 if (hidp_send_frame(session->intr_sock, skb->data, skb->len) < 0) {
450 skb_queue_head(&session->intr_transmit, skb);
451 break;
452 }
453
454 hidp_set_timer(session);
455 kfree_skb(skb);
456 }
457
458 return skb_queue_len(&session->ctrl_transmit) +
459 skb_queue_len(&session->intr_transmit);
460}
461
462static int hidp_session(void *arg)
463{
464 struct hidp_session *session = arg;
465 struct sock *ctrl_sk = session->ctrl_sock->sk;
466 struct sock *intr_sk = session->intr_sock->sk;
467 struct sk_buff *skb;
468 int vendor = 0x0000, product = 0x0000;
469 wait_queue_t ctrl_wait, intr_wait;
470
471 BT_DBG("session %p", session);
472
473 if (session->input) {
474 vendor = session->input->id.vendor;
475 product = session->input->id.product;
476 }
477
478 daemonize("khidpd_%04x%04x", vendor, product);
479 set_user_nice(current, -15);
480 current->flags |= PF_NOFREEZE;
481
482 init_waitqueue_entry(&ctrl_wait, current);
483 init_waitqueue_entry(&intr_wait, current);
484 add_wait_queue(ctrl_sk->sk_sleep, &ctrl_wait);
485 add_wait_queue(intr_sk->sk_sleep, &intr_wait);
486 while (!atomic_read(&session->terminate)) {
487 set_current_state(TASK_INTERRUPTIBLE);
488
489 if (ctrl_sk->sk_state != BT_CONNECTED || intr_sk->sk_state != BT_CONNECTED)
490 break;
491
492 while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) {
493 skb_orphan(skb);
494 hidp_recv_ctrl_frame(session, skb);
495 }
496
497 while ((skb = skb_dequeue(&intr_sk->sk_receive_queue))) {
498 skb_orphan(skb);
499 hidp_recv_intr_frame(session, skb);
500 }
501
502 hidp_process_transmit(session);
503
504 schedule();
505 }
506 set_current_state(TASK_RUNNING);
507 remove_wait_queue(intr_sk->sk_sleep, &intr_wait);
508 remove_wait_queue(ctrl_sk->sk_sleep, &ctrl_wait);
509
510 down_write(&hidp_session_sem);
511
512 hidp_del_timer(session);
513
514 if (intr_sk->sk_state != BT_CONNECTED)
515 wait_event_timeout(*(ctrl_sk->sk_sleep), (ctrl_sk->sk_state == BT_CLOSED), HZ);
516
517 fput(session->ctrl_sock->file);
518
519 wait_event_timeout(*(intr_sk->sk_sleep), (intr_sk->sk_state == BT_CLOSED), HZ);
520
521 fput(session->intr_sock->file);
522
523 __hidp_unlink_session(session);
524
525 if (session->input) {
526 input_unregister_device(session->input);
527 kfree(session->input);
528 }
529
530 up_write(&hidp_session_sem);
531
532 kfree(session);
533 return 0;
534}
535
536static inline void hidp_setup_input(struct hidp_session *session, struct hidp_connadd_req *req)
537{
538 struct input_dev *input = session->input;
539 int i;
540
541 input->private = session;
542
543 input->id.bustype = BUS_BLUETOOTH;
544 input->id.vendor = req->vendor;
545 input->id.product = req->product;
546 input->id.version = req->version;
547
548 if (req->subclass & 0x40) {
549 set_bit(EV_KEY, input->evbit);
550 set_bit(EV_LED, input->evbit);
551 set_bit(EV_REP, input->evbit);
552
553 set_bit(LED_NUML, input->ledbit);
554 set_bit(LED_CAPSL, input->ledbit);
555 set_bit(LED_SCROLLL, input->ledbit);
556 set_bit(LED_COMPOSE, input->ledbit);
557 set_bit(LED_KANA, input->ledbit);
558
559 for (i = 0; i < sizeof(hidp_keycode); i++)
560 set_bit(hidp_keycode[i], input->keybit);
561 clear_bit(0, input->keybit);
562 }
563
564 if (req->subclass & 0x80) {
565 input->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
566 input->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
567 input->relbit[0] = BIT(REL_X) | BIT(REL_Y);
568 input->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA);
569 input->relbit[0] |= BIT(REL_WHEEL);
570 }
571
572 input->event = hidp_input_event;
573
574 input_register_device(input);
575}
576
577int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
578{
579 struct hidp_session *session, *s;
580 int err;
581
582 BT_DBG("");
583
584 if (bacmp(&bt_sk(ctrl_sock->sk)->src, &bt_sk(intr_sock->sk)->src) ||
585 bacmp(&bt_sk(ctrl_sock->sk)->dst, &bt_sk(intr_sock->sk)->dst))
586 return -ENOTUNIQ;
587
588 session = kmalloc(sizeof(struct hidp_session), GFP_KERNEL);
589 if (!session)
590 return -ENOMEM;
591 memset(session, 0, sizeof(struct hidp_session));
592
593 session->input = kmalloc(sizeof(struct input_dev), GFP_KERNEL);
594 if (!session->input) {
595 kfree(session);
596 return -ENOMEM;
597 }
598 memset(session->input, 0, sizeof(struct input_dev));
599
600 down_write(&hidp_session_sem);
601
602 s = __hidp_get_session(&bt_sk(ctrl_sock->sk)->dst);
603 if (s && s->state == BT_CONNECTED) {
604 err = -EEXIST;
605 goto failed;
606 }
607
608 bacpy(&session->bdaddr, &bt_sk(ctrl_sock->sk)->dst);
609
610 session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl_sock->sk)->omtu, l2cap_pi(ctrl_sock->sk)->imtu);
611 session->intr_mtu = min_t(uint, l2cap_pi(intr_sock->sk)->omtu, l2cap_pi(intr_sock->sk)->imtu);
612
613 BT_DBG("ctrl mtu %d intr mtu %d", session->ctrl_mtu, session->intr_mtu);
614
615 session->ctrl_sock = ctrl_sock;
616 session->intr_sock = intr_sock;
617 session->state = BT_CONNECTED;
618
619 init_timer(&session->timer);
620
621 session->timer.function = hidp_idle_timeout;
622 session->timer.data = (unsigned long) session;
623
624 skb_queue_head_init(&session->ctrl_transmit);
625 skb_queue_head_init(&session->intr_transmit);
626
627 session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
628 session->idle_to = req->idle_to;
629
630 if (session->input)
631 hidp_setup_input(session, req);
632
633 __hidp_link_session(session);
634
635 hidp_set_timer(session);
636
637 err = kernel_thread(hidp_session, session, CLONE_KERNEL);
638 if (err < 0)
639 goto unlink;
640
641 if (session->input) {
642 hidp_send_ctrl_message(session,
643 HIDP_TRANS_SET_PROTOCOL | HIDP_PROTO_BOOT, NULL, 0);
644 session->flags |= (1 << HIDP_BOOT_PROTOCOL_MODE);
645
646 session->leds = 0xff;
647 hidp_input_event(session->input, EV_LED, 0, 0);
648 }
649
650 up_write(&hidp_session_sem);
651 return 0;
652
653unlink:
654 hidp_del_timer(session);
655
656 __hidp_unlink_session(session);
657
658 if (session->input)
659 input_unregister_device(session->input);
660
661failed:
662 up_write(&hidp_session_sem);
663
664 if (session->input)
665 kfree(session->input);
666
667 kfree(session);
668 return err;
669}
670
671int hidp_del_connection(struct hidp_conndel_req *req)
672{
673 struct hidp_session *session;
674 int err = 0;
675
676 BT_DBG("");
677
678 down_read(&hidp_session_sem);
679
680 session = __hidp_get_session(&req->bdaddr);
681 if (session) {
682 if (req->flags & (1 << HIDP_VIRTUAL_CABLE_UNPLUG)) {
683 hidp_send_ctrl_message(session,
684 HIDP_TRANS_HID_CONTROL | HIDP_CTRL_VIRTUAL_CABLE_UNPLUG, NULL, 0);
685 } else {
686 /* Flush the transmit queues */
687 skb_queue_purge(&session->ctrl_transmit);
688 skb_queue_purge(&session->intr_transmit);
689
690 /* Kill session thread */
691 atomic_inc(&session->terminate);
692 hidp_schedule(session);
693 }
694 } else
695 err = -ENOENT;
696
697 up_read(&hidp_session_sem);
698 return err;
699}
700
701int hidp_get_connlist(struct hidp_connlist_req *req)
702{
703 struct list_head *p;
704 int err = 0, n = 0;
705
706 BT_DBG("");
707
708 down_read(&hidp_session_sem);
709
710 list_for_each(p, &hidp_session_list) {
711 struct hidp_session *session;
712 struct hidp_conninfo ci;
713
714 session = list_entry(p, struct hidp_session, list);
715
716 __hidp_copy_session(session, &ci);
717
718 if (copy_to_user(req->ci, &ci, sizeof(ci))) {
719 err = -EFAULT;
720 break;
721 }
722
723 if (++n >= req->cnum)
724 break;
725
726 req->ci++;
727 }
728 req->cnum = n;
729
730 up_read(&hidp_session_sem);
731 return err;
732}
733
734int hidp_get_conninfo(struct hidp_conninfo *ci)
735{
736 struct hidp_session *session;
737 int err = 0;
738
739 down_read(&hidp_session_sem);
740
741 session = __hidp_get_session(&ci->bdaddr);
742 if (session)
743 __hidp_copy_session(session, ci);
744 else
745 err = -ENOENT;
746
747 up_read(&hidp_session_sem);
748 return err;
749}
750
751static int __init hidp_init(void)
752{
753 l2cap_load();
754
755 BT_INFO("HIDP (Human Interface Emulation) ver %s", VERSION);
756
757 return hidp_init_sockets();
758}
759
760static void __exit hidp_exit(void)
761{
762 hidp_cleanup_sockets();
763}
764
765module_init(hidp_init);
766module_exit(hidp_exit);
767
768MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
769MODULE_DESCRIPTION("Bluetooth HIDP ver " VERSION);
770MODULE_VERSION(VERSION);
771MODULE_LICENSE("GPL");
772MODULE_ALIAS("bt-proto-6");