18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci   BlueZ - Bluetooth protocol stack for Linux
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci   Copyright (C) 2014 Intel Corporation
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci   This program is free software; you can redistribute it and/or modify
78c2ecf20Sopenharmony_ci   it under the terms of the GNU General Public License version 2 as
88c2ecf20Sopenharmony_ci   published by the Free Software Foundation;
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
118c2ecf20Sopenharmony_ci   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
128c2ecf20Sopenharmony_ci   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
138c2ecf20Sopenharmony_ci   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
148c2ecf20Sopenharmony_ci   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
158c2ecf20Sopenharmony_ci   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
168c2ecf20Sopenharmony_ci   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
178c2ecf20Sopenharmony_ci   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
208c2ecf20Sopenharmony_ci   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
218c2ecf20Sopenharmony_ci   SOFTWARE IS DISCLAIMED.
228c2ecf20Sopenharmony_ci*/
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci#include <linux/debugfs.h>
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci#include <net/bluetooth/bluetooth.h>
278c2ecf20Sopenharmony_ci#include <net/bluetooth/hci_core.h>
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci#include "smp.h"
308c2ecf20Sopenharmony_ci#include "hci_debugfs.h"
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci#define DEFINE_QUIRK_ATTRIBUTE(__name, __quirk)				      \
338c2ecf20Sopenharmony_cistatic ssize_t __name ## _read(struct file *file,			      \
348c2ecf20Sopenharmony_ci				char __user *user_buf,			      \
358c2ecf20Sopenharmony_ci				size_t count, loff_t *ppos)		      \
368c2ecf20Sopenharmony_ci{									      \
378c2ecf20Sopenharmony_ci	struct hci_dev *hdev = file->private_data;			      \
388c2ecf20Sopenharmony_ci	char buf[3];							      \
398c2ecf20Sopenharmony_ci									      \
408c2ecf20Sopenharmony_ci	buf[0] = test_bit(__quirk, &hdev->quirks) ? 'Y' : 'N';		      \
418c2ecf20Sopenharmony_ci	buf[1] = '\n';							      \
428c2ecf20Sopenharmony_ci	buf[2] = '\0';							      \
438c2ecf20Sopenharmony_ci	return simple_read_from_buffer(user_buf, count, ppos, buf, 2);	      \
448c2ecf20Sopenharmony_ci}									      \
458c2ecf20Sopenharmony_ci									      \
468c2ecf20Sopenharmony_cistatic ssize_t __name ## _write(struct file *file,			      \
478c2ecf20Sopenharmony_ci				 const char __user *user_buf,		      \
488c2ecf20Sopenharmony_ci				 size_t count, loff_t *ppos)		      \
498c2ecf20Sopenharmony_ci{									      \
508c2ecf20Sopenharmony_ci	struct hci_dev *hdev = file->private_data;			      \
518c2ecf20Sopenharmony_ci	bool enable;							      \
528c2ecf20Sopenharmony_ci	int err;							      \
538c2ecf20Sopenharmony_ci									      \
548c2ecf20Sopenharmony_ci	if (test_bit(HCI_UP, &hdev->flags))				      \
558c2ecf20Sopenharmony_ci		return -EBUSY;						      \
568c2ecf20Sopenharmony_ci									      \
578c2ecf20Sopenharmony_ci	err = kstrtobool_from_user(user_buf, count, &enable);		      \
588c2ecf20Sopenharmony_ci	if (err)							      \
598c2ecf20Sopenharmony_ci		return err;						      \
608c2ecf20Sopenharmony_ci									      \
618c2ecf20Sopenharmony_ci	if (enable == test_bit(__quirk, &hdev->quirks))			      \
628c2ecf20Sopenharmony_ci		return -EALREADY;					      \
638c2ecf20Sopenharmony_ci									      \
648c2ecf20Sopenharmony_ci	change_bit(__quirk, &hdev->quirks);				      \
658c2ecf20Sopenharmony_ci									      \
668c2ecf20Sopenharmony_ci	return count;							      \
678c2ecf20Sopenharmony_ci}									      \
688c2ecf20Sopenharmony_ci									      \
698c2ecf20Sopenharmony_cistatic const struct file_operations __name ## _fops = {			      \
708c2ecf20Sopenharmony_ci	.open		= simple_open,					      \
718c2ecf20Sopenharmony_ci	.read		= __name ## _read,				      \
728c2ecf20Sopenharmony_ci	.write		= __name ## _write,				      \
738c2ecf20Sopenharmony_ci	.llseek		= default_llseek,				      \
748c2ecf20Sopenharmony_ci}									      \
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci#define DEFINE_INFO_ATTRIBUTE(__name, __field)				      \
778c2ecf20Sopenharmony_cistatic int __name ## _show(struct seq_file *f, void *ptr)		      \
788c2ecf20Sopenharmony_ci{									      \
798c2ecf20Sopenharmony_ci	struct hci_dev *hdev = f->private;				      \
808c2ecf20Sopenharmony_ci									      \
818c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);						      \
828c2ecf20Sopenharmony_ci	seq_printf(f, "%s\n", hdev->__field ? : "");			      \
838c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);						      \
848c2ecf20Sopenharmony_ci									      \
858c2ecf20Sopenharmony_ci	return 0;							      \
868c2ecf20Sopenharmony_ci}									      \
878c2ecf20Sopenharmony_ci									      \
888c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(__name)
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_cistatic int features_show(struct seq_file *f, void *ptr)
918c2ecf20Sopenharmony_ci{
928c2ecf20Sopenharmony_ci	struct hci_dev *hdev = f->private;
938c2ecf20Sopenharmony_ci	u8 p;
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
968c2ecf20Sopenharmony_ci	for (p = 0; p < HCI_MAX_PAGES && p <= hdev->max_page; p++)
978c2ecf20Sopenharmony_ci		seq_printf(f, "%2u: %8ph\n", p, hdev->features[p]);
988c2ecf20Sopenharmony_ci	if (lmp_le_capable(hdev))
998c2ecf20Sopenharmony_ci		seq_printf(f, "LE: %8ph\n", hdev->le_features);
1008c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	return 0;
1038c2ecf20Sopenharmony_ci}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(features);
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_cistatic int device_id_show(struct seq_file *f, void *ptr)
1088c2ecf20Sopenharmony_ci{
1098c2ecf20Sopenharmony_ci	struct hci_dev *hdev = f->private;
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
1128c2ecf20Sopenharmony_ci	seq_printf(f, "%4.4x:%4.4x:%4.4x:%4.4x\n", hdev->devid_source,
1138c2ecf20Sopenharmony_ci		  hdev->devid_vendor, hdev->devid_product, hdev->devid_version);
1148c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	return 0;
1178c2ecf20Sopenharmony_ci}
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(device_id);
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_cistatic int device_list_show(struct seq_file *f, void *ptr)
1228c2ecf20Sopenharmony_ci{
1238c2ecf20Sopenharmony_ci	struct hci_dev *hdev = f->private;
1248c2ecf20Sopenharmony_ci	struct hci_conn_params *p;
1258c2ecf20Sopenharmony_ci	struct bdaddr_list *b;
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
1288c2ecf20Sopenharmony_ci	list_for_each_entry(b, &hdev->accept_list, list)
1298c2ecf20Sopenharmony_ci		seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type);
1308c2ecf20Sopenharmony_ci	list_for_each_entry(p, &hdev->le_conn_params, list) {
1318c2ecf20Sopenharmony_ci		seq_printf(f, "%pMR (type %u) %u\n", &p->addr, p->addr_type,
1328c2ecf20Sopenharmony_ci			   p->auto_connect);
1338c2ecf20Sopenharmony_ci	}
1348c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci	return 0;
1378c2ecf20Sopenharmony_ci}
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(device_list);
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_cistatic int blacklist_show(struct seq_file *f, void *p)
1428c2ecf20Sopenharmony_ci{
1438c2ecf20Sopenharmony_ci	struct hci_dev *hdev = f->private;
1448c2ecf20Sopenharmony_ci	struct bdaddr_list *b;
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
1478c2ecf20Sopenharmony_ci	list_for_each_entry(b, &hdev->reject_list, list)
1488c2ecf20Sopenharmony_ci		seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type);
1498c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	return 0;
1528c2ecf20Sopenharmony_ci}
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(blacklist);
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_cistatic int blocked_keys_show(struct seq_file *f, void *p)
1578c2ecf20Sopenharmony_ci{
1588c2ecf20Sopenharmony_ci	struct hci_dev *hdev = f->private;
1598c2ecf20Sopenharmony_ci	struct blocked_key *key;
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci	rcu_read_lock();
1628c2ecf20Sopenharmony_ci	list_for_each_entry_rcu(key, &hdev->blocked_keys, list)
1638c2ecf20Sopenharmony_ci		seq_printf(f, "%u %*phN\n", key->type, 16, key->val);
1648c2ecf20Sopenharmony_ci	rcu_read_unlock();
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci	return 0;
1678c2ecf20Sopenharmony_ci}
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(blocked_keys);
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_cistatic int uuids_show(struct seq_file *f, void *p)
1728c2ecf20Sopenharmony_ci{
1738c2ecf20Sopenharmony_ci	struct hci_dev *hdev = f->private;
1748c2ecf20Sopenharmony_ci	struct bt_uuid *uuid;
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
1778c2ecf20Sopenharmony_ci	list_for_each_entry(uuid, &hdev->uuids, list) {
1788c2ecf20Sopenharmony_ci		u8 i, val[16];
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci		/* The Bluetooth UUID values are stored in big endian,
1818c2ecf20Sopenharmony_ci		 * but with reversed byte order. So convert them into
1828c2ecf20Sopenharmony_ci		 * the right order for the %pUb modifier.
1838c2ecf20Sopenharmony_ci		 */
1848c2ecf20Sopenharmony_ci		for (i = 0; i < 16; i++)
1858c2ecf20Sopenharmony_ci			val[i] = uuid->uuid[15 - i];
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci		seq_printf(f, "%pUb\n", val);
1888c2ecf20Sopenharmony_ci	}
1898c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci       return 0;
1928c2ecf20Sopenharmony_ci}
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(uuids);
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_cistatic int remote_oob_show(struct seq_file *f, void *ptr)
1978c2ecf20Sopenharmony_ci{
1988c2ecf20Sopenharmony_ci	struct hci_dev *hdev = f->private;
1998c2ecf20Sopenharmony_ci	struct oob_data *data;
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
2028c2ecf20Sopenharmony_ci	list_for_each_entry(data, &hdev->remote_oob_data, list) {
2038c2ecf20Sopenharmony_ci		seq_printf(f, "%pMR (type %u) %u %*phN %*phN %*phN %*phN\n",
2048c2ecf20Sopenharmony_ci			   &data->bdaddr, data->bdaddr_type, data->present,
2058c2ecf20Sopenharmony_ci			   16, data->hash192, 16, data->rand192,
2068c2ecf20Sopenharmony_ci			   16, data->hash256, 16, data->rand256);
2078c2ecf20Sopenharmony_ci	}
2088c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	return 0;
2118c2ecf20Sopenharmony_ci}
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(remote_oob);
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_cistatic int conn_info_min_age_set(void *data, u64 val)
2168c2ecf20Sopenharmony_ci{
2178c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
2208c2ecf20Sopenharmony_ci	if (val == 0 || val > hdev->conn_info_max_age) {
2218c2ecf20Sopenharmony_ci		hci_dev_unlock(hdev);
2228c2ecf20Sopenharmony_ci		return -EINVAL;
2238c2ecf20Sopenharmony_ci	}
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	hdev->conn_info_min_age = val;
2268c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci	return 0;
2298c2ecf20Sopenharmony_ci}
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_cistatic int conn_info_min_age_get(void *data, u64 *val)
2328c2ecf20Sopenharmony_ci{
2338c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
2368c2ecf20Sopenharmony_ci	*val = hdev->conn_info_min_age;
2378c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci	return 0;
2408c2ecf20Sopenharmony_ci}
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ciDEFINE_SIMPLE_ATTRIBUTE(conn_info_min_age_fops, conn_info_min_age_get,
2438c2ecf20Sopenharmony_ci			conn_info_min_age_set, "%llu\n");
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_cistatic int conn_info_max_age_set(void *data, u64 val)
2468c2ecf20Sopenharmony_ci{
2478c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
2508c2ecf20Sopenharmony_ci	if (val == 0 || val < hdev->conn_info_min_age) {
2518c2ecf20Sopenharmony_ci		hci_dev_unlock(hdev);
2528c2ecf20Sopenharmony_ci		return -EINVAL;
2538c2ecf20Sopenharmony_ci	}
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	hdev->conn_info_max_age = val;
2568c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci	return 0;
2598c2ecf20Sopenharmony_ci}
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_cistatic int conn_info_max_age_get(void *data, u64 *val)
2628c2ecf20Sopenharmony_ci{
2638c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
2668c2ecf20Sopenharmony_ci	*val = hdev->conn_info_max_age;
2678c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci	return 0;
2708c2ecf20Sopenharmony_ci}
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ciDEFINE_SIMPLE_ATTRIBUTE(conn_info_max_age_fops, conn_info_max_age_get,
2738c2ecf20Sopenharmony_ci			conn_info_max_age_set, "%llu\n");
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_cistatic ssize_t use_debug_keys_read(struct file *file, char __user *user_buf,
2768c2ecf20Sopenharmony_ci				   size_t count, loff_t *ppos)
2778c2ecf20Sopenharmony_ci{
2788c2ecf20Sopenharmony_ci	struct hci_dev *hdev = file->private_data;
2798c2ecf20Sopenharmony_ci	char buf[3];
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci	buf[0] = hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS) ? 'Y': 'N';
2828c2ecf20Sopenharmony_ci	buf[1] = '\n';
2838c2ecf20Sopenharmony_ci	buf[2] = '\0';
2848c2ecf20Sopenharmony_ci	return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
2858c2ecf20Sopenharmony_ci}
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_cistatic const struct file_operations use_debug_keys_fops = {
2888c2ecf20Sopenharmony_ci	.open		= simple_open,
2898c2ecf20Sopenharmony_ci	.read		= use_debug_keys_read,
2908c2ecf20Sopenharmony_ci	.llseek		= default_llseek,
2918c2ecf20Sopenharmony_ci};
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_cistatic ssize_t sc_only_mode_read(struct file *file, char __user *user_buf,
2948c2ecf20Sopenharmony_ci				 size_t count, loff_t *ppos)
2958c2ecf20Sopenharmony_ci{
2968c2ecf20Sopenharmony_ci	struct hci_dev *hdev = file->private_data;
2978c2ecf20Sopenharmony_ci	char buf[3];
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	buf[0] = hci_dev_test_flag(hdev, HCI_SC_ONLY) ? 'Y': 'N';
3008c2ecf20Sopenharmony_ci	buf[1] = '\n';
3018c2ecf20Sopenharmony_ci	buf[2] = '\0';
3028c2ecf20Sopenharmony_ci	return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
3038c2ecf20Sopenharmony_ci}
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_cistatic const struct file_operations sc_only_mode_fops = {
3068c2ecf20Sopenharmony_ci	.open		= simple_open,
3078c2ecf20Sopenharmony_ci	.read		= sc_only_mode_read,
3088c2ecf20Sopenharmony_ci	.llseek		= default_llseek,
3098c2ecf20Sopenharmony_ci};
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ciDEFINE_INFO_ATTRIBUTE(hardware_info, hw_info);
3128c2ecf20Sopenharmony_ciDEFINE_INFO_ATTRIBUTE(firmware_info, fw_info);
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_civoid hci_debugfs_create_common(struct hci_dev *hdev)
3158c2ecf20Sopenharmony_ci{
3168c2ecf20Sopenharmony_ci	debugfs_create_file("features", 0444, hdev->debugfs, hdev,
3178c2ecf20Sopenharmony_ci			    &features_fops);
3188c2ecf20Sopenharmony_ci	debugfs_create_u16("manufacturer", 0444, hdev->debugfs,
3198c2ecf20Sopenharmony_ci			   &hdev->manufacturer);
3208c2ecf20Sopenharmony_ci	debugfs_create_u8("hci_version", 0444, hdev->debugfs, &hdev->hci_ver);
3218c2ecf20Sopenharmony_ci	debugfs_create_u16("hci_revision", 0444, hdev->debugfs, &hdev->hci_rev);
3228c2ecf20Sopenharmony_ci	debugfs_create_u8("hardware_error", 0444, hdev->debugfs,
3238c2ecf20Sopenharmony_ci			  &hdev->hw_error_code);
3248c2ecf20Sopenharmony_ci	debugfs_create_file("device_id", 0444, hdev->debugfs, hdev,
3258c2ecf20Sopenharmony_ci			    &device_id_fops);
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci	debugfs_create_file("device_list", 0444, hdev->debugfs, hdev,
3288c2ecf20Sopenharmony_ci			    &device_list_fops);
3298c2ecf20Sopenharmony_ci	debugfs_create_file("blacklist", 0444, hdev->debugfs, hdev,
3308c2ecf20Sopenharmony_ci			    &blacklist_fops);
3318c2ecf20Sopenharmony_ci	debugfs_create_file("blocked_keys", 0444, hdev->debugfs, hdev,
3328c2ecf20Sopenharmony_ci			    &blocked_keys_fops);
3338c2ecf20Sopenharmony_ci	debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops);
3348c2ecf20Sopenharmony_ci	debugfs_create_file("remote_oob", 0400, hdev->debugfs, hdev,
3358c2ecf20Sopenharmony_ci			    &remote_oob_fops);
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci	debugfs_create_file("conn_info_min_age", 0644, hdev->debugfs, hdev,
3388c2ecf20Sopenharmony_ci			    &conn_info_min_age_fops);
3398c2ecf20Sopenharmony_ci	debugfs_create_file("conn_info_max_age", 0644, hdev->debugfs, hdev,
3408c2ecf20Sopenharmony_ci			    &conn_info_max_age_fops);
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	if (lmp_ssp_capable(hdev) || lmp_le_capable(hdev))
3438c2ecf20Sopenharmony_ci		debugfs_create_file("use_debug_keys", 0444, hdev->debugfs,
3448c2ecf20Sopenharmony_ci				    hdev, &use_debug_keys_fops);
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci	if (lmp_sc_capable(hdev) || lmp_le_capable(hdev))
3478c2ecf20Sopenharmony_ci		debugfs_create_file("sc_only_mode", 0444, hdev->debugfs,
3488c2ecf20Sopenharmony_ci				    hdev, &sc_only_mode_fops);
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci	if (hdev->hw_info)
3518c2ecf20Sopenharmony_ci		debugfs_create_file("hardware_info", 0444, hdev->debugfs,
3528c2ecf20Sopenharmony_ci				    hdev, &hardware_info_fops);
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	if (hdev->fw_info)
3558c2ecf20Sopenharmony_ci		debugfs_create_file("firmware_info", 0444, hdev->debugfs,
3568c2ecf20Sopenharmony_ci				    hdev, &firmware_info_fops);
3578c2ecf20Sopenharmony_ci}
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_cistatic int inquiry_cache_show(struct seq_file *f, void *p)
3608c2ecf20Sopenharmony_ci{
3618c2ecf20Sopenharmony_ci	struct hci_dev *hdev = f->private;
3628c2ecf20Sopenharmony_ci	struct discovery_state *cache = &hdev->discovery;
3638c2ecf20Sopenharmony_ci	struct inquiry_entry *e;
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci	list_for_each_entry(e, &cache->all, all) {
3688c2ecf20Sopenharmony_ci		struct inquiry_data *data = &e->data;
3698c2ecf20Sopenharmony_ci		seq_printf(f, "%pMR %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n",
3708c2ecf20Sopenharmony_ci			   &data->bdaddr,
3718c2ecf20Sopenharmony_ci			   data->pscan_rep_mode, data->pscan_period_mode,
3728c2ecf20Sopenharmony_ci			   data->pscan_mode, data->dev_class[2],
3738c2ecf20Sopenharmony_ci			   data->dev_class[1], data->dev_class[0],
3748c2ecf20Sopenharmony_ci			   __le16_to_cpu(data->clock_offset),
3758c2ecf20Sopenharmony_ci			   data->rssi, data->ssp_mode, e->timestamp);
3768c2ecf20Sopenharmony_ci	}
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci	return 0;
3818c2ecf20Sopenharmony_ci}
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(inquiry_cache);
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_cistatic int link_keys_show(struct seq_file *f, void *ptr)
3868c2ecf20Sopenharmony_ci{
3878c2ecf20Sopenharmony_ci	struct hci_dev *hdev = f->private;
3888c2ecf20Sopenharmony_ci	struct link_key *key;
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci	rcu_read_lock();
3918c2ecf20Sopenharmony_ci	list_for_each_entry_rcu(key, &hdev->link_keys, list)
3928c2ecf20Sopenharmony_ci		seq_printf(f, "%pMR %u %*phN %u\n", &key->bdaddr, key->type,
3938c2ecf20Sopenharmony_ci			   HCI_LINK_KEY_SIZE, key->val, key->pin_len);
3948c2ecf20Sopenharmony_ci	rcu_read_unlock();
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci	return 0;
3978c2ecf20Sopenharmony_ci}
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(link_keys);
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_cistatic int dev_class_show(struct seq_file *f, void *ptr)
4028c2ecf20Sopenharmony_ci{
4038c2ecf20Sopenharmony_ci	struct hci_dev *hdev = f->private;
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
4068c2ecf20Sopenharmony_ci	seq_printf(f, "0x%.2x%.2x%.2x\n", hdev->dev_class[2],
4078c2ecf20Sopenharmony_ci		   hdev->dev_class[1], hdev->dev_class[0]);
4088c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci	return 0;
4118c2ecf20Sopenharmony_ci}
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(dev_class);
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_cistatic int voice_setting_get(void *data, u64 *val)
4168c2ecf20Sopenharmony_ci{
4178c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
4208c2ecf20Sopenharmony_ci	*val = hdev->voice_setting;
4218c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ci	return 0;
4248c2ecf20Sopenharmony_ci}
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ciDEFINE_SIMPLE_ATTRIBUTE(voice_setting_fops, voice_setting_get,
4278c2ecf20Sopenharmony_ci			NULL, "0x%4.4llx\n");
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_cistatic ssize_t ssp_debug_mode_read(struct file *file, char __user *user_buf,
4308c2ecf20Sopenharmony_ci				   size_t count, loff_t *ppos)
4318c2ecf20Sopenharmony_ci{
4328c2ecf20Sopenharmony_ci	struct hci_dev *hdev = file->private_data;
4338c2ecf20Sopenharmony_ci	char buf[3];
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	buf[0] = hdev->ssp_debug_mode ? 'Y': 'N';
4368c2ecf20Sopenharmony_ci	buf[1] = '\n';
4378c2ecf20Sopenharmony_ci	buf[2] = '\0';
4388c2ecf20Sopenharmony_ci	return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
4398c2ecf20Sopenharmony_ci}
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_cistatic const struct file_operations ssp_debug_mode_fops = {
4428c2ecf20Sopenharmony_ci	.open		= simple_open,
4438c2ecf20Sopenharmony_ci	.read		= ssp_debug_mode_read,
4448c2ecf20Sopenharmony_ci	.llseek		= default_llseek,
4458c2ecf20Sopenharmony_ci};
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_cistatic int auto_accept_delay_set(void *data, u64 val)
4488c2ecf20Sopenharmony_ci{
4498c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
4528c2ecf20Sopenharmony_ci	hdev->auto_accept_delay = val;
4538c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_ci	return 0;
4568c2ecf20Sopenharmony_ci}
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_cistatic int min_encrypt_key_size_set(void *data, u64 val)
4598c2ecf20Sopenharmony_ci{
4608c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci	if (val < 1 || val > 16)
4638c2ecf20Sopenharmony_ci		return -EINVAL;
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
4668c2ecf20Sopenharmony_ci	hdev->min_enc_key_size = val;
4678c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci	return 0;
4708c2ecf20Sopenharmony_ci}
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_cistatic int min_encrypt_key_size_get(void *data, u64 *val)
4738c2ecf20Sopenharmony_ci{
4748c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
4758c2ecf20Sopenharmony_ci
4768c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
4778c2ecf20Sopenharmony_ci	*val = hdev->min_enc_key_size;
4788c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci	return 0;
4818c2ecf20Sopenharmony_ci}
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ciDEFINE_SIMPLE_ATTRIBUTE(min_encrypt_key_size_fops,
4848c2ecf20Sopenharmony_ci			min_encrypt_key_size_get,
4858c2ecf20Sopenharmony_ci			min_encrypt_key_size_set, "%llu\n");
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_cistatic int auto_accept_delay_get(void *data, u64 *val)
4888c2ecf20Sopenharmony_ci{
4898c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
4928c2ecf20Sopenharmony_ci	*val = hdev->auto_accept_delay;
4938c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_ci	return 0;
4968c2ecf20Sopenharmony_ci}
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ciDEFINE_SIMPLE_ATTRIBUTE(auto_accept_delay_fops, auto_accept_delay_get,
4998c2ecf20Sopenharmony_ci			auto_accept_delay_set, "%llu\n");
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_cistatic int idle_timeout_set(void *data, u64 val)
5028c2ecf20Sopenharmony_ci{
5038c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ci	if (val != 0 && (val < 500 || val > 3600000))
5068c2ecf20Sopenharmony_ci		return -EINVAL;
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
5098c2ecf20Sopenharmony_ci	hdev->idle_timeout = val;
5108c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ci	return 0;
5138c2ecf20Sopenharmony_ci}
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_cistatic int idle_timeout_get(void *data, u64 *val)
5168c2ecf20Sopenharmony_ci{
5178c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
5208c2ecf20Sopenharmony_ci	*val = hdev->idle_timeout;
5218c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
5228c2ecf20Sopenharmony_ci
5238c2ecf20Sopenharmony_ci	return 0;
5248c2ecf20Sopenharmony_ci}
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ciDEFINE_SIMPLE_ATTRIBUTE(idle_timeout_fops, idle_timeout_get,
5278c2ecf20Sopenharmony_ci			idle_timeout_set, "%llu\n");
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_cistatic int sniff_min_interval_set(void *data, u64 val)
5308c2ecf20Sopenharmony_ci{
5318c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
5348c2ecf20Sopenharmony_ci	if (val == 0 || val % 2 || val > hdev->sniff_max_interval) {
5358c2ecf20Sopenharmony_ci		hci_dev_unlock(hdev);
5368c2ecf20Sopenharmony_ci		return -EINVAL;
5378c2ecf20Sopenharmony_ci	}
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_ci	hdev->sniff_min_interval = val;
5408c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_ci	return 0;
5438c2ecf20Sopenharmony_ci}
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_cistatic int sniff_min_interval_get(void *data, u64 *val)
5468c2ecf20Sopenharmony_ci{
5478c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
5508c2ecf20Sopenharmony_ci	*val = hdev->sniff_min_interval;
5518c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_ci	return 0;
5548c2ecf20Sopenharmony_ci}
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_ciDEFINE_SIMPLE_ATTRIBUTE(sniff_min_interval_fops, sniff_min_interval_get,
5578c2ecf20Sopenharmony_ci			sniff_min_interval_set, "%llu\n");
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_cistatic int sniff_max_interval_set(void *data, u64 val)
5608c2ecf20Sopenharmony_ci{
5618c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
5628c2ecf20Sopenharmony_ci
5638c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
5648c2ecf20Sopenharmony_ci	if (val == 0 || val % 2 || val < hdev->sniff_min_interval) {
5658c2ecf20Sopenharmony_ci		hci_dev_unlock(hdev);
5668c2ecf20Sopenharmony_ci		return -EINVAL;
5678c2ecf20Sopenharmony_ci	}
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci	hdev->sniff_max_interval = val;
5708c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci	return 0;
5738c2ecf20Sopenharmony_ci}
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_cistatic int sniff_max_interval_get(void *data, u64 *val)
5768c2ecf20Sopenharmony_ci{
5778c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
5808c2ecf20Sopenharmony_ci	*val = hdev->sniff_max_interval;
5818c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci	return 0;
5848c2ecf20Sopenharmony_ci}
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_ciDEFINE_SIMPLE_ATTRIBUTE(sniff_max_interval_fops, sniff_max_interval_get,
5878c2ecf20Sopenharmony_ci			sniff_max_interval_set, "%llu\n");
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_civoid hci_debugfs_create_bredr(struct hci_dev *hdev)
5908c2ecf20Sopenharmony_ci{
5918c2ecf20Sopenharmony_ci	debugfs_create_file("inquiry_cache", 0444, hdev->debugfs, hdev,
5928c2ecf20Sopenharmony_ci			    &inquiry_cache_fops);
5938c2ecf20Sopenharmony_ci	debugfs_create_file("link_keys", 0400, hdev->debugfs, hdev,
5948c2ecf20Sopenharmony_ci			    &link_keys_fops);
5958c2ecf20Sopenharmony_ci	debugfs_create_file("dev_class", 0444, hdev->debugfs, hdev,
5968c2ecf20Sopenharmony_ci			    &dev_class_fops);
5978c2ecf20Sopenharmony_ci	debugfs_create_file("voice_setting", 0444, hdev->debugfs, hdev,
5988c2ecf20Sopenharmony_ci			    &voice_setting_fops);
5998c2ecf20Sopenharmony_ci
6008c2ecf20Sopenharmony_ci	if (lmp_ssp_capable(hdev)) {
6018c2ecf20Sopenharmony_ci		debugfs_create_file("ssp_debug_mode", 0444, hdev->debugfs,
6028c2ecf20Sopenharmony_ci				    hdev, &ssp_debug_mode_fops);
6038c2ecf20Sopenharmony_ci		debugfs_create_file("min_encrypt_key_size", 0644, hdev->debugfs,
6048c2ecf20Sopenharmony_ci				    hdev, &min_encrypt_key_size_fops);
6058c2ecf20Sopenharmony_ci		debugfs_create_file("auto_accept_delay", 0644, hdev->debugfs,
6068c2ecf20Sopenharmony_ci				    hdev, &auto_accept_delay_fops);
6078c2ecf20Sopenharmony_ci	}
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ci	if (lmp_sniff_capable(hdev)) {
6108c2ecf20Sopenharmony_ci		debugfs_create_file("idle_timeout", 0644, hdev->debugfs,
6118c2ecf20Sopenharmony_ci				    hdev, &idle_timeout_fops);
6128c2ecf20Sopenharmony_ci		debugfs_create_file("sniff_min_interval", 0644, hdev->debugfs,
6138c2ecf20Sopenharmony_ci				    hdev, &sniff_min_interval_fops);
6148c2ecf20Sopenharmony_ci		debugfs_create_file("sniff_max_interval", 0644, hdev->debugfs,
6158c2ecf20Sopenharmony_ci				    hdev, &sniff_max_interval_fops);
6168c2ecf20Sopenharmony_ci	}
6178c2ecf20Sopenharmony_ci}
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_cistatic int identity_show(struct seq_file *f, void *p)
6208c2ecf20Sopenharmony_ci{
6218c2ecf20Sopenharmony_ci	struct hci_dev *hdev = f->private;
6228c2ecf20Sopenharmony_ci	bdaddr_t addr;
6238c2ecf20Sopenharmony_ci	u8 addr_type;
6248c2ecf20Sopenharmony_ci
6258c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_ci	hci_copy_identity_address(hdev, &addr, &addr_type);
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_ci	seq_printf(f, "%pMR (type %u) %*phN %pMR\n", &addr, addr_type,
6308c2ecf20Sopenharmony_ci		   16, hdev->irk, &hdev->rpa);
6318c2ecf20Sopenharmony_ci
6328c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_ci	return 0;
6358c2ecf20Sopenharmony_ci}
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(identity);
6388c2ecf20Sopenharmony_ci
6398c2ecf20Sopenharmony_cistatic int rpa_timeout_set(void *data, u64 val)
6408c2ecf20Sopenharmony_ci{
6418c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
6428c2ecf20Sopenharmony_ci
6438c2ecf20Sopenharmony_ci	/* Require the RPA timeout to be at least 30 seconds and at most
6448c2ecf20Sopenharmony_ci	 * 24 hours.
6458c2ecf20Sopenharmony_ci	 */
6468c2ecf20Sopenharmony_ci	if (val < 30 || val > (60 * 60 * 24))
6478c2ecf20Sopenharmony_ci		return -EINVAL;
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
6508c2ecf20Sopenharmony_ci	hdev->rpa_timeout = val;
6518c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_ci	return 0;
6548c2ecf20Sopenharmony_ci}
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_cistatic int rpa_timeout_get(void *data, u64 *val)
6578c2ecf20Sopenharmony_ci{
6588c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
6598c2ecf20Sopenharmony_ci
6608c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
6618c2ecf20Sopenharmony_ci	*val = hdev->rpa_timeout;
6628c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
6638c2ecf20Sopenharmony_ci
6648c2ecf20Sopenharmony_ci	return 0;
6658c2ecf20Sopenharmony_ci}
6668c2ecf20Sopenharmony_ci
6678c2ecf20Sopenharmony_ciDEFINE_SIMPLE_ATTRIBUTE(rpa_timeout_fops, rpa_timeout_get,
6688c2ecf20Sopenharmony_ci			rpa_timeout_set, "%llu\n");
6698c2ecf20Sopenharmony_ci
6708c2ecf20Sopenharmony_cistatic int random_address_show(struct seq_file *f, void *p)
6718c2ecf20Sopenharmony_ci{
6728c2ecf20Sopenharmony_ci	struct hci_dev *hdev = f->private;
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
6758c2ecf20Sopenharmony_ci	seq_printf(f, "%pMR\n", &hdev->random_addr);
6768c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_ci	return 0;
6798c2ecf20Sopenharmony_ci}
6808c2ecf20Sopenharmony_ci
6818c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(random_address);
6828c2ecf20Sopenharmony_ci
6838c2ecf20Sopenharmony_cistatic int static_address_show(struct seq_file *f, void *p)
6848c2ecf20Sopenharmony_ci{
6858c2ecf20Sopenharmony_ci	struct hci_dev *hdev = f->private;
6868c2ecf20Sopenharmony_ci
6878c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
6888c2ecf20Sopenharmony_ci	seq_printf(f, "%pMR\n", &hdev->static_addr);
6898c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_ci	return 0;
6928c2ecf20Sopenharmony_ci}
6938c2ecf20Sopenharmony_ci
6948c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(static_address);
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_cistatic ssize_t force_static_address_read(struct file *file,
6978c2ecf20Sopenharmony_ci					 char __user *user_buf,
6988c2ecf20Sopenharmony_ci					 size_t count, loff_t *ppos)
6998c2ecf20Sopenharmony_ci{
7008c2ecf20Sopenharmony_ci	struct hci_dev *hdev = file->private_data;
7018c2ecf20Sopenharmony_ci	char buf[3];
7028c2ecf20Sopenharmony_ci
7038c2ecf20Sopenharmony_ci	buf[0] = hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ? 'Y': 'N';
7048c2ecf20Sopenharmony_ci	buf[1] = '\n';
7058c2ecf20Sopenharmony_ci	buf[2] = '\0';
7068c2ecf20Sopenharmony_ci	return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
7078c2ecf20Sopenharmony_ci}
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_cistatic ssize_t force_static_address_write(struct file *file,
7108c2ecf20Sopenharmony_ci					  const char __user *user_buf,
7118c2ecf20Sopenharmony_ci					  size_t count, loff_t *ppos)
7128c2ecf20Sopenharmony_ci{
7138c2ecf20Sopenharmony_ci	struct hci_dev *hdev = file->private_data;
7148c2ecf20Sopenharmony_ci	bool enable;
7158c2ecf20Sopenharmony_ci	int err;
7168c2ecf20Sopenharmony_ci
7178c2ecf20Sopenharmony_ci	if (test_bit(HCI_UP, &hdev->flags))
7188c2ecf20Sopenharmony_ci		return -EBUSY;
7198c2ecf20Sopenharmony_ci
7208c2ecf20Sopenharmony_ci	err = kstrtobool_from_user(user_buf, count, &enable);
7218c2ecf20Sopenharmony_ci	if (err)
7228c2ecf20Sopenharmony_ci		return err;
7238c2ecf20Sopenharmony_ci
7248c2ecf20Sopenharmony_ci	if (enable == hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR))
7258c2ecf20Sopenharmony_ci		return -EALREADY;
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ci	hci_dev_change_flag(hdev, HCI_FORCE_STATIC_ADDR);
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_ci	return count;
7308c2ecf20Sopenharmony_ci}
7318c2ecf20Sopenharmony_ci
7328c2ecf20Sopenharmony_cistatic const struct file_operations force_static_address_fops = {
7338c2ecf20Sopenharmony_ci	.open		= simple_open,
7348c2ecf20Sopenharmony_ci	.read		= force_static_address_read,
7358c2ecf20Sopenharmony_ci	.write		= force_static_address_write,
7368c2ecf20Sopenharmony_ci	.llseek		= default_llseek,
7378c2ecf20Sopenharmony_ci};
7388c2ecf20Sopenharmony_ci
7398c2ecf20Sopenharmony_cistatic int white_list_show(struct seq_file *f, void *ptr)
7408c2ecf20Sopenharmony_ci{
7418c2ecf20Sopenharmony_ci	struct hci_dev *hdev = f->private;
7428c2ecf20Sopenharmony_ci	struct bdaddr_list *b;
7438c2ecf20Sopenharmony_ci
7448c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
7458c2ecf20Sopenharmony_ci	list_for_each_entry(b, &hdev->le_accept_list, list)
7468c2ecf20Sopenharmony_ci		seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type);
7478c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
7488c2ecf20Sopenharmony_ci
7498c2ecf20Sopenharmony_ci	return 0;
7508c2ecf20Sopenharmony_ci}
7518c2ecf20Sopenharmony_ci
7528c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(white_list);
7538c2ecf20Sopenharmony_ci
7548c2ecf20Sopenharmony_cistatic int resolv_list_show(struct seq_file *f, void *ptr)
7558c2ecf20Sopenharmony_ci{
7568c2ecf20Sopenharmony_ci	struct hci_dev *hdev = f->private;
7578c2ecf20Sopenharmony_ci	struct bdaddr_list *b;
7588c2ecf20Sopenharmony_ci
7598c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
7608c2ecf20Sopenharmony_ci	list_for_each_entry(b, &hdev->le_resolv_list, list)
7618c2ecf20Sopenharmony_ci		seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type);
7628c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
7638c2ecf20Sopenharmony_ci
7648c2ecf20Sopenharmony_ci	return 0;
7658c2ecf20Sopenharmony_ci}
7668c2ecf20Sopenharmony_ci
7678c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(resolv_list);
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_cistatic int identity_resolving_keys_show(struct seq_file *f, void *ptr)
7708c2ecf20Sopenharmony_ci{
7718c2ecf20Sopenharmony_ci	struct hci_dev *hdev = f->private;
7728c2ecf20Sopenharmony_ci	struct smp_irk *irk;
7738c2ecf20Sopenharmony_ci
7748c2ecf20Sopenharmony_ci	rcu_read_lock();
7758c2ecf20Sopenharmony_ci	list_for_each_entry_rcu(irk, &hdev->identity_resolving_keys, list) {
7768c2ecf20Sopenharmony_ci		seq_printf(f, "%pMR (type %u) %*phN %pMR\n",
7778c2ecf20Sopenharmony_ci			   &irk->bdaddr, irk->addr_type,
7788c2ecf20Sopenharmony_ci			   16, irk->val, &irk->rpa);
7798c2ecf20Sopenharmony_ci	}
7808c2ecf20Sopenharmony_ci	rcu_read_unlock();
7818c2ecf20Sopenharmony_ci
7828c2ecf20Sopenharmony_ci	return 0;
7838c2ecf20Sopenharmony_ci}
7848c2ecf20Sopenharmony_ci
7858c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(identity_resolving_keys);
7868c2ecf20Sopenharmony_ci
7878c2ecf20Sopenharmony_cistatic int long_term_keys_show(struct seq_file *f, void *ptr)
7888c2ecf20Sopenharmony_ci{
7898c2ecf20Sopenharmony_ci	struct hci_dev *hdev = f->private;
7908c2ecf20Sopenharmony_ci	struct smp_ltk *ltk;
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_ci	rcu_read_lock();
7938c2ecf20Sopenharmony_ci	list_for_each_entry_rcu(ltk, &hdev->long_term_keys, list)
7948c2ecf20Sopenharmony_ci		seq_printf(f, "%pMR (type %u) %u 0x%02x %u %.4x %.16llx %*phN\n",
7958c2ecf20Sopenharmony_ci			   &ltk->bdaddr, ltk->bdaddr_type, ltk->authenticated,
7968c2ecf20Sopenharmony_ci			   ltk->type, ltk->enc_size, __le16_to_cpu(ltk->ediv),
7978c2ecf20Sopenharmony_ci			   __le64_to_cpu(ltk->rand), 16, ltk->val);
7988c2ecf20Sopenharmony_ci	rcu_read_unlock();
7998c2ecf20Sopenharmony_ci
8008c2ecf20Sopenharmony_ci	return 0;
8018c2ecf20Sopenharmony_ci}
8028c2ecf20Sopenharmony_ci
8038c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(long_term_keys);
8048c2ecf20Sopenharmony_ci
8058c2ecf20Sopenharmony_cistatic int conn_min_interval_set(void *data, u64 val)
8068c2ecf20Sopenharmony_ci{
8078c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
8108c2ecf20Sopenharmony_ci	if (val < 0x0006 || val > 0x0c80 || val > hdev->le_conn_max_interval) {
8118c2ecf20Sopenharmony_ci		hci_dev_unlock(hdev);
8128c2ecf20Sopenharmony_ci		return -EINVAL;
8138c2ecf20Sopenharmony_ci	}
8148c2ecf20Sopenharmony_ci
8158c2ecf20Sopenharmony_ci	hdev->le_conn_min_interval = val;
8168c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
8178c2ecf20Sopenharmony_ci
8188c2ecf20Sopenharmony_ci	return 0;
8198c2ecf20Sopenharmony_ci}
8208c2ecf20Sopenharmony_ci
8218c2ecf20Sopenharmony_cistatic int conn_min_interval_get(void *data, u64 *val)
8228c2ecf20Sopenharmony_ci{
8238c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
8248c2ecf20Sopenharmony_ci
8258c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
8268c2ecf20Sopenharmony_ci	*val = hdev->le_conn_min_interval;
8278c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_ci	return 0;
8308c2ecf20Sopenharmony_ci}
8318c2ecf20Sopenharmony_ci
8328c2ecf20Sopenharmony_ciDEFINE_SIMPLE_ATTRIBUTE(conn_min_interval_fops, conn_min_interval_get,
8338c2ecf20Sopenharmony_ci			conn_min_interval_set, "%llu\n");
8348c2ecf20Sopenharmony_ci
8358c2ecf20Sopenharmony_cistatic int conn_max_interval_set(void *data, u64 val)
8368c2ecf20Sopenharmony_ci{
8378c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
8388c2ecf20Sopenharmony_ci
8398c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
8408c2ecf20Sopenharmony_ci	if (val < 0x0006 || val > 0x0c80 || val < hdev->le_conn_min_interval) {
8418c2ecf20Sopenharmony_ci		hci_dev_unlock(hdev);
8428c2ecf20Sopenharmony_ci		return -EINVAL;
8438c2ecf20Sopenharmony_ci	}
8448c2ecf20Sopenharmony_ci
8458c2ecf20Sopenharmony_ci	hdev->le_conn_max_interval = val;
8468c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
8478c2ecf20Sopenharmony_ci
8488c2ecf20Sopenharmony_ci	return 0;
8498c2ecf20Sopenharmony_ci}
8508c2ecf20Sopenharmony_ci
8518c2ecf20Sopenharmony_cistatic int conn_max_interval_get(void *data, u64 *val)
8528c2ecf20Sopenharmony_ci{
8538c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
8548c2ecf20Sopenharmony_ci
8558c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
8568c2ecf20Sopenharmony_ci	*val = hdev->le_conn_max_interval;
8578c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_ci	return 0;
8608c2ecf20Sopenharmony_ci}
8618c2ecf20Sopenharmony_ci
8628c2ecf20Sopenharmony_ciDEFINE_SIMPLE_ATTRIBUTE(conn_max_interval_fops, conn_max_interval_get,
8638c2ecf20Sopenharmony_ci			conn_max_interval_set, "%llu\n");
8648c2ecf20Sopenharmony_ci
8658c2ecf20Sopenharmony_cistatic int conn_latency_set(void *data, u64 val)
8668c2ecf20Sopenharmony_ci{
8678c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_ci	if (val > 0x01f3)
8708c2ecf20Sopenharmony_ci		return -EINVAL;
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
8738c2ecf20Sopenharmony_ci	hdev->le_conn_latency = val;
8748c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
8758c2ecf20Sopenharmony_ci
8768c2ecf20Sopenharmony_ci	return 0;
8778c2ecf20Sopenharmony_ci}
8788c2ecf20Sopenharmony_ci
8798c2ecf20Sopenharmony_cistatic int conn_latency_get(void *data, u64 *val)
8808c2ecf20Sopenharmony_ci{
8818c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
8828c2ecf20Sopenharmony_ci
8838c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
8848c2ecf20Sopenharmony_ci	*val = hdev->le_conn_latency;
8858c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
8868c2ecf20Sopenharmony_ci
8878c2ecf20Sopenharmony_ci	return 0;
8888c2ecf20Sopenharmony_ci}
8898c2ecf20Sopenharmony_ci
8908c2ecf20Sopenharmony_ciDEFINE_SIMPLE_ATTRIBUTE(conn_latency_fops, conn_latency_get,
8918c2ecf20Sopenharmony_ci			conn_latency_set, "%llu\n");
8928c2ecf20Sopenharmony_ci
8938c2ecf20Sopenharmony_cistatic int supervision_timeout_set(void *data, u64 val)
8948c2ecf20Sopenharmony_ci{
8958c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
8968c2ecf20Sopenharmony_ci
8978c2ecf20Sopenharmony_ci	if (val < 0x000a || val > 0x0c80)
8988c2ecf20Sopenharmony_ci		return -EINVAL;
8998c2ecf20Sopenharmony_ci
9008c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
9018c2ecf20Sopenharmony_ci	hdev->le_supv_timeout = val;
9028c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
9038c2ecf20Sopenharmony_ci
9048c2ecf20Sopenharmony_ci	return 0;
9058c2ecf20Sopenharmony_ci}
9068c2ecf20Sopenharmony_ci
9078c2ecf20Sopenharmony_cistatic int supervision_timeout_get(void *data, u64 *val)
9088c2ecf20Sopenharmony_ci{
9098c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
9108c2ecf20Sopenharmony_ci
9118c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
9128c2ecf20Sopenharmony_ci	*val = hdev->le_supv_timeout;
9138c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
9148c2ecf20Sopenharmony_ci
9158c2ecf20Sopenharmony_ci	return 0;
9168c2ecf20Sopenharmony_ci}
9178c2ecf20Sopenharmony_ci
9188c2ecf20Sopenharmony_ciDEFINE_SIMPLE_ATTRIBUTE(supervision_timeout_fops, supervision_timeout_get,
9198c2ecf20Sopenharmony_ci			supervision_timeout_set, "%llu\n");
9208c2ecf20Sopenharmony_ci
9218c2ecf20Sopenharmony_cistatic int adv_channel_map_set(void *data, u64 val)
9228c2ecf20Sopenharmony_ci{
9238c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
9248c2ecf20Sopenharmony_ci
9258c2ecf20Sopenharmony_ci	if (val < 0x01 || val > 0x07)
9268c2ecf20Sopenharmony_ci		return -EINVAL;
9278c2ecf20Sopenharmony_ci
9288c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
9298c2ecf20Sopenharmony_ci	hdev->le_adv_channel_map = val;
9308c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
9318c2ecf20Sopenharmony_ci
9328c2ecf20Sopenharmony_ci	return 0;
9338c2ecf20Sopenharmony_ci}
9348c2ecf20Sopenharmony_ci
9358c2ecf20Sopenharmony_cistatic int adv_channel_map_get(void *data, u64 *val)
9368c2ecf20Sopenharmony_ci{
9378c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
9388c2ecf20Sopenharmony_ci
9398c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
9408c2ecf20Sopenharmony_ci	*val = hdev->le_adv_channel_map;
9418c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
9428c2ecf20Sopenharmony_ci
9438c2ecf20Sopenharmony_ci	return 0;
9448c2ecf20Sopenharmony_ci}
9458c2ecf20Sopenharmony_ci
9468c2ecf20Sopenharmony_ciDEFINE_SIMPLE_ATTRIBUTE(adv_channel_map_fops, adv_channel_map_get,
9478c2ecf20Sopenharmony_ci			adv_channel_map_set, "%llu\n");
9488c2ecf20Sopenharmony_ci
9498c2ecf20Sopenharmony_cistatic int adv_min_interval_set(void *data, u64 val)
9508c2ecf20Sopenharmony_ci{
9518c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
9528c2ecf20Sopenharmony_ci
9538c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
9548c2ecf20Sopenharmony_ci	if (val < 0x0020 || val > 0x4000 || val > hdev->le_adv_max_interval) {
9558c2ecf20Sopenharmony_ci		hci_dev_unlock(hdev);
9568c2ecf20Sopenharmony_ci		return -EINVAL;
9578c2ecf20Sopenharmony_ci	}
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_ci	hdev->le_adv_min_interval = val;
9608c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
9618c2ecf20Sopenharmony_ci
9628c2ecf20Sopenharmony_ci	return 0;
9638c2ecf20Sopenharmony_ci}
9648c2ecf20Sopenharmony_ci
9658c2ecf20Sopenharmony_cistatic int adv_min_interval_get(void *data, u64 *val)
9668c2ecf20Sopenharmony_ci{
9678c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
9688c2ecf20Sopenharmony_ci
9698c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
9708c2ecf20Sopenharmony_ci	*val = hdev->le_adv_min_interval;
9718c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
9728c2ecf20Sopenharmony_ci
9738c2ecf20Sopenharmony_ci	return 0;
9748c2ecf20Sopenharmony_ci}
9758c2ecf20Sopenharmony_ci
9768c2ecf20Sopenharmony_ciDEFINE_SIMPLE_ATTRIBUTE(adv_min_interval_fops, adv_min_interval_get,
9778c2ecf20Sopenharmony_ci			adv_min_interval_set, "%llu\n");
9788c2ecf20Sopenharmony_ci
9798c2ecf20Sopenharmony_cistatic int adv_max_interval_set(void *data, u64 val)
9808c2ecf20Sopenharmony_ci{
9818c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
9828c2ecf20Sopenharmony_ci
9838c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
9848c2ecf20Sopenharmony_ci	if (val < 0x0020 || val > 0x4000 || val < hdev->le_adv_min_interval) {
9858c2ecf20Sopenharmony_ci		hci_dev_unlock(hdev);
9868c2ecf20Sopenharmony_ci		return -EINVAL;
9878c2ecf20Sopenharmony_ci	}
9888c2ecf20Sopenharmony_ci
9898c2ecf20Sopenharmony_ci	hdev->le_adv_max_interval = val;
9908c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
9918c2ecf20Sopenharmony_ci
9928c2ecf20Sopenharmony_ci	return 0;
9938c2ecf20Sopenharmony_ci}
9948c2ecf20Sopenharmony_ci
9958c2ecf20Sopenharmony_cistatic int adv_max_interval_get(void *data, u64 *val)
9968c2ecf20Sopenharmony_ci{
9978c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
9988c2ecf20Sopenharmony_ci
9998c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
10008c2ecf20Sopenharmony_ci	*val = hdev->le_adv_max_interval;
10018c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
10028c2ecf20Sopenharmony_ci
10038c2ecf20Sopenharmony_ci	return 0;
10048c2ecf20Sopenharmony_ci}
10058c2ecf20Sopenharmony_ci
10068c2ecf20Sopenharmony_ciDEFINE_SIMPLE_ATTRIBUTE(adv_max_interval_fops, adv_max_interval_get,
10078c2ecf20Sopenharmony_ci			adv_max_interval_set, "%llu\n");
10088c2ecf20Sopenharmony_ci
10098c2ecf20Sopenharmony_cistatic int min_key_size_set(void *data, u64 val)
10108c2ecf20Sopenharmony_ci{
10118c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
10128c2ecf20Sopenharmony_ci
10138c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
10148c2ecf20Sopenharmony_ci	if (val > hdev->le_max_key_size || val < SMP_MIN_ENC_KEY_SIZE) {
10158c2ecf20Sopenharmony_ci		hci_dev_unlock(hdev);
10168c2ecf20Sopenharmony_ci		return -EINVAL;
10178c2ecf20Sopenharmony_ci	}
10188c2ecf20Sopenharmony_ci
10198c2ecf20Sopenharmony_ci	hdev->le_min_key_size = val;
10208c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
10218c2ecf20Sopenharmony_ci
10228c2ecf20Sopenharmony_ci	return 0;
10238c2ecf20Sopenharmony_ci}
10248c2ecf20Sopenharmony_ci
10258c2ecf20Sopenharmony_cistatic int min_key_size_get(void *data, u64 *val)
10268c2ecf20Sopenharmony_ci{
10278c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
10288c2ecf20Sopenharmony_ci
10298c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
10308c2ecf20Sopenharmony_ci	*val = hdev->le_min_key_size;
10318c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
10328c2ecf20Sopenharmony_ci
10338c2ecf20Sopenharmony_ci	return 0;
10348c2ecf20Sopenharmony_ci}
10358c2ecf20Sopenharmony_ci
10368c2ecf20Sopenharmony_ciDEFINE_SIMPLE_ATTRIBUTE(min_key_size_fops, min_key_size_get,
10378c2ecf20Sopenharmony_ci			min_key_size_set, "%llu\n");
10388c2ecf20Sopenharmony_ci
10398c2ecf20Sopenharmony_cistatic int max_key_size_set(void *data, u64 val)
10408c2ecf20Sopenharmony_ci{
10418c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
10428c2ecf20Sopenharmony_ci
10438c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
10448c2ecf20Sopenharmony_ci	if (val > SMP_MAX_ENC_KEY_SIZE || val < hdev->le_min_key_size) {
10458c2ecf20Sopenharmony_ci		hci_dev_unlock(hdev);
10468c2ecf20Sopenharmony_ci		return -EINVAL;
10478c2ecf20Sopenharmony_ci	}
10488c2ecf20Sopenharmony_ci
10498c2ecf20Sopenharmony_ci	hdev->le_max_key_size = val;
10508c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
10518c2ecf20Sopenharmony_ci
10528c2ecf20Sopenharmony_ci	return 0;
10538c2ecf20Sopenharmony_ci}
10548c2ecf20Sopenharmony_ci
10558c2ecf20Sopenharmony_cistatic int max_key_size_get(void *data, u64 *val)
10568c2ecf20Sopenharmony_ci{
10578c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
10588c2ecf20Sopenharmony_ci
10598c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
10608c2ecf20Sopenharmony_ci	*val = hdev->le_max_key_size;
10618c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
10628c2ecf20Sopenharmony_ci
10638c2ecf20Sopenharmony_ci	return 0;
10648c2ecf20Sopenharmony_ci}
10658c2ecf20Sopenharmony_ci
10668c2ecf20Sopenharmony_ciDEFINE_SIMPLE_ATTRIBUTE(max_key_size_fops, max_key_size_get,
10678c2ecf20Sopenharmony_ci			max_key_size_set, "%llu\n");
10688c2ecf20Sopenharmony_ci
10698c2ecf20Sopenharmony_cistatic int auth_payload_timeout_set(void *data, u64 val)
10708c2ecf20Sopenharmony_ci{
10718c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
10728c2ecf20Sopenharmony_ci
10738c2ecf20Sopenharmony_ci	if (val < 0x0001 || val > 0xffff)
10748c2ecf20Sopenharmony_ci		return -EINVAL;
10758c2ecf20Sopenharmony_ci
10768c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
10778c2ecf20Sopenharmony_ci	hdev->auth_payload_timeout = val;
10788c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
10798c2ecf20Sopenharmony_ci
10808c2ecf20Sopenharmony_ci	return 0;
10818c2ecf20Sopenharmony_ci}
10828c2ecf20Sopenharmony_ci
10838c2ecf20Sopenharmony_cistatic int auth_payload_timeout_get(void *data, u64 *val)
10848c2ecf20Sopenharmony_ci{
10858c2ecf20Sopenharmony_ci	struct hci_dev *hdev = data;
10868c2ecf20Sopenharmony_ci
10878c2ecf20Sopenharmony_ci	hci_dev_lock(hdev);
10888c2ecf20Sopenharmony_ci	*val = hdev->auth_payload_timeout;
10898c2ecf20Sopenharmony_ci	hci_dev_unlock(hdev);
10908c2ecf20Sopenharmony_ci
10918c2ecf20Sopenharmony_ci	return 0;
10928c2ecf20Sopenharmony_ci}
10938c2ecf20Sopenharmony_ci
10948c2ecf20Sopenharmony_ciDEFINE_SIMPLE_ATTRIBUTE(auth_payload_timeout_fops,
10958c2ecf20Sopenharmony_ci			auth_payload_timeout_get,
10968c2ecf20Sopenharmony_ci			auth_payload_timeout_set, "%llu\n");
10978c2ecf20Sopenharmony_ci
10988c2ecf20Sopenharmony_cistatic ssize_t force_no_mitm_read(struct file *file,
10998c2ecf20Sopenharmony_ci				  char __user *user_buf,
11008c2ecf20Sopenharmony_ci				  size_t count, loff_t *ppos)
11018c2ecf20Sopenharmony_ci{
11028c2ecf20Sopenharmony_ci	struct hci_dev *hdev = file->private_data;
11038c2ecf20Sopenharmony_ci	char buf[3];
11048c2ecf20Sopenharmony_ci
11058c2ecf20Sopenharmony_ci	buf[0] = hci_dev_test_flag(hdev, HCI_FORCE_NO_MITM) ? 'Y' : 'N';
11068c2ecf20Sopenharmony_ci	buf[1] = '\n';
11078c2ecf20Sopenharmony_ci	buf[2] = '\0';
11088c2ecf20Sopenharmony_ci	return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
11098c2ecf20Sopenharmony_ci}
11108c2ecf20Sopenharmony_ci
11118c2ecf20Sopenharmony_cistatic ssize_t force_no_mitm_write(struct file *file,
11128c2ecf20Sopenharmony_ci				   const char __user *user_buf,
11138c2ecf20Sopenharmony_ci				   size_t count, loff_t *ppos)
11148c2ecf20Sopenharmony_ci{
11158c2ecf20Sopenharmony_ci	struct hci_dev *hdev = file->private_data;
11168c2ecf20Sopenharmony_ci	char buf[32];
11178c2ecf20Sopenharmony_ci	size_t buf_size = min(count, (sizeof(buf) - 1));
11188c2ecf20Sopenharmony_ci	bool enable;
11198c2ecf20Sopenharmony_ci
11208c2ecf20Sopenharmony_ci	if (copy_from_user(buf, user_buf, buf_size))
11218c2ecf20Sopenharmony_ci		return -EFAULT;
11228c2ecf20Sopenharmony_ci
11238c2ecf20Sopenharmony_ci	buf[buf_size] = '\0';
11248c2ecf20Sopenharmony_ci	if (strtobool(buf, &enable))
11258c2ecf20Sopenharmony_ci		return -EINVAL;
11268c2ecf20Sopenharmony_ci
11278c2ecf20Sopenharmony_ci	if (enable == hci_dev_test_flag(hdev, HCI_FORCE_NO_MITM))
11288c2ecf20Sopenharmony_ci		return -EALREADY;
11298c2ecf20Sopenharmony_ci
11308c2ecf20Sopenharmony_ci	hci_dev_change_flag(hdev, HCI_FORCE_NO_MITM);
11318c2ecf20Sopenharmony_ci
11328c2ecf20Sopenharmony_ci	return count;
11338c2ecf20Sopenharmony_ci}
11348c2ecf20Sopenharmony_ci
11358c2ecf20Sopenharmony_cistatic const struct file_operations force_no_mitm_fops = {
11368c2ecf20Sopenharmony_ci	.open		= simple_open,
11378c2ecf20Sopenharmony_ci	.read		= force_no_mitm_read,
11388c2ecf20Sopenharmony_ci	.write		= force_no_mitm_write,
11398c2ecf20Sopenharmony_ci	.llseek		= default_llseek,
11408c2ecf20Sopenharmony_ci};
11418c2ecf20Sopenharmony_ci
11428c2ecf20Sopenharmony_ciDEFINE_QUIRK_ATTRIBUTE(quirk_strict_duplicate_filter,
11438c2ecf20Sopenharmony_ci		       HCI_QUIRK_STRICT_DUPLICATE_FILTER);
11448c2ecf20Sopenharmony_ciDEFINE_QUIRK_ATTRIBUTE(quirk_simultaneous_discovery,
11458c2ecf20Sopenharmony_ci		       HCI_QUIRK_SIMULTANEOUS_DISCOVERY);
11468c2ecf20Sopenharmony_ci
11478c2ecf20Sopenharmony_civoid hci_debugfs_create_le(struct hci_dev *hdev)
11488c2ecf20Sopenharmony_ci{
11498c2ecf20Sopenharmony_ci	debugfs_create_file("identity", 0400, hdev->debugfs, hdev,
11508c2ecf20Sopenharmony_ci			    &identity_fops);
11518c2ecf20Sopenharmony_ci	debugfs_create_file("rpa_timeout", 0644, hdev->debugfs, hdev,
11528c2ecf20Sopenharmony_ci			    &rpa_timeout_fops);
11538c2ecf20Sopenharmony_ci	debugfs_create_file("random_address", 0444, hdev->debugfs, hdev,
11548c2ecf20Sopenharmony_ci			    &random_address_fops);
11558c2ecf20Sopenharmony_ci	debugfs_create_file("static_address", 0444, hdev->debugfs, hdev,
11568c2ecf20Sopenharmony_ci			    &static_address_fops);
11578c2ecf20Sopenharmony_ci
11588c2ecf20Sopenharmony_ci	/* For controllers with a public address, provide a debug
11598c2ecf20Sopenharmony_ci	 * option to force the usage of the configured static
11608c2ecf20Sopenharmony_ci	 * address. By default the public address is used.
11618c2ecf20Sopenharmony_ci	 */
11628c2ecf20Sopenharmony_ci	if (bacmp(&hdev->bdaddr, BDADDR_ANY))
11638c2ecf20Sopenharmony_ci		debugfs_create_file("force_static_address", 0644,
11648c2ecf20Sopenharmony_ci				    hdev->debugfs, hdev,
11658c2ecf20Sopenharmony_ci				    &force_static_address_fops);
11668c2ecf20Sopenharmony_ci
11678c2ecf20Sopenharmony_ci	debugfs_create_u8("white_list_size", 0444, hdev->debugfs,
11688c2ecf20Sopenharmony_ci			  &hdev->le_accept_list_size);
11698c2ecf20Sopenharmony_ci	debugfs_create_file("white_list", 0444, hdev->debugfs, hdev,
11708c2ecf20Sopenharmony_ci			    &white_list_fops);
11718c2ecf20Sopenharmony_ci	debugfs_create_u8("resolv_list_size", 0444, hdev->debugfs,
11728c2ecf20Sopenharmony_ci			  &hdev->le_resolv_list_size);
11738c2ecf20Sopenharmony_ci	debugfs_create_file("resolv_list", 0444, hdev->debugfs, hdev,
11748c2ecf20Sopenharmony_ci			    &resolv_list_fops);
11758c2ecf20Sopenharmony_ci	debugfs_create_file("identity_resolving_keys", 0400, hdev->debugfs,
11768c2ecf20Sopenharmony_ci			    hdev, &identity_resolving_keys_fops);
11778c2ecf20Sopenharmony_ci	debugfs_create_file("long_term_keys", 0400, hdev->debugfs, hdev,
11788c2ecf20Sopenharmony_ci			    &long_term_keys_fops);
11798c2ecf20Sopenharmony_ci	debugfs_create_file("conn_min_interval", 0644, hdev->debugfs, hdev,
11808c2ecf20Sopenharmony_ci			    &conn_min_interval_fops);
11818c2ecf20Sopenharmony_ci	debugfs_create_file("conn_max_interval", 0644, hdev->debugfs, hdev,
11828c2ecf20Sopenharmony_ci			    &conn_max_interval_fops);
11838c2ecf20Sopenharmony_ci	debugfs_create_file("conn_latency", 0644, hdev->debugfs, hdev,
11848c2ecf20Sopenharmony_ci			    &conn_latency_fops);
11858c2ecf20Sopenharmony_ci	debugfs_create_file("supervision_timeout", 0644, hdev->debugfs, hdev,
11868c2ecf20Sopenharmony_ci			    &supervision_timeout_fops);
11878c2ecf20Sopenharmony_ci	debugfs_create_file("adv_channel_map", 0644, hdev->debugfs, hdev,
11888c2ecf20Sopenharmony_ci			    &adv_channel_map_fops);
11898c2ecf20Sopenharmony_ci	debugfs_create_file("adv_min_interval", 0644, hdev->debugfs, hdev,
11908c2ecf20Sopenharmony_ci			    &adv_min_interval_fops);
11918c2ecf20Sopenharmony_ci	debugfs_create_file("adv_max_interval", 0644, hdev->debugfs, hdev,
11928c2ecf20Sopenharmony_ci			    &adv_max_interval_fops);
11938c2ecf20Sopenharmony_ci	debugfs_create_u16("discov_interleaved_timeout", 0644, hdev->debugfs,
11948c2ecf20Sopenharmony_ci			   &hdev->discov_interleaved_timeout);
11958c2ecf20Sopenharmony_ci	debugfs_create_file("min_key_size", 0644, hdev->debugfs, hdev,
11968c2ecf20Sopenharmony_ci			    &min_key_size_fops);
11978c2ecf20Sopenharmony_ci	debugfs_create_file("max_key_size", 0644, hdev->debugfs, hdev,
11988c2ecf20Sopenharmony_ci			    &max_key_size_fops);
11998c2ecf20Sopenharmony_ci	debugfs_create_file("auth_payload_timeout", 0644, hdev->debugfs, hdev,
12008c2ecf20Sopenharmony_ci			    &auth_payload_timeout_fops);
12018c2ecf20Sopenharmony_ci	debugfs_create_file("force_no_mitm", 0644, hdev->debugfs, hdev,
12028c2ecf20Sopenharmony_ci			    &force_no_mitm_fops);
12038c2ecf20Sopenharmony_ci
12048c2ecf20Sopenharmony_ci	debugfs_create_file("quirk_strict_duplicate_filter", 0644,
12058c2ecf20Sopenharmony_ci			    hdev->debugfs, hdev,
12068c2ecf20Sopenharmony_ci			    &quirk_strict_duplicate_filter_fops);
12078c2ecf20Sopenharmony_ci	debugfs_create_file("quirk_simultaneous_discovery", 0644,
12088c2ecf20Sopenharmony_ci			    hdev->debugfs, hdev,
12098c2ecf20Sopenharmony_ci			    &quirk_simultaneous_discovery_fops);
12108c2ecf20Sopenharmony_ci}
12118c2ecf20Sopenharmony_ci
12128c2ecf20Sopenharmony_civoid hci_debugfs_create_conn(struct hci_conn *conn)
12138c2ecf20Sopenharmony_ci{
12148c2ecf20Sopenharmony_ci	struct hci_dev *hdev = conn->hdev;
12158c2ecf20Sopenharmony_ci	char name[6];
12168c2ecf20Sopenharmony_ci
12178c2ecf20Sopenharmony_ci	if (IS_ERR_OR_NULL(hdev->debugfs))
12188c2ecf20Sopenharmony_ci		return;
12198c2ecf20Sopenharmony_ci
12208c2ecf20Sopenharmony_ci	snprintf(name, sizeof(name), "%u", conn->handle);
12218c2ecf20Sopenharmony_ci	conn->debugfs = debugfs_create_dir(name, hdev->debugfs);
12228c2ecf20Sopenharmony_ci}
1223