diff options
| author | John W. Linville <linville@tuxdriver.com> | 2012-09-24 14:39:16 -0400 |
|---|---|---|
| committer | John W. Linville <linville@tuxdriver.com> | 2012-09-24 14:39:16 -0400 |
| commit | 791ef39cd18ae2745a63c51a5dbbd23312be0744 (patch) | |
| tree | 195a547ce1bde51ba3f37cd771648c18d84cc947 /net/bluetooth | |
| parent | e5a876250d05d9708895da3d5408bdf67f1180f3 (diff) | |
| parent | 0c1abbd1aa0416258881c303a88e618cbca0759c (diff) | |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
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 | { |
