blob: 57403bd567d0680f7e890b6e3ddcf7f83f9511fe [file] [log] [blame]
Marcel Holtmann60c5f5f2014-12-20 16:05:13 +01001/*
2 BlueZ - Bluetooth protocol stack for Linux
3
4 Copyright (C) 2014 Intel Corporation
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License version 2 as
8 published by the Free Software Foundation;
9
10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
11 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
13 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
14 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
15 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
19 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
20 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
21 SOFTWARE IS DISCLAIMED.
22*/
23
24#include <linux/debugfs.h>
25
26#include <net/bluetooth/bluetooth.h>
27#include <net/bluetooth/hci_core.h>
28
29#include "hci_debugfs.h"
30
Jakub Pawlowskib55d1ab2015-03-20 11:14:50 -070031#define DEFINE_QUIRK_ATTRIBUTE(__name, __quirk) \
32static 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 \
45static 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 \
72static const struct file_operations __name ## _fops = { \
73 .open = simple_open, \
74 .read = __name ## _read, \
75 .write = __name ## _write, \
76 .llseek = default_llseek, \
77} \
78
Marcel Holtmann5177a832016-07-17 19:55:16 +020079#define DEFINE_INFO_ATTRIBUTE(__name, __field) \
80static int __name ## _show(struct seq_file *f, void *ptr) \
81{ \
82 struct hci_dev *hdev = f->private; \
83 \
84 hci_dev_lock(hdev); \
85 seq_printf(f, "%s\n", hdev->__field ? : ""); \
86 hci_dev_unlock(hdev); \
87 \
88 return 0; \
89} \
90 \
Andy Shevchenko22b371c2017-11-22 23:15:46 +020091DEFINE_SHOW_ATTRIBUTE(__name)
92
93#define DEFINE_SHOW_ATTRIBUTE(__name) \
Marcel Holtmann5177a832016-07-17 19:55:16 +020094static int __name ## _open(struct inode *inode, struct file *file) \
95{ \
96 return single_open(file, __name ## _show, inode->i_private); \
97} \
98 \
99static const struct file_operations __name ## _fops = { \
100 .open = __name ## _open, \
101 .read = seq_read, \
102 .llseek = seq_lseek, \
103 .release = single_release, \
104} \
105
Marcel Holtmann40ce72b2014-12-20 16:05:14 +0100106static int features_show(struct seq_file *f, void *ptr)
107{
108 struct hci_dev *hdev = f->private;
109 u8 p;
110
111 hci_dev_lock(hdev);
Andy Shevchenko8a9507942017-12-11 12:10:33 +0200112 for (p = 0; p < HCI_MAX_PAGES && p <= hdev->max_page; p++)
113 seq_printf(f, "%2u: %8ph\n", p, hdev->features[p]);
Marcel Holtmann40ce72b2014-12-20 16:05:14 +0100114 if (lmp_le_capable(hdev))
Andy Shevchenko8a9507942017-12-11 12:10:33 +0200115 seq_printf(f, "LE: %8ph\n", hdev->le_features);
Marcel Holtmann40ce72b2014-12-20 16:05:14 +0100116 hci_dev_unlock(hdev);
117
118 return 0;
119}
120
Andy Shevchenko22b371c2017-11-22 23:15:46 +0200121DEFINE_SHOW_ATTRIBUTE(features);
Marcel Holtmann40ce72b2014-12-20 16:05:14 +0100122
Marcel Holtmannc3370de2015-04-01 13:21:37 -0700123static int device_id_show(struct seq_file *f, void *ptr)
124{
125 struct hci_dev *hdev = f->private;
126
127 hci_dev_lock(hdev);
128 seq_printf(f, "%4.4x:%4.4x:%4.4x:%4.4x\n", hdev->devid_source,
129 hdev->devid_vendor, hdev->devid_product, hdev->devid_version);
130 hci_dev_unlock(hdev);
131
132 return 0;
133}
134
Andy Shevchenko22b371c2017-11-22 23:15:46 +0200135DEFINE_SHOW_ATTRIBUTE(device_id);
Marcel Holtmannc3370de2015-04-01 13:21:37 -0700136
Marcel Holtmann40ce72b2014-12-20 16:05:14 +0100137static int device_list_show(struct seq_file *f, void *ptr)
138{
139 struct hci_dev *hdev = f->private;
140 struct hci_conn_params *p;
141 struct bdaddr_list *b;
142
143 hci_dev_lock(hdev);
144 list_for_each_entry(b, &hdev->whitelist, list)
145 seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type);
146 list_for_each_entry(p, &hdev->le_conn_params, list) {
147 seq_printf(f, "%pMR (type %u) %u\n", &p->addr, p->addr_type,
148 p->auto_connect);
149 }
150 hci_dev_unlock(hdev);
151
152 return 0;
153}
154
Andy Shevchenko22b371c2017-11-22 23:15:46 +0200155DEFINE_SHOW_ATTRIBUTE(device_list);
Marcel Holtmann40ce72b2014-12-20 16:05:14 +0100156
157static int blacklist_show(struct seq_file *f, void *p)
158{
159 struct hci_dev *hdev = f->private;
160 struct bdaddr_list *b;
161
162 hci_dev_lock(hdev);
163 list_for_each_entry(b, &hdev->blacklist, list)
164 seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type);
165 hci_dev_unlock(hdev);
166
167 return 0;
168}
169
Andy Shevchenko22b371c2017-11-22 23:15:46 +0200170DEFINE_SHOW_ATTRIBUTE(blacklist);
Marcel Holtmann40ce72b2014-12-20 16:05:14 +0100171
172static int uuids_show(struct seq_file *f, void *p)
173{
174 struct hci_dev *hdev = f->private;
175 struct bt_uuid *uuid;
176
177 hci_dev_lock(hdev);
178 list_for_each_entry(uuid, &hdev->uuids, list) {
179 u8 i, val[16];
180
181 /* The Bluetooth UUID values are stored in big endian,
182 * but with reversed byte order. So convert them into
183 * the right order for the %pUb modifier.
184 */
185 for (i = 0; i < 16; i++)
186 val[i] = uuid->uuid[15 - i];
187
188 seq_printf(f, "%pUb\n", val);
189 }
190 hci_dev_unlock(hdev);
191
192 return 0;
193}
194
Andy Shevchenko22b371c2017-11-22 23:15:46 +0200195DEFINE_SHOW_ATTRIBUTE(uuids);
Marcel Holtmann40ce72b2014-12-20 16:05:14 +0100196
Marcel Holtmann6858bcd2015-01-31 21:01:07 -0800197static int remote_oob_show(struct seq_file *f, void *ptr)
198{
199 struct hci_dev *hdev = f->private;
200 struct oob_data *data;
201
202 hci_dev_lock(hdev);
203 list_for_each_entry(data, &hdev->remote_oob_data, list) {
204 seq_printf(f, "%pMR (type %u) %u %*phN %*phN %*phN %*phN\n",
205 &data->bdaddr, data->bdaddr_type, data->present,
206 16, data->hash192, 16, data->rand192,
Marcel Holtmannb880ab82015-03-16 12:34:58 -0700207 16, data->hash256, 16, data->rand256);
Marcel Holtmann6858bcd2015-01-31 21:01:07 -0800208 }
209 hci_dev_unlock(hdev);
210
211 return 0;
212}
213
Andy Shevchenko22b371c2017-11-22 23:15:46 +0200214DEFINE_SHOW_ATTRIBUTE(remote_oob);
Marcel Holtmann6858bcd2015-01-31 21:01:07 -0800215
Marcel Holtmann40ce72b2014-12-20 16:05:14 +0100216static int conn_info_min_age_set(void *data, u64 val)
217{
218 struct hci_dev *hdev = data;
219
220 if (val == 0 || val > hdev->conn_info_max_age)
221 return -EINVAL;
222
223 hci_dev_lock(hdev);
224 hdev->conn_info_min_age = val;
225 hci_dev_unlock(hdev);
226
227 return 0;
228}
229
230static int conn_info_min_age_get(void *data, u64 *val)
231{
232 struct hci_dev *hdev = data;
233
234 hci_dev_lock(hdev);
235 *val = hdev->conn_info_min_age;
236 hci_dev_unlock(hdev);
237
238 return 0;
239}
240
241DEFINE_SIMPLE_ATTRIBUTE(conn_info_min_age_fops, conn_info_min_age_get,
242 conn_info_min_age_set, "%llu\n");
243
244static int conn_info_max_age_set(void *data, u64 val)
245{
246 struct hci_dev *hdev = data;
247
248 if (val == 0 || val < hdev->conn_info_min_age)
249 return -EINVAL;
250
251 hci_dev_lock(hdev);
252 hdev->conn_info_max_age = val;
253 hci_dev_unlock(hdev);
254
255 return 0;
256}
257
258static int conn_info_max_age_get(void *data, u64 *val)
259{
260 struct hci_dev *hdev = data;
261
262 hci_dev_lock(hdev);
263 *val = hdev->conn_info_max_age;
264 hci_dev_unlock(hdev);
265
266 return 0;
267}
268
269DEFINE_SIMPLE_ATTRIBUTE(conn_info_max_age_fops, conn_info_max_age_get,
270 conn_info_max_age_set, "%llu\n");
271
Marcel Holtmann0886aea2015-01-31 15:12:06 -0800272static ssize_t use_debug_keys_read(struct file *file, char __user *user_buf,
273 size_t count, loff_t *ppos)
274{
275 struct hci_dev *hdev = file->private_data;
276 char buf[3];
277
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700278 buf[0] = hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS) ? 'Y': 'N';
Marcel Holtmann0886aea2015-01-31 15:12:06 -0800279 buf[1] = '\n';
280 buf[2] = '\0';
281 return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
282}
283
284static const struct file_operations use_debug_keys_fops = {
285 .open = simple_open,
286 .read = use_debug_keys_read,
287 .llseek = default_llseek,
288};
289
Marcel Holtmanncb0d2fa2014-12-31 14:43:19 -0800290static ssize_t sc_only_mode_read(struct file *file, char __user *user_buf,
291 size_t count, loff_t *ppos)
292{
293 struct hci_dev *hdev = file->private_data;
294 char buf[3];
295
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700296 buf[0] = hci_dev_test_flag(hdev, HCI_SC_ONLY) ? 'Y': 'N';
Marcel Holtmanncb0d2fa2014-12-31 14:43:19 -0800297 buf[1] = '\n';
298 buf[2] = '\0';
299 return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
300}
301
302static const struct file_operations sc_only_mode_fops = {
303 .open = simple_open,
304 .read = sc_only_mode_read,
305 .llseek = default_llseek,
306};
307
Marcel Holtmann5177a832016-07-17 19:55:16 +0200308DEFINE_INFO_ATTRIBUTE(hardware_info, hw_info);
309DEFINE_INFO_ATTRIBUTE(firmware_info, fw_info);
310
Marcel Holtmann60c5f5f2014-12-20 16:05:13 +0100311void hci_debugfs_create_common(struct hci_dev *hdev)
312{
Marcel Holtmann40ce72b2014-12-20 16:05:14 +0100313 debugfs_create_file("features", 0444, hdev->debugfs, hdev,
314 &features_fops);
315 debugfs_create_u16("manufacturer", 0444, hdev->debugfs,
316 &hdev->manufacturer);
317 debugfs_create_u8("hci_version", 0444, hdev->debugfs, &hdev->hci_ver);
318 debugfs_create_u16("hci_revision", 0444, hdev->debugfs, &hdev->hci_rev);
Marcel Holtmann5789f372015-01-31 19:54:39 -0800319 debugfs_create_u8("hardware_error", 0444, hdev->debugfs,
320 &hdev->hw_error_code);
Marcel Holtmannc3370de2015-04-01 13:21:37 -0700321 debugfs_create_file("device_id", 0444, hdev->debugfs, hdev,
322 &device_id_fops);
Marcel Holtmann5789f372015-01-31 19:54:39 -0800323
Marcel Holtmann40ce72b2014-12-20 16:05:14 +0100324 debugfs_create_file("device_list", 0444, hdev->debugfs, hdev,
325 &device_list_fops);
326 debugfs_create_file("blacklist", 0444, hdev->debugfs, hdev,
327 &blacklist_fops);
328 debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops);
Marcel Holtmann6858bcd2015-01-31 21:01:07 -0800329 debugfs_create_file("remote_oob", 0400, hdev->debugfs, hdev,
330 &remote_oob_fops);
Marcel Holtmann40ce72b2014-12-20 16:05:14 +0100331
332 debugfs_create_file("conn_info_min_age", 0644, hdev->debugfs, hdev,
333 &conn_info_min_age_fops);
334 debugfs_create_file("conn_info_max_age", 0644, hdev->debugfs, hdev,
335 &conn_info_max_age_fops);
Marcel Holtmanncb0d2fa2014-12-31 14:43:19 -0800336
Marcel Holtmann0886aea2015-01-31 15:12:06 -0800337 if (lmp_ssp_capable(hdev) || lmp_le_capable(hdev))
338 debugfs_create_file("use_debug_keys", 0444, hdev->debugfs,
339 hdev, &use_debug_keys_fops);
340
Marcel Holtmanncb0d2fa2014-12-31 14:43:19 -0800341 if (lmp_sc_capable(hdev) || lmp_le_capable(hdev))
342 debugfs_create_file("sc_only_mode", 0444, hdev->debugfs,
343 hdev, &sc_only_mode_fops);
Marcel Holtmann5177a832016-07-17 19:55:16 +0200344
345 if (hdev->hw_info)
346 debugfs_create_file("hardware_info", 0444, hdev->debugfs,
347 hdev, &hardware_info_fops);
348
349 if (hdev->fw_info)
350 debugfs_create_file("firmware_info", 0444, hdev->debugfs,
351 hdev, &firmware_info_fops);
Marcel Holtmann60c5f5f2014-12-20 16:05:13 +0100352}
353
Marcel Holtmann71c3b602014-12-20 16:05:15 +0100354static int inquiry_cache_show(struct seq_file *f, void *p)
355{
356 struct hci_dev *hdev = f->private;
357 struct discovery_state *cache = &hdev->discovery;
358 struct inquiry_entry *e;
359
360 hci_dev_lock(hdev);
361
362 list_for_each_entry(e, &cache->all, all) {
363 struct inquiry_data *data = &e->data;
364 seq_printf(f, "%pMR %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n",
365 &data->bdaddr,
366 data->pscan_rep_mode, data->pscan_period_mode,
367 data->pscan_mode, data->dev_class[2],
368 data->dev_class[1], data->dev_class[0],
369 __le16_to_cpu(data->clock_offset),
370 data->rssi, data->ssp_mode, e->timestamp);
371 }
372
373 hci_dev_unlock(hdev);
374
375 return 0;
376}
377
Andy Shevchenko22b371c2017-11-22 23:15:46 +0200378DEFINE_SHOW_ATTRIBUTE(inquiry_cache);
Marcel Holtmann71c3b602014-12-20 16:05:15 +0100379
380static int link_keys_show(struct seq_file *f, void *ptr)
381{
382 struct hci_dev *hdev = f->private;
383 struct link_key *key;
384
385 rcu_read_lock();
386 list_for_each_entry_rcu(key, &hdev->link_keys, list)
387 seq_printf(f, "%pMR %u %*phN %u\n", &key->bdaddr, key->type,
388 HCI_LINK_KEY_SIZE, key->val, key->pin_len);
389 rcu_read_unlock();
390
391 return 0;
392}
393
Andy Shevchenko22b371c2017-11-22 23:15:46 +0200394DEFINE_SHOW_ATTRIBUTE(link_keys);
Marcel Holtmann71c3b602014-12-20 16:05:15 +0100395
396static int dev_class_show(struct seq_file *f, void *ptr)
397{
398 struct hci_dev *hdev = f->private;
399
400 hci_dev_lock(hdev);
401 seq_printf(f, "0x%.2x%.2x%.2x\n", hdev->dev_class[2],
402 hdev->dev_class[1], hdev->dev_class[0]);
403 hci_dev_unlock(hdev);
404
405 return 0;
406}
407
Andy Shevchenko22b371c2017-11-22 23:15:46 +0200408DEFINE_SHOW_ATTRIBUTE(dev_class);
Marcel Holtmann71c3b602014-12-20 16:05:15 +0100409
410static int voice_setting_get(void *data, u64 *val)
411{
412 struct hci_dev *hdev = data;
413
414 hci_dev_lock(hdev);
415 *val = hdev->voice_setting;
416 hci_dev_unlock(hdev);
417
418 return 0;
419}
420
421DEFINE_SIMPLE_ATTRIBUTE(voice_setting_fops, voice_setting_get,
422 NULL, "0x%4.4llx\n");
423
Marcel Holtmann6e072312015-01-31 15:07:51 -0800424static ssize_t ssp_debug_mode_read(struct file *file, char __user *user_buf,
425 size_t count, loff_t *ppos)
426{
427 struct hci_dev *hdev = file->private_data;
428 char buf[3];
429
430 buf[0] = hdev->ssp_debug_mode ? 'Y': 'N';
431 buf[1] = '\n';
432 buf[2] = '\0';
433 return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
434}
435
436static const struct file_operations ssp_debug_mode_fops = {
437 .open = simple_open,
438 .read = ssp_debug_mode_read,
439 .llseek = default_llseek,
440};
441
Marcel Holtmann71c3b602014-12-20 16:05:15 +0100442static int auto_accept_delay_set(void *data, u64 val)
443{
444 struct hci_dev *hdev = data;
445
446 hci_dev_lock(hdev);
447 hdev->auto_accept_delay = val;
448 hci_dev_unlock(hdev);
449
450 return 0;
451}
452
453static int auto_accept_delay_get(void *data, u64 *val)
454{
455 struct hci_dev *hdev = data;
456
457 hci_dev_lock(hdev);
458 *val = hdev->auto_accept_delay;
459 hci_dev_unlock(hdev);
460
461 return 0;
462}
463
464DEFINE_SIMPLE_ATTRIBUTE(auto_accept_delay_fops, auto_accept_delay_get,
465 auto_accept_delay_set, "%llu\n");
466
Marcel Holtmann71c3b602014-12-20 16:05:15 +0100467static int idle_timeout_set(void *data, u64 val)
468{
469 struct hci_dev *hdev = data;
470
471 if (val != 0 && (val < 500 || val > 3600000))
472 return -EINVAL;
473
474 hci_dev_lock(hdev);
475 hdev->idle_timeout = val;
476 hci_dev_unlock(hdev);
477
478 return 0;
479}
480
481static int idle_timeout_get(void *data, u64 *val)
482{
483 struct hci_dev *hdev = data;
484
485 hci_dev_lock(hdev);
486 *val = hdev->idle_timeout;
487 hci_dev_unlock(hdev);
488
489 return 0;
490}
491
492DEFINE_SIMPLE_ATTRIBUTE(idle_timeout_fops, idle_timeout_get,
493 idle_timeout_set, "%llu\n");
494
495static int sniff_min_interval_set(void *data, u64 val)
496{
497 struct hci_dev *hdev = data;
498
499 if (val == 0 || val % 2 || val > hdev->sniff_max_interval)
500 return -EINVAL;
501
502 hci_dev_lock(hdev);
503 hdev->sniff_min_interval = val;
504 hci_dev_unlock(hdev);
505
506 return 0;
507}
508
509static int sniff_min_interval_get(void *data, u64 *val)
510{
511 struct hci_dev *hdev = data;
512
513 hci_dev_lock(hdev);
514 *val = hdev->sniff_min_interval;
515 hci_dev_unlock(hdev);
516
517 return 0;
518}
519
520DEFINE_SIMPLE_ATTRIBUTE(sniff_min_interval_fops, sniff_min_interval_get,
521 sniff_min_interval_set, "%llu\n");
522
523static int sniff_max_interval_set(void *data, u64 val)
524{
525 struct hci_dev *hdev = data;
526
527 if (val == 0 || val % 2 || val < hdev->sniff_min_interval)
528 return -EINVAL;
529
530 hci_dev_lock(hdev);
531 hdev->sniff_max_interval = val;
532 hci_dev_unlock(hdev);
533
534 return 0;
535}
536
537static int sniff_max_interval_get(void *data, u64 *val)
538{
539 struct hci_dev *hdev = data;
540
541 hci_dev_lock(hdev);
542 *val = hdev->sniff_max_interval;
543 hci_dev_unlock(hdev);
544
545 return 0;
546}
547
548DEFINE_SIMPLE_ATTRIBUTE(sniff_max_interval_fops, sniff_max_interval_get,
549 sniff_max_interval_set, "%llu\n");
550
Marcel Holtmann60c5f5f2014-12-20 16:05:13 +0100551void hci_debugfs_create_bredr(struct hci_dev *hdev)
552{
Marcel Holtmann71c3b602014-12-20 16:05:15 +0100553 debugfs_create_file("inquiry_cache", 0444, hdev->debugfs, hdev,
554 &inquiry_cache_fops);
555 debugfs_create_file("link_keys", 0400, hdev->debugfs, hdev,
556 &link_keys_fops);
557 debugfs_create_file("dev_class", 0444, hdev->debugfs, hdev,
558 &dev_class_fops);
559 debugfs_create_file("voice_setting", 0444, hdev->debugfs, hdev,
560 &voice_setting_fops);
561
Marcel Holtmann6e072312015-01-31 15:07:51 -0800562 if (lmp_ssp_capable(hdev)) {
563 debugfs_create_file("ssp_debug_mode", 0444, hdev->debugfs,
564 hdev, &ssp_debug_mode_fops);
Marcel Holtmann71c3b602014-12-20 16:05:15 +0100565 debugfs_create_file("auto_accept_delay", 0644, hdev->debugfs,
566 hdev, &auto_accept_delay_fops);
Marcel Holtmann6e072312015-01-31 15:07:51 -0800567 }
Marcel Holtmann71c3b602014-12-20 16:05:15 +0100568
569 if (lmp_sniff_capable(hdev)) {
570 debugfs_create_file("idle_timeout", 0644, hdev->debugfs,
571 hdev, &idle_timeout_fops);
572 debugfs_create_file("sniff_min_interval", 0644, hdev->debugfs,
573 hdev, &sniff_min_interval_fops);
574 debugfs_create_file("sniff_max_interval", 0644, hdev->debugfs,
575 hdev, &sniff_max_interval_fops);
576 }
Marcel Holtmann60c5f5f2014-12-20 16:05:13 +0100577}
578
Marcel Holtmann3a5c82b2014-12-20 16:05:16 +0100579static int identity_show(struct seq_file *f, void *p)
580{
581 struct hci_dev *hdev = f->private;
582 bdaddr_t addr;
583 u8 addr_type;
584
585 hci_dev_lock(hdev);
586
587 hci_copy_identity_address(hdev, &addr, &addr_type);
588
589 seq_printf(f, "%pMR (type %u) %*phN %pMR\n", &addr, addr_type,
590 16, hdev->irk, &hdev->rpa);
591
592 hci_dev_unlock(hdev);
593
594 return 0;
595}
596
Andy Shevchenko22b371c2017-11-22 23:15:46 +0200597DEFINE_SHOW_ATTRIBUTE(identity);
Marcel Holtmann3a5c82b2014-12-20 16:05:16 +0100598
599static int rpa_timeout_set(void *data, u64 val)
600{
601 struct hci_dev *hdev = data;
602
603 /* Require the RPA timeout to be at least 30 seconds and at most
604 * 24 hours.
605 */
606 if (val < 30 || val > (60 * 60 * 24))
607 return -EINVAL;
608
609 hci_dev_lock(hdev);
610 hdev->rpa_timeout = val;
611 hci_dev_unlock(hdev);
612
613 return 0;
614}
615
616static int rpa_timeout_get(void *data, u64 *val)
617{
618 struct hci_dev *hdev = data;
619
620 hci_dev_lock(hdev);
621 *val = hdev->rpa_timeout;
622 hci_dev_unlock(hdev);
623
624 return 0;
625}
626
627DEFINE_SIMPLE_ATTRIBUTE(rpa_timeout_fops, rpa_timeout_get,
628 rpa_timeout_set, "%llu\n");
629
630static int random_address_show(struct seq_file *f, void *p)
631{
632 struct hci_dev *hdev = f->private;
633
634 hci_dev_lock(hdev);
635 seq_printf(f, "%pMR\n", &hdev->random_addr);
636 hci_dev_unlock(hdev);
637
638 return 0;
639}
640
Andy Shevchenko22b371c2017-11-22 23:15:46 +0200641DEFINE_SHOW_ATTRIBUTE(random_address);
Marcel Holtmann3a5c82b2014-12-20 16:05:16 +0100642
643static int static_address_show(struct seq_file *f, void *p)
644{
645 struct hci_dev *hdev = f->private;
646
647 hci_dev_lock(hdev);
648 seq_printf(f, "%pMR\n", &hdev->static_addr);
649 hci_dev_unlock(hdev);
650
651 return 0;
652}
653
Andy Shevchenko22b371c2017-11-22 23:15:46 +0200654DEFINE_SHOW_ATTRIBUTE(static_address);
Marcel Holtmann3a5c82b2014-12-20 16:05:16 +0100655
656static ssize_t force_static_address_read(struct file *file,
657 char __user *user_buf,
658 size_t count, loff_t *ppos)
659{
660 struct hci_dev *hdev = file->private_data;
661 char buf[3];
662
Marcel Holtmannb7cb93e2015-03-13 10:20:35 -0700663 buf[0] = hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ? 'Y': 'N';
Marcel Holtmann3a5c82b2014-12-20 16:05:16 +0100664 buf[1] = '\n';
665 buf[2] = '\0';
666 return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
667}
668
669static ssize_t force_static_address_write(struct file *file,
670 const char __user *user_buf,
671 size_t count, loff_t *ppos)
672{
673 struct hci_dev *hdev = file->private_data;
674 char buf[32];
675 size_t buf_size = min(count, (sizeof(buf)-1));
676 bool enable;
677
678 if (test_bit(HCI_UP, &hdev->flags))
679 return -EBUSY;
680
681 if (copy_from_user(buf, user_buf, buf_size))
682 return -EFAULT;
683
684 buf[buf_size] = '\0';
685 if (strtobool(buf, &enable))
686 return -EINVAL;
687
Marcel Holtmannb7cb93e2015-03-13 10:20:35 -0700688 if (enable == hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR))
Marcel Holtmann3a5c82b2014-12-20 16:05:16 +0100689 return -EALREADY;
690
Marcel Holtmannb7cb93e2015-03-13 10:20:35 -0700691 hci_dev_change_flag(hdev, HCI_FORCE_STATIC_ADDR);
Marcel Holtmann3a5c82b2014-12-20 16:05:16 +0100692
693 return count;
694}
695
696static const struct file_operations force_static_address_fops = {
697 .open = simple_open,
698 .read = force_static_address_read,
699 .write = force_static_address_write,
700 .llseek = default_llseek,
701};
702
703static int white_list_show(struct seq_file *f, void *ptr)
704{
705 struct hci_dev *hdev = f->private;
706 struct bdaddr_list *b;
707
708 hci_dev_lock(hdev);
709 list_for_each_entry(b, &hdev->le_white_list, list)
710 seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type);
711 hci_dev_unlock(hdev);
712
713 return 0;
714}
715
Andy Shevchenko22b371c2017-11-22 23:15:46 +0200716DEFINE_SHOW_ATTRIBUTE(white_list);
Marcel Holtmann3a5c82b2014-12-20 16:05:16 +0100717
718static int identity_resolving_keys_show(struct seq_file *f, void *ptr)
719{
720 struct hci_dev *hdev = f->private;
721 struct smp_irk *irk;
722
723 rcu_read_lock();
724 list_for_each_entry_rcu(irk, &hdev->identity_resolving_keys, list) {
725 seq_printf(f, "%pMR (type %u) %*phN %pMR\n",
726 &irk->bdaddr, irk->addr_type,
727 16, irk->val, &irk->rpa);
728 }
729 rcu_read_unlock();
730
731 return 0;
732}
733
Andy Shevchenko22b371c2017-11-22 23:15:46 +0200734DEFINE_SHOW_ATTRIBUTE(identity_resolving_keys);
Marcel Holtmann3a5c82b2014-12-20 16:05:16 +0100735
736static int long_term_keys_show(struct seq_file *f, void *ptr)
737{
738 struct hci_dev *hdev = f->private;
739 struct smp_ltk *ltk;
740
741 rcu_read_lock();
742 list_for_each_entry_rcu(ltk, &hdev->long_term_keys, list)
743 seq_printf(f, "%pMR (type %u) %u 0x%02x %u %.4x %.16llx %*phN\n",
744 &ltk->bdaddr, ltk->bdaddr_type, ltk->authenticated,
745 ltk->type, ltk->enc_size, __le16_to_cpu(ltk->ediv),
746 __le64_to_cpu(ltk->rand), 16, ltk->val);
747 rcu_read_unlock();
748
749 return 0;
750}
751
Andy Shevchenko22b371c2017-11-22 23:15:46 +0200752DEFINE_SHOW_ATTRIBUTE(long_term_keys);
Marcel Holtmann3a5c82b2014-12-20 16:05:16 +0100753
754static int conn_min_interval_set(void *data, u64 val)
755{
756 struct hci_dev *hdev = data;
757
758 if (val < 0x0006 || val > 0x0c80 || val > hdev->le_conn_max_interval)
759 return -EINVAL;
760
761 hci_dev_lock(hdev);
762 hdev->le_conn_min_interval = val;
763 hci_dev_unlock(hdev);
764
765 return 0;
766}
767
768static int conn_min_interval_get(void *data, u64 *val)
769{
770 struct hci_dev *hdev = data;
771
772 hci_dev_lock(hdev);
773 *val = hdev->le_conn_min_interval;
774 hci_dev_unlock(hdev);
775
776 return 0;
777}
778
779DEFINE_SIMPLE_ATTRIBUTE(conn_min_interval_fops, conn_min_interval_get,
780 conn_min_interval_set, "%llu\n");
781
782static int conn_max_interval_set(void *data, u64 val)
783{
784 struct hci_dev *hdev = data;
785
786 if (val < 0x0006 || val > 0x0c80 || val < hdev->le_conn_min_interval)
787 return -EINVAL;
788
789 hci_dev_lock(hdev);
790 hdev->le_conn_max_interval = val;
791 hci_dev_unlock(hdev);
792
793 return 0;
794}
795
796static int conn_max_interval_get(void *data, u64 *val)
797{
798 struct hci_dev *hdev = data;
799
800 hci_dev_lock(hdev);
801 *val = hdev->le_conn_max_interval;
802 hci_dev_unlock(hdev);
803
804 return 0;
805}
806
807DEFINE_SIMPLE_ATTRIBUTE(conn_max_interval_fops, conn_max_interval_get,
808 conn_max_interval_set, "%llu\n");
809
810static int conn_latency_set(void *data, u64 val)
811{
812 struct hci_dev *hdev = data;
813
814 if (val > 0x01f3)
815 return -EINVAL;
816
817 hci_dev_lock(hdev);
818 hdev->le_conn_latency = val;
819 hci_dev_unlock(hdev);
820
821 return 0;
822}
823
824static int conn_latency_get(void *data, u64 *val)
825{
826 struct hci_dev *hdev = data;
827
828 hci_dev_lock(hdev);
829 *val = hdev->le_conn_latency;
830 hci_dev_unlock(hdev);
831
832 return 0;
833}
834
835DEFINE_SIMPLE_ATTRIBUTE(conn_latency_fops, conn_latency_get,
836 conn_latency_set, "%llu\n");
837
838static int supervision_timeout_set(void *data, u64 val)
839{
840 struct hci_dev *hdev = data;
841
842 if (val < 0x000a || val > 0x0c80)
843 return -EINVAL;
844
845 hci_dev_lock(hdev);
846 hdev->le_supv_timeout = val;
847 hci_dev_unlock(hdev);
848
849 return 0;
850}
851
852static int supervision_timeout_get(void *data, u64 *val)
853{
854 struct hci_dev *hdev = data;
855
856 hci_dev_lock(hdev);
857 *val = hdev->le_supv_timeout;
858 hci_dev_unlock(hdev);
859
860 return 0;
861}
862
863DEFINE_SIMPLE_ATTRIBUTE(supervision_timeout_fops, supervision_timeout_get,
864 supervision_timeout_set, "%llu\n");
865
866static int adv_channel_map_set(void *data, u64 val)
867{
868 struct hci_dev *hdev = data;
869
870 if (val < 0x01 || val > 0x07)
871 return -EINVAL;
872
873 hci_dev_lock(hdev);
874 hdev->le_adv_channel_map = val;
875 hci_dev_unlock(hdev);
876
877 return 0;
878}
879
880static int adv_channel_map_get(void *data, u64 *val)
881{
882 struct hci_dev *hdev = data;
883
884 hci_dev_lock(hdev);
885 *val = hdev->le_adv_channel_map;
886 hci_dev_unlock(hdev);
887
888 return 0;
889}
890
891DEFINE_SIMPLE_ATTRIBUTE(adv_channel_map_fops, adv_channel_map_get,
892 adv_channel_map_set, "%llu\n");
893
894static int adv_min_interval_set(void *data, u64 val)
895{
896 struct hci_dev *hdev = data;
897
898 if (val < 0x0020 || val > 0x4000 || val > hdev->le_adv_max_interval)
899 return -EINVAL;
900
901 hci_dev_lock(hdev);
902 hdev->le_adv_min_interval = val;
903 hci_dev_unlock(hdev);
904
905 return 0;
906}
907
908static int adv_min_interval_get(void *data, u64 *val)
909{
910 struct hci_dev *hdev = data;
911
912 hci_dev_lock(hdev);
913 *val = hdev->le_adv_min_interval;
914 hci_dev_unlock(hdev);
915
916 return 0;
917}
918
919DEFINE_SIMPLE_ATTRIBUTE(adv_min_interval_fops, adv_min_interval_get,
920 adv_min_interval_set, "%llu\n");
921
922static int adv_max_interval_set(void *data, u64 val)
923{
924 struct hci_dev *hdev = data;
925
926 if (val < 0x0020 || val > 0x4000 || val < hdev->le_adv_min_interval)
927 return -EINVAL;
928
929 hci_dev_lock(hdev);
930 hdev->le_adv_max_interval = val;
931 hci_dev_unlock(hdev);
932
933 return 0;
934}
935
936static int adv_max_interval_get(void *data, u64 *val)
937{
938 struct hci_dev *hdev = data;
939
940 hci_dev_lock(hdev);
941 *val = hdev->le_adv_max_interval;
942 hci_dev_unlock(hdev);
943
944 return 0;
945}
946
947DEFINE_SIMPLE_ATTRIBUTE(adv_max_interval_fops, adv_max_interval_get,
948 adv_max_interval_set, "%llu\n");
949
Jakub Pawlowskib55d1ab2015-03-20 11:14:50 -0700950DEFINE_QUIRK_ATTRIBUTE(quirk_strict_duplicate_filter,
951 HCI_QUIRK_STRICT_DUPLICATE_FILTER);
952DEFINE_QUIRK_ATTRIBUTE(quirk_simultaneous_discovery,
953 HCI_QUIRK_SIMULTANEOUS_DISCOVERY);
954
Marcel Holtmann60c5f5f2014-12-20 16:05:13 +0100955void hci_debugfs_create_le(struct hci_dev *hdev)
956{
Marcel Holtmann3a5c82b2014-12-20 16:05:16 +0100957 debugfs_create_file("identity", 0400, hdev->debugfs, hdev,
958 &identity_fops);
959 debugfs_create_file("rpa_timeout", 0644, hdev->debugfs, hdev,
960 &rpa_timeout_fops);
961 debugfs_create_file("random_address", 0444, hdev->debugfs, hdev,
962 &random_address_fops);
963 debugfs_create_file("static_address", 0444, hdev->debugfs, hdev,
964 &static_address_fops);
965
966 /* For controllers with a public address, provide a debug
967 * option to force the usage of the configured static
968 * address. By default the public address is used.
969 */
970 if (bacmp(&hdev->bdaddr, BDADDR_ANY))
971 debugfs_create_file("force_static_address", 0644,
972 hdev->debugfs, hdev,
973 &force_static_address_fops);
974
975 debugfs_create_u8("white_list_size", 0444, hdev->debugfs,
976 &hdev->le_white_list_size);
977 debugfs_create_file("white_list", 0444, hdev->debugfs, hdev,
978 &white_list_fops);
979 debugfs_create_file("identity_resolving_keys", 0400, hdev->debugfs,
980 hdev, &identity_resolving_keys_fops);
981 debugfs_create_file("long_term_keys", 0400, hdev->debugfs, hdev,
982 &long_term_keys_fops);
983 debugfs_create_file("conn_min_interval", 0644, hdev->debugfs, hdev,
984 &conn_min_interval_fops);
985 debugfs_create_file("conn_max_interval", 0644, hdev->debugfs, hdev,
986 &conn_max_interval_fops);
987 debugfs_create_file("conn_latency", 0644, hdev->debugfs, hdev,
988 &conn_latency_fops);
989 debugfs_create_file("supervision_timeout", 0644, hdev->debugfs, hdev,
990 &supervision_timeout_fops);
991 debugfs_create_file("adv_channel_map", 0644, hdev->debugfs, hdev,
992 &adv_channel_map_fops);
993 debugfs_create_file("adv_min_interval", 0644, hdev->debugfs, hdev,
994 &adv_min_interval_fops);
995 debugfs_create_file("adv_max_interval", 0644, hdev->debugfs, hdev,
996 &adv_max_interval_fops);
997 debugfs_create_u16("discov_interleaved_timeout", 0644, hdev->debugfs,
998 &hdev->discov_interleaved_timeout);
Jakub Pawlowskib55d1ab2015-03-20 11:14:50 -0700999
1000 debugfs_create_file("quirk_strict_duplicate_filter", 0644,
1001 hdev->debugfs, hdev,
1002 &quirk_strict_duplicate_filter_fops);
1003 debugfs_create_file("quirk_simultaneous_discovery", 0644,
1004 hdev->debugfs, hdev,
1005 &quirk_simultaneous_discovery_fops);
Marcel Holtmann60c5f5f2014-12-20 16:05:13 +01001006}
Marcel Holtmann23b9ceb2014-12-20 17:13:41 +01001007
1008void hci_debugfs_create_conn(struct hci_conn *conn)
1009{
1010 struct hci_dev *hdev = conn->hdev;
1011 char name[6];
1012
1013 if (IS_ERR_OR_NULL(hdev->debugfs))
1014 return;
1015
1016 snprintf(name, sizeof(name), "%u", conn->handle);
1017 conn->debugfs = debugfs_create_dir(name, hdev->debugfs);
1018}