xref: /OK3568_Linux_fs/kernel/net/bluetooth/hci_debugfs.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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 			   &ltk->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