diff options
-rw-r--r-- | net/bluetooth/hci_debugfs.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/net/bluetooth/hci_debugfs.c b/net/bluetooth/hci_debugfs.c index 0818fabf346a..e6255833a258 100644 --- a/net/bluetooth/hci_debugfs.c +++ b/net/bluetooth/hci_debugfs.c | |||
@@ -28,6 +28,54 @@ | |||
28 | 28 | ||
29 | #include "hci_debugfs.h" | 29 | #include "hci_debugfs.h" |
30 | 30 | ||
31 | #define DEFINE_QUIRK_ATTRIBUTE(__name, __quirk) \ | ||
32 | static ssize_t __name ## _read(struct file *file, \ | ||
33 | char __user *user_buf, \ | ||
34 | size_t count, loff_t *ppos) \ | ||
35 | { \ | ||
36 | struct hci_dev *hdev = file->private_data; \ | ||
37 | char buf[3]; \ | ||
38 | \ | ||
39 | buf[0] = test_bit(__quirk, &hdev->quirks) ? 'Y' : 'N'; \ | ||
40 | buf[1] = '\n'; \ | ||
41 | buf[2] = '\0'; \ | ||
42 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); \ | ||
43 | } \ | ||
44 | \ | ||
45 | static ssize_t __name ## _write(struct file *file, \ | ||
46 | const char __user *user_buf, \ | ||
47 | size_t count, loff_t *ppos) \ | ||
48 | { \ | ||
49 | struct hci_dev *hdev = file->private_data; \ | ||
50 | char buf[32]; \ | ||
51 | size_t buf_size = min(count, (sizeof(buf) - 1)); \ | ||
52 | bool enable; \ | ||
53 | \ | ||
54 | if (test_bit(HCI_UP, &hdev->flags)) \ | ||
55 | return -EBUSY; \ | ||
56 | \ | ||
57 | if (copy_from_user(buf, user_buf, buf_size)) \ | ||
58 | return -EFAULT; \ | ||
59 | \ | ||
60 | buf[buf_size] = '\0'; \ | ||
61 | if (strtobool(buf, &enable)) \ | ||
62 | return -EINVAL; \ | ||
63 | \ | ||
64 | if (enable == test_bit(__quirk, &hdev->quirks)) \ | ||
65 | return -EALREADY; \ | ||
66 | \ | ||
67 | change_bit(__quirk, &hdev->quirks); \ | ||
68 | \ | ||
69 | return count; \ | ||
70 | } \ | ||
71 | \ | ||
72 | static const struct file_operations __name ## _fops = { \ | ||
73 | .open = simple_open, \ | ||
74 | .read = __name ## _read, \ | ||
75 | .write = __name ## _write, \ | ||
76 | .llseek = default_llseek, \ | ||
77 | } \ | ||
78 | |||
31 | static int features_show(struct seq_file *f, void *ptr) | 79 | static int features_show(struct seq_file *f, void *ptr) |
32 | { | 80 | { |
33 | struct hci_dev *hdev = f->private; | 81 | struct hci_dev *hdev = f->private; |
@@ -997,6 +1045,11 @@ static int adv_max_interval_get(void *data, u64 *val) | |||
997 | DEFINE_SIMPLE_ATTRIBUTE(adv_max_interval_fops, adv_max_interval_get, | 1045 | DEFINE_SIMPLE_ATTRIBUTE(adv_max_interval_fops, adv_max_interval_get, |
998 | adv_max_interval_set, "%llu\n"); | 1046 | adv_max_interval_set, "%llu\n"); |
999 | 1047 | ||
1048 | DEFINE_QUIRK_ATTRIBUTE(quirk_strict_duplicate_filter, | ||
1049 | HCI_QUIRK_STRICT_DUPLICATE_FILTER); | ||
1050 | DEFINE_QUIRK_ATTRIBUTE(quirk_simultaneous_discovery, | ||
1051 | HCI_QUIRK_SIMULTANEOUS_DISCOVERY); | ||
1052 | |||
1000 | void hci_debugfs_create_le(struct hci_dev *hdev) | 1053 | void hci_debugfs_create_le(struct hci_dev *hdev) |
1001 | { | 1054 | { |
1002 | debugfs_create_file("identity", 0400, hdev->debugfs, hdev, | 1055 | debugfs_create_file("identity", 0400, hdev->debugfs, hdev, |
@@ -1041,6 +1094,13 @@ void hci_debugfs_create_le(struct hci_dev *hdev) | |||
1041 | &adv_max_interval_fops); | 1094 | &adv_max_interval_fops); |
1042 | debugfs_create_u16("discov_interleaved_timeout", 0644, hdev->debugfs, | 1095 | debugfs_create_u16("discov_interleaved_timeout", 0644, hdev->debugfs, |
1043 | &hdev->discov_interleaved_timeout); | 1096 | &hdev->discov_interleaved_timeout); |
1097 | |||
1098 | debugfs_create_file("quirk_strict_duplicate_filter", 0644, | ||
1099 | hdev->debugfs, hdev, | ||
1100 | &quirk_strict_duplicate_filter_fops); | ||
1101 | debugfs_create_file("quirk_simultaneous_discovery", 0644, | ||
1102 | hdev->debugfs, hdev, | ||
1103 | &quirk_simultaneous_discovery_fops); | ||
1044 | } | 1104 | } |
1045 | 1105 | ||
1046 | void hci_debugfs_create_conn(struct hci_conn *conn) | 1106 | void hci_debugfs_create_conn(struct hci_conn *conn) |