Bluetooth: Grace period to re-enable encryption
If the remote device does not support Encryption Pause,
It might disable Encryption during role switch. Allow a
Grace period of 500 ms for such devices to re-enable.
Change-Id: I8af8082e16e185fe8c15adaf07169cc73179c59f
CRs-fixed: 336828
Signed-off-by: Prabhakaran Mc <prabhakaranmc@codeaurora.org>
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index f87be20..d60bf00 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -364,6 +364,24 @@
hci_read_rssi(conn);
}
+static void encryption_disabled_timeout(unsigned long userdata)
+{
+ struct hci_conn *conn = (struct hci_conn *)userdata;
+ BT_INFO("conn %p Grace Prd Exp ", conn);
+
+ hci_encrypt_cfm(conn, 0, 0);
+
+ if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
+ struct hci_cp_set_conn_encrypt cp;
+ BT_INFO("HCI_CONN_ENCRYPT_PEND is set");
+ cp.handle = cpu_to_le16(conn->handle);
+ cp.encrypt = 1;
+ hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT,
+ sizeof(cp), &cp);
+ }
+
+}
+
struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type,
__u16 pkt_type, bdaddr_t *dst)
{
@@ -417,6 +435,8 @@
setup_timer(&conn->disc_timer, hci_conn_timeout, (unsigned long)conn);
setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn);
INIT_DELAYED_WORK(&conn->rssi_update_work, hci_conn_rssi_update);
+ setup_timer(&conn->encrypt_pause_timer, encryption_disabled_timeout,
+ (unsigned long)conn);
atomic_set(&conn->refcnt, 0);
@@ -460,6 +480,7 @@
del_timer(&conn->disc_timer);
del_timer(&conn->smp_timer);
__cancel_delayed_work(&conn->rssi_update_work);
+ del_timer(&conn->encrypt_pause_timer);
if (conn->type == ACL_LINK) {
struct hci_conn *sco = conn->link;
@@ -854,6 +875,10 @@
if (hci_conn_auth(conn, sec_level, auth_type)) {
struct hci_cp_set_conn_encrypt cp;
+ if (timer_pending(&conn->encrypt_pause_timer)) {
+ BT_INFO("encrypt_pause_timer is pending");
+ return 0;
+ }
cp.handle = cpu_to_le16(conn->handle);
cp.encrypt = 1;
hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT,
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 74d0851..f4f833b 100755
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1920,8 +1920,25 @@
hci_proto_connect_cfm(conn, ev->status);
hci_conn_put(conn);
- } else
- hci_encrypt_cfm(conn, ev->status, ev->encrypt);
+ } else {
+ /*
+ * If the remote device does not support
+ * Pause Encryption, usually during the
+ * roleSwitch we see Encryption disable
+ * for short duration. Allow remote device
+ * to disable encryption
+ * for short duration in this case.
+ */
+ if ((ev->encrypt == 0) && (ev->status == 0) &&
+ ((conn->features[5] & LMP_PAUSE_ENC) == 0)) {
+ mod_timer(&conn->encrypt_pause_timer,
+ jiffies + msecs_to_jiffies(500));
+ BT_INFO("enc pause timer, enc_pend_flag set");
+ } else {
+ del_timer(&conn->encrypt_pause_timer);
+ hci_encrypt_cfm(conn, ev->status, ev->encrypt);
+ }
+ }
if (test_bit(HCI_MGMT, &hdev->flags))
mgmt_encrypt_change(hdev->id, &conn->dst, ev->status);