1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun BlueZ - Bluetooth protocol stack for Linux
3*4882a593Smuzhiyun
4*4882a593Smuzhiyun Copyright (C) 2014 Intel Corporation
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun This program is free software; you can redistribute it and/or modify
7*4882a593Smuzhiyun it under the terms of the GNU General Public License version 2 as
8*4882a593Smuzhiyun published by the Free Software Foundation;
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
11*4882a593Smuzhiyun OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12*4882a593Smuzhiyun FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
13*4882a593Smuzhiyun IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
14*4882a593Smuzhiyun CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
15*4882a593Smuzhiyun WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16*4882a593Smuzhiyun ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17*4882a593Smuzhiyun OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
20*4882a593Smuzhiyun COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
21*4882a593Smuzhiyun SOFTWARE IS DISCLAIMED.
22*4882a593Smuzhiyun */
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun #include <linux/debugfs.h>
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun #include <net/bluetooth/bluetooth.h>
27*4882a593Smuzhiyun #include <net/bluetooth/hci_core.h>
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun #include "smp.h"
30*4882a593Smuzhiyun #include "hci_debugfs.h"
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun #define DEFINE_QUIRK_ATTRIBUTE(__name, __quirk) \
33*4882a593Smuzhiyun static ssize_t __name ## _read(struct file *file, \
34*4882a593Smuzhiyun char __user *user_buf, \
35*4882a593Smuzhiyun size_t count, loff_t *ppos) \
36*4882a593Smuzhiyun { \
37*4882a593Smuzhiyun struct hci_dev *hdev = file->private_data; \
38*4882a593Smuzhiyun char buf[3]; \
39*4882a593Smuzhiyun \
40*4882a593Smuzhiyun buf[0] = test_bit(__quirk, &hdev->quirks) ? 'Y' : 'N'; \
41*4882a593Smuzhiyun buf[1] = '\n'; \
42*4882a593Smuzhiyun buf[2] = '\0'; \
43*4882a593Smuzhiyun return simple_read_from_buffer(user_buf, count, ppos, buf, 2); \
44*4882a593Smuzhiyun } \
45*4882a593Smuzhiyun \
46*4882a593Smuzhiyun static ssize_t __name ## _write(struct file *file, \
47*4882a593Smuzhiyun const char __user *user_buf, \
48*4882a593Smuzhiyun size_t count, loff_t *ppos) \
49*4882a593Smuzhiyun { \
50*4882a593Smuzhiyun struct hci_dev *hdev = file->private_data; \
51*4882a593Smuzhiyun bool enable; \
52*4882a593Smuzhiyun int err; \
53*4882a593Smuzhiyun \
54*4882a593Smuzhiyun if (test_bit(HCI_UP, &hdev->flags)) \
55*4882a593Smuzhiyun return -EBUSY; \
56*4882a593Smuzhiyun \
57*4882a593Smuzhiyun err = kstrtobool_from_user(user_buf, count, &enable); \
58*4882a593Smuzhiyun if (err) \
59*4882a593Smuzhiyun return err; \
60*4882a593Smuzhiyun \
61*4882a593Smuzhiyun if (enable == test_bit(__quirk, &hdev->quirks)) \
62*4882a593Smuzhiyun return -EALREADY; \
63*4882a593Smuzhiyun \
64*4882a593Smuzhiyun change_bit(__quirk, &hdev->quirks); \
65*4882a593Smuzhiyun \
66*4882a593Smuzhiyun return count; \
67*4882a593Smuzhiyun } \
68*4882a593Smuzhiyun \
69*4882a593Smuzhiyun static const struct file_operations __name ## _fops = { \
70*4882a593Smuzhiyun .open = simple_open, \
71*4882a593Smuzhiyun .read = __name ## _read, \
72*4882a593Smuzhiyun .write = __name ## _write, \
73*4882a593Smuzhiyun .llseek = default_llseek, \
74*4882a593Smuzhiyun } \
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun #define DEFINE_INFO_ATTRIBUTE(__name, __field) \
77*4882a593Smuzhiyun static int __name ## _show(struct seq_file *f, void *ptr) \
78*4882a593Smuzhiyun { \
79*4882a593Smuzhiyun struct hci_dev *hdev = f->private; \
80*4882a593Smuzhiyun \
81*4882a593Smuzhiyun hci_dev_lock(hdev); \
82*4882a593Smuzhiyun seq_printf(f, "%s\n", hdev->__field ? : ""); \
83*4882a593Smuzhiyun hci_dev_unlock(hdev); \
84*4882a593Smuzhiyun \
85*4882a593Smuzhiyun return 0; \
86*4882a593Smuzhiyun } \
87*4882a593Smuzhiyun \
88*4882a593Smuzhiyun DEFINE_SHOW_ATTRIBUTE(__name)
89*4882a593Smuzhiyun
features_show(struct seq_file * f,void * ptr)90*4882a593Smuzhiyun static int features_show(struct seq_file *f, void *ptr)
91*4882a593Smuzhiyun {
92*4882a593Smuzhiyun struct hci_dev *hdev = f->private;
93*4882a593Smuzhiyun u8 p;
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun hci_dev_lock(hdev);
96*4882a593Smuzhiyun for (p = 0; p < HCI_MAX_PAGES && p <= hdev->max_page; p++)
97*4882a593Smuzhiyun seq_printf(f, "%2u: %8ph\n", p, hdev->features[p]);
98*4882a593Smuzhiyun if (lmp_le_capable(hdev))
99*4882a593Smuzhiyun seq_printf(f, "LE: %8ph\n", hdev->le_features);
100*4882a593Smuzhiyun hci_dev_unlock(hdev);
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun return 0;
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun DEFINE_SHOW_ATTRIBUTE(features);
106*4882a593Smuzhiyun
device_id_show(struct seq_file * f,void * ptr)107*4882a593Smuzhiyun static int device_id_show(struct seq_file *f, void *ptr)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun struct hci_dev *hdev = f->private;
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun hci_dev_lock(hdev);
112*4882a593Smuzhiyun seq_printf(f, "%4.4x:%4.4x:%4.4x:%4.4x\n", hdev->devid_source,
113*4882a593Smuzhiyun hdev->devid_vendor, hdev->devid_product, hdev->devid_version);
114*4882a593Smuzhiyun hci_dev_unlock(hdev);
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun return 0;
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun DEFINE_SHOW_ATTRIBUTE(device_id);
120*4882a593Smuzhiyun
device_list_show(struct seq_file * f,void * ptr)121*4882a593Smuzhiyun static int device_list_show(struct seq_file *f, void *ptr)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun struct hci_dev *hdev = f->private;
124*4882a593Smuzhiyun struct hci_conn_params *p;
125*4882a593Smuzhiyun struct bdaddr_list *b;
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun hci_dev_lock(hdev);
128*4882a593Smuzhiyun list_for_each_entry(b, &hdev->whitelist, list)
129*4882a593Smuzhiyun seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type);
130*4882a593Smuzhiyun list_for_each_entry(p, &hdev->le_conn_params, list) {
131*4882a593Smuzhiyun seq_printf(f, "%pMR (type %u) %u\n", &p->addr, p->addr_type,
132*4882a593Smuzhiyun p->auto_connect);
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun hci_dev_unlock(hdev);
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun return 0;
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun DEFINE_SHOW_ATTRIBUTE(device_list);
140*4882a593Smuzhiyun
blacklist_show(struct seq_file * f,void * p)141*4882a593Smuzhiyun static int blacklist_show(struct seq_file *f, void *p)
142*4882a593Smuzhiyun {
143*4882a593Smuzhiyun struct hci_dev *hdev = f->private;
144*4882a593Smuzhiyun struct bdaddr_list *b;
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun hci_dev_lock(hdev);
147*4882a593Smuzhiyun list_for_each_entry(b, &hdev->blacklist, list)
148*4882a593Smuzhiyun seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type);
149*4882a593Smuzhiyun hci_dev_unlock(hdev);
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun return 0;
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun DEFINE_SHOW_ATTRIBUTE(blacklist);
155*4882a593Smuzhiyun
blocked_keys_show(struct seq_file * f,void * p)156*4882a593Smuzhiyun static int blocked_keys_show(struct seq_file *f, void *p)
157*4882a593Smuzhiyun {
158*4882a593Smuzhiyun struct hci_dev *hdev = f->private;
159*4882a593Smuzhiyun struct blocked_key *key;
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun rcu_read_lock();
162*4882a593Smuzhiyun list_for_each_entry_rcu(key, &hdev->blocked_keys, list)
163*4882a593Smuzhiyun seq_printf(f, "%u %*phN\n", key->type, 16, key->val);
164*4882a593Smuzhiyun rcu_read_unlock();
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun return 0;
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun DEFINE_SHOW_ATTRIBUTE(blocked_keys);
170*4882a593Smuzhiyun
uuids_show(struct seq_file * f,void * p)171*4882a593Smuzhiyun static int uuids_show(struct seq_file *f, void *p)
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun struct hci_dev *hdev = f->private;
174*4882a593Smuzhiyun struct bt_uuid *uuid;
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun hci_dev_lock(hdev);
177*4882a593Smuzhiyun list_for_each_entry(uuid, &hdev->uuids, list) {
178*4882a593Smuzhiyun u8 i, val[16];
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun /* The Bluetooth UUID values are stored in big endian,
181*4882a593Smuzhiyun * but with reversed byte order. So convert them into
182*4882a593Smuzhiyun * the right order for the %pUb modifier.
183*4882a593Smuzhiyun */
184*4882a593Smuzhiyun for (i = 0; i < 16; i++)
185*4882a593Smuzhiyun val[i] = uuid->uuid[15 - i];
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun seq_printf(f, "%pUb\n", val);
188*4882a593Smuzhiyun }
189*4882a593Smuzhiyun hci_dev_unlock(hdev);
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun return 0;
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun DEFINE_SHOW_ATTRIBUTE(uuids);
195*4882a593Smuzhiyun
remote_oob_show(struct seq_file * f,void * ptr)196*4882a593Smuzhiyun static int remote_oob_show(struct seq_file *f, void *ptr)
197*4882a593Smuzhiyun {
198*4882a593Smuzhiyun struct hci_dev *hdev = f->private;
199*4882a593Smuzhiyun struct oob_data *data;
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun hci_dev_lock(hdev);
202*4882a593Smuzhiyun list_for_each_entry(data, &hdev->remote_oob_data, list) {
203*4882a593Smuzhiyun seq_printf(f, "%pMR (type %u) %u %*phN %*phN %*phN %*phN\n",
204*4882a593Smuzhiyun &data->bdaddr, data->bdaddr_type, data->present,
205*4882a593Smuzhiyun 16, data->hash192, 16, data->rand192,
206*4882a593Smuzhiyun 16, data->hash256, 16, data->rand256);
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun hci_dev_unlock(hdev);
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun return 0;
211*4882a593Smuzhiyun }
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun DEFINE_SHOW_ATTRIBUTE(remote_oob);
214*4882a593Smuzhiyun
conn_info_min_age_set(void * data,u64 val)215*4882a593Smuzhiyun static int conn_info_min_age_set(void *data, u64 val)
216*4882a593Smuzhiyun {
217*4882a593Smuzhiyun struct hci_dev *hdev = data;
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun if (val == 0 || val > hdev->conn_info_max_age)
220*4882a593Smuzhiyun return -EINVAL;
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun hci_dev_lock(hdev);
223*4882a593Smuzhiyun hdev->conn_info_min_age = val;
224*4882a593Smuzhiyun hci_dev_unlock(hdev);
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun return 0;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun
conn_info_min_age_get(void * data,u64 * val)229*4882a593Smuzhiyun static int conn_info_min_age_get(void *data, u64 *val)
230*4882a593Smuzhiyun {
231*4882a593Smuzhiyun struct hci_dev *hdev = data;
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun hci_dev_lock(hdev);
234*4882a593Smuzhiyun *val = hdev->conn_info_min_age;
235*4882a593Smuzhiyun hci_dev_unlock(hdev);
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun return 0;
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun DEFINE_SIMPLE_ATTRIBUTE(conn_info_min_age_fops, conn_info_min_age_get,
241*4882a593Smuzhiyun conn_info_min_age_set, "%llu\n");
242*4882a593Smuzhiyun
conn_info_max_age_set(void * data,u64 val)243*4882a593Smuzhiyun static int conn_info_max_age_set(void *data, u64 val)
244*4882a593Smuzhiyun {
245*4882a593Smuzhiyun struct hci_dev *hdev = data;
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun if (val == 0 || val < hdev->conn_info_min_age)
248*4882a593Smuzhiyun return -EINVAL;
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun hci_dev_lock(hdev);
251*4882a593Smuzhiyun hdev->conn_info_max_age = val;
252*4882a593Smuzhiyun hci_dev_unlock(hdev);
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun return 0;
255*4882a593Smuzhiyun }
256*4882a593Smuzhiyun
conn_info_max_age_get(void * data,u64 * val)257*4882a593Smuzhiyun static int conn_info_max_age_get(void *data, u64 *val)
258*4882a593Smuzhiyun {
259*4882a593Smuzhiyun struct hci_dev *hdev = data;
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun hci_dev_lock(hdev);
262*4882a593Smuzhiyun *val = hdev->conn_info_max_age;
263*4882a593Smuzhiyun hci_dev_unlock(hdev);
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun return 0;
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun DEFINE_SIMPLE_ATTRIBUTE(conn_info_max_age_fops, conn_info_max_age_get,
269*4882a593Smuzhiyun conn_info_max_age_set, "%llu\n");
270*4882a593Smuzhiyun
use_debug_keys_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)271*4882a593Smuzhiyun static ssize_t use_debug_keys_read(struct file *file, char __user *user_buf,
272*4882a593Smuzhiyun size_t count, loff_t *ppos)
273*4882a593Smuzhiyun {
274*4882a593Smuzhiyun struct hci_dev *hdev = file->private_data;
275*4882a593Smuzhiyun char buf[3];
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun buf[0] = hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS) ? 'Y': 'N';
278*4882a593Smuzhiyun buf[1] = '\n';
279*4882a593Smuzhiyun buf[2] = '\0';
280*4882a593Smuzhiyun return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
281*4882a593Smuzhiyun }
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun static const struct file_operations use_debug_keys_fops = {
284*4882a593Smuzhiyun .open = simple_open,
285*4882a593Smuzhiyun .read = use_debug_keys_read,
286*4882a593Smuzhiyun .llseek = default_llseek,
287*4882a593Smuzhiyun };
288*4882a593Smuzhiyun
sc_only_mode_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)289*4882a593Smuzhiyun static ssize_t sc_only_mode_read(struct file *file, char __user *user_buf,
290*4882a593Smuzhiyun size_t count, loff_t *ppos)
291*4882a593Smuzhiyun {
292*4882a593Smuzhiyun struct hci_dev *hdev = file->private_data;
293*4882a593Smuzhiyun char buf[3];
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun buf[0] = hci_dev_test_flag(hdev, HCI_SC_ONLY) ? 'Y': 'N';
296*4882a593Smuzhiyun buf[1] = '\n';
297*4882a593Smuzhiyun buf[2] = '\0';
298*4882a593Smuzhiyun return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun static const struct file_operations sc_only_mode_fops = {
302*4882a593Smuzhiyun .open = simple_open,
303*4882a593Smuzhiyun .read = sc_only_mode_read,
304*4882a593Smuzhiyun .llseek = default_llseek,
305*4882a593Smuzhiyun };
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun DEFINE_INFO_ATTRIBUTE(hardware_info, hw_info);
308*4882a593Smuzhiyun DEFINE_INFO_ATTRIBUTE(firmware_info, fw_info);
309*4882a593Smuzhiyun
hci_debugfs_create_common(struct hci_dev * hdev)310*4882a593Smuzhiyun void hci_debugfs_create_common(struct hci_dev *hdev)
311*4882a593Smuzhiyun {
312*4882a593Smuzhiyun debugfs_create_file("features", 0444, hdev->debugfs, hdev,
313*4882a593Smuzhiyun &features_fops);
314*4882a593Smuzhiyun debugfs_create_u16("manufacturer", 0444, hdev->debugfs,
315*4882a593Smuzhiyun &hdev->manufacturer);
316*4882a593Smuzhiyun debugfs_create_u8("hci_version", 0444, hdev->debugfs, &hdev->hci_ver);
317*4882a593Smuzhiyun debugfs_create_u16("hci_revision", 0444, hdev->debugfs, &hdev->hci_rev);
318*4882a593Smuzhiyun debugfs_create_u8("hardware_error", 0444, hdev->debugfs,
319*4882a593Smuzhiyun &hdev->hw_error_code);
320*4882a593Smuzhiyun debugfs_create_file("device_id", 0444, hdev->debugfs, hdev,
321*4882a593Smuzhiyun &device_id_fops);
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun debugfs_create_file("device_list", 0444, hdev->debugfs, hdev,
324*4882a593Smuzhiyun &device_list_fops);
325*4882a593Smuzhiyun debugfs_create_file("blacklist", 0444, hdev->debugfs, hdev,
326*4882a593Smuzhiyun &blacklist_fops);
327*4882a593Smuzhiyun debugfs_create_file("blocked_keys", 0444, hdev->debugfs, hdev,
328*4882a593Smuzhiyun &blocked_keys_fops);
329*4882a593Smuzhiyun debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops);
330*4882a593Smuzhiyun debugfs_create_file("remote_oob", 0400, hdev->debugfs, hdev,
331*4882a593Smuzhiyun &remote_oob_fops);
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun debugfs_create_file("conn_info_min_age", 0644, hdev->debugfs, hdev,
334*4882a593Smuzhiyun &conn_info_min_age_fops);
335*4882a593Smuzhiyun debugfs_create_file("conn_info_max_age", 0644, hdev->debugfs, hdev,
336*4882a593Smuzhiyun &conn_info_max_age_fops);
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun if (lmp_ssp_capable(hdev) || lmp_le_capable(hdev))
339*4882a593Smuzhiyun debugfs_create_file("use_debug_keys", 0444, hdev->debugfs,
340*4882a593Smuzhiyun hdev, &use_debug_keys_fops);
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun if (lmp_sc_capable(hdev) || lmp_le_capable(hdev))
343*4882a593Smuzhiyun debugfs_create_file("sc_only_mode", 0444, hdev->debugfs,
344*4882a593Smuzhiyun hdev, &sc_only_mode_fops);
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun if (hdev->hw_info)
347*4882a593Smuzhiyun debugfs_create_file("hardware_info", 0444, hdev->debugfs,
348*4882a593Smuzhiyun hdev, &hardware_info_fops);
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun if (hdev->fw_info)
351*4882a593Smuzhiyun debugfs_create_file("firmware_info", 0444, hdev->debugfs,
352*4882a593Smuzhiyun hdev, &firmware_info_fops);
353*4882a593Smuzhiyun }
354*4882a593Smuzhiyun
inquiry_cache_show(struct seq_file * f,void * p)355*4882a593Smuzhiyun static int inquiry_cache_show(struct seq_file *f, void *p)
356*4882a593Smuzhiyun {
357*4882a593Smuzhiyun struct hci_dev *hdev = f->private;
358*4882a593Smuzhiyun struct discovery_state *cache = &hdev->discovery;
359*4882a593Smuzhiyun struct inquiry_entry *e;
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun hci_dev_lock(hdev);
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun list_for_each_entry(e, &cache->all, all) {
364*4882a593Smuzhiyun struct inquiry_data *data = &e->data;
365*4882a593Smuzhiyun seq_printf(f, "%pMR %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n",
366*4882a593Smuzhiyun &data->bdaddr,
367*4882a593Smuzhiyun data->pscan_rep_mode, data->pscan_period_mode,
368*4882a593Smuzhiyun data->pscan_mode, data->dev_class[2],
369*4882a593Smuzhiyun data->dev_class[1], data->dev_class[0],
370*4882a593Smuzhiyun __le16_to_cpu(data->clock_offset),
371*4882a593Smuzhiyun data->rssi, data->ssp_mode, e->timestamp);
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun hci_dev_unlock(hdev);
375*4882a593Smuzhiyun
376*4882a593Smuzhiyun return 0;
377*4882a593Smuzhiyun }
378*4882a593Smuzhiyun
379*4882a593Smuzhiyun DEFINE_SHOW_ATTRIBUTE(inquiry_cache);
380*4882a593Smuzhiyun
link_keys_show(struct seq_file * f,void * ptr)381*4882a593Smuzhiyun static int link_keys_show(struct seq_file *f, void *ptr)
382*4882a593Smuzhiyun {
383*4882a593Smuzhiyun struct hci_dev *hdev = f->private;
384*4882a593Smuzhiyun struct link_key *key;
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun rcu_read_lock();
387*4882a593Smuzhiyun list_for_each_entry_rcu(key, &hdev->link_keys, list)
388*4882a593Smuzhiyun seq_printf(f, "%pMR %u %*phN %u\n", &key->bdaddr, key->type,
389*4882a593Smuzhiyun HCI_LINK_KEY_SIZE, key->val, key->pin_len);
390*4882a593Smuzhiyun rcu_read_unlock();
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun return 0;
393*4882a593Smuzhiyun }
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun DEFINE_SHOW_ATTRIBUTE(link_keys);
396*4882a593Smuzhiyun
dev_class_show(struct seq_file * f,void * ptr)397*4882a593Smuzhiyun static int dev_class_show(struct seq_file *f, void *ptr)
398*4882a593Smuzhiyun {
399*4882a593Smuzhiyun struct hci_dev *hdev = f->private;
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun hci_dev_lock(hdev);
402*4882a593Smuzhiyun seq_printf(f, "0x%.2x%.2x%.2x\n", hdev->dev_class[2],
403*4882a593Smuzhiyun hdev->dev_class[1], hdev->dev_class[0]);
404*4882a593Smuzhiyun hci_dev_unlock(hdev);
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun return 0;
407*4882a593Smuzhiyun }
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun DEFINE_SHOW_ATTRIBUTE(dev_class);
410*4882a593Smuzhiyun
voice_setting_get(void * data,u64 * val)411*4882a593Smuzhiyun static int voice_setting_get(void *data, u64 *val)
412*4882a593Smuzhiyun {
413*4882a593Smuzhiyun struct hci_dev *hdev = data;
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun hci_dev_lock(hdev);
416*4882a593Smuzhiyun *val = hdev->voice_setting;
417*4882a593Smuzhiyun hci_dev_unlock(hdev);
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun return 0;
420*4882a593Smuzhiyun }
421*4882a593Smuzhiyun
422*4882a593Smuzhiyun DEFINE_SIMPLE_ATTRIBUTE(voice_setting_fops, voice_setting_get,
423*4882a593Smuzhiyun NULL, "0x%4.4llx\n");
424*4882a593Smuzhiyun
ssp_debug_mode_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)425*4882a593Smuzhiyun static ssize_t ssp_debug_mode_read(struct file *file, char __user *user_buf,
426*4882a593Smuzhiyun size_t count, loff_t *ppos)
427*4882a593Smuzhiyun {
428*4882a593Smuzhiyun struct hci_dev *hdev = file->private_data;
429*4882a593Smuzhiyun char buf[3];
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun buf[0] = hdev->ssp_debug_mode ? 'Y': 'N';
432*4882a593Smuzhiyun buf[1] = '\n';
433*4882a593Smuzhiyun buf[2] = '\0';
434*4882a593Smuzhiyun return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
435*4882a593Smuzhiyun }
436*4882a593Smuzhiyun
437*4882a593Smuzhiyun static const struct file_operations ssp_debug_mode_fops = {
438*4882a593Smuzhiyun .open = simple_open,
439*4882a593Smuzhiyun .read = ssp_debug_mode_read,
440*4882a593Smuzhiyun .llseek = default_llseek,
441*4882a593Smuzhiyun };
442*4882a593Smuzhiyun
auto_accept_delay_set(void * data,u64 val)443*4882a593Smuzhiyun static int auto_accept_delay_set(void *data, u64 val)
444*4882a593Smuzhiyun {
445*4882a593Smuzhiyun struct hci_dev *hdev = data;
446*4882a593Smuzhiyun
447*4882a593Smuzhiyun hci_dev_lock(hdev);
448*4882a593Smuzhiyun hdev->auto_accept_delay = val;
449*4882a593Smuzhiyun hci_dev_unlock(hdev);
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun return 0;
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun
min_encrypt_key_size_set(void * data,u64 val)454*4882a593Smuzhiyun static int min_encrypt_key_size_set(void *data, u64 val)
455*4882a593Smuzhiyun {
456*4882a593Smuzhiyun struct hci_dev *hdev = data;
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun if (val < 1 || val > 16)
459*4882a593Smuzhiyun return -EINVAL;
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun hci_dev_lock(hdev);
462*4882a593Smuzhiyun hdev->min_enc_key_size = val;
463*4882a593Smuzhiyun hci_dev_unlock(hdev);
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun return 0;
466*4882a593Smuzhiyun }
467*4882a593Smuzhiyun
min_encrypt_key_size_get(void * data,u64 * val)468*4882a593Smuzhiyun static int min_encrypt_key_size_get(void *data, u64 *val)
469*4882a593Smuzhiyun {
470*4882a593Smuzhiyun struct hci_dev *hdev = data;
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun hci_dev_lock(hdev);
473*4882a593Smuzhiyun *val = hdev->min_enc_key_size;
474*4882a593Smuzhiyun hci_dev_unlock(hdev);
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun return 0;
477*4882a593Smuzhiyun }
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun DEFINE_SIMPLE_ATTRIBUTE(min_encrypt_key_size_fops,
480*4882a593Smuzhiyun min_encrypt_key_size_get,
481*4882a593Smuzhiyun min_encrypt_key_size_set, "%llu\n");
482*4882a593Smuzhiyun
auto_accept_delay_get(void * data,u64 * val)483*4882a593Smuzhiyun static int auto_accept_delay_get(void *data, u64 *val)
484*4882a593Smuzhiyun {
485*4882a593Smuzhiyun struct hci_dev *hdev = data;
486*4882a593Smuzhiyun
487*4882a593Smuzhiyun hci_dev_lock(hdev);
488*4882a593Smuzhiyun *val = hdev->auto_accept_delay;
489*4882a593Smuzhiyun hci_dev_unlock(hdev);
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun return 0;
492*4882a593Smuzhiyun }
493*4882a593Smuzhiyun
494*4882a593Smuzhiyun DEFINE_SIMPLE_ATTRIBUTE(auto_accept_delay_fops, auto_accept_delay_get,
495*4882a593Smuzhiyun auto_accept_delay_set, "%llu\n");
496*4882a593Smuzhiyun
idle_timeout_set(void * data,u64 val)497*4882a593Smuzhiyun static int idle_timeout_set(void *data, u64 val)
498*4882a593Smuzhiyun {
499*4882a593Smuzhiyun struct hci_dev *hdev = data;
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun if (val != 0 && (val < 500 || val > 3600000))
502*4882a593Smuzhiyun return -EINVAL;
503*4882a593Smuzhiyun
504*4882a593Smuzhiyun hci_dev_lock(hdev);
505*4882a593Smuzhiyun hdev->idle_timeout = val;
506*4882a593Smuzhiyun hci_dev_unlock(hdev);
507*4882a593Smuzhiyun
508*4882a593Smuzhiyun return 0;
509*4882a593Smuzhiyun }
510*4882a593Smuzhiyun
idle_timeout_get(void * data,u64 * val)511*4882a593Smuzhiyun static int idle_timeout_get(void *data, u64 *val)
512*4882a593Smuzhiyun {
513*4882a593Smuzhiyun struct hci_dev *hdev = data;
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun hci_dev_lock(hdev);
516*4882a593Smuzhiyun *val = hdev->idle_timeout;
517*4882a593Smuzhiyun hci_dev_unlock(hdev);
518*4882a593Smuzhiyun
519*4882a593Smuzhiyun return 0;
520*4882a593Smuzhiyun }
521*4882a593Smuzhiyun
522*4882a593Smuzhiyun DEFINE_SIMPLE_ATTRIBUTE(idle_timeout_fops, idle_timeout_get,
523*4882a593Smuzhiyun idle_timeout_set, "%llu\n");
524*4882a593Smuzhiyun
sniff_min_interval_set(void * data,u64 val)525*4882a593Smuzhiyun static int sniff_min_interval_set(void *data, u64 val)
526*4882a593Smuzhiyun {
527*4882a593Smuzhiyun struct hci_dev *hdev = data;
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun if (val == 0 || val % 2 || val > hdev->sniff_max_interval)
530*4882a593Smuzhiyun return -EINVAL;
531*4882a593Smuzhiyun
532*4882a593Smuzhiyun hci_dev_lock(hdev);
533*4882a593Smuzhiyun hdev->sniff_min_interval = val;
534*4882a593Smuzhiyun hci_dev_unlock(hdev);
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun return 0;
537*4882a593Smuzhiyun }
538*4882a593Smuzhiyun
sniff_min_interval_get(void * data,u64 * val)539*4882a593Smuzhiyun static int sniff_min_interval_get(void *data, u64 *val)
540*4882a593Smuzhiyun {
541*4882a593Smuzhiyun struct hci_dev *hdev = data;
542*4882a593Smuzhiyun
543*4882a593Smuzhiyun hci_dev_lock(hdev);
544*4882a593Smuzhiyun *val = hdev->sniff_min_interval;
545*4882a593Smuzhiyun hci_dev_unlock(hdev);
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun return 0;
548*4882a593Smuzhiyun }
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun DEFINE_SIMPLE_ATTRIBUTE(sniff_min_interval_fops, sniff_min_interval_get,
551*4882a593Smuzhiyun sniff_min_interval_set, "%llu\n");
552*4882a593Smuzhiyun
sniff_max_interval_set(void * data,u64 val)553*4882a593Smuzhiyun static int sniff_max_interval_set(void *data, u64 val)
554*4882a593Smuzhiyun {
555*4882a593Smuzhiyun struct hci_dev *hdev = data;
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun if (val == 0 || val % 2 || val < hdev->sniff_min_interval)
558*4882a593Smuzhiyun return -EINVAL;
559*4882a593Smuzhiyun
560*4882a593Smuzhiyun hci_dev_lock(hdev);
561*4882a593Smuzhiyun hdev->sniff_max_interval = val;
562*4882a593Smuzhiyun hci_dev_unlock(hdev);
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun return 0;
565*4882a593Smuzhiyun }
566*4882a593Smuzhiyun
sniff_max_interval_get(void * data,u64 * val)567*4882a593Smuzhiyun static int sniff_max_interval_get(void *data, u64 *val)
568*4882a593Smuzhiyun {
569*4882a593Smuzhiyun struct hci_dev *hdev = data;
570*4882a593Smuzhiyun
571*4882a593Smuzhiyun hci_dev_lock(hdev);
572*4882a593Smuzhiyun *val = hdev->sniff_max_interval;
573*4882a593Smuzhiyun hci_dev_unlock(hdev);
574*4882a593Smuzhiyun
575*4882a593Smuzhiyun return 0;
576*4882a593Smuzhiyun }
577*4882a593Smuzhiyun
578*4882a593Smuzhiyun DEFINE_SIMPLE_ATTRIBUTE(sniff_max_interval_fops, sniff_max_interval_get,
579*4882a593Smuzhiyun sniff_max_interval_set, "%llu\n");
580*4882a593Smuzhiyun
hci_debugfs_create_bredr(struct hci_dev * hdev)581*4882a593Smuzhiyun void hci_debugfs_create_bredr(struct hci_dev *hdev)
582*4882a593Smuzhiyun {
583*4882a593Smuzhiyun debugfs_create_file("inquiry_cache", 0444, hdev->debugfs, hdev,
584*4882a593Smuzhiyun &inquiry_cache_fops);
585*4882a593Smuzhiyun debugfs_create_file("link_keys", 0400, hdev->debugfs, hdev,
586*4882a593Smuzhiyun &link_keys_fops);
587*4882a593Smuzhiyun debugfs_create_file("dev_class", 0444, hdev->debugfs, hdev,
588*4882a593Smuzhiyun &dev_class_fops);
589*4882a593Smuzhiyun debugfs_create_file("voice_setting", 0444, hdev->debugfs, hdev,
590*4882a593Smuzhiyun &voice_setting_fops);
591*4882a593Smuzhiyun
592*4882a593Smuzhiyun if (lmp_ssp_capable(hdev)) {
593*4882a593Smuzhiyun debugfs_create_file("ssp_debug_mode", 0444, hdev->debugfs,
594*4882a593Smuzhiyun hdev, &ssp_debug_mode_fops);
595*4882a593Smuzhiyun debugfs_create_file("min_encrypt_key_size", 0644, hdev->debugfs,
596*4882a593Smuzhiyun hdev, &min_encrypt_key_size_fops);
597*4882a593Smuzhiyun debugfs_create_file("auto_accept_delay", 0644, hdev->debugfs,
598*4882a593Smuzhiyun hdev, &auto_accept_delay_fops);
599*4882a593Smuzhiyun }
600*4882a593Smuzhiyun
601*4882a593Smuzhiyun if (lmp_sniff_capable(hdev)) {
602*4882a593Smuzhiyun debugfs_create_file("idle_timeout", 0644, hdev->debugfs,
603*4882a593Smuzhiyun hdev, &idle_timeout_fops);
604*4882a593Smuzhiyun debugfs_create_file("sniff_min_interval", 0644, hdev->debugfs,
605*4882a593Smuzhiyun hdev, &sniff_min_interval_fops);
606*4882a593Smuzhiyun debugfs_create_file("sniff_max_interval", 0644, hdev->debugfs,
607*4882a593Smuzhiyun hdev, &sniff_max_interval_fops);
608*4882a593Smuzhiyun }
609*4882a593Smuzhiyun }
610*4882a593Smuzhiyun
identity_show(struct seq_file * f,void * p)611*4882a593Smuzhiyun static int identity_show(struct seq_file *f, void *p)
612*4882a593Smuzhiyun {
613*4882a593Smuzhiyun struct hci_dev *hdev = f->private;
614*4882a593Smuzhiyun bdaddr_t addr;
615*4882a593Smuzhiyun u8 addr_type;
616*4882a593Smuzhiyun
617*4882a593Smuzhiyun hci_dev_lock(hdev);
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun hci_copy_identity_address(hdev, &addr, &addr_type);
620*4882a593Smuzhiyun
621*4882a593Smuzhiyun seq_printf(f, "%pMR (type %u) %*phN %pMR\n", &addr, addr_type,
622*4882a593Smuzhiyun 16, hdev->irk, &hdev->rpa);
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun hci_dev_unlock(hdev);
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun return 0;
627*4882a593Smuzhiyun }
628*4882a593Smuzhiyun
629*4882a593Smuzhiyun DEFINE_SHOW_ATTRIBUTE(identity);
630*4882a593Smuzhiyun
rpa_timeout_set(void * data,u64 val)631*4882a593Smuzhiyun static int rpa_timeout_set(void *data, u64 val)
632*4882a593Smuzhiyun {
633*4882a593Smuzhiyun struct hci_dev *hdev = data;
634*4882a593Smuzhiyun
635*4882a593Smuzhiyun /* Require the RPA timeout to be at least 30 seconds and at most
636*4882a593Smuzhiyun * 24 hours.
637*4882a593Smuzhiyun */
638*4882a593Smuzhiyun if (val < 30 || val > (60 * 60 * 24))
639*4882a593Smuzhiyun return -EINVAL;
640*4882a593Smuzhiyun
641*4882a593Smuzhiyun hci_dev_lock(hdev);
642*4882a593Smuzhiyun hdev->rpa_timeout = val;
643*4882a593Smuzhiyun hci_dev_unlock(hdev);
644*4882a593Smuzhiyun
645*4882a593Smuzhiyun return 0;
646*4882a593Smuzhiyun }
647*4882a593Smuzhiyun
rpa_timeout_get(void * data,u64 * val)648*4882a593Smuzhiyun static int rpa_timeout_get(void *data, u64 *val)
649*4882a593Smuzhiyun {
650*4882a593Smuzhiyun struct hci_dev *hdev = data;
651*4882a593Smuzhiyun
652*4882a593Smuzhiyun hci_dev_lock(hdev);
653*4882a593Smuzhiyun *val = hdev->rpa_timeout;
654*4882a593Smuzhiyun hci_dev_unlock(hdev);
655*4882a593Smuzhiyun
656*4882a593Smuzhiyun return 0;
657*4882a593Smuzhiyun }
658*4882a593Smuzhiyun
659*4882a593Smuzhiyun DEFINE_SIMPLE_ATTRIBUTE(rpa_timeout_fops, rpa_timeout_get,
660*4882a593Smuzhiyun rpa_timeout_set, "%llu\n");
661*4882a593Smuzhiyun
random_address_show(struct seq_file * f,void * p)662*4882a593Smuzhiyun static int random_address_show(struct seq_file *f, void *p)
663*4882a593Smuzhiyun {
664*4882a593Smuzhiyun struct hci_dev *hdev = f->private;
665*4882a593Smuzhiyun
666*4882a593Smuzhiyun hci_dev_lock(hdev);
667*4882a593Smuzhiyun seq_printf(f, "%pMR\n", &hdev->random_addr);
668*4882a593Smuzhiyun hci_dev_unlock(hdev);
669*4882a593Smuzhiyun
670*4882a593Smuzhiyun return 0;
671*4882a593Smuzhiyun }
672*4882a593Smuzhiyun
673*4882a593Smuzhiyun DEFINE_SHOW_ATTRIBUTE(random_address);
674*4882a593Smuzhiyun
static_address_show(struct seq_file * f,void * p)675*4882a593Smuzhiyun static int static_address_show(struct seq_file *f, void *p)
676*4882a593Smuzhiyun {
677*4882a593Smuzhiyun struct hci_dev *hdev = f->private;
678*4882a593Smuzhiyun
679*4882a593Smuzhiyun hci_dev_lock(hdev);
680*4882a593Smuzhiyun seq_printf(f, "%pMR\n", &hdev->static_addr);
681*4882a593Smuzhiyun hci_dev_unlock(hdev);
682*4882a593Smuzhiyun
683*4882a593Smuzhiyun return 0;
684*4882a593Smuzhiyun }
685*4882a593Smuzhiyun
686*4882a593Smuzhiyun DEFINE_SHOW_ATTRIBUTE(static_address);
687*4882a593Smuzhiyun
force_static_address_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)688*4882a593Smuzhiyun static ssize_t force_static_address_read(struct file *file,
689*4882a593Smuzhiyun char __user *user_buf,
690*4882a593Smuzhiyun size_t count, loff_t *ppos)
691*4882a593Smuzhiyun {
692*4882a593Smuzhiyun struct hci_dev *hdev = file->private_data;
693*4882a593Smuzhiyun char buf[3];
694*4882a593Smuzhiyun
695*4882a593Smuzhiyun buf[0] = hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ? 'Y': 'N';
696*4882a593Smuzhiyun buf[1] = '\n';
697*4882a593Smuzhiyun buf[2] = '\0';
698*4882a593Smuzhiyun return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
699*4882a593Smuzhiyun }
700*4882a593Smuzhiyun
force_static_address_write(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)701*4882a593Smuzhiyun static ssize_t force_static_address_write(struct file *file,
702*4882a593Smuzhiyun const char __user *user_buf,
703*4882a593Smuzhiyun size_t count, loff_t *ppos)
704*4882a593Smuzhiyun {
705*4882a593Smuzhiyun struct hci_dev *hdev = file->private_data;
706*4882a593Smuzhiyun bool enable;
707*4882a593Smuzhiyun int err;
708*4882a593Smuzhiyun
709*4882a593Smuzhiyun if (test_bit(HCI_UP, &hdev->flags))
710*4882a593Smuzhiyun return -EBUSY;
711*4882a593Smuzhiyun
712*4882a593Smuzhiyun err = kstrtobool_from_user(user_buf, count, &enable);
713*4882a593Smuzhiyun if (err)
714*4882a593Smuzhiyun return err;
715*4882a593Smuzhiyun
716*4882a593Smuzhiyun if (enable == hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR))
717*4882a593Smuzhiyun return -EALREADY;
718*4882a593Smuzhiyun
719*4882a593Smuzhiyun hci_dev_change_flag(hdev, HCI_FORCE_STATIC_ADDR);
720*4882a593Smuzhiyun
721*4882a593Smuzhiyun return count;
722*4882a593Smuzhiyun }
723*4882a593Smuzhiyun
724*4882a593Smuzhiyun static const struct file_operations force_static_address_fops = {
725*4882a593Smuzhiyun .open = simple_open,
726*4882a593Smuzhiyun .read = force_static_address_read,
727*4882a593Smuzhiyun .write = force_static_address_write,
728*4882a593Smuzhiyun .llseek = default_llseek,
729*4882a593Smuzhiyun };
730*4882a593Smuzhiyun
white_list_show(struct seq_file * f,void * ptr)731*4882a593Smuzhiyun static int white_list_show(struct seq_file *f, void *ptr)
732*4882a593Smuzhiyun {
733*4882a593Smuzhiyun struct hci_dev *hdev = f->private;
734*4882a593Smuzhiyun struct bdaddr_list *b;
735*4882a593Smuzhiyun
736*4882a593Smuzhiyun hci_dev_lock(hdev);
737*4882a593Smuzhiyun list_for_each_entry(b, &hdev->le_white_list, list)
738*4882a593Smuzhiyun seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type);
739*4882a593Smuzhiyun hci_dev_unlock(hdev);
740*4882a593Smuzhiyun
741*4882a593Smuzhiyun return 0;
742*4882a593Smuzhiyun }
743*4882a593Smuzhiyun
744*4882a593Smuzhiyun DEFINE_SHOW_ATTRIBUTE(white_list);
745*4882a593Smuzhiyun
resolv_list_show(struct seq_file * f,void * ptr)746*4882a593Smuzhiyun static int resolv_list_show(struct seq_file *f, void *ptr)
747*4882a593Smuzhiyun {
748*4882a593Smuzhiyun struct hci_dev *hdev = f->private;
749*4882a593Smuzhiyun struct bdaddr_list *b;
750*4882a593Smuzhiyun
751*4882a593Smuzhiyun hci_dev_lock(hdev);
752*4882a593Smuzhiyun list_for_each_entry(b, &hdev->le_resolv_list, list)
753*4882a593Smuzhiyun seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type);
754*4882a593Smuzhiyun hci_dev_unlock(hdev);
755*4882a593Smuzhiyun
756*4882a593Smuzhiyun return 0;
757*4882a593Smuzhiyun }
758*4882a593Smuzhiyun
759*4882a593Smuzhiyun DEFINE_SHOW_ATTRIBUTE(resolv_list);
760*4882a593Smuzhiyun
identity_resolving_keys_show(struct seq_file * f,void * ptr)761*4882a593Smuzhiyun static int identity_resolving_keys_show(struct seq_file *f, void *ptr)
762*4882a593Smuzhiyun {
763*4882a593Smuzhiyun struct hci_dev *hdev = f->private;
764*4882a593Smuzhiyun struct smp_irk *irk;
765*4882a593Smuzhiyun
766*4882a593Smuzhiyun rcu_read_lock();
767*4882a593Smuzhiyun list_for_each_entry_rcu(irk, &hdev->identity_resolving_keys, list) {
768*4882a593Smuzhiyun seq_printf(f, "%pMR (type %u) %*phN %pMR\n",
769*4882a593Smuzhiyun &irk->bdaddr, irk->addr_type,
770*4882a593Smuzhiyun 16, irk->val, &irk->rpa);
771*4882a593Smuzhiyun }
772*4882a593Smuzhiyun rcu_read_unlock();
773*4882a593Smuzhiyun
774*4882a593Smuzhiyun return 0;
775*4882a593Smuzhiyun }
776*4882a593Smuzhiyun
777*4882a593Smuzhiyun DEFINE_SHOW_ATTRIBUTE(identity_resolving_keys);
778*4882a593Smuzhiyun
long_term_keys_show(struct seq_file * f,void * ptr)779*4882a593Smuzhiyun static int long_term_keys_show(struct seq_file *f, void *ptr)
780*4882a593Smuzhiyun {
781*4882a593Smuzhiyun struct hci_dev *hdev = f->private;
782*4882a593Smuzhiyun struct smp_ltk *ltk;
783*4882a593Smuzhiyun
784*4882a593Smuzhiyun rcu_read_lock();
785*4882a593Smuzhiyun list_for_each_entry_rcu(ltk, &hdev->long_term_keys, list)
786*4882a593Smuzhiyun seq_printf(f, "%pMR (type %u) %u 0x%02x %u %.4x %.16llx %*phN\n",
787*4882a593Smuzhiyun <k->bdaddr, ltk->bdaddr_type, ltk->authenticated,
788*4882a593Smuzhiyun ltk->type, ltk->enc_size, __le16_to_cpu(ltk->ediv),
789*4882a593Smuzhiyun __le64_to_cpu(ltk->rand), 16, ltk->val);
790*4882a593Smuzhiyun rcu_read_unlock();
791*4882a593Smuzhiyun
792*4882a593Smuzhiyun return 0;
793*4882a593Smuzhiyun }
794*4882a593Smuzhiyun
795*4882a593Smuzhiyun DEFINE_SHOW_ATTRIBUTE(long_term_keys);
796*4882a593Smuzhiyun
conn_min_interval_set(void * data,u64 val)797*4882a593Smuzhiyun static int conn_min_interval_set(void *data, u64 val)
798*4882a593Smuzhiyun {
799*4882a593Smuzhiyun struct hci_dev *hdev = data;
800*4882a593Smuzhiyun
801*4882a593Smuzhiyun if (val < 0x0006 || val > 0x0c80 || val > hdev->le_conn_max_interval)
802*4882a593Smuzhiyun return -EINVAL;
803*4882a593Smuzhiyun
804*4882a593Smuzhiyun hci_dev_lock(hdev);
805*4882a593Smuzhiyun hdev->le_conn_min_interval = val;
806*4882a593Smuzhiyun hci_dev_unlock(hdev);
807*4882a593Smuzhiyun
808*4882a593Smuzhiyun return 0;
809*4882a593Smuzhiyun }
810*4882a593Smuzhiyun
conn_min_interval_get(void * data,u64 * val)811*4882a593Smuzhiyun static int conn_min_interval_get(void *data, u64 *val)
812*4882a593Smuzhiyun {
813*4882a593Smuzhiyun struct hci_dev *hdev = data;
814*4882a593Smuzhiyun
815*4882a593Smuzhiyun hci_dev_lock(hdev);
816*4882a593Smuzhiyun *val = hdev->le_conn_min_interval;
817*4882a593Smuzhiyun hci_dev_unlock(hdev);
818*4882a593Smuzhiyun
819*4882a593Smuzhiyun return 0;
820*4882a593Smuzhiyun }
821*4882a593Smuzhiyun
822*4882a593Smuzhiyun DEFINE_SIMPLE_ATTRIBUTE(conn_min_interval_fops, conn_min_interval_get,
823*4882a593Smuzhiyun conn_min_interval_set, "%llu\n");
824*4882a593Smuzhiyun
conn_max_interval_set(void * data,u64 val)825*4882a593Smuzhiyun static int conn_max_interval_set(void *data, u64 val)
826*4882a593Smuzhiyun {
827*4882a593Smuzhiyun struct hci_dev *hdev = data;
828*4882a593Smuzhiyun
829*4882a593Smuzhiyun if (val < 0x0006 || val > 0x0c80 || val < hdev->le_conn_min_interval)
830*4882a593Smuzhiyun return -EINVAL;
831*4882a593Smuzhiyun
832*4882a593Smuzhiyun hci_dev_lock(hdev);
833*4882a593Smuzhiyun hdev->le_conn_max_interval = val;
834*4882a593Smuzhiyun hci_dev_unlock(hdev);
835*4882a593Smuzhiyun
836*4882a593Smuzhiyun return 0;
837*4882a593Smuzhiyun }
838*4882a593Smuzhiyun
conn_max_interval_get(void * data,u64 * val)839*4882a593Smuzhiyun static int conn_max_interval_get(void *data, u64 *val)
840*4882a593Smuzhiyun {
841*4882a593Smuzhiyun struct hci_dev *hdev = data;
842*4882a593Smuzhiyun
843*4882a593Smuzhiyun hci_dev_lock(hdev);
844*4882a593Smuzhiyun *val = hdev->le_conn_max_interval;
845*4882a593Smuzhiyun hci_dev_unlock(hdev);
846*4882a593Smuzhiyun
847*4882a593Smuzhiyun return 0;
848*4882a593Smuzhiyun }
849*4882a593Smuzhiyun
850*4882a593Smuzhiyun DEFINE_SIMPLE_ATTRIBUTE(conn_max_interval_fops, conn_max_interval_get,
851*4882a593Smuzhiyun conn_max_interval_set, "%llu\n");
852*4882a593Smuzhiyun
conn_latency_set(void * data,u64 val)853*4882a593Smuzhiyun static int conn_latency_set(void *data, u64 val)
854*4882a593Smuzhiyun {
855*4882a593Smuzhiyun struct hci_dev *hdev = data;
856*4882a593Smuzhiyun
857*4882a593Smuzhiyun if (val > 0x01f3)
858*4882a593Smuzhiyun return -EINVAL;
859*4882a593Smuzhiyun
860*4882a593Smuzhiyun hci_dev_lock(hdev);
861*4882a593Smuzhiyun hdev->le_conn_latency = val;
862*4882a593Smuzhiyun hci_dev_unlock(hdev);
863*4882a593Smuzhiyun
864*4882a593Smuzhiyun return 0;
865*4882a593Smuzhiyun }
866*4882a593Smuzhiyun
conn_latency_get(void * data,u64 * val)867*4882a593Smuzhiyun static int conn_latency_get(void *data, u64 *val)
868*4882a593Smuzhiyun {
869*4882a593Smuzhiyun struct hci_dev *hdev = data;
870*4882a593Smuzhiyun
871*4882a593Smuzhiyun hci_dev_lock(hdev);
872*4882a593Smuzhiyun *val = hdev->le_conn_latency;
873*4882a593Smuzhiyun hci_dev_unlock(hdev);
874*4882a593Smuzhiyun
875*4882a593Smuzhiyun return 0;
876*4882a593Smuzhiyun }
877*4882a593Smuzhiyun
878*4882a593Smuzhiyun DEFINE_SIMPLE_ATTRIBUTE(conn_latency_fops, conn_latency_get,
879*4882a593Smuzhiyun conn_latency_set, "%llu\n");
880*4882a593Smuzhiyun
supervision_timeout_set(void * data,u64 val)881*4882a593Smuzhiyun static int supervision_timeout_set(void *data, u64 val)
882*4882a593Smuzhiyun {
883*4882a593Smuzhiyun struct hci_dev *hdev = data;
884*4882a593Smuzhiyun
885*4882a593Smuzhiyun if (val < 0x000a || val > 0x0c80)
886*4882a593Smuzhiyun return -EINVAL;
887*4882a593Smuzhiyun
888*4882a593Smuzhiyun hci_dev_lock(hdev);
889*4882a593Smuzhiyun hdev->le_supv_timeout = val;
890*4882a593Smuzhiyun hci_dev_unlock(hdev);
891*4882a593Smuzhiyun
892*4882a593Smuzhiyun return 0;
893*4882a593Smuzhiyun }
894*4882a593Smuzhiyun
supervision_timeout_get(void * data,u64 * val)895*4882a593Smuzhiyun static int supervision_timeout_get(void *data, u64 *val)
896*4882a593Smuzhiyun {
897*4882a593Smuzhiyun struct hci_dev *hdev = data;
898*4882a593Smuzhiyun
899*4882a593Smuzhiyun hci_dev_lock(hdev);
900*4882a593Smuzhiyun *val = hdev->le_supv_timeout;
901*4882a593Smuzhiyun hci_dev_unlock(hdev);
902*4882a593Smuzhiyun
903*4882a593Smuzhiyun return 0;
904*4882a593Smuzhiyun }
905*4882a593Smuzhiyun
906*4882a593Smuzhiyun DEFINE_SIMPLE_ATTRIBUTE(supervision_timeout_fops, supervision_timeout_get,
907*4882a593Smuzhiyun supervision_timeout_set, "%llu\n");
908*4882a593Smuzhiyun
adv_channel_map_set(void * data,u64 val)909*4882a593Smuzhiyun static int adv_channel_map_set(void *data, u64 val)
910*4882a593Smuzhiyun {
911*4882a593Smuzhiyun struct hci_dev *hdev = data;
912*4882a593Smuzhiyun
913*4882a593Smuzhiyun if (val < 0x01 || val > 0x07)
914*4882a593Smuzhiyun return -EINVAL;
915*4882a593Smuzhiyun
916*4882a593Smuzhiyun hci_dev_lock(hdev);
917*4882a593Smuzhiyun hdev->le_adv_channel_map = val;
918*4882a593Smuzhiyun hci_dev_unlock(hdev);
919*4882a593Smuzhiyun
920*4882a593Smuzhiyun return 0;
921*4882a593Smuzhiyun }
922*4882a593Smuzhiyun
adv_channel_map_get(void * data,u64 * val)923*4882a593Smuzhiyun static int adv_channel_map_get(void *data, u64 *val)
924*4882a593Smuzhiyun {
925*4882a593Smuzhiyun struct hci_dev *hdev = data;
926*4882a593Smuzhiyun
927*4882a593Smuzhiyun hci_dev_lock(hdev);
928*4882a593Smuzhiyun *val = hdev->le_adv_channel_map;
929*4882a593Smuzhiyun hci_dev_unlock(hdev);
930*4882a593Smuzhiyun
931*4882a593Smuzhiyun return 0;
932*4882a593Smuzhiyun }
933*4882a593Smuzhiyun
934*4882a593Smuzhiyun DEFINE_SIMPLE_ATTRIBUTE(adv_channel_map_fops, adv_channel_map_get,
935*4882a593Smuzhiyun adv_channel_map_set, "%llu\n");
936*4882a593Smuzhiyun
adv_min_interval_set(void * data,u64 val)937*4882a593Smuzhiyun static int adv_min_interval_set(void *data, u64 val)
938*4882a593Smuzhiyun {
939*4882a593Smuzhiyun struct hci_dev *hdev = data;
940*4882a593Smuzhiyun
941*4882a593Smuzhiyun if (val < 0x0020 || val > 0x4000 || val > hdev->le_adv_max_interval)
942*4882a593Smuzhiyun return -EINVAL;
943*4882a593Smuzhiyun
944*4882a593Smuzhiyun hci_dev_lock(hdev);
945*4882a593Smuzhiyun hdev->le_adv_min_interval = val;
946*4882a593Smuzhiyun hci_dev_unlock(hdev);
947*4882a593Smuzhiyun
948*4882a593Smuzhiyun return 0;
949*4882a593Smuzhiyun }
950*4882a593Smuzhiyun
adv_min_interval_get(void * data,u64 * val)951*4882a593Smuzhiyun static int adv_min_interval_get(void *data, u64 *val)
952*4882a593Smuzhiyun {
953*4882a593Smuzhiyun struct hci_dev *hdev = data;
954*4882a593Smuzhiyun
955*4882a593Smuzhiyun hci_dev_lock(hdev);
956*4882a593Smuzhiyun *val = hdev->le_adv_min_interval;
957*4882a593Smuzhiyun hci_dev_unlock(hdev);
958*4882a593Smuzhiyun
959*4882a593Smuzhiyun return 0;
960*4882a593Smuzhiyun }
961*4882a593Smuzhiyun
962*4882a593Smuzhiyun DEFINE_SIMPLE_ATTRIBUTE(adv_min_interval_fops, adv_min_interval_get,
963*4882a593Smuzhiyun adv_min_interval_set, "%llu\n");
964*4882a593Smuzhiyun
adv_max_interval_set(void * data,u64 val)965*4882a593Smuzhiyun static int adv_max_interval_set(void *data, u64 val)
966*4882a593Smuzhiyun {
967*4882a593Smuzhiyun struct hci_dev *hdev = data;
968*4882a593Smuzhiyun
969*4882a593Smuzhiyun if (val < 0x0020 || val > 0x4000 || val < hdev->le_adv_min_interval)
970*4882a593Smuzhiyun return -EINVAL;
971*4882a593Smuzhiyun
972*4882a593Smuzhiyun hci_dev_lock(hdev);
973*4882a593Smuzhiyun hdev->le_adv_max_interval = val;
974*4882a593Smuzhiyun hci_dev_unlock(hdev);
975*4882a593Smuzhiyun
976*4882a593Smuzhiyun return 0;
977*4882a593Smuzhiyun }
978*4882a593Smuzhiyun
adv_max_interval_get(void * data,u64 * val)979*4882a593Smuzhiyun static int adv_max_interval_get(void *data, u64 *val)
980*4882a593Smuzhiyun {
981*4882a593Smuzhiyun struct hci_dev *hdev = data;
982*4882a593Smuzhiyun
983*4882a593Smuzhiyun hci_dev_lock(hdev);
984*4882a593Smuzhiyun *val = hdev->le_adv_max_interval;
985*4882a593Smuzhiyun hci_dev_unlock(hdev);
986*4882a593Smuzhiyun
987*4882a593Smuzhiyun return 0;
988*4882a593Smuzhiyun }
989*4882a593Smuzhiyun
990*4882a593Smuzhiyun DEFINE_SIMPLE_ATTRIBUTE(adv_max_interval_fops, adv_max_interval_get,
991*4882a593Smuzhiyun adv_max_interval_set, "%llu\n");
992*4882a593Smuzhiyun
min_key_size_set(void * data,u64 val)993*4882a593Smuzhiyun static int min_key_size_set(void *data, u64 val)
994*4882a593Smuzhiyun {
995*4882a593Smuzhiyun struct hci_dev *hdev = data;
996*4882a593Smuzhiyun
997*4882a593Smuzhiyun if (val > hdev->le_max_key_size || val < SMP_MIN_ENC_KEY_SIZE)
998*4882a593Smuzhiyun return -EINVAL;
999*4882a593Smuzhiyun
1000*4882a593Smuzhiyun hci_dev_lock(hdev);
1001*4882a593Smuzhiyun hdev->le_min_key_size = val;
1002*4882a593Smuzhiyun hci_dev_unlock(hdev);
1003*4882a593Smuzhiyun
1004*4882a593Smuzhiyun return 0;
1005*4882a593Smuzhiyun }
1006*4882a593Smuzhiyun
min_key_size_get(void * data,u64 * val)1007*4882a593Smuzhiyun static int min_key_size_get(void *data, u64 *val)
1008*4882a593Smuzhiyun {
1009*4882a593Smuzhiyun struct hci_dev *hdev = data;
1010*4882a593Smuzhiyun
1011*4882a593Smuzhiyun hci_dev_lock(hdev);
1012*4882a593Smuzhiyun *val = hdev->le_min_key_size;
1013*4882a593Smuzhiyun hci_dev_unlock(hdev);
1014*4882a593Smuzhiyun
1015*4882a593Smuzhiyun return 0;
1016*4882a593Smuzhiyun }
1017*4882a593Smuzhiyun
1018*4882a593Smuzhiyun DEFINE_SIMPLE_ATTRIBUTE(min_key_size_fops, min_key_size_get,
1019*4882a593Smuzhiyun min_key_size_set, "%llu\n");
1020*4882a593Smuzhiyun
max_key_size_set(void * data,u64 val)1021*4882a593Smuzhiyun static int max_key_size_set(void *data, u64 val)
1022*4882a593Smuzhiyun {
1023*4882a593Smuzhiyun struct hci_dev *hdev = data;
1024*4882a593Smuzhiyun
1025*4882a593Smuzhiyun if (val > SMP_MAX_ENC_KEY_SIZE || val < hdev->le_min_key_size)
1026*4882a593Smuzhiyun return -EINVAL;
1027*4882a593Smuzhiyun
1028*4882a593Smuzhiyun hci_dev_lock(hdev);
1029*4882a593Smuzhiyun hdev->le_max_key_size = val;
1030*4882a593Smuzhiyun hci_dev_unlock(hdev);
1031*4882a593Smuzhiyun
1032*4882a593Smuzhiyun return 0;
1033*4882a593Smuzhiyun }
1034*4882a593Smuzhiyun
max_key_size_get(void * data,u64 * val)1035*4882a593Smuzhiyun static int max_key_size_get(void *data, u64 *val)
1036*4882a593Smuzhiyun {
1037*4882a593Smuzhiyun struct hci_dev *hdev = data;
1038*4882a593Smuzhiyun
1039*4882a593Smuzhiyun hci_dev_lock(hdev);
1040*4882a593Smuzhiyun *val = hdev->le_max_key_size;
1041*4882a593Smuzhiyun hci_dev_unlock(hdev);
1042*4882a593Smuzhiyun
1043*4882a593Smuzhiyun return 0;
1044*4882a593Smuzhiyun }
1045*4882a593Smuzhiyun
1046*4882a593Smuzhiyun DEFINE_SIMPLE_ATTRIBUTE(max_key_size_fops, max_key_size_get,
1047*4882a593Smuzhiyun max_key_size_set, "%llu\n");
1048*4882a593Smuzhiyun
auth_payload_timeout_set(void * data,u64 val)1049*4882a593Smuzhiyun static int auth_payload_timeout_set(void *data, u64 val)
1050*4882a593Smuzhiyun {
1051*4882a593Smuzhiyun struct hci_dev *hdev = data;
1052*4882a593Smuzhiyun
1053*4882a593Smuzhiyun if (val < 0x0001 || val > 0xffff)
1054*4882a593Smuzhiyun return -EINVAL;
1055*4882a593Smuzhiyun
1056*4882a593Smuzhiyun hci_dev_lock(hdev);
1057*4882a593Smuzhiyun hdev->auth_payload_timeout = val;
1058*4882a593Smuzhiyun hci_dev_unlock(hdev);
1059*4882a593Smuzhiyun
1060*4882a593Smuzhiyun return 0;
1061*4882a593Smuzhiyun }
1062*4882a593Smuzhiyun
auth_payload_timeout_get(void * data,u64 * val)1063*4882a593Smuzhiyun static int auth_payload_timeout_get(void *data, u64 *val)
1064*4882a593Smuzhiyun {
1065*4882a593Smuzhiyun struct hci_dev *hdev = data;
1066*4882a593Smuzhiyun
1067*4882a593Smuzhiyun hci_dev_lock(hdev);
1068*4882a593Smuzhiyun *val = hdev->auth_payload_timeout;
1069*4882a593Smuzhiyun hci_dev_unlock(hdev);
1070*4882a593Smuzhiyun
1071*4882a593Smuzhiyun return 0;
1072*4882a593Smuzhiyun }
1073*4882a593Smuzhiyun
1074*4882a593Smuzhiyun DEFINE_SIMPLE_ATTRIBUTE(auth_payload_timeout_fops,
1075*4882a593Smuzhiyun auth_payload_timeout_get,
1076*4882a593Smuzhiyun auth_payload_timeout_set, "%llu\n");
1077*4882a593Smuzhiyun
force_no_mitm_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)1078*4882a593Smuzhiyun static ssize_t force_no_mitm_read(struct file *file,
1079*4882a593Smuzhiyun char __user *user_buf,
1080*4882a593Smuzhiyun size_t count, loff_t *ppos)
1081*4882a593Smuzhiyun {
1082*4882a593Smuzhiyun struct hci_dev *hdev = file->private_data;
1083*4882a593Smuzhiyun char buf[3];
1084*4882a593Smuzhiyun
1085*4882a593Smuzhiyun buf[0] = hci_dev_test_flag(hdev, HCI_FORCE_NO_MITM) ? 'Y' : 'N';
1086*4882a593Smuzhiyun buf[1] = '\n';
1087*4882a593Smuzhiyun buf[2] = '\0';
1088*4882a593Smuzhiyun return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
1089*4882a593Smuzhiyun }
1090*4882a593Smuzhiyun
force_no_mitm_write(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)1091*4882a593Smuzhiyun static ssize_t force_no_mitm_write(struct file *file,
1092*4882a593Smuzhiyun const char __user *user_buf,
1093*4882a593Smuzhiyun size_t count, loff_t *ppos)
1094*4882a593Smuzhiyun {
1095*4882a593Smuzhiyun struct hci_dev *hdev = file->private_data;
1096*4882a593Smuzhiyun char buf[32];
1097*4882a593Smuzhiyun size_t buf_size = min(count, (sizeof(buf) - 1));
1098*4882a593Smuzhiyun bool enable;
1099*4882a593Smuzhiyun
1100*4882a593Smuzhiyun if (copy_from_user(buf, user_buf, buf_size))
1101*4882a593Smuzhiyun return -EFAULT;
1102*4882a593Smuzhiyun
1103*4882a593Smuzhiyun buf[buf_size] = '\0';
1104*4882a593Smuzhiyun if (strtobool(buf, &enable))
1105*4882a593Smuzhiyun return -EINVAL;
1106*4882a593Smuzhiyun
1107*4882a593Smuzhiyun if (enable == hci_dev_test_flag(hdev, HCI_FORCE_NO_MITM))
1108*4882a593Smuzhiyun return -EALREADY;
1109*4882a593Smuzhiyun
1110*4882a593Smuzhiyun hci_dev_change_flag(hdev, HCI_FORCE_NO_MITM);
1111*4882a593Smuzhiyun
1112*4882a593Smuzhiyun return count;
1113*4882a593Smuzhiyun }
1114*4882a593Smuzhiyun
1115*4882a593Smuzhiyun static const struct file_operations force_no_mitm_fops = {
1116*4882a593Smuzhiyun .open = simple_open,
1117*4882a593Smuzhiyun .read = force_no_mitm_read,
1118*4882a593Smuzhiyun .write = force_no_mitm_write,
1119*4882a593Smuzhiyun .llseek = default_llseek,
1120*4882a593Smuzhiyun };
1121*4882a593Smuzhiyun
1122*4882a593Smuzhiyun DEFINE_QUIRK_ATTRIBUTE(quirk_strict_duplicate_filter,
1123*4882a593Smuzhiyun HCI_QUIRK_STRICT_DUPLICATE_FILTER);
1124*4882a593Smuzhiyun DEFINE_QUIRK_ATTRIBUTE(quirk_simultaneous_discovery,
1125*4882a593Smuzhiyun HCI_QUIRK_SIMULTANEOUS_DISCOVERY);
1126*4882a593Smuzhiyun
hci_debugfs_create_le(struct hci_dev * hdev)1127*4882a593Smuzhiyun void hci_debugfs_create_le(struct hci_dev *hdev)
1128*4882a593Smuzhiyun {
1129*4882a593Smuzhiyun debugfs_create_file("identity", 0400, hdev->debugfs, hdev,
1130*4882a593Smuzhiyun &identity_fops);
1131*4882a593Smuzhiyun debugfs_create_file("rpa_timeout", 0644, hdev->debugfs, hdev,
1132*4882a593Smuzhiyun &rpa_timeout_fops);
1133*4882a593Smuzhiyun debugfs_create_file("random_address", 0444, hdev->debugfs, hdev,
1134*4882a593Smuzhiyun &random_address_fops);
1135*4882a593Smuzhiyun debugfs_create_file("static_address", 0444, hdev->debugfs, hdev,
1136*4882a593Smuzhiyun &static_address_fops);
1137*4882a593Smuzhiyun
1138*4882a593Smuzhiyun /* For controllers with a public address, provide a debug
1139*4882a593Smuzhiyun * option to force the usage of the configured static
1140*4882a593Smuzhiyun * address. By default the public address is used.
1141*4882a593Smuzhiyun */
1142*4882a593Smuzhiyun if (bacmp(&hdev->bdaddr, BDADDR_ANY))
1143*4882a593Smuzhiyun debugfs_create_file("force_static_address", 0644,
1144*4882a593Smuzhiyun hdev->debugfs, hdev,
1145*4882a593Smuzhiyun &force_static_address_fops);
1146*4882a593Smuzhiyun
1147*4882a593Smuzhiyun debugfs_create_u8("white_list_size", 0444, hdev->debugfs,
1148*4882a593Smuzhiyun &hdev->le_white_list_size);
1149*4882a593Smuzhiyun debugfs_create_file("white_list", 0444, hdev->debugfs, hdev,
1150*4882a593Smuzhiyun &white_list_fops);
1151*4882a593Smuzhiyun debugfs_create_u8("resolv_list_size", 0444, hdev->debugfs,
1152*4882a593Smuzhiyun &hdev->le_resolv_list_size);
1153*4882a593Smuzhiyun debugfs_create_file("resolv_list", 0444, hdev->debugfs, hdev,
1154*4882a593Smuzhiyun &resolv_list_fops);
1155*4882a593Smuzhiyun debugfs_create_file("identity_resolving_keys", 0400, hdev->debugfs,
1156*4882a593Smuzhiyun hdev, &identity_resolving_keys_fops);
1157*4882a593Smuzhiyun debugfs_create_file("long_term_keys", 0400, hdev->debugfs, hdev,
1158*4882a593Smuzhiyun &long_term_keys_fops);
1159*4882a593Smuzhiyun debugfs_create_file("conn_min_interval", 0644, hdev->debugfs, hdev,
1160*4882a593Smuzhiyun &conn_min_interval_fops);
1161*4882a593Smuzhiyun debugfs_create_file("conn_max_interval", 0644, hdev->debugfs, hdev,
1162*4882a593Smuzhiyun &conn_max_interval_fops);
1163*4882a593Smuzhiyun debugfs_create_file("conn_latency", 0644, hdev->debugfs, hdev,
1164*4882a593Smuzhiyun &conn_latency_fops);
1165*4882a593Smuzhiyun debugfs_create_file("supervision_timeout", 0644, hdev->debugfs, hdev,
1166*4882a593Smuzhiyun &supervision_timeout_fops);
1167*4882a593Smuzhiyun debugfs_create_file("adv_channel_map", 0644, hdev->debugfs, hdev,
1168*4882a593Smuzhiyun &adv_channel_map_fops);
1169*4882a593Smuzhiyun debugfs_create_file("adv_min_interval", 0644, hdev->debugfs, hdev,
1170*4882a593Smuzhiyun &adv_min_interval_fops);
1171*4882a593Smuzhiyun debugfs_create_file("adv_max_interval", 0644, hdev->debugfs, hdev,
1172*4882a593Smuzhiyun &adv_max_interval_fops);
1173*4882a593Smuzhiyun debugfs_create_u16("discov_interleaved_timeout", 0644, hdev->debugfs,
1174*4882a593Smuzhiyun &hdev->discov_interleaved_timeout);
1175*4882a593Smuzhiyun debugfs_create_file("min_key_size", 0644, hdev->debugfs, hdev,
1176*4882a593Smuzhiyun &min_key_size_fops);
1177*4882a593Smuzhiyun debugfs_create_file("max_key_size", 0644, hdev->debugfs, hdev,
1178*4882a593Smuzhiyun &max_key_size_fops);
1179*4882a593Smuzhiyun debugfs_create_file("auth_payload_timeout", 0644, hdev->debugfs, hdev,
1180*4882a593Smuzhiyun &auth_payload_timeout_fops);
1181*4882a593Smuzhiyun debugfs_create_file("force_no_mitm", 0644, hdev->debugfs, hdev,
1182*4882a593Smuzhiyun &force_no_mitm_fops);
1183*4882a593Smuzhiyun
1184*4882a593Smuzhiyun debugfs_create_file("quirk_strict_duplicate_filter", 0644,
1185*4882a593Smuzhiyun hdev->debugfs, hdev,
1186*4882a593Smuzhiyun &quirk_strict_duplicate_filter_fops);
1187*4882a593Smuzhiyun debugfs_create_file("quirk_simultaneous_discovery", 0644,
1188*4882a593Smuzhiyun hdev->debugfs, hdev,
1189*4882a593Smuzhiyun &quirk_simultaneous_discovery_fops);
1190*4882a593Smuzhiyun }
1191*4882a593Smuzhiyun
hci_debugfs_create_conn(struct hci_conn * conn)1192*4882a593Smuzhiyun void hci_debugfs_create_conn(struct hci_conn *conn)
1193*4882a593Smuzhiyun {
1194*4882a593Smuzhiyun struct hci_dev *hdev = conn->hdev;
1195*4882a593Smuzhiyun char name[6];
1196*4882a593Smuzhiyun
1197*4882a593Smuzhiyun if (IS_ERR_OR_NULL(hdev->debugfs))
1198*4882a593Smuzhiyun return;
1199*4882a593Smuzhiyun
1200*4882a593Smuzhiyun snprintf(name, sizeof(name), "%u", conn->handle);
1201*4882a593Smuzhiyun conn->debugfs = debugfs_create_dir(name, hdev->debugfs);
1202*4882a593Smuzhiyun }
1203