diff options
author | Marcel Holtmann <marcel@holtmann.org> | 2014-12-20 10:05:15 -0500 |
---|---|---|
committer | Johan Hedberg <johan.hedberg@intel.com> | 2014-12-20 10:51:07 -0500 |
commit | 71c3b60ec6d288f2551b517186b025da4cbb18b5 (patch) | |
tree | 393cd2602ba3688f14263d6ce93ffb3c174f65b7 /net/bluetooth | |
parent | 40ce72b1951c594c7f9f5f5df4aeebed6a07af92 (diff) |
Bluetooth: Move BR/EDR debugfs file creation into hci_debugfs.c
This patch moves the creation of the debugs files for BR/EDR controllers
into hci_debugfs.c file.
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/hci_core.c | 350 | ||||
-rw-r--r-- | net/bluetooth/hci_debugfs.c | 349 |
2 files changed, 350 insertions, 349 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index dde29f4bfaa9..d8976cb01b89 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -139,266 +139,6 @@ static const struct file_operations dut_mode_fops = { | |||
139 | .llseek = default_llseek, | 139 | .llseek = default_llseek, |
140 | }; | 140 | }; |
141 | 141 | ||
142 | static int inquiry_cache_show(struct seq_file *f, void *p) | ||
143 | { | ||
144 | struct hci_dev *hdev = f->private; | ||
145 | struct discovery_state *cache = &hdev->discovery; | ||
146 | struct inquiry_entry *e; | ||
147 | |||
148 | hci_dev_lock(hdev); | ||
149 | |||
150 | list_for_each_entry(e, &cache->all, all) { | ||
151 | struct inquiry_data *data = &e->data; | ||
152 | seq_printf(f, "%pMR %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n", | ||
153 | &data->bdaddr, | ||
154 | data->pscan_rep_mode, data->pscan_period_mode, | ||
155 | data->pscan_mode, data->dev_class[2], | ||
156 | data->dev_class[1], data->dev_class[0], | ||
157 | __le16_to_cpu(data->clock_offset), | ||
158 | data->rssi, data->ssp_mode, e->timestamp); | ||
159 | } | ||
160 | |||
161 | hci_dev_unlock(hdev); | ||
162 | |||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | static int inquiry_cache_open(struct inode *inode, struct file *file) | ||
167 | { | ||
168 | return single_open(file, inquiry_cache_show, inode->i_private); | ||
169 | } | ||
170 | |||
171 | static const struct file_operations inquiry_cache_fops = { | ||
172 | .open = inquiry_cache_open, | ||
173 | .read = seq_read, | ||
174 | .llseek = seq_lseek, | ||
175 | .release = single_release, | ||
176 | }; | ||
177 | |||
178 | static int link_keys_show(struct seq_file *f, void *ptr) | ||
179 | { | ||
180 | struct hci_dev *hdev = f->private; | ||
181 | struct link_key *key; | ||
182 | |||
183 | rcu_read_lock(); | ||
184 | list_for_each_entry_rcu(key, &hdev->link_keys, list) | ||
185 | seq_printf(f, "%pMR %u %*phN %u\n", &key->bdaddr, key->type, | ||
186 | HCI_LINK_KEY_SIZE, key->val, key->pin_len); | ||
187 | rcu_read_unlock(); | ||
188 | |||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static int link_keys_open(struct inode *inode, struct file *file) | ||
193 | { | ||
194 | return single_open(file, link_keys_show, inode->i_private); | ||
195 | } | ||
196 | |||
197 | static const struct file_operations link_keys_fops = { | ||
198 | .open = link_keys_open, | ||
199 | .read = seq_read, | ||
200 | .llseek = seq_lseek, | ||
201 | .release = single_release, | ||
202 | }; | ||
203 | |||
204 | static int dev_class_show(struct seq_file *f, void *ptr) | ||
205 | { | ||
206 | struct hci_dev *hdev = f->private; | ||
207 | |||
208 | hci_dev_lock(hdev); | ||
209 | seq_printf(f, "0x%.2x%.2x%.2x\n", hdev->dev_class[2], | ||
210 | hdev->dev_class[1], hdev->dev_class[0]); | ||
211 | hci_dev_unlock(hdev); | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static int dev_class_open(struct inode *inode, struct file *file) | ||
217 | { | ||
218 | return single_open(file, dev_class_show, inode->i_private); | ||
219 | } | ||
220 | |||
221 | static const struct file_operations dev_class_fops = { | ||
222 | .open = dev_class_open, | ||
223 | .read = seq_read, | ||
224 | .llseek = seq_lseek, | ||
225 | .release = single_release, | ||
226 | }; | ||
227 | |||
228 | static int voice_setting_get(void *data, u64 *val) | ||
229 | { | ||
230 | struct hci_dev *hdev = data; | ||
231 | |||
232 | hci_dev_lock(hdev); | ||
233 | *val = hdev->voice_setting; | ||
234 | hci_dev_unlock(hdev); | ||
235 | |||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | DEFINE_SIMPLE_ATTRIBUTE(voice_setting_fops, voice_setting_get, | ||
240 | NULL, "0x%4.4llx\n"); | ||
241 | |||
242 | static int auto_accept_delay_set(void *data, u64 val) | ||
243 | { | ||
244 | struct hci_dev *hdev = data; | ||
245 | |||
246 | hci_dev_lock(hdev); | ||
247 | hdev->auto_accept_delay = val; | ||
248 | hci_dev_unlock(hdev); | ||
249 | |||
250 | return 0; | ||
251 | } | ||
252 | |||
253 | static int auto_accept_delay_get(void *data, u64 *val) | ||
254 | { | ||
255 | struct hci_dev *hdev = data; | ||
256 | |||
257 | hci_dev_lock(hdev); | ||
258 | *val = hdev->auto_accept_delay; | ||
259 | hci_dev_unlock(hdev); | ||
260 | |||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | DEFINE_SIMPLE_ATTRIBUTE(auto_accept_delay_fops, auto_accept_delay_get, | ||
265 | auto_accept_delay_set, "%llu\n"); | ||
266 | |||
267 | static ssize_t force_sc_support_read(struct file *file, char __user *user_buf, | ||
268 | size_t count, loff_t *ppos) | ||
269 | { | ||
270 | struct hci_dev *hdev = file->private_data; | ||
271 | char buf[3]; | ||
272 | |||
273 | buf[0] = test_bit(HCI_FORCE_SC, &hdev->dbg_flags) ? 'Y': 'N'; | ||
274 | buf[1] = '\n'; | ||
275 | buf[2] = '\0'; | ||
276 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); | ||
277 | } | ||
278 | |||
279 | static ssize_t force_sc_support_write(struct file *file, | ||
280 | const char __user *user_buf, | ||
281 | size_t count, loff_t *ppos) | ||
282 | { | ||
283 | struct hci_dev *hdev = file->private_data; | ||
284 | char buf[32]; | ||
285 | size_t buf_size = min(count, (sizeof(buf)-1)); | ||
286 | bool enable; | ||
287 | |||
288 | if (test_bit(HCI_UP, &hdev->flags)) | ||
289 | return -EBUSY; | ||
290 | |||
291 | if (copy_from_user(buf, user_buf, buf_size)) | ||
292 | return -EFAULT; | ||
293 | |||
294 | buf[buf_size] = '\0'; | ||
295 | if (strtobool(buf, &enable)) | ||
296 | return -EINVAL; | ||
297 | |||
298 | if (enable == test_bit(HCI_FORCE_SC, &hdev->dbg_flags)) | ||
299 | return -EALREADY; | ||
300 | |||
301 | change_bit(HCI_FORCE_SC, &hdev->dbg_flags); | ||
302 | |||
303 | return count; | ||
304 | } | ||
305 | |||
306 | static const struct file_operations force_sc_support_fops = { | ||
307 | .open = simple_open, | ||
308 | .read = force_sc_support_read, | ||
309 | .write = force_sc_support_write, | ||
310 | .llseek = default_llseek, | ||
311 | }; | ||
312 | |||
313 | static ssize_t force_lesc_support_read(struct file *file, char __user *user_buf, | ||
314 | size_t count, loff_t *ppos) | ||
315 | { | ||
316 | struct hci_dev *hdev = file->private_data; | ||
317 | char buf[3]; | ||
318 | |||
319 | buf[0] = test_bit(HCI_FORCE_LESC, &hdev->dbg_flags) ? 'Y': 'N'; | ||
320 | buf[1] = '\n'; | ||
321 | buf[2] = '\0'; | ||
322 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); | ||
323 | } | ||
324 | |||
325 | static ssize_t force_lesc_support_write(struct file *file, | ||
326 | const char __user *user_buf, | ||
327 | size_t count, loff_t *ppos) | ||
328 | { | ||
329 | struct hci_dev *hdev = file->private_data; | ||
330 | char buf[32]; | ||
331 | size_t buf_size = min(count, (sizeof(buf)-1)); | ||
332 | bool enable; | ||
333 | |||
334 | if (copy_from_user(buf, user_buf, buf_size)) | ||
335 | return -EFAULT; | ||
336 | |||
337 | buf[buf_size] = '\0'; | ||
338 | if (strtobool(buf, &enable)) | ||
339 | return -EINVAL; | ||
340 | |||
341 | if (enable == test_bit(HCI_FORCE_LESC, &hdev->dbg_flags)) | ||
342 | return -EALREADY; | ||
343 | |||
344 | change_bit(HCI_FORCE_LESC, &hdev->dbg_flags); | ||
345 | |||
346 | return count; | ||
347 | } | ||
348 | |||
349 | static const struct file_operations force_lesc_support_fops = { | ||
350 | .open = simple_open, | ||
351 | .read = force_lesc_support_read, | ||
352 | .write = force_lesc_support_write, | ||
353 | .llseek = default_llseek, | ||
354 | }; | ||
355 | |||
356 | static ssize_t sc_only_mode_read(struct file *file, char __user *user_buf, | ||
357 | size_t count, loff_t *ppos) | ||
358 | { | ||
359 | struct hci_dev *hdev = file->private_data; | ||
360 | char buf[3]; | ||
361 | |||
362 | buf[0] = test_bit(HCI_SC_ONLY, &hdev->dev_flags) ? 'Y': 'N'; | ||
363 | buf[1] = '\n'; | ||
364 | buf[2] = '\0'; | ||
365 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); | ||
366 | } | ||
367 | |||
368 | static const struct file_operations sc_only_mode_fops = { | ||
369 | .open = simple_open, | ||
370 | .read = sc_only_mode_read, | ||
371 | .llseek = default_llseek, | ||
372 | }; | ||
373 | |||
374 | static int idle_timeout_set(void *data, u64 val) | ||
375 | { | ||
376 | struct hci_dev *hdev = data; | ||
377 | |||
378 | if (val != 0 && (val < 500 || val > 3600000)) | ||
379 | return -EINVAL; | ||
380 | |||
381 | hci_dev_lock(hdev); | ||
382 | hdev->idle_timeout = val; | ||
383 | hci_dev_unlock(hdev); | ||
384 | |||
385 | return 0; | ||
386 | } | ||
387 | |||
388 | static int idle_timeout_get(void *data, u64 *val) | ||
389 | { | ||
390 | struct hci_dev *hdev = data; | ||
391 | |||
392 | hci_dev_lock(hdev); | ||
393 | *val = hdev->idle_timeout; | ||
394 | hci_dev_unlock(hdev); | ||
395 | |||
396 | return 0; | ||
397 | } | ||
398 | |||
399 | DEFINE_SIMPLE_ATTRIBUTE(idle_timeout_fops, idle_timeout_get, | ||
400 | idle_timeout_set, "%llu\n"); | ||
401 | |||
402 | static int rpa_timeout_set(void *data, u64 val) | 142 | static int rpa_timeout_set(void *data, u64 val) |
403 | { | 143 | { |
404 | struct hci_dev *hdev = data; | 144 | struct hci_dev *hdev = data; |
@@ -430,62 +170,6 @@ static int rpa_timeout_get(void *data, u64 *val) | |||
430 | DEFINE_SIMPLE_ATTRIBUTE(rpa_timeout_fops, rpa_timeout_get, | 170 | DEFINE_SIMPLE_ATTRIBUTE(rpa_timeout_fops, rpa_timeout_get, |
431 | rpa_timeout_set, "%llu\n"); | 171 | rpa_timeout_set, "%llu\n"); |
432 | 172 | ||
433 | static int sniff_min_interval_set(void *data, u64 val) | ||
434 | { | ||
435 | struct hci_dev *hdev = data; | ||
436 | |||
437 | if (val == 0 || val % 2 || val > hdev->sniff_max_interval) | ||
438 | return -EINVAL; | ||
439 | |||
440 | hci_dev_lock(hdev); | ||
441 | hdev->sniff_min_interval = val; | ||
442 | hci_dev_unlock(hdev); | ||
443 | |||
444 | return 0; | ||
445 | } | ||
446 | |||
447 | static int sniff_min_interval_get(void *data, u64 *val) | ||
448 | { | ||
449 | struct hci_dev *hdev = data; | ||
450 | |||
451 | hci_dev_lock(hdev); | ||
452 | *val = hdev->sniff_min_interval; | ||
453 | hci_dev_unlock(hdev); | ||
454 | |||
455 | return 0; | ||
456 | } | ||
457 | |||
458 | DEFINE_SIMPLE_ATTRIBUTE(sniff_min_interval_fops, sniff_min_interval_get, | ||
459 | sniff_min_interval_set, "%llu\n"); | ||
460 | |||
461 | static int sniff_max_interval_set(void *data, u64 val) | ||
462 | { | ||
463 | struct hci_dev *hdev = data; | ||
464 | |||
465 | if (val == 0 || val % 2 || val < hdev->sniff_min_interval) | ||
466 | return -EINVAL; | ||
467 | |||
468 | hci_dev_lock(hdev); | ||
469 | hdev->sniff_max_interval = val; | ||
470 | hci_dev_unlock(hdev); | ||
471 | |||
472 | return 0; | ||
473 | } | ||
474 | |||
475 | static int sniff_max_interval_get(void *data, u64 *val) | ||
476 | { | ||
477 | struct hci_dev *hdev = data; | ||
478 | |||
479 | hci_dev_lock(hdev); | ||
480 | *val = hdev->sniff_max_interval; | ||
481 | hci_dev_unlock(hdev); | ||
482 | |||
483 | return 0; | ||
484 | } | ||
485 | |||
486 | DEFINE_SIMPLE_ATTRIBUTE(sniff_max_interval_fops, sniff_max_interval_get, | ||
487 | sniff_max_interval_set, "%llu\n"); | ||
488 | |||
489 | static int identity_show(struct seq_file *f, void *p) | 173 | static int identity_show(struct seq_file *f, void *p) |
490 | { | 174 | { |
491 | struct hci_dev *hdev = f->private; | 175 | struct hci_dev *hdev = f->private; |
@@ -1667,40 +1351,8 @@ static int __hci_init(struct hci_dev *hdev) | |||
1667 | 1351 | ||
1668 | hci_debugfs_create_common(hdev); | 1352 | hci_debugfs_create_common(hdev); |
1669 | 1353 | ||
1670 | if (lmp_bredr_capable(hdev)) { | 1354 | if (lmp_bredr_capable(hdev)) |
1671 | debugfs_create_file("inquiry_cache", 0444, hdev->debugfs, | ||
1672 | hdev, &inquiry_cache_fops); | ||
1673 | debugfs_create_file("link_keys", 0400, hdev->debugfs, | ||
1674 | hdev, &link_keys_fops); | ||
1675 | debugfs_create_file("dev_class", 0444, hdev->debugfs, | ||
1676 | hdev, &dev_class_fops); | ||
1677 | debugfs_create_file("voice_setting", 0444, hdev->debugfs, | ||
1678 | hdev, &voice_setting_fops); | ||
1679 | |||
1680 | hci_debugfs_create_bredr(hdev); | 1355 | hci_debugfs_create_bredr(hdev); |
1681 | } | ||
1682 | |||
1683 | if (lmp_ssp_capable(hdev)) { | ||
1684 | debugfs_create_file("auto_accept_delay", 0644, hdev->debugfs, | ||
1685 | hdev, &auto_accept_delay_fops); | ||
1686 | debugfs_create_file("force_sc_support", 0644, hdev->debugfs, | ||
1687 | hdev, &force_sc_support_fops); | ||
1688 | debugfs_create_file("sc_only_mode", 0444, hdev->debugfs, | ||
1689 | hdev, &sc_only_mode_fops); | ||
1690 | if (lmp_le_capable(hdev)) | ||
1691 | debugfs_create_file("force_lesc_support", 0644, | ||
1692 | hdev->debugfs, hdev, | ||
1693 | &force_lesc_support_fops); | ||
1694 | } | ||
1695 | |||
1696 | if (lmp_sniff_capable(hdev)) { | ||
1697 | debugfs_create_file("idle_timeout", 0644, hdev->debugfs, | ||
1698 | hdev, &idle_timeout_fops); | ||
1699 | debugfs_create_file("sniff_min_interval", 0644, hdev->debugfs, | ||
1700 | hdev, &sniff_min_interval_fops); | ||
1701 | debugfs_create_file("sniff_max_interval", 0644, hdev->debugfs, | ||
1702 | hdev, &sniff_max_interval_fops); | ||
1703 | } | ||
1704 | 1356 | ||
1705 | if (lmp_le_capable(hdev)) { | 1357 | if (lmp_le_capable(hdev)) { |
1706 | debugfs_create_file("identity", 0400, hdev->debugfs, | 1358 | debugfs_create_file("identity", 0400, hdev->debugfs, |
diff --git a/net/bluetooth/hci_debugfs.c b/net/bluetooth/hci_debugfs.c index 4d06beef8c53..435f091301cd 100644 --- a/net/bluetooth/hci_debugfs.c +++ b/net/bluetooth/hci_debugfs.c | |||
@@ -232,8 +232,357 @@ void hci_debugfs_create_common(struct hci_dev *hdev) | |||
232 | &conn_info_max_age_fops); | 232 | &conn_info_max_age_fops); |
233 | } | 233 | } |
234 | 234 | ||
235 | static int inquiry_cache_show(struct seq_file *f, void *p) | ||
236 | { | ||
237 | struct hci_dev *hdev = f->private; | ||
238 | struct discovery_state *cache = &hdev->discovery; | ||
239 | struct inquiry_entry *e; | ||
240 | |||
241 | hci_dev_lock(hdev); | ||
242 | |||
243 | list_for_each_entry(e, &cache->all, all) { | ||
244 | struct inquiry_data *data = &e->data; | ||
245 | seq_printf(f, "%pMR %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n", | ||
246 | &data->bdaddr, | ||
247 | data->pscan_rep_mode, data->pscan_period_mode, | ||
248 | data->pscan_mode, data->dev_class[2], | ||
249 | data->dev_class[1], data->dev_class[0], | ||
250 | __le16_to_cpu(data->clock_offset), | ||
251 | data->rssi, data->ssp_mode, e->timestamp); | ||
252 | } | ||
253 | |||
254 | hci_dev_unlock(hdev); | ||
255 | |||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | static int inquiry_cache_open(struct inode *inode, struct file *file) | ||
260 | { | ||
261 | return single_open(file, inquiry_cache_show, inode->i_private); | ||
262 | } | ||
263 | |||
264 | static const struct file_operations inquiry_cache_fops = { | ||
265 | .open = inquiry_cache_open, | ||
266 | .read = seq_read, | ||
267 | .llseek = seq_lseek, | ||
268 | .release = single_release, | ||
269 | }; | ||
270 | |||
271 | static int link_keys_show(struct seq_file *f, void *ptr) | ||
272 | { | ||
273 | struct hci_dev *hdev = f->private; | ||
274 | struct link_key *key; | ||
275 | |||
276 | rcu_read_lock(); | ||
277 | list_for_each_entry_rcu(key, &hdev->link_keys, list) | ||
278 | seq_printf(f, "%pMR %u %*phN %u\n", &key->bdaddr, key->type, | ||
279 | HCI_LINK_KEY_SIZE, key->val, key->pin_len); | ||
280 | rcu_read_unlock(); | ||
281 | |||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static int link_keys_open(struct inode *inode, struct file *file) | ||
286 | { | ||
287 | return single_open(file, link_keys_show, inode->i_private); | ||
288 | } | ||
289 | |||
290 | static const struct file_operations link_keys_fops = { | ||
291 | .open = link_keys_open, | ||
292 | .read = seq_read, | ||
293 | .llseek = seq_lseek, | ||
294 | .release = single_release, | ||
295 | }; | ||
296 | |||
297 | static int dev_class_show(struct seq_file *f, void *ptr) | ||
298 | { | ||
299 | struct hci_dev *hdev = f->private; | ||
300 | |||
301 | hci_dev_lock(hdev); | ||
302 | seq_printf(f, "0x%.2x%.2x%.2x\n", hdev->dev_class[2], | ||
303 | hdev->dev_class[1], hdev->dev_class[0]); | ||
304 | hci_dev_unlock(hdev); | ||
305 | |||
306 | return 0; | ||
307 | } | ||
308 | |||
309 | static int dev_class_open(struct inode *inode, struct file *file) | ||
310 | { | ||
311 | return single_open(file, dev_class_show, inode->i_private); | ||
312 | } | ||
313 | |||
314 | static const struct file_operations dev_class_fops = { | ||
315 | .open = dev_class_open, | ||
316 | .read = seq_read, | ||
317 | .llseek = seq_lseek, | ||
318 | .release = single_release, | ||
319 | }; | ||
320 | |||
321 | static int voice_setting_get(void *data, u64 *val) | ||
322 | { | ||
323 | struct hci_dev *hdev = data; | ||
324 | |||
325 | hci_dev_lock(hdev); | ||
326 | *val = hdev->voice_setting; | ||
327 | hci_dev_unlock(hdev); | ||
328 | |||
329 | return 0; | ||
330 | } | ||
331 | |||
332 | DEFINE_SIMPLE_ATTRIBUTE(voice_setting_fops, voice_setting_get, | ||
333 | NULL, "0x%4.4llx\n"); | ||
334 | |||
335 | static int auto_accept_delay_set(void *data, u64 val) | ||
336 | { | ||
337 | struct hci_dev *hdev = data; | ||
338 | |||
339 | hci_dev_lock(hdev); | ||
340 | hdev->auto_accept_delay = val; | ||
341 | hci_dev_unlock(hdev); | ||
342 | |||
343 | return 0; | ||
344 | } | ||
345 | |||
346 | static int auto_accept_delay_get(void *data, u64 *val) | ||
347 | { | ||
348 | struct hci_dev *hdev = data; | ||
349 | |||
350 | hci_dev_lock(hdev); | ||
351 | *val = hdev->auto_accept_delay; | ||
352 | hci_dev_unlock(hdev); | ||
353 | |||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | DEFINE_SIMPLE_ATTRIBUTE(auto_accept_delay_fops, auto_accept_delay_get, | ||
358 | auto_accept_delay_set, "%llu\n"); | ||
359 | |||
360 | static ssize_t sc_only_mode_read(struct file *file, char __user *user_buf, | ||
361 | size_t count, loff_t *ppos) | ||
362 | { | ||
363 | struct hci_dev *hdev = file->private_data; | ||
364 | char buf[3]; | ||
365 | |||
366 | buf[0] = test_bit(HCI_SC_ONLY, &hdev->dev_flags) ? 'Y': 'N'; | ||
367 | buf[1] = '\n'; | ||
368 | buf[2] = '\0'; | ||
369 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); | ||
370 | } | ||
371 | |||
372 | static const struct file_operations sc_only_mode_fops = { | ||
373 | .open = simple_open, | ||
374 | .read = sc_only_mode_read, | ||
375 | .llseek = default_llseek, | ||
376 | }; | ||
377 | |||
378 | static ssize_t force_sc_support_read(struct file *file, char __user *user_buf, | ||
379 | size_t count, loff_t *ppos) | ||
380 | { | ||
381 | struct hci_dev *hdev = file->private_data; | ||
382 | char buf[3]; | ||
383 | |||
384 | buf[0] = test_bit(HCI_FORCE_SC, &hdev->dbg_flags) ? 'Y': 'N'; | ||
385 | buf[1] = '\n'; | ||
386 | buf[2] = '\0'; | ||
387 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); | ||
388 | } | ||
389 | |||
390 | static ssize_t force_sc_support_write(struct file *file, | ||
391 | const char __user *user_buf, | ||
392 | size_t count, loff_t *ppos) | ||
393 | { | ||
394 | struct hci_dev *hdev = file->private_data; | ||
395 | char buf[32]; | ||
396 | size_t buf_size = min(count, (sizeof(buf)-1)); | ||
397 | bool enable; | ||
398 | |||
399 | if (test_bit(HCI_UP, &hdev->flags)) | ||
400 | return -EBUSY; | ||
401 | |||
402 | if (copy_from_user(buf, user_buf, buf_size)) | ||
403 | return -EFAULT; | ||
404 | |||
405 | buf[buf_size] = '\0'; | ||
406 | if (strtobool(buf, &enable)) | ||
407 | return -EINVAL; | ||
408 | |||
409 | if (enable == test_bit(HCI_FORCE_SC, &hdev->dbg_flags)) | ||
410 | return -EALREADY; | ||
411 | |||
412 | change_bit(HCI_FORCE_SC, &hdev->dbg_flags); | ||
413 | |||
414 | return count; | ||
415 | } | ||
416 | |||
417 | static const struct file_operations force_sc_support_fops = { | ||
418 | .open = simple_open, | ||
419 | .read = force_sc_support_read, | ||
420 | .write = force_sc_support_write, | ||
421 | .llseek = default_llseek, | ||
422 | }; | ||
423 | |||
424 | static ssize_t force_lesc_support_read(struct file *file, | ||
425 | char __user *user_buf, | ||
426 | size_t count, loff_t *ppos) | ||
427 | { | ||
428 | struct hci_dev *hdev = file->private_data; | ||
429 | char buf[3]; | ||
430 | |||
431 | buf[0] = test_bit(HCI_FORCE_LESC, &hdev->dbg_flags) ? 'Y': 'N'; | ||
432 | buf[1] = '\n'; | ||
433 | buf[2] = '\0'; | ||
434 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); | ||
435 | } | ||
436 | |||
437 | static ssize_t force_lesc_support_write(struct file *file, | ||
438 | const char __user *user_buf, | ||
439 | size_t count, loff_t *ppos) | ||
440 | { | ||
441 | struct hci_dev *hdev = file->private_data; | ||
442 | char buf[32]; | ||
443 | size_t buf_size = min(count, (sizeof(buf)-1)); | ||
444 | bool enable; | ||
445 | |||
446 | if (copy_from_user(buf, user_buf, buf_size)) | ||
447 | return -EFAULT; | ||
448 | |||
449 | buf[buf_size] = '\0'; | ||
450 | if (strtobool(buf, &enable)) | ||
451 | return -EINVAL; | ||
452 | |||
453 | if (enable == test_bit(HCI_FORCE_LESC, &hdev->dbg_flags)) | ||
454 | return -EALREADY; | ||
455 | |||
456 | change_bit(HCI_FORCE_LESC, &hdev->dbg_flags); | ||
457 | |||
458 | return count; | ||
459 | } | ||
460 | |||
461 | static const struct file_operations force_lesc_support_fops = { | ||
462 | .open = simple_open, | ||
463 | .read = force_lesc_support_read, | ||
464 | .write = force_lesc_support_write, | ||
465 | .llseek = default_llseek, | ||
466 | }; | ||
467 | |||
468 | static int idle_timeout_set(void *data, u64 val) | ||
469 | { | ||
470 | struct hci_dev *hdev = data; | ||
471 | |||
472 | if (val != 0 && (val < 500 || val > 3600000)) | ||
473 | return -EINVAL; | ||
474 | |||
475 | hci_dev_lock(hdev); | ||
476 | hdev->idle_timeout = val; | ||
477 | hci_dev_unlock(hdev); | ||
478 | |||
479 | return 0; | ||
480 | } | ||
481 | |||
482 | static int idle_timeout_get(void *data, u64 *val) | ||
483 | { | ||
484 | struct hci_dev *hdev = data; | ||
485 | |||
486 | hci_dev_lock(hdev); | ||
487 | *val = hdev->idle_timeout; | ||
488 | hci_dev_unlock(hdev); | ||
489 | |||
490 | return 0; | ||
491 | } | ||
492 | |||
493 | DEFINE_SIMPLE_ATTRIBUTE(idle_timeout_fops, idle_timeout_get, | ||
494 | idle_timeout_set, "%llu\n"); | ||
495 | |||
496 | static int sniff_min_interval_set(void *data, u64 val) | ||
497 | { | ||
498 | struct hci_dev *hdev = data; | ||
499 | |||
500 | if (val == 0 || val % 2 || val > hdev->sniff_max_interval) | ||
501 | return -EINVAL; | ||
502 | |||
503 | hci_dev_lock(hdev); | ||
504 | hdev->sniff_min_interval = val; | ||
505 | hci_dev_unlock(hdev); | ||
506 | |||
507 | return 0; | ||
508 | } | ||
509 | |||
510 | static int sniff_min_interval_get(void *data, u64 *val) | ||
511 | { | ||
512 | struct hci_dev *hdev = data; | ||
513 | |||
514 | hci_dev_lock(hdev); | ||
515 | *val = hdev->sniff_min_interval; | ||
516 | hci_dev_unlock(hdev); | ||
517 | |||
518 | return 0; | ||
519 | } | ||
520 | |||
521 | DEFINE_SIMPLE_ATTRIBUTE(sniff_min_interval_fops, sniff_min_interval_get, | ||
522 | sniff_min_interval_set, "%llu\n"); | ||
523 | |||
524 | static int sniff_max_interval_set(void *data, u64 val) | ||
525 | { | ||
526 | struct hci_dev *hdev = data; | ||
527 | |||
528 | if (val == 0 || val % 2 || val < hdev->sniff_min_interval) | ||
529 | return -EINVAL; | ||
530 | |||
531 | hci_dev_lock(hdev); | ||
532 | hdev->sniff_max_interval = val; | ||
533 | hci_dev_unlock(hdev); | ||
534 | |||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | static int sniff_max_interval_get(void *data, u64 *val) | ||
539 | { | ||
540 | struct hci_dev *hdev = data; | ||
541 | |||
542 | hci_dev_lock(hdev); | ||
543 | *val = hdev->sniff_max_interval; | ||
544 | hci_dev_unlock(hdev); | ||
545 | |||
546 | return 0; | ||
547 | } | ||
548 | |||
549 | DEFINE_SIMPLE_ATTRIBUTE(sniff_max_interval_fops, sniff_max_interval_get, | ||
550 | sniff_max_interval_set, "%llu\n"); | ||
551 | |||
235 | void hci_debugfs_create_bredr(struct hci_dev *hdev) | 552 | void hci_debugfs_create_bredr(struct hci_dev *hdev) |
236 | { | 553 | { |
554 | debugfs_create_file("inquiry_cache", 0444, hdev->debugfs, hdev, | ||
555 | &inquiry_cache_fops); | ||
556 | debugfs_create_file("link_keys", 0400, hdev->debugfs, hdev, | ||
557 | &link_keys_fops); | ||
558 | debugfs_create_file("dev_class", 0444, hdev->debugfs, hdev, | ||
559 | &dev_class_fops); | ||
560 | debugfs_create_file("voice_setting", 0444, hdev->debugfs, hdev, | ||
561 | &voice_setting_fops); | ||
562 | |||
563 | if (lmp_ssp_capable(hdev)) { | ||
564 | debugfs_create_file("auto_accept_delay", 0644, hdev->debugfs, | ||
565 | hdev, &auto_accept_delay_fops); | ||
566 | debugfs_create_file("sc_only_mode", 0444, hdev->debugfs, | ||
567 | hdev, &sc_only_mode_fops); | ||
568 | |||
569 | debugfs_create_file("force_sc_support", 0644, hdev->debugfs, | ||
570 | hdev, &force_sc_support_fops); | ||
571 | |||
572 | if (lmp_le_capable(hdev)) | ||
573 | debugfs_create_file("force_lesc_support", 0644, | ||
574 | hdev->debugfs, hdev, | ||
575 | &force_lesc_support_fops); | ||
576 | } | ||
577 | |||
578 | if (lmp_sniff_capable(hdev)) { | ||
579 | debugfs_create_file("idle_timeout", 0644, hdev->debugfs, | ||
580 | hdev, &idle_timeout_fops); | ||
581 | debugfs_create_file("sniff_min_interval", 0644, hdev->debugfs, | ||
582 | hdev, &sniff_min_interval_fops); | ||
583 | debugfs_create_file("sniff_max_interval", 0644, hdev->debugfs, | ||
584 | hdev, &sniff_max_interval_fops); | ||
585 | } | ||
237 | } | 586 | } |
238 | 587 | ||
239 | void hci_debugfs_create_le(struct hci_dev *hdev) | 588 | void hci_debugfs_create_le(struct hci_dev *hdev) |