Bluetooth: Add debugfs switch for forcing SMP over BR/EDR
authorJohan Hedberg <johan.hedberg@intel.com>
Thu, 16 Oct 2014 08:45:31 +0000 (10:45 +0200)
committerMarcel Holtmann <marcel@holtmann.org>
Wed, 3 Dec 2014 15:51:20 +0000 (16:51 +0100)
To make it possible to use LE SC functionality over BR/EDR with pre-4.1
controllers (that do not support BR/EDR SC links) it's useful to be able
to force LE SC operations even over a traditional SSP protected link.
This patch adds a debugfs switch to force a special debug flag which is
used to skip the checks for BR/EDR SC support.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
include/net/bluetooth/hci.h
net/bluetooth/hci_core.c

index e56f9099f8e34b6f2970928da3d17de9c12de019..569c077778b692c80250f65208f80531e66ea8a1 100644 (file)
@@ -163,6 +163,7 @@ enum {
 enum {
        HCI_DUT_MODE,
        HCI_FORCE_SC,
+       HCI_FORCE_LESC,
        HCI_FORCE_STATIC_ADDR,
 };
 
index 2fa9f2b2bee3d06e099550cb40551e410ae18b2b..581e13e9dc32734071db04333068b5eb0704fab7 100644 (file)
@@ -406,6 +406,49 @@ static const struct file_operations force_sc_support_fops = {
        .llseek         = default_llseek,
 };
 
+static ssize_t force_lesc_support_read(struct file *file, char __user *user_buf,
+                                      size_t count, loff_t *ppos)
+{
+       struct hci_dev *hdev = file->private_data;
+       char buf[3];
+
+       buf[0] = test_bit(HCI_FORCE_LESC, &hdev->dbg_flags) ? 'Y': 'N';
+       buf[1] = '\n';
+       buf[2] = '\0';
+       return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
+}
+
+static ssize_t force_lesc_support_write(struct file *file,
+                                       const char __user *user_buf,
+                                       size_t count, loff_t *ppos)
+{
+       struct hci_dev *hdev = file->private_data;
+       char buf[32];
+       size_t buf_size = min(count, (sizeof(buf)-1));
+       bool enable;
+
+       if (copy_from_user(buf, user_buf, buf_size))
+               return -EFAULT;
+
+       buf[buf_size] = '\0';
+       if (strtobool(buf, &enable))
+               return -EINVAL;
+
+       if (enable == test_bit(HCI_FORCE_LESC, &hdev->dbg_flags))
+               return -EALREADY;
+
+       change_bit(HCI_FORCE_LESC, &hdev->dbg_flags);
+
+       return count;
+}
+
+static const struct file_operations force_lesc_support_fops = {
+       .open           = simple_open,
+       .read           = force_lesc_support_read,
+       .write          = force_lesc_support_write,
+       .llseek         = default_llseek,
+};
+
 static ssize_t sc_only_mode_read(struct file *file, char __user *user_buf,
                                 size_t count, loff_t *ppos)
 {
@@ -1817,6 +1860,10 @@ static int __hci_init(struct hci_dev *hdev)
                                    hdev, &force_sc_support_fops);
                debugfs_create_file("sc_only_mode", 0444, hdev->debugfs,
                                    hdev, &sc_only_mode_fops);
+               if (lmp_le_capable(hdev))
+                       debugfs_create_file("force_lesc_support", 0644,
+                                           hdev->debugfs, hdev,
+                                           &force_lesc_support_fops);
        }
 
        if (lmp_sniff_capable(hdev)) {