11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds BlueZ - Bluetooth protocol stack for Linux 32d0a0346SRon Shaffer Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved. 41da177e4SLinus Torvalds 51da177e4SLinus Torvalds Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> 61da177e4SLinus Torvalds 71da177e4SLinus Torvalds This program is free software; you can redistribute it and/or modify 81da177e4SLinus Torvalds it under the terms of the GNU General Public License version 2 as 91da177e4SLinus Torvalds published by the Free Software Foundation; 101da177e4SLinus Torvalds 111da177e4SLinus Torvalds THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 121da177e4SLinus Torvalds OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 131da177e4SLinus Torvalds FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 141da177e4SLinus Torvalds IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 151da177e4SLinus Torvalds CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 161da177e4SLinus Torvalds WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 171da177e4SLinus Torvalds ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 181da177e4SLinus Torvalds OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 211da177e4SLinus Torvalds COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 221da177e4SLinus Torvalds SOFTWARE IS DISCLAIMED. 231da177e4SLinus Torvalds */ 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds /* Bluetooth HCI event handling. */ 261da177e4SLinus Torvalds 271da177e4SLinus Torvalds #include <asm/unaligned.h> 281da177e4SLinus Torvalds 291da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h> 301da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h> 31f0d6a0eaSMikel Astiz #include <net/bluetooth/mgmt.h> 327ef9fbf0SMarcel Holtmann 330857dd3bSJohan Hedberg #include "hci_request.h" 3423b9ceb7SMarcel Holtmann #include "hci_debugfs.h" 357024728eSMarcel Holtmann #include "a2mp.h" 367ef9fbf0SMarcel Holtmann #include "amp.h" 372ceba539SJohan Hedberg #include "smp.h" 38145373cbSMiao-chen Chou #include "msft.h" 391da177e4SLinus Torvalds 40aa5b0345SMarcel Holtmann #define ZERO_KEY "\x00\x00\x00\x00\x00\x00\x00\x00" \ 41aa5b0345SMarcel Holtmann "\x00\x00\x00\x00\x00\x00\x00\x00" 42aa5b0345SMarcel Holtmann 431da177e4SLinus Torvalds /* Handle HCI Event packets */ 441da177e4SLinus Torvalds 45adf1d692SSonny Sasaka static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb, 46adf1d692SSonny Sasaka u8 *new_status) 471da177e4SLinus Torvalds { 48a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 491da177e4SLinus Torvalds 509f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 511da177e4SLinus Torvalds 52adf1d692SSonny Sasaka /* It is possible that we receive Inquiry Complete event right 53adf1d692SSonny Sasaka * before we receive Inquiry Cancel Command Complete event, in 54adf1d692SSonny Sasaka * which case the latter event should have status of Command 55adf1d692SSonny Sasaka * Disallowed (0x0c). This should not be treated as error, since 56adf1d692SSonny Sasaka * we actually achieve what Inquiry Cancel wants to achieve, 57adf1d692SSonny Sasaka * which is to end the last Inquiry session. 58adf1d692SSonny Sasaka */ 59adf1d692SSonny Sasaka if (status == 0x0c && !test_bit(HCI_INQUIRY, &hdev->flags)) { 60adf1d692SSonny Sasaka bt_dev_warn(hdev, "Ignoring error of Inquiry Cancel command"); 61adf1d692SSonny Sasaka status = 0x00; 62adf1d692SSonny Sasaka } 63adf1d692SSonny Sasaka 64adf1d692SSonny Sasaka *new_status = status; 65adf1d692SSonny Sasaka 6682f4785cSAndre Guedes if (status) 67a9de9248SMarcel Holtmann return; 681da177e4SLinus Torvalds 6989352e7dSAndre Guedes clear_bit(HCI_INQUIRY, &hdev->flags); 704e857c58SPeter Zijlstra smp_mb__after_atomic(); /* wake_up_bit advises about this barrier */ 713e13fa1eSAndre Guedes wake_up_bit(&hdev->flags, HCI_INQUIRY); 7289352e7dSAndre Guedes 7350143a43SJohan Hedberg hci_dev_lock(hdev); 74168b8a25SJakub Pawlowski /* Set discovery state to stopped if we're not doing LE active 75168b8a25SJakub Pawlowski * scanning. 76168b8a25SJakub Pawlowski */ 77168b8a25SJakub Pawlowski if (!hci_dev_test_flag(hdev, HCI_LE_SCAN) || 78168b8a25SJakub Pawlowski hdev->le_scan_type != LE_SCAN_ACTIVE) 7950143a43SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 8050143a43SJohan Hedberg hci_dev_unlock(hdev); 8150143a43SJohan Hedberg 82a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 831da177e4SLinus Torvalds } 846bd57416SMarcel Holtmann 854d93483bSAndre Guedes static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 864d93483bSAndre Guedes { 874d93483bSAndre Guedes __u8 status = *((__u8 *) skb->data); 884d93483bSAndre Guedes 899f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 90ae854a70SAndre Guedes 91ae854a70SAndre Guedes if (status) 92ae854a70SAndre Guedes return; 93ae854a70SAndre Guedes 94a1536da2SMarcel Holtmann hci_dev_set_flag(hdev, HCI_PERIODIC_INQ); 954d93483bSAndre Guedes } 964d93483bSAndre Guedes 97a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 981da177e4SLinus Torvalds { 99a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 100a9de9248SMarcel Holtmann 1019f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 102a9de9248SMarcel Holtmann 103a9de9248SMarcel Holtmann if (status) 104a9de9248SMarcel Holtmann return; 105a9de9248SMarcel Holtmann 106a358dc11SMarcel Holtmann hci_dev_clear_flag(hdev, HCI_PERIODIC_INQ); 107ae854a70SAndre Guedes 108a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 109a9de9248SMarcel Holtmann } 110a9de9248SMarcel Holtmann 111807deac2SGustavo Padovan static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, 112807deac2SGustavo Padovan struct sk_buff *skb) 113a9de9248SMarcel Holtmann { 114a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 115a9de9248SMarcel Holtmann } 116a9de9248SMarcel Holtmann 117a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb) 118a9de9248SMarcel Holtmann { 119a9de9248SMarcel Holtmann struct hci_rp_role_discovery *rp = (void *) skb->data; 1201da177e4SLinus Torvalds struct hci_conn *conn; 1211da177e4SLinus Torvalds 1229f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1231da177e4SLinus Torvalds 124a9de9248SMarcel Holtmann if (rp->status) 125a9de9248SMarcel Holtmann return; 1261da177e4SLinus Torvalds 1271da177e4SLinus Torvalds hci_dev_lock(hdev); 1281da177e4SLinus Torvalds 129a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 13040bef302SJohan Hedberg if (conn) 13140bef302SJohan Hedberg conn->role = rp->role; 1321da177e4SLinus Torvalds 1331da177e4SLinus Torvalds hci_dev_unlock(hdev); 134a9de9248SMarcel Holtmann } 1351da177e4SLinus Torvalds 136e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 137e4e8e37cSMarcel Holtmann { 138e4e8e37cSMarcel Holtmann struct hci_rp_read_link_policy *rp = (void *) skb->data; 139e4e8e37cSMarcel Holtmann struct hci_conn *conn; 140e4e8e37cSMarcel Holtmann 1419f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 142e4e8e37cSMarcel Holtmann 143e4e8e37cSMarcel Holtmann if (rp->status) 144e4e8e37cSMarcel Holtmann return; 145e4e8e37cSMarcel Holtmann 146e4e8e37cSMarcel Holtmann hci_dev_lock(hdev); 147e4e8e37cSMarcel Holtmann 148e4e8e37cSMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 149e4e8e37cSMarcel Holtmann if (conn) 150e4e8e37cSMarcel Holtmann conn->link_policy = __le16_to_cpu(rp->policy); 151e4e8e37cSMarcel Holtmann 152e4e8e37cSMarcel Holtmann hci_dev_unlock(hdev); 153e4e8e37cSMarcel Holtmann } 154e4e8e37cSMarcel Holtmann 155a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 156a9de9248SMarcel Holtmann { 157a9de9248SMarcel Holtmann struct hci_rp_write_link_policy *rp = (void *) skb->data; 158a9de9248SMarcel Holtmann struct hci_conn *conn; 159a9de9248SMarcel Holtmann void *sent; 160a9de9248SMarcel Holtmann 1619f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 162a9de9248SMarcel Holtmann 163a9de9248SMarcel Holtmann if (rp->status) 164a9de9248SMarcel Holtmann return; 165a9de9248SMarcel Holtmann 166a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY); 16704837f64SMarcel Holtmann if (!sent) 168a9de9248SMarcel Holtmann return; 16904837f64SMarcel Holtmann 17004837f64SMarcel Holtmann hci_dev_lock(hdev); 17104837f64SMarcel Holtmann 172a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 173e4e8e37cSMarcel Holtmann if (conn) 17483985319SHarvey Harrison conn->link_policy = get_unaligned_le16(sent + 2); 17504837f64SMarcel Holtmann 17604837f64SMarcel Holtmann hci_dev_unlock(hdev); 1771da177e4SLinus Torvalds } 1781da177e4SLinus Torvalds 179807deac2SGustavo Padovan static void hci_cc_read_def_link_policy(struct hci_dev *hdev, 180807deac2SGustavo Padovan struct sk_buff *skb) 181e4e8e37cSMarcel Holtmann { 182e4e8e37cSMarcel Holtmann struct hci_rp_read_def_link_policy *rp = (void *) skb->data; 183e4e8e37cSMarcel Holtmann 1849f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 185e4e8e37cSMarcel Holtmann 186e4e8e37cSMarcel Holtmann if (rp->status) 187e4e8e37cSMarcel Holtmann return; 188e4e8e37cSMarcel Holtmann 189e4e8e37cSMarcel Holtmann hdev->link_policy = __le16_to_cpu(rp->policy); 190e4e8e37cSMarcel Holtmann } 191e4e8e37cSMarcel Holtmann 192807deac2SGustavo Padovan static void hci_cc_write_def_link_policy(struct hci_dev *hdev, 193807deac2SGustavo Padovan struct sk_buff *skb) 194e4e8e37cSMarcel Holtmann { 195e4e8e37cSMarcel Holtmann __u8 status = *((__u8 *) skb->data); 196e4e8e37cSMarcel Holtmann void *sent; 197e4e8e37cSMarcel Holtmann 1989f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 199e4e8e37cSMarcel Holtmann 20045296acdSMarcel Holtmann if (status) 20145296acdSMarcel Holtmann return; 20245296acdSMarcel Holtmann 203e4e8e37cSMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY); 204e4e8e37cSMarcel Holtmann if (!sent) 205e4e8e37cSMarcel Holtmann return; 206e4e8e37cSMarcel Holtmann 207e4e8e37cSMarcel Holtmann hdev->link_policy = get_unaligned_le16(sent); 208e4e8e37cSMarcel Holtmann } 209e4e8e37cSMarcel Holtmann 210a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) 2111da177e4SLinus Torvalds { 212a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 213a9de9248SMarcel Holtmann 2149f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 215a9de9248SMarcel Holtmann 21610572132SGustavo F. Padovan clear_bit(HCI_RESET, &hdev->flags); 21710572132SGustavo F. Padovan 2188761f9d6SMarcel Holtmann if (status) 2198761f9d6SMarcel Holtmann return; 2208761f9d6SMarcel Holtmann 221a297e97cSJohan Hedberg /* Reset all non-persistent flags */ 222eacb44dfSMarcel Holtmann hci_dev_clear_volatile_flags(hdev); 22369775ff6SAndre Guedes 22439c5d970SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 22539c5d970SJohan Hedberg 226bbaf444aSJohan Hedberg hdev->inq_tx_power = HCI_TX_POWER_INVALID; 227bbaf444aSJohan Hedberg hdev->adv_tx_power = HCI_TX_POWER_INVALID; 2283f0f524bSJohan Hedberg 2293f0f524bSJohan Hedberg memset(hdev->adv_data, 0, sizeof(hdev->adv_data)); 2303f0f524bSJohan Hedberg hdev->adv_data_len = 0; 231f8e808bdSMarcel Holtmann 232f8e808bdSMarcel Holtmann memset(hdev->scan_rsp_data, 0, sizeof(hdev->scan_rsp_data)); 233f8e808bdSMarcel Holtmann hdev->scan_rsp_data_len = 0; 23406f5b778SMarcel Holtmann 235533553f8SMarcel Holtmann hdev->le_scan_type = LE_SCAN_PASSIVE; 236533553f8SMarcel Holtmann 23706f5b778SMarcel Holtmann hdev->ssp_debug_mode = 0; 238a4d5504dSMarcel Holtmann 239a4d5504dSMarcel Holtmann hci_bdaddr_list_clear(&hdev->le_white_list); 240cfdb0c2dSAnkit Navik hci_bdaddr_list_clear(&hdev->le_resolv_list); 241a9de9248SMarcel Holtmann } 242a9de9248SMarcel Holtmann 243c2f0f979SMarcel Holtmann static void hci_cc_read_stored_link_key(struct hci_dev *hdev, 244c2f0f979SMarcel Holtmann struct sk_buff *skb) 245c2f0f979SMarcel Holtmann { 246c2f0f979SMarcel Holtmann struct hci_rp_read_stored_link_key *rp = (void *)skb->data; 247c2f0f979SMarcel Holtmann struct hci_cp_read_stored_link_key *sent; 248c2f0f979SMarcel Holtmann 249c2f0f979SMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 250c2f0f979SMarcel Holtmann 251c2f0f979SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_READ_STORED_LINK_KEY); 252c2f0f979SMarcel Holtmann if (!sent) 253c2f0f979SMarcel Holtmann return; 254c2f0f979SMarcel Holtmann 255c2f0f979SMarcel Holtmann if (!rp->status && sent->read_all == 0x01) { 256c2f0f979SMarcel Holtmann hdev->stored_max_keys = rp->max_keys; 257c2f0f979SMarcel Holtmann hdev->stored_num_keys = rp->num_keys; 258c2f0f979SMarcel Holtmann } 259c2f0f979SMarcel Holtmann } 260c2f0f979SMarcel Holtmann 261a9366120SMarcel Holtmann static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, 262a9366120SMarcel Holtmann struct sk_buff *skb) 263a9366120SMarcel Holtmann { 264a9366120SMarcel Holtmann struct hci_rp_delete_stored_link_key *rp = (void *)skb->data; 265a9366120SMarcel Holtmann 266a9366120SMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 267a9366120SMarcel Holtmann 268a9366120SMarcel Holtmann if (rp->status) 269a9366120SMarcel Holtmann return; 270a9366120SMarcel Holtmann 271a9366120SMarcel Holtmann if (rp->num_keys <= hdev->stored_num_keys) 272a9366120SMarcel Holtmann hdev->stored_num_keys -= rp->num_keys; 273a9366120SMarcel Holtmann else 274a9366120SMarcel Holtmann hdev->stored_num_keys = 0; 275a9366120SMarcel Holtmann } 276a9366120SMarcel Holtmann 277a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) 278a9de9248SMarcel Holtmann { 279a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 2801da177e4SLinus Torvalds void *sent; 2811da177e4SLinus Torvalds 2829f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 2831da177e4SLinus Torvalds 284a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); 2851da177e4SLinus Torvalds if (!sent) 286a9de9248SMarcel Holtmann return; 2871da177e4SLinus Torvalds 28856e5cb86SJohan Hedberg hci_dev_lock(hdev); 28956e5cb86SJohan Hedberg 290d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_MGMT)) 291f51d5b24SJohan Hedberg mgmt_set_local_name_complete(hdev, sent, status); 29228cc7bdeSJohan Hedberg else if (!status) 29328cc7bdeSJohan Hedberg memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); 294f51d5b24SJohan Hedberg 29556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 296a9de9248SMarcel Holtmann } 297a9de9248SMarcel Holtmann 298a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) 299a9de9248SMarcel Holtmann { 300a9de9248SMarcel Holtmann struct hci_rp_read_local_name *rp = (void *) skb->data; 301a9de9248SMarcel Holtmann 3029f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 303a9de9248SMarcel Holtmann 304a9de9248SMarcel Holtmann if (rp->status) 305a9de9248SMarcel Holtmann return; 306a9de9248SMarcel Holtmann 307d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_SETUP) || 308d7a5a11dSMarcel Holtmann hci_dev_test_flag(hdev, HCI_CONFIG)) 3091f6c6378SJohan Hedberg memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); 310a9de9248SMarcel Holtmann } 311a9de9248SMarcel Holtmann 312a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) 313a9de9248SMarcel Holtmann { 314a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 315a9de9248SMarcel Holtmann void *sent; 316a9de9248SMarcel Holtmann 3179f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 318a9de9248SMarcel Holtmann 319a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); 320a9de9248SMarcel Holtmann if (!sent) 321a9de9248SMarcel Holtmann return; 3221da177e4SLinus Torvalds 3235c1a4c8fSJaganath Kanakkassery hci_dev_lock(hdev); 3245c1a4c8fSJaganath Kanakkassery 3251da177e4SLinus Torvalds if (!status) { 326a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 327a9de9248SMarcel Holtmann 3281da177e4SLinus Torvalds if (param == AUTH_ENABLED) 3291da177e4SLinus Torvalds set_bit(HCI_AUTH, &hdev->flags); 3301da177e4SLinus Torvalds else 3311da177e4SLinus Torvalds clear_bit(HCI_AUTH, &hdev->flags); 3321da177e4SLinus Torvalds } 333a9de9248SMarcel Holtmann 334d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_MGMT)) 33533ef95edSJohan Hedberg mgmt_auth_enable_complete(hdev, status); 3365c1a4c8fSJaganath Kanakkassery 3375c1a4c8fSJaganath Kanakkassery hci_dev_unlock(hdev); 338a9de9248SMarcel Holtmann } 3391da177e4SLinus Torvalds 340a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) 341a9de9248SMarcel Holtmann { 342a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 34345296acdSMarcel Holtmann __u8 param; 344a9de9248SMarcel Holtmann void *sent; 345a9de9248SMarcel Holtmann 3469f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 347a9de9248SMarcel Holtmann 34845296acdSMarcel Holtmann if (status) 34945296acdSMarcel Holtmann return; 35045296acdSMarcel Holtmann 351a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); 3521da177e4SLinus Torvalds if (!sent) 353a9de9248SMarcel Holtmann return; 3541da177e4SLinus Torvalds 35545296acdSMarcel Holtmann param = *((__u8 *) sent); 356a9de9248SMarcel Holtmann 3571da177e4SLinus Torvalds if (param) 3581da177e4SLinus Torvalds set_bit(HCI_ENCRYPT, &hdev->flags); 3591da177e4SLinus Torvalds else 3601da177e4SLinus Torvalds clear_bit(HCI_ENCRYPT, &hdev->flags); 3611da177e4SLinus Torvalds } 3621da177e4SLinus Torvalds 363a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) 364a9de9248SMarcel Holtmann { 36545296acdSMarcel Holtmann __u8 status = *((__u8 *) skb->data); 36645296acdSMarcel Holtmann __u8 param; 367a9de9248SMarcel Holtmann void *sent; 3681da177e4SLinus Torvalds 3699f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 370a9de9248SMarcel Holtmann 371a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); 3721da177e4SLinus Torvalds if (!sent) 373a9de9248SMarcel Holtmann return; 3741da177e4SLinus Torvalds 37536f7fc7eSJohan Hedberg param = *((__u8 *) sent); 376a9de9248SMarcel Holtmann 37756e5cb86SJohan Hedberg hci_dev_lock(hdev); 37856e5cb86SJohan Hedberg 379fa1bd918SMikel Astiz if (status) { 3802d7cee58SJohan Hedberg hdev->discov_timeout = 0; 3812d7cee58SJohan Hedberg goto done; 3822d7cee58SJohan Hedberg } 3832d7cee58SJohan Hedberg 384bc6d2d04SJohan Hedberg if (param & SCAN_INQUIRY) 3851da177e4SLinus Torvalds set_bit(HCI_ISCAN, &hdev->flags); 386bc6d2d04SJohan Hedberg else 387bc6d2d04SJohan Hedberg clear_bit(HCI_ISCAN, &hdev->flags); 3881da177e4SLinus Torvalds 389031547d8SJohan Hedberg if (param & SCAN_PAGE) 3901da177e4SLinus Torvalds set_bit(HCI_PSCAN, &hdev->flags); 391bc6d2d04SJohan Hedberg else 392204e3990SJohan Hedberg clear_bit(HCI_PSCAN, &hdev->flags); 393a9de9248SMarcel Holtmann 39436f7fc7eSJohan Hedberg done: 39556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 3961da177e4SLinus Torvalds } 3971da177e4SLinus Torvalds 398a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 399a9de9248SMarcel Holtmann { 400a9de9248SMarcel Holtmann struct hci_rp_read_class_of_dev *rp = (void *) skb->data; 401a9de9248SMarcel Holtmann 4029f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 403a9de9248SMarcel Holtmann 404a9de9248SMarcel Holtmann if (rp->status) 405a9de9248SMarcel Holtmann return; 406a9de9248SMarcel Holtmann 407a9de9248SMarcel Holtmann memcpy(hdev->dev_class, rp->dev_class, 3); 408a9de9248SMarcel Holtmann 409a9de9248SMarcel Holtmann BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, 410a9de9248SMarcel Holtmann hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); 411a9de9248SMarcel Holtmann } 412a9de9248SMarcel Holtmann 413a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 414a9de9248SMarcel Holtmann { 415a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 416a9de9248SMarcel Holtmann void *sent; 417a9de9248SMarcel Holtmann 4189f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 419a9de9248SMarcel Holtmann 420a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); 421a9de9248SMarcel Holtmann if (!sent) 422a9de9248SMarcel Holtmann return; 423a9de9248SMarcel Holtmann 4247f9a903cSMarcel Holtmann hci_dev_lock(hdev); 4257f9a903cSMarcel Holtmann 4267f9a903cSMarcel Holtmann if (status == 0) 427a9de9248SMarcel Holtmann memcpy(hdev->dev_class, sent, 3); 4287f9a903cSMarcel Holtmann 429d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_MGMT)) 4307f9a903cSMarcel Holtmann mgmt_set_class_of_dev_complete(hdev, sent, status); 4317f9a903cSMarcel Holtmann 4327f9a903cSMarcel Holtmann hci_dev_unlock(hdev); 433a9de9248SMarcel Holtmann } 434a9de9248SMarcel Holtmann 435a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 436a9de9248SMarcel Holtmann { 437a9de9248SMarcel Holtmann struct hci_rp_read_voice_setting *rp = (void *) skb->data; 438a9de9248SMarcel Holtmann __u16 setting; 439a9de9248SMarcel Holtmann 4409f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 441a9de9248SMarcel Holtmann 442a9de9248SMarcel Holtmann if (rp->status) 443a9de9248SMarcel Holtmann return; 444a9de9248SMarcel Holtmann 445a9de9248SMarcel Holtmann setting = __le16_to_cpu(rp->voice_setting); 446a9de9248SMarcel Holtmann 447a9de9248SMarcel Holtmann if (hdev->voice_setting == setting) 448a9de9248SMarcel Holtmann return; 449a9de9248SMarcel Holtmann 450a9de9248SMarcel Holtmann hdev->voice_setting = setting; 451a9de9248SMarcel Holtmann 4529f1db00cSAndrei Emeltchenko BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting); 453a9de9248SMarcel Holtmann 4543c54711cSGustavo F. Padovan if (hdev->notify) 455a9de9248SMarcel Holtmann hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 456a9de9248SMarcel Holtmann } 457a9de9248SMarcel Holtmann 4588fc9ced3SGustavo Padovan static void hci_cc_write_voice_setting(struct hci_dev *hdev, 4598fc9ced3SGustavo Padovan struct sk_buff *skb) 460a9de9248SMarcel Holtmann { 461a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 462f383f275SMarcel Holtmann __u16 setting; 463a9de9248SMarcel Holtmann void *sent; 464a9de9248SMarcel Holtmann 4659f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 466a9de9248SMarcel Holtmann 467f383f275SMarcel Holtmann if (status) 468f383f275SMarcel Holtmann return; 469f383f275SMarcel Holtmann 470a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); 471a9de9248SMarcel Holtmann if (!sent) 472a9de9248SMarcel Holtmann return; 473a9de9248SMarcel Holtmann 474f383f275SMarcel Holtmann setting = get_unaligned_le16(sent); 4751da177e4SLinus Torvalds 476f383f275SMarcel Holtmann if (hdev->voice_setting == setting) 477f383f275SMarcel Holtmann return; 478f383f275SMarcel Holtmann 4791da177e4SLinus Torvalds hdev->voice_setting = setting; 4801da177e4SLinus Torvalds 4819f1db00cSAndrei Emeltchenko BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting); 4821da177e4SLinus Torvalds 4833c54711cSGustavo F. Padovan if (hdev->notify) 4841da177e4SLinus Torvalds hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 4851da177e4SLinus Torvalds } 4861da177e4SLinus Torvalds 487b4cb9fb2SMarcel Holtmann static void hci_cc_read_num_supported_iac(struct hci_dev *hdev, 488b4cb9fb2SMarcel Holtmann struct sk_buff *skb) 489b4cb9fb2SMarcel Holtmann { 490b4cb9fb2SMarcel Holtmann struct hci_rp_read_num_supported_iac *rp = (void *) skb->data; 491b4cb9fb2SMarcel Holtmann 492b4cb9fb2SMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 493b4cb9fb2SMarcel Holtmann 494b4cb9fb2SMarcel Holtmann if (rp->status) 495b4cb9fb2SMarcel Holtmann return; 496b4cb9fb2SMarcel Holtmann 497b4cb9fb2SMarcel Holtmann hdev->num_iac = rp->num_iac; 498b4cb9fb2SMarcel Holtmann 499b4cb9fb2SMarcel Holtmann BT_DBG("%s num iac %d", hdev->name, hdev->num_iac); 500b4cb9fb2SMarcel Holtmann } 501b4cb9fb2SMarcel Holtmann 502333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 503333140b5SMarcel Holtmann { 504333140b5SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 5055ed8eb2fSJohan Hedberg struct hci_cp_write_ssp_mode *sent; 506333140b5SMarcel Holtmann 5079f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 508333140b5SMarcel Holtmann 509333140b5SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); 510333140b5SMarcel Holtmann if (!sent) 511333140b5SMarcel Holtmann return; 512333140b5SMarcel Holtmann 5135c1a4c8fSJaganath Kanakkassery hci_dev_lock(hdev); 5145c1a4c8fSJaganath Kanakkassery 5155ed8eb2fSJohan Hedberg if (!status) { 5165ed8eb2fSJohan Hedberg if (sent->mode) 517cad718edSJohan Hedberg hdev->features[1][0] |= LMP_HOST_SSP; 5185ed8eb2fSJohan Hedberg else 519cad718edSJohan Hedberg hdev->features[1][0] &= ~LMP_HOST_SSP; 5205ed8eb2fSJohan Hedberg } 5215ed8eb2fSJohan Hedberg 522d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_MGMT)) 5235ed8eb2fSJohan Hedberg mgmt_ssp_enable_complete(hdev, sent->mode, status); 524c0ecddc2SJohan Hedberg else if (!status) { 5255ed8eb2fSJohan Hedberg if (sent->mode) 526a1536da2SMarcel Holtmann hci_dev_set_flag(hdev, HCI_SSP_ENABLED); 52784bde9d6SJohan Hedberg else 528a358dc11SMarcel Holtmann hci_dev_clear_flag(hdev, HCI_SSP_ENABLED); 529c0ecddc2SJohan Hedberg } 5305c1a4c8fSJaganath Kanakkassery 5315c1a4c8fSJaganath Kanakkassery hci_dev_unlock(hdev); 532333140b5SMarcel Holtmann } 533333140b5SMarcel Holtmann 534eac83dc6SMarcel Holtmann static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb) 535eac83dc6SMarcel Holtmann { 536eac83dc6SMarcel Holtmann u8 status = *((u8 *) skb->data); 537eac83dc6SMarcel Holtmann struct hci_cp_write_sc_support *sent; 538eac83dc6SMarcel Holtmann 539eac83dc6SMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, status); 540eac83dc6SMarcel Holtmann 541eac83dc6SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SC_SUPPORT); 542eac83dc6SMarcel Holtmann if (!sent) 543eac83dc6SMarcel Holtmann return; 544eac83dc6SMarcel Holtmann 5455c1a4c8fSJaganath Kanakkassery hci_dev_lock(hdev); 5465c1a4c8fSJaganath Kanakkassery 547eac83dc6SMarcel Holtmann if (!status) { 548eac83dc6SMarcel Holtmann if (sent->support) 549eac83dc6SMarcel Holtmann hdev->features[1][0] |= LMP_HOST_SC; 550eac83dc6SMarcel Holtmann else 551eac83dc6SMarcel Holtmann hdev->features[1][0] &= ~LMP_HOST_SC; 552eac83dc6SMarcel Holtmann } 553eac83dc6SMarcel Holtmann 554d7a5a11dSMarcel Holtmann if (!hci_dev_test_flag(hdev, HCI_MGMT) && !status) { 555eac83dc6SMarcel Holtmann if (sent->support) 556a1536da2SMarcel Holtmann hci_dev_set_flag(hdev, HCI_SC_ENABLED); 557eac83dc6SMarcel Holtmann else 558a358dc11SMarcel Holtmann hci_dev_clear_flag(hdev, HCI_SC_ENABLED); 559eac83dc6SMarcel Holtmann } 5605c1a4c8fSJaganath Kanakkassery 5615c1a4c8fSJaganath Kanakkassery hci_dev_unlock(hdev); 562eac83dc6SMarcel Holtmann } 563eac83dc6SMarcel Holtmann 564a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) 565a9de9248SMarcel Holtmann { 566a9de9248SMarcel Holtmann struct hci_rp_read_local_version *rp = (void *) skb->data; 5671143e5a6SMarcel Holtmann 5689f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 5691143e5a6SMarcel Holtmann 570a9de9248SMarcel Holtmann if (rp->status) 57142c6b129SJohan Hedberg return; 5721143e5a6SMarcel Holtmann 573d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_SETUP) || 574d7a5a11dSMarcel Holtmann hci_dev_test_flag(hdev, HCI_CONFIG)) { 575a9de9248SMarcel Holtmann hdev->hci_ver = rp->hci_ver; 576e4e8e37cSMarcel Holtmann hdev->hci_rev = __le16_to_cpu(rp->hci_rev); 577d5859e22SJohan Hedberg hdev->lmp_ver = rp->lmp_ver; 578e4e8e37cSMarcel Holtmann hdev->manufacturer = __le16_to_cpu(rp->manufacturer); 579d5859e22SJohan Hedberg hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); 5800d5551f5SMarcel Holtmann } 581d5859e22SJohan Hedberg } 582d5859e22SJohan Hedberg 5838fc9ced3SGustavo Padovan static void hci_cc_read_local_commands(struct hci_dev *hdev, 5848fc9ced3SGustavo Padovan struct sk_buff *skb) 585a9de9248SMarcel Holtmann { 586a9de9248SMarcel Holtmann struct hci_rp_read_local_commands *rp = (void *) skb->data; 587a9de9248SMarcel Holtmann 5889f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 589a9de9248SMarcel Holtmann 5906a070e6eSMarcel Holtmann if (rp->status) 5916a070e6eSMarcel Holtmann return; 5926a070e6eSMarcel Holtmann 593d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_SETUP) || 594d7a5a11dSMarcel Holtmann hci_dev_test_flag(hdev, HCI_CONFIG)) 595a9de9248SMarcel Holtmann memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); 596a9de9248SMarcel Holtmann } 597a9de9248SMarcel Holtmann 598302975cbSSpoorthi Ravishankar Koppad static void hci_cc_read_auth_payload_timeout(struct hci_dev *hdev, 599302975cbSSpoorthi Ravishankar Koppad struct sk_buff *skb) 600302975cbSSpoorthi Ravishankar Koppad { 601302975cbSSpoorthi Ravishankar Koppad struct hci_rp_read_auth_payload_to *rp = (void *)skb->data; 602302975cbSSpoorthi Ravishankar Koppad struct hci_conn *conn; 603302975cbSSpoorthi Ravishankar Koppad 604302975cbSSpoorthi Ravishankar Koppad BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 605302975cbSSpoorthi Ravishankar Koppad 606302975cbSSpoorthi Ravishankar Koppad if (rp->status) 607302975cbSSpoorthi Ravishankar Koppad return; 608302975cbSSpoorthi Ravishankar Koppad 609302975cbSSpoorthi Ravishankar Koppad hci_dev_lock(hdev); 610302975cbSSpoorthi Ravishankar Koppad 611302975cbSSpoorthi Ravishankar Koppad conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 612302975cbSSpoorthi Ravishankar Koppad if (conn) 613302975cbSSpoorthi Ravishankar Koppad conn->auth_payload_timeout = __le16_to_cpu(rp->timeout); 614302975cbSSpoorthi Ravishankar Koppad 615302975cbSSpoorthi Ravishankar Koppad hci_dev_unlock(hdev); 616302975cbSSpoorthi Ravishankar Koppad } 617302975cbSSpoorthi Ravishankar Koppad 618302975cbSSpoorthi Ravishankar Koppad static void hci_cc_write_auth_payload_timeout(struct hci_dev *hdev, 619302975cbSSpoorthi Ravishankar Koppad struct sk_buff *skb) 620302975cbSSpoorthi Ravishankar Koppad { 621302975cbSSpoorthi Ravishankar Koppad struct hci_rp_write_auth_payload_to *rp = (void *)skb->data; 622302975cbSSpoorthi Ravishankar Koppad struct hci_conn *conn; 623302975cbSSpoorthi Ravishankar Koppad void *sent; 624302975cbSSpoorthi Ravishankar Koppad 625302975cbSSpoorthi Ravishankar Koppad BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 626302975cbSSpoorthi Ravishankar Koppad 627302975cbSSpoorthi Ravishankar Koppad if (rp->status) 628302975cbSSpoorthi Ravishankar Koppad return; 629302975cbSSpoorthi Ravishankar Koppad 630302975cbSSpoorthi Ravishankar Koppad sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_PAYLOAD_TO); 631302975cbSSpoorthi Ravishankar Koppad if (!sent) 632302975cbSSpoorthi Ravishankar Koppad return; 633302975cbSSpoorthi Ravishankar Koppad 634302975cbSSpoorthi Ravishankar Koppad hci_dev_lock(hdev); 635302975cbSSpoorthi Ravishankar Koppad 636302975cbSSpoorthi Ravishankar Koppad conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 637302975cbSSpoorthi Ravishankar Koppad if (conn) 638302975cbSSpoorthi Ravishankar Koppad conn->auth_payload_timeout = get_unaligned_le16(sent + 2); 639302975cbSSpoorthi Ravishankar Koppad 640302975cbSSpoorthi Ravishankar Koppad hci_dev_unlock(hdev); 641302975cbSSpoorthi Ravishankar Koppad } 642302975cbSSpoorthi Ravishankar Koppad 6438fc9ced3SGustavo Padovan static void hci_cc_read_local_features(struct hci_dev *hdev, 6448fc9ced3SGustavo Padovan struct sk_buff *skb) 645a9de9248SMarcel Holtmann { 646a9de9248SMarcel Holtmann struct hci_rp_read_local_features *rp = (void *) skb->data; 647a9de9248SMarcel Holtmann 6489f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 649a9de9248SMarcel Holtmann 650a9de9248SMarcel Holtmann if (rp->status) 651a9de9248SMarcel Holtmann return; 652a9de9248SMarcel Holtmann 653a9de9248SMarcel Holtmann memcpy(hdev->features, rp->features, 8); 6541da177e4SLinus Torvalds 6551da177e4SLinus Torvalds /* Adjust default settings according to features 6561da177e4SLinus Torvalds * supported by device. */ 657a9de9248SMarcel Holtmann 658cad718edSJohan Hedberg if (hdev->features[0][0] & LMP_3SLOT) 6591da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM3 | HCI_DH3); 6601da177e4SLinus Torvalds 661cad718edSJohan Hedberg if (hdev->features[0][0] & LMP_5SLOT) 6621da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM5 | HCI_DH5); 6631da177e4SLinus Torvalds 664cad718edSJohan Hedberg if (hdev->features[0][1] & LMP_HV2) { 6651da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV2); 6665b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV2); 6675b7f9909SMarcel Holtmann } 6681da177e4SLinus Torvalds 669cad718edSJohan Hedberg if (hdev->features[0][1] & LMP_HV3) { 6701da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV3); 6715b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV3); 6725b7f9909SMarcel Holtmann } 6735b7f9909SMarcel Holtmann 67445db810fSAndre Guedes if (lmp_esco_capable(hdev)) 6755b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV3); 6765b7f9909SMarcel Holtmann 677cad718edSJohan Hedberg if (hdev->features[0][4] & LMP_EV4) 6785b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV4); 6795b7f9909SMarcel Holtmann 680cad718edSJohan Hedberg if (hdev->features[0][4] & LMP_EV5) 6815b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV5); 6821da177e4SLinus Torvalds 683cad718edSJohan Hedberg if (hdev->features[0][5] & LMP_EDR_ESCO_2M) 684efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV3); 685efc7688bSMarcel Holtmann 686cad718edSJohan Hedberg if (hdev->features[0][5] & LMP_EDR_ESCO_3M) 687efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_3EV3); 688efc7688bSMarcel Holtmann 689cad718edSJohan Hedberg if (hdev->features[0][5] & LMP_EDR_3S_ESCO) 690efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); 6911da177e4SLinus Torvalds } 6921da177e4SLinus Torvalds 693971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev, 694971e3a4bSAndre Guedes struct sk_buff *skb) 695971e3a4bSAndre Guedes { 696971e3a4bSAndre Guedes struct hci_rp_read_local_ext_features *rp = (void *) skb->data; 697971e3a4bSAndre Guedes 6989f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 699971e3a4bSAndre Guedes 700971e3a4bSAndre Guedes if (rp->status) 70142c6b129SJohan Hedberg return; 702971e3a4bSAndre Guedes 70357af75a8SMarcel Holtmann if (hdev->max_page < rp->max_page) 704d2c5d77fSJohan Hedberg hdev->max_page = rp->max_page; 705d2c5d77fSJohan Hedberg 706cad718edSJohan Hedberg if (rp->page < HCI_MAX_PAGES) 707cad718edSJohan Hedberg memcpy(hdev->features[rp->page], rp->features, 8); 708971e3a4bSAndre Guedes } 709971e3a4bSAndre Guedes 7101e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, 7111e89cffbSAndrei Emeltchenko struct sk_buff *skb) 7121e89cffbSAndrei Emeltchenko { 7131e89cffbSAndrei Emeltchenko struct hci_rp_read_flow_control_mode *rp = (void *) skb->data; 7141e89cffbSAndrei Emeltchenko 7159f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 7161e89cffbSAndrei Emeltchenko 71745296acdSMarcel Holtmann if (rp->status) 71845296acdSMarcel Holtmann return; 71945296acdSMarcel Holtmann 7201e89cffbSAndrei Emeltchenko hdev->flow_ctl_mode = rp->mode; 7211e89cffbSAndrei Emeltchenko } 7221e89cffbSAndrei Emeltchenko 723a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 724a9de9248SMarcel Holtmann { 725a9de9248SMarcel Holtmann struct hci_rp_read_buffer_size *rp = (void *) skb->data; 726a9de9248SMarcel Holtmann 7279f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 728a9de9248SMarcel Holtmann 729a9de9248SMarcel Holtmann if (rp->status) 730a9de9248SMarcel Holtmann return; 731a9de9248SMarcel Holtmann 732a9de9248SMarcel Holtmann hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); 733a9de9248SMarcel Holtmann hdev->sco_mtu = rp->sco_mtu; 734a9de9248SMarcel Holtmann hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); 735a9de9248SMarcel Holtmann hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); 736da1f5198SMarcel Holtmann 737da1f5198SMarcel Holtmann if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { 738da1f5198SMarcel Holtmann hdev->sco_mtu = 64; 739da1f5198SMarcel Holtmann hdev->sco_pkts = 8; 740da1f5198SMarcel Holtmann } 741da1f5198SMarcel Holtmann 742da1f5198SMarcel Holtmann hdev->acl_cnt = hdev->acl_pkts; 743da1f5198SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 7441da177e4SLinus Torvalds 745807deac2SGustavo Padovan BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu, 746807deac2SGustavo Padovan hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts); 7471da177e4SLinus Torvalds } 7481da177e4SLinus Torvalds 749a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) 750a9de9248SMarcel Holtmann { 751a9de9248SMarcel Holtmann struct hci_rp_read_bd_addr *rp = (void *) skb->data; 7521da177e4SLinus Torvalds 7539f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 754a9de9248SMarcel Holtmann 755e30d3f5fSMarcel Holtmann if (rp->status) 756e30d3f5fSMarcel Holtmann return; 757e30d3f5fSMarcel Holtmann 758e30d3f5fSMarcel Holtmann if (test_bit(HCI_INIT, &hdev->flags)) 759a9de9248SMarcel Holtmann bacpy(&hdev->bdaddr, &rp->bdaddr); 760e30d3f5fSMarcel Holtmann 761d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_SETUP)) 762e30d3f5fSMarcel Holtmann bacpy(&hdev->setup_addr, &rp->bdaddr); 76323bb5763SJohan Hedberg } 76423bb5763SJohan Hedberg 765a4790360SMarcel Holtmann static void hci_cc_read_local_pairing_opts(struct hci_dev *hdev, 766a4790360SMarcel Holtmann struct sk_buff *skb) 767a4790360SMarcel Holtmann { 768a4790360SMarcel Holtmann struct hci_rp_read_local_pairing_opts *rp = (void *) skb->data; 769a4790360SMarcel Holtmann 770a4790360SMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 771a4790360SMarcel Holtmann 772a4790360SMarcel Holtmann if (rp->status) 773a4790360SMarcel Holtmann return; 774a4790360SMarcel Holtmann 775a4790360SMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_SETUP) || 776a4790360SMarcel Holtmann hci_dev_test_flag(hdev, HCI_CONFIG)) { 777a4790360SMarcel Holtmann hdev->pairing_opts = rp->pairing_opts; 778a4790360SMarcel Holtmann hdev->max_enc_key_size = rp->max_key_size; 779a4790360SMarcel Holtmann } 780a4790360SMarcel Holtmann } 781a4790360SMarcel Holtmann 782f332ec66SJohan Hedberg static void hci_cc_read_page_scan_activity(struct hci_dev *hdev, 783f332ec66SJohan Hedberg struct sk_buff *skb) 784f332ec66SJohan Hedberg { 785f332ec66SJohan Hedberg struct hci_rp_read_page_scan_activity *rp = (void *) skb->data; 786f332ec66SJohan Hedberg 787f332ec66SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 788f332ec66SJohan Hedberg 78945296acdSMarcel Holtmann if (rp->status) 79045296acdSMarcel Holtmann return; 79145296acdSMarcel Holtmann 79245296acdSMarcel Holtmann if (test_bit(HCI_INIT, &hdev->flags)) { 793f332ec66SJohan Hedberg hdev->page_scan_interval = __le16_to_cpu(rp->interval); 794f332ec66SJohan Hedberg hdev->page_scan_window = __le16_to_cpu(rp->window); 795f332ec66SJohan Hedberg } 796f332ec66SJohan Hedberg } 797f332ec66SJohan Hedberg 7984a3ee763SJohan Hedberg static void hci_cc_write_page_scan_activity(struct hci_dev *hdev, 7994a3ee763SJohan Hedberg struct sk_buff *skb) 8004a3ee763SJohan Hedberg { 8014a3ee763SJohan Hedberg u8 status = *((u8 *) skb->data); 8024a3ee763SJohan Hedberg struct hci_cp_write_page_scan_activity *sent; 8034a3ee763SJohan Hedberg 8044a3ee763SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 8054a3ee763SJohan Hedberg 8064a3ee763SJohan Hedberg if (status) 8074a3ee763SJohan Hedberg return; 8084a3ee763SJohan Hedberg 8094a3ee763SJohan Hedberg sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY); 8104a3ee763SJohan Hedberg if (!sent) 8114a3ee763SJohan Hedberg return; 8124a3ee763SJohan Hedberg 8134a3ee763SJohan Hedberg hdev->page_scan_interval = __le16_to_cpu(sent->interval); 8144a3ee763SJohan Hedberg hdev->page_scan_window = __le16_to_cpu(sent->window); 8154a3ee763SJohan Hedberg } 8164a3ee763SJohan Hedberg 817f332ec66SJohan Hedberg static void hci_cc_read_page_scan_type(struct hci_dev *hdev, 818f332ec66SJohan Hedberg struct sk_buff *skb) 819f332ec66SJohan Hedberg { 820f332ec66SJohan Hedberg struct hci_rp_read_page_scan_type *rp = (void *) skb->data; 821f332ec66SJohan Hedberg 822f332ec66SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 823f332ec66SJohan Hedberg 82445296acdSMarcel Holtmann if (rp->status) 82545296acdSMarcel Holtmann return; 82645296acdSMarcel Holtmann 82745296acdSMarcel Holtmann if (test_bit(HCI_INIT, &hdev->flags)) 828f332ec66SJohan Hedberg hdev->page_scan_type = rp->type; 829f332ec66SJohan Hedberg } 830f332ec66SJohan Hedberg 8314a3ee763SJohan Hedberg static void hci_cc_write_page_scan_type(struct hci_dev *hdev, 8324a3ee763SJohan Hedberg struct sk_buff *skb) 8334a3ee763SJohan Hedberg { 8344a3ee763SJohan Hedberg u8 status = *((u8 *) skb->data); 8354a3ee763SJohan Hedberg u8 *type; 8364a3ee763SJohan Hedberg 8374a3ee763SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 8384a3ee763SJohan Hedberg 8394a3ee763SJohan Hedberg if (status) 8404a3ee763SJohan Hedberg return; 8414a3ee763SJohan Hedberg 8424a3ee763SJohan Hedberg type = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE); 8434a3ee763SJohan Hedberg if (type) 8444a3ee763SJohan Hedberg hdev->page_scan_type = *type; 8454a3ee763SJohan Hedberg } 8464a3ee763SJohan Hedberg 847350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev, 848350ee4cfSAndrei Emeltchenko struct sk_buff *skb) 849350ee4cfSAndrei Emeltchenko { 850350ee4cfSAndrei Emeltchenko struct hci_rp_read_data_block_size *rp = (void *) skb->data; 851350ee4cfSAndrei Emeltchenko 8529f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 853350ee4cfSAndrei Emeltchenko 854350ee4cfSAndrei Emeltchenko if (rp->status) 855350ee4cfSAndrei Emeltchenko return; 856350ee4cfSAndrei Emeltchenko 857350ee4cfSAndrei Emeltchenko hdev->block_mtu = __le16_to_cpu(rp->max_acl_len); 858350ee4cfSAndrei Emeltchenko hdev->block_len = __le16_to_cpu(rp->block_len); 859350ee4cfSAndrei Emeltchenko hdev->num_blocks = __le16_to_cpu(rp->num_blocks); 860350ee4cfSAndrei Emeltchenko 861350ee4cfSAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 862350ee4cfSAndrei Emeltchenko 863350ee4cfSAndrei Emeltchenko BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu, 864350ee4cfSAndrei Emeltchenko hdev->block_cnt, hdev->block_len); 865350ee4cfSAndrei Emeltchenko } 866350ee4cfSAndrei Emeltchenko 86733f35721SJohan Hedberg static void hci_cc_read_clock(struct hci_dev *hdev, struct sk_buff *skb) 86833f35721SJohan Hedberg { 86933f35721SJohan Hedberg struct hci_rp_read_clock *rp = (void *) skb->data; 87033f35721SJohan Hedberg struct hci_cp_read_clock *cp; 87133f35721SJohan Hedberg struct hci_conn *conn; 87233f35721SJohan Hedberg 87333f35721SJohan Hedberg BT_DBG("%s", hdev->name); 87433f35721SJohan Hedberg 87533f35721SJohan Hedberg if (skb->len < sizeof(*rp)) 87633f35721SJohan Hedberg return; 87733f35721SJohan Hedberg 87833f35721SJohan Hedberg if (rp->status) 87933f35721SJohan Hedberg return; 88033f35721SJohan Hedberg 88133f35721SJohan Hedberg hci_dev_lock(hdev); 88233f35721SJohan Hedberg 88333f35721SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK); 88433f35721SJohan Hedberg if (!cp) 88533f35721SJohan Hedberg goto unlock; 88633f35721SJohan Hedberg 88733f35721SJohan Hedberg if (cp->which == 0x00) { 88833f35721SJohan Hedberg hdev->clock = le32_to_cpu(rp->clock); 88933f35721SJohan Hedberg goto unlock; 89033f35721SJohan Hedberg } 89133f35721SJohan Hedberg 89233f35721SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 89333f35721SJohan Hedberg if (conn) { 89433f35721SJohan Hedberg conn->clock = le32_to_cpu(rp->clock); 89533f35721SJohan Hedberg conn->clock_accuracy = le16_to_cpu(rp->accuracy); 89633f35721SJohan Hedberg } 89733f35721SJohan Hedberg 89833f35721SJohan Hedberg unlock: 89933f35721SJohan Hedberg hci_dev_unlock(hdev); 90033f35721SJohan Hedberg } 90133f35721SJohan Hedberg 902928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev, 903928abaa7SAndrei Emeltchenko struct sk_buff *skb) 904928abaa7SAndrei Emeltchenko { 905928abaa7SAndrei Emeltchenko struct hci_rp_read_local_amp_info *rp = (void *) skb->data; 906928abaa7SAndrei Emeltchenko 9079f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 908928abaa7SAndrei Emeltchenko 909928abaa7SAndrei Emeltchenko if (rp->status) 91083927882SArron Wang return; 911928abaa7SAndrei Emeltchenko 912928abaa7SAndrei Emeltchenko hdev->amp_status = rp->amp_status; 913928abaa7SAndrei Emeltchenko hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); 914928abaa7SAndrei Emeltchenko hdev->amp_max_bw = __le32_to_cpu(rp->max_bw); 915928abaa7SAndrei Emeltchenko hdev->amp_min_latency = __le32_to_cpu(rp->min_latency); 916928abaa7SAndrei Emeltchenko hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu); 917928abaa7SAndrei Emeltchenko hdev->amp_type = rp->amp_type; 918928abaa7SAndrei Emeltchenko hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap); 919928abaa7SAndrei Emeltchenko hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size); 920928abaa7SAndrei Emeltchenko hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); 921928abaa7SAndrei Emeltchenko hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); 922928abaa7SAndrei Emeltchenko } 923928abaa7SAndrei Emeltchenko 924d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, 925d5859e22SJohan Hedberg struct sk_buff *skb) 926d5859e22SJohan Hedberg { 92791c4e9b1SMarcel Holtmann struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data; 928d5859e22SJohan Hedberg 9299f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 930d5859e22SJohan Hedberg 93145296acdSMarcel Holtmann if (rp->status) 93245296acdSMarcel Holtmann return; 93345296acdSMarcel Holtmann 93491c4e9b1SMarcel Holtmann hdev->inq_tx_power = rp->tx_power; 935d5859e22SJohan Hedberg } 936d5859e22SJohan Hedberg 93700bce3fbSAlain Michaud static void hci_cc_read_def_err_data_reporting(struct hci_dev *hdev, 93800bce3fbSAlain Michaud struct sk_buff *skb) 93900bce3fbSAlain Michaud { 94000bce3fbSAlain Michaud struct hci_rp_read_def_err_data_reporting *rp = (void *)skb->data; 94100bce3fbSAlain Michaud 94200bce3fbSAlain Michaud BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 94300bce3fbSAlain Michaud 94400bce3fbSAlain Michaud if (rp->status) 94500bce3fbSAlain Michaud return; 94600bce3fbSAlain Michaud 94700bce3fbSAlain Michaud hdev->err_data_reporting = rp->err_data_reporting; 94800bce3fbSAlain Michaud } 94900bce3fbSAlain Michaud 95000bce3fbSAlain Michaud static void hci_cc_write_def_err_data_reporting(struct hci_dev *hdev, 95100bce3fbSAlain Michaud struct sk_buff *skb) 95200bce3fbSAlain Michaud { 95300bce3fbSAlain Michaud __u8 status = *((__u8 *)skb->data); 95400bce3fbSAlain Michaud struct hci_cp_write_def_err_data_reporting *cp; 95500bce3fbSAlain Michaud 95600bce3fbSAlain Michaud BT_DBG("%s status 0x%2.2x", hdev->name, status); 95700bce3fbSAlain Michaud 95800bce3fbSAlain Michaud if (status) 95900bce3fbSAlain Michaud return; 96000bce3fbSAlain Michaud 96100bce3fbSAlain Michaud cp = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_ERR_DATA_REPORTING); 96200bce3fbSAlain Michaud if (!cp) 96300bce3fbSAlain Michaud return; 96400bce3fbSAlain Michaud 96500bce3fbSAlain Michaud hdev->err_data_reporting = cp->err_data_reporting; 96600bce3fbSAlain Michaud } 96700bce3fbSAlain Michaud 968980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) 969980e1a53SJohan Hedberg { 970980e1a53SJohan Hedberg struct hci_rp_pin_code_reply *rp = (void *) skb->data; 971980e1a53SJohan Hedberg struct hci_cp_pin_code_reply *cp; 972980e1a53SJohan Hedberg struct hci_conn *conn; 973980e1a53SJohan Hedberg 9749f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 975980e1a53SJohan Hedberg 97656e5cb86SJohan Hedberg hci_dev_lock(hdev); 97756e5cb86SJohan Hedberg 978d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_MGMT)) 979744cf19eSJohan Hedberg mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); 980980e1a53SJohan Hedberg 981fa1bd918SMikel Astiz if (rp->status) 98256e5cb86SJohan Hedberg goto unlock; 983980e1a53SJohan Hedberg 984980e1a53SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); 985980e1a53SJohan Hedberg if (!cp) 98656e5cb86SJohan Hedberg goto unlock; 987980e1a53SJohan Hedberg 988980e1a53SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 989980e1a53SJohan Hedberg if (conn) 990980e1a53SJohan Hedberg conn->pin_length = cp->pin_len; 99156e5cb86SJohan Hedberg 99256e5cb86SJohan Hedberg unlock: 99356e5cb86SJohan Hedberg hci_dev_unlock(hdev); 994980e1a53SJohan Hedberg } 995980e1a53SJohan Hedberg 996980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 997980e1a53SJohan Hedberg { 998980e1a53SJohan Hedberg struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data; 999980e1a53SJohan Hedberg 10009f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1001980e1a53SJohan Hedberg 100256e5cb86SJohan Hedberg hci_dev_lock(hdev); 100356e5cb86SJohan Hedberg 1004d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_MGMT)) 1005744cf19eSJohan Hedberg mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr, 1006980e1a53SJohan Hedberg rp->status); 100756e5cb86SJohan Hedberg 100856e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1009980e1a53SJohan Hedberg } 101056e5cb86SJohan Hedberg 10116ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, 10126ed58ec5SVille Tervo struct sk_buff *skb) 10136ed58ec5SVille Tervo { 10146ed58ec5SVille Tervo struct hci_rp_le_read_buffer_size *rp = (void *) skb->data; 10156ed58ec5SVille Tervo 10169f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 10176ed58ec5SVille Tervo 10186ed58ec5SVille Tervo if (rp->status) 10196ed58ec5SVille Tervo return; 10206ed58ec5SVille Tervo 10216ed58ec5SVille Tervo hdev->le_mtu = __le16_to_cpu(rp->le_mtu); 10226ed58ec5SVille Tervo hdev->le_pkts = rp->le_max_pkt; 10236ed58ec5SVille Tervo 10246ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 10256ed58ec5SVille Tervo 10266ed58ec5SVille Tervo BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); 10276ed58ec5SVille Tervo } 1028980e1a53SJohan Hedberg 102960e77321SJohan Hedberg static void hci_cc_le_read_local_features(struct hci_dev *hdev, 103060e77321SJohan Hedberg struct sk_buff *skb) 103160e77321SJohan Hedberg { 103260e77321SJohan Hedberg struct hci_rp_le_read_local_features *rp = (void *) skb->data; 103360e77321SJohan Hedberg 103460e77321SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 103560e77321SJohan Hedberg 103645296acdSMarcel Holtmann if (rp->status) 103745296acdSMarcel Holtmann return; 103845296acdSMarcel Holtmann 103960e77321SJohan Hedberg memcpy(hdev->le_features, rp->features, 8); 104060e77321SJohan Hedberg } 104160e77321SJohan Hedberg 10428fa19098SJohan Hedberg static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, 10438fa19098SJohan Hedberg struct sk_buff *skb) 10448fa19098SJohan Hedberg { 10458fa19098SJohan Hedberg struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data; 10468fa19098SJohan Hedberg 10478fa19098SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 10488fa19098SJohan Hedberg 104945296acdSMarcel Holtmann if (rp->status) 105045296acdSMarcel Holtmann return; 105145296acdSMarcel Holtmann 10528fa19098SJohan Hedberg hdev->adv_tx_power = rp->tx_power; 10538fa19098SJohan Hedberg } 10548fa19098SJohan Hedberg 1055a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) 1056a5c29683SJohan Hedberg { 1057a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 1058a5c29683SJohan Hedberg 10599f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1060a5c29683SJohan Hedberg 106156e5cb86SJohan Hedberg hci_dev_lock(hdev); 106256e5cb86SJohan Hedberg 1063d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_MGMT)) 106404124681SGustavo F. Padovan mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0, 106504124681SGustavo F. Padovan rp->status); 106656e5cb86SJohan Hedberg 106756e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1068a5c29683SJohan Hedberg } 1069a5c29683SJohan Hedberg 1070a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, 1071a5c29683SJohan Hedberg struct sk_buff *skb) 1072a5c29683SJohan Hedberg { 1073a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 1074a5c29683SJohan Hedberg 10759f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1076a5c29683SJohan Hedberg 107756e5cb86SJohan Hedberg hci_dev_lock(hdev); 107856e5cb86SJohan Hedberg 1079d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_MGMT)) 1080744cf19eSJohan Hedberg mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr, 108104124681SGustavo F. Padovan ACL_LINK, 0, rp->status); 108256e5cb86SJohan Hedberg 108356e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1084a5c29683SJohan Hedberg } 1085a5c29683SJohan Hedberg 10861143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb) 10871143d458SBrian Gix { 10881143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 10891143d458SBrian Gix 10909f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 10911143d458SBrian Gix 10921143d458SBrian Gix hci_dev_lock(hdev); 10931143d458SBrian Gix 1094d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_MGMT)) 1095272d90dfSJohan Hedberg mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 1096272d90dfSJohan Hedberg 0, rp->status); 10971143d458SBrian Gix 10981143d458SBrian Gix hci_dev_unlock(hdev); 10991143d458SBrian Gix } 11001143d458SBrian Gix 11011143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, 11021143d458SBrian Gix struct sk_buff *skb) 11031143d458SBrian Gix { 11041143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 11051143d458SBrian Gix 11069f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 11071143d458SBrian Gix 11081143d458SBrian Gix hci_dev_lock(hdev); 11091143d458SBrian Gix 1110d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_MGMT)) 11111143d458SBrian Gix mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr, 111204124681SGustavo F. Padovan ACL_LINK, 0, rp->status); 11131143d458SBrian Gix 11141143d458SBrian Gix hci_dev_unlock(hdev); 11151143d458SBrian Gix } 11161143d458SBrian Gix 11174d2d2796SMarcel Holtmann static void hci_cc_read_local_oob_data(struct hci_dev *hdev, 1118c35938b2SSzymon Janc struct sk_buff *skb) 1119c35938b2SSzymon Janc { 1120c35938b2SSzymon Janc struct hci_rp_read_local_oob_data *rp = (void *) skb->data; 1121c35938b2SSzymon Janc 11229f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 11234d2d2796SMarcel Holtmann } 11244d2d2796SMarcel Holtmann 11254d2d2796SMarcel Holtmann static void hci_cc_read_local_oob_ext_data(struct hci_dev *hdev, 11264d2d2796SMarcel Holtmann struct sk_buff *skb) 11274d2d2796SMarcel Holtmann { 11284d2d2796SMarcel Holtmann struct hci_rp_read_local_oob_ext_data *rp = (void *) skb->data; 11294d2d2796SMarcel Holtmann 11304d2d2796SMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1131c35938b2SSzymon Janc } 1132c35938b2SSzymon Janc 11337a4cd51dSMarcel Holtmann static void hci_cc_le_set_random_addr(struct hci_dev *hdev, struct sk_buff *skb) 11347a4cd51dSMarcel Holtmann { 11357a4cd51dSMarcel Holtmann __u8 status = *((__u8 *) skb->data); 11367a4cd51dSMarcel Holtmann bdaddr_t *sent; 11377a4cd51dSMarcel Holtmann 11387a4cd51dSMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, status); 11397a4cd51dSMarcel Holtmann 114045296acdSMarcel Holtmann if (status) 114145296acdSMarcel Holtmann return; 114245296acdSMarcel Holtmann 11437a4cd51dSMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_RANDOM_ADDR); 11447a4cd51dSMarcel Holtmann if (!sent) 11457a4cd51dSMarcel Holtmann return; 11467a4cd51dSMarcel Holtmann 11477a4cd51dSMarcel Holtmann hci_dev_lock(hdev); 11487a4cd51dSMarcel Holtmann 11497a4cd51dSMarcel Holtmann bacpy(&hdev->random_addr, sent); 11507a4cd51dSMarcel Holtmann 11517a4cd51dSMarcel Holtmann hci_dev_unlock(hdev); 11527a4cd51dSMarcel Holtmann } 11537a4cd51dSMarcel Holtmann 11540314f286SJaganath Kanakkassery static void hci_cc_le_set_default_phy(struct hci_dev *hdev, struct sk_buff *skb) 11550314f286SJaganath Kanakkassery { 11560314f286SJaganath Kanakkassery __u8 status = *((__u8 *) skb->data); 11570314f286SJaganath Kanakkassery struct hci_cp_le_set_default_phy *cp; 11580314f286SJaganath Kanakkassery 11590314f286SJaganath Kanakkassery BT_DBG("%s status 0x%2.2x", hdev->name, status); 11600314f286SJaganath Kanakkassery 11610314f286SJaganath Kanakkassery if (status) 11620314f286SJaganath Kanakkassery return; 11630314f286SJaganath Kanakkassery 11640314f286SJaganath Kanakkassery cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_DEFAULT_PHY); 11650314f286SJaganath Kanakkassery if (!cp) 11660314f286SJaganath Kanakkassery return; 11670314f286SJaganath Kanakkassery 11680314f286SJaganath Kanakkassery hci_dev_lock(hdev); 11690314f286SJaganath Kanakkassery 11700314f286SJaganath Kanakkassery hdev->le_tx_def_phys = cp->tx_phys; 11710314f286SJaganath Kanakkassery hdev->le_rx_def_phys = cp->rx_phys; 11720314f286SJaganath Kanakkassery 11730314f286SJaganath Kanakkassery hci_dev_unlock(hdev); 11740314f286SJaganath Kanakkassery } 11750314f286SJaganath Kanakkassery 1176a73c046aSJaganath Kanakkassery static void hci_cc_le_set_adv_set_random_addr(struct hci_dev *hdev, 1177a73c046aSJaganath Kanakkassery struct sk_buff *skb) 1178a73c046aSJaganath Kanakkassery { 1179a73c046aSJaganath Kanakkassery __u8 status = *((__u8 *) skb->data); 1180a73c046aSJaganath Kanakkassery struct hci_cp_le_set_adv_set_rand_addr *cp; 1181a73c046aSJaganath Kanakkassery struct adv_info *adv_instance; 1182a73c046aSJaganath Kanakkassery 1183a73c046aSJaganath Kanakkassery if (status) 1184a73c046aSJaganath Kanakkassery return; 1185a73c046aSJaganath Kanakkassery 1186a73c046aSJaganath Kanakkassery cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_SET_RAND_ADDR); 1187a73c046aSJaganath Kanakkassery if (!cp) 1188a73c046aSJaganath Kanakkassery return; 1189a73c046aSJaganath Kanakkassery 1190a73c046aSJaganath Kanakkassery hci_dev_lock(hdev); 1191a73c046aSJaganath Kanakkassery 1192a73c046aSJaganath Kanakkassery if (!hdev->cur_adv_instance) { 1193a73c046aSJaganath Kanakkassery /* Store in hdev for instance 0 (Set adv and Directed advs) */ 1194a73c046aSJaganath Kanakkassery bacpy(&hdev->random_addr, &cp->bdaddr); 1195a73c046aSJaganath Kanakkassery } else { 1196a73c046aSJaganath Kanakkassery adv_instance = hci_find_adv_instance(hdev, 1197a73c046aSJaganath Kanakkassery hdev->cur_adv_instance); 1198a73c046aSJaganath Kanakkassery if (adv_instance) 1199a73c046aSJaganath Kanakkassery bacpy(&adv_instance->random_addr, &cp->bdaddr); 1200a73c046aSJaganath Kanakkassery } 1201a73c046aSJaganath Kanakkassery 1202a73c046aSJaganath Kanakkassery hci_dev_unlock(hdev); 1203a73c046aSJaganath Kanakkassery } 1204a73c046aSJaganath Kanakkassery 1205c1d5dc4aSJohan Hedberg static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb) 1206c1d5dc4aSJohan Hedberg { 1207c1d5dc4aSJohan Hedberg __u8 *sent, status = *((__u8 *) skb->data); 1208c1d5dc4aSJohan Hedberg 1209c1d5dc4aSJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 1210c1d5dc4aSJohan Hedberg 121145296acdSMarcel Holtmann if (status) 1212c1d5dc4aSJohan Hedberg return; 1213c1d5dc4aSJohan Hedberg 121445296acdSMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE); 121545296acdSMarcel Holtmann if (!sent) 12163c857757SJohan Hedberg return; 12173c857757SJohan Hedberg 1218c1d5dc4aSJohan Hedberg hci_dev_lock(hdev); 1219c1d5dc4aSJohan Hedberg 122049c922bbSStephen Hemminger /* If we're doing connection initiation as peripheral. Set a 12213c857757SJohan Hedberg * timeout in case something goes wrong. 12223c857757SJohan Hedberg */ 12233c857757SJohan Hedberg if (*sent) { 12243c857757SJohan Hedberg struct hci_conn *conn; 12253c857757SJohan Hedberg 1226a1536da2SMarcel Holtmann hci_dev_set_flag(hdev, HCI_LE_ADV); 122766c417c1SJohan Hedberg 1228e7d9ab73SJakub Pawlowski conn = hci_lookup_le_connect(hdev); 12293c857757SJohan Hedberg if (conn) 12303c857757SJohan Hedberg queue_delayed_work(hdev->workqueue, 12313c857757SJohan Hedberg &conn->le_conn_timeout, 123209ae260bSJohan Hedberg conn->conn_timeout); 123366c417c1SJohan Hedberg } else { 1234a358dc11SMarcel Holtmann hci_dev_clear_flag(hdev, HCI_LE_ADV); 12353c857757SJohan Hedberg } 12363c857757SJohan Hedberg 123704b4edcbSJohan Hedberg hci_dev_unlock(hdev); 1238c1d5dc4aSJohan Hedberg } 1239c1d5dc4aSJohan Hedberg 1240de181e88SJaganath Kanakkassery static void hci_cc_le_set_ext_adv_enable(struct hci_dev *hdev, 1241de181e88SJaganath Kanakkassery struct sk_buff *skb) 1242de181e88SJaganath Kanakkassery { 1243de181e88SJaganath Kanakkassery struct hci_cp_le_set_ext_adv_enable *cp; 1244de181e88SJaganath Kanakkassery __u8 status = *((__u8 *) skb->data); 1245de181e88SJaganath Kanakkassery 1246de181e88SJaganath Kanakkassery BT_DBG("%s status 0x%2.2x", hdev->name, status); 1247de181e88SJaganath Kanakkassery 1248de181e88SJaganath Kanakkassery if (status) 1249de181e88SJaganath Kanakkassery return; 1250de181e88SJaganath Kanakkassery 1251de181e88SJaganath Kanakkassery cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_ADV_ENABLE); 1252de181e88SJaganath Kanakkassery if (!cp) 1253de181e88SJaganath Kanakkassery return; 1254de181e88SJaganath Kanakkassery 1255de181e88SJaganath Kanakkassery hci_dev_lock(hdev); 1256de181e88SJaganath Kanakkassery 1257de181e88SJaganath Kanakkassery if (cp->enable) { 1258de181e88SJaganath Kanakkassery struct hci_conn *conn; 1259de181e88SJaganath Kanakkassery 1260de181e88SJaganath Kanakkassery hci_dev_set_flag(hdev, HCI_LE_ADV); 1261de181e88SJaganath Kanakkassery 1262de181e88SJaganath Kanakkassery conn = hci_lookup_le_connect(hdev); 1263de181e88SJaganath Kanakkassery if (conn) 1264de181e88SJaganath Kanakkassery queue_delayed_work(hdev->workqueue, 1265de181e88SJaganath Kanakkassery &conn->le_conn_timeout, 1266de181e88SJaganath Kanakkassery conn->conn_timeout); 126745b7749fSJaganath Kanakkassery } else { 126845b7749fSJaganath Kanakkassery hci_dev_clear_flag(hdev, HCI_LE_ADV); 1269de181e88SJaganath Kanakkassery } 1270de181e88SJaganath Kanakkassery 1271de181e88SJaganath Kanakkassery hci_dev_unlock(hdev); 1272de181e88SJaganath Kanakkassery } 1273de181e88SJaganath Kanakkassery 1274533553f8SMarcel Holtmann static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) 1275533553f8SMarcel Holtmann { 1276533553f8SMarcel Holtmann struct hci_cp_le_set_scan_param *cp; 1277533553f8SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 1278533553f8SMarcel Holtmann 1279533553f8SMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, status); 1280533553f8SMarcel Holtmann 128145296acdSMarcel Holtmann if (status) 128245296acdSMarcel Holtmann return; 128345296acdSMarcel Holtmann 1284533553f8SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_PARAM); 1285533553f8SMarcel Holtmann if (!cp) 1286533553f8SMarcel Holtmann return; 1287533553f8SMarcel Holtmann 1288533553f8SMarcel Holtmann hci_dev_lock(hdev); 1289533553f8SMarcel Holtmann 1290533553f8SMarcel Holtmann hdev->le_scan_type = cp->type; 1291533553f8SMarcel Holtmann 1292533553f8SMarcel Holtmann hci_dev_unlock(hdev); 1293533553f8SMarcel Holtmann } 1294533553f8SMarcel Holtmann 1295a2344b9eSJaganath Kanakkassery static void hci_cc_le_set_ext_scan_param(struct hci_dev *hdev, 1296a2344b9eSJaganath Kanakkassery struct sk_buff *skb) 1297a2344b9eSJaganath Kanakkassery { 1298a2344b9eSJaganath Kanakkassery struct hci_cp_le_set_ext_scan_params *cp; 1299a2344b9eSJaganath Kanakkassery __u8 status = *((__u8 *) skb->data); 1300a2344b9eSJaganath Kanakkassery struct hci_cp_le_scan_phy_params *phy_param; 1301a2344b9eSJaganath Kanakkassery 1302a2344b9eSJaganath Kanakkassery BT_DBG("%s status 0x%2.2x", hdev->name, status); 1303a2344b9eSJaganath Kanakkassery 1304a2344b9eSJaganath Kanakkassery if (status) 1305a2344b9eSJaganath Kanakkassery return; 1306a2344b9eSJaganath Kanakkassery 1307a2344b9eSJaganath Kanakkassery cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_SCAN_PARAMS); 1308a2344b9eSJaganath Kanakkassery if (!cp) 1309a2344b9eSJaganath Kanakkassery return; 1310a2344b9eSJaganath Kanakkassery 1311a2344b9eSJaganath Kanakkassery phy_param = (void *)cp->data; 1312a2344b9eSJaganath Kanakkassery 1313a2344b9eSJaganath Kanakkassery hci_dev_lock(hdev); 1314a2344b9eSJaganath Kanakkassery 1315a2344b9eSJaganath Kanakkassery hdev->le_scan_type = phy_param->type; 1316a2344b9eSJaganath Kanakkassery 1317a2344b9eSJaganath Kanakkassery hci_dev_unlock(hdev); 1318a2344b9eSJaganath Kanakkassery } 1319a2344b9eSJaganath Kanakkassery 1320b9a6328fSJohan Hedberg static bool has_pending_adv_report(struct hci_dev *hdev) 1321b9a6328fSJohan Hedberg { 1322b9a6328fSJohan Hedberg struct discovery_state *d = &hdev->discovery; 1323b9a6328fSJohan Hedberg 1324b9a6328fSJohan Hedberg return bacmp(&d->last_adv_addr, BDADDR_ANY); 1325b9a6328fSJohan Hedberg } 1326b9a6328fSJohan Hedberg 1327b9a6328fSJohan Hedberg static void clear_pending_adv_report(struct hci_dev *hdev) 1328b9a6328fSJohan Hedberg { 1329b9a6328fSJohan Hedberg struct discovery_state *d = &hdev->discovery; 1330b9a6328fSJohan Hedberg 1331b9a6328fSJohan Hedberg bacpy(&d->last_adv_addr, BDADDR_ANY); 1332b9a6328fSJohan Hedberg d->last_adv_data_len = 0; 1333b9a6328fSJohan Hedberg } 1334b9a6328fSJohan Hedberg 1335b9a6328fSJohan Hedberg static void store_pending_adv_report(struct hci_dev *hdev, bdaddr_t *bdaddr, 1336c70a7e4cSMarcel Holtmann u8 bdaddr_type, s8 rssi, u32 flags, 1337c70a7e4cSMarcel Holtmann u8 *data, u8 len) 1338b9a6328fSJohan Hedberg { 1339b9a6328fSJohan Hedberg struct discovery_state *d = &hdev->discovery; 1340b9a6328fSJohan Hedberg 1341b9a6328fSJohan Hedberg bacpy(&d->last_adv_addr, bdaddr); 1342b9a6328fSJohan Hedberg d->last_adv_addr_type = bdaddr_type; 1343ff5cd29fSJohan Hedberg d->last_adv_rssi = rssi; 1344c70a7e4cSMarcel Holtmann d->last_adv_flags = flags; 1345b9a6328fSJohan Hedberg memcpy(d->last_adv_data, data, len); 1346b9a6328fSJohan Hedberg d->last_adv_data_len = len; 1347b9a6328fSJohan Hedberg } 1348b9a6328fSJohan Hedberg 13493baef810SJaganath Kanakkassery static void le_set_scan_enable_complete(struct hci_dev *hdev, u8 enable) 1350eb9d91f5SAndre Guedes { 13515c1a4c8fSJaganath Kanakkassery hci_dev_lock(hdev); 13525c1a4c8fSJaganath Kanakkassery 13533baef810SJaganath Kanakkassery switch (enable) { 13543fd319b8SAndre Guedes case LE_SCAN_ENABLE: 1355a1536da2SMarcel Holtmann hci_dev_set_flag(hdev, HCI_LE_SCAN); 1356b9a6328fSJohan Hedberg if (hdev->le_scan_type == LE_SCAN_ACTIVE) 1357b9a6328fSJohan Hedberg clear_pending_adv_report(hdev); 135868a8aea4SAndrei Emeltchenko break; 135968a8aea4SAndrei Emeltchenko 136076a388beSAndre Guedes case LE_SCAN_DISABLE: 1361b9a6328fSJohan Hedberg /* We do this here instead of when setting DISCOVERY_STOPPED 1362b9a6328fSJohan Hedberg * since the latter would potentially require waiting for 1363b9a6328fSJohan Hedberg * inquiry to stop too. 1364b9a6328fSJohan Hedberg */ 1365b9a6328fSJohan Hedberg if (has_pending_adv_report(hdev)) { 1366b9a6328fSJohan Hedberg struct discovery_state *d = &hdev->discovery; 1367b9a6328fSJohan Hedberg 1368b9a6328fSJohan Hedberg mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK, 1369ab0aa433SJohan Hedberg d->last_adv_addr_type, NULL, 1370c70a7e4cSMarcel Holtmann d->last_adv_rssi, d->last_adv_flags, 1371ab0aa433SJohan Hedberg d->last_adv_data, 1372b9a6328fSJohan Hedberg d->last_adv_data_len, NULL, 0); 1373b9a6328fSJohan Hedberg } 1374b9a6328fSJohan Hedberg 1375317ac8cbSJohan Hedberg /* Cancel this timer so that we don't try to disable scanning 1376317ac8cbSJohan Hedberg * when it's already disabled. 1377317ac8cbSJohan Hedberg */ 1378317ac8cbSJohan Hedberg cancel_delayed_work(&hdev->le_scan_disable); 1379317ac8cbSJohan Hedberg 1380a358dc11SMarcel Holtmann hci_dev_clear_flag(hdev, HCI_LE_SCAN); 1381e8bb6b97SJohan Hedberg 138281ad6fd9SJohan Hedberg /* The HCI_LE_SCAN_INTERRUPTED flag indicates that we 138381ad6fd9SJohan Hedberg * interrupted scanning due to a connect request. Mark 1384e8bb6b97SJohan Hedberg * therefore discovery as stopped. If this was not 1385e8bb6b97SJohan Hedberg * because of a connect request advertising might have 1386e8bb6b97SJohan Hedberg * been disabled because of active scanning, so 1387e8bb6b97SJohan Hedberg * re-enable it again if necessary. 138881ad6fd9SJohan Hedberg */ 1389a69d8927SMarcel Holtmann if (hci_dev_test_and_clear_flag(hdev, HCI_LE_SCAN_INTERRUPTED)) 139081ad6fd9SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 1391d7a5a11dSMarcel Holtmann else if (!hci_dev_test_flag(hdev, HCI_LE_ADV) && 139234722277SJohan Hedberg hdev->discovery.state == DISCOVERY_FINDING) 1393f2252570SJohan Hedberg hci_req_reenable_advertising(hdev); 1394e8bb6b97SJohan Hedberg 139568a8aea4SAndrei Emeltchenko break; 139668a8aea4SAndrei Emeltchenko 139768a8aea4SAndrei Emeltchenko default: 13982064ee33SMarcel Holtmann bt_dev_err(hdev, "use of reserved LE_Scan_Enable param %d", 13993baef810SJaganath Kanakkassery enable); 140068a8aea4SAndrei Emeltchenko break; 140135815085SAndre Guedes } 14025c1a4c8fSJaganath Kanakkassery 14035c1a4c8fSJaganath Kanakkassery hci_dev_unlock(hdev); 1404eb9d91f5SAndre Guedes } 1405eb9d91f5SAndre Guedes 14063baef810SJaganath Kanakkassery static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, 14073baef810SJaganath Kanakkassery struct sk_buff *skb) 14083baef810SJaganath Kanakkassery { 14093baef810SJaganath Kanakkassery struct hci_cp_le_set_scan_enable *cp; 14103baef810SJaganath Kanakkassery __u8 status = *((__u8 *) skb->data); 14113baef810SJaganath Kanakkassery 14123baef810SJaganath Kanakkassery BT_DBG("%s status 0x%2.2x", hdev->name, status); 14133baef810SJaganath Kanakkassery 14143baef810SJaganath Kanakkassery if (status) 14153baef810SJaganath Kanakkassery return; 14163baef810SJaganath Kanakkassery 14173baef810SJaganath Kanakkassery cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE); 14183baef810SJaganath Kanakkassery if (!cp) 14193baef810SJaganath Kanakkassery return; 14203baef810SJaganath Kanakkassery 14213baef810SJaganath Kanakkassery le_set_scan_enable_complete(hdev, cp->enable); 14223baef810SJaganath Kanakkassery } 14233baef810SJaganath Kanakkassery 1424a2344b9eSJaganath Kanakkassery static void hci_cc_le_set_ext_scan_enable(struct hci_dev *hdev, 1425a2344b9eSJaganath Kanakkassery struct sk_buff *skb) 1426a2344b9eSJaganath Kanakkassery { 1427a2344b9eSJaganath Kanakkassery struct hci_cp_le_set_ext_scan_enable *cp; 1428a2344b9eSJaganath Kanakkassery __u8 status = *((__u8 *) skb->data); 1429a2344b9eSJaganath Kanakkassery 1430a2344b9eSJaganath Kanakkassery BT_DBG("%s status 0x%2.2x", hdev->name, status); 1431a2344b9eSJaganath Kanakkassery 1432a2344b9eSJaganath Kanakkassery if (status) 1433a2344b9eSJaganath Kanakkassery return; 1434a2344b9eSJaganath Kanakkassery 1435a2344b9eSJaganath Kanakkassery cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_SCAN_ENABLE); 1436a2344b9eSJaganath Kanakkassery if (!cp) 1437a2344b9eSJaganath Kanakkassery return; 1438a2344b9eSJaganath Kanakkassery 1439a2344b9eSJaganath Kanakkassery le_set_scan_enable_complete(hdev, cp->enable); 1440a2344b9eSJaganath Kanakkassery } 1441a2344b9eSJaganath Kanakkassery 14426b49bcb4SJaganath Kanakkassery static void hci_cc_le_read_num_adv_sets(struct hci_dev *hdev, 14436b49bcb4SJaganath Kanakkassery struct sk_buff *skb) 14446b49bcb4SJaganath Kanakkassery { 14456b49bcb4SJaganath Kanakkassery struct hci_rp_le_read_num_supported_adv_sets *rp = (void *) skb->data; 14466b49bcb4SJaganath Kanakkassery 14476b49bcb4SJaganath Kanakkassery BT_DBG("%s status 0x%2.2x No of Adv sets %u", hdev->name, rp->status, 14486b49bcb4SJaganath Kanakkassery rp->num_of_sets); 14496b49bcb4SJaganath Kanakkassery 14506b49bcb4SJaganath Kanakkassery if (rp->status) 14516b49bcb4SJaganath Kanakkassery return; 14526b49bcb4SJaganath Kanakkassery 14536b49bcb4SJaganath Kanakkassery hdev->le_num_of_adv_sets = rp->num_of_sets; 14546b49bcb4SJaganath Kanakkassery } 14556b49bcb4SJaganath Kanakkassery 1456cf1d081fSJohan Hedberg static void hci_cc_le_read_white_list_size(struct hci_dev *hdev, 1457cf1d081fSJohan Hedberg struct sk_buff *skb) 1458cf1d081fSJohan Hedberg { 1459cf1d081fSJohan Hedberg struct hci_rp_le_read_white_list_size *rp = (void *) skb->data; 1460cf1d081fSJohan Hedberg 1461cf1d081fSJohan Hedberg BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size); 1462cf1d081fSJohan Hedberg 146345296acdSMarcel Holtmann if (rp->status) 146445296acdSMarcel Holtmann return; 146545296acdSMarcel Holtmann 1466cf1d081fSJohan Hedberg hdev->le_white_list_size = rp->size; 1467cf1d081fSJohan Hedberg } 1468cf1d081fSJohan Hedberg 14690f36b589SMarcel Holtmann static void hci_cc_le_clear_white_list(struct hci_dev *hdev, 14700f36b589SMarcel Holtmann struct sk_buff *skb) 14710f36b589SMarcel Holtmann { 14720f36b589SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 14730f36b589SMarcel Holtmann 14740f36b589SMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, status); 14750f36b589SMarcel Holtmann 147645296acdSMarcel Holtmann if (status) 147745296acdSMarcel Holtmann return; 147845296acdSMarcel Holtmann 1479dcc36c16SJohan Hedberg hci_bdaddr_list_clear(&hdev->le_white_list); 14800f36b589SMarcel Holtmann } 14810f36b589SMarcel Holtmann 14820f36b589SMarcel Holtmann static void hci_cc_le_add_to_white_list(struct hci_dev *hdev, 14830f36b589SMarcel Holtmann struct sk_buff *skb) 14840f36b589SMarcel Holtmann { 14850f36b589SMarcel Holtmann struct hci_cp_le_add_to_white_list *sent; 14860f36b589SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 14870f36b589SMarcel Holtmann 14880f36b589SMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, status); 14890f36b589SMarcel Holtmann 149045296acdSMarcel Holtmann if (status) 149145296acdSMarcel Holtmann return; 149245296acdSMarcel Holtmann 14930f36b589SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_WHITE_LIST); 14940f36b589SMarcel Holtmann if (!sent) 14950f36b589SMarcel Holtmann return; 14960f36b589SMarcel Holtmann 1497dcc36c16SJohan Hedberg hci_bdaddr_list_add(&hdev->le_white_list, &sent->bdaddr, 1498dcc36c16SJohan Hedberg sent->bdaddr_type); 14990f36b589SMarcel Holtmann } 15000f36b589SMarcel Holtmann 15010f36b589SMarcel Holtmann static void hci_cc_le_del_from_white_list(struct hci_dev *hdev, 15020f36b589SMarcel Holtmann struct sk_buff *skb) 15030f36b589SMarcel Holtmann { 15040f36b589SMarcel Holtmann struct hci_cp_le_del_from_white_list *sent; 15050f36b589SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 15060f36b589SMarcel Holtmann 15070f36b589SMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, status); 15080f36b589SMarcel Holtmann 150945296acdSMarcel Holtmann if (status) 151045296acdSMarcel Holtmann return; 151145296acdSMarcel Holtmann 15120f36b589SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_LE_DEL_FROM_WHITE_LIST); 15130f36b589SMarcel Holtmann if (!sent) 15140f36b589SMarcel Holtmann return; 15150f36b589SMarcel Holtmann 1516dcc36c16SJohan Hedberg hci_bdaddr_list_del(&hdev->le_white_list, &sent->bdaddr, 1517dcc36c16SJohan Hedberg sent->bdaddr_type); 15180f36b589SMarcel Holtmann } 15190f36b589SMarcel Holtmann 15209b008c04SJohan Hedberg static void hci_cc_le_read_supported_states(struct hci_dev *hdev, 15219b008c04SJohan Hedberg struct sk_buff *skb) 15229b008c04SJohan Hedberg { 15239b008c04SJohan Hedberg struct hci_rp_le_read_supported_states *rp = (void *) skb->data; 15249b008c04SJohan Hedberg 15259b008c04SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 15269b008c04SJohan Hedberg 152745296acdSMarcel Holtmann if (rp->status) 152845296acdSMarcel Holtmann return; 152945296acdSMarcel Holtmann 15309b008c04SJohan Hedberg memcpy(hdev->le_states, rp->le_states, 8); 15319b008c04SJohan Hedberg } 15329b008c04SJohan Hedberg 1533a8e1bfaaSMarcel Holtmann static void hci_cc_le_read_def_data_len(struct hci_dev *hdev, 1534a8e1bfaaSMarcel Holtmann struct sk_buff *skb) 1535a8e1bfaaSMarcel Holtmann { 1536a8e1bfaaSMarcel Holtmann struct hci_rp_le_read_def_data_len *rp = (void *) skb->data; 1537a8e1bfaaSMarcel Holtmann 1538a8e1bfaaSMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1539a8e1bfaaSMarcel Holtmann 1540a8e1bfaaSMarcel Holtmann if (rp->status) 1541a8e1bfaaSMarcel Holtmann return; 1542a8e1bfaaSMarcel Holtmann 1543a8e1bfaaSMarcel Holtmann hdev->le_def_tx_len = le16_to_cpu(rp->tx_len); 1544a8e1bfaaSMarcel Holtmann hdev->le_def_tx_time = le16_to_cpu(rp->tx_time); 1545a8e1bfaaSMarcel Holtmann } 1546a8e1bfaaSMarcel Holtmann 1547a8e1bfaaSMarcel Holtmann static void hci_cc_le_write_def_data_len(struct hci_dev *hdev, 1548a8e1bfaaSMarcel Holtmann struct sk_buff *skb) 1549a8e1bfaaSMarcel Holtmann { 1550a8e1bfaaSMarcel Holtmann struct hci_cp_le_write_def_data_len *sent; 1551a8e1bfaaSMarcel Holtmann __u8 status = *((__u8 *) skb->data); 1552a8e1bfaaSMarcel Holtmann 1553a8e1bfaaSMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, status); 1554a8e1bfaaSMarcel Holtmann 1555a8e1bfaaSMarcel Holtmann if (status) 1556a8e1bfaaSMarcel Holtmann return; 1557a8e1bfaaSMarcel Holtmann 1558a8e1bfaaSMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_LE_WRITE_DEF_DATA_LEN); 1559a8e1bfaaSMarcel Holtmann if (!sent) 1560a8e1bfaaSMarcel Holtmann return; 1561a8e1bfaaSMarcel Holtmann 1562a8e1bfaaSMarcel Holtmann hdev->le_def_tx_len = le16_to_cpu(sent->tx_len); 1563a8e1bfaaSMarcel Holtmann hdev->le_def_tx_time = le16_to_cpu(sent->tx_time); 1564a8e1bfaaSMarcel Holtmann } 1565a8e1bfaaSMarcel Holtmann 1566b950aa88SAnkit Navik static void hci_cc_le_add_to_resolv_list(struct hci_dev *hdev, 1567b950aa88SAnkit Navik struct sk_buff *skb) 1568b950aa88SAnkit Navik { 1569b950aa88SAnkit Navik struct hci_cp_le_add_to_resolv_list *sent; 1570b950aa88SAnkit Navik __u8 status = *((__u8 *) skb->data); 1571b950aa88SAnkit Navik 1572b950aa88SAnkit Navik BT_DBG("%s status 0x%2.2x", hdev->name, status); 1573b950aa88SAnkit Navik 1574b950aa88SAnkit Navik if (status) 1575b950aa88SAnkit Navik return; 1576b950aa88SAnkit Navik 1577b950aa88SAnkit Navik sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_RESOLV_LIST); 1578b950aa88SAnkit Navik if (!sent) 1579b950aa88SAnkit Navik return; 1580b950aa88SAnkit Navik 1581b950aa88SAnkit Navik hci_bdaddr_list_add_with_irk(&hdev->le_resolv_list, &sent->bdaddr, 1582b950aa88SAnkit Navik sent->bdaddr_type, sent->peer_irk, 1583b950aa88SAnkit Navik sent->local_irk); 1584b950aa88SAnkit Navik } 1585b950aa88SAnkit Navik 1586b950aa88SAnkit Navik static void hci_cc_le_del_from_resolv_list(struct hci_dev *hdev, 1587b950aa88SAnkit Navik struct sk_buff *skb) 1588b950aa88SAnkit Navik { 1589b950aa88SAnkit Navik struct hci_cp_le_del_from_resolv_list *sent; 1590b950aa88SAnkit Navik __u8 status = *((__u8 *) skb->data); 1591b950aa88SAnkit Navik 1592b950aa88SAnkit Navik BT_DBG("%s status 0x%2.2x", hdev->name, status); 1593b950aa88SAnkit Navik 1594b950aa88SAnkit Navik if (status) 1595b950aa88SAnkit Navik return; 1596b950aa88SAnkit Navik 1597b950aa88SAnkit Navik sent = hci_sent_cmd_data(hdev, HCI_OP_LE_DEL_FROM_RESOLV_LIST); 1598b950aa88SAnkit Navik if (!sent) 1599b950aa88SAnkit Navik return; 1600b950aa88SAnkit Navik 1601b950aa88SAnkit Navik hci_bdaddr_list_del_with_irk(&hdev->le_resolv_list, &sent->bdaddr, 1602b950aa88SAnkit Navik sent->bdaddr_type); 1603b950aa88SAnkit Navik } 1604b950aa88SAnkit Navik 1605545f2596SAnkit Navik static void hci_cc_le_clear_resolv_list(struct hci_dev *hdev, 1606545f2596SAnkit Navik struct sk_buff *skb) 1607545f2596SAnkit Navik { 1608545f2596SAnkit Navik __u8 status = *((__u8 *) skb->data); 1609545f2596SAnkit Navik 1610545f2596SAnkit Navik BT_DBG("%s status 0x%2.2x", hdev->name, status); 1611545f2596SAnkit Navik 1612545f2596SAnkit Navik if (status) 1613545f2596SAnkit Navik return; 1614545f2596SAnkit Navik 1615545f2596SAnkit Navik hci_bdaddr_list_clear(&hdev->le_resolv_list); 1616545f2596SAnkit Navik } 1617545f2596SAnkit Navik 1618cfdb0c2dSAnkit Navik static void hci_cc_le_read_resolv_list_size(struct hci_dev *hdev, 1619cfdb0c2dSAnkit Navik struct sk_buff *skb) 1620cfdb0c2dSAnkit Navik { 1621cfdb0c2dSAnkit Navik struct hci_rp_le_read_resolv_list_size *rp = (void *) skb->data; 1622cfdb0c2dSAnkit Navik 1623cfdb0c2dSAnkit Navik BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size); 1624cfdb0c2dSAnkit Navik 1625cfdb0c2dSAnkit Navik if (rp->status) 1626cfdb0c2dSAnkit Navik return; 1627cfdb0c2dSAnkit Navik 1628cfdb0c2dSAnkit Navik hdev->le_resolv_list_size = rp->size; 1629cfdb0c2dSAnkit Navik } 1630cfdb0c2dSAnkit Navik 1631aa12af77SAnkit Navik static void hci_cc_le_set_addr_resolution_enable(struct hci_dev *hdev, 1632aa12af77SAnkit Navik struct sk_buff *skb) 1633aa12af77SAnkit Navik { 1634aa12af77SAnkit Navik __u8 *sent, status = *((__u8 *) skb->data); 1635aa12af77SAnkit Navik 1636aa12af77SAnkit Navik BT_DBG("%s status 0x%2.2x", hdev->name, status); 1637aa12af77SAnkit Navik 1638aa12af77SAnkit Navik if (status) 1639aa12af77SAnkit Navik return; 1640aa12af77SAnkit Navik 1641aa12af77SAnkit Navik sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADDR_RESOLV_ENABLE); 1642aa12af77SAnkit Navik if (!sent) 1643aa12af77SAnkit Navik return; 1644aa12af77SAnkit Navik 1645aa12af77SAnkit Navik hci_dev_lock(hdev); 1646aa12af77SAnkit Navik 1647aa12af77SAnkit Navik if (*sent) 1648aa12af77SAnkit Navik hci_dev_set_flag(hdev, HCI_LL_RPA_RESOLUTION); 1649aa12af77SAnkit Navik else 1650aa12af77SAnkit Navik hci_dev_clear_flag(hdev, HCI_LL_RPA_RESOLUTION); 1651aa12af77SAnkit Navik 1652aa12af77SAnkit Navik hci_dev_unlock(hdev); 1653aa12af77SAnkit Navik } 1654aa12af77SAnkit Navik 1655a8e1bfaaSMarcel Holtmann static void hci_cc_le_read_max_data_len(struct hci_dev *hdev, 1656a8e1bfaaSMarcel Holtmann struct sk_buff *skb) 1657a8e1bfaaSMarcel Holtmann { 1658a8e1bfaaSMarcel Holtmann struct hci_rp_le_read_max_data_len *rp = (void *) skb->data; 1659a8e1bfaaSMarcel Holtmann 1660a8e1bfaaSMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1661a8e1bfaaSMarcel Holtmann 1662a8e1bfaaSMarcel Holtmann if (rp->status) 1663a8e1bfaaSMarcel Holtmann return; 1664a8e1bfaaSMarcel Holtmann 1665a8e1bfaaSMarcel Holtmann hdev->le_max_tx_len = le16_to_cpu(rp->tx_len); 1666a8e1bfaaSMarcel Holtmann hdev->le_max_tx_time = le16_to_cpu(rp->tx_time); 1667a8e1bfaaSMarcel Holtmann hdev->le_max_rx_len = le16_to_cpu(rp->rx_len); 1668a8e1bfaaSMarcel Holtmann hdev->le_max_rx_time = le16_to_cpu(rp->rx_time); 1669a8e1bfaaSMarcel Holtmann } 1670a8e1bfaaSMarcel Holtmann 16716039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev, 1672f9b49306SAndre Guedes struct sk_buff *skb) 1673f9b49306SAndre Guedes { 167406199cf8SJohan Hedberg struct hci_cp_write_le_host_supported *sent; 1675f9b49306SAndre Guedes __u8 status = *((__u8 *) skb->data); 1676f9b49306SAndre Guedes 16779f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1678f9b49306SAndre Guedes 167945296acdSMarcel Holtmann if (status) 168045296acdSMarcel Holtmann return; 168145296acdSMarcel Holtmann 168206199cf8SJohan Hedberg sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED); 16838f984dfaSJohan Hedberg if (!sent) 1684f9b49306SAndre Guedes return; 1685f9b49306SAndre Guedes 16865c1a4c8fSJaganath Kanakkassery hci_dev_lock(hdev); 16875c1a4c8fSJaganath Kanakkassery 1688416a4ae5SJohan Hedberg if (sent->le) { 1689cad718edSJohan Hedberg hdev->features[1][0] |= LMP_HOST_LE; 1690a1536da2SMarcel Holtmann hci_dev_set_flag(hdev, HCI_LE_ENABLED); 1691416a4ae5SJohan Hedberg } else { 1692cad718edSJohan Hedberg hdev->features[1][0] &= ~LMP_HOST_LE; 1693a358dc11SMarcel Holtmann hci_dev_clear_flag(hdev, HCI_LE_ENABLED); 1694a358dc11SMarcel Holtmann hci_dev_clear_flag(hdev, HCI_ADVERTISING); 1695416a4ae5SJohan Hedberg } 169653b2caabSJohan Hedberg 169753b2caabSJohan Hedberg if (sent->simul) 1698cad718edSJohan Hedberg hdev->features[1][0] |= LMP_HOST_LE_BREDR; 169953b2caabSJohan Hedberg else 1700cad718edSJohan Hedberg hdev->features[1][0] &= ~LMP_HOST_LE_BREDR; 17015c1a4c8fSJaganath Kanakkassery 17025c1a4c8fSJaganath Kanakkassery hci_dev_unlock(hdev); 17038f984dfaSJohan Hedberg } 1704f9b49306SAndre Guedes 170556ed2cb8SJohan Hedberg static void hci_cc_set_adv_param(struct hci_dev *hdev, struct sk_buff *skb) 170656ed2cb8SJohan Hedberg { 170756ed2cb8SJohan Hedberg struct hci_cp_le_set_adv_param *cp; 170856ed2cb8SJohan Hedberg u8 status = *((u8 *) skb->data); 170956ed2cb8SJohan Hedberg 171056ed2cb8SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 171156ed2cb8SJohan Hedberg 171256ed2cb8SJohan Hedberg if (status) 171356ed2cb8SJohan Hedberg return; 171456ed2cb8SJohan Hedberg 171556ed2cb8SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_PARAM); 171656ed2cb8SJohan Hedberg if (!cp) 171756ed2cb8SJohan Hedberg return; 171856ed2cb8SJohan Hedberg 171956ed2cb8SJohan Hedberg hci_dev_lock(hdev); 172056ed2cb8SJohan Hedberg hdev->adv_addr_type = cp->own_address_type; 172156ed2cb8SJohan Hedberg hci_dev_unlock(hdev); 172256ed2cb8SJohan Hedberg } 172356ed2cb8SJohan Hedberg 1724de181e88SJaganath Kanakkassery static void hci_cc_set_ext_adv_param(struct hci_dev *hdev, struct sk_buff *skb) 1725de181e88SJaganath Kanakkassery { 1726de181e88SJaganath Kanakkassery struct hci_rp_le_set_ext_adv_params *rp = (void *) skb->data; 1727de181e88SJaganath Kanakkassery struct hci_cp_le_set_ext_adv_params *cp; 1728de181e88SJaganath Kanakkassery struct adv_info *adv_instance; 1729de181e88SJaganath Kanakkassery 1730de181e88SJaganath Kanakkassery BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1731de181e88SJaganath Kanakkassery 1732de181e88SJaganath Kanakkassery if (rp->status) 1733de181e88SJaganath Kanakkassery return; 1734de181e88SJaganath Kanakkassery 1735de181e88SJaganath Kanakkassery cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_ADV_PARAMS); 1736de181e88SJaganath Kanakkassery if (!cp) 1737de181e88SJaganath Kanakkassery return; 1738de181e88SJaganath Kanakkassery 1739de181e88SJaganath Kanakkassery hci_dev_lock(hdev); 1740de181e88SJaganath Kanakkassery hdev->adv_addr_type = cp->own_addr_type; 1741de181e88SJaganath Kanakkassery if (!hdev->cur_adv_instance) { 1742de181e88SJaganath Kanakkassery /* Store in hdev for instance 0 */ 1743de181e88SJaganath Kanakkassery hdev->adv_tx_power = rp->tx_power; 1744de181e88SJaganath Kanakkassery } else { 1745de181e88SJaganath Kanakkassery adv_instance = hci_find_adv_instance(hdev, 1746de181e88SJaganath Kanakkassery hdev->cur_adv_instance); 1747de181e88SJaganath Kanakkassery if (adv_instance) 1748de181e88SJaganath Kanakkassery adv_instance->tx_power = rp->tx_power; 1749de181e88SJaganath Kanakkassery } 1750a0fb3726SJaganath Kanakkassery /* Update adv data as tx power is known now */ 1751a0fb3726SJaganath Kanakkassery hci_req_update_adv_data(hdev, hdev->cur_adv_instance); 1752de181e88SJaganath Kanakkassery hci_dev_unlock(hdev); 1753de181e88SJaganath Kanakkassery } 1754de181e88SJaganath Kanakkassery 17555ae76a94SAndrzej Kaczmarek static void hci_cc_read_rssi(struct hci_dev *hdev, struct sk_buff *skb) 17565ae76a94SAndrzej Kaczmarek { 17575ae76a94SAndrzej Kaczmarek struct hci_rp_read_rssi *rp = (void *) skb->data; 17585ae76a94SAndrzej Kaczmarek struct hci_conn *conn; 17595ae76a94SAndrzej Kaczmarek 17605ae76a94SAndrzej Kaczmarek BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 17615ae76a94SAndrzej Kaczmarek 17625ae76a94SAndrzej Kaczmarek if (rp->status) 17635ae76a94SAndrzej Kaczmarek return; 17645ae76a94SAndrzej Kaczmarek 17655ae76a94SAndrzej Kaczmarek hci_dev_lock(hdev); 17665ae76a94SAndrzej Kaczmarek 17675ae76a94SAndrzej Kaczmarek conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 17685ae76a94SAndrzej Kaczmarek if (conn) 17695ae76a94SAndrzej Kaczmarek conn->rssi = rp->rssi; 17705ae76a94SAndrzej Kaczmarek 17715ae76a94SAndrzej Kaczmarek hci_dev_unlock(hdev); 17725ae76a94SAndrzej Kaczmarek } 17735ae76a94SAndrzej Kaczmarek 17745a134faeSAndrzej Kaczmarek static void hci_cc_read_tx_power(struct hci_dev *hdev, struct sk_buff *skb) 17755a134faeSAndrzej Kaczmarek { 17765a134faeSAndrzej Kaczmarek struct hci_cp_read_tx_power *sent; 17775a134faeSAndrzej Kaczmarek struct hci_rp_read_tx_power *rp = (void *) skb->data; 17785a134faeSAndrzej Kaczmarek struct hci_conn *conn; 17795a134faeSAndrzej Kaczmarek 17805a134faeSAndrzej Kaczmarek BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 17815a134faeSAndrzej Kaczmarek 17825a134faeSAndrzej Kaczmarek if (rp->status) 17835a134faeSAndrzej Kaczmarek return; 17845a134faeSAndrzej Kaczmarek 17855a134faeSAndrzej Kaczmarek sent = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER); 17865a134faeSAndrzej Kaczmarek if (!sent) 17875a134faeSAndrzej Kaczmarek return; 17885a134faeSAndrzej Kaczmarek 17895a134faeSAndrzej Kaczmarek hci_dev_lock(hdev); 17905a134faeSAndrzej Kaczmarek 17915a134faeSAndrzej Kaczmarek conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 1792d0455ed9SAndrzej Kaczmarek if (!conn) 1793d0455ed9SAndrzej Kaczmarek goto unlock; 17945a134faeSAndrzej Kaczmarek 1795d0455ed9SAndrzej Kaczmarek switch (sent->type) { 1796d0455ed9SAndrzej Kaczmarek case 0x00: 1797d0455ed9SAndrzej Kaczmarek conn->tx_power = rp->tx_power; 1798d0455ed9SAndrzej Kaczmarek break; 1799d0455ed9SAndrzej Kaczmarek case 0x01: 1800d0455ed9SAndrzej Kaczmarek conn->max_tx_power = rp->tx_power; 1801d0455ed9SAndrzej Kaczmarek break; 1802d0455ed9SAndrzej Kaczmarek } 1803d0455ed9SAndrzej Kaczmarek 1804d0455ed9SAndrzej Kaczmarek unlock: 18055a134faeSAndrzej Kaczmarek hci_dev_unlock(hdev); 18065a134faeSAndrzej Kaczmarek } 18075a134faeSAndrzej Kaczmarek 1808c50b33c8SMarcel Holtmann static void hci_cc_write_ssp_debug_mode(struct hci_dev *hdev, struct sk_buff *skb) 1809c50b33c8SMarcel Holtmann { 1810c50b33c8SMarcel Holtmann u8 status = *((u8 *) skb->data); 1811c50b33c8SMarcel Holtmann u8 *mode; 1812c50b33c8SMarcel Holtmann 1813c50b33c8SMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, status); 1814c50b33c8SMarcel Holtmann 1815c50b33c8SMarcel Holtmann if (status) 1816c50b33c8SMarcel Holtmann return; 1817c50b33c8SMarcel Holtmann 1818c50b33c8SMarcel Holtmann mode = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE); 1819c50b33c8SMarcel Holtmann if (mode) 1820c50b33c8SMarcel Holtmann hdev->ssp_debug_mode = *mode; 1821c50b33c8SMarcel Holtmann } 1822c50b33c8SMarcel Holtmann 18236039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 1824a9de9248SMarcel Holtmann { 18259f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1826a9de9248SMarcel Holtmann 1827a9de9248SMarcel Holtmann if (status) { 1828a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 1829314b2381SJohan Hedberg return; 1830314b2381SJohan Hedberg } 1831314b2381SJohan Hedberg 183289352e7dSAndre Guedes set_bit(HCI_INQUIRY, &hdev->flags); 1833a9de9248SMarcel Holtmann } 1834a9de9248SMarcel Holtmann 18356039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 18361da177e4SLinus Torvalds { 1837a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 18381da177e4SLinus Torvalds struct hci_conn *conn; 18391da177e4SLinus Torvalds 18409f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1841a9de9248SMarcel Holtmann 1842a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 18431da177e4SLinus Torvalds if (!cp) 18441da177e4SLinus Torvalds return; 18451da177e4SLinus Torvalds 18461da177e4SLinus Torvalds hci_dev_lock(hdev); 18471da177e4SLinus Torvalds 18481da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 18491da177e4SLinus Torvalds 18506ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn); 18511da177e4SLinus Torvalds 18521da177e4SLinus Torvalds if (status) { 18531da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 18544c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 18551da177e4SLinus Torvalds conn->state = BT_CLOSED; 1856539c496dSJohan Hedberg hci_connect_cfm(conn, status); 18571da177e4SLinus Torvalds hci_conn_del(conn); 18584c67bc74SMarcel Holtmann } else 18594c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 18601da177e4SLinus Torvalds } 18611da177e4SLinus Torvalds } else { 18621da177e4SLinus Torvalds if (!conn) { 1863a5c4e309SJohan Hedberg conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr, 1864a5c4e309SJohan Hedberg HCI_ROLE_MASTER); 1865a5c4e309SJohan Hedberg if (!conn) 18662064ee33SMarcel Holtmann bt_dev_err(hdev, "no memory for new connection"); 18671da177e4SLinus Torvalds } 18681da177e4SLinus Torvalds } 18691da177e4SLinus Torvalds 18701da177e4SLinus Torvalds hci_dev_unlock(hdev); 18711da177e4SLinus Torvalds } 18721da177e4SLinus Torvalds 1873a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 18741da177e4SLinus Torvalds { 1875a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 18761da177e4SLinus Torvalds struct hci_conn *acl, *sco; 18771da177e4SLinus Torvalds __u16 handle; 18781da177e4SLinus Torvalds 18799f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1880b6a0dc82SMarcel Holtmann 1881a9de9248SMarcel Holtmann if (!status) 1882a9de9248SMarcel Holtmann return; 1883a9de9248SMarcel Holtmann 1884a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 18851da177e4SLinus Torvalds if (!cp) 1886a9de9248SMarcel Holtmann return; 18871da177e4SLinus Torvalds 18881da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 18891da177e4SLinus Torvalds 18909f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, handle); 18911da177e4SLinus Torvalds 18921da177e4SLinus Torvalds hci_dev_lock(hdev); 18931da177e4SLinus Torvalds 18941da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 18955a08ecceSAndrei Emeltchenko if (acl) { 18965a08ecceSAndrei Emeltchenko sco = acl->link; 18975a08ecceSAndrei Emeltchenko if (sco) { 18981da177e4SLinus Torvalds sco->state = BT_CLOSED; 18991da177e4SLinus Torvalds 1900539c496dSJohan Hedberg hci_connect_cfm(sco, status); 19011da177e4SLinus Torvalds hci_conn_del(sco); 19021da177e4SLinus Torvalds } 19035a08ecceSAndrei Emeltchenko } 19041da177e4SLinus Torvalds 19051da177e4SLinus Torvalds hci_dev_unlock(hdev); 19061da177e4SLinus Torvalds } 19071da177e4SLinus Torvalds 1908f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 1909f8558555SMarcel Holtmann { 1910f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 1911f8558555SMarcel Holtmann struct hci_conn *conn; 1912f8558555SMarcel Holtmann 19139f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1914f8558555SMarcel Holtmann 1915f8558555SMarcel Holtmann if (!status) 1916f8558555SMarcel Holtmann return; 1917f8558555SMarcel Holtmann 1918f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 1919f8558555SMarcel Holtmann if (!cp) 1920f8558555SMarcel Holtmann return; 1921f8558555SMarcel Holtmann 1922f8558555SMarcel Holtmann hci_dev_lock(hdev); 1923f8558555SMarcel Holtmann 1924f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1925f8558555SMarcel Holtmann if (conn) { 1926f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1927539c496dSJohan Hedberg hci_connect_cfm(conn, status); 192876a68ba0SDavid Herrmann hci_conn_drop(conn); 1929f8558555SMarcel Holtmann } 1930f8558555SMarcel Holtmann } 1931f8558555SMarcel Holtmann 1932f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1933f8558555SMarcel Holtmann } 1934f8558555SMarcel Holtmann 1935f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 1936f8558555SMarcel Holtmann { 1937f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 1938f8558555SMarcel Holtmann struct hci_conn *conn; 1939f8558555SMarcel Holtmann 19409f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1941f8558555SMarcel Holtmann 1942f8558555SMarcel Holtmann if (!status) 1943f8558555SMarcel Holtmann return; 1944f8558555SMarcel Holtmann 1945f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 1946f8558555SMarcel Holtmann if (!cp) 1947f8558555SMarcel Holtmann return; 1948f8558555SMarcel Holtmann 1949f8558555SMarcel Holtmann hci_dev_lock(hdev); 1950f8558555SMarcel Holtmann 1951f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1952f8558555SMarcel Holtmann if (conn) { 1953f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1954539c496dSJohan Hedberg hci_connect_cfm(conn, status); 195576a68ba0SDavid Herrmann hci_conn_drop(conn); 1956f8558555SMarcel Holtmann } 1957f8558555SMarcel Holtmann } 1958f8558555SMarcel Holtmann 1959f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1960f8558555SMarcel Holtmann } 1961f8558555SMarcel Holtmann 1962127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev, 1963392599b9SJohan Hedberg struct hci_conn *conn) 1964392599b9SJohan Hedberg { 1965392599b9SJohan Hedberg if (conn->state != BT_CONFIG || !conn->out) 1966392599b9SJohan Hedberg return 0; 1967392599b9SJohan Hedberg 1968765c2a96SJohan Hedberg if (conn->pending_sec_level == BT_SECURITY_SDP) 1969392599b9SJohan Hedberg return 0; 1970392599b9SJohan Hedberg 1971392599b9SJohan Hedberg /* Only request authentication for SSP connections or non-SSP 1972264b8b4eSJohan Hedberg * devices with sec_level MEDIUM or HIGH or if MITM protection 1973264b8b4eSJohan Hedberg * is requested. 1974264b8b4eSJohan Hedberg */ 1975807deac2SGustavo Padovan if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) && 19767e3691e1SJohan Hedberg conn->pending_sec_level != BT_SECURITY_FIPS && 1977264b8b4eSJohan Hedberg conn->pending_sec_level != BT_SECURITY_HIGH && 1978264b8b4eSJohan Hedberg conn->pending_sec_level != BT_SECURITY_MEDIUM) 1979392599b9SJohan Hedberg return 0; 1980392599b9SJohan Hedberg 1981392599b9SJohan Hedberg return 1; 1982392599b9SJohan Hedberg } 1983392599b9SJohan Hedberg 19846039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev, 198500abfe44SGustavo F. Padovan struct inquiry_entry *e) 198630dc78e1SJohan Hedberg { 198730dc78e1SJohan Hedberg struct hci_cp_remote_name_req cp; 198830dc78e1SJohan Hedberg 198930dc78e1SJohan Hedberg memset(&cp, 0, sizeof(cp)); 199030dc78e1SJohan Hedberg 199130dc78e1SJohan Hedberg bacpy(&cp.bdaddr, &e->data.bdaddr); 199230dc78e1SJohan Hedberg cp.pscan_rep_mode = e->data.pscan_rep_mode; 199330dc78e1SJohan Hedberg cp.pscan_mode = e->data.pscan_mode; 199430dc78e1SJohan Hedberg cp.clock_offset = e->data.clock_offset; 199530dc78e1SJohan Hedberg 199630dc78e1SJohan Hedberg return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 199730dc78e1SJohan Hedberg } 199830dc78e1SJohan Hedberg 1999b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev) 200030dc78e1SJohan Hedberg { 200130dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 200230dc78e1SJohan Hedberg struct inquiry_entry *e; 200330dc78e1SJohan Hedberg 2004b644ba33SJohan Hedberg if (list_empty(&discov->resolve)) 2005b644ba33SJohan Hedberg return false; 2006b644ba33SJohan Hedberg 2007b644ba33SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 2008c810089cSRam Malovany if (!e) 2009c810089cSRam Malovany return false; 2010c810089cSRam Malovany 2011b644ba33SJohan Hedberg if (hci_resolve_name(hdev, e) == 0) { 2012b644ba33SJohan Hedberg e->name_state = NAME_PENDING; 2013b644ba33SJohan Hedberg return true; 2014b644ba33SJohan Hedberg } 2015b644ba33SJohan Hedberg 2016b644ba33SJohan Hedberg return false; 2017b644ba33SJohan Hedberg } 2018b644ba33SJohan Hedberg 2019b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn, 2020b644ba33SJohan Hedberg bdaddr_t *bdaddr, u8 *name, u8 name_len) 2021b644ba33SJohan Hedberg { 2022b644ba33SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 2023b644ba33SJohan Hedberg struct inquiry_entry *e; 2024b644ba33SJohan Hedberg 202560cb49d2SJohan Hedberg /* Update the mgmt connected state if necessary. Be careful with 202660cb49d2SJohan Hedberg * conn objects that exist but are not (yet) connected however. 202760cb49d2SJohan Hedberg * Only those in BT_CONFIG or BT_CONNECTED states can be 202860cb49d2SJohan Hedberg * considered connected. 202960cb49d2SJohan Hedberg */ 203060cb49d2SJohan Hedberg if (conn && 203160cb49d2SJohan Hedberg (conn->state == BT_CONFIG || conn->state == BT_CONNECTED) && 2032cb77c3ecSJaganath Kanakkassery !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 203348ec92faSAlfonso Acosta mgmt_device_connected(hdev, conn, 0, name, name_len); 2034b644ba33SJohan Hedberg 2035b644ba33SJohan Hedberg if (discov->state == DISCOVERY_STOPPED) 2036b644ba33SJohan Hedberg return; 2037b644ba33SJohan Hedberg 203830dc78e1SJohan Hedberg if (discov->state == DISCOVERY_STOPPING) 203930dc78e1SJohan Hedberg goto discov_complete; 204030dc78e1SJohan Hedberg 204130dc78e1SJohan Hedberg if (discov->state != DISCOVERY_RESOLVING) 204230dc78e1SJohan Hedberg return; 204330dc78e1SJohan Hedberg 204430dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING); 20457cc8380eSRam Malovany /* If the device was not found in a list of found devices names of which 20467cc8380eSRam Malovany * are pending. there is no need to continue resolving a next name as it 20477cc8380eSRam Malovany * will be done upon receiving another Remote Name Request Complete 20487cc8380eSRam Malovany * Event */ 20497cc8380eSRam Malovany if (!e) 20507cc8380eSRam Malovany return; 20517cc8380eSRam Malovany 205230dc78e1SJohan Hedberg list_del(&e->list); 20537cc8380eSRam Malovany if (name) { 20547cc8380eSRam Malovany e->name_state = NAME_KNOWN; 2055b644ba33SJohan Hedberg mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, 2056b644ba33SJohan Hedberg e->data.rssi, name, name_len); 2057c3e7c0d9SRam Malovany } else { 2058c3e7c0d9SRam Malovany e->name_state = NAME_NOT_KNOWN; 205930dc78e1SJohan Hedberg } 206030dc78e1SJohan Hedberg 2061b644ba33SJohan Hedberg if (hci_resolve_next_name(hdev)) 206230dc78e1SJohan Hedberg return; 206330dc78e1SJohan Hedberg 206430dc78e1SJohan Hedberg discov_complete: 206530dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 206630dc78e1SJohan Hedberg } 206730dc78e1SJohan Hedberg 2068a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 20691da177e4SLinus Torvalds { 2070127178d2SJohan Hedberg struct hci_cp_remote_name_req *cp; 2071127178d2SJohan Hedberg struct hci_conn *conn; 2072127178d2SJohan Hedberg 20739f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 2074127178d2SJohan Hedberg 2075127178d2SJohan Hedberg /* If successful wait for the name req complete event before 2076127178d2SJohan Hedberg * checking for the need to do authentication */ 2077127178d2SJohan Hedberg if (!status) 2078127178d2SJohan Hedberg return; 2079127178d2SJohan Hedberg 2080127178d2SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); 2081127178d2SJohan Hedberg if (!cp) 2082127178d2SJohan Hedberg return; 2083127178d2SJohan Hedberg 2084127178d2SJohan Hedberg hci_dev_lock(hdev); 2085127178d2SJohan Hedberg 2086127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 2087b644ba33SJohan Hedberg 2088d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_MGMT)) 2089b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0); 2090b644ba33SJohan Hedberg 209179c6c70cSJohan Hedberg if (!conn) 209279c6c70cSJohan Hedberg goto unlock; 209379c6c70cSJohan Hedberg 209479c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 209579c6c70cSJohan Hedberg goto unlock; 209679c6c70cSJohan Hedberg 209751a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 2098c1f23a2bSJohannes Berg struct hci_cp_auth_requested auth_cp; 2099c1f23a2bSJohannes Berg 2100977f8fceSJohan Hedberg set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags); 2101977f8fceSJohan Hedberg 2102c1f23a2bSJohannes Berg auth_cp.handle = __cpu_to_le16(conn->handle); 2103c1f23a2bSJohannes Berg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, 2104c1f23a2bSJohannes Berg sizeof(auth_cp), &auth_cp); 2105127178d2SJohan Hedberg } 2106127178d2SJohan Hedberg 210779c6c70cSJohan Hedberg unlock: 2108127178d2SJohan Hedberg hci_dev_unlock(hdev); 2109a9de9248SMarcel Holtmann } 21101da177e4SLinus Torvalds 2111769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 2112769be974SMarcel Holtmann { 2113769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 2114769be974SMarcel Holtmann struct hci_conn *conn; 2115769be974SMarcel Holtmann 21169f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 2117769be974SMarcel Holtmann 2118769be974SMarcel Holtmann if (!status) 2119769be974SMarcel Holtmann return; 2120769be974SMarcel Holtmann 2121769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 2122769be974SMarcel Holtmann if (!cp) 2123769be974SMarcel Holtmann return; 2124769be974SMarcel Holtmann 2125769be974SMarcel Holtmann hci_dev_lock(hdev); 2126769be974SMarcel Holtmann 2127769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 2128769be974SMarcel Holtmann if (conn) { 2129769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 2130539c496dSJohan Hedberg hci_connect_cfm(conn, status); 213176a68ba0SDavid Herrmann hci_conn_drop(conn); 2132769be974SMarcel Holtmann } 2133769be974SMarcel Holtmann } 2134769be974SMarcel Holtmann 2135769be974SMarcel Holtmann hci_dev_unlock(hdev); 2136769be974SMarcel Holtmann } 2137769be974SMarcel Holtmann 2138769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 2139769be974SMarcel Holtmann { 2140769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features *cp; 2141769be974SMarcel Holtmann struct hci_conn *conn; 2142769be974SMarcel Holtmann 21439f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 2144769be974SMarcel Holtmann 2145769be974SMarcel Holtmann if (!status) 2146769be974SMarcel Holtmann return; 2147769be974SMarcel Holtmann 2148769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 2149769be974SMarcel Holtmann if (!cp) 2150769be974SMarcel Holtmann return; 2151769be974SMarcel Holtmann 2152769be974SMarcel Holtmann hci_dev_lock(hdev); 2153769be974SMarcel Holtmann 2154769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 2155769be974SMarcel Holtmann if (conn) { 2156769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 2157539c496dSJohan Hedberg hci_connect_cfm(conn, status); 215876a68ba0SDavid Herrmann hci_conn_drop(conn); 2159769be974SMarcel Holtmann } 2160769be974SMarcel Holtmann } 2161769be974SMarcel Holtmann 2162769be974SMarcel Holtmann hci_dev_unlock(hdev); 2163769be974SMarcel Holtmann } 2164769be974SMarcel Holtmann 2165a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 2166a9de9248SMarcel Holtmann { 2167b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 2168b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 2169b6a0dc82SMarcel Holtmann __u16 handle; 2170b6a0dc82SMarcel Holtmann 21719f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 2172b6a0dc82SMarcel Holtmann 2173b6a0dc82SMarcel Holtmann if (!status) 2174b6a0dc82SMarcel Holtmann return; 2175b6a0dc82SMarcel Holtmann 2176b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 2177b6a0dc82SMarcel Holtmann if (!cp) 2178b6a0dc82SMarcel Holtmann return; 2179b6a0dc82SMarcel Holtmann 2180b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 2181b6a0dc82SMarcel Holtmann 21829f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, handle); 2183b6a0dc82SMarcel Holtmann 2184b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 2185b6a0dc82SMarcel Holtmann 2186b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 21875a08ecceSAndrei Emeltchenko if (acl) { 21885a08ecceSAndrei Emeltchenko sco = acl->link; 21895a08ecceSAndrei Emeltchenko if (sco) { 2190b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 2191b6a0dc82SMarcel Holtmann 2192539c496dSJohan Hedberg hci_connect_cfm(sco, status); 2193b6a0dc82SMarcel Holtmann hci_conn_del(sco); 2194b6a0dc82SMarcel Holtmann } 21955a08ecceSAndrei Emeltchenko } 2196b6a0dc82SMarcel Holtmann 2197b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 2198a9de9248SMarcel Holtmann } 2199a9de9248SMarcel Holtmann 2200a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 2201a9de9248SMarcel Holtmann { 2202a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 220304837f64SMarcel Holtmann struct hci_conn *conn; 220404837f64SMarcel Holtmann 22059f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 2206a9de9248SMarcel Holtmann 2207a9de9248SMarcel Holtmann if (!status) 2208a9de9248SMarcel Holtmann return; 2209a9de9248SMarcel Holtmann 2210a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 221104837f64SMarcel Holtmann if (!cp) 2212a9de9248SMarcel Holtmann return; 221304837f64SMarcel Holtmann 221404837f64SMarcel Holtmann hci_dev_lock(hdev); 221504837f64SMarcel Holtmann 221604837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 2217e73439d8SMarcel Holtmann if (conn) { 221851a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 221904837f64SMarcel Holtmann 222051a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 2221e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 2222e73439d8SMarcel Holtmann } 2223e73439d8SMarcel Holtmann 222404837f64SMarcel Holtmann hci_dev_unlock(hdev); 222504837f64SMarcel Holtmann } 222604837f64SMarcel Holtmann 2227a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 2228a9de9248SMarcel Holtmann { 2229a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 223004837f64SMarcel Holtmann struct hci_conn *conn; 223104837f64SMarcel Holtmann 22329f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 2233a9de9248SMarcel Holtmann 2234a9de9248SMarcel Holtmann if (!status) 2235a9de9248SMarcel Holtmann return; 2236a9de9248SMarcel Holtmann 2237a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 223804837f64SMarcel Holtmann if (!cp) 2239a9de9248SMarcel Holtmann return; 224004837f64SMarcel Holtmann 224104837f64SMarcel Holtmann hci_dev_lock(hdev); 224204837f64SMarcel Holtmann 224304837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 2244e73439d8SMarcel Holtmann if (conn) { 224551a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 224604837f64SMarcel Holtmann 224751a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 2248e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 2249e73439d8SMarcel Holtmann } 2250e73439d8SMarcel Holtmann 225104837f64SMarcel Holtmann hci_dev_unlock(hdev); 225204837f64SMarcel Holtmann } 225304837f64SMarcel Holtmann 225488c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) 225588c3df13SJohan Hedberg { 225688c3df13SJohan Hedberg struct hci_cp_disconnect *cp; 225788c3df13SJohan Hedberg struct hci_conn *conn; 225888c3df13SJohan Hedberg 225988c3df13SJohan Hedberg if (!status) 226088c3df13SJohan Hedberg return; 226188c3df13SJohan Hedberg 226288c3df13SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT); 226388c3df13SJohan Hedberg if (!cp) 226488c3df13SJohan Hedberg return; 226588c3df13SJohan Hedberg 226688c3df13SJohan Hedberg hci_dev_lock(hdev); 226788c3df13SJohan Hedberg 226888c3df13SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 2269b8d29052SJoseph Hwang if (conn) { 2270b8d29052SJoseph Hwang u8 type = conn->type; 2271b8d29052SJoseph Hwang 227288c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 227388c3df13SJohan Hedberg conn->dst_type, status); 227488c3df13SJohan Hedberg 2275b8d29052SJoseph Hwang /* If the disconnection failed for any reason, the upper layer 2276b8d29052SJoseph Hwang * does not retry to disconnect in current implementation. 2277b8d29052SJoseph Hwang * Hence, we need to do some basic cleanup here and re-enable 2278b8d29052SJoseph Hwang * advertising if necessary. 2279b8d29052SJoseph Hwang */ 2280b8d29052SJoseph Hwang hci_conn_del(conn); 2281b8d29052SJoseph Hwang if (type == LE_LINK) 2282b8d29052SJoseph Hwang hci_req_reenable_advertising(hdev); 2283b8d29052SJoseph Hwang } 2284b8d29052SJoseph Hwang 228588c3df13SJohan Hedberg hci_dev_unlock(hdev); 228688c3df13SJohan Hedberg } 228788c3df13SJohan Hedberg 2288d12fb056SJaganath Kanakkassery static void cs_le_create_conn(struct hci_dev *hdev, bdaddr_t *peer_addr, 2289d12fb056SJaganath Kanakkassery u8 peer_addr_type, u8 own_address_type, 2290d12fb056SJaganath Kanakkassery u8 filter_policy) 2291d12fb056SJaganath Kanakkassery { 2292d12fb056SJaganath Kanakkassery struct hci_conn *conn; 2293d12fb056SJaganath Kanakkassery 2294d12fb056SJaganath Kanakkassery conn = hci_conn_hash_lookup_le(hdev, peer_addr, 2295d12fb056SJaganath Kanakkassery peer_addr_type); 2296d12fb056SJaganath Kanakkassery if (!conn) 2297d12fb056SJaganath Kanakkassery return; 2298d12fb056SJaganath Kanakkassery 2299b31bc00bSSathish Narasimman /* When using controller based address resolution, then the new 2300b31bc00bSSathish Narasimman * address types 0x02 and 0x03 are used. These types need to be 2301b31bc00bSSathish Narasimman * converted back into either public address or random address type 2302b31bc00bSSathish Narasimman */ 2303b31bc00bSSathish Narasimman if (use_ll_privacy(hdev) && 2304b31bc00bSSathish Narasimman hci_dev_test_flag(hdev, HCI_LL_RPA_RESOLUTION)) { 2305b31bc00bSSathish Narasimman switch (own_address_type) { 2306b31bc00bSSathish Narasimman case ADDR_LE_DEV_PUBLIC_RESOLVED: 2307b31bc00bSSathish Narasimman own_address_type = ADDR_LE_DEV_PUBLIC; 2308b31bc00bSSathish Narasimman break; 2309b31bc00bSSathish Narasimman case ADDR_LE_DEV_RANDOM_RESOLVED: 2310b31bc00bSSathish Narasimman own_address_type = ADDR_LE_DEV_RANDOM; 2311b31bc00bSSathish Narasimman break; 2312b31bc00bSSathish Narasimman } 2313b31bc00bSSathish Narasimman } 2314b31bc00bSSathish Narasimman 2315d12fb056SJaganath Kanakkassery /* Store the initiator and responder address information which 2316d12fb056SJaganath Kanakkassery * is needed for SMP. These values will not change during the 2317d12fb056SJaganath Kanakkassery * lifetime of the connection. 2318d12fb056SJaganath Kanakkassery */ 2319d12fb056SJaganath Kanakkassery conn->init_addr_type = own_address_type; 2320d12fb056SJaganath Kanakkassery if (own_address_type == ADDR_LE_DEV_RANDOM) 2321d12fb056SJaganath Kanakkassery bacpy(&conn->init_addr, &hdev->random_addr); 2322d12fb056SJaganath Kanakkassery else 2323d12fb056SJaganath Kanakkassery bacpy(&conn->init_addr, &hdev->bdaddr); 2324d12fb056SJaganath Kanakkassery 2325d12fb056SJaganath Kanakkassery conn->resp_addr_type = peer_addr_type; 2326d12fb056SJaganath Kanakkassery bacpy(&conn->resp_addr, peer_addr); 2327d12fb056SJaganath Kanakkassery 2328d12fb056SJaganath Kanakkassery /* We don't want the connection attempt to stick around 2329d12fb056SJaganath Kanakkassery * indefinitely since LE doesn't have a page timeout concept 2330d12fb056SJaganath Kanakkassery * like BR/EDR. Set a timer for any connection that doesn't use 2331d12fb056SJaganath Kanakkassery * the white list for connecting. 2332d12fb056SJaganath Kanakkassery */ 2333d12fb056SJaganath Kanakkassery if (filter_policy == HCI_LE_USE_PEER_ADDR) 2334d12fb056SJaganath Kanakkassery queue_delayed_work(conn->hdev->workqueue, 2335d12fb056SJaganath Kanakkassery &conn->le_conn_timeout, 2336d12fb056SJaganath Kanakkassery conn->conn_timeout); 2337d12fb056SJaganath Kanakkassery } 2338d12fb056SJaganath Kanakkassery 2339cb1d68f7SJohan Hedberg static void hci_cs_le_create_conn(struct hci_dev *hdev, u8 status) 2340cb1d68f7SJohan Hedberg { 2341cb1d68f7SJohan Hedberg struct hci_cp_le_create_conn *cp; 2342cb1d68f7SJohan Hedberg 2343cb1d68f7SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 2344cb1d68f7SJohan Hedberg 2345cb1d68f7SJohan Hedberg /* All connection failure handling is taken care of by the 2346cb1d68f7SJohan Hedberg * hci_le_conn_failed function which is triggered by the HCI 2347cb1d68f7SJohan Hedberg * request completion callbacks used for connecting. 2348cb1d68f7SJohan Hedberg */ 2349cb1d68f7SJohan Hedberg if (status) 2350cb1d68f7SJohan Hedberg return; 2351cb1d68f7SJohan Hedberg 2352cb1d68f7SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN); 2353cb1d68f7SJohan Hedberg if (!cp) 2354cb1d68f7SJohan Hedberg return; 2355cb1d68f7SJohan Hedberg 2356cb1d68f7SJohan Hedberg hci_dev_lock(hdev); 2357cb1d68f7SJohan Hedberg 2358d12fb056SJaganath Kanakkassery cs_le_create_conn(hdev, &cp->peer_addr, cp->peer_addr_type, 2359d12fb056SJaganath Kanakkassery cp->own_address_type, cp->filter_policy); 2360cb1d68f7SJohan Hedberg 2361cb1d68f7SJohan Hedberg hci_dev_unlock(hdev); 2362cb1d68f7SJohan Hedberg } 2363cb1d68f7SJohan Hedberg 23644d94f95dSJaganath Kanakkassery static void hci_cs_le_ext_create_conn(struct hci_dev *hdev, u8 status) 23654d94f95dSJaganath Kanakkassery { 23664d94f95dSJaganath Kanakkassery struct hci_cp_le_ext_create_conn *cp; 23674d94f95dSJaganath Kanakkassery 23684d94f95dSJaganath Kanakkassery BT_DBG("%s status 0x%2.2x", hdev->name, status); 23694d94f95dSJaganath Kanakkassery 23704d94f95dSJaganath Kanakkassery /* All connection failure handling is taken care of by the 23714d94f95dSJaganath Kanakkassery * hci_le_conn_failed function which is triggered by the HCI 23724d94f95dSJaganath Kanakkassery * request completion callbacks used for connecting. 23734d94f95dSJaganath Kanakkassery */ 23744d94f95dSJaganath Kanakkassery if (status) 23754d94f95dSJaganath Kanakkassery return; 23764d94f95dSJaganath Kanakkassery 23774d94f95dSJaganath Kanakkassery cp = hci_sent_cmd_data(hdev, HCI_OP_LE_EXT_CREATE_CONN); 23784d94f95dSJaganath Kanakkassery if (!cp) 23794d94f95dSJaganath Kanakkassery return; 23804d94f95dSJaganath Kanakkassery 23814d94f95dSJaganath Kanakkassery hci_dev_lock(hdev); 23824d94f95dSJaganath Kanakkassery 23834d94f95dSJaganath Kanakkassery cs_le_create_conn(hdev, &cp->peer_addr, cp->peer_addr_type, 23844d94f95dSJaganath Kanakkassery cp->own_addr_type, cp->filter_policy); 23854d94f95dSJaganath Kanakkassery 23864d94f95dSJaganath Kanakkassery hci_dev_unlock(hdev); 23874d94f95dSJaganath Kanakkassery } 23884d94f95dSJaganath Kanakkassery 23890fe29fd1SMarcel Holtmann static void hci_cs_le_read_remote_features(struct hci_dev *hdev, u8 status) 23900fe29fd1SMarcel Holtmann { 23910fe29fd1SMarcel Holtmann struct hci_cp_le_read_remote_features *cp; 23920fe29fd1SMarcel Holtmann struct hci_conn *conn; 23930fe29fd1SMarcel Holtmann 23940fe29fd1SMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, status); 23950fe29fd1SMarcel Holtmann 23960fe29fd1SMarcel Holtmann if (!status) 23970fe29fd1SMarcel Holtmann return; 23980fe29fd1SMarcel Holtmann 23990fe29fd1SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_LE_READ_REMOTE_FEATURES); 24000fe29fd1SMarcel Holtmann if (!cp) 24010fe29fd1SMarcel Holtmann return; 24020fe29fd1SMarcel Holtmann 24030fe29fd1SMarcel Holtmann hci_dev_lock(hdev); 24040fe29fd1SMarcel Holtmann 24050fe29fd1SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 24060fe29fd1SMarcel Holtmann if (conn) { 24070fe29fd1SMarcel Holtmann if (conn->state == BT_CONFIG) { 24080fe29fd1SMarcel Holtmann hci_connect_cfm(conn, status); 24090fe29fd1SMarcel Holtmann hci_conn_drop(conn); 24100fe29fd1SMarcel Holtmann } 24110fe29fd1SMarcel Holtmann } 24120fe29fd1SMarcel Holtmann 24130fe29fd1SMarcel Holtmann hci_dev_unlock(hdev); 24140fe29fd1SMarcel Holtmann } 24150fe29fd1SMarcel Holtmann 241681d0c8adSJohan Hedberg static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) 241781d0c8adSJohan Hedberg { 241881d0c8adSJohan Hedberg struct hci_cp_le_start_enc *cp; 241981d0c8adSJohan Hedberg struct hci_conn *conn; 242081d0c8adSJohan Hedberg 242181d0c8adSJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 242281d0c8adSJohan Hedberg 242381d0c8adSJohan Hedberg if (!status) 242481d0c8adSJohan Hedberg return; 242581d0c8adSJohan Hedberg 242681d0c8adSJohan Hedberg hci_dev_lock(hdev); 242781d0c8adSJohan Hedberg 242881d0c8adSJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_LE_START_ENC); 242981d0c8adSJohan Hedberg if (!cp) 243081d0c8adSJohan Hedberg goto unlock; 243181d0c8adSJohan Hedberg 243281d0c8adSJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 243381d0c8adSJohan Hedberg if (!conn) 243481d0c8adSJohan Hedberg goto unlock; 243581d0c8adSJohan Hedberg 243681d0c8adSJohan Hedberg if (conn->state != BT_CONNECTED) 243781d0c8adSJohan Hedberg goto unlock; 243881d0c8adSJohan Hedberg 243981d0c8adSJohan Hedberg hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); 244081d0c8adSJohan Hedberg hci_conn_drop(conn); 244181d0c8adSJohan Hedberg 244281d0c8adSJohan Hedberg unlock: 244381d0c8adSJohan Hedberg hci_dev_unlock(hdev); 244481d0c8adSJohan Hedberg } 244581d0c8adSJohan Hedberg 244650fc85f1SKuba Pawlak static void hci_cs_switch_role(struct hci_dev *hdev, u8 status) 244750fc85f1SKuba Pawlak { 244850fc85f1SKuba Pawlak struct hci_cp_switch_role *cp; 244950fc85f1SKuba Pawlak struct hci_conn *conn; 245050fc85f1SKuba Pawlak 245150fc85f1SKuba Pawlak BT_DBG("%s status 0x%2.2x", hdev->name, status); 245250fc85f1SKuba Pawlak 245350fc85f1SKuba Pawlak if (!status) 245450fc85f1SKuba Pawlak return; 245550fc85f1SKuba Pawlak 245650fc85f1SKuba Pawlak cp = hci_sent_cmd_data(hdev, HCI_OP_SWITCH_ROLE); 245750fc85f1SKuba Pawlak if (!cp) 245850fc85f1SKuba Pawlak return; 245950fc85f1SKuba Pawlak 246050fc85f1SKuba Pawlak hci_dev_lock(hdev); 246150fc85f1SKuba Pawlak 246250fc85f1SKuba Pawlak conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 246350fc85f1SKuba Pawlak if (conn) 246450fc85f1SKuba Pawlak clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); 246550fc85f1SKuba Pawlak 246650fc85f1SKuba Pawlak hci_dev_unlock(hdev); 246750fc85f1SKuba Pawlak } 246850fc85f1SKuba Pawlak 24696039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 24701da177e4SLinus Torvalds { 24711da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 247230dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 247330dc78e1SJohan Hedberg struct inquiry_entry *e; 24741da177e4SLinus Torvalds 24759f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 24761da177e4SLinus Torvalds 2477a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 247889352e7dSAndre Guedes 247989352e7dSAndre Guedes if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) 248089352e7dSAndre Guedes return; 248189352e7dSAndre Guedes 24824e857c58SPeter Zijlstra smp_mb__after_atomic(); /* wake_up_bit advises about this barrier */ 24833e13fa1eSAndre Guedes wake_up_bit(&hdev->flags, HCI_INQUIRY); 24843e13fa1eSAndre Guedes 2485d7a5a11dSMarcel Holtmann if (!hci_dev_test_flag(hdev, HCI_MGMT)) 248630dc78e1SJohan Hedberg return; 248730dc78e1SJohan Hedberg 248856e5cb86SJohan Hedberg hci_dev_lock(hdev); 248930dc78e1SJohan Hedberg 2490343f935bSAndre Guedes if (discov->state != DISCOVERY_FINDING) 249130dc78e1SJohan Hedberg goto unlock; 249230dc78e1SJohan Hedberg 249330dc78e1SJohan Hedberg if (list_empty(&discov->resolve)) { 249407d2334aSJakub Pawlowski /* When BR/EDR inquiry is active and no LE scanning is in 249507d2334aSJakub Pawlowski * progress, then change discovery state to indicate completion. 249607d2334aSJakub Pawlowski * 249707d2334aSJakub Pawlowski * When running LE scanning and BR/EDR inquiry simultaneously 249807d2334aSJakub Pawlowski * and the LE scan already finished, then change the discovery 249907d2334aSJakub Pawlowski * state to indicate completion. 250007d2334aSJakub Pawlowski */ 250107d2334aSJakub Pawlowski if (!hci_dev_test_flag(hdev, HCI_LE_SCAN) || 250207d2334aSJakub Pawlowski !test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks)) 2503ff9ef578SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 250430dc78e1SJohan Hedberg goto unlock; 250530dc78e1SJohan Hedberg } 250630dc78e1SJohan Hedberg 250730dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 250830dc78e1SJohan Hedberg if (e && hci_resolve_name(hdev, e) == 0) { 250930dc78e1SJohan Hedberg e->name_state = NAME_PENDING; 251030dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_RESOLVING); 251130dc78e1SJohan Hedberg } else { 251207d2334aSJakub Pawlowski /* When BR/EDR inquiry is active and no LE scanning is in 251307d2334aSJakub Pawlowski * progress, then change discovery state to indicate completion. 251407d2334aSJakub Pawlowski * 251507d2334aSJakub Pawlowski * When running LE scanning and BR/EDR inquiry simultaneously 251607d2334aSJakub Pawlowski * and the LE scan already finished, then change the discovery 251707d2334aSJakub Pawlowski * state to indicate completion. 251807d2334aSJakub Pawlowski */ 251907d2334aSJakub Pawlowski if (!hci_dev_test_flag(hdev, HCI_LE_SCAN) || 252007d2334aSJakub Pawlowski !test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks)) 252130dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 252230dc78e1SJohan Hedberg } 252330dc78e1SJohan Hedberg 252430dc78e1SJohan Hedberg unlock: 252556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 25261da177e4SLinus Torvalds } 25271da177e4SLinus Torvalds 25286039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 25291da177e4SLinus Torvalds { 253045bb4bf0SMarcel Holtmann struct inquiry_data data; 2531a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 25321da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 25331da177e4SLinus Torvalds 25341da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 25351da177e4SLinus Torvalds 253675bbd2eaSPeilin Ye if (!num_rsp || skb->len < num_rsp * sizeof(*info) + 1) 253745bb4bf0SMarcel Holtmann return; 253845bb4bf0SMarcel Holtmann 2539d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) 25401519cc17SAndre Guedes return; 25411519cc17SAndre Guedes 25421da177e4SLinus Torvalds hci_dev_lock(hdev); 254345bb4bf0SMarcel Holtmann 2544e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2545af58925cSMarcel Holtmann u32 flags; 25463175405bSJohan Hedberg 25471da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 25481da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 25491da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 25501da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 25511da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 25521da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 2553efb2513fSMarcel Holtmann data.rssi = HCI_RSSI_INVALID; 255441a96212SMarcel Holtmann data.ssp_mode = 0x00; 25553175405bSJohan Hedberg 2556af58925cSMarcel Holtmann flags = hci_inquiry_cache_update(hdev, &data, false); 2557af58925cSMarcel Holtmann 255848264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2559efb2513fSMarcel Holtmann info->dev_class, HCI_RSSI_INVALID, 2560efb2513fSMarcel Holtmann flags, NULL, 0, NULL, 0); 25611da177e4SLinus Torvalds } 256245bb4bf0SMarcel Holtmann 25631da177e4SLinus Torvalds hci_dev_unlock(hdev); 25641da177e4SLinus Torvalds } 25651da177e4SLinus Torvalds 25666039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 25671da177e4SLinus Torvalds { 2568a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 25694f40afc6SAbhishek Pandit-Subedi struct inquiry_entry *ie; 2570a9de9248SMarcel Holtmann struct hci_conn *conn; 25711da177e4SLinus Torvalds 2572a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 257345bb4bf0SMarcel Holtmann 25741da177e4SLinus Torvalds hci_dev_lock(hdev); 257545bb4bf0SMarcel Holtmann 2576a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 25779499237aSMarcel Holtmann if (!conn) { 25784f40afc6SAbhishek Pandit-Subedi /* Connection may not exist if auto-connected. Check the inquiry 25794f40afc6SAbhishek Pandit-Subedi * cache to see if we've already discovered this bdaddr before. 25804f40afc6SAbhishek Pandit-Subedi * If found and link is an ACL type, create a connection class 25814f40afc6SAbhishek Pandit-Subedi * automatically. 25824f40afc6SAbhishek Pandit-Subedi */ 25834f40afc6SAbhishek Pandit-Subedi ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 25844f40afc6SAbhishek Pandit-Subedi if (ie && ev->link_type == ACL_LINK) { 25854f40afc6SAbhishek Pandit-Subedi conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr, 25864f40afc6SAbhishek Pandit-Subedi HCI_ROLE_SLAVE); 25874f40afc6SAbhishek Pandit-Subedi if (!conn) { 25884f40afc6SAbhishek Pandit-Subedi bt_dev_err(hdev, "no memory for new conn"); 25894f40afc6SAbhishek Pandit-Subedi goto unlock; 25904f40afc6SAbhishek Pandit-Subedi } 25912d186fcdSAbhishek Pandit-Subedi } else { 25929499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 25939499237aSMarcel Holtmann goto unlock; 25949499237aSMarcel Holtmann 25952d186fcdSAbhishek Pandit-Subedi conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, 25962d186fcdSAbhishek Pandit-Subedi &ev->bdaddr); 2597a9de9248SMarcel Holtmann if (!conn) 2598a9de9248SMarcel Holtmann goto unlock; 259945bb4bf0SMarcel Holtmann 26009499237aSMarcel Holtmann conn->type = SCO_LINK; 26019499237aSMarcel Holtmann } 26022d186fcdSAbhishek Pandit-Subedi } 26039499237aSMarcel Holtmann 2604a9de9248SMarcel Holtmann if (!ev->status) { 2605a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 2606769be974SMarcel Holtmann 2607769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 2608769be974SMarcel Holtmann conn->state = BT_CONFIG; 2609769be974SMarcel Holtmann hci_conn_hold(conn); 2610a9ea3ed9SSzymon Janc 2611a9ea3ed9SSzymon Janc if (!conn->out && !hci_conn_ssp_enabled(conn) && 2612a9ea3ed9SSzymon Janc !hci_find_link_key(hdev, &ev->bdaddr)) 2613a9ea3ed9SSzymon Janc conn->disc_timeout = HCI_PAIRING_TIMEOUT; 2614a9ea3ed9SSzymon Janc else 2615052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2616769be974SMarcel Holtmann } else 2617a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 2618a9de9248SMarcel Holtmann 261923b9ceb7SMarcel Holtmann hci_debugfs_create_conn(conn); 26207d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 26217d0db0a3SMarcel Holtmann 2622a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 26234dae2798SJohan Hedberg set_bit(HCI_CONN_AUTH, &conn->flags); 2624a9de9248SMarcel Holtmann 2625a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 26264dae2798SJohan Hedberg set_bit(HCI_CONN_ENCRYPT, &conn->flags); 2627a9de9248SMarcel Holtmann 2628a9de9248SMarcel Holtmann /* Get remote features */ 2629a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 2630a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 2631a9de9248SMarcel Holtmann cp.handle = ev->handle; 2632769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 2633769be974SMarcel Holtmann sizeof(cp), &cp); 263422f433dcSJohan Hedberg 263501b1cb87SJohan Hedberg hci_req_update_scan(hdev); 263645bb4bf0SMarcel Holtmann } 2637a9de9248SMarcel Holtmann 2638a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 2639d095c1ebSAndrei Emeltchenko if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) { 2640a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 2641a9de9248SMarcel Holtmann cp.handle = ev->handle; 2642a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 264304124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp), 264404124681SGustavo F. Padovan &cp); 2645a9de9248SMarcel Holtmann } 264617d5c04cSJohan Hedberg } else { 2647a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 264817d5c04cSJohan Hedberg if (conn->type == ACL_LINK) 264964c7b77cSMarcel Holtmann mgmt_connect_failed(hdev, &conn->dst, conn->type, 265048264f06SJohan Hedberg conn->dst_type, ev->status); 265117d5c04cSJohan Hedberg } 265245bb4bf0SMarcel Holtmann 2653e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 2654e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 265545bb4bf0SMarcel Holtmann 2656769be974SMarcel Holtmann if (ev->status) { 2657539c496dSJohan Hedberg hci_connect_cfm(conn, ev->status); 2658a9de9248SMarcel Holtmann hci_conn_del(conn); 26591f8330eaSSathish Narsimman } else if (ev->link_type == SCO_LINK) { 26601f8330eaSSathish Narsimman switch (conn->setting & SCO_AIRMODE_MASK) { 26611f8330eaSSathish Narsimman case SCO_AIRMODE_CVSD: 26621f8330eaSSathish Narsimman if (hdev->notify) 26631f8330eaSSathish Narsimman hdev->notify(hdev, HCI_NOTIFY_ENABLE_SCO_CVSD); 26641f8330eaSSathish Narsimman break; 26651f8330eaSSathish Narsimman } 26661f8330eaSSathish Narsimman 2667539c496dSJohan Hedberg hci_connect_cfm(conn, ev->status); 26681f8330eaSSathish Narsimman } 2669a9de9248SMarcel Holtmann 2670a9de9248SMarcel Holtmann unlock: 26711da177e4SLinus Torvalds hci_dev_unlock(hdev); 2672a9de9248SMarcel Holtmann 2673a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 26741da177e4SLinus Torvalds } 26751da177e4SLinus Torvalds 267670c46425SJohan Hedberg static void hci_reject_conn(struct hci_dev *hdev, bdaddr_t *bdaddr) 267770c46425SJohan Hedberg { 267870c46425SJohan Hedberg struct hci_cp_reject_conn_req cp; 267970c46425SJohan Hedberg 268070c46425SJohan Hedberg bacpy(&cp.bdaddr, bdaddr); 268170c46425SJohan Hedberg cp.reason = HCI_ERROR_REJ_BAD_ADDR; 268270c46425SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 268370c46425SJohan Hedberg } 268470c46425SJohan Hedberg 26856039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 26861da177e4SLinus Torvalds { 2687a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 26881da177e4SLinus Torvalds int mask = hdev->link_mode; 268970c46425SJohan Hedberg struct inquiry_entry *ie; 269070c46425SJohan Hedberg struct hci_conn *conn; 269120714bfeSFrédéric Dalleau __u8 flags = 0; 26921da177e4SLinus Torvalds 26936ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr, 2694807deac2SGustavo Padovan ev->link_type); 26951da177e4SLinus Torvalds 269620714bfeSFrédéric Dalleau mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type, 269720714bfeSFrédéric Dalleau &flags); 26981da177e4SLinus Torvalds 269970c46425SJohan Hedberg if (!(mask & HCI_LM_ACCEPT)) { 270070c46425SJohan Hedberg hci_reject_conn(hdev, &ev->bdaddr); 270170c46425SJohan Hedberg return; 270270c46425SJohan Hedberg } 270370c46425SJohan Hedberg 2704a55bd29dSJohan Hedberg if (hci_bdaddr_list_lookup(&hdev->blacklist, &ev->bdaddr, 2705dcc36c16SJohan Hedberg BDADDR_BREDR)) { 270670c46425SJohan Hedberg hci_reject_conn(hdev, &ev->bdaddr); 270770c46425SJohan Hedberg return; 270870c46425SJohan Hedberg } 270946c4c941SJohan Hedberg 27106a8fc95cSJohan Hedberg /* Require HCI_CONNECTABLE or a whitelist entry to accept the 27116a8fc95cSJohan Hedberg * connection. These features are only touched through mgmt so 27126a8fc95cSJohan Hedberg * only do the checks if HCI_MGMT is set. 27136a8fc95cSJohan Hedberg */ 2714d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_MGMT) && 2715d7a5a11dSMarcel Holtmann !hci_dev_test_flag(hdev, HCI_CONNECTABLE) && 27168baaa403SAbhishek Pandit-Subedi !hci_bdaddr_list_lookup_with_flags(&hdev->whitelist, &ev->bdaddr, 2717a55bd29dSJohan Hedberg BDADDR_BREDR)) { 2718a55bd29dSJohan Hedberg hci_reject_conn(hdev, &ev->bdaddr); 2719a55bd29dSJohan Hedberg return; 2720a55bd29dSJohan Hedberg } 272170c46425SJohan Hedberg 27221da177e4SLinus Torvalds /* Connection accepted */ 27231da177e4SLinus Torvalds 27241da177e4SLinus Torvalds hci_dev_lock(hdev); 2725b6a0dc82SMarcel Holtmann 2726cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2727cc11b9c1SAndrei Emeltchenko if (ie) 2728c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 2729c7bdd502SMarcel Holtmann 27308fc9ced3SGustavo Padovan conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, 27318fc9ced3SGustavo Padovan &ev->bdaddr); 27321da177e4SLinus Torvalds if (!conn) { 2733a5c4e309SJohan Hedberg conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr, 2734a5c4e309SJohan Hedberg HCI_ROLE_SLAVE); 2735cc11b9c1SAndrei Emeltchenko if (!conn) { 27362064ee33SMarcel Holtmann bt_dev_err(hdev, "no memory for new connection"); 27371da177e4SLinus Torvalds hci_dev_unlock(hdev); 27381da177e4SLinus Torvalds return; 27391da177e4SLinus Torvalds } 27401da177e4SLinus Torvalds } 2741b6a0dc82SMarcel Holtmann 27421da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 2743b6a0dc82SMarcel Holtmann 27441da177e4SLinus Torvalds hci_dev_unlock(hdev); 27451da177e4SLinus Torvalds 274620714bfeSFrédéric Dalleau if (ev->link_type == ACL_LINK || 274720714bfeSFrédéric Dalleau (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) { 2748b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 274920714bfeSFrédéric Dalleau conn->state = BT_CONNECT; 2750b6a0dc82SMarcel Holtmann 27511da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 27521da177e4SLinus Torvalds 27531da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 27541da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 27551da177e4SLinus Torvalds else 27561da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 27571da177e4SLinus Torvalds 275870c46425SJohan Hedberg hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp); 275920714bfeSFrédéric Dalleau } else if (!(flags & HCI_PROTO_DEFER)) { 2760b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 276120714bfeSFrédéric Dalleau conn->state = BT_CONNECT; 2762b6a0dc82SMarcel Holtmann 2763b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 2764a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 2765b6a0dc82SMarcel Holtmann 2766dcf4adbfSJoe Perches cp.tx_bandwidth = cpu_to_le32(0x00001f40); 2767dcf4adbfSJoe Perches cp.rx_bandwidth = cpu_to_le32(0x00001f40); 2768dcf4adbfSJoe Perches cp.max_latency = cpu_to_le16(0xffff); 2769b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 2770b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 2771b6a0dc82SMarcel Holtmann 277270c46425SJohan Hedberg hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, sizeof(cp), 277370c46425SJohan Hedberg &cp); 277420714bfeSFrédéric Dalleau } else { 277520714bfeSFrédéric Dalleau conn->state = BT_CONNECT2; 2776539c496dSJohan Hedberg hci_connect_cfm(conn, 0); 2777b6a0dc82SMarcel Holtmann } 27781da177e4SLinus Torvalds } 27791da177e4SLinus Torvalds 2780f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err) 2781f0d6a0eaSMikel Astiz { 2782f0d6a0eaSMikel Astiz switch (err) { 2783f0d6a0eaSMikel Astiz case HCI_ERROR_CONNECTION_TIMEOUT: 2784f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_TIMEOUT; 2785f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_USER_TERM: 2786f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_LOW_RESOURCES: 2787f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_POWER_OFF: 2788f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_REMOTE; 2789f0d6a0eaSMikel Astiz case HCI_ERROR_LOCAL_HOST_TERM: 2790f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_LOCAL_HOST; 2791f0d6a0eaSMikel Astiz default: 2792f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_UNKNOWN; 2793f0d6a0eaSMikel Astiz } 2794f0d6a0eaSMikel Astiz } 2795f0d6a0eaSMikel Astiz 27966039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 27971da177e4SLinus Torvalds { 2798a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 2799160b9251SSzymon Janc u8 reason; 28009fcb18efSAndre Guedes struct hci_conn_params *params; 280104837f64SMarcel Holtmann struct hci_conn *conn; 280212d4a3b2SJohan Hedberg bool mgmt_connected; 28033846220bSAndre Guedes u8 type; 28041da177e4SLinus Torvalds 28059f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 28061da177e4SLinus Torvalds 28071da177e4SLinus Torvalds hci_dev_lock(hdev); 28081da177e4SLinus Torvalds 280904837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2810f7520543SJohan Hedberg if (!conn) 2811f7520543SJohan Hedberg goto unlock; 2812f7520543SJohan Hedberg 2813f0d6a0eaSMikel Astiz if (ev->status) { 281488c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 281588c3df13SJohan Hedberg conn->dst_type, ev->status); 2816abf54a50SAndre Guedes goto unlock; 2817abf54a50SAndre Guedes } 2818f0d6a0eaSMikel Astiz 28193846220bSAndre Guedes conn->state = BT_CLOSED; 28203846220bSAndre Guedes 282112d4a3b2SJohan Hedberg mgmt_connected = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags); 2822160b9251SSzymon Janc 2823160b9251SSzymon Janc if (test_bit(HCI_CONN_AUTH_FAILURE, &conn->flags)) 2824160b9251SSzymon Janc reason = MGMT_DEV_DISCONN_AUTH_FAILURE; 2825160b9251SSzymon Janc else 2826160b9251SSzymon Janc reason = hci_to_mgmt_reason(ev->reason); 2827160b9251SSzymon Janc 282812d4a3b2SJohan Hedberg mgmt_device_disconnected(hdev, &conn->dst, conn->type, conn->dst_type, 282912d4a3b2SJohan Hedberg reason, mgmt_connected); 2830f7520543SJohan Hedberg 283122f433dcSJohan Hedberg if (conn->type == ACL_LINK) { 283222f433dcSJohan Hedberg if (test_bit(HCI_CONN_FLUSH_KEY, &conn->flags)) 28336ec5bcadSVishal Agarwal hci_remove_link_key(hdev, &conn->dst); 28343846220bSAndre Guedes 283501b1cb87SJohan Hedberg hci_req_update_scan(hdev); 283622f433dcSJohan Hedberg } 283722f433dcSJohan Hedberg 28389fcb18efSAndre Guedes params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type); 28399fcb18efSAndre Guedes if (params) { 28409fcb18efSAndre Guedes switch (params->auto_connect) { 28419fcb18efSAndre Guedes case HCI_AUTO_CONN_LINK_LOSS: 28429fcb18efSAndre Guedes if (ev->reason != HCI_ERROR_CONNECTION_TIMEOUT) 28439fcb18efSAndre Guedes break; 284419186c7bSGustavo A. R. Silva fallthrough; 28459fcb18efSAndre Guedes 28464b9e7e75SMarcel Holtmann case HCI_AUTO_CONN_DIRECT: 28479fcb18efSAndre Guedes case HCI_AUTO_CONN_ALWAYS: 2848418025d1SJohan Hedberg list_del_init(¶ms->action); 2849418025d1SJohan Hedberg list_add(¶ms->action, &hdev->pend_le_conns); 2850418025d1SJohan Hedberg hci_update_background_scan(hdev); 28519fcb18efSAndre Guedes break; 28529fcb18efSAndre Guedes 28539fcb18efSAndre Guedes default: 28549fcb18efSAndre Guedes break; 28559fcb18efSAndre Guedes } 28569fcb18efSAndre Guedes } 28579fcb18efSAndre Guedes 28583846220bSAndre Guedes type = conn->type; 28593846220bSAndre Guedes 28603a6d576bSJohan Hedberg hci_disconn_cfm(conn, ev->reason); 28611da177e4SLinus Torvalds hci_conn_del(conn); 28622210246cSJohan Hedberg 28634f40afc6SAbhishek Pandit-Subedi /* The suspend notifier is waiting for all devices to disconnect so 28644f40afc6SAbhishek Pandit-Subedi * clear the bit from pending tasks and inform the wait queue. 28654f40afc6SAbhishek Pandit-Subedi */ 28664f40afc6SAbhishek Pandit-Subedi if (list_empty(&hdev->conn_hash.list) && 28674f40afc6SAbhishek Pandit-Subedi test_and_clear_bit(SUSPEND_DISCONNECTING, hdev->suspend_tasks)) { 28684f40afc6SAbhishek Pandit-Subedi wake_up(&hdev->suspend_wait_q); 28694f40afc6SAbhishek Pandit-Subedi } 28704f40afc6SAbhishek Pandit-Subedi 28712210246cSJohan Hedberg /* Re-enable advertising if necessary, since it might 28722210246cSJohan Hedberg * have been disabled by the connection. From the 28732210246cSJohan Hedberg * HCI_LE_Set_Advertise_Enable command description in 28742210246cSJohan Hedberg * the core specification (v4.0): 28752210246cSJohan Hedberg * "The Controller shall continue advertising until the Host 28762210246cSJohan Hedberg * issues an LE_Set_Advertise_Enable command with 28772210246cSJohan Hedberg * Advertising_Enable set to 0x00 (Advertising is disabled) 28782210246cSJohan Hedberg * or until a connection is created or until the Advertising 28792210246cSJohan Hedberg * is timed out due to Directed Advertising." 28802210246cSJohan Hedberg */ 28812210246cSJohan Hedberg if (type == LE_LINK) 2882f2252570SJohan Hedberg hci_req_reenable_advertising(hdev); 28831da177e4SLinus Torvalds 2884f7520543SJohan Hedberg unlock: 28851da177e4SLinus Torvalds hci_dev_unlock(hdev); 28861da177e4SLinus Torvalds } 28871da177e4SLinus Torvalds 28886039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2889a9de9248SMarcel Holtmann { 2890a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 2891a9de9248SMarcel Holtmann struct hci_conn *conn; 2892a9de9248SMarcel Holtmann 28939f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2894a9de9248SMarcel Holtmann 2895a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2896a9de9248SMarcel Holtmann 2897a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2898d7556e20SWaldemar Rymarkiewicz if (!conn) 2899d7556e20SWaldemar Rymarkiewicz goto unlock; 2900d7556e20SWaldemar Rymarkiewicz 2901765c2a96SJohan Hedberg if (!ev->status) { 2902160b9251SSzymon Janc clear_bit(HCI_CONN_AUTH_FAILURE, &conn->flags); 2903160b9251SSzymon Janc 2904aa64a8b5SJohan Hedberg if (!hci_conn_ssp_enabled(conn) && 290551a8efd7SJohan Hedberg test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) { 29062064ee33SMarcel Holtmann bt_dev_info(hdev, "re-auth of legacy device is not possible."); 290719f8def0SWaldemar Rymarkiewicz } else { 29084dae2798SJohan Hedberg set_bit(HCI_CONN_AUTH, &conn->flags); 2909765c2a96SJohan Hedberg conn->sec_level = conn->pending_sec_level; 291019f8def0SWaldemar Rymarkiewicz } 29112a611692SJohan Hedberg } else { 2912160b9251SSzymon Janc if (ev->status == HCI_ERROR_PIN_OR_KEY_MISSING) 2913160b9251SSzymon Janc set_bit(HCI_CONN_AUTH_FAILURE, &conn->flags); 2914160b9251SSzymon Janc 2915e1e930f5SJohan Hedberg mgmt_auth_failed(conn, ev->status); 29162a611692SJohan Hedberg } 2917a9de9248SMarcel Holtmann 291851a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 291951a8efd7SJohan Hedberg clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags); 2920a9de9248SMarcel Holtmann 2921f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 2922aa64a8b5SJohan Hedberg if (!ev->status && hci_conn_ssp_enabled(conn)) { 2923f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 2924f8558555SMarcel Holtmann cp.handle = ev->handle; 2925f8558555SMarcel Holtmann cp.encrypt = 0x01; 2926d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 2927d7556e20SWaldemar Rymarkiewicz &cp); 2928f8558555SMarcel Holtmann } else { 2929f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 2930539c496dSJohan Hedberg hci_connect_cfm(conn, ev->status); 293176a68ba0SDavid Herrmann hci_conn_drop(conn); 2932f8558555SMarcel Holtmann } 2933052b30b0SMarcel Holtmann } else { 2934a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 2935a9de9248SMarcel Holtmann 2936052b30b0SMarcel Holtmann hci_conn_hold(conn); 2937052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 293876a68ba0SDavid Herrmann hci_conn_drop(conn); 2939052b30b0SMarcel Holtmann } 2940052b30b0SMarcel Holtmann 294151a8efd7SJohan Hedberg if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) { 2942a9de9248SMarcel Holtmann if (!ev->status) { 2943a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 2944f8558555SMarcel Holtmann cp.handle = ev->handle; 2945f8558555SMarcel Holtmann cp.encrypt = 0x01; 2946d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 2947d7556e20SWaldemar Rymarkiewicz &cp); 2948a9de9248SMarcel Holtmann } else { 294951a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 29503ca44c16SLuiz Augusto von Dentz hci_encrypt_cfm(conn, ev->status); 2951a9de9248SMarcel Holtmann } 2952a9de9248SMarcel Holtmann } 2953a9de9248SMarcel Holtmann 2954d7556e20SWaldemar Rymarkiewicz unlock: 2955a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2956a9de9248SMarcel Holtmann } 2957a9de9248SMarcel Holtmann 29586039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 2959a9de9248SMarcel Holtmann { 2960127178d2SJohan Hedberg struct hci_ev_remote_name *ev = (void *) skb->data; 2961127178d2SJohan Hedberg struct hci_conn *conn; 2962127178d2SJohan Hedberg 2963a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2964a9de9248SMarcel Holtmann 2965a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 2966127178d2SJohan Hedberg 2967127178d2SJohan Hedberg hci_dev_lock(hdev); 2968127178d2SJohan Hedberg 2969127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2970b644ba33SJohan Hedberg 2971d7a5a11dSMarcel Holtmann if (!hci_dev_test_flag(hdev, HCI_MGMT)) 2972b644ba33SJohan Hedberg goto check_auth; 2973b644ba33SJohan Hedberg 2974b644ba33SJohan Hedberg if (ev->status == 0) 2975b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name, 2976b644ba33SJohan Hedberg strnlen(ev->name, HCI_MAX_NAME_LENGTH)); 2977b644ba33SJohan Hedberg else 2978b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0); 2979b644ba33SJohan Hedberg 2980b644ba33SJohan Hedberg check_auth: 298179c6c70cSJohan Hedberg if (!conn) 298279c6c70cSJohan Hedberg goto unlock; 298379c6c70cSJohan Hedberg 298479c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 298579c6c70cSJohan Hedberg goto unlock; 298679c6c70cSJohan Hedberg 298751a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 2988127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 2989977f8fceSJohan Hedberg 2990977f8fceSJohan Hedberg set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags); 2991977f8fceSJohan Hedberg 2992127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 2993127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 2994127178d2SJohan Hedberg } 2995127178d2SJohan Hedberg 299679c6c70cSJohan Hedberg unlock: 2997127178d2SJohan Hedberg hci_dev_unlock(hdev); 2998a9de9248SMarcel Holtmann } 2999a9de9248SMarcel Holtmann 3000821f3766SJohan Hedberg static void read_enc_key_size_complete(struct hci_dev *hdev, u8 status, 3001821f3766SJohan Hedberg u16 opcode, struct sk_buff *skb) 3002821f3766SJohan Hedberg { 3003821f3766SJohan Hedberg const struct hci_rp_read_enc_key_size *rp; 3004821f3766SJohan Hedberg struct hci_conn *conn; 3005821f3766SJohan Hedberg u16 handle; 3006821f3766SJohan Hedberg 3007821f3766SJohan Hedberg BT_DBG("%s status 0x%02x", hdev->name, status); 3008821f3766SJohan Hedberg 3009821f3766SJohan Hedberg if (!skb || skb->len < sizeof(*rp)) { 30102064ee33SMarcel Holtmann bt_dev_err(hdev, "invalid read key size response"); 3011821f3766SJohan Hedberg return; 3012821f3766SJohan Hedberg } 3013821f3766SJohan Hedberg 3014821f3766SJohan Hedberg rp = (void *)skb->data; 3015821f3766SJohan Hedberg handle = le16_to_cpu(rp->handle); 3016821f3766SJohan Hedberg 3017821f3766SJohan Hedberg hci_dev_lock(hdev); 3018821f3766SJohan Hedberg 3019821f3766SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, handle); 3020821f3766SJohan Hedberg if (!conn) 3021821f3766SJohan Hedberg goto unlock; 3022821f3766SJohan Hedberg 302332b50729SAlain Michaud /* While unexpected, the read_enc_key_size command may fail. The most 302432b50729SAlain Michaud * secure approach is to then assume the key size is 0 to force a 302532b50729SAlain Michaud * disconnection. 3026821f3766SJohan Hedberg */ 3027821f3766SJohan Hedberg if (rp->status) { 30282064ee33SMarcel Holtmann bt_dev_err(hdev, "failed to read key size for handle %u", 3029821f3766SJohan Hedberg handle); 303032b50729SAlain Michaud conn->enc_key_size = 0; 3031821f3766SJohan Hedberg } else { 3032821f3766SJohan Hedberg conn->enc_key_size = rp->key_size; 3033821f3766SJohan Hedberg } 3034821f3766SJohan Hedberg 30353ca44c16SLuiz Augusto von Dentz hci_encrypt_cfm(conn, 0); 3036821f3766SJohan Hedberg 3037821f3766SJohan Hedberg unlock: 3038821f3766SJohan Hedberg hci_dev_unlock(hdev); 3039821f3766SJohan Hedberg } 3040821f3766SJohan Hedberg 30416039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 3042a9de9248SMarcel Holtmann { 3043a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 3044a9de9248SMarcel Holtmann struct hci_conn *conn; 3045a9de9248SMarcel Holtmann 30469f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 3047a9de9248SMarcel Holtmann 3048a9de9248SMarcel Holtmann hci_dev_lock(hdev); 3049a9de9248SMarcel Holtmann 3050a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3051dc8357ccSMarcel Holtmann if (!conn) 3052dc8357ccSMarcel Holtmann goto unlock; 3053dc8357ccSMarcel Holtmann 3054a9de9248SMarcel Holtmann if (!ev->status) { 3055ae293196SMarcel Holtmann if (ev->encrypt) { 3056ae293196SMarcel Holtmann /* Encryption implies authentication */ 30574dae2798SJohan Hedberg set_bit(HCI_CONN_AUTH, &conn->flags); 30584dae2798SJohan Hedberg set_bit(HCI_CONN_ENCRYPT, &conn->flags); 3059da85e5e5SVinicius Costa Gomes conn->sec_level = conn->pending_sec_level; 3060abf76badSMarcel Holtmann 3061914a6ffeSMarcel Holtmann /* P-256 authentication key implies FIPS */ 3062914a6ffeSMarcel Holtmann if (conn->key_type == HCI_LK_AUTH_COMBINATION_P256) 30634dae2798SJohan Hedberg set_bit(HCI_CONN_FIPS, &conn->flags); 3064914a6ffeSMarcel Holtmann 3065abf76badSMarcel Holtmann if ((conn->type == ACL_LINK && ev->encrypt == 0x02) || 3066abf76badSMarcel Holtmann conn->type == LE_LINK) 3067abf76badSMarcel Holtmann set_bit(HCI_CONN_AES_CCM, &conn->flags); 3068abf76badSMarcel Holtmann } else { 30694dae2798SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT, &conn->flags); 3070abf76badSMarcel Holtmann clear_bit(HCI_CONN_AES_CCM, &conn->flags); 3071abf76badSMarcel Holtmann } 3072a9de9248SMarcel Holtmann } 3073a9de9248SMarcel Holtmann 30747ed3fa20SJohan Hedberg /* We should disregard the current RPA and generate a new one 30757ed3fa20SJohan Hedberg * whenever the encryption procedure fails. 30767ed3fa20SJohan Hedberg */ 3077a73c046aSJaganath Kanakkassery if (ev->status && conn->type == LE_LINK) { 3078a1536da2SMarcel Holtmann hci_dev_set_flag(hdev, HCI_RPA_EXPIRED); 3079a73c046aSJaganath Kanakkassery hci_adv_instances_set_rpa_expired(hdev, true); 3080a73c046aSJaganath Kanakkassery } 30817ed3fa20SJohan Hedberg 308251a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 3083a9de9248SMarcel Holtmann 30848746f135SLuiz Augusto von Dentz /* Check link security requirements are met */ 30858746f135SLuiz Augusto von Dentz if (!hci_conn_check_link_mode(conn)) 30868746f135SLuiz Augusto von Dentz ev->status = HCI_ERROR_AUTH_FAILURE; 30878746f135SLuiz Augusto von Dentz 3088a7d7723aSGustavo Padovan if (ev->status && conn->state == BT_CONNECTED) { 3089160b9251SSzymon Janc if (ev->status == HCI_ERROR_PIN_OR_KEY_MISSING) 3090160b9251SSzymon Janc set_bit(HCI_CONN_AUTH_FAILURE, &conn->flags); 3091160b9251SSzymon Janc 30928746f135SLuiz Augusto von Dentz /* Notify upper layers so they can cleanup before 30938746f135SLuiz Augusto von Dentz * disconnecting. 309440b552aaSMarcel Holtmann */ 30958746f135SLuiz Augusto von Dentz hci_encrypt_cfm(conn, ev->status); 30968746f135SLuiz Augusto von Dentz hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); 309740b552aaSMarcel Holtmann hci_conn_drop(conn); 309840b552aaSMarcel Holtmann goto unlock; 309940b552aaSMarcel Holtmann } 310040b552aaSMarcel Holtmann 3101821f3766SJohan Hedberg /* Try reading the encryption key size for encrypted ACL links */ 3102821f3766SJohan Hedberg if (!ev->status && ev->encrypt && conn->type == ACL_LINK) { 3103821f3766SJohan Hedberg struct hci_cp_read_enc_key_size cp; 3104821f3766SJohan Hedberg struct hci_request req; 3105821f3766SJohan Hedberg 3106821f3766SJohan Hedberg /* Only send HCI_Read_Encryption_Key_Size if the 3107821f3766SJohan Hedberg * controller really supports it. If it doesn't, assume 3108821f3766SJohan Hedberg * the default size (16). 3109821f3766SJohan Hedberg */ 3110821f3766SJohan Hedberg if (!(hdev->commands[20] & 0x10)) { 3111821f3766SJohan Hedberg conn->enc_key_size = HCI_LINK_KEY_SIZE; 3112821f3766SJohan Hedberg goto notify; 3113821f3766SJohan Hedberg } 3114821f3766SJohan Hedberg 3115821f3766SJohan Hedberg hci_req_init(&req, hdev); 3116821f3766SJohan Hedberg 3117821f3766SJohan Hedberg cp.handle = cpu_to_le16(conn->handle); 3118821f3766SJohan Hedberg hci_req_add(&req, HCI_OP_READ_ENC_KEY_SIZE, sizeof(cp), &cp); 3119821f3766SJohan Hedberg 3120821f3766SJohan Hedberg if (hci_req_run_skb(&req, read_enc_key_size_complete)) { 31212064ee33SMarcel Holtmann bt_dev_err(hdev, "sending read key size failed"); 3122821f3766SJohan Hedberg conn->enc_key_size = HCI_LINK_KEY_SIZE; 3123821f3766SJohan Hedberg goto notify; 3124821f3766SJohan Hedberg } 3125821f3766SJohan Hedberg 3126821f3766SJohan Hedberg goto unlock; 3127821f3766SJohan Hedberg } 3128821f3766SJohan Hedberg 3129302975cbSSpoorthi Ravishankar Koppad /* Set the default Authenticated Payload Timeout after 3130302975cbSSpoorthi Ravishankar Koppad * an LE Link is established. As per Core Spec v5.0, Vol 2, Part B 3131302975cbSSpoorthi Ravishankar Koppad * Section 3.3, the HCI command WRITE_AUTH_PAYLOAD_TIMEOUT should be 3132302975cbSSpoorthi Ravishankar Koppad * sent when the link is active and Encryption is enabled, the conn 3133302975cbSSpoorthi Ravishankar Koppad * type can be either LE or ACL and controller must support LMP Ping. 3134302975cbSSpoorthi Ravishankar Koppad * Ensure for AES-CCM encryption as well. 3135302975cbSSpoorthi Ravishankar Koppad */ 3136302975cbSSpoorthi Ravishankar Koppad if (test_bit(HCI_CONN_ENCRYPT, &conn->flags) && 3137302975cbSSpoorthi Ravishankar Koppad test_bit(HCI_CONN_AES_CCM, &conn->flags) && 3138302975cbSSpoorthi Ravishankar Koppad ((conn->type == ACL_LINK && lmp_ping_capable(hdev)) || 3139302975cbSSpoorthi Ravishankar Koppad (conn->type == LE_LINK && (hdev->le_features[0] & HCI_LE_PING)))) { 3140302975cbSSpoorthi Ravishankar Koppad struct hci_cp_write_auth_payload_to cp; 3141302975cbSSpoorthi Ravishankar Koppad 3142302975cbSSpoorthi Ravishankar Koppad cp.handle = cpu_to_le16(conn->handle); 3143302975cbSSpoorthi Ravishankar Koppad cp.timeout = cpu_to_le16(hdev->auth_payload_timeout); 3144302975cbSSpoorthi Ravishankar Koppad hci_send_cmd(conn->hdev, HCI_OP_WRITE_AUTH_PAYLOAD_TO, 3145302975cbSSpoorthi Ravishankar Koppad sizeof(cp), &cp); 3146302975cbSSpoorthi Ravishankar Koppad } 3147302975cbSSpoorthi Ravishankar Koppad 3148821f3766SJohan Hedberg notify: 31493ca44c16SLuiz Augusto von Dentz hci_encrypt_cfm(conn, ev->status); 3150a9de9248SMarcel Holtmann 3151a7d7723aSGustavo Padovan unlock: 3152a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 3153a9de9248SMarcel Holtmann } 3154a9de9248SMarcel Holtmann 31556039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev, 3156807deac2SGustavo Padovan struct sk_buff *skb) 3157a9de9248SMarcel Holtmann { 3158a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 3159a9de9248SMarcel Holtmann struct hci_conn *conn; 3160a9de9248SMarcel Holtmann 31619f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 3162a9de9248SMarcel Holtmann 3163a9de9248SMarcel Holtmann hci_dev_lock(hdev); 3164a9de9248SMarcel Holtmann 3165a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3166a9de9248SMarcel Holtmann if (conn) { 3167a9de9248SMarcel Holtmann if (!ev->status) 31684dae2798SJohan Hedberg set_bit(HCI_CONN_SECURE, &conn->flags); 3169a9de9248SMarcel Holtmann 317051a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 3171a9de9248SMarcel Holtmann 3172a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 3173a9de9248SMarcel Holtmann } 3174a9de9248SMarcel Holtmann 3175a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 3176a9de9248SMarcel Holtmann } 3177a9de9248SMarcel Holtmann 31786039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev, 3179807deac2SGustavo Padovan struct sk_buff *skb) 3180a9de9248SMarcel Holtmann { 3181a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 3182a9de9248SMarcel Holtmann struct hci_conn *conn; 3183a9de9248SMarcel Holtmann 31849f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 3185a9de9248SMarcel Holtmann 3186a9de9248SMarcel Holtmann hci_dev_lock(hdev); 3187a9de9248SMarcel Holtmann 3188a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3189ccd556feSJohan Hedberg if (!conn) 3190ccd556feSJohan Hedberg goto unlock; 3191ccd556feSJohan Hedberg 3192769be974SMarcel Holtmann if (!ev->status) 3193cad718edSJohan Hedberg memcpy(conn->features[0], ev->features, 8); 3194a9de9248SMarcel Holtmann 3195ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 3196ccd556feSJohan Hedberg goto unlock; 3197ccd556feSJohan Hedberg 3198ac363cf9SSzymon Janc if (!ev->status && lmp_ext_feat_capable(hdev) && 3199ac363cf9SSzymon Janc lmp_ext_feat_capable(conn)) { 3200769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 3201769be974SMarcel Holtmann cp.handle = ev->handle; 3202769be974SMarcel Holtmann cp.page = 0x01; 3203ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 3204769be974SMarcel Holtmann sizeof(cp), &cp); 3205392599b9SJohan Hedberg goto unlock; 3206392599b9SJohan Hedberg } 3207392599b9SJohan Hedberg 3208671267bfSJohan Hedberg if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { 3209127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 3210127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 3211127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 3212127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 3213127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 3214b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 321548ec92faSAlfonso Acosta mgmt_device_connected(hdev, conn, 0, NULL, 0); 3216392599b9SJohan Hedberg 3217127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 3218769be974SMarcel Holtmann conn->state = BT_CONNECTED; 3219539c496dSJohan Hedberg hci_connect_cfm(conn, ev->status); 322076a68ba0SDavid Herrmann hci_conn_drop(conn); 3221769be974SMarcel Holtmann } 3222769be974SMarcel Holtmann 3223ccd556feSJohan Hedberg unlock: 3224a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 3225a9de9248SMarcel Holtmann } 3226a9de9248SMarcel Holtmann 3227e6214487SJohan Hedberg static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb, 3228e6214487SJohan Hedberg u16 *opcode, u8 *status, 3229e6214487SJohan Hedberg hci_req_complete_t *req_complete, 3230e6214487SJohan Hedberg hci_req_complete_skb_t *req_complete_skb) 3231a9de9248SMarcel Holtmann { 3232a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 3233e6214487SJohan Hedberg 3234e6214487SJohan Hedberg *opcode = __le16_to_cpu(ev->opcode); 3235e6214487SJohan Hedberg *status = skb->data[sizeof(*ev)]; 3236a9de9248SMarcel Holtmann 3237a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 3238a9de9248SMarcel Holtmann 3239e6214487SJohan Hedberg switch (*opcode) { 3240a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 3241adf1d692SSonny Sasaka hci_cc_inquiry_cancel(hdev, skb, status); 3242a9de9248SMarcel Holtmann break; 3243a9de9248SMarcel Holtmann 32444d93483bSAndre Guedes case HCI_OP_PERIODIC_INQ: 32454d93483bSAndre Guedes hci_cc_periodic_inq(hdev, skb); 32464d93483bSAndre Guedes break; 32474d93483bSAndre Guedes 3248a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 3249a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 3250a9de9248SMarcel Holtmann break; 3251a9de9248SMarcel Holtmann 3252a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 3253a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 3254a9de9248SMarcel Holtmann break; 3255a9de9248SMarcel Holtmann 3256a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 3257a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 3258a9de9248SMarcel Holtmann break; 3259a9de9248SMarcel Holtmann 3260e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 3261e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 3262e4e8e37cSMarcel Holtmann break; 3263e4e8e37cSMarcel Holtmann 3264a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 3265a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 3266a9de9248SMarcel Holtmann break; 3267a9de9248SMarcel Holtmann 3268e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 3269e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 3270e4e8e37cSMarcel Holtmann break; 3271e4e8e37cSMarcel Holtmann 3272e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 3273e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 3274e4e8e37cSMarcel Holtmann break; 3275e4e8e37cSMarcel Holtmann 3276a9de9248SMarcel Holtmann case HCI_OP_RESET: 3277a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 3278a9de9248SMarcel Holtmann break; 3279a9de9248SMarcel Holtmann 3280c2f0f979SMarcel Holtmann case HCI_OP_READ_STORED_LINK_KEY: 3281c2f0f979SMarcel Holtmann hci_cc_read_stored_link_key(hdev, skb); 3282c2f0f979SMarcel Holtmann break; 3283c2f0f979SMarcel Holtmann 3284a9366120SMarcel Holtmann case HCI_OP_DELETE_STORED_LINK_KEY: 3285a9366120SMarcel Holtmann hci_cc_delete_stored_link_key(hdev, skb); 3286a9366120SMarcel Holtmann break; 3287a9366120SMarcel Holtmann 3288a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 3289a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 3290a9de9248SMarcel Holtmann break; 3291a9de9248SMarcel Holtmann 3292a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 3293a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 3294a9de9248SMarcel Holtmann break; 3295a9de9248SMarcel Holtmann 3296a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 3297a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 3298a9de9248SMarcel Holtmann break; 3299a9de9248SMarcel Holtmann 3300a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 3301a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 3302a9de9248SMarcel Holtmann break; 3303a9de9248SMarcel Holtmann 3304a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 3305a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 3306a9de9248SMarcel Holtmann break; 3307a9de9248SMarcel Holtmann 3308a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 3309a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 3310a9de9248SMarcel Holtmann break; 3311a9de9248SMarcel Holtmann 3312a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 3313a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 3314a9de9248SMarcel Holtmann break; 3315a9de9248SMarcel Holtmann 3316a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 3317a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 3318a9de9248SMarcel Holtmann break; 3319a9de9248SMarcel Holtmann 3320a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 3321a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 3322a9de9248SMarcel Holtmann break; 3323a9de9248SMarcel Holtmann 3324b4cb9fb2SMarcel Holtmann case HCI_OP_READ_NUM_SUPPORTED_IAC: 3325b4cb9fb2SMarcel Holtmann hci_cc_read_num_supported_iac(hdev, skb); 3326b4cb9fb2SMarcel Holtmann break; 3327b4cb9fb2SMarcel Holtmann 3328333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 3329333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 3330333140b5SMarcel Holtmann break; 3331333140b5SMarcel Holtmann 3332eac83dc6SMarcel Holtmann case HCI_OP_WRITE_SC_SUPPORT: 3333eac83dc6SMarcel Holtmann hci_cc_write_sc_support(hdev, skb); 3334eac83dc6SMarcel Holtmann break; 3335eac83dc6SMarcel Holtmann 3336302975cbSSpoorthi Ravishankar Koppad case HCI_OP_READ_AUTH_PAYLOAD_TO: 3337302975cbSSpoorthi Ravishankar Koppad hci_cc_read_auth_payload_timeout(hdev, skb); 3338302975cbSSpoorthi Ravishankar Koppad break; 3339302975cbSSpoorthi Ravishankar Koppad 3340302975cbSSpoorthi Ravishankar Koppad case HCI_OP_WRITE_AUTH_PAYLOAD_TO: 3341302975cbSSpoorthi Ravishankar Koppad hci_cc_write_auth_payload_timeout(hdev, skb); 3342302975cbSSpoorthi Ravishankar Koppad break; 3343302975cbSSpoorthi Ravishankar Koppad 3344a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 3345a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 3346a9de9248SMarcel Holtmann break; 3347a9de9248SMarcel Holtmann 3348a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 3349a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 3350a9de9248SMarcel Holtmann break; 3351a9de9248SMarcel Holtmann 3352a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 3353a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 3354a9de9248SMarcel Holtmann break; 3355a9de9248SMarcel Holtmann 3356971e3a4bSAndre Guedes case HCI_OP_READ_LOCAL_EXT_FEATURES: 3357971e3a4bSAndre Guedes hci_cc_read_local_ext_features(hdev, skb); 3358971e3a4bSAndre Guedes break; 3359971e3a4bSAndre Guedes 3360a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 3361a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 3362a9de9248SMarcel Holtmann break; 3363a9de9248SMarcel Holtmann 3364a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 3365a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 3366a9de9248SMarcel Holtmann break; 3367a9de9248SMarcel Holtmann 3368a4790360SMarcel Holtmann case HCI_OP_READ_LOCAL_PAIRING_OPTS: 3369a4790360SMarcel Holtmann hci_cc_read_local_pairing_opts(hdev, skb); 3370a4790360SMarcel Holtmann break; 3371a4790360SMarcel Holtmann 3372f332ec66SJohan Hedberg case HCI_OP_READ_PAGE_SCAN_ACTIVITY: 3373f332ec66SJohan Hedberg hci_cc_read_page_scan_activity(hdev, skb); 3374f332ec66SJohan Hedberg break; 3375f332ec66SJohan Hedberg 33764a3ee763SJohan Hedberg case HCI_OP_WRITE_PAGE_SCAN_ACTIVITY: 33774a3ee763SJohan Hedberg hci_cc_write_page_scan_activity(hdev, skb); 33784a3ee763SJohan Hedberg break; 33794a3ee763SJohan Hedberg 3380f332ec66SJohan Hedberg case HCI_OP_READ_PAGE_SCAN_TYPE: 3381f332ec66SJohan Hedberg hci_cc_read_page_scan_type(hdev, skb); 3382f332ec66SJohan Hedberg break; 3383f332ec66SJohan Hedberg 33844a3ee763SJohan Hedberg case HCI_OP_WRITE_PAGE_SCAN_TYPE: 33854a3ee763SJohan Hedberg hci_cc_write_page_scan_type(hdev, skb); 33864a3ee763SJohan Hedberg break; 33874a3ee763SJohan Hedberg 3388350ee4cfSAndrei Emeltchenko case HCI_OP_READ_DATA_BLOCK_SIZE: 3389350ee4cfSAndrei Emeltchenko hci_cc_read_data_block_size(hdev, skb); 3390350ee4cfSAndrei Emeltchenko break; 3391350ee4cfSAndrei Emeltchenko 33921e89cffbSAndrei Emeltchenko case HCI_OP_READ_FLOW_CONTROL_MODE: 33931e89cffbSAndrei Emeltchenko hci_cc_read_flow_control_mode(hdev, skb); 33941e89cffbSAndrei Emeltchenko break; 33951e89cffbSAndrei Emeltchenko 3396928abaa7SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_INFO: 3397928abaa7SAndrei Emeltchenko hci_cc_read_local_amp_info(hdev, skb); 3398928abaa7SAndrei Emeltchenko break; 3399928abaa7SAndrei Emeltchenko 340033f35721SJohan Hedberg case HCI_OP_READ_CLOCK: 340133f35721SJohan Hedberg hci_cc_read_clock(hdev, skb); 340233f35721SJohan Hedberg break; 340333f35721SJohan Hedberg 3404d5859e22SJohan Hedberg case HCI_OP_READ_INQ_RSP_TX_POWER: 3405d5859e22SJohan Hedberg hci_cc_read_inq_rsp_tx_power(hdev, skb); 3406d5859e22SJohan Hedberg break; 3407d5859e22SJohan Hedberg 340800bce3fbSAlain Michaud case HCI_OP_READ_DEF_ERR_DATA_REPORTING: 340900bce3fbSAlain Michaud hci_cc_read_def_err_data_reporting(hdev, skb); 341000bce3fbSAlain Michaud break; 341100bce3fbSAlain Michaud 341200bce3fbSAlain Michaud case HCI_OP_WRITE_DEF_ERR_DATA_REPORTING: 341300bce3fbSAlain Michaud hci_cc_write_def_err_data_reporting(hdev, skb); 341400bce3fbSAlain Michaud break; 341500bce3fbSAlain Michaud 3416980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_REPLY: 3417980e1a53SJohan Hedberg hci_cc_pin_code_reply(hdev, skb); 3418980e1a53SJohan Hedberg break; 3419980e1a53SJohan Hedberg 3420980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_NEG_REPLY: 3421980e1a53SJohan Hedberg hci_cc_pin_code_neg_reply(hdev, skb); 3422980e1a53SJohan Hedberg break; 3423980e1a53SJohan Hedberg 3424c35938b2SSzymon Janc case HCI_OP_READ_LOCAL_OOB_DATA: 34254d2d2796SMarcel Holtmann hci_cc_read_local_oob_data(hdev, skb); 34264d2d2796SMarcel Holtmann break; 34274d2d2796SMarcel Holtmann 34284d2d2796SMarcel Holtmann case HCI_OP_READ_LOCAL_OOB_EXT_DATA: 34294d2d2796SMarcel Holtmann hci_cc_read_local_oob_ext_data(hdev, skb); 3430c35938b2SSzymon Janc break; 3431c35938b2SSzymon Janc 34326ed58ec5SVille Tervo case HCI_OP_LE_READ_BUFFER_SIZE: 34336ed58ec5SVille Tervo hci_cc_le_read_buffer_size(hdev, skb); 34346ed58ec5SVille Tervo break; 34356ed58ec5SVille Tervo 343660e77321SJohan Hedberg case HCI_OP_LE_READ_LOCAL_FEATURES: 343760e77321SJohan Hedberg hci_cc_le_read_local_features(hdev, skb); 343860e77321SJohan Hedberg break; 343960e77321SJohan Hedberg 34408fa19098SJohan Hedberg case HCI_OP_LE_READ_ADV_TX_POWER: 34418fa19098SJohan Hedberg hci_cc_le_read_adv_tx_power(hdev, skb); 34428fa19098SJohan Hedberg break; 34438fa19098SJohan Hedberg 3444a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_REPLY: 3445a5c29683SJohan Hedberg hci_cc_user_confirm_reply(hdev, skb); 3446a5c29683SJohan Hedberg break; 3447a5c29683SJohan Hedberg 3448a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_NEG_REPLY: 3449a5c29683SJohan Hedberg hci_cc_user_confirm_neg_reply(hdev, skb); 3450a5c29683SJohan Hedberg break; 3451a5c29683SJohan Hedberg 34521143d458SBrian Gix case HCI_OP_USER_PASSKEY_REPLY: 34531143d458SBrian Gix hci_cc_user_passkey_reply(hdev, skb); 34541143d458SBrian Gix break; 34551143d458SBrian Gix 34561143d458SBrian Gix case HCI_OP_USER_PASSKEY_NEG_REPLY: 34571143d458SBrian Gix hci_cc_user_passkey_neg_reply(hdev, skb); 345816cde993SSzymon Janc break; 345907f7fa5dSAndre Guedes 34607a4cd51dSMarcel Holtmann case HCI_OP_LE_SET_RANDOM_ADDR: 34617a4cd51dSMarcel Holtmann hci_cc_le_set_random_addr(hdev, skb); 34627a4cd51dSMarcel Holtmann break; 34637a4cd51dSMarcel Holtmann 3464c1d5dc4aSJohan Hedberg case HCI_OP_LE_SET_ADV_ENABLE: 3465c1d5dc4aSJohan Hedberg hci_cc_le_set_adv_enable(hdev, skb); 3466c1d5dc4aSJohan Hedberg break; 3467c1d5dc4aSJohan Hedberg 3468533553f8SMarcel Holtmann case HCI_OP_LE_SET_SCAN_PARAM: 3469533553f8SMarcel Holtmann hci_cc_le_set_scan_param(hdev, skb); 3470533553f8SMarcel Holtmann break; 3471533553f8SMarcel Holtmann 3472eb9d91f5SAndre Guedes case HCI_OP_LE_SET_SCAN_ENABLE: 3473eb9d91f5SAndre Guedes hci_cc_le_set_scan_enable(hdev, skb); 3474eb9d91f5SAndre Guedes break; 3475eb9d91f5SAndre Guedes 3476cf1d081fSJohan Hedberg case HCI_OP_LE_READ_WHITE_LIST_SIZE: 3477cf1d081fSJohan Hedberg hci_cc_le_read_white_list_size(hdev, skb); 3478cf1d081fSJohan Hedberg break; 3479cf1d081fSJohan Hedberg 34800f36b589SMarcel Holtmann case HCI_OP_LE_CLEAR_WHITE_LIST: 34810f36b589SMarcel Holtmann hci_cc_le_clear_white_list(hdev, skb); 34820f36b589SMarcel Holtmann break; 34830f36b589SMarcel Holtmann 34840f36b589SMarcel Holtmann case HCI_OP_LE_ADD_TO_WHITE_LIST: 34850f36b589SMarcel Holtmann hci_cc_le_add_to_white_list(hdev, skb); 34860f36b589SMarcel Holtmann break; 34870f36b589SMarcel Holtmann 34880f36b589SMarcel Holtmann case HCI_OP_LE_DEL_FROM_WHITE_LIST: 34890f36b589SMarcel Holtmann hci_cc_le_del_from_white_list(hdev, skb); 34900f36b589SMarcel Holtmann break; 34910f36b589SMarcel Holtmann 34929b008c04SJohan Hedberg case HCI_OP_LE_READ_SUPPORTED_STATES: 34939b008c04SJohan Hedberg hci_cc_le_read_supported_states(hdev, skb); 34949b008c04SJohan Hedberg break; 34959b008c04SJohan Hedberg 3496a8e1bfaaSMarcel Holtmann case HCI_OP_LE_READ_DEF_DATA_LEN: 3497a8e1bfaaSMarcel Holtmann hci_cc_le_read_def_data_len(hdev, skb); 3498a8e1bfaaSMarcel Holtmann break; 3499a8e1bfaaSMarcel Holtmann 3500a8e1bfaaSMarcel Holtmann case HCI_OP_LE_WRITE_DEF_DATA_LEN: 3501a8e1bfaaSMarcel Holtmann hci_cc_le_write_def_data_len(hdev, skb); 3502a8e1bfaaSMarcel Holtmann break; 3503a8e1bfaaSMarcel Holtmann 3504b950aa88SAnkit Navik case HCI_OP_LE_ADD_TO_RESOLV_LIST: 3505b950aa88SAnkit Navik hci_cc_le_add_to_resolv_list(hdev, skb); 3506b950aa88SAnkit Navik break; 3507b950aa88SAnkit Navik 3508b950aa88SAnkit Navik case HCI_OP_LE_DEL_FROM_RESOLV_LIST: 3509b950aa88SAnkit Navik hci_cc_le_del_from_resolv_list(hdev, skb); 3510b950aa88SAnkit Navik break; 3511b950aa88SAnkit Navik 3512545f2596SAnkit Navik case HCI_OP_LE_CLEAR_RESOLV_LIST: 3513545f2596SAnkit Navik hci_cc_le_clear_resolv_list(hdev, skb); 3514545f2596SAnkit Navik break; 3515545f2596SAnkit Navik 3516cfdb0c2dSAnkit Navik case HCI_OP_LE_READ_RESOLV_LIST_SIZE: 3517cfdb0c2dSAnkit Navik hci_cc_le_read_resolv_list_size(hdev, skb); 3518cfdb0c2dSAnkit Navik break; 3519cfdb0c2dSAnkit Navik 3520aa12af77SAnkit Navik case HCI_OP_LE_SET_ADDR_RESOLV_ENABLE: 3521aa12af77SAnkit Navik hci_cc_le_set_addr_resolution_enable(hdev, skb); 3522aa12af77SAnkit Navik break; 3523aa12af77SAnkit Navik 3524a8e1bfaaSMarcel Holtmann case HCI_OP_LE_READ_MAX_DATA_LEN: 3525a8e1bfaaSMarcel Holtmann hci_cc_le_read_max_data_len(hdev, skb); 3526a8e1bfaaSMarcel Holtmann break; 3527a8e1bfaaSMarcel Holtmann 3528f9b49306SAndre Guedes case HCI_OP_WRITE_LE_HOST_SUPPORTED: 3529f9b49306SAndre Guedes hci_cc_write_le_host_supported(hdev, skb); 3530f9b49306SAndre Guedes break; 3531f9b49306SAndre Guedes 353256ed2cb8SJohan Hedberg case HCI_OP_LE_SET_ADV_PARAM: 353356ed2cb8SJohan Hedberg hci_cc_set_adv_param(hdev, skb); 353456ed2cb8SJohan Hedberg break; 353556ed2cb8SJohan Hedberg 35365ae76a94SAndrzej Kaczmarek case HCI_OP_READ_RSSI: 35375ae76a94SAndrzej Kaczmarek hci_cc_read_rssi(hdev, skb); 35385ae76a94SAndrzej Kaczmarek break; 35395ae76a94SAndrzej Kaczmarek 35405a134faeSAndrzej Kaczmarek case HCI_OP_READ_TX_POWER: 35415a134faeSAndrzej Kaczmarek hci_cc_read_tx_power(hdev, skb); 35425a134faeSAndrzej Kaczmarek break; 35435a134faeSAndrzej Kaczmarek 3544c50b33c8SMarcel Holtmann case HCI_OP_WRITE_SSP_DEBUG_MODE: 3545c50b33c8SMarcel Holtmann hci_cc_write_ssp_debug_mode(hdev, skb); 3546c50b33c8SMarcel Holtmann break; 3547c50b33c8SMarcel Holtmann 3548a2344b9eSJaganath Kanakkassery case HCI_OP_LE_SET_EXT_SCAN_PARAMS: 3549a2344b9eSJaganath Kanakkassery hci_cc_le_set_ext_scan_param(hdev, skb); 3550a2344b9eSJaganath Kanakkassery break; 3551a2344b9eSJaganath Kanakkassery 3552a2344b9eSJaganath Kanakkassery case HCI_OP_LE_SET_EXT_SCAN_ENABLE: 3553a2344b9eSJaganath Kanakkassery hci_cc_le_set_ext_scan_enable(hdev, skb); 3554a2344b9eSJaganath Kanakkassery break; 3555a2344b9eSJaganath Kanakkassery 35560314f286SJaganath Kanakkassery case HCI_OP_LE_SET_DEFAULT_PHY: 35570314f286SJaganath Kanakkassery hci_cc_le_set_default_phy(hdev, skb); 35580314f286SJaganath Kanakkassery break; 35590314f286SJaganath Kanakkassery 35606b49bcb4SJaganath Kanakkassery case HCI_OP_LE_READ_NUM_SUPPORTED_ADV_SETS: 35616b49bcb4SJaganath Kanakkassery hci_cc_le_read_num_adv_sets(hdev, skb); 35626b49bcb4SJaganath Kanakkassery break; 35636b49bcb4SJaganath Kanakkassery 3564de181e88SJaganath Kanakkassery case HCI_OP_LE_SET_EXT_ADV_PARAMS: 3565de181e88SJaganath Kanakkassery hci_cc_set_ext_adv_param(hdev, skb); 3566de181e88SJaganath Kanakkassery break; 3567de181e88SJaganath Kanakkassery 3568de181e88SJaganath Kanakkassery case HCI_OP_LE_SET_EXT_ADV_ENABLE: 3569de181e88SJaganath Kanakkassery hci_cc_le_set_ext_adv_enable(hdev, skb); 3570de181e88SJaganath Kanakkassery break; 3571de181e88SJaganath Kanakkassery 3572a73c046aSJaganath Kanakkassery case HCI_OP_LE_SET_ADV_SET_RAND_ADDR: 3573a73c046aSJaganath Kanakkassery hci_cc_le_set_adv_set_random_addr(hdev, skb); 3574a73c046aSJaganath Kanakkassery break; 3575a73c046aSJaganath Kanakkassery 3576a9de9248SMarcel Holtmann default: 3577e6214487SJohan Hedberg BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode); 3578a9de9248SMarcel Holtmann break; 3579a9de9248SMarcel Holtmann } 3580a9de9248SMarcel Holtmann 3581e6214487SJohan Hedberg if (*opcode != HCI_OP_NOP) 358265cc2b49SMarcel Holtmann cancel_delayed_work(&hdev->cmd_timer); 35836bd32326SVille Tervo 3584600b2150SJohan Hedberg if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) 3585600b2150SJohan Hedberg atomic_set(&hdev->cmd_cnt, 1); 3586600b2150SJohan Hedberg 3587e6214487SJohan Hedberg hci_req_cmd_complete(hdev, *opcode, *status, req_complete, 3588e6214487SJohan Hedberg req_complete_skb); 35899238f36aSJohan Hedberg 3590f80c5dadSJoão Paulo Rechi Vita if (hci_dev_test_flag(hdev, HCI_CMD_PENDING)) { 3591f80c5dadSJoão Paulo Rechi Vita bt_dev_err(hdev, 3592f80c5dadSJoão Paulo Rechi Vita "unexpected event for opcode 0x%4.4x", *opcode); 3593f80c5dadSJoão Paulo Rechi Vita return; 3594f80c5dadSJoão Paulo Rechi Vita } 3595f80c5dadSJoão Paulo Rechi Vita 3596600b2150SJohan Hedberg if (atomic_read(&hdev->cmd_cnt) && !skb_queue_empty(&hdev->cmd_q)) 3597c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 3598a9de9248SMarcel Holtmann } 3599a9de9248SMarcel Holtmann 3600e6214487SJohan Hedberg static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb, 3601e6214487SJohan Hedberg u16 *opcode, u8 *status, 3602e6214487SJohan Hedberg hci_req_complete_t *req_complete, 3603e6214487SJohan Hedberg hci_req_complete_skb_t *req_complete_skb) 3604a9de9248SMarcel Holtmann { 3605a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 3606a9de9248SMarcel Holtmann 3607a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 3608a9de9248SMarcel Holtmann 3609e6214487SJohan Hedberg *opcode = __le16_to_cpu(ev->opcode); 3610e6214487SJohan Hedberg *status = ev->status; 3611a9de9248SMarcel Holtmann 3612e6214487SJohan Hedberg switch (*opcode) { 3613a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 3614a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 3615a9de9248SMarcel Holtmann break; 3616a9de9248SMarcel Holtmann 3617a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 3618a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 3619a9de9248SMarcel Holtmann break; 3620a9de9248SMarcel Holtmann 36219645c76cSKuba Pawlak case HCI_OP_DISCONNECT: 36229645c76cSKuba Pawlak hci_cs_disconnect(hdev, ev->status); 36239645c76cSKuba Pawlak break; 36249645c76cSKuba Pawlak 3625a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 3626a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 3627a9de9248SMarcel Holtmann break; 3628a9de9248SMarcel Holtmann 3629f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 3630f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 3631f8558555SMarcel Holtmann break; 3632f8558555SMarcel Holtmann 3633f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 3634f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 3635f8558555SMarcel Holtmann break; 3636f8558555SMarcel Holtmann 3637a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 3638a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 3639a9de9248SMarcel Holtmann break; 3640a9de9248SMarcel Holtmann 3641769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 3642769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 3643769be974SMarcel Holtmann break; 3644769be974SMarcel Holtmann 3645769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 3646769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 3647769be974SMarcel Holtmann break; 3648769be974SMarcel Holtmann 3649a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 3650a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 3651a9de9248SMarcel Holtmann break; 3652a9de9248SMarcel Holtmann 3653a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 3654a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 3655a9de9248SMarcel Holtmann break; 3656a9de9248SMarcel Holtmann 3657a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 3658a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 3659a9de9248SMarcel Holtmann break; 3660a9de9248SMarcel Holtmann 366150fc85f1SKuba Pawlak case HCI_OP_SWITCH_ROLE: 366250fc85f1SKuba Pawlak hci_cs_switch_role(hdev, ev->status); 366350fc85f1SKuba Pawlak break; 366450fc85f1SKuba Pawlak 3665cb1d68f7SJohan Hedberg case HCI_OP_LE_CREATE_CONN: 3666cb1d68f7SJohan Hedberg hci_cs_le_create_conn(hdev, ev->status); 3667cb1d68f7SJohan Hedberg break; 3668cb1d68f7SJohan Hedberg 36690fe29fd1SMarcel Holtmann case HCI_OP_LE_READ_REMOTE_FEATURES: 36700fe29fd1SMarcel Holtmann hci_cs_le_read_remote_features(hdev, ev->status); 36710fe29fd1SMarcel Holtmann break; 36720fe29fd1SMarcel Holtmann 367381d0c8adSJohan Hedberg case HCI_OP_LE_START_ENC: 367481d0c8adSJohan Hedberg hci_cs_le_start_enc(hdev, ev->status); 367581d0c8adSJohan Hedberg break; 367681d0c8adSJohan Hedberg 36774d94f95dSJaganath Kanakkassery case HCI_OP_LE_EXT_CREATE_CONN: 36784d94f95dSJaganath Kanakkassery hci_cs_le_ext_create_conn(hdev, ev->status); 36794d94f95dSJaganath Kanakkassery break; 36804d94f95dSJaganath Kanakkassery 3681a9de9248SMarcel Holtmann default: 3682e6214487SJohan Hedberg BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode); 3683a9de9248SMarcel Holtmann break; 3684a9de9248SMarcel Holtmann } 3685a9de9248SMarcel Holtmann 3686e6214487SJohan Hedberg if (*opcode != HCI_OP_NOP) 368765cc2b49SMarcel Holtmann cancel_delayed_work(&hdev->cmd_timer); 36886bd32326SVille Tervo 3689600b2150SJohan Hedberg if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) 3690600b2150SJohan Hedberg atomic_set(&hdev->cmd_cnt, 1); 3691600b2150SJohan Hedberg 3692444c6dd5SJohan Hedberg /* Indicate request completion if the command failed. Also, if 3693444c6dd5SJohan Hedberg * we're not waiting for a special event and we get a success 3694444c6dd5SJohan Hedberg * command status we should try to flag the request as completed 3695444c6dd5SJohan Hedberg * (since for this kind of commands there will not be a command 3696444c6dd5SJohan Hedberg * complete event). 3697444c6dd5SJohan Hedberg */ 369802350a72SJohan Hedberg if (ev->status || 3699242c0ebdSMarcel Holtmann (hdev->sent_cmd && !bt_cb(hdev->sent_cmd)->hci.req_event)) 3700e6214487SJohan Hedberg hci_req_cmd_complete(hdev, *opcode, ev->status, req_complete, 3701e6214487SJohan Hedberg req_complete_skb); 37029238f36aSJohan Hedberg 3703f80c5dadSJoão Paulo Rechi Vita if (hci_dev_test_flag(hdev, HCI_CMD_PENDING)) { 3704f80c5dadSJoão Paulo Rechi Vita bt_dev_err(hdev, 3705f80c5dadSJoão Paulo Rechi Vita "unexpected event for opcode 0x%4.4x", *opcode); 3706f80c5dadSJoão Paulo Rechi Vita return; 3707f80c5dadSJoão Paulo Rechi Vita } 3708f80c5dadSJoão Paulo Rechi Vita 3709600b2150SJohan Hedberg if (atomic_read(&hdev->cmd_cnt) && !skb_queue_empty(&hdev->cmd_q)) 3710c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 3711a9de9248SMarcel Holtmann } 3712a9de9248SMarcel Holtmann 371324dfa343SMarcel Holtmann static void hci_hardware_error_evt(struct hci_dev *hdev, struct sk_buff *skb) 371424dfa343SMarcel Holtmann { 371524dfa343SMarcel Holtmann struct hci_ev_hardware_error *ev = (void *) skb->data; 371624dfa343SMarcel Holtmann 3717c7741d16SMarcel Holtmann hdev->hw_error_code = ev->code; 3718c7741d16SMarcel Holtmann 3719c7741d16SMarcel Holtmann queue_work(hdev->req_workqueue, &hdev->error_reset); 372024dfa343SMarcel Holtmann } 372124dfa343SMarcel Holtmann 37226039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 3723a9de9248SMarcel Holtmann { 3724a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 3725a9de9248SMarcel Holtmann struct hci_conn *conn; 3726a9de9248SMarcel Holtmann 37279f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 3728a9de9248SMarcel Holtmann 3729a9de9248SMarcel Holtmann hci_dev_lock(hdev); 3730a9de9248SMarcel Holtmann 3731a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 3732a9de9248SMarcel Holtmann if (conn) { 373340bef302SJohan Hedberg if (!ev->status) 373440bef302SJohan Hedberg conn->role = ev->role; 3735a9de9248SMarcel Holtmann 373651a8efd7SJohan Hedberg clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); 3737a9de9248SMarcel Holtmann 3738a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 3739a9de9248SMarcel Holtmann } 3740a9de9248SMarcel Holtmann 3741a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 3742a9de9248SMarcel Holtmann } 3743a9de9248SMarcel Holtmann 37446039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 37451da177e4SLinus Torvalds { 3746a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 37471da177e4SLinus Torvalds int i; 37481da177e4SLinus Torvalds 374932ac5b9bSAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) { 37502064ee33SMarcel Holtmann bt_dev_err(hdev, "wrong event for mode %d", hdev->flow_ctl_mode); 375132ac5b9bSAndrei Emeltchenko return; 375232ac5b9bSAndrei Emeltchenko } 375332ac5b9bSAndrei Emeltchenko 375416e18342SGustavo A. R. Silva if (skb->len < sizeof(*ev) || 375516e18342SGustavo A. R. Silva skb->len < struct_size(ev, handles, ev->num_hndl)) { 37561da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 37571da177e4SLinus Torvalds return; 37581da177e4SLinus Torvalds } 37591da177e4SLinus Torvalds 3760c5993de8SAndrei Emeltchenko BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 3761c5993de8SAndrei Emeltchenko 3762613a1c0cSAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 3763613a1c0cSAndrei Emeltchenko struct hci_comp_pkts_info *info = &ev->handles[i]; 37641da177e4SLinus Torvalds struct hci_conn *conn; 37651da177e4SLinus Torvalds __u16 handle, count; 37661da177e4SLinus Torvalds 3767613a1c0cSAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 3768613a1c0cSAndrei Emeltchenko count = __le16_to_cpu(info->count); 37691da177e4SLinus Torvalds 37701da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 3771f4280918SAndrei Emeltchenko if (!conn) 3772f4280918SAndrei Emeltchenko continue; 3773f4280918SAndrei Emeltchenko 37741da177e4SLinus Torvalds conn->sent -= count; 37751da177e4SLinus Torvalds 3776f4280918SAndrei Emeltchenko switch (conn->type) { 3777f4280918SAndrei Emeltchenko case ACL_LINK: 377870f23020SAndrei Emeltchenko hdev->acl_cnt += count; 377970f23020SAndrei Emeltchenko if (hdev->acl_cnt > hdev->acl_pkts) 37801da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 3781f4280918SAndrei Emeltchenko break; 3782f4280918SAndrei Emeltchenko 3783f4280918SAndrei Emeltchenko case LE_LINK: 37846ed58ec5SVille Tervo if (hdev->le_pkts) { 37856ed58ec5SVille Tervo hdev->le_cnt += count; 37866ed58ec5SVille Tervo if (hdev->le_cnt > hdev->le_pkts) 37876ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 37886ed58ec5SVille Tervo } else { 37896ed58ec5SVille Tervo hdev->acl_cnt += count; 37906ed58ec5SVille Tervo if (hdev->acl_cnt > hdev->acl_pkts) 37916ed58ec5SVille Tervo hdev->acl_cnt = hdev->acl_pkts; 37926ed58ec5SVille Tervo } 3793f4280918SAndrei Emeltchenko break; 3794f4280918SAndrei Emeltchenko 3795f4280918SAndrei Emeltchenko case SCO_LINK: 379670f23020SAndrei Emeltchenko hdev->sco_cnt += count; 379770f23020SAndrei Emeltchenko if (hdev->sco_cnt > hdev->sco_pkts) 37985b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 3799f4280918SAndrei Emeltchenko break; 3800f4280918SAndrei Emeltchenko 3801f4280918SAndrei Emeltchenko default: 38022064ee33SMarcel Holtmann bt_dev_err(hdev, "unknown type %d conn %p", 38032064ee33SMarcel Holtmann conn->type, conn); 3804f4280918SAndrei Emeltchenko break; 38051da177e4SLinus Torvalds } 38061da177e4SLinus Torvalds } 3807a9de9248SMarcel Holtmann 38083eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 38091da177e4SLinus Torvalds } 38101da177e4SLinus Torvalds 381176ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev, 381276ef7cf7SAndrei Emeltchenko __u16 handle) 381376ef7cf7SAndrei Emeltchenko { 381476ef7cf7SAndrei Emeltchenko struct hci_chan *chan; 381576ef7cf7SAndrei Emeltchenko 381676ef7cf7SAndrei Emeltchenko switch (hdev->dev_type) { 3817ca8bee5dSMarcel Holtmann case HCI_PRIMARY: 381876ef7cf7SAndrei Emeltchenko return hci_conn_hash_lookup_handle(hdev, handle); 381976ef7cf7SAndrei Emeltchenko case HCI_AMP: 382076ef7cf7SAndrei Emeltchenko chan = hci_chan_lookup_handle(hdev, handle); 382176ef7cf7SAndrei Emeltchenko if (chan) 382276ef7cf7SAndrei Emeltchenko return chan->conn; 382376ef7cf7SAndrei Emeltchenko break; 382476ef7cf7SAndrei Emeltchenko default: 38252064ee33SMarcel Holtmann bt_dev_err(hdev, "unknown dev_type %d", hdev->dev_type); 382676ef7cf7SAndrei Emeltchenko break; 382776ef7cf7SAndrei Emeltchenko } 382876ef7cf7SAndrei Emeltchenko 382976ef7cf7SAndrei Emeltchenko return NULL; 383076ef7cf7SAndrei Emeltchenko } 383176ef7cf7SAndrei Emeltchenko 38326039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb) 383325e89e99SAndrei Emeltchenko { 383425e89e99SAndrei Emeltchenko struct hci_ev_num_comp_blocks *ev = (void *) skb->data; 383525e89e99SAndrei Emeltchenko int i; 383625e89e99SAndrei Emeltchenko 383725e89e99SAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) { 38382064ee33SMarcel Holtmann bt_dev_err(hdev, "wrong event for mode %d", hdev->flow_ctl_mode); 383925e89e99SAndrei Emeltchenko return; 384025e89e99SAndrei Emeltchenko } 384125e89e99SAndrei Emeltchenko 384216e18342SGustavo A. R. Silva if (skb->len < sizeof(*ev) || 384316e18342SGustavo A. R. Silva skb->len < struct_size(ev, handles, ev->num_hndl)) { 384425e89e99SAndrei Emeltchenko BT_DBG("%s bad parameters", hdev->name); 384525e89e99SAndrei Emeltchenko return; 384625e89e99SAndrei Emeltchenko } 384725e89e99SAndrei Emeltchenko 384825e89e99SAndrei Emeltchenko BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks, 384925e89e99SAndrei Emeltchenko ev->num_hndl); 385025e89e99SAndrei Emeltchenko 385125e89e99SAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 385225e89e99SAndrei Emeltchenko struct hci_comp_blocks_info *info = &ev->handles[i]; 385376ef7cf7SAndrei Emeltchenko struct hci_conn *conn = NULL; 385425e89e99SAndrei Emeltchenko __u16 handle, block_count; 385525e89e99SAndrei Emeltchenko 385625e89e99SAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 385725e89e99SAndrei Emeltchenko block_count = __le16_to_cpu(info->blocks); 385825e89e99SAndrei Emeltchenko 385976ef7cf7SAndrei Emeltchenko conn = __hci_conn_lookup_handle(hdev, handle); 386025e89e99SAndrei Emeltchenko if (!conn) 386125e89e99SAndrei Emeltchenko continue; 386225e89e99SAndrei Emeltchenko 386325e89e99SAndrei Emeltchenko conn->sent -= block_count; 386425e89e99SAndrei Emeltchenko 386525e89e99SAndrei Emeltchenko switch (conn->type) { 386625e89e99SAndrei Emeltchenko case ACL_LINK: 3867bd1eb66bSAndrei Emeltchenko case AMP_LINK: 386825e89e99SAndrei Emeltchenko hdev->block_cnt += block_count; 386925e89e99SAndrei Emeltchenko if (hdev->block_cnt > hdev->num_blocks) 387025e89e99SAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 387125e89e99SAndrei Emeltchenko break; 387225e89e99SAndrei Emeltchenko 387325e89e99SAndrei Emeltchenko default: 38742064ee33SMarcel Holtmann bt_dev_err(hdev, "unknown type %d conn %p", 38752064ee33SMarcel Holtmann conn->type, conn); 387625e89e99SAndrei Emeltchenko break; 387725e89e99SAndrei Emeltchenko } 387825e89e99SAndrei Emeltchenko } 387925e89e99SAndrei Emeltchenko 388025e89e99SAndrei Emeltchenko queue_work(hdev->workqueue, &hdev->tx_work); 388125e89e99SAndrei Emeltchenko } 388225e89e99SAndrei Emeltchenko 38836039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 38841da177e4SLinus Torvalds { 3885a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 388604837f64SMarcel Holtmann struct hci_conn *conn; 38871da177e4SLinus Torvalds 38889f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 38891da177e4SLinus Torvalds 38901da177e4SLinus Torvalds hci_dev_lock(hdev); 38911da177e4SLinus Torvalds 389204837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 389304837f64SMarcel Holtmann if (conn) { 389404837f64SMarcel Holtmann conn->mode = ev->mode; 389504837f64SMarcel Holtmann 38968fc9ced3SGustavo Padovan if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, 38978fc9ced3SGustavo Padovan &conn->flags)) { 389804837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 389958a681efSJohan Hedberg set_bit(HCI_CONN_POWER_SAVE, &conn->flags); 390004837f64SMarcel Holtmann else 390158a681efSJohan Hedberg clear_bit(HCI_CONN_POWER_SAVE, &conn->flags); 390204837f64SMarcel Holtmann } 3903e73439d8SMarcel Holtmann 390451a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 3905e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 390604837f64SMarcel Holtmann } 390704837f64SMarcel Holtmann 390804837f64SMarcel Holtmann hci_dev_unlock(hdev); 390904837f64SMarcel Holtmann } 391004837f64SMarcel Holtmann 39116039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 39121da177e4SLinus Torvalds { 3913052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 3914052b30b0SMarcel Holtmann struct hci_conn *conn; 3915052b30b0SMarcel Holtmann 3916a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 3917052b30b0SMarcel Holtmann 3918052b30b0SMarcel Holtmann hci_dev_lock(hdev); 3919052b30b0SMarcel Holtmann 3920052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 3921b6f98044SWaldemar Rymarkiewicz if (!conn) 3922b6f98044SWaldemar Rymarkiewicz goto unlock; 3923b6f98044SWaldemar Rymarkiewicz 3924b6f98044SWaldemar Rymarkiewicz if (conn->state == BT_CONNECTED) { 3925052b30b0SMarcel Holtmann hci_conn_hold(conn); 3926052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 392776a68ba0SDavid Herrmann hci_conn_drop(conn); 3928052b30b0SMarcel Holtmann } 3929052b30b0SMarcel Holtmann 3930d7a5a11dSMarcel Holtmann if (!hci_dev_test_flag(hdev, HCI_BONDABLE) && 39312f407f0aSJohan Hedberg !test_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags)) { 393203b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 393303b555e1SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 3934d7a5a11dSMarcel Holtmann } else if (hci_dev_test_flag(hdev, HCI_MGMT)) { 3935a770bb5aSWaldemar Rymarkiewicz u8 secure; 3936a770bb5aSWaldemar Rymarkiewicz 3937a770bb5aSWaldemar Rymarkiewicz if (conn->pending_sec_level == BT_SECURITY_HIGH) 3938a770bb5aSWaldemar Rymarkiewicz secure = 1; 3939a770bb5aSWaldemar Rymarkiewicz else 3940a770bb5aSWaldemar Rymarkiewicz secure = 0; 3941a770bb5aSWaldemar Rymarkiewicz 3942744cf19eSJohan Hedberg mgmt_pin_code_request(hdev, &ev->bdaddr, secure); 3943a770bb5aSWaldemar Rymarkiewicz } 3944980e1a53SJohan Hedberg 3945b6f98044SWaldemar Rymarkiewicz unlock: 3946052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 39471da177e4SLinus Torvalds } 39481da177e4SLinus Torvalds 3949cb6f3f7aSJohan Hedberg static void conn_set_key(struct hci_conn *conn, u8 key_type, u8 pin_len) 3950cb6f3f7aSJohan Hedberg { 3951cb6f3f7aSJohan Hedberg if (key_type == HCI_LK_CHANGED_COMBINATION) 3952cb6f3f7aSJohan Hedberg return; 3953cb6f3f7aSJohan Hedberg 3954cb6f3f7aSJohan Hedberg conn->pin_length = pin_len; 3955cb6f3f7aSJohan Hedberg conn->key_type = key_type; 3956cb6f3f7aSJohan Hedberg 3957cb6f3f7aSJohan Hedberg switch (key_type) { 3958cb6f3f7aSJohan Hedberg case HCI_LK_LOCAL_UNIT: 3959cb6f3f7aSJohan Hedberg case HCI_LK_REMOTE_UNIT: 3960cb6f3f7aSJohan Hedberg case HCI_LK_DEBUG_COMBINATION: 3961cb6f3f7aSJohan Hedberg return; 3962cb6f3f7aSJohan Hedberg case HCI_LK_COMBINATION: 3963cb6f3f7aSJohan Hedberg if (pin_len == 16) 3964cb6f3f7aSJohan Hedberg conn->pending_sec_level = BT_SECURITY_HIGH; 3965cb6f3f7aSJohan Hedberg else 3966cb6f3f7aSJohan Hedberg conn->pending_sec_level = BT_SECURITY_MEDIUM; 3967cb6f3f7aSJohan Hedberg break; 3968cb6f3f7aSJohan Hedberg case HCI_LK_UNAUTH_COMBINATION_P192: 3969cb6f3f7aSJohan Hedberg case HCI_LK_UNAUTH_COMBINATION_P256: 3970cb6f3f7aSJohan Hedberg conn->pending_sec_level = BT_SECURITY_MEDIUM; 3971cb6f3f7aSJohan Hedberg break; 3972cb6f3f7aSJohan Hedberg case HCI_LK_AUTH_COMBINATION_P192: 3973cb6f3f7aSJohan Hedberg conn->pending_sec_level = BT_SECURITY_HIGH; 3974cb6f3f7aSJohan Hedberg break; 3975cb6f3f7aSJohan Hedberg case HCI_LK_AUTH_COMBINATION_P256: 3976cb6f3f7aSJohan Hedberg conn->pending_sec_level = BT_SECURITY_FIPS; 3977cb6f3f7aSJohan Hedberg break; 3978cb6f3f7aSJohan Hedberg } 3979cb6f3f7aSJohan Hedberg } 3980cb6f3f7aSJohan Hedberg 39816039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 39821da177e4SLinus Torvalds { 398355ed8ca1SJohan Hedberg struct hci_ev_link_key_req *ev = (void *) skb->data; 398455ed8ca1SJohan Hedberg struct hci_cp_link_key_reply cp; 398555ed8ca1SJohan Hedberg struct hci_conn *conn; 398655ed8ca1SJohan Hedberg struct link_key *key; 398755ed8ca1SJohan Hedberg 3988a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 398955ed8ca1SJohan Hedberg 3990d7a5a11dSMarcel Holtmann if (!hci_dev_test_flag(hdev, HCI_MGMT)) 399155ed8ca1SJohan Hedberg return; 399255ed8ca1SJohan Hedberg 399355ed8ca1SJohan Hedberg hci_dev_lock(hdev); 399455ed8ca1SJohan Hedberg 399555ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, &ev->bdaddr); 399655ed8ca1SJohan Hedberg if (!key) { 39976ed93dc6SAndrei Emeltchenko BT_DBG("%s link key not found for %pMR", hdev->name, 39986ed93dc6SAndrei Emeltchenko &ev->bdaddr); 399955ed8ca1SJohan Hedberg goto not_found; 400055ed8ca1SJohan Hedberg } 400155ed8ca1SJohan Hedberg 40026ed93dc6SAndrei Emeltchenko BT_DBG("%s found key type %u for %pMR", hdev->name, key->type, 40036ed93dc6SAndrei Emeltchenko &ev->bdaddr); 400455ed8ca1SJohan Hedberg 400555ed8ca1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 400660b83f57SWaldemar Rymarkiewicz if (conn) { 4007fe8bc5acSJohan Hedberg clear_bit(HCI_CONN_NEW_LINK_KEY, &conn->flags); 4008fe8bc5acSJohan Hedberg 400966138ce8SMarcel Holtmann if ((key->type == HCI_LK_UNAUTH_COMBINATION_P192 || 401066138ce8SMarcel Holtmann key->type == HCI_LK_UNAUTH_COMBINATION_P256) && 4011807deac2SGustavo Padovan conn->auth_type != 0xff && (conn->auth_type & 0x01)) { 401255ed8ca1SJohan Hedberg BT_DBG("%s ignoring unauthenticated key", hdev->name); 401355ed8ca1SJohan Hedberg goto not_found; 401455ed8ca1SJohan Hedberg } 401555ed8ca1SJohan Hedberg 401660b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && 4017f3fb0b58SJohan Hedberg (conn->pending_sec_level == BT_SECURITY_HIGH || 4018f3fb0b58SJohan Hedberg conn->pending_sec_level == BT_SECURITY_FIPS)) { 40198fc9ced3SGustavo Padovan BT_DBG("%s ignoring key unauthenticated for high security", 40208fc9ced3SGustavo Padovan hdev->name); 402160b83f57SWaldemar Rymarkiewicz goto not_found; 402260b83f57SWaldemar Rymarkiewicz } 402360b83f57SWaldemar Rymarkiewicz 4024cb6f3f7aSJohan Hedberg conn_set_key(conn, key->type, key->pin_len); 402560b83f57SWaldemar Rymarkiewicz } 402660b83f57SWaldemar Rymarkiewicz 402755ed8ca1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 40289b3b4460SAndrei Emeltchenko memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE); 402955ed8ca1SJohan Hedberg 403055ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 403155ed8ca1SJohan Hedberg 403255ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 403355ed8ca1SJohan Hedberg 403455ed8ca1SJohan Hedberg return; 403555ed8ca1SJohan Hedberg 403655ed8ca1SJohan Hedberg not_found: 403755ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 403855ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 40391da177e4SLinus Torvalds } 40401da177e4SLinus Torvalds 40416039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 40421da177e4SLinus Torvalds { 4043052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 4044052b30b0SMarcel Holtmann struct hci_conn *conn; 40457652ff6aSJohan Hedberg struct link_key *key; 40467652ff6aSJohan Hedberg bool persistent; 404755ed8ca1SJohan Hedberg u8 pin_len = 0; 4048052b30b0SMarcel Holtmann 4049a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 4050052b30b0SMarcel Holtmann 4051052b30b0SMarcel Holtmann hci_dev_lock(hdev); 4052052b30b0SMarcel Holtmann 4053052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 405482c13d42SJohan Hedberg if (!conn) 405582c13d42SJohan Hedberg goto unlock; 405682c13d42SJohan Hedberg 4057052b30b0SMarcel Holtmann hci_conn_hold(conn); 4058052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 405976a68ba0SDavid Herrmann hci_conn_drop(conn); 406082c13d42SJohan Hedberg 4061fe8bc5acSJohan Hedberg set_bit(HCI_CONN_NEW_LINK_KEY, &conn->flags); 4062cb6f3f7aSJohan Hedberg conn_set_key(conn, ev->key_type, conn->pin_length); 4063052b30b0SMarcel Holtmann 4064d7a5a11dSMarcel Holtmann if (!hci_dev_test_flag(hdev, HCI_MGMT)) 40657652ff6aSJohan Hedberg goto unlock; 406655ed8ca1SJohan Hedberg 40677652ff6aSJohan Hedberg key = hci_add_link_key(hdev, conn, &ev->bdaddr, ev->link_key, 40687652ff6aSJohan Hedberg ev->key_type, pin_len, &persistent); 40697652ff6aSJohan Hedberg if (!key) 40707652ff6aSJohan Hedberg goto unlock; 40717652ff6aSJohan Hedberg 4072cb6f3f7aSJohan Hedberg /* Update connection information since adding the key will have 4073cb6f3f7aSJohan Hedberg * fixed up the type in the case of changed combination keys. 4074cb6f3f7aSJohan Hedberg */ 4075cb6f3f7aSJohan Hedberg if (ev->key_type == HCI_LK_CHANGED_COMBINATION) 4076cb6f3f7aSJohan Hedberg conn_set_key(conn, key->type, key->pin_len); 4077cb6f3f7aSJohan Hedberg 40787652ff6aSJohan Hedberg mgmt_new_link_key(hdev, key, persistent); 40797652ff6aSJohan Hedberg 40806d5650c4SJohan Hedberg /* Keep debug keys around only if the HCI_KEEP_DEBUG_KEYS flag 40816d5650c4SJohan Hedberg * is set. If it's not set simply remove the key from the kernel 40826d5650c4SJohan Hedberg * list (we've still notified user space about it but with 40836d5650c4SJohan Hedberg * store_hint being 0). 40846d5650c4SJohan Hedberg */ 40856d5650c4SJohan Hedberg if (key->type == HCI_LK_DEBUG_COMBINATION && 4086d7a5a11dSMarcel Holtmann !hci_dev_test_flag(hdev, HCI_KEEP_DEBUG_KEYS)) { 40870378b597SJohan Hedberg list_del_rcu(&key->list); 40880378b597SJohan Hedberg kfree_rcu(key, rcu); 408982c13d42SJohan Hedberg goto unlock; 409082c13d42SJohan Hedberg } 409182c13d42SJohan Hedberg 4092af6a9c32SJohan Hedberg if (persistent) 4093af6a9c32SJohan Hedberg clear_bit(HCI_CONN_FLUSH_KEY, &conn->flags); 4094af6a9c32SJohan Hedberg else 4095af6a9c32SJohan Hedberg set_bit(HCI_CONN_FLUSH_KEY, &conn->flags); 40967652ff6aSJohan Hedberg 40977652ff6aSJohan Hedberg unlock: 4098052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 40991da177e4SLinus Torvalds } 41001da177e4SLinus Torvalds 41016039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 410204837f64SMarcel Holtmann { 4103a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 410404837f64SMarcel Holtmann struct hci_conn *conn; 410504837f64SMarcel Holtmann 41069f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 410704837f64SMarcel Holtmann 410804837f64SMarcel Holtmann hci_dev_lock(hdev); 410904837f64SMarcel Holtmann 411004837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 41111da177e4SLinus Torvalds if (conn && !ev->status) { 41121da177e4SLinus Torvalds struct inquiry_entry *ie; 41131da177e4SLinus Torvalds 4114cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 4115cc11b9c1SAndrei Emeltchenko if (ie) { 41161da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 41171da177e4SLinus Torvalds ie->timestamp = jiffies; 41181da177e4SLinus Torvalds } 41191da177e4SLinus Torvalds } 41201da177e4SLinus Torvalds 41211da177e4SLinus Torvalds hci_dev_unlock(hdev); 41221da177e4SLinus Torvalds } 41231da177e4SLinus Torvalds 41246039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 4125a8746417SMarcel Holtmann { 4126a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 4127a8746417SMarcel Holtmann struct hci_conn *conn; 4128a8746417SMarcel Holtmann 41299f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 4130a8746417SMarcel Holtmann 4131a8746417SMarcel Holtmann hci_dev_lock(hdev); 4132a8746417SMarcel Holtmann 4133a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 4134a8746417SMarcel Holtmann if (conn && !ev->status) 4135a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 4136a8746417SMarcel Holtmann 4137a8746417SMarcel Holtmann hci_dev_unlock(hdev); 4138a8746417SMarcel Holtmann } 4139a8746417SMarcel Holtmann 41406039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 414185a1e930SMarcel Holtmann { 4142a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 414385a1e930SMarcel Holtmann struct inquiry_entry *ie; 414485a1e930SMarcel Holtmann 414585a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 414685a1e930SMarcel Holtmann 414785a1e930SMarcel Holtmann hci_dev_lock(hdev); 414885a1e930SMarcel Holtmann 4149cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 4150cc11b9c1SAndrei Emeltchenko if (ie) { 415185a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 415285a1e930SMarcel Holtmann ie->timestamp = jiffies; 415385a1e930SMarcel Holtmann } 415485a1e930SMarcel Holtmann 415585a1e930SMarcel Holtmann hci_dev_unlock(hdev); 415685a1e930SMarcel Holtmann } 415785a1e930SMarcel Holtmann 41586039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, 4159807deac2SGustavo Padovan struct sk_buff *skb) 4160a9de9248SMarcel Holtmann { 4161a9de9248SMarcel Holtmann struct inquiry_data data; 4162a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 4163a9de9248SMarcel Holtmann 4164a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 4165a9de9248SMarcel Holtmann 4166a9de9248SMarcel Holtmann if (!num_rsp) 4167a9de9248SMarcel Holtmann return; 4168a9de9248SMarcel Holtmann 4169d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) 41701519cc17SAndre Guedes return; 41711519cc17SAndre Guedes 4172a9de9248SMarcel Holtmann hci_dev_lock(hdev); 4173a9de9248SMarcel Holtmann 4174a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 4175138d22efSSzymon Janc struct inquiry_info_with_rssi_and_pscan_mode *info; 4176138d22efSSzymon Janc info = (void *) (skb->data + 1); 4177a9de9248SMarcel Holtmann 4178629b49c8SPeilin Ye if (skb->len < num_rsp * sizeof(*info) + 1) 4179629b49c8SPeilin Ye goto unlock; 4180629b49c8SPeilin Ye 4181e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 4182af58925cSMarcel Holtmann u32 flags; 4183af58925cSMarcel Holtmann 4184a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 4185a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 4186a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 4187a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 4188a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 4189a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 4190a9de9248SMarcel Holtmann data.rssi = info->rssi; 419141a96212SMarcel Holtmann data.ssp_mode = 0x00; 41923175405bSJohan Hedberg 4193af58925cSMarcel Holtmann flags = hci_inquiry_cache_update(hdev, &data, false); 4194af58925cSMarcel Holtmann 419548264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 4196e17acd40SJohan Hedberg info->dev_class, info->rssi, 4197af58925cSMarcel Holtmann flags, NULL, 0, NULL, 0); 4198a9de9248SMarcel Holtmann } 4199a9de9248SMarcel Holtmann } else { 4200a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 4201a9de9248SMarcel Holtmann 4202629b49c8SPeilin Ye if (skb->len < num_rsp * sizeof(*info) + 1) 4203629b49c8SPeilin Ye goto unlock; 4204629b49c8SPeilin Ye 4205e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 4206af58925cSMarcel Holtmann u32 flags; 4207af58925cSMarcel Holtmann 4208a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 4209a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 4210a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 4211a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 4212a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 4213a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 4214a9de9248SMarcel Holtmann data.rssi = info->rssi; 421541a96212SMarcel Holtmann data.ssp_mode = 0x00; 4216af58925cSMarcel Holtmann 4217af58925cSMarcel Holtmann flags = hci_inquiry_cache_update(hdev, &data, false); 4218af58925cSMarcel Holtmann 421948264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 4220e17acd40SJohan Hedberg info->dev_class, info->rssi, 4221af58925cSMarcel Holtmann flags, NULL, 0, NULL, 0); 4222a9de9248SMarcel Holtmann } 4223a9de9248SMarcel Holtmann } 4224a9de9248SMarcel Holtmann 4225629b49c8SPeilin Ye unlock: 4226a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 4227a9de9248SMarcel Holtmann } 4228a9de9248SMarcel Holtmann 42296039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev, 4230807deac2SGustavo Padovan struct sk_buff *skb) 4231a9de9248SMarcel Holtmann { 423241a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 423341a96212SMarcel Holtmann struct hci_conn *conn; 423441a96212SMarcel Holtmann 4235a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 423641a96212SMarcel Holtmann 423741a96212SMarcel Holtmann hci_dev_lock(hdev); 423841a96212SMarcel Holtmann 423941a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 4240ccd556feSJohan Hedberg if (!conn) 4241ccd556feSJohan Hedberg goto unlock; 4242ccd556feSJohan Hedberg 4243cad718edSJohan Hedberg if (ev->page < HCI_MAX_PAGES) 4244cad718edSJohan Hedberg memcpy(conn->features[ev->page], ev->features, 8); 4245cad718edSJohan Hedberg 4246769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 424741a96212SMarcel Holtmann struct inquiry_entry *ie; 424841a96212SMarcel Holtmann 4249cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 4250cc11b9c1SAndrei Emeltchenko if (ie) 425102b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 425241a96212SMarcel Holtmann 4253bbb0eadaSJaganath Kanakkassery if (ev->features[0] & LMP_HOST_SSP) { 425458a681efSJohan Hedberg set_bit(HCI_CONN_SSP_ENABLED, &conn->flags); 4255bbb0eadaSJaganath Kanakkassery } else { 4256bbb0eadaSJaganath Kanakkassery /* It is mandatory by the Bluetooth specification that 4257bbb0eadaSJaganath Kanakkassery * Extended Inquiry Results are only used when Secure 4258bbb0eadaSJaganath Kanakkassery * Simple Pairing is enabled, but some devices violate 4259bbb0eadaSJaganath Kanakkassery * this. 4260bbb0eadaSJaganath Kanakkassery * 4261bbb0eadaSJaganath Kanakkassery * To make these devices work, the internal SSP 4262bbb0eadaSJaganath Kanakkassery * enabled flag needs to be cleared if the remote host 4263bbb0eadaSJaganath Kanakkassery * features do not indicate SSP support */ 4264bbb0eadaSJaganath Kanakkassery clear_bit(HCI_CONN_SSP_ENABLED, &conn->flags); 4265bbb0eadaSJaganath Kanakkassery } 4266eb9a8f3fSMarcel Holtmann 4267eb9a8f3fSMarcel Holtmann if (ev->features[0] & LMP_HOST_SC) 4268eb9a8f3fSMarcel Holtmann set_bit(HCI_CONN_SC_ENABLED, &conn->flags); 426941a96212SMarcel Holtmann } 427041a96212SMarcel Holtmann 4271ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 4272ccd556feSJohan Hedberg goto unlock; 4273ccd556feSJohan Hedberg 4274671267bfSJohan Hedberg if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { 4275127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 4276127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 4277127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 4278127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 4279127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 4280b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 428148ec92faSAlfonso Acosta mgmt_device_connected(hdev, conn, 0, NULL, 0); 4282392599b9SJohan Hedberg 4283127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 4284769be974SMarcel Holtmann conn->state = BT_CONNECTED; 4285539c496dSJohan Hedberg hci_connect_cfm(conn, ev->status); 428676a68ba0SDavid Herrmann hci_conn_drop(conn); 4287769be974SMarcel Holtmann } 4288769be974SMarcel Holtmann 4289ccd556feSJohan Hedberg unlock: 429041a96212SMarcel Holtmann hci_dev_unlock(hdev); 4291a9de9248SMarcel Holtmann } 4292a9de9248SMarcel Holtmann 42936039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev, 4294807deac2SGustavo Padovan struct sk_buff *skb) 4295a9de9248SMarcel Holtmann { 4296b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 4297b6a0dc82SMarcel Holtmann struct hci_conn *conn; 4298b6a0dc82SMarcel Holtmann 42999f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 4300b6a0dc82SMarcel Holtmann 4301b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 4302b6a0dc82SMarcel Holtmann 4303b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 43049dc0a3afSMarcel Holtmann if (!conn) { 43059dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 43069dc0a3afSMarcel Holtmann goto unlock; 43079dc0a3afSMarcel Holtmann 4308618353b1SKuba Pawlak /* When the link type in the event indicates SCO connection 4309618353b1SKuba Pawlak * and lookup of the connection object fails, then check 4310618353b1SKuba Pawlak * if an eSCO connection object exists. 4311618353b1SKuba Pawlak * 4312618353b1SKuba Pawlak * The core limits the synchronous connections to either 4313618353b1SKuba Pawlak * SCO or eSCO. The eSCO connection is preferred and tried 4314618353b1SKuba Pawlak * to be setup first and until successfully established, 4315618353b1SKuba Pawlak * the link type will be hinted as eSCO. 4316618353b1SKuba Pawlak */ 43179dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 4318b6a0dc82SMarcel Holtmann if (!conn) 4319b6a0dc82SMarcel Holtmann goto unlock; 43209dc0a3afSMarcel Holtmann } 43219dc0a3afSMarcel Holtmann 4322732547f9SMarcel Holtmann switch (ev->status) { 4323732547f9SMarcel Holtmann case 0x00: 4324732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 4325732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 4326618353b1SKuba Pawlak conn->type = ev->link_type; 4327732547f9SMarcel Holtmann 432823b9ceb7SMarcel Holtmann hci_debugfs_create_conn(conn); 4329732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 4330732547f9SMarcel Holtmann break; 4331732547f9SMarcel Holtmann 433281218d20SNick Pelly case 0x10: /* Connection Accept Timeout */ 43331a4c958cSFrédéric Dalleau case 0x0d: /* Connection Rejected due to Limited Resources */ 4334705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 4335732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 43361038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 433756b5453aSHsin-Yu Chao case 0x1e: /* Invalid LMP Parameters */ 4338732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 433927539bc4SAndrew Earl case 0x20: /* Unsupported LMP Parameter value */ 43402dea632fSFrédéric Dalleau if (conn->out) { 4341efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 4342efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 43432dea632fSFrédéric Dalleau if (hci_setup_sync(conn, conn->link->handle)) 4344efc7688bSMarcel Holtmann goto unlock; 4345efc7688bSMarcel Holtmann } 434619186c7bSGustavo A. R. Silva fallthrough; 4347efc7688bSMarcel Holtmann 4348732547f9SMarcel Holtmann default: 4349b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 4350732547f9SMarcel Holtmann break; 4351732547f9SMarcel Holtmann } 4352b6a0dc82SMarcel Holtmann 43531f8330eaSSathish Narsimman bt_dev_dbg(hdev, "SCO connected with air mode: %02x", ev->air_mode); 43541f8330eaSSathish Narsimman 43551f8330eaSSathish Narsimman switch (conn->setting & SCO_AIRMODE_MASK) { 43561f8330eaSSathish Narsimman case SCO_AIRMODE_CVSD: 43571f8330eaSSathish Narsimman if (hdev->notify) 43581f8330eaSSathish Narsimman hdev->notify(hdev, HCI_NOTIFY_ENABLE_SCO_CVSD); 43591f8330eaSSathish Narsimman break; 43601f8330eaSSathish Narsimman case SCO_AIRMODE_TRANSP: 43611f8330eaSSathish Narsimman if (hdev->notify) 43621f8330eaSSathish Narsimman hdev->notify(hdev, HCI_NOTIFY_ENABLE_SCO_TRANSP); 43631f8330eaSSathish Narsimman break; 43641f8330eaSSathish Narsimman } 43651f8330eaSSathish Narsimman 4366539c496dSJohan Hedberg hci_connect_cfm(conn, ev->status); 4367b6a0dc82SMarcel Holtmann if (ev->status) 4368b6a0dc82SMarcel Holtmann hci_conn_del(conn); 4369b6a0dc82SMarcel Holtmann 4370b6a0dc82SMarcel Holtmann unlock: 4371b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 4372a9de9248SMarcel Holtmann } 4373a9de9248SMarcel Holtmann 4374efdcf8e3SMarcel Holtmann static inline size_t eir_get_length(u8 *eir, size_t eir_len) 4375efdcf8e3SMarcel Holtmann { 4376efdcf8e3SMarcel Holtmann size_t parsed = 0; 4377efdcf8e3SMarcel Holtmann 4378efdcf8e3SMarcel Holtmann while (parsed < eir_len) { 4379efdcf8e3SMarcel Holtmann u8 field_len = eir[0]; 4380efdcf8e3SMarcel Holtmann 4381efdcf8e3SMarcel Holtmann if (field_len == 0) 4382efdcf8e3SMarcel Holtmann return parsed; 4383efdcf8e3SMarcel Holtmann 4384efdcf8e3SMarcel Holtmann parsed += field_len + 1; 4385efdcf8e3SMarcel Holtmann eir += field_len + 1; 4386efdcf8e3SMarcel Holtmann } 4387efdcf8e3SMarcel Holtmann 4388efdcf8e3SMarcel Holtmann return eir_len; 4389efdcf8e3SMarcel Holtmann } 4390efdcf8e3SMarcel Holtmann 43916039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, 4392807deac2SGustavo Padovan struct sk_buff *skb) 4393a9de9248SMarcel Holtmann { 4394a9de9248SMarcel Holtmann struct inquiry_data data; 4395a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 4396a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 43979d939d94SVishal Agarwal size_t eir_len; 4398a9de9248SMarcel Holtmann 4399a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 4400a9de9248SMarcel Holtmann 440151c19bf3SPeilin Ye if (!num_rsp || skb->len < num_rsp * sizeof(*info) + 1) 4402a9de9248SMarcel Holtmann return; 4403a9de9248SMarcel Holtmann 4404d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) 44051519cc17SAndre Guedes return; 44061519cc17SAndre Guedes 4407a9de9248SMarcel Holtmann hci_dev_lock(hdev); 4408a9de9248SMarcel Holtmann 4409e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 4410af58925cSMarcel Holtmann u32 flags; 4411af58925cSMarcel Holtmann bool name_known; 4412561aafbcSJohan Hedberg 4413a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 4414a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 4415a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 4416a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 4417a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 4418a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 4419a9de9248SMarcel Holtmann data.rssi = info->rssi; 442041a96212SMarcel Holtmann data.ssp_mode = 0x01; 4421561aafbcSJohan Hedberg 4422d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_MGMT)) 44230d3b7f64SJohan Hedberg name_known = eir_get_data(info->data, 44244ddb1930SJohan Hedberg sizeof(info->data), 44250d3b7f64SJohan Hedberg EIR_NAME_COMPLETE, NULL); 4426561aafbcSJohan Hedberg else 4427561aafbcSJohan Hedberg name_known = true; 4428561aafbcSJohan Hedberg 4429af58925cSMarcel Holtmann flags = hci_inquiry_cache_update(hdev, &data, name_known); 4430af58925cSMarcel Holtmann 44319d939d94SVishal Agarwal eir_len = eir_get_length(info->data, sizeof(info->data)); 4432af58925cSMarcel Holtmann 443348264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 4434af58925cSMarcel Holtmann info->dev_class, info->rssi, 4435af58925cSMarcel Holtmann flags, info->data, eir_len, NULL, 0); 4436a9de9248SMarcel Holtmann } 4437a9de9248SMarcel Holtmann 4438a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 4439a9de9248SMarcel Holtmann } 4440a9de9248SMarcel Holtmann 44411c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev, 44421c2e0041SJohan Hedberg struct sk_buff *skb) 44431c2e0041SJohan Hedberg { 44441c2e0041SJohan Hedberg struct hci_ev_key_refresh_complete *ev = (void *) skb->data; 44451c2e0041SJohan Hedberg struct hci_conn *conn; 44461c2e0041SJohan Hedberg 44479f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status, 44481c2e0041SJohan Hedberg __le16_to_cpu(ev->handle)); 44491c2e0041SJohan Hedberg 44501c2e0041SJohan Hedberg hci_dev_lock(hdev); 44511c2e0041SJohan Hedberg 44521c2e0041SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 44531c2e0041SJohan Hedberg if (!conn) 44541c2e0041SJohan Hedberg goto unlock; 44551c2e0041SJohan Hedberg 44569eb1fbfaSJohan Hedberg /* For BR/EDR the necessary steps are taken through the 44579eb1fbfaSJohan Hedberg * auth_complete event. 44589eb1fbfaSJohan Hedberg */ 44599eb1fbfaSJohan Hedberg if (conn->type != LE_LINK) 44609eb1fbfaSJohan Hedberg goto unlock; 44619eb1fbfaSJohan Hedberg 44621c2e0041SJohan Hedberg if (!ev->status) 44631c2e0041SJohan Hedberg conn->sec_level = conn->pending_sec_level; 44641c2e0041SJohan Hedberg 44651c2e0041SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 44661c2e0041SJohan Hedberg 44671c2e0041SJohan Hedberg if (ev->status && conn->state == BT_CONNECTED) { 4468bed71748SAndre Guedes hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); 446976a68ba0SDavid Herrmann hci_conn_drop(conn); 44701c2e0041SJohan Hedberg goto unlock; 44711c2e0041SJohan Hedberg } 44721c2e0041SJohan Hedberg 44731c2e0041SJohan Hedberg if (conn->state == BT_CONFIG) { 44741c2e0041SJohan Hedberg if (!ev->status) 44751c2e0041SJohan Hedberg conn->state = BT_CONNECTED; 44761c2e0041SJohan Hedberg 4477539c496dSJohan Hedberg hci_connect_cfm(conn, ev->status); 447876a68ba0SDavid Herrmann hci_conn_drop(conn); 44791c2e0041SJohan Hedberg } else { 44801c2e0041SJohan Hedberg hci_auth_cfm(conn, ev->status); 44811c2e0041SJohan Hedberg 44821c2e0041SJohan Hedberg hci_conn_hold(conn); 44831c2e0041SJohan Hedberg conn->disc_timeout = HCI_DISCONN_TIMEOUT; 448476a68ba0SDavid Herrmann hci_conn_drop(conn); 44851c2e0041SJohan Hedberg } 44861c2e0041SJohan Hedberg 44871c2e0041SJohan Hedberg unlock: 44881c2e0041SJohan Hedberg hci_dev_unlock(hdev); 44891c2e0041SJohan Hedberg } 44901c2e0041SJohan Hedberg 44916039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn) 449217fa4b9dSJohan Hedberg { 449317fa4b9dSJohan Hedberg /* If remote requests no-bonding follow that lead */ 4494acabae96SMikel Astiz if (conn->remote_auth == HCI_AT_NO_BONDING || 4495acabae96SMikel Astiz conn->remote_auth == HCI_AT_NO_BONDING_MITM) 449658797bf7SWaldemar Rymarkiewicz return conn->remote_auth | (conn->auth_type & 0x01); 449717fa4b9dSJohan Hedberg 4498b7f94c88SMikel Astiz /* If both remote and local have enough IO capabilities, require 4499b7f94c88SMikel Astiz * MITM protection 4500b7f94c88SMikel Astiz */ 4501b7f94c88SMikel Astiz if (conn->remote_cap != HCI_IO_NO_INPUT_OUTPUT && 4502b7f94c88SMikel Astiz conn->io_capability != HCI_IO_NO_INPUT_OUTPUT) 4503b7f94c88SMikel Astiz return conn->remote_auth | 0x01; 4504b7f94c88SMikel Astiz 45057e74170aSTimo Mueller /* No MITM protection possible so ignore remote requirement */ 45067e74170aSTimo Mueller return (conn->remote_auth & ~0x01) | (conn->auth_type & 0x01); 450717fa4b9dSJohan Hedberg } 450817fa4b9dSJohan Hedberg 4509a83ed81eSMarcel Holtmann static u8 bredr_oob_data_present(struct hci_conn *conn) 4510a83ed81eSMarcel Holtmann { 4511a83ed81eSMarcel Holtmann struct hci_dev *hdev = conn->hdev; 4512a83ed81eSMarcel Holtmann struct oob_data *data; 4513a83ed81eSMarcel Holtmann 4514a83ed81eSMarcel Holtmann data = hci_find_remote_oob_data(hdev, &conn->dst, BDADDR_BREDR); 4515a83ed81eSMarcel Holtmann if (!data) 4516a83ed81eSMarcel Holtmann return 0x00; 4517a83ed81eSMarcel Holtmann 4518bf21d793SMarcel Holtmann if (bredr_sc_enabled(hdev)) { 4519bf21d793SMarcel Holtmann /* When Secure Connections is enabled, then just 4520bf21d793SMarcel Holtmann * return the present value stored with the OOB 4521bf21d793SMarcel Holtmann * data. The stored value contains the right present 4522bf21d793SMarcel Holtmann * information. However it can only be trusted when 4523bf21d793SMarcel Holtmann * not in Secure Connection Only mode. 4524aa5b0345SMarcel Holtmann */ 4525d7a5a11dSMarcel Holtmann if (!hci_dev_test_flag(hdev, HCI_SC_ONLY)) 4526bf21d793SMarcel Holtmann return data->present; 4527bf21d793SMarcel Holtmann 4528bf21d793SMarcel Holtmann /* When Secure Connections Only mode is enabled, then 4529bf21d793SMarcel Holtmann * the P-256 values are required. If they are not 4530bf21d793SMarcel Holtmann * available, then do not declare that OOB data is 4531bf21d793SMarcel Holtmann * present. 4532bf21d793SMarcel Holtmann */ 4533bf21d793SMarcel Holtmann if (!memcmp(data->rand256, ZERO_KEY, 16) || 4534bf21d793SMarcel Holtmann !memcmp(data->hash256, ZERO_KEY, 16)) 4535aa5b0345SMarcel Holtmann return 0x00; 4536aa5b0345SMarcel Holtmann 4537bf21d793SMarcel Holtmann return 0x02; 4538bf21d793SMarcel Holtmann } 4539659c7fb0SMarcel Holtmann 4540659c7fb0SMarcel Holtmann /* When Secure Connections is not enabled or actually 4541659c7fb0SMarcel Holtmann * not supported by the hardware, then check that if 4542659c7fb0SMarcel Holtmann * P-192 data values are present. 4543659c7fb0SMarcel Holtmann */ 4544659c7fb0SMarcel Holtmann if (!memcmp(data->rand192, ZERO_KEY, 16) || 4545659c7fb0SMarcel Holtmann !memcmp(data->hash192, ZERO_KEY, 16)) 4546659c7fb0SMarcel Holtmann return 0x00; 4547659c7fb0SMarcel Holtmann 4548a83ed81eSMarcel Holtmann return 0x01; 4549659c7fb0SMarcel Holtmann } 4550a83ed81eSMarcel Holtmann 45516039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 45520493684eSMarcel Holtmann { 45530493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 45540493684eSMarcel Holtmann struct hci_conn *conn; 45550493684eSMarcel Holtmann 45560493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 45570493684eSMarcel Holtmann 45580493684eSMarcel Holtmann hci_dev_lock(hdev); 45590493684eSMarcel Holtmann 45600493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 456103b555e1SJohan Hedberg if (!conn) 456203b555e1SJohan Hedberg goto unlock; 456303b555e1SJohan Hedberg 45640493684eSMarcel Holtmann hci_conn_hold(conn); 45650493684eSMarcel Holtmann 4566d7a5a11dSMarcel Holtmann if (!hci_dev_test_flag(hdev, HCI_MGMT)) 456703b555e1SJohan Hedberg goto unlock; 456803b555e1SJohan Hedberg 45692f407f0aSJohan Hedberg /* Allow pairing if we're pairable, the initiators of the 45702f407f0aSJohan Hedberg * pairing or if the remote is not requesting bonding. 45712f407f0aSJohan Hedberg */ 4572d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_BONDABLE) || 45732f407f0aSJohan Hedberg test_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags) || 457403b555e1SJohan Hedberg (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 457517fa4b9dSJohan Hedberg struct hci_cp_io_capability_reply cp; 457617fa4b9dSJohan Hedberg 457717fa4b9dSJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 45787a7f1e7cSHemant Gupta /* Change the IO capability from KeyboardDisplay 45797a7f1e7cSHemant Gupta * to DisplayYesNo as it is not supported by BT spec. */ 45807a7f1e7cSHemant Gupta cp.capability = (conn->io_capability == 0x04) ? 4581a767631aSMikel Astiz HCI_IO_DISPLAY_YESNO : conn->io_capability; 4582b7f94c88SMikel Astiz 4583b7f94c88SMikel Astiz /* If we are initiators, there is no remote information yet */ 4584b7f94c88SMikel Astiz if (conn->remote_auth == 0xff) { 4585b16c6604SMikel Astiz /* Request MITM protection if our IO caps allow it 45864ad51a75SJohan Hedberg * except for the no-bonding case. 4587b16c6604SMikel Astiz */ 45886fd6b915SMikel Astiz if (conn->io_capability != HCI_IO_NO_INPUT_OUTPUT && 45899f743d74SJohan Hedberg conn->auth_type != HCI_AT_NO_BONDING) 45906c53823aSJohan Hedberg conn->auth_type |= 0x01; 4591b7f94c88SMikel Astiz } else { 45927cbc9bd9SJohan Hedberg conn->auth_type = hci_get_auth_req(conn); 4593b7f94c88SMikel Astiz } 459417fa4b9dSJohan Hedberg 459582c295b1SJohan Hedberg /* If we're not bondable, force one of the non-bondable 459682c295b1SJohan Hedberg * authentication requirement values. 459782c295b1SJohan Hedberg */ 4598d7a5a11dSMarcel Holtmann if (!hci_dev_test_flag(hdev, HCI_BONDABLE)) 459982c295b1SJohan Hedberg conn->auth_type &= HCI_AT_NO_BONDING_MITM; 460082c295b1SJohan Hedberg 460182c295b1SJohan Hedberg cp.authentication = conn->auth_type; 4602a83ed81eSMarcel Holtmann cp.oob_data = bredr_oob_data_present(conn); 4603ce85ee13SSzymon Janc 460417fa4b9dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, 460517fa4b9dSJohan Hedberg sizeof(cp), &cp); 460603b555e1SJohan Hedberg } else { 460703b555e1SJohan Hedberg struct hci_cp_io_capability_neg_reply cp; 460803b555e1SJohan Hedberg 460903b555e1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 46109f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED; 461103b555e1SJohan Hedberg 461203b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 461303b555e1SJohan Hedberg sizeof(cp), &cp); 461403b555e1SJohan Hedberg } 461503b555e1SJohan Hedberg 461603b555e1SJohan Hedberg unlock: 461703b555e1SJohan Hedberg hci_dev_unlock(hdev); 461803b555e1SJohan Hedberg } 461903b555e1SJohan Hedberg 46206039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 462103b555e1SJohan Hedberg { 462203b555e1SJohan Hedberg struct hci_ev_io_capa_reply *ev = (void *) skb->data; 462303b555e1SJohan Hedberg struct hci_conn *conn; 462403b555e1SJohan Hedberg 462503b555e1SJohan Hedberg BT_DBG("%s", hdev->name); 462603b555e1SJohan Hedberg 462703b555e1SJohan Hedberg hci_dev_lock(hdev); 462803b555e1SJohan Hedberg 462903b555e1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 463003b555e1SJohan Hedberg if (!conn) 463103b555e1SJohan Hedberg goto unlock; 463203b555e1SJohan Hedberg 463303b555e1SJohan Hedberg conn->remote_cap = ev->capability; 463403b555e1SJohan Hedberg conn->remote_auth = ev->authentication; 463503b555e1SJohan Hedberg 463603b555e1SJohan Hedberg unlock: 46370493684eSMarcel Holtmann hci_dev_unlock(hdev); 46380493684eSMarcel Holtmann } 46390493684eSMarcel Holtmann 46406039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev, 4641a5c29683SJohan Hedberg struct sk_buff *skb) 4642a5c29683SJohan Hedberg { 4643a5c29683SJohan Hedberg struct hci_ev_user_confirm_req *ev = (void *) skb->data; 464455bc1a37SJohan Hedberg int loc_mitm, rem_mitm, confirm_hint = 0; 46457a828908SJohan Hedberg struct hci_conn *conn; 4646a5c29683SJohan Hedberg 4647a5c29683SJohan Hedberg BT_DBG("%s", hdev->name); 4648a5c29683SJohan Hedberg 4649a5c29683SJohan Hedberg hci_dev_lock(hdev); 4650a5c29683SJohan Hedberg 4651d7a5a11dSMarcel Holtmann if (!hci_dev_test_flag(hdev, HCI_MGMT)) 46527a828908SJohan Hedberg goto unlock; 46537a828908SJohan Hedberg 46547a828908SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 46557a828908SJohan Hedberg if (!conn) 46567a828908SJohan Hedberg goto unlock; 46577a828908SJohan Hedberg 46587a828908SJohan Hedberg loc_mitm = (conn->auth_type & 0x01); 46597a828908SJohan Hedberg rem_mitm = (conn->remote_auth & 0x01); 46607a828908SJohan Hedberg 46617a828908SJohan Hedberg /* If we require MITM but the remote device can't provide that 46626c53823aSJohan Hedberg * (it has NoInputNoOutput) then reject the confirmation 46636c53823aSJohan Hedberg * request. We check the security level here since it doesn't 46646c53823aSJohan Hedberg * necessarily match conn->auth_type. 46656fd6b915SMikel Astiz */ 46666c53823aSJohan Hedberg if (conn->pending_sec_level > BT_SECURITY_MEDIUM && 46676c53823aSJohan Hedberg conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) { 46687a828908SJohan Hedberg BT_DBG("Rejecting request: remote device can't provide MITM"); 46697a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, 46707a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 46717a828908SJohan Hedberg goto unlock; 46727a828908SJohan Hedberg } 46737a828908SJohan Hedberg 46747a828908SJohan Hedberg /* If no side requires MITM protection; auto-accept */ 4675a767631aSMikel Astiz if ((!loc_mitm || conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) && 4676a767631aSMikel Astiz (!rem_mitm || conn->io_capability == HCI_IO_NO_INPUT_OUTPUT)) { 467755bc1a37SJohan Hedberg 467855bc1a37SJohan Hedberg /* If we're not the initiators request authorization to 467955bc1a37SJohan Hedberg * proceed from user space (mgmt_user_confirm with 4680ba15a58bSJohan Hedberg * confirm_hint set to 1). The exception is if neither 468102f3e254SJohan Hedberg * side had MITM or if the local IO capability is 468202f3e254SJohan Hedberg * NoInputNoOutput, in which case we do auto-accept 4683ba15a58bSJohan Hedberg */ 4684ba15a58bSJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && 468502f3e254SJohan Hedberg conn->io_capability != HCI_IO_NO_INPUT_OUTPUT && 4686ba15a58bSJohan Hedberg (loc_mitm || rem_mitm)) { 468755bc1a37SJohan Hedberg BT_DBG("Confirming auto-accept as acceptor"); 468855bc1a37SJohan Hedberg confirm_hint = 1; 468955bc1a37SJohan Hedberg goto confirm; 469055bc1a37SJohan Hedberg } 469155bc1a37SJohan Hedberg 4692cee5f20fSHoward Chung /* If there already exists link key in local host, leave the 4693cee5f20fSHoward Chung * decision to user space since the remote device could be 4694cee5f20fSHoward Chung * legitimate or malicious. 4695cee5f20fSHoward Chung */ 4696cee5f20fSHoward Chung if (hci_find_link_key(hdev, &ev->bdaddr)) { 4697cee5f20fSHoward Chung bt_dev_dbg(hdev, "Local host already has link key"); 4698cee5f20fSHoward Chung confirm_hint = 1; 4699cee5f20fSHoward Chung goto confirm; 4700cee5f20fSHoward Chung } 4701cee5f20fSHoward Chung 47029f61656aSJohan Hedberg BT_DBG("Auto-accept of user confirmation with %ums delay", 47039f61656aSJohan Hedberg hdev->auto_accept_delay); 47049f61656aSJohan Hedberg 47059f61656aSJohan Hedberg if (hdev->auto_accept_delay > 0) { 47069f61656aSJohan Hedberg int delay = msecs_to_jiffies(hdev->auto_accept_delay); 47077bc18d9dSJohan Hedberg queue_delayed_work(conn->hdev->workqueue, 47087bc18d9dSJohan Hedberg &conn->auto_accept_work, delay); 47099f61656aSJohan Hedberg goto unlock; 47109f61656aSJohan Hedberg } 47119f61656aSJohan Hedberg 47127a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, 47137a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 47147a828908SJohan Hedberg goto unlock; 47157a828908SJohan Hedberg } 47167a828908SJohan Hedberg 471755bc1a37SJohan Hedberg confirm: 471839adbffeSJohan Hedberg mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, 471939adbffeSJohan Hedberg le32_to_cpu(ev->passkey), confirm_hint); 4720a5c29683SJohan Hedberg 47217a828908SJohan Hedberg unlock: 4722a5c29683SJohan Hedberg hci_dev_unlock(hdev); 4723a5c29683SJohan Hedberg } 4724a5c29683SJohan Hedberg 47256039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev, 47261143d458SBrian Gix struct sk_buff *skb) 47271143d458SBrian Gix { 47281143d458SBrian Gix struct hci_ev_user_passkey_req *ev = (void *) skb->data; 47291143d458SBrian Gix 47301143d458SBrian Gix BT_DBG("%s", hdev->name); 47311143d458SBrian Gix 4732d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_MGMT)) 4733272d90dfSJohan Hedberg mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); 47341143d458SBrian Gix } 47351143d458SBrian Gix 473692a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev, 473792a25256SJohan Hedberg struct sk_buff *skb) 473892a25256SJohan Hedberg { 473992a25256SJohan Hedberg struct hci_ev_user_passkey_notify *ev = (void *) skb->data; 474092a25256SJohan Hedberg struct hci_conn *conn; 474192a25256SJohan Hedberg 474292a25256SJohan Hedberg BT_DBG("%s", hdev->name); 474392a25256SJohan Hedberg 474492a25256SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 474592a25256SJohan Hedberg if (!conn) 474692a25256SJohan Hedberg return; 474792a25256SJohan Hedberg 474892a25256SJohan Hedberg conn->passkey_notify = __le32_to_cpu(ev->passkey); 474992a25256SJohan Hedberg conn->passkey_entered = 0; 475092a25256SJohan Hedberg 4751d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_MGMT)) 475292a25256SJohan Hedberg mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, 475392a25256SJohan Hedberg conn->dst_type, conn->passkey_notify, 475492a25256SJohan Hedberg conn->passkey_entered); 475592a25256SJohan Hedberg } 475692a25256SJohan Hedberg 475792a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 475892a25256SJohan Hedberg { 475992a25256SJohan Hedberg struct hci_ev_keypress_notify *ev = (void *) skb->data; 476092a25256SJohan Hedberg struct hci_conn *conn; 476192a25256SJohan Hedberg 476292a25256SJohan Hedberg BT_DBG("%s", hdev->name); 476392a25256SJohan Hedberg 476492a25256SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 476592a25256SJohan Hedberg if (!conn) 476692a25256SJohan Hedberg return; 476792a25256SJohan Hedberg 476892a25256SJohan Hedberg switch (ev->type) { 476992a25256SJohan Hedberg case HCI_KEYPRESS_STARTED: 477092a25256SJohan Hedberg conn->passkey_entered = 0; 477192a25256SJohan Hedberg return; 477292a25256SJohan Hedberg 477392a25256SJohan Hedberg case HCI_KEYPRESS_ENTERED: 477492a25256SJohan Hedberg conn->passkey_entered++; 477592a25256SJohan Hedberg break; 477692a25256SJohan Hedberg 477792a25256SJohan Hedberg case HCI_KEYPRESS_ERASED: 477892a25256SJohan Hedberg conn->passkey_entered--; 477992a25256SJohan Hedberg break; 478092a25256SJohan Hedberg 478192a25256SJohan Hedberg case HCI_KEYPRESS_CLEARED: 478292a25256SJohan Hedberg conn->passkey_entered = 0; 478392a25256SJohan Hedberg break; 478492a25256SJohan Hedberg 478592a25256SJohan Hedberg case HCI_KEYPRESS_COMPLETED: 478692a25256SJohan Hedberg return; 478792a25256SJohan Hedberg } 478892a25256SJohan Hedberg 4789d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_MGMT)) 479092a25256SJohan Hedberg mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, 479192a25256SJohan Hedberg conn->dst_type, conn->passkey_notify, 479292a25256SJohan Hedberg conn->passkey_entered); 479392a25256SJohan Hedberg } 479492a25256SJohan Hedberg 47956039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev, 4796807deac2SGustavo Padovan struct sk_buff *skb) 47970493684eSMarcel Holtmann { 47980493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 47990493684eSMarcel Holtmann struct hci_conn *conn; 48000493684eSMarcel Holtmann 48010493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 48020493684eSMarcel Holtmann 48030493684eSMarcel Holtmann hci_dev_lock(hdev); 48040493684eSMarcel Holtmann 48050493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 48062a611692SJohan Hedberg if (!conn) 48072a611692SJohan Hedberg goto unlock; 48082a611692SJohan Hedberg 4809c1d4fa7aSJohan Hedberg /* Reset the authentication requirement to unknown */ 4810c1d4fa7aSJohan Hedberg conn->remote_auth = 0xff; 4811c1d4fa7aSJohan Hedberg 48122a611692SJohan Hedberg /* To avoid duplicate auth_failed events to user space we check 48132a611692SJohan Hedberg * the HCI_CONN_AUTH_PEND flag which will be set if we 48142a611692SJohan Hedberg * initiated the authentication. A traditional auth_complete 48152a611692SJohan Hedberg * event gets always produced as initiator and is also mapped to 48162a611692SJohan Hedberg * the mgmt_auth_failed event */ 4817fa1bd918SMikel Astiz if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status) 4818e1e930f5SJohan Hedberg mgmt_auth_failed(conn, ev->status); 48192a611692SJohan Hedberg 482076a68ba0SDavid Herrmann hci_conn_drop(conn); 48210493684eSMarcel Holtmann 48222a611692SJohan Hedberg unlock: 48230493684eSMarcel Holtmann hci_dev_unlock(hdev); 48240493684eSMarcel Holtmann } 48250493684eSMarcel Holtmann 48266039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev, 4827807deac2SGustavo Padovan struct sk_buff *skb) 482841a96212SMarcel Holtmann { 482941a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 483041a96212SMarcel Holtmann struct inquiry_entry *ie; 4831cad718edSJohan Hedberg struct hci_conn *conn; 483241a96212SMarcel Holtmann 483341a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 483441a96212SMarcel Holtmann 483541a96212SMarcel Holtmann hci_dev_lock(hdev); 483641a96212SMarcel Holtmann 4837cad718edSJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 4838cad718edSJohan Hedberg if (conn) 4839cad718edSJohan Hedberg memcpy(conn->features[1], ev->features, 8); 4840cad718edSJohan Hedberg 4841cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 4842cc11b9c1SAndrei Emeltchenko if (ie) 484302b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 484441a96212SMarcel Holtmann 484541a96212SMarcel Holtmann hci_dev_unlock(hdev); 484641a96212SMarcel Holtmann } 484741a96212SMarcel Holtmann 48486039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev, 48492763eda6SSzymon Janc struct sk_buff *skb) 48502763eda6SSzymon Janc { 48512763eda6SSzymon Janc struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; 48522763eda6SSzymon Janc struct oob_data *data; 48532763eda6SSzymon Janc 48542763eda6SSzymon Janc BT_DBG("%s", hdev->name); 48552763eda6SSzymon Janc 48562763eda6SSzymon Janc hci_dev_lock(hdev); 48572763eda6SSzymon Janc 4858d7a5a11dSMarcel Holtmann if (!hci_dev_test_flag(hdev, HCI_MGMT)) 4859e1ba1f15SSzymon Janc goto unlock; 4860e1ba1f15SSzymon Janc 48616928a924SJohan Hedberg data = hci_find_remote_oob_data(hdev, &ev->bdaddr, BDADDR_BREDR); 48626665d057SMarcel Holtmann if (!data) { 48636665d057SMarcel Holtmann struct hci_cp_remote_oob_data_neg_reply cp; 48646665d057SMarcel Holtmann 48656665d057SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 48666665d057SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, 48676665d057SMarcel Holtmann sizeof(cp), &cp); 48686665d057SMarcel Holtmann goto unlock; 48696665d057SMarcel Holtmann } 48706665d057SMarcel Holtmann 4871710f11c0SJohan Hedberg if (bredr_sc_enabled(hdev)) { 4872519ca9d0SMarcel Holtmann struct hci_cp_remote_oob_ext_data_reply cp; 4873519ca9d0SMarcel Holtmann 4874519ca9d0SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 4875d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_SC_ONLY)) { 48766665d057SMarcel Holtmann memset(cp.hash192, 0, sizeof(cp.hash192)); 48776665d057SMarcel Holtmann memset(cp.rand192, 0, sizeof(cp.rand192)); 48786665d057SMarcel Holtmann } else { 4879519ca9d0SMarcel Holtmann memcpy(cp.hash192, data->hash192, sizeof(cp.hash192)); 488038da1703SJohan Hedberg memcpy(cp.rand192, data->rand192, sizeof(cp.rand192)); 48816665d057SMarcel Holtmann } 4882519ca9d0SMarcel Holtmann memcpy(cp.hash256, data->hash256, sizeof(cp.hash256)); 488338da1703SJohan Hedberg memcpy(cp.rand256, data->rand256, sizeof(cp.rand256)); 4884519ca9d0SMarcel Holtmann 4885519ca9d0SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_EXT_DATA_REPLY, 4886519ca9d0SMarcel Holtmann sizeof(cp), &cp); 4887519ca9d0SMarcel Holtmann } else { 48882763eda6SSzymon Janc struct hci_cp_remote_oob_data_reply cp; 48892763eda6SSzymon Janc 48902763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 4891519ca9d0SMarcel Holtmann memcpy(cp.hash, data->hash192, sizeof(cp.hash)); 489238da1703SJohan Hedberg memcpy(cp.rand, data->rand192, sizeof(cp.rand)); 48932763eda6SSzymon Janc 4894519ca9d0SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, 4895519ca9d0SMarcel Holtmann sizeof(cp), &cp); 4896519ca9d0SMarcel Holtmann } 48972763eda6SSzymon Janc 4898e1ba1f15SSzymon Janc unlock: 48992763eda6SSzymon Janc hci_dev_unlock(hdev); 49002763eda6SSzymon Janc } 49012763eda6SSzymon Janc 4902a77a6a14SArron Wang #if IS_ENABLED(CONFIG_BT_HS) 4903a77a6a14SArron Wang static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb) 4904a77a6a14SArron Wang { 4905a77a6a14SArron Wang struct hci_ev_channel_selected *ev = (void *)skb->data; 4906a77a6a14SArron Wang struct hci_conn *hcon; 4907a77a6a14SArron Wang 4908a77a6a14SArron Wang BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle); 4909a77a6a14SArron Wang 4910a77a6a14SArron Wang skb_pull(skb, sizeof(*ev)); 4911a77a6a14SArron Wang 4912a77a6a14SArron Wang hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 4913a77a6a14SArron Wang if (!hcon) 4914a77a6a14SArron Wang return; 4915a77a6a14SArron Wang 4916a77a6a14SArron Wang amp_read_loc_assoc_final_data(hdev, hcon); 4917a77a6a14SArron Wang } 4918a77a6a14SArron Wang 4919d5e91192SAndrei Emeltchenko static void hci_phy_link_complete_evt(struct hci_dev *hdev, 4920d5e91192SAndrei Emeltchenko struct sk_buff *skb) 4921d5e91192SAndrei Emeltchenko { 4922d5e91192SAndrei Emeltchenko struct hci_ev_phy_link_complete *ev = (void *) skb->data; 4923d5e91192SAndrei Emeltchenko struct hci_conn *hcon, *bredr_hcon; 4924d5e91192SAndrei Emeltchenko 4925d5e91192SAndrei Emeltchenko BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle, 4926d5e91192SAndrei Emeltchenko ev->status); 4927d5e91192SAndrei Emeltchenko 4928d5e91192SAndrei Emeltchenko hci_dev_lock(hdev); 4929d5e91192SAndrei Emeltchenko 4930d5e91192SAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 4931d5e91192SAndrei Emeltchenko if (!hcon) { 4932d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 4933d5e91192SAndrei Emeltchenko return; 4934d5e91192SAndrei Emeltchenko } 4935d5e91192SAndrei Emeltchenko 4936d5e91192SAndrei Emeltchenko if (ev->status) { 4937d5e91192SAndrei Emeltchenko hci_conn_del(hcon); 4938d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 4939d5e91192SAndrei Emeltchenko return; 4940d5e91192SAndrei Emeltchenko } 4941d5e91192SAndrei Emeltchenko 4942d5e91192SAndrei Emeltchenko bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon; 4943d5e91192SAndrei Emeltchenko 4944d5e91192SAndrei Emeltchenko hcon->state = BT_CONNECTED; 4945d5e91192SAndrei Emeltchenko bacpy(&hcon->dst, &bredr_hcon->dst); 4946d5e91192SAndrei Emeltchenko 4947d5e91192SAndrei Emeltchenko hci_conn_hold(hcon); 4948d5e91192SAndrei Emeltchenko hcon->disc_timeout = HCI_DISCONN_TIMEOUT; 494976a68ba0SDavid Herrmann hci_conn_drop(hcon); 4950d5e91192SAndrei Emeltchenko 495123b9ceb7SMarcel Holtmann hci_debugfs_create_conn(hcon); 4952d5e91192SAndrei Emeltchenko hci_conn_add_sysfs(hcon); 4953d5e91192SAndrei Emeltchenko 4954cf70ff22SAndrei Emeltchenko amp_physical_cfm(bredr_hcon, hcon); 4955cf70ff22SAndrei Emeltchenko 4956d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 4957d5e91192SAndrei Emeltchenko } 4958d5e91192SAndrei Emeltchenko 495927695fb4SAndrei Emeltchenko static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 496027695fb4SAndrei Emeltchenko { 496127695fb4SAndrei Emeltchenko struct hci_ev_logical_link_complete *ev = (void *) skb->data; 496227695fb4SAndrei Emeltchenko struct hci_conn *hcon; 496327695fb4SAndrei Emeltchenko struct hci_chan *hchan; 496427695fb4SAndrei Emeltchenko struct amp_mgr *mgr; 496527695fb4SAndrei Emeltchenko 496627695fb4SAndrei Emeltchenko BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x", 496727695fb4SAndrei Emeltchenko hdev->name, le16_to_cpu(ev->handle), ev->phy_handle, 496827695fb4SAndrei Emeltchenko ev->status); 496927695fb4SAndrei Emeltchenko 497027695fb4SAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 497127695fb4SAndrei Emeltchenko if (!hcon) 497227695fb4SAndrei Emeltchenko return; 497327695fb4SAndrei Emeltchenko 497427695fb4SAndrei Emeltchenko /* Create AMP hchan */ 497527695fb4SAndrei Emeltchenko hchan = hci_chan_create(hcon); 497627695fb4SAndrei Emeltchenko if (!hchan) 497727695fb4SAndrei Emeltchenko return; 497827695fb4SAndrei Emeltchenko 497927695fb4SAndrei Emeltchenko hchan->handle = le16_to_cpu(ev->handle); 498027695fb4SAndrei Emeltchenko 498127695fb4SAndrei Emeltchenko BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan); 498227695fb4SAndrei Emeltchenko 498327695fb4SAndrei Emeltchenko mgr = hcon->amp_mgr; 498427695fb4SAndrei Emeltchenko if (mgr && mgr->bredr_chan) { 498527695fb4SAndrei Emeltchenko struct l2cap_chan *bredr_chan = mgr->bredr_chan; 498627695fb4SAndrei Emeltchenko 498727695fb4SAndrei Emeltchenko l2cap_chan_lock(bredr_chan); 498827695fb4SAndrei Emeltchenko 498927695fb4SAndrei Emeltchenko bredr_chan->conn->mtu = hdev->block_mtu; 499027695fb4SAndrei Emeltchenko l2cap_logical_cfm(bredr_chan, hchan, 0); 499127695fb4SAndrei Emeltchenko hci_conn_hold(hcon); 499227695fb4SAndrei Emeltchenko 499327695fb4SAndrei Emeltchenko l2cap_chan_unlock(bredr_chan); 499427695fb4SAndrei Emeltchenko } 499527695fb4SAndrei Emeltchenko } 499627695fb4SAndrei Emeltchenko 4997606e2a10SAndrei Emeltchenko static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev, 4998606e2a10SAndrei Emeltchenko struct sk_buff *skb) 4999606e2a10SAndrei Emeltchenko { 5000606e2a10SAndrei Emeltchenko struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data; 5001606e2a10SAndrei Emeltchenko struct hci_chan *hchan; 5002606e2a10SAndrei Emeltchenko 5003606e2a10SAndrei Emeltchenko BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name, 5004606e2a10SAndrei Emeltchenko le16_to_cpu(ev->handle), ev->status); 5005606e2a10SAndrei Emeltchenko 5006606e2a10SAndrei Emeltchenko if (ev->status) 5007606e2a10SAndrei Emeltchenko return; 5008606e2a10SAndrei Emeltchenko 5009606e2a10SAndrei Emeltchenko hci_dev_lock(hdev); 5010606e2a10SAndrei Emeltchenko 5011606e2a10SAndrei Emeltchenko hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle)); 5012606e2a10SAndrei Emeltchenko if (!hchan) 5013606e2a10SAndrei Emeltchenko goto unlock; 5014606e2a10SAndrei Emeltchenko 5015606e2a10SAndrei Emeltchenko amp_destroy_logical_link(hchan, ev->reason); 5016606e2a10SAndrei Emeltchenko 5017606e2a10SAndrei Emeltchenko unlock: 5018606e2a10SAndrei Emeltchenko hci_dev_unlock(hdev); 5019606e2a10SAndrei Emeltchenko } 5020606e2a10SAndrei Emeltchenko 50219eef6b3aSAndrei Emeltchenko static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev, 50229eef6b3aSAndrei Emeltchenko struct sk_buff *skb) 50239eef6b3aSAndrei Emeltchenko { 50249eef6b3aSAndrei Emeltchenko struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data; 50259eef6b3aSAndrei Emeltchenko struct hci_conn *hcon; 50269eef6b3aSAndrei Emeltchenko 50279eef6b3aSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 50289eef6b3aSAndrei Emeltchenko 50299eef6b3aSAndrei Emeltchenko if (ev->status) 50309eef6b3aSAndrei Emeltchenko return; 50319eef6b3aSAndrei Emeltchenko 50329eef6b3aSAndrei Emeltchenko hci_dev_lock(hdev); 50339eef6b3aSAndrei Emeltchenko 50349eef6b3aSAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 50359eef6b3aSAndrei Emeltchenko if (hcon) { 50369eef6b3aSAndrei Emeltchenko hcon->state = BT_CLOSED; 50379eef6b3aSAndrei Emeltchenko hci_conn_del(hcon); 50389eef6b3aSAndrei Emeltchenko } 50399eef6b3aSAndrei Emeltchenko 50409eef6b3aSAndrei Emeltchenko hci_dev_unlock(hdev); 50419eef6b3aSAndrei Emeltchenko } 5042a77a6a14SArron Wang #endif 50439eef6b3aSAndrei Emeltchenko 5044d12fb056SJaganath Kanakkassery static void le_conn_complete_evt(struct hci_dev *hdev, u8 status, 5045d12fb056SJaganath Kanakkassery bdaddr_t *bdaddr, u8 bdaddr_type, u8 role, u16 handle, 5046d12fb056SJaganath Kanakkassery u16 interval, u16 latency, u16 supervision_timeout) 5047fcd89c09SVille Tervo { 5048912b42efSJohan Hedberg struct hci_conn_params *params; 5049fcd89c09SVille Tervo struct hci_conn *conn; 505068d6f6deSJohan Hedberg struct smp_irk *irk; 5051837d502eSJohan Hedberg u8 addr_type; 5052fcd89c09SVille Tervo 5053fcd89c09SVille Tervo hci_dev_lock(hdev); 5054fcd89c09SVille Tervo 5055fbd96c15SJohan Hedberg /* All controllers implicitly stop advertising in the event of a 5056fbd96c15SJohan Hedberg * connection, so ensure that the state bit is cleared. 5057fbd96c15SJohan Hedberg */ 5058a358dc11SMarcel Holtmann hci_dev_clear_flag(hdev, HCI_LE_ADV); 5059fbd96c15SJohan Hedberg 5060e7d9ab73SJakub Pawlowski conn = hci_lookup_le_connect(hdev); 5061b62f328bSVille Tervo if (!conn) { 5062d12fb056SJaganath Kanakkassery conn = hci_conn_add(hdev, LE_LINK, bdaddr, role); 5063b62f328bSVille Tervo if (!conn) { 50642064ee33SMarcel Holtmann bt_dev_err(hdev, "no memory for new connection"); 5065230fd16aSAndre Guedes goto unlock; 5066b62f328bSVille Tervo } 506729b7988aSAndre Guedes 5068d12fb056SJaganath Kanakkassery conn->dst_type = bdaddr_type; 5069b9b343d2SAndre Guedes 5070cb1d68f7SJohan Hedberg /* If we didn't have a hci_conn object previously 5071cb1d68f7SJohan Hedberg * but we're in master role this must be something 5072cb1d68f7SJohan Hedberg * initiated using a white list. Since white list based 5073cb1d68f7SJohan Hedberg * connections are not "first class citizens" we don't 5074cb1d68f7SJohan Hedberg * have full tracking of them. Therefore, we go ahead 5075cb1d68f7SJohan Hedberg * with a "best effort" approach of determining the 5076cb1d68f7SJohan Hedberg * initiator address based on the HCI_PRIVACY flag. 5077cb1d68f7SJohan Hedberg */ 5078cb1d68f7SJohan Hedberg if (conn->out) { 5079d12fb056SJaganath Kanakkassery conn->resp_addr_type = bdaddr_type; 5080d12fb056SJaganath Kanakkassery bacpy(&conn->resp_addr, bdaddr); 5081d7a5a11dSMarcel Holtmann if (hci_dev_test_flag(hdev, HCI_PRIVACY)) { 5082cb1d68f7SJohan Hedberg conn->init_addr_type = ADDR_LE_DEV_RANDOM; 5083cb1d68f7SJohan Hedberg bacpy(&conn->init_addr, &hdev->rpa); 5084cb1d68f7SJohan Hedberg } else { 5085cb1d68f7SJohan Hedberg hci_copy_identity_address(hdev, 5086cb1d68f7SJohan Hedberg &conn->init_addr, 5087cb1d68f7SJohan Hedberg &conn->init_addr_type); 5088cb1d68f7SJohan Hedberg } 508980c24ab8SJohan Hedberg } 5090cb1d68f7SJohan Hedberg } else { 509180c24ab8SJohan Hedberg cancel_delayed_work(&conn->le_conn_timeout); 509280c24ab8SJohan Hedberg } 509380c24ab8SJohan Hedberg 509480c24ab8SJohan Hedberg if (!conn->out) { 5095cb1d68f7SJohan Hedberg /* Set the responder (our side) address type based on 5096cb1d68f7SJohan Hedberg * the advertising address type. 5097cb1d68f7SJohan Hedberg */ 5098cb1d68f7SJohan Hedberg conn->resp_addr_type = hdev->adv_addr_type; 5099acf0aeaeSJaganath Kanakkassery if (hdev->adv_addr_type == ADDR_LE_DEV_RANDOM) { 5100acf0aeaeSJaganath Kanakkassery /* In case of ext adv, resp_addr will be updated in 5101acf0aeaeSJaganath Kanakkassery * Adv Terminated event. 5102acf0aeaeSJaganath Kanakkassery */ 5103acf0aeaeSJaganath Kanakkassery if (!ext_adv_capable(hdev)) 5104cb1d68f7SJohan Hedberg bacpy(&conn->resp_addr, &hdev->random_addr); 5105acf0aeaeSJaganath Kanakkassery } else { 5106cb1d68f7SJohan Hedberg bacpy(&conn->resp_addr, &hdev->bdaddr); 5107acf0aeaeSJaganath Kanakkassery } 5108cb1d68f7SJohan Hedberg 5109d12fb056SJaganath Kanakkassery conn->init_addr_type = bdaddr_type; 5110d12fb056SJaganath Kanakkassery bacpy(&conn->init_addr, bdaddr); 5111a720d735SMarcel Holtmann 5112a720d735SMarcel Holtmann /* For incoming connections, set the default minimum 5113a720d735SMarcel Holtmann * and maximum connection interval. They will be used 5114a720d735SMarcel Holtmann * to check if the parameters are in range and if not 5115a720d735SMarcel Holtmann * trigger the connection update procedure. 5116a720d735SMarcel Holtmann */ 5117a720d735SMarcel Holtmann conn->le_conn_min_interval = hdev->le_conn_min_interval; 5118a720d735SMarcel Holtmann conn->le_conn_max_interval = hdev->le_conn_max_interval; 5119cb1d68f7SJohan Hedberg } 51207be2edbbSJohan Hedberg 5121edb4b466SMarcel Holtmann /* Lookup the identity address from the stored connection 5122edb4b466SMarcel Holtmann * address and address type. 5123edb4b466SMarcel Holtmann * 5124edb4b466SMarcel Holtmann * When establishing connections to an identity address, the 5125edb4b466SMarcel Holtmann * connection procedure will store the resolvable random 5126edb4b466SMarcel Holtmann * address first. Now if it can be converted back into the 5127edb4b466SMarcel Holtmann * identity address, start using the identity address from 5128edb4b466SMarcel Holtmann * now on. 5129edb4b466SMarcel Holtmann */ 5130edb4b466SMarcel Holtmann irk = hci_get_irk(hdev, &conn->dst, conn->dst_type); 513168d6f6deSJohan Hedberg if (irk) { 513268d6f6deSJohan Hedberg bacpy(&conn->dst, &irk->bdaddr); 513368d6f6deSJohan Hedberg conn->dst_type = irk->addr_type; 513468d6f6deSJohan Hedberg } 513568d6f6deSJohan Hedberg 5136d12fb056SJaganath Kanakkassery if (status) { 5137d12fb056SJaganath Kanakkassery hci_le_conn_failed(conn, status); 5138837d502eSJohan Hedberg goto unlock; 5139837d502eSJohan Hedberg } 5140837d502eSJohan Hedberg 514108853f18SJohan Hedberg if (conn->dst_type == ADDR_LE_DEV_PUBLIC) 514208853f18SJohan Hedberg addr_type = BDADDR_LE_PUBLIC; 514308853f18SJohan Hedberg else 514408853f18SJohan Hedberg addr_type = BDADDR_LE_RANDOM; 514508853f18SJohan Hedberg 51462d3c2260SJohan Hedberg /* Drop the connection if the device is blocked */ 51472d3c2260SJohan Hedberg if (hci_bdaddr_list_lookup(&hdev->blacklist, &conn->dst, addr_type)) { 51482d3c2260SJohan Hedberg hci_conn_drop(conn); 5149cd17decbSAndre Guedes goto unlock; 5150cd17decbSAndre Guedes } 5151cd17decbSAndre Guedes 5152b644ba33SJohan Hedberg if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 515348ec92faSAlfonso Acosta mgmt_device_connected(hdev, conn, 0, NULL, 0); 515483bc71b4SVinicius Costa Gomes 51557b5c0d52SVinicius Costa Gomes conn->sec_level = BT_SECURITY_LOW; 5156d12fb056SJaganath Kanakkassery conn->handle = handle; 51570fe29fd1SMarcel Holtmann conn->state = BT_CONFIG; 5158fcd89c09SVille Tervo 5159d12fb056SJaganath Kanakkassery conn->le_conn_interval = interval; 5160d12fb056SJaganath Kanakkassery conn->le_conn_latency = latency; 5161d12fb056SJaganath Kanakkassery conn->le_supv_timeout = supervision_timeout; 5162e04fde60SMarcel Holtmann 516323b9ceb7SMarcel Holtmann hci_debugfs_create_conn(conn); 5164fcd89c09SVille Tervo hci_conn_add_sysfs(conn); 5165fcd89c09SVille Tervo 51660fe29fd1SMarcel Holtmann /* The remote features procedure is defined for master 51670fe29fd1SMarcel Holtmann * role only. So only in case of an initiated connection 51680fe29fd1SMarcel Holtmann * request the remote features. 51690fe29fd1SMarcel Holtmann * 51700fe29fd1SMarcel Holtmann * If the local controller supports slave-initiated features 51710fe29fd1SMarcel Holtmann * exchange, then requesting the remote features in slave 51720fe29fd1SMarcel Holtmann * role is possible. Otherwise just transition into the 51730fe29fd1SMarcel Holtmann * connected state without requesting the remote features. 51740fe29fd1SMarcel Holtmann */ 51750fe29fd1SMarcel Holtmann if (conn->out || 51760fe29fd1SMarcel Holtmann (hdev->le_features[0] & HCI_LE_SLAVE_FEATURES)) { 51770fe29fd1SMarcel Holtmann struct hci_cp_le_read_remote_features cp; 51780fe29fd1SMarcel Holtmann 51790fe29fd1SMarcel Holtmann cp.handle = __cpu_to_le16(conn->handle); 51800fe29fd1SMarcel Holtmann 51810fe29fd1SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_LE_READ_REMOTE_FEATURES, 51820fe29fd1SMarcel Holtmann sizeof(cp), &cp); 51830fe29fd1SMarcel Holtmann 51840fe29fd1SMarcel Holtmann hci_conn_hold(conn); 51850fe29fd1SMarcel Holtmann } else { 51860fe29fd1SMarcel Holtmann conn->state = BT_CONNECTED; 5187d12fb056SJaganath Kanakkassery hci_connect_cfm(conn, status); 51880fe29fd1SMarcel Holtmann } 5189fcd89c09SVille Tervo 51905477610fSJohan Hedberg params = hci_pend_le_action_lookup(&hdev->pend_le_conns, &conn->dst, 51915477610fSJohan Hedberg conn->dst_type); 5192f161dd41SJohan Hedberg if (params) { 519395305baaSJohan Hedberg list_del_init(¶ms->action); 5194f161dd41SJohan Hedberg if (params->conn) { 5195f161dd41SJohan Hedberg hci_conn_drop(params->conn); 5196f8aaf9b6SJohan Hedberg hci_conn_put(params->conn); 5197f161dd41SJohan Hedberg params->conn = NULL; 5198f161dd41SJohan Hedberg } 5199f161dd41SJohan Hedberg } 5200a4790dbdSAndre Guedes 5201fcd89c09SVille Tervo unlock: 5202223683a5SJohan Hedberg hci_update_background_scan(hdev); 5203fcd89c09SVille Tervo hci_dev_unlock(hdev); 5204fcd89c09SVille Tervo } 5205fcd89c09SVille Tervo 5206d12fb056SJaganath Kanakkassery static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 5207d12fb056SJaganath Kanakkassery { 5208d12fb056SJaganath Kanakkassery struct hci_ev_le_conn_complete *ev = (void *) skb->data; 5209d12fb056SJaganath Kanakkassery 5210d12fb056SJaganath Kanakkassery BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 5211d12fb056SJaganath Kanakkassery 5212d12fb056SJaganath Kanakkassery le_conn_complete_evt(hdev, ev->status, &ev->bdaddr, ev->bdaddr_type, 5213d12fb056SJaganath Kanakkassery ev->role, le16_to_cpu(ev->handle), 5214d12fb056SJaganath Kanakkassery le16_to_cpu(ev->interval), 5215d12fb056SJaganath Kanakkassery le16_to_cpu(ev->latency), 5216d12fb056SJaganath Kanakkassery le16_to_cpu(ev->supervision_timeout)); 5217d12fb056SJaganath Kanakkassery } 5218d12fb056SJaganath Kanakkassery 52194d94f95dSJaganath Kanakkassery static void hci_le_enh_conn_complete_evt(struct hci_dev *hdev, 52204d94f95dSJaganath Kanakkassery struct sk_buff *skb) 52214d94f95dSJaganath Kanakkassery { 52224d94f95dSJaganath Kanakkassery struct hci_ev_le_enh_conn_complete *ev = (void *) skb->data; 52234d94f95dSJaganath Kanakkassery 52244d94f95dSJaganath Kanakkassery BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 52254d94f95dSJaganath Kanakkassery 52264d94f95dSJaganath Kanakkassery le_conn_complete_evt(hdev, ev->status, &ev->bdaddr, ev->bdaddr_type, 52274d94f95dSJaganath Kanakkassery ev->role, le16_to_cpu(ev->handle), 52284d94f95dSJaganath Kanakkassery le16_to_cpu(ev->interval), 52294d94f95dSJaganath Kanakkassery le16_to_cpu(ev->latency), 52304d94f95dSJaganath Kanakkassery le16_to_cpu(ev->supervision_timeout)); 52315c49bcceSSathish Narasimman 52325c49bcceSSathish Narasimman if (use_ll_privacy(hdev) && 5233cbbdfa6fSSathish Narasimman hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY) && 52345c49bcceSSathish Narasimman hci_dev_test_flag(hdev, HCI_LL_RPA_RESOLUTION)) 52355c49bcceSSathish Narasimman hci_req_disable_address_resolution(hdev); 52364d94f95dSJaganath Kanakkassery } 52374d94f95dSJaganath Kanakkassery 5238acf0aeaeSJaganath Kanakkassery static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, struct sk_buff *skb) 5239acf0aeaeSJaganath Kanakkassery { 5240acf0aeaeSJaganath Kanakkassery struct hci_evt_le_ext_adv_set_term *ev = (void *) skb->data; 5241acf0aeaeSJaganath Kanakkassery struct hci_conn *conn; 5242acf0aeaeSJaganath Kanakkassery 5243acf0aeaeSJaganath Kanakkassery BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 5244acf0aeaeSJaganath Kanakkassery 5245acf0aeaeSJaganath Kanakkassery if (ev->status) 5246acf0aeaeSJaganath Kanakkassery return; 5247acf0aeaeSJaganath Kanakkassery 5248acf0aeaeSJaganath Kanakkassery conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->conn_handle)); 5249acf0aeaeSJaganath Kanakkassery if (conn) { 5250acf0aeaeSJaganath Kanakkassery struct adv_info *adv_instance; 5251acf0aeaeSJaganath Kanakkassery 5252acf0aeaeSJaganath Kanakkassery if (hdev->adv_addr_type != ADDR_LE_DEV_RANDOM) 5253acf0aeaeSJaganath Kanakkassery return; 5254acf0aeaeSJaganath Kanakkassery 5255acf0aeaeSJaganath Kanakkassery if (!hdev->cur_adv_instance) { 5256acf0aeaeSJaganath Kanakkassery bacpy(&conn->resp_addr, &hdev->random_addr); 5257acf0aeaeSJaganath Kanakkassery return; 5258acf0aeaeSJaganath Kanakkassery } 5259acf0aeaeSJaganath Kanakkassery 5260acf0aeaeSJaganath Kanakkassery adv_instance = hci_find_adv_instance(hdev, hdev->cur_adv_instance); 5261acf0aeaeSJaganath Kanakkassery if (adv_instance) 5262acf0aeaeSJaganath Kanakkassery bacpy(&conn->resp_addr, &adv_instance->random_addr); 5263acf0aeaeSJaganath Kanakkassery } 5264acf0aeaeSJaganath Kanakkassery } 5265acf0aeaeSJaganath Kanakkassery 52661855d92dSMarcel Holtmann static void hci_le_conn_update_complete_evt(struct hci_dev *hdev, 52671855d92dSMarcel Holtmann struct sk_buff *skb) 52681855d92dSMarcel Holtmann { 52691855d92dSMarcel Holtmann struct hci_ev_le_conn_update_complete *ev = (void *) skb->data; 52701855d92dSMarcel Holtmann struct hci_conn *conn; 52711855d92dSMarcel Holtmann 52721855d92dSMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 52731855d92dSMarcel Holtmann 52741855d92dSMarcel Holtmann if (ev->status) 52751855d92dSMarcel Holtmann return; 52761855d92dSMarcel Holtmann 52771855d92dSMarcel Holtmann hci_dev_lock(hdev); 52781855d92dSMarcel Holtmann 52791855d92dSMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 52801855d92dSMarcel Holtmann if (conn) { 52811855d92dSMarcel Holtmann conn->le_conn_interval = le16_to_cpu(ev->interval); 52821855d92dSMarcel Holtmann conn->le_conn_latency = le16_to_cpu(ev->latency); 52831855d92dSMarcel Holtmann conn->le_supv_timeout = le16_to_cpu(ev->supervision_timeout); 52841855d92dSMarcel Holtmann } 52851855d92dSMarcel Holtmann 52861855d92dSMarcel Holtmann hci_dev_unlock(hdev); 52871855d92dSMarcel Holtmann } 52881855d92dSMarcel Holtmann 5289a4790dbdSAndre Guedes /* This function requires the caller holds hdev->lock */ 5290fd45ada9SAlfonso Acosta static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev, 5291fd45ada9SAlfonso Acosta bdaddr_t *addr, 5292082f2300SSzymon Janc u8 addr_type, u8 adv_type, 5293082f2300SSzymon Janc bdaddr_t *direct_rpa) 5294a4790dbdSAndre Guedes { 5295a4790dbdSAndre Guedes struct hci_conn *conn; 52964b9e7e75SMarcel Holtmann struct hci_conn_params *params; 5297a4790dbdSAndre Guedes 52981c1abcabSJohan Hedberg /* If the event is not connectable don't proceed further */ 52991c1abcabSJohan Hedberg if (adv_type != LE_ADV_IND && adv_type != LE_ADV_DIRECT_IND) 5300fd45ada9SAlfonso Acosta return NULL; 53011c1abcabSJohan Hedberg 53021c1abcabSJohan Hedberg /* Ignore if the device is blocked */ 5303dcc36c16SJohan Hedberg if (hci_bdaddr_list_lookup(&hdev->blacklist, addr, addr_type)) 5304fd45ada9SAlfonso Acosta return NULL; 53051c1abcabSJohan Hedberg 5306f99353cfSJohan Hedberg /* Most controller will fail if we try to create new connections 5307f99353cfSJohan Hedberg * while we have an existing one in slave role. 5308f99353cfSJohan Hedberg */ 53094364f2e9SAlain Michaud if (hdev->conn_hash.le_num_slave > 0 && 53104364f2e9SAlain Michaud (!test_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks) || 53114364f2e9SAlain Michaud !(hdev->le_states[3] & 0x10))) 5312fd45ada9SAlfonso Acosta return NULL; 5313f99353cfSJohan Hedberg 53141c1abcabSJohan Hedberg /* If we're not connectable only connect devices that we have in 53151c1abcabSJohan Hedberg * our pend_le_conns list. 53161c1abcabSJohan Hedberg */ 531749c50922SJohan Hedberg params = hci_pend_le_action_lookup(&hdev->pend_le_conns, addr, 531849c50922SJohan Hedberg addr_type); 53194b9e7e75SMarcel Holtmann if (!params) 5320fd45ada9SAlfonso Acosta return NULL; 5321a4790dbdSAndre Guedes 532228a667c9SJakub Pawlowski if (!params->explicit_connect) { 53234b9e7e75SMarcel Holtmann switch (params->auto_connect) { 53244b9e7e75SMarcel Holtmann case HCI_AUTO_CONN_DIRECT: 53254b9e7e75SMarcel Holtmann /* Only devices advertising with ADV_DIRECT_IND are 53264b9e7e75SMarcel Holtmann * triggering a connection attempt. This is allowing 53274b9e7e75SMarcel Holtmann * incoming connections from slave devices. 53284b9e7e75SMarcel Holtmann */ 53294b9e7e75SMarcel Holtmann if (adv_type != LE_ADV_DIRECT_IND) 5330fd45ada9SAlfonso Acosta return NULL; 53314b9e7e75SMarcel Holtmann break; 53324b9e7e75SMarcel Holtmann case HCI_AUTO_CONN_ALWAYS: 53334b9e7e75SMarcel Holtmann /* Devices advertising with ADV_IND or ADV_DIRECT_IND 53344b9e7e75SMarcel Holtmann * are triggering a connection attempt. This means 53351e5479beSAlain Michaud * that incoming connections from slave device are 53364b9e7e75SMarcel Holtmann * accepted and also outgoing connections to slave 53374b9e7e75SMarcel Holtmann * devices are established when found. 53384b9e7e75SMarcel Holtmann */ 53394b9e7e75SMarcel Holtmann break; 53404b9e7e75SMarcel Holtmann default: 5341fd45ada9SAlfonso Acosta return NULL; 53424b9e7e75SMarcel Holtmann } 534328a667c9SJakub Pawlowski } 53444b9e7e75SMarcel Holtmann 5345a4790dbdSAndre Guedes conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW, 534649b020c1SAlain Michaud hdev->def_le_autoconnect_timeout, HCI_ROLE_MASTER, 5347082f2300SSzymon Janc direct_rpa); 5348f161dd41SJohan Hedberg if (!IS_ERR(conn)) { 534928a667c9SJakub Pawlowski /* If HCI_AUTO_CONN_EXPLICIT is set, conn is already owned 535028a667c9SJakub Pawlowski * by higher layer that tried to connect, if no then 535128a667c9SJakub Pawlowski * store the pointer since we don't really have any 5352f161dd41SJohan Hedberg * other owner of the object besides the params that 5353f161dd41SJohan Hedberg * triggered it. This way we can abort the connection if 5354f161dd41SJohan Hedberg * the parameters get removed and keep the reference 5355f161dd41SJohan Hedberg * count consistent once the connection is established. 5356f161dd41SJohan Hedberg */ 535728a667c9SJakub Pawlowski 535828a667c9SJakub Pawlowski if (!params->explicit_connect) 5359f8aaf9b6SJohan Hedberg params->conn = hci_conn_get(conn); 536028a667c9SJakub Pawlowski 5361fd45ada9SAlfonso Acosta return conn; 5362f161dd41SJohan Hedberg } 5363a4790dbdSAndre Guedes 5364a4790dbdSAndre Guedes switch (PTR_ERR(conn)) { 5365a4790dbdSAndre Guedes case -EBUSY: 5366a4790dbdSAndre Guedes /* If hci_connect() returns -EBUSY it means there is already 5367a4790dbdSAndre Guedes * an LE connection attempt going on. Since controllers don't 5368a4790dbdSAndre Guedes * support more than one connection attempt at the time, we 5369a4790dbdSAndre Guedes * don't consider this an error case. 5370a4790dbdSAndre Guedes */ 5371a4790dbdSAndre Guedes break; 5372a4790dbdSAndre Guedes default: 5373a4790dbdSAndre Guedes BT_DBG("Failed to connect: err %ld", PTR_ERR(conn)); 5374fd45ada9SAlfonso Acosta return NULL; 5375a4790dbdSAndre Guedes } 5376fd45ada9SAlfonso Acosta 5377fd45ada9SAlfonso Acosta return NULL; 5378a4790dbdSAndre Guedes } 5379a4790dbdSAndre Guedes 53804af605d8SJohan Hedberg static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, 53812f010b55SMarcel Holtmann u8 bdaddr_type, bdaddr_t *direct_addr, 53822f010b55SMarcel Holtmann u8 direct_addr_type, s8 rssi, u8 *data, u8 len) 53834af605d8SJohan Hedberg { 5384b9a6328fSJohan Hedberg struct discovery_state *d = &hdev->discovery; 53851c1abcabSJohan Hedberg struct smp_irk *irk; 5386fd45ada9SAlfonso Acosta struct hci_conn *conn; 5387474ee066SJohan Hedberg bool match; 5388c70a7e4cSMarcel Holtmann u32 flags; 53896818375eSSzymon Janc u8 *ptr, real_len; 53906818375eSSzymon Janc 539156b40fbfSJohan Hedberg switch (type) { 539256b40fbfSJohan Hedberg case LE_ADV_IND: 539356b40fbfSJohan Hedberg case LE_ADV_DIRECT_IND: 539456b40fbfSJohan Hedberg case LE_ADV_SCAN_IND: 539556b40fbfSJohan Hedberg case LE_ADV_NONCONN_IND: 539656b40fbfSJohan Hedberg case LE_ADV_SCAN_RSP: 539756b40fbfSJohan Hedberg break; 539856b40fbfSJohan Hedberg default: 53992064ee33SMarcel Holtmann bt_dev_err_ratelimited(hdev, "unknown advertising packet " 54002064ee33SMarcel Holtmann "type: 0x%02x", type); 540156b40fbfSJohan Hedberg return; 540256b40fbfSJohan Hedberg } 540356b40fbfSJohan Hedberg 54046818375eSSzymon Janc /* Find the end of the data in case the report contains padded zero 54056818375eSSzymon Janc * bytes at the end causing an invalid length value. 54066818375eSSzymon Janc * 54076818375eSSzymon Janc * When data is NULL, len is 0 so there is no need for extra ptr 54086818375eSSzymon Janc * check as 'ptr < data + 0' is already false in such case. 54096818375eSSzymon Janc */ 54106818375eSSzymon Janc for (ptr = data; ptr < data + len && *ptr; ptr += *ptr + 1) { 54116818375eSSzymon Janc if (ptr + 1 + *ptr > data + len) 54126818375eSSzymon Janc break; 54136818375eSSzymon Janc } 54146818375eSSzymon Janc 54156818375eSSzymon Janc real_len = ptr - data; 54166818375eSSzymon Janc 54176818375eSSzymon Janc /* Adjust for actual length */ 54186818375eSSzymon Janc if (len != real_len) { 5419943d5d92SDaniels Umanovskis bt_dev_err_ratelimited(hdev, "advertising data len corrected %u -> %u", 5420943d5d92SDaniels Umanovskis len, real_len); 54216818375eSSzymon Janc len = real_len; 54226818375eSSzymon Janc } 5423b9a6328fSJohan Hedberg 54242f010b55SMarcel Holtmann /* If the direct address is present, then this report is from 54252f010b55SMarcel Holtmann * a LE Direct Advertising Report event. In that case it is 54262f010b55SMarcel Holtmann * important to see if the address is matching the local 54272f010b55SMarcel Holtmann * controller address. 54282f010b55SMarcel Holtmann */ 54292f010b55SMarcel Holtmann if (direct_addr) { 54302f010b55SMarcel Holtmann /* Only resolvable random addresses are valid for these 54312f010b55SMarcel Holtmann * kind of reports and others can be ignored. 54322f010b55SMarcel Holtmann */ 54332f010b55SMarcel Holtmann if (!hci_bdaddr_is_rpa(direct_addr, direct_addr_type)) 54342f010b55SMarcel Holtmann return; 54352f010b55SMarcel Holtmann 54362f010b55SMarcel Holtmann /* If the controller is not using resolvable random 54372f010b55SMarcel Holtmann * addresses, then this report can be ignored. 54382f010b55SMarcel Holtmann */ 5439d7a5a11dSMarcel Holtmann if (!hci_dev_test_flag(hdev, HCI_PRIVACY)) 54402f010b55SMarcel Holtmann return; 54412f010b55SMarcel Holtmann 54422f010b55SMarcel Holtmann /* If the local IRK of the controller does not match 54432f010b55SMarcel Holtmann * with the resolvable random address provided, then 54442f010b55SMarcel Holtmann * this report can be ignored. 54452f010b55SMarcel Holtmann */ 54462f010b55SMarcel Holtmann if (!smp_irk_matches(hdev, hdev->irk, direct_addr)) 54472f010b55SMarcel Holtmann return; 54482f010b55SMarcel Holtmann } 54492f010b55SMarcel Holtmann 5450435a13d8SJohan Hedberg /* Check if we need to convert to identity address */ 5451435a13d8SJohan Hedberg irk = hci_get_irk(hdev, bdaddr, bdaddr_type); 5452435a13d8SJohan Hedberg if (irk) { 5453435a13d8SJohan Hedberg bdaddr = &irk->bdaddr; 5454435a13d8SJohan Hedberg bdaddr_type = irk->addr_type; 5455435a13d8SJohan Hedberg } 5456435a13d8SJohan Hedberg 5457082f2300SSzymon Janc /* Check if we have been requested to connect to this device. 5458082f2300SSzymon Janc * 5459082f2300SSzymon Janc * direct_addr is set only for directed advertising reports (it is NULL 5460082f2300SSzymon Janc * for advertising reports) and is already verified to be RPA above. 5461082f2300SSzymon Janc */ 5462082f2300SSzymon Janc conn = check_pending_le_conn(hdev, bdaddr, bdaddr_type, type, 5463082f2300SSzymon Janc direct_addr); 5464fd45ada9SAlfonso Acosta if (conn && type == LE_ADV_IND) { 5465fd45ada9SAlfonso Acosta /* Store report for later inclusion by 5466fd45ada9SAlfonso Acosta * mgmt_device_connected 5467fd45ada9SAlfonso Acosta */ 5468fd45ada9SAlfonso Acosta memcpy(conn->le_adv_data, data, len); 5469fd45ada9SAlfonso Acosta conn->le_adv_data_len = len; 5470fd45ada9SAlfonso Acosta } 547199a6768eSJohan Hedberg 54721c1abcabSJohan Hedberg /* Passive scanning shouldn't trigger any device found events, 54731c1abcabSJohan Hedberg * except for devices marked as CONN_REPORT for which we do send 54748208f5a9SMiao-chen Chou * device found events, or advertisement monitoring requested. 54751c1abcabSJohan Hedberg */ 54761c1abcabSJohan Hedberg if (hdev->le_scan_type == LE_SCAN_PASSIVE) { 54770d2bf134SJohan Hedberg if (type == LE_ADV_DIRECT_IND) 54780d2bf134SJohan Hedberg return; 54790d2bf134SJohan Hedberg 54803a19b6feSJohan Hedberg if (!hci_pend_le_action_lookup(&hdev->pend_le_reports, 54818208f5a9SMiao-chen Chou bdaddr, bdaddr_type) && 54828208f5a9SMiao-chen Chou idr_is_empty(&hdev->adv_monitors_idr)) 54830d2bf134SJohan Hedberg return; 54840d2bf134SJohan Hedberg 54850d2bf134SJohan Hedberg if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND) 54860d2bf134SJohan Hedberg flags = MGMT_DEV_FOUND_NOT_CONNECTABLE; 54870d2bf134SJohan Hedberg else 54880d2bf134SJohan Hedberg flags = 0; 54890d2bf134SJohan Hedberg mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL, 54900d2bf134SJohan Hedberg rssi, flags, data, len, NULL, 0); 549197bf2e99SJohan Hedberg return; 5492ca5c4be7SJohan Hedberg } 54934af605d8SJohan Hedberg 5494c70a7e4cSMarcel Holtmann /* When receiving non-connectable or scannable undirected 5495c70a7e4cSMarcel Holtmann * advertising reports, this means that the remote device is 5496c70a7e4cSMarcel Holtmann * not connectable and then clearly indicate this in the 5497c70a7e4cSMarcel Holtmann * device found event. 5498c70a7e4cSMarcel Holtmann * 5499c70a7e4cSMarcel Holtmann * When receiving a scan response, then there is no way to 5500c70a7e4cSMarcel Holtmann * know if the remote device is connectable or not. However 5501c70a7e4cSMarcel Holtmann * since scan responses are merged with a previously seen 5502c70a7e4cSMarcel Holtmann * advertising report, the flags field from that report 5503c70a7e4cSMarcel Holtmann * will be used. 5504c70a7e4cSMarcel Holtmann * 5505c70a7e4cSMarcel Holtmann * In the really unlikely case that a controller get confused 5506c70a7e4cSMarcel Holtmann * and just sends a scan response event, then it is marked as 5507c70a7e4cSMarcel Holtmann * not connectable as well. 5508c70a7e4cSMarcel Holtmann */ 5509c70a7e4cSMarcel Holtmann if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND || 5510c70a7e4cSMarcel Holtmann type == LE_ADV_SCAN_RSP) 5511c70a7e4cSMarcel Holtmann flags = MGMT_DEV_FOUND_NOT_CONNECTABLE; 5512c70a7e4cSMarcel Holtmann else 5513c70a7e4cSMarcel Holtmann flags = 0; 5514c70a7e4cSMarcel Holtmann 5515b9a6328fSJohan Hedberg /* If there's nothing pending either store the data from this 5516b9a6328fSJohan Hedberg * event or send an immediate device found event if the data 5517b9a6328fSJohan Hedberg * should not be stored for later. 5518b9a6328fSJohan Hedberg */ 5519b9a6328fSJohan Hedberg if (!has_pending_adv_report(hdev)) { 5520b9a6328fSJohan Hedberg /* If the report will trigger a SCAN_REQ store it for 5521b9a6328fSJohan Hedberg * later merging. 5522b9a6328fSJohan Hedberg */ 5523b9a6328fSJohan Hedberg if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) { 5524b9a6328fSJohan Hedberg store_pending_adv_report(hdev, bdaddr, bdaddr_type, 5525c70a7e4cSMarcel Holtmann rssi, flags, data, len); 5526b9a6328fSJohan Hedberg return; 5527b9a6328fSJohan Hedberg } 5528b9a6328fSJohan Hedberg 5529b9a6328fSJohan Hedberg mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL, 5530c70a7e4cSMarcel Holtmann rssi, flags, data, len, NULL, 0); 5531b9a6328fSJohan Hedberg return; 5532b9a6328fSJohan Hedberg } 5533b9a6328fSJohan Hedberg 5534474ee066SJohan Hedberg /* Check if the pending report is for the same device as the new one */ 5535474ee066SJohan Hedberg match = (!bacmp(bdaddr, &d->last_adv_addr) && 5536474ee066SJohan Hedberg bdaddr_type == d->last_adv_addr_type); 5537474ee066SJohan Hedberg 5538b9a6328fSJohan Hedberg /* If the pending data doesn't match this report or this isn't a 5539b9a6328fSJohan Hedberg * scan response (e.g. we got a duplicate ADV_IND) then force 5540b9a6328fSJohan Hedberg * sending of the pending data. 5541b9a6328fSJohan Hedberg */ 5542474ee066SJohan Hedberg if (type != LE_ADV_SCAN_RSP || !match) { 5543474ee066SJohan Hedberg /* Send out whatever is in the cache, but skip duplicates */ 5544474ee066SJohan Hedberg if (!match) 5545b9a6328fSJohan Hedberg mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK, 5546ff5cd29fSJohan Hedberg d->last_adv_addr_type, NULL, 5547c70a7e4cSMarcel Holtmann d->last_adv_rssi, d->last_adv_flags, 5548ff5cd29fSJohan Hedberg d->last_adv_data, 5549474ee066SJohan Hedberg d->last_adv_data_len, NULL, 0); 5550b9a6328fSJohan Hedberg 5551b9a6328fSJohan Hedberg /* If the new report will trigger a SCAN_REQ store it for 5552b9a6328fSJohan Hedberg * later merging. 5553b9a6328fSJohan Hedberg */ 5554b9a6328fSJohan Hedberg if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) { 5555b9a6328fSJohan Hedberg store_pending_adv_report(hdev, bdaddr, bdaddr_type, 5556c70a7e4cSMarcel Holtmann rssi, flags, data, len); 5557b9a6328fSJohan Hedberg return; 5558b9a6328fSJohan Hedberg } 5559b9a6328fSJohan Hedberg 5560b9a6328fSJohan Hedberg /* The advertising reports cannot be merged, so clear 5561b9a6328fSJohan Hedberg * the pending report and send out a device found event. 5562b9a6328fSJohan Hedberg */ 5563b9a6328fSJohan Hedberg clear_pending_adv_report(hdev); 55645c5b93e4SJohan Hedberg mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL, 5565c70a7e4cSMarcel Holtmann rssi, flags, data, len, NULL, 0); 5566b9a6328fSJohan Hedberg return; 5567b9a6328fSJohan Hedberg } 5568b9a6328fSJohan Hedberg 5569b9a6328fSJohan Hedberg /* If we get here we've got a pending ADV_IND or ADV_SCAN_IND and 5570b9a6328fSJohan Hedberg * the new event is a SCAN_RSP. We can therefore proceed with 5571b9a6328fSJohan Hedberg * sending a merged device found event. 5572b9a6328fSJohan Hedberg */ 5573b9a6328fSJohan Hedberg mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK, 5574c70a7e4cSMarcel Holtmann d->last_adv_addr_type, NULL, rssi, d->last_adv_flags, 557542bd6a56SMarcel Holtmann d->last_adv_data, d->last_adv_data_len, data, len); 5576b9a6328fSJohan Hedberg clear_pending_adv_report(hdev); 55774af605d8SJohan Hedberg } 55784af605d8SJohan Hedberg 55796039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) 55809aa04c91SAndre Guedes { 5581e95beb41SAndre Guedes u8 num_reports = skb->data[0]; 5582e95beb41SAndre Guedes void *ptr = &skb->data[1]; 55839aa04c91SAndre Guedes 5584a4790dbdSAndre Guedes hci_dev_lock(hdev); 5585a4790dbdSAndre Guedes 5586e95beb41SAndre Guedes while (num_reports--) { 5587e95beb41SAndre Guedes struct hci_ev_le_advertising_info *ev = ptr; 55884af605d8SJohan Hedberg s8 rssi; 5589a4790dbdSAndre Guedes 5590ee649346SChriz Chow if (ev->length <= HCI_MAX_AD_LENGTH) { 55913c9e9195SAndre Guedes rssi = ev->data[ev->length]; 55924af605d8SJohan Hedberg process_adv_report(hdev, ev->evt_type, &ev->bdaddr, 55932f010b55SMarcel Holtmann ev->bdaddr_type, NULL, 0, rssi, 55942f010b55SMarcel Holtmann ev->data, ev->length); 5595ee649346SChriz Chow } else { 5596ee649346SChriz Chow bt_dev_err(hdev, "Dropping invalid advertising data"); 5597ee649346SChriz Chow } 55983c9e9195SAndre Guedes 5599e95beb41SAndre Guedes ptr += sizeof(*ev) + ev->length + 1; 56009aa04c91SAndre Guedes } 5601a4790dbdSAndre Guedes 5602a4790dbdSAndre Guedes hci_dev_unlock(hdev); 56039aa04c91SAndre Guedes } 56049aa04c91SAndre Guedes 5605657cc646SMarcel Holtmann static u8 ext_evt_type_to_legacy(struct hci_dev *hdev, u16 evt_type) 5606c215e939SJaganath Kanakkassery { 5607b2cc9761SJaganath Kanakkassery if (evt_type & LE_EXT_ADV_LEGACY_PDU) { 5608c215e939SJaganath Kanakkassery switch (evt_type) { 5609c215e939SJaganath Kanakkassery case LE_LEGACY_ADV_IND: 5610c215e939SJaganath Kanakkassery return LE_ADV_IND; 5611c215e939SJaganath Kanakkassery case LE_LEGACY_ADV_DIRECT_IND: 5612c215e939SJaganath Kanakkassery return LE_ADV_DIRECT_IND; 5613c215e939SJaganath Kanakkassery case LE_LEGACY_ADV_SCAN_IND: 5614c215e939SJaganath Kanakkassery return LE_ADV_SCAN_IND; 5615c215e939SJaganath Kanakkassery case LE_LEGACY_NONCONN_IND: 5616c215e939SJaganath Kanakkassery return LE_ADV_NONCONN_IND; 5617c215e939SJaganath Kanakkassery case LE_LEGACY_SCAN_RSP_ADV: 5618c215e939SJaganath Kanakkassery case LE_LEGACY_SCAN_RSP_ADV_SCAN: 5619c215e939SJaganath Kanakkassery return LE_ADV_SCAN_RSP; 5620c215e939SJaganath Kanakkassery } 5621c215e939SJaganath Kanakkassery 5622657cc646SMarcel Holtmann goto invalid; 5623c215e939SJaganath Kanakkassery } 5624c215e939SJaganath Kanakkassery 5625b2cc9761SJaganath Kanakkassery if (evt_type & LE_EXT_ADV_CONN_IND) { 5626b2cc9761SJaganath Kanakkassery if (evt_type & LE_EXT_ADV_DIRECT_IND) 5627b2cc9761SJaganath Kanakkassery return LE_ADV_DIRECT_IND; 5628b2cc9761SJaganath Kanakkassery 5629b2cc9761SJaganath Kanakkassery return LE_ADV_IND; 5630b2cc9761SJaganath Kanakkassery } 5631b2cc9761SJaganath Kanakkassery 5632b2cc9761SJaganath Kanakkassery if (evt_type & LE_EXT_ADV_SCAN_RSP) 5633b2cc9761SJaganath Kanakkassery return LE_ADV_SCAN_RSP; 5634b2cc9761SJaganath Kanakkassery 5635b2cc9761SJaganath Kanakkassery if (evt_type & LE_EXT_ADV_SCAN_IND) 5636b2cc9761SJaganath Kanakkassery return LE_ADV_SCAN_IND; 5637b2cc9761SJaganath Kanakkassery 5638b2cc9761SJaganath Kanakkassery if (evt_type == LE_EXT_ADV_NON_CONN_IND || 5639b2cc9761SJaganath Kanakkassery evt_type & LE_EXT_ADV_DIRECT_IND) 5640b2cc9761SJaganath Kanakkassery return LE_ADV_NONCONN_IND; 5641b2cc9761SJaganath Kanakkassery 5642657cc646SMarcel Holtmann invalid: 5643657cc646SMarcel Holtmann bt_dev_err_ratelimited(hdev, "Unknown advertising packet type: 0x%02x", 5644b2cc9761SJaganath Kanakkassery evt_type); 5645b2cc9761SJaganath Kanakkassery 5646b2cc9761SJaganath Kanakkassery return LE_ADV_INVALID; 5647b2cc9761SJaganath Kanakkassery } 5648b2cc9761SJaganath Kanakkassery 5649c215e939SJaganath Kanakkassery static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) 5650c215e939SJaganath Kanakkassery { 5651c215e939SJaganath Kanakkassery u8 num_reports = skb->data[0]; 5652c215e939SJaganath Kanakkassery void *ptr = &skb->data[1]; 5653c215e939SJaganath Kanakkassery 5654c215e939SJaganath Kanakkassery hci_dev_lock(hdev); 5655c215e939SJaganath Kanakkassery 5656c215e939SJaganath Kanakkassery while (num_reports--) { 5657c215e939SJaganath Kanakkassery struct hci_ev_le_ext_adv_report *ev = ptr; 5658c215e939SJaganath Kanakkassery u8 legacy_evt_type; 5659c215e939SJaganath Kanakkassery u16 evt_type; 5660c215e939SJaganath Kanakkassery 5661c215e939SJaganath Kanakkassery evt_type = __le16_to_cpu(ev->evt_type); 5662657cc646SMarcel Holtmann legacy_evt_type = ext_evt_type_to_legacy(hdev, evt_type); 5663c215e939SJaganath Kanakkassery if (legacy_evt_type != LE_ADV_INVALID) { 5664c215e939SJaganath Kanakkassery process_adv_report(hdev, legacy_evt_type, &ev->bdaddr, 5665c215e939SJaganath Kanakkassery ev->bdaddr_type, NULL, 0, ev->rssi, 5666c215e939SJaganath Kanakkassery ev->data, ev->length); 5667c215e939SJaganath Kanakkassery } 5668c215e939SJaganath Kanakkassery 5669cd9151b6SJaganath Kanakkassery ptr += sizeof(*ev) + ev->length; 5670c215e939SJaganath Kanakkassery } 5671c215e939SJaganath Kanakkassery 5672c215e939SJaganath Kanakkassery hci_dev_unlock(hdev); 5673c215e939SJaganath Kanakkassery } 5674c215e939SJaganath Kanakkassery 56750fe29fd1SMarcel Holtmann static void hci_le_remote_feat_complete_evt(struct hci_dev *hdev, 56760fe29fd1SMarcel Holtmann struct sk_buff *skb) 56770fe29fd1SMarcel Holtmann { 56780fe29fd1SMarcel Holtmann struct hci_ev_le_remote_feat_complete *ev = (void *)skb->data; 56790fe29fd1SMarcel Holtmann struct hci_conn *conn; 56800fe29fd1SMarcel Holtmann 56810fe29fd1SMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 56820fe29fd1SMarcel Holtmann 56830fe29fd1SMarcel Holtmann hci_dev_lock(hdev); 56840fe29fd1SMarcel Holtmann 56850fe29fd1SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 56860fe29fd1SMarcel Holtmann if (conn) { 56870fe29fd1SMarcel Holtmann if (!ev->status) 56880fe29fd1SMarcel Holtmann memcpy(conn->features[0], ev->features, 8); 56890fe29fd1SMarcel Holtmann 56900fe29fd1SMarcel Holtmann if (conn->state == BT_CONFIG) { 56910fe29fd1SMarcel Holtmann __u8 status; 56920fe29fd1SMarcel Holtmann 56930fe29fd1SMarcel Holtmann /* If the local controller supports slave-initiated 56940fe29fd1SMarcel Holtmann * features exchange, but the remote controller does 56950fe29fd1SMarcel Holtmann * not, then it is possible that the error code 0x1a 56960fe29fd1SMarcel Holtmann * for unsupported remote feature gets returned. 56970fe29fd1SMarcel Holtmann * 56980fe29fd1SMarcel Holtmann * In this specific case, allow the connection to 56990fe29fd1SMarcel Holtmann * transition into connected state and mark it as 57000fe29fd1SMarcel Holtmann * successful. 57010fe29fd1SMarcel Holtmann */ 57020fe29fd1SMarcel Holtmann if ((hdev->le_features[0] & HCI_LE_SLAVE_FEATURES) && 57030fe29fd1SMarcel Holtmann !conn->out && ev->status == 0x1a) 57040fe29fd1SMarcel Holtmann status = 0x00; 57050fe29fd1SMarcel Holtmann else 57060fe29fd1SMarcel Holtmann status = ev->status; 57070fe29fd1SMarcel Holtmann 57080fe29fd1SMarcel Holtmann conn->state = BT_CONNECTED; 57090fe29fd1SMarcel Holtmann hci_connect_cfm(conn, status); 57100fe29fd1SMarcel Holtmann hci_conn_drop(conn); 57110fe29fd1SMarcel Holtmann } 57120fe29fd1SMarcel Holtmann } 57130fe29fd1SMarcel Holtmann 57140fe29fd1SMarcel Holtmann hci_dev_unlock(hdev); 57150fe29fd1SMarcel Holtmann } 57160fe29fd1SMarcel Holtmann 57176039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 5718a7a595f6SVinicius Costa Gomes { 5719a7a595f6SVinicius Costa Gomes struct hci_ev_le_ltk_req *ev = (void *) skb->data; 5720a7a595f6SVinicius Costa Gomes struct hci_cp_le_ltk_reply cp; 5721bea710feSVinicius Costa Gomes struct hci_cp_le_ltk_neg_reply neg; 5722a7a595f6SVinicius Costa Gomes struct hci_conn *conn; 5723c9839a11SVinicius Costa Gomes struct smp_ltk *ltk; 5724a7a595f6SVinicius Costa Gomes 57259f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle)); 5726a7a595f6SVinicius Costa Gomes 5727a7a595f6SVinicius Costa Gomes hci_dev_lock(hdev); 5728a7a595f6SVinicius Costa Gomes 5729a7a595f6SVinicius Costa Gomes conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 5730bea710feSVinicius Costa Gomes if (conn == NULL) 5731bea710feSVinicius Costa Gomes goto not_found; 5732a7a595f6SVinicius Costa Gomes 5733f3a73d97SJohan Hedberg ltk = hci_find_ltk(hdev, &conn->dst, conn->dst_type, conn->role); 57345378bc56SJohan Hedberg if (!ltk) 5735bea710feSVinicius Costa Gomes goto not_found; 5736bea710feSVinicius Costa Gomes 57375378bc56SJohan Hedberg if (smp_ltk_is_sc(ltk)) { 57385378bc56SJohan Hedberg /* With SC both EDiv and Rand are set to zero */ 57395378bc56SJohan Hedberg if (ev->ediv || ev->rand) 57405378bc56SJohan Hedberg goto not_found; 57415378bc56SJohan Hedberg } else { 57425378bc56SJohan Hedberg /* For non-SC keys check that EDiv and Rand match */ 57435378bc56SJohan Hedberg if (ev->ediv != ltk->ediv || ev->rand != ltk->rand) 57445378bc56SJohan Hedberg goto not_found; 57455378bc56SJohan Hedberg } 57465378bc56SJohan Hedberg 57478b76ce34SJohan Hedberg memcpy(cp.ltk, ltk->val, ltk->enc_size); 57488b76ce34SJohan Hedberg memset(cp.ltk + ltk->enc_size, 0, sizeof(cp.ltk) - ltk->enc_size); 5749a7a595f6SVinicius Costa Gomes cp.handle = cpu_to_le16(conn->handle); 5750c9839a11SVinicius Costa Gomes 5751a6f7833cSJohan Hedberg conn->pending_sec_level = smp_ltk_sec_level(ltk); 5752a7a595f6SVinicius Costa Gomes 575389cbb4daSAndre Guedes conn->enc_key_size = ltk->enc_size; 5754a7a595f6SVinicius Costa Gomes 5755a7a595f6SVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); 5756a7a595f6SVinicius Costa Gomes 57575981a882SClaudio Takahasi /* Ref. Bluetooth Core SPEC pages 1975 and 2004. STK is a 57585981a882SClaudio Takahasi * temporary key used to encrypt a connection following 57595981a882SClaudio Takahasi * pairing. It is used during the Encrypted Session Setup to 57605981a882SClaudio Takahasi * distribute the keys. Later, security can be re-established 57615981a882SClaudio Takahasi * using a distributed LTK. 57625981a882SClaudio Takahasi */ 57632ceba539SJohan Hedberg if (ltk->type == SMP_STK) { 5764fe59a05fSJohan Hedberg set_bit(HCI_CONN_STK_ENCRYPT, &conn->flags); 5765970d0f1bSJohan Hedberg list_del_rcu(<k->list); 5766970d0f1bSJohan Hedberg kfree_rcu(ltk, rcu); 5767fe59a05fSJohan Hedberg } else { 5768fe59a05fSJohan Hedberg clear_bit(HCI_CONN_STK_ENCRYPT, &conn->flags); 5769c9839a11SVinicius Costa Gomes } 5770c9839a11SVinicius Costa Gomes 5771a7a595f6SVinicius Costa Gomes hci_dev_unlock(hdev); 5772bea710feSVinicius Costa Gomes 5773bea710feSVinicius Costa Gomes return; 5774bea710feSVinicius Costa Gomes 5775bea710feSVinicius Costa Gomes not_found: 5776bea710feSVinicius Costa Gomes neg.handle = ev->handle; 5777bea710feSVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg); 5778bea710feSVinicius Costa Gomes hci_dev_unlock(hdev); 5779a7a595f6SVinicius Costa Gomes } 5780a7a595f6SVinicius Costa Gomes 57818e75b46aSAndre Guedes static void send_conn_param_neg_reply(struct hci_dev *hdev, u16 handle, 57828e75b46aSAndre Guedes u8 reason) 57838e75b46aSAndre Guedes { 57848e75b46aSAndre Guedes struct hci_cp_le_conn_param_req_neg_reply cp; 57858e75b46aSAndre Guedes 57868e75b46aSAndre Guedes cp.handle = cpu_to_le16(handle); 57878e75b46aSAndre Guedes cp.reason = reason; 57888e75b46aSAndre Guedes 57898e75b46aSAndre Guedes hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY, sizeof(cp), 57908e75b46aSAndre Guedes &cp); 57918e75b46aSAndre Guedes } 57928e75b46aSAndre Guedes 57938e75b46aSAndre Guedes static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev, 57948e75b46aSAndre Guedes struct sk_buff *skb) 57958e75b46aSAndre Guedes { 57968e75b46aSAndre Guedes struct hci_ev_le_remote_conn_param_req *ev = (void *) skb->data; 57978e75b46aSAndre Guedes struct hci_cp_le_conn_param_req_reply cp; 57988e75b46aSAndre Guedes struct hci_conn *hcon; 57998e75b46aSAndre Guedes u16 handle, min, max, latency, timeout; 58008e75b46aSAndre Guedes 58018e75b46aSAndre Guedes handle = le16_to_cpu(ev->handle); 58028e75b46aSAndre Guedes min = le16_to_cpu(ev->interval_min); 58038e75b46aSAndre Guedes max = le16_to_cpu(ev->interval_max); 58048e75b46aSAndre Guedes latency = le16_to_cpu(ev->latency); 58058e75b46aSAndre Guedes timeout = le16_to_cpu(ev->timeout); 58068e75b46aSAndre Guedes 58078e75b46aSAndre Guedes hcon = hci_conn_hash_lookup_handle(hdev, handle); 58088e75b46aSAndre Guedes if (!hcon || hcon->state != BT_CONNECTED) 58098e75b46aSAndre Guedes return send_conn_param_neg_reply(hdev, handle, 58108e75b46aSAndre Guedes HCI_ERROR_UNKNOWN_CONN_ID); 58118e75b46aSAndre Guedes 58128e75b46aSAndre Guedes if (hci_check_conn_params(min, max, latency, timeout)) 58138e75b46aSAndre Guedes return send_conn_param_neg_reply(hdev, handle, 58148e75b46aSAndre Guedes HCI_ERROR_INVALID_LL_PARAMS); 58158e75b46aSAndre Guedes 581640bef302SJohan Hedberg if (hcon->role == HCI_ROLE_MASTER) { 5817348d50b8SJohan Hedberg struct hci_conn_params *params; 5818f4869e2aSJohan Hedberg u8 store_hint; 5819348d50b8SJohan Hedberg 5820348d50b8SJohan Hedberg hci_dev_lock(hdev); 5821348d50b8SJohan Hedberg 5822348d50b8SJohan Hedberg params = hci_conn_params_lookup(hdev, &hcon->dst, 5823348d50b8SJohan Hedberg hcon->dst_type); 5824348d50b8SJohan Hedberg if (params) { 5825348d50b8SJohan Hedberg params->conn_min_interval = min; 5826348d50b8SJohan Hedberg params->conn_max_interval = max; 5827348d50b8SJohan Hedberg params->conn_latency = latency; 5828348d50b8SJohan Hedberg params->supervision_timeout = timeout; 5829f4869e2aSJohan Hedberg store_hint = 0x01; 5830f4869e2aSJohan Hedberg } else{ 5831f4869e2aSJohan Hedberg store_hint = 0x00; 5832348d50b8SJohan Hedberg } 5833348d50b8SJohan Hedberg 5834348d50b8SJohan Hedberg hci_dev_unlock(hdev); 5835348d50b8SJohan Hedberg 5836f4869e2aSJohan Hedberg mgmt_new_conn_param(hdev, &hcon->dst, hcon->dst_type, 5837f4869e2aSJohan Hedberg store_hint, min, max, latency, timeout); 5838348d50b8SJohan Hedberg } 5839ffb5a827SAndre Guedes 58408e75b46aSAndre Guedes cp.handle = ev->handle; 58418e75b46aSAndre Guedes cp.interval_min = ev->interval_min; 58428e75b46aSAndre Guedes cp.interval_max = ev->interval_max; 58438e75b46aSAndre Guedes cp.latency = ev->latency; 58448e75b46aSAndre Guedes cp.timeout = ev->timeout; 58458e75b46aSAndre Guedes cp.min_ce_len = 0; 58468e75b46aSAndre Guedes cp.max_ce_len = 0; 58478e75b46aSAndre Guedes 58488e75b46aSAndre Guedes hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_REPLY, sizeof(cp), &cp); 58498e75b46aSAndre Guedes } 58508e75b46aSAndre Guedes 58512f010b55SMarcel Holtmann static void hci_le_direct_adv_report_evt(struct hci_dev *hdev, 58522f010b55SMarcel Holtmann struct sk_buff *skb) 58532f010b55SMarcel Holtmann { 58542f010b55SMarcel Holtmann u8 num_reports = skb->data[0]; 58552f010b55SMarcel Holtmann void *ptr = &skb->data[1]; 58562f010b55SMarcel Holtmann 58572f010b55SMarcel Holtmann hci_dev_lock(hdev); 58582f010b55SMarcel Holtmann 58592f010b55SMarcel Holtmann while (num_reports--) { 58602f010b55SMarcel Holtmann struct hci_ev_le_direct_adv_info *ev = ptr; 58612f010b55SMarcel Holtmann 58622f010b55SMarcel Holtmann process_adv_report(hdev, ev->evt_type, &ev->bdaddr, 58632f010b55SMarcel Holtmann ev->bdaddr_type, &ev->direct_addr, 58642f010b55SMarcel Holtmann ev->direct_addr_type, ev->rssi, NULL, 0); 58652f010b55SMarcel Holtmann 58662f010b55SMarcel Holtmann ptr += sizeof(*ev); 58672f010b55SMarcel Holtmann } 58682f010b55SMarcel Holtmann 58692f010b55SMarcel Holtmann hci_dev_unlock(hdev); 58702f010b55SMarcel Holtmann } 58712f010b55SMarcel Holtmann 58721efd927dSLuiz Augusto von Dentz static void hci_le_phy_update_evt(struct hci_dev *hdev, struct sk_buff *skb) 58731efd927dSLuiz Augusto von Dentz { 58741efd927dSLuiz Augusto von Dentz struct hci_ev_le_phy_update_complete *ev = (void *) skb->data; 58751efd927dSLuiz Augusto von Dentz struct hci_conn *conn; 58761efd927dSLuiz Augusto von Dentz 58771efd927dSLuiz Augusto von Dentz BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 58781efd927dSLuiz Augusto von Dentz 58791efd927dSLuiz Augusto von Dentz if (!ev->status) 58801efd927dSLuiz Augusto von Dentz return; 58811efd927dSLuiz Augusto von Dentz 58821efd927dSLuiz Augusto von Dentz hci_dev_lock(hdev); 58831efd927dSLuiz Augusto von Dentz 58841efd927dSLuiz Augusto von Dentz conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 58851efd927dSLuiz Augusto von Dentz if (!conn) 58861efd927dSLuiz Augusto von Dentz goto unlock; 58871efd927dSLuiz Augusto von Dentz 58881efd927dSLuiz Augusto von Dentz conn->le_tx_phy = ev->tx_phy; 58891efd927dSLuiz Augusto von Dentz conn->le_rx_phy = ev->rx_phy; 58901efd927dSLuiz Augusto von Dentz 58911efd927dSLuiz Augusto von Dentz unlock: 58921efd927dSLuiz Augusto von Dentz hci_dev_unlock(hdev); 58931efd927dSLuiz Augusto von Dentz } 58941efd927dSLuiz Augusto von Dentz 58956039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 5896fcd89c09SVille Tervo { 5897fcd89c09SVille Tervo struct hci_ev_le_meta *le_ev = (void *) skb->data; 5898fcd89c09SVille Tervo 5899fcd89c09SVille Tervo skb_pull(skb, sizeof(*le_ev)); 5900fcd89c09SVille Tervo 5901fcd89c09SVille Tervo switch (le_ev->subevent) { 5902fcd89c09SVille Tervo case HCI_EV_LE_CONN_COMPLETE: 5903fcd89c09SVille Tervo hci_le_conn_complete_evt(hdev, skb); 5904fcd89c09SVille Tervo break; 5905fcd89c09SVille Tervo 59061855d92dSMarcel Holtmann case HCI_EV_LE_CONN_UPDATE_COMPLETE: 59071855d92dSMarcel Holtmann hci_le_conn_update_complete_evt(hdev, skb); 59081855d92dSMarcel Holtmann break; 59091855d92dSMarcel Holtmann 59109aa04c91SAndre Guedes case HCI_EV_LE_ADVERTISING_REPORT: 59119aa04c91SAndre Guedes hci_le_adv_report_evt(hdev, skb); 59129aa04c91SAndre Guedes break; 59139aa04c91SAndre Guedes 59140fe29fd1SMarcel Holtmann case HCI_EV_LE_REMOTE_FEAT_COMPLETE: 59150fe29fd1SMarcel Holtmann hci_le_remote_feat_complete_evt(hdev, skb); 59160fe29fd1SMarcel Holtmann break; 59170fe29fd1SMarcel Holtmann 5918a7a595f6SVinicius Costa Gomes case HCI_EV_LE_LTK_REQ: 5919a7a595f6SVinicius Costa Gomes hci_le_ltk_request_evt(hdev, skb); 5920a7a595f6SVinicius Costa Gomes break; 5921a7a595f6SVinicius Costa Gomes 59228e75b46aSAndre Guedes case HCI_EV_LE_REMOTE_CONN_PARAM_REQ: 59238e75b46aSAndre Guedes hci_le_remote_conn_param_req_evt(hdev, skb); 59248e75b46aSAndre Guedes break; 59258e75b46aSAndre Guedes 59262f010b55SMarcel Holtmann case HCI_EV_LE_DIRECT_ADV_REPORT: 59272f010b55SMarcel Holtmann hci_le_direct_adv_report_evt(hdev, skb); 59282f010b55SMarcel Holtmann break; 59292f010b55SMarcel Holtmann 59301efd927dSLuiz Augusto von Dentz case HCI_EV_LE_PHY_UPDATE_COMPLETE: 59311efd927dSLuiz Augusto von Dentz hci_le_phy_update_evt(hdev, skb); 59321efd927dSLuiz Augusto von Dentz break; 59331efd927dSLuiz Augusto von Dentz 5934c215e939SJaganath Kanakkassery case HCI_EV_LE_EXT_ADV_REPORT: 5935c215e939SJaganath Kanakkassery hci_le_ext_adv_report_evt(hdev, skb); 5936c215e939SJaganath Kanakkassery break; 5937c215e939SJaganath Kanakkassery 59384d94f95dSJaganath Kanakkassery case HCI_EV_LE_ENHANCED_CONN_COMPLETE: 59394d94f95dSJaganath Kanakkassery hci_le_enh_conn_complete_evt(hdev, skb); 59404d94f95dSJaganath Kanakkassery break; 59414d94f95dSJaganath Kanakkassery 5942acf0aeaeSJaganath Kanakkassery case HCI_EV_LE_EXT_ADV_SET_TERM: 5943acf0aeaeSJaganath Kanakkassery hci_le_ext_adv_term_evt(hdev, skb); 5944acf0aeaeSJaganath Kanakkassery break; 5945acf0aeaeSJaganath Kanakkassery 5946fcd89c09SVille Tervo default: 5947fcd89c09SVille Tervo break; 5948fcd89c09SVille Tervo } 5949fcd89c09SVille Tervo } 5950fcd89c09SVille Tervo 5951757aa0b5SJohan Hedberg static bool hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode, 5952757aa0b5SJohan Hedberg u8 event, struct sk_buff *skb) 5953757aa0b5SJohan Hedberg { 5954757aa0b5SJohan Hedberg struct hci_ev_cmd_complete *ev; 5955757aa0b5SJohan Hedberg struct hci_event_hdr *hdr; 5956757aa0b5SJohan Hedberg 5957757aa0b5SJohan Hedberg if (!skb) 5958757aa0b5SJohan Hedberg return false; 5959757aa0b5SJohan Hedberg 5960757aa0b5SJohan Hedberg if (skb->len < sizeof(*hdr)) { 59612064ee33SMarcel Holtmann bt_dev_err(hdev, "too short HCI event"); 5962757aa0b5SJohan Hedberg return false; 5963757aa0b5SJohan Hedberg } 5964757aa0b5SJohan Hedberg 5965757aa0b5SJohan Hedberg hdr = (void *) skb->data; 5966757aa0b5SJohan Hedberg skb_pull(skb, HCI_EVENT_HDR_SIZE); 5967757aa0b5SJohan Hedberg 5968757aa0b5SJohan Hedberg if (event) { 5969757aa0b5SJohan Hedberg if (hdr->evt != event) 5970757aa0b5SJohan Hedberg return false; 5971757aa0b5SJohan Hedberg return true; 5972757aa0b5SJohan Hedberg } 5973757aa0b5SJohan Hedberg 59741629db9cSJohan Hedberg /* Check if request ended in Command Status - no way to retreive 59751629db9cSJohan Hedberg * any extra parameters in this case. 59761629db9cSJohan Hedberg */ 59771629db9cSJohan Hedberg if (hdr->evt == HCI_EV_CMD_STATUS) 59781629db9cSJohan Hedberg return false; 59791629db9cSJohan Hedberg 5980757aa0b5SJohan Hedberg if (hdr->evt != HCI_EV_CMD_COMPLETE) { 59812064ee33SMarcel Holtmann bt_dev_err(hdev, "last event is not cmd complete (0x%2.2x)", 59822064ee33SMarcel Holtmann hdr->evt); 5983757aa0b5SJohan Hedberg return false; 5984757aa0b5SJohan Hedberg } 5985757aa0b5SJohan Hedberg 5986757aa0b5SJohan Hedberg if (skb->len < sizeof(*ev)) { 59872064ee33SMarcel Holtmann bt_dev_err(hdev, "too short cmd_complete event"); 5988757aa0b5SJohan Hedberg return false; 5989757aa0b5SJohan Hedberg } 5990757aa0b5SJohan Hedberg 5991757aa0b5SJohan Hedberg ev = (void *) skb->data; 5992757aa0b5SJohan Hedberg skb_pull(skb, sizeof(*ev)); 5993757aa0b5SJohan Hedberg 5994757aa0b5SJohan Hedberg if (opcode != __le16_to_cpu(ev->opcode)) { 5995757aa0b5SJohan Hedberg BT_DBG("opcode doesn't match (0x%2.2x != 0x%2.2x)", opcode, 5996757aa0b5SJohan Hedberg __le16_to_cpu(ev->opcode)); 5997757aa0b5SJohan Hedberg return false; 5998757aa0b5SJohan Hedberg } 5999757aa0b5SJohan Hedberg 6000757aa0b5SJohan Hedberg return true; 6001757aa0b5SJohan Hedberg } 6002757aa0b5SJohan Hedberg 60032f20216cSAbhishek Pandit-Subedi static void hci_store_wake_reason(struct hci_dev *hdev, u8 event, 60042f20216cSAbhishek Pandit-Subedi struct sk_buff *skb) 60052f20216cSAbhishek Pandit-Subedi { 60062f20216cSAbhishek Pandit-Subedi struct hci_ev_le_advertising_info *adv; 60072f20216cSAbhishek Pandit-Subedi struct hci_ev_le_direct_adv_info *direct_adv; 60082f20216cSAbhishek Pandit-Subedi struct hci_ev_le_ext_adv_report *ext_adv; 60092f20216cSAbhishek Pandit-Subedi const struct hci_ev_conn_complete *conn_complete = (void *)skb->data; 60102f20216cSAbhishek Pandit-Subedi const struct hci_ev_conn_request *conn_request = (void *)skb->data; 60112f20216cSAbhishek Pandit-Subedi 60122f20216cSAbhishek Pandit-Subedi hci_dev_lock(hdev); 60132f20216cSAbhishek Pandit-Subedi 60142f20216cSAbhishek Pandit-Subedi /* If we are currently suspended and this is the first BT event seen, 60152f20216cSAbhishek Pandit-Subedi * save the wake reason associated with the event. 60162f20216cSAbhishek Pandit-Subedi */ 60172f20216cSAbhishek Pandit-Subedi if (!hdev->suspended || hdev->wake_reason) 60182f20216cSAbhishek Pandit-Subedi goto unlock; 60192f20216cSAbhishek Pandit-Subedi 60202f20216cSAbhishek Pandit-Subedi /* Default to remote wake. Values for wake_reason are documented in the 60212f20216cSAbhishek Pandit-Subedi * Bluez mgmt api docs. 60222f20216cSAbhishek Pandit-Subedi */ 60232f20216cSAbhishek Pandit-Subedi hdev->wake_reason = MGMT_WAKE_REASON_REMOTE_WAKE; 60242f20216cSAbhishek Pandit-Subedi 60252f20216cSAbhishek Pandit-Subedi /* Once configured for remote wakeup, we should only wake up for 60262f20216cSAbhishek Pandit-Subedi * reconnections. It's useful to see which device is waking us up so 60272f20216cSAbhishek Pandit-Subedi * keep track of the bdaddr of the connection event that woke us up. 60282f20216cSAbhishek Pandit-Subedi */ 60292f20216cSAbhishek Pandit-Subedi if (event == HCI_EV_CONN_REQUEST) { 60302f20216cSAbhishek Pandit-Subedi bacpy(&hdev->wake_addr, &conn_complete->bdaddr); 60312f20216cSAbhishek Pandit-Subedi hdev->wake_addr_type = BDADDR_BREDR; 60322f20216cSAbhishek Pandit-Subedi } else if (event == HCI_EV_CONN_COMPLETE) { 60332f20216cSAbhishek Pandit-Subedi bacpy(&hdev->wake_addr, &conn_request->bdaddr); 60342f20216cSAbhishek Pandit-Subedi hdev->wake_addr_type = BDADDR_BREDR; 60352f20216cSAbhishek Pandit-Subedi } else if (event == HCI_EV_LE_META) { 60362f20216cSAbhishek Pandit-Subedi struct hci_ev_le_meta *le_ev = (void *)skb->data; 60372f20216cSAbhishek Pandit-Subedi u8 subevent = le_ev->subevent; 60382f20216cSAbhishek Pandit-Subedi u8 *ptr = &skb->data[sizeof(*le_ev)]; 60392f20216cSAbhishek Pandit-Subedi u8 num_reports = *ptr; 60402f20216cSAbhishek Pandit-Subedi 60412f20216cSAbhishek Pandit-Subedi if ((subevent == HCI_EV_LE_ADVERTISING_REPORT || 60422f20216cSAbhishek Pandit-Subedi subevent == HCI_EV_LE_DIRECT_ADV_REPORT || 60432f20216cSAbhishek Pandit-Subedi subevent == HCI_EV_LE_EXT_ADV_REPORT) && 60442f20216cSAbhishek Pandit-Subedi num_reports) { 60452f20216cSAbhishek Pandit-Subedi adv = (void *)(ptr + 1); 60462f20216cSAbhishek Pandit-Subedi direct_adv = (void *)(ptr + 1); 60472f20216cSAbhishek Pandit-Subedi ext_adv = (void *)(ptr + 1); 60482f20216cSAbhishek Pandit-Subedi 60492f20216cSAbhishek Pandit-Subedi switch (subevent) { 60502f20216cSAbhishek Pandit-Subedi case HCI_EV_LE_ADVERTISING_REPORT: 60512f20216cSAbhishek Pandit-Subedi bacpy(&hdev->wake_addr, &adv->bdaddr); 60522f20216cSAbhishek Pandit-Subedi hdev->wake_addr_type = adv->bdaddr_type; 60532f20216cSAbhishek Pandit-Subedi break; 60542f20216cSAbhishek Pandit-Subedi case HCI_EV_LE_DIRECT_ADV_REPORT: 60552f20216cSAbhishek Pandit-Subedi bacpy(&hdev->wake_addr, &direct_adv->bdaddr); 60562f20216cSAbhishek Pandit-Subedi hdev->wake_addr_type = direct_adv->bdaddr_type; 60572f20216cSAbhishek Pandit-Subedi break; 60582f20216cSAbhishek Pandit-Subedi case HCI_EV_LE_EXT_ADV_REPORT: 60592f20216cSAbhishek Pandit-Subedi bacpy(&hdev->wake_addr, &ext_adv->bdaddr); 60602f20216cSAbhishek Pandit-Subedi hdev->wake_addr_type = ext_adv->bdaddr_type; 60612f20216cSAbhishek Pandit-Subedi break; 60622f20216cSAbhishek Pandit-Subedi } 60632f20216cSAbhishek Pandit-Subedi } 60642f20216cSAbhishek Pandit-Subedi } else { 60652f20216cSAbhishek Pandit-Subedi hdev->wake_reason = MGMT_WAKE_REASON_UNEXPECTED; 60662f20216cSAbhishek Pandit-Subedi } 60672f20216cSAbhishek Pandit-Subedi 60682f20216cSAbhishek Pandit-Subedi unlock: 60692f20216cSAbhishek Pandit-Subedi hci_dev_unlock(hdev); 60702f20216cSAbhishek Pandit-Subedi } 60712f20216cSAbhishek Pandit-Subedi 60721da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 60731da177e4SLinus Torvalds { 6074a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 6075e6214487SJohan Hedberg hci_req_complete_t req_complete = NULL; 6076e6214487SJohan Hedberg hci_req_complete_skb_t req_complete_skb = NULL; 6077e6214487SJohan Hedberg struct sk_buff *orig_skb = NULL; 6078757aa0b5SJohan Hedberg u8 status = 0, event = hdr->evt, req_evt = 0; 6079e6214487SJohan Hedberg u16 opcode = HCI_OP_NOP; 60801da177e4SLinus Torvalds 608108bb4da9SAlain Michaud if (!event) { 608208bb4da9SAlain Michaud bt_dev_warn(hdev, "Received unexpected HCI Event 00000000"); 608308bb4da9SAlain Michaud goto done; 608408bb4da9SAlain Michaud } 608508bb4da9SAlain Michaud 6086242c0ebdSMarcel Holtmann if (hdev->sent_cmd && bt_cb(hdev->sent_cmd)->hci.req_event == event) { 6087c1f23a2bSJohannes Berg struct hci_command_hdr *cmd_hdr = (void *) hdev->sent_cmd->data; 6088e6214487SJohan Hedberg opcode = __le16_to_cpu(cmd_hdr->opcode); 6089e6214487SJohan Hedberg hci_req_cmd_complete(hdev, opcode, status, &req_complete, 6090e6214487SJohan Hedberg &req_complete_skb); 6091757aa0b5SJohan Hedberg req_evt = event; 609202350a72SJohan Hedberg } 609302350a72SJohan Hedberg 6094e6214487SJohan Hedberg /* If it looks like we might end up having to call 6095e6214487SJohan Hedberg * req_complete_skb, store a pristine copy of the skb since the 6096e6214487SJohan Hedberg * various handlers may modify the original one through 6097e6214487SJohan Hedberg * skb_pull() calls, etc. 6098e6214487SJohan Hedberg */ 6099e6214487SJohan Hedberg if (req_complete_skb || event == HCI_EV_CMD_STATUS || 6100e6214487SJohan Hedberg event == HCI_EV_CMD_COMPLETE) 6101e6214487SJohan Hedberg orig_skb = skb_clone(skb, GFP_KERNEL); 6102e6214487SJohan Hedberg 6103e6214487SJohan Hedberg skb_pull(skb, HCI_EVENT_HDR_SIZE); 6104e6214487SJohan Hedberg 61052f20216cSAbhishek Pandit-Subedi /* Store wake reason if we're suspended */ 61062f20216cSAbhishek Pandit-Subedi hci_store_wake_reason(hdev, event, skb); 61072f20216cSAbhishek Pandit-Subedi 6108a9de9248SMarcel Holtmann switch (event) { 61091da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 61101da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 61111da177e4SLinus Torvalds break; 61121da177e4SLinus Torvalds 61131da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 61141da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 61151da177e4SLinus Torvalds break; 61161da177e4SLinus Torvalds 6117a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 6118a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 611921d9e30eSMarcel Holtmann break; 612021d9e30eSMarcel Holtmann 61211da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 61221da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 61231da177e4SLinus Torvalds break; 61241da177e4SLinus Torvalds 61251da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 61261da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 61271da177e4SLinus Torvalds break; 61281da177e4SLinus Torvalds 61291da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 61301da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 61311da177e4SLinus Torvalds break; 61321da177e4SLinus Torvalds 6133a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 6134a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 6135a9de9248SMarcel Holtmann break; 6136a9de9248SMarcel Holtmann 61371da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 61381da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 61391da177e4SLinus Torvalds break; 61401da177e4SLinus Torvalds 6141a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 6142a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 6143a9de9248SMarcel Holtmann break; 6144a9de9248SMarcel Holtmann 6145a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 6146a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 6147a9de9248SMarcel Holtmann break; 6148a9de9248SMarcel Holtmann 6149a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 6150e6214487SJohan Hedberg hci_cmd_complete_evt(hdev, skb, &opcode, &status, 6151e6214487SJohan Hedberg &req_complete, &req_complete_skb); 6152a9de9248SMarcel Holtmann break; 6153a9de9248SMarcel Holtmann 6154a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 6155e6214487SJohan Hedberg hci_cmd_status_evt(hdev, skb, &opcode, &status, &req_complete, 6156e6214487SJohan Hedberg &req_complete_skb); 6157a9de9248SMarcel Holtmann break; 6158a9de9248SMarcel Holtmann 615924dfa343SMarcel Holtmann case HCI_EV_HARDWARE_ERROR: 616024dfa343SMarcel Holtmann hci_hardware_error_evt(hdev, skb); 616124dfa343SMarcel Holtmann break; 616224dfa343SMarcel Holtmann 6163a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 6164a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 6165a9de9248SMarcel Holtmann break; 6166a9de9248SMarcel Holtmann 6167a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 6168a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 6169a9de9248SMarcel Holtmann break; 6170a9de9248SMarcel Holtmann 6171a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 6172a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 61731da177e4SLinus Torvalds break; 61741da177e4SLinus Torvalds 61751da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 61761da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 61771da177e4SLinus Torvalds break; 61781da177e4SLinus Torvalds 61791da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 61801da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 61811da177e4SLinus Torvalds break; 61821da177e4SLinus Torvalds 61831da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 61841da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 61851da177e4SLinus Torvalds break; 61861da177e4SLinus Torvalds 61871da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 61881da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 61891da177e4SLinus Torvalds break; 61901da177e4SLinus Torvalds 6191a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 6192a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 6193a8746417SMarcel Holtmann break; 6194a8746417SMarcel Holtmann 619585a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 619685a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 619785a1e930SMarcel Holtmann break; 619885a1e930SMarcel Holtmann 6199a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 6200a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 6201a9de9248SMarcel Holtmann break; 6202a9de9248SMarcel Holtmann 6203a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 6204a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 6205a9de9248SMarcel Holtmann break; 6206a9de9248SMarcel Holtmann 6207a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 6208a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 6209a9de9248SMarcel Holtmann break; 6210a9de9248SMarcel Holtmann 6211a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 6212a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 62131da177e4SLinus Torvalds break; 62141da177e4SLinus Torvalds 62151c2e0041SJohan Hedberg case HCI_EV_KEY_REFRESH_COMPLETE: 62161c2e0041SJohan Hedberg hci_key_refresh_complete_evt(hdev, skb); 62171c2e0041SJohan Hedberg break; 62181c2e0041SJohan Hedberg 62190493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 62200493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 62210493684eSMarcel Holtmann break; 62220493684eSMarcel Holtmann 622303b555e1SJohan Hedberg case HCI_EV_IO_CAPA_REPLY: 622403b555e1SJohan Hedberg hci_io_capa_reply_evt(hdev, skb); 622503b555e1SJohan Hedberg break; 622603b555e1SJohan Hedberg 6227a5c29683SJohan Hedberg case HCI_EV_USER_CONFIRM_REQUEST: 6228a5c29683SJohan Hedberg hci_user_confirm_request_evt(hdev, skb); 6229a5c29683SJohan Hedberg break; 6230a5c29683SJohan Hedberg 62311143d458SBrian Gix case HCI_EV_USER_PASSKEY_REQUEST: 62321143d458SBrian Gix hci_user_passkey_request_evt(hdev, skb); 62331143d458SBrian Gix break; 62341143d458SBrian Gix 623592a25256SJohan Hedberg case HCI_EV_USER_PASSKEY_NOTIFY: 623692a25256SJohan Hedberg hci_user_passkey_notify_evt(hdev, skb); 623792a25256SJohan Hedberg break; 623892a25256SJohan Hedberg 623992a25256SJohan Hedberg case HCI_EV_KEYPRESS_NOTIFY: 624092a25256SJohan Hedberg hci_keypress_notify_evt(hdev, skb); 624192a25256SJohan Hedberg break; 624292a25256SJohan Hedberg 62430493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 62440493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 62450493684eSMarcel Holtmann break; 62460493684eSMarcel Holtmann 624741a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 624841a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 624941a96212SMarcel Holtmann break; 625041a96212SMarcel Holtmann 6251fcd89c09SVille Tervo case HCI_EV_LE_META: 6252fcd89c09SVille Tervo hci_le_meta_evt(hdev, skb); 6253fcd89c09SVille Tervo break; 6254fcd89c09SVille Tervo 62552763eda6SSzymon Janc case HCI_EV_REMOTE_OOB_DATA_REQUEST: 62562763eda6SSzymon Janc hci_remote_oob_data_request_evt(hdev, skb); 62572763eda6SSzymon Janc break; 62582763eda6SSzymon Janc 6259a77a6a14SArron Wang #if IS_ENABLED(CONFIG_BT_HS) 6260a77a6a14SArron Wang case HCI_EV_CHANNEL_SELECTED: 6261a77a6a14SArron Wang hci_chan_selected_evt(hdev, skb); 6262a77a6a14SArron Wang break; 6263a77a6a14SArron Wang 6264d5e91192SAndrei Emeltchenko case HCI_EV_PHY_LINK_COMPLETE: 6265d5e91192SAndrei Emeltchenko hci_phy_link_complete_evt(hdev, skb); 6266d5e91192SAndrei Emeltchenko break; 6267d5e91192SAndrei Emeltchenko 626827695fb4SAndrei Emeltchenko case HCI_EV_LOGICAL_LINK_COMPLETE: 626927695fb4SAndrei Emeltchenko hci_loglink_complete_evt(hdev, skb); 627027695fb4SAndrei Emeltchenko break; 627127695fb4SAndrei Emeltchenko 6272606e2a10SAndrei Emeltchenko case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE: 6273606e2a10SAndrei Emeltchenko hci_disconn_loglink_complete_evt(hdev, skb); 6274606e2a10SAndrei Emeltchenko break; 6275606e2a10SAndrei Emeltchenko 62769eef6b3aSAndrei Emeltchenko case HCI_EV_DISCONN_PHY_LINK_COMPLETE: 62779eef6b3aSAndrei Emeltchenko hci_disconn_phylink_complete_evt(hdev, skb); 62789eef6b3aSAndrei Emeltchenko break; 6279a77a6a14SArron Wang #endif 62809eef6b3aSAndrei Emeltchenko 628125e89e99SAndrei Emeltchenko case HCI_EV_NUM_COMP_BLOCKS: 628225e89e99SAndrei Emeltchenko hci_num_comp_blocks_evt(hdev, skb); 628325e89e99SAndrei Emeltchenko break; 628425e89e99SAndrei Emeltchenko 6285145373cbSMiao-chen Chou case HCI_EV_VENDOR: 6286145373cbSMiao-chen Chou msft_vendor_evt(hdev, skb); 6287145373cbSMiao-chen Chou break; 6288145373cbSMiao-chen Chou 62891da177e4SLinus Torvalds default: 62909f1db00cSAndrei Emeltchenko BT_DBG("%s event 0x%2.2x", hdev->name, event); 62911da177e4SLinus Torvalds break; 62921da177e4SLinus Torvalds } 62931da177e4SLinus Torvalds 6294757aa0b5SJohan Hedberg if (req_complete) { 6295e6214487SJohan Hedberg req_complete(hdev, status, opcode); 6296757aa0b5SJohan Hedberg } else if (req_complete_skb) { 6297757aa0b5SJohan Hedberg if (!hci_get_cmd_complete(hdev, opcode, req_evt, orig_skb)) { 6298757aa0b5SJohan Hedberg kfree_skb(orig_skb); 6299757aa0b5SJohan Hedberg orig_skb = NULL; 6300757aa0b5SJohan Hedberg } 6301e6214487SJohan Hedberg req_complete_skb(hdev, status, opcode, orig_skb); 6302757aa0b5SJohan Hedberg } 6303e6214487SJohan Hedberg 630408bb4da9SAlain Michaud done: 6305e6214487SJohan Hedberg kfree_skb(orig_skb); 63061da177e4SLinus Torvalds kfree_skb(skb); 63071da177e4SLinus Torvalds hdev->stat.evt_rx++; 63081da177e4SLinus Torvalds } 6309