18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci BlueZ - Bluetooth protocol stack for Linux 38c2ecf20Sopenharmony_ci Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved. 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci This program is free software; you can redistribute it and/or modify 88c2ecf20Sopenharmony_ci it under the terms of the GNU General Public License version 2 as 98c2ecf20Sopenharmony_ci published by the Free Software Foundation; 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 128c2ecf20Sopenharmony_ci OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 138c2ecf20Sopenharmony_ci FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 148c2ecf20Sopenharmony_ci IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 158c2ecf20Sopenharmony_ci CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 168c2ecf20Sopenharmony_ci WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 178c2ecf20Sopenharmony_ci ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 188c2ecf20Sopenharmony_ci OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 218c2ecf20Sopenharmony_ci COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 228c2ecf20Sopenharmony_ci SOFTWARE IS DISCLAIMED. 238c2ecf20Sopenharmony_ci*/ 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci/* Bluetooth HCI event handling. */ 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#include <asm/unaligned.h> 288c2ecf20Sopenharmony_ci#include <linux/crypto.h> 298c2ecf20Sopenharmony_ci#include <crypto/algapi.h> 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#include <net/bluetooth/bluetooth.h> 328c2ecf20Sopenharmony_ci#include <net/bluetooth/hci_core.h> 338c2ecf20Sopenharmony_ci#include <net/bluetooth/mgmt.h> 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#include "hci_request.h" 368c2ecf20Sopenharmony_ci#include "hci_debugfs.h" 378c2ecf20Sopenharmony_ci#include "a2mp.h" 388c2ecf20Sopenharmony_ci#include "amp.h" 398c2ecf20Sopenharmony_ci#include "smp.h" 408c2ecf20Sopenharmony_ci#include "msft.h" 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci#define ZERO_KEY "\x00\x00\x00\x00\x00\x00\x00\x00" \ 438c2ecf20Sopenharmony_ci "\x00\x00\x00\x00\x00\x00\x00\x00" 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci/* Handle HCI Event packets */ 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_cistatic void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb, 488c2ecf20Sopenharmony_ci u8 *new_status) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci __u8 status = *((__u8 *) skb->data); 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci /* It is possible that we receive Inquiry Complete event right 558c2ecf20Sopenharmony_ci * before we receive Inquiry Cancel Command Complete event, in 568c2ecf20Sopenharmony_ci * which case the latter event should have status of Command 578c2ecf20Sopenharmony_ci * Disallowed (0x0c). This should not be treated as error, since 588c2ecf20Sopenharmony_ci * we actually achieve what Inquiry Cancel wants to achieve, 598c2ecf20Sopenharmony_ci * which is to end the last Inquiry session. 608c2ecf20Sopenharmony_ci */ 618c2ecf20Sopenharmony_ci if (status == 0x0c && !test_bit(HCI_INQUIRY, &hdev->flags)) { 628c2ecf20Sopenharmony_ci bt_dev_warn(hdev, "Ignoring error of Inquiry Cancel command"); 638c2ecf20Sopenharmony_ci status = 0x00; 648c2ecf20Sopenharmony_ci } 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci *new_status = status; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci if (status) 698c2ecf20Sopenharmony_ci return; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci clear_bit(HCI_INQUIRY, &hdev->flags); 728c2ecf20Sopenharmony_ci smp_mb__after_atomic(); /* wake_up_bit advises about this barrier */ 738c2ecf20Sopenharmony_ci wake_up_bit(&hdev->flags, HCI_INQUIRY); 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 768c2ecf20Sopenharmony_ci /* Set discovery state to stopped if we're not doing LE active 778c2ecf20Sopenharmony_ci * scanning. 788c2ecf20Sopenharmony_ci */ 798c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_LE_SCAN) || 808c2ecf20Sopenharmony_ci hdev->le_scan_type != LE_SCAN_ACTIVE) 818c2ecf20Sopenharmony_ci hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 828c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci hci_conn_check_pending(hdev); 858c2ecf20Sopenharmony_ci} 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_cistatic void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 888c2ecf20Sopenharmony_ci{ 898c2ecf20Sopenharmony_ci __u8 status = *((__u8 *) skb->data); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci if (status) 948c2ecf20Sopenharmony_ci return; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci hci_dev_set_flag(hdev, HCI_PERIODIC_INQ); 978c2ecf20Sopenharmony_ci} 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_cistatic void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 1008c2ecf20Sopenharmony_ci{ 1018c2ecf20Sopenharmony_ci __u8 status = *((__u8 *) skb->data); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci if (status) 1068c2ecf20Sopenharmony_ci return; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci hci_dev_clear_flag(hdev, HCI_PERIODIC_INQ); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci hci_conn_check_pending(hdev); 1118c2ecf20Sopenharmony_ci} 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_cistatic void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, 1148c2ecf20Sopenharmony_ci struct sk_buff *skb) 1158c2ecf20Sopenharmony_ci{ 1168c2ecf20Sopenharmony_ci BT_DBG("%s", hdev->name); 1178c2ecf20Sopenharmony_ci} 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_cistatic void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb) 1208c2ecf20Sopenharmony_ci{ 1218c2ecf20Sopenharmony_ci struct hci_rp_role_discovery *rp = (void *) skb->data; 1228c2ecf20Sopenharmony_ci struct hci_conn *conn; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci if (rp->status) 1278c2ecf20Sopenharmony_ci return; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 1328c2ecf20Sopenharmony_ci if (conn) 1338c2ecf20Sopenharmony_ci conn->role = rp->role; 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 1368c2ecf20Sopenharmony_ci} 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_cistatic void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 1398c2ecf20Sopenharmony_ci{ 1408c2ecf20Sopenharmony_ci struct hci_rp_read_link_policy *rp = (void *) skb->data; 1418c2ecf20Sopenharmony_ci struct hci_conn *conn; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci if (rp->status) 1468c2ecf20Sopenharmony_ci return; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 1518c2ecf20Sopenharmony_ci if (conn) 1528c2ecf20Sopenharmony_ci conn->link_policy = __le16_to_cpu(rp->policy); 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 1558c2ecf20Sopenharmony_ci} 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_cistatic void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci struct hci_rp_write_link_policy *rp = (void *) skb->data; 1608c2ecf20Sopenharmony_ci struct hci_conn *conn; 1618c2ecf20Sopenharmony_ci void *sent; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci if (rp->status) 1668c2ecf20Sopenharmony_ci return; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY); 1698c2ecf20Sopenharmony_ci if (!sent) 1708c2ecf20Sopenharmony_ci return; 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 1758c2ecf20Sopenharmony_ci if (conn) 1768c2ecf20Sopenharmony_ci conn->link_policy = get_unaligned_le16(sent + 2); 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 1798c2ecf20Sopenharmony_ci} 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_cistatic void hci_cc_read_def_link_policy(struct hci_dev *hdev, 1828c2ecf20Sopenharmony_ci struct sk_buff *skb) 1838c2ecf20Sopenharmony_ci{ 1848c2ecf20Sopenharmony_ci struct hci_rp_read_def_link_policy *rp = (void *) skb->data; 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci if (rp->status) 1898c2ecf20Sopenharmony_ci return; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci hdev->link_policy = __le16_to_cpu(rp->policy); 1928c2ecf20Sopenharmony_ci} 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_cistatic void hci_cc_write_def_link_policy(struct hci_dev *hdev, 1958c2ecf20Sopenharmony_ci struct sk_buff *skb) 1968c2ecf20Sopenharmony_ci{ 1978c2ecf20Sopenharmony_ci __u8 status = *((__u8 *) skb->data); 1988c2ecf20Sopenharmony_ci void *sent; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci if (status) 2038c2ecf20Sopenharmony_ci return; 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY); 2068c2ecf20Sopenharmony_ci if (!sent) 2078c2ecf20Sopenharmony_ci return; 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci hdev->link_policy = get_unaligned_le16(sent); 2108c2ecf20Sopenharmony_ci} 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_cistatic void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) 2138c2ecf20Sopenharmony_ci{ 2148c2ecf20Sopenharmony_ci __u8 status = *((__u8 *) skb->data); 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci clear_bit(HCI_RESET, &hdev->flags); 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci if (status) 2218c2ecf20Sopenharmony_ci return; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci /* Reset all non-persistent flags */ 2248c2ecf20Sopenharmony_ci hci_dev_clear_volatile_flags(hdev); 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci hdev->inq_tx_power = HCI_TX_POWER_INVALID; 2298c2ecf20Sopenharmony_ci hdev->adv_tx_power = HCI_TX_POWER_INVALID; 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci memset(hdev->adv_data, 0, sizeof(hdev->adv_data)); 2328c2ecf20Sopenharmony_ci hdev->adv_data_len = 0; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci memset(hdev->scan_rsp_data, 0, sizeof(hdev->scan_rsp_data)); 2358c2ecf20Sopenharmony_ci hdev->scan_rsp_data_len = 0; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci hdev->le_scan_type = LE_SCAN_PASSIVE; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci hdev->ssp_debug_mode = 0; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci hci_bdaddr_list_clear(&hdev->le_accept_list); 2428c2ecf20Sopenharmony_ci hci_bdaddr_list_clear(&hdev->le_resolv_list); 2438c2ecf20Sopenharmony_ci} 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_cistatic void hci_cc_read_stored_link_key(struct hci_dev *hdev, 2468c2ecf20Sopenharmony_ci struct sk_buff *skb) 2478c2ecf20Sopenharmony_ci{ 2488c2ecf20Sopenharmony_ci struct hci_rp_read_stored_link_key *rp = (void *)skb->data; 2498c2ecf20Sopenharmony_ci struct hci_cp_read_stored_link_key *sent; 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci sent = hci_sent_cmd_data(hdev, HCI_OP_READ_STORED_LINK_KEY); 2548c2ecf20Sopenharmony_ci if (!sent) 2558c2ecf20Sopenharmony_ci return; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci if (!rp->status && sent->read_all == 0x01) { 2588c2ecf20Sopenharmony_ci hdev->stored_max_keys = rp->max_keys; 2598c2ecf20Sopenharmony_ci hdev->stored_num_keys = rp->num_keys; 2608c2ecf20Sopenharmony_ci } 2618c2ecf20Sopenharmony_ci} 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_cistatic void hci_cc_delete_stored_link_key(struct hci_dev *hdev, 2648c2ecf20Sopenharmony_ci struct sk_buff *skb) 2658c2ecf20Sopenharmony_ci{ 2668c2ecf20Sopenharmony_ci struct hci_rp_delete_stored_link_key *rp = (void *)skb->data; 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci if (rp->status) 2718c2ecf20Sopenharmony_ci return; 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci if (rp->num_keys <= hdev->stored_num_keys) 2748c2ecf20Sopenharmony_ci hdev->stored_num_keys -= rp->num_keys; 2758c2ecf20Sopenharmony_ci else 2768c2ecf20Sopenharmony_ci hdev->stored_num_keys = 0; 2778c2ecf20Sopenharmony_ci} 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_cistatic void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) 2808c2ecf20Sopenharmony_ci{ 2818c2ecf20Sopenharmony_ci __u8 status = *((__u8 *) skb->data); 2828c2ecf20Sopenharmony_ci void *sent; 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); 2878c2ecf20Sopenharmony_ci if (!sent) 2888c2ecf20Sopenharmony_ci return; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_MGMT)) 2938c2ecf20Sopenharmony_ci mgmt_set_local_name_complete(hdev, sent, status); 2948c2ecf20Sopenharmony_ci else if (!status) 2958c2ecf20Sopenharmony_ci memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 2988c2ecf20Sopenharmony_ci} 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_cistatic void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) 3018c2ecf20Sopenharmony_ci{ 3028c2ecf20Sopenharmony_ci struct hci_rp_read_local_name *rp = (void *) skb->data; 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci if (rp->status) 3078c2ecf20Sopenharmony_ci return; 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_SETUP) || 3108c2ecf20Sopenharmony_ci hci_dev_test_flag(hdev, HCI_CONFIG)) 3118c2ecf20Sopenharmony_ci memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); 3128c2ecf20Sopenharmony_ci} 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_cistatic void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) 3158c2ecf20Sopenharmony_ci{ 3168c2ecf20Sopenharmony_ci __u8 status = *((__u8 *) skb->data); 3178c2ecf20Sopenharmony_ci void *sent; 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); 3228c2ecf20Sopenharmony_ci if (!sent) 3238c2ecf20Sopenharmony_ci return; 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci if (!status) { 3288c2ecf20Sopenharmony_ci __u8 param = *((__u8 *) sent); 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci if (param == AUTH_ENABLED) 3318c2ecf20Sopenharmony_ci set_bit(HCI_AUTH, &hdev->flags); 3328c2ecf20Sopenharmony_ci else 3338c2ecf20Sopenharmony_ci clear_bit(HCI_AUTH, &hdev->flags); 3348c2ecf20Sopenharmony_ci } 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_MGMT)) 3378c2ecf20Sopenharmony_ci mgmt_auth_enable_complete(hdev, status); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 3408c2ecf20Sopenharmony_ci} 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_cistatic void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) 3438c2ecf20Sopenharmony_ci{ 3448c2ecf20Sopenharmony_ci __u8 status = *((__u8 *) skb->data); 3458c2ecf20Sopenharmony_ci __u8 param; 3468c2ecf20Sopenharmony_ci void *sent; 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci if (status) 3518c2ecf20Sopenharmony_ci return; 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); 3548c2ecf20Sopenharmony_ci if (!sent) 3558c2ecf20Sopenharmony_ci return; 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci param = *((__u8 *) sent); 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci if (param) 3608c2ecf20Sopenharmony_ci set_bit(HCI_ENCRYPT, &hdev->flags); 3618c2ecf20Sopenharmony_ci else 3628c2ecf20Sopenharmony_ci clear_bit(HCI_ENCRYPT, &hdev->flags); 3638c2ecf20Sopenharmony_ci} 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_cistatic void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) 3668c2ecf20Sopenharmony_ci{ 3678c2ecf20Sopenharmony_ci __u8 status = *((__u8 *) skb->data); 3688c2ecf20Sopenharmony_ci __u8 param; 3698c2ecf20Sopenharmony_ci void *sent; 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); 3748c2ecf20Sopenharmony_ci if (!sent) 3758c2ecf20Sopenharmony_ci return; 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci param = *((__u8 *) sent); 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci if (status) { 3828c2ecf20Sopenharmony_ci hdev->discov_timeout = 0; 3838c2ecf20Sopenharmony_ci goto done; 3848c2ecf20Sopenharmony_ci } 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci if (param & SCAN_INQUIRY) 3878c2ecf20Sopenharmony_ci set_bit(HCI_ISCAN, &hdev->flags); 3888c2ecf20Sopenharmony_ci else 3898c2ecf20Sopenharmony_ci clear_bit(HCI_ISCAN, &hdev->flags); 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci if (param & SCAN_PAGE) 3928c2ecf20Sopenharmony_ci set_bit(HCI_PSCAN, &hdev->flags); 3938c2ecf20Sopenharmony_ci else 3948c2ecf20Sopenharmony_ci clear_bit(HCI_PSCAN, &hdev->flags); 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_cidone: 3978c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 3988c2ecf20Sopenharmony_ci} 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_cistatic void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 4018c2ecf20Sopenharmony_ci{ 4028c2ecf20Sopenharmony_ci struct hci_rp_read_class_of_dev *rp = (void *) skb->data; 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci if (rp->status) 4078c2ecf20Sopenharmony_ci return; 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci memcpy(hdev->dev_class, rp->dev_class, 3); 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, 4128c2ecf20Sopenharmony_ci hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); 4138c2ecf20Sopenharmony_ci} 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_cistatic void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 4168c2ecf20Sopenharmony_ci{ 4178c2ecf20Sopenharmony_ci __u8 status = *((__u8 *) skb->data); 4188c2ecf20Sopenharmony_ci void *sent; 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); 4238c2ecf20Sopenharmony_ci if (!sent) 4248c2ecf20Sopenharmony_ci return; 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci if (status == 0) 4298c2ecf20Sopenharmony_ci memcpy(hdev->dev_class, sent, 3); 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_MGMT)) 4328c2ecf20Sopenharmony_ci mgmt_set_class_of_dev_complete(hdev, sent, status); 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 4358c2ecf20Sopenharmony_ci} 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_cistatic void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 4388c2ecf20Sopenharmony_ci{ 4398c2ecf20Sopenharmony_ci struct hci_rp_read_voice_setting *rp = (void *) skb->data; 4408c2ecf20Sopenharmony_ci __u16 setting; 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci if (rp->status) 4458c2ecf20Sopenharmony_ci return; 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci setting = __le16_to_cpu(rp->voice_setting); 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ci if (hdev->voice_setting == setting) 4508c2ecf20Sopenharmony_ci return; 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci hdev->voice_setting = setting; 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting); 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci if (hdev->notify) 4578c2ecf20Sopenharmony_ci hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 4588c2ecf20Sopenharmony_ci} 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_cistatic void hci_cc_write_voice_setting(struct hci_dev *hdev, 4618c2ecf20Sopenharmony_ci struct sk_buff *skb) 4628c2ecf20Sopenharmony_ci{ 4638c2ecf20Sopenharmony_ci __u8 status = *((__u8 *) skb->data); 4648c2ecf20Sopenharmony_ci __u16 setting; 4658c2ecf20Sopenharmony_ci void *sent; 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci if (status) 4708c2ecf20Sopenharmony_ci return; 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); 4738c2ecf20Sopenharmony_ci if (!sent) 4748c2ecf20Sopenharmony_ci return; 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_ci setting = get_unaligned_le16(sent); 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci if (hdev->voice_setting == setting) 4798c2ecf20Sopenharmony_ci return; 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci hdev->voice_setting = setting; 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting); 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci if (hdev->notify) 4868c2ecf20Sopenharmony_ci hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 4878c2ecf20Sopenharmony_ci} 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_cistatic void hci_cc_read_num_supported_iac(struct hci_dev *hdev, 4908c2ecf20Sopenharmony_ci struct sk_buff *skb) 4918c2ecf20Sopenharmony_ci{ 4928c2ecf20Sopenharmony_ci struct hci_rp_read_num_supported_iac *rp = (void *) skb->data; 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci if (rp->status) 4978c2ecf20Sopenharmony_ci return; 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci hdev->num_iac = rp->num_iac; 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci BT_DBG("%s num iac %d", hdev->name, hdev->num_iac); 5028c2ecf20Sopenharmony_ci} 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_cistatic void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 5058c2ecf20Sopenharmony_ci{ 5068c2ecf20Sopenharmony_ci __u8 status = *((__u8 *) skb->data); 5078c2ecf20Sopenharmony_ci struct hci_cp_write_ssp_mode *sent; 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); 5128c2ecf20Sopenharmony_ci if (!sent) 5138c2ecf20Sopenharmony_ci return; 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci if (!status) { 5188c2ecf20Sopenharmony_ci if (sent->mode) 5198c2ecf20Sopenharmony_ci hdev->features[1][0] |= LMP_HOST_SSP; 5208c2ecf20Sopenharmony_ci else 5218c2ecf20Sopenharmony_ci hdev->features[1][0] &= ~LMP_HOST_SSP; 5228c2ecf20Sopenharmony_ci } 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_MGMT)) 5258c2ecf20Sopenharmony_ci mgmt_ssp_enable_complete(hdev, sent->mode, status); 5268c2ecf20Sopenharmony_ci else if (!status) { 5278c2ecf20Sopenharmony_ci if (sent->mode) 5288c2ecf20Sopenharmony_ci hci_dev_set_flag(hdev, HCI_SSP_ENABLED); 5298c2ecf20Sopenharmony_ci else 5308c2ecf20Sopenharmony_ci hci_dev_clear_flag(hdev, HCI_SSP_ENABLED); 5318c2ecf20Sopenharmony_ci } 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 5348c2ecf20Sopenharmony_ci} 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_cistatic void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb) 5378c2ecf20Sopenharmony_ci{ 5388c2ecf20Sopenharmony_ci u8 status = *((u8 *) skb->data); 5398c2ecf20Sopenharmony_ci struct hci_cp_write_sc_support *sent; 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SC_SUPPORT); 5448c2ecf20Sopenharmony_ci if (!sent) 5458c2ecf20Sopenharmony_ci return; 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci if (!status) { 5508c2ecf20Sopenharmony_ci if (sent->support) 5518c2ecf20Sopenharmony_ci hdev->features[1][0] |= LMP_HOST_SC; 5528c2ecf20Sopenharmony_ci else 5538c2ecf20Sopenharmony_ci hdev->features[1][0] &= ~LMP_HOST_SC; 5548c2ecf20Sopenharmony_ci } 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_MGMT) && !status) { 5578c2ecf20Sopenharmony_ci if (sent->support) 5588c2ecf20Sopenharmony_ci hci_dev_set_flag(hdev, HCI_SC_ENABLED); 5598c2ecf20Sopenharmony_ci else 5608c2ecf20Sopenharmony_ci hci_dev_clear_flag(hdev, HCI_SC_ENABLED); 5618c2ecf20Sopenharmony_ci } 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 5648c2ecf20Sopenharmony_ci} 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_cistatic void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) 5678c2ecf20Sopenharmony_ci{ 5688c2ecf20Sopenharmony_ci struct hci_rp_read_local_version *rp = (void *) skb->data; 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci if (rp->status) 5738c2ecf20Sopenharmony_ci return; 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_SETUP) || 5768c2ecf20Sopenharmony_ci hci_dev_test_flag(hdev, HCI_CONFIG)) { 5778c2ecf20Sopenharmony_ci hdev->hci_ver = rp->hci_ver; 5788c2ecf20Sopenharmony_ci hdev->hci_rev = __le16_to_cpu(rp->hci_rev); 5798c2ecf20Sopenharmony_ci hdev->lmp_ver = rp->lmp_ver; 5808c2ecf20Sopenharmony_ci hdev->manufacturer = __le16_to_cpu(rp->manufacturer); 5818c2ecf20Sopenharmony_ci hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); 5828c2ecf20Sopenharmony_ci } 5838c2ecf20Sopenharmony_ci} 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_cistatic void hci_cc_read_local_commands(struct hci_dev *hdev, 5868c2ecf20Sopenharmony_ci struct sk_buff *skb) 5878c2ecf20Sopenharmony_ci{ 5888c2ecf20Sopenharmony_ci struct hci_rp_read_local_commands *rp = (void *) skb->data; 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci if (rp->status) 5938c2ecf20Sopenharmony_ci return; 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_SETUP) || 5968c2ecf20Sopenharmony_ci hci_dev_test_flag(hdev, HCI_CONFIG)) 5978c2ecf20Sopenharmony_ci memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); 5988c2ecf20Sopenharmony_ci} 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_cistatic void hci_cc_read_auth_payload_timeout(struct hci_dev *hdev, 6018c2ecf20Sopenharmony_ci struct sk_buff *skb) 6028c2ecf20Sopenharmony_ci{ 6038c2ecf20Sopenharmony_ci struct hci_rp_read_auth_payload_to *rp = (void *)skb->data; 6048c2ecf20Sopenharmony_ci struct hci_conn *conn; 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci if (rp->status) 6098c2ecf20Sopenharmony_ci return; 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 6148c2ecf20Sopenharmony_ci if (conn) 6158c2ecf20Sopenharmony_ci conn->auth_payload_timeout = __le16_to_cpu(rp->timeout); 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 6188c2ecf20Sopenharmony_ci} 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_cistatic void hci_cc_write_auth_payload_timeout(struct hci_dev *hdev, 6218c2ecf20Sopenharmony_ci struct sk_buff *skb) 6228c2ecf20Sopenharmony_ci{ 6238c2ecf20Sopenharmony_ci struct hci_rp_write_auth_payload_to *rp = (void *)skb->data; 6248c2ecf20Sopenharmony_ci struct hci_conn *conn; 6258c2ecf20Sopenharmony_ci void *sent; 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci if (rp->status) 6308c2ecf20Sopenharmony_ci return; 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_ci sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_PAYLOAD_TO); 6338c2ecf20Sopenharmony_ci if (!sent) 6348c2ecf20Sopenharmony_ci return; 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 6398c2ecf20Sopenharmony_ci if (conn) 6408c2ecf20Sopenharmony_ci conn->auth_payload_timeout = get_unaligned_le16(sent + 2); 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 6438c2ecf20Sopenharmony_ci} 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_cistatic void hci_cc_read_local_features(struct hci_dev *hdev, 6468c2ecf20Sopenharmony_ci struct sk_buff *skb) 6478c2ecf20Sopenharmony_ci{ 6488c2ecf20Sopenharmony_ci struct hci_rp_read_local_features *rp = (void *) skb->data; 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci if (rp->status) 6538c2ecf20Sopenharmony_ci return; 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci memcpy(hdev->features, rp->features, 8); 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci /* Adjust default settings according to features 6588c2ecf20Sopenharmony_ci * supported by device. */ 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_ci if (hdev->features[0][0] & LMP_3SLOT) 6618c2ecf20Sopenharmony_ci hdev->pkt_type |= (HCI_DM3 | HCI_DH3); 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci if (hdev->features[0][0] & LMP_5SLOT) 6648c2ecf20Sopenharmony_ci hdev->pkt_type |= (HCI_DM5 | HCI_DH5); 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci if (hdev->features[0][1] & LMP_HV2) { 6678c2ecf20Sopenharmony_ci hdev->pkt_type |= (HCI_HV2); 6688c2ecf20Sopenharmony_ci hdev->esco_type |= (ESCO_HV2); 6698c2ecf20Sopenharmony_ci } 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_ci if (hdev->features[0][1] & LMP_HV3) { 6728c2ecf20Sopenharmony_ci hdev->pkt_type |= (HCI_HV3); 6738c2ecf20Sopenharmony_ci hdev->esco_type |= (ESCO_HV3); 6748c2ecf20Sopenharmony_ci } 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci if (lmp_esco_capable(hdev)) 6778c2ecf20Sopenharmony_ci hdev->esco_type |= (ESCO_EV3); 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci if (hdev->features[0][4] & LMP_EV4) 6808c2ecf20Sopenharmony_ci hdev->esco_type |= (ESCO_EV4); 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_ci if (hdev->features[0][4] & LMP_EV5) 6838c2ecf20Sopenharmony_ci hdev->esco_type |= (ESCO_EV5); 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci if (hdev->features[0][5] & LMP_EDR_ESCO_2M) 6868c2ecf20Sopenharmony_ci hdev->esco_type |= (ESCO_2EV3); 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci if (hdev->features[0][5] & LMP_EDR_ESCO_3M) 6898c2ecf20Sopenharmony_ci hdev->esco_type |= (ESCO_3EV3); 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci if (hdev->features[0][5] & LMP_EDR_3S_ESCO) 6928c2ecf20Sopenharmony_ci hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); 6938c2ecf20Sopenharmony_ci} 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_cistatic void hci_cc_read_local_ext_features(struct hci_dev *hdev, 6968c2ecf20Sopenharmony_ci struct sk_buff *skb) 6978c2ecf20Sopenharmony_ci{ 6988c2ecf20Sopenharmony_ci struct hci_rp_read_local_ext_features *rp = (void *) skb->data; 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci if (rp->status) 7038c2ecf20Sopenharmony_ci return; 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci if (hdev->max_page < rp->max_page) 7068c2ecf20Sopenharmony_ci hdev->max_page = rp->max_page; 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_ci if (rp->page < HCI_MAX_PAGES) 7098c2ecf20Sopenharmony_ci memcpy(hdev->features[rp->page], rp->features, 8); 7108c2ecf20Sopenharmony_ci} 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_cistatic void hci_cc_read_flow_control_mode(struct hci_dev *hdev, 7138c2ecf20Sopenharmony_ci struct sk_buff *skb) 7148c2ecf20Sopenharmony_ci{ 7158c2ecf20Sopenharmony_ci struct hci_rp_read_flow_control_mode *rp = (void *) skb->data; 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci if (rp->status) 7208c2ecf20Sopenharmony_ci return; 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci hdev->flow_ctl_mode = rp->mode; 7238c2ecf20Sopenharmony_ci} 7248c2ecf20Sopenharmony_ci 7258c2ecf20Sopenharmony_cistatic void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 7268c2ecf20Sopenharmony_ci{ 7278c2ecf20Sopenharmony_ci struct hci_rp_read_buffer_size *rp = (void *) skb->data; 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_ci if (rp->status) 7328c2ecf20Sopenharmony_ci return; 7338c2ecf20Sopenharmony_ci 7348c2ecf20Sopenharmony_ci hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); 7358c2ecf20Sopenharmony_ci hdev->sco_mtu = rp->sco_mtu; 7368c2ecf20Sopenharmony_ci hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); 7378c2ecf20Sopenharmony_ci hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { 7408c2ecf20Sopenharmony_ci hdev->sco_mtu = 64; 7418c2ecf20Sopenharmony_ci hdev->sco_pkts = 8; 7428c2ecf20Sopenharmony_ci } 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_ci hdev->acl_cnt = hdev->acl_pkts; 7458c2ecf20Sopenharmony_ci hdev->sco_cnt = hdev->sco_pkts; 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu, 7488c2ecf20Sopenharmony_ci hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts); 7498c2ecf20Sopenharmony_ci} 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_cistatic void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) 7528c2ecf20Sopenharmony_ci{ 7538c2ecf20Sopenharmony_ci struct hci_rp_read_bd_addr *rp = (void *) skb->data; 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 7568c2ecf20Sopenharmony_ci 7578c2ecf20Sopenharmony_ci if (rp->status) 7588c2ecf20Sopenharmony_ci return; 7598c2ecf20Sopenharmony_ci 7608c2ecf20Sopenharmony_ci if (test_bit(HCI_INIT, &hdev->flags)) 7618c2ecf20Sopenharmony_ci bacpy(&hdev->bdaddr, &rp->bdaddr); 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_SETUP)) 7648c2ecf20Sopenharmony_ci bacpy(&hdev->setup_addr, &rp->bdaddr); 7658c2ecf20Sopenharmony_ci} 7668c2ecf20Sopenharmony_ci 7678c2ecf20Sopenharmony_cistatic void hci_cc_read_local_pairing_opts(struct hci_dev *hdev, 7688c2ecf20Sopenharmony_ci struct sk_buff *skb) 7698c2ecf20Sopenharmony_ci{ 7708c2ecf20Sopenharmony_ci struct hci_rp_read_local_pairing_opts *rp = (void *) skb->data; 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_ci if (rp->status) 7758c2ecf20Sopenharmony_ci return; 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_SETUP) || 7788c2ecf20Sopenharmony_ci hci_dev_test_flag(hdev, HCI_CONFIG)) { 7798c2ecf20Sopenharmony_ci hdev->pairing_opts = rp->pairing_opts; 7808c2ecf20Sopenharmony_ci hdev->max_enc_key_size = rp->max_key_size; 7818c2ecf20Sopenharmony_ci } 7828c2ecf20Sopenharmony_ci} 7838c2ecf20Sopenharmony_ci 7848c2ecf20Sopenharmony_cistatic void hci_cc_read_page_scan_activity(struct hci_dev *hdev, 7858c2ecf20Sopenharmony_ci struct sk_buff *skb) 7868c2ecf20Sopenharmony_ci{ 7878c2ecf20Sopenharmony_ci struct hci_rp_read_page_scan_activity *rp = (void *) skb->data; 7888c2ecf20Sopenharmony_ci 7898c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ci if (rp->status) 7928c2ecf20Sopenharmony_ci return; 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_ci if (test_bit(HCI_INIT, &hdev->flags)) { 7958c2ecf20Sopenharmony_ci hdev->page_scan_interval = __le16_to_cpu(rp->interval); 7968c2ecf20Sopenharmony_ci hdev->page_scan_window = __le16_to_cpu(rp->window); 7978c2ecf20Sopenharmony_ci } 7988c2ecf20Sopenharmony_ci} 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_cistatic void hci_cc_write_page_scan_activity(struct hci_dev *hdev, 8018c2ecf20Sopenharmony_ci struct sk_buff *skb) 8028c2ecf20Sopenharmony_ci{ 8038c2ecf20Sopenharmony_ci u8 status = *((u8 *) skb->data); 8048c2ecf20Sopenharmony_ci struct hci_cp_write_page_scan_activity *sent; 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 8078c2ecf20Sopenharmony_ci 8088c2ecf20Sopenharmony_ci if (status) 8098c2ecf20Sopenharmony_ci return; 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_ci sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY); 8128c2ecf20Sopenharmony_ci if (!sent) 8138c2ecf20Sopenharmony_ci return; 8148c2ecf20Sopenharmony_ci 8158c2ecf20Sopenharmony_ci hdev->page_scan_interval = __le16_to_cpu(sent->interval); 8168c2ecf20Sopenharmony_ci hdev->page_scan_window = __le16_to_cpu(sent->window); 8178c2ecf20Sopenharmony_ci} 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_cistatic void hci_cc_read_page_scan_type(struct hci_dev *hdev, 8208c2ecf20Sopenharmony_ci struct sk_buff *skb) 8218c2ecf20Sopenharmony_ci{ 8228c2ecf20Sopenharmony_ci struct hci_rp_read_page_scan_type *rp = (void *) skb->data; 8238c2ecf20Sopenharmony_ci 8248c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_ci if (rp->status) 8278c2ecf20Sopenharmony_ci return; 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_ci if (test_bit(HCI_INIT, &hdev->flags)) 8308c2ecf20Sopenharmony_ci hdev->page_scan_type = rp->type; 8318c2ecf20Sopenharmony_ci} 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_cistatic void hci_cc_write_page_scan_type(struct hci_dev *hdev, 8348c2ecf20Sopenharmony_ci struct sk_buff *skb) 8358c2ecf20Sopenharmony_ci{ 8368c2ecf20Sopenharmony_ci u8 status = *((u8 *) skb->data); 8378c2ecf20Sopenharmony_ci u8 *type; 8388c2ecf20Sopenharmony_ci 8398c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_ci if (status) 8428c2ecf20Sopenharmony_ci return; 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci type = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE); 8458c2ecf20Sopenharmony_ci if (type) 8468c2ecf20Sopenharmony_ci hdev->page_scan_type = *type; 8478c2ecf20Sopenharmony_ci} 8488c2ecf20Sopenharmony_ci 8498c2ecf20Sopenharmony_cistatic void hci_cc_read_data_block_size(struct hci_dev *hdev, 8508c2ecf20Sopenharmony_ci struct sk_buff *skb) 8518c2ecf20Sopenharmony_ci{ 8528c2ecf20Sopenharmony_ci struct hci_rp_read_data_block_size *rp = (void *) skb->data; 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 8558c2ecf20Sopenharmony_ci 8568c2ecf20Sopenharmony_ci if (rp->status) 8578c2ecf20Sopenharmony_ci return; 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci hdev->block_mtu = __le16_to_cpu(rp->max_acl_len); 8608c2ecf20Sopenharmony_ci hdev->block_len = __le16_to_cpu(rp->block_len); 8618c2ecf20Sopenharmony_ci hdev->num_blocks = __le16_to_cpu(rp->num_blocks); 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_ci hdev->block_cnt = hdev->num_blocks; 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu, 8668c2ecf20Sopenharmony_ci hdev->block_cnt, hdev->block_len); 8678c2ecf20Sopenharmony_ci} 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_cistatic void hci_cc_read_clock(struct hci_dev *hdev, struct sk_buff *skb) 8708c2ecf20Sopenharmony_ci{ 8718c2ecf20Sopenharmony_ci struct hci_rp_read_clock *rp = (void *) skb->data; 8728c2ecf20Sopenharmony_ci struct hci_cp_read_clock *cp; 8738c2ecf20Sopenharmony_ci struct hci_conn *conn; 8748c2ecf20Sopenharmony_ci 8758c2ecf20Sopenharmony_ci BT_DBG("%s", hdev->name); 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci if (skb->len < sizeof(*rp)) 8788c2ecf20Sopenharmony_ci return; 8798c2ecf20Sopenharmony_ci 8808c2ecf20Sopenharmony_ci if (rp->status) 8818c2ecf20Sopenharmony_ci return; 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_ci cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK); 8868c2ecf20Sopenharmony_ci if (!cp) 8878c2ecf20Sopenharmony_ci goto unlock; 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci if (cp->which == 0x00) { 8908c2ecf20Sopenharmony_ci hdev->clock = le32_to_cpu(rp->clock); 8918c2ecf20Sopenharmony_ci goto unlock; 8928c2ecf20Sopenharmony_ci } 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 8958c2ecf20Sopenharmony_ci if (conn) { 8968c2ecf20Sopenharmony_ci conn->clock = le32_to_cpu(rp->clock); 8978c2ecf20Sopenharmony_ci conn->clock_accuracy = le16_to_cpu(rp->accuracy); 8988c2ecf20Sopenharmony_ci } 8998c2ecf20Sopenharmony_ci 9008c2ecf20Sopenharmony_ciunlock: 9018c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 9028c2ecf20Sopenharmony_ci} 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_cistatic void hci_cc_read_local_amp_info(struct hci_dev *hdev, 9058c2ecf20Sopenharmony_ci struct sk_buff *skb) 9068c2ecf20Sopenharmony_ci{ 9078c2ecf20Sopenharmony_ci struct hci_rp_read_local_amp_info *rp = (void *) skb->data; 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ci if (rp->status) 9128c2ecf20Sopenharmony_ci return; 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_ci hdev->amp_status = rp->amp_status; 9158c2ecf20Sopenharmony_ci hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); 9168c2ecf20Sopenharmony_ci hdev->amp_max_bw = __le32_to_cpu(rp->max_bw); 9178c2ecf20Sopenharmony_ci hdev->amp_min_latency = __le32_to_cpu(rp->min_latency); 9188c2ecf20Sopenharmony_ci hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu); 9198c2ecf20Sopenharmony_ci hdev->amp_type = rp->amp_type; 9208c2ecf20Sopenharmony_ci hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap); 9218c2ecf20Sopenharmony_ci hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size); 9228c2ecf20Sopenharmony_ci hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); 9238c2ecf20Sopenharmony_ci hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); 9248c2ecf20Sopenharmony_ci} 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_cistatic void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, 9278c2ecf20Sopenharmony_ci struct sk_buff *skb) 9288c2ecf20Sopenharmony_ci{ 9298c2ecf20Sopenharmony_ci struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data; 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_ci if (rp->status) 9348c2ecf20Sopenharmony_ci return; 9358c2ecf20Sopenharmony_ci 9368c2ecf20Sopenharmony_ci hdev->inq_tx_power = rp->tx_power; 9378c2ecf20Sopenharmony_ci} 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_cistatic void hci_cc_read_def_err_data_reporting(struct hci_dev *hdev, 9408c2ecf20Sopenharmony_ci struct sk_buff *skb) 9418c2ecf20Sopenharmony_ci{ 9428c2ecf20Sopenharmony_ci struct hci_rp_read_def_err_data_reporting *rp = (void *)skb->data; 9438c2ecf20Sopenharmony_ci 9448c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 9458c2ecf20Sopenharmony_ci 9468c2ecf20Sopenharmony_ci if (rp->status) 9478c2ecf20Sopenharmony_ci return; 9488c2ecf20Sopenharmony_ci 9498c2ecf20Sopenharmony_ci hdev->err_data_reporting = rp->err_data_reporting; 9508c2ecf20Sopenharmony_ci} 9518c2ecf20Sopenharmony_ci 9528c2ecf20Sopenharmony_cistatic void hci_cc_write_def_err_data_reporting(struct hci_dev *hdev, 9538c2ecf20Sopenharmony_ci struct sk_buff *skb) 9548c2ecf20Sopenharmony_ci{ 9558c2ecf20Sopenharmony_ci __u8 status = *((__u8 *)skb->data); 9568c2ecf20Sopenharmony_ci struct hci_cp_write_def_err_data_reporting *cp; 9578c2ecf20Sopenharmony_ci 9588c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_ci if (status) 9618c2ecf20Sopenharmony_ci return; 9628c2ecf20Sopenharmony_ci 9638c2ecf20Sopenharmony_ci cp = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_ERR_DATA_REPORTING); 9648c2ecf20Sopenharmony_ci if (!cp) 9658c2ecf20Sopenharmony_ci return; 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_ci hdev->err_data_reporting = cp->err_data_reporting; 9688c2ecf20Sopenharmony_ci} 9698c2ecf20Sopenharmony_ci 9708c2ecf20Sopenharmony_cistatic void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) 9718c2ecf20Sopenharmony_ci{ 9728c2ecf20Sopenharmony_ci struct hci_rp_pin_code_reply *rp = (void *) skb->data; 9738c2ecf20Sopenharmony_ci struct hci_cp_pin_code_reply *cp; 9748c2ecf20Sopenharmony_ci struct hci_conn *conn; 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 9798c2ecf20Sopenharmony_ci 9808c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_MGMT)) 9818c2ecf20Sopenharmony_ci mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci if (rp->status) 9848c2ecf20Sopenharmony_ci goto unlock; 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_ci cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); 9878c2ecf20Sopenharmony_ci if (!cp) 9888c2ecf20Sopenharmony_ci goto unlock; 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 9918c2ecf20Sopenharmony_ci if (conn) 9928c2ecf20Sopenharmony_ci conn->pin_length = cp->pin_len; 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_ciunlock: 9958c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 9968c2ecf20Sopenharmony_ci} 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_cistatic void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 9998c2ecf20Sopenharmony_ci{ 10008c2ecf20Sopenharmony_ci struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data; 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 10038c2ecf20Sopenharmony_ci 10048c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 10058c2ecf20Sopenharmony_ci 10068c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_MGMT)) 10078c2ecf20Sopenharmony_ci mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr, 10088c2ecf20Sopenharmony_ci rp->status); 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 10118c2ecf20Sopenharmony_ci} 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_cistatic void hci_cc_le_read_buffer_size(struct hci_dev *hdev, 10148c2ecf20Sopenharmony_ci struct sk_buff *skb) 10158c2ecf20Sopenharmony_ci{ 10168c2ecf20Sopenharmony_ci struct hci_rp_le_read_buffer_size *rp = (void *) skb->data; 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 10198c2ecf20Sopenharmony_ci 10208c2ecf20Sopenharmony_ci if (rp->status) 10218c2ecf20Sopenharmony_ci return; 10228c2ecf20Sopenharmony_ci 10238c2ecf20Sopenharmony_ci hdev->le_mtu = __le16_to_cpu(rp->le_mtu); 10248c2ecf20Sopenharmony_ci hdev->le_pkts = rp->le_max_pkt; 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_ci hdev->le_cnt = hdev->le_pkts; 10278c2ecf20Sopenharmony_ci 10288c2ecf20Sopenharmony_ci BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); 10298c2ecf20Sopenharmony_ci} 10308c2ecf20Sopenharmony_ci 10318c2ecf20Sopenharmony_cistatic void hci_cc_le_read_local_features(struct hci_dev *hdev, 10328c2ecf20Sopenharmony_ci struct sk_buff *skb) 10338c2ecf20Sopenharmony_ci{ 10348c2ecf20Sopenharmony_ci struct hci_rp_le_read_local_features *rp = (void *) skb->data; 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_ci if (rp->status) 10398c2ecf20Sopenharmony_ci return; 10408c2ecf20Sopenharmony_ci 10418c2ecf20Sopenharmony_ci memcpy(hdev->le_features, rp->features, 8); 10428c2ecf20Sopenharmony_ci} 10438c2ecf20Sopenharmony_ci 10448c2ecf20Sopenharmony_cistatic void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, 10458c2ecf20Sopenharmony_ci struct sk_buff *skb) 10468c2ecf20Sopenharmony_ci{ 10478c2ecf20Sopenharmony_ci struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data; 10488c2ecf20Sopenharmony_ci 10498c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 10508c2ecf20Sopenharmony_ci 10518c2ecf20Sopenharmony_ci if (rp->status) 10528c2ecf20Sopenharmony_ci return; 10538c2ecf20Sopenharmony_ci 10548c2ecf20Sopenharmony_ci hdev->adv_tx_power = rp->tx_power; 10558c2ecf20Sopenharmony_ci} 10568c2ecf20Sopenharmony_ci 10578c2ecf20Sopenharmony_cistatic void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) 10588c2ecf20Sopenharmony_ci{ 10598c2ecf20Sopenharmony_ci struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 10608c2ecf20Sopenharmony_ci 10618c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 10628c2ecf20Sopenharmony_ci 10638c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_MGMT)) 10668c2ecf20Sopenharmony_ci mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0, 10678c2ecf20Sopenharmony_ci rp->status); 10688c2ecf20Sopenharmony_ci 10698c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 10708c2ecf20Sopenharmony_ci} 10718c2ecf20Sopenharmony_ci 10728c2ecf20Sopenharmony_cistatic void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, 10738c2ecf20Sopenharmony_ci struct sk_buff *skb) 10748c2ecf20Sopenharmony_ci{ 10758c2ecf20Sopenharmony_ci struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 10768c2ecf20Sopenharmony_ci 10778c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 10808c2ecf20Sopenharmony_ci 10818c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_MGMT)) 10828c2ecf20Sopenharmony_ci mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr, 10838c2ecf20Sopenharmony_ci ACL_LINK, 0, rp->status); 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 10868c2ecf20Sopenharmony_ci} 10878c2ecf20Sopenharmony_ci 10888c2ecf20Sopenharmony_cistatic void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb) 10898c2ecf20Sopenharmony_ci{ 10908c2ecf20Sopenharmony_ci struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 10918c2ecf20Sopenharmony_ci 10928c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 10938c2ecf20Sopenharmony_ci 10948c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 10958c2ecf20Sopenharmony_ci 10968c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_MGMT)) 10978c2ecf20Sopenharmony_ci mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 10988c2ecf20Sopenharmony_ci 0, rp->status); 10998c2ecf20Sopenharmony_ci 11008c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 11018c2ecf20Sopenharmony_ci} 11028c2ecf20Sopenharmony_ci 11038c2ecf20Sopenharmony_cistatic void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, 11048c2ecf20Sopenharmony_ci struct sk_buff *skb) 11058c2ecf20Sopenharmony_ci{ 11068c2ecf20Sopenharmony_ci struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 11098c2ecf20Sopenharmony_ci 11108c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 11118c2ecf20Sopenharmony_ci 11128c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_MGMT)) 11138c2ecf20Sopenharmony_ci mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr, 11148c2ecf20Sopenharmony_ci ACL_LINK, 0, rp->status); 11158c2ecf20Sopenharmony_ci 11168c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 11178c2ecf20Sopenharmony_ci} 11188c2ecf20Sopenharmony_ci 11198c2ecf20Sopenharmony_cistatic void hci_cc_read_local_oob_data(struct hci_dev *hdev, 11208c2ecf20Sopenharmony_ci struct sk_buff *skb) 11218c2ecf20Sopenharmony_ci{ 11228c2ecf20Sopenharmony_ci struct hci_rp_read_local_oob_data *rp = (void *) skb->data; 11238c2ecf20Sopenharmony_ci 11248c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 11258c2ecf20Sopenharmony_ci} 11268c2ecf20Sopenharmony_ci 11278c2ecf20Sopenharmony_cistatic void hci_cc_read_local_oob_ext_data(struct hci_dev *hdev, 11288c2ecf20Sopenharmony_ci struct sk_buff *skb) 11298c2ecf20Sopenharmony_ci{ 11308c2ecf20Sopenharmony_ci struct hci_rp_read_local_oob_ext_data *rp = (void *) skb->data; 11318c2ecf20Sopenharmony_ci 11328c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 11338c2ecf20Sopenharmony_ci} 11348c2ecf20Sopenharmony_ci 11358c2ecf20Sopenharmony_cistatic void hci_cc_le_set_random_addr(struct hci_dev *hdev, struct sk_buff *skb) 11368c2ecf20Sopenharmony_ci{ 11378c2ecf20Sopenharmony_ci __u8 status = *((__u8 *) skb->data); 11388c2ecf20Sopenharmony_ci bdaddr_t *sent; 11398c2ecf20Sopenharmony_ci 11408c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 11418c2ecf20Sopenharmony_ci 11428c2ecf20Sopenharmony_ci if (status) 11438c2ecf20Sopenharmony_ci return; 11448c2ecf20Sopenharmony_ci 11458c2ecf20Sopenharmony_ci sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_RANDOM_ADDR); 11468c2ecf20Sopenharmony_ci if (!sent) 11478c2ecf20Sopenharmony_ci return; 11488c2ecf20Sopenharmony_ci 11498c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 11508c2ecf20Sopenharmony_ci 11518c2ecf20Sopenharmony_ci bacpy(&hdev->random_addr, sent); 11528c2ecf20Sopenharmony_ci 11538c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 11548c2ecf20Sopenharmony_ci} 11558c2ecf20Sopenharmony_ci 11568c2ecf20Sopenharmony_cistatic void hci_cc_le_set_default_phy(struct hci_dev *hdev, struct sk_buff *skb) 11578c2ecf20Sopenharmony_ci{ 11588c2ecf20Sopenharmony_ci __u8 status = *((__u8 *) skb->data); 11598c2ecf20Sopenharmony_ci struct hci_cp_le_set_default_phy *cp; 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 11628c2ecf20Sopenharmony_ci 11638c2ecf20Sopenharmony_ci if (status) 11648c2ecf20Sopenharmony_ci return; 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_ci cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_DEFAULT_PHY); 11678c2ecf20Sopenharmony_ci if (!cp) 11688c2ecf20Sopenharmony_ci return; 11698c2ecf20Sopenharmony_ci 11708c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 11718c2ecf20Sopenharmony_ci 11728c2ecf20Sopenharmony_ci hdev->le_tx_def_phys = cp->tx_phys; 11738c2ecf20Sopenharmony_ci hdev->le_rx_def_phys = cp->rx_phys; 11748c2ecf20Sopenharmony_ci 11758c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 11768c2ecf20Sopenharmony_ci} 11778c2ecf20Sopenharmony_ci 11788c2ecf20Sopenharmony_cistatic void hci_cc_le_set_adv_set_random_addr(struct hci_dev *hdev, 11798c2ecf20Sopenharmony_ci struct sk_buff *skb) 11808c2ecf20Sopenharmony_ci{ 11818c2ecf20Sopenharmony_ci __u8 status = *((__u8 *) skb->data); 11828c2ecf20Sopenharmony_ci struct hci_cp_le_set_adv_set_rand_addr *cp; 11838c2ecf20Sopenharmony_ci struct adv_info *adv_instance; 11848c2ecf20Sopenharmony_ci 11858c2ecf20Sopenharmony_ci if (status) 11868c2ecf20Sopenharmony_ci return; 11878c2ecf20Sopenharmony_ci 11888c2ecf20Sopenharmony_ci cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_SET_RAND_ADDR); 11898c2ecf20Sopenharmony_ci if (!cp) 11908c2ecf20Sopenharmony_ci return; 11918c2ecf20Sopenharmony_ci 11928c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 11938c2ecf20Sopenharmony_ci 11948c2ecf20Sopenharmony_ci if (!hdev->cur_adv_instance) { 11958c2ecf20Sopenharmony_ci /* Store in hdev for instance 0 (Set adv and Directed advs) */ 11968c2ecf20Sopenharmony_ci bacpy(&hdev->random_addr, &cp->bdaddr); 11978c2ecf20Sopenharmony_ci } else { 11988c2ecf20Sopenharmony_ci adv_instance = hci_find_adv_instance(hdev, 11998c2ecf20Sopenharmony_ci hdev->cur_adv_instance); 12008c2ecf20Sopenharmony_ci if (adv_instance) 12018c2ecf20Sopenharmony_ci bacpy(&adv_instance->random_addr, &cp->bdaddr); 12028c2ecf20Sopenharmony_ci } 12038c2ecf20Sopenharmony_ci 12048c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 12058c2ecf20Sopenharmony_ci} 12068c2ecf20Sopenharmony_ci 12078c2ecf20Sopenharmony_cistatic void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb) 12088c2ecf20Sopenharmony_ci{ 12098c2ecf20Sopenharmony_ci __u8 *sent, status = *((__u8 *) skb->data); 12108c2ecf20Sopenharmony_ci 12118c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 12128c2ecf20Sopenharmony_ci 12138c2ecf20Sopenharmony_ci if (status) 12148c2ecf20Sopenharmony_ci return; 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_ci sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE); 12178c2ecf20Sopenharmony_ci if (!sent) 12188c2ecf20Sopenharmony_ci return; 12198c2ecf20Sopenharmony_ci 12208c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 12218c2ecf20Sopenharmony_ci 12228c2ecf20Sopenharmony_ci /* If we're doing connection initiation as peripheral. Set a 12238c2ecf20Sopenharmony_ci * timeout in case something goes wrong. 12248c2ecf20Sopenharmony_ci */ 12258c2ecf20Sopenharmony_ci if (*sent) { 12268c2ecf20Sopenharmony_ci struct hci_conn *conn; 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_ci hci_dev_set_flag(hdev, HCI_LE_ADV); 12298c2ecf20Sopenharmony_ci 12308c2ecf20Sopenharmony_ci conn = hci_lookup_le_connect(hdev); 12318c2ecf20Sopenharmony_ci if (conn) 12328c2ecf20Sopenharmony_ci queue_delayed_work(hdev->workqueue, 12338c2ecf20Sopenharmony_ci &conn->le_conn_timeout, 12348c2ecf20Sopenharmony_ci conn->conn_timeout); 12358c2ecf20Sopenharmony_ci } else { 12368c2ecf20Sopenharmony_ci hci_dev_clear_flag(hdev, HCI_LE_ADV); 12378c2ecf20Sopenharmony_ci } 12388c2ecf20Sopenharmony_ci 12398c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 12408c2ecf20Sopenharmony_ci} 12418c2ecf20Sopenharmony_ci 12428c2ecf20Sopenharmony_cistatic void hci_cc_le_set_ext_adv_enable(struct hci_dev *hdev, 12438c2ecf20Sopenharmony_ci struct sk_buff *skb) 12448c2ecf20Sopenharmony_ci{ 12458c2ecf20Sopenharmony_ci struct hci_cp_le_set_ext_adv_enable *cp; 12468c2ecf20Sopenharmony_ci __u8 status = *((__u8 *) skb->data); 12478c2ecf20Sopenharmony_ci 12488c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 12498c2ecf20Sopenharmony_ci 12508c2ecf20Sopenharmony_ci if (status) 12518c2ecf20Sopenharmony_ci return; 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_ci cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_ADV_ENABLE); 12548c2ecf20Sopenharmony_ci if (!cp) 12558c2ecf20Sopenharmony_ci return; 12568c2ecf20Sopenharmony_ci 12578c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 12588c2ecf20Sopenharmony_ci 12598c2ecf20Sopenharmony_ci if (cp->enable) { 12608c2ecf20Sopenharmony_ci struct hci_conn *conn; 12618c2ecf20Sopenharmony_ci 12628c2ecf20Sopenharmony_ci hci_dev_set_flag(hdev, HCI_LE_ADV); 12638c2ecf20Sopenharmony_ci 12648c2ecf20Sopenharmony_ci conn = hci_lookup_le_connect(hdev); 12658c2ecf20Sopenharmony_ci if (conn) 12668c2ecf20Sopenharmony_ci queue_delayed_work(hdev->workqueue, 12678c2ecf20Sopenharmony_ci &conn->le_conn_timeout, 12688c2ecf20Sopenharmony_ci conn->conn_timeout); 12698c2ecf20Sopenharmony_ci } else { 12708c2ecf20Sopenharmony_ci hci_dev_clear_flag(hdev, HCI_LE_ADV); 12718c2ecf20Sopenharmony_ci } 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 12748c2ecf20Sopenharmony_ci} 12758c2ecf20Sopenharmony_ci 12768c2ecf20Sopenharmony_cistatic void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) 12778c2ecf20Sopenharmony_ci{ 12788c2ecf20Sopenharmony_ci struct hci_cp_le_set_scan_param *cp; 12798c2ecf20Sopenharmony_ci __u8 status = *((__u8 *) skb->data); 12808c2ecf20Sopenharmony_ci 12818c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_ci if (status) 12848c2ecf20Sopenharmony_ci return; 12858c2ecf20Sopenharmony_ci 12868c2ecf20Sopenharmony_ci cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_PARAM); 12878c2ecf20Sopenharmony_ci if (!cp) 12888c2ecf20Sopenharmony_ci return; 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 12918c2ecf20Sopenharmony_ci 12928c2ecf20Sopenharmony_ci hdev->le_scan_type = cp->type; 12938c2ecf20Sopenharmony_ci 12948c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 12958c2ecf20Sopenharmony_ci} 12968c2ecf20Sopenharmony_ci 12978c2ecf20Sopenharmony_cistatic void hci_cc_le_set_ext_scan_param(struct hci_dev *hdev, 12988c2ecf20Sopenharmony_ci struct sk_buff *skb) 12998c2ecf20Sopenharmony_ci{ 13008c2ecf20Sopenharmony_ci struct hci_cp_le_set_ext_scan_params *cp; 13018c2ecf20Sopenharmony_ci __u8 status = *((__u8 *) skb->data); 13028c2ecf20Sopenharmony_ci struct hci_cp_le_scan_phy_params *phy_param; 13038c2ecf20Sopenharmony_ci 13048c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 13058c2ecf20Sopenharmony_ci 13068c2ecf20Sopenharmony_ci if (status) 13078c2ecf20Sopenharmony_ci return; 13088c2ecf20Sopenharmony_ci 13098c2ecf20Sopenharmony_ci cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_SCAN_PARAMS); 13108c2ecf20Sopenharmony_ci if (!cp) 13118c2ecf20Sopenharmony_ci return; 13128c2ecf20Sopenharmony_ci 13138c2ecf20Sopenharmony_ci phy_param = (void *)cp->data; 13148c2ecf20Sopenharmony_ci 13158c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 13168c2ecf20Sopenharmony_ci 13178c2ecf20Sopenharmony_ci hdev->le_scan_type = phy_param->type; 13188c2ecf20Sopenharmony_ci 13198c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 13208c2ecf20Sopenharmony_ci} 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_cistatic bool has_pending_adv_report(struct hci_dev *hdev) 13238c2ecf20Sopenharmony_ci{ 13248c2ecf20Sopenharmony_ci struct discovery_state *d = &hdev->discovery; 13258c2ecf20Sopenharmony_ci 13268c2ecf20Sopenharmony_ci return bacmp(&d->last_adv_addr, BDADDR_ANY); 13278c2ecf20Sopenharmony_ci} 13288c2ecf20Sopenharmony_ci 13298c2ecf20Sopenharmony_cistatic void clear_pending_adv_report(struct hci_dev *hdev) 13308c2ecf20Sopenharmony_ci{ 13318c2ecf20Sopenharmony_ci struct discovery_state *d = &hdev->discovery; 13328c2ecf20Sopenharmony_ci 13338c2ecf20Sopenharmony_ci bacpy(&d->last_adv_addr, BDADDR_ANY); 13348c2ecf20Sopenharmony_ci d->last_adv_data_len = 0; 13358c2ecf20Sopenharmony_ci} 13368c2ecf20Sopenharmony_ci 13378c2ecf20Sopenharmony_cistatic void store_pending_adv_report(struct hci_dev *hdev, bdaddr_t *bdaddr, 13388c2ecf20Sopenharmony_ci u8 bdaddr_type, s8 rssi, u32 flags, 13398c2ecf20Sopenharmony_ci u8 *data, u8 len) 13408c2ecf20Sopenharmony_ci{ 13418c2ecf20Sopenharmony_ci struct discovery_state *d = &hdev->discovery; 13428c2ecf20Sopenharmony_ci 13438c2ecf20Sopenharmony_ci if (len > HCI_MAX_AD_LENGTH) 13448c2ecf20Sopenharmony_ci return; 13458c2ecf20Sopenharmony_ci 13468c2ecf20Sopenharmony_ci bacpy(&d->last_adv_addr, bdaddr); 13478c2ecf20Sopenharmony_ci d->last_adv_addr_type = bdaddr_type; 13488c2ecf20Sopenharmony_ci d->last_adv_rssi = rssi; 13498c2ecf20Sopenharmony_ci d->last_adv_flags = flags; 13508c2ecf20Sopenharmony_ci memcpy(d->last_adv_data, data, len); 13518c2ecf20Sopenharmony_ci d->last_adv_data_len = len; 13528c2ecf20Sopenharmony_ci} 13538c2ecf20Sopenharmony_ci 13548c2ecf20Sopenharmony_cistatic void le_set_scan_enable_complete(struct hci_dev *hdev, u8 enable) 13558c2ecf20Sopenharmony_ci{ 13568c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 13578c2ecf20Sopenharmony_ci 13588c2ecf20Sopenharmony_ci switch (enable) { 13598c2ecf20Sopenharmony_ci case LE_SCAN_ENABLE: 13608c2ecf20Sopenharmony_ci hci_dev_set_flag(hdev, HCI_LE_SCAN); 13618c2ecf20Sopenharmony_ci if (hdev->le_scan_type == LE_SCAN_ACTIVE) 13628c2ecf20Sopenharmony_ci clear_pending_adv_report(hdev); 13638c2ecf20Sopenharmony_ci break; 13648c2ecf20Sopenharmony_ci 13658c2ecf20Sopenharmony_ci case LE_SCAN_DISABLE: 13668c2ecf20Sopenharmony_ci /* We do this here instead of when setting DISCOVERY_STOPPED 13678c2ecf20Sopenharmony_ci * since the latter would potentially require waiting for 13688c2ecf20Sopenharmony_ci * inquiry to stop too. 13698c2ecf20Sopenharmony_ci */ 13708c2ecf20Sopenharmony_ci if (has_pending_adv_report(hdev)) { 13718c2ecf20Sopenharmony_ci struct discovery_state *d = &hdev->discovery; 13728c2ecf20Sopenharmony_ci 13738c2ecf20Sopenharmony_ci mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK, 13748c2ecf20Sopenharmony_ci d->last_adv_addr_type, NULL, 13758c2ecf20Sopenharmony_ci d->last_adv_rssi, d->last_adv_flags, 13768c2ecf20Sopenharmony_ci d->last_adv_data, 13778c2ecf20Sopenharmony_ci d->last_adv_data_len, NULL, 0); 13788c2ecf20Sopenharmony_ci } 13798c2ecf20Sopenharmony_ci 13808c2ecf20Sopenharmony_ci /* Cancel this timer so that we don't try to disable scanning 13818c2ecf20Sopenharmony_ci * when it's already disabled. 13828c2ecf20Sopenharmony_ci */ 13838c2ecf20Sopenharmony_ci cancel_delayed_work(&hdev->le_scan_disable); 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_ci hci_dev_clear_flag(hdev, HCI_LE_SCAN); 13868c2ecf20Sopenharmony_ci 13878c2ecf20Sopenharmony_ci /* The HCI_LE_SCAN_INTERRUPTED flag indicates that we 13888c2ecf20Sopenharmony_ci * interrupted scanning due to a connect request. Mark 13898c2ecf20Sopenharmony_ci * therefore discovery as stopped. If this was not 13908c2ecf20Sopenharmony_ci * because of a connect request advertising might have 13918c2ecf20Sopenharmony_ci * been disabled because of active scanning, so 13928c2ecf20Sopenharmony_ci * re-enable it again if necessary. 13938c2ecf20Sopenharmony_ci */ 13948c2ecf20Sopenharmony_ci if (hci_dev_test_and_clear_flag(hdev, HCI_LE_SCAN_INTERRUPTED)) 13958c2ecf20Sopenharmony_ci hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 13968c2ecf20Sopenharmony_ci else if (!hci_dev_test_flag(hdev, HCI_LE_ADV) && 13978c2ecf20Sopenharmony_ci hdev->discovery.state == DISCOVERY_FINDING) 13988c2ecf20Sopenharmony_ci hci_req_reenable_advertising(hdev); 13998c2ecf20Sopenharmony_ci 14008c2ecf20Sopenharmony_ci break; 14018c2ecf20Sopenharmony_ci 14028c2ecf20Sopenharmony_ci default: 14038c2ecf20Sopenharmony_ci bt_dev_err(hdev, "use of reserved LE_Scan_Enable param %d", 14048c2ecf20Sopenharmony_ci enable); 14058c2ecf20Sopenharmony_ci break; 14068c2ecf20Sopenharmony_ci } 14078c2ecf20Sopenharmony_ci 14088c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 14098c2ecf20Sopenharmony_ci} 14108c2ecf20Sopenharmony_ci 14118c2ecf20Sopenharmony_cistatic void hci_cc_le_set_scan_enable(struct hci_dev *hdev, 14128c2ecf20Sopenharmony_ci struct sk_buff *skb) 14138c2ecf20Sopenharmony_ci{ 14148c2ecf20Sopenharmony_ci struct hci_cp_le_set_scan_enable *cp; 14158c2ecf20Sopenharmony_ci __u8 status = *((__u8 *) skb->data); 14168c2ecf20Sopenharmony_ci 14178c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 14188c2ecf20Sopenharmony_ci 14198c2ecf20Sopenharmony_ci if (status) 14208c2ecf20Sopenharmony_ci return; 14218c2ecf20Sopenharmony_ci 14228c2ecf20Sopenharmony_ci cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE); 14238c2ecf20Sopenharmony_ci if (!cp) 14248c2ecf20Sopenharmony_ci return; 14258c2ecf20Sopenharmony_ci 14268c2ecf20Sopenharmony_ci le_set_scan_enable_complete(hdev, cp->enable); 14278c2ecf20Sopenharmony_ci} 14288c2ecf20Sopenharmony_ci 14298c2ecf20Sopenharmony_cistatic void hci_cc_le_set_ext_scan_enable(struct hci_dev *hdev, 14308c2ecf20Sopenharmony_ci struct sk_buff *skb) 14318c2ecf20Sopenharmony_ci{ 14328c2ecf20Sopenharmony_ci struct hci_cp_le_set_ext_scan_enable *cp; 14338c2ecf20Sopenharmony_ci __u8 status = *((__u8 *) skb->data); 14348c2ecf20Sopenharmony_ci 14358c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 14368c2ecf20Sopenharmony_ci 14378c2ecf20Sopenharmony_ci if (status) 14388c2ecf20Sopenharmony_ci return; 14398c2ecf20Sopenharmony_ci 14408c2ecf20Sopenharmony_ci cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_SCAN_ENABLE); 14418c2ecf20Sopenharmony_ci if (!cp) 14428c2ecf20Sopenharmony_ci return; 14438c2ecf20Sopenharmony_ci 14448c2ecf20Sopenharmony_ci le_set_scan_enable_complete(hdev, cp->enable); 14458c2ecf20Sopenharmony_ci} 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_cistatic void hci_cc_le_read_num_adv_sets(struct hci_dev *hdev, 14488c2ecf20Sopenharmony_ci struct sk_buff *skb) 14498c2ecf20Sopenharmony_ci{ 14508c2ecf20Sopenharmony_ci struct hci_rp_le_read_num_supported_adv_sets *rp = (void *) skb->data; 14518c2ecf20Sopenharmony_ci 14528c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x No of Adv sets %u", hdev->name, rp->status, 14538c2ecf20Sopenharmony_ci rp->num_of_sets); 14548c2ecf20Sopenharmony_ci 14558c2ecf20Sopenharmony_ci if (rp->status) 14568c2ecf20Sopenharmony_ci return; 14578c2ecf20Sopenharmony_ci 14588c2ecf20Sopenharmony_ci hdev->le_num_of_adv_sets = rp->num_of_sets; 14598c2ecf20Sopenharmony_ci} 14608c2ecf20Sopenharmony_ci 14618c2ecf20Sopenharmony_cistatic void hci_cc_le_read_accept_list_size(struct hci_dev *hdev, 14628c2ecf20Sopenharmony_ci struct sk_buff *skb) 14638c2ecf20Sopenharmony_ci{ 14648c2ecf20Sopenharmony_ci struct hci_rp_le_read_accept_list_size *rp = (void *)skb->data; 14658c2ecf20Sopenharmony_ci 14668c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size); 14678c2ecf20Sopenharmony_ci 14688c2ecf20Sopenharmony_ci if (rp->status) 14698c2ecf20Sopenharmony_ci return; 14708c2ecf20Sopenharmony_ci 14718c2ecf20Sopenharmony_ci hdev->le_accept_list_size = rp->size; 14728c2ecf20Sopenharmony_ci} 14738c2ecf20Sopenharmony_ci 14748c2ecf20Sopenharmony_cistatic void hci_cc_le_clear_accept_list(struct hci_dev *hdev, 14758c2ecf20Sopenharmony_ci struct sk_buff *skb) 14768c2ecf20Sopenharmony_ci{ 14778c2ecf20Sopenharmony_ci __u8 status = *((__u8 *) skb->data); 14788c2ecf20Sopenharmony_ci 14798c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 14808c2ecf20Sopenharmony_ci 14818c2ecf20Sopenharmony_ci if (status) 14828c2ecf20Sopenharmony_ci return; 14838c2ecf20Sopenharmony_ci 14848c2ecf20Sopenharmony_ci hci_bdaddr_list_clear(&hdev->le_accept_list); 14858c2ecf20Sopenharmony_ci} 14868c2ecf20Sopenharmony_ci 14878c2ecf20Sopenharmony_cistatic void hci_cc_le_add_to_accept_list(struct hci_dev *hdev, 14888c2ecf20Sopenharmony_ci struct sk_buff *skb) 14898c2ecf20Sopenharmony_ci{ 14908c2ecf20Sopenharmony_ci struct hci_cp_le_add_to_accept_list *sent; 14918c2ecf20Sopenharmony_ci __u8 status = *((__u8 *) skb->data); 14928c2ecf20Sopenharmony_ci 14938c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 14948c2ecf20Sopenharmony_ci 14958c2ecf20Sopenharmony_ci if (status) 14968c2ecf20Sopenharmony_ci return; 14978c2ecf20Sopenharmony_ci 14988c2ecf20Sopenharmony_ci sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_ACCEPT_LIST); 14998c2ecf20Sopenharmony_ci if (!sent) 15008c2ecf20Sopenharmony_ci return; 15018c2ecf20Sopenharmony_ci 15028c2ecf20Sopenharmony_ci hci_bdaddr_list_add(&hdev->le_accept_list, &sent->bdaddr, 15038c2ecf20Sopenharmony_ci sent->bdaddr_type); 15048c2ecf20Sopenharmony_ci} 15058c2ecf20Sopenharmony_ci 15068c2ecf20Sopenharmony_cistatic void hci_cc_le_del_from_accept_list(struct hci_dev *hdev, 15078c2ecf20Sopenharmony_ci struct sk_buff *skb) 15088c2ecf20Sopenharmony_ci{ 15098c2ecf20Sopenharmony_ci struct hci_cp_le_del_from_accept_list *sent; 15108c2ecf20Sopenharmony_ci __u8 status = *((__u8 *) skb->data); 15118c2ecf20Sopenharmony_ci 15128c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 15138c2ecf20Sopenharmony_ci 15148c2ecf20Sopenharmony_ci if (status) 15158c2ecf20Sopenharmony_ci return; 15168c2ecf20Sopenharmony_ci 15178c2ecf20Sopenharmony_ci sent = hci_sent_cmd_data(hdev, HCI_OP_LE_DEL_FROM_ACCEPT_LIST); 15188c2ecf20Sopenharmony_ci if (!sent) 15198c2ecf20Sopenharmony_ci return; 15208c2ecf20Sopenharmony_ci 15218c2ecf20Sopenharmony_ci hci_bdaddr_list_del(&hdev->le_accept_list, &sent->bdaddr, 15228c2ecf20Sopenharmony_ci sent->bdaddr_type); 15238c2ecf20Sopenharmony_ci} 15248c2ecf20Sopenharmony_ci 15258c2ecf20Sopenharmony_cistatic void hci_cc_le_read_supported_states(struct hci_dev *hdev, 15268c2ecf20Sopenharmony_ci struct sk_buff *skb) 15278c2ecf20Sopenharmony_ci{ 15288c2ecf20Sopenharmony_ci struct hci_rp_le_read_supported_states *rp = (void *) skb->data; 15298c2ecf20Sopenharmony_ci 15308c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 15318c2ecf20Sopenharmony_ci 15328c2ecf20Sopenharmony_ci if (rp->status) 15338c2ecf20Sopenharmony_ci return; 15348c2ecf20Sopenharmony_ci 15358c2ecf20Sopenharmony_ci memcpy(hdev->le_states, rp->le_states, 8); 15368c2ecf20Sopenharmony_ci} 15378c2ecf20Sopenharmony_ci 15388c2ecf20Sopenharmony_cistatic void hci_cc_le_read_def_data_len(struct hci_dev *hdev, 15398c2ecf20Sopenharmony_ci struct sk_buff *skb) 15408c2ecf20Sopenharmony_ci{ 15418c2ecf20Sopenharmony_ci struct hci_rp_le_read_def_data_len *rp = (void *) skb->data; 15428c2ecf20Sopenharmony_ci 15438c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 15448c2ecf20Sopenharmony_ci 15458c2ecf20Sopenharmony_ci if (rp->status) 15468c2ecf20Sopenharmony_ci return; 15478c2ecf20Sopenharmony_ci 15488c2ecf20Sopenharmony_ci hdev->le_def_tx_len = le16_to_cpu(rp->tx_len); 15498c2ecf20Sopenharmony_ci hdev->le_def_tx_time = le16_to_cpu(rp->tx_time); 15508c2ecf20Sopenharmony_ci} 15518c2ecf20Sopenharmony_ci 15528c2ecf20Sopenharmony_cistatic void hci_cc_le_write_def_data_len(struct hci_dev *hdev, 15538c2ecf20Sopenharmony_ci struct sk_buff *skb) 15548c2ecf20Sopenharmony_ci{ 15558c2ecf20Sopenharmony_ci struct hci_cp_le_write_def_data_len *sent; 15568c2ecf20Sopenharmony_ci __u8 status = *((__u8 *) skb->data); 15578c2ecf20Sopenharmony_ci 15588c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 15598c2ecf20Sopenharmony_ci 15608c2ecf20Sopenharmony_ci if (status) 15618c2ecf20Sopenharmony_ci return; 15628c2ecf20Sopenharmony_ci 15638c2ecf20Sopenharmony_ci sent = hci_sent_cmd_data(hdev, HCI_OP_LE_WRITE_DEF_DATA_LEN); 15648c2ecf20Sopenharmony_ci if (!sent) 15658c2ecf20Sopenharmony_ci return; 15668c2ecf20Sopenharmony_ci 15678c2ecf20Sopenharmony_ci hdev->le_def_tx_len = le16_to_cpu(sent->tx_len); 15688c2ecf20Sopenharmony_ci hdev->le_def_tx_time = le16_to_cpu(sent->tx_time); 15698c2ecf20Sopenharmony_ci} 15708c2ecf20Sopenharmony_ci 15718c2ecf20Sopenharmony_cistatic void hci_cc_le_add_to_resolv_list(struct hci_dev *hdev, 15728c2ecf20Sopenharmony_ci struct sk_buff *skb) 15738c2ecf20Sopenharmony_ci{ 15748c2ecf20Sopenharmony_ci struct hci_cp_le_add_to_resolv_list *sent; 15758c2ecf20Sopenharmony_ci __u8 status = *((__u8 *) skb->data); 15768c2ecf20Sopenharmony_ci 15778c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 15788c2ecf20Sopenharmony_ci 15798c2ecf20Sopenharmony_ci if (status) 15808c2ecf20Sopenharmony_ci return; 15818c2ecf20Sopenharmony_ci 15828c2ecf20Sopenharmony_ci sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_RESOLV_LIST); 15838c2ecf20Sopenharmony_ci if (!sent) 15848c2ecf20Sopenharmony_ci return; 15858c2ecf20Sopenharmony_ci 15868c2ecf20Sopenharmony_ci hci_bdaddr_list_add_with_irk(&hdev->le_resolv_list, &sent->bdaddr, 15878c2ecf20Sopenharmony_ci sent->bdaddr_type, sent->peer_irk, 15888c2ecf20Sopenharmony_ci sent->local_irk); 15898c2ecf20Sopenharmony_ci} 15908c2ecf20Sopenharmony_ci 15918c2ecf20Sopenharmony_cistatic void hci_cc_le_del_from_resolv_list(struct hci_dev *hdev, 15928c2ecf20Sopenharmony_ci struct sk_buff *skb) 15938c2ecf20Sopenharmony_ci{ 15948c2ecf20Sopenharmony_ci struct hci_cp_le_del_from_resolv_list *sent; 15958c2ecf20Sopenharmony_ci __u8 status = *((__u8 *) skb->data); 15968c2ecf20Sopenharmony_ci 15978c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 15988c2ecf20Sopenharmony_ci 15998c2ecf20Sopenharmony_ci if (status) 16008c2ecf20Sopenharmony_ci return; 16018c2ecf20Sopenharmony_ci 16028c2ecf20Sopenharmony_ci sent = hci_sent_cmd_data(hdev, HCI_OP_LE_DEL_FROM_RESOLV_LIST); 16038c2ecf20Sopenharmony_ci if (!sent) 16048c2ecf20Sopenharmony_ci return; 16058c2ecf20Sopenharmony_ci 16068c2ecf20Sopenharmony_ci hci_bdaddr_list_del_with_irk(&hdev->le_resolv_list, &sent->bdaddr, 16078c2ecf20Sopenharmony_ci sent->bdaddr_type); 16088c2ecf20Sopenharmony_ci} 16098c2ecf20Sopenharmony_ci 16108c2ecf20Sopenharmony_cistatic void hci_cc_le_clear_resolv_list(struct hci_dev *hdev, 16118c2ecf20Sopenharmony_ci struct sk_buff *skb) 16128c2ecf20Sopenharmony_ci{ 16138c2ecf20Sopenharmony_ci __u8 status = *((__u8 *) skb->data); 16148c2ecf20Sopenharmony_ci 16158c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 16168c2ecf20Sopenharmony_ci 16178c2ecf20Sopenharmony_ci if (status) 16188c2ecf20Sopenharmony_ci return; 16198c2ecf20Sopenharmony_ci 16208c2ecf20Sopenharmony_ci hci_bdaddr_list_clear(&hdev->le_resolv_list); 16218c2ecf20Sopenharmony_ci} 16228c2ecf20Sopenharmony_ci 16238c2ecf20Sopenharmony_cistatic void hci_cc_le_read_resolv_list_size(struct hci_dev *hdev, 16248c2ecf20Sopenharmony_ci struct sk_buff *skb) 16258c2ecf20Sopenharmony_ci{ 16268c2ecf20Sopenharmony_ci struct hci_rp_le_read_resolv_list_size *rp = (void *) skb->data; 16278c2ecf20Sopenharmony_ci 16288c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size); 16298c2ecf20Sopenharmony_ci 16308c2ecf20Sopenharmony_ci if (rp->status) 16318c2ecf20Sopenharmony_ci return; 16328c2ecf20Sopenharmony_ci 16338c2ecf20Sopenharmony_ci hdev->le_resolv_list_size = rp->size; 16348c2ecf20Sopenharmony_ci} 16358c2ecf20Sopenharmony_ci 16368c2ecf20Sopenharmony_cistatic void hci_cc_le_set_addr_resolution_enable(struct hci_dev *hdev, 16378c2ecf20Sopenharmony_ci struct sk_buff *skb) 16388c2ecf20Sopenharmony_ci{ 16398c2ecf20Sopenharmony_ci __u8 *sent, status = *((__u8 *) skb->data); 16408c2ecf20Sopenharmony_ci 16418c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 16428c2ecf20Sopenharmony_ci 16438c2ecf20Sopenharmony_ci if (status) 16448c2ecf20Sopenharmony_ci return; 16458c2ecf20Sopenharmony_ci 16468c2ecf20Sopenharmony_ci sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADDR_RESOLV_ENABLE); 16478c2ecf20Sopenharmony_ci if (!sent) 16488c2ecf20Sopenharmony_ci return; 16498c2ecf20Sopenharmony_ci 16508c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 16518c2ecf20Sopenharmony_ci 16528c2ecf20Sopenharmony_ci if (*sent) 16538c2ecf20Sopenharmony_ci hci_dev_set_flag(hdev, HCI_LL_RPA_RESOLUTION); 16548c2ecf20Sopenharmony_ci else 16558c2ecf20Sopenharmony_ci hci_dev_clear_flag(hdev, HCI_LL_RPA_RESOLUTION); 16568c2ecf20Sopenharmony_ci 16578c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 16588c2ecf20Sopenharmony_ci} 16598c2ecf20Sopenharmony_ci 16608c2ecf20Sopenharmony_cistatic void hci_cc_le_read_max_data_len(struct hci_dev *hdev, 16618c2ecf20Sopenharmony_ci struct sk_buff *skb) 16628c2ecf20Sopenharmony_ci{ 16638c2ecf20Sopenharmony_ci struct hci_rp_le_read_max_data_len *rp = (void *) skb->data; 16648c2ecf20Sopenharmony_ci 16658c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 16668c2ecf20Sopenharmony_ci 16678c2ecf20Sopenharmony_ci if (rp->status) 16688c2ecf20Sopenharmony_ci return; 16698c2ecf20Sopenharmony_ci 16708c2ecf20Sopenharmony_ci hdev->le_max_tx_len = le16_to_cpu(rp->tx_len); 16718c2ecf20Sopenharmony_ci hdev->le_max_tx_time = le16_to_cpu(rp->tx_time); 16728c2ecf20Sopenharmony_ci hdev->le_max_rx_len = le16_to_cpu(rp->rx_len); 16738c2ecf20Sopenharmony_ci hdev->le_max_rx_time = le16_to_cpu(rp->rx_time); 16748c2ecf20Sopenharmony_ci} 16758c2ecf20Sopenharmony_ci 16768c2ecf20Sopenharmony_cistatic void hci_cc_write_le_host_supported(struct hci_dev *hdev, 16778c2ecf20Sopenharmony_ci struct sk_buff *skb) 16788c2ecf20Sopenharmony_ci{ 16798c2ecf20Sopenharmony_ci struct hci_cp_write_le_host_supported *sent; 16808c2ecf20Sopenharmony_ci __u8 status = *((__u8 *) skb->data); 16818c2ecf20Sopenharmony_ci 16828c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 16838c2ecf20Sopenharmony_ci 16848c2ecf20Sopenharmony_ci if (status) 16858c2ecf20Sopenharmony_ci return; 16868c2ecf20Sopenharmony_ci 16878c2ecf20Sopenharmony_ci sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED); 16888c2ecf20Sopenharmony_ci if (!sent) 16898c2ecf20Sopenharmony_ci return; 16908c2ecf20Sopenharmony_ci 16918c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 16928c2ecf20Sopenharmony_ci 16938c2ecf20Sopenharmony_ci if (sent->le) { 16948c2ecf20Sopenharmony_ci hdev->features[1][0] |= LMP_HOST_LE; 16958c2ecf20Sopenharmony_ci hci_dev_set_flag(hdev, HCI_LE_ENABLED); 16968c2ecf20Sopenharmony_ci } else { 16978c2ecf20Sopenharmony_ci hdev->features[1][0] &= ~LMP_HOST_LE; 16988c2ecf20Sopenharmony_ci hci_dev_clear_flag(hdev, HCI_LE_ENABLED); 16998c2ecf20Sopenharmony_ci hci_dev_clear_flag(hdev, HCI_ADVERTISING); 17008c2ecf20Sopenharmony_ci } 17018c2ecf20Sopenharmony_ci 17028c2ecf20Sopenharmony_ci if (sent->simul) 17038c2ecf20Sopenharmony_ci hdev->features[1][0] |= LMP_HOST_LE_BREDR; 17048c2ecf20Sopenharmony_ci else 17058c2ecf20Sopenharmony_ci hdev->features[1][0] &= ~LMP_HOST_LE_BREDR; 17068c2ecf20Sopenharmony_ci 17078c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 17088c2ecf20Sopenharmony_ci} 17098c2ecf20Sopenharmony_ci 17108c2ecf20Sopenharmony_cistatic void hci_cc_set_adv_param(struct hci_dev *hdev, struct sk_buff *skb) 17118c2ecf20Sopenharmony_ci{ 17128c2ecf20Sopenharmony_ci struct hci_cp_le_set_adv_param *cp; 17138c2ecf20Sopenharmony_ci u8 status = *((u8 *) skb->data); 17148c2ecf20Sopenharmony_ci 17158c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 17168c2ecf20Sopenharmony_ci 17178c2ecf20Sopenharmony_ci if (status) 17188c2ecf20Sopenharmony_ci return; 17198c2ecf20Sopenharmony_ci 17208c2ecf20Sopenharmony_ci cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_PARAM); 17218c2ecf20Sopenharmony_ci if (!cp) 17228c2ecf20Sopenharmony_ci return; 17238c2ecf20Sopenharmony_ci 17248c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 17258c2ecf20Sopenharmony_ci hdev->adv_addr_type = cp->own_address_type; 17268c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 17278c2ecf20Sopenharmony_ci} 17288c2ecf20Sopenharmony_ci 17298c2ecf20Sopenharmony_cistatic void hci_cc_set_ext_adv_param(struct hci_dev *hdev, struct sk_buff *skb) 17308c2ecf20Sopenharmony_ci{ 17318c2ecf20Sopenharmony_ci struct hci_rp_le_set_ext_adv_params *rp = (void *) skb->data; 17328c2ecf20Sopenharmony_ci struct hci_cp_le_set_ext_adv_params *cp; 17338c2ecf20Sopenharmony_ci struct adv_info *adv_instance; 17348c2ecf20Sopenharmony_ci 17358c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 17368c2ecf20Sopenharmony_ci 17378c2ecf20Sopenharmony_ci if (rp->status) 17388c2ecf20Sopenharmony_ci return; 17398c2ecf20Sopenharmony_ci 17408c2ecf20Sopenharmony_ci cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_ADV_PARAMS); 17418c2ecf20Sopenharmony_ci if (!cp) 17428c2ecf20Sopenharmony_ci return; 17438c2ecf20Sopenharmony_ci 17448c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 17458c2ecf20Sopenharmony_ci hdev->adv_addr_type = cp->own_addr_type; 17468c2ecf20Sopenharmony_ci if (!hdev->cur_adv_instance) { 17478c2ecf20Sopenharmony_ci /* Store in hdev for instance 0 */ 17488c2ecf20Sopenharmony_ci hdev->adv_tx_power = rp->tx_power; 17498c2ecf20Sopenharmony_ci } else { 17508c2ecf20Sopenharmony_ci adv_instance = hci_find_adv_instance(hdev, 17518c2ecf20Sopenharmony_ci hdev->cur_adv_instance); 17528c2ecf20Sopenharmony_ci if (adv_instance) 17538c2ecf20Sopenharmony_ci adv_instance->tx_power = rp->tx_power; 17548c2ecf20Sopenharmony_ci } 17558c2ecf20Sopenharmony_ci /* Update adv data as tx power is known now */ 17568c2ecf20Sopenharmony_ci hci_req_update_adv_data(hdev, hdev->cur_adv_instance); 17578c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 17588c2ecf20Sopenharmony_ci} 17598c2ecf20Sopenharmony_ci 17608c2ecf20Sopenharmony_cistatic void hci_cc_read_rssi(struct hci_dev *hdev, struct sk_buff *skb) 17618c2ecf20Sopenharmony_ci{ 17628c2ecf20Sopenharmony_ci struct hci_rp_read_rssi *rp = (void *) skb->data; 17638c2ecf20Sopenharmony_ci struct hci_conn *conn; 17648c2ecf20Sopenharmony_ci 17658c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 17668c2ecf20Sopenharmony_ci 17678c2ecf20Sopenharmony_ci if (rp->status) 17688c2ecf20Sopenharmony_ci return; 17698c2ecf20Sopenharmony_ci 17708c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 17718c2ecf20Sopenharmony_ci 17728c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 17738c2ecf20Sopenharmony_ci if (conn) 17748c2ecf20Sopenharmony_ci conn->rssi = rp->rssi; 17758c2ecf20Sopenharmony_ci 17768c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 17778c2ecf20Sopenharmony_ci} 17788c2ecf20Sopenharmony_ci 17798c2ecf20Sopenharmony_cistatic void hci_cc_read_tx_power(struct hci_dev *hdev, struct sk_buff *skb) 17808c2ecf20Sopenharmony_ci{ 17818c2ecf20Sopenharmony_ci struct hci_cp_read_tx_power *sent; 17828c2ecf20Sopenharmony_ci struct hci_rp_read_tx_power *rp = (void *) skb->data; 17838c2ecf20Sopenharmony_ci struct hci_conn *conn; 17848c2ecf20Sopenharmony_ci 17858c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 17868c2ecf20Sopenharmony_ci 17878c2ecf20Sopenharmony_ci if (rp->status) 17888c2ecf20Sopenharmony_ci return; 17898c2ecf20Sopenharmony_ci 17908c2ecf20Sopenharmony_ci sent = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER); 17918c2ecf20Sopenharmony_ci if (!sent) 17928c2ecf20Sopenharmony_ci return; 17938c2ecf20Sopenharmony_ci 17948c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 17958c2ecf20Sopenharmony_ci 17968c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 17978c2ecf20Sopenharmony_ci if (!conn) 17988c2ecf20Sopenharmony_ci goto unlock; 17998c2ecf20Sopenharmony_ci 18008c2ecf20Sopenharmony_ci switch (sent->type) { 18018c2ecf20Sopenharmony_ci case 0x00: 18028c2ecf20Sopenharmony_ci conn->tx_power = rp->tx_power; 18038c2ecf20Sopenharmony_ci break; 18048c2ecf20Sopenharmony_ci case 0x01: 18058c2ecf20Sopenharmony_ci conn->max_tx_power = rp->tx_power; 18068c2ecf20Sopenharmony_ci break; 18078c2ecf20Sopenharmony_ci } 18088c2ecf20Sopenharmony_ci 18098c2ecf20Sopenharmony_ciunlock: 18108c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 18118c2ecf20Sopenharmony_ci} 18128c2ecf20Sopenharmony_ci 18138c2ecf20Sopenharmony_cistatic void hci_cc_write_ssp_debug_mode(struct hci_dev *hdev, struct sk_buff *skb) 18148c2ecf20Sopenharmony_ci{ 18158c2ecf20Sopenharmony_ci u8 status = *((u8 *) skb->data); 18168c2ecf20Sopenharmony_ci u8 *mode; 18178c2ecf20Sopenharmony_ci 18188c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 18198c2ecf20Sopenharmony_ci 18208c2ecf20Sopenharmony_ci if (status) 18218c2ecf20Sopenharmony_ci return; 18228c2ecf20Sopenharmony_ci 18238c2ecf20Sopenharmony_ci mode = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE); 18248c2ecf20Sopenharmony_ci if (mode) 18258c2ecf20Sopenharmony_ci hdev->ssp_debug_mode = *mode; 18268c2ecf20Sopenharmony_ci} 18278c2ecf20Sopenharmony_ci 18288c2ecf20Sopenharmony_cistatic void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 18298c2ecf20Sopenharmony_ci{ 18308c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 18318c2ecf20Sopenharmony_ci 18328c2ecf20Sopenharmony_ci if (status) { 18338c2ecf20Sopenharmony_ci hci_conn_check_pending(hdev); 18348c2ecf20Sopenharmony_ci return; 18358c2ecf20Sopenharmony_ci } 18368c2ecf20Sopenharmony_ci 18378c2ecf20Sopenharmony_ci if (hci_sent_cmd_data(hdev, HCI_OP_INQUIRY)) 18388c2ecf20Sopenharmony_ci set_bit(HCI_INQUIRY, &hdev->flags); 18398c2ecf20Sopenharmony_ci} 18408c2ecf20Sopenharmony_ci 18418c2ecf20Sopenharmony_cistatic void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 18428c2ecf20Sopenharmony_ci{ 18438c2ecf20Sopenharmony_ci struct hci_cp_create_conn *cp; 18448c2ecf20Sopenharmony_ci struct hci_conn *conn; 18458c2ecf20Sopenharmony_ci 18468c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 18478c2ecf20Sopenharmony_ci 18488c2ecf20Sopenharmony_ci cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 18498c2ecf20Sopenharmony_ci if (!cp) 18508c2ecf20Sopenharmony_ci return; 18518c2ecf20Sopenharmony_ci 18528c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 18538c2ecf20Sopenharmony_ci 18548c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 18558c2ecf20Sopenharmony_ci 18568c2ecf20Sopenharmony_ci BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn); 18578c2ecf20Sopenharmony_ci 18588c2ecf20Sopenharmony_ci if (status) { 18598c2ecf20Sopenharmony_ci if (conn && conn->state == BT_CONNECT) { 18608c2ecf20Sopenharmony_ci if (status != 0x0c || conn->attempt > 2) { 18618c2ecf20Sopenharmony_ci conn->state = BT_CLOSED; 18628c2ecf20Sopenharmony_ci hci_connect_cfm(conn, status); 18638c2ecf20Sopenharmony_ci hci_conn_del(conn); 18648c2ecf20Sopenharmony_ci } else 18658c2ecf20Sopenharmony_ci conn->state = BT_CONNECT2; 18668c2ecf20Sopenharmony_ci } 18678c2ecf20Sopenharmony_ci } else { 18688c2ecf20Sopenharmony_ci if (!conn) { 18698c2ecf20Sopenharmony_ci conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr, 18708c2ecf20Sopenharmony_ci HCI_ROLE_MASTER); 18718c2ecf20Sopenharmony_ci if (!conn) 18728c2ecf20Sopenharmony_ci bt_dev_err(hdev, "no memory for new connection"); 18738c2ecf20Sopenharmony_ci } 18748c2ecf20Sopenharmony_ci } 18758c2ecf20Sopenharmony_ci 18768c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 18778c2ecf20Sopenharmony_ci} 18788c2ecf20Sopenharmony_ci 18798c2ecf20Sopenharmony_cistatic void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 18808c2ecf20Sopenharmony_ci{ 18818c2ecf20Sopenharmony_ci struct hci_cp_add_sco *cp; 18828c2ecf20Sopenharmony_ci struct hci_conn *acl, *sco; 18838c2ecf20Sopenharmony_ci __u16 handle; 18848c2ecf20Sopenharmony_ci 18858c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 18868c2ecf20Sopenharmony_ci 18878c2ecf20Sopenharmony_ci if (!status) 18888c2ecf20Sopenharmony_ci return; 18898c2ecf20Sopenharmony_ci 18908c2ecf20Sopenharmony_ci cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 18918c2ecf20Sopenharmony_ci if (!cp) 18928c2ecf20Sopenharmony_ci return; 18938c2ecf20Sopenharmony_ci 18948c2ecf20Sopenharmony_ci handle = __le16_to_cpu(cp->handle); 18958c2ecf20Sopenharmony_ci 18968c2ecf20Sopenharmony_ci BT_DBG("%s handle 0x%4.4x", hdev->name, handle); 18978c2ecf20Sopenharmony_ci 18988c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 18998c2ecf20Sopenharmony_ci 19008c2ecf20Sopenharmony_ci acl = hci_conn_hash_lookup_handle(hdev, handle); 19018c2ecf20Sopenharmony_ci if (acl) { 19028c2ecf20Sopenharmony_ci sco = acl->link; 19038c2ecf20Sopenharmony_ci if (sco) { 19048c2ecf20Sopenharmony_ci sco->state = BT_CLOSED; 19058c2ecf20Sopenharmony_ci 19068c2ecf20Sopenharmony_ci hci_connect_cfm(sco, status); 19078c2ecf20Sopenharmony_ci hci_conn_del(sco); 19088c2ecf20Sopenharmony_ci } 19098c2ecf20Sopenharmony_ci } 19108c2ecf20Sopenharmony_ci 19118c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 19128c2ecf20Sopenharmony_ci} 19138c2ecf20Sopenharmony_ci 19148c2ecf20Sopenharmony_cistatic void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 19158c2ecf20Sopenharmony_ci{ 19168c2ecf20Sopenharmony_ci struct hci_cp_auth_requested *cp; 19178c2ecf20Sopenharmony_ci struct hci_conn *conn; 19188c2ecf20Sopenharmony_ci 19198c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 19208c2ecf20Sopenharmony_ci 19218c2ecf20Sopenharmony_ci if (!status) 19228c2ecf20Sopenharmony_ci return; 19238c2ecf20Sopenharmony_ci 19248c2ecf20Sopenharmony_ci cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 19258c2ecf20Sopenharmony_ci if (!cp) 19268c2ecf20Sopenharmony_ci return; 19278c2ecf20Sopenharmony_ci 19288c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 19298c2ecf20Sopenharmony_ci 19308c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 19318c2ecf20Sopenharmony_ci if (conn) { 19328c2ecf20Sopenharmony_ci if (conn->state == BT_CONFIG) { 19338c2ecf20Sopenharmony_ci hci_connect_cfm(conn, status); 19348c2ecf20Sopenharmony_ci hci_conn_drop(conn); 19358c2ecf20Sopenharmony_ci } 19368c2ecf20Sopenharmony_ci } 19378c2ecf20Sopenharmony_ci 19388c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 19398c2ecf20Sopenharmony_ci} 19408c2ecf20Sopenharmony_ci 19418c2ecf20Sopenharmony_cistatic void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 19428c2ecf20Sopenharmony_ci{ 19438c2ecf20Sopenharmony_ci struct hci_cp_set_conn_encrypt *cp; 19448c2ecf20Sopenharmony_ci struct hci_conn *conn; 19458c2ecf20Sopenharmony_ci 19468c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 19478c2ecf20Sopenharmony_ci 19488c2ecf20Sopenharmony_ci if (!status) 19498c2ecf20Sopenharmony_ci return; 19508c2ecf20Sopenharmony_ci 19518c2ecf20Sopenharmony_ci cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 19528c2ecf20Sopenharmony_ci if (!cp) 19538c2ecf20Sopenharmony_ci return; 19548c2ecf20Sopenharmony_ci 19558c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 19568c2ecf20Sopenharmony_ci 19578c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 19588c2ecf20Sopenharmony_ci if (conn) { 19598c2ecf20Sopenharmony_ci if (conn->state == BT_CONFIG) { 19608c2ecf20Sopenharmony_ci hci_connect_cfm(conn, status); 19618c2ecf20Sopenharmony_ci hci_conn_drop(conn); 19628c2ecf20Sopenharmony_ci } 19638c2ecf20Sopenharmony_ci } 19648c2ecf20Sopenharmony_ci 19658c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 19668c2ecf20Sopenharmony_ci} 19678c2ecf20Sopenharmony_ci 19688c2ecf20Sopenharmony_cistatic int hci_outgoing_auth_needed(struct hci_dev *hdev, 19698c2ecf20Sopenharmony_ci struct hci_conn *conn) 19708c2ecf20Sopenharmony_ci{ 19718c2ecf20Sopenharmony_ci if (conn->state != BT_CONFIG || !conn->out) 19728c2ecf20Sopenharmony_ci return 0; 19738c2ecf20Sopenharmony_ci 19748c2ecf20Sopenharmony_ci if (conn->pending_sec_level == BT_SECURITY_SDP) 19758c2ecf20Sopenharmony_ci return 0; 19768c2ecf20Sopenharmony_ci 19778c2ecf20Sopenharmony_ci /* Only request authentication for SSP connections or non-SSP 19788c2ecf20Sopenharmony_ci * devices with sec_level MEDIUM or HIGH or if MITM protection 19798c2ecf20Sopenharmony_ci * is requested. 19808c2ecf20Sopenharmony_ci */ 19818c2ecf20Sopenharmony_ci if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) && 19828c2ecf20Sopenharmony_ci conn->pending_sec_level != BT_SECURITY_FIPS && 19838c2ecf20Sopenharmony_ci conn->pending_sec_level != BT_SECURITY_HIGH && 19848c2ecf20Sopenharmony_ci conn->pending_sec_level != BT_SECURITY_MEDIUM) 19858c2ecf20Sopenharmony_ci return 0; 19868c2ecf20Sopenharmony_ci 19878c2ecf20Sopenharmony_ci return 1; 19888c2ecf20Sopenharmony_ci} 19898c2ecf20Sopenharmony_ci 19908c2ecf20Sopenharmony_cistatic int hci_resolve_name(struct hci_dev *hdev, 19918c2ecf20Sopenharmony_ci struct inquiry_entry *e) 19928c2ecf20Sopenharmony_ci{ 19938c2ecf20Sopenharmony_ci struct hci_cp_remote_name_req cp; 19948c2ecf20Sopenharmony_ci 19958c2ecf20Sopenharmony_ci memset(&cp, 0, sizeof(cp)); 19968c2ecf20Sopenharmony_ci 19978c2ecf20Sopenharmony_ci bacpy(&cp.bdaddr, &e->data.bdaddr); 19988c2ecf20Sopenharmony_ci cp.pscan_rep_mode = e->data.pscan_rep_mode; 19998c2ecf20Sopenharmony_ci cp.pscan_mode = e->data.pscan_mode; 20008c2ecf20Sopenharmony_ci cp.clock_offset = e->data.clock_offset; 20018c2ecf20Sopenharmony_ci 20028c2ecf20Sopenharmony_ci return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 20038c2ecf20Sopenharmony_ci} 20048c2ecf20Sopenharmony_ci 20058c2ecf20Sopenharmony_cistatic bool hci_resolve_next_name(struct hci_dev *hdev) 20068c2ecf20Sopenharmony_ci{ 20078c2ecf20Sopenharmony_ci struct discovery_state *discov = &hdev->discovery; 20088c2ecf20Sopenharmony_ci struct inquiry_entry *e; 20098c2ecf20Sopenharmony_ci 20108c2ecf20Sopenharmony_ci if (list_empty(&discov->resolve)) 20118c2ecf20Sopenharmony_ci return false; 20128c2ecf20Sopenharmony_ci 20138c2ecf20Sopenharmony_ci e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 20148c2ecf20Sopenharmony_ci if (!e) 20158c2ecf20Sopenharmony_ci return false; 20168c2ecf20Sopenharmony_ci 20178c2ecf20Sopenharmony_ci if (hci_resolve_name(hdev, e) == 0) { 20188c2ecf20Sopenharmony_ci e->name_state = NAME_PENDING; 20198c2ecf20Sopenharmony_ci return true; 20208c2ecf20Sopenharmony_ci } 20218c2ecf20Sopenharmony_ci 20228c2ecf20Sopenharmony_ci return false; 20238c2ecf20Sopenharmony_ci} 20248c2ecf20Sopenharmony_ci 20258c2ecf20Sopenharmony_cistatic void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn, 20268c2ecf20Sopenharmony_ci bdaddr_t *bdaddr, u8 *name, u8 name_len) 20278c2ecf20Sopenharmony_ci{ 20288c2ecf20Sopenharmony_ci struct discovery_state *discov = &hdev->discovery; 20298c2ecf20Sopenharmony_ci struct inquiry_entry *e; 20308c2ecf20Sopenharmony_ci 20318c2ecf20Sopenharmony_ci /* Update the mgmt connected state if necessary. Be careful with 20328c2ecf20Sopenharmony_ci * conn objects that exist but are not (yet) connected however. 20338c2ecf20Sopenharmony_ci * Only those in BT_CONFIG or BT_CONNECTED states can be 20348c2ecf20Sopenharmony_ci * considered connected. 20358c2ecf20Sopenharmony_ci */ 20368c2ecf20Sopenharmony_ci if (conn && 20378c2ecf20Sopenharmony_ci (conn->state == BT_CONFIG || conn->state == BT_CONNECTED) && 20388c2ecf20Sopenharmony_ci !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 20398c2ecf20Sopenharmony_ci mgmt_device_connected(hdev, conn, 0, name, name_len); 20408c2ecf20Sopenharmony_ci 20418c2ecf20Sopenharmony_ci if (discov->state == DISCOVERY_STOPPED) 20428c2ecf20Sopenharmony_ci return; 20438c2ecf20Sopenharmony_ci 20448c2ecf20Sopenharmony_ci if (discov->state == DISCOVERY_STOPPING) 20458c2ecf20Sopenharmony_ci goto discov_complete; 20468c2ecf20Sopenharmony_ci 20478c2ecf20Sopenharmony_ci if (discov->state != DISCOVERY_RESOLVING) 20488c2ecf20Sopenharmony_ci return; 20498c2ecf20Sopenharmony_ci 20508c2ecf20Sopenharmony_ci e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING); 20518c2ecf20Sopenharmony_ci /* If the device was not found in a list of found devices names of which 20528c2ecf20Sopenharmony_ci * are pending. there is no need to continue resolving a next name as it 20538c2ecf20Sopenharmony_ci * will be done upon receiving another Remote Name Request Complete 20548c2ecf20Sopenharmony_ci * Event */ 20558c2ecf20Sopenharmony_ci if (!e) 20568c2ecf20Sopenharmony_ci return; 20578c2ecf20Sopenharmony_ci 20588c2ecf20Sopenharmony_ci list_del(&e->list); 20598c2ecf20Sopenharmony_ci if (name) { 20608c2ecf20Sopenharmony_ci e->name_state = NAME_KNOWN; 20618c2ecf20Sopenharmony_ci mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, 20628c2ecf20Sopenharmony_ci e->data.rssi, name, name_len); 20638c2ecf20Sopenharmony_ci } else { 20648c2ecf20Sopenharmony_ci e->name_state = NAME_NOT_KNOWN; 20658c2ecf20Sopenharmony_ci } 20668c2ecf20Sopenharmony_ci 20678c2ecf20Sopenharmony_ci if (hci_resolve_next_name(hdev)) 20688c2ecf20Sopenharmony_ci return; 20698c2ecf20Sopenharmony_ci 20708c2ecf20Sopenharmony_cidiscov_complete: 20718c2ecf20Sopenharmony_ci hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 20728c2ecf20Sopenharmony_ci} 20738c2ecf20Sopenharmony_ci 20748c2ecf20Sopenharmony_cistatic void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 20758c2ecf20Sopenharmony_ci{ 20768c2ecf20Sopenharmony_ci struct hci_cp_remote_name_req *cp; 20778c2ecf20Sopenharmony_ci struct hci_conn *conn; 20788c2ecf20Sopenharmony_ci 20798c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 20808c2ecf20Sopenharmony_ci 20818c2ecf20Sopenharmony_ci /* If successful wait for the name req complete event before 20828c2ecf20Sopenharmony_ci * checking for the need to do authentication */ 20838c2ecf20Sopenharmony_ci if (!status) 20848c2ecf20Sopenharmony_ci return; 20858c2ecf20Sopenharmony_ci 20868c2ecf20Sopenharmony_ci cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); 20878c2ecf20Sopenharmony_ci if (!cp) 20888c2ecf20Sopenharmony_ci return; 20898c2ecf20Sopenharmony_ci 20908c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 20918c2ecf20Sopenharmony_ci 20928c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 20938c2ecf20Sopenharmony_ci 20948c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_MGMT)) 20958c2ecf20Sopenharmony_ci hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0); 20968c2ecf20Sopenharmony_ci 20978c2ecf20Sopenharmony_ci if (!conn) 20988c2ecf20Sopenharmony_ci goto unlock; 20998c2ecf20Sopenharmony_ci 21008c2ecf20Sopenharmony_ci if (!hci_outgoing_auth_needed(hdev, conn)) 21018c2ecf20Sopenharmony_ci goto unlock; 21028c2ecf20Sopenharmony_ci 21038c2ecf20Sopenharmony_ci if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 21048c2ecf20Sopenharmony_ci struct hci_cp_auth_requested auth_cp; 21058c2ecf20Sopenharmony_ci 21068c2ecf20Sopenharmony_ci set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags); 21078c2ecf20Sopenharmony_ci 21088c2ecf20Sopenharmony_ci auth_cp.handle = __cpu_to_le16(conn->handle); 21098c2ecf20Sopenharmony_ci hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, 21108c2ecf20Sopenharmony_ci sizeof(auth_cp), &auth_cp); 21118c2ecf20Sopenharmony_ci } 21128c2ecf20Sopenharmony_ci 21138c2ecf20Sopenharmony_ciunlock: 21148c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 21158c2ecf20Sopenharmony_ci} 21168c2ecf20Sopenharmony_ci 21178c2ecf20Sopenharmony_cistatic void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 21188c2ecf20Sopenharmony_ci{ 21198c2ecf20Sopenharmony_ci struct hci_cp_read_remote_features *cp; 21208c2ecf20Sopenharmony_ci struct hci_conn *conn; 21218c2ecf20Sopenharmony_ci 21228c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 21238c2ecf20Sopenharmony_ci 21248c2ecf20Sopenharmony_ci if (!status) 21258c2ecf20Sopenharmony_ci return; 21268c2ecf20Sopenharmony_ci 21278c2ecf20Sopenharmony_ci cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 21288c2ecf20Sopenharmony_ci if (!cp) 21298c2ecf20Sopenharmony_ci return; 21308c2ecf20Sopenharmony_ci 21318c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 21328c2ecf20Sopenharmony_ci 21338c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 21348c2ecf20Sopenharmony_ci if (conn) { 21358c2ecf20Sopenharmony_ci if (conn->state == BT_CONFIG) { 21368c2ecf20Sopenharmony_ci hci_connect_cfm(conn, status); 21378c2ecf20Sopenharmony_ci hci_conn_drop(conn); 21388c2ecf20Sopenharmony_ci } 21398c2ecf20Sopenharmony_ci } 21408c2ecf20Sopenharmony_ci 21418c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 21428c2ecf20Sopenharmony_ci} 21438c2ecf20Sopenharmony_ci 21448c2ecf20Sopenharmony_cistatic void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 21458c2ecf20Sopenharmony_ci{ 21468c2ecf20Sopenharmony_ci struct hci_cp_read_remote_ext_features *cp; 21478c2ecf20Sopenharmony_ci struct hci_conn *conn; 21488c2ecf20Sopenharmony_ci 21498c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 21508c2ecf20Sopenharmony_ci 21518c2ecf20Sopenharmony_ci if (!status) 21528c2ecf20Sopenharmony_ci return; 21538c2ecf20Sopenharmony_ci 21548c2ecf20Sopenharmony_ci cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 21558c2ecf20Sopenharmony_ci if (!cp) 21568c2ecf20Sopenharmony_ci return; 21578c2ecf20Sopenharmony_ci 21588c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 21598c2ecf20Sopenharmony_ci 21608c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 21618c2ecf20Sopenharmony_ci if (conn) { 21628c2ecf20Sopenharmony_ci if (conn->state == BT_CONFIG) { 21638c2ecf20Sopenharmony_ci hci_connect_cfm(conn, status); 21648c2ecf20Sopenharmony_ci hci_conn_drop(conn); 21658c2ecf20Sopenharmony_ci } 21668c2ecf20Sopenharmony_ci } 21678c2ecf20Sopenharmony_ci 21688c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 21698c2ecf20Sopenharmony_ci} 21708c2ecf20Sopenharmony_ci 21718c2ecf20Sopenharmony_cistatic void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 21728c2ecf20Sopenharmony_ci{ 21738c2ecf20Sopenharmony_ci struct hci_cp_setup_sync_conn *cp; 21748c2ecf20Sopenharmony_ci struct hci_conn *acl, *sco; 21758c2ecf20Sopenharmony_ci __u16 handle; 21768c2ecf20Sopenharmony_ci 21778c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 21788c2ecf20Sopenharmony_ci 21798c2ecf20Sopenharmony_ci if (!status) 21808c2ecf20Sopenharmony_ci return; 21818c2ecf20Sopenharmony_ci 21828c2ecf20Sopenharmony_ci cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 21838c2ecf20Sopenharmony_ci if (!cp) 21848c2ecf20Sopenharmony_ci return; 21858c2ecf20Sopenharmony_ci 21868c2ecf20Sopenharmony_ci handle = __le16_to_cpu(cp->handle); 21878c2ecf20Sopenharmony_ci 21888c2ecf20Sopenharmony_ci BT_DBG("%s handle 0x%4.4x", hdev->name, handle); 21898c2ecf20Sopenharmony_ci 21908c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 21918c2ecf20Sopenharmony_ci 21928c2ecf20Sopenharmony_ci acl = hci_conn_hash_lookup_handle(hdev, handle); 21938c2ecf20Sopenharmony_ci if (acl) { 21948c2ecf20Sopenharmony_ci sco = acl->link; 21958c2ecf20Sopenharmony_ci if (sco) { 21968c2ecf20Sopenharmony_ci sco->state = BT_CLOSED; 21978c2ecf20Sopenharmony_ci 21988c2ecf20Sopenharmony_ci hci_connect_cfm(sco, status); 21998c2ecf20Sopenharmony_ci hci_conn_del(sco); 22008c2ecf20Sopenharmony_ci } 22018c2ecf20Sopenharmony_ci } 22028c2ecf20Sopenharmony_ci 22038c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 22048c2ecf20Sopenharmony_ci} 22058c2ecf20Sopenharmony_ci 22068c2ecf20Sopenharmony_cistatic void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 22078c2ecf20Sopenharmony_ci{ 22088c2ecf20Sopenharmony_ci struct hci_cp_sniff_mode *cp; 22098c2ecf20Sopenharmony_ci struct hci_conn *conn; 22108c2ecf20Sopenharmony_ci 22118c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 22128c2ecf20Sopenharmony_ci 22138c2ecf20Sopenharmony_ci if (!status) 22148c2ecf20Sopenharmony_ci return; 22158c2ecf20Sopenharmony_ci 22168c2ecf20Sopenharmony_ci cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 22178c2ecf20Sopenharmony_ci if (!cp) 22188c2ecf20Sopenharmony_ci return; 22198c2ecf20Sopenharmony_ci 22208c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 22218c2ecf20Sopenharmony_ci 22228c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 22238c2ecf20Sopenharmony_ci if (conn) { 22248c2ecf20Sopenharmony_ci clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 22258c2ecf20Sopenharmony_ci 22268c2ecf20Sopenharmony_ci if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 22278c2ecf20Sopenharmony_ci hci_sco_setup(conn, status); 22288c2ecf20Sopenharmony_ci } 22298c2ecf20Sopenharmony_ci 22308c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 22318c2ecf20Sopenharmony_ci} 22328c2ecf20Sopenharmony_ci 22338c2ecf20Sopenharmony_cistatic void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 22348c2ecf20Sopenharmony_ci{ 22358c2ecf20Sopenharmony_ci struct hci_cp_exit_sniff_mode *cp; 22368c2ecf20Sopenharmony_ci struct hci_conn *conn; 22378c2ecf20Sopenharmony_ci 22388c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 22398c2ecf20Sopenharmony_ci 22408c2ecf20Sopenharmony_ci if (!status) 22418c2ecf20Sopenharmony_ci return; 22428c2ecf20Sopenharmony_ci 22438c2ecf20Sopenharmony_ci cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 22448c2ecf20Sopenharmony_ci if (!cp) 22458c2ecf20Sopenharmony_ci return; 22468c2ecf20Sopenharmony_ci 22478c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 22488c2ecf20Sopenharmony_ci 22498c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 22508c2ecf20Sopenharmony_ci if (conn) { 22518c2ecf20Sopenharmony_ci clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 22528c2ecf20Sopenharmony_ci 22538c2ecf20Sopenharmony_ci if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 22548c2ecf20Sopenharmony_ci hci_sco_setup(conn, status); 22558c2ecf20Sopenharmony_ci } 22568c2ecf20Sopenharmony_ci 22578c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 22588c2ecf20Sopenharmony_ci} 22598c2ecf20Sopenharmony_ci 22608c2ecf20Sopenharmony_cistatic void hci_cs_disconnect(struct hci_dev *hdev, u8 status) 22618c2ecf20Sopenharmony_ci{ 22628c2ecf20Sopenharmony_ci struct hci_cp_disconnect *cp; 22638c2ecf20Sopenharmony_ci struct hci_conn *conn; 22648c2ecf20Sopenharmony_ci 22658c2ecf20Sopenharmony_ci if (!status) 22668c2ecf20Sopenharmony_ci return; 22678c2ecf20Sopenharmony_ci 22688c2ecf20Sopenharmony_ci cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT); 22698c2ecf20Sopenharmony_ci if (!cp) 22708c2ecf20Sopenharmony_ci return; 22718c2ecf20Sopenharmony_ci 22728c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 22738c2ecf20Sopenharmony_ci 22748c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 22758c2ecf20Sopenharmony_ci if (conn) { 22768c2ecf20Sopenharmony_ci u8 type = conn->type; 22778c2ecf20Sopenharmony_ci 22788c2ecf20Sopenharmony_ci mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 22798c2ecf20Sopenharmony_ci conn->dst_type, status); 22808c2ecf20Sopenharmony_ci 22818c2ecf20Sopenharmony_ci /* If the disconnection failed for any reason, the upper layer 22828c2ecf20Sopenharmony_ci * does not retry to disconnect in current implementation. 22838c2ecf20Sopenharmony_ci * Hence, we need to do some basic cleanup here and re-enable 22848c2ecf20Sopenharmony_ci * advertising if necessary. 22858c2ecf20Sopenharmony_ci */ 22868c2ecf20Sopenharmony_ci hci_conn_del(conn); 22878c2ecf20Sopenharmony_ci if (type == LE_LINK) 22888c2ecf20Sopenharmony_ci hci_req_reenable_advertising(hdev); 22898c2ecf20Sopenharmony_ci } 22908c2ecf20Sopenharmony_ci 22918c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 22928c2ecf20Sopenharmony_ci} 22938c2ecf20Sopenharmony_ci 22948c2ecf20Sopenharmony_cistatic void cs_le_create_conn(struct hci_dev *hdev, bdaddr_t *peer_addr, 22958c2ecf20Sopenharmony_ci u8 peer_addr_type, u8 own_address_type, 22968c2ecf20Sopenharmony_ci u8 filter_policy) 22978c2ecf20Sopenharmony_ci{ 22988c2ecf20Sopenharmony_ci struct hci_conn *conn; 22998c2ecf20Sopenharmony_ci 23008c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_le(hdev, peer_addr, 23018c2ecf20Sopenharmony_ci peer_addr_type); 23028c2ecf20Sopenharmony_ci if (!conn) 23038c2ecf20Sopenharmony_ci return; 23048c2ecf20Sopenharmony_ci 23058c2ecf20Sopenharmony_ci /* When using controller based address resolution, then the new 23068c2ecf20Sopenharmony_ci * address types 0x02 and 0x03 are used. These types need to be 23078c2ecf20Sopenharmony_ci * converted back into either public address or random address type 23088c2ecf20Sopenharmony_ci */ 23098c2ecf20Sopenharmony_ci if (use_ll_privacy(hdev) && 23108c2ecf20Sopenharmony_ci hci_dev_test_flag(hdev, HCI_LL_RPA_RESOLUTION)) { 23118c2ecf20Sopenharmony_ci switch (own_address_type) { 23128c2ecf20Sopenharmony_ci case ADDR_LE_DEV_PUBLIC_RESOLVED: 23138c2ecf20Sopenharmony_ci own_address_type = ADDR_LE_DEV_PUBLIC; 23148c2ecf20Sopenharmony_ci break; 23158c2ecf20Sopenharmony_ci case ADDR_LE_DEV_RANDOM_RESOLVED: 23168c2ecf20Sopenharmony_ci own_address_type = ADDR_LE_DEV_RANDOM; 23178c2ecf20Sopenharmony_ci break; 23188c2ecf20Sopenharmony_ci } 23198c2ecf20Sopenharmony_ci } 23208c2ecf20Sopenharmony_ci 23218c2ecf20Sopenharmony_ci /* Store the initiator and responder address information which 23228c2ecf20Sopenharmony_ci * is needed for SMP. These values will not change during the 23238c2ecf20Sopenharmony_ci * lifetime of the connection. 23248c2ecf20Sopenharmony_ci */ 23258c2ecf20Sopenharmony_ci conn->init_addr_type = own_address_type; 23268c2ecf20Sopenharmony_ci if (own_address_type == ADDR_LE_DEV_RANDOM) 23278c2ecf20Sopenharmony_ci bacpy(&conn->init_addr, &hdev->random_addr); 23288c2ecf20Sopenharmony_ci else 23298c2ecf20Sopenharmony_ci bacpy(&conn->init_addr, &hdev->bdaddr); 23308c2ecf20Sopenharmony_ci 23318c2ecf20Sopenharmony_ci conn->resp_addr_type = peer_addr_type; 23328c2ecf20Sopenharmony_ci bacpy(&conn->resp_addr, peer_addr); 23338c2ecf20Sopenharmony_ci 23348c2ecf20Sopenharmony_ci /* We don't want the connection attempt to stick around 23358c2ecf20Sopenharmony_ci * indefinitely since LE doesn't have a page timeout concept 23368c2ecf20Sopenharmony_ci * like BR/EDR. Set a timer for any connection that doesn't use 23378c2ecf20Sopenharmony_ci * the accept list for connecting. 23388c2ecf20Sopenharmony_ci */ 23398c2ecf20Sopenharmony_ci if (filter_policy == HCI_LE_USE_PEER_ADDR) 23408c2ecf20Sopenharmony_ci queue_delayed_work(conn->hdev->workqueue, 23418c2ecf20Sopenharmony_ci &conn->le_conn_timeout, 23428c2ecf20Sopenharmony_ci conn->conn_timeout); 23438c2ecf20Sopenharmony_ci} 23448c2ecf20Sopenharmony_ci 23458c2ecf20Sopenharmony_cistatic void hci_cs_le_create_conn(struct hci_dev *hdev, u8 status) 23468c2ecf20Sopenharmony_ci{ 23478c2ecf20Sopenharmony_ci struct hci_cp_le_create_conn *cp; 23488c2ecf20Sopenharmony_ci 23498c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 23508c2ecf20Sopenharmony_ci 23518c2ecf20Sopenharmony_ci /* All connection failure handling is taken care of by the 23528c2ecf20Sopenharmony_ci * hci_le_conn_failed function which is triggered by the HCI 23538c2ecf20Sopenharmony_ci * request completion callbacks used for connecting. 23548c2ecf20Sopenharmony_ci */ 23558c2ecf20Sopenharmony_ci if (status) 23568c2ecf20Sopenharmony_ci return; 23578c2ecf20Sopenharmony_ci 23588c2ecf20Sopenharmony_ci cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN); 23598c2ecf20Sopenharmony_ci if (!cp) 23608c2ecf20Sopenharmony_ci return; 23618c2ecf20Sopenharmony_ci 23628c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 23638c2ecf20Sopenharmony_ci 23648c2ecf20Sopenharmony_ci cs_le_create_conn(hdev, &cp->peer_addr, cp->peer_addr_type, 23658c2ecf20Sopenharmony_ci cp->own_address_type, cp->filter_policy); 23668c2ecf20Sopenharmony_ci 23678c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 23688c2ecf20Sopenharmony_ci} 23698c2ecf20Sopenharmony_ci 23708c2ecf20Sopenharmony_cistatic void hci_cs_le_ext_create_conn(struct hci_dev *hdev, u8 status) 23718c2ecf20Sopenharmony_ci{ 23728c2ecf20Sopenharmony_ci struct hci_cp_le_ext_create_conn *cp; 23738c2ecf20Sopenharmony_ci 23748c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 23758c2ecf20Sopenharmony_ci 23768c2ecf20Sopenharmony_ci /* All connection failure handling is taken care of by the 23778c2ecf20Sopenharmony_ci * hci_le_conn_failed function which is triggered by the HCI 23788c2ecf20Sopenharmony_ci * request completion callbacks used for connecting. 23798c2ecf20Sopenharmony_ci */ 23808c2ecf20Sopenharmony_ci if (status) 23818c2ecf20Sopenharmony_ci return; 23828c2ecf20Sopenharmony_ci 23838c2ecf20Sopenharmony_ci cp = hci_sent_cmd_data(hdev, HCI_OP_LE_EXT_CREATE_CONN); 23848c2ecf20Sopenharmony_ci if (!cp) 23858c2ecf20Sopenharmony_ci return; 23868c2ecf20Sopenharmony_ci 23878c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 23888c2ecf20Sopenharmony_ci 23898c2ecf20Sopenharmony_ci cs_le_create_conn(hdev, &cp->peer_addr, cp->peer_addr_type, 23908c2ecf20Sopenharmony_ci cp->own_addr_type, cp->filter_policy); 23918c2ecf20Sopenharmony_ci 23928c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 23938c2ecf20Sopenharmony_ci} 23948c2ecf20Sopenharmony_ci 23958c2ecf20Sopenharmony_cistatic void hci_cs_le_read_remote_features(struct hci_dev *hdev, u8 status) 23968c2ecf20Sopenharmony_ci{ 23978c2ecf20Sopenharmony_ci struct hci_cp_le_read_remote_features *cp; 23988c2ecf20Sopenharmony_ci struct hci_conn *conn; 23998c2ecf20Sopenharmony_ci 24008c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 24018c2ecf20Sopenharmony_ci 24028c2ecf20Sopenharmony_ci if (!status) 24038c2ecf20Sopenharmony_ci return; 24048c2ecf20Sopenharmony_ci 24058c2ecf20Sopenharmony_ci cp = hci_sent_cmd_data(hdev, HCI_OP_LE_READ_REMOTE_FEATURES); 24068c2ecf20Sopenharmony_ci if (!cp) 24078c2ecf20Sopenharmony_ci return; 24088c2ecf20Sopenharmony_ci 24098c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 24108c2ecf20Sopenharmony_ci 24118c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 24128c2ecf20Sopenharmony_ci if (conn) { 24138c2ecf20Sopenharmony_ci if (conn->state == BT_CONFIG) { 24148c2ecf20Sopenharmony_ci hci_connect_cfm(conn, status); 24158c2ecf20Sopenharmony_ci hci_conn_drop(conn); 24168c2ecf20Sopenharmony_ci } 24178c2ecf20Sopenharmony_ci } 24188c2ecf20Sopenharmony_ci 24198c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 24208c2ecf20Sopenharmony_ci} 24218c2ecf20Sopenharmony_ci 24228c2ecf20Sopenharmony_cistatic void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) 24238c2ecf20Sopenharmony_ci{ 24248c2ecf20Sopenharmony_ci struct hci_cp_le_start_enc *cp; 24258c2ecf20Sopenharmony_ci struct hci_conn *conn; 24268c2ecf20Sopenharmony_ci 24278c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 24288c2ecf20Sopenharmony_ci 24298c2ecf20Sopenharmony_ci if (!status) 24308c2ecf20Sopenharmony_ci return; 24318c2ecf20Sopenharmony_ci 24328c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 24338c2ecf20Sopenharmony_ci 24348c2ecf20Sopenharmony_ci cp = hci_sent_cmd_data(hdev, HCI_OP_LE_START_ENC); 24358c2ecf20Sopenharmony_ci if (!cp) 24368c2ecf20Sopenharmony_ci goto unlock; 24378c2ecf20Sopenharmony_ci 24388c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 24398c2ecf20Sopenharmony_ci if (!conn) 24408c2ecf20Sopenharmony_ci goto unlock; 24418c2ecf20Sopenharmony_ci 24428c2ecf20Sopenharmony_ci if (conn->state != BT_CONNECTED) 24438c2ecf20Sopenharmony_ci goto unlock; 24448c2ecf20Sopenharmony_ci 24458c2ecf20Sopenharmony_ci hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); 24468c2ecf20Sopenharmony_ci hci_conn_drop(conn); 24478c2ecf20Sopenharmony_ci 24488c2ecf20Sopenharmony_ciunlock: 24498c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 24508c2ecf20Sopenharmony_ci} 24518c2ecf20Sopenharmony_ci 24528c2ecf20Sopenharmony_cistatic void hci_cs_switch_role(struct hci_dev *hdev, u8 status) 24538c2ecf20Sopenharmony_ci{ 24548c2ecf20Sopenharmony_ci struct hci_cp_switch_role *cp; 24558c2ecf20Sopenharmony_ci struct hci_conn *conn; 24568c2ecf20Sopenharmony_ci 24578c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 24588c2ecf20Sopenharmony_ci 24598c2ecf20Sopenharmony_ci if (!status) 24608c2ecf20Sopenharmony_ci return; 24618c2ecf20Sopenharmony_ci 24628c2ecf20Sopenharmony_ci cp = hci_sent_cmd_data(hdev, HCI_OP_SWITCH_ROLE); 24638c2ecf20Sopenharmony_ci if (!cp) 24648c2ecf20Sopenharmony_ci return; 24658c2ecf20Sopenharmony_ci 24668c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 24678c2ecf20Sopenharmony_ci 24688c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 24698c2ecf20Sopenharmony_ci if (conn) 24708c2ecf20Sopenharmony_ci clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); 24718c2ecf20Sopenharmony_ci 24728c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 24738c2ecf20Sopenharmony_ci} 24748c2ecf20Sopenharmony_ci 24758c2ecf20Sopenharmony_cistatic void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 24768c2ecf20Sopenharmony_ci{ 24778c2ecf20Sopenharmony_ci __u8 status = *((__u8 *) skb->data); 24788c2ecf20Sopenharmony_ci struct discovery_state *discov = &hdev->discovery; 24798c2ecf20Sopenharmony_ci struct inquiry_entry *e; 24808c2ecf20Sopenharmony_ci 24818c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, status); 24828c2ecf20Sopenharmony_ci 24838c2ecf20Sopenharmony_ci hci_conn_check_pending(hdev); 24848c2ecf20Sopenharmony_ci 24858c2ecf20Sopenharmony_ci if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) 24868c2ecf20Sopenharmony_ci return; 24878c2ecf20Sopenharmony_ci 24888c2ecf20Sopenharmony_ci smp_mb__after_atomic(); /* wake_up_bit advises about this barrier */ 24898c2ecf20Sopenharmony_ci wake_up_bit(&hdev->flags, HCI_INQUIRY); 24908c2ecf20Sopenharmony_ci 24918c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_MGMT)) 24928c2ecf20Sopenharmony_ci return; 24938c2ecf20Sopenharmony_ci 24948c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 24958c2ecf20Sopenharmony_ci 24968c2ecf20Sopenharmony_ci if (discov->state != DISCOVERY_FINDING) 24978c2ecf20Sopenharmony_ci goto unlock; 24988c2ecf20Sopenharmony_ci 24998c2ecf20Sopenharmony_ci if (list_empty(&discov->resolve)) { 25008c2ecf20Sopenharmony_ci /* When BR/EDR inquiry is active and no LE scanning is in 25018c2ecf20Sopenharmony_ci * progress, then change discovery state to indicate completion. 25028c2ecf20Sopenharmony_ci * 25038c2ecf20Sopenharmony_ci * When running LE scanning and BR/EDR inquiry simultaneously 25048c2ecf20Sopenharmony_ci * and the LE scan already finished, then change the discovery 25058c2ecf20Sopenharmony_ci * state to indicate completion. 25068c2ecf20Sopenharmony_ci */ 25078c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_LE_SCAN) || 25088c2ecf20Sopenharmony_ci !test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks)) 25098c2ecf20Sopenharmony_ci hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 25108c2ecf20Sopenharmony_ci goto unlock; 25118c2ecf20Sopenharmony_ci } 25128c2ecf20Sopenharmony_ci 25138c2ecf20Sopenharmony_ci e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 25148c2ecf20Sopenharmony_ci if (e && hci_resolve_name(hdev, e) == 0) { 25158c2ecf20Sopenharmony_ci e->name_state = NAME_PENDING; 25168c2ecf20Sopenharmony_ci hci_discovery_set_state(hdev, DISCOVERY_RESOLVING); 25178c2ecf20Sopenharmony_ci } else { 25188c2ecf20Sopenharmony_ci /* When BR/EDR inquiry is active and no LE scanning is in 25198c2ecf20Sopenharmony_ci * progress, then change discovery state to indicate completion. 25208c2ecf20Sopenharmony_ci * 25218c2ecf20Sopenharmony_ci * When running LE scanning and BR/EDR inquiry simultaneously 25228c2ecf20Sopenharmony_ci * and the LE scan already finished, then change the discovery 25238c2ecf20Sopenharmony_ci * state to indicate completion. 25248c2ecf20Sopenharmony_ci */ 25258c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_LE_SCAN) || 25268c2ecf20Sopenharmony_ci !test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks)) 25278c2ecf20Sopenharmony_ci hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 25288c2ecf20Sopenharmony_ci } 25298c2ecf20Sopenharmony_ci 25308c2ecf20Sopenharmony_ciunlock: 25318c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 25328c2ecf20Sopenharmony_ci} 25338c2ecf20Sopenharmony_ci 25348c2ecf20Sopenharmony_cistatic void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 25358c2ecf20Sopenharmony_ci{ 25368c2ecf20Sopenharmony_ci struct inquiry_data data; 25378c2ecf20Sopenharmony_ci struct inquiry_info *info = (void *) (skb->data + 1); 25388c2ecf20Sopenharmony_ci int num_rsp = *((__u8 *) skb->data); 25398c2ecf20Sopenharmony_ci 25408c2ecf20Sopenharmony_ci BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 25418c2ecf20Sopenharmony_ci 25428c2ecf20Sopenharmony_ci if (!num_rsp || skb->len < num_rsp * sizeof(*info) + 1) 25438c2ecf20Sopenharmony_ci return; 25448c2ecf20Sopenharmony_ci 25458c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) 25468c2ecf20Sopenharmony_ci return; 25478c2ecf20Sopenharmony_ci 25488c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 25498c2ecf20Sopenharmony_ci 25508c2ecf20Sopenharmony_ci for (; num_rsp; num_rsp--, info++) { 25518c2ecf20Sopenharmony_ci u32 flags; 25528c2ecf20Sopenharmony_ci 25538c2ecf20Sopenharmony_ci bacpy(&data.bdaddr, &info->bdaddr); 25548c2ecf20Sopenharmony_ci data.pscan_rep_mode = info->pscan_rep_mode; 25558c2ecf20Sopenharmony_ci data.pscan_period_mode = info->pscan_period_mode; 25568c2ecf20Sopenharmony_ci data.pscan_mode = info->pscan_mode; 25578c2ecf20Sopenharmony_ci memcpy(data.dev_class, info->dev_class, 3); 25588c2ecf20Sopenharmony_ci data.clock_offset = info->clock_offset; 25598c2ecf20Sopenharmony_ci data.rssi = HCI_RSSI_INVALID; 25608c2ecf20Sopenharmony_ci data.ssp_mode = 0x00; 25618c2ecf20Sopenharmony_ci 25628c2ecf20Sopenharmony_ci flags = hci_inquiry_cache_update(hdev, &data, false); 25638c2ecf20Sopenharmony_ci 25648c2ecf20Sopenharmony_ci mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 25658c2ecf20Sopenharmony_ci info->dev_class, HCI_RSSI_INVALID, 25668c2ecf20Sopenharmony_ci flags, NULL, 0, NULL, 0); 25678c2ecf20Sopenharmony_ci } 25688c2ecf20Sopenharmony_ci 25698c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 25708c2ecf20Sopenharmony_ci} 25718c2ecf20Sopenharmony_ci 25728c2ecf20Sopenharmony_cistatic void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 25738c2ecf20Sopenharmony_ci{ 25748c2ecf20Sopenharmony_ci struct hci_ev_conn_complete *ev = (void *) skb->data; 25758c2ecf20Sopenharmony_ci struct hci_conn *conn; 25768c2ecf20Sopenharmony_ci 25778c2ecf20Sopenharmony_ci BT_DBG("%s", hdev->name); 25788c2ecf20Sopenharmony_ci 25798c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 25808c2ecf20Sopenharmony_ci 25818c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 25828c2ecf20Sopenharmony_ci if (!conn) { 25838c2ecf20Sopenharmony_ci /* Connection may not exist if auto-connected. Check the bredr 25848c2ecf20Sopenharmony_ci * allowlist to see if this device is allowed to auto connect. 25858c2ecf20Sopenharmony_ci * If link is an ACL type, create a connection class 25868c2ecf20Sopenharmony_ci * automatically. 25878c2ecf20Sopenharmony_ci * 25888c2ecf20Sopenharmony_ci * Auto-connect will only occur if the event filter is 25898c2ecf20Sopenharmony_ci * programmed with a given address. Right now, event filter is 25908c2ecf20Sopenharmony_ci * only used during suspend. 25918c2ecf20Sopenharmony_ci */ 25928c2ecf20Sopenharmony_ci if (ev->link_type == ACL_LINK && 25938c2ecf20Sopenharmony_ci hci_bdaddr_list_lookup_with_flags(&hdev->accept_list, 25948c2ecf20Sopenharmony_ci &ev->bdaddr, 25958c2ecf20Sopenharmony_ci BDADDR_BREDR)) { 25968c2ecf20Sopenharmony_ci conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr, 25978c2ecf20Sopenharmony_ci HCI_ROLE_SLAVE); 25988c2ecf20Sopenharmony_ci if (!conn) { 25998c2ecf20Sopenharmony_ci bt_dev_err(hdev, "no memory for new conn"); 26008c2ecf20Sopenharmony_ci goto unlock; 26018c2ecf20Sopenharmony_ci } 26028c2ecf20Sopenharmony_ci } else { 26038c2ecf20Sopenharmony_ci if (ev->link_type != SCO_LINK) 26048c2ecf20Sopenharmony_ci goto unlock; 26058c2ecf20Sopenharmony_ci 26068c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, 26078c2ecf20Sopenharmony_ci &ev->bdaddr); 26088c2ecf20Sopenharmony_ci if (!conn) 26098c2ecf20Sopenharmony_ci goto unlock; 26108c2ecf20Sopenharmony_ci 26118c2ecf20Sopenharmony_ci conn->type = SCO_LINK; 26128c2ecf20Sopenharmony_ci } 26138c2ecf20Sopenharmony_ci } 26148c2ecf20Sopenharmony_ci 26158c2ecf20Sopenharmony_ci if (!ev->status) { 26168c2ecf20Sopenharmony_ci conn->handle = __le16_to_cpu(ev->handle); 26178c2ecf20Sopenharmony_ci 26188c2ecf20Sopenharmony_ci if (conn->type == ACL_LINK) { 26198c2ecf20Sopenharmony_ci conn->state = BT_CONFIG; 26208c2ecf20Sopenharmony_ci hci_conn_hold(conn); 26218c2ecf20Sopenharmony_ci 26228c2ecf20Sopenharmony_ci if (!conn->out && !hci_conn_ssp_enabled(conn) && 26238c2ecf20Sopenharmony_ci !hci_find_link_key(hdev, &ev->bdaddr)) 26248c2ecf20Sopenharmony_ci conn->disc_timeout = HCI_PAIRING_TIMEOUT; 26258c2ecf20Sopenharmony_ci else 26268c2ecf20Sopenharmony_ci conn->disc_timeout = HCI_DISCONN_TIMEOUT; 26278c2ecf20Sopenharmony_ci } else 26288c2ecf20Sopenharmony_ci conn->state = BT_CONNECTED; 26298c2ecf20Sopenharmony_ci 26308c2ecf20Sopenharmony_ci hci_debugfs_create_conn(conn); 26318c2ecf20Sopenharmony_ci hci_conn_add_sysfs(conn); 26328c2ecf20Sopenharmony_ci 26338c2ecf20Sopenharmony_ci if (test_bit(HCI_AUTH, &hdev->flags)) 26348c2ecf20Sopenharmony_ci set_bit(HCI_CONN_AUTH, &conn->flags); 26358c2ecf20Sopenharmony_ci 26368c2ecf20Sopenharmony_ci if (test_bit(HCI_ENCRYPT, &hdev->flags)) 26378c2ecf20Sopenharmony_ci set_bit(HCI_CONN_ENCRYPT, &conn->flags); 26388c2ecf20Sopenharmony_ci 26398c2ecf20Sopenharmony_ci /* Get remote features */ 26408c2ecf20Sopenharmony_ci if (conn->type == ACL_LINK) { 26418c2ecf20Sopenharmony_ci struct hci_cp_read_remote_features cp; 26428c2ecf20Sopenharmony_ci cp.handle = ev->handle; 26438c2ecf20Sopenharmony_ci hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 26448c2ecf20Sopenharmony_ci sizeof(cp), &cp); 26458c2ecf20Sopenharmony_ci 26468c2ecf20Sopenharmony_ci hci_req_update_scan(hdev); 26478c2ecf20Sopenharmony_ci } 26488c2ecf20Sopenharmony_ci 26498c2ecf20Sopenharmony_ci /* Set packet type for incoming connection */ 26508c2ecf20Sopenharmony_ci if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) { 26518c2ecf20Sopenharmony_ci struct hci_cp_change_conn_ptype cp; 26528c2ecf20Sopenharmony_ci cp.handle = ev->handle; 26538c2ecf20Sopenharmony_ci cp.pkt_type = cpu_to_le16(conn->pkt_type); 26548c2ecf20Sopenharmony_ci hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp), 26558c2ecf20Sopenharmony_ci &cp); 26568c2ecf20Sopenharmony_ci } 26578c2ecf20Sopenharmony_ci } else { 26588c2ecf20Sopenharmony_ci conn->state = BT_CLOSED; 26598c2ecf20Sopenharmony_ci if (conn->type == ACL_LINK) 26608c2ecf20Sopenharmony_ci mgmt_connect_failed(hdev, &conn->dst, conn->type, 26618c2ecf20Sopenharmony_ci conn->dst_type, ev->status); 26628c2ecf20Sopenharmony_ci } 26638c2ecf20Sopenharmony_ci 26648c2ecf20Sopenharmony_ci if (conn->type == ACL_LINK) 26658c2ecf20Sopenharmony_ci hci_sco_setup(conn, ev->status); 26668c2ecf20Sopenharmony_ci 26678c2ecf20Sopenharmony_ci if (ev->status) { 26688c2ecf20Sopenharmony_ci hci_connect_cfm(conn, ev->status); 26698c2ecf20Sopenharmony_ci hci_conn_del(conn); 26708c2ecf20Sopenharmony_ci } else if (ev->link_type == SCO_LINK) { 26718c2ecf20Sopenharmony_ci switch (conn->setting & SCO_AIRMODE_MASK) { 26728c2ecf20Sopenharmony_ci case SCO_AIRMODE_CVSD: 26738c2ecf20Sopenharmony_ci if (hdev->notify) 26748c2ecf20Sopenharmony_ci hdev->notify(hdev, HCI_NOTIFY_ENABLE_SCO_CVSD); 26758c2ecf20Sopenharmony_ci break; 26768c2ecf20Sopenharmony_ci } 26778c2ecf20Sopenharmony_ci 26788c2ecf20Sopenharmony_ci hci_connect_cfm(conn, ev->status); 26798c2ecf20Sopenharmony_ci } 26808c2ecf20Sopenharmony_ci 26818c2ecf20Sopenharmony_ciunlock: 26828c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 26838c2ecf20Sopenharmony_ci 26848c2ecf20Sopenharmony_ci hci_conn_check_pending(hdev); 26858c2ecf20Sopenharmony_ci} 26868c2ecf20Sopenharmony_ci 26878c2ecf20Sopenharmony_cistatic void hci_reject_conn(struct hci_dev *hdev, bdaddr_t *bdaddr) 26888c2ecf20Sopenharmony_ci{ 26898c2ecf20Sopenharmony_ci struct hci_cp_reject_conn_req cp; 26908c2ecf20Sopenharmony_ci 26918c2ecf20Sopenharmony_ci bacpy(&cp.bdaddr, bdaddr); 26928c2ecf20Sopenharmony_ci cp.reason = HCI_ERROR_REJ_BAD_ADDR; 26938c2ecf20Sopenharmony_ci hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 26948c2ecf20Sopenharmony_ci} 26958c2ecf20Sopenharmony_ci 26968c2ecf20Sopenharmony_cistatic void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 26978c2ecf20Sopenharmony_ci{ 26988c2ecf20Sopenharmony_ci struct hci_ev_conn_request *ev = (void *) skb->data; 26998c2ecf20Sopenharmony_ci int mask = hdev->link_mode; 27008c2ecf20Sopenharmony_ci struct inquiry_entry *ie; 27018c2ecf20Sopenharmony_ci struct hci_conn *conn; 27028c2ecf20Sopenharmony_ci __u8 flags = 0; 27038c2ecf20Sopenharmony_ci 27048c2ecf20Sopenharmony_ci BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr, 27058c2ecf20Sopenharmony_ci ev->link_type); 27068c2ecf20Sopenharmony_ci 27078c2ecf20Sopenharmony_ci /* Reject incoming connection from device with same BD ADDR against 27088c2ecf20Sopenharmony_ci * CVE-2020-26555 27098c2ecf20Sopenharmony_ci */ 27108c2ecf20Sopenharmony_ci if (hdev && !bacmp(&hdev->bdaddr, &ev->bdaddr)) { 27118c2ecf20Sopenharmony_ci bt_dev_dbg(hdev, "Reject connection with same BD_ADDR %pMR\n", 27128c2ecf20Sopenharmony_ci &ev->bdaddr); 27138c2ecf20Sopenharmony_ci hci_reject_conn(hdev, &ev->bdaddr); 27148c2ecf20Sopenharmony_ci return; 27158c2ecf20Sopenharmony_ci } 27168c2ecf20Sopenharmony_ci 27178c2ecf20Sopenharmony_ci mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type, 27188c2ecf20Sopenharmony_ci &flags); 27198c2ecf20Sopenharmony_ci 27208c2ecf20Sopenharmony_ci if (!(mask & HCI_LM_ACCEPT)) { 27218c2ecf20Sopenharmony_ci hci_reject_conn(hdev, &ev->bdaddr); 27228c2ecf20Sopenharmony_ci return; 27238c2ecf20Sopenharmony_ci } 27248c2ecf20Sopenharmony_ci 27258c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 27268c2ecf20Sopenharmony_ci 27278c2ecf20Sopenharmony_ci if (hci_bdaddr_list_lookup(&hdev->reject_list, &ev->bdaddr, 27288c2ecf20Sopenharmony_ci BDADDR_BREDR)) { 27298c2ecf20Sopenharmony_ci hci_reject_conn(hdev, &ev->bdaddr); 27308c2ecf20Sopenharmony_ci goto unlock; 27318c2ecf20Sopenharmony_ci } 27328c2ecf20Sopenharmony_ci 27338c2ecf20Sopenharmony_ci /* Require HCI_CONNECTABLE or an accept list entry to accept the 27348c2ecf20Sopenharmony_ci * connection. These features are only touched through mgmt so 27358c2ecf20Sopenharmony_ci * only do the checks if HCI_MGMT is set. 27368c2ecf20Sopenharmony_ci */ 27378c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_MGMT) && 27388c2ecf20Sopenharmony_ci !hci_dev_test_flag(hdev, HCI_CONNECTABLE) && 27398c2ecf20Sopenharmony_ci !hci_bdaddr_list_lookup_with_flags(&hdev->accept_list, &ev->bdaddr, 27408c2ecf20Sopenharmony_ci BDADDR_BREDR)) { 27418c2ecf20Sopenharmony_ci hci_reject_conn(hdev, &ev->bdaddr); 27428c2ecf20Sopenharmony_ci goto unlock; 27438c2ecf20Sopenharmony_ci } 27448c2ecf20Sopenharmony_ci 27458c2ecf20Sopenharmony_ci /* Connection accepted */ 27468c2ecf20Sopenharmony_ci 27478c2ecf20Sopenharmony_ci ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 27488c2ecf20Sopenharmony_ci if (ie) 27498c2ecf20Sopenharmony_ci memcpy(ie->data.dev_class, ev->dev_class, 3); 27508c2ecf20Sopenharmony_ci 27518c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, 27528c2ecf20Sopenharmony_ci &ev->bdaddr); 27538c2ecf20Sopenharmony_ci if (!conn) { 27548c2ecf20Sopenharmony_ci conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr, 27558c2ecf20Sopenharmony_ci HCI_ROLE_SLAVE); 27568c2ecf20Sopenharmony_ci if (!conn) { 27578c2ecf20Sopenharmony_ci bt_dev_err(hdev, "no memory for new connection"); 27588c2ecf20Sopenharmony_ci goto unlock; 27598c2ecf20Sopenharmony_ci } 27608c2ecf20Sopenharmony_ci } 27618c2ecf20Sopenharmony_ci 27628c2ecf20Sopenharmony_ci memcpy(conn->dev_class, ev->dev_class, 3); 27638c2ecf20Sopenharmony_ci 27648c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 27658c2ecf20Sopenharmony_ci 27668c2ecf20Sopenharmony_ci if (ev->link_type == ACL_LINK || 27678c2ecf20Sopenharmony_ci (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) { 27688c2ecf20Sopenharmony_ci struct hci_cp_accept_conn_req cp; 27698c2ecf20Sopenharmony_ci conn->state = BT_CONNECT; 27708c2ecf20Sopenharmony_ci 27718c2ecf20Sopenharmony_ci bacpy(&cp.bdaddr, &ev->bdaddr); 27728c2ecf20Sopenharmony_ci 27738c2ecf20Sopenharmony_ci if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 27748c2ecf20Sopenharmony_ci cp.role = 0x00; /* Become central */ 27758c2ecf20Sopenharmony_ci else 27768c2ecf20Sopenharmony_ci cp.role = 0x01; /* Remain peripheral */ 27778c2ecf20Sopenharmony_ci 27788c2ecf20Sopenharmony_ci hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp); 27798c2ecf20Sopenharmony_ci } else if (!(flags & HCI_PROTO_DEFER)) { 27808c2ecf20Sopenharmony_ci struct hci_cp_accept_sync_conn_req cp; 27818c2ecf20Sopenharmony_ci conn->state = BT_CONNECT; 27828c2ecf20Sopenharmony_ci 27838c2ecf20Sopenharmony_ci bacpy(&cp.bdaddr, &ev->bdaddr); 27848c2ecf20Sopenharmony_ci cp.pkt_type = cpu_to_le16(conn->pkt_type); 27858c2ecf20Sopenharmony_ci 27868c2ecf20Sopenharmony_ci cp.tx_bandwidth = cpu_to_le32(0x00001f40); 27878c2ecf20Sopenharmony_ci cp.rx_bandwidth = cpu_to_le32(0x00001f40); 27888c2ecf20Sopenharmony_ci cp.max_latency = cpu_to_le16(0xffff); 27898c2ecf20Sopenharmony_ci cp.content_format = cpu_to_le16(hdev->voice_setting); 27908c2ecf20Sopenharmony_ci cp.retrans_effort = 0xff; 27918c2ecf20Sopenharmony_ci 27928c2ecf20Sopenharmony_ci hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, sizeof(cp), 27938c2ecf20Sopenharmony_ci &cp); 27948c2ecf20Sopenharmony_ci } else { 27958c2ecf20Sopenharmony_ci conn->state = BT_CONNECT2; 27968c2ecf20Sopenharmony_ci hci_connect_cfm(conn, 0); 27978c2ecf20Sopenharmony_ci } 27988c2ecf20Sopenharmony_ci 27998c2ecf20Sopenharmony_ci return; 28008c2ecf20Sopenharmony_ciunlock: 28018c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 28028c2ecf20Sopenharmony_ci} 28038c2ecf20Sopenharmony_ci 28048c2ecf20Sopenharmony_cistatic u8 hci_to_mgmt_reason(u8 err) 28058c2ecf20Sopenharmony_ci{ 28068c2ecf20Sopenharmony_ci switch (err) { 28078c2ecf20Sopenharmony_ci case HCI_ERROR_CONNECTION_TIMEOUT: 28088c2ecf20Sopenharmony_ci return MGMT_DEV_DISCONN_TIMEOUT; 28098c2ecf20Sopenharmony_ci case HCI_ERROR_REMOTE_USER_TERM: 28108c2ecf20Sopenharmony_ci case HCI_ERROR_REMOTE_LOW_RESOURCES: 28118c2ecf20Sopenharmony_ci case HCI_ERROR_REMOTE_POWER_OFF: 28128c2ecf20Sopenharmony_ci return MGMT_DEV_DISCONN_REMOTE; 28138c2ecf20Sopenharmony_ci case HCI_ERROR_LOCAL_HOST_TERM: 28148c2ecf20Sopenharmony_ci return MGMT_DEV_DISCONN_LOCAL_HOST; 28158c2ecf20Sopenharmony_ci default: 28168c2ecf20Sopenharmony_ci return MGMT_DEV_DISCONN_UNKNOWN; 28178c2ecf20Sopenharmony_ci } 28188c2ecf20Sopenharmony_ci} 28198c2ecf20Sopenharmony_ci 28208c2ecf20Sopenharmony_cistatic void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 28218c2ecf20Sopenharmony_ci{ 28228c2ecf20Sopenharmony_ci struct hci_ev_disconn_complete *ev = (void *) skb->data; 28238c2ecf20Sopenharmony_ci u8 reason; 28248c2ecf20Sopenharmony_ci struct hci_conn_params *params; 28258c2ecf20Sopenharmony_ci struct hci_conn *conn; 28268c2ecf20Sopenharmony_ci bool mgmt_connected; 28278c2ecf20Sopenharmony_ci u8 type; 28288c2ecf20Sopenharmony_ci 28298c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 28308c2ecf20Sopenharmony_ci 28318c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 28328c2ecf20Sopenharmony_ci 28338c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 28348c2ecf20Sopenharmony_ci if (!conn) 28358c2ecf20Sopenharmony_ci goto unlock; 28368c2ecf20Sopenharmony_ci 28378c2ecf20Sopenharmony_ci if (ev->status) { 28388c2ecf20Sopenharmony_ci mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 28398c2ecf20Sopenharmony_ci conn->dst_type, ev->status); 28408c2ecf20Sopenharmony_ci goto unlock; 28418c2ecf20Sopenharmony_ci } 28428c2ecf20Sopenharmony_ci 28438c2ecf20Sopenharmony_ci conn->state = BT_CLOSED; 28448c2ecf20Sopenharmony_ci 28458c2ecf20Sopenharmony_ci mgmt_connected = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags); 28468c2ecf20Sopenharmony_ci 28478c2ecf20Sopenharmony_ci if (test_bit(HCI_CONN_AUTH_FAILURE, &conn->flags)) 28488c2ecf20Sopenharmony_ci reason = MGMT_DEV_DISCONN_AUTH_FAILURE; 28498c2ecf20Sopenharmony_ci else 28508c2ecf20Sopenharmony_ci reason = hci_to_mgmt_reason(ev->reason); 28518c2ecf20Sopenharmony_ci 28528c2ecf20Sopenharmony_ci mgmt_device_disconnected(hdev, &conn->dst, conn->type, conn->dst_type, 28538c2ecf20Sopenharmony_ci reason, mgmt_connected); 28548c2ecf20Sopenharmony_ci 28558c2ecf20Sopenharmony_ci if (conn->type == ACL_LINK) { 28568c2ecf20Sopenharmony_ci if (test_bit(HCI_CONN_FLUSH_KEY, &conn->flags)) 28578c2ecf20Sopenharmony_ci hci_remove_link_key(hdev, &conn->dst); 28588c2ecf20Sopenharmony_ci 28598c2ecf20Sopenharmony_ci hci_req_update_scan(hdev); 28608c2ecf20Sopenharmony_ci } 28618c2ecf20Sopenharmony_ci 28628c2ecf20Sopenharmony_ci params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type); 28638c2ecf20Sopenharmony_ci if (params) { 28648c2ecf20Sopenharmony_ci switch (params->auto_connect) { 28658c2ecf20Sopenharmony_ci case HCI_AUTO_CONN_LINK_LOSS: 28668c2ecf20Sopenharmony_ci if (ev->reason != HCI_ERROR_CONNECTION_TIMEOUT) 28678c2ecf20Sopenharmony_ci break; 28688c2ecf20Sopenharmony_ci fallthrough; 28698c2ecf20Sopenharmony_ci 28708c2ecf20Sopenharmony_ci case HCI_AUTO_CONN_DIRECT: 28718c2ecf20Sopenharmony_ci case HCI_AUTO_CONN_ALWAYS: 28728c2ecf20Sopenharmony_ci list_del_init(¶ms->action); 28738c2ecf20Sopenharmony_ci list_add(¶ms->action, &hdev->pend_le_conns); 28748c2ecf20Sopenharmony_ci hci_update_background_scan(hdev); 28758c2ecf20Sopenharmony_ci break; 28768c2ecf20Sopenharmony_ci 28778c2ecf20Sopenharmony_ci default: 28788c2ecf20Sopenharmony_ci break; 28798c2ecf20Sopenharmony_ci } 28808c2ecf20Sopenharmony_ci } 28818c2ecf20Sopenharmony_ci 28828c2ecf20Sopenharmony_ci type = conn->type; 28838c2ecf20Sopenharmony_ci 28848c2ecf20Sopenharmony_ci hci_disconn_cfm(conn, ev->reason); 28858c2ecf20Sopenharmony_ci hci_conn_del(conn); 28868c2ecf20Sopenharmony_ci 28878c2ecf20Sopenharmony_ci /* The suspend notifier is waiting for all devices to disconnect so 28888c2ecf20Sopenharmony_ci * clear the bit from pending tasks and inform the wait queue. 28898c2ecf20Sopenharmony_ci */ 28908c2ecf20Sopenharmony_ci if (list_empty(&hdev->conn_hash.list) && 28918c2ecf20Sopenharmony_ci test_and_clear_bit(SUSPEND_DISCONNECTING, hdev->suspend_tasks)) { 28928c2ecf20Sopenharmony_ci wake_up(&hdev->suspend_wait_q); 28938c2ecf20Sopenharmony_ci } 28948c2ecf20Sopenharmony_ci 28958c2ecf20Sopenharmony_ci /* Re-enable advertising if necessary, since it might 28968c2ecf20Sopenharmony_ci * have been disabled by the connection. From the 28978c2ecf20Sopenharmony_ci * HCI_LE_Set_Advertise_Enable command description in 28988c2ecf20Sopenharmony_ci * the core specification (v4.0): 28998c2ecf20Sopenharmony_ci * "The Controller shall continue advertising until the Host 29008c2ecf20Sopenharmony_ci * issues an LE_Set_Advertise_Enable command with 29018c2ecf20Sopenharmony_ci * Advertising_Enable set to 0x00 (Advertising is disabled) 29028c2ecf20Sopenharmony_ci * or until a connection is created or until the Advertising 29038c2ecf20Sopenharmony_ci * is timed out due to Directed Advertising." 29048c2ecf20Sopenharmony_ci */ 29058c2ecf20Sopenharmony_ci if (type == LE_LINK) 29068c2ecf20Sopenharmony_ci hci_req_reenable_advertising(hdev); 29078c2ecf20Sopenharmony_ci 29088c2ecf20Sopenharmony_ciunlock: 29098c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 29108c2ecf20Sopenharmony_ci} 29118c2ecf20Sopenharmony_ci 29128c2ecf20Sopenharmony_cistatic void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 29138c2ecf20Sopenharmony_ci{ 29148c2ecf20Sopenharmony_ci struct hci_ev_auth_complete *ev = (void *) skb->data; 29158c2ecf20Sopenharmony_ci struct hci_conn *conn; 29168c2ecf20Sopenharmony_ci 29178c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 29188c2ecf20Sopenharmony_ci 29198c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 29208c2ecf20Sopenharmony_ci 29218c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 29228c2ecf20Sopenharmony_ci if (!conn) 29238c2ecf20Sopenharmony_ci goto unlock; 29248c2ecf20Sopenharmony_ci 29258c2ecf20Sopenharmony_ci if (!ev->status) { 29268c2ecf20Sopenharmony_ci clear_bit(HCI_CONN_AUTH_FAILURE, &conn->flags); 29278c2ecf20Sopenharmony_ci set_bit(HCI_CONN_AUTH, &conn->flags); 29288c2ecf20Sopenharmony_ci conn->sec_level = conn->pending_sec_level; 29298c2ecf20Sopenharmony_ci } else { 29308c2ecf20Sopenharmony_ci if (ev->status == HCI_ERROR_PIN_OR_KEY_MISSING) 29318c2ecf20Sopenharmony_ci set_bit(HCI_CONN_AUTH_FAILURE, &conn->flags); 29328c2ecf20Sopenharmony_ci 29338c2ecf20Sopenharmony_ci mgmt_auth_failed(conn, ev->status); 29348c2ecf20Sopenharmony_ci } 29358c2ecf20Sopenharmony_ci 29368c2ecf20Sopenharmony_ci clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 29378c2ecf20Sopenharmony_ci 29388c2ecf20Sopenharmony_ci if (conn->state == BT_CONFIG) { 29398c2ecf20Sopenharmony_ci if (!ev->status && hci_conn_ssp_enabled(conn)) { 29408c2ecf20Sopenharmony_ci struct hci_cp_set_conn_encrypt cp; 29418c2ecf20Sopenharmony_ci cp.handle = ev->handle; 29428c2ecf20Sopenharmony_ci cp.encrypt = 0x01; 29438c2ecf20Sopenharmony_ci hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 29448c2ecf20Sopenharmony_ci &cp); 29458c2ecf20Sopenharmony_ci } else { 29468c2ecf20Sopenharmony_ci conn->state = BT_CONNECTED; 29478c2ecf20Sopenharmony_ci hci_connect_cfm(conn, ev->status); 29488c2ecf20Sopenharmony_ci hci_conn_drop(conn); 29498c2ecf20Sopenharmony_ci } 29508c2ecf20Sopenharmony_ci } else { 29518c2ecf20Sopenharmony_ci hci_auth_cfm(conn, ev->status); 29528c2ecf20Sopenharmony_ci 29538c2ecf20Sopenharmony_ci hci_conn_hold(conn); 29548c2ecf20Sopenharmony_ci conn->disc_timeout = HCI_DISCONN_TIMEOUT; 29558c2ecf20Sopenharmony_ci hci_conn_drop(conn); 29568c2ecf20Sopenharmony_ci } 29578c2ecf20Sopenharmony_ci 29588c2ecf20Sopenharmony_ci if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) { 29598c2ecf20Sopenharmony_ci if (!ev->status) { 29608c2ecf20Sopenharmony_ci struct hci_cp_set_conn_encrypt cp; 29618c2ecf20Sopenharmony_ci cp.handle = ev->handle; 29628c2ecf20Sopenharmony_ci cp.encrypt = 0x01; 29638c2ecf20Sopenharmony_ci hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 29648c2ecf20Sopenharmony_ci &cp); 29658c2ecf20Sopenharmony_ci } else { 29668c2ecf20Sopenharmony_ci clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 29678c2ecf20Sopenharmony_ci hci_encrypt_cfm(conn, ev->status); 29688c2ecf20Sopenharmony_ci } 29698c2ecf20Sopenharmony_ci } 29708c2ecf20Sopenharmony_ci 29718c2ecf20Sopenharmony_ciunlock: 29728c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 29738c2ecf20Sopenharmony_ci} 29748c2ecf20Sopenharmony_ci 29758c2ecf20Sopenharmony_cistatic void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 29768c2ecf20Sopenharmony_ci{ 29778c2ecf20Sopenharmony_ci struct hci_ev_remote_name *ev = (void *) skb->data; 29788c2ecf20Sopenharmony_ci struct hci_conn *conn; 29798c2ecf20Sopenharmony_ci 29808c2ecf20Sopenharmony_ci BT_DBG("%s", hdev->name); 29818c2ecf20Sopenharmony_ci 29828c2ecf20Sopenharmony_ci hci_conn_check_pending(hdev); 29838c2ecf20Sopenharmony_ci 29848c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 29858c2ecf20Sopenharmony_ci 29868c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 29878c2ecf20Sopenharmony_ci 29888c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_MGMT)) 29898c2ecf20Sopenharmony_ci goto check_auth; 29908c2ecf20Sopenharmony_ci 29918c2ecf20Sopenharmony_ci if (ev->status == 0) 29928c2ecf20Sopenharmony_ci hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name, 29938c2ecf20Sopenharmony_ci strnlen(ev->name, HCI_MAX_NAME_LENGTH)); 29948c2ecf20Sopenharmony_ci else 29958c2ecf20Sopenharmony_ci hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0); 29968c2ecf20Sopenharmony_ci 29978c2ecf20Sopenharmony_cicheck_auth: 29988c2ecf20Sopenharmony_ci if (!conn) 29998c2ecf20Sopenharmony_ci goto unlock; 30008c2ecf20Sopenharmony_ci 30018c2ecf20Sopenharmony_ci if (!hci_outgoing_auth_needed(hdev, conn)) 30028c2ecf20Sopenharmony_ci goto unlock; 30038c2ecf20Sopenharmony_ci 30048c2ecf20Sopenharmony_ci if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 30058c2ecf20Sopenharmony_ci struct hci_cp_auth_requested cp; 30068c2ecf20Sopenharmony_ci 30078c2ecf20Sopenharmony_ci set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags); 30088c2ecf20Sopenharmony_ci 30098c2ecf20Sopenharmony_ci cp.handle = __cpu_to_le16(conn->handle); 30108c2ecf20Sopenharmony_ci hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 30118c2ecf20Sopenharmony_ci } 30128c2ecf20Sopenharmony_ci 30138c2ecf20Sopenharmony_ciunlock: 30148c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 30158c2ecf20Sopenharmony_ci} 30168c2ecf20Sopenharmony_ci 30178c2ecf20Sopenharmony_cistatic void read_enc_key_size_complete(struct hci_dev *hdev, u8 status, 30188c2ecf20Sopenharmony_ci u16 opcode, struct sk_buff *skb) 30198c2ecf20Sopenharmony_ci{ 30208c2ecf20Sopenharmony_ci const struct hci_rp_read_enc_key_size *rp; 30218c2ecf20Sopenharmony_ci struct hci_conn *conn; 30228c2ecf20Sopenharmony_ci u16 handle; 30238c2ecf20Sopenharmony_ci 30248c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%02x", hdev->name, status); 30258c2ecf20Sopenharmony_ci 30268c2ecf20Sopenharmony_ci if (!skb || skb->len < sizeof(*rp)) { 30278c2ecf20Sopenharmony_ci bt_dev_err(hdev, "invalid read key size response"); 30288c2ecf20Sopenharmony_ci return; 30298c2ecf20Sopenharmony_ci } 30308c2ecf20Sopenharmony_ci 30318c2ecf20Sopenharmony_ci rp = (void *)skb->data; 30328c2ecf20Sopenharmony_ci handle = le16_to_cpu(rp->handle); 30338c2ecf20Sopenharmony_ci 30348c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 30358c2ecf20Sopenharmony_ci 30368c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, handle); 30378c2ecf20Sopenharmony_ci if (!conn) 30388c2ecf20Sopenharmony_ci goto unlock; 30398c2ecf20Sopenharmony_ci 30408c2ecf20Sopenharmony_ci /* While unexpected, the read_enc_key_size command may fail. The most 30418c2ecf20Sopenharmony_ci * secure approach is to then assume the key size is 0 to force a 30428c2ecf20Sopenharmony_ci * disconnection. 30438c2ecf20Sopenharmony_ci */ 30448c2ecf20Sopenharmony_ci if (rp->status) { 30458c2ecf20Sopenharmony_ci bt_dev_err(hdev, "failed to read key size for handle %u", 30468c2ecf20Sopenharmony_ci handle); 30478c2ecf20Sopenharmony_ci conn->enc_key_size = 0; 30488c2ecf20Sopenharmony_ci } else { 30498c2ecf20Sopenharmony_ci conn->enc_key_size = rp->key_size; 30508c2ecf20Sopenharmony_ci } 30518c2ecf20Sopenharmony_ci 30528c2ecf20Sopenharmony_ci hci_encrypt_cfm(conn, 0); 30538c2ecf20Sopenharmony_ci 30548c2ecf20Sopenharmony_ciunlock: 30558c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 30568c2ecf20Sopenharmony_ci} 30578c2ecf20Sopenharmony_ci 30588c2ecf20Sopenharmony_cistatic void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 30598c2ecf20Sopenharmony_ci{ 30608c2ecf20Sopenharmony_ci struct hci_ev_encrypt_change *ev = (void *) skb->data; 30618c2ecf20Sopenharmony_ci struct hci_conn *conn; 30628c2ecf20Sopenharmony_ci 30638c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 30648c2ecf20Sopenharmony_ci 30658c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 30668c2ecf20Sopenharmony_ci 30678c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 30688c2ecf20Sopenharmony_ci if (!conn) 30698c2ecf20Sopenharmony_ci goto unlock; 30708c2ecf20Sopenharmony_ci 30718c2ecf20Sopenharmony_ci if (!ev->status) { 30728c2ecf20Sopenharmony_ci if (ev->encrypt) { 30738c2ecf20Sopenharmony_ci /* Encryption implies authentication */ 30748c2ecf20Sopenharmony_ci set_bit(HCI_CONN_AUTH, &conn->flags); 30758c2ecf20Sopenharmony_ci set_bit(HCI_CONN_ENCRYPT, &conn->flags); 30768c2ecf20Sopenharmony_ci conn->sec_level = conn->pending_sec_level; 30778c2ecf20Sopenharmony_ci 30788c2ecf20Sopenharmony_ci /* P-256 authentication key implies FIPS */ 30798c2ecf20Sopenharmony_ci if (conn->key_type == HCI_LK_AUTH_COMBINATION_P256) 30808c2ecf20Sopenharmony_ci set_bit(HCI_CONN_FIPS, &conn->flags); 30818c2ecf20Sopenharmony_ci 30828c2ecf20Sopenharmony_ci if ((conn->type == ACL_LINK && ev->encrypt == 0x02) || 30838c2ecf20Sopenharmony_ci conn->type == LE_LINK) 30848c2ecf20Sopenharmony_ci set_bit(HCI_CONN_AES_CCM, &conn->flags); 30858c2ecf20Sopenharmony_ci } else { 30868c2ecf20Sopenharmony_ci clear_bit(HCI_CONN_ENCRYPT, &conn->flags); 30878c2ecf20Sopenharmony_ci clear_bit(HCI_CONN_AES_CCM, &conn->flags); 30888c2ecf20Sopenharmony_ci } 30898c2ecf20Sopenharmony_ci } 30908c2ecf20Sopenharmony_ci 30918c2ecf20Sopenharmony_ci /* We should disregard the current RPA and generate a new one 30928c2ecf20Sopenharmony_ci * whenever the encryption procedure fails. 30938c2ecf20Sopenharmony_ci */ 30948c2ecf20Sopenharmony_ci if (ev->status && conn->type == LE_LINK) { 30958c2ecf20Sopenharmony_ci hci_dev_set_flag(hdev, HCI_RPA_EXPIRED); 30968c2ecf20Sopenharmony_ci hci_adv_instances_set_rpa_expired(hdev, true); 30978c2ecf20Sopenharmony_ci } 30988c2ecf20Sopenharmony_ci 30998c2ecf20Sopenharmony_ci clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 31008c2ecf20Sopenharmony_ci 31018c2ecf20Sopenharmony_ci /* Check link security requirements are met */ 31028c2ecf20Sopenharmony_ci if (!hci_conn_check_link_mode(conn)) 31038c2ecf20Sopenharmony_ci ev->status = HCI_ERROR_AUTH_FAILURE; 31048c2ecf20Sopenharmony_ci 31058c2ecf20Sopenharmony_ci if (ev->status && conn->state == BT_CONNECTED) { 31068c2ecf20Sopenharmony_ci if (ev->status == HCI_ERROR_PIN_OR_KEY_MISSING) 31078c2ecf20Sopenharmony_ci set_bit(HCI_CONN_AUTH_FAILURE, &conn->flags); 31088c2ecf20Sopenharmony_ci 31098c2ecf20Sopenharmony_ci /* Notify upper layers so they can cleanup before 31108c2ecf20Sopenharmony_ci * disconnecting. 31118c2ecf20Sopenharmony_ci */ 31128c2ecf20Sopenharmony_ci hci_encrypt_cfm(conn, ev->status); 31138c2ecf20Sopenharmony_ci hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); 31148c2ecf20Sopenharmony_ci hci_conn_drop(conn); 31158c2ecf20Sopenharmony_ci goto unlock; 31168c2ecf20Sopenharmony_ci } 31178c2ecf20Sopenharmony_ci 31188c2ecf20Sopenharmony_ci /* Try reading the encryption key size for encrypted ACL links */ 31198c2ecf20Sopenharmony_ci if (!ev->status && ev->encrypt && conn->type == ACL_LINK) { 31208c2ecf20Sopenharmony_ci struct hci_cp_read_enc_key_size cp; 31218c2ecf20Sopenharmony_ci struct hci_request req; 31228c2ecf20Sopenharmony_ci 31238c2ecf20Sopenharmony_ci /* Only send HCI_Read_Encryption_Key_Size if the 31248c2ecf20Sopenharmony_ci * controller really supports it. If it doesn't, assume 31258c2ecf20Sopenharmony_ci * the default size (16). 31268c2ecf20Sopenharmony_ci */ 31278c2ecf20Sopenharmony_ci if (!(hdev->commands[20] & 0x10)) { 31288c2ecf20Sopenharmony_ci conn->enc_key_size = HCI_LINK_KEY_SIZE; 31298c2ecf20Sopenharmony_ci goto notify; 31308c2ecf20Sopenharmony_ci } 31318c2ecf20Sopenharmony_ci 31328c2ecf20Sopenharmony_ci hci_req_init(&req, hdev); 31338c2ecf20Sopenharmony_ci 31348c2ecf20Sopenharmony_ci cp.handle = cpu_to_le16(conn->handle); 31358c2ecf20Sopenharmony_ci hci_req_add(&req, HCI_OP_READ_ENC_KEY_SIZE, sizeof(cp), &cp); 31368c2ecf20Sopenharmony_ci 31378c2ecf20Sopenharmony_ci if (hci_req_run_skb(&req, read_enc_key_size_complete)) { 31388c2ecf20Sopenharmony_ci bt_dev_err(hdev, "sending read key size failed"); 31398c2ecf20Sopenharmony_ci conn->enc_key_size = HCI_LINK_KEY_SIZE; 31408c2ecf20Sopenharmony_ci goto notify; 31418c2ecf20Sopenharmony_ci } 31428c2ecf20Sopenharmony_ci 31438c2ecf20Sopenharmony_ci goto unlock; 31448c2ecf20Sopenharmony_ci } 31458c2ecf20Sopenharmony_ci 31468c2ecf20Sopenharmony_ci /* Set the default Authenticated Payload Timeout after 31478c2ecf20Sopenharmony_ci * an LE Link is established. As per Core Spec v5.0, Vol 2, Part B 31488c2ecf20Sopenharmony_ci * Section 3.3, the HCI command WRITE_AUTH_PAYLOAD_TIMEOUT should be 31498c2ecf20Sopenharmony_ci * sent when the link is active and Encryption is enabled, the conn 31508c2ecf20Sopenharmony_ci * type can be either LE or ACL and controller must support LMP Ping. 31518c2ecf20Sopenharmony_ci * Ensure for AES-CCM encryption as well. 31528c2ecf20Sopenharmony_ci */ 31538c2ecf20Sopenharmony_ci if (test_bit(HCI_CONN_ENCRYPT, &conn->flags) && 31548c2ecf20Sopenharmony_ci test_bit(HCI_CONN_AES_CCM, &conn->flags) && 31558c2ecf20Sopenharmony_ci ((conn->type == ACL_LINK && lmp_ping_capable(hdev)) || 31568c2ecf20Sopenharmony_ci (conn->type == LE_LINK && (hdev->le_features[0] & HCI_LE_PING)))) { 31578c2ecf20Sopenharmony_ci struct hci_cp_write_auth_payload_to cp; 31588c2ecf20Sopenharmony_ci 31598c2ecf20Sopenharmony_ci cp.handle = cpu_to_le16(conn->handle); 31608c2ecf20Sopenharmony_ci cp.timeout = cpu_to_le16(hdev->auth_payload_timeout); 31618c2ecf20Sopenharmony_ci hci_send_cmd(conn->hdev, HCI_OP_WRITE_AUTH_PAYLOAD_TO, 31628c2ecf20Sopenharmony_ci sizeof(cp), &cp); 31638c2ecf20Sopenharmony_ci } 31648c2ecf20Sopenharmony_ci 31658c2ecf20Sopenharmony_cinotify: 31668c2ecf20Sopenharmony_ci hci_encrypt_cfm(conn, ev->status); 31678c2ecf20Sopenharmony_ci 31688c2ecf20Sopenharmony_ciunlock: 31698c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 31708c2ecf20Sopenharmony_ci} 31718c2ecf20Sopenharmony_ci 31728c2ecf20Sopenharmony_cistatic void hci_change_link_key_complete_evt(struct hci_dev *hdev, 31738c2ecf20Sopenharmony_ci struct sk_buff *skb) 31748c2ecf20Sopenharmony_ci{ 31758c2ecf20Sopenharmony_ci struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 31768c2ecf20Sopenharmony_ci struct hci_conn *conn; 31778c2ecf20Sopenharmony_ci 31788c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 31798c2ecf20Sopenharmony_ci 31808c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 31818c2ecf20Sopenharmony_ci 31828c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 31838c2ecf20Sopenharmony_ci if (conn) { 31848c2ecf20Sopenharmony_ci if (!ev->status) 31858c2ecf20Sopenharmony_ci set_bit(HCI_CONN_SECURE, &conn->flags); 31868c2ecf20Sopenharmony_ci 31878c2ecf20Sopenharmony_ci clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 31888c2ecf20Sopenharmony_ci 31898c2ecf20Sopenharmony_ci hci_key_change_cfm(conn, ev->status); 31908c2ecf20Sopenharmony_ci } 31918c2ecf20Sopenharmony_ci 31928c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 31938c2ecf20Sopenharmony_ci} 31948c2ecf20Sopenharmony_ci 31958c2ecf20Sopenharmony_cistatic void hci_remote_features_evt(struct hci_dev *hdev, 31968c2ecf20Sopenharmony_ci struct sk_buff *skb) 31978c2ecf20Sopenharmony_ci{ 31988c2ecf20Sopenharmony_ci struct hci_ev_remote_features *ev = (void *) skb->data; 31998c2ecf20Sopenharmony_ci struct hci_conn *conn; 32008c2ecf20Sopenharmony_ci 32018c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 32028c2ecf20Sopenharmony_ci 32038c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 32048c2ecf20Sopenharmony_ci 32058c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 32068c2ecf20Sopenharmony_ci if (!conn) 32078c2ecf20Sopenharmony_ci goto unlock; 32088c2ecf20Sopenharmony_ci 32098c2ecf20Sopenharmony_ci if (!ev->status) 32108c2ecf20Sopenharmony_ci memcpy(conn->features[0], ev->features, 8); 32118c2ecf20Sopenharmony_ci 32128c2ecf20Sopenharmony_ci if (conn->state != BT_CONFIG) 32138c2ecf20Sopenharmony_ci goto unlock; 32148c2ecf20Sopenharmony_ci 32158c2ecf20Sopenharmony_ci if (!ev->status && lmp_ext_feat_capable(hdev) && 32168c2ecf20Sopenharmony_ci lmp_ext_feat_capable(conn)) { 32178c2ecf20Sopenharmony_ci struct hci_cp_read_remote_ext_features cp; 32188c2ecf20Sopenharmony_ci cp.handle = ev->handle; 32198c2ecf20Sopenharmony_ci cp.page = 0x01; 32208c2ecf20Sopenharmony_ci hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 32218c2ecf20Sopenharmony_ci sizeof(cp), &cp); 32228c2ecf20Sopenharmony_ci goto unlock; 32238c2ecf20Sopenharmony_ci } 32248c2ecf20Sopenharmony_ci 32258c2ecf20Sopenharmony_ci if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { 32268c2ecf20Sopenharmony_ci struct hci_cp_remote_name_req cp; 32278c2ecf20Sopenharmony_ci memset(&cp, 0, sizeof(cp)); 32288c2ecf20Sopenharmony_ci bacpy(&cp.bdaddr, &conn->dst); 32298c2ecf20Sopenharmony_ci cp.pscan_rep_mode = 0x02; 32308c2ecf20Sopenharmony_ci hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 32318c2ecf20Sopenharmony_ci } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 32328c2ecf20Sopenharmony_ci mgmt_device_connected(hdev, conn, 0, NULL, 0); 32338c2ecf20Sopenharmony_ci 32348c2ecf20Sopenharmony_ci if (!hci_outgoing_auth_needed(hdev, conn)) { 32358c2ecf20Sopenharmony_ci conn->state = BT_CONNECTED; 32368c2ecf20Sopenharmony_ci hci_connect_cfm(conn, ev->status); 32378c2ecf20Sopenharmony_ci hci_conn_drop(conn); 32388c2ecf20Sopenharmony_ci } 32398c2ecf20Sopenharmony_ci 32408c2ecf20Sopenharmony_ciunlock: 32418c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 32428c2ecf20Sopenharmony_ci} 32438c2ecf20Sopenharmony_ci 32448c2ecf20Sopenharmony_cistatic void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb, 32458c2ecf20Sopenharmony_ci u16 *opcode, u8 *status, 32468c2ecf20Sopenharmony_ci hci_req_complete_t *req_complete, 32478c2ecf20Sopenharmony_ci hci_req_complete_skb_t *req_complete_skb) 32488c2ecf20Sopenharmony_ci{ 32498c2ecf20Sopenharmony_ci struct hci_ev_cmd_complete *ev = (void *) skb->data; 32508c2ecf20Sopenharmony_ci 32518c2ecf20Sopenharmony_ci *opcode = __le16_to_cpu(ev->opcode); 32528c2ecf20Sopenharmony_ci *status = skb->data[sizeof(*ev)]; 32538c2ecf20Sopenharmony_ci 32548c2ecf20Sopenharmony_ci skb_pull(skb, sizeof(*ev)); 32558c2ecf20Sopenharmony_ci 32568c2ecf20Sopenharmony_ci switch (*opcode) { 32578c2ecf20Sopenharmony_ci case HCI_OP_INQUIRY_CANCEL: 32588c2ecf20Sopenharmony_ci hci_cc_inquiry_cancel(hdev, skb, status); 32598c2ecf20Sopenharmony_ci break; 32608c2ecf20Sopenharmony_ci 32618c2ecf20Sopenharmony_ci case HCI_OP_PERIODIC_INQ: 32628c2ecf20Sopenharmony_ci hci_cc_periodic_inq(hdev, skb); 32638c2ecf20Sopenharmony_ci break; 32648c2ecf20Sopenharmony_ci 32658c2ecf20Sopenharmony_ci case HCI_OP_EXIT_PERIODIC_INQ: 32668c2ecf20Sopenharmony_ci hci_cc_exit_periodic_inq(hdev, skb); 32678c2ecf20Sopenharmony_ci break; 32688c2ecf20Sopenharmony_ci 32698c2ecf20Sopenharmony_ci case HCI_OP_REMOTE_NAME_REQ_CANCEL: 32708c2ecf20Sopenharmony_ci hci_cc_remote_name_req_cancel(hdev, skb); 32718c2ecf20Sopenharmony_ci break; 32728c2ecf20Sopenharmony_ci 32738c2ecf20Sopenharmony_ci case HCI_OP_ROLE_DISCOVERY: 32748c2ecf20Sopenharmony_ci hci_cc_role_discovery(hdev, skb); 32758c2ecf20Sopenharmony_ci break; 32768c2ecf20Sopenharmony_ci 32778c2ecf20Sopenharmony_ci case HCI_OP_READ_LINK_POLICY: 32788c2ecf20Sopenharmony_ci hci_cc_read_link_policy(hdev, skb); 32798c2ecf20Sopenharmony_ci break; 32808c2ecf20Sopenharmony_ci 32818c2ecf20Sopenharmony_ci case HCI_OP_WRITE_LINK_POLICY: 32828c2ecf20Sopenharmony_ci hci_cc_write_link_policy(hdev, skb); 32838c2ecf20Sopenharmony_ci break; 32848c2ecf20Sopenharmony_ci 32858c2ecf20Sopenharmony_ci case HCI_OP_READ_DEF_LINK_POLICY: 32868c2ecf20Sopenharmony_ci hci_cc_read_def_link_policy(hdev, skb); 32878c2ecf20Sopenharmony_ci break; 32888c2ecf20Sopenharmony_ci 32898c2ecf20Sopenharmony_ci case HCI_OP_WRITE_DEF_LINK_POLICY: 32908c2ecf20Sopenharmony_ci hci_cc_write_def_link_policy(hdev, skb); 32918c2ecf20Sopenharmony_ci break; 32928c2ecf20Sopenharmony_ci 32938c2ecf20Sopenharmony_ci case HCI_OP_RESET: 32948c2ecf20Sopenharmony_ci hci_cc_reset(hdev, skb); 32958c2ecf20Sopenharmony_ci break; 32968c2ecf20Sopenharmony_ci 32978c2ecf20Sopenharmony_ci case HCI_OP_READ_STORED_LINK_KEY: 32988c2ecf20Sopenharmony_ci hci_cc_read_stored_link_key(hdev, skb); 32998c2ecf20Sopenharmony_ci break; 33008c2ecf20Sopenharmony_ci 33018c2ecf20Sopenharmony_ci case HCI_OP_DELETE_STORED_LINK_KEY: 33028c2ecf20Sopenharmony_ci hci_cc_delete_stored_link_key(hdev, skb); 33038c2ecf20Sopenharmony_ci break; 33048c2ecf20Sopenharmony_ci 33058c2ecf20Sopenharmony_ci case HCI_OP_WRITE_LOCAL_NAME: 33068c2ecf20Sopenharmony_ci hci_cc_write_local_name(hdev, skb); 33078c2ecf20Sopenharmony_ci break; 33088c2ecf20Sopenharmony_ci 33098c2ecf20Sopenharmony_ci case HCI_OP_READ_LOCAL_NAME: 33108c2ecf20Sopenharmony_ci hci_cc_read_local_name(hdev, skb); 33118c2ecf20Sopenharmony_ci break; 33128c2ecf20Sopenharmony_ci 33138c2ecf20Sopenharmony_ci case HCI_OP_WRITE_AUTH_ENABLE: 33148c2ecf20Sopenharmony_ci hci_cc_write_auth_enable(hdev, skb); 33158c2ecf20Sopenharmony_ci break; 33168c2ecf20Sopenharmony_ci 33178c2ecf20Sopenharmony_ci case HCI_OP_WRITE_ENCRYPT_MODE: 33188c2ecf20Sopenharmony_ci hci_cc_write_encrypt_mode(hdev, skb); 33198c2ecf20Sopenharmony_ci break; 33208c2ecf20Sopenharmony_ci 33218c2ecf20Sopenharmony_ci case HCI_OP_WRITE_SCAN_ENABLE: 33228c2ecf20Sopenharmony_ci hci_cc_write_scan_enable(hdev, skb); 33238c2ecf20Sopenharmony_ci break; 33248c2ecf20Sopenharmony_ci 33258c2ecf20Sopenharmony_ci case HCI_OP_READ_CLASS_OF_DEV: 33268c2ecf20Sopenharmony_ci hci_cc_read_class_of_dev(hdev, skb); 33278c2ecf20Sopenharmony_ci break; 33288c2ecf20Sopenharmony_ci 33298c2ecf20Sopenharmony_ci case HCI_OP_WRITE_CLASS_OF_DEV: 33308c2ecf20Sopenharmony_ci hci_cc_write_class_of_dev(hdev, skb); 33318c2ecf20Sopenharmony_ci break; 33328c2ecf20Sopenharmony_ci 33338c2ecf20Sopenharmony_ci case HCI_OP_READ_VOICE_SETTING: 33348c2ecf20Sopenharmony_ci hci_cc_read_voice_setting(hdev, skb); 33358c2ecf20Sopenharmony_ci break; 33368c2ecf20Sopenharmony_ci 33378c2ecf20Sopenharmony_ci case HCI_OP_WRITE_VOICE_SETTING: 33388c2ecf20Sopenharmony_ci hci_cc_write_voice_setting(hdev, skb); 33398c2ecf20Sopenharmony_ci break; 33408c2ecf20Sopenharmony_ci 33418c2ecf20Sopenharmony_ci case HCI_OP_READ_NUM_SUPPORTED_IAC: 33428c2ecf20Sopenharmony_ci hci_cc_read_num_supported_iac(hdev, skb); 33438c2ecf20Sopenharmony_ci break; 33448c2ecf20Sopenharmony_ci 33458c2ecf20Sopenharmony_ci case HCI_OP_WRITE_SSP_MODE: 33468c2ecf20Sopenharmony_ci hci_cc_write_ssp_mode(hdev, skb); 33478c2ecf20Sopenharmony_ci break; 33488c2ecf20Sopenharmony_ci 33498c2ecf20Sopenharmony_ci case HCI_OP_WRITE_SC_SUPPORT: 33508c2ecf20Sopenharmony_ci hci_cc_write_sc_support(hdev, skb); 33518c2ecf20Sopenharmony_ci break; 33528c2ecf20Sopenharmony_ci 33538c2ecf20Sopenharmony_ci case HCI_OP_READ_AUTH_PAYLOAD_TO: 33548c2ecf20Sopenharmony_ci hci_cc_read_auth_payload_timeout(hdev, skb); 33558c2ecf20Sopenharmony_ci break; 33568c2ecf20Sopenharmony_ci 33578c2ecf20Sopenharmony_ci case HCI_OP_WRITE_AUTH_PAYLOAD_TO: 33588c2ecf20Sopenharmony_ci hci_cc_write_auth_payload_timeout(hdev, skb); 33598c2ecf20Sopenharmony_ci break; 33608c2ecf20Sopenharmony_ci 33618c2ecf20Sopenharmony_ci case HCI_OP_READ_LOCAL_VERSION: 33628c2ecf20Sopenharmony_ci hci_cc_read_local_version(hdev, skb); 33638c2ecf20Sopenharmony_ci break; 33648c2ecf20Sopenharmony_ci 33658c2ecf20Sopenharmony_ci case HCI_OP_READ_LOCAL_COMMANDS: 33668c2ecf20Sopenharmony_ci hci_cc_read_local_commands(hdev, skb); 33678c2ecf20Sopenharmony_ci break; 33688c2ecf20Sopenharmony_ci 33698c2ecf20Sopenharmony_ci case HCI_OP_READ_LOCAL_FEATURES: 33708c2ecf20Sopenharmony_ci hci_cc_read_local_features(hdev, skb); 33718c2ecf20Sopenharmony_ci break; 33728c2ecf20Sopenharmony_ci 33738c2ecf20Sopenharmony_ci case HCI_OP_READ_LOCAL_EXT_FEATURES: 33748c2ecf20Sopenharmony_ci hci_cc_read_local_ext_features(hdev, skb); 33758c2ecf20Sopenharmony_ci break; 33768c2ecf20Sopenharmony_ci 33778c2ecf20Sopenharmony_ci case HCI_OP_READ_BUFFER_SIZE: 33788c2ecf20Sopenharmony_ci hci_cc_read_buffer_size(hdev, skb); 33798c2ecf20Sopenharmony_ci break; 33808c2ecf20Sopenharmony_ci 33818c2ecf20Sopenharmony_ci case HCI_OP_READ_BD_ADDR: 33828c2ecf20Sopenharmony_ci hci_cc_read_bd_addr(hdev, skb); 33838c2ecf20Sopenharmony_ci break; 33848c2ecf20Sopenharmony_ci 33858c2ecf20Sopenharmony_ci case HCI_OP_READ_LOCAL_PAIRING_OPTS: 33868c2ecf20Sopenharmony_ci hci_cc_read_local_pairing_opts(hdev, skb); 33878c2ecf20Sopenharmony_ci break; 33888c2ecf20Sopenharmony_ci 33898c2ecf20Sopenharmony_ci case HCI_OP_READ_PAGE_SCAN_ACTIVITY: 33908c2ecf20Sopenharmony_ci hci_cc_read_page_scan_activity(hdev, skb); 33918c2ecf20Sopenharmony_ci break; 33928c2ecf20Sopenharmony_ci 33938c2ecf20Sopenharmony_ci case HCI_OP_WRITE_PAGE_SCAN_ACTIVITY: 33948c2ecf20Sopenharmony_ci hci_cc_write_page_scan_activity(hdev, skb); 33958c2ecf20Sopenharmony_ci break; 33968c2ecf20Sopenharmony_ci 33978c2ecf20Sopenharmony_ci case HCI_OP_READ_PAGE_SCAN_TYPE: 33988c2ecf20Sopenharmony_ci hci_cc_read_page_scan_type(hdev, skb); 33998c2ecf20Sopenharmony_ci break; 34008c2ecf20Sopenharmony_ci 34018c2ecf20Sopenharmony_ci case HCI_OP_WRITE_PAGE_SCAN_TYPE: 34028c2ecf20Sopenharmony_ci hci_cc_write_page_scan_type(hdev, skb); 34038c2ecf20Sopenharmony_ci break; 34048c2ecf20Sopenharmony_ci 34058c2ecf20Sopenharmony_ci case HCI_OP_READ_DATA_BLOCK_SIZE: 34068c2ecf20Sopenharmony_ci hci_cc_read_data_block_size(hdev, skb); 34078c2ecf20Sopenharmony_ci break; 34088c2ecf20Sopenharmony_ci 34098c2ecf20Sopenharmony_ci case HCI_OP_READ_FLOW_CONTROL_MODE: 34108c2ecf20Sopenharmony_ci hci_cc_read_flow_control_mode(hdev, skb); 34118c2ecf20Sopenharmony_ci break; 34128c2ecf20Sopenharmony_ci 34138c2ecf20Sopenharmony_ci case HCI_OP_READ_LOCAL_AMP_INFO: 34148c2ecf20Sopenharmony_ci hci_cc_read_local_amp_info(hdev, skb); 34158c2ecf20Sopenharmony_ci break; 34168c2ecf20Sopenharmony_ci 34178c2ecf20Sopenharmony_ci case HCI_OP_READ_CLOCK: 34188c2ecf20Sopenharmony_ci hci_cc_read_clock(hdev, skb); 34198c2ecf20Sopenharmony_ci break; 34208c2ecf20Sopenharmony_ci 34218c2ecf20Sopenharmony_ci case HCI_OP_READ_INQ_RSP_TX_POWER: 34228c2ecf20Sopenharmony_ci hci_cc_read_inq_rsp_tx_power(hdev, skb); 34238c2ecf20Sopenharmony_ci break; 34248c2ecf20Sopenharmony_ci 34258c2ecf20Sopenharmony_ci case HCI_OP_READ_DEF_ERR_DATA_REPORTING: 34268c2ecf20Sopenharmony_ci hci_cc_read_def_err_data_reporting(hdev, skb); 34278c2ecf20Sopenharmony_ci break; 34288c2ecf20Sopenharmony_ci 34298c2ecf20Sopenharmony_ci case HCI_OP_WRITE_DEF_ERR_DATA_REPORTING: 34308c2ecf20Sopenharmony_ci hci_cc_write_def_err_data_reporting(hdev, skb); 34318c2ecf20Sopenharmony_ci break; 34328c2ecf20Sopenharmony_ci 34338c2ecf20Sopenharmony_ci case HCI_OP_PIN_CODE_REPLY: 34348c2ecf20Sopenharmony_ci hci_cc_pin_code_reply(hdev, skb); 34358c2ecf20Sopenharmony_ci break; 34368c2ecf20Sopenharmony_ci 34378c2ecf20Sopenharmony_ci case HCI_OP_PIN_CODE_NEG_REPLY: 34388c2ecf20Sopenharmony_ci hci_cc_pin_code_neg_reply(hdev, skb); 34398c2ecf20Sopenharmony_ci break; 34408c2ecf20Sopenharmony_ci 34418c2ecf20Sopenharmony_ci case HCI_OP_READ_LOCAL_OOB_DATA: 34428c2ecf20Sopenharmony_ci hci_cc_read_local_oob_data(hdev, skb); 34438c2ecf20Sopenharmony_ci break; 34448c2ecf20Sopenharmony_ci 34458c2ecf20Sopenharmony_ci case HCI_OP_READ_LOCAL_OOB_EXT_DATA: 34468c2ecf20Sopenharmony_ci hci_cc_read_local_oob_ext_data(hdev, skb); 34478c2ecf20Sopenharmony_ci break; 34488c2ecf20Sopenharmony_ci 34498c2ecf20Sopenharmony_ci case HCI_OP_LE_READ_BUFFER_SIZE: 34508c2ecf20Sopenharmony_ci hci_cc_le_read_buffer_size(hdev, skb); 34518c2ecf20Sopenharmony_ci break; 34528c2ecf20Sopenharmony_ci 34538c2ecf20Sopenharmony_ci case HCI_OP_LE_READ_LOCAL_FEATURES: 34548c2ecf20Sopenharmony_ci hci_cc_le_read_local_features(hdev, skb); 34558c2ecf20Sopenharmony_ci break; 34568c2ecf20Sopenharmony_ci 34578c2ecf20Sopenharmony_ci case HCI_OP_LE_READ_ADV_TX_POWER: 34588c2ecf20Sopenharmony_ci hci_cc_le_read_adv_tx_power(hdev, skb); 34598c2ecf20Sopenharmony_ci break; 34608c2ecf20Sopenharmony_ci 34618c2ecf20Sopenharmony_ci case HCI_OP_USER_CONFIRM_REPLY: 34628c2ecf20Sopenharmony_ci hci_cc_user_confirm_reply(hdev, skb); 34638c2ecf20Sopenharmony_ci break; 34648c2ecf20Sopenharmony_ci 34658c2ecf20Sopenharmony_ci case HCI_OP_USER_CONFIRM_NEG_REPLY: 34668c2ecf20Sopenharmony_ci hci_cc_user_confirm_neg_reply(hdev, skb); 34678c2ecf20Sopenharmony_ci break; 34688c2ecf20Sopenharmony_ci 34698c2ecf20Sopenharmony_ci case HCI_OP_USER_PASSKEY_REPLY: 34708c2ecf20Sopenharmony_ci hci_cc_user_passkey_reply(hdev, skb); 34718c2ecf20Sopenharmony_ci break; 34728c2ecf20Sopenharmony_ci 34738c2ecf20Sopenharmony_ci case HCI_OP_USER_PASSKEY_NEG_REPLY: 34748c2ecf20Sopenharmony_ci hci_cc_user_passkey_neg_reply(hdev, skb); 34758c2ecf20Sopenharmony_ci break; 34768c2ecf20Sopenharmony_ci 34778c2ecf20Sopenharmony_ci case HCI_OP_LE_SET_RANDOM_ADDR: 34788c2ecf20Sopenharmony_ci hci_cc_le_set_random_addr(hdev, skb); 34798c2ecf20Sopenharmony_ci break; 34808c2ecf20Sopenharmony_ci 34818c2ecf20Sopenharmony_ci case HCI_OP_LE_SET_ADV_ENABLE: 34828c2ecf20Sopenharmony_ci hci_cc_le_set_adv_enable(hdev, skb); 34838c2ecf20Sopenharmony_ci break; 34848c2ecf20Sopenharmony_ci 34858c2ecf20Sopenharmony_ci case HCI_OP_LE_SET_SCAN_PARAM: 34868c2ecf20Sopenharmony_ci hci_cc_le_set_scan_param(hdev, skb); 34878c2ecf20Sopenharmony_ci break; 34888c2ecf20Sopenharmony_ci 34898c2ecf20Sopenharmony_ci case HCI_OP_LE_SET_SCAN_ENABLE: 34908c2ecf20Sopenharmony_ci hci_cc_le_set_scan_enable(hdev, skb); 34918c2ecf20Sopenharmony_ci break; 34928c2ecf20Sopenharmony_ci 34938c2ecf20Sopenharmony_ci case HCI_OP_LE_READ_ACCEPT_LIST_SIZE: 34948c2ecf20Sopenharmony_ci hci_cc_le_read_accept_list_size(hdev, skb); 34958c2ecf20Sopenharmony_ci break; 34968c2ecf20Sopenharmony_ci 34978c2ecf20Sopenharmony_ci case HCI_OP_LE_CLEAR_ACCEPT_LIST: 34988c2ecf20Sopenharmony_ci hci_cc_le_clear_accept_list(hdev, skb); 34998c2ecf20Sopenharmony_ci break; 35008c2ecf20Sopenharmony_ci 35018c2ecf20Sopenharmony_ci case HCI_OP_LE_ADD_TO_ACCEPT_LIST: 35028c2ecf20Sopenharmony_ci hci_cc_le_add_to_accept_list(hdev, skb); 35038c2ecf20Sopenharmony_ci break; 35048c2ecf20Sopenharmony_ci 35058c2ecf20Sopenharmony_ci case HCI_OP_LE_DEL_FROM_ACCEPT_LIST: 35068c2ecf20Sopenharmony_ci hci_cc_le_del_from_accept_list(hdev, skb); 35078c2ecf20Sopenharmony_ci break; 35088c2ecf20Sopenharmony_ci 35098c2ecf20Sopenharmony_ci case HCI_OP_LE_READ_SUPPORTED_STATES: 35108c2ecf20Sopenharmony_ci hci_cc_le_read_supported_states(hdev, skb); 35118c2ecf20Sopenharmony_ci break; 35128c2ecf20Sopenharmony_ci 35138c2ecf20Sopenharmony_ci case HCI_OP_LE_READ_DEF_DATA_LEN: 35148c2ecf20Sopenharmony_ci hci_cc_le_read_def_data_len(hdev, skb); 35158c2ecf20Sopenharmony_ci break; 35168c2ecf20Sopenharmony_ci 35178c2ecf20Sopenharmony_ci case HCI_OP_LE_WRITE_DEF_DATA_LEN: 35188c2ecf20Sopenharmony_ci hci_cc_le_write_def_data_len(hdev, skb); 35198c2ecf20Sopenharmony_ci break; 35208c2ecf20Sopenharmony_ci 35218c2ecf20Sopenharmony_ci case HCI_OP_LE_ADD_TO_RESOLV_LIST: 35228c2ecf20Sopenharmony_ci hci_cc_le_add_to_resolv_list(hdev, skb); 35238c2ecf20Sopenharmony_ci break; 35248c2ecf20Sopenharmony_ci 35258c2ecf20Sopenharmony_ci case HCI_OP_LE_DEL_FROM_RESOLV_LIST: 35268c2ecf20Sopenharmony_ci hci_cc_le_del_from_resolv_list(hdev, skb); 35278c2ecf20Sopenharmony_ci break; 35288c2ecf20Sopenharmony_ci 35298c2ecf20Sopenharmony_ci case HCI_OP_LE_CLEAR_RESOLV_LIST: 35308c2ecf20Sopenharmony_ci hci_cc_le_clear_resolv_list(hdev, skb); 35318c2ecf20Sopenharmony_ci break; 35328c2ecf20Sopenharmony_ci 35338c2ecf20Sopenharmony_ci case HCI_OP_LE_READ_RESOLV_LIST_SIZE: 35348c2ecf20Sopenharmony_ci hci_cc_le_read_resolv_list_size(hdev, skb); 35358c2ecf20Sopenharmony_ci break; 35368c2ecf20Sopenharmony_ci 35378c2ecf20Sopenharmony_ci case HCI_OP_LE_SET_ADDR_RESOLV_ENABLE: 35388c2ecf20Sopenharmony_ci hci_cc_le_set_addr_resolution_enable(hdev, skb); 35398c2ecf20Sopenharmony_ci break; 35408c2ecf20Sopenharmony_ci 35418c2ecf20Sopenharmony_ci case HCI_OP_LE_READ_MAX_DATA_LEN: 35428c2ecf20Sopenharmony_ci hci_cc_le_read_max_data_len(hdev, skb); 35438c2ecf20Sopenharmony_ci break; 35448c2ecf20Sopenharmony_ci 35458c2ecf20Sopenharmony_ci case HCI_OP_WRITE_LE_HOST_SUPPORTED: 35468c2ecf20Sopenharmony_ci hci_cc_write_le_host_supported(hdev, skb); 35478c2ecf20Sopenharmony_ci break; 35488c2ecf20Sopenharmony_ci 35498c2ecf20Sopenharmony_ci case HCI_OP_LE_SET_ADV_PARAM: 35508c2ecf20Sopenharmony_ci hci_cc_set_adv_param(hdev, skb); 35518c2ecf20Sopenharmony_ci break; 35528c2ecf20Sopenharmony_ci 35538c2ecf20Sopenharmony_ci case HCI_OP_READ_RSSI: 35548c2ecf20Sopenharmony_ci hci_cc_read_rssi(hdev, skb); 35558c2ecf20Sopenharmony_ci break; 35568c2ecf20Sopenharmony_ci 35578c2ecf20Sopenharmony_ci case HCI_OP_READ_TX_POWER: 35588c2ecf20Sopenharmony_ci hci_cc_read_tx_power(hdev, skb); 35598c2ecf20Sopenharmony_ci break; 35608c2ecf20Sopenharmony_ci 35618c2ecf20Sopenharmony_ci case HCI_OP_WRITE_SSP_DEBUG_MODE: 35628c2ecf20Sopenharmony_ci hci_cc_write_ssp_debug_mode(hdev, skb); 35638c2ecf20Sopenharmony_ci break; 35648c2ecf20Sopenharmony_ci 35658c2ecf20Sopenharmony_ci case HCI_OP_LE_SET_EXT_SCAN_PARAMS: 35668c2ecf20Sopenharmony_ci hci_cc_le_set_ext_scan_param(hdev, skb); 35678c2ecf20Sopenharmony_ci break; 35688c2ecf20Sopenharmony_ci 35698c2ecf20Sopenharmony_ci case HCI_OP_LE_SET_EXT_SCAN_ENABLE: 35708c2ecf20Sopenharmony_ci hci_cc_le_set_ext_scan_enable(hdev, skb); 35718c2ecf20Sopenharmony_ci break; 35728c2ecf20Sopenharmony_ci 35738c2ecf20Sopenharmony_ci case HCI_OP_LE_SET_DEFAULT_PHY: 35748c2ecf20Sopenharmony_ci hci_cc_le_set_default_phy(hdev, skb); 35758c2ecf20Sopenharmony_ci break; 35768c2ecf20Sopenharmony_ci 35778c2ecf20Sopenharmony_ci case HCI_OP_LE_READ_NUM_SUPPORTED_ADV_SETS: 35788c2ecf20Sopenharmony_ci hci_cc_le_read_num_adv_sets(hdev, skb); 35798c2ecf20Sopenharmony_ci break; 35808c2ecf20Sopenharmony_ci 35818c2ecf20Sopenharmony_ci case HCI_OP_LE_SET_EXT_ADV_PARAMS: 35828c2ecf20Sopenharmony_ci hci_cc_set_ext_adv_param(hdev, skb); 35838c2ecf20Sopenharmony_ci break; 35848c2ecf20Sopenharmony_ci 35858c2ecf20Sopenharmony_ci case HCI_OP_LE_SET_EXT_ADV_ENABLE: 35868c2ecf20Sopenharmony_ci hci_cc_le_set_ext_adv_enable(hdev, skb); 35878c2ecf20Sopenharmony_ci break; 35888c2ecf20Sopenharmony_ci 35898c2ecf20Sopenharmony_ci case HCI_OP_LE_SET_ADV_SET_RAND_ADDR: 35908c2ecf20Sopenharmony_ci hci_cc_le_set_adv_set_random_addr(hdev, skb); 35918c2ecf20Sopenharmony_ci break; 35928c2ecf20Sopenharmony_ci 35938c2ecf20Sopenharmony_ci default: 35948c2ecf20Sopenharmony_ci BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode); 35958c2ecf20Sopenharmony_ci break; 35968c2ecf20Sopenharmony_ci } 35978c2ecf20Sopenharmony_ci 35988c2ecf20Sopenharmony_ci if (*opcode != HCI_OP_NOP) 35998c2ecf20Sopenharmony_ci cancel_delayed_work(&hdev->cmd_timer); 36008c2ecf20Sopenharmony_ci 36018c2ecf20Sopenharmony_ci if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) 36028c2ecf20Sopenharmony_ci atomic_set(&hdev->cmd_cnt, 1); 36038c2ecf20Sopenharmony_ci 36048c2ecf20Sopenharmony_ci hci_req_cmd_complete(hdev, *opcode, *status, req_complete, 36058c2ecf20Sopenharmony_ci req_complete_skb); 36068c2ecf20Sopenharmony_ci 36078c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_CMD_PENDING)) { 36088c2ecf20Sopenharmony_ci bt_dev_err(hdev, 36098c2ecf20Sopenharmony_ci "unexpected event for opcode 0x%4.4x", *opcode); 36108c2ecf20Sopenharmony_ci return; 36118c2ecf20Sopenharmony_ci } 36128c2ecf20Sopenharmony_ci 36138c2ecf20Sopenharmony_ci if (atomic_read(&hdev->cmd_cnt) && !skb_queue_empty(&hdev->cmd_q)) 36148c2ecf20Sopenharmony_ci queue_work(hdev->workqueue, &hdev->cmd_work); 36158c2ecf20Sopenharmony_ci} 36168c2ecf20Sopenharmony_ci 36178c2ecf20Sopenharmony_cistatic void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb, 36188c2ecf20Sopenharmony_ci u16 *opcode, u8 *status, 36198c2ecf20Sopenharmony_ci hci_req_complete_t *req_complete, 36208c2ecf20Sopenharmony_ci hci_req_complete_skb_t *req_complete_skb) 36218c2ecf20Sopenharmony_ci{ 36228c2ecf20Sopenharmony_ci struct hci_ev_cmd_status *ev = (void *) skb->data; 36238c2ecf20Sopenharmony_ci 36248c2ecf20Sopenharmony_ci skb_pull(skb, sizeof(*ev)); 36258c2ecf20Sopenharmony_ci 36268c2ecf20Sopenharmony_ci *opcode = __le16_to_cpu(ev->opcode); 36278c2ecf20Sopenharmony_ci *status = ev->status; 36288c2ecf20Sopenharmony_ci 36298c2ecf20Sopenharmony_ci switch (*opcode) { 36308c2ecf20Sopenharmony_ci case HCI_OP_INQUIRY: 36318c2ecf20Sopenharmony_ci hci_cs_inquiry(hdev, ev->status); 36328c2ecf20Sopenharmony_ci break; 36338c2ecf20Sopenharmony_ci 36348c2ecf20Sopenharmony_ci case HCI_OP_CREATE_CONN: 36358c2ecf20Sopenharmony_ci hci_cs_create_conn(hdev, ev->status); 36368c2ecf20Sopenharmony_ci break; 36378c2ecf20Sopenharmony_ci 36388c2ecf20Sopenharmony_ci case HCI_OP_DISCONNECT: 36398c2ecf20Sopenharmony_ci hci_cs_disconnect(hdev, ev->status); 36408c2ecf20Sopenharmony_ci break; 36418c2ecf20Sopenharmony_ci 36428c2ecf20Sopenharmony_ci case HCI_OP_ADD_SCO: 36438c2ecf20Sopenharmony_ci hci_cs_add_sco(hdev, ev->status); 36448c2ecf20Sopenharmony_ci break; 36458c2ecf20Sopenharmony_ci 36468c2ecf20Sopenharmony_ci case HCI_OP_AUTH_REQUESTED: 36478c2ecf20Sopenharmony_ci hci_cs_auth_requested(hdev, ev->status); 36488c2ecf20Sopenharmony_ci break; 36498c2ecf20Sopenharmony_ci 36508c2ecf20Sopenharmony_ci case HCI_OP_SET_CONN_ENCRYPT: 36518c2ecf20Sopenharmony_ci hci_cs_set_conn_encrypt(hdev, ev->status); 36528c2ecf20Sopenharmony_ci break; 36538c2ecf20Sopenharmony_ci 36548c2ecf20Sopenharmony_ci case HCI_OP_REMOTE_NAME_REQ: 36558c2ecf20Sopenharmony_ci hci_cs_remote_name_req(hdev, ev->status); 36568c2ecf20Sopenharmony_ci break; 36578c2ecf20Sopenharmony_ci 36588c2ecf20Sopenharmony_ci case HCI_OP_READ_REMOTE_FEATURES: 36598c2ecf20Sopenharmony_ci hci_cs_read_remote_features(hdev, ev->status); 36608c2ecf20Sopenharmony_ci break; 36618c2ecf20Sopenharmony_ci 36628c2ecf20Sopenharmony_ci case HCI_OP_READ_REMOTE_EXT_FEATURES: 36638c2ecf20Sopenharmony_ci hci_cs_read_remote_ext_features(hdev, ev->status); 36648c2ecf20Sopenharmony_ci break; 36658c2ecf20Sopenharmony_ci 36668c2ecf20Sopenharmony_ci case HCI_OP_SETUP_SYNC_CONN: 36678c2ecf20Sopenharmony_ci hci_cs_setup_sync_conn(hdev, ev->status); 36688c2ecf20Sopenharmony_ci break; 36698c2ecf20Sopenharmony_ci 36708c2ecf20Sopenharmony_ci case HCI_OP_SNIFF_MODE: 36718c2ecf20Sopenharmony_ci hci_cs_sniff_mode(hdev, ev->status); 36728c2ecf20Sopenharmony_ci break; 36738c2ecf20Sopenharmony_ci 36748c2ecf20Sopenharmony_ci case HCI_OP_EXIT_SNIFF_MODE: 36758c2ecf20Sopenharmony_ci hci_cs_exit_sniff_mode(hdev, ev->status); 36768c2ecf20Sopenharmony_ci break; 36778c2ecf20Sopenharmony_ci 36788c2ecf20Sopenharmony_ci case HCI_OP_SWITCH_ROLE: 36798c2ecf20Sopenharmony_ci hci_cs_switch_role(hdev, ev->status); 36808c2ecf20Sopenharmony_ci break; 36818c2ecf20Sopenharmony_ci 36828c2ecf20Sopenharmony_ci case HCI_OP_LE_CREATE_CONN: 36838c2ecf20Sopenharmony_ci hci_cs_le_create_conn(hdev, ev->status); 36848c2ecf20Sopenharmony_ci break; 36858c2ecf20Sopenharmony_ci 36868c2ecf20Sopenharmony_ci case HCI_OP_LE_READ_REMOTE_FEATURES: 36878c2ecf20Sopenharmony_ci hci_cs_le_read_remote_features(hdev, ev->status); 36888c2ecf20Sopenharmony_ci break; 36898c2ecf20Sopenharmony_ci 36908c2ecf20Sopenharmony_ci case HCI_OP_LE_START_ENC: 36918c2ecf20Sopenharmony_ci hci_cs_le_start_enc(hdev, ev->status); 36928c2ecf20Sopenharmony_ci break; 36938c2ecf20Sopenharmony_ci 36948c2ecf20Sopenharmony_ci case HCI_OP_LE_EXT_CREATE_CONN: 36958c2ecf20Sopenharmony_ci hci_cs_le_ext_create_conn(hdev, ev->status); 36968c2ecf20Sopenharmony_ci break; 36978c2ecf20Sopenharmony_ci 36988c2ecf20Sopenharmony_ci default: 36998c2ecf20Sopenharmony_ci BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode); 37008c2ecf20Sopenharmony_ci break; 37018c2ecf20Sopenharmony_ci } 37028c2ecf20Sopenharmony_ci 37038c2ecf20Sopenharmony_ci if (*opcode != HCI_OP_NOP) 37048c2ecf20Sopenharmony_ci cancel_delayed_work(&hdev->cmd_timer); 37058c2ecf20Sopenharmony_ci 37068c2ecf20Sopenharmony_ci if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) 37078c2ecf20Sopenharmony_ci atomic_set(&hdev->cmd_cnt, 1); 37088c2ecf20Sopenharmony_ci 37098c2ecf20Sopenharmony_ci /* Indicate request completion if the command failed. Also, if 37108c2ecf20Sopenharmony_ci * we're not waiting for a special event and we get a success 37118c2ecf20Sopenharmony_ci * command status we should try to flag the request as completed 37128c2ecf20Sopenharmony_ci * (since for this kind of commands there will not be a command 37138c2ecf20Sopenharmony_ci * complete event). 37148c2ecf20Sopenharmony_ci */ 37158c2ecf20Sopenharmony_ci if (ev->status || 37168c2ecf20Sopenharmony_ci (hdev->sent_cmd && !bt_cb(hdev->sent_cmd)->hci.req_event)) 37178c2ecf20Sopenharmony_ci hci_req_cmd_complete(hdev, *opcode, ev->status, req_complete, 37188c2ecf20Sopenharmony_ci req_complete_skb); 37198c2ecf20Sopenharmony_ci 37208c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_CMD_PENDING)) { 37218c2ecf20Sopenharmony_ci bt_dev_err(hdev, 37228c2ecf20Sopenharmony_ci "unexpected event for opcode 0x%4.4x", *opcode); 37238c2ecf20Sopenharmony_ci return; 37248c2ecf20Sopenharmony_ci } 37258c2ecf20Sopenharmony_ci 37268c2ecf20Sopenharmony_ci if (atomic_read(&hdev->cmd_cnt) && !skb_queue_empty(&hdev->cmd_q)) 37278c2ecf20Sopenharmony_ci queue_work(hdev->workqueue, &hdev->cmd_work); 37288c2ecf20Sopenharmony_ci} 37298c2ecf20Sopenharmony_ci 37308c2ecf20Sopenharmony_cistatic void hci_hardware_error_evt(struct hci_dev *hdev, struct sk_buff *skb) 37318c2ecf20Sopenharmony_ci{ 37328c2ecf20Sopenharmony_ci struct hci_ev_hardware_error *ev = (void *) skb->data; 37338c2ecf20Sopenharmony_ci 37348c2ecf20Sopenharmony_ci hdev->hw_error_code = ev->code; 37358c2ecf20Sopenharmony_ci 37368c2ecf20Sopenharmony_ci queue_work(hdev->req_workqueue, &hdev->error_reset); 37378c2ecf20Sopenharmony_ci} 37388c2ecf20Sopenharmony_ci 37398c2ecf20Sopenharmony_cistatic void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 37408c2ecf20Sopenharmony_ci{ 37418c2ecf20Sopenharmony_ci struct hci_ev_role_change *ev = (void *) skb->data; 37428c2ecf20Sopenharmony_ci struct hci_conn *conn; 37438c2ecf20Sopenharmony_ci 37448c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 37458c2ecf20Sopenharmony_ci 37468c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 37478c2ecf20Sopenharmony_ci 37488c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 37498c2ecf20Sopenharmony_ci if (conn) { 37508c2ecf20Sopenharmony_ci if (!ev->status) 37518c2ecf20Sopenharmony_ci conn->role = ev->role; 37528c2ecf20Sopenharmony_ci 37538c2ecf20Sopenharmony_ci clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); 37548c2ecf20Sopenharmony_ci 37558c2ecf20Sopenharmony_ci hci_role_switch_cfm(conn, ev->status, ev->role); 37568c2ecf20Sopenharmony_ci } 37578c2ecf20Sopenharmony_ci 37588c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 37598c2ecf20Sopenharmony_ci} 37608c2ecf20Sopenharmony_ci 37618c2ecf20Sopenharmony_cistatic void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 37628c2ecf20Sopenharmony_ci{ 37638c2ecf20Sopenharmony_ci struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 37648c2ecf20Sopenharmony_ci int i; 37658c2ecf20Sopenharmony_ci 37668c2ecf20Sopenharmony_ci if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) { 37678c2ecf20Sopenharmony_ci bt_dev_err(hdev, "wrong event for mode %d", hdev->flow_ctl_mode); 37688c2ecf20Sopenharmony_ci return; 37698c2ecf20Sopenharmony_ci } 37708c2ecf20Sopenharmony_ci 37718c2ecf20Sopenharmony_ci if (skb->len < sizeof(*ev) || 37728c2ecf20Sopenharmony_ci skb->len < struct_size(ev, handles, ev->num_hndl)) { 37738c2ecf20Sopenharmony_ci BT_DBG("%s bad parameters", hdev->name); 37748c2ecf20Sopenharmony_ci return; 37758c2ecf20Sopenharmony_ci } 37768c2ecf20Sopenharmony_ci 37778c2ecf20Sopenharmony_ci BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 37788c2ecf20Sopenharmony_ci 37798c2ecf20Sopenharmony_ci for (i = 0; i < ev->num_hndl; i++) { 37808c2ecf20Sopenharmony_ci struct hci_comp_pkts_info *info = &ev->handles[i]; 37818c2ecf20Sopenharmony_ci struct hci_conn *conn; 37828c2ecf20Sopenharmony_ci __u16 handle, count; 37838c2ecf20Sopenharmony_ci 37848c2ecf20Sopenharmony_ci handle = __le16_to_cpu(info->handle); 37858c2ecf20Sopenharmony_ci count = __le16_to_cpu(info->count); 37868c2ecf20Sopenharmony_ci 37878c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, handle); 37888c2ecf20Sopenharmony_ci if (!conn) 37898c2ecf20Sopenharmony_ci continue; 37908c2ecf20Sopenharmony_ci 37918c2ecf20Sopenharmony_ci conn->sent -= count; 37928c2ecf20Sopenharmony_ci 37938c2ecf20Sopenharmony_ci switch (conn->type) { 37948c2ecf20Sopenharmony_ci case ACL_LINK: 37958c2ecf20Sopenharmony_ci hdev->acl_cnt += count; 37968c2ecf20Sopenharmony_ci if (hdev->acl_cnt > hdev->acl_pkts) 37978c2ecf20Sopenharmony_ci hdev->acl_cnt = hdev->acl_pkts; 37988c2ecf20Sopenharmony_ci break; 37998c2ecf20Sopenharmony_ci 38008c2ecf20Sopenharmony_ci case LE_LINK: 38018c2ecf20Sopenharmony_ci if (hdev->le_pkts) { 38028c2ecf20Sopenharmony_ci hdev->le_cnt += count; 38038c2ecf20Sopenharmony_ci if (hdev->le_cnt > hdev->le_pkts) 38048c2ecf20Sopenharmony_ci hdev->le_cnt = hdev->le_pkts; 38058c2ecf20Sopenharmony_ci } else { 38068c2ecf20Sopenharmony_ci hdev->acl_cnt += count; 38078c2ecf20Sopenharmony_ci if (hdev->acl_cnt > hdev->acl_pkts) 38088c2ecf20Sopenharmony_ci hdev->acl_cnt = hdev->acl_pkts; 38098c2ecf20Sopenharmony_ci } 38108c2ecf20Sopenharmony_ci break; 38118c2ecf20Sopenharmony_ci 38128c2ecf20Sopenharmony_ci case SCO_LINK: 38138c2ecf20Sopenharmony_ci hdev->sco_cnt += count; 38148c2ecf20Sopenharmony_ci if (hdev->sco_cnt > hdev->sco_pkts) 38158c2ecf20Sopenharmony_ci hdev->sco_cnt = hdev->sco_pkts; 38168c2ecf20Sopenharmony_ci break; 38178c2ecf20Sopenharmony_ci 38188c2ecf20Sopenharmony_ci default: 38198c2ecf20Sopenharmony_ci bt_dev_err(hdev, "unknown type %d conn %p", 38208c2ecf20Sopenharmony_ci conn->type, conn); 38218c2ecf20Sopenharmony_ci break; 38228c2ecf20Sopenharmony_ci } 38238c2ecf20Sopenharmony_ci } 38248c2ecf20Sopenharmony_ci 38258c2ecf20Sopenharmony_ci queue_work(hdev->workqueue, &hdev->tx_work); 38268c2ecf20Sopenharmony_ci} 38278c2ecf20Sopenharmony_ci 38288c2ecf20Sopenharmony_cistatic struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev, 38298c2ecf20Sopenharmony_ci __u16 handle) 38308c2ecf20Sopenharmony_ci{ 38318c2ecf20Sopenharmony_ci struct hci_chan *chan; 38328c2ecf20Sopenharmony_ci 38338c2ecf20Sopenharmony_ci switch (hdev->dev_type) { 38348c2ecf20Sopenharmony_ci case HCI_PRIMARY: 38358c2ecf20Sopenharmony_ci return hci_conn_hash_lookup_handle(hdev, handle); 38368c2ecf20Sopenharmony_ci case HCI_AMP: 38378c2ecf20Sopenharmony_ci chan = hci_chan_lookup_handle(hdev, handle); 38388c2ecf20Sopenharmony_ci if (chan) 38398c2ecf20Sopenharmony_ci return chan->conn; 38408c2ecf20Sopenharmony_ci break; 38418c2ecf20Sopenharmony_ci default: 38428c2ecf20Sopenharmony_ci bt_dev_err(hdev, "unknown dev_type %d", hdev->dev_type); 38438c2ecf20Sopenharmony_ci break; 38448c2ecf20Sopenharmony_ci } 38458c2ecf20Sopenharmony_ci 38468c2ecf20Sopenharmony_ci return NULL; 38478c2ecf20Sopenharmony_ci} 38488c2ecf20Sopenharmony_ci 38498c2ecf20Sopenharmony_cistatic void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb) 38508c2ecf20Sopenharmony_ci{ 38518c2ecf20Sopenharmony_ci struct hci_ev_num_comp_blocks *ev = (void *) skb->data; 38528c2ecf20Sopenharmony_ci int i; 38538c2ecf20Sopenharmony_ci 38548c2ecf20Sopenharmony_ci if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) { 38558c2ecf20Sopenharmony_ci bt_dev_err(hdev, "wrong event for mode %d", hdev->flow_ctl_mode); 38568c2ecf20Sopenharmony_ci return; 38578c2ecf20Sopenharmony_ci } 38588c2ecf20Sopenharmony_ci 38598c2ecf20Sopenharmony_ci if (skb->len < sizeof(*ev) || 38608c2ecf20Sopenharmony_ci skb->len < struct_size(ev, handles, ev->num_hndl)) { 38618c2ecf20Sopenharmony_ci BT_DBG("%s bad parameters", hdev->name); 38628c2ecf20Sopenharmony_ci return; 38638c2ecf20Sopenharmony_ci } 38648c2ecf20Sopenharmony_ci 38658c2ecf20Sopenharmony_ci BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks, 38668c2ecf20Sopenharmony_ci ev->num_hndl); 38678c2ecf20Sopenharmony_ci 38688c2ecf20Sopenharmony_ci for (i = 0; i < ev->num_hndl; i++) { 38698c2ecf20Sopenharmony_ci struct hci_comp_blocks_info *info = &ev->handles[i]; 38708c2ecf20Sopenharmony_ci struct hci_conn *conn = NULL; 38718c2ecf20Sopenharmony_ci __u16 handle, block_count; 38728c2ecf20Sopenharmony_ci 38738c2ecf20Sopenharmony_ci handle = __le16_to_cpu(info->handle); 38748c2ecf20Sopenharmony_ci block_count = __le16_to_cpu(info->blocks); 38758c2ecf20Sopenharmony_ci 38768c2ecf20Sopenharmony_ci conn = __hci_conn_lookup_handle(hdev, handle); 38778c2ecf20Sopenharmony_ci if (!conn) 38788c2ecf20Sopenharmony_ci continue; 38798c2ecf20Sopenharmony_ci 38808c2ecf20Sopenharmony_ci conn->sent -= block_count; 38818c2ecf20Sopenharmony_ci 38828c2ecf20Sopenharmony_ci switch (conn->type) { 38838c2ecf20Sopenharmony_ci case ACL_LINK: 38848c2ecf20Sopenharmony_ci case AMP_LINK: 38858c2ecf20Sopenharmony_ci hdev->block_cnt += block_count; 38868c2ecf20Sopenharmony_ci if (hdev->block_cnt > hdev->num_blocks) 38878c2ecf20Sopenharmony_ci hdev->block_cnt = hdev->num_blocks; 38888c2ecf20Sopenharmony_ci break; 38898c2ecf20Sopenharmony_ci 38908c2ecf20Sopenharmony_ci default: 38918c2ecf20Sopenharmony_ci bt_dev_err(hdev, "unknown type %d conn %p", 38928c2ecf20Sopenharmony_ci conn->type, conn); 38938c2ecf20Sopenharmony_ci break; 38948c2ecf20Sopenharmony_ci } 38958c2ecf20Sopenharmony_ci } 38968c2ecf20Sopenharmony_ci 38978c2ecf20Sopenharmony_ci queue_work(hdev->workqueue, &hdev->tx_work); 38988c2ecf20Sopenharmony_ci} 38998c2ecf20Sopenharmony_ci 39008c2ecf20Sopenharmony_cistatic void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 39018c2ecf20Sopenharmony_ci{ 39028c2ecf20Sopenharmony_ci struct hci_ev_mode_change *ev = (void *) skb->data; 39038c2ecf20Sopenharmony_ci struct hci_conn *conn; 39048c2ecf20Sopenharmony_ci 39058c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 39068c2ecf20Sopenharmony_ci 39078c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 39088c2ecf20Sopenharmony_ci 39098c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 39108c2ecf20Sopenharmony_ci if (conn) { 39118c2ecf20Sopenharmony_ci conn->mode = ev->mode; 39128c2ecf20Sopenharmony_ci 39138c2ecf20Sopenharmony_ci if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, 39148c2ecf20Sopenharmony_ci &conn->flags)) { 39158c2ecf20Sopenharmony_ci if (conn->mode == HCI_CM_ACTIVE) 39168c2ecf20Sopenharmony_ci set_bit(HCI_CONN_POWER_SAVE, &conn->flags); 39178c2ecf20Sopenharmony_ci else 39188c2ecf20Sopenharmony_ci clear_bit(HCI_CONN_POWER_SAVE, &conn->flags); 39198c2ecf20Sopenharmony_ci } 39208c2ecf20Sopenharmony_ci 39218c2ecf20Sopenharmony_ci if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 39228c2ecf20Sopenharmony_ci hci_sco_setup(conn, ev->status); 39238c2ecf20Sopenharmony_ci } 39248c2ecf20Sopenharmony_ci 39258c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 39268c2ecf20Sopenharmony_ci} 39278c2ecf20Sopenharmony_ci 39288c2ecf20Sopenharmony_cistatic void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 39298c2ecf20Sopenharmony_ci{ 39308c2ecf20Sopenharmony_ci struct hci_ev_pin_code_req *ev = (void *) skb->data; 39318c2ecf20Sopenharmony_ci struct hci_conn *conn; 39328c2ecf20Sopenharmony_ci 39338c2ecf20Sopenharmony_ci BT_DBG("%s", hdev->name); 39348c2ecf20Sopenharmony_ci 39358c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 39368c2ecf20Sopenharmony_ci 39378c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 39388c2ecf20Sopenharmony_ci if (!conn) 39398c2ecf20Sopenharmony_ci goto unlock; 39408c2ecf20Sopenharmony_ci 39418c2ecf20Sopenharmony_ci if (conn->state == BT_CONNECTED) { 39428c2ecf20Sopenharmony_ci hci_conn_hold(conn); 39438c2ecf20Sopenharmony_ci conn->disc_timeout = HCI_PAIRING_TIMEOUT; 39448c2ecf20Sopenharmony_ci hci_conn_drop(conn); 39458c2ecf20Sopenharmony_ci } 39468c2ecf20Sopenharmony_ci 39478c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_BONDABLE) && 39488c2ecf20Sopenharmony_ci !test_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags)) { 39498c2ecf20Sopenharmony_ci hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 39508c2ecf20Sopenharmony_ci sizeof(ev->bdaddr), &ev->bdaddr); 39518c2ecf20Sopenharmony_ci } else if (hci_dev_test_flag(hdev, HCI_MGMT)) { 39528c2ecf20Sopenharmony_ci u8 secure; 39538c2ecf20Sopenharmony_ci 39548c2ecf20Sopenharmony_ci if (conn->pending_sec_level == BT_SECURITY_HIGH) 39558c2ecf20Sopenharmony_ci secure = 1; 39568c2ecf20Sopenharmony_ci else 39578c2ecf20Sopenharmony_ci secure = 0; 39588c2ecf20Sopenharmony_ci 39598c2ecf20Sopenharmony_ci mgmt_pin_code_request(hdev, &ev->bdaddr, secure); 39608c2ecf20Sopenharmony_ci } 39618c2ecf20Sopenharmony_ci 39628c2ecf20Sopenharmony_ciunlock: 39638c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 39648c2ecf20Sopenharmony_ci} 39658c2ecf20Sopenharmony_ci 39668c2ecf20Sopenharmony_cistatic void conn_set_key(struct hci_conn *conn, u8 key_type, u8 pin_len) 39678c2ecf20Sopenharmony_ci{ 39688c2ecf20Sopenharmony_ci if (key_type == HCI_LK_CHANGED_COMBINATION) 39698c2ecf20Sopenharmony_ci return; 39708c2ecf20Sopenharmony_ci 39718c2ecf20Sopenharmony_ci conn->pin_length = pin_len; 39728c2ecf20Sopenharmony_ci conn->key_type = key_type; 39738c2ecf20Sopenharmony_ci 39748c2ecf20Sopenharmony_ci switch (key_type) { 39758c2ecf20Sopenharmony_ci case HCI_LK_LOCAL_UNIT: 39768c2ecf20Sopenharmony_ci case HCI_LK_REMOTE_UNIT: 39778c2ecf20Sopenharmony_ci case HCI_LK_DEBUG_COMBINATION: 39788c2ecf20Sopenharmony_ci return; 39798c2ecf20Sopenharmony_ci case HCI_LK_COMBINATION: 39808c2ecf20Sopenharmony_ci if (pin_len == 16) 39818c2ecf20Sopenharmony_ci conn->pending_sec_level = BT_SECURITY_HIGH; 39828c2ecf20Sopenharmony_ci else 39838c2ecf20Sopenharmony_ci conn->pending_sec_level = BT_SECURITY_MEDIUM; 39848c2ecf20Sopenharmony_ci break; 39858c2ecf20Sopenharmony_ci case HCI_LK_UNAUTH_COMBINATION_P192: 39868c2ecf20Sopenharmony_ci case HCI_LK_UNAUTH_COMBINATION_P256: 39878c2ecf20Sopenharmony_ci conn->pending_sec_level = BT_SECURITY_MEDIUM; 39888c2ecf20Sopenharmony_ci break; 39898c2ecf20Sopenharmony_ci case HCI_LK_AUTH_COMBINATION_P192: 39908c2ecf20Sopenharmony_ci conn->pending_sec_level = BT_SECURITY_HIGH; 39918c2ecf20Sopenharmony_ci break; 39928c2ecf20Sopenharmony_ci case HCI_LK_AUTH_COMBINATION_P256: 39938c2ecf20Sopenharmony_ci conn->pending_sec_level = BT_SECURITY_FIPS; 39948c2ecf20Sopenharmony_ci break; 39958c2ecf20Sopenharmony_ci } 39968c2ecf20Sopenharmony_ci} 39978c2ecf20Sopenharmony_ci 39988c2ecf20Sopenharmony_cistatic void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 39998c2ecf20Sopenharmony_ci{ 40008c2ecf20Sopenharmony_ci struct hci_ev_link_key_req *ev = (void *) skb->data; 40018c2ecf20Sopenharmony_ci struct hci_cp_link_key_reply cp; 40028c2ecf20Sopenharmony_ci struct hci_conn *conn; 40038c2ecf20Sopenharmony_ci struct link_key *key; 40048c2ecf20Sopenharmony_ci 40058c2ecf20Sopenharmony_ci BT_DBG("%s", hdev->name); 40068c2ecf20Sopenharmony_ci 40078c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_MGMT)) 40088c2ecf20Sopenharmony_ci return; 40098c2ecf20Sopenharmony_ci 40108c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 40118c2ecf20Sopenharmony_ci 40128c2ecf20Sopenharmony_ci key = hci_find_link_key(hdev, &ev->bdaddr); 40138c2ecf20Sopenharmony_ci if (!key) { 40148c2ecf20Sopenharmony_ci BT_DBG("%s link key not found for %pMR", hdev->name, 40158c2ecf20Sopenharmony_ci &ev->bdaddr); 40168c2ecf20Sopenharmony_ci goto not_found; 40178c2ecf20Sopenharmony_ci } 40188c2ecf20Sopenharmony_ci 40198c2ecf20Sopenharmony_ci BT_DBG("%s found key type %u for %pMR", hdev->name, key->type, 40208c2ecf20Sopenharmony_ci &ev->bdaddr); 40218c2ecf20Sopenharmony_ci 40228c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 40238c2ecf20Sopenharmony_ci if (conn) { 40248c2ecf20Sopenharmony_ci clear_bit(HCI_CONN_NEW_LINK_KEY, &conn->flags); 40258c2ecf20Sopenharmony_ci 40268c2ecf20Sopenharmony_ci if ((key->type == HCI_LK_UNAUTH_COMBINATION_P192 || 40278c2ecf20Sopenharmony_ci key->type == HCI_LK_UNAUTH_COMBINATION_P256) && 40288c2ecf20Sopenharmony_ci conn->auth_type != 0xff && (conn->auth_type & 0x01)) { 40298c2ecf20Sopenharmony_ci BT_DBG("%s ignoring unauthenticated key", hdev->name); 40308c2ecf20Sopenharmony_ci goto not_found; 40318c2ecf20Sopenharmony_ci } 40328c2ecf20Sopenharmony_ci 40338c2ecf20Sopenharmony_ci if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && 40348c2ecf20Sopenharmony_ci (conn->pending_sec_level == BT_SECURITY_HIGH || 40358c2ecf20Sopenharmony_ci conn->pending_sec_level == BT_SECURITY_FIPS)) { 40368c2ecf20Sopenharmony_ci BT_DBG("%s ignoring key unauthenticated for high security", 40378c2ecf20Sopenharmony_ci hdev->name); 40388c2ecf20Sopenharmony_ci goto not_found; 40398c2ecf20Sopenharmony_ci } 40408c2ecf20Sopenharmony_ci 40418c2ecf20Sopenharmony_ci conn_set_key(conn, key->type, key->pin_len); 40428c2ecf20Sopenharmony_ci } 40438c2ecf20Sopenharmony_ci 40448c2ecf20Sopenharmony_ci bacpy(&cp.bdaddr, &ev->bdaddr); 40458c2ecf20Sopenharmony_ci memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE); 40468c2ecf20Sopenharmony_ci 40478c2ecf20Sopenharmony_ci hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 40488c2ecf20Sopenharmony_ci 40498c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 40508c2ecf20Sopenharmony_ci 40518c2ecf20Sopenharmony_ci return; 40528c2ecf20Sopenharmony_ci 40538c2ecf20Sopenharmony_cinot_found: 40548c2ecf20Sopenharmony_ci hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 40558c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 40568c2ecf20Sopenharmony_ci} 40578c2ecf20Sopenharmony_ci 40588c2ecf20Sopenharmony_cistatic void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 40598c2ecf20Sopenharmony_ci{ 40608c2ecf20Sopenharmony_ci struct hci_ev_link_key_notify *ev = (void *) skb->data; 40618c2ecf20Sopenharmony_ci struct hci_conn *conn; 40628c2ecf20Sopenharmony_ci struct link_key *key; 40638c2ecf20Sopenharmony_ci bool persistent; 40648c2ecf20Sopenharmony_ci u8 pin_len = 0; 40658c2ecf20Sopenharmony_ci 40668c2ecf20Sopenharmony_ci BT_DBG("%s", hdev->name); 40678c2ecf20Sopenharmony_ci 40688c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 40698c2ecf20Sopenharmony_ci 40708c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 40718c2ecf20Sopenharmony_ci if (!conn) 40728c2ecf20Sopenharmony_ci goto unlock; 40738c2ecf20Sopenharmony_ci 40748c2ecf20Sopenharmony_ci /* Ignore NULL link key against CVE-2020-26555 */ 40758c2ecf20Sopenharmony_ci if (!crypto_memneq(ev->link_key, ZERO_KEY, HCI_LINK_KEY_SIZE)) { 40768c2ecf20Sopenharmony_ci bt_dev_dbg(hdev, "Ignore NULL link key (ZERO KEY) for %pMR", 40778c2ecf20Sopenharmony_ci &ev->bdaddr); 40788c2ecf20Sopenharmony_ci hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); 40798c2ecf20Sopenharmony_ci hci_conn_drop(conn); 40808c2ecf20Sopenharmony_ci goto unlock; 40818c2ecf20Sopenharmony_ci } 40828c2ecf20Sopenharmony_ci 40838c2ecf20Sopenharmony_ci hci_conn_hold(conn); 40848c2ecf20Sopenharmony_ci conn->disc_timeout = HCI_DISCONN_TIMEOUT; 40858c2ecf20Sopenharmony_ci hci_conn_drop(conn); 40868c2ecf20Sopenharmony_ci 40878c2ecf20Sopenharmony_ci set_bit(HCI_CONN_NEW_LINK_KEY, &conn->flags); 40888c2ecf20Sopenharmony_ci conn_set_key(conn, ev->key_type, conn->pin_length); 40898c2ecf20Sopenharmony_ci 40908c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_MGMT)) 40918c2ecf20Sopenharmony_ci goto unlock; 40928c2ecf20Sopenharmony_ci 40938c2ecf20Sopenharmony_ci key = hci_add_link_key(hdev, conn, &ev->bdaddr, ev->link_key, 40948c2ecf20Sopenharmony_ci ev->key_type, pin_len, &persistent); 40958c2ecf20Sopenharmony_ci if (!key) 40968c2ecf20Sopenharmony_ci goto unlock; 40978c2ecf20Sopenharmony_ci 40988c2ecf20Sopenharmony_ci /* Update connection information since adding the key will have 40998c2ecf20Sopenharmony_ci * fixed up the type in the case of changed combination keys. 41008c2ecf20Sopenharmony_ci */ 41018c2ecf20Sopenharmony_ci if (ev->key_type == HCI_LK_CHANGED_COMBINATION) 41028c2ecf20Sopenharmony_ci conn_set_key(conn, key->type, key->pin_len); 41038c2ecf20Sopenharmony_ci 41048c2ecf20Sopenharmony_ci mgmt_new_link_key(hdev, key, persistent); 41058c2ecf20Sopenharmony_ci 41068c2ecf20Sopenharmony_ci /* Keep debug keys around only if the HCI_KEEP_DEBUG_KEYS flag 41078c2ecf20Sopenharmony_ci * is set. If it's not set simply remove the key from the kernel 41088c2ecf20Sopenharmony_ci * list (we've still notified user space about it but with 41098c2ecf20Sopenharmony_ci * store_hint being 0). 41108c2ecf20Sopenharmony_ci */ 41118c2ecf20Sopenharmony_ci if (key->type == HCI_LK_DEBUG_COMBINATION && 41128c2ecf20Sopenharmony_ci !hci_dev_test_flag(hdev, HCI_KEEP_DEBUG_KEYS)) { 41138c2ecf20Sopenharmony_ci list_del_rcu(&key->list); 41148c2ecf20Sopenharmony_ci kfree_rcu(key, rcu); 41158c2ecf20Sopenharmony_ci goto unlock; 41168c2ecf20Sopenharmony_ci } 41178c2ecf20Sopenharmony_ci 41188c2ecf20Sopenharmony_ci if (persistent) 41198c2ecf20Sopenharmony_ci clear_bit(HCI_CONN_FLUSH_KEY, &conn->flags); 41208c2ecf20Sopenharmony_ci else 41218c2ecf20Sopenharmony_ci set_bit(HCI_CONN_FLUSH_KEY, &conn->flags); 41228c2ecf20Sopenharmony_ci 41238c2ecf20Sopenharmony_ciunlock: 41248c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 41258c2ecf20Sopenharmony_ci} 41268c2ecf20Sopenharmony_ci 41278c2ecf20Sopenharmony_cistatic void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 41288c2ecf20Sopenharmony_ci{ 41298c2ecf20Sopenharmony_ci struct hci_ev_clock_offset *ev = (void *) skb->data; 41308c2ecf20Sopenharmony_ci struct hci_conn *conn; 41318c2ecf20Sopenharmony_ci 41328c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 41338c2ecf20Sopenharmony_ci 41348c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 41358c2ecf20Sopenharmony_ci 41368c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 41378c2ecf20Sopenharmony_ci if (conn && !ev->status) { 41388c2ecf20Sopenharmony_ci struct inquiry_entry *ie; 41398c2ecf20Sopenharmony_ci 41408c2ecf20Sopenharmony_ci ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 41418c2ecf20Sopenharmony_ci if (ie) { 41428c2ecf20Sopenharmony_ci ie->data.clock_offset = ev->clock_offset; 41438c2ecf20Sopenharmony_ci ie->timestamp = jiffies; 41448c2ecf20Sopenharmony_ci } 41458c2ecf20Sopenharmony_ci } 41468c2ecf20Sopenharmony_ci 41478c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 41488c2ecf20Sopenharmony_ci} 41498c2ecf20Sopenharmony_ci 41508c2ecf20Sopenharmony_cistatic void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 41518c2ecf20Sopenharmony_ci{ 41528c2ecf20Sopenharmony_ci struct hci_ev_pkt_type_change *ev = (void *) skb->data; 41538c2ecf20Sopenharmony_ci struct hci_conn *conn; 41548c2ecf20Sopenharmony_ci 41558c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 41568c2ecf20Sopenharmony_ci 41578c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 41588c2ecf20Sopenharmony_ci 41598c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 41608c2ecf20Sopenharmony_ci if (conn && !ev->status) 41618c2ecf20Sopenharmony_ci conn->pkt_type = __le16_to_cpu(ev->pkt_type); 41628c2ecf20Sopenharmony_ci 41638c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 41648c2ecf20Sopenharmony_ci} 41658c2ecf20Sopenharmony_ci 41668c2ecf20Sopenharmony_cistatic void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 41678c2ecf20Sopenharmony_ci{ 41688c2ecf20Sopenharmony_ci struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 41698c2ecf20Sopenharmony_ci struct inquiry_entry *ie; 41708c2ecf20Sopenharmony_ci 41718c2ecf20Sopenharmony_ci BT_DBG("%s", hdev->name); 41728c2ecf20Sopenharmony_ci 41738c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 41748c2ecf20Sopenharmony_ci 41758c2ecf20Sopenharmony_ci ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 41768c2ecf20Sopenharmony_ci if (ie) { 41778c2ecf20Sopenharmony_ci ie->data.pscan_rep_mode = ev->pscan_rep_mode; 41788c2ecf20Sopenharmony_ci ie->timestamp = jiffies; 41798c2ecf20Sopenharmony_ci } 41808c2ecf20Sopenharmony_ci 41818c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 41828c2ecf20Sopenharmony_ci} 41838c2ecf20Sopenharmony_ci 41848c2ecf20Sopenharmony_cistatic void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, 41858c2ecf20Sopenharmony_ci struct sk_buff *skb) 41868c2ecf20Sopenharmony_ci{ 41878c2ecf20Sopenharmony_ci struct inquiry_data data; 41888c2ecf20Sopenharmony_ci int num_rsp = *((__u8 *) skb->data); 41898c2ecf20Sopenharmony_ci 41908c2ecf20Sopenharmony_ci BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 41918c2ecf20Sopenharmony_ci 41928c2ecf20Sopenharmony_ci if (!num_rsp) 41938c2ecf20Sopenharmony_ci return; 41948c2ecf20Sopenharmony_ci 41958c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) 41968c2ecf20Sopenharmony_ci return; 41978c2ecf20Sopenharmony_ci 41988c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 41998c2ecf20Sopenharmony_ci 42008c2ecf20Sopenharmony_ci if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 42018c2ecf20Sopenharmony_ci struct inquiry_info_with_rssi_and_pscan_mode *info; 42028c2ecf20Sopenharmony_ci info = (void *) (skb->data + 1); 42038c2ecf20Sopenharmony_ci 42048c2ecf20Sopenharmony_ci if (skb->len < num_rsp * sizeof(*info) + 1) 42058c2ecf20Sopenharmony_ci goto unlock; 42068c2ecf20Sopenharmony_ci 42078c2ecf20Sopenharmony_ci for (; num_rsp; num_rsp--, info++) { 42088c2ecf20Sopenharmony_ci u32 flags; 42098c2ecf20Sopenharmony_ci 42108c2ecf20Sopenharmony_ci bacpy(&data.bdaddr, &info->bdaddr); 42118c2ecf20Sopenharmony_ci data.pscan_rep_mode = info->pscan_rep_mode; 42128c2ecf20Sopenharmony_ci data.pscan_period_mode = info->pscan_period_mode; 42138c2ecf20Sopenharmony_ci data.pscan_mode = info->pscan_mode; 42148c2ecf20Sopenharmony_ci memcpy(data.dev_class, info->dev_class, 3); 42158c2ecf20Sopenharmony_ci data.clock_offset = info->clock_offset; 42168c2ecf20Sopenharmony_ci data.rssi = info->rssi; 42178c2ecf20Sopenharmony_ci data.ssp_mode = 0x00; 42188c2ecf20Sopenharmony_ci 42198c2ecf20Sopenharmony_ci flags = hci_inquiry_cache_update(hdev, &data, false); 42208c2ecf20Sopenharmony_ci 42218c2ecf20Sopenharmony_ci mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 42228c2ecf20Sopenharmony_ci info->dev_class, info->rssi, 42238c2ecf20Sopenharmony_ci flags, NULL, 0, NULL, 0); 42248c2ecf20Sopenharmony_ci } 42258c2ecf20Sopenharmony_ci } else { 42268c2ecf20Sopenharmony_ci struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 42278c2ecf20Sopenharmony_ci 42288c2ecf20Sopenharmony_ci if (skb->len < num_rsp * sizeof(*info) + 1) 42298c2ecf20Sopenharmony_ci goto unlock; 42308c2ecf20Sopenharmony_ci 42318c2ecf20Sopenharmony_ci for (; num_rsp; num_rsp--, info++) { 42328c2ecf20Sopenharmony_ci u32 flags; 42338c2ecf20Sopenharmony_ci 42348c2ecf20Sopenharmony_ci bacpy(&data.bdaddr, &info->bdaddr); 42358c2ecf20Sopenharmony_ci data.pscan_rep_mode = info->pscan_rep_mode; 42368c2ecf20Sopenharmony_ci data.pscan_period_mode = info->pscan_period_mode; 42378c2ecf20Sopenharmony_ci data.pscan_mode = 0x00; 42388c2ecf20Sopenharmony_ci memcpy(data.dev_class, info->dev_class, 3); 42398c2ecf20Sopenharmony_ci data.clock_offset = info->clock_offset; 42408c2ecf20Sopenharmony_ci data.rssi = info->rssi; 42418c2ecf20Sopenharmony_ci data.ssp_mode = 0x00; 42428c2ecf20Sopenharmony_ci 42438c2ecf20Sopenharmony_ci flags = hci_inquiry_cache_update(hdev, &data, false); 42448c2ecf20Sopenharmony_ci 42458c2ecf20Sopenharmony_ci mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 42468c2ecf20Sopenharmony_ci info->dev_class, info->rssi, 42478c2ecf20Sopenharmony_ci flags, NULL, 0, NULL, 0); 42488c2ecf20Sopenharmony_ci } 42498c2ecf20Sopenharmony_ci } 42508c2ecf20Sopenharmony_ci 42518c2ecf20Sopenharmony_ciunlock: 42528c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 42538c2ecf20Sopenharmony_ci} 42548c2ecf20Sopenharmony_ci 42558c2ecf20Sopenharmony_cistatic void hci_remote_ext_features_evt(struct hci_dev *hdev, 42568c2ecf20Sopenharmony_ci struct sk_buff *skb) 42578c2ecf20Sopenharmony_ci{ 42588c2ecf20Sopenharmony_ci struct hci_ev_remote_ext_features *ev = (void *) skb->data; 42598c2ecf20Sopenharmony_ci struct hci_conn *conn; 42608c2ecf20Sopenharmony_ci 42618c2ecf20Sopenharmony_ci BT_DBG("%s", hdev->name); 42628c2ecf20Sopenharmony_ci 42638c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 42648c2ecf20Sopenharmony_ci 42658c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 42668c2ecf20Sopenharmony_ci if (!conn) 42678c2ecf20Sopenharmony_ci goto unlock; 42688c2ecf20Sopenharmony_ci 42698c2ecf20Sopenharmony_ci if (ev->page < HCI_MAX_PAGES) 42708c2ecf20Sopenharmony_ci memcpy(conn->features[ev->page], ev->features, 8); 42718c2ecf20Sopenharmony_ci 42728c2ecf20Sopenharmony_ci if (!ev->status && ev->page == 0x01) { 42738c2ecf20Sopenharmony_ci struct inquiry_entry *ie; 42748c2ecf20Sopenharmony_ci 42758c2ecf20Sopenharmony_ci ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 42768c2ecf20Sopenharmony_ci if (ie) 42778c2ecf20Sopenharmony_ci ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 42788c2ecf20Sopenharmony_ci 42798c2ecf20Sopenharmony_ci if (ev->features[0] & LMP_HOST_SSP) { 42808c2ecf20Sopenharmony_ci set_bit(HCI_CONN_SSP_ENABLED, &conn->flags); 42818c2ecf20Sopenharmony_ci } else { 42828c2ecf20Sopenharmony_ci /* It is mandatory by the Bluetooth specification that 42838c2ecf20Sopenharmony_ci * Extended Inquiry Results are only used when Secure 42848c2ecf20Sopenharmony_ci * Simple Pairing is enabled, but some devices violate 42858c2ecf20Sopenharmony_ci * this. 42868c2ecf20Sopenharmony_ci * 42878c2ecf20Sopenharmony_ci * To make these devices work, the internal SSP 42888c2ecf20Sopenharmony_ci * enabled flag needs to be cleared if the remote host 42898c2ecf20Sopenharmony_ci * features do not indicate SSP support */ 42908c2ecf20Sopenharmony_ci clear_bit(HCI_CONN_SSP_ENABLED, &conn->flags); 42918c2ecf20Sopenharmony_ci } 42928c2ecf20Sopenharmony_ci 42938c2ecf20Sopenharmony_ci if (ev->features[0] & LMP_HOST_SC) 42948c2ecf20Sopenharmony_ci set_bit(HCI_CONN_SC_ENABLED, &conn->flags); 42958c2ecf20Sopenharmony_ci } 42968c2ecf20Sopenharmony_ci 42978c2ecf20Sopenharmony_ci if (conn->state != BT_CONFIG) 42988c2ecf20Sopenharmony_ci goto unlock; 42998c2ecf20Sopenharmony_ci 43008c2ecf20Sopenharmony_ci if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { 43018c2ecf20Sopenharmony_ci struct hci_cp_remote_name_req cp; 43028c2ecf20Sopenharmony_ci memset(&cp, 0, sizeof(cp)); 43038c2ecf20Sopenharmony_ci bacpy(&cp.bdaddr, &conn->dst); 43048c2ecf20Sopenharmony_ci cp.pscan_rep_mode = 0x02; 43058c2ecf20Sopenharmony_ci hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 43068c2ecf20Sopenharmony_ci } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 43078c2ecf20Sopenharmony_ci mgmt_device_connected(hdev, conn, 0, NULL, 0); 43088c2ecf20Sopenharmony_ci 43098c2ecf20Sopenharmony_ci if (!hci_outgoing_auth_needed(hdev, conn)) { 43108c2ecf20Sopenharmony_ci conn->state = BT_CONNECTED; 43118c2ecf20Sopenharmony_ci hci_connect_cfm(conn, ev->status); 43128c2ecf20Sopenharmony_ci hci_conn_drop(conn); 43138c2ecf20Sopenharmony_ci } 43148c2ecf20Sopenharmony_ci 43158c2ecf20Sopenharmony_ciunlock: 43168c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 43178c2ecf20Sopenharmony_ci} 43188c2ecf20Sopenharmony_ci 43198c2ecf20Sopenharmony_cistatic void hci_sync_conn_complete_evt(struct hci_dev *hdev, 43208c2ecf20Sopenharmony_ci struct sk_buff *skb) 43218c2ecf20Sopenharmony_ci{ 43228c2ecf20Sopenharmony_ci struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 43238c2ecf20Sopenharmony_ci struct hci_conn *conn; 43248c2ecf20Sopenharmony_ci 43258c2ecf20Sopenharmony_ci switch (ev->link_type) { 43268c2ecf20Sopenharmony_ci case SCO_LINK: 43278c2ecf20Sopenharmony_ci case ESCO_LINK: 43288c2ecf20Sopenharmony_ci break; 43298c2ecf20Sopenharmony_ci default: 43308c2ecf20Sopenharmony_ci /* As per Core 5.3 Vol 4 Part E 7.7.35 (p.2219), Link_Type 43318c2ecf20Sopenharmony_ci * for HCI_Synchronous_Connection_Complete is limited to 43328c2ecf20Sopenharmony_ci * either SCO or eSCO 43338c2ecf20Sopenharmony_ci */ 43348c2ecf20Sopenharmony_ci bt_dev_err(hdev, "Ignoring connect complete event for invalid link type"); 43358c2ecf20Sopenharmony_ci return; 43368c2ecf20Sopenharmony_ci } 43378c2ecf20Sopenharmony_ci 43388c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 43398c2ecf20Sopenharmony_ci 43408c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 43418c2ecf20Sopenharmony_ci 43428c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 43438c2ecf20Sopenharmony_ci if (!conn) { 43448c2ecf20Sopenharmony_ci if (ev->link_type == ESCO_LINK) 43458c2ecf20Sopenharmony_ci goto unlock; 43468c2ecf20Sopenharmony_ci 43478c2ecf20Sopenharmony_ci /* When the link type in the event indicates SCO connection 43488c2ecf20Sopenharmony_ci * and lookup of the connection object fails, then check 43498c2ecf20Sopenharmony_ci * if an eSCO connection object exists. 43508c2ecf20Sopenharmony_ci * 43518c2ecf20Sopenharmony_ci * The core limits the synchronous connections to either 43528c2ecf20Sopenharmony_ci * SCO or eSCO. The eSCO connection is preferred and tried 43538c2ecf20Sopenharmony_ci * to be setup first and until successfully established, 43548c2ecf20Sopenharmony_ci * the link type will be hinted as eSCO. 43558c2ecf20Sopenharmony_ci */ 43568c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 43578c2ecf20Sopenharmony_ci if (!conn) 43588c2ecf20Sopenharmony_ci goto unlock; 43598c2ecf20Sopenharmony_ci } 43608c2ecf20Sopenharmony_ci 43618c2ecf20Sopenharmony_ci switch (ev->status) { 43628c2ecf20Sopenharmony_ci case 0x00: 43638c2ecf20Sopenharmony_ci /* The synchronous connection complete event should only be 43648c2ecf20Sopenharmony_ci * sent once per new connection. Receiving a successful 43658c2ecf20Sopenharmony_ci * complete event when the connection status is already 43668c2ecf20Sopenharmony_ci * BT_CONNECTED means that the device is misbehaving and sent 43678c2ecf20Sopenharmony_ci * multiple complete event packets for the same new connection. 43688c2ecf20Sopenharmony_ci * 43698c2ecf20Sopenharmony_ci * Registering the device more than once can corrupt kernel 43708c2ecf20Sopenharmony_ci * memory, hence upon detecting this invalid event, we report 43718c2ecf20Sopenharmony_ci * an error and ignore the packet. 43728c2ecf20Sopenharmony_ci */ 43738c2ecf20Sopenharmony_ci if (conn->state == BT_CONNECTED) { 43748c2ecf20Sopenharmony_ci bt_dev_err(hdev, "Ignoring connect complete event for existing connection"); 43758c2ecf20Sopenharmony_ci goto unlock; 43768c2ecf20Sopenharmony_ci } 43778c2ecf20Sopenharmony_ci 43788c2ecf20Sopenharmony_ci conn->handle = __le16_to_cpu(ev->handle); 43798c2ecf20Sopenharmony_ci conn->state = BT_CONNECTED; 43808c2ecf20Sopenharmony_ci conn->type = ev->link_type; 43818c2ecf20Sopenharmony_ci 43828c2ecf20Sopenharmony_ci hci_debugfs_create_conn(conn); 43838c2ecf20Sopenharmony_ci hci_conn_add_sysfs(conn); 43848c2ecf20Sopenharmony_ci break; 43858c2ecf20Sopenharmony_ci 43868c2ecf20Sopenharmony_ci case 0x10: /* Connection Accept Timeout */ 43878c2ecf20Sopenharmony_ci case 0x0d: /* Connection Rejected due to Limited Resources */ 43888c2ecf20Sopenharmony_ci case 0x11: /* Unsupported Feature or Parameter Value */ 43898c2ecf20Sopenharmony_ci case 0x1c: /* SCO interval rejected */ 43908c2ecf20Sopenharmony_ci case 0x1a: /* Unsupported Remote Feature */ 43918c2ecf20Sopenharmony_ci case 0x1e: /* Invalid LMP Parameters */ 43928c2ecf20Sopenharmony_ci case 0x1f: /* Unspecified error */ 43938c2ecf20Sopenharmony_ci case 0x20: /* Unsupported LMP Parameter value */ 43948c2ecf20Sopenharmony_ci if (conn->out) { 43958c2ecf20Sopenharmony_ci conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 43968c2ecf20Sopenharmony_ci (hdev->esco_type & EDR_ESCO_MASK); 43978c2ecf20Sopenharmony_ci if (hci_setup_sync(conn, conn->link->handle)) 43988c2ecf20Sopenharmony_ci goto unlock; 43998c2ecf20Sopenharmony_ci } 44008c2ecf20Sopenharmony_ci fallthrough; 44018c2ecf20Sopenharmony_ci 44028c2ecf20Sopenharmony_ci default: 44038c2ecf20Sopenharmony_ci conn->state = BT_CLOSED; 44048c2ecf20Sopenharmony_ci break; 44058c2ecf20Sopenharmony_ci } 44068c2ecf20Sopenharmony_ci 44078c2ecf20Sopenharmony_ci bt_dev_dbg(hdev, "SCO connected with air mode: %02x", ev->air_mode); 44088c2ecf20Sopenharmony_ci 44098c2ecf20Sopenharmony_ci switch (ev->air_mode) { 44108c2ecf20Sopenharmony_ci case 0x02: 44118c2ecf20Sopenharmony_ci if (hdev->notify) 44128c2ecf20Sopenharmony_ci hdev->notify(hdev, HCI_NOTIFY_ENABLE_SCO_CVSD); 44138c2ecf20Sopenharmony_ci break; 44148c2ecf20Sopenharmony_ci case 0x03: 44158c2ecf20Sopenharmony_ci if (hdev->notify) 44168c2ecf20Sopenharmony_ci hdev->notify(hdev, HCI_NOTIFY_ENABLE_SCO_TRANSP); 44178c2ecf20Sopenharmony_ci break; 44188c2ecf20Sopenharmony_ci } 44198c2ecf20Sopenharmony_ci 44208c2ecf20Sopenharmony_ci hci_connect_cfm(conn, ev->status); 44218c2ecf20Sopenharmony_ci if (ev->status) 44228c2ecf20Sopenharmony_ci hci_conn_del(conn); 44238c2ecf20Sopenharmony_ci 44248c2ecf20Sopenharmony_ciunlock: 44258c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 44268c2ecf20Sopenharmony_ci} 44278c2ecf20Sopenharmony_ci 44288c2ecf20Sopenharmony_cistatic inline size_t eir_get_length(u8 *eir, size_t eir_len) 44298c2ecf20Sopenharmony_ci{ 44308c2ecf20Sopenharmony_ci size_t parsed = 0; 44318c2ecf20Sopenharmony_ci 44328c2ecf20Sopenharmony_ci while (parsed < eir_len) { 44338c2ecf20Sopenharmony_ci u8 field_len = eir[0]; 44348c2ecf20Sopenharmony_ci 44358c2ecf20Sopenharmony_ci if (field_len == 0) 44368c2ecf20Sopenharmony_ci return parsed; 44378c2ecf20Sopenharmony_ci 44388c2ecf20Sopenharmony_ci parsed += field_len + 1; 44398c2ecf20Sopenharmony_ci eir += field_len + 1; 44408c2ecf20Sopenharmony_ci } 44418c2ecf20Sopenharmony_ci 44428c2ecf20Sopenharmony_ci return eir_len; 44438c2ecf20Sopenharmony_ci} 44448c2ecf20Sopenharmony_ci 44458c2ecf20Sopenharmony_cistatic void hci_extended_inquiry_result_evt(struct hci_dev *hdev, 44468c2ecf20Sopenharmony_ci struct sk_buff *skb) 44478c2ecf20Sopenharmony_ci{ 44488c2ecf20Sopenharmony_ci struct inquiry_data data; 44498c2ecf20Sopenharmony_ci struct extended_inquiry_info *info = (void *) (skb->data + 1); 44508c2ecf20Sopenharmony_ci int num_rsp = *((__u8 *) skb->data); 44518c2ecf20Sopenharmony_ci size_t eir_len; 44528c2ecf20Sopenharmony_ci 44538c2ecf20Sopenharmony_ci BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 44548c2ecf20Sopenharmony_ci 44558c2ecf20Sopenharmony_ci if (!num_rsp || skb->len < num_rsp * sizeof(*info) + 1) 44568c2ecf20Sopenharmony_ci return; 44578c2ecf20Sopenharmony_ci 44588c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) 44598c2ecf20Sopenharmony_ci return; 44608c2ecf20Sopenharmony_ci 44618c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 44628c2ecf20Sopenharmony_ci 44638c2ecf20Sopenharmony_ci for (; num_rsp; num_rsp--, info++) { 44648c2ecf20Sopenharmony_ci u32 flags; 44658c2ecf20Sopenharmony_ci bool name_known; 44668c2ecf20Sopenharmony_ci 44678c2ecf20Sopenharmony_ci bacpy(&data.bdaddr, &info->bdaddr); 44688c2ecf20Sopenharmony_ci data.pscan_rep_mode = info->pscan_rep_mode; 44698c2ecf20Sopenharmony_ci data.pscan_period_mode = info->pscan_period_mode; 44708c2ecf20Sopenharmony_ci data.pscan_mode = 0x00; 44718c2ecf20Sopenharmony_ci memcpy(data.dev_class, info->dev_class, 3); 44728c2ecf20Sopenharmony_ci data.clock_offset = info->clock_offset; 44738c2ecf20Sopenharmony_ci data.rssi = info->rssi; 44748c2ecf20Sopenharmony_ci data.ssp_mode = 0x01; 44758c2ecf20Sopenharmony_ci 44768c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_MGMT)) 44778c2ecf20Sopenharmony_ci name_known = eir_get_data(info->data, 44788c2ecf20Sopenharmony_ci sizeof(info->data), 44798c2ecf20Sopenharmony_ci EIR_NAME_COMPLETE, NULL); 44808c2ecf20Sopenharmony_ci else 44818c2ecf20Sopenharmony_ci name_known = true; 44828c2ecf20Sopenharmony_ci 44838c2ecf20Sopenharmony_ci flags = hci_inquiry_cache_update(hdev, &data, name_known); 44848c2ecf20Sopenharmony_ci 44858c2ecf20Sopenharmony_ci eir_len = eir_get_length(info->data, sizeof(info->data)); 44868c2ecf20Sopenharmony_ci 44878c2ecf20Sopenharmony_ci mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 44888c2ecf20Sopenharmony_ci info->dev_class, info->rssi, 44898c2ecf20Sopenharmony_ci flags, info->data, eir_len, NULL, 0); 44908c2ecf20Sopenharmony_ci } 44918c2ecf20Sopenharmony_ci 44928c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 44938c2ecf20Sopenharmony_ci} 44948c2ecf20Sopenharmony_ci 44958c2ecf20Sopenharmony_cistatic void hci_key_refresh_complete_evt(struct hci_dev *hdev, 44968c2ecf20Sopenharmony_ci struct sk_buff *skb) 44978c2ecf20Sopenharmony_ci{ 44988c2ecf20Sopenharmony_ci struct hci_ev_key_refresh_complete *ev = (void *) skb->data; 44998c2ecf20Sopenharmony_ci struct hci_conn *conn; 45008c2ecf20Sopenharmony_ci 45018c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status, 45028c2ecf20Sopenharmony_ci __le16_to_cpu(ev->handle)); 45038c2ecf20Sopenharmony_ci 45048c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 45058c2ecf20Sopenharmony_ci 45068c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 45078c2ecf20Sopenharmony_ci if (!conn) 45088c2ecf20Sopenharmony_ci goto unlock; 45098c2ecf20Sopenharmony_ci 45108c2ecf20Sopenharmony_ci /* For BR/EDR the necessary steps are taken through the 45118c2ecf20Sopenharmony_ci * auth_complete event. 45128c2ecf20Sopenharmony_ci */ 45138c2ecf20Sopenharmony_ci if (conn->type != LE_LINK) 45148c2ecf20Sopenharmony_ci goto unlock; 45158c2ecf20Sopenharmony_ci 45168c2ecf20Sopenharmony_ci if (!ev->status) 45178c2ecf20Sopenharmony_ci conn->sec_level = conn->pending_sec_level; 45188c2ecf20Sopenharmony_ci 45198c2ecf20Sopenharmony_ci clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 45208c2ecf20Sopenharmony_ci 45218c2ecf20Sopenharmony_ci if (ev->status && conn->state == BT_CONNECTED) { 45228c2ecf20Sopenharmony_ci hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); 45238c2ecf20Sopenharmony_ci hci_conn_drop(conn); 45248c2ecf20Sopenharmony_ci goto unlock; 45258c2ecf20Sopenharmony_ci } 45268c2ecf20Sopenharmony_ci 45278c2ecf20Sopenharmony_ci if (conn->state == BT_CONFIG) { 45288c2ecf20Sopenharmony_ci if (!ev->status) 45298c2ecf20Sopenharmony_ci conn->state = BT_CONNECTED; 45308c2ecf20Sopenharmony_ci 45318c2ecf20Sopenharmony_ci hci_connect_cfm(conn, ev->status); 45328c2ecf20Sopenharmony_ci hci_conn_drop(conn); 45338c2ecf20Sopenharmony_ci } else { 45348c2ecf20Sopenharmony_ci hci_auth_cfm(conn, ev->status); 45358c2ecf20Sopenharmony_ci 45368c2ecf20Sopenharmony_ci hci_conn_hold(conn); 45378c2ecf20Sopenharmony_ci conn->disc_timeout = HCI_DISCONN_TIMEOUT; 45388c2ecf20Sopenharmony_ci hci_conn_drop(conn); 45398c2ecf20Sopenharmony_ci } 45408c2ecf20Sopenharmony_ci 45418c2ecf20Sopenharmony_ciunlock: 45428c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 45438c2ecf20Sopenharmony_ci} 45448c2ecf20Sopenharmony_ci 45458c2ecf20Sopenharmony_cistatic u8 hci_get_auth_req(struct hci_conn *conn) 45468c2ecf20Sopenharmony_ci{ 45478c2ecf20Sopenharmony_ci /* If remote requests no-bonding follow that lead */ 45488c2ecf20Sopenharmony_ci if (conn->remote_auth == HCI_AT_NO_BONDING || 45498c2ecf20Sopenharmony_ci conn->remote_auth == HCI_AT_NO_BONDING_MITM) 45508c2ecf20Sopenharmony_ci return conn->remote_auth | (conn->auth_type & 0x01); 45518c2ecf20Sopenharmony_ci 45528c2ecf20Sopenharmony_ci /* If both remote and local have enough IO capabilities, require 45538c2ecf20Sopenharmony_ci * MITM protection 45548c2ecf20Sopenharmony_ci */ 45558c2ecf20Sopenharmony_ci if (conn->remote_cap != HCI_IO_NO_INPUT_OUTPUT && 45568c2ecf20Sopenharmony_ci conn->io_capability != HCI_IO_NO_INPUT_OUTPUT) 45578c2ecf20Sopenharmony_ci return conn->remote_auth | 0x01; 45588c2ecf20Sopenharmony_ci 45598c2ecf20Sopenharmony_ci /* No MITM protection possible so ignore remote requirement */ 45608c2ecf20Sopenharmony_ci return (conn->remote_auth & ~0x01) | (conn->auth_type & 0x01); 45618c2ecf20Sopenharmony_ci} 45628c2ecf20Sopenharmony_ci 45638c2ecf20Sopenharmony_cistatic u8 bredr_oob_data_present(struct hci_conn *conn) 45648c2ecf20Sopenharmony_ci{ 45658c2ecf20Sopenharmony_ci struct hci_dev *hdev = conn->hdev; 45668c2ecf20Sopenharmony_ci struct oob_data *data; 45678c2ecf20Sopenharmony_ci 45688c2ecf20Sopenharmony_ci data = hci_find_remote_oob_data(hdev, &conn->dst, BDADDR_BREDR); 45698c2ecf20Sopenharmony_ci if (!data) 45708c2ecf20Sopenharmony_ci return 0x00; 45718c2ecf20Sopenharmony_ci 45728c2ecf20Sopenharmony_ci if (bredr_sc_enabled(hdev)) { 45738c2ecf20Sopenharmony_ci /* When Secure Connections is enabled, then just 45748c2ecf20Sopenharmony_ci * return the present value stored with the OOB 45758c2ecf20Sopenharmony_ci * data. The stored value contains the right present 45768c2ecf20Sopenharmony_ci * information. However it can only be trusted when 45778c2ecf20Sopenharmony_ci * not in Secure Connection Only mode. 45788c2ecf20Sopenharmony_ci */ 45798c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_SC_ONLY)) 45808c2ecf20Sopenharmony_ci return data->present; 45818c2ecf20Sopenharmony_ci 45828c2ecf20Sopenharmony_ci /* When Secure Connections Only mode is enabled, then 45838c2ecf20Sopenharmony_ci * the P-256 values are required. If they are not 45848c2ecf20Sopenharmony_ci * available, then do not declare that OOB data is 45858c2ecf20Sopenharmony_ci * present. 45868c2ecf20Sopenharmony_ci */ 45878c2ecf20Sopenharmony_ci if (!crypto_memneq(data->rand256, ZERO_KEY, 16) || 45888c2ecf20Sopenharmony_ci !crypto_memneq(data->hash256, ZERO_KEY, 16)) 45898c2ecf20Sopenharmony_ci return 0x00; 45908c2ecf20Sopenharmony_ci 45918c2ecf20Sopenharmony_ci return 0x02; 45928c2ecf20Sopenharmony_ci } 45938c2ecf20Sopenharmony_ci 45948c2ecf20Sopenharmony_ci /* When Secure Connections is not enabled or actually 45958c2ecf20Sopenharmony_ci * not supported by the hardware, then check that if 45968c2ecf20Sopenharmony_ci * P-192 data values are present. 45978c2ecf20Sopenharmony_ci */ 45988c2ecf20Sopenharmony_ci if (!crypto_memneq(data->rand192, ZERO_KEY, 16) || 45998c2ecf20Sopenharmony_ci !crypto_memneq(data->hash192, ZERO_KEY, 16)) 46008c2ecf20Sopenharmony_ci return 0x00; 46018c2ecf20Sopenharmony_ci 46028c2ecf20Sopenharmony_ci return 0x01; 46038c2ecf20Sopenharmony_ci} 46048c2ecf20Sopenharmony_ci 46058c2ecf20Sopenharmony_cistatic void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 46068c2ecf20Sopenharmony_ci{ 46078c2ecf20Sopenharmony_ci struct hci_ev_io_capa_request *ev = (void *) skb->data; 46088c2ecf20Sopenharmony_ci struct hci_conn *conn; 46098c2ecf20Sopenharmony_ci 46108c2ecf20Sopenharmony_ci BT_DBG("%s", hdev->name); 46118c2ecf20Sopenharmony_ci 46128c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 46138c2ecf20Sopenharmony_ci 46148c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 46158c2ecf20Sopenharmony_ci if (!conn || !hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) 46168c2ecf20Sopenharmony_ci goto unlock; 46178c2ecf20Sopenharmony_ci 46188c2ecf20Sopenharmony_ci /* Assume remote supports SSP since it has triggered this event */ 46198c2ecf20Sopenharmony_ci set_bit(HCI_CONN_SSP_ENABLED, &conn->flags); 46208c2ecf20Sopenharmony_ci 46218c2ecf20Sopenharmony_ci hci_conn_hold(conn); 46228c2ecf20Sopenharmony_ci 46238c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_MGMT)) 46248c2ecf20Sopenharmony_ci goto unlock; 46258c2ecf20Sopenharmony_ci 46268c2ecf20Sopenharmony_ci /* Allow pairing if we're pairable, the initiators of the 46278c2ecf20Sopenharmony_ci * pairing or if the remote is not requesting bonding. 46288c2ecf20Sopenharmony_ci */ 46298c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_BONDABLE) || 46308c2ecf20Sopenharmony_ci test_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags) || 46318c2ecf20Sopenharmony_ci (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 46328c2ecf20Sopenharmony_ci struct hci_cp_io_capability_reply cp; 46338c2ecf20Sopenharmony_ci 46348c2ecf20Sopenharmony_ci bacpy(&cp.bdaddr, &ev->bdaddr); 46358c2ecf20Sopenharmony_ci /* Change the IO capability from KeyboardDisplay 46368c2ecf20Sopenharmony_ci * to DisplayYesNo as it is not supported by BT spec. */ 46378c2ecf20Sopenharmony_ci cp.capability = (conn->io_capability == 0x04) ? 46388c2ecf20Sopenharmony_ci HCI_IO_DISPLAY_YESNO : conn->io_capability; 46398c2ecf20Sopenharmony_ci 46408c2ecf20Sopenharmony_ci /* If we are initiators, there is no remote information yet */ 46418c2ecf20Sopenharmony_ci if (conn->remote_auth == 0xff) { 46428c2ecf20Sopenharmony_ci /* Request MITM protection if our IO caps allow it 46438c2ecf20Sopenharmony_ci * except for the no-bonding case. 46448c2ecf20Sopenharmony_ci */ 46458c2ecf20Sopenharmony_ci if (conn->io_capability != HCI_IO_NO_INPUT_OUTPUT && 46468c2ecf20Sopenharmony_ci conn->auth_type != HCI_AT_NO_BONDING) 46478c2ecf20Sopenharmony_ci conn->auth_type |= 0x01; 46488c2ecf20Sopenharmony_ci } else { 46498c2ecf20Sopenharmony_ci conn->auth_type = hci_get_auth_req(conn); 46508c2ecf20Sopenharmony_ci } 46518c2ecf20Sopenharmony_ci 46528c2ecf20Sopenharmony_ci /* If we're not bondable, force one of the non-bondable 46538c2ecf20Sopenharmony_ci * authentication requirement values. 46548c2ecf20Sopenharmony_ci */ 46558c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_BONDABLE)) 46568c2ecf20Sopenharmony_ci conn->auth_type &= HCI_AT_NO_BONDING_MITM; 46578c2ecf20Sopenharmony_ci 46588c2ecf20Sopenharmony_ci cp.authentication = conn->auth_type; 46598c2ecf20Sopenharmony_ci cp.oob_data = bredr_oob_data_present(conn); 46608c2ecf20Sopenharmony_ci 46618c2ecf20Sopenharmony_ci hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, 46628c2ecf20Sopenharmony_ci sizeof(cp), &cp); 46638c2ecf20Sopenharmony_ci } else { 46648c2ecf20Sopenharmony_ci struct hci_cp_io_capability_neg_reply cp; 46658c2ecf20Sopenharmony_ci 46668c2ecf20Sopenharmony_ci bacpy(&cp.bdaddr, &ev->bdaddr); 46678c2ecf20Sopenharmony_ci cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED; 46688c2ecf20Sopenharmony_ci 46698c2ecf20Sopenharmony_ci hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 46708c2ecf20Sopenharmony_ci sizeof(cp), &cp); 46718c2ecf20Sopenharmony_ci } 46728c2ecf20Sopenharmony_ci 46738c2ecf20Sopenharmony_ciunlock: 46748c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 46758c2ecf20Sopenharmony_ci} 46768c2ecf20Sopenharmony_ci 46778c2ecf20Sopenharmony_cistatic void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 46788c2ecf20Sopenharmony_ci{ 46798c2ecf20Sopenharmony_ci struct hci_ev_io_capa_reply *ev = (void *) skb->data; 46808c2ecf20Sopenharmony_ci struct hci_conn *conn; 46818c2ecf20Sopenharmony_ci 46828c2ecf20Sopenharmony_ci BT_DBG("%s", hdev->name); 46838c2ecf20Sopenharmony_ci 46848c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 46858c2ecf20Sopenharmony_ci 46868c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 46878c2ecf20Sopenharmony_ci if (!conn) 46888c2ecf20Sopenharmony_ci goto unlock; 46898c2ecf20Sopenharmony_ci 46908c2ecf20Sopenharmony_ci conn->remote_cap = ev->capability; 46918c2ecf20Sopenharmony_ci conn->remote_auth = ev->authentication; 46928c2ecf20Sopenharmony_ci 46938c2ecf20Sopenharmony_ciunlock: 46948c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 46958c2ecf20Sopenharmony_ci} 46968c2ecf20Sopenharmony_ci 46978c2ecf20Sopenharmony_cistatic void hci_user_confirm_request_evt(struct hci_dev *hdev, 46988c2ecf20Sopenharmony_ci struct sk_buff *skb) 46998c2ecf20Sopenharmony_ci{ 47008c2ecf20Sopenharmony_ci struct hci_ev_user_confirm_req *ev = (void *) skb->data; 47018c2ecf20Sopenharmony_ci int loc_mitm, rem_mitm, confirm_hint = 0; 47028c2ecf20Sopenharmony_ci struct hci_conn *conn; 47038c2ecf20Sopenharmony_ci 47048c2ecf20Sopenharmony_ci BT_DBG("%s", hdev->name); 47058c2ecf20Sopenharmony_ci 47068c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 47078c2ecf20Sopenharmony_ci 47088c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_MGMT)) 47098c2ecf20Sopenharmony_ci goto unlock; 47108c2ecf20Sopenharmony_ci 47118c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 47128c2ecf20Sopenharmony_ci if (!conn) 47138c2ecf20Sopenharmony_ci goto unlock; 47148c2ecf20Sopenharmony_ci 47158c2ecf20Sopenharmony_ci loc_mitm = (conn->auth_type & 0x01); 47168c2ecf20Sopenharmony_ci rem_mitm = (conn->remote_auth & 0x01); 47178c2ecf20Sopenharmony_ci 47188c2ecf20Sopenharmony_ci /* If we require MITM but the remote device can't provide that 47198c2ecf20Sopenharmony_ci * (it has NoInputNoOutput) then reject the confirmation 47208c2ecf20Sopenharmony_ci * request. We check the security level here since it doesn't 47218c2ecf20Sopenharmony_ci * necessarily match conn->auth_type. 47228c2ecf20Sopenharmony_ci */ 47238c2ecf20Sopenharmony_ci if (conn->pending_sec_level > BT_SECURITY_MEDIUM && 47248c2ecf20Sopenharmony_ci conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) { 47258c2ecf20Sopenharmony_ci BT_DBG("Rejecting request: remote device can't provide MITM"); 47268c2ecf20Sopenharmony_ci hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, 47278c2ecf20Sopenharmony_ci sizeof(ev->bdaddr), &ev->bdaddr); 47288c2ecf20Sopenharmony_ci goto unlock; 47298c2ecf20Sopenharmony_ci } 47308c2ecf20Sopenharmony_ci 47318c2ecf20Sopenharmony_ci /* If no side requires MITM protection; auto-accept */ 47328c2ecf20Sopenharmony_ci if ((!loc_mitm || conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) && 47338c2ecf20Sopenharmony_ci (!rem_mitm || conn->io_capability == HCI_IO_NO_INPUT_OUTPUT)) { 47348c2ecf20Sopenharmony_ci 47358c2ecf20Sopenharmony_ci /* If we're not the initiators request authorization to 47368c2ecf20Sopenharmony_ci * proceed from user space (mgmt_user_confirm with 47378c2ecf20Sopenharmony_ci * confirm_hint set to 1). The exception is if neither 47388c2ecf20Sopenharmony_ci * side had MITM or if the local IO capability is 47398c2ecf20Sopenharmony_ci * NoInputNoOutput, in which case we do auto-accept 47408c2ecf20Sopenharmony_ci */ 47418c2ecf20Sopenharmony_ci if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && 47428c2ecf20Sopenharmony_ci conn->io_capability != HCI_IO_NO_INPUT_OUTPUT && 47438c2ecf20Sopenharmony_ci (loc_mitm || rem_mitm)) { 47448c2ecf20Sopenharmony_ci BT_DBG("Confirming auto-accept as acceptor"); 47458c2ecf20Sopenharmony_ci confirm_hint = 1; 47468c2ecf20Sopenharmony_ci goto confirm; 47478c2ecf20Sopenharmony_ci } 47488c2ecf20Sopenharmony_ci 47498c2ecf20Sopenharmony_ci /* If there already exists link key in local host, leave the 47508c2ecf20Sopenharmony_ci * decision to user space since the remote device could be 47518c2ecf20Sopenharmony_ci * legitimate or malicious. 47528c2ecf20Sopenharmony_ci */ 47538c2ecf20Sopenharmony_ci if (hci_find_link_key(hdev, &ev->bdaddr)) { 47548c2ecf20Sopenharmony_ci bt_dev_dbg(hdev, "Local host already has link key"); 47558c2ecf20Sopenharmony_ci confirm_hint = 1; 47568c2ecf20Sopenharmony_ci goto confirm; 47578c2ecf20Sopenharmony_ci } 47588c2ecf20Sopenharmony_ci 47598c2ecf20Sopenharmony_ci BT_DBG("Auto-accept of user confirmation with %ums delay", 47608c2ecf20Sopenharmony_ci hdev->auto_accept_delay); 47618c2ecf20Sopenharmony_ci 47628c2ecf20Sopenharmony_ci if (hdev->auto_accept_delay > 0) { 47638c2ecf20Sopenharmony_ci int delay = msecs_to_jiffies(hdev->auto_accept_delay); 47648c2ecf20Sopenharmony_ci queue_delayed_work(conn->hdev->workqueue, 47658c2ecf20Sopenharmony_ci &conn->auto_accept_work, delay); 47668c2ecf20Sopenharmony_ci goto unlock; 47678c2ecf20Sopenharmony_ci } 47688c2ecf20Sopenharmony_ci 47698c2ecf20Sopenharmony_ci hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, 47708c2ecf20Sopenharmony_ci sizeof(ev->bdaddr), &ev->bdaddr); 47718c2ecf20Sopenharmony_ci goto unlock; 47728c2ecf20Sopenharmony_ci } 47738c2ecf20Sopenharmony_ci 47748c2ecf20Sopenharmony_ciconfirm: 47758c2ecf20Sopenharmony_ci mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, 47768c2ecf20Sopenharmony_ci le32_to_cpu(ev->passkey), confirm_hint); 47778c2ecf20Sopenharmony_ci 47788c2ecf20Sopenharmony_ciunlock: 47798c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 47808c2ecf20Sopenharmony_ci} 47818c2ecf20Sopenharmony_ci 47828c2ecf20Sopenharmony_cistatic void hci_user_passkey_request_evt(struct hci_dev *hdev, 47838c2ecf20Sopenharmony_ci struct sk_buff *skb) 47848c2ecf20Sopenharmony_ci{ 47858c2ecf20Sopenharmony_ci struct hci_ev_user_passkey_req *ev = (void *) skb->data; 47868c2ecf20Sopenharmony_ci 47878c2ecf20Sopenharmony_ci BT_DBG("%s", hdev->name); 47888c2ecf20Sopenharmony_ci 47898c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_MGMT)) 47908c2ecf20Sopenharmony_ci mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); 47918c2ecf20Sopenharmony_ci} 47928c2ecf20Sopenharmony_ci 47938c2ecf20Sopenharmony_cistatic void hci_user_passkey_notify_evt(struct hci_dev *hdev, 47948c2ecf20Sopenharmony_ci struct sk_buff *skb) 47958c2ecf20Sopenharmony_ci{ 47968c2ecf20Sopenharmony_ci struct hci_ev_user_passkey_notify *ev = (void *) skb->data; 47978c2ecf20Sopenharmony_ci struct hci_conn *conn; 47988c2ecf20Sopenharmony_ci 47998c2ecf20Sopenharmony_ci BT_DBG("%s", hdev->name); 48008c2ecf20Sopenharmony_ci 48018c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 48028c2ecf20Sopenharmony_ci if (!conn) 48038c2ecf20Sopenharmony_ci return; 48048c2ecf20Sopenharmony_ci 48058c2ecf20Sopenharmony_ci conn->passkey_notify = __le32_to_cpu(ev->passkey); 48068c2ecf20Sopenharmony_ci conn->passkey_entered = 0; 48078c2ecf20Sopenharmony_ci 48088c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_MGMT)) 48098c2ecf20Sopenharmony_ci mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, 48108c2ecf20Sopenharmony_ci conn->dst_type, conn->passkey_notify, 48118c2ecf20Sopenharmony_ci conn->passkey_entered); 48128c2ecf20Sopenharmony_ci} 48138c2ecf20Sopenharmony_ci 48148c2ecf20Sopenharmony_cistatic void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 48158c2ecf20Sopenharmony_ci{ 48168c2ecf20Sopenharmony_ci struct hci_ev_keypress_notify *ev = (void *) skb->data; 48178c2ecf20Sopenharmony_ci struct hci_conn *conn; 48188c2ecf20Sopenharmony_ci 48198c2ecf20Sopenharmony_ci BT_DBG("%s", hdev->name); 48208c2ecf20Sopenharmony_ci 48218c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 48228c2ecf20Sopenharmony_ci if (!conn) 48238c2ecf20Sopenharmony_ci return; 48248c2ecf20Sopenharmony_ci 48258c2ecf20Sopenharmony_ci switch (ev->type) { 48268c2ecf20Sopenharmony_ci case HCI_KEYPRESS_STARTED: 48278c2ecf20Sopenharmony_ci conn->passkey_entered = 0; 48288c2ecf20Sopenharmony_ci return; 48298c2ecf20Sopenharmony_ci 48308c2ecf20Sopenharmony_ci case HCI_KEYPRESS_ENTERED: 48318c2ecf20Sopenharmony_ci conn->passkey_entered++; 48328c2ecf20Sopenharmony_ci break; 48338c2ecf20Sopenharmony_ci 48348c2ecf20Sopenharmony_ci case HCI_KEYPRESS_ERASED: 48358c2ecf20Sopenharmony_ci conn->passkey_entered--; 48368c2ecf20Sopenharmony_ci break; 48378c2ecf20Sopenharmony_ci 48388c2ecf20Sopenharmony_ci case HCI_KEYPRESS_CLEARED: 48398c2ecf20Sopenharmony_ci conn->passkey_entered = 0; 48408c2ecf20Sopenharmony_ci break; 48418c2ecf20Sopenharmony_ci 48428c2ecf20Sopenharmony_ci case HCI_KEYPRESS_COMPLETED: 48438c2ecf20Sopenharmony_ci return; 48448c2ecf20Sopenharmony_ci } 48458c2ecf20Sopenharmony_ci 48468c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_MGMT)) 48478c2ecf20Sopenharmony_ci mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, 48488c2ecf20Sopenharmony_ci conn->dst_type, conn->passkey_notify, 48498c2ecf20Sopenharmony_ci conn->passkey_entered); 48508c2ecf20Sopenharmony_ci} 48518c2ecf20Sopenharmony_ci 48528c2ecf20Sopenharmony_cistatic void hci_simple_pair_complete_evt(struct hci_dev *hdev, 48538c2ecf20Sopenharmony_ci struct sk_buff *skb) 48548c2ecf20Sopenharmony_ci{ 48558c2ecf20Sopenharmony_ci struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 48568c2ecf20Sopenharmony_ci struct hci_conn *conn; 48578c2ecf20Sopenharmony_ci 48588c2ecf20Sopenharmony_ci BT_DBG("%s", hdev->name); 48598c2ecf20Sopenharmony_ci 48608c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 48618c2ecf20Sopenharmony_ci 48628c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 48638c2ecf20Sopenharmony_ci if (!conn || !hci_conn_ssp_enabled(conn)) 48648c2ecf20Sopenharmony_ci goto unlock; 48658c2ecf20Sopenharmony_ci 48668c2ecf20Sopenharmony_ci /* Reset the authentication requirement to unknown */ 48678c2ecf20Sopenharmony_ci conn->remote_auth = 0xff; 48688c2ecf20Sopenharmony_ci 48698c2ecf20Sopenharmony_ci /* To avoid duplicate auth_failed events to user space we check 48708c2ecf20Sopenharmony_ci * the HCI_CONN_AUTH_PEND flag which will be set if we 48718c2ecf20Sopenharmony_ci * initiated the authentication. A traditional auth_complete 48728c2ecf20Sopenharmony_ci * event gets always produced as initiator and is also mapped to 48738c2ecf20Sopenharmony_ci * the mgmt_auth_failed event */ 48748c2ecf20Sopenharmony_ci if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status) 48758c2ecf20Sopenharmony_ci mgmt_auth_failed(conn, ev->status); 48768c2ecf20Sopenharmony_ci 48778c2ecf20Sopenharmony_ci hci_conn_drop(conn); 48788c2ecf20Sopenharmony_ci 48798c2ecf20Sopenharmony_ciunlock: 48808c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 48818c2ecf20Sopenharmony_ci} 48828c2ecf20Sopenharmony_ci 48838c2ecf20Sopenharmony_cistatic void hci_remote_host_features_evt(struct hci_dev *hdev, 48848c2ecf20Sopenharmony_ci struct sk_buff *skb) 48858c2ecf20Sopenharmony_ci{ 48868c2ecf20Sopenharmony_ci struct hci_ev_remote_host_features *ev = (void *) skb->data; 48878c2ecf20Sopenharmony_ci struct inquiry_entry *ie; 48888c2ecf20Sopenharmony_ci struct hci_conn *conn; 48898c2ecf20Sopenharmony_ci 48908c2ecf20Sopenharmony_ci BT_DBG("%s", hdev->name); 48918c2ecf20Sopenharmony_ci 48928c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 48938c2ecf20Sopenharmony_ci 48948c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 48958c2ecf20Sopenharmony_ci if (conn) 48968c2ecf20Sopenharmony_ci memcpy(conn->features[1], ev->features, 8); 48978c2ecf20Sopenharmony_ci 48988c2ecf20Sopenharmony_ci ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 48998c2ecf20Sopenharmony_ci if (ie) 49008c2ecf20Sopenharmony_ci ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 49018c2ecf20Sopenharmony_ci 49028c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 49038c2ecf20Sopenharmony_ci} 49048c2ecf20Sopenharmony_ci 49058c2ecf20Sopenharmony_cistatic void hci_remote_oob_data_request_evt(struct hci_dev *hdev, 49068c2ecf20Sopenharmony_ci struct sk_buff *skb) 49078c2ecf20Sopenharmony_ci{ 49088c2ecf20Sopenharmony_ci struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; 49098c2ecf20Sopenharmony_ci struct oob_data *data; 49108c2ecf20Sopenharmony_ci 49118c2ecf20Sopenharmony_ci BT_DBG("%s", hdev->name); 49128c2ecf20Sopenharmony_ci 49138c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 49148c2ecf20Sopenharmony_ci 49158c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_MGMT)) 49168c2ecf20Sopenharmony_ci goto unlock; 49178c2ecf20Sopenharmony_ci 49188c2ecf20Sopenharmony_ci data = hci_find_remote_oob_data(hdev, &ev->bdaddr, BDADDR_BREDR); 49198c2ecf20Sopenharmony_ci if (!data) { 49208c2ecf20Sopenharmony_ci struct hci_cp_remote_oob_data_neg_reply cp; 49218c2ecf20Sopenharmony_ci 49228c2ecf20Sopenharmony_ci bacpy(&cp.bdaddr, &ev->bdaddr); 49238c2ecf20Sopenharmony_ci hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, 49248c2ecf20Sopenharmony_ci sizeof(cp), &cp); 49258c2ecf20Sopenharmony_ci goto unlock; 49268c2ecf20Sopenharmony_ci } 49278c2ecf20Sopenharmony_ci 49288c2ecf20Sopenharmony_ci if (bredr_sc_enabled(hdev)) { 49298c2ecf20Sopenharmony_ci struct hci_cp_remote_oob_ext_data_reply cp; 49308c2ecf20Sopenharmony_ci 49318c2ecf20Sopenharmony_ci bacpy(&cp.bdaddr, &ev->bdaddr); 49328c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_SC_ONLY)) { 49338c2ecf20Sopenharmony_ci memset(cp.hash192, 0, sizeof(cp.hash192)); 49348c2ecf20Sopenharmony_ci memset(cp.rand192, 0, sizeof(cp.rand192)); 49358c2ecf20Sopenharmony_ci } else { 49368c2ecf20Sopenharmony_ci memcpy(cp.hash192, data->hash192, sizeof(cp.hash192)); 49378c2ecf20Sopenharmony_ci memcpy(cp.rand192, data->rand192, sizeof(cp.rand192)); 49388c2ecf20Sopenharmony_ci } 49398c2ecf20Sopenharmony_ci memcpy(cp.hash256, data->hash256, sizeof(cp.hash256)); 49408c2ecf20Sopenharmony_ci memcpy(cp.rand256, data->rand256, sizeof(cp.rand256)); 49418c2ecf20Sopenharmony_ci 49428c2ecf20Sopenharmony_ci hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_EXT_DATA_REPLY, 49438c2ecf20Sopenharmony_ci sizeof(cp), &cp); 49448c2ecf20Sopenharmony_ci } else { 49458c2ecf20Sopenharmony_ci struct hci_cp_remote_oob_data_reply cp; 49468c2ecf20Sopenharmony_ci 49478c2ecf20Sopenharmony_ci bacpy(&cp.bdaddr, &ev->bdaddr); 49488c2ecf20Sopenharmony_ci memcpy(cp.hash, data->hash192, sizeof(cp.hash)); 49498c2ecf20Sopenharmony_ci memcpy(cp.rand, data->rand192, sizeof(cp.rand)); 49508c2ecf20Sopenharmony_ci 49518c2ecf20Sopenharmony_ci hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, 49528c2ecf20Sopenharmony_ci sizeof(cp), &cp); 49538c2ecf20Sopenharmony_ci } 49548c2ecf20Sopenharmony_ci 49558c2ecf20Sopenharmony_ciunlock: 49568c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 49578c2ecf20Sopenharmony_ci} 49588c2ecf20Sopenharmony_ci 49598c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_BT_HS) 49608c2ecf20Sopenharmony_cistatic void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb) 49618c2ecf20Sopenharmony_ci{ 49628c2ecf20Sopenharmony_ci struct hci_ev_channel_selected *ev = (void *)skb->data; 49638c2ecf20Sopenharmony_ci struct hci_conn *hcon; 49648c2ecf20Sopenharmony_ci 49658c2ecf20Sopenharmony_ci BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle); 49668c2ecf20Sopenharmony_ci 49678c2ecf20Sopenharmony_ci skb_pull(skb, sizeof(*ev)); 49688c2ecf20Sopenharmony_ci 49698c2ecf20Sopenharmony_ci hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 49708c2ecf20Sopenharmony_ci if (!hcon) 49718c2ecf20Sopenharmony_ci return; 49728c2ecf20Sopenharmony_ci 49738c2ecf20Sopenharmony_ci amp_read_loc_assoc_final_data(hdev, hcon); 49748c2ecf20Sopenharmony_ci} 49758c2ecf20Sopenharmony_ci 49768c2ecf20Sopenharmony_cistatic void hci_phy_link_complete_evt(struct hci_dev *hdev, 49778c2ecf20Sopenharmony_ci struct sk_buff *skb) 49788c2ecf20Sopenharmony_ci{ 49798c2ecf20Sopenharmony_ci struct hci_ev_phy_link_complete *ev = (void *) skb->data; 49808c2ecf20Sopenharmony_ci struct hci_conn *hcon, *bredr_hcon; 49818c2ecf20Sopenharmony_ci 49828c2ecf20Sopenharmony_ci BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle, 49838c2ecf20Sopenharmony_ci ev->status); 49848c2ecf20Sopenharmony_ci 49858c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 49868c2ecf20Sopenharmony_ci 49878c2ecf20Sopenharmony_ci hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 49888c2ecf20Sopenharmony_ci if (!hcon) { 49898c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 49908c2ecf20Sopenharmony_ci return; 49918c2ecf20Sopenharmony_ci } 49928c2ecf20Sopenharmony_ci 49938c2ecf20Sopenharmony_ci if (!hcon->amp_mgr) { 49948c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 49958c2ecf20Sopenharmony_ci return; 49968c2ecf20Sopenharmony_ci } 49978c2ecf20Sopenharmony_ci 49988c2ecf20Sopenharmony_ci if (ev->status) { 49998c2ecf20Sopenharmony_ci hci_conn_del(hcon); 50008c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 50018c2ecf20Sopenharmony_ci return; 50028c2ecf20Sopenharmony_ci } 50038c2ecf20Sopenharmony_ci 50048c2ecf20Sopenharmony_ci bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon; 50058c2ecf20Sopenharmony_ci 50068c2ecf20Sopenharmony_ci hcon->state = BT_CONNECTED; 50078c2ecf20Sopenharmony_ci bacpy(&hcon->dst, &bredr_hcon->dst); 50088c2ecf20Sopenharmony_ci 50098c2ecf20Sopenharmony_ci hci_conn_hold(hcon); 50108c2ecf20Sopenharmony_ci hcon->disc_timeout = HCI_DISCONN_TIMEOUT; 50118c2ecf20Sopenharmony_ci hci_conn_drop(hcon); 50128c2ecf20Sopenharmony_ci 50138c2ecf20Sopenharmony_ci hci_debugfs_create_conn(hcon); 50148c2ecf20Sopenharmony_ci hci_conn_add_sysfs(hcon); 50158c2ecf20Sopenharmony_ci 50168c2ecf20Sopenharmony_ci amp_physical_cfm(bredr_hcon, hcon); 50178c2ecf20Sopenharmony_ci 50188c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 50198c2ecf20Sopenharmony_ci} 50208c2ecf20Sopenharmony_ci 50218c2ecf20Sopenharmony_cistatic void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 50228c2ecf20Sopenharmony_ci{ 50238c2ecf20Sopenharmony_ci struct hci_ev_logical_link_complete *ev = (void *) skb->data; 50248c2ecf20Sopenharmony_ci struct hci_conn *hcon; 50258c2ecf20Sopenharmony_ci struct hci_chan *hchan; 50268c2ecf20Sopenharmony_ci struct amp_mgr *mgr; 50278c2ecf20Sopenharmony_ci 50288c2ecf20Sopenharmony_ci BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x", 50298c2ecf20Sopenharmony_ci hdev->name, le16_to_cpu(ev->handle), ev->phy_handle, 50308c2ecf20Sopenharmony_ci ev->status); 50318c2ecf20Sopenharmony_ci 50328c2ecf20Sopenharmony_ci hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 50338c2ecf20Sopenharmony_ci if (!hcon) 50348c2ecf20Sopenharmony_ci return; 50358c2ecf20Sopenharmony_ci 50368c2ecf20Sopenharmony_ci /* Create AMP hchan */ 50378c2ecf20Sopenharmony_ci hchan = hci_chan_create(hcon); 50388c2ecf20Sopenharmony_ci if (!hchan) 50398c2ecf20Sopenharmony_ci return; 50408c2ecf20Sopenharmony_ci 50418c2ecf20Sopenharmony_ci hchan->handle = le16_to_cpu(ev->handle); 50428c2ecf20Sopenharmony_ci hchan->amp = true; 50438c2ecf20Sopenharmony_ci 50448c2ecf20Sopenharmony_ci BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan); 50458c2ecf20Sopenharmony_ci 50468c2ecf20Sopenharmony_ci mgr = hcon->amp_mgr; 50478c2ecf20Sopenharmony_ci if (mgr && mgr->bredr_chan) { 50488c2ecf20Sopenharmony_ci struct l2cap_chan *bredr_chan = mgr->bredr_chan; 50498c2ecf20Sopenharmony_ci 50508c2ecf20Sopenharmony_ci l2cap_chan_lock(bredr_chan); 50518c2ecf20Sopenharmony_ci 50528c2ecf20Sopenharmony_ci bredr_chan->conn->mtu = hdev->block_mtu; 50538c2ecf20Sopenharmony_ci l2cap_logical_cfm(bredr_chan, hchan, 0); 50548c2ecf20Sopenharmony_ci hci_conn_hold(hcon); 50558c2ecf20Sopenharmony_ci 50568c2ecf20Sopenharmony_ci l2cap_chan_unlock(bredr_chan); 50578c2ecf20Sopenharmony_ci } 50588c2ecf20Sopenharmony_ci} 50598c2ecf20Sopenharmony_ci 50608c2ecf20Sopenharmony_cistatic void hci_disconn_loglink_complete_evt(struct hci_dev *hdev, 50618c2ecf20Sopenharmony_ci struct sk_buff *skb) 50628c2ecf20Sopenharmony_ci{ 50638c2ecf20Sopenharmony_ci struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data; 50648c2ecf20Sopenharmony_ci struct hci_chan *hchan; 50658c2ecf20Sopenharmony_ci 50668c2ecf20Sopenharmony_ci BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name, 50678c2ecf20Sopenharmony_ci le16_to_cpu(ev->handle), ev->status); 50688c2ecf20Sopenharmony_ci 50698c2ecf20Sopenharmony_ci if (ev->status) 50708c2ecf20Sopenharmony_ci return; 50718c2ecf20Sopenharmony_ci 50728c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 50738c2ecf20Sopenharmony_ci 50748c2ecf20Sopenharmony_ci hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle)); 50758c2ecf20Sopenharmony_ci if (!hchan || !hchan->amp) 50768c2ecf20Sopenharmony_ci goto unlock; 50778c2ecf20Sopenharmony_ci 50788c2ecf20Sopenharmony_ci amp_destroy_logical_link(hchan, ev->reason); 50798c2ecf20Sopenharmony_ci 50808c2ecf20Sopenharmony_ciunlock: 50818c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 50828c2ecf20Sopenharmony_ci} 50838c2ecf20Sopenharmony_ci 50848c2ecf20Sopenharmony_cistatic void hci_disconn_phylink_complete_evt(struct hci_dev *hdev, 50858c2ecf20Sopenharmony_ci struct sk_buff *skb) 50868c2ecf20Sopenharmony_ci{ 50878c2ecf20Sopenharmony_ci struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data; 50888c2ecf20Sopenharmony_ci struct hci_conn *hcon; 50898c2ecf20Sopenharmony_ci 50908c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 50918c2ecf20Sopenharmony_ci 50928c2ecf20Sopenharmony_ci if (ev->status) 50938c2ecf20Sopenharmony_ci return; 50948c2ecf20Sopenharmony_ci 50958c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 50968c2ecf20Sopenharmony_ci 50978c2ecf20Sopenharmony_ci hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 50988c2ecf20Sopenharmony_ci if (hcon && hcon->type == AMP_LINK) { 50998c2ecf20Sopenharmony_ci hcon->state = BT_CLOSED; 51008c2ecf20Sopenharmony_ci hci_disconn_cfm(hcon, ev->reason); 51018c2ecf20Sopenharmony_ci hci_conn_del(hcon); 51028c2ecf20Sopenharmony_ci } 51038c2ecf20Sopenharmony_ci 51048c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 51058c2ecf20Sopenharmony_ci} 51068c2ecf20Sopenharmony_ci#endif 51078c2ecf20Sopenharmony_ci 51088c2ecf20Sopenharmony_cistatic void le_conn_update_addr(struct hci_conn *conn, bdaddr_t *bdaddr, 51098c2ecf20Sopenharmony_ci u8 bdaddr_type, bdaddr_t *local_rpa) 51108c2ecf20Sopenharmony_ci{ 51118c2ecf20Sopenharmony_ci if (conn->out) { 51128c2ecf20Sopenharmony_ci conn->dst_type = bdaddr_type; 51138c2ecf20Sopenharmony_ci conn->resp_addr_type = bdaddr_type; 51148c2ecf20Sopenharmony_ci bacpy(&conn->resp_addr, bdaddr); 51158c2ecf20Sopenharmony_ci 51168c2ecf20Sopenharmony_ci /* Check if the controller has set a Local RPA then it must be 51178c2ecf20Sopenharmony_ci * used instead or hdev->rpa. 51188c2ecf20Sopenharmony_ci */ 51198c2ecf20Sopenharmony_ci if (local_rpa && bacmp(local_rpa, BDADDR_ANY)) { 51208c2ecf20Sopenharmony_ci conn->init_addr_type = ADDR_LE_DEV_RANDOM; 51218c2ecf20Sopenharmony_ci bacpy(&conn->init_addr, local_rpa); 51228c2ecf20Sopenharmony_ci } else if (hci_dev_test_flag(conn->hdev, HCI_PRIVACY)) { 51238c2ecf20Sopenharmony_ci conn->init_addr_type = ADDR_LE_DEV_RANDOM; 51248c2ecf20Sopenharmony_ci bacpy(&conn->init_addr, &conn->hdev->rpa); 51258c2ecf20Sopenharmony_ci } else { 51268c2ecf20Sopenharmony_ci hci_copy_identity_address(conn->hdev, &conn->init_addr, 51278c2ecf20Sopenharmony_ci &conn->init_addr_type); 51288c2ecf20Sopenharmony_ci } 51298c2ecf20Sopenharmony_ci } else { 51308c2ecf20Sopenharmony_ci conn->resp_addr_type = conn->hdev->adv_addr_type; 51318c2ecf20Sopenharmony_ci /* Check if the controller has set a Local RPA then it must be 51328c2ecf20Sopenharmony_ci * used instead or hdev->rpa. 51338c2ecf20Sopenharmony_ci */ 51348c2ecf20Sopenharmony_ci if (local_rpa && bacmp(local_rpa, BDADDR_ANY)) { 51358c2ecf20Sopenharmony_ci conn->resp_addr_type = ADDR_LE_DEV_RANDOM; 51368c2ecf20Sopenharmony_ci bacpy(&conn->resp_addr, local_rpa); 51378c2ecf20Sopenharmony_ci } else if (conn->hdev->adv_addr_type == ADDR_LE_DEV_RANDOM) { 51388c2ecf20Sopenharmony_ci /* In case of ext adv, resp_addr will be updated in 51398c2ecf20Sopenharmony_ci * Adv Terminated event. 51408c2ecf20Sopenharmony_ci */ 51418c2ecf20Sopenharmony_ci if (!ext_adv_capable(conn->hdev)) 51428c2ecf20Sopenharmony_ci bacpy(&conn->resp_addr, 51438c2ecf20Sopenharmony_ci &conn->hdev->random_addr); 51448c2ecf20Sopenharmony_ci } else { 51458c2ecf20Sopenharmony_ci bacpy(&conn->resp_addr, &conn->hdev->bdaddr); 51468c2ecf20Sopenharmony_ci } 51478c2ecf20Sopenharmony_ci 51488c2ecf20Sopenharmony_ci conn->init_addr_type = bdaddr_type; 51498c2ecf20Sopenharmony_ci bacpy(&conn->init_addr, bdaddr); 51508c2ecf20Sopenharmony_ci 51518c2ecf20Sopenharmony_ci /* For incoming connections, set the default minimum 51528c2ecf20Sopenharmony_ci * and maximum connection interval. They will be used 51538c2ecf20Sopenharmony_ci * to check if the parameters are in range and if not 51548c2ecf20Sopenharmony_ci * trigger the connection update procedure. 51558c2ecf20Sopenharmony_ci */ 51568c2ecf20Sopenharmony_ci conn->le_conn_min_interval = conn->hdev->le_conn_min_interval; 51578c2ecf20Sopenharmony_ci conn->le_conn_max_interval = conn->hdev->le_conn_max_interval; 51588c2ecf20Sopenharmony_ci } 51598c2ecf20Sopenharmony_ci} 51608c2ecf20Sopenharmony_ci 51618c2ecf20Sopenharmony_cistatic void le_conn_complete_evt(struct hci_dev *hdev, u8 status, 51628c2ecf20Sopenharmony_ci bdaddr_t *bdaddr, u8 bdaddr_type, 51638c2ecf20Sopenharmony_ci bdaddr_t *local_rpa, u8 role, u16 handle, 51648c2ecf20Sopenharmony_ci u16 interval, u16 latency, 51658c2ecf20Sopenharmony_ci u16 supervision_timeout) 51668c2ecf20Sopenharmony_ci{ 51678c2ecf20Sopenharmony_ci struct hci_conn_params *params; 51688c2ecf20Sopenharmony_ci struct hci_conn *conn; 51698c2ecf20Sopenharmony_ci struct smp_irk *irk; 51708c2ecf20Sopenharmony_ci u8 addr_type; 51718c2ecf20Sopenharmony_ci 51728c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 51738c2ecf20Sopenharmony_ci 51748c2ecf20Sopenharmony_ci /* All controllers implicitly stop advertising in the event of a 51758c2ecf20Sopenharmony_ci * connection, so ensure that the state bit is cleared. 51768c2ecf20Sopenharmony_ci */ 51778c2ecf20Sopenharmony_ci hci_dev_clear_flag(hdev, HCI_LE_ADV); 51788c2ecf20Sopenharmony_ci 51798c2ecf20Sopenharmony_ci conn = hci_lookup_le_connect(hdev); 51808c2ecf20Sopenharmony_ci if (!conn) { 51818c2ecf20Sopenharmony_ci conn = hci_conn_add(hdev, LE_LINK, bdaddr, role); 51828c2ecf20Sopenharmony_ci if (!conn) { 51838c2ecf20Sopenharmony_ci bt_dev_err(hdev, "no memory for new connection"); 51848c2ecf20Sopenharmony_ci goto unlock; 51858c2ecf20Sopenharmony_ci } 51868c2ecf20Sopenharmony_ci 51878c2ecf20Sopenharmony_ci conn->dst_type = bdaddr_type; 51888c2ecf20Sopenharmony_ci 51898c2ecf20Sopenharmony_ci /* If we didn't have a hci_conn object previously 51908c2ecf20Sopenharmony_ci * but we're in central role this must be something 51918c2ecf20Sopenharmony_ci * initiated using an accept list. Since accept list based 51928c2ecf20Sopenharmony_ci * connections are not "first class citizens" we don't 51938c2ecf20Sopenharmony_ci * have full tracking of them. Therefore, we go ahead 51948c2ecf20Sopenharmony_ci * with a "best effort" approach of determining the 51958c2ecf20Sopenharmony_ci * initiator address based on the HCI_PRIVACY flag. 51968c2ecf20Sopenharmony_ci */ 51978c2ecf20Sopenharmony_ci if (conn->out) { 51988c2ecf20Sopenharmony_ci conn->resp_addr_type = bdaddr_type; 51998c2ecf20Sopenharmony_ci bacpy(&conn->resp_addr, bdaddr); 52008c2ecf20Sopenharmony_ci if (hci_dev_test_flag(hdev, HCI_PRIVACY)) { 52018c2ecf20Sopenharmony_ci conn->init_addr_type = ADDR_LE_DEV_RANDOM; 52028c2ecf20Sopenharmony_ci bacpy(&conn->init_addr, &hdev->rpa); 52038c2ecf20Sopenharmony_ci } else { 52048c2ecf20Sopenharmony_ci hci_copy_identity_address(hdev, 52058c2ecf20Sopenharmony_ci &conn->init_addr, 52068c2ecf20Sopenharmony_ci &conn->init_addr_type); 52078c2ecf20Sopenharmony_ci } 52088c2ecf20Sopenharmony_ci } 52098c2ecf20Sopenharmony_ci } else { 52108c2ecf20Sopenharmony_ci cancel_delayed_work(&conn->le_conn_timeout); 52118c2ecf20Sopenharmony_ci } 52128c2ecf20Sopenharmony_ci 52138c2ecf20Sopenharmony_ci le_conn_update_addr(conn, bdaddr, bdaddr_type, local_rpa); 52148c2ecf20Sopenharmony_ci 52158c2ecf20Sopenharmony_ci /* Lookup the identity address from the stored connection 52168c2ecf20Sopenharmony_ci * address and address type. 52178c2ecf20Sopenharmony_ci * 52188c2ecf20Sopenharmony_ci * When establishing connections to an identity address, the 52198c2ecf20Sopenharmony_ci * connection procedure will store the resolvable random 52208c2ecf20Sopenharmony_ci * address first. Now if it can be converted back into the 52218c2ecf20Sopenharmony_ci * identity address, start using the identity address from 52228c2ecf20Sopenharmony_ci * now on. 52238c2ecf20Sopenharmony_ci */ 52248c2ecf20Sopenharmony_ci irk = hci_get_irk(hdev, &conn->dst, conn->dst_type); 52258c2ecf20Sopenharmony_ci if (irk) { 52268c2ecf20Sopenharmony_ci bacpy(&conn->dst, &irk->bdaddr); 52278c2ecf20Sopenharmony_ci conn->dst_type = irk->addr_type; 52288c2ecf20Sopenharmony_ci } 52298c2ecf20Sopenharmony_ci 52308c2ecf20Sopenharmony_ci if (status) { 52318c2ecf20Sopenharmony_ci hci_le_conn_failed(conn, status); 52328c2ecf20Sopenharmony_ci goto unlock; 52338c2ecf20Sopenharmony_ci } 52348c2ecf20Sopenharmony_ci 52358c2ecf20Sopenharmony_ci if (conn->dst_type == ADDR_LE_DEV_PUBLIC) 52368c2ecf20Sopenharmony_ci addr_type = BDADDR_LE_PUBLIC; 52378c2ecf20Sopenharmony_ci else 52388c2ecf20Sopenharmony_ci addr_type = BDADDR_LE_RANDOM; 52398c2ecf20Sopenharmony_ci 52408c2ecf20Sopenharmony_ci /* Drop the connection if the device is blocked */ 52418c2ecf20Sopenharmony_ci if (hci_bdaddr_list_lookup(&hdev->reject_list, &conn->dst, addr_type)) { 52428c2ecf20Sopenharmony_ci hci_conn_drop(conn); 52438c2ecf20Sopenharmony_ci goto unlock; 52448c2ecf20Sopenharmony_ci } 52458c2ecf20Sopenharmony_ci 52468c2ecf20Sopenharmony_ci if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 52478c2ecf20Sopenharmony_ci mgmt_device_connected(hdev, conn, 0, NULL, 0); 52488c2ecf20Sopenharmony_ci 52498c2ecf20Sopenharmony_ci conn->sec_level = BT_SECURITY_LOW; 52508c2ecf20Sopenharmony_ci conn->handle = handle; 52518c2ecf20Sopenharmony_ci conn->state = BT_CONFIG; 52528c2ecf20Sopenharmony_ci 52538c2ecf20Sopenharmony_ci conn->le_conn_interval = interval; 52548c2ecf20Sopenharmony_ci conn->le_conn_latency = latency; 52558c2ecf20Sopenharmony_ci conn->le_supv_timeout = supervision_timeout; 52568c2ecf20Sopenharmony_ci 52578c2ecf20Sopenharmony_ci hci_debugfs_create_conn(conn); 52588c2ecf20Sopenharmony_ci hci_conn_add_sysfs(conn); 52598c2ecf20Sopenharmony_ci 52608c2ecf20Sopenharmony_ci /* The remote features procedure is defined for master 52618c2ecf20Sopenharmony_ci * role only. So only in case of an initiated connection 52628c2ecf20Sopenharmony_ci * request the remote features. 52638c2ecf20Sopenharmony_ci * 52648c2ecf20Sopenharmony_ci * If the local controller supports slave-initiated features 52658c2ecf20Sopenharmony_ci * exchange, then requesting the remote features in slave 52668c2ecf20Sopenharmony_ci * role is possible. Otherwise just transition into the 52678c2ecf20Sopenharmony_ci * connected state without requesting the remote features. 52688c2ecf20Sopenharmony_ci */ 52698c2ecf20Sopenharmony_ci if (conn->out || 52708c2ecf20Sopenharmony_ci (hdev->le_features[0] & HCI_LE_SLAVE_FEATURES)) { 52718c2ecf20Sopenharmony_ci struct hci_cp_le_read_remote_features cp; 52728c2ecf20Sopenharmony_ci 52738c2ecf20Sopenharmony_ci cp.handle = __cpu_to_le16(conn->handle); 52748c2ecf20Sopenharmony_ci 52758c2ecf20Sopenharmony_ci hci_send_cmd(hdev, HCI_OP_LE_READ_REMOTE_FEATURES, 52768c2ecf20Sopenharmony_ci sizeof(cp), &cp); 52778c2ecf20Sopenharmony_ci 52788c2ecf20Sopenharmony_ci hci_conn_hold(conn); 52798c2ecf20Sopenharmony_ci } else { 52808c2ecf20Sopenharmony_ci conn->state = BT_CONNECTED; 52818c2ecf20Sopenharmony_ci hci_connect_cfm(conn, status); 52828c2ecf20Sopenharmony_ci } 52838c2ecf20Sopenharmony_ci 52848c2ecf20Sopenharmony_ci params = hci_pend_le_action_lookup(&hdev->pend_le_conns, &conn->dst, 52858c2ecf20Sopenharmony_ci conn->dst_type); 52868c2ecf20Sopenharmony_ci if (params) { 52878c2ecf20Sopenharmony_ci list_del_init(¶ms->action); 52888c2ecf20Sopenharmony_ci if (params->conn) { 52898c2ecf20Sopenharmony_ci hci_conn_drop(params->conn); 52908c2ecf20Sopenharmony_ci hci_conn_put(params->conn); 52918c2ecf20Sopenharmony_ci params->conn = NULL; 52928c2ecf20Sopenharmony_ci } 52938c2ecf20Sopenharmony_ci } 52948c2ecf20Sopenharmony_ci 52958c2ecf20Sopenharmony_ciunlock: 52968c2ecf20Sopenharmony_ci hci_update_background_scan(hdev); 52978c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 52988c2ecf20Sopenharmony_ci} 52998c2ecf20Sopenharmony_ci 53008c2ecf20Sopenharmony_cistatic void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 53018c2ecf20Sopenharmony_ci{ 53028c2ecf20Sopenharmony_ci struct hci_ev_le_conn_complete *ev = (void *) skb->data; 53038c2ecf20Sopenharmony_ci 53048c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 53058c2ecf20Sopenharmony_ci 53068c2ecf20Sopenharmony_ci le_conn_complete_evt(hdev, ev->status, &ev->bdaddr, ev->bdaddr_type, 53078c2ecf20Sopenharmony_ci NULL, ev->role, le16_to_cpu(ev->handle), 53088c2ecf20Sopenharmony_ci le16_to_cpu(ev->interval), 53098c2ecf20Sopenharmony_ci le16_to_cpu(ev->latency), 53108c2ecf20Sopenharmony_ci le16_to_cpu(ev->supervision_timeout)); 53118c2ecf20Sopenharmony_ci} 53128c2ecf20Sopenharmony_ci 53138c2ecf20Sopenharmony_cistatic void hci_le_enh_conn_complete_evt(struct hci_dev *hdev, 53148c2ecf20Sopenharmony_ci struct sk_buff *skb) 53158c2ecf20Sopenharmony_ci{ 53168c2ecf20Sopenharmony_ci struct hci_ev_le_enh_conn_complete *ev = (void *) skb->data; 53178c2ecf20Sopenharmony_ci 53188c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 53198c2ecf20Sopenharmony_ci 53208c2ecf20Sopenharmony_ci le_conn_complete_evt(hdev, ev->status, &ev->bdaddr, ev->bdaddr_type, 53218c2ecf20Sopenharmony_ci &ev->local_rpa, ev->role, le16_to_cpu(ev->handle), 53228c2ecf20Sopenharmony_ci le16_to_cpu(ev->interval), 53238c2ecf20Sopenharmony_ci le16_to_cpu(ev->latency), 53248c2ecf20Sopenharmony_ci le16_to_cpu(ev->supervision_timeout)); 53258c2ecf20Sopenharmony_ci 53268c2ecf20Sopenharmony_ci if (use_ll_privacy(hdev) && 53278c2ecf20Sopenharmony_ci hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY) && 53288c2ecf20Sopenharmony_ci hci_dev_test_flag(hdev, HCI_LL_RPA_RESOLUTION)) 53298c2ecf20Sopenharmony_ci hci_req_disable_address_resolution(hdev); 53308c2ecf20Sopenharmony_ci} 53318c2ecf20Sopenharmony_ci 53328c2ecf20Sopenharmony_cistatic void hci_le_ext_adv_term_evt(struct hci_dev *hdev, struct sk_buff *skb) 53338c2ecf20Sopenharmony_ci{ 53348c2ecf20Sopenharmony_ci struct hci_evt_le_ext_adv_set_term *ev = (void *) skb->data; 53358c2ecf20Sopenharmony_ci struct hci_conn *conn; 53368c2ecf20Sopenharmony_ci 53378c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 53388c2ecf20Sopenharmony_ci 53398c2ecf20Sopenharmony_ci if (ev->status) { 53408c2ecf20Sopenharmony_ci struct adv_info *adv; 53418c2ecf20Sopenharmony_ci 53428c2ecf20Sopenharmony_ci adv = hci_find_adv_instance(hdev, ev->handle); 53438c2ecf20Sopenharmony_ci if (!adv) 53448c2ecf20Sopenharmony_ci return; 53458c2ecf20Sopenharmony_ci 53468c2ecf20Sopenharmony_ci /* Remove advertising as it has been terminated */ 53478c2ecf20Sopenharmony_ci hci_remove_adv_instance(hdev, ev->handle); 53488c2ecf20Sopenharmony_ci mgmt_advertising_removed(NULL, hdev, ev->handle); 53498c2ecf20Sopenharmony_ci 53508c2ecf20Sopenharmony_ci return; 53518c2ecf20Sopenharmony_ci } 53528c2ecf20Sopenharmony_ci 53538c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->conn_handle)); 53548c2ecf20Sopenharmony_ci if (conn) { 53558c2ecf20Sopenharmony_ci struct adv_info *adv_instance; 53568c2ecf20Sopenharmony_ci 53578c2ecf20Sopenharmony_ci if (hdev->adv_addr_type != ADDR_LE_DEV_RANDOM || 53588c2ecf20Sopenharmony_ci bacmp(&conn->resp_addr, BDADDR_ANY)) 53598c2ecf20Sopenharmony_ci return; 53608c2ecf20Sopenharmony_ci 53618c2ecf20Sopenharmony_ci if (!hdev->cur_adv_instance) { 53628c2ecf20Sopenharmony_ci bacpy(&conn->resp_addr, &hdev->random_addr); 53638c2ecf20Sopenharmony_ci return; 53648c2ecf20Sopenharmony_ci } 53658c2ecf20Sopenharmony_ci 53668c2ecf20Sopenharmony_ci adv_instance = hci_find_adv_instance(hdev, hdev->cur_adv_instance); 53678c2ecf20Sopenharmony_ci if (adv_instance) 53688c2ecf20Sopenharmony_ci bacpy(&conn->resp_addr, &adv_instance->random_addr); 53698c2ecf20Sopenharmony_ci } 53708c2ecf20Sopenharmony_ci} 53718c2ecf20Sopenharmony_ci 53728c2ecf20Sopenharmony_cistatic void hci_le_conn_update_complete_evt(struct hci_dev *hdev, 53738c2ecf20Sopenharmony_ci struct sk_buff *skb) 53748c2ecf20Sopenharmony_ci{ 53758c2ecf20Sopenharmony_ci struct hci_ev_le_conn_update_complete *ev = (void *) skb->data; 53768c2ecf20Sopenharmony_ci struct hci_conn *conn; 53778c2ecf20Sopenharmony_ci 53788c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 53798c2ecf20Sopenharmony_ci 53808c2ecf20Sopenharmony_ci if (ev->status) 53818c2ecf20Sopenharmony_ci return; 53828c2ecf20Sopenharmony_ci 53838c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 53848c2ecf20Sopenharmony_ci 53858c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 53868c2ecf20Sopenharmony_ci if (conn) { 53878c2ecf20Sopenharmony_ci conn->le_conn_interval = le16_to_cpu(ev->interval); 53888c2ecf20Sopenharmony_ci conn->le_conn_latency = le16_to_cpu(ev->latency); 53898c2ecf20Sopenharmony_ci conn->le_supv_timeout = le16_to_cpu(ev->supervision_timeout); 53908c2ecf20Sopenharmony_ci } 53918c2ecf20Sopenharmony_ci 53928c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 53938c2ecf20Sopenharmony_ci} 53948c2ecf20Sopenharmony_ci 53958c2ecf20Sopenharmony_ci/* This function requires the caller holds hdev->lock */ 53968c2ecf20Sopenharmony_cistatic struct hci_conn *check_pending_le_conn(struct hci_dev *hdev, 53978c2ecf20Sopenharmony_ci bdaddr_t *addr, 53988c2ecf20Sopenharmony_ci u8 addr_type, u8 adv_type, 53998c2ecf20Sopenharmony_ci bdaddr_t *direct_rpa) 54008c2ecf20Sopenharmony_ci{ 54018c2ecf20Sopenharmony_ci struct hci_conn *conn; 54028c2ecf20Sopenharmony_ci struct hci_conn_params *params; 54038c2ecf20Sopenharmony_ci 54048c2ecf20Sopenharmony_ci /* If the event is not connectable don't proceed further */ 54058c2ecf20Sopenharmony_ci if (adv_type != LE_ADV_IND && adv_type != LE_ADV_DIRECT_IND) 54068c2ecf20Sopenharmony_ci return NULL; 54078c2ecf20Sopenharmony_ci 54088c2ecf20Sopenharmony_ci /* Ignore if the device is blocked */ 54098c2ecf20Sopenharmony_ci if (hci_bdaddr_list_lookup(&hdev->reject_list, addr, addr_type)) 54108c2ecf20Sopenharmony_ci return NULL; 54118c2ecf20Sopenharmony_ci 54128c2ecf20Sopenharmony_ci /* Most controller will fail if we try to create new connections 54138c2ecf20Sopenharmony_ci * while we have an existing one in slave role. 54148c2ecf20Sopenharmony_ci */ 54158c2ecf20Sopenharmony_ci if (hdev->conn_hash.le_num_slave > 0 && 54168c2ecf20Sopenharmony_ci (!test_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks) || 54178c2ecf20Sopenharmony_ci !(hdev->le_states[3] & 0x10))) 54188c2ecf20Sopenharmony_ci return NULL; 54198c2ecf20Sopenharmony_ci 54208c2ecf20Sopenharmony_ci /* If we're not connectable only connect devices that we have in 54218c2ecf20Sopenharmony_ci * our pend_le_conns list. 54228c2ecf20Sopenharmony_ci */ 54238c2ecf20Sopenharmony_ci params = hci_pend_le_action_lookup(&hdev->pend_le_conns, addr, 54248c2ecf20Sopenharmony_ci addr_type); 54258c2ecf20Sopenharmony_ci if (!params) 54268c2ecf20Sopenharmony_ci return NULL; 54278c2ecf20Sopenharmony_ci 54288c2ecf20Sopenharmony_ci if (!params->explicit_connect) { 54298c2ecf20Sopenharmony_ci switch (params->auto_connect) { 54308c2ecf20Sopenharmony_ci case HCI_AUTO_CONN_DIRECT: 54318c2ecf20Sopenharmony_ci /* Only devices advertising with ADV_DIRECT_IND are 54328c2ecf20Sopenharmony_ci * triggering a connection attempt. This is allowing 54338c2ecf20Sopenharmony_ci * incoming connections from slave devices. 54348c2ecf20Sopenharmony_ci */ 54358c2ecf20Sopenharmony_ci if (adv_type != LE_ADV_DIRECT_IND) 54368c2ecf20Sopenharmony_ci return NULL; 54378c2ecf20Sopenharmony_ci break; 54388c2ecf20Sopenharmony_ci case HCI_AUTO_CONN_ALWAYS: 54398c2ecf20Sopenharmony_ci /* Devices advertising with ADV_IND or ADV_DIRECT_IND 54408c2ecf20Sopenharmony_ci * are triggering a connection attempt. This means 54418c2ecf20Sopenharmony_ci * that incoming connections from slave device are 54428c2ecf20Sopenharmony_ci * accepted and also outgoing connections to slave 54438c2ecf20Sopenharmony_ci * devices are established when found. 54448c2ecf20Sopenharmony_ci */ 54458c2ecf20Sopenharmony_ci break; 54468c2ecf20Sopenharmony_ci default: 54478c2ecf20Sopenharmony_ci return NULL; 54488c2ecf20Sopenharmony_ci } 54498c2ecf20Sopenharmony_ci } 54508c2ecf20Sopenharmony_ci 54518c2ecf20Sopenharmony_ci conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW, 54528c2ecf20Sopenharmony_ci hdev->def_le_autoconnect_timeout, HCI_ROLE_MASTER, 54538c2ecf20Sopenharmony_ci direct_rpa); 54548c2ecf20Sopenharmony_ci if (!IS_ERR(conn)) { 54558c2ecf20Sopenharmony_ci /* If HCI_AUTO_CONN_EXPLICIT is set, conn is already owned 54568c2ecf20Sopenharmony_ci * by higher layer that tried to connect, if no then 54578c2ecf20Sopenharmony_ci * store the pointer since we don't really have any 54588c2ecf20Sopenharmony_ci * other owner of the object besides the params that 54598c2ecf20Sopenharmony_ci * triggered it. This way we can abort the connection if 54608c2ecf20Sopenharmony_ci * the parameters get removed and keep the reference 54618c2ecf20Sopenharmony_ci * count consistent once the connection is established. 54628c2ecf20Sopenharmony_ci */ 54638c2ecf20Sopenharmony_ci 54648c2ecf20Sopenharmony_ci if (!params->explicit_connect) 54658c2ecf20Sopenharmony_ci params->conn = hci_conn_get(conn); 54668c2ecf20Sopenharmony_ci 54678c2ecf20Sopenharmony_ci return conn; 54688c2ecf20Sopenharmony_ci } 54698c2ecf20Sopenharmony_ci 54708c2ecf20Sopenharmony_ci switch (PTR_ERR(conn)) { 54718c2ecf20Sopenharmony_ci case -EBUSY: 54728c2ecf20Sopenharmony_ci /* If hci_connect() returns -EBUSY it means there is already 54738c2ecf20Sopenharmony_ci * an LE connection attempt going on. Since controllers don't 54748c2ecf20Sopenharmony_ci * support more than one connection attempt at the time, we 54758c2ecf20Sopenharmony_ci * don't consider this an error case. 54768c2ecf20Sopenharmony_ci */ 54778c2ecf20Sopenharmony_ci break; 54788c2ecf20Sopenharmony_ci default: 54798c2ecf20Sopenharmony_ci BT_DBG("Failed to connect: err %ld", PTR_ERR(conn)); 54808c2ecf20Sopenharmony_ci return NULL; 54818c2ecf20Sopenharmony_ci } 54828c2ecf20Sopenharmony_ci 54838c2ecf20Sopenharmony_ci return NULL; 54848c2ecf20Sopenharmony_ci} 54858c2ecf20Sopenharmony_ci 54868c2ecf20Sopenharmony_cistatic void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, 54878c2ecf20Sopenharmony_ci u8 bdaddr_type, bdaddr_t *direct_addr, 54888c2ecf20Sopenharmony_ci u8 direct_addr_type, s8 rssi, u8 *data, u8 len, 54898c2ecf20Sopenharmony_ci bool ext_adv) 54908c2ecf20Sopenharmony_ci{ 54918c2ecf20Sopenharmony_ci struct discovery_state *d = &hdev->discovery; 54928c2ecf20Sopenharmony_ci struct smp_irk *irk; 54938c2ecf20Sopenharmony_ci struct hci_conn *conn; 54948c2ecf20Sopenharmony_ci bool match; 54958c2ecf20Sopenharmony_ci u32 flags; 54968c2ecf20Sopenharmony_ci u8 *ptr; 54978c2ecf20Sopenharmony_ci 54988c2ecf20Sopenharmony_ci switch (type) { 54998c2ecf20Sopenharmony_ci case LE_ADV_IND: 55008c2ecf20Sopenharmony_ci case LE_ADV_DIRECT_IND: 55018c2ecf20Sopenharmony_ci case LE_ADV_SCAN_IND: 55028c2ecf20Sopenharmony_ci case LE_ADV_NONCONN_IND: 55038c2ecf20Sopenharmony_ci case LE_ADV_SCAN_RSP: 55048c2ecf20Sopenharmony_ci break; 55058c2ecf20Sopenharmony_ci default: 55068c2ecf20Sopenharmony_ci bt_dev_err_ratelimited(hdev, "unknown advertising packet " 55078c2ecf20Sopenharmony_ci "type: 0x%02x", type); 55088c2ecf20Sopenharmony_ci return; 55098c2ecf20Sopenharmony_ci } 55108c2ecf20Sopenharmony_ci 55118c2ecf20Sopenharmony_ci if (!ext_adv && len > HCI_MAX_AD_LENGTH) { 55128c2ecf20Sopenharmony_ci bt_dev_err_ratelimited(hdev, "legacy adv larger than 31 bytes"); 55138c2ecf20Sopenharmony_ci return; 55148c2ecf20Sopenharmony_ci } 55158c2ecf20Sopenharmony_ci 55168c2ecf20Sopenharmony_ci /* Find the end of the data in case the report contains padded zero 55178c2ecf20Sopenharmony_ci * bytes at the end causing an invalid length value. 55188c2ecf20Sopenharmony_ci * 55198c2ecf20Sopenharmony_ci * When data is NULL, len is 0 so there is no need for extra ptr 55208c2ecf20Sopenharmony_ci * check as 'ptr < data + 0' is already false in such case. 55218c2ecf20Sopenharmony_ci */ 55228c2ecf20Sopenharmony_ci for (ptr = data; ptr < data + len && *ptr; ptr += *ptr + 1) { 55238c2ecf20Sopenharmony_ci if (ptr + 1 + *ptr > data + len) 55248c2ecf20Sopenharmony_ci break; 55258c2ecf20Sopenharmony_ci } 55268c2ecf20Sopenharmony_ci 55278c2ecf20Sopenharmony_ci /* Adjust for actual length. This handles the case when remote 55288c2ecf20Sopenharmony_ci * device is advertising with incorrect data length. 55298c2ecf20Sopenharmony_ci */ 55308c2ecf20Sopenharmony_ci len = ptr - data; 55318c2ecf20Sopenharmony_ci 55328c2ecf20Sopenharmony_ci /* If the direct address is present, then this report is from 55338c2ecf20Sopenharmony_ci * a LE Direct Advertising Report event. In that case it is 55348c2ecf20Sopenharmony_ci * important to see if the address is matching the local 55358c2ecf20Sopenharmony_ci * controller address. 55368c2ecf20Sopenharmony_ci */ 55378c2ecf20Sopenharmony_ci if (direct_addr) { 55388c2ecf20Sopenharmony_ci /* Only resolvable random addresses are valid for these 55398c2ecf20Sopenharmony_ci * kind of reports and others can be ignored. 55408c2ecf20Sopenharmony_ci */ 55418c2ecf20Sopenharmony_ci if (!hci_bdaddr_is_rpa(direct_addr, direct_addr_type)) 55428c2ecf20Sopenharmony_ci return; 55438c2ecf20Sopenharmony_ci 55448c2ecf20Sopenharmony_ci /* If the controller is not using resolvable random 55458c2ecf20Sopenharmony_ci * addresses, then this report can be ignored. 55468c2ecf20Sopenharmony_ci */ 55478c2ecf20Sopenharmony_ci if (!hci_dev_test_flag(hdev, HCI_PRIVACY)) 55488c2ecf20Sopenharmony_ci return; 55498c2ecf20Sopenharmony_ci 55508c2ecf20Sopenharmony_ci /* If the local IRK of the controller does not match 55518c2ecf20Sopenharmony_ci * with the resolvable random address provided, then 55528c2ecf20Sopenharmony_ci * this report can be ignored. 55538c2ecf20Sopenharmony_ci */ 55548c2ecf20Sopenharmony_ci if (!smp_irk_matches(hdev, hdev->irk, direct_addr)) 55558c2ecf20Sopenharmony_ci return; 55568c2ecf20Sopenharmony_ci } 55578c2ecf20Sopenharmony_ci 55588c2ecf20Sopenharmony_ci /* Check if we need to convert to identity address */ 55598c2ecf20Sopenharmony_ci irk = hci_get_irk(hdev, bdaddr, bdaddr_type); 55608c2ecf20Sopenharmony_ci if (irk) { 55618c2ecf20Sopenharmony_ci bdaddr = &irk->bdaddr; 55628c2ecf20Sopenharmony_ci bdaddr_type = irk->addr_type; 55638c2ecf20Sopenharmony_ci } 55648c2ecf20Sopenharmony_ci 55658c2ecf20Sopenharmony_ci /* Check if we have been requested to connect to this device. 55668c2ecf20Sopenharmony_ci * 55678c2ecf20Sopenharmony_ci * direct_addr is set only for directed advertising reports (it is NULL 55688c2ecf20Sopenharmony_ci * for advertising reports) and is already verified to be RPA above. 55698c2ecf20Sopenharmony_ci */ 55708c2ecf20Sopenharmony_ci conn = check_pending_le_conn(hdev, bdaddr, bdaddr_type, type, 55718c2ecf20Sopenharmony_ci direct_addr); 55728c2ecf20Sopenharmony_ci if (!ext_adv && conn && type == LE_ADV_IND && len <= HCI_MAX_AD_LENGTH) { 55738c2ecf20Sopenharmony_ci /* Store report for later inclusion by 55748c2ecf20Sopenharmony_ci * mgmt_device_connected 55758c2ecf20Sopenharmony_ci */ 55768c2ecf20Sopenharmony_ci memcpy(conn->le_adv_data, data, len); 55778c2ecf20Sopenharmony_ci conn->le_adv_data_len = len; 55788c2ecf20Sopenharmony_ci } 55798c2ecf20Sopenharmony_ci 55808c2ecf20Sopenharmony_ci /* Passive scanning shouldn't trigger any device found events, 55818c2ecf20Sopenharmony_ci * except for devices marked as CONN_REPORT for which we do send 55828c2ecf20Sopenharmony_ci * device found events, or advertisement monitoring requested. 55838c2ecf20Sopenharmony_ci */ 55848c2ecf20Sopenharmony_ci if (hdev->le_scan_type == LE_SCAN_PASSIVE) { 55858c2ecf20Sopenharmony_ci if (type == LE_ADV_DIRECT_IND) 55868c2ecf20Sopenharmony_ci return; 55878c2ecf20Sopenharmony_ci 55888c2ecf20Sopenharmony_ci if (!hci_pend_le_action_lookup(&hdev->pend_le_reports, 55898c2ecf20Sopenharmony_ci bdaddr, bdaddr_type) && 55908c2ecf20Sopenharmony_ci idr_is_empty(&hdev->adv_monitors_idr)) 55918c2ecf20Sopenharmony_ci return; 55928c2ecf20Sopenharmony_ci 55938c2ecf20Sopenharmony_ci if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND) 55948c2ecf20Sopenharmony_ci flags = MGMT_DEV_FOUND_NOT_CONNECTABLE; 55958c2ecf20Sopenharmony_ci else 55968c2ecf20Sopenharmony_ci flags = 0; 55978c2ecf20Sopenharmony_ci mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL, 55988c2ecf20Sopenharmony_ci rssi, flags, data, len, NULL, 0); 55998c2ecf20Sopenharmony_ci return; 56008c2ecf20Sopenharmony_ci } 56018c2ecf20Sopenharmony_ci 56028c2ecf20Sopenharmony_ci /* When receiving non-connectable or scannable undirected 56038c2ecf20Sopenharmony_ci * advertising reports, this means that the remote device is 56048c2ecf20Sopenharmony_ci * not connectable and then clearly indicate this in the 56058c2ecf20Sopenharmony_ci * device found event. 56068c2ecf20Sopenharmony_ci * 56078c2ecf20Sopenharmony_ci * When receiving a scan response, then there is no way to 56088c2ecf20Sopenharmony_ci * know if the remote device is connectable or not. However 56098c2ecf20Sopenharmony_ci * since scan responses are merged with a previously seen 56108c2ecf20Sopenharmony_ci * advertising report, the flags field from that report 56118c2ecf20Sopenharmony_ci * will be used. 56128c2ecf20Sopenharmony_ci * 56138c2ecf20Sopenharmony_ci * In the really unlikely case that a controller get confused 56148c2ecf20Sopenharmony_ci * and just sends a scan response event, then it is marked as 56158c2ecf20Sopenharmony_ci * not connectable as well. 56168c2ecf20Sopenharmony_ci */ 56178c2ecf20Sopenharmony_ci if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND || 56188c2ecf20Sopenharmony_ci type == LE_ADV_SCAN_RSP) 56198c2ecf20Sopenharmony_ci flags = MGMT_DEV_FOUND_NOT_CONNECTABLE; 56208c2ecf20Sopenharmony_ci else 56218c2ecf20Sopenharmony_ci flags = 0; 56228c2ecf20Sopenharmony_ci 56238c2ecf20Sopenharmony_ci /* If there's nothing pending either store the data from this 56248c2ecf20Sopenharmony_ci * event or send an immediate device found event if the data 56258c2ecf20Sopenharmony_ci * should not be stored for later. 56268c2ecf20Sopenharmony_ci */ 56278c2ecf20Sopenharmony_ci if (!ext_adv && !has_pending_adv_report(hdev)) { 56288c2ecf20Sopenharmony_ci /* If the report will trigger a SCAN_REQ store it for 56298c2ecf20Sopenharmony_ci * later merging. 56308c2ecf20Sopenharmony_ci */ 56318c2ecf20Sopenharmony_ci if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) { 56328c2ecf20Sopenharmony_ci store_pending_adv_report(hdev, bdaddr, bdaddr_type, 56338c2ecf20Sopenharmony_ci rssi, flags, data, len); 56348c2ecf20Sopenharmony_ci return; 56358c2ecf20Sopenharmony_ci } 56368c2ecf20Sopenharmony_ci 56378c2ecf20Sopenharmony_ci mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL, 56388c2ecf20Sopenharmony_ci rssi, flags, data, len, NULL, 0); 56398c2ecf20Sopenharmony_ci return; 56408c2ecf20Sopenharmony_ci } 56418c2ecf20Sopenharmony_ci 56428c2ecf20Sopenharmony_ci /* Check if the pending report is for the same device as the new one */ 56438c2ecf20Sopenharmony_ci match = (!bacmp(bdaddr, &d->last_adv_addr) && 56448c2ecf20Sopenharmony_ci bdaddr_type == d->last_adv_addr_type); 56458c2ecf20Sopenharmony_ci 56468c2ecf20Sopenharmony_ci /* If the pending data doesn't match this report or this isn't a 56478c2ecf20Sopenharmony_ci * scan response (e.g. we got a duplicate ADV_IND) then force 56488c2ecf20Sopenharmony_ci * sending of the pending data. 56498c2ecf20Sopenharmony_ci */ 56508c2ecf20Sopenharmony_ci if (type != LE_ADV_SCAN_RSP || !match) { 56518c2ecf20Sopenharmony_ci /* Send out whatever is in the cache, but skip duplicates */ 56528c2ecf20Sopenharmony_ci if (!match) 56538c2ecf20Sopenharmony_ci mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK, 56548c2ecf20Sopenharmony_ci d->last_adv_addr_type, NULL, 56558c2ecf20Sopenharmony_ci d->last_adv_rssi, d->last_adv_flags, 56568c2ecf20Sopenharmony_ci d->last_adv_data, 56578c2ecf20Sopenharmony_ci d->last_adv_data_len, NULL, 0); 56588c2ecf20Sopenharmony_ci 56598c2ecf20Sopenharmony_ci /* If the new report will trigger a SCAN_REQ store it for 56608c2ecf20Sopenharmony_ci * later merging. 56618c2ecf20Sopenharmony_ci */ 56628c2ecf20Sopenharmony_ci if (!ext_adv && (type == LE_ADV_IND || 56638c2ecf20Sopenharmony_ci type == LE_ADV_SCAN_IND)) { 56648c2ecf20Sopenharmony_ci store_pending_adv_report(hdev, bdaddr, bdaddr_type, 56658c2ecf20Sopenharmony_ci rssi, flags, data, len); 56668c2ecf20Sopenharmony_ci return; 56678c2ecf20Sopenharmony_ci } 56688c2ecf20Sopenharmony_ci 56698c2ecf20Sopenharmony_ci /* The advertising reports cannot be merged, so clear 56708c2ecf20Sopenharmony_ci * the pending report and send out a device found event. 56718c2ecf20Sopenharmony_ci */ 56728c2ecf20Sopenharmony_ci clear_pending_adv_report(hdev); 56738c2ecf20Sopenharmony_ci mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL, 56748c2ecf20Sopenharmony_ci rssi, flags, data, len, NULL, 0); 56758c2ecf20Sopenharmony_ci return; 56768c2ecf20Sopenharmony_ci } 56778c2ecf20Sopenharmony_ci 56788c2ecf20Sopenharmony_ci /* If we get here we've got a pending ADV_IND or ADV_SCAN_IND and 56798c2ecf20Sopenharmony_ci * the new event is a SCAN_RSP. We can therefore proceed with 56808c2ecf20Sopenharmony_ci * sending a merged device found event. 56818c2ecf20Sopenharmony_ci */ 56828c2ecf20Sopenharmony_ci mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK, 56838c2ecf20Sopenharmony_ci d->last_adv_addr_type, NULL, rssi, d->last_adv_flags, 56848c2ecf20Sopenharmony_ci d->last_adv_data, d->last_adv_data_len, data, len); 56858c2ecf20Sopenharmony_ci clear_pending_adv_report(hdev); 56868c2ecf20Sopenharmony_ci} 56878c2ecf20Sopenharmony_ci 56888c2ecf20Sopenharmony_cistatic void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) 56898c2ecf20Sopenharmony_ci{ 56908c2ecf20Sopenharmony_ci u8 num_reports = skb->data[0]; 56918c2ecf20Sopenharmony_ci void *ptr = &skb->data[1]; 56928c2ecf20Sopenharmony_ci 56938c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 56948c2ecf20Sopenharmony_ci 56958c2ecf20Sopenharmony_ci while (num_reports--) { 56968c2ecf20Sopenharmony_ci struct hci_ev_le_advertising_info *ev = ptr; 56978c2ecf20Sopenharmony_ci s8 rssi; 56988c2ecf20Sopenharmony_ci 56998c2ecf20Sopenharmony_ci if (ptr > (void *)skb_tail_pointer(skb) - sizeof(*ev)) { 57008c2ecf20Sopenharmony_ci bt_dev_err(hdev, "Malicious advertising data."); 57018c2ecf20Sopenharmony_ci break; 57028c2ecf20Sopenharmony_ci } 57038c2ecf20Sopenharmony_ci 57048c2ecf20Sopenharmony_ci if (ev->length <= HCI_MAX_AD_LENGTH && 57058c2ecf20Sopenharmony_ci ev->data + ev->length <= skb_tail_pointer(skb)) { 57068c2ecf20Sopenharmony_ci rssi = ev->data[ev->length]; 57078c2ecf20Sopenharmony_ci process_adv_report(hdev, ev->evt_type, &ev->bdaddr, 57088c2ecf20Sopenharmony_ci ev->bdaddr_type, NULL, 0, rssi, 57098c2ecf20Sopenharmony_ci ev->data, ev->length, false); 57108c2ecf20Sopenharmony_ci } else { 57118c2ecf20Sopenharmony_ci bt_dev_err(hdev, "Dropping invalid advertising data"); 57128c2ecf20Sopenharmony_ci } 57138c2ecf20Sopenharmony_ci 57148c2ecf20Sopenharmony_ci ptr += sizeof(*ev) + ev->length + 1; 57158c2ecf20Sopenharmony_ci } 57168c2ecf20Sopenharmony_ci 57178c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 57188c2ecf20Sopenharmony_ci} 57198c2ecf20Sopenharmony_ci 57208c2ecf20Sopenharmony_cistatic u8 ext_evt_type_to_legacy(struct hci_dev *hdev, u16 evt_type) 57218c2ecf20Sopenharmony_ci{ 57228c2ecf20Sopenharmony_ci if (evt_type & LE_EXT_ADV_LEGACY_PDU) { 57238c2ecf20Sopenharmony_ci switch (evt_type) { 57248c2ecf20Sopenharmony_ci case LE_LEGACY_ADV_IND: 57258c2ecf20Sopenharmony_ci return LE_ADV_IND; 57268c2ecf20Sopenharmony_ci case LE_LEGACY_ADV_DIRECT_IND: 57278c2ecf20Sopenharmony_ci return LE_ADV_DIRECT_IND; 57288c2ecf20Sopenharmony_ci case LE_LEGACY_ADV_SCAN_IND: 57298c2ecf20Sopenharmony_ci return LE_ADV_SCAN_IND; 57308c2ecf20Sopenharmony_ci case LE_LEGACY_NONCONN_IND: 57318c2ecf20Sopenharmony_ci return LE_ADV_NONCONN_IND; 57328c2ecf20Sopenharmony_ci case LE_LEGACY_SCAN_RSP_ADV: 57338c2ecf20Sopenharmony_ci case LE_LEGACY_SCAN_RSP_ADV_SCAN: 57348c2ecf20Sopenharmony_ci return LE_ADV_SCAN_RSP; 57358c2ecf20Sopenharmony_ci } 57368c2ecf20Sopenharmony_ci 57378c2ecf20Sopenharmony_ci goto invalid; 57388c2ecf20Sopenharmony_ci } 57398c2ecf20Sopenharmony_ci 57408c2ecf20Sopenharmony_ci if (evt_type & LE_EXT_ADV_CONN_IND) { 57418c2ecf20Sopenharmony_ci if (evt_type & LE_EXT_ADV_DIRECT_IND) 57428c2ecf20Sopenharmony_ci return LE_ADV_DIRECT_IND; 57438c2ecf20Sopenharmony_ci 57448c2ecf20Sopenharmony_ci return LE_ADV_IND; 57458c2ecf20Sopenharmony_ci } 57468c2ecf20Sopenharmony_ci 57478c2ecf20Sopenharmony_ci if (evt_type & LE_EXT_ADV_SCAN_RSP) 57488c2ecf20Sopenharmony_ci return LE_ADV_SCAN_RSP; 57498c2ecf20Sopenharmony_ci 57508c2ecf20Sopenharmony_ci if (evt_type & LE_EXT_ADV_SCAN_IND) 57518c2ecf20Sopenharmony_ci return LE_ADV_SCAN_IND; 57528c2ecf20Sopenharmony_ci 57538c2ecf20Sopenharmony_ci if (evt_type == LE_EXT_ADV_NON_CONN_IND || 57548c2ecf20Sopenharmony_ci evt_type & LE_EXT_ADV_DIRECT_IND) 57558c2ecf20Sopenharmony_ci return LE_ADV_NONCONN_IND; 57568c2ecf20Sopenharmony_ci 57578c2ecf20Sopenharmony_ciinvalid: 57588c2ecf20Sopenharmony_ci bt_dev_err_ratelimited(hdev, "Unknown advertising packet type: 0x%02x", 57598c2ecf20Sopenharmony_ci evt_type); 57608c2ecf20Sopenharmony_ci 57618c2ecf20Sopenharmony_ci return LE_ADV_INVALID; 57628c2ecf20Sopenharmony_ci} 57638c2ecf20Sopenharmony_ci 57648c2ecf20Sopenharmony_cistatic void hci_le_ext_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) 57658c2ecf20Sopenharmony_ci{ 57668c2ecf20Sopenharmony_ci u8 num_reports = skb->data[0]; 57678c2ecf20Sopenharmony_ci void *ptr = &skb->data[1]; 57688c2ecf20Sopenharmony_ci 57698c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 57708c2ecf20Sopenharmony_ci 57718c2ecf20Sopenharmony_ci while (num_reports--) { 57728c2ecf20Sopenharmony_ci struct hci_ev_le_ext_adv_report *ev = ptr; 57738c2ecf20Sopenharmony_ci u8 legacy_evt_type; 57748c2ecf20Sopenharmony_ci u16 evt_type; 57758c2ecf20Sopenharmony_ci 57768c2ecf20Sopenharmony_ci evt_type = __le16_to_cpu(ev->evt_type); 57778c2ecf20Sopenharmony_ci legacy_evt_type = ext_evt_type_to_legacy(hdev, evt_type); 57788c2ecf20Sopenharmony_ci if (legacy_evt_type != LE_ADV_INVALID) { 57798c2ecf20Sopenharmony_ci process_adv_report(hdev, legacy_evt_type, &ev->bdaddr, 57808c2ecf20Sopenharmony_ci ev->bdaddr_type, NULL, 0, ev->rssi, 57818c2ecf20Sopenharmony_ci ev->data, ev->length, 57828c2ecf20Sopenharmony_ci !(evt_type & LE_EXT_ADV_LEGACY_PDU)); 57838c2ecf20Sopenharmony_ci } 57848c2ecf20Sopenharmony_ci 57858c2ecf20Sopenharmony_ci ptr += sizeof(*ev) + ev->length; 57868c2ecf20Sopenharmony_ci } 57878c2ecf20Sopenharmony_ci 57888c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 57898c2ecf20Sopenharmony_ci} 57908c2ecf20Sopenharmony_ci 57918c2ecf20Sopenharmony_cistatic void hci_le_remote_feat_complete_evt(struct hci_dev *hdev, 57928c2ecf20Sopenharmony_ci struct sk_buff *skb) 57938c2ecf20Sopenharmony_ci{ 57948c2ecf20Sopenharmony_ci struct hci_ev_le_remote_feat_complete *ev = (void *)skb->data; 57958c2ecf20Sopenharmony_ci struct hci_conn *conn; 57968c2ecf20Sopenharmony_ci 57978c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 57988c2ecf20Sopenharmony_ci 57998c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 58008c2ecf20Sopenharmony_ci 58018c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 58028c2ecf20Sopenharmony_ci if (conn) { 58038c2ecf20Sopenharmony_ci if (!ev->status) 58048c2ecf20Sopenharmony_ci memcpy(conn->features[0], ev->features, 8); 58058c2ecf20Sopenharmony_ci 58068c2ecf20Sopenharmony_ci if (conn->state == BT_CONFIG) { 58078c2ecf20Sopenharmony_ci __u8 status; 58088c2ecf20Sopenharmony_ci 58098c2ecf20Sopenharmony_ci /* If the local controller supports slave-initiated 58108c2ecf20Sopenharmony_ci * features exchange, but the remote controller does 58118c2ecf20Sopenharmony_ci * not, then it is possible that the error code 0x1a 58128c2ecf20Sopenharmony_ci * for unsupported remote feature gets returned. 58138c2ecf20Sopenharmony_ci * 58148c2ecf20Sopenharmony_ci * In this specific case, allow the connection to 58158c2ecf20Sopenharmony_ci * transition into connected state and mark it as 58168c2ecf20Sopenharmony_ci * successful. 58178c2ecf20Sopenharmony_ci */ 58188c2ecf20Sopenharmony_ci if ((hdev->le_features[0] & HCI_LE_SLAVE_FEATURES) && 58198c2ecf20Sopenharmony_ci !conn->out && ev->status == 0x1a) 58208c2ecf20Sopenharmony_ci status = 0x00; 58218c2ecf20Sopenharmony_ci else 58228c2ecf20Sopenharmony_ci status = ev->status; 58238c2ecf20Sopenharmony_ci 58248c2ecf20Sopenharmony_ci conn->state = BT_CONNECTED; 58258c2ecf20Sopenharmony_ci hci_connect_cfm(conn, status); 58268c2ecf20Sopenharmony_ci hci_conn_drop(conn); 58278c2ecf20Sopenharmony_ci } 58288c2ecf20Sopenharmony_ci } 58298c2ecf20Sopenharmony_ci 58308c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 58318c2ecf20Sopenharmony_ci} 58328c2ecf20Sopenharmony_ci 58338c2ecf20Sopenharmony_cistatic void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 58348c2ecf20Sopenharmony_ci{ 58358c2ecf20Sopenharmony_ci struct hci_ev_le_ltk_req *ev = (void *) skb->data; 58368c2ecf20Sopenharmony_ci struct hci_cp_le_ltk_reply cp; 58378c2ecf20Sopenharmony_ci struct hci_cp_le_ltk_neg_reply neg; 58388c2ecf20Sopenharmony_ci struct hci_conn *conn; 58398c2ecf20Sopenharmony_ci struct smp_ltk *ltk; 58408c2ecf20Sopenharmony_ci 58418c2ecf20Sopenharmony_ci BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle)); 58428c2ecf20Sopenharmony_ci 58438c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 58448c2ecf20Sopenharmony_ci 58458c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 58468c2ecf20Sopenharmony_ci if (conn == NULL) 58478c2ecf20Sopenharmony_ci goto not_found; 58488c2ecf20Sopenharmony_ci 58498c2ecf20Sopenharmony_ci ltk = hci_find_ltk(hdev, &conn->dst, conn->dst_type, conn->role); 58508c2ecf20Sopenharmony_ci if (!ltk) 58518c2ecf20Sopenharmony_ci goto not_found; 58528c2ecf20Sopenharmony_ci 58538c2ecf20Sopenharmony_ci if (smp_ltk_is_sc(ltk)) { 58548c2ecf20Sopenharmony_ci /* With SC both EDiv and Rand are set to zero */ 58558c2ecf20Sopenharmony_ci if (ev->ediv || ev->rand) 58568c2ecf20Sopenharmony_ci goto not_found; 58578c2ecf20Sopenharmony_ci } else { 58588c2ecf20Sopenharmony_ci /* For non-SC keys check that EDiv and Rand match */ 58598c2ecf20Sopenharmony_ci if (ev->ediv != ltk->ediv || ev->rand != ltk->rand) 58608c2ecf20Sopenharmony_ci goto not_found; 58618c2ecf20Sopenharmony_ci } 58628c2ecf20Sopenharmony_ci 58638c2ecf20Sopenharmony_ci memcpy(cp.ltk, ltk->val, ltk->enc_size); 58648c2ecf20Sopenharmony_ci memset(cp.ltk + ltk->enc_size, 0, sizeof(cp.ltk) - ltk->enc_size); 58658c2ecf20Sopenharmony_ci cp.handle = cpu_to_le16(conn->handle); 58668c2ecf20Sopenharmony_ci 58678c2ecf20Sopenharmony_ci conn->pending_sec_level = smp_ltk_sec_level(ltk); 58688c2ecf20Sopenharmony_ci 58698c2ecf20Sopenharmony_ci conn->enc_key_size = ltk->enc_size; 58708c2ecf20Sopenharmony_ci 58718c2ecf20Sopenharmony_ci hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); 58728c2ecf20Sopenharmony_ci 58738c2ecf20Sopenharmony_ci /* Ref. Bluetooth Core SPEC pages 1975 and 2004. STK is a 58748c2ecf20Sopenharmony_ci * temporary key used to encrypt a connection following 58758c2ecf20Sopenharmony_ci * pairing. It is used during the Encrypted Session Setup to 58768c2ecf20Sopenharmony_ci * distribute the keys. Later, security can be re-established 58778c2ecf20Sopenharmony_ci * using a distributed LTK. 58788c2ecf20Sopenharmony_ci */ 58798c2ecf20Sopenharmony_ci if (ltk->type == SMP_STK) { 58808c2ecf20Sopenharmony_ci set_bit(HCI_CONN_STK_ENCRYPT, &conn->flags); 58818c2ecf20Sopenharmony_ci list_del_rcu(<k->list); 58828c2ecf20Sopenharmony_ci kfree_rcu(ltk, rcu); 58838c2ecf20Sopenharmony_ci } else { 58848c2ecf20Sopenharmony_ci clear_bit(HCI_CONN_STK_ENCRYPT, &conn->flags); 58858c2ecf20Sopenharmony_ci } 58868c2ecf20Sopenharmony_ci 58878c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 58888c2ecf20Sopenharmony_ci 58898c2ecf20Sopenharmony_ci return; 58908c2ecf20Sopenharmony_ci 58918c2ecf20Sopenharmony_cinot_found: 58928c2ecf20Sopenharmony_ci neg.handle = ev->handle; 58938c2ecf20Sopenharmony_ci hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg); 58948c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 58958c2ecf20Sopenharmony_ci} 58968c2ecf20Sopenharmony_ci 58978c2ecf20Sopenharmony_cistatic void send_conn_param_neg_reply(struct hci_dev *hdev, u16 handle, 58988c2ecf20Sopenharmony_ci u8 reason) 58998c2ecf20Sopenharmony_ci{ 59008c2ecf20Sopenharmony_ci struct hci_cp_le_conn_param_req_neg_reply cp; 59018c2ecf20Sopenharmony_ci 59028c2ecf20Sopenharmony_ci cp.handle = cpu_to_le16(handle); 59038c2ecf20Sopenharmony_ci cp.reason = reason; 59048c2ecf20Sopenharmony_ci 59058c2ecf20Sopenharmony_ci hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY, sizeof(cp), 59068c2ecf20Sopenharmony_ci &cp); 59078c2ecf20Sopenharmony_ci} 59088c2ecf20Sopenharmony_ci 59098c2ecf20Sopenharmony_cistatic void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev, 59108c2ecf20Sopenharmony_ci struct sk_buff *skb) 59118c2ecf20Sopenharmony_ci{ 59128c2ecf20Sopenharmony_ci struct hci_ev_le_remote_conn_param_req *ev = (void *) skb->data; 59138c2ecf20Sopenharmony_ci struct hci_cp_le_conn_param_req_reply cp; 59148c2ecf20Sopenharmony_ci struct hci_conn *hcon; 59158c2ecf20Sopenharmony_ci u16 handle, min, max, latency, timeout; 59168c2ecf20Sopenharmony_ci 59178c2ecf20Sopenharmony_ci handle = le16_to_cpu(ev->handle); 59188c2ecf20Sopenharmony_ci min = le16_to_cpu(ev->interval_min); 59198c2ecf20Sopenharmony_ci max = le16_to_cpu(ev->interval_max); 59208c2ecf20Sopenharmony_ci latency = le16_to_cpu(ev->latency); 59218c2ecf20Sopenharmony_ci timeout = le16_to_cpu(ev->timeout); 59228c2ecf20Sopenharmony_ci 59238c2ecf20Sopenharmony_ci hcon = hci_conn_hash_lookup_handle(hdev, handle); 59248c2ecf20Sopenharmony_ci if (!hcon || hcon->state != BT_CONNECTED) 59258c2ecf20Sopenharmony_ci return send_conn_param_neg_reply(hdev, handle, 59268c2ecf20Sopenharmony_ci HCI_ERROR_UNKNOWN_CONN_ID); 59278c2ecf20Sopenharmony_ci 59288c2ecf20Sopenharmony_ci if (hci_check_conn_params(min, max, latency, timeout)) 59298c2ecf20Sopenharmony_ci return send_conn_param_neg_reply(hdev, handle, 59308c2ecf20Sopenharmony_ci HCI_ERROR_INVALID_LL_PARAMS); 59318c2ecf20Sopenharmony_ci 59328c2ecf20Sopenharmony_ci if (hcon->role == HCI_ROLE_MASTER) { 59338c2ecf20Sopenharmony_ci struct hci_conn_params *params; 59348c2ecf20Sopenharmony_ci u8 store_hint; 59358c2ecf20Sopenharmony_ci 59368c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 59378c2ecf20Sopenharmony_ci 59388c2ecf20Sopenharmony_ci params = hci_conn_params_lookup(hdev, &hcon->dst, 59398c2ecf20Sopenharmony_ci hcon->dst_type); 59408c2ecf20Sopenharmony_ci if (params) { 59418c2ecf20Sopenharmony_ci params->conn_min_interval = min; 59428c2ecf20Sopenharmony_ci params->conn_max_interval = max; 59438c2ecf20Sopenharmony_ci params->conn_latency = latency; 59448c2ecf20Sopenharmony_ci params->supervision_timeout = timeout; 59458c2ecf20Sopenharmony_ci store_hint = 0x01; 59468c2ecf20Sopenharmony_ci } else{ 59478c2ecf20Sopenharmony_ci store_hint = 0x00; 59488c2ecf20Sopenharmony_ci } 59498c2ecf20Sopenharmony_ci 59508c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 59518c2ecf20Sopenharmony_ci 59528c2ecf20Sopenharmony_ci mgmt_new_conn_param(hdev, &hcon->dst, hcon->dst_type, 59538c2ecf20Sopenharmony_ci store_hint, min, max, latency, timeout); 59548c2ecf20Sopenharmony_ci } 59558c2ecf20Sopenharmony_ci 59568c2ecf20Sopenharmony_ci cp.handle = ev->handle; 59578c2ecf20Sopenharmony_ci cp.interval_min = ev->interval_min; 59588c2ecf20Sopenharmony_ci cp.interval_max = ev->interval_max; 59598c2ecf20Sopenharmony_ci cp.latency = ev->latency; 59608c2ecf20Sopenharmony_ci cp.timeout = ev->timeout; 59618c2ecf20Sopenharmony_ci cp.min_ce_len = 0; 59628c2ecf20Sopenharmony_ci cp.max_ce_len = 0; 59638c2ecf20Sopenharmony_ci 59648c2ecf20Sopenharmony_ci hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_REPLY, sizeof(cp), &cp); 59658c2ecf20Sopenharmony_ci} 59668c2ecf20Sopenharmony_ci 59678c2ecf20Sopenharmony_cistatic void hci_le_direct_adv_report_evt(struct hci_dev *hdev, 59688c2ecf20Sopenharmony_ci struct sk_buff *skb) 59698c2ecf20Sopenharmony_ci{ 59708c2ecf20Sopenharmony_ci u8 num_reports = skb->data[0]; 59718c2ecf20Sopenharmony_ci struct hci_ev_le_direct_adv_info *ev = (void *)&skb->data[1]; 59728c2ecf20Sopenharmony_ci 59738c2ecf20Sopenharmony_ci if (!num_reports || skb->len < num_reports * sizeof(*ev) + 1) 59748c2ecf20Sopenharmony_ci return; 59758c2ecf20Sopenharmony_ci 59768c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 59778c2ecf20Sopenharmony_ci 59788c2ecf20Sopenharmony_ci for (; num_reports; num_reports--, ev++) 59798c2ecf20Sopenharmony_ci process_adv_report(hdev, ev->evt_type, &ev->bdaddr, 59808c2ecf20Sopenharmony_ci ev->bdaddr_type, &ev->direct_addr, 59818c2ecf20Sopenharmony_ci ev->direct_addr_type, ev->rssi, NULL, 0, 59828c2ecf20Sopenharmony_ci false); 59838c2ecf20Sopenharmony_ci 59848c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 59858c2ecf20Sopenharmony_ci} 59868c2ecf20Sopenharmony_ci 59878c2ecf20Sopenharmony_cistatic void hci_le_phy_update_evt(struct hci_dev *hdev, struct sk_buff *skb) 59888c2ecf20Sopenharmony_ci{ 59898c2ecf20Sopenharmony_ci struct hci_ev_le_phy_update_complete *ev = (void *) skb->data; 59908c2ecf20Sopenharmony_ci struct hci_conn *conn; 59918c2ecf20Sopenharmony_ci 59928c2ecf20Sopenharmony_ci BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 59938c2ecf20Sopenharmony_ci 59948c2ecf20Sopenharmony_ci if (ev->status) 59958c2ecf20Sopenharmony_ci return; 59968c2ecf20Sopenharmony_ci 59978c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 59988c2ecf20Sopenharmony_ci 59998c2ecf20Sopenharmony_ci conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 60008c2ecf20Sopenharmony_ci if (!conn) 60018c2ecf20Sopenharmony_ci goto unlock; 60028c2ecf20Sopenharmony_ci 60038c2ecf20Sopenharmony_ci conn->le_tx_phy = ev->tx_phy; 60048c2ecf20Sopenharmony_ci conn->le_rx_phy = ev->rx_phy; 60058c2ecf20Sopenharmony_ci 60068c2ecf20Sopenharmony_ciunlock: 60078c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 60088c2ecf20Sopenharmony_ci} 60098c2ecf20Sopenharmony_ci 60108c2ecf20Sopenharmony_cistatic void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 60118c2ecf20Sopenharmony_ci{ 60128c2ecf20Sopenharmony_ci struct hci_ev_le_meta *le_ev = (void *) skb->data; 60138c2ecf20Sopenharmony_ci 60148c2ecf20Sopenharmony_ci skb_pull(skb, sizeof(*le_ev)); 60158c2ecf20Sopenharmony_ci 60168c2ecf20Sopenharmony_ci switch (le_ev->subevent) { 60178c2ecf20Sopenharmony_ci case HCI_EV_LE_CONN_COMPLETE: 60188c2ecf20Sopenharmony_ci hci_le_conn_complete_evt(hdev, skb); 60198c2ecf20Sopenharmony_ci break; 60208c2ecf20Sopenharmony_ci 60218c2ecf20Sopenharmony_ci case HCI_EV_LE_CONN_UPDATE_COMPLETE: 60228c2ecf20Sopenharmony_ci hci_le_conn_update_complete_evt(hdev, skb); 60238c2ecf20Sopenharmony_ci break; 60248c2ecf20Sopenharmony_ci 60258c2ecf20Sopenharmony_ci case HCI_EV_LE_ADVERTISING_REPORT: 60268c2ecf20Sopenharmony_ci hci_le_adv_report_evt(hdev, skb); 60278c2ecf20Sopenharmony_ci break; 60288c2ecf20Sopenharmony_ci 60298c2ecf20Sopenharmony_ci case HCI_EV_LE_REMOTE_FEAT_COMPLETE: 60308c2ecf20Sopenharmony_ci hci_le_remote_feat_complete_evt(hdev, skb); 60318c2ecf20Sopenharmony_ci break; 60328c2ecf20Sopenharmony_ci 60338c2ecf20Sopenharmony_ci case HCI_EV_LE_LTK_REQ: 60348c2ecf20Sopenharmony_ci hci_le_ltk_request_evt(hdev, skb); 60358c2ecf20Sopenharmony_ci break; 60368c2ecf20Sopenharmony_ci 60378c2ecf20Sopenharmony_ci case HCI_EV_LE_REMOTE_CONN_PARAM_REQ: 60388c2ecf20Sopenharmony_ci hci_le_remote_conn_param_req_evt(hdev, skb); 60398c2ecf20Sopenharmony_ci break; 60408c2ecf20Sopenharmony_ci 60418c2ecf20Sopenharmony_ci case HCI_EV_LE_DIRECT_ADV_REPORT: 60428c2ecf20Sopenharmony_ci hci_le_direct_adv_report_evt(hdev, skb); 60438c2ecf20Sopenharmony_ci break; 60448c2ecf20Sopenharmony_ci 60458c2ecf20Sopenharmony_ci case HCI_EV_LE_PHY_UPDATE_COMPLETE: 60468c2ecf20Sopenharmony_ci hci_le_phy_update_evt(hdev, skb); 60478c2ecf20Sopenharmony_ci break; 60488c2ecf20Sopenharmony_ci 60498c2ecf20Sopenharmony_ci case HCI_EV_LE_EXT_ADV_REPORT: 60508c2ecf20Sopenharmony_ci hci_le_ext_adv_report_evt(hdev, skb); 60518c2ecf20Sopenharmony_ci break; 60528c2ecf20Sopenharmony_ci 60538c2ecf20Sopenharmony_ci case HCI_EV_LE_ENHANCED_CONN_COMPLETE: 60548c2ecf20Sopenharmony_ci hci_le_enh_conn_complete_evt(hdev, skb); 60558c2ecf20Sopenharmony_ci break; 60568c2ecf20Sopenharmony_ci 60578c2ecf20Sopenharmony_ci case HCI_EV_LE_EXT_ADV_SET_TERM: 60588c2ecf20Sopenharmony_ci hci_le_ext_adv_term_evt(hdev, skb); 60598c2ecf20Sopenharmony_ci break; 60608c2ecf20Sopenharmony_ci 60618c2ecf20Sopenharmony_ci default: 60628c2ecf20Sopenharmony_ci break; 60638c2ecf20Sopenharmony_ci } 60648c2ecf20Sopenharmony_ci} 60658c2ecf20Sopenharmony_ci 60668c2ecf20Sopenharmony_cistatic bool hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode, 60678c2ecf20Sopenharmony_ci u8 event, struct sk_buff *skb) 60688c2ecf20Sopenharmony_ci{ 60698c2ecf20Sopenharmony_ci struct hci_ev_cmd_complete *ev; 60708c2ecf20Sopenharmony_ci struct hci_event_hdr *hdr; 60718c2ecf20Sopenharmony_ci 60728c2ecf20Sopenharmony_ci if (!skb) 60738c2ecf20Sopenharmony_ci return false; 60748c2ecf20Sopenharmony_ci 60758c2ecf20Sopenharmony_ci if (skb->len < sizeof(*hdr)) { 60768c2ecf20Sopenharmony_ci bt_dev_err(hdev, "too short HCI event"); 60778c2ecf20Sopenharmony_ci return false; 60788c2ecf20Sopenharmony_ci } 60798c2ecf20Sopenharmony_ci 60808c2ecf20Sopenharmony_ci hdr = (void *) skb->data; 60818c2ecf20Sopenharmony_ci skb_pull(skb, HCI_EVENT_HDR_SIZE); 60828c2ecf20Sopenharmony_ci 60838c2ecf20Sopenharmony_ci if (event) { 60848c2ecf20Sopenharmony_ci if (hdr->evt != event) 60858c2ecf20Sopenharmony_ci return false; 60868c2ecf20Sopenharmony_ci return true; 60878c2ecf20Sopenharmony_ci } 60888c2ecf20Sopenharmony_ci 60898c2ecf20Sopenharmony_ci /* Check if request ended in Command Status - no way to retreive 60908c2ecf20Sopenharmony_ci * any extra parameters in this case. 60918c2ecf20Sopenharmony_ci */ 60928c2ecf20Sopenharmony_ci if (hdr->evt == HCI_EV_CMD_STATUS) 60938c2ecf20Sopenharmony_ci return false; 60948c2ecf20Sopenharmony_ci 60958c2ecf20Sopenharmony_ci if (hdr->evt != HCI_EV_CMD_COMPLETE) { 60968c2ecf20Sopenharmony_ci bt_dev_err(hdev, "last event is not cmd complete (0x%2.2x)", 60978c2ecf20Sopenharmony_ci hdr->evt); 60988c2ecf20Sopenharmony_ci return false; 60998c2ecf20Sopenharmony_ci } 61008c2ecf20Sopenharmony_ci 61018c2ecf20Sopenharmony_ci if (skb->len < sizeof(*ev)) { 61028c2ecf20Sopenharmony_ci bt_dev_err(hdev, "too short cmd_complete event"); 61038c2ecf20Sopenharmony_ci return false; 61048c2ecf20Sopenharmony_ci } 61058c2ecf20Sopenharmony_ci 61068c2ecf20Sopenharmony_ci ev = (void *) skb->data; 61078c2ecf20Sopenharmony_ci skb_pull(skb, sizeof(*ev)); 61088c2ecf20Sopenharmony_ci 61098c2ecf20Sopenharmony_ci if (opcode != __le16_to_cpu(ev->opcode)) { 61108c2ecf20Sopenharmony_ci BT_DBG("opcode doesn't match (0x%2.2x != 0x%2.2x)", opcode, 61118c2ecf20Sopenharmony_ci __le16_to_cpu(ev->opcode)); 61128c2ecf20Sopenharmony_ci return false; 61138c2ecf20Sopenharmony_ci } 61148c2ecf20Sopenharmony_ci 61158c2ecf20Sopenharmony_ci return true; 61168c2ecf20Sopenharmony_ci} 61178c2ecf20Sopenharmony_ci 61188c2ecf20Sopenharmony_cistatic void hci_store_wake_reason(struct hci_dev *hdev, u8 event, 61198c2ecf20Sopenharmony_ci struct sk_buff *skb) 61208c2ecf20Sopenharmony_ci{ 61218c2ecf20Sopenharmony_ci struct hci_ev_le_advertising_info *adv; 61228c2ecf20Sopenharmony_ci struct hci_ev_le_direct_adv_info *direct_adv; 61238c2ecf20Sopenharmony_ci struct hci_ev_le_ext_adv_report *ext_adv; 61248c2ecf20Sopenharmony_ci const struct hci_ev_conn_complete *conn_complete = (void *)skb->data; 61258c2ecf20Sopenharmony_ci const struct hci_ev_conn_request *conn_request = (void *)skb->data; 61268c2ecf20Sopenharmony_ci 61278c2ecf20Sopenharmony_ci hci_dev_lock(hdev); 61288c2ecf20Sopenharmony_ci 61298c2ecf20Sopenharmony_ci /* If we are currently suspended and this is the first BT event seen, 61308c2ecf20Sopenharmony_ci * save the wake reason associated with the event. 61318c2ecf20Sopenharmony_ci */ 61328c2ecf20Sopenharmony_ci if (!hdev->suspended || hdev->wake_reason) 61338c2ecf20Sopenharmony_ci goto unlock; 61348c2ecf20Sopenharmony_ci 61358c2ecf20Sopenharmony_ci /* Default to remote wake. Values for wake_reason are documented in the 61368c2ecf20Sopenharmony_ci * Bluez mgmt api docs. 61378c2ecf20Sopenharmony_ci */ 61388c2ecf20Sopenharmony_ci hdev->wake_reason = MGMT_WAKE_REASON_REMOTE_WAKE; 61398c2ecf20Sopenharmony_ci 61408c2ecf20Sopenharmony_ci /* Once configured for remote wakeup, we should only wake up for 61418c2ecf20Sopenharmony_ci * reconnections. It's useful to see which device is waking us up so 61428c2ecf20Sopenharmony_ci * keep track of the bdaddr of the connection event that woke us up. 61438c2ecf20Sopenharmony_ci */ 61448c2ecf20Sopenharmony_ci if (event == HCI_EV_CONN_REQUEST) { 61458c2ecf20Sopenharmony_ci bacpy(&hdev->wake_addr, &conn_complete->bdaddr); 61468c2ecf20Sopenharmony_ci hdev->wake_addr_type = BDADDR_BREDR; 61478c2ecf20Sopenharmony_ci } else if (event == HCI_EV_CONN_COMPLETE) { 61488c2ecf20Sopenharmony_ci bacpy(&hdev->wake_addr, &conn_request->bdaddr); 61498c2ecf20Sopenharmony_ci hdev->wake_addr_type = BDADDR_BREDR; 61508c2ecf20Sopenharmony_ci } else if (event == HCI_EV_LE_META) { 61518c2ecf20Sopenharmony_ci struct hci_ev_le_meta *le_ev = (void *)skb->data; 61528c2ecf20Sopenharmony_ci u8 subevent = le_ev->subevent; 61538c2ecf20Sopenharmony_ci u8 *ptr = &skb->data[sizeof(*le_ev)]; 61548c2ecf20Sopenharmony_ci u8 num_reports = *ptr; 61558c2ecf20Sopenharmony_ci 61568c2ecf20Sopenharmony_ci if ((subevent == HCI_EV_LE_ADVERTISING_REPORT || 61578c2ecf20Sopenharmony_ci subevent == HCI_EV_LE_DIRECT_ADV_REPORT || 61588c2ecf20Sopenharmony_ci subevent == HCI_EV_LE_EXT_ADV_REPORT) && 61598c2ecf20Sopenharmony_ci num_reports) { 61608c2ecf20Sopenharmony_ci adv = (void *)(ptr + 1); 61618c2ecf20Sopenharmony_ci direct_adv = (void *)(ptr + 1); 61628c2ecf20Sopenharmony_ci ext_adv = (void *)(ptr + 1); 61638c2ecf20Sopenharmony_ci 61648c2ecf20Sopenharmony_ci switch (subevent) { 61658c2ecf20Sopenharmony_ci case HCI_EV_LE_ADVERTISING_REPORT: 61668c2ecf20Sopenharmony_ci bacpy(&hdev->wake_addr, &adv->bdaddr); 61678c2ecf20Sopenharmony_ci hdev->wake_addr_type = adv->bdaddr_type; 61688c2ecf20Sopenharmony_ci break; 61698c2ecf20Sopenharmony_ci case HCI_EV_LE_DIRECT_ADV_REPORT: 61708c2ecf20Sopenharmony_ci bacpy(&hdev->wake_addr, &direct_adv->bdaddr); 61718c2ecf20Sopenharmony_ci hdev->wake_addr_type = direct_adv->bdaddr_type; 61728c2ecf20Sopenharmony_ci break; 61738c2ecf20Sopenharmony_ci case HCI_EV_LE_EXT_ADV_REPORT: 61748c2ecf20Sopenharmony_ci bacpy(&hdev->wake_addr, &ext_adv->bdaddr); 61758c2ecf20Sopenharmony_ci hdev->wake_addr_type = ext_adv->bdaddr_type; 61768c2ecf20Sopenharmony_ci break; 61778c2ecf20Sopenharmony_ci } 61788c2ecf20Sopenharmony_ci } 61798c2ecf20Sopenharmony_ci } else { 61808c2ecf20Sopenharmony_ci hdev->wake_reason = MGMT_WAKE_REASON_UNEXPECTED; 61818c2ecf20Sopenharmony_ci } 61828c2ecf20Sopenharmony_ci 61838c2ecf20Sopenharmony_ciunlock: 61848c2ecf20Sopenharmony_ci hci_dev_unlock(hdev); 61858c2ecf20Sopenharmony_ci} 61868c2ecf20Sopenharmony_ci 61878c2ecf20Sopenharmony_civoid hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 61888c2ecf20Sopenharmony_ci{ 61898c2ecf20Sopenharmony_ci struct hci_event_hdr *hdr = (void *) skb->data; 61908c2ecf20Sopenharmony_ci hci_req_complete_t req_complete = NULL; 61918c2ecf20Sopenharmony_ci hci_req_complete_skb_t req_complete_skb = NULL; 61928c2ecf20Sopenharmony_ci struct sk_buff *orig_skb = NULL; 61938c2ecf20Sopenharmony_ci u8 status = 0, event = hdr->evt, req_evt = 0; 61948c2ecf20Sopenharmony_ci u16 opcode = HCI_OP_NOP; 61958c2ecf20Sopenharmony_ci 61968c2ecf20Sopenharmony_ci if (!event) { 61978c2ecf20Sopenharmony_ci bt_dev_warn(hdev, "Received unexpected HCI Event 00000000"); 61988c2ecf20Sopenharmony_ci goto done; 61998c2ecf20Sopenharmony_ci } 62008c2ecf20Sopenharmony_ci 62018c2ecf20Sopenharmony_ci if (hdev->sent_cmd && bt_cb(hdev->sent_cmd)->hci.req_event == event) { 62028c2ecf20Sopenharmony_ci struct hci_command_hdr *cmd_hdr = (void *) hdev->sent_cmd->data; 62038c2ecf20Sopenharmony_ci opcode = __le16_to_cpu(cmd_hdr->opcode); 62048c2ecf20Sopenharmony_ci hci_req_cmd_complete(hdev, opcode, status, &req_complete, 62058c2ecf20Sopenharmony_ci &req_complete_skb); 62068c2ecf20Sopenharmony_ci req_evt = event; 62078c2ecf20Sopenharmony_ci } 62088c2ecf20Sopenharmony_ci 62098c2ecf20Sopenharmony_ci /* If it looks like we might end up having to call 62108c2ecf20Sopenharmony_ci * req_complete_skb, store a pristine copy of the skb since the 62118c2ecf20Sopenharmony_ci * various handlers may modify the original one through 62128c2ecf20Sopenharmony_ci * skb_pull() calls, etc. 62138c2ecf20Sopenharmony_ci */ 62148c2ecf20Sopenharmony_ci if (req_complete_skb || event == HCI_EV_CMD_STATUS || 62158c2ecf20Sopenharmony_ci event == HCI_EV_CMD_COMPLETE) 62168c2ecf20Sopenharmony_ci orig_skb = skb_clone(skb, GFP_KERNEL); 62178c2ecf20Sopenharmony_ci 62188c2ecf20Sopenharmony_ci skb_pull(skb, HCI_EVENT_HDR_SIZE); 62198c2ecf20Sopenharmony_ci 62208c2ecf20Sopenharmony_ci /* Store wake reason if we're suspended */ 62218c2ecf20Sopenharmony_ci hci_store_wake_reason(hdev, event, skb); 62228c2ecf20Sopenharmony_ci 62238c2ecf20Sopenharmony_ci switch (event) { 62248c2ecf20Sopenharmony_ci case HCI_EV_INQUIRY_COMPLETE: 62258c2ecf20Sopenharmony_ci hci_inquiry_complete_evt(hdev, skb); 62268c2ecf20Sopenharmony_ci break; 62278c2ecf20Sopenharmony_ci 62288c2ecf20Sopenharmony_ci case HCI_EV_INQUIRY_RESULT: 62298c2ecf20Sopenharmony_ci hci_inquiry_result_evt(hdev, skb); 62308c2ecf20Sopenharmony_ci break; 62318c2ecf20Sopenharmony_ci 62328c2ecf20Sopenharmony_ci case HCI_EV_CONN_COMPLETE: 62338c2ecf20Sopenharmony_ci hci_conn_complete_evt(hdev, skb); 62348c2ecf20Sopenharmony_ci break; 62358c2ecf20Sopenharmony_ci 62368c2ecf20Sopenharmony_ci case HCI_EV_CONN_REQUEST: 62378c2ecf20Sopenharmony_ci hci_conn_request_evt(hdev, skb); 62388c2ecf20Sopenharmony_ci break; 62398c2ecf20Sopenharmony_ci 62408c2ecf20Sopenharmony_ci case HCI_EV_DISCONN_COMPLETE: 62418c2ecf20Sopenharmony_ci hci_disconn_complete_evt(hdev, skb); 62428c2ecf20Sopenharmony_ci break; 62438c2ecf20Sopenharmony_ci 62448c2ecf20Sopenharmony_ci case HCI_EV_AUTH_COMPLETE: 62458c2ecf20Sopenharmony_ci hci_auth_complete_evt(hdev, skb); 62468c2ecf20Sopenharmony_ci break; 62478c2ecf20Sopenharmony_ci 62488c2ecf20Sopenharmony_ci case HCI_EV_REMOTE_NAME: 62498c2ecf20Sopenharmony_ci hci_remote_name_evt(hdev, skb); 62508c2ecf20Sopenharmony_ci break; 62518c2ecf20Sopenharmony_ci 62528c2ecf20Sopenharmony_ci case HCI_EV_ENCRYPT_CHANGE: 62538c2ecf20Sopenharmony_ci hci_encrypt_change_evt(hdev, skb); 62548c2ecf20Sopenharmony_ci break; 62558c2ecf20Sopenharmony_ci 62568c2ecf20Sopenharmony_ci case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 62578c2ecf20Sopenharmony_ci hci_change_link_key_complete_evt(hdev, skb); 62588c2ecf20Sopenharmony_ci break; 62598c2ecf20Sopenharmony_ci 62608c2ecf20Sopenharmony_ci case HCI_EV_REMOTE_FEATURES: 62618c2ecf20Sopenharmony_ci hci_remote_features_evt(hdev, skb); 62628c2ecf20Sopenharmony_ci break; 62638c2ecf20Sopenharmony_ci 62648c2ecf20Sopenharmony_ci case HCI_EV_CMD_COMPLETE: 62658c2ecf20Sopenharmony_ci hci_cmd_complete_evt(hdev, skb, &opcode, &status, 62668c2ecf20Sopenharmony_ci &req_complete, &req_complete_skb); 62678c2ecf20Sopenharmony_ci break; 62688c2ecf20Sopenharmony_ci 62698c2ecf20Sopenharmony_ci case HCI_EV_CMD_STATUS: 62708c2ecf20Sopenharmony_ci hci_cmd_status_evt(hdev, skb, &opcode, &status, &req_complete, 62718c2ecf20Sopenharmony_ci &req_complete_skb); 62728c2ecf20Sopenharmony_ci break; 62738c2ecf20Sopenharmony_ci 62748c2ecf20Sopenharmony_ci case HCI_EV_HARDWARE_ERROR: 62758c2ecf20Sopenharmony_ci hci_hardware_error_evt(hdev, skb); 62768c2ecf20Sopenharmony_ci break; 62778c2ecf20Sopenharmony_ci 62788c2ecf20Sopenharmony_ci case HCI_EV_ROLE_CHANGE: 62798c2ecf20Sopenharmony_ci hci_role_change_evt(hdev, skb); 62808c2ecf20Sopenharmony_ci break; 62818c2ecf20Sopenharmony_ci 62828c2ecf20Sopenharmony_ci case HCI_EV_NUM_COMP_PKTS: 62838c2ecf20Sopenharmony_ci hci_num_comp_pkts_evt(hdev, skb); 62848c2ecf20Sopenharmony_ci break; 62858c2ecf20Sopenharmony_ci 62868c2ecf20Sopenharmony_ci case HCI_EV_MODE_CHANGE: 62878c2ecf20Sopenharmony_ci hci_mode_change_evt(hdev, skb); 62888c2ecf20Sopenharmony_ci break; 62898c2ecf20Sopenharmony_ci 62908c2ecf20Sopenharmony_ci case HCI_EV_PIN_CODE_REQ: 62918c2ecf20Sopenharmony_ci hci_pin_code_request_evt(hdev, skb); 62928c2ecf20Sopenharmony_ci break; 62938c2ecf20Sopenharmony_ci 62948c2ecf20Sopenharmony_ci case HCI_EV_LINK_KEY_REQ: 62958c2ecf20Sopenharmony_ci hci_link_key_request_evt(hdev, skb); 62968c2ecf20Sopenharmony_ci break; 62978c2ecf20Sopenharmony_ci 62988c2ecf20Sopenharmony_ci case HCI_EV_LINK_KEY_NOTIFY: 62998c2ecf20Sopenharmony_ci hci_link_key_notify_evt(hdev, skb); 63008c2ecf20Sopenharmony_ci break; 63018c2ecf20Sopenharmony_ci 63028c2ecf20Sopenharmony_ci case HCI_EV_CLOCK_OFFSET: 63038c2ecf20Sopenharmony_ci hci_clock_offset_evt(hdev, skb); 63048c2ecf20Sopenharmony_ci break; 63058c2ecf20Sopenharmony_ci 63068c2ecf20Sopenharmony_ci case HCI_EV_PKT_TYPE_CHANGE: 63078c2ecf20Sopenharmony_ci hci_pkt_type_change_evt(hdev, skb); 63088c2ecf20Sopenharmony_ci break; 63098c2ecf20Sopenharmony_ci 63108c2ecf20Sopenharmony_ci case HCI_EV_PSCAN_REP_MODE: 63118c2ecf20Sopenharmony_ci hci_pscan_rep_mode_evt(hdev, skb); 63128c2ecf20Sopenharmony_ci break; 63138c2ecf20Sopenharmony_ci 63148c2ecf20Sopenharmony_ci case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 63158c2ecf20Sopenharmony_ci hci_inquiry_result_with_rssi_evt(hdev, skb); 63168c2ecf20Sopenharmony_ci break; 63178c2ecf20Sopenharmony_ci 63188c2ecf20Sopenharmony_ci case HCI_EV_REMOTE_EXT_FEATURES: 63198c2ecf20Sopenharmony_ci hci_remote_ext_features_evt(hdev, skb); 63208c2ecf20Sopenharmony_ci break; 63218c2ecf20Sopenharmony_ci 63228c2ecf20Sopenharmony_ci case HCI_EV_SYNC_CONN_COMPLETE: 63238c2ecf20Sopenharmony_ci hci_sync_conn_complete_evt(hdev, skb); 63248c2ecf20Sopenharmony_ci break; 63258c2ecf20Sopenharmony_ci 63268c2ecf20Sopenharmony_ci case HCI_EV_EXTENDED_INQUIRY_RESULT: 63278c2ecf20Sopenharmony_ci hci_extended_inquiry_result_evt(hdev, skb); 63288c2ecf20Sopenharmony_ci break; 63298c2ecf20Sopenharmony_ci 63308c2ecf20Sopenharmony_ci case HCI_EV_KEY_REFRESH_COMPLETE: 63318c2ecf20Sopenharmony_ci hci_key_refresh_complete_evt(hdev, skb); 63328c2ecf20Sopenharmony_ci break; 63338c2ecf20Sopenharmony_ci 63348c2ecf20Sopenharmony_ci case HCI_EV_IO_CAPA_REQUEST: 63358c2ecf20Sopenharmony_ci hci_io_capa_request_evt(hdev, skb); 63368c2ecf20Sopenharmony_ci break; 63378c2ecf20Sopenharmony_ci 63388c2ecf20Sopenharmony_ci case HCI_EV_IO_CAPA_REPLY: 63398c2ecf20Sopenharmony_ci hci_io_capa_reply_evt(hdev, skb); 63408c2ecf20Sopenharmony_ci break; 63418c2ecf20Sopenharmony_ci 63428c2ecf20Sopenharmony_ci case HCI_EV_USER_CONFIRM_REQUEST: 63438c2ecf20Sopenharmony_ci hci_user_confirm_request_evt(hdev, skb); 63448c2ecf20Sopenharmony_ci break; 63458c2ecf20Sopenharmony_ci 63468c2ecf20Sopenharmony_ci case HCI_EV_USER_PASSKEY_REQUEST: 63478c2ecf20Sopenharmony_ci hci_user_passkey_request_evt(hdev, skb); 63488c2ecf20Sopenharmony_ci break; 63498c2ecf20Sopenharmony_ci 63508c2ecf20Sopenharmony_ci case HCI_EV_USER_PASSKEY_NOTIFY: 63518c2ecf20Sopenharmony_ci hci_user_passkey_notify_evt(hdev, skb); 63528c2ecf20Sopenharmony_ci break; 63538c2ecf20Sopenharmony_ci 63548c2ecf20Sopenharmony_ci case HCI_EV_KEYPRESS_NOTIFY: 63558c2ecf20Sopenharmony_ci hci_keypress_notify_evt(hdev, skb); 63568c2ecf20Sopenharmony_ci break; 63578c2ecf20Sopenharmony_ci 63588c2ecf20Sopenharmony_ci case HCI_EV_SIMPLE_PAIR_COMPLETE: 63598c2ecf20Sopenharmony_ci hci_simple_pair_complete_evt(hdev, skb); 63608c2ecf20Sopenharmony_ci break; 63618c2ecf20Sopenharmony_ci 63628c2ecf20Sopenharmony_ci case HCI_EV_REMOTE_HOST_FEATURES: 63638c2ecf20Sopenharmony_ci hci_remote_host_features_evt(hdev, skb); 63648c2ecf20Sopenharmony_ci break; 63658c2ecf20Sopenharmony_ci 63668c2ecf20Sopenharmony_ci case HCI_EV_LE_META: 63678c2ecf20Sopenharmony_ci hci_le_meta_evt(hdev, skb); 63688c2ecf20Sopenharmony_ci break; 63698c2ecf20Sopenharmony_ci 63708c2ecf20Sopenharmony_ci case HCI_EV_REMOTE_OOB_DATA_REQUEST: 63718c2ecf20Sopenharmony_ci hci_remote_oob_data_request_evt(hdev, skb); 63728c2ecf20Sopenharmony_ci break; 63738c2ecf20Sopenharmony_ci 63748c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_BT_HS) 63758c2ecf20Sopenharmony_ci case HCI_EV_CHANNEL_SELECTED: 63768c2ecf20Sopenharmony_ci hci_chan_selected_evt(hdev, skb); 63778c2ecf20Sopenharmony_ci break; 63788c2ecf20Sopenharmony_ci 63798c2ecf20Sopenharmony_ci case HCI_EV_PHY_LINK_COMPLETE: 63808c2ecf20Sopenharmony_ci hci_phy_link_complete_evt(hdev, skb); 63818c2ecf20Sopenharmony_ci break; 63828c2ecf20Sopenharmony_ci 63838c2ecf20Sopenharmony_ci case HCI_EV_LOGICAL_LINK_COMPLETE: 63848c2ecf20Sopenharmony_ci hci_loglink_complete_evt(hdev, skb); 63858c2ecf20Sopenharmony_ci break; 63868c2ecf20Sopenharmony_ci 63878c2ecf20Sopenharmony_ci case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE: 63888c2ecf20Sopenharmony_ci hci_disconn_loglink_complete_evt(hdev, skb); 63898c2ecf20Sopenharmony_ci break; 63908c2ecf20Sopenharmony_ci 63918c2ecf20Sopenharmony_ci case HCI_EV_DISCONN_PHY_LINK_COMPLETE: 63928c2ecf20Sopenharmony_ci hci_disconn_phylink_complete_evt(hdev, skb); 63938c2ecf20Sopenharmony_ci break; 63948c2ecf20Sopenharmony_ci#endif 63958c2ecf20Sopenharmony_ci 63968c2ecf20Sopenharmony_ci case HCI_EV_NUM_COMP_BLOCKS: 63978c2ecf20Sopenharmony_ci hci_num_comp_blocks_evt(hdev, skb); 63988c2ecf20Sopenharmony_ci break; 63998c2ecf20Sopenharmony_ci 64008c2ecf20Sopenharmony_ci case HCI_EV_VENDOR: 64018c2ecf20Sopenharmony_ci msft_vendor_evt(hdev, skb); 64028c2ecf20Sopenharmony_ci break; 64038c2ecf20Sopenharmony_ci 64048c2ecf20Sopenharmony_ci default: 64058c2ecf20Sopenharmony_ci BT_DBG("%s event 0x%2.2x", hdev->name, event); 64068c2ecf20Sopenharmony_ci break; 64078c2ecf20Sopenharmony_ci } 64088c2ecf20Sopenharmony_ci 64098c2ecf20Sopenharmony_ci if (req_complete) { 64108c2ecf20Sopenharmony_ci req_complete(hdev, status, opcode); 64118c2ecf20Sopenharmony_ci } else if (req_complete_skb) { 64128c2ecf20Sopenharmony_ci if (!hci_get_cmd_complete(hdev, opcode, req_evt, orig_skb)) { 64138c2ecf20Sopenharmony_ci kfree_skb(orig_skb); 64148c2ecf20Sopenharmony_ci orig_skb = NULL; 64158c2ecf20Sopenharmony_ci } 64168c2ecf20Sopenharmony_ci req_complete_skb(hdev, status, opcode, orig_skb); 64178c2ecf20Sopenharmony_ci } 64188c2ecf20Sopenharmony_ci 64198c2ecf20Sopenharmony_cidone: 64208c2ecf20Sopenharmony_ci kfree_skb(orig_skb); 64218c2ecf20Sopenharmony_ci kfree_skb(skb); 64228c2ecf20Sopenharmony_ci hdev->stat.evt_rx++; 64238c2ecf20Sopenharmony_ci} 6424