aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/bluetooth/hci_core.h3
-rw-r--r--include/net/bluetooth/mgmt.h4
-rw-r--r--net/bluetooth/hci_event.c28
-rw-r--r--net/bluetooth/mgmt.c28
4 files changed, 42 insertions, 21 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 7107790817a..634a0cdcdad 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -958,7 +958,8 @@ int mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
958 u8 *dev_class); 958 u8 *dev_class);
959int mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, 959int mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
960 u8 link_type, u8 addr_type); 960 u8 link_type, u8 addr_type);
961int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status); 961int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
962 u8 link_type, u8 addr_type, u8 status);
962int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, 963int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
963 u8 addr_type, u8 status); 964 u8 addr_type, u8 status);
964int mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure); 965int mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure);
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 4c18cd5fb8c..735e547e344 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -177,10 +177,10 @@ struct mgmt_cp_load_long_term_keys {
177 177
178#define MGMT_OP_DISCONNECT 0x0014 178#define MGMT_OP_DISCONNECT 0x0014
179struct mgmt_cp_disconnect { 179struct mgmt_cp_disconnect {
180 bdaddr_t bdaddr; 180 struct mgmt_addr_info addr;
181} __packed; 181} __packed;
182struct mgmt_rp_disconnect { 182struct mgmt_rp_disconnect {
183 bdaddr_t bdaddr; 183 struct mgmt_addr_info addr;
184 __u8 status; 184 __u8 status;
185} __packed; 185} __packed;
186 186
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index ad5f37b13f7..f0c822db28d 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1550,6 +1550,28 @@ static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
1550 hci_dev_unlock(hdev); 1550 hci_dev_unlock(hdev);
1551} 1551}
1552 1552
1553static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
1554{
1555 struct hci_cp_disconnect *cp;
1556 struct hci_conn *conn;
1557
1558 if (!status)
1559 return;
1560
1561 cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
1562 if (!cp)
1563 return;
1564
1565 hci_dev_lock(hdev);
1566
1567 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
1568 if (conn)
1569 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
1570 conn->dst_type, status);
1571
1572 hci_dev_unlock(hdev);
1573}
1574
1553static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) 1575static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1554{ 1576{
1555 struct hci_cp_le_create_conn *cp; 1577 struct hci_cp_le_create_conn *cp;
@@ -1839,7 +1861,8 @@ static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff
1839 if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) && 1861 if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
1840 (conn->type == ACL_LINK || conn->type == LE_LINK)) { 1862 (conn->type == ACL_LINK || conn->type == LE_LINK)) {
1841 if (ev->status != 0) 1863 if (ev->status != 0)
1842 mgmt_disconnect_failed(hdev, &conn->dst, ev->status); 1864 mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
1865 conn->dst_type, ev->status);
1843 else 1866 else
1844 mgmt_device_disconnected(hdev, &conn->dst, conn->type, 1867 mgmt_device_disconnected(hdev, &conn->dst, conn->type,
1845 conn->dst_type); 1868 conn->dst_type);
@@ -2350,8 +2373,7 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
2350 break; 2373 break;
2351 2374
2352 case HCI_OP_DISCONNECT: 2375 case HCI_OP_DISCONNECT:
2353 if (ev->status != 0) 2376 hci_cs_disconnect(hdev, ev->status);
2354 mgmt_disconnect_failed(hdev, NULL, ev->status);
2355 break; 2377 break;
2356 2378
2357 case HCI_OP_LE_CREATE_CONN: 2379 case HCI_OP_LE_CREATE_CONN:
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index c64e5db7f59..f1257ee5afb 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1185,9 +1185,10 @@ static int disconnect(struct sock *sk, u16 index, void *data, u16 len)
1185 goto failed; 1185 goto failed;
1186 } 1186 }
1187 1187
1188 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 1188 if (cp->addr.type == MGMT_ADDR_BREDR)
1189 if (!conn) 1189 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
1190 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->bdaddr); 1190 else
1191 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
1191 1192
1192 if (!conn) { 1193 if (!conn) {
1193 err = cmd_status(sk, index, MGMT_OP_DISCONNECT, 1194 err = cmd_status(sk, index, MGMT_OP_DISCONNECT,
@@ -2619,7 +2620,8 @@ static void disconnect_rsp(struct pending_cmd *cmd, void *data)
2619 struct sock **sk = data; 2620 struct sock **sk = data;
2620 struct mgmt_rp_disconnect rp; 2621 struct mgmt_rp_disconnect rp;
2621 2622
2622 bacpy(&rp.bdaddr, &cp->bdaddr); 2623 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2624 rp.addr.type = cp->addr.type;
2623 rp.status = 0; 2625 rp.status = 0;
2624 2626
2625 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, &rp, sizeof(rp)); 2627 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, &rp, sizeof(rp));
@@ -2672,27 +2674,23 @@ int mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
2672 return err; 2674 return err;
2673} 2675}
2674 2676
2675int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status) 2677int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
2678 u8 link_type, u8 addr_type, u8 status)
2676{ 2679{
2680 struct mgmt_rp_disconnect rp;
2677 struct pending_cmd *cmd; 2681 struct pending_cmd *cmd;
2678 u8 mgmt_err = mgmt_status(status);
2679 int err; 2682 int err;
2680 2683
2681 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev); 2684 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
2682 if (!cmd) 2685 if (!cmd)
2683 return -ENOENT; 2686 return -ENOENT;
2684 2687
2685 if (bdaddr) { 2688 bacpy(&rp.addr.bdaddr, bdaddr);
2686 struct mgmt_rp_disconnect rp; 2689 rp.addr.type = link_to_mgmt(link_type, addr_type);
2687 2690 rp.status = mgmt_status(status);
2688 bacpy(&rp.bdaddr, bdaddr);
2689 rp.status = status;
2690 2691
2691 err = cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 2692 err = cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
2692 &rp, sizeof(rp)); 2693 &rp, sizeof(rp));
2693 } else
2694 err = cmd_status(cmd->sk, hdev->id, MGMT_OP_DISCONNECT,
2695 mgmt_err);
2696 2694
2697 mgmt_pending_remove(cmd); 2695 mgmt_pending_remove(cmd);
2698 2696