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 <k->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