Linux-2.6.12-rc2
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / net / bluetooth / hidp / core.c
blob2cf98ceabcc75a2e3e1932a93f50d55970994a66
1 /*
2 HIDP implementation for Linux Bluetooth stack (BlueZ).
3 Copyright (C) 2003-2004 Marcel Holtmann <marcel@holtmann.org>
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;
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.
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.
23 #include <linux/config.h>
24 #include <linux/module.h>
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>
42 #include <linux/input.h>
44 #include <net/bluetooth/bluetooth.h>
45 #include <net/bluetooth/l2cap.h>
47 #include "hidp.h"
49 #ifndef CONFIG_BT_HIDP_DEBUG
50 #undef BT_DBG
51 #define BT_DBG(D...)
52 #endif
54 #define VERSION "1.1"
56 static DECLARE_RWSEM(hidp_session_sem);
57 static LIST_HEAD(hidp_session_list);
59 static 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
78 static unsigned char hidp_mkeyspat[] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 };
80 static struct hidp_session *__hidp_get_session(bdaddr_t *bdaddr)
82 struct hidp_session *session;
83 struct list_head *p;
85 BT_DBG("");
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;
92 return NULL;
95 static void __hidp_link_session(struct hidp_session *session)
97 __module_get(THIS_MODULE);
98 list_add(&session->list, &hidp_session_list);
101 static void __hidp_unlink_session(struct hidp_session *session)
103 list_del(&session->list);
104 module_put(THIS_MODULE);
107 static void __hidp_copy_session(struct hidp_session *session, struct hidp_conninfo *ci)
109 bacpy(&ci->bdaddr, &session->bdaddr);
111 ci->flags = session->flags;
112 ci->state = session->state;
114 ci->vendor = 0x0000;
115 ci->product = 0x0000;
116 ci->version = 0x0000;
117 memset(ci->name, 0, 128);
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);
130 static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
132 struct hidp_session *session = dev->private;
133 struct sk_buff *skb;
134 unsigned char newleds;
136 BT_DBG("input %p type %d code %d value %d", dev, type, code, value);
138 if (type != EV_LED)
139 return -1;
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));
147 if (session->leds == newleds)
148 return 0;
150 session->leds = newleds;
152 if (!(skb = alloc_skb(3, GFP_ATOMIC))) {
153 BT_ERR("Can't allocate memory for new frame");
154 return -ENOMEM;
157 *skb_put(skb, 1) = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
158 *skb_put(skb, 1) = 0x01;
159 *skb_put(skb, 1) = newleds;
161 skb_queue_tail(&session->intr_transmit, skb);
163 hidp_schedule(session);
165 return 0;
168 static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
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;
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);
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;
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]);
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]);
202 memcpy(keys, udata, 8);
203 break;
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);
212 input_report_rel(dev, REL_X, sdata[1]);
213 input_report_rel(dev, REL_Y, sdata[2]);
215 if (size > 3)
216 input_report_rel(dev, REL_WHEEL, sdata[3]);
217 break;
220 input_sync(dev);
223 static void hidp_idle_timeout(unsigned long arg)
225 struct hidp_session *session = (struct hidp_session *) arg;
227 atomic_inc(&session->terminate);
228 hidp_schedule(session);
231 static inline void hidp_set_timer(struct hidp_session *session)
233 if (session->idle_to > 0)
234 mod_timer(&session->timer, jiffies + HZ * session->idle_to);
237 static inline void hidp_del_timer(struct hidp_session *session)
239 if (session->idle_to > 0)
240 del_timer(&session->timer);
243 static int __hidp_send_ctrl_message(struct hidp_session *session,
244 unsigned char hdr, unsigned char *data, int size)
246 struct sk_buff *skb;
248 BT_DBG("session %p data %p size %d", session, data, size);
250 if (!(skb = alloc_skb(size + 1, GFP_ATOMIC))) {
251 BT_ERR("Can't allocate memory for new frame");
252 return -ENOMEM;
255 *skb_put(skb, 1) = hdr;
256 if (data && size > 0)
257 memcpy(skb_put(skb, size), data, size);
259 skb_queue_tail(&session->ctrl_transmit, skb);
261 return 0;
264 static int inline hidp_send_ctrl_message(struct hidp_session *session,
265 unsigned char hdr, unsigned char *data, int size)
267 int err;
269 err = __hidp_send_ctrl_message(session, hdr, data, size);
271 hidp_schedule(session);
273 return err;
276 static inline void hidp_process_handshake(struct hidp_session *session, unsigned char param)
278 BT_DBG("session %p param 0x%02x", session, param);
280 switch (param) {
281 case HIDP_HSHK_SUCCESSFUL:
282 /* FIXME: Call into SET_ GET_ handlers here */
283 break;
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;
292 case HIDP_HSHK_ERR_UNKNOWN:
293 break;
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;
302 default:
303 __hidp_send_ctrl_message(session,
304 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
305 break;
309 static inline void hidp_process_hid_control(struct hidp_session *session, unsigned char param)
311 BT_DBG("session %p param 0x%02x", session, param);
313 switch (param) {
314 case HIDP_CTRL_NOP:
315 break;
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);
322 /* Kill session thread */
323 atomic_inc(&session->terminate);
324 break;
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;
333 default:
334 __hidp_send_ctrl_message(session,
335 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
336 break;
340 static inline void hidp_process_data(struct hidp_session *session, struct sk_buff *skb, unsigned char param)
342 BT_DBG("session %p skb %p len %d param 0x%02x", session, skb, skb->len, param);
344 switch (param) {
345 case HIDP_DATA_RTYPE_INPUT:
346 hidp_set_timer(session);
348 if (session->input)
349 hidp_input_report(session, skb);
350 break;
352 case HIDP_DATA_RTYPE_OTHER:
353 case HIDP_DATA_RTYPE_OUPUT:
354 case HIDP_DATA_RTYPE_FEATURE:
355 break;
357 default:
358 __hidp_send_ctrl_message(session,
359 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
363 static inline void hidp_recv_ctrl_frame(struct hidp_session *session, struct sk_buff *skb)
365 unsigned char hdr, type, param;
367 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
369 hdr = skb->data[0];
370 skb_pull(skb, 1);
372 type = hdr & HIDP_HEADER_TRANS_MASK;
373 param = hdr & HIDP_HEADER_PARAM_MASK;
375 switch (type) {
376 case HIDP_TRANS_HANDSHAKE:
377 hidp_process_handshake(session, param);
378 break;
380 case HIDP_TRANS_HID_CONTROL:
381 hidp_process_hid_control(session, param);
382 break;
384 case HIDP_TRANS_DATA:
385 hidp_process_data(session, skb, param);
386 break;
388 default:
389 __hidp_send_ctrl_message(session,
390 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_UNSUPPORTED_REQUEST, NULL, 0);
391 break;
394 kfree_skb(skb);
397 static inline void hidp_recv_intr_frame(struct hidp_session *session, struct sk_buff *skb)
399 unsigned char hdr;
401 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
403 hdr = skb->data[0];
404 skb_pull(skb, 1);
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);
414 kfree_skb(skb);
417 static int hidp_send_frame(struct socket *sock, unsigned char *data, int len)
419 struct kvec iv = { data, len };
420 struct msghdr msg;
422 BT_DBG("sock %p data %p len %d", sock, data, len);
424 if (!len)
425 return 0;
427 memset(&msg, 0, sizeof(msg));
429 return kernel_sendmsg(sock, &msg, &iv, 1, len);
432 static int hidp_process_transmit(struct hidp_session *session)
434 struct sk_buff *skb;
436 BT_DBG("session %p", session);
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;
444 hidp_set_timer(session);
445 kfree_skb(skb);
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;
454 hidp_set_timer(session);
455 kfree_skb(skb);
458 return skb_queue_len(&session->ctrl_transmit) +
459 skb_queue_len(&session->intr_transmit);
462 static int hidp_session(void *arg)
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;
471 BT_DBG("session %p", session);
473 if (session->input) {
474 vendor = session->input->id.vendor;
475 product = session->input->id.product;
478 daemonize("khidpd_%04x%04x", vendor, product);
479 set_user_nice(current, -15);
480 current->flags |= PF_NOFREEZE;
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);
489 if (ctrl_sk->sk_state != BT_CONNECTED || intr_sk->sk_state != BT_CONNECTED)
490 break;
492 while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) {
493 skb_orphan(skb);
494 hidp_recv_ctrl_frame(session, skb);
497 while ((skb = skb_dequeue(&intr_sk->sk_receive_queue))) {
498 skb_orphan(skb);
499 hidp_recv_intr_frame(session, skb);
502 hidp_process_transmit(session);
504 schedule();
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);
510 down_write(&hidp_session_sem);
512 hidp_del_timer(session);
514 if (intr_sk->sk_state != BT_CONNECTED)
515 wait_event_timeout(*(ctrl_sk->sk_sleep), (ctrl_sk->sk_state == BT_CLOSED), HZ);
517 fput(session->ctrl_sock->file);
519 wait_event_timeout(*(intr_sk->sk_sleep), (intr_sk->sk_state == BT_CLOSED), HZ);
521 fput(session->intr_sock->file);
523 __hidp_unlink_session(session);
525 if (session->input) {
526 input_unregister_device(session->input);
527 kfree(session->input);
530 up_write(&hidp_session_sem);
532 kfree(session);
533 return 0;
536 static inline void hidp_setup_input(struct hidp_session *session, struct hidp_connadd_req *req)
538 struct input_dev *input = session->input;
539 int i;
541 input->private = session;
543 input->id.bustype = BUS_BLUETOOTH;
544 input->id.vendor = req->vendor;
545 input->id.product = req->product;
546 input->id.version = req->version;
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);
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);
559 for (i = 0; i < sizeof(hidp_keycode); i++)
560 set_bit(hidp_keycode[i], input->keybit);
561 clear_bit(0, input->keybit);
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);
572 input->event = hidp_input_event;
574 input_register_device(input);
577 int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
579 struct hidp_session *session, *s;
580 int err;
582 BT_DBG("");
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;
588 session = kmalloc(sizeof(struct hidp_session), GFP_KERNEL);
589 if (!session)
590 return -ENOMEM;
591 memset(session, 0, sizeof(struct hidp_session));
593 session->input = kmalloc(sizeof(struct input_dev), GFP_KERNEL);
594 if (!session->input) {
595 kfree(session);
596 return -ENOMEM;
598 memset(session->input, 0, sizeof(struct input_dev));
600 down_write(&hidp_session_sem);
602 s = __hidp_get_session(&bt_sk(ctrl_sock->sk)->dst);
603 if (s && s->state == BT_CONNECTED) {
604 err = -EEXIST;
605 goto failed;
608 bacpy(&session->bdaddr, &bt_sk(ctrl_sock->sk)->dst);
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);
613 BT_DBG("ctrl mtu %d intr mtu %d", session->ctrl_mtu, session->intr_mtu);
615 session->ctrl_sock = ctrl_sock;
616 session->intr_sock = intr_sock;
617 session->state = BT_CONNECTED;
619 init_timer(&session->timer);
621 session->timer.function = hidp_idle_timeout;
622 session->timer.data = (unsigned long) session;
624 skb_queue_head_init(&session->ctrl_transmit);
625 skb_queue_head_init(&session->intr_transmit);
627 session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
628 session->idle_to = req->idle_to;
630 if (session->input)
631 hidp_setup_input(session, req);
633 __hidp_link_session(session);
635 hidp_set_timer(session);
637 err = kernel_thread(hidp_session, session, CLONE_KERNEL);
638 if (err < 0)
639 goto unlink;
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);
646 session->leds = 0xff;
647 hidp_input_event(session->input, EV_LED, 0, 0);
650 up_write(&hidp_session_sem);
651 return 0;
653 unlink:
654 hidp_del_timer(session);
656 __hidp_unlink_session(session);
658 if (session->input)
659 input_unregister_device(session->input);
661 failed:
662 up_write(&hidp_session_sem);
664 if (session->input)
665 kfree(session->input);
667 kfree(session);
668 return err;
671 int hidp_del_connection(struct hidp_conndel_req *req)
673 struct hidp_session *session;
674 int err = 0;
676 BT_DBG("");
678 down_read(&hidp_session_sem);
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);
690 /* Kill session thread */
691 atomic_inc(&session->terminate);
692 hidp_schedule(session);
694 } else
695 err = -ENOENT;
697 up_read(&hidp_session_sem);
698 return err;
701 int hidp_get_connlist(struct hidp_connlist_req *req)
703 struct list_head *p;
704 int err = 0, n = 0;
706 BT_DBG("");
708 down_read(&hidp_session_sem);
710 list_for_each(p, &hidp_session_list) {
711 struct hidp_session *session;
712 struct hidp_conninfo ci;
714 session = list_entry(p, struct hidp_session, list);
716 __hidp_copy_session(session, &ci);
718 if (copy_to_user(req->ci, &ci, sizeof(ci))) {
719 err = -EFAULT;
720 break;
723 if (++n >= req->cnum)
724 break;
726 req->ci++;
728 req->cnum = n;
730 up_read(&hidp_session_sem);
731 return err;
734 int hidp_get_conninfo(struct hidp_conninfo *ci)
736 struct hidp_session *session;
737 int err = 0;
739 down_read(&hidp_session_sem);
741 session = __hidp_get_session(&ci->bdaddr);
742 if (session)
743 __hidp_copy_session(session, ci);
744 else
745 err = -ENOENT;
747 up_read(&hidp_session_sem);
748 return err;
751 static int __init hidp_init(void)
753 l2cap_load();
755 BT_INFO("HIDP (Human Interface Emulation) ver %s", VERSION);
757 return hidp_init_sockets();
760 static void __exit hidp_exit(void)
762 hidp_cleanup_sockets();
765 module_init(hidp_init);
766 module_exit(hidp_exit);
768 MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
769 MODULE_DESCRIPTION("Bluetooth HIDP ver " VERSION);
770 MODULE_VERSION(VERSION);
771 MODULE_LICENSE("GPL");
772 MODULE_ALIAS("bt-proto-6");