|
@@ -1057,10 +1057,34 @@ static int clean_up_hci_state(struct hci_dev *hdev)
|
|
|
|
|
|
list_for_each_entry(conn, &hdev->conn_hash.list, list) {
|
|
list_for_each_entry(conn, &hdev->conn_hash.list, list) {
|
|
struct hci_cp_disconnect dc;
|
|
struct hci_cp_disconnect dc;
|
|
-
|
|
|
|
- dc.handle = cpu_to_le16(conn->handle);
|
|
|
|
- dc.reason = 0x15; /* Terminated due to Power Off */
|
|
|
|
- hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
|
|
|
|
|
|
+ struct hci_cp_reject_conn_req rej;
|
|
|
|
+
|
|
|
|
+ switch (conn->state) {
|
|
|
|
+ case BT_CONNECTED:
|
|
|
|
+ case BT_CONFIG:
|
|
|
|
+ dc.handle = cpu_to_le16(conn->handle);
|
|
|
|
+ dc.reason = 0x15; /* Terminated due to Power Off */
|
|
|
|
+ hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
|
|
|
|
+ break;
|
|
|
|
+ case BT_CONNECT:
|
|
|
|
+ if (conn->type == LE_LINK)
|
|
|
|
+ hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
|
|
|
|
+ 0, NULL);
|
|
|
|
+ else if (conn->type == ACL_LINK)
|
|
|
|
+ hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
|
|
|
|
+ 6, &conn->dst);
|
|
|
|
+ break;
|
|
|
|
+ case BT_CONNECT2:
|
|
|
|
+ bacpy(&rej.bdaddr, &conn->dst);
|
|
|
|
+ rej.reason = 0x15; /* Terminated due to Power Off */
|
|
|
|
+ if (conn->type == ACL_LINK)
|
|
|
|
+ hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
|
|
|
|
+ sizeof(rej), &rej);
|
|
|
|
+ else if (conn->type == SCO_LINK)
|
|
|
|
+ hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
|
|
|
|
+ sizeof(rej), &rej);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
return hci_req_run(&req, clean_up_hci_complete);
|
|
return hci_req_run(&req, clean_up_hci_complete);
|
|
@@ -5184,6 +5208,18 @@ void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
|
|
u8 addr_type, u8 status)
|
|
u8 addr_type, u8 status)
|
|
{
|
|
{
|
|
struct mgmt_ev_connect_failed ev;
|
|
struct mgmt_ev_connect_failed ev;
|
|
|
|
+ struct pending_cmd *power_off;
|
|
|
|
+
|
|
|
|
+ power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
|
|
|
|
+ if (power_off) {
|
|
|
|
+ struct mgmt_mode *cp = power_off->param;
|
|
|
|
+
|
|
|
|
+ /* The connection is still in hci_conn_hash so test for 1
|
|
|
|
+ * instead of 0 to know if this is the last one.
|
|
|
|
+ */
|
|
|
|
+ if (!cp->val && hci_conn_count(hdev) == 1)
|
|
|
|
+ queue_work(hdev->req_workqueue, &hdev->power_off.work);
|
|
|
|
+ }
|
|
|
|
|
|
bacpy(&ev.addr.bdaddr, bdaddr);
|
|
bacpy(&ev.addr.bdaddr, bdaddr);
|
|
ev.addr.type = link_to_bdaddr(link_type, addr_type);
|
|
ev.addr.type = link_to_bdaddr(link_type, addr_type);
|