18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci BlueZ - Bluetooth protocol stack for Linux 38c2ecf20Sopenharmony_ci Copyright (C) 2000-2001 Qualcomm Incorporated 48c2ecf20Sopenharmony_ci Copyright (C) 2011 ProFUSION Embedded Systems 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci This program is free software; you can redistribute it and/or modify 98c2ecf20Sopenharmony_ci it under the terms of the GNU General Public License version 2 as 108c2ecf20Sopenharmony_ci published by the Free Software Foundation; 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 138c2ecf20Sopenharmony_ci OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 148c2ecf20Sopenharmony_ci FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 158c2ecf20Sopenharmony_ci IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 168c2ecf20Sopenharmony_ci CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 178c2ecf20Sopenharmony_ci WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 188c2ecf20Sopenharmony_ci ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 198c2ecf20Sopenharmony_ci OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 228c2ecf20Sopenharmony_ci COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 238c2ecf20Sopenharmony_ci SOFTWARE IS DISCLAIMED. 248c2ecf20Sopenharmony_ci*/ 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci/* Bluetooth HCI core. */ 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#include <linux/export.h> 298c2ecf20Sopenharmony_ci#include <linux/rfkill.h> 308c2ecf20Sopenharmony_ci#include <linux/debugfs.h> 318c2ecf20Sopenharmony_ci#include <linux/crypto.h> 328c2ecf20Sopenharmony_ci#include <linux/property.h> 338c2ecf20Sopenharmony_ci#include <linux/suspend.h> 348c2ecf20Sopenharmony_ci#include <linux/wait.h> 358c2ecf20Sopenharmony_ci#include <asm/unaligned.h> 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci#include <net/bluetooth/bluetooth.h> 388c2ecf20Sopenharmony_ci#include <net/bluetooth/hci_core.h> 398c2ecf20Sopenharmony_ci#include <net/bluetooth/l2cap.h> 408c2ecf20Sopenharmony_ci#include <net/bluetooth/mgmt.h> 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci#include "hci_request.h" 438c2ecf20Sopenharmony_ci#include "hci_debugfs.h" 448c2ecf20Sopenharmony_ci#include "smp.h" 458c2ecf20Sopenharmony_ci#include "leds.h" 468c2ecf20Sopenharmony_ci#include "msft.h" 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_cistatic void hci_rx_work(struct work_struct *work); 498c2ecf20Sopenharmony_cistatic void hci_cmd_work(struct work_struct *work); 508c2ecf20Sopenharmony_cistatic void hci_tx_work(struct work_struct *work); 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci/* HCI device list */ 538c2ecf20Sopenharmony_ciLIST_HEAD(hci_dev_list); 548c2ecf20Sopenharmony_ciDEFINE_RWLOCK(hci_dev_list_lock); 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci/* HCI callback list */ 578c2ecf20Sopenharmony_ciLIST_HEAD(hci_cb_list); 588c2ecf20Sopenharmony_ciDEFINE_MUTEX(hci_cb_list_lock); 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci/* HCI ID Numbering */ 618c2ecf20Sopenharmony_cistatic DEFINE_IDA(hci_index_ida); 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci/* ---- HCI debugfs entries ---- */ 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_cistatic ssize_t dut_mode_read(struct file *file, char __user *user_buf, 668c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 678c2ecf20Sopenharmony_ci{ 688c2ecf20Sopenharmony_ci struct hci_dev *hdev = file->private_data; 698c2ecf20Sopenharmony_ci char buf[3]; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci buf[0] = hci_dev_test_flag(hdev, HCI_DUT_MODE) ? 'Y' : 'N'; 728c2ecf20Sopenharmony_ci buf[1] = '\n'; 738c2ecf20Sopenharmony_ci buf[2] = '\0'; 748c2ecf20Sopenharmony_ci return simple_read_from_buffer(user_buf, count, ppos, buf, 2); 758c2ecf20Sopenharmony_ci} 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_cistatic ssize_t dut_mode_write(struct file *file, const char __user *user_buf, 788c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 798c2ecf20Sopenharmony_ci{ 808c2ecf20Sopenharmony_ci struct hci_dev *hdev = file->private_data; 818c2ecf20Sopenharmony_ci struct sk_buff *skb; 828c2ecf20Sopenharmony_ci bool enable; 838c2ecf20Sopenharmony_ci int err; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci if (!test_bit(HCI_UP, &hdev->flags)) 868c2ecf20Sopenharmony_ci return -ENETDOWN; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci err = kstrtobool_from_user(user_buf, count, &enable); 898c2ecf20Sopenharmony_ci if (err) 908c2ecf20Sopenharmony_ci return err; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci if (enable == hci_dev_test_flag(hdev, HCI_DUT_MODE)) 938c2ecf20Sopenharmony_ci return -EALREADY; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci hci_req_sync_lock(hdev); 968c2ecf20Sopenharmony_ci if (enable) 978c2ecf20Sopenharmony_ci skb = __hci_cmd_sync(hdev, HCI_OP_ENABLE_DUT_MODE, 0, NULL, 988c2ecf20Sopenharmony_ci HCI_CMD_TIMEOUT); 998c2ecf20Sopenharmony_ci else 1008c2ecf20Sopenharmony_ci skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, 1018c2ecf20Sopenharmony_ci HCI_CMD_TIMEOUT); 1028c2ecf20Sopenharmony_ci hci_req_sync_unlock(hdev); 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci if (IS_ERR(skb)) 1058c2ecf20Sopenharmony_ci return PTR_ERR(skb); 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci kfree_skb(skb); 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci hci_dev_change_flag(hdev, HCI_DUT_MODE); 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci return count; 1128c2ecf20Sopenharmony_ci} 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_cistatic const struct file_operations dut_mode_fops = { 1158c2ecf20Sopenharmony_ci .open = simple_open, 1168c2ecf20Sopenharmony_ci .read = dut_mode_read, 1178c2ecf20Sopenharmony_ci .write = dut_mode_write, 1188c2ecf20Sopenharmony_ci .llseek = default_llseek, 1198c2ecf20Sopenharmony_ci}; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_cistatic ssize_t vendor_diag_read(struct file *file, char __user *user_buf, 1228c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 1238c2ecf20Sopenharmony_ci{ 1248c2ecf20Sopenharmony_ci struct hci_dev *hdev = file->private_data; 1258c2ecf20Sopenharmony_ci char buf[3]; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci buf[0] = hci_dev_test_flag(hdev, HCI_VENDOR_DIAG) ? 'Y' : 'N'; 1288c2ecf20Sopenharmony_ci buf[1] = '\n'; 1298c2ecf20Sopenharmony_ci buf[2] = '\0'; 1308c2ecf20Sopenharmony_ci return simple_read_from_buffer(user_buf, count, ppos, buf, 2); 1318c2ecf20Sopenharmony_ci} 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_cistatic ssize_t vendor_diag_write(struct file *file, const char __user *user_buf, 1348c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 1358c2ecf20Sopenharmony_ci{ 1368c2ecf20Sopenharmony_ci struct hci_dev *hdev = file->private_data; 1378c2ecf20Sopenharmony_ci bool enable; 1388c2ecf20Sopenharmony_ci int err; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci err = kstrtobool_from_user(user_buf, count, &enable); 1418c2ecf20Sopenharmony_ci if (err) 1428c2ecf20Sopenharmony_ci return err; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci /* When the diagnostic flags are not persistent and the transport 1458c2ecf20Sopenharmony_ci * is not active or in user channel operation, then there is no need 1468c2ecf20Sopenharmony_ci * for the vendor callback. Instead just store the desired value and 1478c2ecf20Sopenharmony_ci * the setting will be programmed when the controller gets powered on. 1488c2ecf20Sopenharmony_ci */ 1498c2ecf20Sopenharmony_ci if (test_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks) && 1508c2ecf20Sopenharmony_ci (!test_bit(HCI_RUNNING, &hdev->flags) || 1518c2ecf20Sopenharmony_ci hci_dev_test_flag(hdev, HCI_USER_CHANNEL))) 1528c2ecf20Sopenharmony_ci goto done; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci hci_req_sync_lock(hdev); 1558c2ecf20Sopenharmony_ci err = hdev->set_diag(hdev, enable); 1568c2ecf20Sopenharmony_ci hci_req_sync_unlock(hdev); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci if (err < 0) 1598c2ecf20Sopenharmony_ci return err; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_cidone: 1628c2ecf20Sopenharmony_ci if (enable) 1638c2ecf20Sopenharmony_ci hci_dev_set_flag(hdev, HCI_VENDOR_DIAG); 1648c2ecf20Sopenharmony_ci else 1658c2ecf20Sopenharmony_ci hci_dev_clear_flag(hdev, HCI_VENDOR_DIAG); 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci return count; 1688c2ecf20Sopenharmony_ci} 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_cistatic const struct file_operations vendor_diag_fops = { 1718c2ecf20Sopenharmony_ci .open = simple_open, 1728c2ecf20Sopenharmony_ci .read = vendor_diag_read, 1738c2ecf20Sopenharmony_ci .write = vendor_diag_write, 1748c2ecf20Sopenharmony_ci .llseek = default_llseek, 1758c2ecf20Sopenharmony_ci}; 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_cistatic void hci_debugfs_create_basic(struct hci_dev *hdev) 1788c2ecf20Sopenharmony_ci{ 1798c2ecf20Sopenharmony_ci debugfs_create_file("dut_mode", 0644, hdev->debugfs, hdev, 1808c2ecf20Sopenharmony_ci &dut_mode_fops); 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci if (hdev->set_diag) 1838c2ecf20Sopenharmony_ci debugfs_create_file("vendor_diag", 0644, hdev->debugfs, hdev, 1848c2ecf20Sopenharmony_ci &vendor_diag_fops); 1858c2ecf20Sopenharmony_ci} 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_cistatic int hci_reset_req(struct hci_request *req, unsigned long opt) 1888c2ecf20Sopenharmony_ci{ 1898c2ecf20Sopenharmony_ci BT_DBG("%s %ld", req->hdev->name, opt); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci /* Reset device */ 1928c2ecf20Sopenharmony_ci set_bit(HCI_RESET, &req->hdev->flags); 1938c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_RESET, 0, NULL); 1948c2ecf20Sopenharmony_ci return 0; 1958c2ecf20Sopenharmony_ci} 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_cistatic void bredr_init(struct hci_request *req) 1988c2ecf20Sopenharmony_ci{ 1998c2ecf20Sopenharmony_ci req->hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_PACKET_BASED; 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci /* Read Local Supported Features */ 2028c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_READ_LOCAL_FEATURES, 0, NULL); 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci /* Read Local Version */ 2058c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_READ_LOCAL_VERSION, 0, NULL); 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci /* Read BD Address */ 2088c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_READ_BD_ADDR, 0, NULL); 2098c2ecf20Sopenharmony_ci} 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_cistatic void amp_init1(struct hci_request *req) 2128c2ecf20Sopenharmony_ci{ 2138c2ecf20Sopenharmony_ci req->hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_BLOCK_BASED; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci /* Read Local Version */ 2168c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_READ_LOCAL_VERSION, 0, NULL); 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci /* Read Local Supported Commands */ 2198c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci /* Read Local AMP Info */ 2228c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL); 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci /* Read Data Blk size */ 2258c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_READ_DATA_BLOCK_SIZE, 0, NULL); 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci /* Read Flow Control Mode */ 2288c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_READ_FLOW_CONTROL_MODE, 0, NULL); 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci /* Read Location Data */ 2318c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_READ_LOCATION_DATA, 0, NULL); 2328c2ecf20Sopenharmony_ci} 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_cistatic int amp_init2(struct hci_request *req) 2358c2ecf20Sopenharmony_ci{ 2368c2ecf20Sopenharmony_ci /* Read Local Supported Features. Not all AMP controllers 2378c2ecf20Sopenharmony_ci * support this so it's placed conditionally in the second 2388c2ecf20Sopenharmony_ci * stage init. 2398c2ecf20Sopenharmony_ci */ 2408c2ecf20Sopenharmony_ci if (req->hdev->commands[14] & 0x20) 2418c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_READ_LOCAL_FEATURES, 0, NULL); 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci return 0; 2448c2ecf20Sopenharmony_ci} 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_cistatic int hci_init1_req(struct hci_request *req, unsigned long opt) 2478c2ecf20Sopenharmony_ci{ 2488c2ecf20Sopenharmony_ci struct hci_dev *hdev = req->hdev; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci BT_DBG("%s %ld", hdev->name, opt); 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci /* Reset */ 2538c2ecf20Sopenharmony_ci if (!test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks)) 2548c2ecf20Sopenharmony_ci hci_reset_req(req, 0); 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci switch (hdev->dev_type) { 2578c2ecf20Sopenharmony_ci case HCI_PRIMARY: 2588c2ecf20Sopenharmony_ci bredr_init(req); 2598c2ecf20Sopenharmony_ci break; 2608c2ecf20Sopenharmony_ci case HCI_AMP: 2618c2ecf20Sopenharmony_ci amp_init1(req); 2628c2ecf20Sopenharmony_ci break; 2638c2ecf20Sopenharmony_ci default: 2648c2ecf20Sopenharmony_ci bt_dev_err(hdev, "Unknown device type %d", hdev->dev_type); 2658c2ecf20Sopenharmony_ci break; 2668c2ecf20Sopenharmony_ci } 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci return 0; 2698c2ecf20Sopenharmony_ci} 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_cistatic void bredr_setup(struct hci_request *req) 2728c2ecf20Sopenharmony_ci{ 2738c2ecf20Sopenharmony_ci __le16 param; 2748c2ecf20Sopenharmony_ci __u8 flt_type; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci /* Read Buffer Size (ACL mtu, max pkt, etc.) */ 2778c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_READ_BUFFER_SIZE, 0, NULL); 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci /* Read Class of Device */ 2808c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_READ_CLASS_OF_DEV, 0, NULL); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci /* Read Local Name */ 2838c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_READ_LOCAL_NAME, 0, NULL); 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci /* Read Voice Setting */ 2868c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_READ_VOICE_SETTING, 0, NULL); 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci /* Read Number of Supported IAC */ 2898c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_READ_NUM_SUPPORTED_IAC, 0, NULL); 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci /* Read Current IAC LAP */ 2928c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_READ_CURRENT_IAC_LAP, 0, NULL); 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci /* Clear Event Filters */ 2958c2ecf20Sopenharmony_ci flt_type = HCI_FLT_CLEAR_ALL; 2968c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_SET_EVENT_FLT, 1, &flt_type); 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci /* Connection accept timeout ~20 secs */ 2998c2ecf20Sopenharmony_ci param = cpu_to_le16(0x7d00); 3008c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m); 3018c2ecf20Sopenharmony_ci} 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_cistatic void le_setup(struct hci_request *req) 3048c2ecf20Sopenharmony_ci{ 3058c2ecf20Sopenharmony_ci struct hci_dev *hdev = req->hdev; 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci /* Read LE Buffer Size */ 3088c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL); 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci /* Read LE Local Supported Features */ 3118c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_LE_READ_LOCAL_FEATURES, 0, NULL); 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci /* Read LE Supported States */ 3148c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_LE_READ_SUPPORTED_STATES, 0, NULL); 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci /* LE-only controllers have LE implicitly enabled */ 3178c2ecf20Sopenharmony_ci if (!lmp_bredr_capable(hdev)) 3188c2ecf20Sopenharmony_ci hci_dev_set_flag(hdev, HCI_LE_ENABLED); 3198c2ecf20Sopenharmony_ci} 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_cistatic void hci_setup_event_mask(struct hci_request *req) 3228c2ecf20Sopenharmony_ci{ 3238c2ecf20Sopenharmony_ci struct hci_dev *hdev = req->hdev; 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci /* The second byte is 0xff instead of 0x9f (two reserved bits 3268c2ecf20Sopenharmony_ci * disabled) since a Broadcom 1.2 dongle doesn't respond to the 3278c2ecf20Sopenharmony_ci * command otherwise. 3288c2ecf20Sopenharmony_ci */ 3298c2ecf20Sopenharmony_ci u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 }; 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci /* CSR 1.1 dongles does not accept any bitfield so don't try to set 3328c2ecf20Sopenharmony_ci * any event mask for pre 1.2 devices. 3338c2ecf20Sopenharmony_ci */ 3348c2ecf20Sopenharmony_ci if (hdev->hci_ver < BLUETOOTH_VER_1_2) 3358c2ecf20Sopenharmony_ci return; 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci if (lmp_bredr_capable(hdev)) { 3388c2ecf20Sopenharmony_ci events[4] |= 0x01; /* Flow Specification Complete */ 3398c2ecf20Sopenharmony_ci } else { 3408c2ecf20Sopenharmony_ci /* Use a different default for LE-only devices */ 3418c2ecf20Sopenharmony_ci memset(events, 0, sizeof(events)); 3428c2ecf20Sopenharmony_ci events[1] |= 0x20; /* Command Complete */ 3438c2ecf20Sopenharmony_ci events[1] |= 0x40; /* Command Status */ 3448c2ecf20Sopenharmony_ci events[1] |= 0x80; /* Hardware Error */ 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci /* If the controller supports the Disconnect command, enable 3478c2ecf20Sopenharmony_ci * the corresponding event. In addition enable packet flow 3488c2ecf20Sopenharmony_ci * control related events. 3498c2ecf20Sopenharmony_ci */ 3508c2ecf20Sopenharmony_ci if (hdev->commands[0] & 0x20) { 3518c2ecf20Sopenharmony_ci events[0] |= 0x10; /* Disconnection Complete */ 3528c2ecf20Sopenharmony_ci events[2] |= 0x04; /* Number of Completed Packets */ 3538c2ecf20Sopenharmony_ci events[3] |= 0x02; /* Data Buffer Overflow */ 3548c2ecf20Sopenharmony_ci } 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci /* If the controller supports the Read Remote Version 3578c2ecf20Sopenharmony_ci * Information command, enable the corresponding event. 3588c2ecf20Sopenharmony_ci */ 3598c2ecf20Sopenharmony_ci if (hdev->commands[2] & 0x80) 3608c2ecf20Sopenharmony_ci events[1] |= 0x08; /* Read Remote Version Information 3618c2ecf20Sopenharmony_ci * Complete 3628c2ecf20Sopenharmony_ci */ 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci if (hdev->le_features[0] & HCI_LE_ENCRYPTION) { 3658c2ecf20Sopenharmony_ci events[0] |= 0x80; /* Encryption Change */ 3668c2ecf20Sopenharmony_ci events[5] |= 0x80; /* Encryption Key Refresh Complete */ 3678c2ecf20Sopenharmony_ci } 3688c2ecf20Sopenharmony_ci } 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci if (lmp_inq_rssi_capable(hdev) || 3718c2ecf20Sopenharmony_ci test_bit(HCI_QUIRK_FIXUP_INQUIRY_MODE, &hdev->quirks)) 3728c2ecf20Sopenharmony_ci events[4] |= 0x02; /* Inquiry Result with RSSI */ 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci if (lmp_ext_feat_capable(hdev)) 3758c2ecf20Sopenharmony_ci events[4] |= 0x04; /* Read Remote Extended Features Complete */ 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci if (lmp_esco_capable(hdev)) { 3788c2ecf20Sopenharmony_ci events[5] |= 0x08; /* Synchronous Connection Complete */ 3798c2ecf20Sopenharmony_ci events[5] |= 0x10; /* Synchronous Connection Changed */ 3808c2ecf20Sopenharmony_ci } 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci if (lmp_sniffsubr_capable(hdev)) 3838c2ecf20Sopenharmony_ci events[5] |= 0x20; /* Sniff Subrating */ 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci if (lmp_pause_enc_capable(hdev)) 3868c2ecf20Sopenharmony_ci events[5] |= 0x80; /* Encryption Key Refresh Complete */ 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci if (lmp_ext_inq_capable(hdev)) 3898c2ecf20Sopenharmony_ci events[5] |= 0x40; /* Extended Inquiry Result */ 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci if (lmp_no_flush_capable(hdev)) 3928c2ecf20Sopenharmony_ci events[7] |= 0x01; /* Enhanced Flush Complete */ 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci if (lmp_lsto_capable(hdev)) 3958c2ecf20Sopenharmony_ci events[6] |= 0x80; /* Link Supervision Timeout Changed */ 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci if (lmp_ssp_capable(hdev)) { 3988c2ecf20Sopenharmony_ci events[6] |= 0x01; /* IO Capability Request */ 3998c2ecf20Sopenharmony_ci events[6] |= 0x02; /* IO Capability Response */ 4008c2ecf20Sopenharmony_ci events[6] |= 0x04; /* User Confirmation Request */ 4018c2ecf20Sopenharmony_ci events[6] |= 0x08; /* User Passkey Request */ 4028c2ecf20Sopenharmony_ci events[6] |= 0x10; /* Remote OOB Data Request */ 4038c2ecf20Sopenharmony_ci events[6] |= 0x20; /* Simple Pairing Complete */ 4048c2ecf20Sopenharmony_ci events[7] |= 0x04; /* User Passkey Notification */ 4058c2ecf20Sopenharmony_ci events[7] |= 0x08; /* Keypress Notification */ 4068c2ecf20Sopenharmony_ci events[7] |= 0x10; /* Remote Host Supported 4078c2ecf20Sopenharmony_ci * Features Notification 4088c2ecf20Sopenharmony_ci */ 4098c2ecf20Sopenharmony_ci } 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci if (lmp_le_capable(hdev)) 4128c2ecf20Sopenharmony_ci events[7] |= 0x20; /* LE Meta-Event */ 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_SET_EVENT_MASK, sizeof(events), events); 4158c2ecf20Sopenharmony_ci} 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_cistatic int hci_init2_req(struct hci_request *req, unsigned long opt) 4188c2ecf20Sopenharmony_ci{ 4198c2ecf20Sopenharmony_ci struct hci_dev *hdev = req->hdev; 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci if (hdev->dev_type == HCI_AMP) 4228c2ecf20Sopenharmony_ci return amp_init2(req); 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci if (lmp_bredr_capable(hdev)) 4258c2ecf20Sopenharmony_ci bredr_setup(req); 4268c2ecf20Sopenharmony_ci else 4278c2ecf20Sopenharmony_ci hci_dev_clear_flag(hdev, HCI_BREDR_ENABLED); 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci if (lmp_le_capable(hdev)) 4308c2ecf20Sopenharmony_ci le_setup(req); 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci /* All Bluetooth 1.2 and later controllers should support the 4338c2ecf20Sopenharmony_ci * HCI command for reading the local supported commands. 4348c2ecf20Sopenharmony_ci * 4358c2ecf20Sopenharmony_ci * Unfortunately some controllers indicate Bluetooth 1.2 support, 4368c2ecf20Sopenharmony_ci * but do not have support for this command. If that is the case, 4378c2ecf20Sopenharmony_ci * the driver can quirk the behavior and skip reading the local 4388c2ecf20Sopenharmony_ci * supported commands. 4398c2ecf20Sopenharmony_ci */ 4408c2ecf20Sopenharmony_ci if (hdev->hci_ver > BLUETOOTH_VER_1_1 && 4418c2ecf20Sopenharmony_ci !test_bit(HCI_QUIRK_BROKEN_LOCAL_COMMANDS, &hdev->quirks)) 4428c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci if (lmp_ssp_capable(hdev)) { 4458c2ecf20Sopenharmony_ci /* When SSP is available, then the host features page 4468c2ecf20Sopenharmony_ci * should also be available as well. However some 4478c2ecf20Sopenharmony_ci * controllers list the max_page as 0 as long as SSP 4488c2ecf20Sopenharmony_ci * has not been enabled. To achieve proper debugging 4498c2ecf20Sopenharmony_ci * output, force the minimum max_page to 1 at least. 4508c2ecf20Sopenharmony_ci */ 4518c2ecf20Sopenharmony_ci hdev->max_page = 0x01; 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) { 4548c2ecf20Sopenharmony_ci u8 mode = 0x01; 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_WRITE_SSP_MODE, 4578c2ecf20Sopenharmony_ci sizeof(mode), &mode); 4588c2ecf20Sopenharmony_ci } else { 4598c2ecf20Sopenharmony_ci struct hci_cp_write_eir cp; 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci memset(hdev->eir, 0, sizeof(hdev->eir)); 4628c2ecf20Sopenharmony_ci memset(&cp, 0, sizeof(cp)); 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp); 4658c2ecf20Sopenharmony_ci } 4668c2ecf20Sopenharmony_ci } 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci if (lmp_inq_rssi_capable(hdev) || 4698c2ecf20Sopenharmony_ci test_bit(HCI_QUIRK_FIXUP_INQUIRY_MODE, &hdev->quirks)) { 4708c2ecf20Sopenharmony_ci u8 mode; 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci /* If Extended Inquiry Result events are supported, then 4738c2ecf20Sopenharmony_ci * they are clearly preferred over Inquiry Result with RSSI 4748c2ecf20Sopenharmony_ci * events. 4758c2ecf20Sopenharmony_ci */ 4768c2ecf20Sopenharmony_ci mode = lmp_ext_inq_capable(hdev) ? 0x02 : 0x01; 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode); 4798c2ecf20Sopenharmony_ci } 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci if (lmp_inq_tx_pwr_capable(hdev)) 4828c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL); 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci if (lmp_ext_feat_capable(hdev)) { 4858c2ecf20Sopenharmony_ci struct hci_cp_read_local_ext_features cp; 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci cp.page = 0x01; 4888c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_READ_LOCAL_EXT_FEATURES, 4898c2ecf20Sopenharmony_ci sizeof(cp), &cp); 4908c2ecf20Sopenharmony_ci } 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_LINK_SECURITY)) { 4938c2ecf20Sopenharmony_ci u8 enable = 1; 4948c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable), 4958c2ecf20Sopenharmony_ci &enable); 4968c2ecf20Sopenharmony_ci } 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci return 0; 4998c2ecf20Sopenharmony_ci} 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_cistatic void hci_setup_link_policy(struct hci_request *req) 5028c2ecf20Sopenharmony_ci{ 5038c2ecf20Sopenharmony_ci struct hci_dev *hdev = req->hdev; 5048c2ecf20Sopenharmony_ci struct hci_cp_write_def_link_policy cp; 5058c2ecf20Sopenharmony_ci u16 link_policy = 0; 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci if (lmp_rswitch_capable(hdev)) 5088c2ecf20Sopenharmony_ci link_policy |= HCI_LP_RSWITCH; 5098c2ecf20Sopenharmony_ci if (lmp_hold_capable(hdev)) 5108c2ecf20Sopenharmony_ci link_policy |= HCI_LP_HOLD; 5118c2ecf20Sopenharmony_ci if (lmp_sniff_capable(hdev)) 5128c2ecf20Sopenharmony_ci link_policy |= HCI_LP_SNIFF; 5138c2ecf20Sopenharmony_ci if (lmp_park_capable(hdev)) 5148c2ecf20Sopenharmony_ci link_policy |= HCI_LP_PARK; 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci cp.policy = cpu_to_le16(link_policy); 5178c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp); 5188c2ecf20Sopenharmony_ci} 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_cistatic void hci_set_le_support(struct hci_request *req) 5218c2ecf20Sopenharmony_ci{ 5228c2ecf20Sopenharmony_ci struct hci_dev *hdev = req->hdev; 5238c2ecf20Sopenharmony_ci struct hci_cp_write_le_host_supported cp; 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci /* LE-only devices do not support explicit enablement */ 5268c2ecf20Sopenharmony_ci if (!lmp_bredr_capable(hdev)) 5278c2ecf20Sopenharmony_ci return; 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci memset(&cp, 0, sizeof(cp)); 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) { 5328c2ecf20Sopenharmony_ci cp.le = 0x01; 5338c2ecf20Sopenharmony_ci cp.simul = 0x00; 5348c2ecf20Sopenharmony_ci } 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci if (cp.le != lmp_host_le_capable(hdev)) 5378c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), 5388c2ecf20Sopenharmony_ci &cp); 5398c2ecf20Sopenharmony_ci} 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_cistatic void hci_set_event_mask_page_2(struct hci_request *req) 5428c2ecf20Sopenharmony_ci{ 5438c2ecf20Sopenharmony_ci struct hci_dev *hdev = req->hdev; 5448c2ecf20Sopenharmony_ci u8 events[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 5458c2ecf20Sopenharmony_ci bool changed = false; 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci /* If Connectionless Slave Broadcast master role is supported 5488c2ecf20Sopenharmony_ci * enable all necessary events for it. 5498c2ecf20Sopenharmony_ci */ 5508c2ecf20Sopenharmony_ci if (lmp_csb_master_capable(hdev)) { 5518c2ecf20Sopenharmony_ci events[1] |= 0x40; /* Triggered Clock Capture */ 5528c2ecf20Sopenharmony_ci events[1] |= 0x80; /* Synchronization Train Complete */ 5538c2ecf20Sopenharmony_ci events[2] |= 0x10; /* Slave Page Response Timeout */ 5548c2ecf20Sopenharmony_ci events[2] |= 0x20; /* CSB Channel Map Change */ 5558c2ecf20Sopenharmony_ci changed = true; 5568c2ecf20Sopenharmony_ci } 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci /* If Connectionless Slave Broadcast slave role is supported 5598c2ecf20Sopenharmony_ci * enable all necessary events for it. 5608c2ecf20Sopenharmony_ci */ 5618c2ecf20Sopenharmony_ci if (lmp_csb_slave_capable(hdev)) { 5628c2ecf20Sopenharmony_ci events[2] |= 0x01; /* Synchronization Train Received */ 5638c2ecf20Sopenharmony_ci events[2] |= 0x02; /* CSB Receive */ 5648c2ecf20Sopenharmony_ci events[2] |= 0x04; /* CSB Timeout */ 5658c2ecf20Sopenharmony_ci events[2] |= 0x08; /* Truncated Page Complete */ 5668c2ecf20Sopenharmony_ci changed = true; 5678c2ecf20Sopenharmony_ci } 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci /* Enable Authenticated Payload Timeout Expired event if supported */ 5708c2ecf20Sopenharmony_ci if (lmp_ping_capable(hdev) || hdev->le_features[0] & HCI_LE_PING) { 5718c2ecf20Sopenharmony_ci events[2] |= 0x80; 5728c2ecf20Sopenharmony_ci changed = true; 5738c2ecf20Sopenharmony_ci } 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci /* Some Broadcom based controllers indicate support for Set Event 5768c2ecf20Sopenharmony_ci * Mask Page 2 command, but then actually do not support it. Since 5778c2ecf20Sopenharmony_ci * the default value is all bits set to zero, the command is only 5788c2ecf20Sopenharmony_ci * required if the event mask has to be changed. In case no change 5798c2ecf20Sopenharmony_ci * to the event mask is needed, skip this command. 5808c2ecf20Sopenharmony_ci */ 5818c2ecf20Sopenharmony_ci if (changed) 5828c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_SET_EVENT_MASK_PAGE_2, 5838c2ecf20Sopenharmony_ci sizeof(events), events); 5848c2ecf20Sopenharmony_ci} 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_cistatic int hci_init3_req(struct hci_request *req, unsigned long opt) 5878c2ecf20Sopenharmony_ci{ 5888c2ecf20Sopenharmony_ci struct hci_dev *hdev = req->hdev; 5898c2ecf20Sopenharmony_ci u8 p; 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci hci_setup_event_mask(req); 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci if (hdev->commands[6] & 0x20 && 5948c2ecf20Sopenharmony_ci !test_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks)) { 5958c2ecf20Sopenharmony_ci struct hci_cp_read_stored_link_key cp; 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_ci bacpy(&cp.bdaddr, BDADDR_ANY); 5988c2ecf20Sopenharmony_ci cp.read_all = 0x01; 5998c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_READ_STORED_LINK_KEY, sizeof(cp), &cp); 6008c2ecf20Sopenharmony_ci } 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci if (hdev->commands[5] & 0x10) 6038c2ecf20Sopenharmony_ci hci_setup_link_policy(req); 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci if (hdev->commands[8] & 0x01) 6068c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_READ_PAGE_SCAN_ACTIVITY, 0, NULL); 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci if (hdev->commands[18] & 0x04 && 6098c2ecf20Sopenharmony_ci !test_bit(HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, &hdev->quirks)) 6108c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_READ_DEF_ERR_DATA_REPORTING, 0, NULL); 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci /* Some older Broadcom based Bluetooth 1.2 controllers do not 6138c2ecf20Sopenharmony_ci * support the Read Page Scan Type command. Check support for 6148c2ecf20Sopenharmony_ci * this command in the bit mask of supported commands. 6158c2ecf20Sopenharmony_ci */ 6168c2ecf20Sopenharmony_ci if (hdev->commands[13] & 0x01) 6178c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_READ_PAGE_SCAN_TYPE, 0, NULL); 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci if (lmp_le_capable(hdev)) { 6208c2ecf20Sopenharmony_ci u8 events[8]; 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci memset(events, 0, sizeof(events)); 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_ci if (hdev->le_features[0] & HCI_LE_ENCRYPTION) 6258c2ecf20Sopenharmony_ci events[0] |= 0x10; /* LE Long Term Key Request */ 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci /* If controller supports the Connection Parameters Request 6288c2ecf20Sopenharmony_ci * Link Layer Procedure, enable the corresponding event. 6298c2ecf20Sopenharmony_ci */ 6308c2ecf20Sopenharmony_ci if (hdev->le_features[0] & HCI_LE_CONN_PARAM_REQ_PROC) 6318c2ecf20Sopenharmony_ci events[0] |= 0x20; /* LE Remote Connection 6328c2ecf20Sopenharmony_ci * Parameter Request 6338c2ecf20Sopenharmony_ci */ 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci /* If the controller supports the Data Length Extension 6368c2ecf20Sopenharmony_ci * feature, enable the corresponding event. 6378c2ecf20Sopenharmony_ci */ 6388c2ecf20Sopenharmony_ci if (hdev->le_features[0] & HCI_LE_DATA_LEN_EXT) 6398c2ecf20Sopenharmony_ci events[0] |= 0x40; /* LE Data Length Change */ 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci /* If the controller supports LL Privacy feature, enable 6428c2ecf20Sopenharmony_ci * the corresponding event. 6438c2ecf20Sopenharmony_ci */ 6448c2ecf20Sopenharmony_ci if (hdev->le_features[0] & HCI_LE_LL_PRIVACY) 6458c2ecf20Sopenharmony_ci events[1] |= 0x02; /* LE Enhanced Connection 6468c2ecf20Sopenharmony_ci * Complete 6478c2ecf20Sopenharmony_ci */ 6488c2ecf20Sopenharmony_ci 6498c2ecf20Sopenharmony_ci /* If the controller supports Extended Scanner Filter 6508c2ecf20Sopenharmony_ci * Policies, enable the correspondig event. 6518c2ecf20Sopenharmony_ci */ 6528c2ecf20Sopenharmony_ci if (hdev->le_features[0] & HCI_LE_EXT_SCAN_POLICY) 6538c2ecf20Sopenharmony_ci events[1] |= 0x04; /* LE Direct Advertising 6548c2ecf20Sopenharmony_ci * Report 6558c2ecf20Sopenharmony_ci */ 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci /* If the controller supports Channel Selection Algorithm #2 6588c2ecf20Sopenharmony_ci * feature, enable the corresponding event. 6598c2ecf20Sopenharmony_ci */ 6608c2ecf20Sopenharmony_ci if (hdev->le_features[1] & HCI_LE_CHAN_SEL_ALG2) 6618c2ecf20Sopenharmony_ci events[2] |= 0x08; /* LE Channel Selection 6628c2ecf20Sopenharmony_ci * Algorithm 6638c2ecf20Sopenharmony_ci */ 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci /* If the controller supports the LE Set Scan Enable command, 6668c2ecf20Sopenharmony_ci * enable the corresponding advertising report event. 6678c2ecf20Sopenharmony_ci */ 6688c2ecf20Sopenharmony_ci if (hdev->commands[26] & 0x08) 6698c2ecf20Sopenharmony_ci events[0] |= 0x02; /* LE Advertising Report */ 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_ci /* If the controller supports the LE Create Connection 6728c2ecf20Sopenharmony_ci * command, enable the corresponding event. 6738c2ecf20Sopenharmony_ci */ 6748c2ecf20Sopenharmony_ci if (hdev->commands[26] & 0x10) 6758c2ecf20Sopenharmony_ci events[0] |= 0x01; /* LE Connection Complete */ 6768c2ecf20Sopenharmony_ci 6778c2ecf20Sopenharmony_ci /* If the controller supports the LE Connection Update 6788c2ecf20Sopenharmony_ci * command, enable the corresponding event. 6798c2ecf20Sopenharmony_ci */ 6808c2ecf20Sopenharmony_ci if (hdev->commands[27] & 0x04) 6818c2ecf20Sopenharmony_ci events[0] |= 0x04; /* LE Connection Update 6828c2ecf20Sopenharmony_ci * Complete 6838c2ecf20Sopenharmony_ci */ 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci /* If the controller supports the LE Read Remote Used Features 6868c2ecf20Sopenharmony_ci * command, enable the corresponding event. 6878c2ecf20Sopenharmony_ci */ 6888c2ecf20Sopenharmony_ci if (hdev->commands[27] & 0x20) 6898c2ecf20Sopenharmony_ci events[0] |= 0x08; /* LE Read Remote Used 6908c2ecf20Sopenharmony_ci * Features Complete 6918c2ecf20Sopenharmony_ci */ 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ci /* If the controller supports the LE Read Local P-256 6948c2ecf20Sopenharmony_ci * Public Key command, enable the corresponding event. 6958c2ecf20Sopenharmony_ci */ 6968c2ecf20Sopenharmony_ci if (hdev->commands[34] & 0x02) 6978c2ecf20Sopenharmony_ci events[0] |= 0x80; /* LE Read Local P-256 6988c2ecf20Sopenharmony_ci * Public Key Complete 6998c2ecf20Sopenharmony_ci */ 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci /* If the controller supports the LE Generate DHKey 7028c2ecf20Sopenharmony_ci * command, enable the corresponding event. 7038c2ecf20Sopenharmony_ci */ 7048c2ecf20Sopenharmony_ci if (hdev->commands[34] & 0x04) 7058c2ecf20Sopenharmony_ci events[1] |= 0x01; /* LE Generate DHKey Complete */ 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_ci /* If the controller supports the LE Set Default PHY or 7088c2ecf20Sopenharmony_ci * LE Set PHY commands, enable the corresponding event. 7098c2ecf20Sopenharmony_ci */ 7108c2ecf20Sopenharmony_ci if (hdev->commands[35] & (0x20 | 0x40)) 7118c2ecf20Sopenharmony_ci events[1] |= 0x08; /* LE PHY Update Complete */ 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_ci /* If the controller supports LE Set Extended Scan Parameters 7148c2ecf20Sopenharmony_ci * and LE Set Extended Scan Enable commands, enable the 7158c2ecf20Sopenharmony_ci * corresponding event. 7168c2ecf20Sopenharmony_ci */ 7178c2ecf20Sopenharmony_ci if (use_ext_scan(hdev)) 7188c2ecf20Sopenharmony_ci events[1] |= 0x10; /* LE Extended Advertising 7198c2ecf20Sopenharmony_ci * Report 7208c2ecf20Sopenharmony_ci */ 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci /* If the controller supports the LE Extended Advertising 7238c2ecf20Sopenharmony_ci * command, enable the corresponding event. 7248c2ecf20Sopenharmony_ci */ 7258c2ecf20Sopenharmony_ci if (ext_adv_capable(hdev)) 7268c2ecf20Sopenharmony_ci events[2] |= 0x02; /* LE Advertising Set 7278c2ecf20Sopenharmony_ci * Terminated 7288c2ecf20Sopenharmony_ci */ 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_LE_SET_EVENT_MASK, sizeof(events), 7318c2ecf20Sopenharmony_ci events); 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci /* Read LE Advertising Channel TX Power */ 7348c2ecf20Sopenharmony_ci if ((hdev->commands[25] & 0x40) && !ext_adv_capable(hdev)) { 7358c2ecf20Sopenharmony_ci /* HCI TS spec forbids mixing of legacy and extended 7368c2ecf20Sopenharmony_ci * advertising commands wherein READ_ADV_TX_POWER is 7378c2ecf20Sopenharmony_ci * also included. So do not call it if extended adv 7388c2ecf20Sopenharmony_ci * is supported otherwise controller will return 7398c2ecf20Sopenharmony_ci * COMMAND_DISALLOWED for extended commands. 7408c2ecf20Sopenharmony_ci */ 7418c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL); 7428c2ecf20Sopenharmony_ci } 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_ci if (hdev->commands[26] & 0x40) { 7458c2ecf20Sopenharmony_ci /* Read LE Accept List Size */ 7468c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_LE_READ_ACCEPT_LIST_SIZE, 7478c2ecf20Sopenharmony_ci 0, NULL); 7488c2ecf20Sopenharmony_ci } 7498c2ecf20Sopenharmony_ci 7508c2ecf20Sopenharmony_ci if (hdev->commands[26] & 0x80) { 7518c2ecf20Sopenharmony_ci /* Clear LE Accept List */ 7528c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_LE_CLEAR_ACCEPT_LIST, 0, NULL); 7538c2ecf20Sopenharmony_ci } 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_ci if (hdev->commands[34] & 0x40) { 7568c2ecf20Sopenharmony_ci /* Read LE Resolving List Size */ 7578c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_LE_READ_RESOLV_LIST_SIZE, 7588c2ecf20Sopenharmony_ci 0, NULL); 7598c2ecf20Sopenharmony_ci } 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci if (hdev->commands[34] & 0x20) { 7628c2ecf20Sopenharmony_ci /* Clear LE Resolving List */ 7638c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_LE_CLEAR_RESOLV_LIST, 0, NULL); 7648c2ecf20Sopenharmony_ci } 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci if (hdev->commands[35] & 0x04) { 7678c2ecf20Sopenharmony_ci __le16 rpa_timeout = cpu_to_le16(hdev->rpa_timeout); 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci /* Set RPA timeout */ 7708c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_LE_SET_RPA_TIMEOUT, 2, 7718c2ecf20Sopenharmony_ci &rpa_timeout); 7728c2ecf20Sopenharmony_ci } 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_ci if (hdev->le_features[0] & HCI_LE_DATA_LEN_EXT) { 7758c2ecf20Sopenharmony_ci /* Read LE Maximum Data Length */ 7768c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_LE_READ_MAX_DATA_LEN, 0, NULL); 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_ci /* Read LE Suggested Default Data Length */ 7798c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_LE_READ_DEF_DATA_LEN, 0, NULL); 7808c2ecf20Sopenharmony_ci } 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_ci if (ext_adv_capable(hdev)) { 7838c2ecf20Sopenharmony_ci /* Read LE Number of Supported Advertising Sets */ 7848c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_LE_READ_NUM_SUPPORTED_ADV_SETS, 7858c2ecf20Sopenharmony_ci 0, NULL); 7868c2ecf20Sopenharmony_ci } 7878c2ecf20Sopenharmony_ci 7888c2ecf20Sopenharmony_ci hci_set_le_support(req); 7898c2ecf20Sopenharmony_ci } 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ci /* Read features beyond page 1 if available */ 7928c2ecf20Sopenharmony_ci for (p = 2; p < HCI_MAX_PAGES && p <= hdev->max_page; p++) { 7938c2ecf20Sopenharmony_ci struct hci_cp_read_local_ext_features cp; 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci cp.page = p; 7968c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_READ_LOCAL_EXT_FEATURES, 7978c2ecf20Sopenharmony_ci sizeof(cp), &cp); 7988c2ecf20Sopenharmony_ci } 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci return 0; 8018c2ecf20Sopenharmony_ci} 8028c2ecf20Sopenharmony_ci 8038c2ecf20Sopenharmony_cistatic int hci_init4_req(struct hci_request *req, unsigned long opt) 8048c2ecf20Sopenharmony_ci{ 8058c2ecf20Sopenharmony_ci struct hci_dev *hdev = req->hdev; 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci /* Some Broadcom based Bluetooth controllers do not support the 8088c2ecf20Sopenharmony_ci * Delete Stored Link Key command. They are clearly indicating its 8098c2ecf20Sopenharmony_ci * absence in the bit mask of supported commands. 8108c2ecf20Sopenharmony_ci * 8118c2ecf20Sopenharmony_ci * Check the supported commands and only if the command is marked 8128c2ecf20Sopenharmony_ci * as supported send it. If not supported assume that the controller 8138c2ecf20Sopenharmony_ci * does not have actual support for stored link keys which makes this 8148c2ecf20Sopenharmony_ci * command redundant anyway. 8158c2ecf20Sopenharmony_ci * 8168c2ecf20Sopenharmony_ci * Some controllers indicate that they support handling deleting 8178c2ecf20Sopenharmony_ci * stored link keys, but they don't. The quirk lets a driver 8188c2ecf20Sopenharmony_ci * just disable this command. 8198c2ecf20Sopenharmony_ci */ 8208c2ecf20Sopenharmony_ci if (hdev->commands[6] & 0x80 && 8218c2ecf20Sopenharmony_ci !test_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks)) { 8228c2ecf20Sopenharmony_ci struct hci_cp_delete_stored_link_key cp; 8238c2ecf20Sopenharmony_ci 8248c2ecf20Sopenharmony_ci bacpy(&cp.bdaddr, BDADDR_ANY); 8258c2ecf20Sopenharmony_ci cp.delete_all = 0x01; 8268c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_DELETE_STORED_LINK_KEY, 8278c2ecf20Sopenharmony_ci sizeof(cp), &cp); 8288c2ecf20Sopenharmony_ci } 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_ci /* Set event mask page 2 if the HCI command for it is supported */ 8318c2ecf20Sopenharmony_ci if (hdev->commands[22] & 0x04) 8328c2ecf20Sopenharmony_ci hci_set_event_mask_page_2(req); 8338c2ecf20Sopenharmony_ci 8348c2ecf20Sopenharmony_ci /* Read local codec list if the HCI command is supported */ 8358c2ecf20Sopenharmony_ci if (hdev->commands[29] & 0x20) 8368c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_READ_LOCAL_CODECS, 0, NULL); 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ci /* Read local pairing options if the HCI command is supported */ 8398c2ecf20Sopenharmony_ci if (hdev->commands[41] & 0x08) 8408c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_READ_LOCAL_PAIRING_OPTS, 0, NULL); 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_ci /* Get MWS transport configuration if the HCI command is supported */ 8438c2ecf20Sopenharmony_ci if (hdev->commands[30] & 0x08) 8448c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_GET_MWS_TRANSPORT_CONFIG, 0, NULL); 8458c2ecf20Sopenharmony_ci 8468c2ecf20Sopenharmony_ci /* Check for Synchronization Train support */ 8478c2ecf20Sopenharmony_ci if (lmp_sync_train_capable(hdev)) 8488c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_READ_SYNC_TRAIN_PARAMS, 0, NULL); 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_ci /* Enable Secure Connections if supported and configured */ 8518c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED) && 8528c2ecf20Sopenharmony_ci bredr_sc_enabled(hdev)) { 8538c2ecf20Sopenharmony_ci u8 support = 0x01; 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_WRITE_SC_SUPPORT, 8568c2ecf20Sopenharmony_ci sizeof(support), &support); 8578c2ecf20Sopenharmony_ci } 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci /* Set erroneous data reporting if supported to the wideband speech 8608c2ecf20Sopenharmony_ci * setting value 8618c2ecf20Sopenharmony_ci */ 8628c2ecf20Sopenharmony_ci if (hdev->commands[18] & 0x08 && 8638c2ecf20Sopenharmony_ci !test_bit(HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, &hdev->quirks)) { 8648c2ecf20Sopenharmony_ci bool enabled = hci_dev_test_flag(hdev, 8658c2ecf20Sopenharmony_ci HCI_WIDEBAND_SPEECH_ENABLED); 8668c2ecf20Sopenharmony_ci 8678c2ecf20Sopenharmony_ci if (enabled != 8688c2ecf20Sopenharmony_ci (hdev->err_data_reporting == ERR_DATA_REPORTING_ENABLED)) { 8698c2ecf20Sopenharmony_ci struct hci_cp_write_def_err_data_reporting cp; 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_ci cp.err_data_reporting = enabled ? 8728c2ecf20Sopenharmony_ci ERR_DATA_REPORTING_ENABLED : 8738c2ecf20Sopenharmony_ci ERR_DATA_REPORTING_DISABLED; 8748c2ecf20Sopenharmony_ci 8758c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_WRITE_DEF_ERR_DATA_REPORTING, 8768c2ecf20Sopenharmony_ci sizeof(cp), &cp); 8778c2ecf20Sopenharmony_ci } 8788c2ecf20Sopenharmony_ci } 8798c2ecf20Sopenharmony_ci 8808c2ecf20Sopenharmony_ci /* Set Suggested Default Data Length to maximum if supported */ 8818c2ecf20Sopenharmony_ci if (hdev->le_features[0] & HCI_LE_DATA_LEN_EXT) { 8828c2ecf20Sopenharmony_ci struct hci_cp_le_write_def_data_len cp; 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci cp.tx_len = cpu_to_le16(hdev->le_max_tx_len); 8858c2ecf20Sopenharmony_ci cp.tx_time = cpu_to_le16(hdev->le_max_tx_time); 8868c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_LE_WRITE_DEF_DATA_LEN, sizeof(cp), &cp); 8878c2ecf20Sopenharmony_ci } 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci /* Set Default PHY parameters if command is supported */ 8908c2ecf20Sopenharmony_ci if (hdev->commands[35] & 0x20) { 8918c2ecf20Sopenharmony_ci struct hci_cp_le_set_default_phy cp; 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci cp.all_phys = 0x00; 8948c2ecf20Sopenharmony_ci cp.tx_phys = hdev->le_tx_def_phys; 8958c2ecf20Sopenharmony_ci cp.rx_phys = hdev->le_rx_def_phys; 8968c2ecf20Sopenharmony_ci 8978c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_LE_SET_DEFAULT_PHY, sizeof(cp), &cp); 8988c2ecf20Sopenharmony_ci } 8998c2ecf20Sopenharmony_ci 9008c2ecf20Sopenharmony_ci return 0; 9018c2ecf20Sopenharmony_ci} 9028c2ecf20Sopenharmony_ci 9038c2ecf20Sopenharmony_cistatic int __hci_init(struct hci_dev *hdev) 9048c2ecf20Sopenharmony_ci{ 9058c2ecf20Sopenharmony_ci int err; 9068c2ecf20Sopenharmony_ci 9078c2ecf20Sopenharmony_ci err = __hci_req_sync(hdev, hci_init1_req, 0, HCI_INIT_TIMEOUT, NULL); 9088c2ecf20Sopenharmony_ci if (err < 0) 9098c2ecf20Sopenharmony_ci return err; 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_SETUP)) 9128c2ecf20Sopenharmony_ci hci_debugfs_create_basic(hdev); 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_ci err = __hci_req_sync(hdev, hci_init2_req, 0, HCI_INIT_TIMEOUT, NULL); 9158c2ecf20Sopenharmony_ci if (err < 0) 9168c2ecf20Sopenharmony_ci return err; 9178c2ecf20Sopenharmony_ci 9188c2ecf20Sopenharmony_ci /* HCI_PRIMARY covers both single-mode LE, BR/EDR and dual-mode 9198c2ecf20Sopenharmony_ci * BR/EDR/LE type controllers. AMP controllers only need the 9208c2ecf20Sopenharmony_ci * first two stages of init. 9218c2ecf20Sopenharmony_ci */ 9228c2ecf20Sopenharmony_ci if (hdev->dev_type != HCI_PRIMARY) 9238c2ecf20Sopenharmony_ci return 0; 9248c2ecf20Sopenharmony_ci 9258c2ecf20Sopenharmony_ci err = __hci_req_sync(hdev, hci_init3_req, 0, HCI_INIT_TIMEOUT, NULL); 9268c2ecf20Sopenharmony_ci if (err < 0) 9278c2ecf20Sopenharmony_ci return err; 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci err = __hci_req_sync(hdev, hci_init4_req, 0, HCI_INIT_TIMEOUT, NULL); 9308c2ecf20Sopenharmony_ci if (err < 0) 9318c2ecf20Sopenharmony_ci return err; 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_ci /* This function is only called when the controller is actually in 9348c2ecf20Sopenharmony_ci * configured state. When the controller is marked as unconfigured, 9358c2ecf20Sopenharmony_ci * this initialization procedure is not run. 9368c2ecf20Sopenharmony_ci * 9378c2ecf20Sopenharmony_ci * It means that it is possible that a controller runs through its 9388c2ecf20Sopenharmony_ci * setup phase and then discovers missing settings. If that is the 9398c2ecf20Sopenharmony_ci * case, then this function will not be called. It then will only 9408c2ecf20Sopenharmony_ci * be called during the config phase. 9418c2ecf20Sopenharmony_ci * 9428c2ecf20Sopenharmony_ci * So only when in setup phase or config phase, create the debugfs 9438c2ecf20Sopenharmony_ci * entries and register the SMP channels. 9448c2ecf20Sopenharmony_ci */ 9458c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_SETUP) && 9468c2ecf20Sopenharmony_ci !hci_dev_test_flag(hdev, HCI_CONFIG)) 9478c2ecf20Sopenharmony_ci return 0; 9488c2ecf20Sopenharmony_ci 9498c2ecf20Sopenharmony_ci hci_debugfs_create_common(hdev); 9508c2ecf20Sopenharmony_ci 9518c2ecf20Sopenharmony_ci if (lmp_bredr_capable(hdev)) 9528c2ecf20Sopenharmony_ci hci_debugfs_create_bredr(hdev); 9538c2ecf20Sopenharmony_ci 9548c2ecf20Sopenharmony_ci if (lmp_le_capable(hdev)) 9558c2ecf20Sopenharmony_ci hci_debugfs_create_le(hdev); 9568c2ecf20Sopenharmony_ci 9578c2ecf20Sopenharmony_ci return 0; 9588c2ecf20Sopenharmony_ci} 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_cistatic int hci_init0_req(struct hci_request *req, unsigned long opt) 9618c2ecf20Sopenharmony_ci{ 9628c2ecf20Sopenharmony_ci struct hci_dev *hdev = req->hdev; 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_ci BT_DBG("%s %ld", hdev->name, opt); 9658c2ecf20Sopenharmony_ci 9668c2ecf20Sopenharmony_ci /* Reset */ 9678c2ecf20Sopenharmony_ci if (!test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks)) 9688c2ecf20Sopenharmony_ci hci_reset_req(req, 0); 9698c2ecf20Sopenharmony_ci 9708c2ecf20Sopenharmony_ci /* Read Local Version */ 9718c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_READ_LOCAL_VERSION, 0, NULL); 9728c2ecf20Sopenharmony_ci 9738c2ecf20Sopenharmony_ci /* Read BD Address */ 9748c2ecf20Sopenharmony_ci if (hdev->set_bdaddr) 9758c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_READ_BD_ADDR, 0, NULL); 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_ci return 0; 9788c2ecf20Sopenharmony_ci} 9798c2ecf20Sopenharmony_ci 9808c2ecf20Sopenharmony_cistatic int __hci_unconf_init(struct hci_dev *hdev) 9818c2ecf20Sopenharmony_ci{ 9828c2ecf20Sopenharmony_ci int err; 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_ci if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) 9858c2ecf20Sopenharmony_ci return 0; 9868c2ecf20Sopenharmony_ci 9878c2ecf20Sopenharmony_ci err = __hci_req_sync(hdev, hci_init0_req, 0, HCI_INIT_TIMEOUT, NULL); 9888c2ecf20Sopenharmony_ci if (err < 0) 9898c2ecf20Sopenharmony_ci return err; 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_SETUP)) 9928c2ecf20Sopenharmony_ci hci_debugfs_create_basic(hdev); 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_ci return 0; 9958c2ecf20Sopenharmony_ci} 9968c2ecf20Sopenharmony_ci 9978c2ecf20Sopenharmony_cistatic int hci_scan_req(struct hci_request *req, unsigned long opt) 9988c2ecf20Sopenharmony_ci{ 9998c2ecf20Sopenharmony_ci __u8 scan = opt; 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_ci BT_DBG("%s %x", req->hdev->name, scan); 10028c2ecf20Sopenharmony_ci 10038c2ecf20Sopenharmony_ci /* Inquiry and Page scans */ 10048c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); 10058c2ecf20Sopenharmony_ci return 0; 10068c2ecf20Sopenharmony_ci} 10078c2ecf20Sopenharmony_ci 10088c2ecf20Sopenharmony_cistatic int hci_auth_req(struct hci_request *req, unsigned long opt) 10098c2ecf20Sopenharmony_ci{ 10108c2ecf20Sopenharmony_ci __u8 auth = opt; 10118c2ecf20Sopenharmony_ci 10128c2ecf20Sopenharmony_ci BT_DBG("%s %x", req->hdev->name, auth); 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_ci /* Authentication */ 10158c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_WRITE_AUTH_ENABLE, 1, &auth); 10168c2ecf20Sopenharmony_ci return 0; 10178c2ecf20Sopenharmony_ci} 10188c2ecf20Sopenharmony_ci 10198c2ecf20Sopenharmony_cistatic int hci_encrypt_req(struct hci_request *req, unsigned long opt) 10208c2ecf20Sopenharmony_ci{ 10218c2ecf20Sopenharmony_ci __u8 encrypt = opt; 10228c2ecf20Sopenharmony_ci 10238c2ecf20Sopenharmony_ci BT_DBG("%s %x", req->hdev->name, encrypt); 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_ci /* Encryption */ 10268c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_WRITE_ENCRYPT_MODE, 1, &encrypt); 10278c2ecf20Sopenharmony_ci return 0; 10288c2ecf20Sopenharmony_ci} 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_cistatic int hci_linkpol_req(struct hci_request *req, unsigned long opt) 10318c2ecf20Sopenharmony_ci{ 10328c2ecf20Sopenharmony_ci __le16 policy = cpu_to_le16(opt); 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_ci BT_DBG("%s %x", req->hdev->name, policy); 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_ci /* Default link policy */ 10378c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_WRITE_DEF_LINK_POLICY, 2, &policy); 10388c2ecf20Sopenharmony_ci return 0; 10398c2ecf20Sopenharmony_ci} 10408c2ecf20Sopenharmony_ci 10418c2ecf20Sopenharmony_ci/* Get HCI device by index. 10428c2ecf20Sopenharmony_ci * Device is held on return. */ 10438c2ecf20Sopenharmony_cistruct hci_dev *hci_dev_get(int index) 10448c2ecf20Sopenharmony_ci{ 10458c2ecf20Sopenharmony_ci struct hci_dev *hdev = NULL, *d; 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_ci BT_DBG("%d", index); 10488c2ecf20Sopenharmony_ci 10498c2ecf20Sopenharmony_ci if (index < 0) 10508c2ecf20Sopenharmony_ci return NULL; 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_ci read_lock(&hci_dev_list_lock); 10538c2ecf20Sopenharmony_ci list_for_each_entry(d, &hci_dev_list, list) { 10548c2ecf20Sopenharmony_ci if (d->id == index) { 10558c2ecf20Sopenharmony_ci hdev = hci_dev_hold(d); 10568c2ecf20Sopenharmony_ci break; 10578c2ecf20Sopenharmony_ci } 10588c2ecf20Sopenharmony_ci } 10598c2ecf20Sopenharmony_ci read_unlock(&hci_dev_list_lock); 10608c2ecf20Sopenharmony_ci return hdev; 10618c2ecf20Sopenharmony_ci} 10628c2ecf20Sopenharmony_ci 10638c2ecf20Sopenharmony_ci/* ---- Inquiry support ---- */ 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_cibool hci_discovery_active(struct hci_dev *hdev) 10668c2ecf20Sopenharmony_ci{ 10678c2ecf20Sopenharmony_ci struct discovery_state *discov = &hdev->discovery; 10688c2ecf20Sopenharmony_ci 10698c2ecf20Sopenharmony_ci switch (discov->state) { 10708c2ecf20Sopenharmony_ci case DISCOVERY_FINDING: 10718c2ecf20Sopenharmony_ci case DISCOVERY_RESOLVING: 10728c2ecf20Sopenharmony_ci return true; 10738c2ecf20Sopenharmony_ci 10748c2ecf20Sopenharmony_ci default: 10758c2ecf20Sopenharmony_ci return false; 10768c2ecf20Sopenharmony_ci } 10778c2ecf20Sopenharmony_ci} 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_civoid hci_discovery_set_state(struct hci_dev *hdev, int state) 10808c2ecf20Sopenharmony_ci{ 10818c2ecf20Sopenharmony_ci int old_state = hdev->discovery.state; 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_ci BT_DBG("%s state %u -> %u", hdev->name, hdev->discovery.state, state); 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_ci if (old_state == state) 10868c2ecf20Sopenharmony_ci return; 10878c2ecf20Sopenharmony_ci 10888c2ecf20Sopenharmony_ci hdev->discovery.state = state; 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_ci switch (state) { 10918c2ecf20Sopenharmony_ci case DISCOVERY_STOPPED: 10928c2ecf20Sopenharmony_ci hci_update_background_scan(hdev); 10938c2ecf20Sopenharmony_ci 10948c2ecf20Sopenharmony_ci if (old_state != DISCOVERY_STARTING) 10958c2ecf20Sopenharmony_ci mgmt_discovering(hdev, 0); 10968c2ecf20Sopenharmony_ci break; 10978c2ecf20Sopenharmony_ci case DISCOVERY_STARTING: 10988c2ecf20Sopenharmony_ci break; 10998c2ecf20Sopenharmony_ci case DISCOVERY_FINDING: 11008c2ecf20Sopenharmony_ci mgmt_discovering(hdev, 1); 11018c2ecf20Sopenharmony_ci break; 11028c2ecf20Sopenharmony_ci case DISCOVERY_RESOLVING: 11038c2ecf20Sopenharmony_ci break; 11048c2ecf20Sopenharmony_ci case DISCOVERY_STOPPING: 11058c2ecf20Sopenharmony_ci break; 11068c2ecf20Sopenharmony_ci } 11078c2ecf20Sopenharmony_ci} 11088c2ecf20Sopenharmony_ci 11098c2ecf20Sopenharmony_civoid hci_inquiry_cache_flush(struct hci_dev *hdev) 11108c2ecf20Sopenharmony_ci{ 11118c2ecf20Sopenharmony_ci struct discovery_state *cache = &hdev->discovery; 11128c2ecf20Sopenharmony_ci struct inquiry_entry *p, *n; 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_ci list_for_each_entry_safe(p, n, &cache->all, all) { 11158c2ecf20Sopenharmony_ci list_del(&p->all); 11168c2ecf20Sopenharmony_ci kfree(p); 11178c2ecf20Sopenharmony_ci } 11188c2ecf20Sopenharmony_ci 11198c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&cache->unknown); 11208c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&cache->resolve); 11218c2ecf20Sopenharmony_ci} 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_cistruct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev, 11248c2ecf20Sopenharmony_ci bdaddr_t *bdaddr) 11258c2ecf20Sopenharmony_ci{ 11268c2ecf20Sopenharmony_ci struct discovery_state *cache = &hdev->discovery; 11278c2ecf20Sopenharmony_ci struct inquiry_entry *e; 11288c2ecf20Sopenharmony_ci 11298c2ecf20Sopenharmony_ci BT_DBG("cache %p, %pMR", cache, bdaddr); 11308c2ecf20Sopenharmony_ci 11318c2ecf20Sopenharmony_ci list_for_each_entry(e, &cache->all, all) { 11328c2ecf20Sopenharmony_ci if (!bacmp(&e->data.bdaddr, bdaddr)) 11338c2ecf20Sopenharmony_ci return e; 11348c2ecf20Sopenharmony_ci } 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_ci return NULL; 11378c2ecf20Sopenharmony_ci} 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_cistruct inquiry_entry *hci_inquiry_cache_lookup_unknown(struct hci_dev *hdev, 11408c2ecf20Sopenharmony_ci bdaddr_t *bdaddr) 11418c2ecf20Sopenharmony_ci{ 11428c2ecf20Sopenharmony_ci struct discovery_state *cache = &hdev->discovery; 11438c2ecf20Sopenharmony_ci struct inquiry_entry *e; 11448c2ecf20Sopenharmony_ci 11458c2ecf20Sopenharmony_ci BT_DBG("cache %p, %pMR", cache, bdaddr); 11468c2ecf20Sopenharmony_ci 11478c2ecf20Sopenharmony_ci list_for_each_entry(e, &cache->unknown, list) { 11488c2ecf20Sopenharmony_ci if (!bacmp(&e->data.bdaddr, bdaddr)) 11498c2ecf20Sopenharmony_ci return e; 11508c2ecf20Sopenharmony_ci } 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_ci return NULL; 11538c2ecf20Sopenharmony_ci} 11548c2ecf20Sopenharmony_ci 11558c2ecf20Sopenharmony_cistruct inquiry_entry *hci_inquiry_cache_lookup_resolve(struct hci_dev *hdev, 11568c2ecf20Sopenharmony_ci bdaddr_t *bdaddr, 11578c2ecf20Sopenharmony_ci int state) 11588c2ecf20Sopenharmony_ci{ 11598c2ecf20Sopenharmony_ci struct discovery_state *cache = &hdev->discovery; 11608c2ecf20Sopenharmony_ci struct inquiry_entry *e; 11618c2ecf20Sopenharmony_ci 11628c2ecf20Sopenharmony_ci BT_DBG("cache %p bdaddr %pMR state %d", cache, bdaddr, state); 11638c2ecf20Sopenharmony_ci 11648c2ecf20Sopenharmony_ci list_for_each_entry(e, &cache->resolve, list) { 11658c2ecf20Sopenharmony_ci if (!bacmp(bdaddr, BDADDR_ANY) && e->name_state == state) 11668c2ecf20Sopenharmony_ci return e; 11678c2ecf20Sopenharmony_ci if (!bacmp(&e->data.bdaddr, bdaddr)) 11688c2ecf20Sopenharmony_ci return e; 11698c2ecf20Sopenharmony_ci } 11708c2ecf20Sopenharmony_ci 11718c2ecf20Sopenharmony_ci return NULL; 11728c2ecf20Sopenharmony_ci} 11738c2ecf20Sopenharmony_ci 11748c2ecf20Sopenharmony_civoid hci_inquiry_cache_update_resolve(struct hci_dev *hdev, 11758c2ecf20Sopenharmony_ci struct inquiry_entry *ie) 11768c2ecf20Sopenharmony_ci{ 11778c2ecf20Sopenharmony_ci struct discovery_state *cache = &hdev->discovery; 11788c2ecf20Sopenharmony_ci struct list_head *pos = &cache->resolve; 11798c2ecf20Sopenharmony_ci struct inquiry_entry *p; 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_ci list_del(&ie->list); 11828c2ecf20Sopenharmony_ci 11838c2ecf20Sopenharmony_ci list_for_each_entry(p, &cache->resolve, list) { 11848c2ecf20Sopenharmony_ci if (p->name_state != NAME_PENDING && 11858c2ecf20Sopenharmony_ci abs(p->data.rssi) >= abs(ie->data.rssi)) 11868c2ecf20Sopenharmony_ci break; 11878c2ecf20Sopenharmony_ci pos = &p->list; 11888c2ecf20Sopenharmony_ci } 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_ci list_add(&ie->list, pos); 11918c2ecf20Sopenharmony_ci} 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_ciu32 hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data, 11948c2ecf20Sopenharmony_ci bool name_known) 11958c2ecf20Sopenharmony_ci{ 11968c2ecf20Sopenharmony_ci struct discovery_state *cache = &hdev->discovery; 11978c2ecf20Sopenharmony_ci struct inquiry_entry *ie; 11988c2ecf20Sopenharmony_ci u32 flags = 0; 11998c2ecf20Sopenharmony_ci 12008c2ecf20Sopenharmony_ci BT_DBG("cache %p, %pMR", cache, &data->bdaddr); 12018c2ecf20Sopenharmony_ci 12028c2ecf20Sopenharmony_ci hci_remove_remote_oob_data(hdev, &data->bdaddr, BDADDR_BREDR); 12038c2ecf20Sopenharmony_ci 12048c2ecf20Sopenharmony_ci if (!data->ssp_mode) 12058c2ecf20Sopenharmony_ci flags |= MGMT_DEV_FOUND_LEGACY_PAIRING; 12068c2ecf20Sopenharmony_ci 12078c2ecf20Sopenharmony_ci ie = hci_inquiry_cache_lookup(hdev, &data->bdaddr); 12088c2ecf20Sopenharmony_ci if (ie) { 12098c2ecf20Sopenharmony_ci if (!ie->data.ssp_mode) 12108c2ecf20Sopenharmony_ci flags |= MGMT_DEV_FOUND_LEGACY_PAIRING; 12118c2ecf20Sopenharmony_ci 12128c2ecf20Sopenharmony_ci if (ie->name_state == NAME_NEEDED && 12138c2ecf20Sopenharmony_ci data->rssi != ie->data.rssi) { 12148c2ecf20Sopenharmony_ci ie->data.rssi = data->rssi; 12158c2ecf20Sopenharmony_ci hci_inquiry_cache_update_resolve(hdev, ie); 12168c2ecf20Sopenharmony_ci } 12178c2ecf20Sopenharmony_ci 12188c2ecf20Sopenharmony_ci goto update; 12198c2ecf20Sopenharmony_ci } 12208c2ecf20Sopenharmony_ci 12218c2ecf20Sopenharmony_ci /* Entry not in the cache. Add new one. */ 12228c2ecf20Sopenharmony_ci ie = kzalloc(sizeof(*ie), GFP_KERNEL); 12238c2ecf20Sopenharmony_ci if (!ie) { 12248c2ecf20Sopenharmony_ci flags |= MGMT_DEV_FOUND_CONFIRM_NAME; 12258c2ecf20Sopenharmony_ci goto done; 12268c2ecf20Sopenharmony_ci } 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_ci list_add(&ie->all, &cache->all); 12298c2ecf20Sopenharmony_ci 12308c2ecf20Sopenharmony_ci if (name_known) { 12318c2ecf20Sopenharmony_ci ie->name_state = NAME_KNOWN; 12328c2ecf20Sopenharmony_ci } else { 12338c2ecf20Sopenharmony_ci ie->name_state = NAME_NOT_KNOWN; 12348c2ecf20Sopenharmony_ci list_add(&ie->list, &cache->unknown); 12358c2ecf20Sopenharmony_ci } 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_ciupdate: 12388c2ecf20Sopenharmony_ci if (name_known && ie->name_state != NAME_KNOWN && 12398c2ecf20Sopenharmony_ci ie->name_state != NAME_PENDING) { 12408c2ecf20Sopenharmony_ci ie->name_state = NAME_KNOWN; 12418c2ecf20Sopenharmony_ci list_del(&ie->list); 12428c2ecf20Sopenharmony_ci } 12438c2ecf20Sopenharmony_ci 12448c2ecf20Sopenharmony_ci memcpy(&ie->data, data, sizeof(*data)); 12458c2ecf20Sopenharmony_ci ie->timestamp = jiffies; 12468c2ecf20Sopenharmony_ci cache->timestamp = jiffies; 12478c2ecf20Sopenharmony_ci 12488c2ecf20Sopenharmony_ci if (ie->name_state == NAME_NOT_KNOWN) 12498c2ecf20Sopenharmony_ci flags |= MGMT_DEV_FOUND_CONFIRM_NAME; 12508c2ecf20Sopenharmony_ci 12518c2ecf20Sopenharmony_cidone: 12528c2ecf20Sopenharmony_ci return flags; 12538c2ecf20Sopenharmony_ci} 12548c2ecf20Sopenharmony_ci 12558c2ecf20Sopenharmony_cistatic int inquiry_cache_dump(struct hci_dev *hdev, int num, __u8 *buf) 12568c2ecf20Sopenharmony_ci{ 12578c2ecf20Sopenharmony_ci struct discovery_state *cache = &hdev->discovery; 12588c2ecf20Sopenharmony_ci struct inquiry_info *info = (struct inquiry_info *) buf; 12598c2ecf20Sopenharmony_ci struct inquiry_entry *e; 12608c2ecf20Sopenharmony_ci int copied = 0; 12618c2ecf20Sopenharmony_ci 12628c2ecf20Sopenharmony_ci list_for_each_entry(e, &cache->all, all) { 12638c2ecf20Sopenharmony_ci struct inquiry_data *data = &e->data; 12648c2ecf20Sopenharmony_ci 12658c2ecf20Sopenharmony_ci if (copied >= num) 12668c2ecf20Sopenharmony_ci break; 12678c2ecf20Sopenharmony_ci 12688c2ecf20Sopenharmony_ci bacpy(&info->bdaddr, &data->bdaddr); 12698c2ecf20Sopenharmony_ci info->pscan_rep_mode = data->pscan_rep_mode; 12708c2ecf20Sopenharmony_ci info->pscan_period_mode = data->pscan_period_mode; 12718c2ecf20Sopenharmony_ci info->pscan_mode = data->pscan_mode; 12728c2ecf20Sopenharmony_ci memcpy(info->dev_class, data->dev_class, 3); 12738c2ecf20Sopenharmony_ci info->clock_offset = data->clock_offset; 12748c2ecf20Sopenharmony_ci 12758c2ecf20Sopenharmony_ci info++; 12768c2ecf20Sopenharmony_ci copied++; 12778c2ecf20Sopenharmony_ci } 12788c2ecf20Sopenharmony_ci 12798c2ecf20Sopenharmony_ci BT_DBG("cache %p, copied %d", cache, copied); 12808c2ecf20Sopenharmony_ci return copied; 12818c2ecf20Sopenharmony_ci} 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_cistatic int hci_inq_req(struct hci_request *req, unsigned long opt) 12848c2ecf20Sopenharmony_ci{ 12858c2ecf20Sopenharmony_ci struct hci_inquiry_req *ir = (struct hci_inquiry_req *) opt; 12868c2ecf20Sopenharmony_ci struct hci_dev *hdev = req->hdev; 12878c2ecf20Sopenharmony_ci struct hci_cp_inquiry cp; 12888c2ecf20Sopenharmony_ci 12898c2ecf20Sopenharmony_ci BT_DBG("%s", hdev->name); 12908c2ecf20Sopenharmony_ci 12918c2ecf20Sopenharmony_ci if (test_bit(HCI_INQUIRY, &hdev->flags)) 12928c2ecf20Sopenharmony_ci return 0; 12938c2ecf20Sopenharmony_ci 12948c2ecf20Sopenharmony_ci /* Start Inquiry */ 12958c2ecf20Sopenharmony_ci memcpy(&cp.lap, &ir->lap, 3); 12968c2ecf20Sopenharmony_ci cp.length = ir->length; 12978c2ecf20Sopenharmony_ci cp.num_rsp = ir->num_rsp; 12988c2ecf20Sopenharmony_ci hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp); 12998c2ecf20Sopenharmony_ci 13008c2ecf20Sopenharmony_ci return 0; 13018c2ecf20Sopenharmony_ci} 13028c2ecf20Sopenharmony_ci 13038c2ecf20Sopenharmony_ciint hci_inquiry(void __user *arg) 13048c2ecf20Sopenharmony_ci{ 13058c2ecf20Sopenharmony_ci __u8 __user *ptr = arg; 13068c2ecf20Sopenharmony_ci struct hci_inquiry_req ir; 13078c2ecf20Sopenharmony_ci struct hci_dev *hdev; 13088c2ecf20Sopenharmony_ci int err = 0, do_inquiry = 0, max_rsp; 13098c2ecf20Sopenharmony_ci long timeo; 13108c2ecf20Sopenharmony_ci __u8 *buf; 13118c2ecf20Sopenharmony_ci 13128c2ecf20Sopenharmony_ci if (copy_from_user(&ir, ptr, sizeof(ir))) 13138c2ecf20Sopenharmony_ci return -EFAULT; 13148c2ecf20Sopenharmony_ci 13158c2ecf20Sopenharmony_ci hdev = hci_dev_get(ir.dev_id); 13168c2ecf20Sopenharmony_ci if (!hdev) 13178c2ecf20Sopenharmony_ci return -ENODEV; 13188c2ecf20Sopenharmony_ci 13198c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) { 13208c2ecf20Sopenharmony_ci err = -EBUSY; 13218c2ecf20Sopenharmony_ci goto done; 13228c2ecf20Sopenharmony_ci } 13238c2ecf20Sopenharmony_ci 13248c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) { 13258c2ecf20Sopenharmony_ci err = -EOPNOTSUPP; 13268c2ecf20Sopenharmony_ci goto done; 13278c2ecf20Sopenharmony_ci } 13288c2ecf20Sopenharmony_ci 13298c2ecf20Sopenharmony_ci if (hdev->dev_type != HCI_PRIMARY) { 13308c2ecf20Sopenharmony_ci err = -EOPNOTSUPP; 13318c2ecf20Sopenharmony_ci goto done; 13328c2ecf20Sopenharmony_ci } 13338c2ecf20Sopenharmony_ci 13348c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) { 13358c2ecf20Sopenharmony_ci err = -EOPNOTSUPP; 13368c2ecf20Sopenharmony_ci goto done; 13378c2ecf20Sopenharmony_ci } 13388c2ecf20Sopenharmony_ci 13398c2ecf20Sopenharmony_ci /* Restrict maximum inquiry length to 60 seconds */ 13408c2ecf20Sopenharmony_ci if (ir.length > 60) { 13418c2ecf20Sopenharmony_ci err = -EINVAL; 13428c2ecf20Sopenharmony_ci goto done; 13438c2ecf20Sopenharmony_ci } 13448c2ecf20Sopenharmony_ci 13458c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 13468c2ecf20Sopenharmony_ci if (inquiry_cache_age(hdev) > INQUIRY_CACHE_AGE_MAX || 13478c2ecf20Sopenharmony_ci inquiry_cache_empty(hdev) || ir.flags & IREQ_CACHE_FLUSH) { 13488c2ecf20Sopenharmony_ci hci_inquiry_cache_flush(hdev); 13498c2ecf20Sopenharmony_ci do_inquiry = 1; 13508c2ecf20Sopenharmony_ci } 13518c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 13528c2ecf20Sopenharmony_ci 13538c2ecf20Sopenharmony_ci timeo = ir.length * msecs_to_jiffies(2000); 13548c2ecf20Sopenharmony_ci 13558c2ecf20Sopenharmony_ci if (do_inquiry) { 13568c2ecf20Sopenharmony_ci err = hci_req_sync(hdev, hci_inq_req, (unsigned long) &ir, 13578c2ecf20Sopenharmony_ci timeo, NULL); 13588c2ecf20Sopenharmony_ci if (err < 0) 13598c2ecf20Sopenharmony_ci goto done; 13608c2ecf20Sopenharmony_ci 13618c2ecf20Sopenharmony_ci /* Wait until Inquiry procedure finishes (HCI_INQUIRY flag is 13628c2ecf20Sopenharmony_ci * cleared). If it is interrupted by a signal, return -EINTR. 13638c2ecf20Sopenharmony_ci */ 13648c2ecf20Sopenharmony_ci if (wait_on_bit(&hdev->flags, HCI_INQUIRY, 13658c2ecf20Sopenharmony_ci TASK_INTERRUPTIBLE)) { 13668c2ecf20Sopenharmony_ci err = -EINTR; 13678c2ecf20Sopenharmony_ci goto done; 13688c2ecf20Sopenharmony_ci } 13698c2ecf20Sopenharmony_ci } 13708c2ecf20Sopenharmony_ci 13718c2ecf20Sopenharmony_ci /* for unlimited number of responses we will use buffer with 13728c2ecf20Sopenharmony_ci * 255 entries 13738c2ecf20Sopenharmony_ci */ 13748c2ecf20Sopenharmony_ci max_rsp = (ir.num_rsp == 0) ? 255 : ir.num_rsp; 13758c2ecf20Sopenharmony_ci 13768c2ecf20Sopenharmony_ci /* cache_dump can't sleep. Therefore we allocate temp buffer and then 13778c2ecf20Sopenharmony_ci * copy it to the user space. 13788c2ecf20Sopenharmony_ci */ 13798c2ecf20Sopenharmony_ci buf = kmalloc_array(max_rsp, sizeof(struct inquiry_info), GFP_KERNEL); 13808c2ecf20Sopenharmony_ci if (!buf) { 13818c2ecf20Sopenharmony_ci err = -ENOMEM; 13828c2ecf20Sopenharmony_ci goto done; 13838c2ecf20Sopenharmony_ci } 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 13868c2ecf20Sopenharmony_ci ir.num_rsp = inquiry_cache_dump(hdev, max_rsp, buf); 13878c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 13888c2ecf20Sopenharmony_ci 13898c2ecf20Sopenharmony_ci BT_DBG("num_rsp %d", ir.num_rsp); 13908c2ecf20Sopenharmony_ci 13918c2ecf20Sopenharmony_ci if (!copy_to_user(ptr, &ir, sizeof(ir))) { 13928c2ecf20Sopenharmony_ci ptr += sizeof(ir); 13938c2ecf20Sopenharmony_ci if (copy_to_user(ptr, buf, sizeof(struct inquiry_info) * 13948c2ecf20Sopenharmony_ci ir.num_rsp)) 13958c2ecf20Sopenharmony_ci err = -EFAULT; 13968c2ecf20Sopenharmony_ci } else 13978c2ecf20Sopenharmony_ci err = -EFAULT; 13988c2ecf20Sopenharmony_ci 13998c2ecf20Sopenharmony_ci kfree(buf); 14008c2ecf20Sopenharmony_ci 14018c2ecf20Sopenharmony_cidone: 14028c2ecf20Sopenharmony_ci hci_dev_put(hdev); 14038c2ecf20Sopenharmony_ci return err; 14048c2ecf20Sopenharmony_ci} 14058c2ecf20Sopenharmony_ci 14068c2ecf20Sopenharmony_ci/** 14078c2ecf20Sopenharmony_ci * hci_dev_get_bd_addr_from_property - Get the Bluetooth Device Address 14088c2ecf20Sopenharmony_ci * (BD_ADDR) for a HCI device from 14098c2ecf20Sopenharmony_ci * a firmware node property. 14108c2ecf20Sopenharmony_ci * @hdev: The HCI device 14118c2ecf20Sopenharmony_ci * 14128c2ecf20Sopenharmony_ci * Search the firmware node for 'local-bd-address'. 14138c2ecf20Sopenharmony_ci * 14148c2ecf20Sopenharmony_ci * All-zero BD addresses are rejected, because those could be properties 14158c2ecf20Sopenharmony_ci * that exist in the firmware tables, but were not updated by the firmware. For 14168c2ecf20Sopenharmony_ci * example, the DTS could define 'local-bd-address', with zero BD addresses. 14178c2ecf20Sopenharmony_ci */ 14188c2ecf20Sopenharmony_cistatic void hci_dev_get_bd_addr_from_property(struct hci_dev *hdev) 14198c2ecf20Sopenharmony_ci{ 14208c2ecf20Sopenharmony_ci struct fwnode_handle *fwnode = dev_fwnode(hdev->dev.parent); 14218c2ecf20Sopenharmony_ci bdaddr_t ba; 14228c2ecf20Sopenharmony_ci int ret; 14238c2ecf20Sopenharmony_ci 14248c2ecf20Sopenharmony_ci ret = fwnode_property_read_u8_array(fwnode, "local-bd-address", 14258c2ecf20Sopenharmony_ci (u8 *)&ba, sizeof(ba)); 14268c2ecf20Sopenharmony_ci if (ret < 0 || !bacmp(&ba, BDADDR_ANY)) 14278c2ecf20Sopenharmony_ci return; 14288c2ecf20Sopenharmony_ci 14298c2ecf20Sopenharmony_ci bacpy(&hdev->public_addr, &ba); 14308c2ecf20Sopenharmony_ci} 14318c2ecf20Sopenharmony_ci 14328c2ecf20Sopenharmony_cistatic int hci_dev_do_open(struct hci_dev *hdev) 14338c2ecf20Sopenharmony_ci{ 14348c2ecf20Sopenharmony_ci int ret = 0; 14358c2ecf20Sopenharmony_ci 14368c2ecf20Sopenharmony_ci BT_DBG("%s %p", hdev->name, hdev); 14378c2ecf20Sopenharmony_ci 14388c2ecf20Sopenharmony_ci hci_req_sync_lock(hdev); 14398c2ecf20Sopenharmony_ci 14408c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_UNREGISTER)) { 14418c2ecf20Sopenharmony_ci ret = -ENODEV; 14428c2ecf20Sopenharmony_ci goto done; 14438c2ecf20Sopenharmony_ci } 14448c2ecf20Sopenharmony_ci 14458c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_SETUP) && 14468c2ecf20Sopenharmony_ci !hci_dev_test_flag(hdev, HCI_CONFIG)) { 14478c2ecf20Sopenharmony_ci /* Check for rfkill but allow the HCI setup stage to 14488c2ecf20Sopenharmony_ci * proceed (which in itself doesn't cause any RF activity). 14498c2ecf20Sopenharmony_ci */ 14508c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_RFKILLED)) { 14518c2ecf20Sopenharmony_ci ret = -ERFKILL; 14528c2ecf20Sopenharmony_ci goto done; 14538c2ecf20Sopenharmony_ci } 14548c2ecf20Sopenharmony_ci 14558c2ecf20Sopenharmony_ci /* Check for valid public address or a configured static 14568c2ecf20Sopenharmony_ci * random adddress, but let the HCI setup proceed to 14578c2ecf20Sopenharmony_ci * be able to determine if there is a public address 14588c2ecf20Sopenharmony_ci * or not. 14598c2ecf20Sopenharmony_ci * 14608c2ecf20Sopenharmony_ci * In case of user channel usage, it is not important 14618c2ecf20Sopenharmony_ci * if a public address or static random address is 14628c2ecf20Sopenharmony_ci * available. 14638c2ecf20Sopenharmony_ci * 14648c2ecf20Sopenharmony_ci * This check is only valid for BR/EDR controllers 14658c2ecf20Sopenharmony_ci * since AMP controllers do not have an address. 14668c2ecf20Sopenharmony_ci */ 14678c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL) && 14688c2ecf20Sopenharmony_ci hdev->dev_type == HCI_PRIMARY && 14698c2ecf20Sopenharmony_ci !bacmp(&hdev->bdaddr, BDADDR_ANY) && 14708c2ecf20Sopenharmony_ci !bacmp(&hdev->static_addr, BDADDR_ANY)) { 14718c2ecf20Sopenharmony_ci ret = -EADDRNOTAVAIL; 14728c2ecf20Sopenharmony_ci goto done; 14738c2ecf20Sopenharmony_ci } 14748c2ecf20Sopenharmony_ci } 14758c2ecf20Sopenharmony_ci 14768c2ecf20Sopenharmony_ci if (test_bit(HCI_UP, &hdev->flags)) { 14778c2ecf20Sopenharmony_ci ret = -EALREADY; 14788c2ecf20Sopenharmony_ci goto done; 14798c2ecf20Sopenharmony_ci } 14808c2ecf20Sopenharmony_ci 14818c2ecf20Sopenharmony_ci if (hdev->open(hdev)) { 14828c2ecf20Sopenharmony_ci ret = -EIO; 14838c2ecf20Sopenharmony_ci goto done; 14848c2ecf20Sopenharmony_ci } 14858c2ecf20Sopenharmony_ci 14868c2ecf20Sopenharmony_ci set_bit(HCI_RUNNING, &hdev->flags); 14878c2ecf20Sopenharmony_ci hci_sock_dev_event(hdev, HCI_DEV_OPEN); 14888c2ecf20Sopenharmony_ci 14898c2ecf20Sopenharmony_ci atomic_set(&hdev->cmd_cnt, 1); 14908c2ecf20Sopenharmony_ci set_bit(HCI_INIT, &hdev->flags); 14918c2ecf20Sopenharmony_ci 14928c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_SETUP) || 14938c2ecf20Sopenharmony_ci test_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks)) { 14948c2ecf20Sopenharmony_ci bool invalid_bdaddr; 14958c2ecf20Sopenharmony_ci 14968c2ecf20Sopenharmony_ci hci_sock_dev_event(hdev, HCI_DEV_SETUP); 14978c2ecf20Sopenharmony_ci 14988c2ecf20Sopenharmony_ci if (hdev->setup) 14998c2ecf20Sopenharmony_ci ret = hdev->setup(hdev); 15008c2ecf20Sopenharmony_ci 15018c2ecf20Sopenharmony_ci /* The transport driver can set the quirk to mark the 15028c2ecf20Sopenharmony_ci * BD_ADDR invalid before creating the HCI device or in 15038c2ecf20Sopenharmony_ci * its setup callback. 15048c2ecf20Sopenharmony_ci */ 15058c2ecf20Sopenharmony_ci invalid_bdaddr = test_bit(HCI_QUIRK_INVALID_BDADDR, 15068c2ecf20Sopenharmony_ci &hdev->quirks); 15078c2ecf20Sopenharmony_ci 15088c2ecf20Sopenharmony_ci if (ret) 15098c2ecf20Sopenharmony_ci goto setup_failed; 15108c2ecf20Sopenharmony_ci 15118c2ecf20Sopenharmony_ci if (test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks)) { 15128c2ecf20Sopenharmony_ci if (!bacmp(&hdev->public_addr, BDADDR_ANY)) 15138c2ecf20Sopenharmony_ci hci_dev_get_bd_addr_from_property(hdev); 15148c2ecf20Sopenharmony_ci 15158c2ecf20Sopenharmony_ci if (bacmp(&hdev->public_addr, BDADDR_ANY) && 15168c2ecf20Sopenharmony_ci hdev->set_bdaddr) { 15178c2ecf20Sopenharmony_ci ret = hdev->set_bdaddr(hdev, 15188c2ecf20Sopenharmony_ci &hdev->public_addr); 15198c2ecf20Sopenharmony_ci 15208c2ecf20Sopenharmony_ci /* If setting of the BD_ADDR from the device 15218c2ecf20Sopenharmony_ci * property succeeds, then treat the address 15228c2ecf20Sopenharmony_ci * as valid even if the invalid BD_ADDR 15238c2ecf20Sopenharmony_ci * quirk indicates otherwise. 15248c2ecf20Sopenharmony_ci */ 15258c2ecf20Sopenharmony_ci if (!ret) 15268c2ecf20Sopenharmony_ci invalid_bdaddr = false; 15278c2ecf20Sopenharmony_ci } 15288c2ecf20Sopenharmony_ci } 15298c2ecf20Sopenharmony_ci 15308c2ecf20Sopenharmony_cisetup_failed: 15318c2ecf20Sopenharmony_ci /* The transport driver can set these quirks before 15328c2ecf20Sopenharmony_ci * creating the HCI device or in its setup callback. 15338c2ecf20Sopenharmony_ci * 15348c2ecf20Sopenharmony_ci * For the invalid BD_ADDR quirk it is possible that 15358c2ecf20Sopenharmony_ci * it becomes a valid address if the bootloader does 15368c2ecf20Sopenharmony_ci * provide it (see above). 15378c2ecf20Sopenharmony_ci * 15388c2ecf20Sopenharmony_ci * In case any of them is set, the controller has to 15398c2ecf20Sopenharmony_ci * start up as unconfigured. 15408c2ecf20Sopenharmony_ci */ 15418c2ecf20Sopenharmony_ci if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) || 15428c2ecf20Sopenharmony_ci invalid_bdaddr) 15438c2ecf20Sopenharmony_ci hci_dev_set_flag(hdev, HCI_UNCONFIGURED); 15448c2ecf20Sopenharmony_ci 15458c2ecf20Sopenharmony_ci /* For an unconfigured controller it is required to 15468c2ecf20Sopenharmony_ci * read at least the version information provided by 15478c2ecf20Sopenharmony_ci * the Read Local Version Information command. 15488c2ecf20Sopenharmony_ci * 15498c2ecf20Sopenharmony_ci * If the set_bdaddr driver callback is provided, then 15508c2ecf20Sopenharmony_ci * also the original Bluetooth public device address 15518c2ecf20Sopenharmony_ci * will be read using the Read BD Address command. 15528c2ecf20Sopenharmony_ci */ 15538c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) 15548c2ecf20Sopenharmony_ci ret = __hci_unconf_init(hdev); 15558c2ecf20Sopenharmony_ci } 15568c2ecf20Sopenharmony_ci 15578c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_CONFIG)) { 15588c2ecf20Sopenharmony_ci /* If public address change is configured, ensure that 15598c2ecf20Sopenharmony_ci * the address gets programmed. If the driver does not 15608c2ecf20Sopenharmony_ci * support changing the public address, fail the power 15618c2ecf20Sopenharmony_ci * on procedure. 15628c2ecf20Sopenharmony_ci */ 15638c2ecf20Sopenharmony_ci if (bacmp(&hdev->public_addr, BDADDR_ANY) && 15648c2ecf20Sopenharmony_ci hdev->set_bdaddr) 15658c2ecf20Sopenharmony_ci ret = hdev->set_bdaddr(hdev, &hdev->public_addr); 15668c2ecf20Sopenharmony_ci else 15678c2ecf20Sopenharmony_ci ret = -EADDRNOTAVAIL; 15688c2ecf20Sopenharmony_ci } 15698c2ecf20Sopenharmony_ci 15708c2ecf20Sopenharmony_ci if (!ret) { 15718c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_UNCONFIGURED) && 15728c2ecf20Sopenharmony_ci !hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) { 15738c2ecf20Sopenharmony_ci ret = __hci_init(hdev); 15748c2ecf20Sopenharmony_ci if (!ret && hdev->post_init) 15758c2ecf20Sopenharmony_ci ret = hdev->post_init(hdev); 15768c2ecf20Sopenharmony_ci } 15778c2ecf20Sopenharmony_ci } 15788c2ecf20Sopenharmony_ci 15798c2ecf20Sopenharmony_ci /* If the HCI Reset command is clearing all diagnostic settings, 15808c2ecf20Sopenharmony_ci * then they need to be reprogrammed after the init procedure 15818c2ecf20Sopenharmony_ci * completed. 15828c2ecf20Sopenharmony_ci */ 15838c2ecf20Sopenharmony_ci if (test_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks) && 15848c2ecf20Sopenharmony_ci !hci_dev_test_flag(hdev, HCI_USER_CHANNEL) && 15858c2ecf20Sopenharmony_ci hci_dev_test_flag(hdev, HCI_VENDOR_DIAG) && hdev->set_diag) 15868c2ecf20Sopenharmony_ci ret = hdev->set_diag(hdev, true); 15878c2ecf20Sopenharmony_ci 15888c2ecf20Sopenharmony_ci msft_do_open(hdev); 15898c2ecf20Sopenharmony_ci 15908c2ecf20Sopenharmony_ci clear_bit(HCI_INIT, &hdev->flags); 15918c2ecf20Sopenharmony_ci 15928c2ecf20Sopenharmony_ci if (!ret) { 15938c2ecf20Sopenharmony_ci hci_dev_hold(hdev); 15948c2ecf20Sopenharmony_ci hci_dev_set_flag(hdev, HCI_RPA_EXPIRED); 15958c2ecf20Sopenharmony_ci hci_adv_instances_set_rpa_expired(hdev, true); 15968c2ecf20Sopenharmony_ci set_bit(HCI_UP, &hdev->flags); 15978c2ecf20Sopenharmony_ci hci_sock_dev_event(hdev, HCI_DEV_UP); 15988c2ecf20Sopenharmony_ci hci_leds_update_powered(hdev, true); 15998c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_SETUP) && 16008c2ecf20Sopenharmony_ci !hci_dev_test_flag(hdev, HCI_CONFIG) && 16018c2ecf20Sopenharmony_ci !hci_dev_test_flag(hdev, HCI_UNCONFIGURED) && 16028c2ecf20Sopenharmony_ci !hci_dev_test_flag(hdev, HCI_USER_CHANNEL) && 16038c2ecf20Sopenharmony_ci hci_dev_test_flag(hdev, HCI_MGMT) && 16048c2ecf20Sopenharmony_ci hdev->dev_type == HCI_PRIMARY) { 16058c2ecf20Sopenharmony_ci ret = __hci_req_hci_power_on(hdev); 16068c2ecf20Sopenharmony_ci mgmt_power_on(hdev, ret); 16078c2ecf20Sopenharmony_ci } 16088c2ecf20Sopenharmony_ci } else { 16098c2ecf20Sopenharmony_ci /* Init failed, cleanup */ 16108c2ecf20Sopenharmony_ci flush_work(&hdev->tx_work); 16118c2ecf20Sopenharmony_ci 16128c2ecf20Sopenharmony_ci /* Since hci_rx_work() is possible to awake new cmd_work 16138c2ecf20Sopenharmony_ci * it should be flushed first to avoid unexpected call of 16148c2ecf20Sopenharmony_ci * hci_cmd_work() 16158c2ecf20Sopenharmony_ci */ 16168c2ecf20Sopenharmony_ci flush_work(&hdev->rx_work); 16178c2ecf20Sopenharmony_ci flush_work(&hdev->cmd_work); 16188c2ecf20Sopenharmony_ci 16198c2ecf20Sopenharmony_ci skb_queue_purge(&hdev->cmd_q); 16208c2ecf20Sopenharmony_ci skb_queue_purge(&hdev->rx_q); 16218c2ecf20Sopenharmony_ci 16228c2ecf20Sopenharmony_ci if (hdev->flush) 16238c2ecf20Sopenharmony_ci hdev->flush(hdev); 16248c2ecf20Sopenharmony_ci 16258c2ecf20Sopenharmony_ci if (hdev->sent_cmd) { 16268c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&hdev->cmd_timer); 16278c2ecf20Sopenharmony_ci kfree_skb(hdev->sent_cmd); 16288c2ecf20Sopenharmony_ci hdev->sent_cmd = NULL; 16298c2ecf20Sopenharmony_ci } 16308c2ecf20Sopenharmony_ci 16318c2ecf20Sopenharmony_ci clear_bit(HCI_RUNNING, &hdev->flags); 16328c2ecf20Sopenharmony_ci hci_sock_dev_event(hdev, HCI_DEV_CLOSE); 16338c2ecf20Sopenharmony_ci 16348c2ecf20Sopenharmony_ci hdev->close(hdev); 16358c2ecf20Sopenharmony_ci hdev->flags &= BIT(HCI_RAW); 16368c2ecf20Sopenharmony_ci } 16378c2ecf20Sopenharmony_ci 16388c2ecf20Sopenharmony_cidone: 16398c2ecf20Sopenharmony_ci hci_req_sync_unlock(hdev); 16408c2ecf20Sopenharmony_ci return ret; 16418c2ecf20Sopenharmony_ci} 16428c2ecf20Sopenharmony_ci 16438c2ecf20Sopenharmony_ci/* ---- HCI ioctl helpers ---- */ 16448c2ecf20Sopenharmony_ci 16458c2ecf20Sopenharmony_ciint hci_dev_open(__u16 dev) 16468c2ecf20Sopenharmony_ci{ 16478c2ecf20Sopenharmony_ci struct hci_dev *hdev; 16488c2ecf20Sopenharmony_ci int err; 16498c2ecf20Sopenharmony_ci 16508c2ecf20Sopenharmony_ci hdev = hci_dev_get(dev); 16518c2ecf20Sopenharmony_ci if (!hdev) 16528c2ecf20Sopenharmony_ci return -ENODEV; 16538c2ecf20Sopenharmony_ci 16548c2ecf20Sopenharmony_ci /* Devices that are marked as unconfigured can only be powered 16558c2ecf20Sopenharmony_ci * up as user channel. Trying to bring them up as normal devices 16568c2ecf20Sopenharmony_ci * will result into a failure. Only user channel operation is 16578c2ecf20Sopenharmony_ci * possible. 16588c2ecf20Sopenharmony_ci * 16598c2ecf20Sopenharmony_ci * When this function is called for a user channel, the flag 16608c2ecf20Sopenharmony_ci * HCI_USER_CHANNEL will be set first before attempting to 16618c2ecf20Sopenharmony_ci * open the device. 16628c2ecf20Sopenharmony_ci */ 16638c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) && 16648c2ecf20Sopenharmony_ci !hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) { 16658c2ecf20Sopenharmony_ci err = -EOPNOTSUPP; 16668c2ecf20Sopenharmony_ci goto done; 16678c2ecf20Sopenharmony_ci } 16688c2ecf20Sopenharmony_ci 16698c2ecf20Sopenharmony_ci /* We need to ensure that no other power on/off work is pending 16708c2ecf20Sopenharmony_ci * before proceeding to call hci_dev_do_open. This is 16718c2ecf20Sopenharmony_ci * particularly important if the setup procedure has not yet 16728c2ecf20Sopenharmony_ci * completed. 16738c2ecf20Sopenharmony_ci */ 16748c2ecf20Sopenharmony_ci if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) 16758c2ecf20Sopenharmony_ci cancel_delayed_work(&hdev->power_off); 16768c2ecf20Sopenharmony_ci 16778c2ecf20Sopenharmony_ci /* After this call it is guaranteed that the setup procedure 16788c2ecf20Sopenharmony_ci * has finished. This means that error conditions like RFKILL 16798c2ecf20Sopenharmony_ci * or no valid public or static random address apply. 16808c2ecf20Sopenharmony_ci */ 16818c2ecf20Sopenharmony_ci flush_workqueue(hdev->req_workqueue); 16828c2ecf20Sopenharmony_ci 16838c2ecf20Sopenharmony_ci /* For controllers not using the management interface and that 16848c2ecf20Sopenharmony_ci * are brought up using legacy ioctl, set the HCI_BONDABLE bit 16858c2ecf20Sopenharmony_ci * so that pairing works for them. Once the management interface 16868c2ecf20Sopenharmony_ci * is in use this bit will be cleared again and userspace has 16878c2ecf20Sopenharmony_ci * to explicitly enable it. 16888c2ecf20Sopenharmony_ci */ 16898c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL) && 16908c2ecf20Sopenharmony_ci !hci_dev_test_flag(hdev, HCI_MGMT)) 16918c2ecf20Sopenharmony_ci hci_dev_set_flag(hdev, HCI_BONDABLE); 16928c2ecf20Sopenharmony_ci 16938c2ecf20Sopenharmony_ci err = hci_dev_do_open(hdev); 16948c2ecf20Sopenharmony_ci 16958c2ecf20Sopenharmony_cidone: 16968c2ecf20Sopenharmony_ci hci_dev_put(hdev); 16978c2ecf20Sopenharmony_ci return err; 16988c2ecf20Sopenharmony_ci} 16998c2ecf20Sopenharmony_ci 17008c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */ 17018c2ecf20Sopenharmony_cistatic void hci_pend_le_actions_clear(struct hci_dev *hdev) 17028c2ecf20Sopenharmony_ci{ 17038c2ecf20Sopenharmony_ci struct hci_conn_params *p; 17048c2ecf20Sopenharmony_ci 17058c2ecf20Sopenharmony_ci list_for_each_entry(p, &hdev->le_conn_params, list) { 17068c2ecf20Sopenharmony_ci if (p->conn) { 17078c2ecf20Sopenharmony_ci hci_conn_drop(p->conn); 17088c2ecf20Sopenharmony_ci hci_conn_put(p->conn); 17098c2ecf20Sopenharmony_ci p->conn = NULL; 17108c2ecf20Sopenharmony_ci } 17118c2ecf20Sopenharmony_ci list_del_init(&p->action); 17128c2ecf20Sopenharmony_ci } 17138c2ecf20Sopenharmony_ci 17148c2ecf20Sopenharmony_ci BT_DBG("All LE pending actions cleared"); 17158c2ecf20Sopenharmony_ci} 17168c2ecf20Sopenharmony_ci 17178c2ecf20Sopenharmony_ciint hci_dev_do_close(struct hci_dev *hdev) 17188c2ecf20Sopenharmony_ci{ 17198c2ecf20Sopenharmony_ci bool auto_off; 17208c2ecf20Sopenharmony_ci 17218c2ecf20Sopenharmony_ci BT_DBG("%s %p", hdev->name, hdev); 17228c2ecf20Sopenharmony_ci 17238c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_UNREGISTER) && 17248c2ecf20Sopenharmony_ci !hci_dev_test_flag(hdev, HCI_USER_CHANNEL) && 17258c2ecf20Sopenharmony_ci test_bit(HCI_UP, &hdev->flags)) { 17268c2ecf20Sopenharmony_ci /* Execute vendor specific shutdown routine */ 17278c2ecf20Sopenharmony_ci if (hdev->shutdown) 17288c2ecf20Sopenharmony_ci hdev->shutdown(hdev); 17298c2ecf20Sopenharmony_ci } 17308c2ecf20Sopenharmony_ci 17318c2ecf20Sopenharmony_ci cancel_delayed_work(&hdev->power_off); 17328c2ecf20Sopenharmony_ci 17338c2ecf20Sopenharmony_ci hci_request_cancel_all(hdev); 17348c2ecf20Sopenharmony_ci hci_req_sync_lock(hdev); 17358c2ecf20Sopenharmony_ci 17368c2ecf20Sopenharmony_ci if (!test_and_clear_bit(HCI_UP, &hdev->flags)) { 17378c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&hdev->cmd_timer); 17388c2ecf20Sopenharmony_ci hci_req_sync_unlock(hdev); 17398c2ecf20Sopenharmony_ci return 0; 17408c2ecf20Sopenharmony_ci } 17418c2ecf20Sopenharmony_ci 17428c2ecf20Sopenharmony_ci hci_leds_update_powered(hdev, false); 17438c2ecf20Sopenharmony_ci 17448c2ecf20Sopenharmony_ci /* Flush RX and TX works */ 17458c2ecf20Sopenharmony_ci flush_work(&hdev->tx_work); 17468c2ecf20Sopenharmony_ci flush_work(&hdev->rx_work); 17478c2ecf20Sopenharmony_ci 17488c2ecf20Sopenharmony_ci if (hdev->discov_timeout > 0) { 17498c2ecf20Sopenharmony_ci hdev->discov_timeout = 0; 17508c2ecf20Sopenharmony_ci hci_dev_clear_flag(hdev, HCI_DISCOVERABLE); 17518c2ecf20Sopenharmony_ci hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE); 17528c2ecf20Sopenharmony_ci } 17538c2ecf20Sopenharmony_ci 17548c2ecf20Sopenharmony_ci if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE)) 17558c2ecf20Sopenharmony_ci cancel_delayed_work(&hdev->service_cache); 17568c2ecf20Sopenharmony_ci 17578c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_MGMT)) { 17588c2ecf20Sopenharmony_ci struct adv_info *adv_instance; 17598c2ecf20Sopenharmony_ci 17608c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&hdev->rpa_expired); 17618c2ecf20Sopenharmony_ci 17628c2ecf20Sopenharmony_ci list_for_each_entry(adv_instance, &hdev->adv_instances, list) 17638c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&adv_instance->rpa_expired_cb); 17648c2ecf20Sopenharmony_ci } 17658c2ecf20Sopenharmony_ci 17668c2ecf20Sopenharmony_ci /* Avoid potential lockdep warnings from the *_flush() calls by 17678c2ecf20Sopenharmony_ci * ensuring the workqueue is empty up front. 17688c2ecf20Sopenharmony_ci */ 17698c2ecf20Sopenharmony_ci drain_workqueue(hdev->workqueue); 17708c2ecf20Sopenharmony_ci 17718c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 17728c2ecf20Sopenharmony_ci 17738c2ecf20Sopenharmony_ci hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 17748c2ecf20Sopenharmony_ci 17758c2ecf20Sopenharmony_ci auto_off = hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF); 17768c2ecf20Sopenharmony_ci 17778c2ecf20Sopenharmony_ci if (!auto_off && hdev->dev_type == HCI_PRIMARY && 17788c2ecf20Sopenharmony_ci !hci_dev_test_flag(hdev, HCI_USER_CHANNEL) && 17798c2ecf20Sopenharmony_ci hci_dev_test_flag(hdev, HCI_MGMT)) 17808c2ecf20Sopenharmony_ci __mgmt_power_off(hdev); 17818c2ecf20Sopenharmony_ci 17828c2ecf20Sopenharmony_ci hci_inquiry_cache_flush(hdev); 17838c2ecf20Sopenharmony_ci hci_pend_le_actions_clear(hdev); 17848c2ecf20Sopenharmony_ci hci_conn_hash_flush(hdev); 17858c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 17868c2ecf20Sopenharmony_ci 17878c2ecf20Sopenharmony_ci smp_unregister(hdev); 17888c2ecf20Sopenharmony_ci 17898c2ecf20Sopenharmony_ci hci_sock_dev_event(hdev, HCI_DEV_DOWN); 17908c2ecf20Sopenharmony_ci 17918c2ecf20Sopenharmony_ci msft_do_close(hdev); 17928c2ecf20Sopenharmony_ci 17938c2ecf20Sopenharmony_ci if (hdev->flush) 17948c2ecf20Sopenharmony_ci hdev->flush(hdev); 17958c2ecf20Sopenharmony_ci 17968c2ecf20Sopenharmony_ci /* Reset device */ 17978c2ecf20Sopenharmony_ci skb_queue_purge(&hdev->cmd_q); 17988c2ecf20Sopenharmony_ci atomic_set(&hdev->cmd_cnt, 1); 17998c2ecf20Sopenharmony_ci if (test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks) && 18008c2ecf20Sopenharmony_ci !auto_off && !hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) { 18018c2ecf20Sopenharmony_ci set_bit(HCI_INIT, &hdev->flags); 18028c2ecf20Sopenharmony_ci __hci_req_sync(hdev, hci_reset_req, 0, HCI_CMD_TIMEOUT, NULL); 18038c2ecf20Sopenharmony_ci clear_bit(HCI_INIT, &hdev->flags); 18048c2ecf20Sopenharmony_ci } 18058c2ecf20Sopenharmony_ci 18068c2ecf20Sopenharmony_ci /* flush cmd work */ 18078c2ecf20Sopenharmony_ci flush_work(&hdev->cmd_work); 18088c2ecf20Sopenharmony_ci 18098c2ecf20Sopenharmony_ci /* Drop queues */ 18108c2ecf20Sopenharmony_ci skb_queue_purge(&hdev->rx_q); 18118c2ecf20Sopenharmony_ci skb_queue_purge(&hdev->cmd_q); 18128c2ecf20Sopenharmony_ci skb_queue_purge(&hdev->raw_q); 18138c2ecf20Sopenharmony_ci 18148c2ecf20Sopenharmony_ci /* Drop last sent command */ 18158c2ecf20Sopenharmony_ci if (hdev->sent_cmd) { 18168c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&hdev->cmd_timer); 18178c2ecf20Sopenharmony_ci kfree_skb(hdev->sent_cmd); 18188c2ecf20Sopenharmony_ci hdev->sent_cmd = NULL; 18198c2ecf20Sopenharmony_ci } 18208c2ecf20Sopenharmony_ci 18218c2ecf20Sopenharmony_ci clear_bit(HCI_RUNNING, &hdev->flags); 18228c2ecf20Sopenharmony_ci hci_sock_dev_event(hdev, HCI_DEV_CLOSE); 18238c2ecf20Sopenharmony_ci 18248c2ecf20Sopenharmony_ci if (test_and_clear_bit(SUSPEND_POWERING_DOWN, hdev->suspend_tasks)) 18258c2ecf20Sopenharmony_ci wake_up(&hdev->suspend_wait_q); 18268c2ecf20Sopenharmony_ci 18278c2ecf20Sopenharmony_ci /* After this point our queues are empty 18288c2ecf20Sopenharmony_ci * and no tasks are scheduled. */ 18298c2ecf20Sopenharmony_ci hdev->close(hdev); 18308c2ecf20Sopenharmony_ci 18318c2ecf20Sopenharmony_ci /* Clear flags */ 18328c2ecf20Sopenharmony_ci hdev->flags &= BIT(HCI_RAW); 18338c2ecf20Sopenharmony_ci hci_dev_clear_volatile_flags(hdev); 18348c2ecf20Sopenharmony_ci 18358c2ecf20Sopenharmony_ci /* Controller radio is available but is currently powered down */ 18368c2ecf20Sopenharmony_ci hdev->amp_status = AMP_STATUS_POWERED_DOWN; 18378c2ecf20Sopenharmony_ci 18388c2ecf20Sopenharmony_ci memset(hdev->eir, 0, sizeof(hdev->eir)); 18398c2ecf20Sopenharmony_ci memset(hdev->dev_class, 0, sizeof(hdev->dev_class)); 18408c2ecf20Sopenharmony_ci bacpy(&hdev->random_addr, BDADDR_ANY); 18418c2ecf20Sopenharmony_ci 18428c2ecf20Sopenharmony_ci hci_req_sync_unlock(hdev); 18438c2ecf20Sopenharmony_ci 18448c2ecf20Sopenharmony_ci hci_dev_put(hdev); 18458c2ecf20Sopenharmony_ci return 0; 18468c2ecf20Sopenharmony_ci} 18478c2ecf20Sopenharmony_ci 18488c2ecf20Sopenharmony_ciint hci_dev_close(__u16 dev) 18498c2ecf20Sopenharmony_ci{ 18508c2ecf20Sopenharmony_ci struct hci_dev *hdev; 18518c2ecf20Sopenharmony_ci int err; 18528c2ecf20Sopenharmony_ci 18538c2ecf20Sopenharmony_ci hdev = hci_dev_get(dev); 18548c2ecf20Sopenharmony_ci if (!hdev) 18558c2ecf20Sopenharmony_ci return -ENODEV; 18568c2ecf20Sopenharmony_ci 18578c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) { 18588c2ecf20Sopenharmony_ci err = -EBUSY; 18598c2ecf20Sopenharmony_ci goto done; 18608c2ecf20Sopenharmony_ci } 18618c2ecf20Sopenharmony_ci 18628c2ecf20Sopenharmony_ci if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) 18638c2ecf20Sopenharmony_ci cancel_delayed_work(&hdev->power_off); 18648c2ecf20Sopenharmony_ci 18658c2ecf20Sopenharmony_ci err = hci_dev_do_close(hdev); 18668c2ecf20Sopenharmony_ci 18678c2ecf20Sopenharmony_cidone: 18688c2ecf20Sopenharmony_ci hci_dev_put(hdev); 18698c2ecf20Sopenharmony_ci return err; 18708c2ecf20Sopenharmony_ci} 18718c2ecf20Sopenharmony_ci 18728c2ecf20Sopenharmony_cistatic int hci_dev_do_reset(struct hci_dev *hdev) 18738c2ecf20Sopenharmony_ci{ 18748c2ecf20Sopenharmony_ci int ret; 18758c2ecf20Sopenharmony_ci 18768c2ecf20Sopenharmony_ci BT_DBG("%s %p", hdev->name, hdev); 18778c2ecf20Sopenharmony_ci 18788c2ecf20Sopenharmony_ci hci_req_sync_lock(hdev); 18798c2ecf20Sopenharmony_ci 18808c2ecf20Sopenharmony_ci /* Drop queues */ 18818c2ecf20Sopenharmony_ci skb_queue_purge(&hdev->rx_q); 18828c2ecf20Sopenharmony_ci skb_queue_purge(&hdev->cmd_q); 18838c2ecf20Sopenharmony_ci 18848c2ecf20Sopenharmony_ci /* Avoid potential lockdep warnings from the *_flush() calls by 18858c2ecf20Sopenharmony_ci * ensuring the workqueue is empty up front. 18868c2ecf20Sopenharmony_ci */ 18878c2ecf20Sopenharmony_ci drain_workqueue(hdev->workqueue); 18888c2ecf20Sopenharmony_ci 18898c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 18908c2ecf20Sopenharmony_ci hci_inquiry_cache_flush(hdev); 18918c2ecf20Sopenharmony_ci hci_conn_hash_flush(hdev); 18928c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 18938c2ecf20Sopenharmony_ci 18948c2ecf20Sopenharmony_ci if (hdev->flush) 18958c2ecf20Sopenharmony_ci hdev->flush(hdev); 18968c2ecf20Sopenharmony_ci 18978c2ecf20Sopenharmony_ci atomic_set(&hdev->cmd_cnt, 1); 18988c2ecf20Sopenharmony_ci hdev->acl_cnt = 0; hdev->sco_cnt = 0; hdev->le_cnt = 0; 18998c2ecf20Sopenharmony_ci 19008c2ecf20Sopenharmony_ci ret = __hci_req_sync(hdev, hci_reset_req, 0, HCI_INIT_TIMEOUT, NULL); 19018c2ecf20Sopenharmony_ci 19028c2ecf20Sopenharmony_ci hci_req_sync_unlock(hdev); 19038c2ecf20Sopenharmony_ci return ret; 19048c2ecf20Sopenharmony_ci} 19058c2ecf20Sopenharmony_ci 19068c2ecf20Sopenharmony_ciint hci_dev_reset(__u16 dev) 19078c2ecf20Sopenharmony_ci{ 19088c2ecf20Sopenharmony_ci struct hci_dev *hdev; 19098c2ecf20Sopenharmony_ci int err; 19108c2ecf20Sopenharmony_ci 19118c2ecf20Sopenharmony_ci hdev = hci_dev_get(dev); 19128c2ecf20Sopenharmony_ci if (!hdev) 19138c2ecf20Sopenharmony_ci return -ENODEV; 19148c2ecf20Sopenharmony_ci 19158c2ecf20Sopenharmony_ci if (!test_bit(HCI_UP, &hdev->flags)) { 19168c2ecf20Sopenharmony_ci err = -ENETDOWN; 19178c2ecf20Sopenharmony_ci goto done; 19188c2ecf20Sopenharmony_ci } 19198c2ecf20Sopenharmony_ci 19208c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) { 19218c2ecf20Sopenharmony_ci err = -EBUSY; 19228c2ecf20Sopenharmony_ci goto done; 19238c2ecf20Sopenharmony_ci } 19248c2ecf20Sopenharmony_ci 19258c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) { 19268c2ecf20Sopenharmony_ci err = -EOPNOTSUPP; 19278c2ecf20Sopenharmony_ci goto done; 19288c2ecf20Sopenharmony_ci } 19298c2ecf20Sopenharmony_ci 19308c2ecf20Sopenharmony_ci err = hci_dev_do_reset(hdev); 19318c2ecf20Sopenharmony_ci 19328c2ecf20Sopenharmony_cidone: 19338c2ecf20Sopenharmony_ci hci_dev_put(hdev); 19348c2ecf20Sopenharmony_ci return err; 19358c2ecf20Sopenharmony_ci} 19368c2ecf20Sopenharmony_ci 19378c2ecf20Sopenharmony_ciint hci_dev_reset_stat(__u16 dev) 19388c2ecf20Sopenharmony_ci{ 19398c2ecf20Sopenharmony_ci struct hci_dev *hdev; 19408c2ecf20Sopenharmony_ci int ret = 0; 19418c2ecf20Sopenharmony_ci 19428c2ecf20Sopenharmony_ci hdev = hci_dev_get(dev); 19438c2ecf20Sopenharmony_ci if (!hdev) 19448c2ecf20Sopenharmony_ci return -ENODEV; 19458c2ecf20Sopenharmony_ci 19468c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) { 19478c2ecf20Sopenharmony_ci ret = -EBUSY; 19488c2ecf20Sopenharmony_ci goto done; 19498c2ecf20Sopenharmony_ci } 19508c2ecf20Sopenharmony_ci 19518c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) { 19528c2ecf20Sopenharmony_ci ret = -EOPNOTSUPP; 19538c2ecf20Sopenharmony_ci goto done; 19548c2ecf20Sopenharmony_ci } 19558c2ecf20Sopenharmony_ci 19568c2ecf20Sopenharmony_ci memset(&hdev->stat, 0, sizeof(struct hci_dev_stats)); 19578c2ecf20Sopenharmony_ci 19588c2ecf20Sopenharmony_cidone: 19598c2ecf20Sopenharmony_ci hci_dev_put(hdev); 19608c2ecf20Sopenharmony_ci return ret; 19618c2ecf20Sopenharmony_ci} 19628c2ecf20Sopenharmony_ci 19638c2ecf20Sopenharmony_cistatic void hci_update_scan_state(struct hci_dev *hdev, u8 scan) 19648c2ecf20Sopenharmony_ci{ 19658c2ecf20Sopenharmony_ci bool conn_changed, discov_changed; 19668c2ecf20Sopenharmony_ci 19678c2ecf20Sopenharmony_ci BT_DBG("%s scan 0x%02x", hdev->name, scan); 19688c2ecf20Sopenharmony_ci 19698c2ecf20Sopenharmony_ci if ((scan & SCAN_PAGE)) 19708c2ecf20Sopenharmony_ci conn_changed = !hci_dev_test_and_set_flag(hdev, 19718c2ecf20Sopenharmony_ci HCI_CONNECTABLE); 19728c2ecf20Sopenharmony_ci else 19738c2ecf20Sopenharmony_ci conn_changed = hci_dev_test_and_clear_flag(hdev, 19748c2ecf20Sopenharmony_ci HCI_CONNECTABLE); 19758c2ecf20Sopenharmony_ci 19768c2ecf20Sopenharmony_ci if ((scan & SCAN_INQUIRY)) { 19778c2ecf20Sopenharmony_ci discov_changed = !hci_dev_test_and_set_flag(hdev, 19788c2ecf20Sopenharmony_ci HCI_DISCOVERABLE); 19798c2ecf20Sopenharmony_ci } else { 19808c2ecf20Sopenharmony_ci hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE); 19818c2ecf20Sopenharmony_ci discov_changed = hci_dev_test_and_clear_flag(hdev, 19828c2ecf20Sopenharmony_ci HCI_DISCOVERABLE); 19838c2ecf20Sopenharmony_ci } 19848c2ecf20Sopenharmony_ci 19858c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_MGMT)) 19868c2ecf20Sopenharmony_ci return; 19878c2ecf20Sopenharmony_ci 19888c2ecf20Sopenharmony_ci if (conn_changed || discov_changed) { 19898c2ecf20Sopenharmony_ci /* In case this was disabled through mgmt */ 19908c2ecf20Sopenharmony_ci hci_dev_set_flag(hdev, HCI_BREDR_ENABLED); 19918c2ecf20Sopenharmony_ci 19928c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) 19938c2ecf20Sopenharmony_ci hci_req_update_adv_data(hdev, hdev->cur_adv_instance); 19948c2ecf20Sopenharmony_ci 19958c2ecf20Sopenharmony_ci mgmt_new_settings(hdev); 19968c2ecf20Sopenharmony_ci } 19978c2ecf20Sopenharmony_ci} 19988c2ecf20Sopenharmony_ci 19998c2ecf20Sopenharmony_ciint hci_dev_cmd(unsigned int cmd, void __user *arg) 20008c2ecf20Sopenharmony_ci{ 20018c2ecf20Sopenharmony_ci struct hci_dev *hdev; 20028c2ecf20Sopenharmony_ci struct hci_dev_req dr; 20038c2ecf20Sopenharmony_ci int err = 0; 20048c2ecf20Sopenharmony_ci 20058c2ecf20Sopenharmony_ci if (copy_from_user(&dr, arg, sizeof(dr))) 20068c2ecf20Sopenharmony_ci return -EFAULT; 20078c2ecf20Sopenharmony_ci 20088c2ecf20Sopenharmony_ci hdev = hci_dev_get(dr.dev_id); 20098c2ecf20Sopenharmony_ci if (!hdev) 20108c2ecf20Sopenharmony_ci return -ENODEV; 20118c2ecf20Sopenharmony_ci 20128c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) { 20138c2ecf20Sopenharmony_ci err = -EBUSY; 20148c2ecf20Sopenharmony_ci goto done; 20158c2ecf20Sopenharmony_ci } 20168c2ecf20Sopenharmony_ci 20178c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) { 20188c2ecf20Sopenharmony_ci err = -EOPNOTSUPP; 20198c2ecf20Sopenharmony_ci goto done; 20208c2ecf20Sopenharmony_ci } 20218c2ecf20Sopenharmony_ci 20228c2ecf20Sopenharmony_ci if (hdev->dev_type != HCI_PRIMARY) { 20238c2ecf20Sopenharmony_ci err = -EOPNOTSUPP; 20248c2ecf20Sopenharmony_ci goto done; 20258c2ecf20Sopenharmony_ci } 20268c2ecf20Sopenharmony_ci 20278c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) { 20288c2ecf20Sopenharmony_ci err = -EOPNOTSUPP; 20298c2ecf20Sopenharmony_ci goto done; 20308c2ecf20Sopenharmony_ci } 20318c2ecf20Sopenharmony_ci 20328c2ecf20Sopenharmony_ci switch (cmd) { 20338c2ecf20Sopenharmony_ci case HCISETAUTH: 20348c2ecf20Sopenharmony_ci err = hci_req_sync(hdev, hci_auth_req, dr.dev_opt, 20358c2ecf20Sopenharmony_ci HCI_INIT_TIMEOUT, NULL); 20368c2ecf20Sopenharmony_ci break; 20378c2ecf20Sopenharmony_ci 20388c2ecf20Sopenharmony_ci case HCISETENCRYPT: 20398c2ecf20Sopenharmony_ci if (!lmp_encrypt_capable(hdev)) { 20408c2ecf20Sopenharmony_ci err = -EOPNOTSUPP; 20418c2ecf20Sopenharmony_ci break; 20428c2ecf20Sopenharmony_ci } 20438c2ecf20Sopenharmony_ci 20448c2ecf20Sopenharmony_ci if (!test_bit(HCI_AUTH, &hdev->flags)) { 20458c2ecf20Sopenharmony_ci /* Auth must be enabled first */ 20468c2ecf20Sopenharmony_ci err = hci_req_sync(hdev, hci_auth_req, dr.dev_opt, 20478c2ecf20Sopenharmony_ci HCI_INIT_TIMEOUT, NULL); 20488c2ecf20Sopenharmony_ci if (err) 20498c2ecf20Sopenharmony_ci break; 20508c2ecf20Sopenharmony_ci } 20518c2ecf20Sopenharmony_ci 20528c2ecf20Sopenharmony_ci err = hci_req_sync(hdev, hci_encrypt_req, dr.dev_opt, 20538c2ecf20Sopenharmony_ci HCI_INIT_TIMEOUT, NULL); 20548c2ecf20Sopenharmony_ci break; 20558c2ecf20Sopenharmony_ci 20568c2ecf20Sopenharmony_ci case HCISETSCAN: 20578c2ecf20Sopenharmony_ci err = hci_req_sync(hdev, hci_scan_req, dr.dev_opt, 20588c2ecf20Sopenharmony_ci HCI_INIT_TIMEOUT, NULL); 20598c2ecf20Sopenharmony_ci 20608c2ecf20Sopenharmony_ci /* Ensure that the connectable and discoverable states 20618c2ecf20Sopenharmony_ci * get correctly modified as this was a non-mgmt change. 20628c2ecf20Sopenharmony_ci */ 20638c2ecf20Sopenharmony_ci if (!err) 20648c2ecf20Sopenharmony_ci hci_update_scan_state(hdev, dr.dev_opt); 20658c2ecf20Sopenharmony_ci break; 20668c2ecf20Sopenharmony_ci 20678c2ecf20Sopenharmony_ci case HCISETLINKPOL: 20688c2ecf20Sopenharmony_ci err = hci_req_sync(hdev, hci_linkpol_req, dr.dev_opt, 20698c2ecf20Sopenharmony_ci HCI_INIT_TIMEOUT, NULL); 20708c2ecf20Sopenharmony_ci break; 20718c2ecf20Sopenharmony_ci 20728c2ecf20Sopenharmony_ci case HCISETLINKMODE: 20738c2ecf20Sopenharmony_ci hdev->link_mode = ((__u16) dr.dev_opt) & 20748c2ecf20Sopenharmony_ci (HCI_LM_MASTER | HCI_LM_ACCEPT); 20758c2ecf20Sopenharmony_ci break; 20768c2ecf20Sopenharmony_ci 20778c2ecf20Sopenharmony_ci case HCISETPTYPE: 20788c2ecf20Sopenharmony_ci if (hdev->pkt_type == (__u16) dr.dev_opt) 20798c2ecf20Sopenharmony_ci break; 20808c2ecf20Sopenharmony_ci 20818c2ecf20Sopenharmony_ci hdev->pkt_type = (__u16) dr.dev_opt; 20828c2ecf20Sopenharmony_ci mgmt_phy_configuration_changed(hdev, NULL); 20838c2ecf20Sopenharmony_ci break; 20848c2ecf20Sopenharmony_ci 20858c2ecf20Sopenharmony_ci case HCISETACLMTU: 20868c2ecf20Sopenharmony_ci hdev->acl_mtu = *((__u16 *) &dr.dev_opt + 1); 20878c2ecf20Sopenharmony_ci hdev->acl_pkts = *((__u16 *) &dr.dev_opt + 0); 20888c2ecf20Sopenharmony_ci break; 20898c2ecf20Sopenharmony_ci 20908c2ecf20Sopenharmony_ci case HCISETSCOMTU: 20918c2ecf20Sopenharmony_ci hdev->sco_mtu = *((__u16 *) &dr.dev_opt + 1); 20928c2ecf20Sopenharmony_ci hdev->sco_pkts = *((__u16 *) &dr.dev_opt + 0); 20938c2ecf20Sopenharmony_ci break; 20948c2ecf20Sopenharmony_ci 20958c2ecf20Sopenharmony_ci default: 20968c2ecf20Sopenharmony_ci err = -EINVAL; 20978c2ecf20Sopenharmony_ci break; 20988c2ecf20Sopenharmony_ci } 20998c2ecf20Sopenharmony_ci 21008c2ecf20Sopenharmony_cidone: 21018c2ecf20Sopenharmony_ci hci_dev_put(hdev); 21028c2ecf20Sopenharmony_ci return err; 21038c2ecf20Sopenharmony_ci} 21048c2ecf20Sopenharmony_ci 21058c2ecf20Sopenharmony_ciint hci_get_dev_list(void __user *arg) 21068c2ecf20Sopenharmony_ci{ 21078c2ecf20Sopenharmony_ci struct hci_dev *hdev; 21088c2ecf20Sopenharmony_ci struct hci_dev_list_req *dl; 21098c2ecf20Sopenharmony_ci struct hci_dev_req *dr; 21108c2ecf20Sopenharmony_ci int n = 0, size, err; 21118c2ecf20Sopenharmony_ci __u16 dev_num; 21128c2ecf20Sopenharmony_ci 21138c2ecf20Sopenharmony_ci if (get_user(dev_num, (__u16 __user *) arg)) 21148c2ecf20Sopenharmony_ci return -EFAULT; 21158c2ecf20Sopenharmony_ci 21168c2ecf20Sopenharmony_ci if (!dev_num || dev_num > (PAGE_SIZE * 2) / sizeof(*dr)) 21178c2ecf20Sopenharmony_ci return -EINVAL; 21188c2ecf20Sopenharmony_ci 21198c2ecf20Sopenharmony_ci size = sizeof(*dl) + dev_num * sizeof(*dr); 21208c2ecf20Sopenharmony_ci 21218c2ecf20Sopenharmony_ci dl = kzalloc(size, GFP_KERNEL); 21228c2ecf20Sopenharmony_ci if (!dl) 21238c2ecf20Sopenharmony_ci return -ENOMEM; 21248c2ecf20Sopenharmony_ci 21258c2ecf20Sopenharmony_ci dr = dl->dev_req; 21268c2ecf20Sopenharmony_ci 21278c2ecf20Sopenharmony_ci read_lock(&hci_dev_list_lock); 21288c2ecf20Sopenharmony_ci list_for_each_entry(hdev, &hci_dev_list, list) { 21298c2ecf20Sopenharmony_ci unsigned long flags = hdev->flags; 21308c2ecf20Sopenharmony_ci 21318c2ecf20Sopenharmony_ci /* When the auto-off is configured it means the transport 21328c2ecf20Sopenharmony_ci * is running, but in that case still indicate that the 21338c2ecf20Sopenharmony_ci * device is actually down. 21348c2ecf20Sopenharmony_ci */ 21358c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_AUTO_OFF)) 21368c2ecf20Sopenharmony_ci flags &= ~BIT(HCI_UP); 21378c2ecf20Sopenharmony_ci 21388c2ecf20Sopenharmony_ci (dr + n)->dev_id = hdev->id; 21398c2ecf20Sopenharmony_ci (dr + n)->dev_opt = flags; 21408c2ecf20Sopenharmony_ci 21418c2ecf20Sopenharmony_ci if (++n >= dev_num) 21428c2ecf20Sopenharmony_ci break; 21438c2ecf20Sopenharmony_ci } 21448c2ecf20Sopenharmony_ci read_unlock(&hci_dev_list_lock); 21458c2ecf20Sopenharmony_ci 21468c2ecf20Sopenharmony_ci dl->dev_num = n; 21478c2ecf20Sopenharmony_ci size = sizeof(*dl) + n * sizeof(*dr); 21488c2ecf20Sopenharmony_ci 21498c2ecf20Sopenharmony_ci err = copy_to_user(arg, dl, size); 21508c2ecf20Sopenharmony_ci kfree(dl); 21518c2ecf20Sopenharmony_ci 21528c2ecf20Sopenharmony_ci return err ? -EFAULT : 0; 21538c2ecf20Sopenharmony_ci} 21548c2ecf20Sopenharmony_ci 21558c2ecf20Sopenharmony_ciint hci_get_dev_info(void __user *arg) 21568c2ecf20Sopenharmony_ci{ 21578c2ecf20Sopenharmony_ci struct hci_dev *hdev; 21588c2ecf20Sopenharmony_ci struct hci_dev_info di; 21598c2ecf20Sopenharmony_ci unsigned long flags; 21608c2ecf20Sopenharmony_ci int err = 0; 21618c2ecf20Sopenharmony_ci 21628c2ecf20Sopenharmony_ci if (copy_from_user(&di, arg, sizeof(di))) 21638c2ecf20Sopenharmony_ci return -EFAULT; 21648c2ecf20Sopenharmony_ci 21658c2ecf20Sopenharmony_ci hdev = hci_dev_get(di.dev_id); 21668c2ecf20Sopenharmony_ci if (!hdev) 21678c2ecf20Sopenharmony_ci return -ENODEV; 21688c2ecf20Sopenharmony_ci 21698c2ecf20Sopenharmony_ci /* When the auto-off is configured it means the transport 21708c2ecf20Sopenharmony_ci * is running, but in that case still indicate that the 21718c2ecf20Sopenharmony_ci * device is actually down. 21728c2ecf20Sopenharmony_ci */ 21738c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_AUTO_OFF)) 21748c2ecf20Sopenharmony_ci flags = hdev->flags & ~BIT(HCI_UP); 21758c2ecf20Sopenharmony_ci else 21768c2ecf20Sopenharmony_ci flags = hdev->flags; 21778c2ecf20Sopenharmony_ci 21788c2ecf20Sopenharmony_ci strscpy(di.name, hdev->name, sizeof(di.name)); 21798c2ecf20Sopenharmony_ci di.bdaddr = hdev->bdaddr; 21808c2ecf20Sopenharmony_ci di.type = (hdev->bus & 0x0f) | ((hdev->dev_type & 0x03) << 4); 21818c2ecf20Sopenharmony_ci di.flags = flags; 21828c2ecf20Sopenharmony_ci di.pkt_type = hdev->pkt_type; 21838c2ecf20Sopenharmony_ci if (lmp_bredr_capable(hdev)) { 21848c2ecf20Sopenharmony_ci di.acl_mtu = hdev->acl_mtu; 21858c2ecf20Sopenharmony_ci di.acl_pkts = hdev->acl_pkts; 21868c2ecf20Sopenharmony_ci di.sco_mtu = hdev->sco_mtu; 21878c2ecf20Sopenharmony_ci di.sco_pkts = hdev->sco_pkts; 21888c2ecf20Sopenharmony_ci } else { 21898c2ecf20Sopenharmony_ci di.acl_mtu = hdev->le_mtu; 21908c2ecf20Sopenharmony_ci di.acl_pkts = hdev->le_pkts; 21918c2ecf20Sopenharmony_ci di.sco_mtu = 0; 21928c2ecf20Sopenharmony_ci di.sco_pkts = 0; 21938c2ecf20Sopenharmony_ci } 21948c2ecf20Sopenharmony_ci di.link_policy = hdev->link_policy; 21958c2ecf20Sopenharmony_ci di.link_mode = hdev->link_mode; 21968c2ecf20Sopenharmony_ci 21978c2ecf20Sopenharmony_ci memcpy(&di.stat, &hdev->stat, sizeof(di.stat)); 21988c2ecf20Sopenharmony_ci memcpy(&di.features, &hdev->features, sizeof(di.features)); 21998c2ecf20Sopenharmony_ci 22008c2ecf20Sopenharmony_ci if (copy_to_user(arg, &di, sizeof(di))) 22018c2ecf20Sopenharmony_ci err = -EFAULT; 22028c2ecf20Sopenharmony_ci 22038c2ecf20Sopenharmony_ci hci_dev_put(hdev); 22048c2ecf20Sopenharmony_ci 22058c2ecf20Sopenharmony_ci return err; 22068c2ecf20Sopenharmony_ci} 22078c2ecf20Sopenharmony_ci 22088c2ecf20Sopenharmony_ci/* ---- Interface to HCI drivers ---- */ 22098c2ecf20Sopenharmony_ci 22108c2ecf20Sopenharmony_cistatic int hci_rfkill_set_block(void *data, bool blocked) 22118c2ecf20Sopenharmony_ci{ 22128c2ecf20Sopenharmony_ci struct hci_dev *hdev = data; 22138c2ecf20Sopenharmony_ci 22148c2ecf20Sopenharmony_ci BT_DBG("%p name %s blocked %d", hdev, hdev->name, blocked); 22158c2ecf20Sopenharmony_ci 22168c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) 22178c2ecf20Sopenharmony_ci return -EBUSY; 22188c2ecf20Sopenharmony_ci 22198c2ecf20Sopenharmony_ci if (blocked) { 22208c2ecf20Sopenharmony_ci hci_dev_set_flag(hdev, HCI_RFKILLED); 22218c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_SETUP) && 22228c2ecf20Sopenharmony_ci !hci_dev_test_flag(hdev, HCI_CONFIG)) 22238c2ecf20Sopenharmony_ci hci_dev_do_close(hdev); 22248c2ecf20Sopenharmony_ci } else { 22258c2ecf20Sopenharmony_ci hci_dev_clear_flag(hdev, HCI_RFKILLED); 22268c2ecf20Sopenharmony_ci } 22278c2ecf20Sopenharmony_ci 22288c2ecf20Sopenharmony_ci return 0; 22298c2ecf20Sopenharmony_ci} 22308c2ecf20Sopenharmony_ci 22318c2ecf20Sopenharmony_cistatic const struct rfkill_ops hci_rfkill_ops = { 22328c2ecf20Sopenharmony_ci .set_block = hci_rfkill_set_block, 22338c2ecf20Sopenharmony_ci}; 22348c2ecf20Sopenharmony_ci 22358c2ecf20Sopenharmony_cistatic void hci_power_on(struct work_struct *work) 22368c2ecf20Sopenharmony_ci{ 22378c2ecf20Sopenharmony_ci struct hci_dev *hdev = container_of(work, struct hci_dev, power_on); 22388c2ecf20Sopenharmony_ci int err; 22398c2ecf20Sopenharmony_ci 22408c2ecf20Sopenharmony_ci BT_DBG("%s", hdev->name); 22418c2ecf20Sopenharmony_ci 22428c2ecf20Sopenharmony_ci if (test_bit(HCI_UP, &hdev->flags) && 22438c2ecf20Sopenharmony_ci hci_dev_test_flag(hdev, HCI_MGMT) && 22448c2ecf20Sopenharmony_ci hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) { 22458c2ecf20Sopenharmony_ci cancel_delayed_work(&hdev->power_off); 22468c2ecf20Sopenharmony_ci hci_req_sync_lock(hdev); 22478c2ecf20Sopenharmony_ci err = __hci_req_hci_power_on(hdev); 22488c2ecf20Sopenharmony_ci hci_req_sync_unlock(hdev); 22498c2ecf20Sopenharmony_ci mgmt_power_on(hdev, err); 22508c2ecf20Sopenharmony_ci return; 22518c2ecf20Sopenharmony_ci } 22528c2ecf20Sopenharmony_ci 22538c2ecf20Sopenharmony_ci err = hci_dev_do_open(hdev); 22548c2ecf20Sopenharmony_ci if (err < 0) { 22558c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 22568c2ecf20Sopenharmony_ci mgmt_set_powered_failed(hdev, err); 22578c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 22588c2ecf20Sopenharmony_ci return; 22598c2ecf20Sopenharmony_ci } 22608c2ecf20Sopenharmony_ci 22618c2ecf20Sopenharmony_ci /* During the HCI setup phase, a few error conditions are 22628c2ecf20Sopenharmony_ci * ignored and they need to be checked now. If they are still 22638c2ecf20Sopenharmony_ci * valid, it is important to turn the device back off. 22648c2ecf20Sopenharmony_ci */ 22658c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_RFKILLED) || 22668c2ecf20Sopenharmony_ci hci_dev_test_flag(hdev, HCI_UNCONFIGURED) || 22678c2ecf20Sopenharmony_ci (hdev->dev_type == HCI_PRIMARY && 22688c2ecf20Sopenharmony_ci !bacmp(&hdev->bdaddr, BDADDR_ANY) && 22698c2ecf20Sopenharmony_ci !bacmp(&hdev->static_addr, BDADDR_ANY))) { 22708c2ecf20Sopenharmony_ci hci_dev_clear_flag(hdev, HCI_AUTO_OFF); 22718c2ecf20Sopenharmony_ci hci_dev_do_close(hdev); 22728c2ecf20Sopenharmony_ci } else if (hci_dev_test_flag(hdev, HCI_AUTO_OFF)) { 22738c2ecf20Sopenharmony_ci queue_delayed_work(hdev->req_workqueue, &hdev->power_off, 22748c2ecf20Sopenharmony_ci HCI_AUTO_OFF_TIMEOUT); 22758c2ecf20Sopenharmony_ci } 22768c2ecf20Sopenharmony_ci 22778c2ecf20Sopenharmony_ci if (hci_dev_test_and_clear_flag(hdev, HCI_SETUP)) { 22788c2ecf20Sopenharmony_ci /* For unconfigured devices, set the HCI_RAW flag 22798c2ecf20Sopenharmony_ci * so that userspace can easily identify them. 22808c2ecf20Sopenharmony_ci */ 22818c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) 22828c2ecf20Sopenharmony_ci set_bit(HCI_RAW, &hdev->flags); 22838c2ecf20Sopenharmony_ci 22848c2ecf20Sopenharmony_ci /* For fully configured devices, this will send 22858c2ecf20Sopenharmony_ci * the Index Added event. For unconfigured devices, 22868c2ecf20Sopenharmony_ci * it will send Unconfigued Index Added event. 22878c2ecf20Sopenharmony_ci * 22888c2ecf20Sopenharmony_ci * Devices with HCI_QUIRK_RAW_DEVICE are ignored 22898c2ecf20Sopenharmony_ci * and no event will be send. 22908c2ecf20Sopenharmony_ci */ 22918c2ecf20Sopenharmony_ci mgmt_index_added(hdev); 22928c2ecf20Sopenharmony_ci } else if (hci_dev_test_and_clear_flag(hdev, HCI_CONFIG)) { 22938c2ecf20Sopenharmony_ci /* When the controller is now configured, then it 22948c2ecf20Sopenharmony_ci * is important to clear the HCI_RAW flag. 22958c2ecf20Sopenharmony_ci */ 22968c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) 22978c2ecf20Sopenharmony_ci clear_bit(HCI_RAW, &hdev->flags); 22988c2ecf20Sopenharmony_ci 22998c2ecf20Sopenharmony_ci /* Powering on the controller with HCI_CONFIG set only 23008c2ecf20Sopenharmony_ci * happens with the transition from unconfigured to 23018c2ecf20Sopenharmony_ci * configured. This will send the Index Added event. 23028c2ecf20Sopenharmony_ci */ 23038c2ecf20Sopenharmony_ci mgmt_index_added(hdev); 23048c2ecf20Sopenharmony_ci } 23058c2ecf20Sopenharmony_ci} 23068c2ecf20Sopenharmony_ci 23078c2ecf20Sopenharmony_cistatic void hci_power_off(struct work_struct *work) 23088c2ecf20Sopenharmony_ci{ 23098c2ecf20Sopenharmony_ci struct hci_dev *hdev = container_of(work, struct hci_dev, 23108c2ecf20Sopenharmony_ci power_off.work); 23118c2ecf20Sopenharmony_ci 23128c2ecf20Sopenharmony_ci BT_DBG("%s", hdev->name); 23138c2ecf20Sopenharmony_ci 23148c2ecf20Sopenharmony_ci hci_dev_do_close(hdev); 23158c2ecf20Sopenharmony_ci} 23168c2ecf20Sopenharmony_ci 23178c2ecf20Sopenharmony_cistatic void hci_error_reset(struct work_struct *work) 23188c2ecf20Sopenharmony_ci{ 23198c2ecf20Sopenharmony_ci struct hci_dev *hdev = container_of(work, struct hci_dev, error_reset); 23208c2ecf20Sopenharmony_ci 23218c2ecf20Sopenharmony_ci hci_dev_hold(hdev); 23228c2ecf20Sopenharmony_ci BT_DBG("%s", hdev->name); 23238c2ecf20Sopenharmony_ci 23248c2ecf20Sopenharmony_ci if (hdev->hw_error) 23258c2ecf20Sopenharmony_ci hdev->hw_error(hdev, hdev->hw_error_code); 23268c2ecf20Sopenharmony_ci else 23278c2ecf20Sopenharmony_ci bt_dev_err(hdev, "hardware error 0x%2.2x", hdev->hw_error_code); 23288c2ecf20Sopenharmony_ci 23298c2ecf20Sopenharmony_ci if (!hci_dev_do_close(hdev)) 23308c2ecf20Sopenharmony_ci hci_dev_do_open(hdev); 23318c2ecf20Sopenharmony_ci 23328c2ecf20Sopenharmony_ci hci_dev_put(hdev); 23338c2ecf20Sopenharmony_ci} 23348c2ecf20Sopenharmony_ci 23358c2ecf20Sopenharmony_civoid hci_uuids_clear(struct hci_dev *hdev) 23368c2ecf20Sopenharmony_ci{ 23378c2ecf20Sopenharmony_ci struct bt_uuid *uuid, *tmp; 23388c2ecf20Sopenharmony_ci 23398c2ecf20Sopenharmony_ci list_for_each_entry_safe(uuid, tmp, &hdev->uuids, list) { 23408c2ecf20Sopenharmony_ci list_del(&uuid->list); 23418c2ecf20Sopenharmony_ci kfree(uuid); 23428c2ecf20Sopenharmony_ci } 23438c2ecf20Sopenharmony_ci} 23448c2ecf20Sopenharmony_ci 23458c2ecf20Sopenharmony_civoid hci_link_keys_clear(struct hci_dev *hdev) 23468c2ecf20Sopenharmony_ci{ 23478c2ecf20Sopenharmony_ci struct link_key *key, *tmp; 23488c2ecf20Sopenharmony_ci 23498c2ecf20Sopenharmony_ci list_for_each_entry_safe(key, tmp, &hdev->link_keys, list) { 23508c2ecf20Sopenharmony_ci list_del_rcu(&key->list); 23518c2ecf20Sopenharmony_ci kfree_rcu(key, rcu); 23528c2ecf20Sopenharmony_ci } 23538c2ecf20Sopenharmony_ci} 23548c2ecf20Sopenharmony_ci 23558c2ecf20Sopenharmony_civoid hci_smp_ltks_clear(struct hci_dev *hdev) 23568c2ecf20Sopenharmony_ci{ 23578c2ecf20Sopenharmony_ci struct smp_ltk *k, *tmp; 23588c2ecf20Sopenharmony_ci 23598c2ecf20Sopenharmony_ci list_for_each_entry_safe(k, tmp, &hdev->long_term_keys, list) { 23608c2ecf20Sopenharmony_ci list_del_rcu(&k->list); 23618c2ecf20Sopenharmony_ci kfree_rcu(k, rcu); 23628c2ecf20Sopenharmony_ci } 23638c2ecf20Sopenharmony_ci} 23648c2ecf20Sopenharmony_ci 23658c2ecf20Sopenharmony_civoid hci_smp_irks_clear(struct hci_dev *hdev) 23668c2ecf20Sopenharmony_ci{ 23678c2ecf20Sopenharmony_ci struct smp_irk *k, *tmp; 23688c2ecf20Sopenharmony_ci 23698c2ecf20Sopenharmony_ci list_for_each_entry_safe(k, tmp, &hdev->identity_resolving_keys, list) { 23708c2ecf20Sopenharmony_ci list_del_rcu(&k->list); 23718c2ecf20Sopenharmony_ci kfree_rcu(k, rcu); 23728c2ecf20Sopenharmony_ci } 23738c2ecf20Sopenharmony_ci} 23748c2ecf20Sopenharmony_ci 23758c2ecf20Sopenharmony_civoid hci_blocked_keys_clear(struct hci_dev *hdev) 23768c2ecf20Sopenharmony_ci{ 23778c2ecf20Sopenharmony_ci struct blocked_key *b, *tmp; 23788c2ecf20Sopenharmony_ci 23798c2ecf20Sopenharmony_ci list_for_each_entry_safe(b, tmp, &hdev->blocked_keys, list) { 23808c2ecf20Sopenharmony_ci list_del_rcu(&b->list); 23818c2ecf20Sopenharmony_ci kfree_rcu(b, rcu); 23828c2ecf20Sopenharmony_ci } 23838c2ecf20Sopenharmony_ci} 23848c2ecf20Sopenharmony_ci 23858c2ecf20Sopenharmony_cibool hci_is_blocked_key(struct hci_dev *hdev, u8 type, u8 val[16]) 23868c2ecf20Sopenharmony_ci{ 23878c2ecf20Sopenharmony_ci bool blocked = false; 23888c2ecf20Sopenharmony_ci struct blocked_key *b; 23898c2ecf20Sopenharmony_ci 23908c2ecf20Sopenharmony_ci rcu_read_lock(); 23918c2ecf20Sopenharmony_ci list_for_each_entry_rcu(b, &hdev->blocked_keys, list) { 23928c2ecf20Sopenharmony_ci if (b->type == type && !memcmp(b->val, val, sizeof(b->val))) { 23938c2ecf20Sopenharmony_ci blocked = true; 23948c2ecf20Sopenharmony_ci break; 23958c2ecf20Sopenharmony_ci } 23968c2ecf20Sopenharmony_ci } 23978c2ecf20Sopenharmony_ci 23988c2ecf20Sopenharmony_ci rcu_read_unlock(); 23998c2ecf20Sopenharmony_ci return blocked; 24008c2ecf20Sopenharmony_ci} 24018c2ecf20Sopenharmony_ci 24028c2ecf20Sopenharmony_cistruct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr) 24038c2ecf20Sopenharmony_ci{ 24048c2ecf20Sopenharmony_ci struct link_key *k; 24058c2ecf20Sopenharmony_ci 24068c2ecf20Sopenharmony_ci rcu_read_lock(); 24078c2ecf20Sopenharmony_ci list_for_each_entry_rcu(k, &hdev->link_keys, list) { 24088c2ecf20Sopenharmony_ci if (bacmp(bdaddr, &k->bdaddr) == 0) { 24098c2ecf20Sopenharmony_ci rcu_read_unlock(); 24108c2ecf20Sopenharmony_ci 24118c2ecf20Sopenharmony_ci if (hci_is_blocked_key(hdev, 24128c2ecf20Sopenharmony_ci HCI_BLOCKED_KEY_TYPE_LINKKEY, 24138c2ecf20Sopenharmony_ci k->val)) { 24148c2ecf20Sopenharmony_ci bt_dev_warn_ratelimited(hdev, 24158c2ecf20Sopenharmony_ci "Link key blocked for %pMR", 24168c2ecf20Sopenharmony_ci &k->bdaddr); 24178c2ecf20Sopenharmony_ci return NULL; 24188c2ecf20Sopenharmony_ci } 24198c2ecf20Sopenharmony_ci 24208c2ecf20Sopenharmony_ci return k; 24218c2ecf20Sopenharmony_ci } 24228c2ecf20Sopenharmony_ci } 24238c2ecf20Sopenharmony_ci rcu_read_unlock(); 24248c2ecf20Sopenharmony_ci 24258c2ecf20Sopenharmony_ci return NULL; 24268c2ecf20Sopenharmony_ci} 24278c2ecf20Sopenharmony_ci 24288c2ecf20Sopenharmony_cistatic bool hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn, 24298c2ecf20Sopenharmony_ci u8 key_type, u8 old_key_type) 24308c2ecf20Sopenharmony_ci{ 24318c2ecf20Sopenharmony_ci /* Legacy key */ 24328c2ecf20Sopenharmony_ci if (key_type < 0x03) 24338c2ecf20Sopenharmony_ci return true; 24348c2ecf20Sopenharmony_ci 24358c2ecf20Sopenharmony_ci /* Debug keys are insecure so don't store them persistently */ 24368c2ecf20Sopenharmony_ci if (key_type == HCI_LK_DEBUG_COMBINATION) 24378c2ecf20Sopenharmony_ci return false; 24388c2ecf20Sopenharmony_ci 24398c2ecf20Sopenharmony_ci /* Changed combination key and there's no previous one */ 24408c2ecf20Sopenharmony_ci if (key_type == HCI_LK_CHANGED_COMBINATION && old_key_type == 0xff) 24418c2ecf20Sopenharmony_ci return false; 24428c2ecf20Sopenharmony_ci 24438c2ecf20Sopenharmony_ci /* Security mode 3 case */ 24448c2ecf20Sopenharmony_ci if (!conn) 24458c2ecf20Sopenharmony_ci return true; 24468c2ecf20Sopenharmony_ci 24478c2ecf20Sopenharmony_ci /* BR/EDR key derived using SC from an LE link */ 24488c2ecf20Sopenharmony_ci if (conn->type == LE_LINK) 24498c2ecf20Sopenharmony_ci return true; 24508c2ecf20Sopenharmony_ci 24518c2ecf20Sopenharmony_ci /* Neither local nor remote side had no-bonding as requirement */ 24528c2ecf20Sopenharmony_ci if (conn->auth_type > 0x01 && conn->remote_auth > 0x01) 24538c2ecf20Sopenharmony_ci return true; 24548c2ecf20Sopenharmony_ci 24558c2ecf20Sopenharmony_ci /* Local side had dedicated bonding as requirement */ 24568c2ecf20Sopenharmony_ci if (conn->auth_type == 0x02 || conn->auth_type == 0x03) 24578c2ecf20Sopenharmony_ci return true; 24588c2ecf20Sopenharmony_ci 24598c2ecf20Sopenharmony_ci /* Remote side had dedicated bonding as requirement */ 24608c2ecf20Sopenharmony_ci if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) 24618c2ecf20Sopenharmony_ci return true; 24628c2ecf20Sopenharmony_ci 24638c2ecf20Sopenharmony_ci /* If none of the above criteria match, then don't store the key 24648c2ecf20Sopenharmony_ci * persistently */ 24658c2ecf20Sopenharmony_ci return false; 24668c2ecf20Sopenharmony_ci} 24678c2ecf20Sopenharmony_ci 24688c2ecf20Sopenharmony_cistatic u8 ltk_role(u8 type) 24698c2ecf20Sopenharmony_ci{ 24708c2ecf20Sopenharmony_ci if (type == SMP_LTK) 24718c2ecf20Sopenharmony_ci return HCI_ROLE_MASTER; 24728c2ecf20Sopenharmony_ci 24738c2ecf20Sopenharmony_ci return HCI_ROLE_SLAVE; 24748c2ecf20Sopenharmony_ci} 24758c2ecf20Sopenharmony_ci 24768c2ecf20Sopenharmony_cistruct smp_ltk *hci_find_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, 24778c2ecf20Sopenharmony_ci u8 addr_type, u8 role) 24788c2ecf20Sopenharmony_ci{ 24798c2ecf20Sopenharmony_ci struct smp_ltk *k; 24808c2ecf20Sopenharmony_ci 24818c2ecf20Sopenharmony_ci rcu_read_lock(); 24828c2ecf20Sopenharmony_ci list_for_each_entry_rcu(k, &hdev->long_term_keys, list) { 24838c2ecf20Sopenharmony_ci if (addr_type != k->bdaddr_type || bacmp(bdaddr, &k->bdaddr)) 24848c2ecf20Sopenharmony_ci continue; 24858c2ecf20Sopenharmony_ci 24868c2ecf20Sopenharmony_ci if (smp_ltk_is_sc(k) || ltk_role(k->type) == role) { 24878c2ecf20Sopenharmony_ci rcu_read_unlock(); 24888c2ecf20Sopenharmony_ci 24898c2ecf20Sopenharmony_ci if (hci_is_blocked_key(hdev, HCI_BLOCKED_KEY_TYPE_LTK, 24908c2ecf20Sopenharmony_ci k->val)) { 24918c2ecf20Sopenharmony_ci bt_dev_warn_ratelimited(hdev, 24928c2ecf20Sopenharmony_ci "LTK blocked for %pMR", 24938c2ecf20Sopenharmony_ci &k->bdaddr); 24948c2ecf20Sopenharmony_ci return NULL; 24958c2ecf20Sopenharmony_ci } 24968c2ecf20Sopenharmony_ci 24978c2ecf20Sopenharmony_ci return k; 24988c2ecf20Sopenharmony_ci } 24998c2ecf20Sopenharmony_ci } 25008c2ecf20Sopenharmony_ci rcu_read_unlock(); 25018c2ecf20Sopenharmony_ci 25028c2ecf20Sopenharmony_ci return NULL; 25038c2ecf20Sopenharmony_ci} 25048c2ecf20Sopenharmony_ci 25058c2ecf20Sopenharmony_cistruct smp_irk *hci_find_irk_by_rpa(struct hci_dev *hdev, bdaddr_t *rpa) 25068c2ecf20Sopenharmony_ci{ 25078c2ecf20Sopenharmony_ci struct smp_irk *irk_to_return = NULL; 25088c2ecf20Sopenharmony_ci struct smp_irk *irk; 25098c2ecf20Sopenharmony_ci 25108c2ecf20Sopenharmony_ci rcu_read_lock(); 25118c2ecf20Sopenharmony_ci list_for_each_entry_rcu(irk, &hdev->identity_resolving_keys, list) { 25128c2ecf20Sopenharmony_ci if (!bacmp(&irk->rpa, rpa)) { 25138c2ecf20Sopenharmony_ci irk_to_return = irk; 25148c2ecf20Sopenharmony_ci goto done; 25158c2ecf20Sopenharmony_ci } 25168c2ecf20Sopenharmony_ci } 25178c2ecf20Sopenharmony_ci 25188c2ecf20Sopenharmony_ci list_for_each_entry_rcu(irk, &hdev->identity_resolving_keys, list) { 25198c2ecf20Sopenharmony_ci if (smp_irk_matches(hdev, irk->val, rpa)) { 25208c2ecf20Sopenharmony_ci bacpy(&irk->rpa, rpa); 25218c2ecf20Sopenharmony_ci irk_to_return = irk; 25228c2ecf20Sopenharmony_ci goto done; 25238c2ecf20Sopenharmony_ci } 25248c2ecf20Sopenharmony_ci } 25258c2ecf20Sopenharmony_ci 25268c2ecf20Sopenharmony_cidone: 25278c2ecf20Sopenharmony_ci if (irk_to_return && hci_is_blocked_key(hdev, HCI_BLOCKED_KEY_TYPE_IRK, 25288c2ecf20Sopenharmony_ci irk_to_return->val)) { 25298c2ecf20Sopenharmony_ci bt_dev_warn_ratelimited(hdev, "Identity key blocked for %pMR", 25308c2ecf20Sopenharmony_ci &irk_to_return->bdaddr); 25318c2ecf20Sopenharmony_ci irk_to_return = NULL; 25328c2ecf20Sopenharmony_ci } 25338c2ecf20Sopenharmony_ci 25348c2ecf20Sopenharmony_ci rcu_read_unlock(); 25358c2ecf20Sopenharmony_ci 25368c2ecf20Sopenharmony_ci return irk_to_return; 25378c2ecf20Sopenharmony_ci} 25388c2ecf20Sopenharmony_ci 25398c2ecf20Sopenharmony_cistruct smp_irk *hci_find_irk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr, 25408c2ecf20Sopenharmony_ci u8 addr_type) 25418c2ecf20Sopenharmony_ci{ 25428c2ecf20Sopenharmony_ci struct smp_irk *irk_to_return = NULL; 25438c2ecf20Sopenharmony_ci struct smp_irk *irk; 25448c2ecf20Sopenharmony_ci 25458c2ecf20Sopenharmony_ci /* Identity Address must be public or static random */ 25468c2ecf20Sopenharmony_ci if (addr_type == ADDR_LE_DEV_RANDOM && (bdaddr->b[5] & 0xc0) != 0xc0) 25478c2ecf20Sopenharmony_ci return NULL; 25488c2ecf20Sopenharmony_ci 25498c2ecf20Sopenharmony_ci rcu_read_lock(); 25508c2ecf20Sopenharmony_ci list_for_each_entry_rcu(irk, &hdev->identity_resolving_keys, list) { 25518c2ecf20Sopenharmony_ci if (addr_type == irk->addr_type && 25528c2ecf20Sopenharmony_ci bacmp(bdaddr, &irk->bdaddr) == 0) { 25538c2ecf20Sopenharmony_ci irk_to_return = irk; 25548c2ecf20Sopenharmony_ci goto done; 25558c2ecf20Sopenharmony_ci } 25568c2ecf20Sopenharmony_ci } 25578c2ecf20Sopenharmony_ci 25588c2ecf20Sopenharmony_cidone: 25598c2ecf20Sopenharmony_ci 25608c2ecf20Sopenharmony_ci if (irk_to_return && hci_is_blocked_key(hdev, HCI_BLOCKED_KEY_TYPE_IRK, 25618c2ecf20Sopenharmony_ci irk_to_return->val)) { 25628c2ecf20Sopenharmony_ci bt_dev_warn_ratelimited(hdev, "Identity key blocked for %pMR", 25638c2ecf20Sopenharmony_ci &irk_to_return->bdaddr); 25648c2ecf20Sopenharmony_ci irk_to_return = NULL; 25658c2ecf20Sopenharmony_ci } 25668c2ecf20Sopenharmony_ci 25678c2ecf20Sopenharmony_ci rcu_read_unlock(); 25688c2ecf20Sopenharmony_ci 25698c2ecf20Sopenharmony_ci return irk_to_return; 25708c2ecf20Sopenharmony_ci} 25718c2ecf20Sopenharmony_ci 25728c2ecf20Sopenharmony_cistruct link_key *hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, 25738c2ecf20Sopenharmony_ci bdaddr_t *bdaddr, u8 *val, u8 type, 25748c2ecf20Sopenharmony_ci u8 pin_len, bool *persistent) 25758c2ecf20Sopenharmony_ci{ 25768c2ecf20Sopenharmony_ci struct link_key *key, *old_key; 25778c2ecf20Sopenharmony_ci u8 old_key_type; 25788c2ecf20Sopenharmony_ci 25798c2ecf20Sopenharmony_ci old_key = hci_find_link_key(hdev, bdaddr); 25808c2ecf20Sopenharmony_ci if (old_key) { 25818c2ecf20Sopenharmony_ci old_key_type = old_key->type; 25828c2ecf20Sopenharmony_ci key = old_key; 25838c2ecf20Sopenharmony_ci } else { 25848c2ecf20Sopenharmony_ci old_key_type = conn ? conn->key_type : 0xff; 25858c2ecf20Sopenharmony_ci key = kzalloc(sizeof(*key), GFP_KERNEL); 25868c2ecf20Sopenharmony_ci if (!key) 25878c2ecf20Sopenharmony_ci return NULL; 25888c2ecf20Sopenharmony_ci list_add_rcu(&key->list, &hdev->link_keys); 25898c2ecf20Sopenharmony_ci } 25908c2ecf20Sopenharmony_ci 25918c2ecf20Sopenharmony_ci BT_DBG("%s key for %pMR type %u", hdev->name, bdaddr, type); 25928c2ecf20Sopenharmony_ci 25938c2ecf20Sopenharmony_ci /* Some buggy controller combinations generate a changed 25948c2ecf20Sopenharmony_ci * combination key for legacy pairing even when there's no 25958c2ecf20Sopenharmony_ci * previous key */ 25968c2ecf20Sopenharmony_ci if (type == HCI_LK_CHANGED_COMBINATION && 25978c2ecf20Sopenharmony_ci (!conn || conn->remote_auth == 0xff) && old_key_type == 0xff) { 25988c2ecf20Sopenharmony_ci type = HCI_LK_COMBINATION; 25998c2ecf20Sopenharmony_ci if (conn) 26008c2ecf20Sopenharmony_ci conn->key_type = type; 26018c2ecf20Sopenharmony_ci } 26028c2ecf20Sopenharmony_ci 26038c2ecf20Sopenharmony_ci bacpy(&key->bdaddr, bdaddr); 26048c2ecf20Sopenharmony_ci memcpy(key->val, val, HCI_LINK_KEY_SIZE); 26058c2ecf20Sopenharmony_ci key->pin_len = pin_len; 26068c2ecf20Sopenharmony_ci 26078c2ecf20Sopenharmony_ci if (type == HCI_LK_CHANGED_COMBINATION) 26088c2ecf20Sopenharmony_ci key->type = old_key_type; 26098c2ecf20Sopenharmony_ci else 26108c2ecf20Sopenharmony_ci key->type = type; 26118c2ecf20Sopenharmony_ci 26128c2ecf20Sopenharmony_ci if (persistent) 26138c2ecf20Sopenharmony_ci *persistent = hci_persistent_key(hdev, conn, type, 26148c2ecf20Sopenharmony_ci old_key_type); 26158c2ecf20Sopenharmony_ci 26168c2ecf20Sopenharmony_ci return key; 26178c2ecf20Sopenharmony_ci} 26188c2ecf20Sopenharmony_ci 26198c2ecf20Sopenharmony_cistruct smp_ltk *hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, 26208c2ecf20Sopenharmony_ci u8 addr_type, u8 type, u8 authenticated, 26218c2ecf20Sopenharmony_ci u8 tk[16], u8 enc_size, __le16 ediv, __le64 rand) 26228c2ecf20Sopenharmony_ci{ 26238c2ecf20Sopenharmony_ci struct smp_ltk *key, *old_key; 26248c2ecf20Sopenharmony_ci u8 role = ltk_role(type); 26258c2ecf20Sopenharmony_ci 26268c2ecf20Sopenharmony_ci old_key = hci_find_ltk(hdev, bdaddr, addr_type, role); 26278c2ecf20Sopenharmony_ci if (old_key) 26288c2ecf20Sopenharmony_ci key = old_key; 26298c2ecf20Sopenharmony_ci else { 26308c2ecf20Sopenharmony_ci key = kzalloc(sizeof(*key), GFP_KERNEL); 26318c2ecf20Sopenharmony_ci if (!key) 26328c2ecf20Sopenharmony_ci return NULL; 26338c2ecf20Sopenharmony_ci list_add_rcu(&key->list, &hdev->long_term_keys); 26348c2ecf20Sopenharmony_ci } 26358c2ecf20Sopenharmony_ci 26368c2ecf20Sopenharmony_ci bacpy(&key->bdaddr, bdaddr); 26378c2ecf20Sopenharmony_ci key->bdaddr_type = addr_type; 26388c2ecf20Sopenharmony_ci memcpy(key->val, tk, sizeof(key->val)); 26398c2ecf20Sopenharmony_ci key->authenticated = authenticated; 26408c2ecf20Sopenharmony_ci key->ediv = ediv; 26418c2ecf20Sopenharmony_ci key->rand = rand; 26428c2ecf20Sopenharmony_ci key->enc_size = enc_size; 26438c2ecf20Sopenharmony_ci key->type = type; 26448c2ecf20Sopenharmony_ci 26458c2ecf20Sopenharmony_ci return key; 26468c2ecf20Sopenharmony_ci} 26478c2ecf20Sopenharmony_ci 26488c2ecf20Sopenharmony_cistruct smp_irk *hci_add_irk(struct hci_dev *hdev, bdaddr_t *bdaddr, 26498c2ecf20Sopenharmony_ci u8 addr_type, u8 val[16], bdaddr_t *rpa) 26508c2ecf20Sopenharmony_ci{ 26518c2ecf20Sopenharmony_ci struct smp_irk *irk; 26528c2ecf20Sopenharmony_ci 26538c2ecf20Sopenharmony_ci irk = hci_find_irk_by_addr(hdev, bdaddr, addr_type); 26548c2ecf20Sopenharmony_ci if (!irk) { 26558c2ecf20Sopenharmony_ci irk = kzalloc(sizeof(*irk), GFP_KERNEL); 26568c2ecf20Sopenharmony_ci if (!irk) 26578c2ecf20Sopenharmony_ci return NULL; 26588c2ecf20Sopenharmony_ci 26598c2ecf20Sopenharmony_ci bacpy(&irk->bdaddr, bdaddr); 26608c2ecf20Sopenharmony_ci irk->addr_type = addr_type; 26618c2ecf20Sopenharmony_ci 26628c2ecf20Sopenharmony_ci list_add_rcu(&irk->list, &hdev->identity_resolving_keys); 26638c2ecf20Sopenharmony_ci } 26648c2ecf20Sopenharmony_ci 26658c2ecf20Sopenharmony_ci memcpy(irk->val, val, 16); 26668c2ecf20Sopenharmony_ci bacpy(&irk->rpa, rpa); 26678c2ecf20Sopenharmony_ci 26688c2ecf20Sopenharmony_ci return irk; 26698c2ecf20Sopenharmony_ci} 26708c2ecf20Sopenharmony_ci 26718c2ecf20Sopenharmony_ciint hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr) 26728c2ecf20Sopenharmony_ci{ 26738c2ecf20Sopenharmony_ci struct link_key *key; 26748c2ecf20Sopenharmony_ci 26758c2ecf20Sopenharmony_ci key = hci_find_link_key(hdev, bdaddr); 26768c2ecf20Sopenharmony_ci if (!key) 26778c2ecf20Sopenharmony_ci return -ENOENT; 26788c2ecf20Sopenharmony_ci 26798c2ecf20Sopenharmony_ci BT_DBG("%s removing %pMR", hdev->name, bdaddr); 26808c2ecf20Sopenharmony_ci 26818c2ecf20Sopenharmony_ci list_del_rcu(&key->list); 26828c2ecf20Sopenharmony_ci kfree_rcu(key, rcu); 26838c2ecf20Sopenharmony_ci 26848c2ecf20Sopenharmony_ci return 0; 26858c2ecf20Sopenharmony_ci} 26868c2ecf20Sopenharmony_ci 26878c2ecf20Sopenharmony_ciint hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 bdaddr_type) 26888c2ecf20Sopenharmony_ci{ 26898c2ecf20Sopenharmony_ci struct smp_ltk *k, *tmp; 26908c2ecf20Sopenharmony_ci int removed = 0; 26918c2ecf20Sopenharmony_ci 26928c2ecf20Sopenharmony_ci list_for_each_entry_safe(k, tmp, &hdev->long_term_keys, list) { 26938c2ecf20Sopenharmony_ci if (bacmp(bdaddr, &k->bdaddr) || k->bdaddr_type != bdaddr_type) 26948c2ecf20Sopenharmony_ci continue; 26958c2ecf20Sopenharmony_ci 26968c2ecf20Sopenharmony_ci BT_DBG("%s removing %pMR", hdev->name, bdaddr); 26978c2ecf20Sopenharmony_ci 26988c2ecf20Sopenharmony_ci list_del_rcu(&k->list); 26998c2ecf20Sopenharmony_ci kfree_rcu(k, rcu); 27008c2ecf20Sopenharmony_ci removed++; 27018c2ecf20Sopenharmony_ci } 27028c2ecf20Sopenharmony_ci 27038c2ecf20Sopenharmony_ci return removed ? 0 : -ENOENT; 27048c2ecf20Sopenharmony_ci} 27058c2ecf20Sopenharmony_ci 27068c2ecf20Sopenharmony_civoid hci_remove_irk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type) 27078c2ecf20Sopenharmony_ci{ 27088c2ecf20Sopenharmony_ci struct smp_irk *k, *tmp; 27098c2ecf20Sopenharmony_ci 27108c2ecf20Sopenharmony_ci list_for_each_entry_safe(k, tmp, &hdev->identity_resolving_keys, list) { 27118c2ecf20Sopenharmony_ci if (bacmp(bdaddr, &k->bdaddr) || k->addr_type != addr_type) 27128c2ecf20Sopenharmony_ci continue; 27138c2ecf20Sopenharmony_ci 27148c2ecf20Sopenharmony_ci BT_DBG("%s removing %pMR", hdev->name, bdaddr); 27158c2ecf20Sopenharmony_ci 27168c2ecf20Sopenharmony_ci list_del_rcu(&k->list); 27178c2ecf20Sopenharmony_ci kfree_rcu(k, rcu); 27188c2ecf20Sopenharmony_ci } 27198c2ecf20Sopenharmony_ci} 27208c2ecf20Sopenharmony_ci 27218c2ecf20Sopenharmony_cibool hci_bdaddr_is_paired(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) 27228c2ecf20Sopenharmony_ci{ 27238c2ecf20Sopenharmony_ci struct smp_ltk *k; 27248c2ecf20Sopenharmony_ci struct smp_irk *irk; 27258c2ecf20Sopenharmony_ci u8 addr_type; 27268c2ecf20Sopenharmony_ci 27278c2ecf20Sopenharmony_ci if (type == BDADDR_BREDR) { 27288c2ecf20Sopenharmony_ci if (hci_find_link_key(hdev, bdaddr)) 27298c2ecf20Sopenharmony_ci return true; 27308c2ecf20Sopenharmony_ci return false; 27318c2ecf20Sopenharmony_ci } 27328c2ecf20Sopenharmony_ci 27338c2ecf20Sopenharmony_ci /* Convert to HCI addr type which struct smp_ltk uses */ 27348c2ecf20Sopenharmony_ci if (type == BDADDR_LE_PUBLIC) 27358c2ecf20Sopenharmony_ci addr_type = ADDR_LE_DEV_PUBLIC; 27368c2ecf20Sopenharmony_ci else 27378c2ecf20Sopenharmony_ci addr_type = ADDR_LE_DEV_RANDOM; 27388c2ecf20Sopenharmony_ci 27398c2ecf20Sopenharmony_ci irk = hci_get_irk(hdev, bdaddr, addr_type); 27408c2ecf20Sopenharmony_ci if (irk) { 27418c2ecf20Sopenharmony_ci bdaddr = &irk->bdaddr; 27428c2ecf20Sopenharmony_ci addr_type = irk->addr_type; 27438c2ecf20Sopenharmony_ci } 27448c2ecf20Sopenharmony_ci 27458c2ecf20Sopenharmony_ci rcu_read_lock(); 27468c2ecf20Sopenharmony_ci list_for_each_entry_rcu(k, &hdev->long_term_keys, list) { 27478c2ecf20Sopenharmony_ci if (k->bdaddr_type == addr_type && !bacmp(bdaddr, &k->bdaddr)) { 27488c2ecf20Sopenharmony_ci rcu_read_unlock(); 27498c2ecf20Sopenharmony_ci return true; 27508c2ecf20Sopenharmony_ci } 27518c2ecf20Sopenharmony_ci } 27528c2ecf20Sopenharmony_ci rcu_read_unlock(); 27538c2ecf20Sopenharmony_ci 27548c2ecf20Sopenharmony_ci return false; 27558c2ecf20Sopenharmony_ci} 27568c2ecf20Sopenharmony_ci 27578c2ecf20Sopenharmony_ci/* HCI command timer function */ 27588c2ecf20Sopenharmony_cistatic void hci_cmd_timeout(struct work_struct *work) 27598c2ecf20Sopenharmony_ci{ 27608c2ecf20Sopenharmony_ci struct hci_dev *hdev = container_of(work, struct hci_dev, 27618c2ecf20Sopenharmony_ci cmd_timer.work); 27628c2ecf20Sopenharmony_ci 27638c2ecf20Sopenharmony_ci if (hdev->sent_cmd) { 27648c2ecf20Sopenharmony_ci struct hci_command_hdr *sent = (void *) hdev->sent_cmd->data; 27658c2ecf20Sopenharmony_ci u16 opcode = __le16_to_cpu(sent->opcode); 27668c2ecf20Sopenharmony_ci 27678c2ecf20Sopenharmony_ci bt_dev_err(hdev, "command 0x%4.4x tx timeout", opcode); 27688c2ecf20Sopenharmony_ci } else { 27698c2ecf20Sopenharmony_ci bt_dev_err(hdev, "command tx timeout"); 27708c2ecf20Sopenharmony_ci } 27718c2ecf20Sopenharmony_ci 27728c2ecf20Sopenharmony_ci if (hdev->cmd_timeout) 27738c2ecf20Sopenharmony_ci hdev->cmd_timeout(hdev); 27748c2ecf20Sopenharmony_ci 27758c2ecf20Sopenharmony_ci atomic_set(&hdev->cmd_cnt, 1); 27768c2ecf20Sopenharmony_ci queue_work(hdev->workqueue, &hdev->cmd_work); 27778c2ecf20Sopenharmony_ci} 27788c2ecf20Sopenharmony_ci 27798c2ecf20Sopenharmony_cistruct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev, 27808c2ecf20Sopenharmony_ci bdaddr_t *bdaddr, u8 bdaddr_type) 27818c2ecf20Sopenharmony_ci{ 27828c2ecf20Sopenharmony_ci struct oob_data *data; 27838c2ecf20Sopenharmony_ci 27848c2ecf20Sopenharmony_ci list_for_each_entry(data, &hdev->remote_oob_data, list) { 27858c2ecf20Sopenharmony_ci if (bacmp(bdaddr, &data->bdaddr) != 0) 27868c2ecf20Sopenharmony_ci continue; 27878c2ecf20Sopenharmony_ci if (data->bdaddr_type != bdaddr_type) 27888c2ecf20Sopenharmony_ci continue; 27898c2ecf20Sopenharmony_ci return data; 27908c2ecf20Sopenharmony_ci } 27918c2ecf20Sopenharmony_ci 27928c2ecf20Sopenharmony_ci return NULL; 27938c2ecf20Sopenharmony_ci} 27948c2ecf20Sopenharmony_ci 27958c2ecf20Sopenharmony_ciint hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, 27968c2ecf20Sopenharmony_ci u8 bdaddr_type) 27978c2ecf20Sopenharmony_ci{ 27988c2ecf20Sopenharmony_ci struct oob_data *data; 27998c2ecf20Sopenharmony_ci 28008c2ecf20Sopenharmony_ci data = hci_find_remote_oob_data(hdev, bdaddr, bdaddr_type); 28018c2ecf20Sopenharmony_ci if (!data) 28028c2ecf20Sopenharmony_ci return -ENOENT; 28038c2ecf20Sopenharmony_ci 28048c2ecf20Sopenharmony_ci BT_DBG("%s removing %pMR (%u)", hdev->name, bdaddr, bdaddr_type); 28058c2ecf20Sopenharmony_ci 28068c2ecf20Sopenharmony_ci list_del(&data->list); 28078c2ecf20Sopenharmony_ci kfree(data); 28088c2ecf20Sopenharmony_ci 28098c2ecf20Sopenharmony_ci return 0; 28108c2ecf20Sopenharmony_ci} 28118c2ecf20Sopenharmony_ci 28128c2ecf20Sopenharmony_civoid hci_remote_oob_data_clear(struct hci_dev *hdev) 28138c2ecf20Sopenharmony_ci{ 28148c2ecf20Sopenharmony_ci struct oob_data *data, *n; 28158c2ecf20Sopenharmony_ci 28168c2ecf20Sopenharmony_ci list_for_each_entry_safe(data, n, &hdev->remote_oob_data, list) { 28178c2ecf20Sopenharmony_ci list_del(&data->list); 28188c2ecf20Sopenharmony_ci kfree(data); 28198c2ecf20Sopenharmony_ci } 28208c2ecf20Sopenharmony_ci} 28218c2ecf20Sopenharmony_ci 28228c2ecf20Sopenharmony_ciint hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, 28238c2ecf20Sopenharmony_ci u8 bdaddr_type, u8 *hash192, u8 *rand192, 28248c2ecf20Sopenharmony_ci u8 *hash256, u8 *rand256) 28258c2ecf20Sopenharmony_ci{ 28268c2ecf20Sopenharmony_ci struct oob_data *data; 28278c2ecf20Sopenharmony_ci 28288c2ecf20Sopenharmony_ci data = hci_find_remote_oob_data(hdev, bdaddr, bdaddr_type); 28298c2ecf20Sopenharmony_ci if (!data) { 28308c2ecf20Sopenharmony_ci data = kmalloc(sizeof(*data), GFP_KERNEL); 28318c2ecf20Sopenharmony_ci if (!data) 28328c2ecf20Sopenharmony_ci return -ENOMEM; 28338c2ecf20Sopenharmony_ci 28348c2ecf20Sopenharmony_ci bacpy(&data->bdaddr, bdaddr); 28358c2ecf20Sopenharmony_ci data->bdaddr_type = bdaddr_type; 28368c2ecf20Sopenharmony_ci list_add(&data->list, &hdev->remote_oob_data); 28378c2ecf20Sopenharmony_ci } 28388c2ecf20Sopenharmony_ci 28398c2ecf20Sopenharmony_ci if (hash192 && rand192) { 28408c2ecf20Sopenharmony_ci memcpy(data->hash192, hash192, sizeof(data->hash192)); 28418c2ecf20Sopenharmony_ci memcpy(data->rand192, rand192, sizeof(data->rand192)); 28428c2ecf20Sopenharmony_ci if (hash256 && rand256) 28438c2ecf20Sopenharmony_ci data->present = 0x03; 28448c2ecf20Sopenharmony_ci } else { 28458c2ecf20Sopenharmony_ci memset(data->hash192, 0, sizeof(data->hash192)); 28468c2ecf20Sopenharmony_ci memset(data->rand192, 0, sizeof(data->rand192)); 28478c2ecf20Sopenharmony_ci if (hash256 && rand256) 28488c2ecf20Sopenharmony_ci data->present = 0x02; 28498c2ecf20Sopenharmony_ci else 28508c2ecf20Sopenharmony_ci data->present = 0x00; 28518c2ecf20Sopenharmony_ci } 28528c2ecf20Sopenharmony_ci 28538c2ecf20Sopenharmony_ci if (hash256 && rand256) { 28548c2ecf20Sopenharmony_ci memcpy(data->hash256, hash256, sizeof(data->hash256)); 28558c2ecf20Sopenharmony_ci memcpy(data->rand256, rand256, sizeof(data->rand256)); 28568c2ecf20Sopenharmony_ci } else { 28578c2ecf20Sopenharmony_ci memset(data->hash256, 0, sizeof(data->hash256)); 28588c2ecf20Sopenharmony_ci memset(data->rand256, 0, sizeof(data->rand256)); 28598c2ecf20Sopenharmony_ci if (hash192 && rand192) 28608c2ecf20Sopenharmony_ci data->present = 0x01; 28618c2ecf20Sopenharmony_ci } 28628c2ecf20Sopenharmony_ci 28638c2ecf20Sopenharmony_ci BT_DBG("%s for %pMR", hdev->name, bdaddr); 28648c2ecf20Sopenharmony_ci 28658c2ecf20Sopenharmony_ci return 0; 28668c2ecf20Sopenharmony_ci} 28678c2ecf20Sopenharmony_ci 28688c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */ 28698c2ecf20Sopenharmony_cistruct adv_info *hci_find_adv_instance(struct hci_dev *hdev, u8 instance) 28708c2ecf20Sopenharmony_ci{ 28718c2ecf20Sopenharmony_ci struct adv_info *adv_instance; 28728c2ecf20Sopenharmony_ci 28738c2ecf20Sopenharmony_ci list_for_each_entry(adv_instance, &hdev->adv_instances, list) { 28748c2ecf20Sopenharmony_ci if (adv_instance->instance == instance) 28758c2ecf20Sopenharmony_ci return adv_instance; 28768c2ecf20Sopenharmony_ci } 28778c2ecf20Sopenharmony_ci 28788c2ecf20Sopenharmony_ci return NULL; 28798c2ecf20Sopenharmony_ci} 28808c2ecf20Sopenharmony_ci 28818c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */ 28828c2ecf20Sopenharmony_cistruct adv_info *hci_get_next_instance(struct hci_dev *hdev, u8 instance) 28838c2ecf20Sopenharmony_ci{ 28848c2ecf20Sopenharmony_ci struct adv_info *cur_instance; 28858c2ecf20Sopenharmony_ci 28868c2ecf20Sopenharmony_ci cur_instance = hci_find_adv_instance(hdev, instance); 28878c2ecf20Sopenharmony_ci if (!cur_instance) 28888c2ecf20Sopenharmony_ci return NULL; 28898c2ecf20Sopenharmony_ci 28908c2ecf20Sopenharmony_ci if (cur_instance == list_last_entry(&hdev->adv_instances, 28918c2ecf20Sopenharmony_ci struct adv_info, list)) 28928c2ecf20Sopenharmony_ci return list_first_entry(&hdev->adv_instances, 28938c2ecf20Sopenharmony_ci struct adv_info, list); 28948c2ecf20Sopenharmony_ci else 28958c2ecf20Sopenharmony_ci return list_next_entry(cur_instance, list); 28968c2ecf20Sopenharmony_ci} 28978c2ecf20Sopenharmony_ci 28988c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */ 28998c2ecf20Sopenharmony_ciint hci_remove_adv_instance(struct hci_dev *hdev, u8 instance) 29008c2ecf20Sopenharmony_ci{ 29018c2ecf20Sopenharmony_ci struct adv_info *adv_instance; 29028c2ecf20Sopenharmony_ci 29038c2ecf20Sopenharmony_ci adv_instance = hci_find_adv_instance(hdev, instance); 29048c2ecf20Sopenharmony_ci if (!adv_instance) 29058c2ecf20Sopenharmony_ci return -ENOENT; 29068c2ecf20Sopenharmony_ci 29078c2ecf20Sopenharmony_ci BT_DBG("%s removing %dMR", hdev->name, instance); 29088c2ecf20Sopenharmony_ci 29098c2ecf20Sopenharmony_ci if (hdev->cur_adv_instance == instance) { 29108c2ecf20Sopenharmony_ci if (hdev->adv_instance_timeout) { 29118c2ecf20Sopenharmony_ci cancel_delayed_work(&hdev->adv_instance_expire); 29128c2ecf20Sopenharmony_ci hdev->adv_instance_timeout = 0; 29138c2ecf20Sopenharmony_ci } 29148c2ecf20Sopenharmony_ci hdev->cur_adv_instance = 0x00; 29158c2ecf20Sopenharmony_ci } 29168c2ecf20Sopenharmony_ci 29178c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&adv_instance->rpa_expired_cb); 29188c2ecf20Sopenharmony_ci 29198c2ecf20Sopenharmony_ci list_del(&adv_instance->list); 29208c2ecf20Sopenharmony_ci kfree(adv_instance); 29218c2ecf20Sopenharmony_ci 29228c2ecf20Sopenharmony_ci hdev->adv_instance_cnt--; 29238c2ecf20Sopenharmony_ci 29248c2ecf20Sopenharmony_ci return 0; 29258c2ecf20Sopenharmony_ci} 29268c2ecf20Sopenharmony_ci 29278c2ecf20Sopenharmony_civoid hci_adv_instances_set_rpa_expired(struct hci_dev *hdev, bool rpa_expired) 29288c2ecf20Sopenharmony_ci{ 29298c2ecf20Sopenharmony_ci struct adv_info *adv_instance, *n; 29308c2ecf20Sopenharmony_ci 29318c2ecf20Sopenharmony_ci list_for_each_entry_safe(adv_instance, n, &hdev->adv_instances, list) 29328c2ecf20Sopenharmony_ci adv_instance->rpa_expired = rpa_expired; 29338c2ecf20Sopenharmony_ci} 29348c2ecf20Sopenharmony_ci 29358c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */ 29368c2ecf20Sopenharmony_civoid hci_adv_instances_clear(struct hci_dev *hdev) 29378c2ecf20Sopenharmony_ci{ 29388c2ecf20Sopenharmony_ci struct adv_info *adv_instance, *n; 29398c2ecf20Sopenharmony_ci 29408c2ecf20Sopenharmony_ci if (hdev->adv_instance_timeout) { 29418c2ecf20Sopenharmony_ci cancel_delayed_work(&hdev->adv_instance_expire); 29428c2ecf20Sopenharmony_ci hdev->adv_instance_timeout = 0; 29438c2ecf20Sopenharmony_ci } 29448c2ecf20Sopenharmony_ci 29458c2ecf20Sopenharmony_ci list_for_each_entry_safe(adv_instance, n, &hdev->adv_instances, list) { 29468c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&adv_instance->rpa_expired_cb); 29478c2ecf20Sopenharmony_ci list_del(&adv_instance->list); 29488c2ecf20Sopenharmony_ci kfree(adv_instance); 29498c2ecf20Sopenharmony_ci } 29508c2ecf20Sopenharmony_ci 29518c2ecf20Sopenharmony_ci hdev->adv_instance_cnt = 0; 29528c2ecf20Sopenharmony_ci hdev->cur_adv_instance = 0x00; 29538c2ecf20Sopenharmony_ci} 29548c2ecf20Sopenharmony_ci 29558c2ecf20Sopenharmony_cistatic void adv_instance_rpa_expired(struct work_struct *work) 29568c2ecf20Sopenharmony_ci{ 29578c2ecf20Sopenharmony_ci struct adv_info *adv_instance = container_of(work, struct adv_info, 29588c2ecf20Sopenharmony_ci rpa_expired_cb.work); 29598c2ecf20Sopenharmony_ci 29608c2ecf20Sopenharmony_ci BT_DBG(""); 29618c2ecf20Sopenharmony_ci 29628c2ecf20Sopenharmony_ci adv_instance->rpa_expired = true; 29638c2ecf20Sopenharmony_ci} 29648c2ecf20Sopenharmony_ci 29658c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */ 29668c2ecf20Sopenharmony_ciint hci_add_adv_instance(struct hci_dev *hdev, u8 instance, u32 flags, 29678c2ecf20Sopenharmony_ci u16 adv_data_len, u8 *adv_data, 29688c2ecf20Sopenharmony_ci u16 scan_rsp_len, u8 *scan_rsp_data, 29698c2ecf20Sopenharmony_ci u16 timeout, u16 duration) 29708c2ecf20Sopenharmony_ci{ 29718c2ecf20Sopenharmony_ci struct adv_info *adv_instance; 29728c2ecf20Sopenharmony_ci 29738c2ecf20Sopenharmony_ci adv_instance = hci_find_adv_instance(hdev, instance); 29748c2ecf20Sopenharmony_ci if (adv_instance) { 29758c2ecf20Sopenharmony_ci memset(adv_instance->adv_data, 0, 29768c2ecf20Sopenharmony_ci sizeof(adv_instance->adv_data)); 29778c2ecf20Sopenharmony_ci memset(adv_instance->scan_rsp_data, 0, 29788c2ecf20Sopenharmony_ci sizeof(adv_instance->scan_rsp_data)); 29798c2ecf20Sopenharmony_ci } else { 29808c2ecf20Sopenharmony_ci if (hdev->adv_instance_cnt >= hdev->le_num_of_adv_sets || 29818c2ecf20Sopenharmony_ci instance < 1 || instance > hdev->le_num_of_adv_sets) 29828c2ecf20Sopenharmony_ci return -EOVERFLOW; 29838c2ecf20Sopenharmony_ci 29848c2ecf20Sopenharmony_ci adv_instance = kzalloc(sizeof(*adv_instance), GFP_KERNEL); 29858c2ecf20Sopenharmony_ci if (!adv_instance) 29868c2ecf20Sopenharmony_ci return -ENOMEM; 29878c2ecf20Sopenharmony_ci 29888c2ecf20Sopenharmony_ci adv_instance->pending = true; 29898c2ecf20Sopenharmony_ci adv_instance->instance = instance; 29908c2ecf20Sopenharmony_ci list_add(&adv_instance->list, &hdev->adv_instances); 29918c2ecf20Sopenharmony_ci hdev->adv_instance_cnt++; 29928c2ecf20Sopenharmony_ci } 29938c2ecf20Sopenharmony_ci 29948c2ecf20Sopenharmony_ci adv_instance->flags = flags; 29958c2ecf20Sopenharmony_ci adv_instance->adv_data_len = adv_data_len; 29968c2ecf20Sopenharmony_ci adv_instance->scan_rsp_len = scan_rsp_len; 29978c2ecf20Sopenharmony_ci 29988c2ecf20Sopenharmony_ci if (adv_data_len) 29998c2ecf20Sopenharmony_ci memcpy(adv_instance->adv_data, adv_data, adv_data_len); 30008c2ecf20Sopenharmony_ci 30018c2ecf20Sopenharmony_ci if (scan_rsp_len) 30028c2ecf20Sopenharmony_ci memcpy(adv_instance->scan_rsp_data, 30038c2ecf20Sopenharmony_ci scan_rsp_data, scan_rsp_len); 30048c2ecf20Sopenharmony_ci 30058c2ecf20Sopenharmony_ci adv_instance->timeout = timeout; 30068c2ecf20Sopenharmony_ci adv_instance->remaining_time = timeout; 30078c2ecf20Sopenharmony_ci 30088c2ecf20Sopenharmony_ci if (duration == 0) 30098c2ecf20Sopenharmony_ci adv_instance->duration = hdev->def_multi_adv_rotation_duration; 30108c2ecf20Sopenharmony_ci else 30118c2ecf20Sopenharmony_ci adv_instance->duration = duration; 30128c2ecf20Sopenharmony_ci 30138c2ecf20Sopenharmony_ci adv_instance->tx_power = HCI_TX_POWER_INVALID; 30148c2ecf20Sopenharmony_ci 30158c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&adv_instance->rpa_expired_cb, 30168c2ecf20Sopenharmony_ci adv_instance_rpa_expired); 30178c2ecf20Sopenharmony_ci 30188c2ecf20Sopenharmony_ci BT_DBG("%s for %dMR", hdev->name, instance); 30198c2ecf20Sopenharmony_ci 30208c2ecf20Sopenharmony_ci return 0; 30218c2ecf20Sopenharmony_ci} 30228c2ecf20Sopenharmony_ci 30238c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */ 30248c2ecf20Sopenharmony_civoid hci_adv_monitors_clear(struct hci_dev *hdev) 30258c2ecf20Sopenharmony_ci{ 30268c2ecf20Sopenharmony_ci struct adv_monitor *monitor; 30278c2ecf20Sopenharmony_ci int handle; 30288c2ecf20Sopenharmony_ci 30298c2ecf20Sopenharmony_ci idr_for_each_entry(&hdev->adv_monitors_idr, monitor, handle) 30308c2ecf20Sopenharmony_ci hci_free_adv_monitor(monitor); 30318c2ecf20Sopenharmony_ci 30328c2ecf20Sopenharmony_ci idr_destroy(&hdev->adv_monitors_idr); 30338c2ecf20Sopenharmony_ci} 30348c2ecf20Sopenharmony_ci 30358c2ecf20Sopenharmony_civoid hci_free_adv_monitor(struct adv_monitor *monitor) 30368c2ecf20Sopenharmony_ci{ 30378c2ecf20Sopenharmony_ci struct adv_pattern *pattern; 30388c2ecf20Sopenharmony_ci struct adv_pattern *tmp; 30398c2ecf20Sopenharmony_ci 30408c2ecf20Sopenharmony_ci if (!monitor) 30418c2ecf20Sopenharmony_ci return; 30428c2ecf20Sopenharmony_ci 30438c2ecf20Sopenharmony_ci list_for_each_entry_safe(pattern, tmp, &monitor->patterns, list) 30448c2ecf20Sopenharmony_ci kfree(pattern); 30458c2ecf20Sopenharmony_ci 30468c2ecf20Sopenharmony_ci kfree(monitor); 30478c2ecf20Sopenharmony_ci} 30488c2ecf20Sopenharmony_ci 30498c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */ 30508c2ecf20Sopenharmony_ciint hci_add_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor) 30518c2ecf20Sopenharmony_ci{ 30528c2ecf20Sopenharmony_ci int min, max, handle; 30538c2ecf20Sopenharmony_ci 30548c2ecf20Sopenharmony_ci if (!monitor) 30558c2ecf20Sopenharmony_ci return -EINVAL; 30568c2ecf20Sopenharmony_ci 30578c2ecf20Sopenharmony_ci min = HCI_MIN_ADV_MONITOR_HANDLE; 30588c2ecf20Sopenharmony_ci max = HCI_MIN_ADV_MONITOR_HANDLE + HCI_MAX_ADV_MONITOR_NUM_HANDLES; 30598c2ecf20Sopenharmony_ci handle = idr_alloc(&hdev->adv_monitors_idr, monitor, min, max, 30608c2ecf20Sopenharmony_ci GFP_KERNEL); 30618c2ecf20Sopenharmony_ci if (handle < 0) 30628c2ecf20Sopenharmony_ci return handle; 30638c2ecf20Sopenharmony_ci 30648c2ecf20Sopenharmony_ci hdev->adv_monitors_cnt++; 30658c2ecf20Sopenharmony_ci monitor->handle = handle; 30668c2ecf20Sopenharmony_ci 30678c2ecf20Sopenharmony_ci hci_update_background_scan(hdev); 30688c2ecf20Sopenharmony_ci 30698c2ecf20Sopenharmony_ci return 0; 30708c2ecf20Sopenharmony_ci} 30718c2ecf20Sopenharmony_ci 30728c2ecf20Sopenharmony_cistatic int free_adv_monitor(int id, void *ptr, void *data) 30738c2ecf20Sopenharmony_ci{ 30748c2ecf20Sopenharmony_ci struct hci_dev *hdev = data; 30758c2ecf20Sopenharmony_ci struct adv_monitor *monitor = ptr; 30768c2ecf20Sopenharmony_ci 30778c2ecf20Sopenharmony_ci idr_remove(&hdev->adv_monitors_idr, monitor->handle); 30788c2ecf20Sopenharmony_ci hci_free_adv_monitor(monitor); 30798c2ecf20Sopenharmony_ci hdev->adv_monitors_cnt--; 30808c2ecf20Sopenharmony_ci 30818c2ecf20Sopenharmony_ci return 0; 30828c2ecf20Sopenharmony_ci} 30838c2ecf20Sopenharmony_ci 30848c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */ 30858c2ecf20Sopenharmony_ciint hci_remove_adv_monitor(struct hci_dev *hdev, u16 handle) 30868c2ecf20Sopenharmony_ci{ 30878c2ecf20Sopenharmony_ci struct adv_monitor *monitor; 30888c2ecf20Sopenharmony_ci 30898c2ecf20Sopenharmony_ci if (handle) { 30908c2ecf20Sopenharmony_ci monitor = idr_find(&hdev->adv_monitors_idr, handle); 30918c2ecf20Sopenharmony_ci if (!monitor) 30928c2ecf20Sopenharmony_ci return -ENOENT; 30938c2ecf20Sopenharmony_ci 30948c2ecf20Sopenharmony_ci idr_remove(&hdev->adv_monitors_idr, monitor->handle); 30958c2ecf20Sopenharmony_ci hci_free_adv_monitor(monitor); 30968c2ecf20Sopenharmony_ci hdev->adv_monitors_cnt--; 30978c2ecf20Sopenharmony_ci } else { 30988c2ecf20Sopenharmony_ci /* Remove all monitors if handle is 0. */ 30998c2ecf20Sopenharmony_ci idr_for_each(&hdev->adv_monitors_idr, &free_adv_monitor, hdev); 31008c2ecf20Sopenharmony_ci } 31018c2ecf20Sopenharmony_ci 31028c2ecf20Sopenharmony_ci hci_update_background_scan(hdev); 31038c2ecf20Sopenharmony_ci 31048c2ecf20Sopenharmony_ci return 0; 31058c2ecf20Sopenharmony_ci} 31068c2ecf20Sopenharmony_ci 31078c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */ 31088c2ecf20Sopenharmony_cibool hci_is_adv_monitoring(struct hci_dev *hdev) 31098c2ecf20Sopenharmony_ci{ 31108c2ecf20Sopenharmony_ci return !idr_is_empty(&hdev->adv_monitors_idr); 31118c2ecf20Sopenharmony_ci} 31128c2ecf20Sopenharmony_ci 31138c2ecf20Sopenharmony_cistruct bdaddr_list *hci_bdaddr_list_lookup(struct list_head *bdaddr_list, 31148c2ecf20Sopenharmony_ci bdaddr_t *bdaddr, u8 type) 31158c2ecf20Sopenharmony_ci{ 31168c2ecf20Sopenharmony_ci struct bdaddr_list *b; 31178c2ecf20Sopenharmony_ci 31188c2ecf20Sopenharmony_ci list_for_each_entry(b, bdaddr_list, list) { 31198c2ecf20Sopenharmony_ci if (!bacmp(&b->bdaddr, bdaddr) && b->bdaddr_type == type) 31208c2ecf20Sopenharmony_ci return b; 31218c2ecf20Sopenharmony_ci } 31228c2ecf20Sopenharmony_ci 31238c2ecf20Sopenharmony_ci return NULL; 31248c2ecf20Sopenharmony_ci} 31258c2ecf20Sopenharmony_ci 31268c2ecf20Sopenharmony_cistruct bdaddr_list_with_irk *hci_bdaddr_list_lookup_with_irk( 31278c2ecf20Sopenharmony_ci struct list_head *bdaddr_list, bdaddr_t *bdaddr, 31288c2ecf20Sopenharmony_ci u8 type) 31298c2ecf20Sopenharmony_ci{ 31308c2ecf20Sopenharmony_ci struct bdaddr_list_with_irk *b; 31318c2ecf20Sopenharmony_ci 31328c2ecf20Sopenharmony_ci list_for_each_entry(b, bdaddr_list, list) { 31338c2ecf20Sopenharmony_ci if (!bacmp(&b->bdaddr, bdaddr) && b->bdaddr_type == type) 31348c2ecf20Sopenharmony_ci return b; 31358c2ecf20Sopenharmony_ci } 31368c2ecf20Sopenharmony_ci 31378c2ecf20Sopenharmony_ci return NULL; 31388c2ecf20Sopenharmony_ci} 31398c2ecf20Sopenharmony_ci 31408c2ecf20Sopenharmony_cistruct bdaddr_list_with_flags * 31418c2ecf20Sopenharmony_cihci_bdaddr_list_lookup_with_flags(struct list_head *bdaddr_list, 31428c2ecf20Sopenharmony_ci bdaddr_t *bdaddr, u8 type) 31438c2ecf20Sopenharmony_ci{ 31448c2ecf20Sopenharmony_ci struct bdaddr_list_with_flags *b; 31458c2ecf20Sopenharmony_ci 31468c2ecf20Sopenharmony_ci list_for_each_entry(b, bdaddr_list, list) { 31478c2ecf20Sopenharmony_ci if (!bacmp(&b->bdaddr, bdaddr) && b->bdaddr_type == type) 31488c2ecf20Sopenharmony_ci return b; 31498c2ecf20Sopenharmony_ci } 31508c2ecf20Sopenharmony_ci 31518c2ecf20Sopenharmony_ci return NULL; 31528c2ecf20Sopenharmony_ci} 31538c2ecf20Sopenharmony_ci 31548c2ecf20Sopenharmony_civoid hci_bdaddr_list_clear(struct list_head *bdaddr_list) 31558c2ecf20Sopenharmony_ci{ 31568c2ecf20Sopenharmony_ci struct bdaddr_list *b, *n; 31578c2ecf20Sopenharmony_ci 31588c2ecf20Sopenharmony_ci list_for_each_entry_safe(b, n, bdaddr_list, list) { 31598c2ecf20Sopenharmony_ci list_del(&b->list); 31608c2ecf20Sopenharmony_ci kfree(b); 31618c2ecf20Sopenharmony_ci } 31628c2ecf20Sopenharmony_ci} 31638c2ecf20Sopenharmony_ci 31648c2ecf20Sopenharmony_ciint hci_bdaddr_list_add(struct list_head *list, bdaddr_t *bdaddr, u8 type) 31658c2ecf20Sopenharmony_ci{ 31668c2ecf20Sopenharmony_ci struct bdaddr_list *entry; 31678c2ecf20Sopenharmony_ci 31688c2ecf20Sopenharmony_ci if (!bacmp(bdaddr, BDADDR_ANY)) 31698c2ecf20Sopenharmony_ci return -EBADF; 31708c2ecf20Sopenharmony_ci 31718c2ecf20Sopenharmony_ci if (hci_bdaddr_list_lookup(list, bdaddr, type)) 31728c2ecf20Sopenharmony_ci return -EEXIST; 31738c2ecf20Sopenharmony_ci 31748c2ecf20Sopenharmony_ci entry = kzalloc(sizeof(*entry), GFP_KERNEL); 31758c2ecf20Sopenharmony_ci if (!entry) 31768c2ecf20Sopenharmony_ci return -ENOMEM; 31778c2ecf20Sopenharmony_ci 31788c2ecf20Sopenharmony_ci bacpy(&entry->bdaddr, bdaddr); 31798c2ecf20Sopenharmony_ci entry->bdaddr_type = type; 31808c2ecf20Sopenharmony_ci 31818c2ecf20Sopenharmony_ci list_add(&entry->list, list); 31828c2ecf20Sopenharmony_ci 31838c2ecf20Sopenharmony_ci return 0; 31848c2ecf20Sopenharmony_ci} 31858c2ecf20Sopenharmony_ci 31868c2ecf20Sopenharmony_ciint hci_bdaddr_list_add_with_irk(struct list_head *list, bdaddr_t *bdaddr, 31878c2ecf20Sopenharmony_ci u8 type, u8 *peer_irk, u8 *local_irk) 31888c2ecf20Sopenharmony_ci{ 31898c2ecf20Sopenharmony_ci struct bdaddr_list_with_irk *entry; 31908c2ecf20Sopenharmony_ci 31918c2ecf20Sopenharmony_ci if (!bacmp(bdaddr, BDADDR_ANY)) 31928c2ecf20Sopenharmony_ci return -EBADF; 31938c2ecf20Sopenharmony_ci 31948c2ecf20Sopenharmony_ci if (hci_bdaddr_list_lookup(list, bdaddr, type)) 31958c2ecf20Sopenharmony_ci return -EEXIST; 31968c2ecf20Sopenharmony_ci 31978c2ecf20Sopenharmony_ci entry = kzalloc(sizeof(*entry), GFP_KERNEL); 31988c2ecf20Sopenharmony_ci if (!entry) 31998c2ecf20Sopenharmony_ci return -ENOMEM; 32008c2ecf20Sopenharmony_ci 32018c2ecf20Sopenharmony_ci bacpy(&entry->bdaddr, bdaddr); 32028c2ecf20Sopenharmony_ci entry->bdaddr_type = type; 32038c2ecf20Sopenharmony_ci 32048c2ecf20Sopenharmony_ci if (peer_irk) 32058c2ecf20Sopenharmony_ci memcpy(entry->peer_irk, peer_irk, 16); 32068c2ecf20Sopenharmony_ci 32078c2ecf20Sopenharmony_ci if (local_irk) 32088c2ecf20Sopenharmony_ci memcpy(entry->local_irk, local_irk, 16); 32098c2ecf20Sopenharmony_ci 32108c2ecf20Sopenharmony_ci list_add(&entry->list, list); 32118c2ecf20Sopenharmony_ci 32128c2ecf20Sopenharmony_ci return 0; 32138c2ecf20Sopenharmony_ci} 32148c2ecf20Sopenharmony_ci 32158c2ecf20Sopenharmony_ciint hci_bdaddr_list_add_with_flags(struct list_head *list, bdaddr_t *bdaddr, 32168c2ecf20Sopenharmony_ci u8 type, u32 flags) 32178c2ecf20Sopenharmony_ci{ 32188c2ecf20Sopenharmony_ci struct bdaddr_list_with_flags *entry; 32198c2ecf20Sopenharmony_ci 32208c2ecf20Sopenharmony_ci if (!bacmp(bdaddr, BDADDR_ANY)) 32218c2ecf20Sopenharmony_ci return -EBADF; 32228c2ecf20Sopenharmony_ci 32238c2ecf20Sopenharmony_ci if (hci_bdaddr_list_lookup(list, bdaddr, type)) 32248c2ecf20Sopenharmony_ci return -EEXIST; 32258c2ecf20Sopenharmony_ci 32268c2ecf20Sopenharmony_ci entry = kzalloc(sizeof(*entry), GFP_KERNEL); 32278c2ecf20Sopenharmony_ci if (!entry) 32288c2ecf20Sopenharmony_ci return -ENOMEM; 32298c2ecf20Sopenharmony_ci 32308c2ecf20Sopenharmony_ci bacpy(&entry->bdaddr, bdaddr); 32318c2ecf20Sopenharmony_ci entry->bdaddr_type = type; 32328c2ecf20Sopenharmony_ci entry->current_flags = flags; 32338c2ecf20Sopenharmony_ci 32348c2ecf20Sopenharmony_ci list_add(&entry->list, list); 32358c2ecf20Sopenharmony_ci 32368c2ecf20Sopenharmony_ci return 0; 32378c2ecf20Sopenharmony_ci} 32388c2ecf20Sopenharmony_ci 32398c2ecf20Sopenharmony_ciint hci_bdaddr_list_del(struct list_head *list, bdaddr_t *bdaddr, u8 type) 32408c2ecf20Sopenharmony_ci{ 32418c2ecf20Sopenharmony_ci struct bdaddr_list *entry; 32428c2ecf20Sopenharmony_ci 32438c2ecf20Sopenharmony_ci if (!bacmp(bdaddr, BDADDR_ANY)) { 32448c2ecf20Sopenharmony_ci hci_bdaddr_list_clear(list); 32458c2ecf20Sopenharmony_ci return 0; 32468c2ecf20Sopenharmony_ci } 32478c2ecf20Sopenharmony_ci 32488c2ecf20Sopenharmony_ci entry = hci_bdaddr_list_lookup(list, bdaddr, type); 32498c2ecf20Sopenharmony_ci if (!entry) 32508c2ecf20Sopenharmony_ci return -ENOENT; 32518c2ecf20Sopenharmony_ci 32528c2ecf20Sopenharmony_ci list_del(&entry->list); 32538c2ecf20Sopenharmony_ci kfree(entry); 32548c2ecf20Sopenharmony_ci 32558c2ecf20Sopenharmony_ci return 0; 32568c2ecf20Sopenharmony_ci} 32578c2ecf20Sopenharmony_ci 32588c2ecf20Sopenharmony_ciint hci_bdaddr_list_del_with_irk(struct list_head *list, bdaddr_t *bdaddr, 32598c2ecf20Sopenharmony_ci u8 type) 32608c2ecf20Sopenharmony_ci{ 32618c2ecf20Sopenharmony_ci struct bdaddr_list_with_irk *entry; 32628c2ecf20Sopenharmony_ci 32638c2ecf20Sopenharmony_ci if (!bacmp(bdaddr, BDADDR_ANY)) { 32648c2ecf20Sopenharmony_ci hci_bdaddr_list_clear(list); 32658c2ecf20Sopenharmony_ci return 0; 32668c2ecf20Sopenharmony_ci } 32678c2ecf20Sopenharmony_ci 32688c2ecf20Sopenharmony_ci entry = hci_bdaddr_list_lookup_with_irk(list, bdaddr, type); 32698c2ecf20Sopenharmony_ci if (!entry) 32708c2ecf20Sopenharmony_ci return -ENOENT; 32718c2ecf20Sopenharmony_ci 32728c2ecf20Sopenharmony_ci list_del(&entry->list); 32738c2ecf20Sopenharmony_ci kfree(entry); 32748c2ecf20Sopenharmony_ci 32758c2ecf20Sopenharmony_ci return 0; 32768c2ecf20Sopenharmony_ci} 32778c2ecf20Sopenharmony_ci 32788c2ecf20Sopenharmony_ciint hci_bdaddr_list_del_with_flags(struct list_head *list, bdaddr_t *bdaddr, 32798c2ecf20Sopenharmony_ci u8 type) 32808c2ecf20Sopenharmony_ci{ 32818c2ecf20Sopenharmony_ci struct bdaddr_list_with_flags *entry; 32828c2ecf20Sopenharmony_ci 32838c2ecf20Sopenharmony_ci if (!bacmp(bdaddr, BDADDR_ANY)) { 32848c2ecf20Sopenharmony_ci hci_bdaddr_list_clear(list); 32858c2ecf20Sopenharmony_ci return 0; 32868c2ecf20Sopenharmony_ci } 32878c2ecf20Sopenharmony_ci 32888c2ecf20Sopenharmony_ci entry = hci_bdaddr_list_lookup_with_flags(list, bdaddr, type); 32898c2ecf20Sopenharmony_ci if (!entry) 32908c2ecf20Sopenharmony_ci return -ENOENT; 32918c2ecf20Sopenharmony_ci 32928c2ecf20Sopenharmony_ci list_del(&entry->list); 32938c2ecf20Sopenharmony_ci kfree(entry); 32948c2ecf20Sopenharmony_ci 32958c2ecf20Sopenharmony_ci return 0; 32968c2ecf20Sopenharmony_ci} 32978c2ecf20Sopenharmony_ci 32988c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */ 32998c2ecf20Sopenharmony_cistruct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev, 33008c2ecf20Sopenharmony_ci bdaddr_t *addr, u8 addr_type) 33018c2ecf20Sopenharmony_ci{ 33028c2ecf20Sopenharmony_ci struct hci_conn_params *params; 33038c2ecf20Sopenharmony_ci 33048c2ecf20Sopenharmony_ci list_for_each_entry(params, &hdev->le_conn_params, list) { 33058c2ecf20Sopenharmony_ci if (bacmp(¶ms->addr, addr) == 0 && 33068c2ecf20Sopenharmony_ci params->addr_type == addr_type) { 33078c2ecf20Sopenharmony_ci return params; 33088c2ecf20Sopenharmony_ci } 33098c2ecf20Sopenharmony_ci } 33108c2ecf20Sopenharmony_ci 33118c2ecf20Sopenharmony_ci return NULL; 33128c2ecf20Sopenharmony_ci} 33138c2ecf20Sopenharmony_ci 33148c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */ 33158c2ecf20Sopenharmony_cistruct hci_conn_params *hci_pend_le_action_lookup(struct list_head *list, 33168c2ecf20Sopenharmony_ci bdaddr_t *addr, u8 addr_type) 33178c2ecf20Sopenharmony_ci{ 33188c2ecf20Sopenharmony_ci struct hci_conn_params *param; 33198c2ecf20Sopenharmony_ci 33208c2ecf20Sopenharmony_ci switch (addr_type) { 33218c2ecf20Sopenharmony_ci case ADDR_LE_DEV_PUBLIC_RESOLVED: 33228c2ecf20Sopenharmony_ci addr_type = ADDR_LE_DEV_PUBLIC; 33238c2ecf20Sopenharmony_ci break; 33248c2ecf20Sopenharmony_ci case ADDR_LE_DEV_RANDOM_RESOLVED: 33258c2ecf20Sopenharmony_ci addr_type = ADDR_LE_DEV_RANDOM; 33268c2ecf20Sopenharmony_ci break; 33278c2ecf20Sopenharmony_ci } 33288c2ecf20Sopenharmony_ci 33298c2ecf20Sopenharmony_ci list_for_each_entry(param, list, action) { 33308c2ecf20Sopenharmony_ci if (bacmp(¶m->addr, addr) == 0 && 33318c2ecf20Sopenharmony_ci param->addr_type == addr_type) 33328c2ecf20Sopenharmony_ci return param; 33338c2ecf20Sopenharmony_ci } 33348c2ecf20Sopenharmony_ci 33358c2ecf20Sopenharmony_ci return NULL; 33368c2ecf20Sopenharmony_ci} 33378c2ecf20Sopenharmony_ci 33388c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */ 33398c2ecf20Sopenharmony_cistruct hci_conn_params *hci_conn_params_add(struct hci_dev *hdev, 33408c2ecf20Sopenharmony_ci bdaddr_t *addr, u8 addr_type) 33418c2ecf20Sopenharmony_ci{ 33428c2ecf20Sopenharmony_ci struct hci_conn_params *params; 33438c2ecf20Sopenharmony_ci 33448c2ecf20Sopenharmony_ci params = hci_conn_params_lookup(hdev, addr, addr_type); 33458c2ecf20Sopenharmony_ci if (params) 33468c2ecf20Sopenharmony_ci return params; 33478c2ecf20Sopenharmony_ci 33488c2ecf20Sopenharmony_ci params = kzalloc(sizeof(*params), GFP_KERNEL); 33498c2ecf20Sopenharmony_ci if (!params) { 33508c2ecf20Sopenharmony_ci bt_dev_err(hdev, "out of memory"); 33518c2ecf20Sopenharmony_ci return NULL; 33528c2ecf20Sopenharmony_ci } 33538c2ecf20Sopenharmony_ci 33548c2ecf20Sopenharmony_ci bacpy(¶ms->addr, addr); 33558c2ecf20Sopenharmony_ci params->addr_type = addr_type; 33568c2ecf20Sopenharmony_ci 33578c2ecf20Sopenharmony_ci list_add(¶ms->list, &hdev->le_conn_params); 33588c2ecf20Sopenharmony_ci INIT_LIST_HEAD(¶ms->action); 33598c2ecf20Sopenharmony_ci 33608c2ecf20Sopenharmony_ci params->conn_min_interval = hdev->le_conn_min_interval; 33618c2ecf20Sopenharmony_ci params->conn_max_interval = hdev->le_conn_max_interval; 33628c2ecf20Sopenharmony_ci params->conn_latency = hdev->le_conn_latency; 33638c2ecf20Sopenharmony_ci params->supervision_timeout = hdev->le_supv_timeout; 33648c2ecf20Sopenharmony_ci params->auto_connect = HCI_AUTO_CONN_DISABLED; 33658c2ecf20Sopenharmony_ci 33668c2ecf20Sopenharmony_ci BT_DBG("addr %pMR (type %u)", addr, addr_type); 33678c2ecf20Sopenharmony_ci 33688c2ecf20Sopenharmony_ci return params; 33698c2ecf20Sopenharmony_ci} 33708c2ecf20Sopenharmony_ci 33718c2ecf20Sopenharmony_cistatic void hci_conn_params_free(struct hci_conn_params *params) 33728c2ecf20Sopenharmony_ci{ 33738c2ecf20Sopenharmony_ci if (params->conn) { 33748c2ecf20Sopenharmony_ci hci_conn_drop(params->conn); 33758c2ecf20Sopenharmony_ci hci_conn_put(params->conn); 33768c2ecf20Sopenharmony_ci } 33778c2ecf20Sopenharmony_ci 33788c2ecf20Sopenharmony_ci list_del(¶ms->action); 33798c2ecf20Sopenharmony_ci list_del(¶ms->list); 33808c2ecf20Sopenharmony_ci kfree(params); 33818c2ecf20Sopenharmony_ci} 33828c2ecf20Sopenharmony_ci 33838c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */ 33848c2ecf20Sopenharmony_civoid hci_conn_params_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type) 33858c2ecf20Sopenharmony_ci{ 33868c2ecf20Sopenharmony_ci struct hci_conn_params *params; 33878c2ecf20Sopenharmony_ci 33888c2ecf20Sopenharmony_ci params = hci_conn_params_lookup(hdev, addr, addr_type); 33898c2ecf20Sopenharmony_ci if (!params) 33908c2ecf20Sopenharmony_ci return; 33918c2ecf20Sopenharmony_ci 33928c2ecf20Sopenharmony_ci hci_conn_params_free(params); 33938c2ecf20Sopenharmony_ci 33948c2ecf20Sopenharmony_ci hci_update_background_scan(hdev); 33958c2ecf20Sopenharmony_ci 33968c2ecf20Sopenharmony_ci BT_DBG("addr %pMR (type %u)", addr, addr_type); 33978c2ecf20Sopenharmony_ci} 33988c2ecf20Sopenharmony_ci 33998c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */ 34008c2ecf20Sopenharmony_civoid hci_conn_params_clear_disabled(struct hci_dev *hdev) 34018c2ecf20Sopenharmony_ci{ 34028c2ecf20Sopenharmony_ci struct hci_conn_params *params, *tmp; 34038c2ecf20Sopenharmony_ci 34048c2ecf20Sopenharmony_ci list_for_each_entry_safe(params, tmp, &hdev->le_conn_params, list) { 34058c2ecf20Sopenharmony_ci if (params->auto_connect != HCI_AUTO_CONN_DISABLED) 34068c2ecf20Sopenharmony_ci continue; 34078c2ecf20Sopenharmony_ci 34088c2ecf20Sopenharmony_ci /* If trying to estabilish one time connection to disabled 34098c2ecf20Sopenharmony_ci * device, leave the params, but mark them as just once. 34108c2ecf20Sopenharmony_ci */ 34118c2ecf20Sopenharmony_ci if (params->explicit_connect) { 34128c2ecf20Sopenharmony_ci params->auto_connect = HCI_AUTO_CONN_EXPLICIT; 34138c2ecf20Sopenharmony_ci continue; 34148c2ecf20Sopenharmony_ci } 34158c2ecf20Sopenharmony_ci 34168c2ecf20Sopenharmony_ci list_del(¶ms->list); 34178c2ecf20Sopenharmony_ci kfree(params); 34188c2ecf20Sopenharmony_ci } 34198c2ecf20Sopenharmony_ci 34208c2ecf20Sopenharmony_ci BT_DBG("All LE disabled connection parameters were removed"); 34218c2ecf20Sopenharmony_ci} 34228c2ecf20Sopenharmony_ci 34238c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */ 34248c2ecf20Sopenharmony_cistatic void hci_conn_params_clear_all(struct hci_dev *hdev) 34258c2ecf20Sopenharmony_ci{ 34268c2ecf20Sopenharmony_ci struct hci_conn_params *params, *tmp; 34278c2ecf20Sopenharmony_ci 34288c2ecf20Sopenharmony_ci list_for_each_entry_safe(params, tmp, &hdev->le_conn_params, list) 34298c2ecf20Sopenharmony_ci hci_conn_params_free(params); 34308c2ecf20Sopenharmony_ci 34318c2ecf20Sopenharmony_ci BT_DBG("All LE connection parameters were removed"); 34328c2ecf20Sopenharmony_ci} 34338c2ecf20Sopenharmony_ci 34348c2ecf20Sopenharmony_ci/* Copy the Identity Address of the controller. 34358c2ecf20Sopenharmony_ci * 34368c2ecf20Sopenharmony_ci * If the controller has a public BD_ADDR, then by default use that one. 34378c2ecf20Sopenharmony_ci * If this is a LE only controller without a public address, default to 34388c2ecf20Sopenharmony_ci * the static random address. 34398c2ecf20Sopenharmony_ci * 34408c2ecf20Sopenharmony_ci * For debugging purposes it is possible to force controllers with a 34418c2ecf20Sopenharmony_ci * public address to use the static random address instead. 34428c2ecf20Sopenharmony_ci * 34438c2ecf20Sopenharmony_ci * In case BR/EDR has been disabled on a dual-mode controller and 34448c2ecf20Sopenharmony_ci * userspace has configured a static address, then that address 34458c2ecf20Sopenharmony_ci * becomes the identity address instead of the public BR/EDR address. 34468c2ecf20Sopenharmony_ci */ 34478c2ecf20Sopenharmony_civoid hci_copy_identity_address(struct hci_dev *hdev, bdaddr_t *bdaddr, 34488c2ecf20Sopenharmony_ci u8 *bdaddr_type) 34498c2ecf20Sopenharmony_ci{ 34508c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) || 34518c2ecf20Sopenharmony_ci !bacmp(&hdev->bdaddr, BDADDR_ANY) || 34528c2ecf20Sopenharmony_ci (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) && 34538c2ecf20Sopenharmony_ci bacmp(&hdev->static_addr, BDADDR_ANY))) { 34548c2ecf20Sopenharmony_ci bacpy(bdaddr, &hdev->static_addr); 34558c2ecf20Sopenharmony_ci *bdaddr_type = ADDR_LE_DEV_RANDOM; 34568c2ecf20Sopenharmony_ci } else { 34578c2ecf20Sopenharmony_ci bacpy(bdaddr, &hdev->bdaddr); 34588c2ecf20Sopenharmony_ci *bdaddr_type = ADDR_LE_DEV_PUBLIC; 34598c2ecf20Sopenharmony_ci } 34608c2ecf20Sopenharmony_ci} 34618c2ecf20Sopenharmony_ci 34628c2ecf20Sopenharmony_cistatic void hci_suspend_clear_tasks(struct hci_dev *hdev) 34638c2ecf20Sopenharmony_ci{ 34648c2ecf20Sopenharmony_ci int i; 34658c2ecf20Sopenharmony_ci 34668c2ecf20Sopenharmony_ci for (i = 0; i < __SUSPEND_NUM_TASKS; i++) 34678c2ecf20Sopenharmony_ci clear_bit(i, hdev->suspend_tasks); 34688c2ecf20Sopenharmony_ci 34698c2ecf20Sopenharmony_ci wake_up(&hdev->suspend_wait_q); 34708c2ecf20Sopenharmony_ci} 34718c2ecf20Sopenharmony_ci 34728c2ecf20Sopenharmony_cistatic int hci_suspend_wait_event(struct hci_dev *hdev) 34738c2ecf20Sopenharmony_ci{ 34748c2ecf20Sopenharmony_ci#define WAKE_COND \ 34758c2ecf20Sopenharmony_ci (find_first_bit(hdev->suspend_tasks, __SUSPEND_NUM_TASKS) == \ 34768c2ecf20Sopenharmony_ci __SUSPEND_NUM_TASKS) 34778c2ecf20Sopenharmony_ci 34788c2ecf20Sopenharmony_ci int i; 34798c2ecf20Sopenharmony_ci int ret = wait_event_timeout(hdev->suspend_wait_q, 34808c2ecf20Sopenharmony_ci WAKE_COND, SUSPEND_NOTIFIER_TIMEOUT); 34818c2ecf20Sopenharmony_ci 34828c2ecf20Sopenharmony_ci if (ret == 0) { 34838c2ecf20Sopenharmony_ci bt_dev_err(hdev, "Timed out waiting for suspend events"); 34848c2ecf20Sopenharmony_ci for (i = 0; i < __SUSPEND_NUM_TASKS; ++i) { 34858c2ecf20Sopenharmony_ci if (test_bit(i, hdev->suspend_tasks)) 34868c2ecf20Sopenharmony_ci bt_dev_err(hdev, "Suspend timeout bit: %d", i); 34878c2ecf20Sopenharmony_ci clear_bit(i, hdev->suspend_tasks); 34888c2ecf20Sopenharmony_ci } 34898c2ecf20Sopenharmony_ci 34908c2ecf20Sopenharmony_ci ret = -ETIMEDOUT; 34918c2ecf20Sopenharmony_ci } else { 34928c2ecf20Sopenharmony_ci ret = 0; 34938c2ecf20Sopenharmony_ci } 34948c2ecf20Sopenharmony_ci 34958c2ecf20Sopenharmony_ci return ret; 34968c2ecf20Sopenharmony_ci} 34978c2ecf20Sopenharmony_ci 34988c2ecf20Sopenharmony_cistatic void hci_prepare_suspend(struct work_struct *work) 34998c2ecf20Sopenharmony_ci{ 35008c2ecf20Sopenharmony_ci struct hci_dev *hdev = 35018c2ecf20Sopenharmony_ci container_of(work, struct hci_dev, suspend_prepare); 35028c2ecf20Sopenharmony_ci 35038c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 35048c2ecf20Sopenharmony_ci hci_req_prepare_suspend(hdev, hdev->suspend_state_next); 35058c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 35068c2ecf20Sopenharmony_ci} 35078c2ecf20Sopenharmony_ci 35088c2ecf20Sopenharmony_cistatic int hci_change_suspend_state(struct hci_dev *hdev, 35098c2ecf20Sopenharmony_ci enum suspended_state next) 35108c2ecf20Sopenharmony_ci{ 35118c2ecf20Sopenharmony_ci hdev->suspend_state_next = next; 35128c2ecf20Sopenharmony_ci set_bit(SUSPEND_PREPARE_NOTIFIER, hdev->suspend_tasks); 35138c2ecf20Sopenharmony_ci queue_work(hdev->req_workqueue, &hdev->suspend_prepare); 35148c2ecf20Sopenharmony_ci return hci_suspend_wait_event(hdev); 35158c2ecf20Sopenharmony_ci} 35168c2ecf20Sopenharmony_ci 35178c2ecf20Sopenharmony_cistatic void hci_clear_wake_reason(struct hci_dev *hdev) 35188c2ecf20Sopenharmony_ci{ 35198c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 35208c2ecf20Sopenharmony_ci 35218c2ecf20Sopenharmony_ci hdev->wake_reason = 0; 35228c2ecf20Sopenharmony_ci bacpy(&hdev->wake_addr, BDADDR_ANY); 35238c2ecf20Sopenharmony_ci hdev->wake_addr_type = 0; 35248c2ecf20Sopenharmony_ci 35258c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 35268c2ecf20Sopenharmony_ci} 35278c2ecf20Sopenharmony_ci 35288c2ecf20Sopenharmony_cistatic int hci_suspend_notifier(struct notifier_block *nb, unsigned long action, 35298c2ecf20Sopenharmony_ci void *data) 35308c2ecf20Sopenharmony_ci{ 35318c2ecf20Sopenharmony_ci struct hci_dev *hdev = 35328c2ecf20Sopenharmony_ci container_of(nb, struct hci_dev, suspend_notifier); 35338c2ecf20Sopenharmony_ci int ret = 0; 35348c2ecf20Sopenharmony_ci u8 state = BT_RUNNING; 35358c2ecf20Sopenharmony_ci 35368c2ecf20Sopenharmony_ci /* If powering down, wait for completion. */ 35378c2ecf20Sopenharmony_ci if (mgmt_powering_down(hdev)) { 35388c2ecf20Sopenharmony_ci set_bit(SUSPEND_POWERING_DOWN, hdev->suspend_tasks); 35398c2ecf20Sopenharmony_ci ret = hci_suspend_wait_event(hdev); 35408c2ecf20Sopenharmony_ci if (ret) 35418c2ecf20Sopenharmony_ci goto done; 35428c2ecf20Sopenharmony_ci } 35438c2ecf20Sopenharmony_ci 35448c2ecf20Sopenharmony_ci /* Suspend notifier should only act on events when powered. */ 35458c2ecf20Sopenharmony_ci if (!hdev_is_powered(hdev) || 35468c2ecf20Sopenharmony_ci hci_dev_test_flag(hdev, HCI_UNREGISTER)) 35478c2ecf20Sopenharmony_ci goto done; 35488c2ecf20Sopenharmony_ci 35498c2ecf20Sopenharmony_ci if (action == PM_SUSPEND_PREPARE) { 35508c2ecf20Sopenharmony_ci /* Suspend consists of two actions: 35518c2ecf20Sopenharmony_ci * - First, disconnect everything and make the controller not 35528c2ecf20Sopenharmony_ci * connectable (disabling scanning) 35538c2ecf20Sopenharmony_ci * - Second, program event filter/accept list and enable scan 35548c2ecf20Sopenharmony_ci */ 35558c2ecf20Sopenharmony_ci ret = hci_change_suspend_state(hdev, BT_SUSPEND_DISCONNECT); 35568c2ecf20Sopenharmony_ci if (!ret) 35578c2ecf20Sopenharmony_ci state = BT_SUSPEND_DISCONNECT; 35588c2ecf20Sopenharmony_ci 35598c2ecf20Sopenharmony_ci /* Only configure accept list if disconnect succeeded and wake 35608c2ecf20Sopenharmony_ci * isn't being prevented. 35618c2ecf20Sopenharmony_ci */ 35628c2ecf20Sopenharmony_ci if (!ret && !(hdev->prevent_wake && hdev->prevent_wake(hdev))) { 35638c2ecf20Sopenharmony_ci ret = hci_change_suspend_state(hdev, 35648c2ecf20Sopenharmony_ci BT_SUSPEND_CONFIGURE_WAKE); 35658c2ecf20Sopenharmony_ci if (!ret) 35668c2ecf20Sopenharmony_ci state = BT_SUSPEND_CONFIGURE_WAKE; 35678c2ecf20Sopenharmony_ci } 35688c2ecf20Sopenharmony_ci 35698c2ecf20Sopenharmony_ci hci_clear_wake_reason(hdev); 35708c2ecf20Sopenharmony_ci mgmt_suspending(hdev, state); 35718c2ecf20Sopenharmony_ci 35728c2ecf20Sopenharmony_ci } else if (action == PM_POST_SUSPEND) { 35738c2ecf20Sopenharmony_ci ret = hci_change_suspend_state(hdev, BT_RUNNING); 35748c2ecf20Sopenharmony_ci 35758c2ecf20Sopenharmony_ci mgmt_resuming(hdev, hdev->wake_reason, &hdev->wake_addr, 35768c2ecf20Sopenharmony_ci hdev->wake_addr_type); 35778c2ecf20Sopenharmony_ci } 35788c2ecf20Sopenharmony_ci 35798c2ecf20Sopenharmony_cidone: 35808c2ecf20Sopenharmony_ci /* We always allow suspend even if suspend preparation failed and 35818c2ecf20Sopenharmony_ci * attempt to recover in resume. 35828c2ecf20Sopenharmony_ci */ 35838c2ecf20Sopenharmony_ci if (ret) 35848c2ecf20Sopenharmony_ci bt_dev_err(hdev, "Suspend notifier action (%lu) failed: %d", 35858c2ecf20Sopenharmony_ci action, ret); 35868c2ecf20Sopenharmony_ci 35878c2ecf20Sopenharmony_ci return NOTIFY_DONE; 35888c2ecf20Sopenharmony_ci} 35898c2ecf20Sopenharmony_ci 35908c2ecf20Sopenharmony_ci/* Alloc HCI device */ 35918c2ecf20Sopenharmony_cistruct hci_dev *hci_alloc_dev(void) 35928c2ecf20Sopenharmony_ci{ 35938c2ecf20Sopenharmony_ci struct hci_dev *hdev; 35948c2ecf20Sopenharmony_ci 35958c2ecf20Sopenharmony_ci hdev = kzalloc(sizeof(*hdev), GFP_KERNEL); 35968c2ecf20Sopenharmony_ci if (!hdev) 35978c2ecf20Sopenharmony_ci return NULL; 35988c2ecf20Sopenharmony_ci 35998c2ecf20Sopenharmony_ci hdev->pkt_type = (HCI_DM1 | HCI_DH1 | HCI_HV1); 36008c2ecf20Sopenharmony_ci hdev->esco_type = (ESCO_HV1); 36018c2ecf20Sopenharmony_ci hdev->link_mode = (HCI_LM_ACCEPT); 36028c2ecf20Sopenharmony_ci hdev->num_iac = 0x01; /* One IAC support is mandatory */ 36038c2ecf20Sopenharmony_ci hdev->io_capability = 0x03; /* No Input No Output */ 36048c2ecf20Sopenharmony_ci hdev->manufacturer = 0xffff; /* Default to internal use */ 36058c2ecf20Sopenharmony_ci hdev->inq_tx_power = HCI_TX_POWER_INVALID; 36068c2ecf20Sopenharmony_ci hdev->adv_tx_power = HCI_TX_POWER_INVALID; 36078c2ecf20Sopenharmony_ci hdev->adv_instance_cnt = 0; 36088c2ecf20Sopenharmony_ci hdev->cur_adv_instance = 0x00; 36098c2ecf20Sopenharmony_ci hdev->adv_instance_timeout = 0; 36108c2ecf20Sopenharmony_ci 36118c2ecf20Sopenharmony_ci hdev->advmon_allowlist_duration = 300; 36128c2ecf20Sopenharmony_ci hdev->advmon_no_filter_duration = 500; 36138c2ecf20Sopenharmony_ci 36148c2ecf20Sopenharmony_ci hdev->sniff_max_interval = 800; 36158c2ecf20Sopenharmony_ci hdev->sniff_min_interval = 80; 36168c2ecf20Sopenharmony_ci 36178c2ecf20Sopenharmony_ci hdev->le_adv_channel_map = 0x07; 36188c2ecf20Sopenharmony_ci hdev->le_adv_min_interval = 0x0800; 36198c2ecf20Sopenharmony_ci hdev->le_adv_max_interval = 0x0800; 36208c2ecf20Sopenharmony_ci hdev->le_scan_interval = 0x0060; 36218c2ecf20Sopenharmony_ci hdev->le_scan_window = 0x0030; 36228c2ecf20Sopenharmony_ci hdev->le_scan_int_suspend = 0x0400; 36238c2ecf20Sopenharmony_ci hdev->le_scan_window_suspend = 0x0012; 36248c2ecf20Sopenharmony_ci hdev->le_scan_int_discovery = DISCOV_LE_SCAN_INT; 36258c2ecf20Sopenharmony_ci hdev->le_scan_window_discovery = DISCOV_LE_SCAN_WIN; 36268c2ecf20Sopenharmony_ci hdev->le_scan_int_connect = 0x0060; 36278c2ecf20Sopenharmony_ci hdev->le_scan_window_connect = 0x0060; 36288c2ecf20Sopenharmony_ci hdev->le_conn_min_interval = 0x0018; 36298c2ecf20Sopenharmony_ci hdev->le_conn_max_interval = 0x0028; 36308c2ecf20Sopenharmony_ci hdev->le_conn_latency = 0x0000; 36318c2ecf20Sopenharmony_ci hdev->le_supv_timeout = 0x002a; 36328c2ecf20Sopenharmony_ci hdev->le_def_tx_len = 0x001b; 36338c2ecf20Sopenharmony_ci hdev->le_def_tx_time = 0x0148; 36348c2ecf20Sopenharmony_ci hdev->le_max_tx_len = 0x001b; 36358c2ecf20Sopenharmony_ci hdev->le_max_tx_time = 0x0148; 36368c2ecf20Sopenharmony_ci hdev->le_max_rx_len = 0x001b; 36378c2ecf20Sopenharmony_ci hdev->le_max_rx_time = 0x0148; 36388c2ecf20Sopenharmony_ci hdev->le_max_key_size = SMP_MAX_ENC_KEY_SIZE; 36398c2ecf20Sopenharmony_ci hdev->le_min_key_size = SMP_MIN_ENC_KEY_SIZE; 36408c2ecf20Sopenharmony_ci hdev->le_tx_def_phys = HCI_LE_SET_PHY_1M; 36418c2ecf20Sopenharmony_ci hdev->le_rx_def_phys = HCI_LE_SET_PHY_1M; 36428c2ecf20Sopenharmony_ci hdev->le_num_of_adv_sets = HCI_MAX_ADV_INSTANCES; 36438c2ecf20Sopenharmony_ci hdev->def_multi_adv_rotation_duration = HCI_DEFAULT_ADV_DURATION; 36448c2ecf20Sopenharmony_ci hdev->def_le_autoconnect_timeout = HCI_LE_AUTOCONN_TIMEOUT; 36458c2ecf20Sopenharmony_ci 36468c2ecf20Sopenharmony_ci hdev->rpa_timeout = HCI_DEFAULT_RPA_TIMEOUT; 36478c2ecf20Sopenharmony_ci hdev->discov_interleaved_timeout = DISCOV_INTERLEAVED_TIMEOUT; 36488c2ecf20Sopenharmony_ci hdev->conn_info_min_age = DEFAULT_CONN_INFO_MIN_AGE; 36498c2ecf20Sopenharmony_ci hdev->conn_info_max_age = DEFAULT_CONN_INFO_MAX_AGE; 36508c2ecf20Sopenharmony_ci hdev->auth_payload_timeout = DEFAULT_AUTH_PAYLOAD_TIMEOUT; 36518c2ecf20Sopenharmony_ci hdev->min_enc_key_size = HCI_MIN_ENC_KEY_SIZE; 36528c2ecf20Sopenharmony_ci 36538c2ecf20Sopenharmony_ci /* default 1.28 sec page scan */ 36548c2ecf20Sopenharmony_ci hdev->def_page_scan_type = PAGE_SCAN_TYPE_STANDARD; 36558c2ecf20Sopenharmony_ci hdev->def_page_scan_int = 0x0800; 36568c2ecf20Sopenharmony_ci hdev->def_page_scan_window = 0x0012; 36578c2ecf20Sopenharmony_ci 36588c2ecf20Sopenharmony_ci mutex_init(&hdev->lock); 36598c2ecf20Sopenharmony_ci mutex_init(&hdev->req_lock); 36608c2ecf20Sopenharmony_ci 36618c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&hdev->mgmt_pending); 36628c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&hdev->reject_list); 36638c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&hdev->accept_list); 36648c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&hdev->uuids); 36658c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&hdev->link_keys); 36668c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&hdev->long_term_keys); 36678c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&hdev->identity_resolving_keys); 36688c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&hdev->remote_oob_data); 36698c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&hdev->le_accept_list); 36708c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&hdev->le_resolv_list); 36718c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&hdev->le_conn_params); 36728c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&hdev->pend_le_conns); 36738c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&hdev->pend_le_reports); 36748c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&hdev->conn_hash.list); 36758c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&hdev->adv_instances); 36768c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&hdev->blocked_keys); 36778c2ecf20Sopenharmony_ci 36788c2ecf20Sopenharmony_ci INIT_WORK(&hdev->rx_work, hci_rx_work); 36798c2ecf20Sopenharmony_ci INIT_WORK(&hdev->cmd_work, hci_cmd_work); 36808c2ecf20Sopenharmony_ci INIT_WORK(&hdev->tx_work, hci_tx_work); 36818c2ecf20Sopenharmony_ci INIT_WORK(&hdev->power_on, hci_power_on); 36828c2ecf20Sopenharmony_ci INIT_WORK(&hdev->error_reset, hci_error_reset); 36838c2ecf20Sopenharmony_ci INIT_WORK(&hdev->suspend_prepare, hci_prepare_suspend); 36848c2ecf20Sopenharmony_ci 36858c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&hdev->power_off, hci_power_off); 36868c2ecf20Sopenharmony_ci 36878c2ecf20Sopenharmony_ci skb_queue_head_init(&hdev->rx_q); 36888c2ecf20Sopenharmony_ci skb_queue_head_init(&hdev->cmd_q); 36898c2ecf20Sopenharmony_ci skb_queue_head_init(&hdev->raw_q); 36908c2ecf20Sopenharmony_ci 36918c2ecf20Sopenharmony_ci init_waitqueue_head(&hdev->req_wait_q); 36928c2ecf20Sopenharmony_ci init_waitqueue_head(&hdev->suspend_wait_q); 36938c2ecf20Sopenharmony_ci 36948c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&hdev->cmd_timer, hci_cmd_timeout); 36958c2ecf20Sopenharmony_ci 36968c2ecf20Sopenharmony_ci hci_request_setup(hdev); 36978c2ecf20Sopenharmony_ci 36988c2ecf20Sopenharmony_ci hci_init_sysfs(hdev); 36998c2ecf20Sopenharmony_ci discovery_init(hdev); 37008c2ecf20Sopenharmony_ci 37018c2ecf20Sopenharmony_ci return hdev; 37028c2ecf20Sopenharmony_ci} 37038c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hci_alloc_dev); 37048c2ecf20Sopenharmony_ci 37058c2ecf20Sopenharmony_ci/* Free HCI device */ 37068c2ecf20Sopenharmony_civoid hci_free_dev(struct hci_dev *hdev) 37078c2ecf20Sopenharmony_ci{ 37088c2ecf20Sopenharmony_ci /* will free via device release */ 37098c2ecf20Sopenharmony_ci put_device(&hdev->dev); 37108c2ecf20Sopenharmony_ci} 37118c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hci_free_dev); 37128c2ecf20Sopenharmony_ci 37138c2ecf20Sopenharmony_ci/* Register HCI device */ 37148c2ecf20Sopenharmony_ciint hci_register_dev(struct hci_dev *hdev) 37158c2ecf20Sopenharmony_ci{ 37168c2ecf20Sopenharmony_ci int id, error; 37178c2ecf20Sopenharmony_ci 37188c2ecf20Sopenharmony_ci if (!hdev->open || !hdev->close || !hdev->send) 37198c2ecf20Sopenharmony_ci return -EINVAL; 37208c2ecf20Sopenharmony_ci 37218c2ecf20Sopenharmony_ci /* Do not allow HCI_AMP devices to register at index 0, 37228c2ecf20Sopenharmony_ci * so the index can be used as the AMP controller ID. 37238c2ecf20Sopenharmony_ci */ 37248c2ecf20Sopenharmony_ci switch (hdev->dev_type) { 37258c2ecf20Sopenharmony_ci case HCI_PRIMARY: 37268c2ecf20Sopenharmony_ci id = ida_simple_get(&hci_index_ida, 0, HCI_MAX_ID, GFP_KERNEL); 37278c2ecf20Sopenharmony_ci break; 37288c2ecf20Sopenharmony_ci case HCI_AMP: 37298c2ecf20Sopenharmony_ci id = ida_simple_get(&hci_index_ida, 1, HCI_MAX_ID, GFP_KERNEL); 37308c2ecf20Sopenharmony_ci break; 37318c2ecf20Sopenharmony_ci default: 37328c2ecf20Sopenharmony_ci return -EINVAL; 37338c2ecf20Sopenharmony_ci } 37348c2ecf20Sopenharmony_ci 37358c2ecf20Sopenharmony_ci if (id < 0) 37368c2ecf20Sopenharmony_ci return id; 37378c2ecf20Sopenharmony_ci 37388c2ecf20Sopenharmony_ci error = dev_set_name(&hdev->dev, "hci%u", id); 37398c2ecf20Sopenharmony_ci if (error) 37408c2ecf20Sopenharmony_ci return error; 37418c2ecf20Sopenharmony_ci 37428c2ecf20Sopenharmony_ci hdev->name = dev_name(&hdev->dev); 37438c2ecf20Sopenharmony_ci hdev->id = id; 37448c2ecf20Sopenharmony_ci 37458c2ecf20Sopenharmony_ci BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); 37468c2ecf20Sopenharmony_ci 37478c2ecf20Sopenharmony_ci hdev->workqueue = alloc_ordered_workqueue("%s", WQ_HIGHPRI, hdev->name); 37488c2ecf20Sopenharmony_ci if (!hdev->workqueue) { 37498c2ecf20Sopenharmony_ci error = -ENOMEM; 37508c2ecf20Sopenharmony_ci goto err; 37518c2ecf20Sopenharmony_ci } 37528c2ecf20Sopenharmony_ci 37538c2ecf20Sopenharmony_ci hdev->req_workqueue = alloc_ordered_workqueue("%s", WQ_HIGHPRI, 37548c2ecf20Sopenharmony_ci hdev->name); 37558c2ecf20Sopenharmony_ci if (!hdev->req_workqueue) { 37568c2ecf20Sopenharmony_ci destroy_workqueue(hdev->workqueue); 37578c2ecf20Sopenharmony_ci error = -ENOMEM; 37588c2ecf20Sopenharmony_ci goto err; 37598c2ecf20Sopenharmony_ci } 37608c2ecf20Sopenharmony_ci 37618c2ecf20Sopenharmony_ci if (!IS_ERR_OR_NULL(bt_debugfs)) 37628c2ecf20Sopenharmony_ci hdev->debugfs = debugfs_create_dir(hdev->name, bt_debugfs); 37638c2ecf20Sopenharmony_ci 37648c2ecf20Sopenharmony_ci error = device_add(&hdev->dev); 37658c2ecf20Sopenharmony_ci if (error < 0) 37668c2ecf20Sopenharmony_ci goto err_wqueue; 37678c2ecf20Sopenharmony_ci 37688c2ecf20Sopenharmony_ci hci_leds_init(hdev); 37698c2ecf20Sopenharmony_ci 37708c2ecf20Sopenharmony_ci hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev, 37718c2ecf20Sopenharmony_ci RFKILL_TYPE_BLUETOOTH, &hci_rfkill_ops, 37728c2ecf20Sopenharmony_ci hdev); 37738c2ecf20Sopenharmony_ci if (hdev->rfkill) { 37748c2ecf20Sopenharmony_ci if (rfkill_register(hdev->rfkill) < 0) { 37758c2ecf20Sopenharmony_ci rfkill_destroy(hdev->rfkill); 37768c2ecf20Sopenharmony_ci hdev->rfkill = NULL; 37778c2ecf20Sopenharmony_ci } 37788c2ecf20Sopenharmony_ci } 37798c2ecf20Sopenharmony_ci 37808c2ecf20Sopenharmony_ci if (hdev->rfkill && rfkill_blocked(hdev->rfkill)) 37818c2ecf20Sopenharmony_ci hci_dev_set_flag(hdev, HCI_RFKILLED); 37828c2ecf20Sopenharmony_ci 37838c2ecf20Sopenharmony_ci hci_dev_set_flag(hdev, HCI_SETUP); 37848c2ecf20Sopenharmony_ci hci_dev_set_flag(hdev, HCI_AUTO_OFF); 37858c2ecf20Sopenharmony_ci 37868c2ecf20Sopenharmony_ci if (hdev->dev_type == HCI_PRIMARY) { 37878c2ecf20Sopenharmony_ci /* Assume BR/EDR support until proven otherwise (such as 37888c2ecf20Sopenharmony_ci * through reading supported features during init. 37898c2ecf20Sopenharmony_ci */ 37908c2ecf20Sopenharmony_ci hci_dev_set_flag(hdev, HCI_BREDR_ENABLED); 37918c2ecf20Sopenharmony_ci } 37928c2ecf20Sopenharmony_ci 37938c2ecf20Sopenharmony_ci write_lock(&hci_dev_list_lock); 37948c2ecf20Sopenharmony_ci list_add(&hdev->list, &hci_dev_list); 37958c2ecf20Sopenharmony_ci write_unlock(&hci_dev_list_lock); 37968c2ecf20Sopenharmony_ci 37978c2ecf20Sopenharmony_ci /* Devices that are marked for raw-only usage are unconfigured 37988c2ecf20Sopenharmony_ci * and should not be included in normal operation. 37998c2ecf20Sopenharmony_ci */ 38008c2ecf20Sopenharmony_ci if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) 38018c2ecf20Sopenharmony_ci hci_dev_set_flag(hdev, HCI_UNCONFIGURED); 38028c2ecf20Sopenharmony_ci 38038c2ecf20Sopenharmony_ci hci_sock_dev_event(hdev, HCI_DEV_REG); 38048c2ecf20Sopenharmony_ci hci_dev_hold(hdev); 38058c2ecf20Sopenharmony_ci 38068c2ecf20Sopenharmony_ci if (!hdev->suspend_notifier.notifier_call && 38078c2ecf20Sopenharmony_ci !test_bit(HCI_QUIRK_NO_SUSPEND_NOTIFIER, &hdev->quirks)) { 38088c2ecf20Sopenharmony_ci hdev->suspend_notifier.notifier_call = hci_suspend_notifier; 38098c2ecf20Sopenharmony_ci error = register_pm_notifier(&hdev->suspend_notifier); 38108c2ecf20Sopenharmony_ci if (error) 38118c2ecf20Sopenharmony_ci goto err_wqueue; 38128c2ecf20Sopenharmony_ci } 38138c2ecf20Sopenharmony_ci 38148c2ecf20Sopenharmony_ci queue_work(hdev->req_workqueue, &hdev->power_on); 38158c2ecf20Sopenharmony_ci 38168c2ecf20Sopenharmony_ci idr_init(&hdev->adv_monitors_idr); 38178c2ecf20Sopenharmony_ci 38188c2ecf20Sopenharmony_ci return id; 38198c2ecf20Sopenharmony_ci 38208c2ecf20Sopenharmony_cierr_wqueue: 38218c2ecf20Sopenharmony_ci debugfs_remove_recursive(hdev->debugfs); 38228c2ecf20Sopenharmony_ci destroy_workqueue(hdev->workqueue); 38238c2ecf20Sopenharmony_ci destroy_workqueue(hdev->req_workqueue); 38248c2ecf20Sopenharmony_cierr: 38258c2ecf20Sopenharmony_ci ida_simple_remove(&hci_index_ida, hdev->id); 38268c2ecf20Sopenharmony_ci 38278c2ecf20Sopenharmony_ci return error; 38288c2ecf20Sopenharmony_ci} 38298c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hci_register_dev); 38308c2ecf20Sopenharmony_ci 38318c2ecf20Sopenharmony_ci/* Unregister HCI device */ 38328c2ecf20Sopenharmony_civoid hci_unregister_dev(struct hci_dev *hdev) 38338c2ecf20Sopenharmony_ci{ 38348c2ecf20Sopenharmony_ci BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); 38358c2ecf20Sopenharmony_ci 38368c2ecf20Sopenharmony_ci hci_dev_set_flag(hdev, HCI_UNREGISTER); 38378c2ecf20Sopenharmony_ci 38388c2ecf20Sopenharmony_ci write_lock(&hci_dev_list_lock); 38398c2ecf20Sopenharmony_ci list_del(&hdev->list); 38408c2ecf20Sopenharmony_ci write_unlock(&hci_dev_list_lock); 38418c2ecf20Sopenharmony_ci 38428c2ecf20Sopenharmony_ci cancel_work_sync(&hdev->rx_work); 38438c2ecf20Sopenharmony_ci cancel_work_sync(&hdev->cmd_work); 38448c2ecf20Sopenharmony_ci cancel_work_sync(&hdev->tx_work); 38458c2ecf20Sopenharmony_ci cancel_work_sync(&hdev->power_on); 38468c2ecf20Sopenharmony_ci cancel_work_sync(&hdev->error_reset); 38478c2ecf20Sopenharmony_ci 38488c2ecf20Sopenharmony_ci if (!test_bit(HCI_QUIRK_NO_SUSPEND_NOTIFIER, &hdev->quirks)) { 38498c2ecf20Sopenharmony_ci hci_suspend_clear_tasks(hdev); 38508c2ecf20Sopenharmony_ci unregister_pm_notifier(&hdev->suspend_notifier); 38518c2ecf20Sopenharmony_ci cancel_work_sync(&hdev->suspend_prepare); 38528c2ecf20Sopenharmony_ci } 38538c2ecf20Sopenharmony_ci 38548c2ecf20Sopenharmony_ci hci_dev_do_close(hdev); 38558c2ecf20Sopenharmony_ci 38568c2ecf20Sopenharmony_ci if (!test_bit(HCI_INIT, &hdev->flags) && 38578c2ecf20Sopenharmony_ci !hci_dev_test_flag(hdev, HCI_SETUP) && 38588c2ecf20Sopenharmony_ci !hci_dev_test_flag(hdev, HCI_CONFIG)) { 38598c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 38608c2ecf20Sopenharmony_ci mgmt_index_removed(hdev); 38618c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 38628c2ecf20Sopenharmony_ci } 38638c2ecf20Sopenharmony_ci 38648c2ecf20Sopenharmony_ci /* mgmt_index_removed should take care of emptying the 38658c2ecf20Sopenharmony_ci * pending list */ 38668c2ecf20Sopenharmony_ci BUG_ON(!list_empty(&hdev->mgmt_pending)); 38678c2ecf20Sopenharmony_ci 38688c2ecf20Sopenharmony_ci hci_sock_dev_event(hdev, HCI_DEV_UNREG); 38698c2ecf20Sopenharmony_ci 38708c2ecf20Sopenharmony_ci if (hdev->rfkill) { 38718c2ecf20Sopenharmony_ci rfkill_unregister(hdev->rfkill); 38728c2ecf20Sopenharmony_ci rfkill_destroy(hdev->rfkill); 38738c2ecf20Sopenharmony_ci } 38748c2ecf20Sopenharmony_ci 38758c2ecf20Sopenharmony_ci device_del(&hdev->dev); 38768c2ecf20Sopenharmony_ci /* Actual cleanup is deferred until hci_cleanup_dev(). */ 38778c2ecf20Sopenharmony_ci hci_dev_put(hdev); 38788c2ecf20Sopenharmony_ci} 38798c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hci_unregister_dev); 38808c2ecf20Sopenharmony_ci 38818c2ecf20Sopenharmony_ci/* Cleanup HCI device */ 38828c2ecf20Sopenharmony_civoid hci_cleanup_dev(struct hci_dev *hdev) 38838c2ecf20Sopenharmony_ci{ 38848c2ecf20Sopenharmony_ci debugfs_remove_recursive(hdev->debugfs); 38858c2ecf20Sopenharmony_ci kfree_const(hdev->hw_info); 38868c2ecf20Sopenharmony_ci kfree_const(hdev->fw_info); 38878c2ecf20Sopenharmony_ci 38888c2ecf20Sopenharmony_ci destroy_workqueue(hdev->workqueue); 38898c2ecf20Sopenharmony_ci destroy_workqueue(hdev->req_workqueue); 38908c2ecf20Sopenharmony_ci 38918c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 38928c2ecf20Sopenharmony_ci hci_bdaddr_list_clear(&hdev->reject_list); 38938c2ecf20Sopenharmony_ci hci_bdaddr_list_clear(&hdev->accept_list); 38948c2ecf20Sopenharmony_ci hci_uuids_clear(hdev); 38958c2ecf20Sopenharmony_ci hci_link_keys_clear(hdev); 38968c2ecf20Sopenharmony_ci hci_smp_ltks_clear(hdev); 38978c2ecf20Sopenharmony_ci hci_smp_irks_clear(hdev); 38988c2ecf20Sopenharmony_ci hci_remote_oob_data_clear(hdev); 38998c2ecf20Sopenharmony_ci hci_adv_instances_clear(hdev); 39008c2ecf20Sopenharmony_ci hci_adv_monitors_clear(hdev); 39018c2ecf20Sopenharmony_ci hci_bdaddr_list_clear(&hdev->le_accept_list); 39028c2ecf20Sopenharmony_ci hci_bdaddr_list_clear(&hdev->le_resolv_list); 39038c2ecf20Sopenharmony_ci hci_conn_params_clear_all(hdev); 39048c2ecf20Sopenharmony_ci hci_discovery_filter_clear(hdev); 39058c2ecf20Sopenharmony_ci hci_blocked_keys_clear(hdev); 39068c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 39078c2ecf20Sopenharmony_ci 39088c2ecf20Sopenharmony_ci ida_simple_remove(&hci_index_ida, hdev->id); 39098c2ecf20Sopenharmony_ci} 39108c2ecf20Sopenharmony_ci 39118c2ecf20Sopenharmony_ci/* Suspend HCI device */ 39128c2ecf20Sopenharmony_ciint hci_suspend_dev(struct hci_dev *hdev) 39138c2ecf20Sopenharmony_ci{ 39148c2ecf20Sopenharmony_ci hci_sock_dev_event(hdev, HCI_DEV_SUSPEND); 39158c2ecf20Sopenharmony_ci return 0; 39168c2ecf20Sopenharmony_ci} 39178c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hci_suspend_dev); 39188c2ecf20Sopenharmony_ci 39198c2ecf20Sopenharmony_ci/* Resume HCI device */ 39208c2ecf20Sopenharmony_ciint hci_resume_dev(struct hci_dev *hdev) 39218c2ecf20Sopenharmony_ci{ 39228c2ecf20Sopenharmony_ci hci_sock_dev_event(hdev, HCI_DEV_RESUME); 39238c2ecf20Sopenharmony_ci return 0; 39248c2ecf20Sopenharmony_ci} 39258c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hci_resume_dev); 39268c2ecf20Sopenharmony_ci 39278c2ecf20Sopenharmony_ci/* Reset HCI device */ 39288c2ecf20Sopenharmony_ciint hci_reset_dev(struct hci_dev *hdev) 39298c2ecf20Sopenharmony_ci{ 39308c2ecf20Sopenharmony_ci static const u8 hw_err[] = { HCI_EV_HARDWARE_ERROR, 0x01, 0x00 }; 39318c2ecf20Sopenharmony_ci struct sk_buff *skb; 39328c2ecf20Sopenharmony_ci 39338c2ecf20Sopenharmony_ci skb = bt_skb_alloc(3, GFP_ATOMIC); 39348c2ecf20Sopenharmony_ci if (!skb) 39358c2ecf20Sopenharmony_ci return -ENOMEM; 39368c2ecf20Sopenharmony_ci 39378c2ecf20Sopenharmony_ci hci_skb_pkt_type(skb) = HCI_EVENT_PKT; 39388c2ecf20Sopenharmony_ci skb_put_data(skb, hw_err, 3); 39398c2ecf20Sopenharmony_ci 39408c2ecf20Sopenharmony_ci /* Send Hardware Error to upper stack */ 39418c2ecf20Sopenharmony_ci return hci_recv_frame(hdev, skb); 39428c2ecf20Sopenharmony_ci} 39438c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hci_reset_dev); 39448c2ecf20Sopenharmony_ci 39458c2ecf20Sopenharmony_ci/* Receive frame from HCI drivers */ 39468c2ecf20Sopenharmony_ciint hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb) 39478c2ecf20Sopenharmony_ci{ 39488c2ecf20Sopenharmony_ci if (!hdev || (!test_bit(HCI_UP, &hdev->flags) 39498c2ecf20Sopenharmony_ci && !test_bit(HCI_INIT, &hdev->flags))) { 39508c2ecf20Sopenharmony_ci kfree_skb(skb); 39518c2ecf20Sopenharmony_ci return -ENXIO; 39528c2ecf20Sopenharmony_ci } 39538c2ecf20Sopenharmony_ci 39548c2ecf20Sopenharmony_ci if (hci_skb_pkt_type(skb) != HCI_EVENT_PKT && 39558c2ecf20Sopenharmony_ci hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT && 39568c2ecf20Sopenharmony_ci hci_skb_pkt_type(skb) != HCI_SCODATA_PKT && 39578c2ecf20Sopenharmony_ci hci_skb_pkt_type(skb) != HCI_ISODATA_PKT) { 39588c2ecf20Sopenharmony_ci kfree_skb(skb); 39598c2ecf20Sopenharmony_ci return -EINVAL; 39608c2ecf20Sopenharmony_ci } 39618c2ecf20Sopenharmony_ci 39628c2ecf20Sopenharmony_ci /* Incoming skb */ 39638c2ecf20Sopenharmony_ci bt_cb(skb)->incoming = 1; 39648c2ecf20Sopenharmony_ci 39658c2ecf20Sopenharmony_ci /* Time stamp */ 39668c2ecf20Sopenharmony_ci __net_timestamp(skb); 39678c2ecf20Sopenharmony_ci 39688c2ecf20Sopenharmony_ci skb_queue_tail(&hdev->rx_q, skb); 39698c2ecf20Sopenharmony_ci queue_work(hdev->workqueue, &hdev->rx_work); 39708c2ecf20Sopenharmony_ci 39718c2ecf20Sopenharmony_ci return 0; 39728c2ecf20Sopenharmony_ci} 39738c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hci_recv_frame); 39748c2ecf20Sopenharmony_ci 39758c2ecf20Sopenharmony_ci/* Receive diagnostic message from HCI drivers */ 39768c2ecf20Sopenharmony_ciint hci_recv_diag(struct hci_dev *hdev, struct sk_buff *skb) 39778c2ecf20Sopenharmony_ci{ 39788c2ecf20Sopenharmony_ci /* Mark as diagnostic packet */ 39798c2ecf20Sopenharmony_ci hci_skb_pkt_type(skb) = HCI_DIAG_PKT; 39808c2ecf20Sopenharmony_ci 39818c2ecf20Sopenharmony_ci /* Time stamp */ 39828c2ecf20Sopenharmony_ci __net_timestamp(skb); 39838c2ecf20Sopenharmony_ci 39848c2ecf20Sopenharmony_ci skb_queue_tail(&hdev->rx_q, skb); 39858c2ecf20Sopenharmony_ci queue_work(hdev->workqueue, &hdev->rx_work); 39868c2ecf20Sopenharmony_ci 39878c2ecf20Sopenharmony_ci return 0; 39888c2ecf20Sopenharmony_ci} 39898c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hci_recv_diag); 39908c2ecf20Sopenharmony_ci 39918c2ecf20Sopenharmony_civoid hci_set_hw_info(struct hci_dev *hdev, const char *fmt, ...) 39928c2ecf20Sopenharmony_ci{ 39938c2ecf20Sopenharmony_ci va_list vargs; 39948c2ecf20Sopenharmony_ci 39958c2ecf20Sopenharmony_ci va_start(vargs, fmt); 39968c2ecf20Sopenharmony_ci kfree_const(hdev->hw_info); 39978c2ecf20Sopenharmony_ci hdev->hw_info = kvasprintf_const(GFP_KERNEL, fmt, vargs); 39988c2ecf20Sopenharmony_ci va_end(vargs); 39998c2ecf20Sopenharmony_ci} 40008c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hci_set_hw_info); 40018c2ecf20Sopenharmony_ci 40028c2ecf20Sopenharmony_civoid hci_set_fw_info(struct hci_dev *hdev, const char *fmt, ...) 40038c2ecf20Sopenharmony_ci{ 40048c2ecf20Sopenharmony_ci va_list vargs; 40058c2ecf20Sopenharmony_ci 40068c2ecf20Sopenharmony_ci va_start(vargs, fmt); 40078c2ecf20Sopenharmony_ci kfree_const(hdev->fw_info); 40088c2ecf20Sopenharmony_ci hdev->fw_info = kvasprintf_const(GFP_KERNEL, fmt, vargs); 40098c2ecf20Sopenharmony_ci va_end(vargs); 40108c2ecf20Sopenharmony_ci} 40118c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hci_set_fw_info); 40128c2ecf20Sopenharmony_ci 40138c2ecf20Sopenharmony_ci/* ---- Interface to upper protocols ---- */ 40148c2ecf20Sopenharmony_ci 40158c2ecf20Sopenharmony_ciint hci_register_cb(struct hci_cb *cb) 40168c2ecf20Sopenharmony_ci{ 40178c2ecf20Sopenharmony_ci BT_DBG("%p name %s", cb, cb->name); 40188c2ecf20Sopenharmony_ci 40198c2ecf20Sopenharmony_ci mutex_lock(&hci_cb_list_lock); 40208c2ecf20Sopenharmony_ci list_add_tail(&cb->list, &hci_cb_list); 40218c2ecf20Sopenharmony_ci mutex_unlock(&hci_cb_list_lock); 40228c2ecf20Sopenharmony_ci 40238c2ecf20Sopenharmony_ci return 0; 40248c2ecf20Sopenharmony_ci} 40258c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hci_register_cb); 40268c2ecf20Sopenharmony_ci 40278c2ecf20Sopenharmony_ciint hci_unregister_cb(struct hci_cb *cb) 40288c2ecf20Sopenharmony_ci{ 40298c2ecf20Sopenharmony_ci BT_DBG("%p name %s", cb, cb->name); 40308c2ecf20Sopenharmony_ci 40318c2ecf20Sopenharmony_ci mutex_lock(&hci_cb_list_lock); 40328c2ecf20Sopenharmony_ci list_del(&cb->list); 40338c2ecf20Sopenharmony_ci mutex_unlock(&hci_cb_list_lock); 40348c2ecf20Sopenharmony_ci 40358c2ecf20Sopenharmony_ci return 0; 40368c2ecf20Sopenharmony_ci} 40378c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hci_unregister_cb); 40388c2ecf20Sopenharmony_ci 40398c2ecf20Sopenharmony_cistatic void hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) 40408c2ecf20Sopenharmony_ci{ 40418c2ecf20Sopenharmony_ci int err; 40428c2ecf20Sopenharmony_ci 40438c2ecf20Sopenharmony_ci BT_DBG("%s type %d len %d", hdev->name, hci_skb_pkt_type(skb), 40448c2ecf20Sopenharmony_ci skb->len); 40458c2ecf20Sopenharmony_ci 40468c2ecf20Sopenharmony_ci /* Time stamp */ 40478c2ecf20Sopenharmony_ci __net_timestamp(skb); 40488c2ecf20Sopenharmony_ci 40498c2ecf20Sopenharmony_ci /* Send copy to monitor */ 40508c2ecf20Sopenharmony_ci hci_send_to_monitor(hdev, skb); 40518c2ecf20Sopenharmony_ci 40528c2ecf20Sopenharmony_ci if (atomic_read(&hdev->promisc)) { 40538c2ecf20Sopenharmony_ci /* Send copy to the sockets */ 40548c2ecf20Sopenharmony_ci hci_send_to_sock(hdev, skb); 40558c2ecf20Sopenharmony_ci } 40568c2ecf20Sopenharmony_ci 40578c2ecf20Sopenharmony_ci /* Get rid of skb owner, prior to sending to the driver. */ 40588c2ecf20Sopenharmony_ci skb_orphan(skb); 40598c2ecf20Sopenharmony_ci 40608c2ecf20Sopenharmony_ci if (!test_bit(HCI_RUNNING, &hdev->flags)) { 40618c2ecf20Sopenharmony_ci kfree_skb(skb); 40628c2ecf20Sopenharmony_ci return; 40638c2ecf20Sopenharmony_ci } 40648c2ecf20Sopenharmony_ci 40658c2ecf20Sopenharmony_ci err = hdev->send(hdev, skb); 40668c2ecf20Sopenharmony_ci if (err < 0) { 40678c2ecf20Sopenharmony_ci bt_dev_err(hdev, "sending frame failed (%d)", err); 40688c2ecf20Sopenharmony_ci kfree_skb(skb); 40698c2ecf20Sopenharmony_ci } 40708c2ecf20Sopenharmony_ci} 40718c2ecf20Sopenharmony_ci 40728c2ecf20Sopenharmony_ci/* Send HCI command */ 40738c2ecf20Sopenharmony_ciint hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, 40748c2ecf20Sopenharmony_ci const void *param) 40758c2ecf20Sopenharmony_ci{ 40768c2ecf20Sopenharmony_ci struct sk_buff *skb; 40778c2ecf20Sopenharmony_ci 40788c2ecf20Sopenharmony_ci BT_DBG("%s opcode 0x%4.4x plen %d", hdev->name, opcode, plen); 40798c2ecf20Sopenharmony_ci 40808c2ecf20Sopenharmony_ci skb = hci_prepare_cmd(hdev, opcode, plen, param); 40818c2ecf20Sopenharmony_ci if (!skb) { 40828c2ecf20Sopenharmony_ci bt_dev_err(hdev, "no memory for command"); 40838c2ecf20Sopenharmony_ci return -ENOMEM; 40848c2ecf20Sopenharmony_ci } 40858c2ecf20Sopenharmony_ci 40868c2ecf20Sopenharmony_ci /* Stand-alone HCI commands must be flagged as 40878c2ecf20Sopenharmony_ci * single-command requests. 40888c2ecf20Sopenharmony_ci */ 40898c2ecf20Sopenharmony_ci bt_cb(skb)->hci.req_flags |= HCI_REQ_START; 40908c2ecf20Sopenharmony_ci 40918c2ecf20Sopenharmony_ci skb_queue_tail(&hdev->cmd_q, skb); 40928c2ecf20Sopenharmony_ci queue_work(hdev->workqueue, &hdev->cmd_work); 40938c2ecf20Sopenharmony_ci 40948c2ecf20Sopenharmony_ci return 0; 40958c2ecf20Sopenharmony_ci} 40968c2ecf20Sopenharmony_ci 40978c2ecf20Sopenharmony_ciint __hci_cmd_send(struct hci_dev *hdev, u16 opcode, u32 plen, 40988c2ecf20Sopenharmony_ci const void *param) 40998c2ecf20Sopenharmony_ci{ 41008c2ecf20Sopenharmony_ci struct sk_buff *skb; 41018c2ecf20Sopenharmony_ci 41028c2ecf20Sopenharmony_ci if (hci_opcode_ogf(opcode) != 0x3f) { 41038c2ecf20Sopenharmony_ci /* A controller receiving a command shall respond with either 41048c2ecf20Sopenharmony_ci * a Command Status Event or a Command Complete Event. 41058c2ecf20Sopenharmony_ci * Therefore, all standard HCI commands must be sent via the 41068c2ecf20Sopenharmony_ci * standard API, using hci_send_cmd or hci_cmd_sync helpers. 41078c2ecf20Sopenharmony_ci * Some vendors do not comply with this rule for vendor-specific 41088c2ecf20Sopenharmony_ci * commands and do not return any event. We want to support 41098c2ecf20Sopenharmony_ci * unresponded commands for such cases only. 41108c2ecf20Sopenharmony_ci */ 41118c2ecf20Sopenharmony_ci bt_dev_err(hdev, "unresponded command not supported"); 41128c2ecf20Sopenharmony_ci return -EINVAL; 41138c2ecf20Sopenharmony_ci } 41148c2ecf20Sopenharmony_ci 41158c2ecf20Sopenharmony_ci skb = hci_prepare_cmd(hdev, opcode, plen, param); 41168c2ecf20Sopenharmony_ci if (!skb) { 41178c2ecf20Sopenharmony_ci bt_dev_err(hdev, "no memory for command (opcode 0x%4.4x)", 41188c2ecf20Sopenharmony_ci opcode); 41198c2ecf20Sopenharmony_ci return -ENOMEM; 41208c2ecf20Sopenharmony_ci } 41218c2ecf20Sopenharmony_ci 41228c2ecf20Sopenharmony_ci hci_send_frame(hdev, skb); 41238c2ecf20Sopenharmony_ci 41248c2ecf20Sopenharmony_ci return 0; 41258c2ecf20Sopenharmony_ci} 41268c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__hci_cmd_send); 41278c2ecf20Sopenharmony_ci 41288c2ecf20Sopenharmony_ci/* Get data from the previously sent command */ 41298c2ecf20Sopenharmony_civoid *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode) 41308c2ecf20Sopenharmony_ci{ 41318c2ecf20Sopenharmony_ci struct hci_command_hdr *hdr; 41328c2ecf20Sopenharmony_ci 41338c2ecf20Sopenharmony_ci if (!hdev->sent_cmd) 41348c2ecf20Sopenharmony_ci return NULL; 41358c2ecf20Sopenharmony_ci 41368c2ecf20Sopenharmony_ci hdr = (void *) hdev->sent_cmd->data; 41378c2ecf20Sopenharmony_ci 41388c2ecf20Sopenharmony_ci if (hdr->opcode != cpu_to_le16(opcode)) 41398c2ecf20Sopenharmony_ci return NULL; 41408c2ecf20Sopenharmony_ci 41418c2ecf20Sopenharmony_ci BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); 41428c2ecf20Sopenharmony_ci 41438c2ecf20Sopenharmony_ci return hdev->sent_cmd->data + HCI_COMMAND_HDR_SIZE; 41448c2ecf20Sopenharmony_ci} 41458c2ecf20Sopenharmony_ci 41468c2ecf20Sopenharmony_ci/* Send HCI command and wait for command commplete event */ 41478c2ecf20Sopenharmony_cistruct sk_buff *hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen, 41488c2ecf20Sopenharmony_ci const void *param, u32 timeout) 41498c2ecf20Sopenharmony_ci{ 41508c2ecf20Sopenharmony_ci struct sk_buff *skb; 41518c2ecf20Sopenharmony_ci 41528c2ecf20Sopenharmony_ci if (!test_bit(HCI_UP, &hdev->flags)) 41538c2ecf20Sopenharmony_ci return ERR_PTR(-ENETDOWN); 41548c2ecf20Sopenharmony_ci 41558c2ecf20Sopenharmony_ci bt_dev_dbg(hdev, "opcode 0x%4.4x plen %d", opcode, plen); 41568c2ecf20Sopenharmony_ci 41578c2ecf20Sopenharmony_ci hci_req_sync_lock(hdev); 41588c2ecf20Sopenharmony_ci skb = __hci_cmd_sync(hdev, opcode, plen, param, timeout); 41598c2ecf20Sopenharmony_ci hci_req_sync_unlock(hdev); 41608c2ecf20Sopenharmony_ci 41618c2ecf20Sopenharmony_ci return skb; 41628c2ecf20Sopenharmony_ci} 41638c2ecf20Sopenharmony_ciEXPORT_SYMBOL(hci_cmd_sync); 41648c2ecf20Sopenharmony_ci 41658c2ecf20Sopenharmony_ci/* Send ACL data */ 41668c2ecf20Sopenharmony_cistatic void hci_add_acl_hdr(struct sk_buff *skb, __u16 handle, __u16 flags) 41678c2ecf20Sopenharmony_ci{ 41688c2ecf20Sopenharmony_ci struct hci_acl_hdr *hdr; 41698c2ecf20Sopenharmony_ci int len = skb->len; 41708c2ecf20Sopenharmony_ci 41718c2ecf20Sopenharmony_ci skb_push(skb, HCI_ACL_HDR_SIZE); 41728c2ecf20Sopenharmony_ci skb_reset_transport_header(skb); 41738c2ecf20Sopenharmony_ci hdr = (struct hci_acl_hdr *)skb_transport_header(skb); 41748c2ecf20Sopenharmony_ci hdr->handle = cpu_to_le16(hci_handle_pack(handle, flags)); 41758c2ecf20Sopenharmony_ci hdr->dlen = cpu_to_le16(len); 41768c2ecf20Sopenharmony_ci} 41778c2ecf20Sopenharmony_ci 41788c2ecf20Sopenharmony_cistatic void hci_queue_acl(struct hci_chan *chan, struct sk_buff_head *queue, 41798c2ecf20Sopenharmony_ci struct sk_buff *skb, __u16 flags) 41808c2ecf20Sopenharmony_ci{ 41818c2ecf20Sopenharmony_ci struct hci_conn *conn = chan->conn; 41828c2ecf20Sopenharmony_ci struct hci_dev *hdev = conn->hdev; 41838c2ecf20Sopenharmony_ci struct sk_buff *list; 41848c2ecf20Sopenharmony_ci 41858c2ecf20Sopenharmony_ci skb->len = skb_headlen(skb); 41868c2ecf20Sopenharmony_ci skb->data_len = 0; 41878c2ecf20Sopenharmony_ci 41888c2ecf20Sopenharmony_ci hci_skb_pkt_type(skb) = HCI_ACLDATA_PKT; 41898c2ecf20Sopenharmony_ci 41908c2ecf20Sopenharmony_ci switch (hdev->dev_type) { 41918c2ecf20Sopenharmony_ci case HCI_PRIMARY: 41928c2ecf20Sopenharmony_ci hci_add_acl_hdr(skb, conn->handle, flags); 41938c2ecf20Sopenharmony_ci break; 41948c2ecf20Sopenharmony_ci case HCI_AMP: 41958c2ecf20Sopenharmony_ci hci_add_acl_hdr(skb, chan->handle, flags); 41968c2ecf20Sopenharmony_ci break; 41978c2ecf20Sopenharmony_ci default: 41988c2ecf20Sopenharmony_ci bt_dev_err(hdev, "unknown dev_type %d", hdev->dev_type); 41998c2ecf20Sopenharmony_ci return; 42008c2ecf20Sopenharmony_ci } 42018c2ecf20Sopenharmony_ci 42028c2ecf20Sopenharmony_ci list = skb_shinfo(skb)->frag_list; 42038c2ecf20Sopenharmony_ci if (!list) { 42048c2ecf20Sopenharmony_ci /* Non fragmented */ 42058c2ecf20Sopenharmony_ci BT_DBG("%s nonfrag skb %p len %d", hdev->name, skb, skb->len); 42068c2ecf20Sopenharmony_ci 42078c2ecf20Sopenharmony_ci skb_queue_tail(queue, skb); 42088c2ecf20Sopenharmony_ci } else { 42098c2ecf20Sopenharmony_ci /* Fragmented */ 42108c2ecf20Sopenharmony_ci BT_DBG("%s frag %p len %d", hdev->name, skb, skb->len); 42118c2ecf20Sopenharmony_ci 42128c2ecf20Sopenharmony_ci skb_shinfo(skb)->frag_list = NULL; 42138c2ecf20Sopenharmony_ci 42148c2ecf20Sopenharmony_ci /* Queue all fragments atomically. We need to use spin_lock_bh 42158c2ecf20Sopenharmony_ci * here because of 6LoWPAN links, as there this function is 42168c2ecf20Sopenharmony_ci * called from softirq and using normal spin lock could cause 42178c2ecf20Sopenharmony_ci * deadlocks. 42188c2ecf20Sopenharmony_ci */ 42198c2ecf20Sopenharmony_ci spin_lock_bh(&queue->lock); 42208c2ecf20Sopenharmony_ci 42218c2ecf20Sopenharmony_ci __skb_queue_tail(queue, skb); 42228c2ecf20Sopenharmony_ci 42238c2ecf20Sopenharmony_ci flags &= ~ACL_START; 42248c2ecf20Sopenharmony_ci flags |= ACL_CONT; 42258c2ecf20Sopenharmony_ci do { 42268c2ecf20Sopenharmony_ci skb = list; list = list->next; 42278c2ecf20Sopenharmony_ci 42288c2ecf20Sopenharmony_ci hci_skb_pkt_type(skb) = HCI_ACLDATA_PKT; 42298c2ecf20Sopenharmony_ci hci_add_acl_hdr(skb, conn->handle, flags); 42308c2ecf20Sopenharmony_ci 42318c2ecf20Sopenharmony_ci BT_DBG("%s frag %p len %d", hdev->name, skb, skb->len); 42328c2ecf20Sopenharmony_ci 42338c2ecf20Sopenharmony_ci __skb_queue_tail(queue, skb); 42348c2ecf20Sopenharmony_ci } while (list); 42358c2ecf20Sopenharmony_ci 42368c2ecf20Sopenharmony_ci spin_unlock_bh(&queue->lock); 42378c2ecf20Sopenharmony_ci } 42388c2ecf20Sopenharmony_ci} 42398c2ecf20Sopenharmony_ci 42408c2ecf20Sopenharmony_civoid hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags) 42418c2ecf20Sopenharmony_ci{ 42428c2ecf20Sopenharmony_ci struct hci_dev *hdev = chan->conn->hdev; 42438c2ecf20Sopenharmony_ci 42448c2ecf20Sopenharmony_ci BT_DBG("%s chan %p flags 0x%4.4x", hdev->name, chan, flags); 42458c2ecf20Sopenharmony_ci 42468c2ecf20Sopenharmony_ci hci_queue_acl(chan, &chan->data_q, skb, flags); 42478c2ecf20Sopenharmony_ci 42488c2ecf20Sopenharmony_ci queue_work(hdev->workqueue, &hdev->tx_work); 42498c2ecf20Sopenharmony_ci} 42508c2ecf20Sopenharmony_ci 42518c2ecf20Sopenharmony_ci/* Send SCO data */ 42528c2ecf20Sopenharmony_civoid hci_send_sco(struct hci_conn *conn, struct sk_buff *skb) 42538c2ecf20Sopenharmony_ci{ 42548c2ecf20Sopenharmony_ci struct hci_dev *hdev = conn->hdev; 42558c2ecf20Sopenharmony_ci struct hci_sco_hdr hdr; 42568c2ecf20Sopenharmony_ci 42578c2ecf20Sopenharmony_ci BT_DBG("%s len %d", hdev->name, skb->len); 42588c2ecf20Sopenharmony_ci 42598c2ecf20Sopenharmony_ci hdr.handle = cpu_to_le16(conn->handle); 42608c2ecf20Sopenharmony_ci hdr.dlen = skb->len; 42618c2ecf20Sopenharmony_ci 42628c2ecf20Sopenharmony_ci skb_push(skb, HCI_SCO_HDR_SIZE); 42638c2ecf20Sopenharmony_ci skb_reset_transport_header(skb); 42648c2ecf20Sopenharmony_ci memcpy(skb_transport_header(skb), &hdr, HCI_SCO_HDR_SIZE); 42658c2ecf20Sopenharmony_ci 42668c2ecf20Sopenharmony_ci hci_skb_pkt_type(skb) = HCI_SCODATA_PKT; 42678c2ecf20Sopenharmony_ci 42688c2ecf20Sopenharmony_ci skb_queue_tail(&conn->data_q, skb); 42698c2ecf20Sopenharmony_ci queue_work(hdev->workqueue, &hdev->tx_work); 42708c2ecf20Sopenharmony_ci} 42718c2ecf20Sopenharmony_ci 42728c2ecf20Sopenharmony_ci/* ---- HCI TX task (outgoing data) ---- */ 42738c2ecf20Sopenharmony_ci 42748c2ecf20Sopenharmony_ci/* HCI Connection scheduler */ 42758c2ecf20Sopenharmony_cistatic struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, 42768c2ecf20Sopenharmony_ci int *quote) 42778c2ecf20Sopenharmony_ci{ 42788c2ecf20Sopenharmony_ci struct hci_conn_hash *h = &hdev->conn_hash; 42798c2ecf20Sopenharmony_ci struct hci_conn *conn = NULL, *c; 42808c2ecf20Sopenharmony_ci unsigned int num = 0, min = ~0; 42818c2ecf20Sopenharmony_ci 42828c2ecf20Sopenharmony_ci /* We don't have to lock device here. Connections are always 42838c2ecf20Sopenharmony_ci * added and removed with TX task disabled. */ 42848c2ecf20Sopenharmony_ci 42858c2ecf20Sopenharmony_ci rcu_read_lock(); 42868c2ecf20Sopenharmony_ci 42878c2ecf20Sopenharmony_ci list_for_each_entry_rcu(c, &h->list, list) { 42888c2ecf20Sopenharmony_ci if (c->type != type || skb_queue_empty(&c->data_q)) 42898c2ecf20Sopenharmony_ci continue; 42908c2ecf20Sopenharmony_ci 42918c2ecf20Sopenharmony_ci if (c->state != BT_CONNECTED && c->state != BT_CONFIG) 42928c2ecf20Sopenharmony_ci continue; 42938c2ecf20Sopenharmony_ci 42948c2ecf20Sopenharmony_ci num++; 42958c2ecf20Sopenharmony_ci 42968c2ecf20Sopenharmony_ci if (c->sent < min) { 42978c2ecf20Sopenharmony_ci min = c->sent; 42988c2ecf20Sopenharmony_ci conn = c; 42998c2ecf20Sopenharmony_ci } 43008c2ecf20Sopenharmony_ci 43018c2ecf20Sopenharmony_ci if (hci_conn_num(hdev, type) == num) 43028c2ecf20Sopenharmony_ci break; 43038c2ecf20Sopenharmony_ci } 43048c2ecf20Sopenharmony_ci 43058c2ecf20Sopenharmony_ci rcu_read_unlock(); 43068c2ecf20Sopenharmony_ci 43078c2ecf20Sopenharmony_ci if (conn) { 43088c2ecf20Sopenharmony_ci int cnt, q; 43098c2ecf20Sopenharmony_ci 43108c2ecf20Sopenharmony_ci switch (conn->type) { 43118c2ecf20Sopenharmony_ci case ACL_LINK: 43128c2ecf20Sopenharmony_ci cnt = hdev->acl_cnt; 43138c2ecf20Sopenharmony_ci break; 43148c2ecf20Sopenharmony_ci case SCO_LINK: 43158c2ecf20Sopenharmony_ci case ESCO_LINK: 43168c2ecf20Sopenharmony_ci cnt = hdev->sco_cnt; 43178c2ecf20Sopenharmony_ci break; 43188c2ecf20Sopenharmony_ci case LE_LINK: 43198c2ecf20Sopenharmony_ci cnt = hdev->le_mtu ? hdev->le_cnt : hdev->acl_cnt; 43208c2ecf20Sopenharmony_ci break; 43218c2ecf20Sopenharmony_ci default: 43228c2ecf20Sopenharmony_ci cnt = 0; 43238c2ecf20Sopenharmony_ci bt_dev_err(hdev, "unknown link type %d", conn->type); 43248c2ecf20Sopenharmony_ci } 43258c2ecf20Sopenharmony_ci 43268c2ecf20Sopenharmony_ci q = cnt / num; 43278c2ecf20Sopenharmony_ci *quote = q ? q : 1; 43288c2ecf20Sopenharmony_ci } else 43298c2ecf20Sopenharmony_ci *quote = 0; 43308c2ecf20Sopenharmony_ci 43318c2ecf20Sopenharmony_ci BT_DBG("conn %p quote %d", conn, *quote); 43328c2ecf20Sopenharmony_ci return conn; 43338c2ecf20Sopenharmony_ci} 43348c2ecf20Sopenharmony_ci 43358c2ecf20Sopenharmony_cistatic void hci_link_tx_to(struct hci_dev *hdev, __u8 type) 43368c2ecf20Sopenharmony_ci{ 43378c2ecf20Sopenharmony_ci struct hci_conn_hash *h = &hdev->conn_hash; 43388c2ecf20Sopenharmony_ci struct hci_conn *c; 43398c2ecf20Sopenharmony_ci 43408c2ecf20Sopenharmony_ci bt_dev_err(hdev, "link tx timeout"); 43418c2ecf20Sopenharmony_ci 43428c2ecf20Sopenharmony_ci rcu_read_lock(); 43438c2ecf20Sopenharmony_ci 43448c2ecf20Sopenharmony_ci /* Kill stalled connections */ 43458c2ecf20Sopenharmony_ci list_for_each_entry_rcu(c, &h->list, list) { 43468c2ecf20Sopenharmony_ci if (c->type == type && c->sent) { 43478c2ecf20Sopenharmony_ci bt_dev_err(hdev, "killing stalled connection %pMR", 43488c2ecf20Sopenharmony_ci &c->dst); 43498c2ecf20Sopenharmony_ci hci_disconnect(c, HCI_ERROR_REMOTE_USER_TERM); 43508c2ecf20Sopenharmony_ci } 43518c2ecf20Sopenharmony_ci } 43528c2ecf20Sopenharmony_ci 43538c2ecf20Sopenharmony_ci rcu_read_unlock(); 43548c2ecf20Sopenharmony_ci} 43558c2ecf20Sopenharmony_ci 43568c2ecf20Sopenharmony_cistatic struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type, 43578c2ecf20Sopenharmony_ci int *quote) 43588c2ecf20Sopenharmony_ci{ 43598c2ecf20Sopenharmony_ci struct hci_conn_hash *h = &hdev->conn_hash; 43608c2ecf20Sopenharmony_ci struct hci_chan *chan = NULL; 43618c2ecf20Sopenharmony_ci unsigned int num = 0, min = ~0, cur_prio = 0; 43628c2ecf20Sopenharmony_ci struct hci_conn *conn; 43638c2ecf20Sopenharmony_ci int cnt, q, conn_num = 0; 43648c2ecf20Sopenharmony_ci 43658c2ecf20Sopenharmony_ci BT_DBG("%s", hdev->name); 43668c2ecf20Sopenharmony_ci 43678c2ecf20Sopenharmony_ci rcu_read_lock(); 43688c2ecf20Sopenharmony_ci 43698c2ecf20Sopenharmony_ci list_for_each_entry_rcu(conn, &h->list, list) { 43708c2ecf20Sopenharmony_ci struct hci_chan *tmp; 43718c2ecf20Sopenharmony_ci 43728c2ecf20Sopenharmony_ci if (conn->type != type) 43738c2ecf20Sopenharmony_ci continue; 43748c2ecf20Sopenharmony_ci 43758c2ecf20Sopenharmony_ci if (conn->state != BT_CONNECTED && conn->state != BT_CONFIG) 43768c2ecf20Sopenharmony_ci continue; 43778c2ecf20Sopenharmony_ci 43788c2ecf20Sopenharmony_ci conn_num++; 43798c2ecf20Sopenharmony_ci 43808c2ecf20Sopenharmony_ci list_for_each_entry_rcu(tmp, &conn->chan_list, list) { 43818c2ecf20Sopenharmony_ci struct sk_buff *skb; 43828c2ecf20Sopenharmony_ci 43838c2ecf20Sopenharmony_ci if (skb_queue_empty(&tmp->data_q)) 43848c2ecf20Sopenharmony_ci continue; 43858c2ecf20Sopenharmony_ci 43868c2ecf20Sopenharmony_ci skb = skb_peek(&tmp->data_q); 43878c2ecf20Sopenharmony_ci if (skb->priority < cur_prio) 43888c2ecf20Sopenharmony_ci continue; 43898c2ecf20Sopenharmony_ci 43908c2ecf20Sopenharmony_ci if (skb->priority > cur_prio) { 43918c2ecf20Sopenharmony_ci num = 0; 43928c2ecf20Sopenharmony_ci min = ~0; 43938c2ecf20Sopenharmony_ci cur_prio = skb->priority; 43948c2ecf20Sopenharmony_ci } 43958c2ecf20Sopenharmony_ci 43968c2ecf20Sopenharmony_ci num++; 43978c2ecf20Sopenharmony_ci 43988c2ecf20Sopenharmony_ci if (conn->sent < min) { 43998c2ecf20Sopenharmony_ci min = conn->sent; 44008c2ecf20Sopenharmony_ci chan = tmp; 44018c2ecf20Sopenharmony_ci } 44028c2ecf20Sopenharmony_ci } 44038c2ecf20Sopenharmony_ci 44048c2ecf20Sopenharmony_ci if (hci_conn_num(hdev, type) == conn_num) 44058c2ecf20Sopenharmony_ci break; 44068c2ecf20Sopenharmony_ci } 44078c2ecf20Sopenharmony_ci 44088c2ecf20Sopenharmony_ci rcu_read_unlock(); 44098c2ecf20Sopenharmony_ci 44108c2ecf20Sopenharmony_ci if (!chan) 44118c2ecf20Sopenharmony_ci return NULL; 44128c2ecf20Sopenharmony_ci 44138c2ecf20Sopenharmony_ci switch (chan->conn->type) { 44148c2ecf20Sopenharmony_ci case ACL_LINK: 44158c2ecf20Sopenharmony_ci cnt = hdev->acl_cnt; 44168c2ecf20Sopenharmony_ci break; 44178c2ecf20Sopenharmony_ci case AMP_LINK: 44188c2ecf20Sopenharmony_ci cnt = hdev->block_cnt; 44198c2ecf20Sopenharmony_ci break; 44208c2ecf20Sopenharmony_ci case SCO_LINK: 44218c2ecf20Sopenharmony_ci case ESCO_LINK: 44228c2ecf20Sopenharmony_ci cnt = hdev->sco_cnt; 44238c2ecf20Sopenharmony_ci break; 44248c2ecf20Sopenharmony_ci case LE_LINK: 44258c2ecf20Sopenharmony_ci cnt = hdev->le_mtu ? hdev->le_cnt : hdev->acl_cnt; 44268c2ecf20Sopenharmony_ci break; 44278c2ecf20Sopenharmony_ci default: 44288c2ecf20Sopenharmony_ci cnt = 0; 44298c2ecf20Sopenharmony_ci bt_dev_err(hdev, "unknown link type %d", chan->conn->type); 44308c2ecf20Sopenharmony_ci } 44318c2ecf20Sopenharmony_ci 44328c2ecf20Sopenharmony_ci q = cnt / num; 44338c2ecf20Sopenharmony_ci *quote = q ? q : 1; 44348c2ecf20Sopenharmony_ci BT_DBG("chan %p quote %d", chan, *quote); 44358c2ecf20Sopenharmony_ci return chan; 44368c2ecf20Sopenharmony_ci} 44378c2ecf20Sopenharmony_ci 44388c2ecf20Sopenharmony_cistatic void hci_prio_recalculate(struct hci_dev *hdev, __u8 type) 44398c2ecf20Sopenharmony_ci{ 44408c2ecf20Sopenharmony_ci struct hci_conn_hash *h = &hdev->conn_hash; 44418c2ecf20Sopenharmony_ci struct hci_conn *conn; 44428c2ecf20Sopenharmony_ci int num = 0; 44438c2ecf20Sopenharmony_ci 44448c2ecf20Sopenharmony_ci BT_DBG("%s", hdev->name); 44458c2ecf20Sopenharmony_ci 44468c2ecf20Sopenharmony_ci rcu_read_lock(); 44478c2ecf20Sopenharmony_ci 44488c2ecf20Sopenharmony_ci list_for_each_entry_rcu(conn, &h->list, list) { 44498c2ecf20Sopenharmony_ci struct hci_chan *chan; 44508c2ecf20Sopenharmony_ci 44518c2ecf20Sopenharmony_ci if (conn->type != type) 44528c2ecf20Sopenharmony_ci continue; 44538c2ecf20Sopenharmony_ci 44548c2ecf20Sopenharmony_ci if (conn->state != BT_CONNECTED && conn->state != BT_CONFIG) 44558c2ecf20Sopenharmony_ci continue; 44568c2ecf20Sopenharmony_ci 44578c2ecf20Sopenharmony_ci num++; 44588c2ecf20Sopenharmony_ci 44598c2ecf20Sopenharmony_ci list_for_each_entry_rcu(chan, &conn->chan_list, list) { 44608c2ecf20Sopenharmony_ci struct sk_buff *skb; 44618c2ecf20Sopenharmony_ci 44628c2ecf20Sopenharmony_ci if (chan->sent) { 44638c2ecf20Sopenharmony_ci chan->sent = 0; 44648c2ecf20Sopenharmony_ci continue; 44658c2ecf20Sopenharmony_ci } 44668c2ecf20Sopenharmony_ci 44678c2ecf20Sopenharmony_ci if (skb_queue_empty(&chan->data_q)) 44688c2ecf20Sopenharmony_ci continue; 44698c2ecf20Sopenharmony_ci 44708c2ecf20Sopenharmony_ci skb = skb_peek(&chan->data_q); 44718c2ecf20Sopenharmony_ci if (skb->priority >= HCI_PRIO_MAX - 1) 44728c2ecf20Sopenharmony_ci continue; 44738c2ecf20Sopenharmony_ci 44748c2ecf20Sopenharmony_ci skb->priority = HCI_PRIO_MAX - 1; 44758c2ecf20Sopenharmony_ci 44768c2ecf20Sopenharmony_ci BT_DBG("chan %p skb %p promoted to %d", chan, skb, 44778c2ecf20Sopenharmony_ci skb->priority); 44788c2ecf20Sopenharmony_ci } 44798c2ecf20Sopenharmony_ci 44808c2ecf20Sopenharmony_ci if (hci_conn_num(hdev, type) == num) 44818c2ecf20Sopenharmony_ci break; 44828c2ecf20Sopenharmony_ci } 44838c2ecf20Sopenharmony_ci 44848c2ecf20Sopenharmony_ci rcu_read_unlock(); 44858c2ecf20Sopenharmony_ci 44868c2ecf20Sopenharmony_ci} 44878c2ecf20Sopenharmony_ci 44888c2ecf20Sopenharmony_cistatic inline int __get_blocks(struct hci_dev *hdev, struct sk_buff *skb) 44898c2ecf20Sopenharmony_ci{ 44908c2ecf20Sopenharmony_ci /* Calculate count of blocks used by this packet */ 44918c2ecf20Sopenharmony_ci return DIV_ROUND_UP(skb->len - HCI_ACL_HDR_SIZE, hdev->block_len); 44928c2ecf20Sopenharmony_ci} 44938c2ecf20Sopenharmony_ci 44948c2ecf20Sopenharmony_cistatic void __check_timeout(struct hci_dev *hdev, unsigned int cnt, u8 type) 44958c2ecf20Sopenharmony_ci{ 44968c2ecf20Sopenharmony_ci unsigned long last_tx; 44978c2ecf20Sopenharmony_ci 44988c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) 44998c2ecf20Sopenharmony_ci return; 45008c2ecf20Sopenharmony_ci 45018c2ecf20Sopenharmony_ci switch (type) { 45028c2ecf20Sopenharmony_ci case LE_LINK: 45038c2ecf20Sopenharmony_ci last_tx = hdev->le_last_tx; 45048c2ecf20Sopenharmony_ci break; 45058c2ecf20Sopenharmony_ci default: 45068c2ecf20Sopenharmony_ci last_tx = hdev->acl_last_tx; 45078c2ecf20Sopenharmony_ci break; 45088c2ecf20Sopenharmony_ci } 45098c2ecf20Sopenharmony_ci 45108c2ecf20Sopenharmony_ci /* tx timeout must be longer than maximum link supervision timeout 45118c2ecf20Sopenharmony_ci * (40.9 seconds) 45128c2ecf20Sopenharmony_ci */ 45138c2ecf20Sopenharmony_ci if (!cnt && time_after(jiffies, last_tx + HCI_ACL_TX_TIMEOUT)) 45148c2ecf20Sopenharmony_ci hci_link_tx_to(hdev, type); 45158c2ecf20Sopenharmony_ci} 45168c2ecf20Sopenharmony_ci 45178c2ecf20Sopenharmony_ci/* Schedule SCO */ 45188c2ecf20Sopenharmony_cistatic void hci_sched_sco(struct hci_dev *hdev) 45198c2ecf20Sopenharmony_ci{ 45208c2ecf20Sopenharmony_ci struct hci_conn *conn; 45218c2ecf20Sopenharmony_ci struct sk_buff *skb; 45228c2ecf20Sopenharmony_ci int quote; 45238c2ecf20Sopenharmony_ci 45248c2ecf20Sopenharmony_ci BT_DBG("%s", hdev->name); 45258c2ecf20Sopenharmony_ci 45268c2ecf20Sopenharmony_ci if (!hci_conn_num(hdev, SCO_LINK)) 45278c2ecf20Sopenharmony_ci return; 45288c2ecf20Sopenharmony_ci 45298c2ecf20Sopenharmony_ci while (hdev->sco_cnt && (conn = hci_low_sent(hdev, SCO_LINK, "e))) { 45308c2ecf20Sopenharmony_ci while (quote-- && (skb = skb_dequeue(&conn->data_q))) { 45318c2ecf20Sopenharmony_ci BT_DBG("skb %p len %d", skb, skb->len); 45328c2ecf20Sopenharmony_ci hci_send_frame(hdev, skb); 45338c2ecf20Sopenharmony_ci 45348c2ecf20Sopenharmony_ci conn->sent++; 45358c2ecf20Sopenharmony_ci if (conn->sent == ~0) 45368c2ecf20Sopenharmony_ci conn->sent = 0; 45378c2ecf20Sopenharmony_ci } 45388c2ecf20Sopenharmony_ci } 45398c2ecf20Sopenharmony_ci} 45408c2ecf20Sopenharmony_ci 45418c2ecf20Sopenharmony_cistatic void hci_sched_esco(struct hci_dev *hdev) 45428c2ecf20Sopenharmony_ci{ 45438c2ecf20Sopenharmony_ci struct hci_conn *conn; 45448c2ecf20Sopenharmony_ci struct sk_buff *skb; 45458c2ecf20Sopenharmony_ci int quote; 45468c2ecf20Sopenharmony_ci 45478c2ecf20Sopenharmony_ci BT_DBG("%s", hdev->name); 45488c2ecf20Sopenharmony_ci 45498c2ecf20Sopenharmony_ci if (!hci_conn_num(hdev, ESCO_LINK)) 45508c2ecf20Sopenharmony_ci return; 45518c2ecf20Sopenharmony_ci 45528c2ecf20Sopenharmony_ci while (hdev->sco_cnt && (conn = hci_low_sent(hdev, ESCO_LINK, 45538c2ecf20Sopenharmony_ci "e))) { 45548c2ecf20Sopenharmony_ci while (quote-- && (skb = skb_dequeue(&conn->data_q))) { 45558c2ecf20Sopenharmony_ci BT_DBG("skb %p len %d", skb, skb->len); 45568c2ecf20Sopenharmony_ci hci_send_frame(hdev, skb); 45578c2ecf20Sopenharmony_ci 45588c2ecf20Sopenharmony_ci conn->sent++; 45598c2ecf20Sopenharmony_ci if (conn->sent == ~0) 45608c2ecf20Sopenharmony_ci conn->sent = 0; 45618c2ecf20Sopenharmony_ci } 45628c2ecf20Sopenharmony_ci } 45638c2ecf20Sopenharmony_ci} 45648c2ecf20Sopenharmony_ci 45658c2ecf20Sopenharmony_cistatic void hci_sched_acl_pkt(struct hci_dev *hdev) 45668c2ecf20Sopenharmony_ci{ 45678c2ecf20Sopenharmony_ci unsigned int cnt = hdev->acl_cnt; 45688c2ecf20Sopenharmony_ci struct hci_chan *chan; 45698c2ecf20Sopenharmony_ci struct sk_buff *skb; 45708c2ecf20Sopenharmony_ci int quote; 45718c2ecf20Sopenharmony_ci 45728c2ecf20Sopenharmony_ci __check_timeout(hdev, cnt, ACL_LINK); 45738c2ecf20Sopenharmony_ci 45748c2ecf20Sopenharmony_ci while (hdev->acl_cnt && 45758c2ecf20Sopenharmony_ci (chan = hci_chan_sent(hdev, ACL_LINK, "e))) { 45768c2ecf20Sopenharmony_ci u32 priority = (skb_peek(&chan->data_q))->priority; 45778c2ecf20Sopenharmony_ci while (quote-- && (skb = skb_peek(&chan->data_q))) { 45788c2ecf20Sopenharmony_ci BT_DBG("chan %p skb %p len %d priority %u", chan, skb, 45798c2ecf20Sopenharmony_ci skb->len, skb->priority); 45808c2ecf20Sopenharmony_ci 45818c2ecf20Sopenharmony_ci /* Stop if priority has changed */ 45828c2ecf20Sopenharmony_ci if (skb->priority < priority) 45838c2ecf20Sopenharmony_ci break; 45848c2ecf20Sopenharmony_ci 45858c2ecf20Sopenharmony_ci skb = skb_dequeue(&chan->data_q); 45868c2ecf20Sopenharmony_ci 45878c2ecf20Sopenharmony_ci hci_conn_enter_active_mode(chan->conn, 45888c2ecf20Sopenharmony_ci bt_cb(skb)->force_active); 45898c2ecf20Sopenharmony_ci 45908c2ecf20Sopenharmony_ci hci_send_frame(hdev, skb); 45918c2ecf20Sopenharmony_ci hdev->acl_last_tx = jiffies; 45928c2ecf20Sopenharmony_ci 45938c2ecf20Sopenharmony_ci hdev->acl_cnt--; 45948c2ecf20Sopenharmony_ci chan->sent++; 45958c2ecf20Sopenharmony_ci chan->conn->sent++; 45968c2ecf20Sopenharmony_ci 45978c2ecf20Sopenharmony_ci /* Send pending SCO packets right away */ 45988c2ecf20Sopenharmony_ci hci_sched_sco(hdev); 45998c2ecf20Sopenharmony_ci hci_sched_esco(hdev); 46008c2ecf20Sopenharmony_ci } 46018c2ecf20Sopenharmony_ci } 46028c2ecf20Sopenharmony_ci 46038c2ecf20Sopenharmony_ci if (cnt != hdev->acl_cnt) 46048c2ecf20Sopenharmony_ci hci_prio_recalculate(hdev, ACL_LINK); 46058c2ecf20Sopenharmony_ci} 46068c2ecf20Sopenharmony_ci 46078c2ecf20Sopenharmony_cistatic void hci_sched_acl_blk(struct hci_dev *hdev) 46088c2ecf20Sopenharmony_ci{ 46098c2ecf20Sopenharmony_ci unsigned int cnt = hdev->block_cnt; 46108c2ecf20Sopenharmony_ci struct hci_chan *chan; 46118c2ecf20Sopenharmony_ci struct sk_buff *skb; 46128c2ecf20Sopenharmony_ci int quote; 46138c2ecf20Sopenharmony_ci u8 type; 46148c2ecf20Sopenharmony_ci 46158c2ecf20Sopenharmony_ci BT_DBG("%s", hdev->name); 46168c2ecf20Sopenharmony_ci 46178c2ecf20Sopenharmony_ci if (hdev->dev_type == HCI_AMP) 46188c2ecf20Sopenharmony_ci type = AMP_LINK; 46198c2ecf20Sopenharmony_ci else 46208c2ecf20Sopenharmony_ci type = ACL_LINK; 46218c2ecf20Sopenharmony_ci 46228c2ecf20Sopenharmony_ci __check_timeout(hdev, cnt, type); 46238c2ecf20Sopenharmony_ci 46248c2ecf20Sopenharmony_ci while (hdev->block_cnt > 0 && 46258c2ecf20Sopenharmony_ci (chan = hci_chan_sent(hdev, type, "e))) { 46268c2ecf20Sopenharmony_ci u32 priority = (skb_peek(&chan->data_q))->priority; 46278c2ecf20Sopenharmony_ci while (quote > 0 && (skb = skb_peek(&chan->data_q))) { 46288c2ecf20Sopenharmony_ci int blocks; 46298c2ecf20Sopenharmony_ci 46308c2ecf20Sopenharmony_ci BT_DBG("chan %p skb %p len %d priority %u", chan, skb, 46318c2ecf20Sopenharmony_ci skb->len, skb->priority); 46328c2ecf20Sopenharmony_ci 46338c2ecf20Sopenharmony_ci /* Stop if priority has changed */ 46348c2ecf20Sopenharmony_ci if (skb->priority < priority) 46358c2ecf20Sopenharmony_ci break; 46368c2ecf20Sopenharmony_ci 46378c2ecf20Sopenharmony_ci skb = skb_dequeue(&chan->data_q); 46388c2ecf20Sopenharmony_ci 46398c2ecf20Sopenharmony_ci blocks = __get_blocks(hdev, skb); 46408c2ecf20Sopenharmony_ci if (blocks > hdev->block_cnt) 46418c2ecf20Sopenharmony_ci return; 46428c2ecf20Sopenharmony_ci 46438c2ecf20Sopenharmony_ci hci_conn_enter_active_mode(chan->conn, 46448c2ecf20Sopenharmony_ci bt_cb(skb)->force_active); 46458c2ecf20Sopenharmony_ci 46468c2ecf20Sopenharmony_ci hci_send_frame(hdev, skb); 46478c2ecf20Sopenharmony_ci hdev->acl_last_tx = jiffies; 46488c2ecf20Sopenharmony_ci 46498c2ecf20Sopenharmony_ci hdev->block_cnt -= blocks; 46508c2ecf20Sopenharmony_ci quote -= blocks; 46518c2ecf20Sopenharmony_ci 46528c2ecf20Sopenharmony_ci chan->sent += blocks; 46538c2ecf20Sopenharmony_ci chan->conn->sent += blocks; 46548c2ecf20Sopenharmony_ci } 46558c2ecf20Sopenharmony_ci } 46568c2ecf20Sopenharmony_ci 46578c2ecf20Sopenharmony_ci if (cnt != hdev->block_cnt) 46588c2ecf20Sopenharmony_ci hci_prio_recalculate(hdev, type); 46598c2ecf20Sopenharmony_ci} 46608c2ecf20Sopenharmony_ci 46618c2ecf20Sopenharmony_cistatic void hci_sched_acl(struct hci_dev *hdev) 46628c2ecf20Sopenharmony_ci{ 46638c2ecf20Sopenharmony_ci BT_DBG("%s", hdev->name); 46648c2ecf20Sopenharmony_ci 46658c2ecf20Sopenharmony_ci /* No ACL link over BR/EDR controller */ 46668c2ecf20Sopenharmony_ci if (!hci_conn_num(hdev, ACL_LINK) && hdev->dev_type == HCI_PRIMARY) 46678c2ecf20Sopenharmony_ci return; 46688c2ecf20Sopenharmony_ci 46698c2ecf20Sopenharmony_ci /* No AMP link over AMP controller */ 46708c2ecf20Sopenharmony_ci if (!hci_conn_num(hdev, AMP_LINK) && hdev->dev_type == HCI_AMP) 46718c2ecf20Sopenharmony_ci return; 46728c2ecf20Sopenharmony_ci 46738c2ecf20Sopenharmony_ci switch (hdev->flow_ctl_mode) { 46748c2ecf20Sopenharmony_ci case HCI_FLOW_CTL_MODE_PACKET_BASED: 46758c2ecf20Sopenharmony_ci hci_sched_acl_pkt(hdev); 46768c2ecf20Sopenharmony_ci break; 46778c2ecf20Sopenharmony_ci 46788c2ecf20Sopenharmony_ci case HCI_FLOW_CTL_MODE_BLOCK_BASED: 46798c2ecf20Sopenharmony_ci hci_sched_acl_blk(hdev); 46808c2ecf20Sopenharmony_ci break; 46818c2ecf20Sopenharmony_ci } 46828c2ecf20Sopenharmony_ci} 46838c2ecf20Sopenharmony_ci 46848c2ecf20Sopenharmony_cistatic void hci_sched_le(struct hci_dev *hdev) 46858c2ecf20Sopenharmony_ci{ 46868c2ecf20Sopenharmony_ci struct hci_chan *chan; 46878c2ecf20Sopenharmony_ci struct sk_buff *skb; 46888c2ecf20Sopenharmony_ci int quote, cnt, tmp; 46898c2ecf20Sopenharmony_ci 46908c2ecf20Sopenharmony_ci BT_DBG("%s", hdev->name); 46918c2ecf20Sopenharmony_ci 46928c2ecf20Sopenharmony_ci if (!hci_conn_num(hdev, LE_LINK)) 46938c2ecf20Sopenharmony_ci return; 46948c2ecf20Sopenharmony_ci 46958c2ecf20Sopenharmony_ci cnt = hdev->le_pkts ? hdev->le_cnt : hdev->acl_cnt; 46968c2ecf20Sopenharmony_ci 46978c2ecf20Sopenharmony_ci __check_timeout(hdev, cnt, LE_LINK); 46988c2ecf20Sopenharmony_ci 46998c2ecf20Sopenharmony_ci tmp = cnt; 47008c2ecf20Sopenharmony_ci while (cnt && (chan = hci_chan_sent(hdev, LE_LINK, "e))) { 47018c2ecf20Sopenharmony_ci u32 priority = (skb_peek(&chan->data_q))->priority; 47028c2ecf20Sopenharmony_ci while (quote-- && (skb = skb_peek(&chan->data_q))) { 47038c2ecf20Sopenharmony_ci BT_DBG("chan %p skb %p len %d priority %u", chan, skb, 47048c2ecf20Sopenharmony_ci skb->len, skb->priority); 47058c2ecf20Sopenharmony_ci 47068c2ecf20Sopenharmony_ci /* Stop if priority has changed */ 47078c2ecf20Sopenharmony_ci if (skb->priority < priority) 47088c2ecf20Sopenharmony_ci break; 47098c2ecf20Sopenharmony_ci 47108c2ecf20Sopenharmony_ci skb = skb_dequeue(&chan->data_q); 47118c2ecf20Sopenharmony_ci 47128c2ecf20Sopenharmony_ci hci_send_frame(hdev, skb); 47138c2ecf20Sopenharmony_ci hdev->le_last_tx = jiffies; 47148c2ecf20Sopenharmony_ci 47158c2ecf20Sopenharmony_ci cnt--; 47168c2ecf20Sopenharmony_ci chan->sent++; 47178c2ecf20Sopenharmony_ci chan->conn->sent++; 47188c2ecf20Sopenharmony_ci 47198c2ecf20Sopenharmony_ci /* Send pending SCO packets right away */ 47208c2ecf20Sopenharmony_ci hci_sched_sco(hdev); 47218c2ecf20Sopenharmony_ci hci_sched_esco(hdev); 47228c2ecf20Sopenharmony_ci } 47238c2ecf20Sopenharmony_ci } 47248c2ecf20Sopenharmony_ci 47258c2ecf20Sopenharmony_ci if (hdev->le_pkts) 47268c2ecf20Sopenharmony_ci hdev->le_cnt = cnt; 47278c2ecf20Sopenharmony_ci else 47288c2ecf20Sopenharmony_ci hdev->acl_cnt = cnt; 47298c2ecf20Sopenharmony_ci 47308c2ecf20Sopenharmony_ci if (cnt != tmp) 47318c2ecf20Sopenharmony_ci hci_prio_recalculate(hdev, LE_LINK); 47328c2ecf20Sopenharmony_ci} 47338c2ecf20Sopenharmony_ci 47348c2ecf20Sopenharmony_cistatic void hci_tx_work(struct work_struct *work) 47358c2ecf20Sopenharmony_ci{ 47368c2ecf20Sopenharmony_ci struct hci_dev *hdev = container_of(work, struct hci_dev, tx_work); 47378c2ecf20Sopenharmony_ci struct sk_buff *skb; 47388c2ecf20Sopenharmony_ci 47398c2ecf20Sopenharmony_ci BT_DBG("%s acl %d sco %d le %d", hdev->name, hdev->acl_cnt, 47408c2ecf20Sopenharmony_ci hdev->sco_cnt, hdev->le_cnt); 47418c2ecf20Sopenharmony_ci 47428c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) { 47438c2ecf20Sopenharmony_ci /* Schedule queues and send stuff to HCI driver */ 47448c2ecf20Sopenharmony_ci hci_sched_sco(hdev); 47458c2ecf20Sopenharmony_ci hci_sched_esco(hdev); 47468c2ecf20Sopenharmony_ci hci_sched_acl(hdev); 47478c2ecf20Sopenharmony_ci hci_sched_le(hdev); 47488c2ecf20Sopenharmony_ci } 47498c2ecf20Sopenharmony_ci 47508c2ecf20Sopenharmony_ci /* Send next queued raw (unknown type) packet */ 47518c2ecf20Sopenharmony_ci while ((skb = skb_dequeue(&hdev->raw_q))) 47528c2ecf20Sopenharmony_ci hci_send_frame(hdev, skb); 47538c2ecf20Sopenharmony_ci} 47548c2ecf20Sopenharmony_ci 47558c2ecf20Sopenharmony_ci/* ----- HCI RX task (incoming data processing) ----- */ 47568c2ecf20Sopenharmony_ci 47578c2ecf20Sopenharmony_ci/* ACL data packet */ 47588c2ecf20Sopenharmony_cistatic void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb) 47598c2ecf20Sopenharmony_ci{ 47608c2ecf20Sopenharmony_ci struct hci_acl_hdr *hdr = (void *) skb->data; 47618c2ecf20Sopenharmony_ci struct hci_conn *conn; 47628c2ecf20Sopenharmony_ci __u16 handle, flags; 47638c2ecf20Sopenharmony_ci 47648c2ecf20Sopenharmony_ci skb_pull(skb, HCI_ACL_HDR_SIZE); 47658c2ecf20Sopenharmony_ci 47668c2ecf20Sopenharmony_ci handle = __le16_to_cpu(hdr->handle); 47678c2ecf20Sopenharmony_ci flags = hci_flags(handle); 47688c2ecf20Sopenharmony_ci handle = hci_handle(handle); 47698c2ecf20Sopenharmony_ci 47708c2ecf20Sopenharmony_ci BT_DBG("%s len %d handle 0x%4.4x flags 0x%4.4x", hdev->name, skb->len, 47718c2ecf20Sopenharmony_ci handle, flags); 47728c2ecf20Sopenharmony_ci 47738c2ecf20Sopenharmony_ci hdev->stat.acl_rx++; 47748c2ecf20Sopenharmony_ci 47758c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 47768c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, handle); 47778c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 47788c2ecf20Sopenharmony_ci 47798c2ecf20Sopenharmony_ci if (conn) { 47808c2ecf20Sopenharmony_ci hci_conn_enter_active_mode(conn, BT_POWER_FORCE_ACTIVE_OFF); 47818c2ecf20Sopenharmony_ci 47828c2ecf20Sopenharmony_ci /* Send to upper protocol */ 47838c2ecf20Sopenharmony_ci l2cap_recv_acldata(conn, skb, flags); 47848c2ecf20Sopenharmony_ci return; 47858c2ecf20Sopenharmony_ci } else { 47868c2ecf20Sopenharmony_ci bt_dev_err(hdev, "ACL packet for unknown connection handle %d", 47878c2ecf20Sopenharmony_ci handle); 47888c2ecf20Sopenharmony_ci } 47898c2ecf20Sopenharmony_ci 47908c2ecf20Sopenharmony_ci kfree_skb(skb); 47918c2ecf20Sopenharmony_ci} 47928c2ecf20Sopenharmony_ci 47938c2ecf20Sopenharmony_ci/* SCO data packet */ 47948c2ecf20Sopenharmony_cistatic void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb) 47958c2ecf20Sopenharmony_ci{ 47968c2ecf20Sopenharmony_ci struct hci_sco_hdr *hdr = (void *) skb->data; 47978c2ecf20Sopenharmony_ci struct hci_conn *conn; 47988c2ecf20Sopenharmony_ci __u16 handle, flags; 47998c2ecf20Sopenharmony_ci 48008c2ecf20Sopenharmony_ci skb_pull(skb, HCI_SCO_HDR_SIZE); 48018c2ecf20Sopenharmony_ci 48028c2ecf20Sopenharmony_ci handle = __le16_to_cpu(hdr->handle); 48038c2ecf20Sopenharmony_ci flags = hci_flags(handle); 48048c2ecf20Sopenharmony_ci handle = hci_handle(handle); 48058c2ecf20Sopenharmony_ci 48068c2ecf20Sopenharmony_ci BT_DBG("%s len %d handle 0x%4.4x flags 0x%4.4x", hdev->name, skb->len, 48078c2ecf20Sopenharmony_ci handle, flags); 48088c2ecf20Sopenharmony_ci 48098c2ecf20Sopenharmony_ci hdev->stat.sco_rx++; 48108c2ecf20Sopenharmony_ci 48118c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 48128c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, handle); 48138c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 48148c2ecf20Sopenharmony_ci 48158c2ecf20Sopenharmony_ci if (conn) { 48168c2ecf20Sopenharmony_ci /* Send to upper protocol */ 48178c2ecf20Sopenharmony_ci bt_cb(skb)->sco.pkt_status = flags & 0x03; 48188c2ecf20Sopenharmony_ci sco_recv_scodata(conn, skb); 48198c2ecf20Sopenharmony_ci return; 48208c2ecf20Sopenharmony_ci } else { 48218c2ecf20Sopenharmony_ci bt_dev_err(hdev, "SCO packet for unknown connection handle %d", 48228c2ecf20Sopenharmony_ci handle); 48238c2ecf20Sopenharmony_ci } 48248c2ecf20Sopenharmony_ci 48258c2ecf20Sopenharmony_ci kfree_skb(skb); 48268c2ecf20Sopenharmony_ci} 48278c2ecf20Sopenharmony_ci 48288c2ecf20Sopenharmony_cistatic bool hci_req_is_complete(struct hci_dev *hdev) 48298c2ecf20Sopenharmony_ci{ 48308c2ecf20Sopenharmony_ci struct sk_buff *skb; 48318c2ecf20Sopenharmony_ci 48328c2ecf20Sopenharmony_ci skb = skb_peek(&hdev->cmd_q); 48338c2ecf20Sopenharmony_ci if (!skb) 48348c2ecf20Sopenharmony_ci return true; 48358c2ecf20Sopenharmony_ci 48368c2ecf20Sopenharmony_ci return (bt_cb(skb)->hci.req_flags & HCI_REQ_START); 48378c2ecf20Sopenharmony_ci} 48388c2ecf20Sopenharmony_ci 48398c2ecf20Sopenharmony_cistatic void hci_resend_last(struct hci_dev *hdev) 48408c2ecf20Sopenharmony_ci{ 48418c2ecf20Sopenharmony_ci struct hci_command_hdr *sent; 48428c2ecf20Sopenharmony_ci struct sk_buff *skb; 48438c2ecf20Sopenharmony_ci u16 opcode; 48448c2ecf20Sopenharmony_ci 48458c2ecf20Sopenharmony_ci if (!hdev->sent_cmd) 48468c2ecf20Sopenharmony_ci return; 48478c2ecf20Sopenharmony_ci 48488c2ecf20Sopenharmony_ci sent = (void *) hdev->sent_cmd->data; 48498c2ecf20Sopenharmony_ci opcode = __le16_to_cpu(sent->opcode); 48508c2ecf20Sopenharmony_ci if (opcode == HCI_OP_RESET) 48518c2ecf20Sopenharmony_ci return; 48528c2ecf20Sopenharmony_ci 48538c2ecf20Sopenharmony_ci skb = skb_clone(hdev->sent_cmd, GFP_KERNEL); 48548c2ecf20Sopenharmony_ci if (!skb) 48558c2ecf20Sopenharmony_ci return; 48568c2ecf20Sopenharmony_ci 48578c2ecf20Sopenharmony_ci skb_queue_head(&hdev->cmd_q, skb); 48588c2ecf20Sopenharmony_ci queue_work(hdev->workqueue, &hdev->cmd_work); 48598c2ecf20Sopenharmony_ci} 48608c2ecf20Sopenharmony_ci 48618c2ecf20Sopenharmony_civoid hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status, 48628c2ecf20Sopenharmony_ci hci_req_complete_t *req_complete, 48638c2ecf20Sopenharmony_ci hci_req_complete_skb_t *req_complete_skb) 48648c2ecf20Sopenharmony_ci{ 48658c2ecf20Sopenharmony_ci struct sk_buff *skb; 48668c2ecf20Sopenharmony_ci unsigned long flags; 48678c2ecf20Sopenharmony_ci 48688c2ecf20Sopenharmony_ci BT_DBG("opcode 0x%04x status 0x%02x", opcode, status); 48698c2ecf20Sopenharmony_ci 48708c2ecf20Sopenharmony_ci /* If the completed command doesn't match the last one that was 48718c2ecf20Sopenharmony_ci * sent we need to do special handling of it. 48728c2ecf20Sopenharmony_ci */ 48738c2ecf20Sopenharmony_ci if (!hci_sent_cmd_data(hdev, opcode)) { 48748c2ecf20Sopenharmony_ci /* Some CSR based controllers generate a spontaneous 48758c2ecf20Sopenharmony_ci * reset complete event during init and any pending 48768c2ecf20Sopenharmony_ci * command will never be completed. In such a case we 48778c2ecf20Sopenharmony_ci * need to resend whatever was the last sent 48788c2ecf20Sopenharmony_ci * command. 48798c2ecf20Sopenharmony_ci */ 48808c2ecf20Sopenharmony_ci if (test_bit(HCI_INIT, &hdev->flags) && opcode == HCI_OP_RESET) 48818c2ecf20Sopenharmony_ci hci_resend_last(hdev); 48828c2ecf20Sopenharmony_ci 48838c2ecf20Sopenharmony_ci return; 48848c2ecf20Sopenharmony_ci } 48858c2ecf20Sopenharmony_ci 48868c2ecf20Sopenharmony_ci /* If we reach this point this event matches the last command sent */ 48878c2ecf20Sopenharmony_ci hci_dev_clear_flag(hdev, HCI_CMD_PENDING); 48888c2ecf20Sopenharmony_ci 48898c2ecf20Sopenharmony_ci /* If the command succeeded and there's still more commands in 48908c2ecf20Sopenharmony_ci * this request the request is not yet complete. 48918c2ecf20Sopenharmony_ci */ 48928c2ecf20Sopenharmony_ci if (!status && !hci_req_is_complete(hdev)) 48938c2ecf20Sopenharmony_ci return; 48948c2ecf20Sopenharmony_ci 48958c2ecf20Sopenharmony_ci /* If this was the last command in a request the complete 48968c2ecf20Sopenharmony_ci * callback would be found in hdev->sent_cmd instead of the 48978c2ecf20Sopenharmony_ci * command queue (hdev->cmd_q). 48988c2ecf20Sopenharmony_ci */ 48998c2ecf20Sopenharmony_ci if (bt_cb(hdev->sent_cmd)->hci.req_flags & HCI_REQ_SKB) { 49008c2ecf20Sopenharmony_ci *req_complete_skb = bt_cb(hdev->sent_cmd)->hci.req_complete_skb; 49018c2ecf20Sopenharmony_ci return; 49028c2ecf20Sopenharmony_ci } 49038c2ecf20Sopenharmony_ci 49048c2ecf20Sopenharmony_ci if (bt_cb(hdev->sent_cmd)->hci.req_complete) { 49058c2ecf20Sopenharmony_ci *req_complete = bt_cb(hdev->sent_cmd)->hci.req_complete; 49068c2ecf20Sopenharmony_ci return; 49078c2ecf20Sopenharmony_ci } 49088c2ecf20Sopenharmony_ci 49098c2ecf20Sopenharmony_ci /* Remove all pending commands belonging to this request */ 49108c2ecf20Sopenharmony_ci spin_lock_irqsave(&hdev->cmd_q.lock, flags); 49118c2ecf20Sopenharmony_ci while ((skb = __skb_dequeue(&hdev->cmd_q))) { 49128c2ecf20Sopenharmony_ci if (bt_cb(skb)->hci.req_flags & HCI_REQ_START) { 49138c2ecf20Sopenharmony_ci __skb_queue_head(&hdev->cmd_q, skb); 49148c2ecf20Sopenharmony_ci break; 49158c2ecf20Sopenharmony_ci } 49168c2ecf20Sopenharmony_ci 49178c2ecf20Sopenharmony_ci if (bt_cb(skb)->hci.req_flags & HCI_REQ_SKB) 49188c2ecf20Sopenharmony_ci *req_complete_skb = bt_cb(skb)->hci.req_complete_skb; 49198c2ecf20Sopenharmony_ci else 49208c2ecf20Sopenharmony_ci *req_complete = bt_cb(skb)->hci.req_complete; 49218c2ecf20Sopenharmony_ci dev_kfree_skb_irq(skb); 49228c2ecf20Sopenharmony_ci } 49238c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&hdev->cmd_q.lock, flags); 49248c2ecf20Sopenharmony_ci} 49258c2ecf20Sopenharmony_ci 49268c2ecf20Sopenharmony_cistatic void hci_rx_work(struct work_struct *work) 49278c2ecf20Sopenharmony_ci{ 49288c2ecf20Sopenharmony_ci struct hci_dev *hdev = container_of(work, struct hci_dev, rx_work); 49298c2ecf20Sopenharmony_ci struct sk_buff *skb; 49308c2ecf20Sopenharmony_ci 49318c2ecf20Sopenharmony_ci BT_DBG("%s", hdev->name); 49328c2ecf20Sopenharmony_ci 49338c2ecf20Sopenharmony_ci while ((skb = skb_dequeue(&hdev->rx_q))) { 49348c2ecf20Sopenharmony_ci /* Send copy to monitor */ 49358c2ecf20Sopenharmony_ci hci_send_to_monitor(hdev, skb); 49368c2ecf20Sopenharmony_ci 49378c2ecf20Sopenharmony_ci if (atomic_read(&hdev->promisc)) { 49388c2ecf20Sopenharmony_ci /* Send copy to the sockets */ 49398c2ecf20Sopenharmony_ci hci_send_to_sock(hdev, skb); 49408c2ecf20Sopenharmony_ci } 49418c2ecf20Sopenharmony_ci 49428c2ecf20Sopenharmony_ci /* If the device has been opened in HCI_USER_CHANNEL, 49438c2ecf20Sopenharmony_ci * the userspace has exclusive access to device. 49448c2ecf20Sopenharmony_ci * When device is HCI_INIT, we still need to process 49458c2ecf20Sopenharmony_ci * the data packets to the driver in order 49468c2ecf20Sopenharmony_ci * to complete its setup(). 49478c2ecf20Sopenharmony_ci */ 49488c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL) && 49498c2ecf20Sopenharmony_ci !test_bit(HCI_INIT, &hdev->flags)) { 49508c2ecf20Sopenharmony_ci kfree_skb(skb); 49518c2ecf20Sopenharmony_ci continue; 49528c2ecf20Sopenharmony_ci } 49538c2ecf20Sopenharmony_ci 49548c2ecf20Sopenharmony_ci if (test_bit(HCI_INIT, &hdev->flags)) { 49558c2ecf20Sopenharmony_ci /* Don't process data packets in this states. */ 49568c2ecf20Sopenharmony_ci switch (hci_skb_pkt_type(skb)) { 49578c2ecf20Sopenharmony_ci case HCI_ACLDATA_PKT: 49588c2ecf20Sopenharmony_ci case HCI_SCODATA_PKT: 49598c2ecf20Sopenharmony_ci case HCI_ISODATA_PKT: 49608c2ecf20Sopenharmony_ci kfree_skb(skb); 49618c2ecf20Sopenharmony_ci continue; 49628c2ecf20Sopenharmony_ci } 49638c2ecf20Sopenharmony_ci } 49648c2ecf20Sopenharmony_ci 49658c2ecf20Sopenharmony_ci /* Process frame */ 49668c2ecf20Sopenharmony_ci switch (hci_skb_pkt_type(skb)) { 49678c2ecf20Sopenharmony_ci case HCI_EVENT_PKT: 49688c2ecf20Sopenharmony_ci BT_DBG("%s Event packet", hdev->name); 49698c2ecf20Sopenharmony_ci hci_event_packet(hdev, skb); 49708c2ecf20Sopenharmony_ci break; 49718c2ecf20Sopenharmony_ci 49728c2ecf20Sopenharmony_ci case HCI_ACLDATA_PKT: 49738c2ecf20Sopenharmony_ci BT_DBG("%s ACL data packet", hdev->name); 49748c2ecf20Sopenharmony_ci hci_acldata_packet(hdev, skb); 49758c2ecf20Sopenharmony_ci break; 49768c2ecf20Sopenharmony_ci 49778c2ecf20Sopenharmony_ci case HCI_SCODATA_PKT: 49788c2ecf20Sopenharmony_ci BT_DBG("%s SCO data packet", hdev->name); 49798c2ecf20Sopenharmony_ci hci_scodata_packet(hdev, skb); 49808c2ecf20Sopenharmony_ci break; 49818c2ecf20Sopenharmony_ci 49828c2ecf20Sopenharmony_ci default: 49838c2ecf20Sopenharmony_ci kfree_skb(skb); 49848c2ecf20Sopenharmony_ci break; 49858c2ecf20Sopenharmony_ci } 49868c2ecf20Sopenharmony_ci } 49878c2ecf20Sopenharmony_ci} 49888c2ecf20Sopenharmony_ci 49898c2ecf20Sopenharmony_cistatic void hci_cmd_work(struct work_struct *work) 49908c2ecf20Sopenharmony_ci{ 49918c2ecf20Sopenharmony_ci struct hci_dev *hdev = container_of(work, struct hci_dev, cmd_work); 49928c2ecf20Sopenharmony_ci struct sk_buff *skb; 49938c2ecf20Sopenharmony_ci 49948c2ecf20Sopenharmony_ci BT_DBG("%s cmd_cnt %d cmd queued %d", hdev->name, 49958c2ecf20Sopenharmony_ci atomic_read(&hdev->cmd_cnt), skb_queue_len(&hdev->cmd_q)); 49968c2ecf20Sopenharmony_ci 49978c2ecf20Sopenharmony_ci /* Send queued commands */ 49988c2ecf20Sopenharmony_ci if (atomic_read(&hdev->cmd_cnt)) { 49998c2ecf20Sopenharmony_ci skb = skb_dequeue(&hdev->cmd_q); 50008c2ecf20Sopenharmony_ci if (!skb) 50018c2ecf20Sopenharmony_ci return; 50028c2ecf20Sopenharmony_ci 50038c2ecf20Sopenharmony_ci kfree_skb(hdev->sent_cmd); 50048c2ecf20Sopenharmony_ci 50058c2ecf20Sopenharmony_ci hdev->sent_cmd = skb_clone(skb, GFP_KERNEL); 50068c2ecf20Sopenharmony_ci if (hdev->sent_cmd) { 50078c2ecf20Sopenharmony_ci if (hci_req_status_pend(hdev)) 50088c2ecf20Sopenharmony_ci hci_dev_set_flag(hdev, HCI_CMD_PENDING); 50098c2ecf20Sopenharmony_ci atomic_dec(&hdev->cmd_cnt); 50108c2ecf20Sopenharmony_ci hci_send_frame(hdev, skb); 50118c2ecf20Sopenharmony_ci if (test_bit(HCI_RESET, &hdev->flags)) 50128c2ecf20Sopenharmony_ci cancel_delayed_work(&hdev->cmd_timer); 50138c2ecf20Sopenharmony_ci else 50148c2ecf20Sopenharmony_ci schedule_delayed_work(&hdev->cmd_timer, 50158c2ecf20Sopenharmony_ci HCI_CMD_TIMEOUT); 50168c2ecf20Sopenharmony_ci } else { 50178c2ecf20Sopenharmony_ci skb_queue_head(&hdev->cmd_q, skb); 50188c2ecf20Sopenharmony_ci queue_work(hdev->workqueue, &hdev->cmd_work); 50198c2ecf20Sopenharmony_ci } 50208c2ecf20Sopenharmony_ci } 50218c2ecf20Sopenharmony_ci} 5022