diff options
Diffstat (limited to 'net/bluetooth/hci_conn.c')
-rw-r--r-- | net/bluetooth/hci_conn.c | 100 |
1 files changed, 62 insertions, 38 deletions
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 3c094e78dde..b9196a44f75 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) |