diff options
Diffstat (limited to 'net/bluetooth/hci_debugfs.c')
| -rw-r--r-- | net/bluetooth/hci_debugfs.c | 98 |
1 files changed, 92 insertions, 6 deletions
diff --git a/net/bluetooth/hci_debugfs.c b/net/bluetooth/hci_debugfs.c index 65261e5d4b84..7db4220941cc 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; |
| @@ -66,6 +114,30 @@ static const struct file_operations features_fops = { | |||
| 66 | .release = single_release, | 114 | .release = single_release, |
| 67 | }; | 115 | }; |
| 68 | 116 | ||
| 117 | static int device_id_show(struct seq_file *f, void *ptr) | ||
| 118 | { | ||
| 119 | struct hci_dev *hdev = f->private; | ||
| 120 | |||
| 121 | hci_dev_lock(hdev); | ||
| 122 | seq_printf(f, "%4.4x:%4.4x:%4.4x:%4.4x\n", hdev->devid_source, | ||
| 123 | hdev->devid_vendor, hdev->devid_product, hdev->devid_version); | ||
| 124 | hci_dev_unlock(hdev); | ||
| 125 | |||
| 126 | return 0; | ||
| 127 | } | ||
| 128 | |||
| 129 | static int device_id_open(struct inode *inode, struct file *file) | ||
| 130 | { | ||
| 131 | return single_open(file, device_id_show, inode->i_private); | ||
| 132 | } | ||
| 133 | |||
| 134 | static const struct file_operations device_id_fops = { | ||
| 135 | .open = device_id_open, | ||
| 136 | .read = seq_read, | ||
| 137 | .llseek = seq_lseek, | ||
| 138 | .release = single_release, | ||
| 139 | }; | ||
| 140 | |||
| 69 | static int device_list_show(struct seq_file *f, void *ptr) | 141 | static int device_list_show(struct seq_file *f, void *ptr) |
| 70 | { | 142 | { |
| 71 | struct hci_dev *hdev = f->private; | 143 | struct hci_dev *hdev = f->private; |
| @@ -166,7 +238,7 @@ static int remote_oob_show(struct seq_file *f, void *ptr) | |||
| 166 | seq_printf(f, "%pMR (type %u) %u %*phN %*phN %*phN %*phN\n", | 238 | seq_printf(f, "%pMR (type %u) %u %*phN %*phN %*phN %*phN\n", |
| 167 | &data->bdaddr, data->bdaddr_type, data->present, | 239 | &data->bdaddr, data->bdaddr_type, data->present, |
| 168 | 16, data->hash192, 16, data->rand192, | 240 | 16, data->hash192, 16, data->rand192, |
| 169 | 16, data->hash256, 19, data->rand256); | 241 | 16, data->hash256, 16, data->rand256); |
| 170 | } | 242 | } |
| 171 | hci_dev_unlock(hdev); | 243 | hci_dev_unlock(hdev); |
| 172 | 244 | ||
| @@ -247,7 +319,7 @@ static ssize_t use_debug_keys_read(struct file *file, char __user *user_buf, | |||
| 247 | struct hci_dev *hdev = file->private_data; | 319 | struct hci_dev *hdev = file->private_data; |
| 248 | char buf[3]; | 320 | char buf[3]; |
| 249 | 321 | ||
| 250 | buf[0] = test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags) ? 'Y': 'N'; | 322 | buf[0] = hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS) ? 'Y': 'N'; |
| 251 | buf[1] = '\n'; | 323 | buf[1] = '\n'; |
| 252 | buf[2] = '\0'; | 324 | buf[2] = '\0'; |
| 253 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); | 325 | 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, | |||
| 265 | struct hci_dev *hdev = file->private_data; | 337 | struct hci_dev *hdev = file->private_data; |
| 266 | char buf[3]; | 338 | char buf[3]; |
| 267 | 339 | ||
| 268 | buf[0] = test_bit(HCI_SC_ONLY, &hdev->dev_flags) ? 'Y': 'N'; | 340 | buf[0] = hci_dev_test_flag(hdev, HCI_SC_ONLY) ? 'Y': 'N'; |
| 269 | buf[1] = '\n'; | 341 | buf[1] = '\n'; |
| 270 | buf[2] = '\0'; | 342 | buf[2] = '\0'; |
| 271 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); | 343 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); |
| @@ -287,6 +359,8 @@ void hci_debugfs_create_common(struct hci_dev *hdev) | |||
| 287 | debugfs_create_u16("hci_revision", 0444, hdev->debugfs, &hdev->hci_rev); | 359 | debugfs_create_u16("hci_revision", 0444, hdev->debugfs, &hdev->hci_rev); |
| 288 | debugfs_create_u8("hardware_error", 0444, hdev->debugfs, | 360 | debugfs_create_u8("hardware_error", 0444, hdev->debugfs, |
| 289 | &hdev->hw_error_code); | 361 | &hdev->hw_error_code); |
| 362 | debugfs_create_file("device_id", 0444, hdev->debugfs, hdev, | ||
| 363 | &device_id_fops); | ||
| 290 | 364 | ||
| 291 | debugfs_create_file("device_list", 0444, hdev->debugfs, hdev, | 365 | debugfs_create_file("device_list", 0444, hdev->debugfs, hdev, |
| 292 | &device_list_fops); | 366 | &device_list_fops); |
| @@ -679,7 +753,7 @@ static ssize_t force_static_address_read(struct file *file, | |||
| 679 | struct hci_dev *hdev = file->private_data; | 753 | struct hci_dev *hdev = file->private_data; |
| 680 | char buf[3]; | 754 | char buf[3]; |
| 681 | 755 | ||
| 682 | buf[0] = test_bit(HCI_FORCE_STATIC_ADDR, &hdev->dbg_flags) ? 'Y': 'N'; | 756 | buf[0] = hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ? 'Y': 'N'; |
| 683 | buf[1] = '\n'; | 757 | buf[1] = '\n'; |
| 684 | buf[2] = '\0'; | 758 | buf[2] = '\0'; |
| 685 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); | 759 | 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, | |||
| 704 | if (strtobool(buf, &enable)) | 778 | if (strtobool(buf, &enable)) |
| 705 | return -EINVAL; | 779 | return -EINVAL; |
| 706 | 780 | ||
| 707 | if (enable == test_bit(HCI_FORCE_STATIC_ADDR, &hdev->dbg_flags)) | 781 | if (enable == hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR)) |
| 708 | return -EALREADY; | 782 | return -EALREADY; |
| 709 | 783 | ||
| 710 | change_bit(HCI_FORCE_STATIC_ADDR, &hdev->dbg_flags); | 784 | hci_dev_change_flag(hdev, HCI_FORCE_STATIC_ADDR); |
| 711 | 785 | ||
| 712 | return count; | 786 | return count; |
| 713 | } | 787 | } |
| @@ -997,6 +1071,11 @@ static int adv_max_interval_get(void *data, u64 *val) | |||
| 997 | DEFINE_SIMPLE_ATTRIBUTE(adv_max_interval_fops, adv_max_interval_get, | 1071 | DEFINE_SIMPLE_ATTRIBUTE(adv_max_interval_fops, adv_max_interval_get, |
| 998 | adv_max_interval_set, "%llu\n"); | 1072 | adv_max_interval_set, "%llu\n"); |
| 999 | 1073 | ||
| 1074 | DEFINE_QUIRK_ATTRIBUTE(quirk_strict_duplicate_filter, | ||
| 1075 | HCI_QUIRK_STRICT_DUPLICATE_FILTER); | ||
| 1076 | DEFINE_QUIRK_ATTRIBUTE(quirk_simultaneous_discovery, | ||
| 1077 | HCI_QUIRK_SIMULTANEOUS_DISCOVERY); | ||
| 1078 | |||
| 1000 | void hci_debugfs_create_le(struct hci_dev *hdev) | 1079 | void hci_debugfs_create_le(struct hci_dev *hdev) |
| 1001 | { | 1080 | { |
| 1002 | debugfs_create_file("identity", 0400, hdev->debugfs, hdev, | 1081 | debugfs_create_file("identity", 0400, hdev->debugfs, hdev, |
| @@ -1041,6 +1120,13 @@ void hci_debugfs_create_le(struct hci_dev *hdev) | |||
| 1041 | &adv_max_interval_fops); | 1120 | &adv_max_interval_fops); |
| 1042 | debugfs_create_u16("discov_interleaved_timeout", 0644, hdev->debugfs, | 1121 | debugfs_create_u16("discov_interleaved_timeout", 0644, hdev->debugfs, |
| 1043 | &hdev->discov_interleaved_timeout); | 1122 | &hdev->discov_interleaved_timeout); |
| 1123 | |||
| 1124 | debugfs_create_file("quirk_strict_duplicate_filter", 0644, | ||
| 1125 | hdev->debugfs, hdev, | ||
| 1126 | &quirk_strict_duplicate_filter_fops); | ||
| 1127 | debugfs_create_file("quirk_simultaneous_discovery", 0644, | ||
| 1128 | hdev->debugfs, hdev, | ||
| 1129 | &quirk_simultaneous_discovery_fops); | ||
| 1044 | } | 1130 | } |
| 1045 | 1131 | ||
| 1046 | void hci_debugfs_create_conn(struct hci_conn *conn) | 1132 | void hci_debugfs_create_conn(struct hci_conn *conn) |
