Bluetooth: Add variable SSP auto-accept delay support
authorJohan Hedberg <johan.hedberg@nokia.com>
Thu, 28 Apr 2011 18:28:54 +0000 (11:28 -0700)
committerGustavo F. Padovan <padovan@profusion.mobi>
Thu, 28 Apr 2011 19:02:30 +0000 (16:02 -0300)
Some test systems require an arbitrary delay to the auto-accept test
cases for Secure Simple Pairing in order for the tests to pass.
Previously when this was handled in user space it was worked around by
code modifications and recompilation, but now that it's on the kernel
side it's more convenient if there's a debugfs interface for it.

Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
include/net/bluetooth/hci_core.h
net/bluetooth/hci_conn.c
net/bluetooth/hci_event.c
net/bluetooth/hci_sysfs.c

index 2995e2e63512f00bc19d0cf0c52836266f965807..09b9dd61e3703f4773626e35242661c1db223761 100644 (file)
@@ -126,6 +126,8 @@ struct hci_dev {
        __u16           sniff_min_interval;
        __u16           sniff_max_interval;
 
+       unsigned int    auto_accept_delay;
+
        unsigned long   quirks;
 
        atomic_t        cmd_cnt;
@@ -246,6 +248,7 @@ struct hci_conn {
 
        struct timer_list disc_timer;
        struct timer_list idle_timer;
+       struct timer_list auto_accept_timer;
 
        struct work_struct work_add;
        struct work_struct work_del;
index 74cd755b38a7f53c7b5c450b8d04dd20b02b663b..7f5ad8a2b22d03c2c3eea300cba7dec3b977d20d 100644 (file)
@@ -269,6 +269,19 @@ static void hci_conn_idle(unsigned long arg)
        hci_conn_enter_sniff_mode(conn);
 }
 
+static void hci_conn_auto_accept(unsigned long arg)
+{
+       struct hci_conn *conn = (void *) arg;
+       struct hci_dev *hdev = conn->hdev;
+
+       hci_dev_lock(hdev);
+
+       hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, sizeof(conn->dst),
+                                                               &conn->dst);
+
+       hci_dev_unlock(hdev);
+}
+
 struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
 {
        struct hci_conn *conn;
@@ -312,6 +325,8 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
 
        setup_timer(&conn->disc_timer, hci_conn_timeout, (unsigned long)conn);
        setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn);
+       setup_timer(&conn->auto_accept_timer, hci_conn_auto_accept,
+                                                       (unsigned long) conn);
 
        atomic_set(&conn->refcnt, 0);
 
@@ -342,6 +357,8 @@ int hci_conn_del(struct hci_conn *conn)
 
        del_timer(&conn->disc_timer);
 
+       del_timer(&conn->auto_accept_timer);
+
        if (conn->type == ACL_LINK) {
                struct hci_conn *sco = conn->link;
                if (sco)
index 514e10e1e0ff30cad0687684764229b35ebd6b53..a479389668ef1a18561f7851e03c98a9eea7c32c 100644 (file)
@@ -2515,7 +2515,15 @@ static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
        /* If no side requires MITM protection; auto-accept */
        if ((!loc_mitm || conn->remote_cap == 0x03) &&
                                (!rem_mitm || conn->io_capability == 0x03)) {
-               BT_DBG("Auto-accept of user confirmation");
+               BT_DBG("Auto-accept of user confirmation with %ums delay",
+                                               hdev->auto_accept_delay);
+
+               if (hdev->auto_accept_delay > 0) {
+                       int delay = msecs_to_jiffies(hdev->auto_accept_delay);
+                       mod_timer(&conn->auto_accept_timer, jiffies + delay);
+                       goto unlock;
+               }
+
                hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
                                                sizeof(ev->bdaddr), &ev->bdaddr);
                goto unlock;
index 8775933ea837f4c2d7cf624b3861faf0d04e73e7..a6c3aa8be1f79796dbfa051af03b3503f23fbe4e 100644 (file)
@@ -511,6 +511,35 @@ static const struct file_operations uuids_fops = {
        .release        = single_release,
 };
 
+static int auto_accept_delay_set(void *data, u64 val)
+{
+       struct hci_dev *hdev = data;
+
+       hci_dev_lock_bh(hdev);
+
+       hdev->auto_accept_delay = val;
+
+       hci_dev_unlock_bh(hdev);
+
+       return 0;
+}
+
+static int auto_accept_delay_get(void *data, u64 *val)
+{
+       struct hci_dev *hdev = data;
+
+       hci_dev_lock_bh(hdev);
+
+       *val = hdev->auto_accept_delay;
+
+       hci_dev_unlock_bh(hdev);
+
+       return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(auto_accept_delay_fops, auto_accept_delay_get,
+                                       auto_accept_delay_set, "%llu\n");
+
 int hci_register_sysfs(struct hci_dev *hdev)
 {
        struct device *dev = &hdev->dev;
@@ -545,6 +574,8 @@ int hci_register_sysfs(struct hci_dev *hdev)
 
        debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops);
 
+       debugfs_create_file("auto_accept_delay", 0444, hdev->debugfs, hdev,
+                                               &auto_accept_delay_fops);
        return 0;
 }