Merge remote-tracking branch 'asoc/topic/core' into asoc-next
[firefly-linux-kernel-4.4.55.git] / net / bluetooth / hci_debugfs.c
index 65261e5d4b84bbbdc1da1d11083b9f32b6233d7a..7db4220941cc60dfed6c5ca4043e7158e4458387 100644 (file)
 
 #include "hci_debugfs.h"
 
+#define DEFINE_QUIRK_ATTRIBUTE(__name, __quirk)                                      \
+static ssize_t __name ## _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(__quirk, &hdev->quirks) ? 'Y' : 'N';                \
+       buf[1] = '\n';                                                        \
+       buf[2] = '\0';                                                        \
+       return simple_read_from_buffer(user_buf, count, ppos, buf, 2);        \
+}                                                                            \
+                                                                             \
+static ssize_t __name ## _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 (test_bit(HCI_UP, &hdev->flags))                                   \
+               return -EBUSY;                                                \
+                                                                             \
+       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(__quirk, &hdev->quirks))                       \
+               return -EALREADY;                                             \
+                                                                             \
+       change_bit(__quirk, &hdev->quirks);                                   \
+                                                                             \
+       return count;                                                         \
+}                                                                            \
+                                                                             \
+static const struct file_operations __name ## _fops = {                              \
+       .open           = simple_open,                                        \
+       .read           = __name ## _read,                                    \
+       .write          = __name ## _write,                                   \
+       .llseek         = default_llseek,                                     \
+}                                                                            \
+
 static int features_show(struct seq_file *f, void *ptr)
 {
        struct hci_dev *hdev = f->private;
@@ -66,6 +114,30 @@ static const struct file_operations features_fops = {
        .release        = single_release,
 };
 
+static int device_id_show(struct seq_file *f, void *ptr)
+{
+       struct hci_dev *hdev = f->private;
+
+       hci_dev_lock(hdev);
+       seq_printf(f, "%4.4x:%4.4x:%4.4x:%4.4x\n", hdev->devid_source,
+                 hdev->devid_vendor, hdev->devid_product, hdev->devid_version);
+       hci_dev_unlock(hdev);
+
+       return 0;
+}
+
+static int device_id_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, device_id_show, inode->i_private);
+}
+
+static const struct file_operations device_id_fops = {
+       .open           = device_id_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
 static int device_list_show(struct seq_file *f, void *ptr)
 {
        struct hci_dev *hdev = f->private;
@@ -166,7 +238,7 @@ static int remote_oob_show(struct seq_file *f, void *ptr)
                seq_printf(f, "%pMR (type %u) %u %*phN %*phN %*phN %*phN\n",
                           &data->bdaddr, data->bdaddr_type, data->present,
                           16, data->hash192, 16, data->rand192,
-                          16, data->hash256, 19, data->rand256);
+                          16, data->hash256, 16, data->rand256);
        }
        hci_dev_unlock(hdev);
 
@@ -247,7 +319,7 @@ static ssize_t use_debug_keys_read(struct file *file, char __user *user_buf,
        struct hci_dev *hdev = file->private_data;
        char buf[3];
 
-       buf[0] = test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags) ? 'Y': 'N';
+       buf[0] = hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS) ? 'Y': 'N';
        buf[1] = '\n';
        buf[2] = '\0';
        return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
@@ -265,7 +337,7 @@ static ssize_t sc_only_mode_read(struct file *file, char __user *user_buf,
        struct hci_dev *hdev = file->private_data;
        char buf[3];
 
-       buf[0] = test_bit(HCI_SC_ONLY, &hdev->dev_flags) ? 'Y': 'N';
+       buf[0] = hci_dev_test_flag(hdev, HCI_SC_ONLY) ? 'Y': 'N';
        buf[1] = '\n';
        buf[2] = '\0';
        return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
@@ -287,6 +359,8 @@ void hci_debugfs_create_common(struct hci_dev *hdev)
        debugfs_create_u16("hci_revision", 0444, hdev->debugfs, &hdev->hci_rev);
        debugfs_create_u8("hardware_error", 0444, hdev->debugfs,
                          &hdev->hw_error_code);
+       debugfs_create_file("device_id", 0444, hdev->debugfs, hdev,
+                           &device_id_fops);
 
        debugfs_create_file("device_list", 0444, hdev->debugfs, hdev,
                            &device_list_fops);
@@ -679,7 +753,7 @@ static ssize_t force_static_address_read(struct file *file,
        struct hci_dev *hdev = file->private_data;
        char buf[3];
 
-       buf[0] = test_bit(HCI_FORCE_STATIC_ADDR, &hdev->dbg_flags) ? 'Y': 'N';
+       buf[0] = hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ? 'Y': 'N';
        buf[1] = '\n';
        buf[2] = '\0';
        return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
@@ -704,10 +778,10 @@ static ssize_t force_static_address_write(struct file *file,
        if (strtobool(buf, &enable))
                return -EINVAL;
 
-       if (enable == test_bit(HCI_FORCE_STATIC_ADDR, &hdev->dbg_flags))
+       if (enable == hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR))
                return -EALREADY;
 
-       change_bit(HCI_FORCE_STATIC_ADDR, &hdev->dbg_flags);
+       hci_dev_change_flag(hdev, HCI_FORCE_STATIC_ADDR);
 
        return count;
 }
@@ -997,6 +1071,11 @@ static int adv_max_interval_get(void *data, u64 *val)
 DEFINE_SIMPLE_ATTRIBUTE(adv_max_interval_fops, adv_max_interval_get,
                        adv_max_interval_set, "%llu\n");
 
+DEFINE_QUIRK_ATTRIBUTE(quirk_strict_duplicate_filter,
+                      HCI_QUIRK_STRICT_DUPLICATE_FILTER);
+DEFINE_QUIRK_ATTRIBUTE(quirk_simultaneous_discovery,
+                      HCI_QUIRK_SIMULTANEOUS_DISCOVERY);
+
 void hci_debugfs_create_le(struct hci_dev *hdev)
 {
        debugfs_create_file("identity", 0400, hdev->debugfs, hdev,
@@ -1041,6 +1120,13 @@ void hci_debugfs_create_le(struct hci_dev *hdev)
                            &adv_max_interval_fops);
        debugfs_create_u16("discov_interleaved_timeout", 0644, hdev->debugfs,
                           &hdev->discov_interleaved_timeout);
+
+       debugfs_create_file("quirk_strict_duplicate_filter", 0644,
+                           hdev->debugfs, hdev,
+                           &quirk_strict_duplicate_filter_fops);
+       debugfs_create_file("quirk_simultaneous_discovery", 0644,
+                           hdev->debugfs, hdev,
+                           &quirk_simultaneous_discovery_fops);
 }
 
 void hci_debugfs_create_conn(struct hci_conn *conn)