|
@@ -2725,10 +2725,40 @@ static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
|
|
|
}
|
|
|
|
|
|
if (cp->addr.type == BDADDR_BREDR) {
|
|
|
+ /* If disconnection is requested, then look up the
|
|
|
+ * connection. If the remote device is connected, it
|
|
|
+ * will be later used to terminate the link.
|
|
|
+ *
|
|
|
+ * Setting it to NULL explicitly will cause no
|
|
|
+ * termination of the link.
|
|
|
+ */
|
|
|
+ if (cp->disconnect)
|
|
|
+ conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
|
|
|
+ &cp->addr.bdaddr);
|
|
|
+ else
|
|
|
+ conn = NULL;
|
|
|
+
|
|
|
err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
|
|
|
} else {
|
|
|
u8 addr_type;
|
|
|
|
|
|
+ conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
|
|
|
+ &cp->addr.bdaddr);
|
|
|
+ if (conn) {
|
|
|
+ /* Defer clearing up the connection parameters
|
|
|
+ * until closing to give a chance of keeping
|
|
|
+ * them if a repairing happens.
|
|
|
+ */
|
|
|
+ set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
|
|
|
+
|
|
|
+ /* If disconnection is not requested, then
|
|
|
+ * clear the connection variable so that the
|
|
|
+ * link is not terminated.
|
|
|
+ */
|
|
|
+ if (!cp->disconnect)
|
|
|
+ conn = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
if (cp->addr.type == BDADDR_LE_PUBLIC)
|
|
|
addr_type = ADDR_LE_DEV_PUBLIC;
|
|
|
else
|
|
@@ -2736,8 +2766,6 @@ static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
|
|
|
|
|
|
hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
|
|
|
|
|
|
- hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
|
|
|
-
|
|
|
err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
|
|
|
}
|
|
|
|
|
@@ -2747,17 +2775,9 @@ static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
|
|
|
goto unlock;
|
|
|
}
|
|
|
|
|
|
- if (cp->disconnect) {
|
|
|
- if (cp->addr.type == BDADDR_BREDR)
|
|
|
- conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
|
|
|
- &cp->addr.bdaddr);
|
|
|
- else
|
|
|
- conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
|
|
|
- &cp->addr.bdaddr);
|
|
|
- } else {
|
|
|
- conn = NULL;
|
|
|
- }
|
|
|
-
|
|
|
+ /* If the connection variable is set, then termination of the
|
|
|
+ * link is requested.
|
|
|
+ */
|
|
|
if (!conn) {
|
|
|
err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
|
|
|
&rp, sizeof(rp));
|
|
@@ -3062,6 +3082,11 @@ static void pairing_complete(struct pending_cmd *cmd, u8 status)
|
|
|
hci_conn_put(conn);
|
|
|
|
|
|
mgmt_pending_remove(cmd);
|
|
|
+
|
|
|
+ /* The device is paired so there is no need to remove
|
|
|
+ * its connection parameters anymore.
|
|
|
+ */
|
|
|
+ clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
|
|
|
}
|
|
|
|
|
|
void mgmt_smp_complete(struct hci_conn *conn, bool complete)
|