diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-08-10 15:13:12 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-08-10 15:13:12 -0400 |
commit | 57f784fed3b9a33084c0cd0f6d08d98f87d2193f (patch) | |
tree | 8af841487980e1efea4942b057195e43847afd4d /net | |
parent | b877f4cf5af86528e07a0182e2b369ded38ccf38 (diff) | |
parent | cd17decbd9af41c9548bb108ccf156519f8253ec (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
Diffstat (limited to 'net')
-rw-r--r-- | net/bluetooth/a2mp.c | 16 | ||||
-rw-r--r-- | net/bluetooth/af_bluetooth.c | 141 | ||||
-rw-r--r-- | net/bluetooth/bnep/sock.c | 22 | ||||
-rw-r--r-- | net/bluetooth/cmtp/sock.c | 23 | ||||
-rw-r--r-- | net/bluetooth/hci_core.c | 6 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 93 | ||||
-rw-r--r-- | net/bluetooth/hci_sock.c | 13 | ||||
-rw-r--r-- | net/bluetooth/hidp/sock.c | 22 | ||||
-rw-r--r-- | net/bluetooth/l2cap_core.c | 32 | ||||
-rw-r--r-- | net/bluetooth/l2cap_sock.c | 22 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 34 | ||||
-rw-r--r-- | net/bluetooth/rfcomm/sock.c | 14 | ||||
-rw-r--r-- | net/bluetooth/sco.c | 16 |
13 files changed, 359 insertions, 95 deletions
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index 4ff0bf3ba9a5..0760d1fed6f0 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c | |||
@@ -316,7 +316,7 @@ send_rsp: | |||
316 | static inline int a2mp_cmd_rsp(struct amp_mgr *mgr, struct sk_buff *skb, | 316 | static inline int a2mp_cmd_rsp(struct amp_mgr *mgr, struct sk_buff *skb, |
317 | struct a2mp_cmd *hdr) | 317 | struct a2mp_cmd *hdr) |
318 | { | 318 | { |
319 | BT_DBG("ident %d code %d", hdr->ident, hdr->code); | 319 | BT_DBG("ident %d code 0x%2.2x", hdr->ident, hdr->code); |
320 | 320 | ||
321 | skb_pull(skb, le16_to_cpu(hdr->len)); | 321 | skb_pull(skb, le16_to_cpu(hdr->len)); |
322 | return 0; | 322 | return 0; |
@@ -325,17 +325,19 @@ static inline int a2mp_cmd_rsp(struct amp_mgr *mgr, struct sk_buff *skb, | |||
325 | /* Handle A2MP signalling */ | 325 | /* Handle A2MP signalling */ |
326 | static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) | 326 | static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) |
327 | { | 327 | { |
328 | struct a2mp_cmd *hdr = (void *) skb->data; | 328 | struct a2mp_cmd *hdr; |
329 | struct amp_mgr *mgr = chan->data; | 329 | struct amp_mgr *mgr = chan->data; |
330 | int err = 0; | 330 | int err = 0; |
331 | 331 | ||
332 | amp_mgr_get(mgr); | 332 | amp_mgr_get(mgr); |
333 | 333 | ||
334 | while (skb->len >= sizeof(*hdr)) { | 334 | while (skb->len >= sizeof(*hdr)) { |
335 | struct a2mp_cmd *hdr = (void *) skb->data; | 335 | u16 len; |
336 | u16 len = le16_to_cpu(hdr->len); | ||
337 | 336 | ||
338 | BT_DBG("code 0x%02x id %d len %d", hdr->code, hdr->ident, len); | 337 | hdr = (void *) skb->data; |
338 | len = le16_to_cpu(hdr->len); | ||
339 | |||
340 | BT_DBG("code 0x%2.2x id %d len %u", hdr->code, hdr->ident, len); | ||
339 | 341 | ||
340 | skb_pull(skb, sizeof(*hdr)); | 342 | skb_pull(skb, sizeof(*hdr)); |
341 | 343 | ||
@@ -393,7 +395,9 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) | |||
393 | 395 | ||
394 | if (err) { | 396 | if (err) { |
395 | struct a2mp_cmd_rej rej; | 397 | struct a2mp_cmd_rej rej; |
398 | |||
396 | rej.reason = __constant_cpu_to_le16(0); | 399 | rej.reason = __constant_cpu_to_le16(0); |
400 | hdr = (void *) skb->data; | ||
397 | 401 | ||
398 | BT_DBG("Send A2MP Rej: cmd 0x%2.2x err %d", hdr->code, err); | 402 | BT_DBG("Send A2MP Rej: cmd 0x%2.2x err %d", hdr->code, err); |
399 | 403 | ||
@@ -412,7 +416,7 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) | |||
412 | 416 | ||
413 | static void a2mp_chan_close_cb(struct l2cap_chan *chan) | 417 | static void a2mp_chan_close_cb(struct l2cap_chan *chan) |
414 | { | 418 | { |
415 | l2cap_chan_destroy(chan); | 419 | l2cap_chan_put(chan); |
416 | } | 420 | } |
417 | 421 | ||
418 | static void a2mp_chan_state_change_cb(struct l2cap_chan *chan, int state) | 422 | static void a2mp_chan_state_change_cb(struct l2cap_chan *chan, int state) |
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index f7db5792ec64..58f9762b339a 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <asm/ioctls.h> | 28 | #include <asm/ioctls.h> |
29 | 29 | ||
30 | #include <net/bluetooth/bluetooth.h> | 30 | #include <net/bluetooth/bluetooth.h> |
31 | #include <linux/proc_fs.h> | ||
31 | 32 | ||
32 | #define VERSION "2.16" | 33 | #define VERSION "2.16" |
33 | 34 | ||
@@ -532,6 +533,146 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo) | |||
532 | } | 533 | } |
533 | EXPORT_SYMBOL(bt_sock_wait_state); | 534 | EXPORT_SYMBOL(bt_sock_wait_state); |
534 | 535 | ||
536 | #ifdef CONFIG_PROC_FS | ||
537 | struct bt_seq_state { | ||
538 | struct bt_sock_list *l; | ||
539 | }; | ||
540 | |||
541 | static void *bt_seq_start(struct seq_file *seq, loff_t *pos) | ||
542 | __acquires(seq->private->l->lock) | ||
543 | { | ||
544 | struct bt_seq_state *s = seq->private; | ||
545 | struct bt_sock_list *l = s->l; | ||
546 | |||
547 | read_lock(&l->lock); | ||
548 | return seq_hlist_start_head(&l->head, *pos); | ||
549 | } | ||
550 | |||
551 | static void *bt_seq_next(struct seq_file *seq, void *v, loff_t *pos) | ||
552 | { | ||
553 | struct bt_seq_state *s = seq->private; | ||
554 | struct bt_sock_list *l = s->l; | ||
555 | |||
556 | return seq_hlist_next(v, &l->head, pos); | ||
557 | } | ||
558 | |||
559 | static void bt_seq_stop(struct seq_file *seq, void *v) | ||
560 | __releases(seq->private->l->lock) | ||
561 | { | ||
562 | struct bt_seq_state *s = seq->private; | ||
563 | struct bt_sock_list *l = s->l; | ||
564 | |||
565 | read_unlock(&l->lock); | ||
566 | } | ||
567 | |||
568 | static int bt_seq_show(struct seq_file *seq, void *v) | ||
569 | { | ||
570 | struct sock *sk; | ||
571 | struct bt_sock *bt; | ||
572 | struct bt_seq_state *s = seq->private; | ||
573 | struct bt_sock_list *l = s->l; | ||
574 | bdaddr_t src_baswapped, dst_baswapped; | ||
575 | |||
576 | if (v == SEQ_START_TOKEN) { | ||
577 | seq_puts(seq ,"sk RefCnt Rmem Wmem User Inode Src Dst Parent"); | ||
578 | |||
579 | if (l->custom_seq_show) { | ||
580 | seq_putc(seq, ' '); | ||
581 | l->custom_seq_show(seq, v); | ||
582 | } | ||
583 | |||
584 | seq_putc(seq, '\n'); | ||
585 | } else { | ||
586 | sk = sk_entry(v); | ||
587 | bt = bt_sk(sk); | ||
588 | baswap(&src_baswapped, &bt->src); | ||
589 | baswap(&dst_baswapped, &bt->dst); | ||
590 | |||
591 | seq_printf(seq, "%pK %-6d %-6u %-6u %-6u %-6lu %pM %pM %-6lu", | ||
592 | sk, | ||
593 | atomic_read(&sk->sk_refcnt), | ||
594 | sk_rmem_alloc_get(sk), | ||
595 | sk_wmem_alloc_get(sk), | ||
596 | sock_i_uid(sk), | ||
597 | sock_i_ino(sk), | ||
598 | &src_baswapped, | ||
599 | &dst_baswapped, | ||
600 | bt->parent? sock_i_ino(bt->parent): 0LU); | ||
601 | |||
602 | if (l->custom_seq_show) { | ||
603 | seq_putc(seq, ' '); | ||
604 | l->custom_seq_show(seq, v); | ||
605 | } | ||
606 | |||
607 | seq_putc(seq, '\n'); | ||
608 | } | ||
609 | return 0; | ||
610 | } | ||
611 | |||
612 | static struct seq_operations bt_seq_ops = { | ||
613 | .start = bt_seq_start, | ||
614 | .next = bt_seq_next, | ||
615 | .stop = bt_seq_stop, | ||
616 | .show = bt_seq_show, | ||
617 | }; | ||
618 | |||
619 | static int bt_seq_open(struct inode *inode, struct file *file) | ||
620 | { | ||
621 | struct bt_sock_list *sk_list; | ||
622 | struct bt_seq_state *s; | ||
623 | |||
624 | sk_list = PDE(inode)->data; | ||
625 | s = __seq_open_private(file, &bt_seq_ops, | ||
626 | sizeof(struct bt_seq_state)); | ||
627 | if (s == NULL) | ||
628 | return -ENOMEM; | ||
629 | |||
630 | s->l = sk_list; | ||
631 | return 0; | ||
632 | } | ||
633 | |||
634 | int bt_procfs_init(struct module* module, struct net *net, const char *name, | ||
635 | struct bt_sock_list* sk_list, | ||
636 | int (* seq_show)(struct seq_file *, void *)) | ||
637 | { | ||
638 | struct proc_dir_entry * pde; | ||
639 | |||
640 | sk_list->custom_seq_show = seq_show; | ||
641 | |||
642 | sk_list->fops.owner = module; | ||
643 | sk_list->fops.open = bt_seq_open; | ||
644 | sk_list->fops.read = seq_read; | ||
645 | sk_list->fops.llseek = seq_lseek; | ||
646 | sk_list->fops.release = seq_release_private; | ||
647 | |||
648 | pde = proc_net_fops_create(net, name, 0, &sk_list->fops); | ||
649 | if (pde == NULL) | ||
650 | return -ENOMEM; | ||
651 | |||
652 | pde->data = sk_list; | ||
653 | |||
654 | return 0; | ||
655 | } | ||
656 | |||
657 | void bt_procfs_cleanup(struct net *net, const char *name) | ||
658 | { | ||
659 | proc_net_remove(net, name); | ||
660 | } | ||
661 | #else | ||
662 | int bt_procfs_init(struct module* module, struct net *net, const char *name, | ||
663 | struct bt_sock_list* sk_list, | ||
664 | int (* seq_show)(struct seq_file *, void *)) | ||
665 | { | ||
666 | return 0; | ||
667 | } | ||
668 | |||
669 | void bt_procfs_cleanup(struct net *net, const char *name) | ||
670 | { | ||
671 | } | ||
672 | #endif | ||
673 | EXPORT_SYMBOL(bt_procfs_init); | ||
674 | EXPORT_SYMBOL(bt_procfs_cleanup); | ||
675 | |||
535 | static struct net_proto_family bt_sock_family_ops = { | 676 | static struct net_proto_family bt_sock_family_ops = { |
536 | .owner = THIS_MODULE, | 677 | .owner = THIS_MODULE, |
537 | .family = PF_BLUETOOTH, | 678 | .family = PF_BLUETOOTH, |
diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c index 5e5f5b410e0b..5b6cc0bf4dec 100644 --- a/net/bluetooth/bnep/sock.c +++ b/net/bluetooth/bnep/sock.c | |||
@@ -29,6 +29,10 @@ | |||
29 | 29 | ||
30 | #include "bnep.h" | 30 | #include "bnep.h" |
31 | 31 | ||
32 | static struct bt_sock_list bnep_sk_list = { | ||
33 | .lock = __RW_LOCK_UNLOCKED(bnep_sk_list.lock) | ||
34 | }; | ||
35 | |||
32 | static int bnep_sock_release(struct socket *sock) | 36 | static int bnep_sock_release(struct socket *sock) |
33 | { | 37 | { |
34 | struct sock *sk = sock->sk; | 38 | struct sock *sk = sock->sk; |
@@ -38,6 +42,8 @@ static int bnep_sock_release(struct socket *sock) | |||
38 | if (!sk) | 42 | if (!sk) |
39 | return 0; | 43 | return 0; |
40 | 44 | ||
45 | bt_sock_unlink(&bnep_sk_list, sk); | ||
46 | |||
41 | sock_orphan(sk); | 47 | sock_orphan(sk); |
42 | sock_put(sk); | 48 | sock_put(sk); |
43 | return 0; | 49 | return 0; |
@@ -204,6 +210,7 @@ static int bnep_sock_create(struct net *net, struct socket *sock, int protocol, | |||
204 | sk->sk_protocol = protocol; | 210 | sk->sk_protocol = protocol; |
205 | sk->sk_state = BT_OPEN; | 211 | sk->sk_state = BT_OPEN; |
206 | 212 | ||
213 | bt_sock_link(&bnep_sk_list, sk); | ||
207 | return 0; | 214 | return 0; |
208 | } | 215 | } |
209 | 216 | ||
@@ -222,19 +229,30 @@ int __init bnep_sock_init(void) | |||
222 | return err; | 229 | return err; |
223 | 230 | ||
224 | err = bt_sock_register(BTPROTO_BNEP, &bnep_sock_family_ops); | 231 | err = bt_sock_register(BTPROTO_BNEP, &bnep_sock_family_ops); |
225 | if (err < 0) | 232 | if (err < 0) { |
233 | BT_ERR("Can't register BNEP socket"); | ||
226 | goto error; | 234 | goto error; |
235 | } | ||
236 | |||
237 | err = bt_procfs_init(THIS_MODULE, &init_net, "bnep", &bnep_sk_list, NULL); | ||
238 | if (err < 0) { | ||
239 | BT_ERR("Failed to create BNEP proc file"); | ||
240 | bt_sock_unregister(BTPROTO_BNEP); | ||
241 | goto error; | ||
242 | } | ||
243 | |||
244 | BT_INFO("BNEP socket layer initialized"); | ||
227 | 245 | ||
228 | return 0; | 246 | return 0; |
229 | 247 | ||
230 | error: | 248 | error: |
231 | BT_ERR("Can't register BNEP socket"); | ||
232 | proto_unregister(&bnep_proto); | 249 | proto_unregister(&bnep_proto); |
233 | return err; | 250 | return err; |
234 | } | 251 | } |
235 | 252 | ||
236 | void __exit bnep_sock_cleanup(void) | 253 | void __exit bnep_sock_cleanup(void) |
237 | { | 254 | { |
255 | bt_procfs_cleanup(&init_net, "bnep"); | ||
238 | if (bt_sock_unregister(BTPROTO_BNEP) < 0) | 256 | if (bt_sock_unregister(BTPROTO_BNEP) < 0) |
239 | BT_ERR("Can't unregister BNEP socket"); | 257 | BT_ERR("Can't unregister BNEP socket"); |
240 | 258 | ||
diff --git a/net/bluetooth/cmtp/sock.c b/net/bluetooth/cmtp/sock.c index 311668d14571..d5cacef52748 100644 --- a/net/bluetooth/cmtp/sock.c +++ b/net/bluetooth/cmtp/sock.c | |||
@@ -42,6 +42,10 @@ | |||
42 | 42 | ||
43 | #include "cmtp.h" | 43 | #include "cmtp.h" |
44 | 44 | ||
45 | static struct bt_sock_list cmtp_sk_list = { | ||
46 | .lock = __RW_LOCK_UNLOCKED(cmtp_sk_list.lock) | ||
47 | }; | ||
48 | |||
45 | static int cmtp_sock_release(struct socket *sock) | 49 | static int cmtp_sock_release(struct socket *sock) |
46 | { | 50 | { |
47 | struct sock *sk = sock->sk; | 51 | struct sock *sk = sock->sk; |
@@ -51,6 +55,8 @@ static int cmtp_sock_release(struct socket *sock) | |||
51 | if (!sk) | 55 | if (!sk) |
52 | return 0; | 56 | return 0; |
53 | 57 | ||
58 | bt_sock_unlink(&cmtp_sk_list, sk); | ||
59 | |||
54 | sock_orphan(sk); | 60 | sock_orphan(sk); |
55 | sock_put(sk); | 61 | sock_put(sk); |
56 | 62 | ||
@@ -214,6 +220,8 @@ static int cmtp_sock_create(struct net *net, struct socket *sock, int protocol, | |||
214 | sk->sk_protocol = protocol; | 220 | sk->sk_protocol = protocol; |
215 | sk->sk_state = BT_OPEN; | 221 | sk->sk_state = BT_OPEN; |
216 | 222 | ||
223 | bt_sock_link(&cmtp_sk_list, sk); | ||
224 | |||
217 | return 0; | 225 | return 0; |
218 | } | 226 | } |
219 | 227 | ||
@@ -232,19 +240,30 @@ int cmtp_init_sockets(void) | |||
232 | return err; | 240 | return err; |
233 | 241 | ||
234 | err = bt_sock_register(BTPROTO_CMTP, &cmtp_sock_family_ops); | 242 | err = bt_sock_register(BTPROTO_CMTP, &cmtp_sock_family_ops); |
235 | if (err < 0) | 243 | if (err < 0) { |
244 | BT_ERR("Can't register CMTP socket"); | ||
236 | goto error; | 245 | goto error; |
246 | } | ||
247 | |||
248 | err = bt_procfs_init(THIS_MODULE, &init_net, "cmtp", &cmtp_sk_list, NULL); | ||
249 | if (err < 0) { | ||
250 | BT_ERR("Failed to create CMTP proc file"); | ||
251 | bt_sock_unregister(BTPROTO_HIDP); | ||
252 | goto error; | ||
253 | } | ||
254 | |||
255 | BT_INFO("CMTP socket layer initialized"); | ||
237 | 256 | ||
238 | return 0; | 257 | return 0; |
239 | 258 | ||
240 | error: | 259 | error: |
241 | BT_ERR("Can't register CMTP socket"); | ||
242 | proto_unregister(&cmtp_proto); | 260 | proto_unregister(&cmtp_proto); |
243 | return err; | 261 | return err; |
244 | } | 262 | } |
245 | 263 | ||
246 | void cmtp_cleanup_sockets(void) | 264 | void cmtp_cleanup_sockets(void) |
247 | { | 265 | { |
266 | bt_procfs_cleanup(&init_net, "cmtp"); | ||
248 | if (bt_sock_unregister(BTPROTO_CMTP) < 0) | 267 | if (bt_sock_unregister(BTPROTO_CMTP) < 0) |
249 | BT_ERR("Can't unregister CMTP socket"); | 268 | BT_ERR("Can't unregister CMTP socket"); |
250 | 269 | ||
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index d4de5db18d5a..fa974a19d365 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -696,7 +696,8 @@ int hci_dev_open(__u16 dev) | |||
696 | hci_dev_hold(hdev); | 696 | hci_dev_hold(hdev); |
697 | set_bit(HCI_UP, &hdev->flags); | 697 | set_bit(HCI_UP, &hdev->flags); |
698 | hci_notify(hdev, HCI_DEV_UP); | 698 | hci_notify(hdev, HCI_DEV_UP); |
699 | if (!test_bit(HCI_SETUP, &hdev->dev_flags)) { | 699 | if (!test_bit(HCI_SETUP, &hdev->dev_flags) && |
700 | mgmt_valid_hdev(hdev)) { | ||
700 | hci_dev_lock(hdev); | 701 | hci_dev_lock(hdev); |
701 | mgmt_powered(hdev, 1); | 702 | mgmt_powered(hdev, 1); |
702 | hci_dev_unlock(hdev); | 703 | hci_dev_unlock(hdev); |
@@ -797,7 +798,8 @@ static int hci_dev_do_close(struct hci_dev *hdev) | |||
797 | * and no tasks are scheduled. */ | 798 | * and no tasks are scheduled. */ |
798 | hdev->close(hdev); | 799 | hdev->close(hdev); |
799 | 800 | ||
800 | if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) { | 801 | if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags) && |
802 | mgmt_valid_hdev(hdev)) { | ||
801 | hci_dev_lock(hdev); | 803 | hci_dev_lock(hdev); |
802 | mgmt_powered(hdev, 0); | 804 | mgmt_powered(hdev, 0); |
803 | hci_dev_unlock(hdev); | 805 | hci_dev_unlock(hdev); |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 41ff978a33f9..32e21ad36a68 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -513,7 +513,7 @@ static void hci_setup_event_mask(struct hci_dev *hdev) | |||
513 | if (hdev->features[3] & LMP_RSSI_INQ) | 513 | if (hdev->features[3] & LMP_RSSI_INQ) |
514 | events[4] |= 0x02; /* Inquiry Result with RSSI */ | 514 | events[4] |= 0x02; /* Inquiry Result with RSSI */ |
515 | 515 | ||
516 | if (hdev->features[5] & LMP_SNIFF_SUBR) | 516 | if (lmp_sniffsubr_capable(hdev)) |
517 | events[5] |= 0x20; /* Sniff Subrating */ | 517 | events[5] |= 0x20; /* Sniff Subrating */ |
518 | 518 | ||
519 | if (hdev->features[5] & LMP_PAUSE_ENC) | 519 | if (hdev->features[5] & LMP_PAUSE_ENC) |
@@ -522,13 +522,13 @@ static void hci_setup_event_mask(struct hci_dev *hdev) | |||
522 | if (hdev->features[6] & LMP_EXT_INQ) | 522 | if (hdev->features[6] & LMP_EXT_INQ) |
523 | events[5] |= 0x40; /* Extended Inquiry Result */ | 523 | events[5] |= 0x40; /* Extended Inquiry Result */ |
524 | 524 | ||
525 | if (hdev->features[6] & LMP_NO_FLUSH) | 525 | if (lmp_no_flush_capable(hdev)) |
526 | events[7] |= 0x01; /* Enhanced Flush Complete */ | 526 | events[7] |= 0x01; /* Enhanced Flush Complete */ |
527 | 527 | ||
528 | if (hdev->features[7] & LMP_LSTO) | 528 | if (hdev->features[7] & LMP_LSTO) |
529 | events[6] |= 0x80; /* Link Supervision Timeout Changed */ | 529 | events[6] |= 0x80; /* Link Supervision Timeout Changed */ |
530 | 530 | ||
531 | if (hdev->features[6] & LMP_SIMPLE_PAIR) { | 531 | if (lmp_ssp_capable(hdev)) { |
532 | events[6] |= 0x01; /* IO Capability Request */ | 532 | events[6] |= 0x01; /* IO Capability Request */ |
533 | events[6] |= 0x02; /* IO Capability Response */ | 533 | events[6] |= 0x02; /* IO Capability Response */ |
534 | events[6] |= 0x04; /* User Confirmation Request */ | 534 | events[6] |= 0x04; /* User Confirmation Request */ |
@@ -541,7 +541,7 @@ static void hci_setup_event_mask(struct hci_dev *hdev) | |||
541 | * Features Notification */ | 541 | * Features Notification */ |
542 | } | 542 | } |
543 | 543 | ||
544 | if (hdev->features[4] & LMP_LE) | 544 | if (lmp_le_capable(hdev)) |
545 | events[7] |= 0x20; /* LE Meta-Event */ | 545 | events[7] |= 0x20; /* LE Meta-Event */ |
546 | 546 | ||
547 | hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); | 547 | hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); |
@@ -623,11 +623,11 @@ static void hci_setup_link_policy(struct hci_dev *hdev) | |||
623 | struct hci_cp_write_def_link_policy cp; | 623 | struct hci_cp_write_def_link_policy cp; |
624 | u16 link_policy = 0; | 624 | u16 link_policy = 0; |
625 | 625 | ||
626 | if (hdev->features[0] & LMP_RSWITCH) | 626 | if (lmp_rswitch_capable(hdev)) |
627 | link_policy |= HCI_LP_RSWITCH; | 627 | link_policy |= HCI_LP_RSWITCH; |
628 | if (hdev->features[0] & LMP_HOLD) | 628 | if (hdev->features[0] & LMP_HOLD) |
629 | link_policy |= HCI_LP_HOLD; | 629 | link_policy |= HCI_LP_HOLD; |
630 | if (hdev->features[0] & LMP_SNIFF) | 630 | if (lmp_sniff_capable(hdev)) |
631 | link_policy |= HCI_LP_SNIFF; | 631 | link_policy |= HCI_LP_SNIFF; |
632 | if (hdev->features[1] & LMP_PARK) | 632 | if (hdev->features[1] & LMP_PARK) |
633 | link_policy |= HCI_LP_PARK; | 633 | link_policy |= HCI_LP_PARK; |
@@ -686,7 +686,7 @@ static void hci_cc_read_local_features(struct hci_dev *hdev, | |||
686 | hdev->esco_type |= (ESCO_HV3); | 686 | hdev->esco_type |= (ESCO_HV3); |
687 | } | 687 | } |
688 | 688 | ||
689 | if (hdev->features[3] & LMP_ESCO) | 689 | if (lmp_esco_capable(hdev)) |
690 | hdev->esco_type |= (ESCO_EV3); | 690 | hdev->esco_type |= (ESCO_EV3); |
691 | 691 | ||
692 | if (hdev->features[4] & LMP_EV4) | 692 | if (hdev->features[4] & LMP_EV4) |
@@ -746,7 +746,7 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev, | |||
746 | break; | 746 | break; |
747 | } | 747 | } |
748 | 748 | ||
749 | if (test_bit(HCI_INIT, &hdev->flags) && hdev->features[4] & LMP_LE) | 749 | if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev)) |
750 | hci_set_le_support(hdev); | 750 | hci_set_le_support(hdev); |
751 | 751 | ||
752 | done: | 752 | done: |
@@ -1614,43 +1614,30 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) | |||
1614 | 1614 | ||
1615 | static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) | 1615 | static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) |
1616 | { | 1616 | { |
1617 | struct hci_cp_le_create_conn *cp; | ||
1618 | struct hci_conn *conn; | 1617 | struct hci_conn *conn; |
1619 | 1618 | ||
1620 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | 1619 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
1621 | 1620 | ||
1622 | cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN); | 1621 | if (status) { |
1623 | if (!cp) | 1622 | hci_dev_lock(hdev); |
1624 | return; | ||
1625 | 1623 | ||
1626 | hci_dev_lock(hdev); | 1624 | conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); |
1625 | if (!conn) { | ||
1626 | hci_dev_unlock(hdev); | ||
1627 | return; | ||
1628 | } | ||
1627 | 1629 | ||
1628 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr); | 1630 | BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&conn->dst), |
1631 | conn); | ||
1629 | 1632 | ||
1630 | BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr), | 1633 | conn->state = BT_CLOSED; |
1631 | conn); | 1634 | mgmt_connect_failed(hdev, &conn->dst, conn->type, |
1635 | conn->dst_type, status); | ||
1636 | hci_proto_connect_cfm(conn, status); | ||
1637 | hci_conn_del(conn); | ||
1632 | 1638 | ||
1633 | if (status) { | 1639 | hci_dev_unlock(hdev); |
1634 | if (conn && conn->state == BT_CONNECT) { | ||
1635 | conn->state = BT_CLOSED; | ||
1636 | mgmt_connect_failed(hdev, &cp->peer_addr, conn->type, | ||
1637 | conn->dst_type, status); | ||
1638 | hci_proto_connect_cfm(conn, status); | ||
1639 | hci_conn_del(conn); | ||
1640 | } | ||
1641 | } else { | ||
1642 | if (!conn) { | ||
1643 | conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr); | ||
1644 | if (conn) { | ||
1645 | conn->dst_type = cp->peer_addr_type; | ||
1646 | conn->out = true; | ||
1647 | } else { | ||
1648 | BT_ERR("No memory for new connection"); | ||
1649 | } | ||
1650 | } | ||
1651 | } | 1640 | } |
1652 | |||
1653 | hci_dev_unlock(hdev); | ||
1654 | } | 1641 | } |
1655 | 1642 | ||
1656 | static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) | 1643 | static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) |
@@ -3252,12 +3239,8 @@ static void hci_user_passkey_request_evt(struct hci_dev *hdev, | |||
3252 | 3239 | ||
3253 | BT_DBG("%s", hdev->name); | 3240 | BT_DBG("%s", hdev->name); |
3254 | 3241 | ||
3255 | hci_dev_lock(hdev); | ||
3256 | |||
3257 | if (test_bit(HCI_MGMT, &hdev->dev_flags)) | 3242 | if (test_bit(HCI_MGMT, &hdev->dev_flags)) |
3258 | mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); | 3243 | mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); |
3259 | |||
3260 | hci_dev_unlock(hdev); | ||
3261 | } | 3244 | } |
3262 | 3245 | ||
3263 | static void hci_simple_pair_complete_evt(struct hci_dev *hdev, | 3246 | static void hci_simple_pair_complete_evt(struct hci_dev *hdev, |
@@ -3350,11 +3333,23 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
3350 | 3333 | ||
3351 | hci_dev_lock(hdev); | 3334 | hci_dev_lock(hdev); |
3352 | 3335 | ||
3353 | if (ev->status) { | 3336 | conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); |
3354 | conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); | 3337 | if (!conn) { |
3355 | if (!conn) | 3338 | conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); |
3339 | if (!conn) { | ||
3340 | BT_ERR("No memory for new connection"); | ||
3356 | goto unlock; | 3341 | goto unlock; |
3342 | } | ||
3357 | 3343 | ||
3344 | conn->dst_type = ev->bdaddr_type; | ||
3345 | |||
3346 | if (ev->role == LE_CONN_ROLE_MASTER) { | ||
3347 | conn->out = true; | ||
3348 | conn->link_mode |= HCI_LM_MASTER; | ||
3349 | } | ||
3350 | } | ||
3351 | |||
3352 | if (ev->status) { | ||
3358 | mgmt_connect_failed(hdev, &conn->dst, conn->type, | 3353 | mgmt_connect_failed(hdev, &conn->dst, conn->type, |
3359 | conn->dst_type, ev->status); | 3354 | conn->dst_type, ev->status); |
3360 | hci_proto_connect_cfm(conn, ev->status); | 3355 | hci_proto_connect_cfm(conn, ev->status); |
@@ -3363,18 +3358,6 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
3363 | goto unlock; | 3358 | goto unlock; |
3364 | } | 3359 | } |
3365 | 3360 | ||
3366 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr); | ||
3367 | if (!conn) { | ||
3368 | conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); | ||
3369 | if (!conn) { | ||
3370 | BT_ERR("No memory for new connection"); | ||
3371 | hci_dev_unlock(hdev); | ||
3372 | return; | ||
3373 | } | ||
3374 | |||
3375 | conn->dst_type = ev->bdaddr_type; | ||
3376 | } | ||
3377 | |||
3378 | if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) | 3361 | if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) |
3379 | mgmt_device_connected(hdev, &ev->bdaddr, conn->type, | 3362 | mgmt_device_connected(hdev, &ev->bdaddr, conn->type, |
3380 | conn->dst_type, 0, NULL, 0, NULL); | 3363 | conn->dst_type, 0, NULL, 0, NULL); |
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index a7f04de03d79..7c3d6c7c6ddb 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c | |||
@@ -1100,21 +1100,30 @@ int __init hci_sock_init(void) | |||
1100 | return err; | 1100 | return err; |
1101 | 1101 | ||
1102 | err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops); | 1102 | err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops); |
1103 | if (err < 0) | 1103 | if (err < 0) { |
1104 | BT_ERR("HCI socket registration failed"); | ||
1104 | goto error; | 1105 | goto error; |
1106 | } | ||
1107 | |||
1108 | err = bt_procfs_init(THIS_MODULE, &init_net, "hci", &hci_sk_list, NULL); | ||
1109 | if (err < 0) { | ||
1110 | BT_ERR("Failed to create HCI proc file"); | ||
1111 | bt_sock_unregister(BTPROTO_HCI); | ||
1112 | goto error; | ||
1113 | } | ||
1105 | 1114 | ||
1106 | BT_INFO("HCI socket layer initialized"); | 1115 | BT_INFO("HCI socket layer initialized"); |
1107 | 1116 | ||
1108 | return 0; | 1117 | return 0; |
1109 | 1118 | ||
1110 | error: | 1119 | error: |
1111 | BT_ERR("HCI socket registration failed"); | ||
1112 | proto_unregister(&hci_sk_proto); | 1120 | proto_unregister(&hci_sk_proto); |
1113 | return err; | 1121 | return err; |
1114 | } | 1122 | } |
1115 | 1123 | ||
1116 | void hci_sock_cleanup(void) | 1124 | void hci_sock_cleanup(void) |
1117 | { | 1125 | { |
1126 | bt_procfs_cleanup(&init_net, "hci"); | ||
1118 | if (bt_sock_unregister(BTPROTO_HCI) < 0) | 1127 | if (bt_sock_unregister(BTPROTO_HCI) < 0) |
1119 | BT_ERR("HCI socket unregistration failed"); | 1128 | BT_ERR("HCI socket unregistration failed"); |
1120 | 1129 | ||
diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c index 18b3f6892a36..eca3889371c4 100644 --- a/net/bluetooth/hidp/sock.c +++ b/net/bluetooth/hidp/sock.c | |||
@@ -25,6 +25,10 @@ | |||
25 | 25 | ||
26 | #include "hidp.h" | 26 | #include "hidp.h" |
27 | 27 | ||
28 | static struct bt_sock_list hidp_sk_list = { | ||
29 | .lock = __RW_LOCK_UNLOCKED(hidp_sk_list.lock) | ||
30 | }; | ||
31 | |||
28 | static int hidp_sock_release(struct socket *sock) | 32 | static int hidp_sock_release(struct socket *sock) |
29 | { | 33 | { |
30 | struct sock *sk = sock->sk; | 34 | struct sock *sk = sock->sk; |
@@ -34,6 +38,8 @@ static int hidp_sock_release(struct socket *sock) | |||
34 | if (!sk) | 38 | if (!sk) |
35 | return 0; | 39 | return 0; |
36 | 40 | ||
41 | bt_sock_unlink(&hidp_sk_list, sk); | ||
42 | |||
37 | sock_orphan(sk); | 43 | sock_orphan(sk); |
38 | sock_put(sk); | 44 | sock_put(sk); |
39 | 45 | ||
@@ -253,6 +259,8 @@ static int hidp_sock_create(struct net *net, struct socket *sock, int protocol, | |||
253 | sk->sk_protocol = protocol; | 259 | sk->sk_protocol = protocol; |
254 | sk->sk_state = BT_OPEN; | 260 | sk->sk_state = BT_OPEN; |
255 | 261 | ||
262 | bt_sock_link(&hidp_sk_list, sk); | ||
263 | |||
256 | return 0; | 264 | return 0; |
257 | } | 265 | } |
258 | 266 | ||
@@ -271,8 +279,19 @@ int __init hidp_init_sockets(void) | |||
271 | return err; | 279 | return err; |
272 | 280 | ||
273 | err = bt_sock_register(BTPROTO_HIDP, &hidp_sock_family_ops); | 281 | err = bt_sock_register(BTPROTO_HIDP, &hidp_sock_family_ops); |
274 | if (err < 0) | 282 | if (err < 0) { |
283 | BT_ERR("Can't register HIDP socket"); | ||
275 | goto error; | 284 | goto error; |
285 | } | ||
286 | |||
287 | err = bt_procfs_init(THIS_MODULE, &init_net, "hidp", &hidp_sk_list, NULL); | ||
288 | if (err < 0) { | ||
289 | BT_ERR("Failed to create HIDP proc file"); | ||
290 | bt_sock_unregister(BTPROTO_HIDP); | ||
291 | goto error; | ||
292 | } | ||
293 | |||
294 | BT_INFO("HIDP socket layer initialized"); | ||
276 | 295 | ||
277 | return 0; | 296 | return 0; |
278 | 297 | ||
@@ -284,6 +303,7 @@ error: | |||
284 | 303 | ||
285 | void __exit hidp_cleanup_sockets(void) | 304 | void __exit hidp_cleanup_sockets(void) |
286 | { | 305 | { |
306 | bt_procfs_cleanup(&init_net, "hidp"); | ||
287 | if (bt_sock_unregister(BTPROTO_HIDP) < 0) | 307 | if (bt_sock_unregister(BTPROTO_HIDP) < 0) |
288 | BT_ERR("Can't unregister HIDP socket"); | 308 | BT_ERR("Can't unregister HIDP socket"); |
289 | 309 | ||
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index a8964db04bfb..9f8b29ef5b68 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -416,13 +416,30 @@ struct l2cap_chan *l2cap_chan_create(void) | |||
416 | return chan; | 416 | return chan; |
417 | } | 417 | } |
418 | 418 | ||
419 | void l2cap_chan_destroy(struct l2cap_chan *chan) | 419 | static void l2cap_chan_destroy(struct l2cap_chan *chan) |
420 | { | 420 | { |
421 | BT_DBG("chan %p", chan); | ||
422 | |||
421 | write_lock(&chan_list_lock); | 423 | write_lock(&chan_list_lock); |
422 | list_del(&chan->global_l); | 424 | list_del(&chan->global_l); |
423 | write_unlock(&chan_list_lock); | 425 | write_unlock(&chan_list_lock); |
424 | 426 | ||
425 | l2cap_chan_put(chan); | 427 | kfree(chan); |
428 | } | ||
429 | |||
430 | void l2cap_chan_hold(struct l2cap_chan *c) | ||
431 | { | ||
432 | BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt)); | ||
433 | |||
434 | atomic_inc(&c->refcnt); | ||
435 | } | ||
436 | |||
437 | void l2cap_chan_put(struct l2cap_chan *c) | ||
438 | { | ||
439 | BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt)); | ||
440 | |||
441 | if (atomic_dec_and_test(&c->refcnt)) | ||
442 | l2cap_chan_destroy(c); | ||
426 | } | 443 | } |
427 | 444 | ||
428 | void l2cap_chan_set_defaults(struct l2cap_chan *chan) | 445 | void l2cap_chan_set_defaults(struct l2cap_chan *chan) |
@@ -5329,7 +5346,7 @@ int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) | |||
5329 | return exact ? lm1 : lm2; | 5346 | return exact ? lm1 : lm2; |
5330 | } | 5347 | } |
5331 | 5348 | ||
5332 | int l2cap_connect_cfm(struct hci_conn *hcon, u8 status) | 5349 | void l2cap_connect_cfm(struct hci_conn *hcon, u8 status) |
5333 | { | 5350 | { |
5334 | struct l2cap_conn *conn; | 5351 | struct l2cap_conn *conn; |
5335 | 5352 | ||
@@ -5342,7 +5359,6 @@ int l2cap_connect_cfm(struct hci_conn *hcon, u8 status) | |||
5342 | } else | 5359 | } else |
5343 | l2cap_conn_del(hcon, bt_to_errno(status)); | 5360 | l2cap_conn_del(hcon, bt_to_errno(status)); |
5344 | 5361 | ||
5345 | return 0; | ||
5346 | } | 5362 | } |
5347 | 5363 | ||
5348 | int l2cap_disconn_ind(struct hci_conn *hcon) | 5364 | int l2cap_disconn_ind(struct hci_conn *hcon) |
@@ -5356,12 +5372,11 @@ int l2cap_disconn_ind(struct hci_conn *hcon) | |||
5356 | return conn->disc_reason; | 5372 | return conn->disc_reason; |
5357 | } | 5373 | } |
5358 | 5374 | ||
5359 | int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) | 5375 | void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) |
5360 | { | 5376 | { |
5361 | BT_DBG("hcon %p reason %d", hcon, reason); | 5377 | BT_DBG("hcon %p reason %d", hcon, reason); |
5362 | 5378 | ||
5363 | l2cap_conn_del(hcon, bt_to_errno(reason)); | 5379 | l2cap_conn_del(hcon, bt_to_errno(reason)); |
5364 | return 0; | ||
5365 | } | 5380 | } |
5366 | 5381 | ||
5367 | static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) | 5382 | static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) |
@@ -5404,6 +5419,11 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
5404 | BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid, | 5419 | BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid, |
5405 | state_to_string(chan->state)); | 5420 | state_to_string(chan->state)); |
5406 | 5421 | ||
5422 | if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { | ||
5423 | l2cap_chan_unlock(chan); | ||
5424 | continue; | ||
5425 | } | ||
5426 | |||
5407 | if (chan->scid == L2CAP_CID_LE_DATA) { | 5427 | if (chan->scid == L2CAP_CID_LE_DATA) { |
5408 | if (!status && encrypt) { | 5428 | if (!status && encrypt) { |
5409 | chan->sec_level = hcon->sec_level; | 5429 | chan->sec_level = hcon->sec_level; |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index a4bb27e8427e..13f6a9816feb 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -34,6 +34,10 @@ | |||
34 | #include <net/bluetooth/l2cap.h> | 34 | #include <net/bluetooth/l2cap.h> |
35 | #include <net/bluetooth/smp.h> | 35 | #include <net/bluetooth/smp.h> |
36 | 36 | ||
37 | static struct bt_sock_list l2cap_sk_list = { | ||
38 | .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock) | ||
39 | }; | ||
40 | |||
37 | static const struct proto_ops l2cap_sock_ops; | 41 | static const struct proto_ops l2cap_sock_ops; |
38 | static void l2cap_sock_init(struct sock *sk, struct sock *parent); | 42 | static void l2cap_sock_init(struct sock *sk, struct sock *parent); |
39 | static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio); | 43 | static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio); |
@@ -823,7 +827,7 @@ static void l2cap_sock_kill(struct sock *sk) | |||
823 | 827 | ||
824 | /* Kill poor orphan */ | 828 | /* Kill poor orphan */ |
825 | 829 | ||
826 | l2cap_chan_destroy(l2cap_pi(sk)->chan); | 830 | l2cap_chan_put(l2cap_pi(sk)->chan); |
827 | sock_set_flag(sk, SOCK_DEAD); | 831 | sock_set_flag(sk, SOCK_DEAD); |
828 | sock_put(sk); | 832 | sock_put(sk); |
829 | } | 833 | } |
@@ -886,6 +890,8 @@ static int l2cap_sock_release(struct socket *sock) | |||
886 | if (!sk) | 890 | if (!sk) |
887 | return 0; | 891 | return 0; |
888 | 892 | ||
893 | bt_sock_unlink(&l2cap_sk_list, sk); | ||
894 | |||
889 | err = l2cap_sock_shutdown(sock, 2); | 895 | err = l2cap_sock_shutdown(sock, 2); |
890 | 896 | ||
891 | sock_orphan(sk); | 897 | sock_orphan(sk); |
@@ -1210,6 +1216,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol, | |||
1210 | return -ENOMEM; | 1216 | return -ENOMEM; |
1211 | 1217 | ||
1212 | l2cap_sock_init(sk, NULL); | 1218 | l2cap_sock_init(sk, NULL); |
1219 | bt_sock_link(&l2cap_sk_list, sk); | ||
1213 | return 0; | 1220 | return 0; |
1214 | } | 1221 | } |
1215 | 1222 | ||
@@ -1248,21 +1255,30 @@ int __init l2cap_init_sockets(void) | |||
1248 | return err; | 1255 | return err; |
1249 | 1256 | ||
1250 | err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops); | 1257 | err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops); |
1251 | if (err < 0) | 1258 | if (err < 0) { |
1259 | BT_ERR("L2CAP socket registration failed"); | ||
1252 | goto error; | 1260 | goto error; |
1261 | } | ||
1262 | |||
1263 | err = bt_procfs_init(THIS_MODULE, &init_net, "l2cap", &l2cap_sk_list, NULL); | ||
1264 | if (err < 0) { | ||
1265 | BT_ERR("Failed to create L2CAP proc file"); | ||
1266 | bt_sock_unregister(BTPROTO_L2CAP); | ||
1267 | goto error; | ||
1268 | } | ||
1253 | 1269 | ||
1254 | BT_INFO("L2CAP socket layer initialized"); | 1270 | BT_INFO("L2CAP socket layer initialized"); |
1255 | 1271 | ||
1256 | return 0; | 1272 | return 0; |
1257 | 1273 | ||
1258 | error: | 1274 | error: |
1259 | BT_ERR("L2CAP socket registration failed"); | ||
1260 | proto_unregister(&l2cap_proto); | 1275 | proto_unregister(&l2cap_proto); |
1261 | return err; | 1276 | return err; |
1262 | } | 1277 | } |
1263 | 1278 | ||
1264 | void l2cap_cleanup_sockets(void) | 1279 | void l2cap_cleanup_sockets(void) |
1265 | { | 1280 | { |
1281 | bt_procfs_cleanup(&init_net, "l2cap"); | ||
1266 | if (bt_sock_unregister(BTPROTO_L2CAP) < 0) | 1282 | if (bt_sock_unregister(BTPROTO_L2CAP) < 0) |
1267 | BT_ERR("L2CAP socket unregistration failed"); | 1283 | BT_ERR("L2CAP socket unregistration failed"); |
1268 | 1284 | ||
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index ad6613d17ca6..a3329cbd3e4d 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -193,6 +193,11 @@ static u8 mgmt_status_table[] = { | |||
193 | MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */ | 193 | MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */ |
194 | }; | 194 | }; |
195 | 195 | ||
196 | bool mgmt_valid_hdev(struct hci_dev *hdev) | ||
197 | { | ||
198 | return hdev->dev_type == HCI_BREDR; | ||
199 | } | ||
200 | |||
196 | static u8 mgmt_status(u8 hci_status) | 201 | static u8 mgmt_status(u8 hci_status) |
197 | { | 202 | { |
198 | if (hci_status < ARRAY_SIZE(mgmt_status_table)) | 203 | if (hci_status < ARRAY_SIZE(mgmt_status_table)) |
@@ -317,7 +322,6 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, | |||
317 | u16 data_len) | 322 | u16 data_len) |
318 | { | 323 | { |
319 | struct mgmt_rp_read_index_list *rp; | 324 | struct mgmt_rp_read_index_list *rp; |
320 | struct list_head *p; | ||
321 | struct hci_dev *d; | 325 | struct hci_dev *d; |
322 | size_t rp_len; | 326 | size_t rp_len; |
323 | u16 count; | 327 | u16 count; |
@@ -328,7 +332,10 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, | |||
328 | read_lock(&hci_dev_list_lock); | 332 | read_lock(&hci_dev_list_lock); |
329 | 333 | ||
330 | count = 0; | 334 | count = 0; |
331 | list_for_each(p, &hci_dev_list) { | 335 | list_for_each_entry(d, &hci_dev_list, list) { |
336 | if (!mgmt_valid_hdev(d)) | ||
337 | continue; | ||
338 | |||
332 | count++; | 339 | count++; |
333 | } | 340 | } |
334 | 341 | ||
@@ -346,6 +353,9 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, | |||
346 | if (test_bit(HCI_SETUP, &d->dev_flags)) | 353 | if (test_bit(HCI_SETUP, &d->dev_flags)) |
347 | continue; | 354 | continue; |
348 | 355 | ||
356 | if (!mgmt_valid_hdev(d)) | ||
357 | continue; | ||
358 | |||
349 | rp->index[i++] = cpu_to_le16(d->id); | 359 | rp->index[i++] = cpu_to_le16(d->id); |
350 | BT_DBG("Added hci%u", d->id); | 360 | BT_DBG("Added hci%u", d->id); |
351 | } | 361 | } |
@@ -370,10 +380,10 @@ static u32 get_supported_settings(struct hci_dev *hdev) | |||
370 | settings |= MGMT_SETTING_DISCOVERABLE; | 380 | settings |= MGMT_SETTING_DISCOVERABLE; |
371 | settings |= MGMT_SETTING_PAIRABLE; | 381 | settings |= MGMT_SETTING_PAIRABLE; |
372 | 382 | ||
373 | if (hdev->features[6] & LMP_SIMPLE_PAIR) | 383 | if (lmp_ssp_capable(hdev)) |
374 | settings |= MGMT_SETTING_SSP; | 384 | settings |= MGMT_SETTING_SSP; |
375 | 385 | ||
376 | if (!(hdev->features[4] & LMP_NO_BREDR)) { | 386 | if (lmp_bredr_capable(hdev)) { |
377 | settings |= MGMT_SETTING_BREDR; | 387 | settings |= MGMT_SETTING_BREDR; |
378 | settings |= MGMT_SETTING_LINK_SECURITY; | 388 | settings |= MGMT_SETTING_LINK_SECURITY; |
379 | } | 389 | } |
@@ -381,7 +391,7 @@ static u32 get_supported_settings(struct hci_dev *hdev) | |||
381 | if (enable_hs) | 391 | if (enable_hs) |
382 | settings |= MGMT_SETTING_HS; | 392 | settings |= MGMT_SETTING_HS; |
383 | 393 | ||
384 | if (hdev->features[4] & LMP_LE) | 394 | if (lmp_le_capable(hdev)) |
385 | settings |= MGMT_SETTING_LE; | 395 | settings |= MGMT_SETTING_LE; |
386 | 396 | ||
387 | return settings; | 397 | return settings; |
@@ -403,7 +413,7 @@ static u32 get_current_settings(struct hci_dev *hdev) | |||
403 | if (test_bit(HCI_PAIRABLE, &hdev->dev_flags)) | 413 | if (test_bit(HCI_PAIRABLE, &hdev->dev_flags)) |
404 | settings |= MGMT_SETTING_PAIRABLE; | 414 | settings |= MGMT_SETTING_PAIRABLE; |
405 | 415 | ||
406 | if (!(hdev->features[4] & LMP_NO_BREDR)) | 416 | if (lmp_bredr_capable(hdev)) |
407 | settings |= MGMT_SETTING_BREDR; | 417 | settings |= MGMT_SETTING_BREDR; |
408 | 418 | ||
409 | if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) | 419 | if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) |
@@ -1111,7 +1121,7 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
1111 | 1121 | ||
1112 | hci_dev_lock(hdev); | 1122 | hci_dev_lock(hdev); |
1113 | 1123 | ||
1114 | if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) { | 1124 | if (!lmp_ssp_capable(hdev)) { |
1115 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, | 1125 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, |
1116 | MGMT_STATUS_NOT_SUPPORTED); | 1126 | MGMT_STATUS_NOT_SUPPORTED); |
1117 | goto failed; | 1127 | goto failed; |
@@ -1195,7 +1205,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
1195 | 1205 | ||
1196 | hci_dev_lock(hdev); | 1206 | hci_dev_lock(hdev); |
1197 | 1207 | ||
1198 | if (!(hdev->features[4] & LMP_LE)) { | 1208 | if (!lmp_le_capable(hdev)) { |
1199 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE, | 1209 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE, |
1200 | MGMT_STATUS_NOT_SUPPORTED); | 1210 | MGMT_STATUS_NOT_SUPPORTED); |
1201 | goto unlock; | 1211 | goto unlock; |
@@ -2191,7 +2201,7 @@ static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev, | |||
2191 | goto unlock; | 2201 | goto unlock; |
2192 | } | 2202 | } |
2193 | 2203 | ||
2194 | if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) { | 2204 | if (!lmp_ssp_capable(hdev)) { |
2195 | err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, | 2205 | err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, |
2196 | MGMT_STATUS_NOT_SUPPORTED); | 2206 | MGMT_STATUS_NOT_SUPPORTED); |
2197 | goto unlock; | 2207 | goto unlock; |
@@ -2820,6 +2830,9 @@ static void cmd_status_rsp(struct pending_cmd *cmd, void *data) | |||
2820 | 2830 | ||
2821 | int mgmt_index_added(struct hci_dev *hdev) | 2831 | int mgmt_index_added(struct hci_dev *hdev) |
2822 | { | 2832 | { |
2833 | if (!mgmt_valid_hdev(hdev)) | ||
2834 | return -ENOTSUPP; | ||
2835 | |||
2823 | return mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL); | 2836 | return mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL); |
2824 | } | 2837 | } |
2825 | 2838 | ||
@@ -2827,6 +2840,9 @@ int mgmt_index_removed(struct hci_dev *hdev) | |||
2827 | { | 2840 | { |
2828 | u8 status = MGMT_STATUS_INVALID_INDEX; | 2841 | u8 status = MGMT_STATUS_INVALID_INDEX; |
2829 | 2842 | ||
2843 | if (!mgmt_valid_hdev(hdev)) | ||
2844 | return -ENOTSUPP; | ||
2845 | |||
2830 | mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); | 2846 | mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); |
2831 | 2847 | ||
2832 | return mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL); | 2848 | return mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL); |
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 7e1e59645c05..260821a2d6e7 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c | |||
@@ -1033,8 +1033,17 @@ int __init rfcomm_init_sockets(void) | |||
1033 | return err; | 1033 | return err; |
1034 | 1034 | ||
1035 | err = bt_sock_register(BTPROTO_RFCOMM, &rfcomm_sock_family_ops); | 1035 | err = bt_sock_register(BTPROTO_RFCOMM, &rfcomm_sock_family_ops); |
1036 | if (err < 0) | 1036 | if (err < 0) { |
1037 | BT_ERR("RFCOMM socket layer registration failed"); | ||
1038 | goto error; | ||
1039 | } | ||
1040 | |||
1041 | err = bt_procfs_init(THIS_MODULE, &init_net, "rfcomm", &rfcomm_sk_list, NULL); | ||
1042 | if (err < 0) { | ||
1043 | BT_ERR("Failed to create RFCOMM proc file"); | ||
1044 | bt_sock_unregister(BTPROTO_RFCOMM); | ||
1037 | goto error; | 1045 | goto error; |
1046 | } | ||
1038 | 1047 | ||
1039 | if (bt_debugfs) { | 1048 | if (bt_debugfs) { |
1040 | rfcomm_sock_debugfs = debugfs_create_file("rfcomm", 0444, | 1049 | rfcomm_sock_debugfs = debugfs_create_file("rfcomm", 0444, |
@@ -1048,13 +1057,14 @@ int __init rfcomm_init_sockets(void) | |||
1048 | return 0; | 1057 | return 0; |
1049 | 1058 | ||
1050 | error: | 1059 | error: |
1051 | BT_ERR("RFCOMM socket layer registration failed"); | ||
1052 | proto_unregister(&rfcomm_proto); | 1060 | proto_unregister(&rfcomm_proto); |
1053 | return err; | 1061 | return err; |
1054 | } | 1062 | } |
1055 | 1063 | ||
1056 | void __exit rfcomm_cleanup_sockets(void) | 1064 | void __exit rfcomm_cleanup_sockets(void) |
1057 | { | 1065 | { |
1066 | bt_procfs_cleanup(&init_net, "rfcomm"); | ||
1067 | |||
1058 | debugfs_remove(rfcomm_sock_debugfs); | 1068 | debugfs_remove(rfcomm_sock_debugfs); |
1059 | 1069 | ||
1060 | if (bt_sock_unregister(BTPROTO_RFCOMM) < 0) | 1070 | if (bt_sock_unregister(BTPROTO_RFCOMM) < 0) |
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 40bbe25dcff7..caa109df6452 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
@@ -913,7 +913,7 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) | |||
913 | return lm; | 913 | return lm; |
914 | } | 914 | } |
915 | 915 | ||
916 | int sco_connect_cfm(struct hci_conn *hcon, __u8 status) | 916 | void sco_connect_cfm(struct hci_conn *hcon, __u8 status) |
917 | { | 917 | { |
918 | BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); | 918 | BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); |
919 | if (!status) { | 919 | if (!status) { |
@@ -924,16 +924,13 @@ int sco_connect_cfm(struct hci_conn *hcon, __u8 status) | |||
924 | sco_conn_ready(conn); | 924 | sco_conn_ready(conn); |
925 | } else | 925 | } else |
926 | sco_conn_del(hcon, bt_to_errno(status)); | 926 | sco_conn_del(hcon, bt_to_errno(status)); |
927 | |||
928 | return 0; | ||
929 | } | 927 | } |
930 | 928 | ||
931 | int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason) | 929 | void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason) |
932 | { | 930 | { |
933 | BT_DBG("hcon %p reason %d", hcon, reason); | 931 | BT_DBG("hcon %p reason %d", hcon, reason); |
934 | 932 | ||
935 | sco_conn_del(hcon, bt_to_errno(reason)); | 933 | sco_conn_del(hcon, bt_to_errno(reason)); |
936 | return 0; | ||
937 | } | 934 | } |
938 | 935 | ||
939 | int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb) | 936 | int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb) |
@@ -1026,6 +1023,13 @@ int __init sco_init(void) | |||
1026 | goto error; | 1023 | goto error; |
1027 | } | 1024 | } |
1028 | 1025 | ||
1026 | err = bt_procfs_init(THIS_MODULE, &init_net, "sco", &sco_sk_list, NULL); | ||
1027 | if (err < 0) { | ||
1028 | BT_ERR("Failed to create SCO proc file"); | ||
1029 | bt_sock_unregister(BTPROTO_SCO); | ||
1030 | goto error; | ||
1031 | } | ||
1032 | |||
1029 | if (bt_debugfs) { | 1033 | if (bt_debugfs) { |
1030 | sco_debugfs = debugfs_create_file("sco", 0444, bt_debugfs, | 1034 | sco_debugfs = debugfs_create_file("sco", 0444, bt_debugfs, |
1031 | NULL, &sco_debugfs_fops); | 1035 | NULL, &sco_debugfs_fops); |
@@ -1044,6 +1048,8 @@ error: | |||
1044 | 1048 | ||
1045 | void __exit sco_exit(void) | 1049 | void __exit sco_exit(void) |
1046 | { | 1050 | { |
1051 | bt_procfs_cleanup(&init_net, "sco"); | ||
1052 | |||
1047 | debugfs_remove(sco_debugfs); | 1053 | debugfs_remove(sco_debugfs); |
1048 | 1054 | ||
1049 | if (bt_sock_unregister(BTPROTO_SCO) < 0) | 1055 | if (bt_sock_unregister(BTPROTO_SCO) < 0) |