diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-09-28 11:11:16 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-09-28 11:11:16 -0400 |
commit | c487606f835a93a725bac1aefd536be98f22474d (patch) | |
tree | c77571a519905945e24a9ea6e4e44d9032fd527d /net/bluetooth | |
parent | d9f72f359e00a45a6cd7cc2d5121b04b9dc927e1 (diff) | |
parent | 97ea6d0f3eb019891038cd2dfddb749d6bf219be (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Conflicts:
net/nfc/netlink.c
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/af_bluetooth.c | 10 | ||||
-rw-r--r-- | net/bluetooth/hci_conn.c | 100 | ||||
-rw-r--r-- | net/bluetooth/hci_core.c | 6 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 99 | ||||
-rw-r--r-- | net/bluetooth/l2cap_core.c | 17 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 28 |
6 files changed, 195 insertions, 65 deletions
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 58f9762b339a..9d49ee6d7219 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c | |||
@@ -567,8 +567,6 @@ static void bt_seq_stop(struct seq_file *seq, void *v) | |||
567 | 567 | ||
568 | static int bt_seq_show(struct seq_file *seq, void *v) | 568 | static int bt_seq_show(struct seq_file *seq, void *v) |
569 | { | 569 | { |
570 | struct sock *sk; | ||
571 | struct bt_sock *bt; | ||
572 | struct bt_seq_state *s = seq->private; | 570 | struct bt_seq_state *s = seq->private; |
573 | struct bt_sock_list *l = s->l; | 571 | struct bt_sock_list *l = s->l; |
574 | bdaddr_t src_baswapped, dst_baswapped; | 572 | bdaddr_t src_baswapped, dst_baswapped; |
@@ -583,8 +581,8 @@ static int bt_seq_show(struct seq_file *seq, void *v) | |||
583 | 581 | ||
584 | seq_putc(seq, '\n'); | 582 | seq_putc(seq, '\n'); |
585 | } else { | 583 | } else { |
586 | sk = sk_entry(v); | 584 | struct sock *sk = sk_entry(v); |
587 | bt = bt_sk(sk); | 585 | struct bt_sock *bt = bt_sk(sk); |
588 | baswap(&src_baswapped, &bt->src); | 586 | baswap(&src_baswapped, &bt->src); |
589 | baswap(&dst_baswapped, &bt->dst); | 587 | baswap(&dst_baswapped, &bt->dst); |
590 | 588 | ||
@@ -624,7 +622,7 @@ static int bt_seq_open(struct inode *inode, struct file *file) | |||
624 | sk_list = PDE(inode)->data; | 622 | sk_list = PDE(inode)->data; |
625 | s = __seq_open_private(file, &bt_seq_ops, | 623 | s = __seq_open_private(file, &bt_seq_ops, |
626 | sizeof(struct bt_seq_state)); | 624 | sizeof(struct bt_seq_state)); |
627 | if (s == NULL) | 625 | if (!s) |
628 | return -ENOMEM; | 626 | return -ENOMEM; |
629 | 627 | ||
630 | s->l = sk_list; | 628 | s->l = sk_list; |
@@ -646,7 +644,7 @@ int bt_procfs_init(struct module* module, struct net *net, const char *name, | |||
646 | sk_list->fops.release = seq_release_private; | 644 | sk_list->fops.release = seq_release_private; |
647 | 645 | ||
648 | pde = proc_net_fops_create(net, name, 0, &sk_list->fops); | 646 | pde = proc_net_fops_create(net, name, 0, &sk_list->fops); |
649 | if (pde == NULL) | 647 | if (!pde) |
650 | return -ENOMEM; | 648 | return -ENOMEM; |
651 | 649 | ||
652 | pde->data = sk_list; | 650 | pde->data = sk_list; |
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 3c094e78dde9..b9196a44f759 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #include <net/bluetooth/a2mp.h> | 31 | #include <net/bluetooth/a2mp.h> |
32 | #include <net/bluetooth/smp.h> | 32 | #include <net/bluetooth/smp.h> |
33 | 33 | ||
34 | static void hci_le_connect(struct hci_conn *conn) | 34 | static void hci_le_create_connection(struct hci_conn *conn) |
35 | { | 35 | { |
36 | struct hci_dev *hdev = conn->hdev; | 36 | struct hci_dev *hdev = conn->hdev; |
37 | struct hci_cp_le_create_conn cp; | 37 | struct hci_cp_le_create_conn cp; |
@@ -55,12 +55,12 @@ static void hci_le_connect(struct hci_conn *conn) | |||
55 | hci_send_cmd(hdev, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp); | 55 | hci_send_cmd(hdev, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp); |
56 | } | 56 | } |
57 | 57 | ||
58 | static void hci_le_connect_cancel(struct hci_conn *conn) | 58 | static void hci_le_create_connection_cancel(struct hci_conn *conn) |
59 | { | 59 | { |
60 | hci_send_cmd(conn->hdev, HCI_OP_LE_CREATE_CONN_CANCEL, 0, NULL); | 60 | hci_send_cmd(conn->hdev, HCI_OP_LE_CREATE_CONN_CANCEL, 0, NULL); |
61 | } | 61 | } |
62 | 62 | ||
63 | void hci_acl_connect(struct hci_conn *conn) | 63 | static void hci_acl_create_connection(struct hci_conn *conn) |
64 | { | 64 | { |
65 | struct hci_dev *hdev = conn->hdev; | 65 | struct hci_dev *hdev = conn->hdev; |
66 | struct inquiry_entry *ie; | 66 | struct inquiry_entry *ie; |
@@ -104,7 +104,7 @@ void hci_acl_connect(struct hci_conn *conn) | |||
104 | hci_send_cmd(hdev, HCI_OP_CREATE_CONN, sizeof(cp), &cp); | 104 | hci_send_cmd(hdev, HCI_OP_CREATE_CONN, sizeof(cp), &cp); |
105 | } | 105 | } |
106 | 106 | ||
107 | static void hci_acl_connect_cancel(struct hci_conn *conn) | 107 | static void hci_acl_create_connection_cancel(struct hci_conn *conn) |
108 | { | 108 | { |
109 | struct hci_cp_create_conn_cancel cp; | 109 | struct hci_cp_create_conn_cancel cp; |
110 | 110 | ||
@@ -130,7 +130,7 @@ void hci_acl_disconn(struct hci_conn *conn, __u8 reason) | |||
130 | hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp); | 130 | hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp); |
131 | } | 131 | } |
132 | 132 | ||
133 | void hci_add_sco(struct hci_conn *conn, __u16 handle) | 133 | static void hci_add_sco(struct hci_conn *conn, __u16 handle) |
134 | { | 134 | { |
135 | struct hci_dev *hdev = conn->hdev; | 135 | struct hci_dev *hdev = conn->hdev; |
136 | struct hci_cp_add_sco cp; | 136 | struct hci_cp_add_sco cp; |
@@ -246,9 +246,9 @@ static void hci_conn_timeout(struct work_struct *work) | |||
246 | case BT_CONNECT2: | 246 | case BT_CONNECT2: |
247 | if (conn->out) { | 247 | if (conn->out) { |
248 | if (conn->type == ACL_LINK) | 248 | if (conn->type == ACL_LINK) |
249 | hci_acl_connect_cancel(conn); | 249 | hci_acl_create_connection_cancel(conn); |
250 | else if (conn->type == LE_LINK) | 250 | else if (conn->type == LE_LINK) |
251 | hci_le_connect_cancel(conn); | 251 | hci_le_create_connection_cancel(conn); |
252 | } | 252 | } |
253 | break; | 253 | break; |
254 | case BT_CONFIG: | 254 | case BT_CONFIG: |
@@ -471,40 +471,37 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src) | |||
471 | } | 471 | } |
472 | EXPORT_SYMBOL(hci_get_route); | 472 | EXPORT_SYMBOL(hci_get_route); |
473 | 473 | ||
474 | /* Create SCO, ACL or LE connection. | 474 | static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, |
475 | * Device _must_ be locked */ | 475 | u8 dst_type, u8 sec_level, u8 auth_type) |
476 | struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, | ||
477 | __u8 dst_type, __u8 sec_level, __u8 auth_type) | ||
478 | { | 476 | { |
479 | struct hci_conn *acl; | ||
480 | struct hci_conn *sco; | ||
481 | struct hci_conn *le; | 477 | struct hci_conn *le; |
482 | 478 | ||
483 | BT_DBG("%s dst %s", hdev->name, batostr(dst)); | 479 | le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst); |
480 | if (!le) { | ||
481 | le = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); | ||
482 | if (le) | ||
483 | return ERR_PTR(-EBUSY); | ||
484 | 484 | ||
485 | if (type == LE_LINK) { | 485 | le = hci_conn_add(hdev, LE_LINK, dst); |
486 | le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst); | 486 | if (!le) |
487 | if (!le) { | 487 | return ERR_PTR(-ENOMEM); |
488 | le = hci_conn_hash_lookup_state(hdev, LE_LINK, | ||
489 | BT_CONNECT); | ||
490 | if (le) | ||
491 | return ERR_PTR(-EBUSY); | ||
492 | 488 | ||
493 | le = hci_conn_add(hdev, LE_LINK, dst); | 489 | le->dst_type = bdaddr_to_le(dst_type); |
494 | if (!le) | 490 | hci_le_create_connection(le); |
495 | return ERR_PTR(-ENOMEM); | 491 | } |
496 | 492 | ||
497 | le->dst_type = bdaddr_to_le(dst_type); | 493 | le->pending_sec_level = sec_level; |
498 | hci_le_connect(le); | 494 | le->auth_type = auth_type; |
499 | } | ||
500 | 495 | ||
501 | le->pending_sec_level = sec_level; | 496 | hci_conn_hold(le); |
502 | le->auth_type = auth_type; | ||
503 | 497 | ||
504 | hci_conn_hold(le); | 498 | return le; |
499 | } | ||
505 | 500 | ||
506 | return le; | 501 | static struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, |
507 | } | 502 | u8 sec_level, u8 auth_type) |
503 | { | ||
504 | struct hci_conn *acl; | ||
508 | 505 | ||
509 | acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst); | 506 | acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst); |
510 | if (!acl) { | 507 | if (!acl) { |
@@ -519,10 +516,20 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, | |||
519 | acl->sec_level = BT_SECURITY_LOW; | 516 | acl->sec_level = BT_SECURITY_LOW; |
520 | acl->pending_sec_level = sec_level; | 517 | acl->pending_sec_level = sec_level; |
521 | acl->auth_type = auth_type; | 518 | acl->auth_type = auth_type; |
522 | hci_acl_connect(acl); | 519 | hci_acl_create_connection(acl); |
523 | } | 520 | } |
524 | 521 | ||
525 | if (type == ACL_LINK) | 522 | return acl; |
523 | } | ||
524 | |||
525 | static struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, | ||
526 | bdaddr_t *dst, u8 sec_level, u8 auth_type) | ||
527 | { | ||
528 | struct hci_conn *acl; | ||
529 | struct hci_conn *sco; | ||
530 | |||
531 | acl = hci_connect_acl(hdev, dst, sec_level, auth_type); | ||
532 | if (IS_ERR(acl)) | ||
526 | return acl; | 533 | return acl; |
527 | 534 | ||
528 | sco = hci_conn_hash_lookup_ba(hdev, type, dst); | 535 | sco = hci_conn_hash_lookup_ba(hdev, type, dst); |
@@ -556,6 +563,25 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, | |||
556 | return sco; | 563 | return sco; |
557 | } | 564 | } |
558 | 565 | ||
566 | /* Create SCO, ACL or LE connection. */ | ||
567 | struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, | ||
568 | __u8 dst_type, __u8 sec_level, __u8 auth_type) | ||
569 | { | ||
570 | BT_DBG("%s dst %s type 0x%x", hdev->name, batostr(dst), type); | ||
571 | |||
572 | switch (type) { | ||
573 | case LE_LINK: | ||
574 | return hci_connect_le(hdev, dst, dst_type, sec_level, auth_type); | ||
575 | case ACL_LINK: | ||
576 | return hci_connect_acl(hdev, dst, sec_level, auth_type); | ||
577 | case SCO_LINK: | ||
578 | case ESCO_LINK: | ||
579 | return hci_connect_sco(hdev, type, dst, sec_level, auth_type); | ||
580 | } | ||
581 | |||
582 | return ERR_PTR(-EINVAL); | ||
583 | } | ||
584 | |||
559 | /* Check link security requirement */ | 585 | /* Check link security requirement */ |
560 | int hci_conn_check_link_mode(struct hci_conn *conn) | 586 | int hci_conn_check_link_mode(struct hci_conn *conn) |
561 | { | 587 | { |
@@ -775,7 +801,7 @@ void hci_conn_check_pending(struct hci_dev *hdev) | |||
775 | 801 | ||
776 | conn = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2); | 802 | conn = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2); |
777 | if (conn) | 803 | if (conn) |
778 | hci_acl_connect(conn); | 804 | hci_acl_create_connection(conn); |
779 | 805 | ||
780 | hci_dev_unlock(hdev); | 806 | hci_dev_unlock(hdev); |
781 | } | 807 | } |
@@ -913,7 +939,7 @@ struct hci_chan *hci_chan_create(struct hci_conn *conn) | |||
913 | return chan; | 939 | return chan; |
914 | } | 940 | } |
915 | 941 | ||
916 | int hci_chan_del(struct hci_chan *chan) | 942 | void hci_chan_del(struct hci_chan *chan) |
917 | { | 943 | { |
918 | struct hci_conn *conn = chan->conn; | 944 | struct hci_conn *conn = chan->conn; |
919 | struct hci_dev *hdev = conn->hdev; | 945 | struct hci_dev *hdev = conn->hdev; |
@@ -926,8 +952,6 @@ int hci_chan_del(struct hci_chan *chan) | |||
926 | 952 | ||
927 | skb_queue_purge(&chan->data_q); | 953 | skb_queue_purge(&chan->data_q); |
928 | kfree(chan); | 954 | kfree(chan); |
929 | |||
930 | return 0; | ||
931 | } | 955 | } |
932 | 956 | ||
933 | void hci_chan_list_flush(struct hci_conn *conn) | 957 | void hci_chan_list_flush(struct hci_conn *conn) |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index fa974a19d365..e4070517ff3b 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -231,6 +231,9 @@ static void amp_init(struct hci_dev *hdev) | |||
231 | 231 | ||
232 | /* Read Local AMP Info */ | 232 | /* Read Local AMP Info */ |
233 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL); | 233 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL); |
234 | |||
235 | /* Read Data Blk size */ | ||
236 | hci_send_cmd(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, 0, NULL); | ||
234 | } | 237 | } |
235 | 238 | ||
236 | static void hci_init_req(struct hci_dev *hdev, unsigned long opt) | 239 | static void hci_init_req(struct hci_dev *hdev, unsigned long opt) |
@@ -268,7 +271,6 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt) | |||
268 | BT_ERR("Unknown device type %d", hdev->dev_type); | 271 | BT_ERR("Unknown device type %d", hdev->dev_type); |
269 | break; | 272 | break; |
270 | } | 273 | } |
271 | |||
272 | } | 274 | } |
273 | 275 | ||
274 | static void hci_le_init_req(struct hci_dev *hdev, unsigned long opt) | 276 | static void hci_le_init_req(struct hci_dev *hdev, unsigned long opt) |
@@ -1652,6 +1654,7 @@ struct hci_dev *hci_alloc_dev(void) | |||
1652 | INIT_LIST_HEAD(&hdev->link_keys); | 1654 | INIT_LIST_HEAD(&hdev->link_keys); |
1653 | INIT_LIST_HEAD(&hdev->long_term_keys); | 1655 | INIT_LIST_HEAD(&hdev->long_term_keys); |
1654 | INIT_LIST_HEAD(&hdev->remote_oob_data); | 1656 | INIT_LIST_HEAD(&hdev->remote_oob_data); |
1657 | INIT_LIST_HEAD(&hdev->conn_hash.list); | ||
1655 | 1658 | ||
1656 | INIT_WORK(&hdev->rx_work, hci_rx_work); | 1659 | INIT_WORK(&hdev->rx_work, hci_rx_work); |
1657 | INIT_WORK(&hdev->cmd_work, hci_cmd_work); | 1660 | INIT_WORK(&hdev->cmd_work, hci_cmd_work); |
@@ -1674,7 +1677,6 @@ struct hci_dev *hci_alloc_dev(void) | |||
1674 | 1677 | ||
1675 | hci_init_sysfs(hdev); | 1678 | hci_init_sysfs(hdev); |
1676 | discovery_init(hdev); | 1679 | discovery_init(hdev); |
1677 | hci_conn_hash_init(hdev); | ||
1678 | 1680 | ||
1679 | return hdev; | 1681 | return hdev; |
1680 | } | 1682 | } |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 4fd2cf3bcd05..2022b43c7353 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -29,6 +29,7 @@ | |||
29 | 29 | ||
30 | #include <net/bluetooth/bluetooth.h> | 30 | #include <net/bluetooth/bluetooth.h> |
31 | #include <net/bluetooth/hci_core.h> | 31 | #include <net/bluetooth/hci_core.h> |
32 | #include <net/bluetooth/mgmt.h> | ||
32 | 33 | ||
33 | /* Handle HCI Event packets */ | 34 | /* Handle HCI Event packets */ |
34 | 35 | ||
@@ -303,7 +304,7 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) | |||
303 | 304 | ||
304 | hci_dev_lock(hdev); | 305 | hci_dev_lock(hdev); |
305 | 306 | ||
306 | if (status != 0) { | 307 | if (status) { |
307 | mgmt_write_scan_failed(hdev, param, status); | 308 | mgmt_write_scan_failed(hdev, param, status); |
308 | hdev->discov_timeout = 0; | 309 | hdev->discov_timeout = 0; |
309 | goto done; | 310 | goto done; |
@@ -925,7 +926,7 @@ static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) | |||
925 | if (test_bit(HCI_MGMT, &hdev->dev_flags)) | 926 | if (test_bit(HCI_MGMT, &hdev->dev_flags)) |
926 | mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); | 927 | mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); |
927 | 928 | ||
928 | if (rp->status != 0) | 929 | if (rp->status) |
929 | goto unlock; | 930 | goto unlock; |
930 | 931 | ||
931 | cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); | 932 | cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); |
@@ -1891,6 +1892,22 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
1891 | } | 1892 | } |
1892 | } | 1893 | } |
1893 | 1894 | ||
1895 | static u8 hci_to_mgmt_reason(u8 err) | ||
1896 | { | ||
1897 | switch (err) { | ||
1898 | case HCI_ERROR_CONNECTION_TIMEOUT: | ||
1899 | return MGMT_DEV_DISCONN_TIMEOUT; | ||
1900 | case HCI_ERROR_REMOTE_USER_TERM: | ||
1901 | case HCI_ERROR_REMOTE_LOW_RESOURCES: | ||
1902 | case HCI_ERROR_REMOTE_POWER_OFF: | ||
1903 | return MGMT_DEV_DISCONN_REMOTE; | ||
1904 | case HCI_ERROR_LOCAL_HOST_TERM: | ||
1905 | return MGMT_DEV_DISCONN_LOCAL_HOST; | ||
1906 | default: | ||
1907 | return MGMT_DEV_DISCONN_UNKNOWN; | ||
1908 | } | ||
1909 | } | ||
1910 | |||
1894 | static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1911 | static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1895 | { | 1912 | { |
1896 | struct hci_ev_disconn_complete *ev = (void *) skb->data; | 1913 | struct hci_ev_disconn_complete *ev = (void *) skb->data; |
@@ -1909,12 +1926,15 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
1909 | 1926 | ||
1910 | if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) && | 1927 | if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) && |
1911 | (conn->type == ACL_LINK || conn->type == LE_LINK)) { | 1928 | (conn->type == ACL_LINK || conn->type == LE_LINK)) { |
1912 | if (ev->status != 0) | 1929 | if (ev->status) { |
1913 | mgmt_disconnect_failed(hdev, &conn->dst, conn->type, | 1930 | mgmt_disconnect_failed(hdev, &conn->dst, conn->type, |
1914 | conn->dst_type, ev->status); | 1931 | conn->dst_type, ev->status); |
1915 | else | 1932 | } else { |
1933 | u8 reason = hci_to_mgmt_reason(ev->reason); | ||
1934 | |||
1916 | mgmt_device_disconnected(hdev, &conn->dst, conn->type, | 1935 | mgmt_device_disconnected(hdev, &conn->dst, conn->type, |
1917 | conn->dst_type); | 1936 | conn->dst_type, reason); |
1937 | } | ||
1918 | } | 1938 | } |
1919 | 1939 | ||
1920 | if (ev->status == 0) { | 1940 | if (ev->status == 0) { |
@@ -3259,6 +3279,65 @@ static void hci_user_passkey_request_evt(struct hci_dev *hdev, | |||
3259 | mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); | 3279 | mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); |
3260 | } | 3280 | } |
3261 | 3281 | ||
3282 | static void hci_user_passkey_notify_evt(struct hci_dev *hdev, | ||
3283 | struct sk_buff *skb) | ||
3284 | { | ||
3285 | struct hci_ev_user_passkey_notify *ev = (void *) skb->data; | ||
3286 | struct hci_conn *conn; | ||
3287 | |||
3288 | BT_DBG("%s", hdev->name); | ||
3289 | |||
3290 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); | ||
3291 | if (!conn) | ||
3292 | return; | ||
3293 | |||
3294 | conn->passkey_notify = __le32_to_cpu(ev->passkey); | ||
3295 | conn->passkey_entered = 0; | ||
3296 | |||
3297 | if (test_bit(HCI_MGMT, &hdev->dev_flags)) | ||
3298 | mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, | ||
3299 | conn->dst_type, conn->passkey_notify, | ||
3300 | conn->passkey_entered); | ||
3301 | } | ||
3302 | |||
3303 | static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
3304 | { | ||
3305 | struct hci_ev_keypress_notify *ev = (void *) skb->data; | ||
3306 | struct hci_conn *conn; | ||
3307 | |||
3308 | BT_DBG("%s", hdev->name); | ||
3309 | |||
3310 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); | ||
3311 | if (!conn) | ||
3312 | return; | ||
3313 | |||
3314 | switch (ev->type) { | ||
3315 | case HCI_KEYPRESS_STARTED: | ||
3316 | conn->passkey_entered = 0; | ||
3317 | return; | ||
3318 | |||
3319 | case HCI_KEYPRESS_ENTERED: | ||
3320 | conn->passkey_entered++; | ||
3321 | break; | ||
3322 | |||
3323 | case HCI_KEYPRESS_ERASED: | ||
3324 | conn->passkey_entered--; | ||
3325 | break; | ||
3326 | |||
3327 | case HCI_KEYPRESS_CLEARED: | ||
3328 | conn->passkey_entered = 0; | ||
3329 | break; | ||
3330 | |||
3331 | case HCI_KEYPRESS_COMPLETED: | ||
3332 | return; | ||
3333 | } | ||
3334 | |||
3335 | if (test_bit(HCI_MGMT, &hdev->dev_flags)) | ||
3336 | mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, | ||
3337 | conn->dst_type, conn->passkey_notify, | ||
3338 | conn->passkey_entered); | ||
3339 | } | ||
3340 | |||
3262 | static void hci_simple_pair_complete_evt(struct hci_dev *hdev, | 3341 | static void hci_simple_pair_complete_evt(struct hci_dev *hdev, |
3263 | struct sk_buff *skb) | 3342 | struct sk_buff *skb) |
3264 | { | 3343 | { |
@@ -3278,7 +3357,7 @@ static void hci_simple_pair_complete_evt(struct hci_dev *hdev, | |||
3278 | * initiated the authentication. A traditional auth_complete | 3357 | * initiated the authentication. A traditional auth_complete |
3279 | * event gets always produced as initiator and is also mapped to | 3358 | * event gets always produced as initiator and is also mapped to |
3280 | * the mgmt_auth_failed event */ | 3359 | * the mgmt_auth_failed event */ |
3281 | if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status != 0) | 3360 | if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status) |
3282 | mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, | 3361 | mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, |
3283 | ev->status); | 3362 | ev->status); |
3284 | 3363 | ||
@@ -3623,6 +3702,14 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
3623 | hci_user_passkey_request_evt(hdev, skb); | 3702 | hci_user_passkey_request_evt(hdev, skb); |
3624 | break; | 3703 | break; |
3625 | 3704 | ||
3705 | case HCI_EV_USER_PASSKEY_NOTIFY: | ||
3706 | hci_user_passkey_notify_evt(hdev, skb); | ||
3707 | break; | ||
3708 | |||
3709 | case HCI_EV_KEYPRESS_NOTIFY: | ||
3710 | hci_keypress_notify_evt(hdev, skb); | ||
3711 | break; | ||
3712 | |||
3626 | case HCI_EV_SIMPLE_PAIR_COMPLETE: | 3713 | case HCI_EV_SIMPLE_PAIR_COMPLETE: |
3627 | hci_simple_pair_complete_evt(hdev, skb); | 3714 | hci_simple_pair_complete_evt(hdev, skb); |
3628 | break; | 3715 | break; |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index e0abaf3cb6a5..7a59e929febc 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -406,7 +406,7 @@ struct l2cap_chan *l2cap_chan_create(void) | |||
406 | 406 | ||
407 | chan->state = BT_OPEN; | 407 | chan->state = BT_OPEN; |
408 | 408 | ||
409 | atomic_set(&chan->refcnt, 1); | 409 | kref_init(&chan->kref); |
410 | 410 | ||
411 | /* This flag is cleared in l2cap_chan_ready() */ | 411 | /* This flag is cleared in l2cap_chan_ready() */ |
412 | set_bit(CONF_NOT_COMPLETE, &chan->conf_state); | 412 | set_bit(CONF_NOT_COMPLETE, &chan->conf_state); |
@@ -416,8 +416,10 @@ struct l2cap_chan *l2cap_chan_create(void) | |||
416 | return chan; | 416 | return chan; |
417 | } | 417 | } |
418 | 418 | ||
419 | static void l2cap_chan_destroy(struct l2cap_chan *chan) | 419 | static void l2cap_chan_destroy(struct kref *kref) |
420 | { | 420 | { |
421 | struct l2cap_chan *chan = container_of(kref, struct l2cap_chan, kref); | ||
422 | |||
421 | BT_DBG("chan %p", chan); | 423 | BT_DBG("chan %p", chan); |
422 | 424 | ||
423 | write_lock(&chan_list_lock); | 425 | write_lock(&chan_list_lock); |
@@ -429,17 +431,16 @@ static void l2cap_chan_destroy(struct l2cap_chan *chan) | |||
429 | 431 | ||
430 | void l2cap_chan_hold(struct l2cap_chan *c) | 432 | void l2cap_chan_hold(struct l2cap_chan *c) |
431 | { | 433 | { |
432 | BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt)); | 434 | BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->kref.refcount)); |
433 | 435 | ||
434 | atomic_inc(&c->refcnt); | 436 | kref_get(&c->kref); |
435 | } | 437 | } |
436 | 438 | ||
437 | void l2cap_chan_put(struct l2cap_chan *c) | 439 | void l2cap_chan_put(struct l2cap_chan *c) |
438 | { | 440 | { |
439 | BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt)); | 441 | BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->kref.refcount)); |
440 | 442 | ||
441 | if (atomic_dec_and_test(&c->refcnt)) | 443 | kref_put(&c->kref, l2cap_chan_destroy); |
442 | l2cap_chan_destroy(c); | ||
443 | } | 444 | } |
444 | 445 | ||
445 | void l2cap_chan_set_defaults(struct l2cap_chan *chan) | 446 | void l2cap_chan_set_defaults(struct l2cap_chan *chan) |
@@ -1448,7 +1449,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | |||
1448 | int err; | 1449 | int err; |
1449 | 1450 | ||
1450 | BT_DBG("%s -> %s (type %u) psm 0x%2.2x", batostr(src), batostr(dst), | 1451 | BT_DBG("%s -> %s (type %u) psm 0x%2.2x", batostr(src), batostr(dst), |
1451 | dst_type, __le16_to_cpu(chan->psm)); | 1452 | dst_type, __le16_to_cpu(psm)); |
1452 | 1453 | ||
1453 | hdev = hci_get_route(dst, src); | 1454 | hdev = hci_get_route(dst, src); |
1454 | if (!hdev) | 1455 | if (!hdev) |
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index a3329cbd3e4d..8934343be0ea 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -35,7 +35,7 @@ | |||
35 | bool enable_hs; | 35 | bool enable_hs; |
36 | 36 | ||
37 | #define MGMT_VERSION 1 | 37 | #define MGMT_VERSION 1 |
38 | #define MGMT_REVISION 1 | 38 | #define MGMT_REVISION 2 |
39 | 39 | ||
40 | static const u16 mgmt_commands[] = { | 40 | static const u16 mgmt_commands[] = { |
41 | MGMT_OP_READ_INDEX_LIST, | 41 | MGMT_OP_READ_INDEX_LIST, |
@@ -99,6 +99,7 @@ static const u16 mgmt_events[] = { | |||
99 | MGMT_EV_DEVICE_BLOCKED, | 99 | MGMT_EV_DEVICE_BLOCKED, |
100 | MGMT_EV_DEVICE_UNBLOCKED, | 100 | MGMT_EV_DEVICE_UNBLOCKED, |
101 | MGMT_EV_DEVICE_UNPAIRED, | 101 | MGMT_EV_DEVICE_UNPAIRED, |
102 | MGMT_EV_PASSKEY_NOTIFY, | ||
102 | }; | 103 | }; |
103 | 104 | ||
104 | /* | 105 | /* |
@@ -3077,16 +3078,17 @@ static void unpair_device_rsp(struct pending_cmd *cmd, void *data) | |||
3077 | } | 3078 | } |
3078 | 3079 | ||
3079 | int mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, | 3080 | int mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, |
3080 | u8 link_type, u8 addr_type) | 3081 | u8 link_type, u8 addr_type, u8 reason) |
3081 | { | 3082 | { |
3082 | struct mgmt_addr_info ev; | 3083 | struct mgmt_ev_device_disconnected ev; |
3083 | struct sock *sk = NULL; | 3084 | struct sock *sk = NULL; |
3084 | int err; | 3085 | int err; |
3085 | 3086 | ||
3086 | mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk); | 3087 | mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk); |
3087 | 3088 | ||
3088 | bacpy(&ev.bdaddr, bdaddr); | 3089 | bacpy(&ev.addr.bdaddr, bdaddr); |
3089 | ev.type = link_to_bdaddr(link_type, addr_type); | 3090 | ev.addr.type = link_to_bdaddr(link_type, addr_type); |
3091 | ev.reason = reason; | ||
3090 | 3092 | ||
3091 | err = mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), | 3093 | err = mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), |
3092 | sk); | 3094 | sk); |
@@ -3275,6 +3277,22 @@ int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
3275 | MGMT_OP_USER_PASSKEY_NEG_REPLY); | 3277 | MGMT_OP_USER_PASSKEY_NEG_REPLY); |
3276 | } | 3278 | } |
3277 | 3279 | ||
3280 | int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr, | ||
3281 | u8 link_type, u8 addr_type, u32 passkey, | ||
3282 | u8 entered) | ||
3283 | { | ||
3284 | struct mgmt_ev_passkey_notify ev; | ||
3285 | |||
3286 | BT_DBG("%s", hdev->name); | ||
3287 | |||
3288 | bacpy(&ev.addr.bdaddr, bdaddr); | ||
3289 | ev.addr.type = link_to_bdaddr(link_type, addr_type); | ||
3290 | ev.passkey = __cpu_to_le32(passkey); | ||
3291 | ev.entered = entered; | ||
3292 | |||
3293 | return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL); | ||
3294 | } | ||
3295 | |||
3278 | int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | 3296 | int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, |
3279 | u8 addr_type, u8 status) | 3297 | u8 addr_type, u8 status) |
3280 | { | 3298 | { |