diff options
Diffstat (limited to 'net/bluetooth/hci_conn.c')
-rw-r--r-- | net/bluetooth/hci_conn.c | 70 |
1 files changed, 64 insertions, 6 deletions
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index b9196a44f759..fe646211c61f 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -130,6 +130,20 @@ 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 | static void hci_amp_disconn(struct hci_conn *conn, __u8 reason) | ||
134 | { | ||
135 | struct hci_cp_disconn_phy_link cp; | ||
136 | |||
137 | BT_DBG("hcon %p", conn); | ||
138 | |||
139 | conn->state = BT_DISCONN; | ||
140 | |||
141 | cp.phy_handle = HCI_PHY_HANDLE(conn->handle); | ||
142 | cp.reason = reason; | ||
143 | hci_send_cmd(conn->hdev, HCI_OP_DISCONN_PHY_LINK, | ||
144 | sizeof(cp), &cp); | ||
145 | } | ||
146 | |||
133 | static void hci_add_sco(struct hci_conn *conn, __u16 handle) | 147 | static void hci_add_sco(struct hci_conn *conn, __u16 handle) |
134 | { | 148 | { |
135 | struct hci_dev *hdev = conn->hdev; | 149 | struct hci_dev *hdev = conn->hdev; |
@@ -230,11 +244,24 @@ void hci_sco_setup(struct hci_conn *conn, __u8 status) | |||
230 | } | 244 | } |
231 | } | 245 | } |
232 | 246 | ||
247 | static void hci_conn_disconnect(struct hci_conn *conn) | ||
248 | { | ||
249 | __u8 reason = hci_proto_disconn_ind(conn); | ||
250 | |||
251 | switch (conn->type) { | ||
252 | case ACL_LINK: | ||
253 | hci_acl_disconn(conn, reason); | ||
254 | break; | ||
255 | case AMP_LINK: | ||
256 | hci_amp_disconn(conn, reason); | ||
257 | break; | ||
258 | } | ||
259 | } | ||
260 | |||
233 | static void hci_conn_timeout(struct work_struct *work) | 261 | static void hci_conn_timeout(struct work_struct *work) |
234 | { | 262 | { |
235 | struct hci_conn *conn = container_of(work, struct hci_conn, | 263 | struct hci_conn *conn = container_of(work, struct hci_conn, |
236 | disc_work.work); | 264 | disc_work.work); |
237 | __u8 reason; | ||
238 | 265 | ||
239 | BT_DBG("hcon %p state %s", conn, state_to_string(conn->state)); | 266 | BT_DBG("hcon %p state %s", conn, state_to_string(conn->state)); |
240 | 267 | ||
@@ -253,8 +280,7 @@ static void hci_conn_timeout(struct work_struct *work) | |||
253 | break; | 280 | break; |
254 | case BT_CONFIG: | 281 | case BT_CONFIG: |
255 | case BT_CONNECTED: | 282 | case BT_CONNECTED: |
256 | reason = hci_proto_disconn_ind(conn); | 283 | hci_conn_disconnect(conn); |
257 | hci_acl_disconn(conn, reason); | ||
258 | break; | 284 | break; |
259 | default: | 285 | default: |
260 | conn->state = BT_CLOSED; | 286 | conn->state = BT_CLOSED; |
@@ -320,7 +346,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) | |||
320 | { | 346 | { |
321 | struct hci_conn *conn; | 347 | struct hci_conn *conn; |
322 | 348 | ||
323 | BT_DBG("%s dst %s", hdev->name, batostr(dst)); | 349 | BT_DBG("%s dst %pMR", hdev->name, dst); |
324 | 350 | ||
325 | conn = kzalloc(sizeof(struct hci_conn), GFP_KERNEL); | 351 | conn = kzalloc(sizeof(struct hci_conn), GFP_KERNEL); |
326 | if (!conn) | 352 | if (!conn) |
@@ -437,7 +463,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src) | |||
437 | int use_src = bacmp(src, BDADDR_ANY); | 463 | int use_src = bacmp(src, BDADDR_ANY); |
438 | struct hci_dev *hdev = NULL, *d; | 464 | struct hci_dev *hdev = NULL, *d; |
439 | 465 | ||
440 | BT_DBG("%s -> %s", batostr(src), batostr(dst)); | 466 | BT_DBG("%pMR -> %pMR", src, dst); |
441 | 467 | ||
442 | read_lock(&hci_dev_list_lock); | 468 | read_lock(&hci_dev_list_lock); |
443 | 469 | ||
@@ -567,7 +593,7 @@ static struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, | |||
567 | struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, | 593 | struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, |
568 | __u8 dst_type, __u8 sec_level, __u8 auth_type) | 594 | __u8 dst_type, __u8 sec_level, __u8 auth_type) |
569 | { | 595 | { |
570 | BT_DBG("%s dst %s type 0x%x", hdev->name, batostr(dst), type); | 596 | BT_DBG("%s dst %pMR type 0x%x", hdev->name, dst, type); |
571 | 597 | ||
572 | switch (type) { | 598 | switch (type) { |
573 | case LE_LINK: | 599 | case LE_LINK: |
@@ -963,3 +989,35 @@ void hci_chan_list_flush(struct hci_conn *conn) | |||
963 | list_for_each_entry_safe(chan, n, &conn->chan_list, list) | 989 | list_for_each_entry_safe(chan, n, &conn->chan_list, list) |
964 | hci_chan_del(chan); | 990 | hci_chan_del(chan); |
965 | } | 991 | } |
992 | |||
993 | static struct hci_chan *__hci_chan_lookup_handle(struct hci_conn *hcon, | ||
994 | __u16 handle) | ||
995 | { | ||
996 | struct hci_chan *hchan; | ||
997 | |||
998 | list_for_each_entry(hchan, &hcon->chan_list, list) { | ||
999 | if (hchan->handle == handle) | ||
1000 | return hchan; | ||
1001 | } | ||
1002 | |||
1003 | return NULL; | ||
1004 | } | ||
1005 | |||
1006 | struct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle) | ||
1007 | { | ||
1008 | struct hci_conn_hash *h = &hdev->conn_hash; | ||
1009 | struct hci_conn *hcon; | ||
1010 | struct hci_chan *hchan = NULL; | ||
1011 | |||
1012 | rcu_read_lock(); | ||
1013 | |||
1014 | list_for_each_entry_rcu(hcon, &h->list, list) { | ||
1015 | hchan = __hci_chan_lookup_handle(hcon, handle); | ||
1016 | if (hchan) | ||
1017 | break; | ||
1018 | } | ||
1019 | |||
1020 | rcu_read_unlock(); | ||
1021 | |||
1022 | return hchan; | ||
1023 | } | ||