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 337024728eSMarcel Holtmann #include "a2mp.h" 347ef9fbf0SMarcel Holtmann #include "amp.h" 352ceba539SJohan Hedberg #include "smp.h" 361da177e4SLinus Torvalds 371da177e4SLinus Torvalds /* Handle HCI Event packets */ 381da177e4SLinus Torvalds 39a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb) 401da177e4SLinus Torvalds { 41a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 421da177e4SLinus Torvalds 439f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 441da177e4SLinus Torvalds 4582f4785cSAndre Guedes if (status) 46a9de9248SMarcel Holtmann return; 471da177e4SLinus Torvalds 4889352e7dSAndre Guedes clear_bit(HCI_INQUIRY, &hdev->flags); 494e857c58SPeter Zijlstra smp_mb__after_atomic(); /* wake_up_bit advises about this barrier */ 503e13fa1eSAndre Guedes wake_up_bit(&hdev->flags, HCI_INQUIRY); 5189352e7dSAndre Guedes 5250143a43SJohan Hedberg hci_dev_lock(hdev); 5350143a43SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 5450143a43SJohan Hedberg hci_dev_unlock(hdev); 5550143a43SJohan Hedberg 56a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 571da177e4SLinus Torvalds } 586bd57416SMarcel Holtmann 594d93483bSAndre Guedes static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 604d93483bSAndre Guedes { 614d93483bSAndre Guedes __u8 status = *((__u8 *) skb->data); 624d93483bSAndre Guedes 639f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 64ae854a70SAndre Guedes 65ae854a70SAndre Guedes if (status) 66ae854a70SAndre Guedes return; 67ae854a70SAndre Guedes 68ae854a70SAndre Guedes set_bit(HCI_PERIODIC_INQ, &hdev->dev_flags); 694d93483bSAndre Guedes } 704d93483bSAndre Guedes 71a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 721da177e4SLinus Torvalds { 73a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 74a9de9248SMarcel Holtmann 759f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 76a9de9248SMarcel Holtmann 77a9de9248SMarcel Holtmann if (status) 78a9de9248SMarcel Holtmann return; 79a9de9248SMarcel Holtmann 80ae854a70SAndre Guedes clear_bit(HCI_PERIODIC_INQ, &hdev->dev_flags); 81ae854a70SAndre Guedes 82a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 83a9de9248SMarcel Holtmann } 84a9de9248SMarcel Holtmann 85807deac2SGustavo Padovan static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, 86807deac2SGustavo Padovan struct sk_buff *skb) 87a9de9248SMarcel Holtmann { 88a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 89a9de9248SMarcel Holtmann } 90a9de9248SMarcel Holtmann 91a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb) 92a9de9248SMarcel Holtmann { 93a9de9248SMarcel Holtmann struct hci_rp_role_discovery *rp = (void *) skb->data; 941da177e4SLinus Torvalds struct hci_conn *conn; 951da177e4SLinus Torvalds 969f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 971da177e4SLinus Torvalds 98a9de9248SMarcel Holtmann if (rp->status) 99a9de9248SMarcel Holtmann return; 1001da177e4SLinus Torvalds 1011da177e4SLinus Torvalds hci_dev_lock(hdev); 1021da177e4SLinus Torvalds 103a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 10440bef302SJohan Hedberg if (conn) 10540bef302SJohan Hedberg conn->role = rp->role; 1061da177e4SLinus Torvalds 1071da177e4SLinus Torvalds hci_dev_unlock(hdev); 108a9de9248SMarcel Holtmann } 1091da177e4SLinus Torvalds 110e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 111e4e8e37cSMarcel Holtmann { 112e4e8e37cSMarcel Holtmann struct hci_rp_read_link_policy *rp = (void *) skb->data; 113e4e8e37cSMarcel Holtmann struct hci_conn *conn; 114e4e8e37cSMarcel Holtmann 1159f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 116e4e8e37cSMarcel Holtmann 117e4e8e37cSMarcel Holtmann if (rp->status) 118e4e8e37cSMarcel Holtmann return; 119e4e8e37cSMarcel Holtmann 120e4e8e37cSMarcel Holtmann hci_dev_lock(hdev); 121e4e8e37cSMarcel Holtmann 122e4e8e37cSMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 123e4e8e37cSMarcel Holtmann if (conn) 124e4e8e37cSMarcel Holtmann conn->link_policy = __le16_to_cpu(rp->policy); 125e4e8e37cSMarcel Holtmann 126e4e8e37cSMarcel Holtmann hci_dev_unlock(hdev); 127e4e8e37cSMarcel Holtmann } 128e4e8e37cSMarcel Holtmann 129a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 130a9de9248SMarcel Holtmann { 131a9de9248SMarcel Holtmann struct hci_rp_write_link_policy *rp = (void *) skb->data; 132a9de9248SMarcel Holtmann struct hci_conn *conn; 133a9de9248SMarcel Holtmann void *sent; 134a9de9248SMarcel Holtmann 1359f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 136a9de9248SMarcel Holtmann 137a9de9248SMarcel Holtmann if (rp->status) 138a9de9248SMarcel Holtmann return; 139a9de9248SMarcel Holtmann 140a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY); 14104837f64SMarcel Holtmann if (!sent) 142a9de9248SMarcel Holtmann return; 14304837f64SMarcel Holtmann 14404837f64SMarcel Holtmann hci_dev_lock(hdev); 14504837f64SMarcel Holtmann 146a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 147e4e8e37cSMarcel Holtmann if (conn) 14883985319SHarvey Harrison conn->link_policy = get_unaligned_le16(sent + 2); 14904837f64SMarcel Holtmann 15004837f64SMarcel Holtmann hci_dev_unlock(hdev); 1511da177e4SLinus Torvalds } 1521da177e4SLinus Torvalds 153807deac2SGustavo Padovan static void hci_cc_read_def_link_policy(struct hci_dev *hdev, 154807deac2SGustavo Padovan struct sk_buff *skb) 155e4e8e37cSMarcel Holtmann { 156e4e8e37cSMarcel Holtmann struct hci_rp_read_def_link_policy *rp = (void *) skb->data; 157e4e8e37cSMarcel Holtmann 1589f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 159e4e8e37cSMarcel Holtmann 160e4e8e37cSMarcel Holtmann if (rp->status) 161e4e8e37cSMarcel Holtmann return; 162e4e8e37cSMarcel Holtmann 163e4e8e37cSMarcel Holtmann hdev->link_policy = __le16_to_cpu(rp->policy); 164e4e8e37cSMarcel Holtmann } 165e4e8e37cSMarcel Holtmann 166807deac2SGustavo Padovan static void hci_cc_write_def_link_policy(struct hci_dev *hdev, 167807deac2SGustavo Padovan struct sk_buff *skb) 168e4e8e37cSMarcel Holtmann { 169e4e8e37cSMarcel Holtmann __u8 status = *((__u8 *) skb->data); 170e4e8e37cSMarcel Holtmann void *sent; 171e4e8e37cSMarcel Holtmann 1729f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 173e4e8e37cSMarcel Holtmann 17445296acdSMarcel Holtmann if (status) 17545296acdSMarcel Holtmann return; 17645296acdSMarcel Holtmann 177e4e8e37cSMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY); 178e4e8e37cSMarcel Holtmann if (!sent) 179e4e8e37cSMarcel Holtmann return; 180e4e8e37cSMarcel Holtmann 181e4e8e37cSMarcel Holtmann hdev->link_policy = get_unaligned_le16(sent); 182e4e8e37cSMarcel Holtmann } 183e4e8e37cSMarcel Holtmann 184a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) 1851da177e4SLinus Torvalds { 186a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 187a9de9248SMarcel Holtmann 1889f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 189a9de9248SMarcel Holtmann 19010572132SGustavo F. Padovan clear_bit(HCI_RESET, &hdev->flags); 19110572132SGustavo F. Padovan 192a297e97cSJohan Hedberg /* Reset all non-persistent flags */ 1932cc6fb00SJohan Hedberg hdev->dev_flags &= ~HCI_PERSISTENT_MASK; 19469775ff6SAndre Guedes 19569775ff6SAndre Guedes hdev->discovery.state = DISCOVERY_STOPPED; 196bbaf444aSJohan Hedberg hdev->inq_tx_power = HCI_TX_POWER_INVALID; 197bbaf444aSJohan Hedberg hdev->adv_tx_power = HCI_TX_POWER_INVALID; 1983f0f524bSJohan Hedberg 1993f0f524bSJohan Hedberg memset(hdev->adv_data, 0, sizeof(hdev->adv_data)); 2003f0f524bSJohan Hedberg hdev->adv_data_len = 0; 201f8e808bdSMarcel Holtmann 202f8e808bdSMarcel Holtmann memset(hdev->scan_rsp_data, 0, sizeof(hdev->scan_rsp_data)); 203f8e808bdSMarcel Holtmann hdev->scan_rsp_data_len = 0; 20406f5b778SMarcel Holtmann 205533553f8SMarcel Holtmann hdev->le_scan_type = LE_SCAN_PASSIVE; 206533553f8SMarcel Holtmann 20706f5b778SMarcel Holtmann hdev->ssp_debug_mode = 0; 208a9de9248SMarcel Holtmann } 209a9de9248SMarcel Holtmann 210a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) 211a9de9248SMarcel Holtmann { 212a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 2131da177e4SLinus Torvalds void *sent; 2141da177e4SLinus Torvalds 2159f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 2161da177e4SLinus Torvalds 217a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); 2181da177e4SLinus Torvalds if (!sent) 219a9de9248SMarcel Holtmann return; 2201da177e4SLinus Torvalds 22156e5cb86SJohan Hedberg hci_dev_lock(hdev); 22256e5cb86SJohan Hedberg 223f51d5b24SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 224f51d5b24SJohan Hedberg mgmt_set_local_name_complete(hdev, sent, status); 22528cc7bdeSJohan Hedberg else if (!status) 22628cc7bdeSJohan Hedberg memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); 227f51d5b24SJohan Hedberg 22856e5cb86SJohan Hedberg hci_dev_unlock(hdev); 229a9de9248SMarcel Holtmann } 230a9de9248SMarcel Holtmann 231a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) 232a9de9248SMarcel Holtmann { 233a9de9248SMarcel Holtmann struct hci_rp_read_local_name *rp = (void *) skb->data; 234a9de9248SMarcel Holtmann 2359f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 236a9de9248SMarcel Holtmann 237a9de9248SMarcel Holtmann if (rp->status) 238a9de9248SMarcel Holtmann return; 239a9de9248SMarcel Holtmann 240db99b5fcSJohan Hedberg if (test_bit(HCI_SETUP, &hdev->dev_flags)) 2411f6c6378SJohan Hedberg memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); 242a9de9248SMarcel Holtmann } 243a9de9248SMarcel Holtmann 244a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) 245a9de9248SMarcel Holtmann { 246a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 247a9de9248SMarcel Holtmann void *sent; 248a9de9248SMarcel Holtmann 2499f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 250a9de9248SMarcel Holtmann 251a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); 252a9de9248SMarcel Holtmann if (!sent) 253a9de9248SMarcel Holtmann return; 2541da177e4SLinus Torvalds 2551da177e4SLinus Torvalds if (!status) { 256a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 257a9de9248SMarcel Holtmann 2581da177e4SLinus Torvalds if (param == AUTH_ENABLED) 2591da177e4SLinus Torvalds set_bit(HCI_AUTH, &hdev->flags); 2601da177e4SLinus Torvalds else 2611da177e4SLinus Torvalds clear_bit(HCI_AUTH, &hdev->flags); 2621da177e4SLinus Torvalds } 263a9de9248SMarcel Holtmann 26433ef95edSJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 26533ef95edSJohan Hedberg mgmt_auth_enable_complete(hdev, status); 266a9de9248SMarcel Holtmann } 2671da177e4SLinus Torvalds 268a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) 269a9de9248SMarcel Holtmann { 270a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 27145296acdSMarcel Holtmann __u8 param; 272a9de9248SMarcel Holtmann void *sent; 273a9de9248SMarcel Holtmann 2749f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 275a9de9248SMarcel Holtmann 27645296acdSMarcel Holtmann if (status) 27745296acdSMarcel Holtmann return; 27845296acdSMarcel Holtmann 279a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); 2801da177e4SLinus Torvalds if (!sent) 281a9de9248SMarcel Holtmann return; 2821da177e4SLinus Torvalds 28345296acdSMarcel Holtmann param = *((__u8 *) sent); 284a9de9248SMarcel Holtmann 2851da177e4SLinus Torvalds if (param) 2861da177e4SLinus Torvalds set_bit(HCI_ENCRYPT, &hdev->flags); 2871da177e4SLinus Torvalds else 2881da177e4SLinus Torvalds clear_bit(HCI_ENCRYPT, &hdev->flags); 2891da177e4SLinus Torvalds } 2901da177e4SLinus Torvalds 291a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) 292a9de9248SMarcel Holtmann { 29345296acdSMarcel Holtmann __u8 status = *((__u8 *) skb->data); 29445296acdSMarcel Holtmann __u8 param; 295a9de9248SMarcel Holtmann void *sent; 2961da177e4SLinus Torvalds 2979f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 298a9de9248SMarcel Holtmann 299a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); 3001da177e4SLinus Torvalds if (!sent) 301a9de9248SMarcel Holtmann return; 3021da177e4SLinus Torvalds 30336f7fc7eSJohan Hedberg param = *((__u8 *) sent); 304a9de9248SMarcel Holtmann 30556e5cb86SJohan Hedberg hci_dev_lock(hdev); 30656e5cb86SJohan Hedberg 307fa1bd918SMikel Astiz if (status) { 3082d7cee58SJohan Hedberg hdev->discov_timeout = 0; 3092d7cee58SJohan Hedberg goto done; 3102d7cee58SJohan Hedberg } 3112d7cee58SJohan Hedberg 312bc6d2d04SJohan Hedberg if (param & SCAN_INQUIRY) 3131da177e4SLinus Torvalds set_bit(HCI_ISCAN, &hdev->flags); 314bc6d2d04SJohan Hedberg else 315bc6d2d04SJohan Hedberg clear_bit(HCI_ISCAN, &hdev->flags); 3161da177e4SLinus Torvalds 317031547d8SJohan Hedberg if (param & SCAN_PAGE) 3181da177e4SLinus Torvalds set_bit(HCI_PSCAN, &hdev->flags); 319bc6d2d04SJohan Hedberg else 320204e3990SJohan Hedberg clear_bit(HCI_PSCAN, &hdev->flags); 321a9de9248SMarcel Holtmann 32236f7fc7eSJohan Hedberg done: 32356e5cb86SJohan Hedberg hci_dev_unlock(hdev); 3241da177e4SLinus Torvalds } 3251da177e4SLinus Torvalds 326a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 327a9de9248SMarcel Holtmann { 328a9de9248SMarcel Holtmann struct hci_rp_read_class_of_dev *rp = (void *) skb->data; 329a9de9248SMarcel Holtmann 3309f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 331a9de9248SMarcel Holtmann 332a9de9248SMarcel Holtmann if (rp->status) 333a9de9248SMarcel Holtmann return; 334a9de9248SMarcel Holtmann 335a9de9248SMarcel Holtmann memcpy(hdev->dev_class, rp->dev_class, 3); 336a9de9248SMarcel Holtmann 337a9de9248SMarcel Holtmann BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, 338a9de9248SMarcel Holtmann hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); 339a9de9248SMarcel Holtmann } 340a9de9248SMarcel Holtmann 341a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 342a9de9248SMarcel Holtmann { 343a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 344a9de9248SMarcel Holtmann void *sent; 345a9de9248SMarcel Holtmann 3469f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 347a9de9248SMarcel Holtmann 348a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); 349a9de9248SMarcel Holtmann if (!sent) 350a9de9248SMarcel Holtmann return; 351a9de9248SMarcel Holtmann 3527f9a903cSMarcel Holtmann hci_dev_lock(hdev); 3537f9a903cSMarcel Holtmann 3547f9a903cSMarcel Holtmann if (status == 0) 355a9de9248SMarcel Holtmann memcpy(hdev->dev_class, sent, 3); 3567f9a903cSMarcel Holtmann 3577f9a903cSMarcel Holtmann if (test_bit(HCI_MGMT, &hdev->dev_flags)) 3587f9a903cSMarcel Holtmann mgmt_set_class_of_dev_complete(hdev, sent, status); 3597f9a903cSMarcel Holtmann 3607f9a903cSMarcel Holtmann hci_dev_unlock(hdev); 361a9de9248SMarcel Holtmann } 362a9de9248SMarcel Holtmann 363a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 364a9de9248SMarcel Holtmann { 365a9de9248SMarcel Holtmann struct hci_rp_read_voice_setting *rp = (void *) skb->data; 366a9de9248SMarcel Holtmann __u16 setting; 367a9de9248SMarcel Holtmann 3689f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 369a9de9248SMarcel Holtmann 370a9de9248SMarcel Holtmann if (rp->status) 371a9de9248SMarcel Holtmann return; 372a9de9248SMarcel Holtmann 373a9de9248SMarcel Holtmann setting = __le16_to_cpu(rp->voice_setting); 374a9de9248SMarcel Holtmann 375a9de9248SMarcel Holtmann if (hdev->voice_setting == setting) 376a9de9248SMarcel Holtmann return; 377a9de9248SMarcel Holtmann 378a9de9248SMarcel Holtmann hdev->voice_setting = setting; 379a9de9248SMarcel Holtmann 3809f1db00cSAndrei Emeltchenko BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting); 381a9de9248SMarcel Holtmann 3823c54711cSGustavo F. Padovan if (hdev->notify) 383a9de9248SMarcel Holtmann hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 384a9de9248SMarcel Holtmann } 385a9de9248SMarcel Holtmann 3868fc9ced3SGustavo Padovan static void hci_cc_write_voice_setting(struct hci_dev *hdev, 3878fc9ced3SGustavo Padovan struct sk_buff *skb) 388a9de9248SMarcel Holtmann { 389a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 390f383f275SMarcel Holtmann __u16 setting; 391a9de9248SMarcel Holtmann void *sent; 392a9de9248SMarcel Holtmann 3939f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 394a9de9248SMarcel Holtmann 395f383f275SMarcel Holtmann if (status) 396f383f275SMarcel Holtmann return; 397f383f275SMarcel Holtmann 398a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); 399a9de9248SMarcel Holtmann if (!sent) 400a9de9248SMarcel Holtmann return; 401a9de9248SMarcel Holtmann 402f383f275SMarcel Holtmann setting = get_unaligned_le16(sent); 4031da177e4SLinus Torvalds 404f383f275SMarcel Holtmann if (hdev->voice_setting == setting) 405f383f275SMarcel Holtmann return; 406f383f275SMarcel Holtmann 4071da177e4SLinus Torvalds hdev->voice_setting = setting; 4081da177e4SLinus Torvalds 4099f1db00cSAndrei Emeltchenko BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting); 4101da177e4SLinus Torvalds 4113c54711cSGustavo F. Padovan if (hdev->notify) 4121da177e4SLinus Torvalds hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 4131da177e4SLinus Torvalds } 4141da177e4SLinus Torvalds 415b4cb9fb2SMarcel Holtmann static void hci_cc_read_num_supported_iac(struct hci_dev *hdev, 416b4cb9fb2SMarcel Holtmann struct sk_buff *skb) 417b4cb9fb2SMarcel Holtmann { 418b4cb9fb2SMarcel Holtmann struct hci_rp_read_num_supported_iac *rp = (void *) skb->data; 419b4cb9fb2SMarcel Holtmann 420b4cb9fb2SMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 421b4cb9fb2SMarcel Holtmann 422b4cb9fb2SMarcel Holtmann if (rp->status) 423b4cb9fb2SMarcel Holtmann return; 424b4cb9fb2SMarcel Holtmann 425b4cb9fb2SMarcel Holtmann hdev->num_iac = rp->num_iac; 426b4cb9fb2SMarcel Holtmann 427b4cb9fb2SMarcel Holtmann BT_DBG("%s num iac %d", hdev->name, hdev->num_iac); 428b4cb9fb2SMarcel Holtmann } 429b4cb9fb2SMarcel Holtmann 430333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 431333140b5SMarcel Holtmann { 432333140b5SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 4335ed8eb2fSJohan Hedberg struct hci_cp_write_ssp_mode *sent; 434333140b5SMarcel Holtmann 4359f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 436333140b5SMarcel Holtmann 437333140b5SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); 438333140b5SMarcel Holtmann if (!sent) 439333140b5SMarcel Holtmann return; 440333140b5SMarcel Holtmann 4415ed8eb2fSJohan Hedberg if (!status) { 4425ed8eb2fSJohan Hedberg if (sent->mode) 443cad718edSJohan Hedberg hdev->features[1][0] |= LMP_HOST_SSP; 4445ed8eb2fSJohan Hedberg else 445cad718edSJohan Hedberg hdev->features[1][0] &= ~LMP_HOST_SSP; 4465ed8eb2fSJohan Hedberg } 4475ed8eb2fSJohan Hedberg 448c0ecddc2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 4495ed8eb2fSJohan Hedberg mgmt_ssp_enable_complete(hdev, sent->mode, status); 450c0ecddc2SJohan Hedberg else if (!status) { 4515ed8eb2fSJohan Hedberg if (sent->mode) 45284bde9d6SJohan Hedberg set_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 45384bde9d6SJohan Hedberg else 45484bde9d6SJohan Hedberg clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 455c0ecddc2SJohan Hedberg } 456333140b5SMarcel Holtmann } 457333140b5SMarcel Holtmann 458eac83dc6SMarcel Holtmann static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb) 459eac83dc6SMarcel Holtmann { 460eac83dc6SMarcel Holtmann u8 status = *((u8 *) skb->data); 461eac83dc6SMarcel Holtmann struct hci_cp_write_sc_support *sent; 462eac83dc6SMarcel Holtmann 463eac83dc6SMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, status); 464eac83dc6SMarcel Holtmann 465eac83dc6SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SC_SUPPORT); 466eac83dc6SMarcel Holtmann if (!sent) 467eac83dc6SMarcel Holtmann return; 468eac83dc6SMarcel Holtmann 469eac83dc6SMarcel Holtmann if (!status) { 470eac83dc6SMarcel Holtmann if (sent->support) 471eac83dc6SMarcel Holtmann hdev->features[1][0] |= LMP_HOST_SC; 472eac83dc6SMarcel Holtmann else 473eac83dc6SMarcel Holtmann hdev->features[1][0] &= ~LMP_HOST_SC; 474eac83dc6SMarcel Holtmann } 475eac83dc6SMarcel Holtmann 476eac83dc6SMarcel Holtmann if (test_bit(HCI_MGMT, &hdev->dev_flags)) 477eac83dc6SMarcel Holtmann mgmt_sc_enable_complete(hdev, sent->support, status); 478eac83dc6SMarcel Holtmann else if (!status) { 479eac83dc6SMarcel Holtmann if (sent->support) 480eac83dc6SMarcel Holtmann set_bit(HCI_SC_ENABLED, &hdev->dev_flags); 481eac83dc6SMarcel Holtmann else 482eac83dc6SMarcel Holtmann clear_bit(HCI_SC_ENABLED, &hdev->dev_flags); 483eac83dc6SMarcel Holtmann } 484eac83dc6SMarcel Holtmann } 485eac83dc6SMarcel Holtmann 486a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) 487a9de9248SMarcel Holtmann { 488a9de9248SMarcel Holtmann struct hci_rp_read_local_version *rp = (void *) skb->data; 4891143e5a6SMarcel Holtmann 4909f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 4911143e5a6SMarcel Holtmann 492a9de9248SMarcel Holtmann if (rp->status) 49342c6b129SJohan Hedberg return; 4941143e5a6SMarcel Holtmann 4950d5551f5SMarcel Holtmann if (test_bit(HCI_SETUP, &hdev->dev_flags)) { 496a9de9248SMarcel Holtmann hdev->hci_ver = rp->hci_ver; 497e4e8e37cSMarcel Holtmann hdev->hci_rev = __le16_to_cpu(rp->hci_rev); 498d5859e22SJohan Hedberg hdev->lmp_ver = rp->lmp_ver; 499e4e8e37cSMarcel Holtmann hdev->manufacturer = __le16_to_cpu(rp->manufacturer); 500d5859e22SJohan Hedberg hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); 5010d5551f5SMarcel Holtmann } 502d5859e22SJohan Hedberg } 503d5859e22SJohan Hedberg 5048fc9ced3SGustavo Padovan static void hci_cc_read_local_commands(struct hci_dev *hdev, 5058fc9ced3SGustavo Padovan struct sk_buff *skb) 506a9de9248SMarcel Holtmann { 507a9de9248SMarcel Holtmann struct hci_rp_read_local_commands *rp = (void *) skb->data; 508a9de9248SMarcel Holtmann 5099f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 510a9de9248SMarcel Holtmann 5116a070e6eSMarcel Holtmann if (rp->status) 5126a070e6eSMarcel Holtmann return; 5136a070e6eSMarcel Holtmann 5146a070e6eSMarcel Holtmann if (test_bit(HCI_SETUP, &hdev->dev_flags)) 515a9de9248SMarcel Holtmann memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); 516a9de9248SMarcel Holtmann } 517a9de9248SMarcel Holtmann 5188fc9ced3SGustavo Padovan static void hci_cc_read_local_features(struct hci_dev *hdev, 5198fc9ced3SGustavo Padovan struct sk_buff *skb) 520a9de9248SMarcel Holtmann { 521a9de9248SMarcel Holtmann struct hci_rp_read_local_features *rp = (void *) skb->data; 522a9de9248SMarcel Holtmann 5239f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 524a9de9248SMarcel Holtmann 525a9de9248SMarcel Holtmann if (rp->status) 526a9de9248SMarcel Holtmann return; 527a9de9248SMarcel Holtmann 528a9de9248SMarcel Holtmann memcpy(hdev->features, rp->features, 8); 5291da177e4SLinus Torvalds 5301da177e4SLinus Torvalds /* Adjust default settings according to features 5311da177e4SLinus Torvalds * supported by device. */ 532a9de9248SMarcel Holtmann 533cad718edSJohan Hedberg if (hdev->features[0][0] & LMP_3SLOT) 5341da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM3 | HCI_DH3); 5351da177e4SLinus Torvalds 536cad718edSJohan Hedberg if (hdev->features[0][0] & LMP_5SLOT) 5371da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM5 | HCI_DH5); 5381da177e4SLinus Torvalds 539cad718edSJohan Hedberg if (hdev->features[0][1] & LMP_HV2) { 5401da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV2); 5415b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV2); 5425b7f9909SMarcel Holtmann } 5431da177e4SLinus Torvalds 544cad718edSJohan Hedberg if (hdev->features[0][1] & LMP_HV3) { 5451da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV3); 5465b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV3); 5475b7f9909SMarcel Holtmann } 5485b7f9909SMarcel Holtmann 54945db810fSAndre Guedes if (lmp_esco_capable(hdev)) 5505b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV3); 5515b7f9909SMarcel Holtmann 552cad718edSJohan Hedberg if (hdev->features[0][4] & LMP_EV4) 5535b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV4); 5545b7f9909SMarcel Holtmann 555cad718edSJohan Hedberg if (hdev->features[0][4] & LMP_EV5) 5565b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV5); 5571da177e4SLinus Torvalds 558cad718edSJohan Hedberg if (hdev->features[0][5] & LMP_EDR_ESCO_2M) 559efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV3); 560efc7688bSMarcel Holtmann 561cad718edSJohan Hedberg if (hdev->features[0][5] & LMP_EDR_ESCO_3M) 562efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_3EV3); 563efc7688bSMarcel Holtmann 564cad718edSJohan Hedberg if (hdev->features[0][5] & LMP_EDR_3S_ESCO) 565efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); 5661da177e4SLinus Torvalds } 5671da177e4SLinus Torvalds 568971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev, 569971e3a4bSAndre Guedes struct sk_buff *skb) 570971e3a4bSAndre Guedes { 571971e3a4bSAndre Guedes struct hci_rp_read_local_ext_features *rp = (void *) skb->data; 572971e3a4bSAndre Guedes 5739f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 574971e3a4bSAndre Guedes 575971e3a4bSAndre Guedes if (rp->status) 57642c6b129SJohan Hedberg return; 577971e3a4bSAndre Guedes 57857af75a8SMarcel Holtmann if (hdev->max_page < rp->max_page) 579d2c5d77fSJohan Hedberg hdev->max_page = rp->max_page; 580d2c5d77fSJohan Hedberg 581cad718edSJohan Hedberg if (rp->page < HCI_MAX_PAGES) 582cad718edSJohan Hedberg memcpy(hdev->features[rp->page], rp->features, 8); 583971e3a4bSAndre Guedes } 584971e3a4bSAndre Guedes 5851e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, 5861e89cffbSAndrei Emeltchenko struct sk_buff *skb) 5871e89cffbSAndrei Emeltchenko { 5881e89cffbSAndrei Emeltchenko struct hci_rp_read_flow_control_mode *rp = (void *) skb->data; 5891e89cffbSAndrei Emeltchenko 5909f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 5911e89cffbSAndrei Emeltchenko 59245296acdSMarcel Holtmann if (rp->status) 59345296acdSMarcel Holtmann return; 59445296acdSMarcel Holtmann 5951e89cffbSAndrei Emeltchenko hdev->flow_ctl_mode = rp->mode; 5961e89cffbSAndrei Emeltchenko } 5971e89cffbSAndrei Emeltchenko 598a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 599a9de9248SMarcel Holtmann { 600a9de9248SMarcel Holtmann struct hci_rp_read_buffer_size *rp = (void *) skb->data; 601a9de9248SMarcel Holtmann 6029f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 603a9de9248SMarcel Holtmann 604a9de9248SMarcel Holtmann if (rp->status) 605a9de9248SMarcel Holtmann return; 606a9de9248SMarcel Holtmann 607a9de9248SMarcel Holtmann hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); 608a9de9248SMarcel Holtmann hdev->sco_mtu = rp->sco_mtu; 609a9de9248SMarcel Holtmann hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); 610a9de9248SMarcel Holtmann hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); 611da1f5198SMarcel Holtmann 612da1f5198SMarcel Holtmann if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { 613da1f5198SMarcel Holtmann hdev->sco_mtu = 64; 614da1f5198SMarcel Holtmann hdev->sco_pkts = 8; 615da1f5198SMarcel Holtmann } 616da1f5198SMarcel Holtmann 617da1f5198SMarcel Holtmann hdev->acl_cnt = hdev->acl_pkts; 618da1f5198SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 6191da177e4SLinus Torvalds 620807deac2SGustavo Padovan BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu, 621807deac2SGustavo Padovan hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts); 6221da177e4SLinus Torvalds } 6231da177e4SLinus Torvalds 624a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) 625a9de9248SMarcel Holtmann { 626a9de9248SMarcel Holtmann struct hci_rp_read_bd_addr *rp = (void *) skb->data; 6271da177e4SLinus Torvalds 6289f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 629a9de9248SMarcel Holtmann 630e30d3f5fSMarcel Holtmann if (rp->status) 631e30d3f5fSMarcel Holtmann return; 632e30d3f5fSMarcel Holtmann 633e30d3f5fSMarcel Holtmann if (test_bit(HCI_INIT, &hdev->flags)) 634a9de9248SMarcel Holtmann bacpy(&hdev->bdaddr, &rp->bdaddr); 635e30d3f5fSMarcel Holtmann 636e30d3f5fSMarcel Holtmann if (test_bit(HCI_SETUP, &hdev->dev_flags)) 637e30d3f5fSMarcel Holtmann bacpy(&hdev->setup_addr, &rp->bdaddr); 63823bb5763SJohan Hedberg } 63923bb5763SJohan Hedberg 640f332ec66SJohan Hedberg static void hci_cc_read_page_scan_activity(struct hci_dev *hdev, 641f332ec66SJohan Hedberg struct sk_buff *skb) 642f332ec66SJohan Hedberg { 643f332ec66SJohan Hedberg struct hci_rp_read_page_scan_activity *rp = (void *) skb->data; 644f332ec66SJohan Hedberg 645f332ec66SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 646f332ec66SJohan Hedberg 64745296acdSMarcel Holtmann if (rp->status) 64845296acdSMarcel Holtmann return; 64945296acdSMarcel Holtmann 65045296acdSMarcel Holtmann if (test_bit(HCI_INIT, &hdev->flags)) { 651f332ec66SJohan Hedberg hdev->page_scan_interval = __le16_to_cpu(rp->interval); 652f332ec66SJohan Hedberg hdev->page_scan_window = __le16_to_cpu(rp->window); 653f332ec66SJohan Hedberg } 654f332ec66SJohan Hedberg } 655f332ec66SJohan Hedberg 6564a3ee763SJohan Hedberg static void hci_cc_write_page_scan_activity(struct hci_dev *hdev, 6574a3ee763SJohan Hedberg struct sk_buff *skb) 6584a3ee763SJohan Hedberg { 6594a3ee763SJohan Hedberg u8 status = *((u8 *) skb->data); 6604a3ee763SJohan Hedberg struct hci_cp_write_page_scan_activity *sent; 6614a3ee763SJohan Hedberg 6624a3ee763SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 6634a3ee763SJohan Hedberg 6644a3ee763SJohan Hedberg if (status) 6654a3ee763SJohan Hedberg return; 6664a3ee763SJohan Hedberg 6674a3ee763SJohan Hedberg sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY); 6684a3ee763SJohan Hedberg if (!sent) 6694a3ee763SJohan Hedberg return; 6704a3ee763SJohan Hedberg 6714a3ee763SJohan Hedberg hdev->page_scan_interval = __le16_to_cpu(sent->interval); 6724a3ee763SJohan Hedberg hdev->page_scan_window = __le16_to_cpu(sent->window); 6734a3ee763SJohan Hedberg } 6744a3ee763SJohan Hedberg 675f332ec66SJohan Hedberg static void hci_cc_read_page_scan_type(struct hci_dev *hdev, 676f332ec66SJohan Hedberg struct sk_buff *skb) 677f332ec66SJohan Hedberg { 678f332ec66SJohan Hedberg struct hci_rp_read_page_scan_type *rp = (void *) skb->data; 679f332ec66SJohan Hedberg 680f332ec66SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 681f332ec66SJohan Hedberg 68245296acdSMarcel Holtmann if (rp->status) 68345296acdSMarcel Holtmann return; 68445296acdSMarcel Holtmann 68545296acdSMarcel Holtmann if (test_bit(HCI_INIT, &hdev->flags)) 686f332ec66SJohan Hedberg hdev->page_scan_type = rp->type; 687f332ec66SJohan Hedberg } 688f332ec66SJohan Hedberg 6894a3ee763SJohan Hedberg static void hci_cc_write_page_scan_type(struct hci_dev *hdev, 6904a3ee763SJohan Hedberg struct sk_buff *skb) 6914a3ee763SJohan Hedberg { 6924a3ee763SJohan Hedberg u8 status = *((u8 *) skb->data); 6934a3ee763SJohan Hedberg u8 *type; 6944a3ee763SJohan Hedberg 6954a3ee763SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 6964a3ee763SJohan Hedberg 6974a3ee763SJohan Hedberg if (status) 6984a3ee763SJohan Hedberg return; 6994a3ee763SJohan Hedberg 7004a3ee763SJohan Hedberg type = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE); 7014a3ee763SJohan Hedberg if (type) 7024a3ee763SJohan Hedberg hdev->page_scan_type = *type; 7034a3ee763SJohan Hedberg } 7044a3ee763SJohan Hedberg 705350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev, 706350ee4cfSAndrei Emeltchenko struct sk_buff *skb) 707350ee4cfSAndrei Emeltchenko { 708350ee4cfSAndrei Emeltchenko struct hci_rp_read_data_block_size *rp = (void *) skb->data; 709350ee4cfSAndrei Emeltchenko 7109f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 711350ee4cfSAndrei Emeltchenko 712350ee4cfSAndrei Emeltchenko if (rp->status) 713350ee4cfSAndrei Emeltchenko return; 714350ee4cfSAndrei Emeltchenko 715350ee4cfSAndrei Emeltchenko hdev->block_mtu = __le16_to_cpu(rp->max_acl_len); 716350ee4cfSAndrei Emeltchenko hdev->block_len = __le16_to_cpu(rp->block_len); 717350ee4cfSAndrei Emeltchenko hdev->num_blocks = __le16_to_cpu(rp->num_blocks); 718350ee4cfSAndrei Emeltchenko 719350ee4cfSAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 720350ee4cfSAndrei Emeltchenko 721350ee4cfSAndrei Emeltchenko BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu, 722350ee4cfSAndrei Emeltchenko hdev->block_cnt, hdev->block_len); 723350ee4cfSAndrei Emeltchenko } 724350ee4cfSAndrei Emeltchenko 72533f35721SJohan Hedberg static void hci_cc_read_clock(struct hci_dev *hdev, struct sk_buff *skb) 72633f35721SJohan Hedberg { 72733f35721SJohan Hedberg struct hci_rp_read_clock *rp = (void *) skb->data; 72833f35721SJohan Hedberg struct hci_cp_read_clock *cp; 72933f35721SJohan Hedberg struct hci_conn *conn; 73033f35721SJohan Hedberg 73133f35721SJohan Hedberg BT_DBG("%s", hdev->name); 73233f35721SJohan Hedberg 73333f35721SJohan Hedberg if (skb->len < sizeof(*rp)) 73433f35721SJohan Hedberg return; 73533f35721SJohan Hedberg 73633f35721SJohan Hedberg if (rp->status) 73733f35721SJohan Hedberg return; 73833f35721SJohan Hedberg 73933f35721SJohan Hedberg hci_dev_lock(hdev); 74033f35721SJohan Hedberg 74133f35721SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK); 74233f35721SJohan Hedberg if (!cp) 74333f35721SJohan Hedberg goto unlock; 74433f35721SJohan Hedberg 74533f35721SJohan Hedberg if (cp->which == 0x00) { 74633f35721SJohan Hedberg hdev->clock = le32_to_cpu(rp->clock); 74733f35721SJohan Hedberg goto unlock; 74833f35721SJohan Hedberg } 74933f35721SJohan Hedberg 75033f35721SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 75133f35721SJohan Hedberg if (conn) { 75233f35721SJohan Hedberg conn->clock = le32_to_cpu(rp->clock); 75333f35721SJohan Hedberg conn->clock_accuracy = le16_to_cpu(rp->accuracy); 75433f35721SJohan Hedberg } 75533f35721SJohan Hedberg 75633f35721SJohan Hedberg unlock: 75733f35721SJohan Hedberg hci_dev_unlock(hdev); 75833f35721SJohan Hedberg } 75933f35721SJohan Hedberg 760928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev, 761928abaa7SAndrei Emeltchenko struct sk_buff *skb) 762928abaa7SAndrei Emeltchenko { 763928abaa7SAndrei Emeltchenko struct hci_rp_read_local_amp_info *rp = (void *) skb->data; 764928abaa7SAndrei Emeltchenko 7659f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 766928abaa7SAndrei Emeltchenko 767928abaa7SAndrei Emeltchenko if (rp->status) 7688e2a0d92SAndrei Emeltchenko goto a2mp_rsp; 769928abaa7SAndrei Emeltchenko 770928abaa7SAndrei Emeltchenko hdev->amp_status = rp->amp_status; 771928abaa7SAndrei Emeltchenko hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); 772928abaa7SAndrei Emeltchenko hdev->amp_max_bw = __le32_to_cpu(rp->max_bw); 773928abaa7SAndrei Emeltchenko hdev->amp_min_latency = __le32_to_cpu(rp->min_latency); 774928abaa7SAndrei Emeltchenko hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu); 775928abaa7SAndrei Emeltchenko hdev->amp_type = rp->amp_type; 776928abaa7SAndrei Emeltchenko hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap); 777928abaa7SAndrei Emeltchenko hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size); 778928abaa7SAndrei Emeltchenko hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); 779928abaa7SAndrei Emeltchenko hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); 780928abaa7SAndrei Emeltchenko 7818e2a0d92SAndrei Emeltchenko a2mp_rsp: 7828e2a0d92SAndrei Emeltchenko a2mp_send_getinfo_rsp(hdev); 783928abaa7SAndrei Emeltchenko } 784928abaa7SAndrei Emeltchenko 785903e4541SAndrei Emeltchenko static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev, 786903e4541SAndrei Emeltchenko struct sk_buff *skb) 787903e4541SAndrei Emeltchenko { 788903e4541SAndrei Emeltchenko struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data; 789903e4541SAndrei Emeltchenko struct amp_assoc *assoc = &hdev->loc_assoc; 790903e4541SAndrei Emeltchenko size_t rem_len, frag_len; 791903e4541SAndrei Emeltchenko 792903e4541SAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 793903e4541SAndrei Emeltchenko 794903e4541SAndrei Emeltchenko if (rp->status) 795903e4541SAndrei Emeltchenko goto a2mp_rsp; 796903e4541SAndrei Emeltchenko 797903e4541SAndrei Emeltchenko frag_len = skb->len - sizeof(*rp); 798903e4541SAndrei Emeltchenko rem_len = __le16_to_cpu(rp->rem_len); 799903e4541SAndrei Emeltchenko 800903e4541SAndrei Emeltchenko if (rem_len > frag_len) { 8012e430be3SAndrei Emeltchenko BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len); 802903e4541SAndrei Emeltchenko 803903e4541SAndrei Emeltchenko memcpy(assoc->data + assoc->offset, rp->frag, frag_len); 804903e4541SAndrei Emeltchenko assoc->offset += frag_len; 805903e4541SAndrei Emeltchenko 806903e4541SAndrei Emeltchenko /* Read other fragments */ 807903e4541SAndrei Emeltchenko amp_read_loc_assoc_frag(hdev, rp->phy_handle); 808903e4541SAndrei Emeltchenko 809903e4541SAndrei Emeltchenko return; 810903e4541SAndrei Emeltchenko } 811903e4541SAndrei Emeltchenko 812903e4541SAndrei Emeltchenko memcpy(assoc->data + assoc->offset, rp->frag, rem_len); 813903e4541SAndrei Emeltchenko assoc->len = assoc->offset + rem_len; 814903e4541SAndrei Emeltchenko assoc->offset = 0; 815903e4541SAndrei Emeltchenko 816903e4541SAndrei Emeltchenko a2mp_rsp: 817903e4541SAndrei Emeltchenko /* Send A2MP Rsp when all fragments are received */ 818903e4541SAndrei Emeltchenko a2mp_send_getampassoc_rsp(hdev, rp->status); 8199495b2eeSAndrei Emeltchenko a2mp_send_create_phy_link_req(hdev, rp->status); 820903e4541SAndrei Emeltchenko } 821903e4541SAndrei Emeltchenko 822d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, 823d5859e22SJohan Hedberg struct sk_buff *skb) 824d5859e22SJohan Hedberg { 82591c4e9b1SMarcel Holtmann struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data; 826d5859e22SJohan Hedberg 8279f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 828d5859e22SJohan Hedberg 82945296acdSMarcel Holtmann if (rp->status) 83045296acdSMarcel Holtmann return; 83145296acdSMarcel Holtmann 83291c4e9b1SMarcel Holtmann hdev->inq_tx_power = rp->tx_power; 833d5859e22SJohan Hedberg } 834d5859e22SJohan Hedberg 835980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) 836980e1a53SJohan Hedberg { 837980e1a53SJohan Hedberg struct hci_rp_pin_code_reply *rp = (void *) skb->data; 838980e1a53SJohan Hedberg struct hci_cp_pin_code_reply *cp; 839980e1a53SJohan Hedberg struct hci_conn *conn; 840980e1a53SJohan Hedberg 8419f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 842980e1a53SJohan Hedberg 84356e5cb86SJohan Hedberg hci_dev_lock(hdev); 84456e5cb86SJohan Hedberg 845a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 846744cf19eSJohan Hedberg mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); 847980e1a53SJohan Hedberg 848fa1bd918SMikel Astiz if (rp->status) 84956e5cb86SJohan Hedberg goto unlock; 850980e1a53SJohan Hedberg 851980e1a53SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); 852980e1a53SJohan Hedberg if (!cp) 85356e5cb86SJohan Hedberg goto unlock; 854980e1a53SJohan Hedberg 855980e1a53SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 856980e1a53SJohan Hedberg if (conn) 857980e1a53SJohan Hedberg conn->pin_length = cp->pin_len; 85856e5cb86SJohan Hedberg 85956e5cb86SJohan Hedberg unlock: 86056e5cb86SJohan Hedberg hci_dev_unlock(hdev); 861980e1a53SJohan Hedberg } 862980e1a53SJohan Hedberg 863980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 864980e1a53SJohan Hedberg { 865980e1a53SJohan Hedberg struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data; 866980e1a53SJohan Hedberg 8679f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 868980e1a53SJohan Hedberg 86956e5cb86SJohan Hedberg hci_dev_lock(hdev); 87056e5cb86SJohan Hedberg 871a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 872744cf19eSJohan Hedberg mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr, 873980e1a53SJohan Hedberg rp->status); 87456e5cb86SJohan Hedberg 87556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 876980e1a53SJohan Hedberg } 87756e5cb86SJohan Hedberg 8786ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, 8796ed58ec5SVille Tervo struct sk_buff *skb) 8806ed58ec5SVille Tervo { 8816ed58ec5SVille Tervo struct hci_rp_le_read_buffer_size *rp = (void *) skb->data; 8826ed58ec5SVille Tervo 8839f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 8846ed58ec5SVille Tervo 8856ed58ec5SVille Tervo if (rp->status) 8866ed58ec5SVille Tervo return; 8876ed58ec5SVille Tervo 8886ed58ec5SVille Tervo hdev->le_mtu = __le16_to_cpu(rp->le_mtu); 8896ed58ec5SVille Tervo hdev->le_pkts = rp->le_max_pkt; 8906ed58ec5SVille Tervo 8916ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 8926ed58ec5SVille Tervo 8936ed58ec5SVille Tervo BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); 8946ed58ec5SVille Tervo } 895980e1a53SJohan Hedberg 89660e77321SJohan Hedberg static void hci_cc_le_read_local_features(struct hci_dev *hdev, 89760e77321SJohan Hedberg struct sk_buff *skb) 89860e77321SJohan Hedberg { 89960e77321SJohan Hedberg struct hci_rp_le_read_local_features *rp = (void *) skb->data; 90060e77321SJohan Hedberg 90160e77321SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 90260e77321SJohan Hedberg 90345296acdSMarcel Holtmann if (rp->status) 90445296acdSMarcel Holtmann return; 90545296acdSMarcel Holtmann 90660e77321SJohan Hedberg memcpy(hdev->le_features, rp->features, 8); 90760e77321SJohan Hedberg } 90860e77321SJohan Hedberg 9098fa19098SJohan Hedberg static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, 9108fa19098SJohan Hedberg struct sk_buff *skb) 9118fa19098SJohan Hedberg { 9128fa19098SJohan Hedberg struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data; 9138fa19098SJohan Hedberg 9148fa19098SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 9158fa19098SJohan Hedberg 91645296acdSMarcel Holtmann if (rp->status) 91745296acdSMarcel Holtmann return; 91845296acdSMarcel Holtmann 9198fa19098SJohan Hedberg hdev->adv_tx_power = rp->tx_power; 9208fa19098SJohan Hedberg } 9218fa19098SJohan Hedberg 922a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) 923a5c29683SJohan Hedberg { 924a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 925a5c29683SJohan Hedberg 9269f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 927a5c29683SJohan Hedberg 92856e5cb86SJohan Hedberg hci_dev_lock(hdev); 92956e5cb86SJohan Hedberg 930a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 93104124681SGustavo F. Padovan mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0, 93204124681SGustavo F. Padovan rp->status); 93356e5cb86SJohan Hedberg 93456e5cb86SJohan Hedberg hci_dev_unlock(hdev); 935a5c29683SJohan Hedberg } 936a5c29683SJohan Hedberg 937a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, 938a5c29683SJohan Hedberg struct sk_buff *skb) 939a5c29683SJohan Hedberg { 940a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 941a5c29683SJohan Hedberg 9429f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 943a5c29683SJohan Hedberg 94456e5cb86SJohan Hedberg hci_dev_lock(hdev); 94556e5cb86SJohan Hedberg 946a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 947744cf19eSJohan Hedberg mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr, 94804124681SGustavo F. Padovan ACL_LINK, 0, rp->status); 94956e5cb86SJohan Hedberg 95056e5cb86SJohan Hedberg hci_dev_unlock(hdev); 951a5c29683SJohan Hedberg } 952a5c29683SJohan Hedberg 9531143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb) 9541143d458SBrian Gix { 9551143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 9561143d458SBrian Gix 9579f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 9581143d458SBrian Gix 9591143d458SBrian Gix hci_dev_lock(hdev); 9601143d458SBrian Gix 961a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 962272d90dfSJohan Hedberg mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 963272d90dfSJohan Hedberg 0, rp->status); 9641143d458SBrian Gix 9651143d458SBrian Gix hci_dev_unlock(hdev); 9661143d458SBrian Gix } 9671143d458SBrian Gix 9681143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, 9691143d458SBrian Gix struct sk_buff *skb) 9701143d458SBrian Gix { 9711143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 9721143d458SBrian Gix 9739f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 9741143d458SBrian Gix 9751143d458SBrian Gix hci_dev_lock(hdev); 9761143d458SBrian Gix 977a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 9781143d458SBrian Gix mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr, 97904124681SGustavo F. Padovan ACL_LINK, 0, rp->status); 9801143d458SBrian Gix 9811143d458SBrian Gix hci_dev_unlock(hdev); 9821143d458SBrian Gix } 9831143d458SBrian Gix 9844d2d2796SMarcel Holtmann static void hci_cc_read_local_oob_data(struct hci_dev *hdev, 985c35938b2SSzymon Janc struct sk_buff *skb) 986c35938b2SSzymon Janc { 987c35938b2SSzymon Janc struct hci_rp_read_local_oob_data *rp = (void *) skb->data; 988c35938b2SSzymon Janc 9899f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 990c35938b2SSzymon Janc 99156e5cb86SJohan Hedberg hci_dev_lock(hdev); 9924d2d2796SMarcel Holtmann mgmt_read_local_oob_data_complete(hdev, rp->hash, rp->randomizer, 9934d2d2796SMarcel Holtmann NULL, NULL, rp->status); 9944d2d2796SMarcel Holtmann hci_dev_unlock(hdev); 9954d2d2796SMarcel Holtmann } 9964d2d2796SMarcel Holtmann 9974d2d2796SMarcel Holtmann static void hci_cc_read_local_oob_ext_data(struct hci_dev *hdev, 9984d2d2796SMarcel Holtmann struct sk_buff *skb) 9994d2d2796SMarcel Holtmann { 10004d2d2796SMarcel Holtmann struct hci_rp_read_local_oob_ext_data *rp = (void *) skb->data; 10014d2d2796SMarcel Holtmann 10024d2d2796SMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 10034d2d2796SMarcel Holtmann 10044d2d2796SMarcel Holtmann hci_dev_lock(hdev); 10054d2d2796SMarcel Holtmann mgmt_read_local_oob_data_complete(hdev, rp->hash192, rp->randomizer192, 10064d2d2796SMarcel Holtmann rp->hash256, rp->randomizer256, 10074d2d2796SMarcel Holtmann rp->status); 100856e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1009c35938b2SSzymon Janc } 1010c35938b2SSzymon Janc 10117a4cd51dSMarcel Holtmann 10127a4cd51dSMarcel Holtmann static void hci_cc_le_set_random_addr(struct hci_dev *hdev, struct sk_buff *skb) 10137a4cd51dSMarcel Holtmann { 10147a4cd51dSMarcel Holtmann __u8 status = *((__u8 *) skb->data); 10157a4cd51dSMarcel Holtmann bdaddr_t *sent; 10167a4cd51dSMarcel Holtmann 10177a4cd51dSMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, status); 10187a4cd51dSMarcel Holtmann 101945296acdSMarcel Holtmann if (status) 102045296acdSMarcel Holtmann return; 102145296acdSMarcel Holtmann 10227a4cd51dSMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_RANDOM_ADDR); 10237a4cd51dSMarcel Holtmann if (!sent) 10247a4cd51dSMarcel Holtmann return; 10257a4cd51dSMarcel Holtmann 10267a4cd51dSMarcel Holtmann hci_dev_lock(hdev); 10277a4cd51dSMarcel Holtmann 10287a4cd51dSMarcel Holtmann bacpy(&hdev->random_addr, sent); 10297a4cd51dSMarcel Holtmann 10307a4cd51dSMarcel Holtmann hci_dev_unlock(hdev); 10317a4cd51dSMarcel Holtmann } 10327a4cd51dSMarcel Holtmann 1033c1d5dc4aSJohan Hedberg static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb) 1034c1d5dc4aSJohan Hedberg { 1035c1d5dc4aSJohan Hedberg __u8 *sent, status = *((__u8 *) skb->data); 1036c1d5dc4aSJohan Hedberg 1037c1d5dc4aSJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 1038c1d5dc4aSJohan Hedberg 103945296acdSMarcel Holtmann if (status) 1040c1d5dc4aSJohan Hedberg return; 1041c1d5dc4aSJohan Hedberg 104245296acdSMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE); 104345296acdSMarcel Holtmann if (!sent) 10443c857757SJohan Hedberg return; 10453c857757SJohan Hedberg 1046c1d5dc4aSJohan Hedberg hci_dev_lock(hdev); 1047c1d5dc4aSJohan Hedberg 10483c857757SJohan Hedberg /* If we're doing connection initation as peripheral. Set a 10493c857757SJohan Hedberg * timeout in case something goes wrong. 10503c857757SJohan Hedberg */ 10513c857757SJohan Hedberg if (*sent) { 10523c857757SJohan Hedberg struct hci_conn *conn; 10533c857757SJohan Hedberg 105466c417c1SJohan Hedberg set_bit(HCI_LE_ADV, &hdev->dev_flags); 105566c417c1SJohan Hedberg 10563c857757SJohan Hedberg conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); 10573c857757SJohan Hedberg if (conn) 10583c857757SJohan Hedberg queue_delayed_work(hdev->workqueue, 10593c857757SJohan Hedberg &conn->le_conn_timeout, 106009ae260bSJohan Hedberg conn->conn_timeout); 106166c417c1SJohan Hedberg } else { 106266c417c1SJohan Hedberg clear_bit(HCI_LE_ADV, &hdev->dev_flags); 10633c857757SJohan Hedberg } 10643c857757SJohan Hedberg 106504b4edcbSJohan Hedberg hci_dev_unlock(hdev); 1066c1d5dc4aSJohan Hedberg } 1067c1d5dc4aSJohan Hedberg 1068533553f8SMarcel Holtmann static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) 1069533553f8SMarcel Holtmann { 1070533553f8SMarcel Holtmann struct hci_cp_le_set_scan_param *cp; 1071533553f8SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 1072533553f8SMarcel Holtmann 1073533553f8SMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, status); 1074533553f8SMarcel Holtmann 107545296acdSMarcel Holtmann if (status) 107645296acdSMarcel Holtmann return; 107745296acdSMarcel Holtmann 1078533553f8SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_PARAM); 1079533553f8SMarcel Holtmann if (!cp) 1080533553f8SMarcel Holtmann return; 1081533553f8SMarcel Holtmann 1082533553f8SMarcel Holtmann hci_dev_lock(hdev); 1083533553f8SMarcel Holtmann 1084533553f8SMarcel Holtmann hdev->le_scan_type = cp->type; 1085533553f8SMarcel Holtmann 1086533553f8SMarcel Holtmann hci_dev_unlock(hdev); 1087533553f8SMarcel Holtmann } 1088533553f8SMarcel Holtmann 1089b9a6328fSJohan Hedberg static bool has_pending_adv_report(struct hci_dev *hdev) 1090b9a6328fSJohan Hedberg { 1091b9a6328fSJohan Hedberg struct discovery_state *d = &hdev->discovery; 1092b9a6328fSJohan Hedberg 1093b9a6328fSJohan Hedberg return bacmp(&d->last_adv_addr, BDADDR_ANY); 1094b9a6328fSJohan Hedberg } 1095b9a6328fSJohan Hedberg 1096b9a6328fSJohan Hedberg static void clear_pending_adv_report(struct hci_dev *hdev) 1097b9a6328fSJohan Hedberg { 1098b9a6328fSJohan Hedberg struct discovery_state *d = &hdev->discovery; 1099b9a6328fSJohan Hedberg 1100b9a6328fSJohan Hedberg bacpy(&d->last_adv_addr, BDADDR_ANY); 1101b9a6328fSJohan Hedberg d->last_adv_data_len = 0; 1102b9a6328fSJohan Hedberg } 1103b9a6328fSJohan Hedberg 1104b9a6328fSJohan Hedberg static void store_pending_adv_report(struct hci_dev *hdev, bdaddr_t *bdaddr, 1105c70a7e4cSMarcel Holtmann u8 bdaddr_type, s8 rssi, u32 flags, 1106c70a7e4cSMarcel Holtmann u8 *data, u8 len) 1107b9a6328fSJohan Hedberg { 1108b9a6328fSJohan Hedberg struct discovery_state *d = &hdev->discovery; 1109b9a6328fSJohan Hedberg 1110b9a6328fSJohan Hedberg bacpy(&d->last_adv_addr, bdaddr); 1111b9a6328fSJohan Hedberg d->last_adv_addr_type = bdaddr_type; 1112ff5cd29fSJohan Hedberg d->last_adv_rssi = rssi; 1113c70a7e4cSMarcel Holtmann d->last_adv_flags = flags; 1114b9a6328fSJohan Hedberg memcpy(d->last_adv_data, data, len); 1115b9a6328fSJohan Hedberg d->last_adv_data_len = len; 1116b9a6328fSJohan Hedberg } 1117b9a6328fSJohan Hedberg 1118eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, 1119eb9d91f5SAndre Guedes struct sk_buff *skb) 1120eb9d91f5SAndre Guedes { 1121eb9d91f5SAndre Guedes struct hci_cp_le_set_scan_enable *cp; 1122eb9d91f5SAndre Guedes __u8 status = *((__u8 *) skb->data); 1123eb9d91f5SAndre Guedes 11249f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1125eb9d91f5SAndre Guedes 112645296acdSMarcel Holtmann if (status) 1127eb9d91f5SAndre Guedes return; 1128eb9d91f5SAndre Guedes 112945296acdSMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE); 113045296acdSMarcel Holtmann if (!cp) 11317ba8b4beSAndre Guedes return; 11327ba8b4beSAndre Guedes 11333fd319b8SAndre Guedes switch (cp->enable) { 11343fd319b8SAndre Guedes case LE_SCAN_ENABLE: 1135d23264a8SAndre Guedes set_bit(HCI_LE_SCAN, &hdev->dev_flags); 1136b9a6328fSJohan Hedberg if (hdev->le_scan_type == LE_SCAN_ACTIVE) 1137b9a6328fSJohan Hedberg clear_pending_adv_report(hdev); 113868a8aea4SAndrei Emeltchenko break; 113968a8aea4SAndrei Emeltchenko 114076a388beSAndre Guedes case LE_SCAN_DISABLE: 1141b9a6328fSJohan Hedberg /* We do this here instead of when setting DISCOVERY_STOPPED 1142b9a6328fSJohan Hedberg * since the latter would potentially require waiting for 1143b9a6328fSJohan Hedberg * inquiry to stop too. 1144b9a6328fSJohan Hedberg */ 1145b9a6328fSJohan Hedberg if (has_pending_adv_report(hdev)) { 1146b9a6328fSJohan Hedberg struct discovery_state *d = &hdev->discovery; 1147b9a6328fSJohan Hedberg 1148b9a6328fSJohan Hedberg mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK, 1149ab0aa433SJohan Hedberg d->last_adv_addr_type, NULL, 1150c70a7e4cSMarcel Holtmann d->last_adv_rssi, d->last_adv_flags, 1151ab0aa433SJohan Hedberg d->last_adv_data, 1152b9a6328fSJohan Hedberg d->last_adv_data_len, NULL, 0); 1153b9a6328fSJohan Hedberg } 1154b9a6328fSJohan Hedberg 1155317ac8cbSJohan Hedberg /* Cancel this timer so that we don't try to disable scanning 1156317ac8cbSJohan Hedberg * when it's already disabled. 1157317ac8cbSJohan Hedberg */ 1158317ac8cbSJohan Hedberg cancel_delayed_work(&hdev->le_scan_disable); 1159317ac8cbSJohan Hedberg 1160d23264a8SAndre Guedes clear_bit(HCI_LE_SCAN, &hdev->dev_flags); 1161e8bb6b97SJohan Hedberg 116281ad6fd9SJohan Hedberg /* The HCI_LE_SCAN_INTERRUPTED flag indicates that we 116381ad6fd9SJohan Hedberg * interrupted scanning due to a connect request. Mark 1164e8bb6b97SJohan Hedberg * therefore discovery as stopped. If this was not 1165e8bb6b97SJohan Hedberg * because of a connect request advertising might have 1166e8bb6b97SJohan Hedberg * been disabled because of active scanning, so 1167e8bb6b97SJohan Hedberg * re-enable it again if necessary. 116881ad6fd9SJohan Hedberg */ 116981ad6fd9SJohan Hedberg if (test_and_clear_bit(HCI_LE_SCAN_INTERRUPTED, 117081ad6fd9SJohan Hedberg &hdev->dev_flags)) 117181ad6fd9SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 1172e8bb6b97SJohan Hedberg else if (!test_bit(HCI_LE_ADV, &hdev->dev_flags) && 117334722277SJohan Hedberg hdev->discovery.state == DISCOVERY_FINDING) 1174e8bb6b97SJohan Hedberg mgmt_reenable_advertising(hdev); 1175e8bb6b97SJohan Hedberg 117668a8aea4SAndrei Emeltchenko break; 117768a8aea4SAndrei Emeltchenko 117868a8aea4SAndrei Emeltchenko default: 117968a8aea4SAndrei Emeltchenko BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable); 118068a8aea4SAndrei Emeltchenko break; 118135815085SAndre Guedes } 1182eb9d91f5SAndre Guedes } 1183eb9d91f5SAndre Guedes 1184cf1d081fSJohan Hedberg static void hci_cc_le_read_white_list_size(struct hci_dev *hdev, 1185cf1d081fSJohan Hedberg struct sk_buff *skb) 1186cf1d081fSJohan Hedberg { 1187cf1d081fSJohan Hedberg struct hci_rp_le_read_white_list_size *rp = (void *) skb->data; 1188cf1d081fSJohan Hedberg 1189cf1d081fSJohan Hedberg BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size); 1190cf1d081fSJohan Hedberg 119145296acdSMarcel Holtmann if (rp->status) 119245296acdSMarcel Holtmann return; 119345296acdSMarcel Holtmann 1194cf1d081fSJohan Hedberg hdev->le_white_list_size = rp->size; 1195cf1d081fSJohan Hedberg } 1196cf1d081fSJohan Hedberg 11970f36b589SMarcel Holtmann static void hci_cc_le_clear_white_list(struct hci_dev *hdev, 11980f36b589SMarcel Holtmann struct sk_buff *skb) 11990f36b589SMarcel Holtmann { 12000f36b589SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 12010f36b589SMarcel Holtmann 12020f36b589SMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, status); 12030f36b589SMarcel Holtmann 120445296acdSMarcel Holtmann if (status) 120545296acdSMarcel Holtmann return; 120645296acdSMarcel Holtmann 1207dcc36c16SJohan Hedberg hci_bdaddr_list_clear(&hdev->le_white_list); 12080f36b589SMarcel Holtmann } 12090f36b589SMarcel Holtmann 12100f36b589SMarcel Holtmann static void hci_cc_le_add_to_white_list(struct hci_dev *hdev, 12110f36b589SMarcel Holtmann struct sk_buff *skb) 12120f36b589SMarcel Holtmann { 12130f36b589SMarcel Holtmann struct hci_cp_le_add_to_white_list *sent; 12140f36b589SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 12150f36b589SMarcel Holtmann 12160f36b589SMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, status); 12170f36b589SMarcel Holtmann 121845296acdSMarcel Holtmann if (status) 121945296acdSMarcel Holtmann return; 122045296acdSMarcel Holtmann 12210f36b589SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_WHITE_LIST); 12220f36b589SMarcel Holtmann if (!sent) 12230f36b589SMarcel Holtmann return; 12240f36b589SMarcel Holtmann 1225dcc36c16SJohan Hedberg hci_bdaddr_list_add(&hdev->le_white_list, &sent->bdaddr, 1226dcc36c16SJohan Hedberg sent->bdaddr_type); 12270f36b589SMarcel Holtmann } 12280f36b589SMarcel Holtmann 12290f36b589SMarcel Holtmann static void hci_cc_le_del_from_white_list(struct hci_dev *hdev, 12300f36b589SMarcel Holtmann struct sk_buff *skb) 12310f36b589SMarcel Holtmann { 12320f36b589SMarcel Holtmann struct hci_cp_le_del_from_white_list *sent; 12330f36b589SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 12340f36b589SMarcel Holtmann 12350f36b589SMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, status); 12360f36b589SMarcel Holtmann 123745296acdSMarcel Holtmann if (status) 123845296acdSMarcel Holtmann return; 123945296acdSMarcel Holtmann 12400f36b589SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_LE_DEL_FROM_WHITE_LIST); 12410f36b589SMarcel Holtmann if (!sent) 12420f36b589SMarcel Holtmann return; 12430f36b589SMarcel Holtmann 1244dcc36c16SJohan Hedberg hci_bdaddr_list_del(&hdev->le_white_list, &sent->bdaddr, 1245dcc36c16SJohan Hedberg sent->bdaddr_type); 12460f36b589SMarcel Holtmann } 12470f36b589SMarcel Holtmann 12489b008c04SJohan Hedberg static void hci_cc_le_read_supported_states(struct hci_dev *hdev, 12499b008c04SJohan Hedberg struct sk_buff *skb) 12509b008c04SJohan Hedberg { 12519b008c04SJohan Hedberg struct hci_rp_le_read_supported_states *rp = (void *) skb->data; 12529b008c04SJohan Hedberg 12539b008c04SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 12549b008c04SJohan Hedberg 125545296acdSMarcel Holtmann if (rp->status) 125645296acdSMarcel Holtmann return; 125745296acdSMarcel Holtmann 12589b008c04SJohan Hedberg memcpy(hdev->le_states, rp->le_states, 8); 12599b008c04SJohan Hedberg } 12609b008c04SJohan Hedberg 12616039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev, 1262f9b49306SAndre Guedes struct sk_buff *skb) 1263f9b49306SAndre Guedes { 126406199cf8SJohan Hedberg struct hci_cp_write_le_host_supported *sent; 1265f9b49306SAndre Guedes __u8 status = *((__u8 *) skb->data); 1266f9b49306SAndre Guedes 12679f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1268f9b49306SAndre Guedes 126945296acdSMarcel Holtmann if (status) 127045296acdSMarcel Holtmann return; 127145296acdSMarcel Holtmann 127206199cf8SJohan Hedberg sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED); 12738f984dfaSJohan Hedberg if (!sent) 1274f9b49306SAndre Guedes return; 1275f9b49306SAndre Guedes 1276416a4ae5SJohan Hedberg if (sent->le) { 1277cad718edSJohan Hedberg hdev->features[1][0] |= LMP_HOST_LE; 1278416a4ae5SJohan Hedberg set_bit(HCI_LE_ENABLED, &hdev->dev_flags); 1279416a4ae5SJohan Hedberg } else { 1280cad718edSJohan Hedberg hdev->features[1][0] &= ~LMP_HOST_LE; 1281416a4ae5SJohan Hedberg clear_bit(HCI_LE_ENABLED, &hdev->dev_flags); 1282f3d3444aSJohan Hedberg clear_bit(HCI_ADVERTISING, &hdev->dev_flags); 1283416a4ae5SJohan Hedberg } 128453b2caabSJohan Hedberg 128553b2caabSJohan Hedberg if (sent->simul) 1286cad718edSJohan Hedberg hdev->features[1][0] |= LMP_HOST_LE_BREDR; 128753b2caabSJohan Hedberg else 1288cad718edSJohan Hedberg hdev->features[1][0] &= ~LMP_HOST_LE_BREDR; 12898f984dfaSJohan Hedberg } 1290f9b49306SAndre Guedes 129156ed2cb8SJohan Hedberg static void hci_cc_set_adv_param(struct hci_dev *hdev, struct sk_buff *skb) 129256ed2cb8SJohan Hedberg { 129356ed2cb8SJohan Hedberg struct hci_cp_le_set_adv_param *cp; 129456ed2cb8SJohan Hedberg u8 status = *((u8 *) skb->data); 129556ed2cb8SJohan Hedberg 129656ed2cb8SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 129756ed2cb8SJohan Hedberg 129856ed2cb8SJohan Hedberg if (status) 129956ed2cb8SJohan Hedberg return; 130056ed2cb8SJohan Hedberg 130156ed2cb8SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_PARAM); 130256ed2cb8SJohan Hedberg if (!cp) 130356ed2cb8SJohan Hedberg return; 130456ed2cb8SJohan Hedberg 130556ed2cb8SJohan Hedberg hci_dev_lock(hdev); 130656ed2cb8SJohan Hedberg hdev->adv_addr_type = cp->own_address_type; 130756ed2cb8SJohan Hedberg hci_dev_unlock(hdev); 130856ed2cb8SJohan Hedberg } 130956ed2cb8SJohan Hedberg 131093c284eeSAndrei Emeltchenko static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev, 131193c284eeSAndrei Emeltchenko struct sk_buff *skb) 131293c284eeSAndrei Emeltchenko { 131393c284eeSAndrei Emeltchenko struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data; 131493c284eeSAndrei Emeltchenko 131593c284eeSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x", 131693c284eeSAndrei Emeltchenko hdev->name, rp->status, rp->phy_handle); 131793c284eeSAndrei Emeltchenko 131893c284eeSAndrei Emeltchenko if (rp->status) 131993c284eeSAndrei Emeltchenko return; 132093c284eeSAndrei Emeltchenko 132193c284eeSAndrei Emeltchenko amp_write_rem_assoc_continue(hdev, rp->phy_handle); 132293c284eeSAndrei Emeltchenko } 132393c284eeSAndrei Emeltchenko 13245ae76a94SAndrzej Kaczmarek static void hci_cc_read_rssi(struct hci_dev *hdev, struct sk_buff *skb) 13255ae76a94SAndrzej Kaczmarek { 13265ae76a94SAndrzej Kaczmarek struct hci_rp_read_rssi *rp = (void *) skb->data; 13275ae76a94SAndrzej Kaczmarek struct hci_conn *conn; 13285ae76a94SAndrzej Kaczmarek 13295ae76a94SAndrzej Kaczmarek BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 13305ae76a94SAndrzej Kaczmarek 13315ae76a94SAndrzej Kaczmarek if (rp->status) 13325ae76a94SAndrzej Kaczmarek return; 13335ae76a94SAndrzej Kaczmarek 13345ae76a94SAndrzej Kaczmarek hci_dev_lock(hdev); 13355ae76a94SAndrzej Kaczmarek 13365ae76a94SAndrzej Kaczmarek conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 13375ae76a94SAndrzej Kaczmarek if (conn) 13385ae76a94SAndrzej Kaczmarek conn->rssi = rp->rssi; 13395ae76a94SAndrzej Kaczmarek 13405ae76a94SAndrzej Kaczmarek hci_dev_unlock(hdev); 13415ae76a94SAndrzej Kaczmarek } 13425ae76a94SAndrzej Kaczmarek 13435a134faeSAndrzej Kaczmarek static void hci_cc_read_tx_power(struct hci_dev *hdev, struct sk_buff *skb) 13445a134faeSAndrzej Kaczmarek { 13455a134faeSAndrzej Kaczmarek struct hci_cp_read_tx_power *sent; 13465a134faeSAndrzej Kaczmarek struct hci_rp_read_tx_power *rp = (void *) skb->data; 13475a134faeSAndrzej Kaczmarek struct hci_conn *conn; 13485a134faeSAndrzej Kaczmarek 13495a134faeSAndrzej Kaczmarek BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 13505a134faeSAndrzej Kaczmarek 13515a134faeSAndrzej Kaczmarek if (rp->status) 13525a134faeSAndrzej Kaczmarek return; 13535a134faeSAndrzej Kaczmarek 13545a134faeSAndrzej Kaczmarek sent = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER); 13555a134faeSAndrzej Kaczmarek if (!sent) 13565a134faeSAndrzej Kaczmarek return; 13575a134faeSAndrzej Kaczmarek 13585a134faeSAndrzej Kaczmarek hci_dev_lock(hdev); 13595a134faeSAndrzej Kaczmarek 13605a134faeSAndrzej Kaczmarek conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 1361d0455ed9SAndrzej Kaczmarek if (!conn) 1362d0455ed9SAndrzej Kaczmarek goto unlock; 13635a134faeSAndrzej Kaczmarek 1364d0455ed9SAndrzej Kaczmarek switch (sent->type) { 1365d0455ed9SAndrzej Kaczmarek case 0x00: 1366d0455ed9SAndrzej Kaczmarek conn->tx_power = rp->tx_power; 1367d0455ed9SAndrzej Kaczmarek break; 1368d0455ed9SAndrzej Kaczmarek case 0x01: 1369d0455ed9SAndrzej Kaczmarek conn->max_tx_power = rp->tx_power; 1370d0455ed9SAndrzej Kaczmarek break; 1371d0455ed9SAndrzej Kaczmarek } 1372d0455ed9SAndrzej Kaczmarek 1373d0455ed9SAndrzej Kaczmarek unlock: 13745a134faeSAndrzej Kaczmarek hci_dev_unlock(hdev); 13755a134faeSAndrzej Kaczmarek } 13765a134faeSAndrzej Kaczmarek 13776039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 1378a9de9248SMarcel Holtmann { 13799f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1380a9de9248SMarcel Holtmann 1381a9de9248SMarcel Holtmann if (status) { 1382a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 1383314b2381SJohan Hedberg return; 1384314b2381SJohan Hedberg } 1385314b2381SJohan Hedberg 138689352e7dSAndre Guedes set_bit(HCI_INQUIRY, &hdev->flags); 1387a9de9248SMarcel Holtmann } 1388a9de9248SMarcel Holtmann 13896039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 13901da177e4SLinus Torvalds { 1391a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 13921da177e4SLinus Torvalds struct hci_conn *conn; 13931da177e4SLinus Torvalds 13949f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1395a9de9248SMarcel Holtmann 1396a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 13971da177e4SLinus Torvalds if (!cp) 13981da177e4SLinus Torvalds return; 13991da177e4SLinus Torvalds 14001da177e4SLinus Torvalds hci_dev_lock(hdev); 14011da177e4SLinus Torvalds 14021da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 14031da177e4SLinus Torvalds 14046ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn); 14051da177e4SLinus Torvalds 14061da177e4SLinus Torvalds if (status) { 14071da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 14084c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 14091da177e4SLinus Torvalds conn->state = BT_CLOSED; 14101da177e4SLinus Torvalds hci_proto_connect_cfm(conn, status); 14111da177e4SLinus Torvalds hci_conn_del(conn); 14124c67bc74SMarcel Holtmann } else 14134c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 14141da177e4SLinus Torvalds } 14151da177e4SLinus Torvalds } else { 14161da177e4SLinus Torvalds if (!conn) { 1417a5c4e309SJohan Hedberg conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr, 1418a5c4e309SJohan Hedberg HCI_ROLE_MASTER); 1419a5c4e309SJohan Hedberg if (!conn) 1420893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 14211da177e4SLinus Torvalds } 14221da177e4SLinus Torvalds } 14231da177e4SLinus Torvalds 14241da177e4SLinus Torvalds hci_dev_unlock(hdev); 14251da177e4SLinus Torvalds } 14261da177e4SLinus Torvalds 1427a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 14281da177e4SLinus Torvalds { 1429a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 14301da177e4SLinus Torvalds struct hci_conn *acl, *sco; 14311da177e4SLinus Torvalds __u16 handle; 14321da177e4SLinus Torvalds 14339f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1434b6a0dc82SMarcel Holtmann 1435a9de9248SMarcel Holtmann if (!status) 1436a9de9248SMarcel Holtmann return; 1437a9de9248SMarcel Holtmann 1438a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 14391da177e4SLinus Torvalds if (!cp) 1440a9de9248SMarcel Holtmann return; 14411da177e4SLinus Torvalds 14421da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 14431da177e4SLinus Torvalds 14449f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, handle); 14451da177e4SLinus Torvalds 14461da177e4SLinus Torvalds hci_dev_lock(hdev); 14471da177e4SLinus Torvalds 14481da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 14495a08ecceSAndrei Emeltchenko if (acl) { 14505a08ecceSAndrei Emeltchenko sco = acl->link; 14515a08ecceSAndrei Emeltchenko if (sco) { 14521da177e4SLinus Torvalds sco->state = BT_CLOSED; 14531da177e4SLinus Torvalds 14541da177e4SLinus Torvalds hci_proto_connect_cfm(sco, status); 14551da177e4SLinus Torvalds hci_conn_del(sco); 14561da177e4SLinus Torvalds } 14575a08ecceSAndrei Emeltchenko } 14581da177e4SLinus Torvalds 14591da177e4SLinus Torvalds hci_dev_unlock(hdev); 14601da177e4SLinus Torvalds } 14611da177e4SLinus Torvalds 1462f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 1463f8558555SMarcel Holtmann { 1464f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 1465f8558555SMarcel Holtmann struct hci_conn *conn; 1466f8558555SMarcel Holtmann 14679f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1468f8558555SMarcel Holtmann 1469f8558555SMarcel Holtmann if (!status) 1470f8558555SMarcel Holtmann return; 1471f8558555SMarcel Holtmann 1472f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 1473f8558555SMarcel Holtmann if (!cp) 1474f8558555SMarcel Holtmann return; 1475f8558555SMarcel Holtmann 1476f8558555SMarcel Holtmann hci_dev_lock(hdev); 1477f8558555SMarcel Holtmann 1478f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1479f8558555SMarcel Holtmann if (conn) { 1480f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1481f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 148276a68ba0SDavid Herrmann hci_conn_drop(conn); 1483f8558555SMarcel Holtmann } 1484f8558555SMarcel Holtmann } 1485f8558555SMarcel Holtmann 1486f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1487f8558555SMarcel Holtmann } 1488f8558555SMarcel Holtmann 1489f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 1490f8558555SMarcel Holtmann { 1491f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 1492f8558555SMarcel Holtmann struct hci_conn *conn; 1493f8558555SMarcel Holtmann 14949f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1495f8558555SMarcel Holtmann 1496f8558555SMarcel Holtmann if (!status) 1497f8558555SMarcel Holtmann return; 1498f8558555SMarcel Holtmann 1499f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 1500f8558555SMarcel Holtmann if (!cp) 1501f8558555SMarcel Holtmann return; 1502f8558555SMarcel Holtmann 1503f8558555SMarcel Holtmann hci_dev_lock(hdev); 1504f8558555SMarcel Holtmann 1505f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1506f8558555SMarcel Holtmann if (conn) { 1507f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1508f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 150976a68ba0SDavid Herrmann hci_conn_drop(conn); 1510f8558555SMarcel Holtmann } 1511f8558555SMarcel Holtmann } 1512f8558555SMarcel Holtmann 1513f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1514f8558555SMarcel Holtmann } 1515f8558555SMarcel Holtmann 1516127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev, 1517392599b9SJohan Hedberg struct hci_conn *conn) 1518392599b9SJohan Hedberg { 1519392599b9SJohan Hedberg if (conn->state != BT_CONFIG || !conn->out) 1520392599b9SJohan Hedberg return 0; 1521392599b9SJohan Hedberg 1522765c2a96SJohan Hedberg if (conn->pending_sec_level == BT_SECURITY_SDP) 1523392599b9SJohan Hedberg return 0; 1524392599b9SJohan Hedberg 1525392599b9SJohan Hedberg /* Only request authentication for SSP connections or non-SSP 1526264b8b4eSJohan Hedberg * devices with sec_level MEDIUM or HIGH or if MITM protection 1527264b8b4eSJohan Hedberg * is requested. 1528264b8b4eSJohan Hedberg */ 1529807deac2SGustavo Padovan if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) && 15307e3691e1SJohan Hedberg conn->pending_sec_level != BT_SECURITY_FIPS && 1531264b8b4eSJohan Hedberg conn->pending_sec_level != BT_SECURITY_HIGH && 1532264b8b4eSJohan Hedberg conn->pending_sec_level != BT_SECURITY_MEDIUM) 1533392599b9SJohan Hedberg return 0; 1534392599b9SJohan Hedberg 1535392599b9SJohan Hedberg return 1; 1536392599b9SJohan Hedberg } 1537392599b9SJohan Hedberg 15386039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev, 153900abfe44SGustavo F. Padovan struct inquiry_entry *e) 154030dc78e1SJohan Hedberg { 154130dc78e1SJohan Hedberg struct hci_cp_remote_name_req cp; 154230dc78e1SJohan Hedberg 154330dc78e1SJohan Hedberg memset(&cp, 0, sizeof(cp)); 154430dc78e1SJohan Hedberg 154530dc78e1SJohan Hedberg bacpy(&cp.bdaddr, &e->data.bdaddr); 154630dc78e1SJohan Hedberg cp.pscan_rep_mode = e->data.pscan_rep_mode; 154730dc78e1SJohan Hedberg cp.pscan_mode = e->data.pscan_mode; 154830dc78e1SJohan Hedberg cp.clock_offset = e->data.clock_offset; 154930dc78e1SJohan Hedberg 155030dc78e1SJohan Hedberg return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 155130dc78e1SJohan Hedberg } 155230dc78e1SJohan Hedberg 1553b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev) 155430dc78e1SJohan Hedberg { 155530dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 155630dc78e1SJohan Hedberg struct inquiry_entry *e; 155730dc78e1SJohan Hedberg 1558b644ba33SJohan Hedberg if (list_empty(&discov->resolve)) 1559b644ba33SJohan Hedberg return false; 1560b644ba33SJohan Hedberg 1561b644ba33SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 1562c810089cSRam Malovany if (!e) 1563c810089cSRam Malovany return false; 1564c810089cSRam Malovany 1565b644ba33SJohan Hedberg if (hci_resolve_name(hdev, e) == 0) { 1566b644ba33SJohan Hedberg e->name_state = NAME_PENDING; 1567b644ba33SJohan Hedberg return true; 1568b644ba33SJohan Hedberg } 1569b644ba33SJohan Hedberg 1570b644ba33SJohan Hedberg return false; 1571b644ba33SJohan Hedberg } 1572b644ba33SJohan Hedberg 1573b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn, 1574b644ba33SJohan Hedberg bdaddr_t *bdaddr, u8 *name, u8 name_len) 1575b644ba33SJohan Hedberg { 1576b644ba33SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 1577b644ba33SJohan Hedberg struct inquiry_entry *e; 1578b644ba33SJohan Hedberg 1579b644ba33SJohan Hedberg if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 158004124681SGustavo F. Padovan mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name, 158104124681SGustavo F. Padovan name_len, conn->dev_class); 1582b644ba33SJohan Hedberg 1583b644ba33SJohan Hedberg if (discov->state == DISCOVERY_STOPPED) 1584b644ba33SJohan Hedberg return; 1585b644ba33SJohan Hedberg 158630dc78e1SJohan Hedberg if (discov->state == DISCOVERY_STOPPING) 158730dc78e1SJohan Hedberg goto discov_complete; 158830dc78e1SJohan Hedberg 158930dc78e1SJohan Hedberg if (discov->state != DISCOVERY_RESOLVING) 159030dc78e1SJohan Hedberg return; 159130dc78e1SJohan Hedberg 159230dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING); 15937cc8380eSRam Malovany /* If the device was not found in a list of found devices names of which 15947cc8380eSRam Malovany * are pending. there is no need to continue resolving a next name as it 15957cc8380eSRam Malovany * will be done upon receiving another Remote Name Request Complete 15967cc8380eSRam Malovany * Event */ 15977cc8380eSRam Malovany if (!e) 15987cc8380eSRam Malovany return; 15997cc8380eSRam Malovany 160030dc78e1SJohan Hedberg list_del(&e->list); 16017cc8380eSRam Malovany if (name) { 16027cc8380eSRam Malovany e->name_state = NAME_KNOWN; 1603b644ba33SJohan Hedberg mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, 1604b644ba33SJohan Hedberg e->data.rssi, name, name_len); 1605c3e7c0d9SRam Malovany } else { 1606c3e7c0d9SRam Malovany e->name_state = NAME_NOT_KNOWN; 160730dc78e1SJohan Hedberg } 160830dc78e1SJohan Hedberg 1609b644ba33SJohan Hedberg if (hci_resolve_next_name(hdev)) 161030dc78e1SJohan Hedberg return; 161130dc78e1SJohan Hedberg 161230dc78e1SJohan Hedberg discov_complete: 161330dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 161430dc78e1SJohan Hedberg } 161530dc78e1SJohan Hedberg 1616a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 16171da177e4SLinus Torvalds { 1618127178d2SJohan Hedberg struct hci_cp_remote_name_req *cp; 1619127178d2SJohan Hedberg struct hci_conn *conn; 1620127178d2SJohan Hedberg 16219f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1622127178d2SJohan Hedberg 1623127178d2SJohan Hedberg /* If successful wait for the name req complete event before 1624127178d2SJohan Hedberg * checking for the need to do authentication */ 1625127178d2SJohan Hedberg if (!status) 1626127178d2SJohan Hedberg return; 1627127178d2SJohan Hedberg 1628127178d2SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); 1629127178d2SJohan Hedberg if (!cp) 1630127178d2SJohan Hedberg return; 1631127178d2SJohan Hedberg 1632127178d2SJohan Hedberg hci_dev_lock(hdev); 1633127178d2SJohan Hedberg 1634127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 1635b644ba33SJohan Hedberg 1636b644ba33SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1637b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0); 1638b644ba33SJohan Hedberg 163979c6c70cSJohan Hedberg if (!conn) 164079c6c70cSJohan Hedberg goto unlock; 164179c6c70cSJohan Hedberg 164279c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 164379c6c70cSJohan Hedberg goto unlock; 164479c6c70cSJohan Hedberg 164551a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 1646c1f23a2bSJohannes Berg struct hci_cp_auth_requested auth_cp; 1647c1f23a2bSJohannes Berg 1648977f8fceSJohan Hedberg set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags); 1649977f8fceSJohan Hedberg 1650c1f23a2bSJohannes Berg auth_cp.handle = __cpu_to_le16(conn->handle); 1651c1f23a2bSJohannes Berg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, 1652c1f23a2bSJohannes Berg sizeof(auth_cp), &auth_cp); 1653127178d2SJohan Hedberg } 1654127178d2SJohan Hedberg 165579c6c70cSJohan Hedberg unlock: 1656127178d2SJohan Hedberg hci_dev_unlock(hdev); 1657a9de9248SMarcel Holtmann } 16581da177e4SLinus Torvalds 1659769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 1660769be974SMarcel Holtmann { 1661769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 1662769be974SMarcel Holtmann struct hci_conn *conn; 1663769be974SMarcel Holtmann 16649f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1665769be974SMarcel Holtmann 1666769be974SMarcel Holtmann if (!status) 1667769be974SMarcel Holtmann return; 1668769be974SMarcel Holtmann 1669769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 1670769be974SMarcel Holtmann if (!cp) 1671769be974SMarcel Holtmann return; 1672769be974SMarcel Holtmann 1673769be974SMarcel Holtmann hci_dev_lock(hdev); 1674769be974SMarcel Holtmann 1675769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1676769be974SMarcel Holtmann if (conn) { 1677769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1678769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 167976a68ba0SDavid Herrmann hci_conn_drop(conn); 1680769be974SMarcel Holtmann } 1681769be974SMarcel Holtmann } 1682769be974SMarcel Holtmann 1683769be974SMarcel Holtmann hci_dev_unlock(hdev); 1684769be974SMarcel Holtmann } 1685769be974SMarcel Holtmann 1686769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 1687769be974SMarcel Holtmann { 1688769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features *cp; 1689769be974SMarcel Holtmann struct hci_conn *conn; 1690769be974SMarcel Holtmann 16919f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1692769be974SMarcel Holtmann 1693769be974SMarcel Holtmann if (!status) 1694769be974SMarcel Holtmann return; 1695769be974SMarcel Holtmann 1696769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 1697769be974SMarcel Holtmann if (!cp) 1698769be974SMarcel Holtmann return; 1699769be974SMarcel Holtmann 1700769be974SMarcel Holtmann hci_dev_lock(hdev); 1701769be974SMarcel Holtmann 1702769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1703769be974SMarcel Holtmann if (conn) { 1704769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1705769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 170676a68ba0SDavid Herrmann hci_conn_drop(conn); 1707769be974SMarcel Holtmann } 1708769be974SMarcel Holtmann } 1709769be974SMarcel Holtmann 1710769be974SMarcel Holtmann hci_dev_unlock(hdev); 1711769be974SMarcel Holtmann } 1712769be974SMarcel Holtmann 1713a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 1714a9de9248SMarcel Holtmann { 1715b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 1716b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 1717b6a0dc82SMarcel Holtmann __u16 handle; 1718b6a0dc82SMarcel Holtmann 17199f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1720b6a0dc82SMarcel Holtmann 1721b6a0dc82SMarcel Holtmann if (!status) 1722b6a0dc82SMarcel Holtmann return; 1723b6a0dc82SMarcel Holtmann 1724b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 1725b6a0dc82SMarcel Holtmann if (!cp) 1726b6a0dc82SMarcel Holtmann return; 1727b6a0dc82SMarcel Holtmann 1728b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 1729b6a0dc82SMarcel Holtmann 17309f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, handle); 1731b6a0dc82SMarcel Holtmann 1732b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 1733b6a0dc82SMarcel Holtmann 1734b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 17355a08ecceSAndrei Emeltchenko if (acl) { 17365a08ecceSAndrei Emeltchenko sco = acl->link; 17375a08ecceSAndrei Emeltchenko if (sco) { 1738b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 1739b6a0dc82SMarcel Holtmann 1740b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(sco, status); 1741b6a0dc82SMarcel Holtmann hci_conn_del(sco); 1742b6a0dc82SMarcel Holtmann } 17435a08ecceSAndrei Emeltchenko } 1744b6a0dc82SMarcel Holtmann 1745b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 1746a9de9248SMarcel Holtmann } 1747a9de9248SMarcel Holtmann 1748a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 1749a9de9248SMarcel Holtmann { 1750a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 175104837f64SMarcel Holtmann struct hci_conn *conn; 175204837f64SMarcel Holtmann 17539f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1754a9de9248SMarcel Holtmann 1755a9de9248SMarcel Holtmann if (!status) 1756a9de9248SMarcel Holtmann return; 1757a9de9248SMarcel Holtmann 1758a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 175904837f64SMarcel Holtmann if (!cp) 1760a9de9248SMarcel Holtmann return; 176104837f64SMarcel Holtmann 176204837f64SMarcel Holtmann hci_dev_lock(hdev); 176304837f64SMarcel Holtmann 176404837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1765e73439d8SMarcel Holtmann if (conn) { 176651a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 176704837f64SMarcel Holtmann 176851a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1769e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1770e73439d8SMarcel Holtmann } 1771e73439d8SMarcel Holtmann 177204837f64SMarcel Holtmann hci_dev_unlock(hdev); 177304837f64SMarcel Holtmann } 177404837f64SMarcel Holtmann 1775a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 1776a9de9248SMarcel Holtmann { 1777a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 177804837f64SMarcel Holtmann struct hci_conn *conn; 177904837f64SMarcel Holtmann 17809f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1781a9de9248SMarcel Holtmann 1782a9de9248SMarcel Holtmann if (!status) 1783a9de9248SMarcel Holtmann return; 1784a9de9248SMarcel Holtmann 1785a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 178604837f64SMarcel Holtmann if (!cp) 1787a9de9248SMarcel Holtmann return; 178804837f64SMarcel Holtmann 178904837f64SMarcel Holtmann hci_dev_lock(hdev); 179004837f64SMarcel Holtmann 179104837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1792e73439d8SMarcel Holtmann if (conn) { 179351a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 179404837f64SMarcel Holtmann 179551a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1796e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1797e73439d8SMarcel Holtmann } 1798e73439d8SMarcel Holtmann 179904837f64SMarcel Holtmann hci_dev_unlock(hdev); 180004837f64SMarcel Holtmann } 180104837f64SMarcel Holtmann 180288c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) 180388c3df13SJohan Hedberg { 180488c3df13SJohan Hedberg struct hci_cp_disconnect *cp; 180588c3df13SJohan Hedberg struct hci_conn *conn; 180688c3df13SJohan Hedberg 180788c3df13SJohan Hedberg if (!status) 180888c3df13SJohan Hedberg return; 180988c3df13SJohan Hedberg 181088c3df13SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT); 181188c3df13SJohan Hedberg if (!cp) 181288c3df13SJohan Hedberg return; 181388c3df13SJohan Hedberg 181488c3df13SJohan Hedberg hci_dev_lock(hdev); 181588c3df13SJohan Hedberg 181688c3df13SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 181788c3df13SJohan Hedberg if (conn) 181888c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 181988c3df13SJohan Hedberg conn->dst_type, status); 182088c3df13SJohan Hedberg 182188c3df13SJohan Hedberg hci_dev_unlock(hdev); 182288c3df13SJohan Hedberg } 182388c3df13SJohan Hedberg 1824a02226d6SAndrei Emeltchenko static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status) 1825a02226d6SAndrei Emeltchenko { 182693c284eeSAndrei Emeltchenko struct hci_cp_create_phy_link *cp; 182793c284eeSAndrei Emeltchenko 1828a02226d6SAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 182993c284eeSAndrei Emeltchenko 183093c284eeSAndrei Emeltchenko cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK); 183193c284eeSAndrei Emeltchenko if (!cp) 183293c284eeSAndrei Emeltchenko return; 183393c284eeSAndrei Emeltchenko 1834e58917b9SAndrei Emeltchenko hci_dev_lock(hdev); 1835e58917b9SAndrei Emeltchenko 1836e58917b9SAndrei Emeltchenko if (status) { 1837e58917b9SAndrei Emeltchenko struct hci_conn *hcon; 1838e58917b9SAndrei Emeltchenko 1839e58917b9SAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle); 1840e58917b9SAndrei Emeltchenko if (hcon) 1841e58917b9SAndrei Emeltchenko hci_conn_del(hcon); 1842e58917b9SAndrei Emeltchenko } else { 184393c284eeSAndrei Emeltchenko amp_write_remote_assoc(hdev, cp->phy_handle); 1844a02226d6SAndrei Emeltchenko } 1845a02226d6SAndrei Emeltchenko 1846e58917b9SAndrei Emeltchenko hci_dev_unlock(hdev); 1847e58917b9SAndrei Emeltchenko } 1848e58917b9SAndrei Emeltchenko 18490b26ab9dSAndrei Emeltchenko static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status) 18500b26ab9dSAndrei Emeltchenko { 18510b26ab9dSAndrei Emeltchenko struct hci_cp_accept_phy_link *cp; 18520b26ab9dSAndrei Emeltchenko 18530b26ab9dSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 18540b26ab9dSAndrei Emeltchenko 18550b26ab9dSAndrei Emeltchenko if (status) 18560b26ab9dSAndrei Emeltchenko return; 18570b26ab9dSAndrei Emeltchenko 18580b26ab9dSAndrei Emeltchenko cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK); 18590b26ab9dSAndrei Emeltchenko if (!cp) 18600b26ab9dSAndrei Emeltchenko return; 18610b26ab9dSAndrei Emeltchenko 18620b26ab9dSAndrei Emeltchenko amp_write_remote_assoc(hdev, cp->phy_handle); 18630b26ab9dSAndrei Emeltchenko } 18640b26ab9dSAndrei Emeltchenko 1865cb1d68f7SJohan Hedberg static void hci_cs_le_create_conn(struct hci_dev *hdev, u8 status) 1866cb1d68f7SJohan Hedberg { 1867cb1d68f7SJohan Hedberg struct hci_cp_le_create_conn *cp; 1868cb1d68f7SJohan Hedberg struct hci_conn *conn; 1869cb1d68f7SJohan Hedberg 1870cb1d68f7SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 1871cb1d68f7SJohan Hedberg 1872cb1d68f7SJohan Hedberg /* All connection failure handling is taken care of by the 1873cb1d68f7SJohan Hedberg * hci_le_conn_failed function which is triggered by the HCI 1874cb1d68f7SJohan Hedberg * request completion callbacks used for connecting. 1875cb1d68f7SJohan Hedberg */ 1876cb1d68f7SJohan Hedberg if (status) 1877cb1d68f7SJohan Hedberg return; 1878cb1d68f7SJohan Hedberg 1879cb1d68f7SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN); 1880cb1d68f7SJohan Hedberg if (!cp) 1881cb1d68f7SJohan Hedberg return; 1882cb1d68f7SJohan Hedberg 1883cb1d68f7SJohan Hedberg hci_dev_lock(hdev); 1884cb1d68f7SJohan Hedberg 1885cb1d68f7SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr); 1886cb1d68f7SJohan Hedberg if (!conn) 1887cb1d68f7SJohan Hedberg goto unlock; 1888cb1d68f7SJohan Hedberg 1889cb1d68f7SJohan Hedberg /* Store the initiator and responder address information which 1890cb1d68f7SJohan Hedberg * is needed for SMP. These values will not change during the 1891cb1d68f7SJohan Hedberg * lifetime of the connection. 1892cb1d68f7SJohan Hedberg */ 1893cb1d68f7SJohan Hedberg conn->init_addr_type = cp->own_address_type; 1894cb1d68f7SJohan Hedberg if (cp->own_address_type == ADDR_LE_DEV_RANDOM) 1895cb1d68f7SJohan Hedberg bacpy(&conn->init_addr, &hdev->random_addr); 1896cb1d68f7SJohan Hedberg else 1897cb1d68f7SJohan Hedberg bacpy(&conn->init_addr, &hdev->bdaddr); 1898cb1d68f7SJohan Hedberg 1899cb1d68f7SJohan Hedberg conn->resp_addr_type = cp->peer_addr_type; 1900cb1d68f7SJohan Hedberg bacpy(&conn->resp_addr, &cp->peer_addr); 1901cb1d68f7SJohan Hedberg 19029489eca4SJohan Hedberg /* We don't want the connection attempt to stick around 19039489eca4SJohan Hedberg * indefinitely since LE doesn't have a page timeout concept 19049489eca4SJohan Hedberg * like BR/EDR. Set a timer for any connection that doesn't use 19059489eca4SJohan Hedberg * the white list for connecting. 19069489eca4SJohan Hedberg */ 19079489eca4SJohan Hedberg if (cp->filter_policy == HCI_LE_USE_PEER_ADDR) 19089489eca4SJohan Hedberg queue_delayed_work(conn->hdev->workqueue, 19099489eca4SJohan Hedberg &conn->le_conn_timeout, 191009ae260bSJohan Hedberg conn->conn_timeout); 19119489eca4SJohan Hedberg 1912cb1d68f7SJohan Hedberg unlock: 1913cb1d68f7SJohan Hedberg hci_dev_unlock(hdev); 1914cb1d68f7SJohan Hedberg } 1915cb1d68f7SJohan Hedberg 191681d0c8adSJohan Hedberg static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) 191781d0c8adSJohan Hedberg { 191881d0c8adSJohan Hedberg struct hci_cp_le_start_enc *cp; 191981d0c8adSJohan Hedberg struct hci_conn *conn; 192081d0c8adSJohan Hedberg 192181d0c8adSJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 192281d0c8adSJohan Hedberg 192381d0c8adSJohan Hedberg if (!status) 192481d0c8adSJohan Hedberg return; 192581d0c8adSJohan Hedberg 192681d0c8adSJohan Hedberg hci_dev_lock(hdev); 192781d0c8adSJohan Hedberg 192881d0c8adSJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_LE_START_ENC); 192981d0c8adSJohan Hedberg if (!cp) 193081d0c8adSJohan Hedberg goto unlock; 193181d0c8adSJohan Hedberg 193281d0c8adSJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 193381d0c8adSJohan Hedberg if (!conn) 193481d0c8adSJohan Hedberg goto unlock; 193581d0c8adSJohan Hedberg 193681d0c8adSJohan Hedberg if (conn->state != BT_CONNECTED) 193781d0c8adSJohan Hedberg goto unlock; 193881d0c8adSJohan Hedberg 193981d0c8adSJohan Hedberg hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); 194081d0c8adSJohan Hedberg hci_conn_drop(conn); 194181d0c8adSJohan Hedberg 194281d0c8adSJohan Hedberg unlock: 194381d0c8adSJohan Hedberg hci_dev_unlock(hdev); 194481d0c8adSJohan Hedberg } 194581d0c8adSJohan Hedberg 19466039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 19471da177e4SLinus Torvalds { 19481da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 194930dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 195030dc78e1SJohan Hedberg struct inquiry_entry *e; 19511da177e4SLinus Torvalds 19529f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 19531da177e4SLinus Torvalds 1954a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 195589352e7dSAndre Guedes 195689352e7dSAndre Guedes if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) 195789352e7dSAndre Guedes return; 195889352e7dSAndre Guedes 19594e857c58SPeter Zijlstra smp_mb__after_atomic(); /* wake_up_bit advises about this barrier */ 19603e13fa1eSAndre Guedes wake_up_bit(&hdev->flags, HCI_INQUIRY); 19613e13fa1eSAndre Guedes 1962a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 196330dc78e1SJohan Hedberg return; 196430dc78e1SJohan Hedberg 196556e5cb86SJohan Hedberg hci_dev_lock(hdev); 196630dc78e1SJohan Hedberg 1967343f935bSAndre Guedes if (discov->state != DISCOVERY_FINDING) 196830dc78e1SJohan Hedberg goto unlock; 196930dc78e1SJohan Hedberg 197030dc78e1SJohan Hedberg if (list_empty(&discov->resolve)) { 1971ff9ef578SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 197230dc78e1SJohan Hedberg goto unlock; 197330dc78e1SJohan Hedberg } 197430dc78e1SJohan Hedberg 197530dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 197630dc78e1SJohan Hedberg if (e && hci_resolve_name(hdev, e) == 0) { 197730dc78e1SJohan Hedberg e->name_state = NAME_PENDING; 197830dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_RESOLVING); 197930dc78e1SJohan Hedberg } else { 198030dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 198130dc78e1SJohan Hedberg } 198230dc78e1SJohan Hedberg 198330dc78e1SJohan Hedberg unlock: 198456e5cb86SJohan Hedberg hci_dev_unlock(hdev); 19851da177e4SLinus Torvalds } 19861da177e4SLinus Torvalds 19876039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 19881da177e4SLinus Torvalds { 198945bb4bf0SMarcel Holtmann struct inquiry_data data; 1990a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 19911da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 19921da177e4SLinus Torvalds 19931da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 19941da177e4SLinus Torvalds 199545bb4bf0SMarcel Holtmann if (!num_rsp) 199645bb4bf0SMarcel Holtmann return; 199745bb4bf0SMarcel Holtmann 19981519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 19991519cc17SAndre Guedes return; 20001519cc17SAndre Guedes 20011da177e4SLinus Torvalds hci_dev_lock(hdev); 200245bb4bf0SMarcel Holtmann 2003e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2004af58925cSMarcel Holtmann u32 flags; 20053175405bSJohan Hedberg 20061da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 20071da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 20081da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 20091da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 20101da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 20111da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 20121da177e4SLinus Torvalds data.rssi = 0x00; 201341a96212SMarcel Holtmann data.ssp_mode = 0x00; 20143175405bSJohan Hedberg 2015af58925cSMarcel Holtmann flags = hci_inquiry_cache_update(hdev, &data, false); 2016af58925cSMarcel Holtmann 201748264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2018af58925cSMarcel Holtmann info->dev_class, 0, flags, NULL, 0, NULL, 0); 20191da177e4SLinus Torvalds } 202045bb4bf0SMarcel Holtmann 20211da177e4SLinus Torvalds hci_dev_unlock(hdev); 20221da177e4SLinus Torvalds } 20231da177e4SLinus Torvalds 20246039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 20251da177e4SLinus Torvalds { 2026a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 2027a9de9248SMarcel Holtmann struct hci_conn *conn; 20281da177e4SLinus Torvalds 2029a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 203045bb4bf0SMarcel Holtmann 20311da177e4SLinus Torvalds hci_dev_lock(hdev); 203245bb4bf0SMarcel Holtmann 2033a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 20349499237aSMarcel Holtmann if (!conn) { 20359499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 20369499237aSMarcel Holtmann goto unlock; 20379499237aSMarcel Holtmann 20389499237aSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 2039a9de9248SMarcel Holtmann if (!conn) 2040a9de9248SMarcel Holtmann goto unlock; 204145bb4bf0SMarcel Holtmann 20429499237aSMarcel Holtmann conn->type = SCO_LINK; 20439499237aSMarcel Holtmann } 20449499237aSMarcel Holtmann 2045a9de9248SMarcel Holtmann if (!ev->status) { 2046a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 2047769be974SMarcel Holtmann 2048769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 2049769be974SMarcel Holtmann conn->state = BT_CONFIG; 2050769be974SMarcel Holtmann hci_conn_hold(conn); 2051a9ea3ed9SSzymon Janc 2052a9ea3ed9SSzymon Janc if (!conn->out && !hci_conn_ssp_enabled(conn) && 2053a9ea3ed9SSzymon Janc !hci_find_link_key(hdev, &ev->bdaddr)) 2054a9ea3ed9SSzymon Janc conn->disc_timeout = HCI_PAIRING_TIMEOUT; 2055a9ea3ed9SSzymon Janc else 2056052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2057769be974SMarcel Holtmann } else 2058a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 2059a9de9248SMarcel Holtmann 20607d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 20617d0db0a3SMarcel Holtmann 2062a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 20634dae2798SJohan Hedberg set_bit(HCI_CONN_AUTH, &conn->flags); 2064a9de9248SMarcel Holtmann 2065a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 20664dae2798SJohan Hedberg set_bit(HCI_CONN_ENCRYPT, &conn->flags); 2067a9de9248SMarcel Holtmann 2068a9de9248SMarcel Holtmann /* Get remote features */ 2069a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 2070a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 2071a9de9248SMarcel Holtmann cp.handle = ev->handle; 2072769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 2073769be974SMarcel Holtmann sizeof(cp), &cp); 207445bb4bf0SMarcel Holtmann } 2075a9de9248SMarcel Holtmann 2076a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 2077d095c1ebSAndrei Emeltchenko if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) { 2078a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 2079a9de9248SMarcel Holtmann cp.handle = ev->handle; 2080a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 208104124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp), 208204124681SGustavo F. Padovan &cp); 2083a9de9248SMarcel Holtmann } 208417d5c04cSJohan Hedberg } else { 2085a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 208617d5c04cSJohan Hedberg if (conn->type == ACL_LINK) 208764c7b77cSMarcel Holtmann mgmt_connect_failed(hdev, &conn->dst, conn->type, 208848264f06SJohan Hedberg conn->dst_type, ev->status); 208917d5c04cSJohan Hedberg } 209045bb4bf0SMarcel Holtmann 2091e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 2092e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 209345bb4bf0SMarcel Holtmann 2094769be974SMarcel Holtmann if (ev->status) { 2095a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2096a9de9248SMarcel Holtmann hci_conn_del(conn); 2097c89b6e6bSMarcel Holtmann } else if (ev->link_type != ACL_LINK) 2098c89b6e6bSMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2099a9de9248SMarcel Holtmann 2100a9de9248SMarcel Holtmann unlock: 21011da177e4SLinus Torvalds hci_dev_unlock(hdev); 2102a9de9248SMarcel Holtmann 2103a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 21041da177e4SLinus Torvalds } 21051da177e4SLinus Torvalds 210670c46425SJohan Hedberg static void hci_reject_conn(struct hci_dev *hdev, bdaddr_t *bdaddr) 210770c46425SJohan Hedberg { 210870c46425SJohan Hedberg struct hci_cp_reject_conn_req cp; 210970c46425SJohan Hedberg 211070c46425SJohan Hedberg bacpy(&cp.bdaddr, bdaddr); 211170c46425SJohan Hedberg cp.reason = HCI_ERROR_REJ_BAD_ADDR; 211270c46425SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 211370c46425SJohan Hedberg } 211470c46425SJohan Hedberg 21156039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 21161da177e4SLinus Torvalds { 2117a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 21181da177e4SLinus Torvalds int mask = hdev->link_mode; 211970c46425SJohan Hedberg struct inquiry_entry *ie; 212070c46425SJohan Hedberg struct hci_conn *conn; 212120714bfeSFrédéric Dalleau __u8 flags = 0; 21221da177e4SLinus Torvalds 21236ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr, 2124807deac2SGustavo Padovan ev->link_type); 21251da177e4SLinus Torvalds 212620714bfeSFrédéric Dalleau mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type, 212720714bfeSFrédéric Dalleau &flags); 21281da177e4SLinus Torvalds 212970c46425SJohan Hedberg if (!(mask & HCI_LM_ACCEPT)) { 213070c46425SJohan Hedberg hci_reject_conn(hdev, &ev->bdaddr); 213170c46425SJohan Hedberg return; 213270c46425SJohan Hedberg } 213370c46425SJohan Hedberg 2134a55bd29dSJohan Hedberg if (hci_bdaddr_list_lookup(&hdev->blacklist, &ev->bdaddr, 2135dcc36c16SJohan Hedberg BDADDR_BREDR)) { 213670c46425SJohan Hedberg hci_reject_conn(hdev, &ev->bdaddr); 213770c46425SJohan Hedberg return; 213870c46425SJohan Hedberg } 213946c4c941SJohan Hedberg 214046c4c941SJohan Hedberg if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags) && 214146c4c941SJohan Hedberg !hci_bdaddr_list_lookup(&hdev->whitelist, &ev->bdaddr, 2142a55bd29dSJohan Hedberg BDADDR_BREDR)) { 2143a55bd29dSJohan Hedberg hci_reject_conn(hdev, &ev->bdaddr); 2144a55bd29dSJohan Hedberg return; 2145a55bd29dSJohan Hedberg } 214670c46425SJohan Hedberg 21471da177e4SLinus Torvalds /* Connection accepted */ 21481da177e4SLinus Torvalds 21491da177e4SLinus Torvalds hci_dev_lock(hdev); 2150b6a0dc82SMarcel Holtmann 2151cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2152cc11b9c1SAndrei Emeltchenko if (ie) 2153c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 2154c7bdd502SMarcel Holtmann 21558fc9ced3SGustavo Padovan conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, 21568fc9ced3SGustavo Padovan &ev->bdaddr); 21571da177e4SLinus Torvalds if (!conn) { 2158a5c4e309SJohan Hedberg conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr, 2159a5c4e309SJohan Hedberg HCI_ROLE_SLAVE); 2160cc11b9c1SAndrei Emeltchenko if (!conn) { 2161893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 21621da177e4SLinus Torvalds hci_dev_unlock(hdev); 21631da177e4SLinus Torvalds return; 21641da177e4SLinus Torvalds } 21651da177e4SLinus Torvalds } 2166b6a0dc82SMarcel Holtmann 21671da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 2168b6a0dc82SMarcel Holtmann 21691da177e4SLinus Torvalds hci_dev_unlock(hdev); 21701da177e4SLinus Torvalds 217120714bfeSFrédéric Dalleau if (ev->link_type == ACL_LINK || 217220714bfeSFrédéric Dalleau (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) { 2173b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 217420714bfeSFrédéric Dalleau conn->state = BT_CONNECT; 2175b6a0dc82SMarcel Holtmann 21761da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 21771da177e4SLinus Torvalds 21781da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 21791da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 21801da177e4SLinus Torvalds else 21811da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 21821da177e4SLinus Torvalds 218370c46425SJohan Hedberg hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp); 218420714bfeSFrédéric Dalleau } else if (!(flags & HCI_PROTO_DEFER)) { 2185b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 218620714bfeSFrédéric Dalleau conn->state = BT_CONNECT; 2187b6a0dc82SMarcel Holtmann 2188b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 2189a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 2190b6a0dc82SMarcel Holtmann 2191dcf4adbfSJoe Perches cp.tx_bandwidth = cpu_to_le32(0x00001f40); 2192dcf4adbfSJoe Perches cp.rx_bandwidth = cpu_to_le32(0x00001f40); 2193dcf4adbfSJoe Perches cp.max_latency = cpu_to_le16(0xffff); 2194b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 2195b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 2196b6a0dc82SMarcel Holtmann 219770c46425SJohan Hedberg hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, sizeof(cp), 219870c46425SJohan Hedberg &cp); 219920714bfeSFrédéric Dalleau } else { 220020714bfeSFrédéric Dalleau conn->state = BT_CONNECT2; 220120714bfeSFrédéric Dalleau hci_proto_connect_cfm(conn, 0); 2202b6a0dc82SMarcel Holtmann } 22031da177e4SLinus Torvalds } 22041da177e4SLinus Torvalds 2205f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err) 2206f0d6a0eaSMikel Astiz { 2207f0d6a0eaSMikel Astiz switch (err) { 2208f0d6a0eaSMikel Astiz case HCI_ERROR_CONNECTION_TIMEOUT: 2209f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_TIMEOUT; 2210f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_USER_TERM: 2211f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_LOW_RESOURCES: 2212f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_POWER_OFF: 2213f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_REMOTE; 2214f0d6a0eaSMikel Astiz case HCI_ERROR_LOCAL_HOST_TERM: 2215f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_LOCAL_HOST; 2216f0d6a0eaSMikel Astiz default: 2217f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_UNKNOWN; 2218f0d6a0eaSMikel Astiz } 2219f0d6a0eaSMikel Astiz } 2220f0d6a0eaSMikel Astiz 22216039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 22221da177e4SLinus Torvalds { 2223a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 2224abf54a50SAndre Guedes u8 reason = hci_to_mgmt_reason(ev->reason); 22259fcb18efSAndre Guedes struct hci_conn_params *params; 222604837f64SMarcel Holtmann struct hci_conn *conn; 222712d4a3b2SJohan Hedberg bool mgmt_connected; 22283846220bSAndre Guedes u8 type; 22291da177e4SLinus Torvalds 22309f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 22311da177e4SLinus Torvalds 22321da177e4SLinus Torvalds hci_dev_lock(hdev); 22331da177e4SLinus Torvalds 223404837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2235f7520543SJohan Hedberg if (!conn) 2236f7520543SJohan Hedberg goto unlock; 2237f7520543SJohan Hedberg 2238f0d6a0eaSMikel Astiz if (ev->status) { 223988c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 224088c3df13SJohan Hedberg conn->dst_type, ev->status); 2241abf54a50SAndre Guedes goto unlock; 2242abf54a50SAndre Guedes } 2243f0d6a0eaSMikel Astiz 22443846220bSAndre Guedes conn->state = BT_CLOSED; 22453846220bSAndre Guedes 224612d4a3b2SJohan Hedberg mgmt_connected = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags); 224712d4a3b2SJohan Hedberg mgmt_device_disconnected(hdev, &conn->dst, conn->type, conn->dst_type, 224812d4a3b2SJohan Hedberg reason, mgmt_connected); 2249f7520543SJohan Hedberg 2250af6a9c32SJohan Hedberg if (conn->type == ACL_LINK && 2251af6a9c32SJohan Hedberg test_bit(HCI_CONN_FLUSH_KEY, &conn->flags)) 22526ec5bcadSVishal Agarwal hci_remove_link_key(hdev, &conn->dst); 22533846220bSAndre Guedes 22549fcb18efSAndre Guedes params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type); 22559fcb18efSAndre Guedes if (params) { 22569fcb18efSAndre Guedes switch (params->auto_connect) { 22579fcb18efSAndre Guedes case HCI_AUTO_CONN_LINK_LOSS: 22589fcb18efSAndre Guedes if (ev->reason != HCI_ERROR_CONNECTION_TIMEOUT) 22599fcb18efSAndre Guedes break; 22609fcb18efSAndre Guedes /* Fall through */ 22619fcb18efSAndre Guedes 22624b9e7e75SMarcel Holtmann case HCI_AUTO_CONN_DIRECT: 22639fcb18efSAndre Guedes case HCI_AUTO_CONN_ALWAYS: 2264418025d1SJohan Hedberg list_del_init(¶ms->action); 2265418025d1SJohan Hedberg list_add(¶ms->action, &hdev->pend_le_conns); 2266418025d1SJohan Hedberg hci_update_background_scan(hdev); 22679fcb18efSAndre Guedes break; 22689fcb18efSAndre Guedes 22699fcb18efSAndre Guedes default: 22709fcb18efSAndre Guedes break; 22719fcb18efSAndre Guedes } 22729fcb18efSAndre Guedes } 22739fcb18efSAndre Guedes 22743846220bSAndre Guedes type = conn->type; 22753846220bSAndre Guedes 22762950f21aSMarcel Holtmann hci_proto_disconn_cfm(conn, ev->reason); 22771da177e4SLinus Torvalds hci_conn_del(conn); 22782210246cSJohan Hedberg 22792210246cSJohan Hedberg /* Re-enable advertising if necessary, since it might 22802210246cSJohan Hedberg * have been disabled by the connection. From the 22812210246cSJohan Hedberg * HCI_LE_Set_Advertise_Enable command description in 22822210246cSJohan Hedberg * the core specification (v4.0): 22832210246cSJohan Hedberg * "The Controller shall continue advertising until the Host 22842210246cSJohan Hedberg * issues an LE_Set_Advertise_Enable command with 22852210246cSJohan Hedberg * Advertising_Enable set to 0x00 (Advertising is disabled) 22862210246cSJohan Hedberg * or until a connection is created or until the Advertising 22872210246cSJohan Hedberg * is timed out due to Directed Advertising." 22882210246cSJohan Hedberg */ 22892210246cSJohan Hedberg if (type == LE_LINK) 22905976e608SMarcel Holtmann mgmt_reenable_advertising(hdev); 22911da177e4SLinus Torvalds 2292f7520543SJohan Hedberg unlock: 22931da177e4SLinus Torvalds hci_dev_unlock(hdev); 22941da177e4SLinus Torvalds } 22951da177e4SLinus Torvalds 22966039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2297a9de9248SMarcel Holtmann { 2298a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 2299a9de9248SMarcel Holtmann struct hci_conn *conn; 2300a9de9248SMarcel Holtmann 23019f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2302a9de9248SMarcel Holtmann 2303a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2304a9de9248SMarcel Holtmann 2305a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2306d7556e20SWaldemar Rymarkiewicz if (!conn) 2307d7556e20SWaldemar Rymarkiewicz goto unlock; 2308d7556e20SWaldemar Rymarkiewicz 2309765c2a96SJohan Hedberg if (!ev->status) { 2310aa64a8b5SJohan Hedberg if (!hci_conn_ssp_enabled(conn) && 231151a8efd7SJohan Hedberg test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) { 2312d7556e20SWaldemar Rymarkiewicz BT_INFO("re-auth of legacy device is not possible."); 231319f8def0SWaldemar Rymarkiewicz } else { 23144dae2798SJohan Hedberg set_bit(HCI_CONN_AUTH, &conn->flags); 2315765c2a96SJohan Hedberg conn->sec_level = conn->pending_sec_level; 231619f8def0SWaldemar Rymarkiewicz } 23172a611692SJohan Hedberg } else { 2318bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 2319bab73cb6SJohan Hedberg ev->status); 23202a611692SJohan Hedberg } 2321a9de9248SMarcel Holtmann 232251a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 232351a8efd7SJohan Hedberg clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags); 2324a9de9248SMarcel Holtmann 2325f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 2326aa64a8b5SJohan Hedberg if (!ev->status && hci_conn_ssp_enabled(conn)) { 2327f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 2328f8558555SMarcel Holtmann cp.handle = ev->handle; 2329f8558555SMarcel Holtmann cp.encrypt = 0x01; 2330d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 2331d7556e20SWaldemar Rymarkiewicz &cp); 2332f8558555SMarcel Holtmann } else { 2333f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 2334f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 233576a68ba0SDavid Herrmann hci_conn_drop(conn); 2336f8558555SMarcel Holtmann } 2337052b30b0SMarcel Holtmann } else { 2338a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 2339a9de9248SMarcel Holtmann 2340052b30b0SMarcel Holtmann hci_conn_hold(conn); 2341052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 234276a68ba0SDavid Herrmann hci_conn_drop(conn); 2343052b30b0SMarcel Holtmann } 2344052b30b0SMarcel Holtmann 234551a8efd7SJohan Hedberg if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) { 2346a9de9248SMarcel Holtmann if (!ev->status) { 2347a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 2348f8558555SMarcel Holtmann cp.handle = ev->handle; 2349f8558555SMarcel Holtmann cp.encrypt = 0x01; 2350d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 2351d7556e20SWaldemar Rymarkiewicz &cp); 2352a9de9248SMarcel Holtmann } else { 235351a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 2354a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 2355a9de9248SMarcel Holtmann } 2356a9de9248SMarcel Holtmann } 2357a9de9248SMarcel Holtmann 2358d7556e20SWaldemar Rymarkiewicz unlock: 2359a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2360a9de9248SMarcel Holtmann } 2361a9de9248SMarcel Holtmann 23626039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 2363a9de9248SMarcel Holtmann { 2364127178d2SJohan Hedberg struct hci_ev_remote_name *ev = (void *) skb->data; 2365127178d2SJohan Hedberg struct hci_conn *conn; 2366127178d2SJohan Hedberg 2367a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2368a9de9248SMarcel Holtmann 2369a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 2370127178d2SJohan Hedberg 2371127178d2SJohan Hedberg hci_dev_lock(hdev); 2372127178d2SJohan Hedberg 2373127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2374b644ba33SJohan Hedberg 2375b644ba33SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 2376b644ba33SJohan Hedberg goto check_auth; 2377b644ba33SJohan Hedberg 2378b644ba33SJohan Hedberg if (ev->status == 0) 2379b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name, 2380b644ba33SJohan Hedberg strnlen(ev->name, HCI_MAX_NAME_LENGTH)); 2381b644ba33SJohan Hedberg else 2382b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0); 2383b644ba33SJohan Hedberg 2384b644ba33SJohan Hedberg check_auth: 238579c6c70cSJohan Hedberg if (!conn) 238679c6c70cSJohan Hedberg goto unlock; 238779c6c70cSJohan Hedberg 238879c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 238979c6c70cSJohan Hedberg goto unlock; 239079c6c70cSJohan Hedberg 239151a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 2392127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 2393977f8fceSJohan Hedberg 2394977f8fceSJohan Hedberg set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags); 2395977f8fceSJohan Hedberg 2396127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 2397127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 2398127178d2SJohan Hedberg } 2399127178d2SJohan Hedberg 240079c6c70cSJohan Hedberg unlock: 2401127178d2SJohan Hedberg hci_dev_unlock(hdev); 2402a9de9248SMarcel Holtmann } 2403a9de9248SMarcel Holtmann 24046039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2405a9de9248SMarcel Holtmann { 2406a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 2407a9de9248SMarcel Holtmann struct hci_conn *conn; 2408a9de9248SMarcel Holtmann 24099f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2410a9de9248SMarcel Holtmann 2411a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2412a9de9248SMarcel Holtmann 2413a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2414dc8357ccSMarcel Holtmann if (!conn) 2415dc8357ccSMarcel Holtmann goto unlock; 2416dc8357ccSMarcel Holtmann 2417a9de9248SMarcel Holtmann if (!ev->status) { 2418ae293196SMarcel Holtmann if (ev->encrypt) { 2419ae293196SMarcel Holtmann /* Encryption implies authentication */ 24204dae2798SJohan Hedberg set_bit(HCI_CONN_AUTH, &conn->flags); 24214dae2798SJohan Hedberg set_bit(HCI_CONN_ENCRYPT, &conn->flags); 2422da85e5e5SVinicius Costa Gomes conn->sec_level = conn->pending_sec_level; 2423abf76badSMarcel Holtmann 2424914a6ffeSMarcel Holtmann /* P-256 authentication key implies FIPS */ 2425914a6ffeSMarcel Holtmann if (conn->key_type == HCI_LK_AUTH_COMBINATION_P256) 24264dae2798SJohan Hedberg set_bit(HCI_CONN_FIPS, &conn->flags); 2427914a6ffeSMarcel Holtmann 2428abf76badSMarcel Holtmann if ((conn->type == ACL_LINK && ev->encrypt == 0x02) || 2429abf76badSMarcel Holtmann conn->type == LE_LINK) 2430abf76badSMarcel Holtmann set_bit(HCI_CONN_AES_CCM, &conn->flags); 2431abf76badSMarcel Holtmann } else { 24324dae2798SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT, &conn->flags); 2433abf76badSMarcel Holtmann clear_bit(HCI_CONN_AES_CCM, &conn->flags); 2434abf76badSMarcel Holtmann } 2435a9de9248SMarcel Holtmann } 2436a9de9248SMarcel Holtmann 243751a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 2438a9de9248SMarcel Holtmann 2439a7d7723aSGustavo Padovan if (ev->status && conn->state == BT_CONNECTED) { 2440bed71748SAndre Guedes hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); 244176a68ba0SDavid Herrmann hci_conn_drop(conn); 2442a7d7723aSGustavo Padovan goto unlock; 2443a7d7723aSGustavo Padovan } 2444a7d7723aSGustavo Padovan 2445f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 2446f8558555SMarcel Holtmann if (!ev->status) 2447f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 2448f8558555SMarcel Holtmann 244940b552aaSMarcel Holtmann /* In Secure Connections Only mode, do not allow any 245040b552aaSMarcel Holtmann * connections that are not encrypted with AES-CCM 245140b552aaSMarcel Holtmann * using a P-256 authenticated combination key. 245240b552aaSMarcel Holtmann */ 245340b552aaSMarcel Holtmann if (test_bit(HCI_SC_ONLY, &hdev->dev_flags) && 245440b552aaSMarcel Holtmann (!test_bit(HCI_CONN_AES_CCM, &conn->flags) || 245540b552aaSMarcel Holtmann conn->key_type != HCI_LK_AUTH_COMBINATION_P256)) { 245640b552aaSMarcel Holtmann hci_proto_connect_cfm(conn, HCI_ERROR_AUTH_FAILURE); 245740b552aaSMarcel Holtmann hci_conn_drop(conn); 245840b552aaSMarcel Holtmann goto unlock; 245940b552aaSMarcel Holtmann } 246040b552aaSMarcel Holtmann 2461f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 246276a68ba0SDavid Herrmann hci_conn_drop(conn); 2463f8558555SMarcel Holtmann } else 2464a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 2465a9de9248SMarcel Holtmann 2466a7d7723aSGustavo Padovan unlock: 2467a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2468a9de9248SMarcel Holtmann } 2469a9de9248SMarcel Holtmann 24706039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev, 2471807deac2SGustavo Padovan struct sk_buff *skb) 2472a9de9248SMarcel Holtmann { 2473a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 2474a9de9248SMarcel Holtmann struct hci_conn *conn; 2475a9de9248SMarcel Holtmann 24769f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2477a9de9248SMarcel Holtmann 2478a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2479a9de9248SMarcel Holtmann 2480a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2481a9de9248SMarcel Holtmann if (conn) { 2482a9de9248SMarcel Holtmann if (!ev->status) 24834dae2798SJohan Hedberg set_bit(HCI_CONN_SECURE, &conn->flags); 2484a9de9248SMarcel Holtmann 248551a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 2486a9de9248SMarcel Holtmann 2487a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 2488a9de9248SMarcel Holtmann } 2489a9de9248SMarcel Holtmann 2490a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2491a9de9248SMarcel Holtmann } 2492a9de9248SMarcel Holtmann 24936039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev, 2494807deac2SGustavo Padovan struct sk_buff *skb) 2495a9de9248SMarcel Holtmann { 2496a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 2497a9de9248SMarcel Holtmann struct hci_conn *conn; 2498a9de9248SMarcel Holtmann 24999f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2500a9de9248SMarcel Holtmann 2501a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2502a9de9248SMarcel Holtmann 2503a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2504ccd556feSJohan Hedberg if (!conn) 2505ccd556feSJohan Hedberg goto unlock; 2506ccd556feSJohan Hedberg 2507769be974SMarcel Holtmann if (!ev->status) 2508cad718edSJohan Hedberg memcpy(conn->features[0], ev->features, 8); 2509a9de9248SMarcel Holtmann 2510ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2511ccd556feSJohan Hedberg goto unlock; 2512ccd556feSJohan Hedberg 2513ccd556feSJohan Hedberg if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { 2514769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 2515769be974SMarcel Holtmann cp.handle = ev->handle; 2516769be974SMarcel Holtmann cp.page = 0x01; 2517ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 2518769be974SMarcel Holtmann sizeof(cp), &cp); 2519392599b9SJohan Hedberg goto unlock; 2520392599b9SJohan Hedberg } 2521392599b9SJohan Hedberg 2522671267bfSJohan Hedberg if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { 2523127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2524127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2525127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2526127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2527127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2528b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 2529b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 253008c79b61SJohan Hedberg conn->dst_type, 0, NULL, 0, 2531b644ba33SJohan Hedberg conn->dev_class); 2532392599b9SJohan Hedberg 2533127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2534769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2535769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 253676a68ba0SDavid Herrmann hci_conn_drop(conn); 2537769be974SMarcel Holtmann } 2538769be974SMarcel Holtmann 2539ccd556feSJohan Hedberg unlock: 2540a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2541a9de9248SMarcel Holtmann } 2542a9de9248SMarcel Holtmann 25436039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2544a9de9248SMarcel Holtmann { 2545a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 25469238f36aSJohan Hedberg u8 status = skb->data[sizeof(*ev)]; 2547a9de9248SMarcel Holtmann __u16 opcode; 2548a9de9248SMarcel Holtmann 2549a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2550a9de9248SMarcel Holtmann 2551a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2552a9de9248SMarcel Holtmann 2553a9de9248SMarcel Holtmann switch (opcode) { 2554a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 2555a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 2556a9de9248SMarcel Holtmann break; 2557a9de9248SMarcel Holtmann 25584d93483bSAndre Guedes case HCI_OP_PERIODIC_INQ: 25594d93483bSAndre Guedes hci_cc_periodic_inq(hdev, skb); 25604d93483bSAndre Guedes break; 25614d93483bSAndre Guedes 2562a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 2563a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 2564a9de9248SMarcel Holtmann break; 2565a9de9248SMarcel Holtmann 2566a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 2567a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 2568a9de9248SMarcel Holtmann break; 2569a9de9248SMarcel Holtmann 2570a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 2571a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 2572a9de9248SMarcel Holtmann break; 2573a9de9248SMarcel Holtmann 2574e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 2575e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 2576e4e8e37cSMarcel Holtmann break; 2577e4e8e37cSMarcel Holtmann 2578a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 2579a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 2580a9de9248SMarcel Holtmann break; 2581a9de9248SMarcel Holtmann 2582e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 2583e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 2584e4e8e37cSMarcel Holtmann break; 2585e4e8e37cSMarcel Holtmann 2586e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 2587e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 2588e4e8e37cSMarcel Holtmann break; 2589e4e8e37cSMarcel Holtmann 2590a9de9248SMarcel Holtmann case HCI_OP_RESET: 2591a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 2592a9de9248SMarcel Holtmann break; 2593a9de9248SMarcel Holtmann 2594a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 2595a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 2596a9de9248SMarcel Holtmann break; 2597a9de9248SMarcel Holtmann 2598a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 2599a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 2600a9de9248SMarcel Holtmann break; 2601a9de9248SMarcel Holtmann 2602a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 2603a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 2604a9de9248SMarcel Holtmann break; 2605a9de9248SMarcel Holtmann 2606a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 2607a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 2608a9de9248SMarcel Holtmann break; 2609a9de9248SMarcel Holtmann 2610a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 2611a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 2612a9de9248SMarcel Holtmann break; 2613a9de9248SMarcel Holtmann 2614a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 2615a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 2616a9de9248SMarcel Holtmann break; 2617a9de9248SMarcel Holtmann 2618a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 2619a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 2620a9de9248SMarcel Holtmann break; 2621a9de9248SMarcel Holtmann 2622a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 2623a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 2624a9de9248SMarcel Holtmann break; 2625a9de9248SMarcel Holtmann 2626a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 2627a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 2628a9de9248SMarcel Holtmann break; 2629a9de9248SMarcel Holtmann 2630b4cb9fb2SMarcel Holtmann case HCI_OP_READ_NUM_SUPPORTED_IAC: 2631b4cb9fb2SMarcel Holtmann hci_cc_read_num_supported_iac(hdev, skb); 2632b4cb9fb2SMarcel Holtmann break; 2633b4cb9fb2SMarcel Holtmann 2634333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 2635333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 2636333140b5SMarcel Holtmann break; 2637333140b5SMarcel Holtmann 2638eac83dc6SMarcel Holtmann case HCI_OP_WRITE_SC_SUPPORT: 2639eac83dc6SMarcel Holtmann hci_cc_write_sc_support(hdev, skb); 2640eac83dc6SMarcel Holtmann break; 2641eac83dc6SMarcel Holtmann 2642a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 2643a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 2644a9de9248SMarcel Holtmann break; 2645a9de9248SMarcel Holtmann 2646a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 2647a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 2648a9de9248SMarcel Holtmann break; 2649a9de9248SMarcel Holtmann 2650a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 2651a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 2652a9de9248SMarcel Holtmann break; 2653a9de9248SMarcel Holtmann 2654971e3a4bSAndre Guedes case HCI_OP_READ_LOCAL_EXT_FEATURES: 2655971e3a4bSAndre Guedes hci_cc_read_local_ext_features(hdev, skb); 2656971e3a4bSAndre Guedes break; 2657971e3a4bSAndre Guedes 2658a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 2659a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 2660a9de9248SMarcel Holtmann break; 2661a9de9248SMarcel Holtmann 2662a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 2663a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 2664a9de9248SMarcel Holtmann break; 2665a9de9248SMarcel Holtmann 2666f332ec66SJohan Hedberg case HCI_OP_READ_PAGE_SCAN_ACTIVITY: 2667f332ec66SJohan Hedberg hci_cc_read_page_scan_activity(hdev, skb); 2668f332ec66SJohan Hedberg break; 2669f332ec66SJohan Hedberg 26704a3ee763SJohan Hedberg case HCI_OP_WRITE_PAGE_SCAN_ACTIVITY: 26714a3ee763SJohan Hedberg hci_cc_write_page_scan_activity(hdev, skb); 26724a3ee763SJohan Hedberg break; 26734a3ee763SJohan Hedberg 2674f332ec66SJohan Hedberg case HCI_OP_READ_PAGE_SCAN_TYPE: 2675f332ec66SJohan Hedberg hci_cc_read_page_scan_type(hdev, skb); 2676f332ec66SJohan Hedberg break; 2677f332ec66SJohan Hedberg 26784a3ee763SJohan Hedberg case HCI_OP_WRITE_PAGE_SCAN_TYPE: 26794a3ee763SJohan Hedberg hci_cc_write_page_scan_type(hdev, skb); 26804a3ee763SJohan Hedberg break; 26814a3ee763SJohan Hedberg 2682350ee4cfSAndrei Emeltchenko case HCI_OP_READ_DATA_BLOCK_SIZE: 2683350ee4cfSAndrei Emeltchenko hci_cc_read_data_block_size(hdev, skb); 2684350ee4cfSAndrei Emeltchenko break; 2685350ee4cfSAndrei Emeltchenko 26861e89cffbSAndrei Emeltchenko case HCI_OP_READ_FLOW_CONTROL_MODE: 26871e89cffbSAndrei Emeltchenko hci_cc_read_flow_control_mode(hdev, skb); 26881e89cffbSAndrei Emeltchenko break; 26891e89cffbSAndrei Emeltchenko 2690928abaa7SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_INFO: 2691928abaa7SAndrei Emeltchenko hci_cc_read_local_amp_info(hdev, skb); 2692928abaa7SAndrei Emeltchenko break; 2693928abaa7SAndrei Emeltchenko 269433f35721SJohan Hedberg case HCI_OP_READ_CLOCK: 269533f35721SJohan Hedberg hci_cc_read_clock(hdev, skb); 269633f35721SJohan Hedberg break; 269733f35721SJohan Hedberg 2698903e4541SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_ASSOC: 2699903e4541SAndrei Emeltchenko hci_cc_read_local_amp_assoc(hdev, skb); 2700903e4541SAndrei Emeltchenko break; 2701903e4541SAndrei Emeltchenko 2702d5859e22SJohan Hedberg case HCI_OP_READ_INQ_RSP_TX_POWER: 2703d5859e22SJohan Hedberg hci_cc_read_inq_rsp_tx_power(hdev, skb); 2704d5859e22SJohan Hedberg break; 2705d5859e22SJohan Hedberg 2706980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_REPLY: 2707980e1a53SJohan Hedberg hci_cc_pin_code_reply(hdev, skb); 2708980e1a53SJohan Hedberg break; 2709980e1a53SJohan Hedberg 2710980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_NEG_REPLY: 2711980e1a53SJohan Hedberg hci_cc_pin_code_neg_reply(hdev, skb); 2712980e1a53SJohan Hedberg break; 2713980e1a53SJohan Hedberg 2714c35938b2SSzymon Janc case HCI_OP_READ_LOCAL_OOB_DATA: 27154d2d2796SMarcel Holtmann hci_cc_read_local_oob_data(hdev, skb); 27164d2d2796SMarcel Holtmann break; 27174d2d2796SMarcel Holtmann 27184d2d2796SMarcel Holtmann case HCI_OP_READ_LOCAL_OOB_EXT_DATA: 27194d2d2796SMarcel Holtmann hci_cc_read_local_oob_ext_data(hdev, skb); 2720c35938b2SSzymon Janc break; 2721c35938b2SSzymon Janc 27226ed58ec5SVille Tervo case HCI_OP_LE_READ_BUFFER_SIZE: 27236ed58ec5SVille Tervo hci_cc_le_read_buffer_size(hdev, skb); 27246ed58ec5SVille Tervo break; 27256ed58ec5SVille Tervo 272660e77321SJohan Hedberg case HCI_OP_LE_READ_LOCAL_FEATURES: 272760e77321SJohan Hedberg hci_cc_le_read_local_features(hdev, skb); 272860e77321SJohan Hedberg break; 272960e77321SJohan Hedberg 27308fa19098SJohan Hedberg case HCI_OP_LE_READ_ADV_TX_POWER: 27318fa19098SJohan Hedberg hci_cc_le_read_adv_tx_power(hdev, skb); 27328fa19098SJohan Hedberg break; 27338fa19098SJohan Hedberg 2734a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_REPLY: 2735a5c29683SJohan Hedberg hci_cc_user_confirm_reply(hdev, skb); 2736a5c29683SJohan Hedberg break; 2737a5c29683SJohan Hedberg 2738a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_NEG_REPLY: 2739a5c29683SJohan Hedberg hci_cc_user_confirm_neg_reply(hdev, skb); 2740a5c29683SJohan Hedberg break; 2741a5c29683SJohan Hedberg 27421143d458SBrian Gix case HCI_OP_USER_PASSKEY_REPLY: 27431143d458SBrian Gix hci_cc_user_passkey_reply(hdev, skb); 27441143d458SBrian Gix break; 27451143d458SBrian Gix 27461143d458SBrian Gix case HCI_OP_USER_PASSKEY_NEG_REPLY: 27471143d458SBrian Gix hci_cc_user_passkey_neg_reply(hdev, skb); 274816cde993SSzymon Janc break; 274907f7fa5dSAndre Guedes 27507a4cd51dSMarcel Holtmann case HCI_OP_LE_SET_RANDOM_ADDR: 27517a4cd51dSMarcel Holtmann hci_cc_le_set_random_addr(hdev, skb); 27527a4cd51dSMarcel Holtmann break; 27537a4cd51dSMarcel Holtmann 2754c1d5dc4aSJohan Hedberg case HCI_OP_LE_SET_ADV_ENABLE: 2755c1d5dc4aSJohan Hedberg hci_cc_le_set_adv_enable(hdev, skb); 2756c1d5dc4aSJohan Hedberg break; 2757c1d5dc4aSJohan Hedberg 2758533553f8SMarcel Holtmann case HCI_OP_LE_SET_SCAN_PARAM: 2759533553f8SMarcel Holtmann hci_cc_le_set_scan_param(hdev, skb); 2760533553f8SMarcel Holtmann break; 2761533553f8SMarcel Holtmann 2762eb9d91f5SAndre Guedes case HCI_OP_LE_SET_SCAN_ENABLE: 2763eb9d91f5SAndre Guedes hci_cc_le_set_scan_enable(hdev, skb); 2764eb9d91f5SAndre Guedes break; 2765eb9d91f5SAndre Guedes 2766cf1d081fSJohan Hedberg case HCI_OP_LE_READ_WHITE_LIST_SIZE: 2767cf1d081fSJohan Hedberg hci_cc_le_read_white_list_size(hdev, skb); 2768cf1d081fSJohan Hedberg break; 2769cf1d081fSJohan Hedberg 27700f36b589SMarcel Holtmann case HCI_OP_LE_CLEAR_WHITE_LIST: 27710f36b589SMarcel Holtmann hci_cc_le_clear_white_list(hdev, skb); 27720f36b589SMarcel Holtmann break; 27730f36b589SMarcel Holtmann 27740f36b589SMarcel Holtmann case HCI_OP_LE_ADD_TO_WHITE_LIST: 27750f36b589SMarcel Holtmann hci_cc_le_add_to_white_list(hdev, skb); 27760f36b589SMarcel Holtmann break; 27770f36b589SMarcel Holtmann 27780f36b589SMarcel Holtmann case HCI_OP_LE_DEL_FROM_WHITE_LIST: 27790f36b589SMarcel Holtmann hci_cc_le_del_from_white_list(hdev, skb); 27800f36b589SMarcel Holtmann break; 27810f36b589SMarcel Holtmann 27829b008c04SJohan Hedberg case HCI_OP_LE_READ_SUPPORTED_STATES: 27839b008c04SJohan Hedberg hci_cc_le_read_supported_states(hdev, skb); 27849b008c04SJohan Hedberg break; 27859b008c04SJohan Hedberg 2786f9b49306SAndre Guedes case HCI_OP_WRITE_LE_HOST_SUPPORTED: 2787f9b49306SAndre Guedes hci_cc_write_le_host_supported(hdev, skb); 2788f9b49306SAndre Guedes break; 2789f9b49306SAndre Guedes 279056ed2cb8SJohan Hedberg case HCI_OP_LE_SET_ADV_PARAM: 279156ed2cb8SJohan Hedberg hci_cc_set_adv_param(hdev, skb); 279256ed2cb8SJohan Hedberg break; 279356ed2cb8SJohan Hedberg 279493c284eeSAndrei Emeltchenko case HCI_OP_WRITE_REMOTE_AMP_ASSOC: 279593c284eeSAndrei Emeltchenko hci_cc_write_remote_amp_assoc(hdev, skb); 279693c284eeSAndrei Emeltchenko break; 279793c284eeSAndrei Emeltchenko 27985ae76a94SAndrzej Kaczmarek case HCI_OP_READ_RSSI: 27995ae76a94SAndrzej Kaczmarek hci_cc_read_rssi(hdev, skb); 28005ae76a94SAndrzej Kaczmarek break; 28015ae76a94SAndrzej Kaczmarek 28025a134faeSAndrzej Kaczmarek case HCI_OP_READ_TX_POWER: 28035a134faeSAndrzej Kaczmarek hci_cc_read_tx_power(hdev, skb); 28045a134faeSAndrzej Kaczmarek break; 28055a134faeSAndrzej Kaczmarek 2806a9de9248SMarcel Holtmann default: 28079f1db00cSAndrei Emeltchenko BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); 2808a9de9248SMarcel Holtmann break; 2809a9de9248SMarcel Holtmann } 2810a9de9248SMarcel Holtmann 2811ad82cdd1SJohan Hedberg if (opcode != HCI_OP_NOP) 281265cc2b49SMarcel Holtmann cancel_delayed_work(&hdev->cmd_timer); 28136bd32326SVille Tervo 2814ad82cdd1SJohan Hedberg hci_req_cmd_complete(hdev, opcode, status); 28159238f36aSJohan Hedberg 2816dbccd791SSzymon Janc if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2817a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2818a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2819c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2820a9de9248SMarcel Holtmann } 2821a9de9248SMarcel Holtmann } 2822a9de9248SMarcel Holtmann 28236039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 2824a9de9248SMarcel Holtmann { 2825a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 2826a9de9248SMarcel Holtmann __u16 opcode; 2827a9de9248SMarcel Holtmann 2828a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2829a9de9248SMarcel Holtmann 2830a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2831a9de9248SMarcel Holtmann 2832a9de9248SMarcel Holtmann switch (opcode) { 2833a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 2834a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 2835a9de9248SMarcel Holtmann break; 2836a9de9248SMarcel Holtmann 2837a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 2838a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 2839a9de9248SMarcel Holtmann break; 2840a9de9248SMarcel Holtmann 2841a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 2842a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 2843a9de9248SMarcel Holtmann break; 2844a9de9248SMarcel Holtmann 2845f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 2846f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 2847f8558555SMarcel Holtmann break; 2848f8558555SMarcel Holtmann 2849f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 2850f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 2851f8558555SMarcel Holtmann break; 2852f8558555SMarcel Holtmann 2853a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 2854a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 2855a9de9248SMarcel Holtmann break; 2856a9de9248SMarcel Holtmann 2857769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 2858769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 2859769be974SMarcel Holtmann break; 2860769be974SMarcel Holtmann 2861769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 2862769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 2863769be974SMarcel Holtmann break; 2864769be974SMarcel Holtmann 2865a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 2866a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 2867a9de9248SMarcel Holtmann break; 2868a9de9248SMarcel Holtmann 2869a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 2870a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 2871a9de9248SMarcel Holtmann break; 2872a9de9248SMarcel Holtmann 2873a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 2874a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 2875a9de9248SMarcel Holtmann break; 2876a9de9248SMarcel Holtmann 28778962ee74SJohan Hedberg case HCI_OP_DISCONNECT: 287888c3df13SJohan Hedberg hci_cs_disconnect(hdev, ev->status); 28798962ee74SJohan Hedberg break; 28808962ee74SJohan Hedberg 2881a02226d6SAndrei Emeltchenko case HCI_OP_CREATE_PHY_LINK: 2882a02226d6SAndrei Emeltchenko hci_cs_create_phylink(hdev, ev->status); 2883a02226d6SAndrei Emeltchenko break; 2884a02226d6SAndrei Emeltchenko 28850b26ab9dSAndrei Emeltchenko case HCI_OP_ACCEPT_PHY_LINK: 28860b26ab9dSAndrei Emeltchenko hci_cs_accept_phylink(hdev, ev->status); 28870b26ab9dSAndrei Emeltchenko break; 28880b26ab9dSAndrei Emeltchenko 2889cb1d68f7SJohan Hedberg case HCI_OP_LE_CREATE_CONN: 2890cb1d68f7SJohan Hedberg hci_cs_le_create_conn(hdev, ev->status); 2891cb1d68f7SJohan Hedberg break; 2892cb1d68f7SJohan Hedberg 289381d0c8adSJohan Hedberg case HCI_OP_LE_START_ENC: 289481d0c8adSJohan Hedberg hci_cs_le_start_enc(hdev, ev->status); 289581d0c8adSJohan Hedberg break; 289681d0c8adSJohan Hedberg 2897a9de9248SMarcel Holtmann default: 28989f1db00cSAndrei Emeltchenko BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); 2899a9de9248SMarcel Holtmann break; 2900a9de9248SMarcel Holtmann } 2901a9de9248SMarcel Holtmann 2902ad82cdd1SJohan Hedberg if (opcode != HCI_OP_NOP) 290365cc2b49SMarcel Holtmann cancel_delayed_work(&hdev->cmd_timer); 29046bd32326SVille Tervo 290502350a72SJohan Hedberg if (ev->status || 290602350a72SJohan Hedberg (hdev->sent_cmd && !bt_cb(hdev->sent_cmd)->req.event)) 290733720450SAndre Guedes hci_req_cmd_complete(hdev, opcode, ev->status); 29089238f36aSJohan Hedberg 290910572132SGustavo F. Padovan if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2910a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2911a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2912c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2913a9de9248SMarcel Holtmann } 2914a9de9248SMarcel Holtmann } 2915a9de9248SMarcel Holtmann 29166039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2917a9de9248SMarcel Holtmann { 2918a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 2919a9de9248SMarcel Holtmann struct hci_conn *conn; 2920a9de9248SMarcel Holtmann 29219f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2922a9de9248SMarcel Holtmann 2923a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2924a9de9248SMarcel Holtmann 2925a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2926a9de9248SMarcel Holtmann if (conn) { 292740bef302SJohan Hedberg if (!ev->status) 292840bef302SJohan Hedberg conn->role = ev->role; 2929a9de9248SMarcel Holtmann 293051a8efd7SJohan Hedberg clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); 2931a9de9248SMarcel Holtmann 2932a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 2933a9de9248SMarcel Holtmann } 2934a9de9248SMarcel Holtmann 2935a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2936a9de9248SMarcel Holtmann } 2937a9de9248SMarcel Holtmann 29386039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 29391da177e4SLinus Torvalds { 2940a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 29411da177e4SLinus Torvalds int i; 29421da177e4SLinus Torvalds 294332ac5b9bSAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) { 294432ac5b9bSAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 294532ac5b9bSAndrei Emeltchenko return; 294632ac5b9bSAndrei Emeltchenko } 294732ac5b9bSAndrei Emeltchenko 2948c5993de8SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 2949c5993de8SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_pkts_info)) { 29501da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 29511da177e4SLinus Torvalds return; 29521da177e4SLinus Torvalds } 29531da177e4SLinus Torvalds 2954c5993de8SAndrei Emeltchenko BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 2955c5993de8SAndrei Emeltchenko 2956613a1c0cSAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 2957613a1c0cSAndrei Emeltchenko struct hci_comp_pkts_info *info = &ev->handles[i]; 29581da177e4SLinus Torvalds struct hci_conn *conn; 29591da177e4SLinus Torvalds __u16 handle, count; 29601da177e4SLinus Torvalds 2961613a1c0cSAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 2962613a1c0cSAndrei Emeltchenko count = __le16_to_cpu(info->count); 29631da177e4SLinus Torvalds 29641da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 2965f4280918SAndrei Emeltchenko if (!conn) 2966f4280918SAndrei Emeltchenko continue; 2967f4280918SAndrei Emeltchenko 29681da177e4SLinus Torvalds conn->sent -= count; 29691da177e4SLinus Torvalds 2970f4280918SAndrei Emeltchenko switch (conn->type) { 2971f4280918SAndrei Emeltchenko case ACL_LINK: 297270f23020SAndrei Emeltchenko hdev->acl_cnt += count; 297370f23020SAndrei Emeltchenko if (hdev->acl_cnt > hdev->acl_pkts) 29741da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 2975f4280918SAndrei Emeltchenko break; 2976f4280918SAndrei Emeltchenko 2977f4280918SAndrei Emeltchenko case LE_LINK: 29786ed58ec5SVille Tervo if (hdev->le_pkts) { 29796ed58ec5SVille Tervo hdev->le_cnt += count; 29806ed58ec5SVille Tervo if (hdev->le_cnt > hdev->le_pkts) 29816ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 29826ed58ec5SVille Tervo } else { 29836ed58ec5SVille Tervo hdev->acl_cnt += count; 29846ed58ec5SVille Tervo if (hdev->acl_cnt > hdev->acl_pkts) 29856ed58ec5SVille Tervo hdev->acl_cnt = hdev->acl_pkts; 29866ed58ec5SVille Tervo } 2987f4280918SAndrei Emeltchenko break; 2988f4280918SAndrei Emeltchenko 2989f4280918SAndrei Emeltchenko case SCO_LINK: 299070f23020SAndrei Emeltchenko hdev->sco_cnt += count; 299170f23020SAndrei Emeltchenko if (hdev->sco_cnt > hdev->sco_pkts) 29925b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 2993f4280918SAndrei Emeltchenko break; 2994f4280918SAndrei Emeltchenko 2995f4280918SAndrei Emeltchenko default: 2996f4280918SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 2997f4280918SAndrei Emeltchenko break; 29981da177e4SLinus Torvalds } 29991da177e4SLinus Torvalds } 3000a9de9248SMarcel Holtmann 30013eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 30021da177e4SLinus Torvalds } 30031da177e4SLinus Torvalds 300476ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev, 300576ef7cf7SAndrei Emeltchenko __u16 handle) 300676ef7cf7SAndrei Emeltchenko { 300776ef7cf7SAndrei Emeltchenko struct hci_chan *chan; 300876ef7cf7SAndrei Emeltchenko 300976ef7cf7SAndrei Emeltchenko switch (hdev->dev_type) { 301076ef7cf7SAndrei Emeltchenko case HCI_BREDR: 301176ef7cf7SAndrei Emeltchenko return hci_conn_hash_lookup_handle(hdev, handle); 301276ef7cf7SAndrei Emeltchenko case HCI_AMP: 301376ef7cf7SAndrei Emeltchenko chan = hci_chan_lookup_handle(hdev, handle); 301476ef7cf7SAndrei Emeltchenko if (chan) 301576ef7cf7SAndrei Emeltchenko return chan->conn; 301676ef7cf7SAndrei Emeltchenko break; 301776ef7cf7SAndrei Emeltchenko default: 301876ef7cf7SAndrei Emeltchenko BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type); 301976ef7cf7SAndrei Emeltchenko break; 302076ef7cf7SAndrei Emeltchenko } 302176ef7cf7SAndrei Emeltchenko 302276ef7cf7SAndrei Emeltchenko return NULL; 302376ef7cf7SAndrei Emeltchenko } 302476ef7cf7SAndrei Emeltchenko 30256039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb) 302625e89e99SAndrei Emeltchenko { 302725e89e99SAndrei Emeltchenko struct hci_ev_num_comp_blocks *ev = (void *) skb->data; 302825e89e99SAndrei Emeltchenko int i; 302925e89e99SAndrei Emeltchenko 303025e89e99SAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) { 303125e89e99SAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 303225e89e99SAndrei Emeltchenko return; 303325e89e99SAndrei Emeltchenko } 303425e89e99SAndrei Emeltchenko 303525e89e99SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 303625e89e99SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_blocks_info)) { 303725e89e99SAndrei Emeltchenko BT_DBG("%s bad parameters", hdev->name); 303825e89e99SAndrei Emeltchenko return; 303925e89e99SAndrei Emeltchenko } 304025e89e99SAndrei Emeltchenko 304125e89e99SAndrei Emeltchenko BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks, 304225e89e99SAndrei Emeltchenko ev->num_hndl); 304325e89e99SAndrei Emeltchenko 304425e89e99SAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 304525e89e99SAndrei Emeltchenko struct hci_comp_blocks_info *info = &ev->handles[i]; 304676ef7cf7SAndrei Emeltchenko struct hci_conn *conn = NULL; 304725e89e99SAndrei Emeltchenko __u16 handle, block_count; 304825e89e99SAndrei Emeltchenko 304925e89e99SAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 305025e89e99SAndrei Emeltchenko block_count = __le16_to_cpu(info->blocks); 305125e89e99SAndrei Emeltchenko 305276ef7cf7SAndrei Emeltchenko conn = __hci_conn_lookup_handle(hdev, handle); 305325e89e99SAndrei Emeltchenko if (!conn) 305425e89e99SAndrei Emeltchenko continue; 305525e89e99SAndrei Emeltchenko 305625e89e99SAndrei Emeltchenko conn->sent -= block_count; 305725e89e99SAndrei Emeltchenko 305825e89e99SAndrei Emeltchenko switch (conn->type) { 305925e89e99SAndrei Emeltchenko case ACL_LINK: 3060bd1eb66bSAndrei Emeltchenko case AMP_LINK: 306125e89e99SAndrei Emeltchenko hdev->block_cnt += block_count; 306225e89e99SAndrei Emeltchenko if (hdev->block_cnt > hdev->num_blocks) 306325e89e99SAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 306425e89e99SAndrei Emeltchenko break; 306525e89e99SAndrei Emeltchenko 306625e89e99SAndrei Emeltchenko default: 306725e89e99SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 306825e89e99SAndrei Emeltchenko break; 306925e89e99SAndrei Emeltchenko } 307025e89e99SAndrei Emeltchenko } 307125e89e99SAndrei Emeltchenko 307225e89e99SAndrei Emeltchenko queue_work(hdev->workqueue, &hdev->tx_work); 307325e89e99SAndrei Emeltchenko } 307425e89e99SAndrei Emeltchenko 30756039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 30761da177e4SLinus Torvalds { 3077a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 307804837f64SMarcel Holtmann struct hci_conn *conn; 30791da177e4SLinus Torvalds 30809f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 30811da177e4SLinus Torvalds 30821da177e4SLinus Torvalds hci_dev_lock(hdev); 30831da177e4SLinus Torvalds 308404837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 308504837f64SMarcel Holtmann if (conn) { 308604837f64SMarcel Holtmann conn->mode = ev->mode; 308704837f64SMarcel Holtmann 30888fc9ced3SGustavo Padovan if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, 30898fc9ced3SGustavo Padovan &conn->flags)) { 309004837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 309158a681efSJohan Hedberg set_bit(HCI_CONN_POWER_SAVE, &conn->flags); 309204837f64SMarcel Holtmann else 309358a681efSJohan Hedberg clear_bit(HCI_CONN_POWER_SAVE, &conn->flags); 309404837f64SMarcel Holtmann } 3095e73439d8SMarcel Holtmann 309651a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 3097e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 309804837f64SMarcel Holtmann } 309904837f64SMarcel Holtmann 310004837f64SMarcel Holtmann hci_dev_unlock(hdev); 310104837f64SMarcel Holtmann } 310204837f64SMarcel Holtmann 31036039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 31041da177e4SLinus Torvalds { 3105052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 3106052b30b0SMarcel Holtmann struct hci_conn *conn; 3107052b30b0SMarcel Holtmann 3108a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 3109052b30b0SMarcel Holtmann 3110052b30b0SMarcel Holtmann hci_dev_lock(hdev); 3111052b30b0SMarcel Holtmann 3112052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 3113b6f98044SWaldemar Rymarkiewicz if (!conn) 3114b6f98044SWaldemar Rymarkiewicz goto unlock; 3115b6f98044SWaldemar Rymarkiewicz 3116b6f98044SWaldemar Rymarkiewicz if (conn->state == BT_CONNECTED) { 3117052b30b0SMarcel Holtmann hci_conn_hold(conn); 3118052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 311976a68ba0SDavid Herrmann hci_conn_drop(conn); 3120052b30b0SMarcel Holtmann } 3121052b30b0SMarcel Holtmann 3122b6ae8457SJohan Hedberg if (!test_bit(HCI_BONDABLE, &hdev->dev_flags) && 31232f407f0aSJohan Hedberg !test_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags)) { 312403b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 312503b555e1SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 31262f407f0aSJohan Hedberg } else if (test_bit(HCI_MGMT, &hdev->dev_flags)) { 3127a770bb5aSWaldemar Rymarkiewicz u8 secure; 3128a770bb5aSWaldemar Rymarkiewicz 3129a770bb5aSWaldemar Rymarkiewicz if (conn->pending_sec_level == BT_SECURITY_HIGH) 3130a770bb5aSWaldemar Rymarkiewicz secure = 1; 3131a770bb5aSWaldemar Rymarkiewicz else 3132a770bb5aSWaldemar Rymarkiewicz secure = 0; 3133a770bb5aSWaldemar Rymarkiewicz 3134744cf19eSJohan Hedberg mgmt_pin_code_request(hdev, &ev->bdaddr, secure); 3135a770bb5aSWaldemar Rymarkiewicz } 3136980e1a53SJohan Hedberg 3137b6f98044SWaldemar Rymarkiewicz unlock: 3138052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 31391da177e4SLinus Torvalds } 31401da177e4SLinus Torvalds 31416039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 31421da177e4SLinus Torvalds { 314355ed8ca1SJohan Hedberg struct hci_ev_link_key_req *ev = (void *) skb->data; 314455ed8ca1SJohan Hedberg struct hci_cp_link_key_reply cp; 314555ed8ca1SJohan Hedberg struct hci_conn *conn; 314655ed8ca1SJohan Hedberg struct link_key *key; 314755ed8ca1SJohan Hedberg 3148a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 314955ed8ca1SJohan Hedberg 3150034cbea0SAndrei Emeltchenko if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 315155ed8ca1SJohan Hedberg return; 315255ed8ca1SJohan Hedberg 315355ed8ca1SJohan Hedberg hci_dev_lock(hdev); 315455ed8ca1SJohan Hedberg 315555ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, &ev->bdaddr); 315655ed8ca1SJohan Hedberg if (!key) { 31576ed93dc6SAndrei Emeltchenko BT_DBG("%s link key not found for %pMR", hdev->name, 31586ed93dc6SAndrei Emeltchenko &ev->bdaddr); 315955ed8ca1SJohan Hedberg goto not_found; 316055ed8ca1SJohan Hedberg } 316155ed8ca1SJohan Hedberg 31626ed93dc6SAndrei Emeltchenko BT_DBG("%s found key type %u for %pMR", hdev->name, key->type, 31636ed93dc6SAndrei Emeltchenko &ev->bdaddr); 316455ed8ca1SJohan Hedberg 316555ed8ca1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 316660b83f57SWaldemar Rymarkiewicz if (conn) { 316766138ce8SMarcel Holtmann if ((key->type == HCI_LK_UNAUTH_COMBINATION_P192 || 316866138ce8SMarcel Holtmann key->type == HCI_LK_UNAUTH_COMBINATION_P256) && 3169807deac2SGustavo Padovan conn->auth_type != 0xff && (conn->auth_type & 0x01)) { 317055ed8ca1SJohan Hedberg BT_DBG("%s ignoring unauthenticated key", hdev->name); 317155ed8ca1SJohan Hedberg goto not_found; 317255ed8ca1SJohan Hedberg } 317355ed8ca1SJohan Hedberg 317460b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && 3175f3fb0b58SJohan Hedberg (conn->pending_sec_level == BT_SECURITY_HIGH || 3176f3fb0b58SJohan Hedberg conn->pending_sec_level == BT_SECURITY_FIPS)) { 31778fc9ced3SGustavo Padovan BT_DBG("%s ignoring key unauthenticated for high security", 31788fc9ced3SGustavo Padovan hdev->name); 317960b83f57SWaldemar Rymarkiewicz goto not_found; 318060b83f57SWaldemar Rymarkiewicz } 318160b83f57SWaldemar Rymarkiewicz 318260b83f57SWaldemar Rymarkiewicz conn->key_type = key->type; 318360b83f57SWaldemar Rymarkiewicz conn->pin_length = key->pin_len; 318460b83f57SWaldemar Rymarkiewicz } 318560b83f57SWaldemar Rymarkiewicz 318655ed8ca1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 31879b3b4460SAndrei Emeltchenko memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE); 318855ed8ca1SJohan Hedberg 318955ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 319055ed8ca1SJohan Hedberg 319155ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 319255ed8ca1SJohan Hedberg 319355ed8ca1SJohan Hedberg return; 319455ed8ca1SJohan Hedberg 319555ed8ca1SJohan Hedberg not_found: 319655ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 319755ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 31981da177e4SLinus Torvalds } 31991da177e4SLinus Torvalds 32006039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 32011da177e4SLinus Torvalds { 3202052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 3203052b30b0SMarcel Holtmann struct hci_conn *conn; 32047652ff6aSJohan Hedberg struct link_key *key; 32057652ff6aSJohan Hedberg bool persistent; 320655ed8ca1SJohan Hedberg u8 pin_len = 0; 3207052b30b0SMarcel Holtmann 3208a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 3209052b30b0SMarcel Holtmann 3210052b30b0SMarcel Holtmann hci_dev_lock(hdev); 3211052b30b0SMarcel Holtmann 3212052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 3213052b30b0SMarcel Holtmann if (conn) { 3214052b30b0SMarcel Holtmann hci_conn_hold(conn); 3215052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 3216980e1a53SJohan Hedberg pin_len = conn->pin_length; 321713d39315SWaldemar Rymarkiewicz 321813d39315SWaldemar Rymarkiewicz if (ev->key_type != HCI_LK_CHANGED_COMBINATION) 321913d39315SWaldemar Rymarkiewicz conn->key_type = ev->key_type; 322013d39315SWaldemar Rymarkiewicz 322176a68ba0SDavid Herrmann hci_conn_drop(conn); 3222052b30b0SMarcel Holtmann } 3223052b30b0SMarcel Holtmann 32247652ff6aSJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 32257652ff6aSJohan Hedberg goto unlock; 322655ed8ca1SJohan Hedberg 32277652ff6aSJohan Hedberg key = hci_add_link_key(hdev, conn, &ev->bdaddr, ev->link_key, 32287652ff6aSJohan Hedberg ev->key_type, pin_len, &persistent); 32297652ff6aSJohan Hedberg if (!key) 32307652ff6aSJohan Hedberg goto unlock; 32317652ff6aSJohan Hedberg 32327652ff6aSJohan Hedberg mgmt_new_link_key(hdev, key, persistent); 32337652ff6aSJohan Hedberg 32346d5650c4SJohan Hedberg /* Keep debug keys around only if the HCI_KEEP_DEBUG_KEYS flag 32356d5650c4SJohan Hedberg * is set. If it's not set simply remove the key from the kernel 32366d5650c4SJohan Hedberg * list (we've still notified user space about it but with 32376d5650c4SJohan Hedberg * store_hint being 0). 32386d5650c4SJohan Hedberg */ 32396d5650c4SJohan Hedberg if (key->type == HCI_LK_DEBUG_COMBINATION && 32406d5650c4SJohan Hedberg !test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags)) { 32416d5650c4SJohan Hedberg list_del(&key->list); 32426d5650c4SJohan Hedberg kfree(key); 32436d5650c4SJohan Hedberg } else if (conn) { 3244af6a9c32SJohan Hedberg if (persistent) 3245af6a9c32SJohan Hedberg clear_bit(HCI_CONN_FLUSH_KEY, &conn->flags); 3246af6a9c32SJohan Hedberg else 3247af6a9c32SJohan Hedberg set_bit(HCI_CONN_FLUSH_KEY, &conn->flags); 32486d5650c4SJohan Hedberg } 32497652ff6aSJohan Hedberg 32507652ff6aSJohan Hedberg unlock: 3251052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 32521da177e4SLinus Torvalds } 32531da177e4SLinus Torvalds 32546039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 325504837f64SMarcel Holtmann { 3256a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 325704837f64SMarcel Holtmann struct hci_conn *conn; 325804837f64SMarcel Holtmann 32599f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 326004837f64SMarcel Holtmann 326104837f64SMarcel Holtmann hci_dev_lock(hdev); 326204837f64SMarcel Holtmann 326304837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 32641da177e4SLinus Torvalds if (conn && !ev->status) { 32651da177e4SLinus Torvalds struct inquiry_entry *ie; 32661da177e4SLinus Torvalds 3267cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 3268cc11b9c1SAndrei Emeltchenko if (ie) { 32691da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 32701da177e4SLinus Torvalds ie->timestamp = jiffies; 32711da177e4SLinus Torvalds } 32721da177e4SLinus Torvalds } 32731da177e4SLinus Torvalds 32741da177e4SLinus Torvalds hci_dev_unlock(hdev); 32751da177e4SLinus Torvalds } 32761da177e4SLinus Torvalds 32776039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 3278a8746417SMarcel Holtmann { 3279a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 3280a8746417SMarcel Holtmann struct hci_conn *conn; 3281a8746417SMarcel Holtmann 32829f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 3283a8746417SMarcel Holtmann 3284a8746417SMarcel Holtmann hci_dev_lock(hdev); 3285a8746417SMarcel Holtmann 3286a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3287a8746417SMarcel Holtmann if (conn && !ev->status) 3288a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 3289a8746417SMarcel Holtmann 3290a8746417SMarcel Holtmann hci_dev_unlock(hdev); 3291a8746417SMarcel Holtmann } 3292a8746417SMarcel Holtmann 32936039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 329485a1e930SMarcel Holtmann { 3295a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 329685a1e930SMarcel Holtmann struct inquiry_entry *ie; 329785a1e930SMarcel Holtmann 329885a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 329985a1e930SMarcel Holtmann 330085a1e930SMarcel Holtmann hci_dev_lock(hdev); 330185a1e930SMarcel Holtmann 3302cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 3303cc11b9c1SAndrei Emeltchenko if (ie) { 330485a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 330585a1e930SMarcel Holtmann ie->timestamp = jiffies; 330685a1e930SMarcel Holtmann } 330785a1e930SMarcel Holtmann 330885a1e930SMarcel Holtmann hci_dev_unlock(hdev); 330985a1e930SMarcel Holtmann } 331085a1e930SMarcel Holtmann 33116039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, 3312807deac2SGustavo Padovan struct sk_buff *skb) 3313a9de9248SMarcel Holtmann { 3314a9de9248SMarcel Holtmann struct inquiry_data data; 3315a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 3316a9de9248SMarcel Holtmann 3317a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 3318a9de9248SMarcel Holtmann 3319a9de9248SMarcel Holtmann if (!num_rsp) 3320a9de9248SMarcel Holtmann return; 3321a9de9248SMarcel Holtmann 33221519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 33231519cc17SAndre Guedes return; 33241519cc17SAndre Guedes 3325a9de9248SMarcel Holtmann hci_dev_lock(hdev); 3326a9de9248SMarcel Holtmann 3327a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 3328138d22efSSzymon Janc struct inquiry_info_with_rssi_and_pscan_mode *info; 3329138d22efSSzymon Janc info = (void *) (skb->data + 1); 3330a9de9248SMarcel Holtmann 3331e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 3332af58925cSMarcel Holtmann u32 flags; 3333af58925cSMarcel Holtmann 3334a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 3335a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 3336a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 3337a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 3338a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 3339a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 3340a9de9248SMarcel Holtmann data.rssi = info->rssi; 334141a96212SMarcel Holtmann data.ssp_mode = 0x00; 33423175405bSJohan Hedberg 3343af58925cSMarcel Holtmann flags = hci_inquiry_cache_update(hdev, &data, false); 3344af58925cSMarcel Holtmann 334548264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 3346e17acd40SJohan Hedberg info->dev_class, info->rssi, 3347af58925cSMarcel Holtmann flags, NULL, 0, NULL, 0); 3348a9de9248SMarcel Holtmann } 3349a9de9248SMarcel Holtmann } else { 3350a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 3351a9de9248SMarcel Holtmann 3352e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 3353af58925cSMarcel Holtmann u32 flags; 3354af58925cSMarcel Holtmann 3355a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 3356a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 3357a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 3358a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 3359a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 3360a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 3361a9de9248SMarcel Holtmann data.rssi = info->rssi; 336241a96212SMarcel Holtmann data.ssp_mode = 0x00; 3363af58925cSMarcel Holtmann 3364af58925cSMarcel Holtmann flags = hci_inquiry_cache_update(hdev, &data, false); 3365af58925cSMarcel Holtmann 336648264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 3367e17acd40SJohan Hedberg info->dev_class, info->rssi, 3368af58925cSMarcel Holtmann flags, NULL, 0, NULL, 0); 3369a9de9248SMarcel Holtmann } 3370a9de9248SMarcel Holtmann } 3371a9de9248SMarcel Holtmann 3372a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 3373a9de9248SMarcel Holtmann } 3374a9de9248SMarcel Holtmann 33756039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev, 3376807deac2SGustavo Padovan struct sk_buff *skb) 3377a9de9248SMarcel Holtmann { 337841a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 337941a96212SMarcel Holtmann struct hci_conn *conn; 338041a96212SMarcel Holtmann 3381a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 338241a96212SMarcel Holtmann 338341a96212SMarcel Holtmann hci_dev_lock(hdev); 338441a96212SMarcel Holtmann 338541a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3386ccd556feSJohan Hedberg if (!conn) 3387ccd556feSJohan Hedberg goto unlock; 3388ccd556feSJohan Hedberg 3389cad718edSJohan Hedberg if (ev->page < HCI_MAX_PAGES) 3390cad718edSJohan Hedberg memcpy(conn->features[ev->page], ev->features, 8); 3391cad718edSJohan Hedberg 3392769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 339341a96212SMarcel Holtmann struct inquiry_entry *ie; 339441a96212SMarcel Holtmann 3395cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 3396cc11b9c1SAndrei Emeltchenko if (ie) 339702b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 339841a96212SMarcel Holtmann 3399bbb0eadaSJaganath Kanakkassery if (ev->features[0] & LMP_HOST_SSP) { 340058a681efSJohan Hedberg set_bit(HCI_CONN_SSP_ENABLED, &conn->flags); 3401bbb0eadaSJaganath Kanakkassery } else { 3402bbb0eadaSJaganath Kanakkassery /* It is mandatory by the Bluetooth specification that 3403bbb0eadaSJaganath Kanakkassery * Extended Inquiry Results are only used when Secure 3404bbb0eadaSJaganath Kanakkassery * Simple Pairing is enabled, but some devices violate 3405bbb0eadaSJaganath Kanakkassery * this. 3406bbb0eadaSJaganath Kanakkassery * 3407bbb0eadaSJaganath Kanakkassery * To make these devices work, the internal SSP 3408bbb0eadaSJaganath Kanakkassery * enabled flag needs to be cleared if the remote host 3409bbb0eadaSJaganath Kanakkassery * features do not indicate SSP support */ 3410bbb0eadaSJaganath Kanakkassery clear_bit(HCI_CONN_SSP_ENABLED, &conn->flags); 3411bbb0eadaSJaganath Kanakkassery } 3412eb9a8f3fSMarcel Holtmann 3413eb9a8f3fSMarcel Holtmann if (ev->features[0] & LMP_HOST_SC) 3414eb9a8f3fSMarcel Holtmann set_bit(HCI_CONN_SC_ENABLED, &conn->flags); 341541a96212SMarcel Holtmann } 341641a96212SMarcel Holtmann 3417ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 3418ccd556feSJohan Hedberg goto unlock; 3419ccd556feSJohan Hedberg 3420671267bfSJohan Hedberg if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { 3421127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 3422127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 3423127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 3424127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 3425127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 3426b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 3427b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 342808c79b61SJohan Hedberg conn->dst_type, 0, NULL, 0, 3429b644ba33SJohan Hedberg conn->dev_class); 3430392599b9SJohan Hedberg 3431127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 3432769be974SMarcel Holtmann conn->state = BT_CONNECTED; 3433769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 343476a68ba0SDavid Herrmann hci_conn_drop(conn); 3435769be974SMarcel Holtmann } 3436769be974SMarcel Holtmann 3437ccd556feSJohan Hedberg unlock: 343841a96212SMarcel Holtmann hci_dev_unlock(hdev); 3439a9de9248SMarcel Holtmann } 3440a9de9248SMarcel Holtmann 34416039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev, 3442807deac2SGustavo Padovan struct sk_buff *skb) 3443a9de9248SMarcel Holtmann { 3444b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 3445b6a0dc82SMarcel Holtmann struct hci_conn *conn; 3446b6a0dc82SMarcel Holtmann 34479f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 3448b6a0dc82SMarcel Holtmann 3449b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 3450b6a0dc82SMarcel Holtmann 3451b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 34529dc0a3afSMarcel Holtmann if (!conn) { 34539dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 34549dc0a3afSMarcel Holtmann goto unlock; 34559dc0a3afSMarcel Holtmann 34569dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 3457b6a0dc82SMarcel Holtmann if (!conn) 3458b6a0dc82SMarcel Holtmann goto unlock; 3459b6a0dc82SMarcel Holtmann 34609dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 34619dc0a3afSMarcel Holtmann } 34629dc0a3afSMarcel Holtmann 3463732547f9SMarcel Holtmann switch (ev->status) { 3464732547f9SMarcel Holtmann case 0x00: 3465732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 3466732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 3467732547f9SMarcel Holtmann 3468732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 3469732547f9SMarcel Holtmann break; 3470732547f9SMarcel Holtmann 347181218d20SNick Pelly case 0x10: /* Connection Accept Timeout */ 34721a4c958cSFrédéric Dalleau case 0x0d: /* Connection Rejected due to Limited Resources */ 3473705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 3474732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 34751038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 3476732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 347727539bc4SAndrew Earl case 0x20: /* Unsupported LMP Parameter value */ 34782dea632fSFrédéric Dalleau if (conn->out) { 3479efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 3480efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 34812dea632fSFrédéric Dalleau if (hci_setup_sync(conn, conn->link->handle)) 3482efc7688bSMarcel Holtmann goto unlock; 3483efc7688bSMarcel Holtmann } 3484732547f9SMarcel Holtmann /* fall through */ 3485efc7688bSMarcel Holtmann 3486732547f9SMarcel Holtmann default: 3487b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 3488732547f9SMarcel Holtmann break; 3489732547f9SMarcel Holtmann } 3490b6a0dc82SMarcel Holtmann 3491b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 3492b6a0dc82SMarcel Holtmann if (ev->status) 3493b6a0dc82SMarcel Holtmann hci_conn_del(conn); 3494b6a0dc82SMarcel Holtmann 3495b6a0dc82SMarcel Holtmann unlock: 3496b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 3497a9de9248SMarcel Holtmann } 3498a9de9248SMarcel Holtmann 3499efdcf8e3SMarcel Holtmann static inline size_t eir_get_length(u8 *eir, size_t eir_len) 3500efdcf8e3SMarcel Holtmann { 3501efdcf8e3SMarcel Holtmann size_t parsed = 0; 3502efdcf8e3SMarcel Holtmann 3503efdcf8e3SMarcel Holtmann while (parsed < eir_len) { 3504efdcf8e3SMarcel Holtmann u8 field_len = eir[0]; 3505efdcf8e3SMarcel Holtmann 3506efdcf8e3SMarcel Holtmann if (field_len == 0) 3507efdcf8e3SMarcel Holtmann return parsed; 3508efdcf8e3SMarcel Holtmann 3509efdcf8e3SMarcel Holtmann parsed += field_len + 1; 3510efdcf8e3SMarcel Holtmann eir += field_len + 1; 3511efdcf8e3SMarcel Holtmann } 3512efdcf8e3SMarcel Holtmann 3513efdcf8e3SMarcel Holtmann return eir_len; 3514efdcf8e3SMarcel Holtmann } 3515efdcf8e3SMarcel Holtmann 35166039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, 3517807deac2SGustavo Padovan struct sk_buff *skb) 3518a9de9248SMarcel Holtmann { 3519a9de9248SMarcel Holtmann struct inquiry_data data; 3520a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 3521a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 35229d939d94SVishal Agarwal size_t eir_len; 3523a9de9248SMarcel Holtmann 3524a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 3525a9de9248SMarcel Holtmann 3526a9de9248SMarcel Holtmann if (!num_rsp) 3527a9de9248SMarcel Holtmann return; 3528a9de9248SMarcel Holtmann 35291519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 35301519cc17SAndre Guedes return; 35311519cc17SAndre Guedes 3532a9de9248SMarcel Holtmann hci_dev_lock(hdev); 3533a9de9248SMarcel Holtmann 3534e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 3535af58925cSMarcel Holtmann u32 flags; 3536af58925cSMarcel Holtmann bool name_known; 3537561aafbcSJohan Hedberg 3538a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 3539a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 3540a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 3541a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 3542a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 3543a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 3544a9de9248SMarcel Holtmann data.rssi = info->rssi; 354541a96212SMarcel Holtmann data.ssp_mode = 0x01; 3546561aafbcSJohan Hedberg 3547a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 35484ddb1930SJohan Hedberg name_known = eir_has_data_type(info->data, 35494ddb1930SJohan Hedberg sizeof(info->data), 35504ddb1930SJohan Hedberg EIR_NAME_COMPLETE); 3551561aafbcSJohan Hedberg else 3552561aafbcSJohan Hedberg name_known = true; 3553561aafbcSJohan Hedberg 3554af58925cSMarcel Holtmann flags = hci_inquiry_cache_update(hdev, &data, name_known); 3555af58925cSMarcel Holtmann 35569d939d94SVishal Agarwal eir_len = eir_get_length(info->data, sizeof(info->data)); 3557af58925cSMarcel Holtmann 355848264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 3559af58925cSMarcel Holtmann info->dev_class, info->rssi, 3560af58925cSMarcel Holtmann flags, info->data, eir_len, NULL, 0); 3561a9de9248SMarcel Holtmann } 3562a9de9248SMarcel Holtmann 3563a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 3564a9de9248SMarcel Holtmann } 3565a9de9248SMarcel Holtmann 35661c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev, 35671c2e0041SJohan Hedberg struct sk_buff *skb) 35681c2e0041SJohan Hedberg { 35691c2e0041SJohan Hedberg struct hci_ev_key_refresh_complete *ev = (void *) skb->data; 35701c2e0041SJohan Hedberg struct hci_conn *conn; 35711c2e0041SJohan Hedberg 35729f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status, 35731c2e0041SJohan Hedberg __le16_to_cpu(ev->handle)); 35741c2e0041SJohan Hedberg 35751c2e0041SJohan Hedberg hci_dev_lock(hdev); 35761c2e0041SJohan Hedberg 35771c2e0041SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 35781c2e0041SJohan Hedberg if (!conn) 35791c2e0041SJohan Hedberg goto unlock; 35801c2e0041SJohan Hedberg 35819eb1fbfaSJohan Hedberg /* For BR/EDR the necessary steps are taken through the 35829eb1fbfaSJohan Hedberg * auth_complete event. 35839eb1fbfaSJohan Hedberg */ 35849eb1fbfaSJohan Hedberg if (conn->type != LE_LINK) 35859eb1fbfaSJohan Hedberg goto unlock; 35869eb1fbfaSJohan Hedberg 35871c2e0041SJohan Hedberg if (!ev->status) 35881c2e0041SJohan Hedberg conn->sec_level = conn->pending_sec_level; 35891c2e0041SJohan Hedberg 35901c2e0041SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 35911c2e0041SJohan Hedberg 35921c2e0041SJohan Hedberg if (ev->status && conn->state == BT_CONNECTED) { 3593bed71748SAndre Guedes hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); 359476a68ba0SDavid Herrmann hci_conn_drop(conn); 35951c2e0041SJohan Hedberg goto unlock; 35961c2e0041SJohan Hedberg } 35971c2e0041SJohan Hedberg 35981c2e0041SJohan Hedberg if (conn->state == BT_CONFIG) { 35991c2e0041SJohan Hedberg if (!ev->status) 36001c2e0041SJohan Hedberg conn->state = BT_CONNECTED; 36011c2e0041SJohan Hedberg 36021c2e0041SJohan Hedberg hci_proto_connect_cfm(conn, ev->status); 360376a68ba0SDavid Herrmann hci_conn_drop(conn); 36041c2e0041SJohan Hedberg } else { 36051c2e0041SJohan Hedberg hci_auth_cfm(conn, ev->status); 36061c2e0041SJohan Hedberg 36071c2e0041SJohan Hedberg hci_conn_hold(conn); 36081c2e0041SJohan Hedberg conn->disc_timeout = HCI_DISCONN_TIMEOUT; 360976a68ba0SDavid Herrmann hci_conn_drop(conn); 36101c2e0041SJohan Hedberg } 36111c2e0041SJohan Hedberg 36121c2e0041SJohan Hedberg unlock: 36131c2e0041SJohan Hedberg hci_dev_unlock(hdev); 36141c2e0041SJohan Hedberg } 36151c2e0041SJohan Hedberg 36166039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn) 361717fa4b9dSJohan Hedberg { 361817fa4b9dSJohan Hedberg /* If remote requests no-bonding follow that lead */ 3619acabae96SMikel Astiz if (conn->remote_auth == HCI_AT_NO_BONDING || 3620acabae96SMikel Astiz conn->remote_auth == HCI_AT_NO_BONDING_MITM) 362158797bf7SWaldemar Rymarkiewicz return conn->remote_auth | (conn->auth_type & 0x01); 362217fa4b9dSJohan Hedberg 3623b7f94c88SMikel Astiz /* If both remote and local have enough IO capabilities, require 3624b7f94c88SMikel Astiz * MITM protection 3625b7f94c88SMikel Astiz */ 3626b7f94c88SMikel Astiz if (conn->remote_cap != HCI_IO_NO_INPUT_OUTPUT && 3627b7f94c88SMikel Astiz conn->io_capability != HCI_IO_NO_INPUT_OUTPUT) 3628b7f94c88SMikel Astiz return conn->remote_auth | 0x01; 3629b7f94c88SMikel Astiz 36307e74170aSTimo Mueller /* No MITM protection possible so ignore remote requirement */ 36317e74170aSTimo Mueller return (conn->remote_auth & ~0x01) | (conn->auth_type & 0x01); 363217fa4b9dSJohan Hedberg } 363317fa4b9dSJohan Hedberg 36346039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 36350493684eSMarcel Holtmann { 36360493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 36370493684eSMarcel Holtmann struct hci_conn *conn; 36380493684eSMarcel Holtmann 36390493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 36400493684eSMarcel Holtmann 36410493684eSMarcel Holtmann hci_dev_lock(hdev); 36420493684eSMarcel Holtmann 36430493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 364403b555e1SJohan Hedberg if (!conn) 364503b555e1SJohan Hedberg goto unlock; 364603b555e1SJohan Hedberg 36470493684eSMarcel Holtmann hci_conn_hold(conn); 36480493684eSMarcel Holtmann 3649a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 365003b555e1SJohan Hedberg goto unlock; 365103b555e1SJohan Hedberg 36522f407f0aSJohan Hedberg /* Allow pairing if we're pairable, the initiators of the 36532f407f0aSJohan Hedberg * pairing or if the remote is not requesting bonding. 36542f407f0aSJohan Hedberg */ 3655b6ae8457SJohan Hedberg if (test_bit(HCI_BONDABLE, &hdev->dev_flags) || 36562f407f0aSJohan Hedberg test_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags) || 365703b555e1SJohan Hedberg (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 365817fa4b9dSJohan Hedberg struct hci_cp_io_capability_reply cp; 365917fa4b9dSJohan Hedberg 366017fa4b9dSJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 36617a7f1e7cSHemant Gupta /* Change the IO capability from KeyboardDisplay 36627a7f1e7cSHemant Gupta * to DisplayYesNo as it is not supported by BT spec. */ 36637a7f1e7cSHemant Gupta cp.capability = (conn->io_capability == 0x04) ? 3664a767631aSMikel Astiz HCI_IO_DISPLAY_YESNO : conn->io_capability; 3665b7f94c88SMikel Astiz 3666b7f94c88SMikel Astiz /* If we are initiators, there is no remote information yet */ 3667b7f94c88SMikel Astiz if (conn->remote_auth == 0xff) { 3668b16c6604SMikel Astiz /* Request MITM protection if our IO caps allow it 36694ad51a75SJohan Hedberg * except for the no-bonding case. 3670b16c6604SMikel Astiz */ 36716fd6b915SMikel Astiz if (conn->io_capability != HCI_IO_NO_INPUT_OUTPUT && 36729f743d74SJohan Hedberg conn->auth_type != HCI_AT_NO_BONDING) 36736c53823aSJohan Hedberg conn->auth_type |= 0x01; 36746c53823aSJohan Hedberg 36756c53823aSJohan Hedberg cp.authentication = conn->auth_type; 3676b7f94c88SMikel Astiz } else { 36777cbc9bd9SJohan Hedberg conn->auth_type = hci_get_auth_req(conn); 36787cbc9bd9SJohan Hedberg cp.authentication = conn->auth_type; 3679b7f94c88SMikel Astiz } 368017fa4b9dSJohan Hedberg 36818fc9ced3SGustavo Padovan if (hci_find_remote_oob_data(hdev, &conn->dst) && 36828fc9ced3SGustavo Padovan (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags))) 3683ce85ee13SSzymon Janc cp.oob_data = 0x01; 3684ce85ee13SSzymon Janc else 3685ce85ee13SSzymon Janc cp.oob_data = 0x00; 3686ce85ee13SSzymon Janc 368717fa4b9dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, 368817fa4b9dSJohan Hedberg sizeof(cp), &cp); 368903b555e1SJohan Hedberg } else { 369003b555e1SJohan Hedberg struct hci_cp_io_capability_neg_reply cp; 369103b555e1SJohan Hedberg 369203b555e1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 36939f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED; 369403b555e1SJohan Hedberg 369503b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 369603b555e1SJohan Hedberg sizeof(cp), &cp); 369703b555e1SJohan Hedberg } 369803b555e1SJohan Hedberg 369903b555e1SJohan Hedberg unlock: 370003b555e1SJohan Hedberg hci_dev_unlock(hdev); 370103b555e1SJohan Hedberg } 370203b555e1SJohan Hedberg 37036039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 370403b555e1SJohan Hedberg { 370503b555e1SJohan Hedberg struct hci_ev_io_capa_reply *ev = (void *) skb->data; 370603b555e1SJohan Hedberg struct hci_conn *conn; 370703b555e1SJohan Hedberg 370803b555e1SJohan Hedberg BT_DBG("%s", hdev->name); 370903b555e1SJohan Hedberg 371003b555e1SJohan Hedberg hci_dev_lock(hdev); 371103b555e1SJohan Hedberg 371203b555e1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 371303b555e1SJohan Hedberg if (!conn) 371403b555e1SJohan Hedberg goto unlock; 371503b555e1SJohan Hedberg 371603b555e1SJohan Hedberg conn->remote_cap = ev->capability; 371703b555e1SJohan Hedberg conn->remote_auth = ev->authentication; 371858a681efSJohan Hedberg if (ev->oob_data) 371958a681efSJohan Hedberg set_bit(HCI_CONN_REMOTE_OOB, &conn->flags); 372003b555e1SJohan Hedberg 372103b555e1SJohan Hedberg unlock: 37220493684eSMarcel Holtmann hci_dev_unlock(hdev); 37230493684eSMarcel Holtmann } 37240493684eSMarcel Holtmann 37256039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev, 3726a5c29683SJohan Hedberg struct sk_buff *skb) 3727a5c29683SJohan Hedberg { 3728a5c29683SJohan Hedberg struct hci_ev_user_confirm_req *ev = (void *) skb->data; 372955bc1a37SJohan Hedberg int loc_mitm, rem_mitm, confirm_hint = 0; 37307a828908SJohan Hedberg struct hci_conn *conn; 3731a5c29683SJohan Hedberg 3732a5c29683SJohan Hedberg BT_DBG("%s", hdev->name); 3733a5c29683SJohan Hedberg 3734a5c29683SJohan Hedberg hci_dev_lock(hdev); 3735a5c29683SJohan Hedberg 3736a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 37377a828908SJohan Hedberg goto unlock; 37387a828908SJohan Hedberg 37397a828908SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 37407a828908SJohan Hedberg if (!conn) 37417a828908SJohan Hedberg goto unlock; 37427a828908SJohan Hedberg 37437a828908SJohan Hedberg loc_mitm = (conn->auth_type & 0x01); 37447a828908SJohan Hedberg rem_mitm = (conn->remote_auth & 0x01); 37457a828908SJohan Hedberg 37467a828908SJohan Hedberg /* If we require MITM but the remote device can't provide that 37476c53823aSJohan Hedberg * (it has NoInputNoOutput) then reject the confirmation 37486c53823aSJohan Hedberg * request. We check the security level here since it doesn't 37496c53823aSJohan Hedberg * necessarily match conn->auth_type. 37506fd6b915SMikel Astiz */ 37516c53823aSJohan Hedberg if (conn->pending_sec_level > BT_SECURITY_MEDIUM && 37526c53823aSJohan Hedberg conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) { 37537a828908SJohan Hedberg BT_DBG("Rejecting request: remote device can't provide MITM"); 37547a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, 37557a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 37567a828908SJohan Hedberg goto unlock; 37577a828908SJohan Hedberg } 37587a828908SJohan Hedberg 37597a828908SJohan Hedberg /* If no side requires MITM protection; auto-accept */ 3760a767631aSMikel Astiz if ((!loc_mitm || conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) && 3761a767631aSMikel Astiz (!rem_mitm || conn->io_capability == HCI_IO_NO_INPUT_OUTPUT)) { 376255bc1a37SJohan Hedberg 376355bc1a37SJohan Hedberg /* If we're not the initiators request authorization to 376455bc1a37SJohan Hedberg * proceed from user space (mgmt_user_confirm with 3765ba15a58bSJohan Hedberg * confirm_hint set to 1). The exception is if neither 376602f3e254SJohan Hedberg * side had MITM or if the local IO capability is 376702f3e254SJohan Hedberg * NoInputNoOutput, in which case we do auto-accept 3768ba15a58bSJohan Hedberg */ 3769ba15a58bSJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && 377002f3e254SJohan Hedberg conn->io_capability != HCI_IO_NO_INPUT_OUTPUT && 3771ba15a58bSJohan Hedberg (loc_mitm || rem_mitm)) { 377255bc1a37SJohan Hedberg BT_DBG("Confirming auto-accept as acceptor"); 377355bc1a37SJohan Hedberg confirm_hint = 1; 377455bc1a37SJohan Hedberg goto confirm; 377555bc1a37SJohan Hedberg } 377655bc1a37SJohan Hedberg 37779f61656aSJohan Hedberg BT_DBG("Auto-accept of user confirmation with %ums delay", 37789f61656aSJohan Hedberg hdev->auto_accept_delay); 37799f61656aSJohan Hedberg 37809f61656aSJohan Hedberg if (hdev->auto_accept_delay > 0) { 37819f61656aSJohan Hedberg int delay = msecs_to_jiffies(hdev->auto_accept_delay); 37827bc18d9dSJohan Hedberg queue_delayed_work(conn->hdev->workqueue, 37837bc18d9dSJohan Hedberg &conn->auto_accept_work, delay); 37849f61656aSJohan Hedberg goto unlock; 37859f61656aSJohan Hedberg } 37869f61656aSJohan Hedberg 37877a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, 37887a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 37897a828908SJohan Hedberg goto unlock; 37907a828908SJohan Hedberg } 37917a828908SJohan Hedberg 379255bc1a37SJohan Hedberg confirm: 379339adbffeSJohan Hedberg mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, 379439adbffeSJohan Hedberg le32_to_cpu(ev->passkey), confirm_hint); 3795a5c29683SJohan Hedberg 37967a828908SJohan Hedberg unlock: 3797a5c29683SJohan Hedberg hci_dev_unlock(hdev); 3798a5c29683SJohan Hedberg } 3799a5c29683SJohan Hedberg 38006039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev, 38011143d458SBrian Gix struct sk_buff *skb) 38021143d458SBrian Gix { 38031143d458SBrian Gix struct hci_ev_user_passkey_req *ev = (void *) skb->data; 38041143d458SBrian Gix 38051143d458SBrian Gix BT_DBG("%s", hdev->name); 38061143d458SBrian Gix 3807a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 3808272d90dfSJohan Hedberg mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); 38091143d458SBrian Gix } 38101143d458SBrian Gix 381192a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev, 381292a25256SJohan Hedberg struct sk_buff *skb) 381392a25256SJohan Hedberg { 381492a25256SJohan Hedberg struct hci_ev_user_passkey_notify *ev = (void *) skb->data; 381592a25256SJohan Hedberg struct hci_conn *conn; 381692a25256SJohan Hedberg 381792a25256SJohan Hedberg BT_DBG("%s", hdev->name); 381892a25256SJohan Hedberg 381992a25256SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 382092a25256SJohan Hedberg if (!conn) 382192a25256SJohan Hedberg return; 382292a25256SJohan Hedberg 382392a25256SJohan Hedberg conn->passkey_notify = __le32_to_cpu(ev->passkey); 382492a25256SJohan Hedberg conn->passkey_entered = 0; 382592a25256SJohan Hedberg 382692a25256SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 382792a25256SJohan Hedberg mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, 382892a25256SJohan Hedberg conn->dst_type, conn->passkey_notify, 382992a25256SJohan Hedberg conn->passkey_entered); 383092a25256SJohan Hedberg } 383192a25256SJohan Hedberg 383292a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 383392a25256SJohan Hedberg { 383492a25256SJohan Hedberg struct hci_ev_keypress_notify *ev = (void *) skb->data; 383592a25256SJohan Hedberg struct hci_conn *conn; 383692a25256SJohan Hedberg 383792a25256SJohan Hedberg BT_DBG("%s", hdev->name); 383892a25256SJohan Hedberg 383992a25256SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 384092a25256SJohan Hedberg if (!conn) 384192a25256SJohan Hedberg return; 384292a25256SJohan Hedberg 384392a25256SJohan Hedberg switch (ev->type) { 384492a25256SJohan Hedberg case HCI_KEYPRESS_STARTED: 384592a25256SJohan Hedberg conn->passkey_entered = 0; 384692a25256SJohan Hedberg return; 384792a25256SJohan Hedberg 384892a25256SJohan Hedberg case HCI_KEYPRESS_ENTERED: 384992a25256SJohan Hedberg conn->passkey_entered++; 385092a25256SJohan Hedberg break; 385192a25256SJohan Hedberg 385292a25256SJohan Hedberg case HCI_KEYPRESS_ERASED: 385392a25256SJohan Hedberg conn->passkey_entered--; 385492a25256SJohan Hedberg break; 385592a25256SJohan Hedberg 385692a25256SJohan Hedberg case HCI_KEYPRESS_CLEARED: 385792a25256SJohan Hedberg conn->passkey_entered = 0; 385892a25256SJohan Hedberg break; 385992a25256SJohan Hedberg 386092a25256SJohan Hedberg case HCI_KEYPRESS_COMPLETED: 386192a25256SJohan Hedberg return; 386292a25256SJohan Hedberg } 386392a25256SJohan Hedberg 386492a25256SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 386592a25256SJohan Hedberg mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, 386692a25256SJohan Hedberg conn->dst_type, conn->passkey_notify, 386792a25256SJohan Hedberg conn->passkey_entered); 386892a25256SJohan Hedberg } 386992a25256SJohan Hedberg 38706039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev, 3871807deac2SGustavo Padovan struct sk_buff *skb) 38720493684eSMarcel Holtmann { 38730493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 38740493684eSMarcel Holtmann struct hci_conn *conn; 38750493684eSMarcel Holtmann 38760493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 38770493684eSMarcel Holtmann 38780493684eSMarcel Holtmann hci_dev_lock(hdev); 38790493684eSMarcel Holtmann 38800493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 38812a611692SJohan Hedberg if (!conn) 38822a611692SJohan Hedberg goto unlock; 38832a611692SJohan Hedberg 3884c1d4fa7aSJohan Hedberg /* Reset the authentication requirement to unknown */ 3885c1d4fa7aSJohan Hedberg conn->remote_auth = 0xff; 3886c1d4fa7aSJohan Hedberg 38872a611692SJohan Hedberg /* To avoid duplicate auth_failed events to user space we check 38882a611692SJohan Hedberg * the HCI_CONN_AUTH_PEND flag which will be set if we 38892a611692SJohan Hedberg * initiated the authentication. A traditional auth_complete 38902a611692SJohan Hedberg * event gets always produced as initiator and is also mapped to 38912a611692SJohan Hedberg * the mgmt_auth_failed event */ 3892fa1bd918SMikel Astiz if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status) 3893bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 3894bab73cb6SJohan Hedberg ev->status); 38952a611692SJohan Hedberg 389676a68ba0SDavid Herrmann hci_conn_drop(conn); 38970493684eSMarcel Holtmann 38982a611692SJohan Hedberg unlock: 38990493684eSMarcel Holtmann hci_dev_unlock(hdev); 39000493684eSMarcel Holtmann } 39010493684eSMarcel Holtmann 39026039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev, 3903807deac2SGustavo Padovan struct sk_buff *skb) 390441a96212SMarcel Holtmann { 390541a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 390641a96212SMarcel Holtmann struct inquiry_entry *ie; 3907cad718edSJohan Hedberg struct hci_conn *conn; 390841a96212SMarcel Holtmann 390941a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 391041a96212SMarcel Holtmann 391141a96212SMarcel Holtmann hci_dev_lock(hdev); 391241a96212SMarcel Holtmann 3913cad718edSJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 3914cad718edSJohan Hedberg if (conn) 3915cad718edSJohan Hedberg memcpy(conn->features[1], ev->features, 8); 3916cad718edSJohan Hedberg 3917cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 3918cc11b9c1SAndrei Emeltchenko if (ie) 391902b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 392041a96212SMarcel Holtmann 392141a96212SMarcel Holtmann hci_dev_unlock(hdev); 392241a96212SMarcel Holtmann } 392341a96212SMarcel Holtmann 39246039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev, 39252763eda6SSzymon Janc struct sk_buff *skb) 39262763eda6SSzymon Janc { 39272763eda6SSzymon Janc struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; 39282763eda6SSzymon Janc struct oob_data *data; 39292763eda6SSzymon Janc 39302763eda6SSzymon Janc BT_DBG("%s", hdev->name); 39312763eda6SSzymon Janc 39322763eda6SSzymon Janc hci_dev_lock(hdev); 39332763eda6SSzymon Janc 3934a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 3935e1ba1f15SSzymon Janc goto unlock; 3936e1ba1f15SSzymon Janc 39372763eda6SSzymon Janc data = hci_find_remote_oob_data(hdev, &ev->bdaddr); 39382763eda6SSzymon Janc if (data) { 3939519ca9d0SMarcel Holtmann if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) { 3940519ca9d0SMarcel Holtmann struct hci_cp_remote_oob_ext_data_reply cp; 3941519ca9d0SMarcel Holtmann 3942519ca9d0SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 3943519ca9d0SMarcel Holtmann memcpy(cp.hash192, data->hash192, sizeof(cp.hash192)); 3944519ca9d0SMarcel Holtmann memcpy(cp.randomizer192, data->randomizer192, 3945519ca9d0SMarcel Holtmann sizeof(cp.randomizer192)); 3946519ca9d0SMarcel Holtmann memcpy(cp.hash256, data->hash256, sizeof(cp.hash256)); 3947519ca9d0SMarcel Holtmann memcpy(cp.randomizer256, data->randomizer256, 3948519ca9d0SMarcel Holtmann sizeof(cp.randomizer256)); 3949519ca9d0SMarcel Holtmann 3950519ca9d0SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_EXT_DATA_REPLY, 3951519ca9d0SMarcel Holtmann sizeof(cp), &cp); 3952519ca9d0SMarcel Holtmann } else { 39532763eda6SSzymon Janc struct hci_cp_remote_oob_data_reply cp; 39542763eda6SSzymon Janc 39552763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 3956519ca9d0SMarcel Holtmann memcpy(cp.hash, data->hash192, sizeof(cp.hash)); 3957519ca9d0SMarcel Holtmann memcpy(cp.randomizer, data->randomizer192, 3958519ca9d0SMarcel Holtmann sizeof(cp.randomizer)); 39592763eda6SSzymon Janc 3960519ca9d0SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, 3961519ca9d0SMarcel Holtmann sizeof(cp), &cp); 3962519ca9d0SMarcel Holtmann } 39632763eda6SSzymon Janc } else { 39642763eda6SSzymon Janc struct hci_cp_remote_oob_data_neg_reply cp; 39652763eda6SSzymon Janc 39662763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 3967519ca9d0SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, 3968519ca9d0SMarcel Holtmann sizeof(cp), &cp); 39692763eda6SSzymon Janc } 39702763eda6SSzymon Janc 3971e1ba1f15SSzymon Janc unlock: 39722763eda6SSzymon Janc hci_dev_unlock(hdev); 39732763eda6SSzymon Janc } 39742763eda6SSzymon Janc 3975d5e91192SAndrei Emeltchenko static void hci_phy_link_complete_evt(struct hci_dev *hdev, 3976d5e91192SAndrei Emeltchenko struct sk_buff *skb) 3977d5e91192SAndrei Emeltchenko { 3978d5e91192SAndrei Emeltchenko struct hci_ev_phy_link_complete *ev = (void *) skb->data; 3979d5e91192SAndrei Emeltchenko struct hci_conn *hcon, *bredr_hcon; 3980d5e91192SAndrei Emeltchenko 3981d5e91192SAndrei Emeltchenko BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle, 3982d5e91192SAndrei Emeltchenko ev->status); 3983d5e91192SAndrei Emeltchenko 3984d5e91192SAndrei Emeltchenko hci_dev_lock(hdev); 3985d5e91192SAndrei Emeltchenko 3986d5e91192SAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 3987d5e91192SAndrei Emeltchenko if (!hcon) { 3988d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 3989d5e91192SAndrei Emeltchenko return; 3990d5e91192SAndrei Emeltchenko } 3991d5e91192SAndrei Emeltchenko 3992d5e91192SAndrei Emeltchenko if (ev->status) { 3993d5e91192SAndrei Emeltchenko hci_conn_del(hcon); 3994d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 3995d5e91192SAndrei Emeltchenko return; 3996d5e91192SAndrei Emeltchenko } 3997d5e91192SAndrei Emeltchenko 3998d5e91192SAndrei Emeltchenko bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon; 3999d5e91192SAndrei Emeltchenko 4000d5e91192SAndrei Emeltchenko hcon->state = BT_CONNECTED; 4001d5e91192SAndrei Emeltchenko bacpy(&hcon->dst, &bredr_hcon->dst); 4002d5e91192SAndrei Emeltchenko 4003d5e91192SAndrei Emeltchenko hci_conn_hold(hcon); 4004d5e91192SAndrei Emeltchenko hcon->disc_timeout = HCI_DISCONN_TIMEOUT; 400576a68ba0SDavid Herrmann hci_conn_drop(hcon); 4006d5e91192SAndrei Emeltchenko 4007d5e91192SAndrei Emeltchenko hci_conn_add_sysfs(hcon); 4008d5e91192SAndrei Emeltchenko 4009cf70ff22SAndrei Emeltchenko amp_physical_cfm(bredr_hcon, hcon); 4010cf70ff22SAndrei Emeltchenko 4011d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 4012d5e91192SAndrei Emeltchenko } 4013d5e91192SAndrei Emeltchenko 401427695fb4SAndrei Emeltchenko static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 401527695fb4SAndrei Emeltchenko { 401627695fb4SAndrei Emeltchenko struct hci_ev_logical_link_complete *ev = (void *) skb->data; 401727695fb4SAndrei Emeltchenko struct hci_conn *hcon; 401827695fb4SAndrei Emeltchenko struct hci_chan *hchan; 401927695fb4SAndrei Emeltchenko struct amp_mgr *mgr; 402027695fb4SAndrei Emeltchenko 402127695fb4SAndrei Emeltchenko BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x", 402227695fb4SAndrei Emeltchenko hdev->name, le16_to_cpu(ev->handle), ev->phy_handle, 402327695fb4SAndrei Emeltchenko ev->status); 402427695fb4SAndrei Emeltchenko 402527695fb4SAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 402627695fb4SAndrei Emeltchenko if (!hcon) 402727695fb4SAndrei Emeltchenko return; 402827695fb4SAndrei Emeltchenko 402927695fb4SAndrei Emeltchenko /* Create AMP hchan */ 403027695fb4SAndrei Emeltchenko hchan = hci_chan_create(hcon); 403127695fb4SAndrei Emeltchenko if (!hchan) 403227695fb4SAndrei Emeltchenko return; 403327695fb4SAndrei Emeltchenko 403427695fb4SAndrei Emeltchenko hchan->handle = le16_to_cpu(ev->handle); 403527695fb4SAndrei Emeltchenko 403627695fb4SAndrei Emeltchenko BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan); 403727695fb4SAndrei Emeltchenko 403827695fb4SAndrei Emeltchenko mgr = hcon->amp_mgr; 403927695fb4SAndrei Emeltchenko if (mgr && mgr->bredr_chan) { 404027695fb4SAndrei Emeltchenko struct l2cap_chan *bredr_chan = mgr->bredr_chan; 404127695fb4SAndrei Emeltchenko 404227695fb4SAndrei Emeltchenko l2cap_chan_lock(bredr_chan); 404327695fb4SAndrei Emeltchenko 404427695fb4SAndrei Emeltchenko bredr_chan->conn->mtu = hdev->block_mtu; 404527695fb4SAndrei Emeltchenko l2cap_logical_cfm(bredr_chan, hchan, 0); 404627695fb4SAndrei Emeltchenko hci_conn_hold(hcon); 404727695fb4SAndrei Emeltchenko 404827695fb4SAndrei Emeltchenko l2cap_chan_unlock(bredr_chan); 404927695fb4SAndrei Emeltchenko } 405027695fb4SAndrei Emeltchenko } 405127695fb4SAndrei Emeltchenko 4052606e2a10SAndrei Emeltchenko static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev, 4053606e2a10SAndrei Emeltchenko struct sk_buff *skb) 4054606e2a10SAndrei Emeltchenko { 4055606e2a10SAndrei Emeltchenko struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data; 4056606e2a10SAndrei Emeltchenko struct hci_chan *hchan; 4057606e2a10SAndrei Emeltchenko 4058606e2a10SAndrei Emeltchenko BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name, 4059606e2a10SAndrei Emeltchenko le16_to_cpu(ev->handle), ev->status); 4060606e2a10SAndrei Emeltchenko 4061606e2a10SAndrei Emeltchenko if (ev->status) 4062606e2a10SAndrei Emeltchenko return; 4063606e2a10SAndrei Emeltchenko 4064606e2a10SAndrei Emeltchenko hci_dev_lock(hdev); 4065606e2a10SAndrei Emeltchenko 4066606e2a10SAndrei Emeltchenko hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle)); 4067606e2a10SAndrei Emeltchenko if (!hchan) 4068606e2a10SAndrei Emeltchenko goto unlock; 4069606e2a10SAndrei Emeltchenko 4070606e2a10SAndrei Emeltchenko amp_destroy_logical_link(hchan, ev->reason); 4071606e2a10SAndrei Emeltchenko 4072606e2a10SAndrei Emeltchenko unlock: 4073606e2a10SAndrei Emeltchenko hci_dev_unlock(hdev); 4074606e2a10SAndrei Emeltchenko } 4075606e2a10SAndrei Emeltchenko 40769eef6b3aSAndrei Emeltchenko static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev, 40779eef6b3aSAndrei Emeltchenko struct sk_buff *skb) 40789eef6b3aSAndrei Emeltchenko { 40799eef6b3aSAndrei Emeltchenko struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data; 40809eef6b3aSAndrei Emeltchenko struct hci_conn *hcon; 40819eef6b3aSAndrei Emeltchenko 40829eef6b3aSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 40839eef6b3aSAndrei Emeltchenko 40849eef6b3aSAndrei Emeltchenko if (ev->status) 40859eef6b3aSAndrei Emeltchenko return; 40869eef6b3aSAndrei Emeltchenko 40879eef6b3aSAndrei Emeltchenko hci_dev_lock(hdev); 40889eef6b3aSAndrei Emeltchenko 40899eef6b3aSAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 40909eef6b3aSAndrei Emeltchenko if (hcon) { 40919eef6b3aSAndrei Emeltchenko hcon->state = BT_CLOSED; 40929eef6b3aSAndrei Emeltchenko hci_conn_del(hcon); 40939eef6b3aSAndrei Emeltchenko } 40949eef6b3aSAndrei Emeltchenko 40959eef6b3aSAndrei Emeltchenko hci_dev_unlock(hdev); 40969eef6b3aSAndrei Emeltchenko } 40979eef6b3aSAndrei Emeltchenko 40986039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 4099fcd89c09SVille Tervo { 4100fcd89c09SVille Tervo struct hci_ev_le_conn_complete *ev = (void *) skb->data; 4101912b42efSJohan Hedberg struct hci_conn_params *params; 4102fcd89c09SVille Tervo struct hci_conn *conn; 410368d6f6deSJohan Hedberg struct smp_irk *irk; 4104837d502eSJohan Hedberg u8 addr_type; 4105fcd89c09SVille Tervo 41069f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 4107fcd89c09SVille Tervo 4108fcd89c09SVille Tervo hci_dev_lock(hdev); 4109fcd89c09SVille Tervo 4110fbd96c15SJohan Hedberg /* All controllers implicitly stop advertising in the event of a 4111fbd96c15SJohan Hedberg * connection, so ensure that the state bit is cleared. 4112fbd96c15SJohan Hedberg */ 4113fbd96c15SJohan Hedberg clear_bit(HCI_LE_ADV, &hdev->dev_flags); 4114fbd96c15SJohan Hedberg 41154f72b329SAndrzej Kaczmarek conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); 4116b62f328bSVille Tervo if (!conn) { 4117a5c4e309SJohan Hedberg conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr, ev->role); 4118b62f328bSVille Tervo if (!conn) { 4119b62f328bSVille Tervo BT_ERR("No memory for new connection"); 4120230fd16aSAndre Guedes goto unlock; 4121b62f328bSVille Tervo } 412229b7988aSAndre Guedes 412329b7988aSAndre Guedes conn->dst_type = ev->bdaddr_type; 4124b9b343d2SAndre Guedes 4125cb1d68f7SJohan Hedberg /* If we didn't have a hci_conn object previously 4126cb1d68f7SJohan Hedberg * but we're in master role this must be something 4127cb1d68f7SJohan Hedberg * initiated using a white list. Since white list based 4128cb1d68f7SJohan Hedberg * connections are not "first class citizens" we don't 4129cb1d68f7SJohan Hedberg * have full tracking of them. Therefore, we go ahead 4130cb1d68f7SJohan Hedberg * with a "best effort" approach of determining the 4131cb1d68f7SJohan Hedberg * initiator address based on the HCI_PRIVACY flag. 4132cb1d68f7SJohan Hedberg */ 4133cb1d68f7SJohan Hedberg if (conn->out) { 4134cb1d68f7SJohan Hedberg conn->resp_addr_type = ev->bdaddr_type; 4135cb1d68f7SJohan Hedberg bacpy(&conn->resp_addr, &ev->bdaddr); 4136cb1d68f7SJohan Hedberg if (test_bit(HCI_PRIVACY, &hdev->dev_flags)) { 4137cb1d68f7SJohan Hedberg conn->init_addr_type = ADDR_LE_DEV_RANDOM; 4138cb1d68f7SJohan Hedberg bacpy(&conn->init_addr, &hdev->rpa); 4139cb1d68f7SJohan Hedberg } else { 4140cb1d68f7SJohan Hedberg hci_copy_identity_address(hdev, 4141cb1d68f7SJohan Hedberg &conn->init_addr, 4142cb1d68f7SJohan Hedberg &conn->init_addr_type); 4143cb1d68f7SJohan Hedberg } 414480c24ab8SJohan Hedberg } 4145cb1d68f7SJohan Hedberg } else { 414680c24ab8SJohan Hedberg cancel_delayed_work(&conn->le_conn_timeout); 414780c24ab8SJohan Hedberg } 414880c24ab8SJohan Hedberg 414980c24ab8SJohan Hedberg if (!conn->out) { 4150cb1d68f7SJohan Hedberg /* Set the responder (our side) address type based on 4151cb1d68f7SJohan Hedberg * the advertising address type. 4152cb1d68f7SJohan Hedberg */ 4153cb1d68f7SJohan Hedberg conn->resp_addr_type = hdev->adv_addr_type; 4154cb1d68f7SJohan Hedberg if (hdev->adv_addr_type == ADDR_LE_DEV_RANDOM) 4155cb1d68f7SJohan Hedberg bacpy(&conn->resp_addr, &hdev->random_addr); 4156cb1d68f7SJohan Hedberg else 4157cb1d68f7SJohan Hedberg bacpy(&conn->resp_addr, &hdev->bdaddr); 4158cb1d68f7SJohan Hedberg 4159cb1d68f7SJohan Hedberg conn->init_addr_type = ev->bdaddr_type; 4160cb1d68f7SJohan Hedberg bacpy(&conn->init_addr, &ev->bdaddr); 4161a720d735SMarcel Holtmann 4162a720d735SMarcel Holtmann /* For incoming connections, set the default minimum 4163a720d735SMarcel Holtmann * and maximum connection interval. They will be used 4164a720d735SMarcel Holtmann * to check if the parameters are in range and if not 4165a720d735SMarcel Holtmann * trigger the connection update procedure. 4166a720d735SMarcel Holtmann */ 4167a720d735SMarcel Holtmann conn->le_conn_min_interval = hdev->le_conn_min_interval; 4168a720d735SMarcel Holtmann conn->le_conn_max_interval = hdev->le_conn_max_interval; 4169cb1d68f7SJohan Hedberg } 41707be2edbbSJohan Hedberg 4171edb4b466SMarcel Holtmann /* Lookup the identity address from the stored connection 4172edb4b466SMarcel Holtmann * address and address type. 4173edb4b466SMarcel Holtmann * 4174edb4b466SMarcel Holtmann * When establishing connections to an identity address, the 4175edb4b466SMarcel Holtmann * connection procedure will store the resolvable random 4176edb4b466SMarcel Holtmann * address first. Now if it can be converted back into the 4177edb4b466SMarcel Holtmann * identity address, start using the identity address from 4178edb4b466SMarcel Holtmann * now on. 4179edb4b466SMarcel Holtmann */ 4180edb4b466SMarcel Holtmann irk = hci_get_irk(hdev, &conn->dst, conn->dst_type); 418168d6f6deSJohan Hedberg if (irk) { 418268d6f6deSJohan Hedberg bacpy(&conn->dst, &irk->bdaddr); 418368d6f6deSJohan Hedberg conn->dst_type = irk->addr_type; 418468d6f6deSJohan Hedberg } 418568d6f6deSJohan Hedberg 4186837d502eSJohan Hedberg if (conn->dst_type == ADDR_LE_DEV_PUBLIC) 4187837d502eSJohan Hedberg addr_type = BDADDR_LE_PUBLIC; 4188837d502eSJohan Hedberg else 4189837d502eSJohan Hedberg addr_type = BDADDR_LE_RANDOM; 4190837d502eSJohan Hedberg 41912d3c2260SJohan Hedberg if (ev->status) { 41922d3c2260SJohan Hedberg hci_le_conn_failed(conn, ev->status); 4193837d502eSJohan Hedberg goto unlock; 4194837d502eSJohan Hedberg } 4195837d502eSJohan Hedberg 41962d3c2260SJohan Hedberg /* Drop the connection if the device is blocked */ 41972d3c2260SJohan Hedberg if (hci_bdaddr_list_lookup(&hdev->blacklist, &conn->dst, addr_type)) { 41982d3c2260SJohan Hedberg hci_conn_drop(conn); 4199cd17decbSAndre Guedes goto unlock; 4200cd17decbSAndre Guedes } 4201cd17decbSAndre Guedes 4202b644ba33SJohan Hedberg if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 420301fdb0fcSMarcel Holtmann mgmt_device_connected(hdev, &conn->dst, conn->type, 420495b23582SSzymon Janc conn->dst_type, 0, NULL, 0, NULL); 420583bc71b4SVinicius Costa Gomes 42067b5c0d52SVinicius Costa Gomes conn->sec_level = BT_SECURITY_LOW; 4207fcd89c09SVille Tervo conn->handle = __le16_to_cpu(ev->handle); 4208fcd89c09SVille Tervo conn->state = BT_CONNECTED; 4209fcd89c09SVille Tervo 4210e04fde60SMarcel Holtmann conn->le_conn_interval = le16_to_cpu(ev->interval); 4211e04fde60SMarcel Holtmann conn->le_conn_latency = le16_to_cpu(ev->latency); 4212e04fde60SMarcel Holtmann conn->le_supv_timeout = le16_to_cpu(ev->supervision_timeout); 4213e04fde60SMarcel Holtmann 4214fcd89c09SVille Tervo hci_conn_add_sysfs(conn); 4215fcd89c09SVille Tervo 4216fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 4217fcd89c09SVille Tervo 4218912b42efSJohan Hedberg params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type); 4219223683a5SJohan Hedberg if (params) 422095305baaSJohan Hedberg list_del_init(¶ms->action); 4221a4790dbdSAndre Guedes 4222fcd89c09SVille Tervo unlock: 4223223683a5SJohan Hedberg hci_update_background_scan(hdev); 4224fcd89c09SVille Tervo hci_dev_unlock(hdev); 4225fcd89c09SVille Tervo } 4226fcd89c09SVille Tervo 42271855d92dSMarcel Holtmann static void hci_le_conn_update_complete_evt(struct hci_dev *hdev, 42281855d92dSMarcel Holtmann struct sk_buff *skb) 42291855d92dSMarcel Holtmann { 42301855d92dSMarcel Holtmann struct hci_ev_le_conn_update_complete *ev = (void *) skb->data; 42311855d92dSMarcel Holtmann struct hci_conn *conn; 42321855d92dSMarcel Holtmann 42331855d92dSMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 42341855d92dSMarcel Holtmann 42351855d92dSMarcel Holtmann if (ev->status) 42361855d92dSMarcel Holtmann return; 42371855d92dSMarcel Holtmann 42381855d92dSMarcel Holtmann hci_dev_lock(hdev); 42391855d92dSMarcel Holtmann 42401855d92dSMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 42411855d92dSMarcel Holtmann if (conn) { 42421855d92dSMarcel Holtmann conn->le_conn_interval = le16_to_cpu(ev->interval); 42431855d92dSMarcel Holtmann conn->le_conn_latency = le16_to_cpu(ev->latency); 42441855d92dSMarcel Holtmann conn->le_supv_timeout = le16_to_cpu(ev->supervision_timeout); 42451855d92dSMarcel Holtmann } 42461855d92dSMarcel Holtmann 42471855d92dSMarcel Holtmann hci_dev_unlock(hdev); 42481855d92dSMarcel Holtmann } 42491855d92dSMarcel Holtmann 4250a4790dbdSAndre Guedes /* This function requires the caller holds hdev->lock */ 42517e899c94SJohan Hedberg static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr, 42521c1abcabSJohan Hedberg u8 addr_type, u8 adv_type) 4253a4790dbdSAndre Guedes { 4254a4790dbdSAndre Guedes struct hci_conn *conn; 42554b9e7e75SMarcel Holtmann struct hci_conn_params *params; 4256a4790dbdSAndre Guedes 42571c1abcabSJohan Hedberg /* If the event is not connectable don't proceed further */ 42581c1abcabSJohan Hedberg if (adv_type != LE_ADV_IND && adv_type != LE_ADV_DIRECT_IND) 42597e899c94SJohan Hedberg return; 42601c1abcabSJohan Hedberg 42611c1abcabSJohan Hedberg /* Ignore if the device is blocked */ 4262dcc36c16SJohan Hedberg if (hci_bdaddr_list_lookup(&hdev->blacklist, addr, addr_type)) 42637e899c94SJohan Hedberg return; 42641c1abcabSJohan Hedberg 4265f99353cfSJohan Hedberg /* Most controller will fail if we try to create new connections 4266f99353cfSJohan Hedberg * while we have an existing one in slave role. 4267f99353cfSJohan Hedberg */ 4268f99353cfSJohan Hedberg if (hdev->conn_hash.le_num_slave > 0) 4269f99353cfSJohan Hedberg return; 4270f99353cfSJohan Hedberg 42711c1abcabSJohan Hedberg /* If we're not connectable only connect devices that we have in 42721c1abcabSJohan Hedberg * our pend_le_conns list. 42731c1abcabSJohan Hedberg */ 42744b9e7e75SMarcel Holtmann params = hci_pend_le_action_lookup(&hdev->pend_le_conns, 42754b9e7e75SMarcel Holtmann addr, addr_type); 42764b9e7e75SMarcel Holtmann if (!params) 42777e899c94SJohan Hedberg return; 4278a4790dbdSAndre Guedes 42794b9e7e75SMarcel Holtmann switch (params->auto_connect) { 42804b9e7e75SMarcel Holtmann case HCI_AUTO_CONN_DIRECT: 42814b9e7e75SMarcel Holtmann /* Only devices advertising with ADV_DIRECT_IND are 42824b9e7e75SMarcel Holtmann * triggering a connection attempt. This is allowing 42834b9e7e75SMarcel Holtmann * incoming connections from slave devices. 42844b9e7e75SMarcel Holtmann */ 42854b9e7e75SMarcel Holtmann if (adv_type != LE_ADV_DIRECT_IND) 42864b9e7e75SMarcel Holtmann return; 42874b9e7e75SMarcel Holtmann break; 42884b9e7e75SMarcel Holtmann case HCI_AUTO_CONN_ALWAYS: 42894b9e7e75SMarcel Holtmann /* Devices advertising with ADV_IND or ADV_DIRECT_IND 42904b9e7e75SMarcel Holtmann * are triggering a connection attempt. This means 42914b9e7e75SMarcel Holtmann * that incoming connectioms from slave device are 42924b9e7e75SMarcel Holtmann * accepted and also outgoing connections to slave 42934b9e7e75SMarcel Holtmann * devices are established when found. 42944b9e7e75SMarcel Holtmann */ 42954b9e7e75SMarcel Holtmann break; 42964b9e7e75SMarcel Holtmann default: 42974b9e7e75SMarcel Holtmann return; 42984b9e7e75SMarcel Holtmann } 42994b9e7e75SMarcel Holtmann 4300a4790dbdSAndre Guedes conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW, 4301e804d25dSJohan Hedberg HCI_LE_AUTOCONN_TIMEOUT, HCI_ROLE_MASTER); 4302a4790dbdSAndre Guedes if (!IS_ERR(conn)) 43037e899c94SJohan Hedberg return; 4304a4790dbdSAndre Guedes 4305a4790dbdSAndre Guedes switch (PTR_ERR(conn)) { 4306a4790dbdSAndre Guedes case -EBUSY: 4307a4790dbdSAndre Guedes /* If hci_connect() returns -EBUSY it means there is already 4308a4790dbdSAndre Guedes * an LE connection attempt going on. Since controllers don't 4309a4790dbdSAndre Guedes * support more than one connection attempt at the time, we 4310a4790dbdSAndre Guedes * don't consider this an error case. 4311a4790dbdSAndre Guedes */ 4312a4790dbdSAndre Guedes break; 4313a4790dbdSAndre Guedes default: 4314a4790dbdSAndre Guedes BT_DBG("Failed to connect: err %ld", PTR_ERR(conn)); 4315a4790dbdSAndre Guedes } 4316a4790dbdSAndre Guedes } 4317a4790dbdSAndre Guedes 43184af605d8SJohan Hedberg static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, 43194af605d8SJohan Hedberg u8 bdaddr_type, s8 rssi, u8 *data, u8 len) 43204af605d8SJohan Hedberg { 4321b9a6328fSJohan Hedberg struct discovery_state *d = &hdev->discovery; 43221c1abcabSJohan Hedberg struct smp_irk *irk; 4323474ee066SJohan Hedberg bool match; 4324c70a7e4cSMarcel Holtmann u32 flags; 4325b9a6328fSJohan Hedberg 4326435a13d8SJohan Hedberg /* Check if we need to convert to identity address */ 4327435a13d8SJohan Hedberg irk = hci_get_irk(hdev, bdaddr, bdaddr_type); 4328435a13d8SJohan Hedberg if (irk) { 4329435a13d8SJohan Hedberg bdaddr = &irk->bdaddr; 4330435a13d8SJohan Hedberg bdaddr_type = irk->addr_type; 4331435a13d8SJohan Hedberg } 4332435a13d8SJohan Hedberg 43331c1abcabSJohan Hedberg /* Check if we have been requested to connect to this device */ 43341c1abcabSJohan Hedberg check_pending_le_conn(hdev, bdaddr, bdaddr_type, type); 433599a6768eSJohan Hedberg 43361c1abcabSJohan Hedberg /* Passive scanning shouldn't trigger any device found events, 43371c1abcabSJohan Hedberg * except for devices marked as CONN_REPORT for which we do send 43381c1abcabSJohan Hedberg * device found events. 43391c1abcabSJohan Hedberg */ 43401c1abcabSJohan Hedberg if (hdev->le_scan_type == LE_SCAN_PASSIVE) { 43410d2bf134SJohan Hedberg if (type == LE_ADV_DIRECT_IND) 43420d2bf134SJohan Hedberg return; 43430d2bf134SJohan Hedberg 43443a19b6feSJohan Hedberg if (!hci_pend_le_action_lookup(&hdev->pend_le_reports, 43453a19b6feSJohan Hedberg bdaddr, bdaddr_type)) 43460d2bf134SJohan Hedberg return; 43470d2bf134SJohan Hedberg 43480d2bf134SJohan Hedberg if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND) 43490d2bf134SJohan Hedberg flags = MGMT_DEV_FOUND_NOT_CONNECTABLE; 43500d2bf134SJohan Hedberg else 43510d2bf134SJohan Hedberg flags = 0; 43520d2bf134SJohan Hedberg mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL, 43530d2bf134SJohan Hedberg rssi, flags, data, len, NULL, 0); 435497bf2e99SJohan Hedberg return; 4355ca5c4be7SJohan Hedberg } 43564af605d8SJohan Hedberg 4357c70a7e4cSMarcel Holtmann /* When receiving non-connectable or scannable undirected 4358c70a7e4cSMarcel Holtmann * advertising reports, this means that the remote device is 4359c70a7e4cSMarcel Holtmann * not connectable and then clearly indicate this in the 4360c70a7e4cSMarcel Holtmann * device found event. 4361c70a7e4cSMarcel Holtmann * 4362c70a7e4cSMarcel Holtmann * When receiving a scan response, then there is no way to 4363c70a7e4cSMarcel Holtmann * know if the remote device is connectable or not. However 4364c70a7e4cSMarcel Holtmann * since scan responses are merged with a previously seen 4365c70a7e4cSMarcel Holtmann * advertising report, the flags field from that report 4366c70a7e4cSMarcel Holtmann * will be used. 4367c70a7e4cSMarcel Holtmann * 4368c70a7e4cSMarcel Holtmann * In the really unlikely case that a controller get confused 4369c70a7e4cSMarcel Holtmann * and just sends a scan response event, then it is marked as 4370c70a7e4cSMarcel Holtmann * not connectable as well. 4371c70a7e4cSMarcel Holtmann */ 4372c70a7e4cSMarcel Holtmann if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND || 4373c70a7e4cSMarcel Holtmann type == LE_ADV_SCAN_RSP) 4374c70a7e4cSMarcel Holtmann flags = MGMT_DEV_FOUND_NOT_CONNECTABLE; 4375c70a7e4cSMarcel Holtmann else 4376c70a7e4cSMarcel Holtmann flags = 0; 4377c70a7e4cSMarcel Holtmann 4378b9a6328fSJohan Hedberg /* If there's nothing pending either store the data from this 4379b9a6328fSJohan Hedberg * event or send an immediate device found event if the data 4380b9a6328fSJohan Hedberg * should not be stored for later. 4381b9a6328fSJohan Hedberg */ 4382b9a6328fSJohan Hedberg if (!has_pending_adv_report(hdev)) { 4383b9a6328fSJohan Hedberg /* If the report will trigger a SCAN_REQ store it for 4384b9a6328fSJohan Hedberg * later merging. 4385b9a6328fSJohan Hedberg */ 4386b9a6328fSJohan Hedberg if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) { 4387b9a6328fSJohan Hedberg store_pending_adv_report(hdev, bdaddr, bdaddr_type, 4388c70a7e4cSMarcel Holtmann rssi, flags, data, len); 4389b9a6328fSJohan Hedberg return; 4390b9a6328fSJohan Hedberg } 4391b9a6328fSJohan Hedberg 4392b9a6328fSJohan Hedberg mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL, 4393c70a7e4cSMarcel Holtmann rssi, flags, data, len, NULL, 0); 4394b9a6328fSJohan Hedberg return; 4395b9a6328fSJohan Hedberg } 4396b9a6328fSJohan Hedberg 4397474ee066SJohan Hedberg /* Check if the pending report is for the same device as the new one */ 4398474ee066SJohan Hedberg match = (!bacmp(bdaddr, &d->last_adv_addr) && 4399474ee066SJohan Hedberg bdaddr_type == d->last_adv_addr_type); 4400474ee066SJohan Hedberg 4401b9a6328fSJohan Hedberg /* If the pending data doesn't match this report or this isn't a 4402b9a6328fSJohan Hedberg * scan response (e.g. we got a duplicate ADV_IND) then force 4403b9a6328fSJohan Hedberg * sending of the pending data. 4404b9a6328fSJohan Hedberg */ 4405474ee066SJohan Hedberg if (type != LE_ADV_SCAN_RSP || !match) { 4406474ee066SJohan Hedberg /* Send out whatever is in the cache, but skip duplicates */ 4407474ee066SJohan Hedberg if (!match) 4408b9a6328fSJohan Hedberg mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK, 4409ff5cd29fSJohan Hedberg d->last_adv_addr_type, NULL, 4410c70a7e4cSMarcel Holtmann d->last_adv_rssi, d->last_adv_flags, 4411ff5cd29fSJohan Hedberg d->last_adv_data, 4412474ee066SJohan Hedberg d->last_adv_data_len, NULL, 0); 4413b9a6328fSJohan Hedberg 4414b9a6328fSJohan Hedberg /* If the new report will trigger a SCAN_REQ store it for 4415b9a6328fSJohan Hedberg * later merging. 4416b9a6328fSJohan Hedberg */ 4417b9a6328fSJohan Hedberg if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) { 4418b9a6328fSJohan Hedberg store_pending_adv_report(hdev, bdaddr, bdaddr_type, 4419c70a7e4cSMarcel Holtmann rssi, flags, data, len); 4420b9a6328fSJohan Hedberg return; 4421b9a6328fSJohan Hedberg } 4422b9a6328fSJohan Hedberg 4423b9a6328fSJohan Hedberg /* The advertising reports cannot be merged, so clear 4424b9a6328fSJohan Hedberg * the pending report and send out a device found event. 4425b9a6328fSJohan Hedberg */ 4426b9a6328fSJohan Hedberg clear_pending_adv_report(hdev); 44275c5b93e4SJohan Hedberg mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL, 4428c70a7e4cSMarcel Holtmann rssi, flags, data, len, NULL, 0); 4429b9a6328fSJohan Hedberg return; 4430b9a6328fSJohan Hedberg } 4431b9a6328fSJohan Hedberg 4432b9a6328fSJohan Hedberg /* If we get here we've got a pending ADV_IND or ADV_SCAN_IND and 4433b9a6328fSJohan Hedberg * the new event is a SCAN_RSP. We can therefore proceed with 4434b9a6328fSJohan Hedberg * sending a merged device found event. 4435b9a6328fSJohan Hedberg */ 4436b9a6328fSJohan Hedberg mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK, 4437c70a7e4cSMarcel Holtmann d->last_adv_addr_type, NULL, rssi, d->last_adv_flags, 443842bd6a56SMarcel Holtmann d->last_adv_data, d->last_adv_data_len, data, len); 4439b9a6328fSJohan Hedberg clear_pending_adv_report(hdev); 44404af605d8SJohan Hedberg } 44414af605d8SJohan Hedberg 44426039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) 44439aa04c91SAndre Guedes { 4444e95beb41SAndre Guedes u8 num_reports = skb->data[0]; 4445e95beb41SAndre Guedes void *ptr = &skb->data[1]; 44469aa04c91SAndre Guedes 4447a4790dbdSAndre Guedes hci_dev_lock(hdev); 4448a4790dbdSAndre Guedes 4449e95beb41SAndre Guedes while (num_reports--) { 4450e95beb41SAndre Guedes struct hci_ev_le_advertising_info *ev = ptr; 44514af605d8SJohan Hedberg s8 rssi; 4452a4790dbdSAndre Guedes 44533c9e9195SAndre Guedes rssi = ev->data[ev->length]; 44544af605d8SJohan Hedberg process_adv_report(hdev, ev->evt_type, &ev->bdaddr, 44554af605d8SJohan Hedberg ev->bdaddr_type, rssi, ev->data, ev->length); 44563c9e9195SAndre Guedes 4457e95beb41SAndre Guedes ptr += sizeof(*ev) + ev->length + 1; 44589aa04c91SAndre Guedes } 4459a4790dbdSAndre Guedes 4460a4790dbdSAndre Guedes hci_dev_unlock(hdev); 44619aa04c91SAndre Guedes } 44629aa04c91SAndre Guedes 44636039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 4464a7a595f6SVinicius Costa Gomes { 4465a7a595f6SVinicius Costa Gomes struct hci_ev_le_ltk_req *ev = (void *) skb->data; 4466a7a595f6SVinicius Costa Gomes struct hci_cp_le_ltk_reply cp; 4467bea710feSVinicius Costa Gomes struct hci_cp_le_ltk_neg_reply neg; 4468a7a595f6SVinicius Costa Gomes struct hci_conn *conn; 4469c9839a11SVinicius Costa Gomes struct smp_ltk *ltk; 4470a7a595f6SVinicius Costa Gomes 44719f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle)); 4472a7a595f6SVinicius Costa Gomes 4473a7a595f6SVinicius Costa Gomes hci_dev_lock(hdev); 4474a7a595f6SVinicius Costa Gomes 4475a7a595f6SVinicius Costa Gomes conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 4476bea710feSVinicius Costa Gomes if (conn == NULL) 4477bea710feSVinicius Costa Gomes goto not_found; 4478a7a595f6SVinicius Costa Gomes 4479e804d25dSJohan Hedberg ltk = hci_find_ltk(hdev, ev->ediv, ev->rand, conn->role); 4480bea710feSVinicius Costa Gomes if (ltk == NULL) 4481bea710feSVinicius Costa Gomes goto not_found; 4482bea710feSVinicius Costa Gomes 4483bea710feSVinicius Costa Gomes memcpy(cp.ltk, ltk->val, sizeof(ltk->val)); 4484a7a595f6SVinicius Costa Gomes cp.handle = cpu_to_le16(conn->handle); 4485c9839a11SVinicius Costa Gomes 4486c9839a11SVinicius Costa Gomes if (ltk->authenticated) 4487f8776218SAndre Guedes conn->pending_sec_level = BT_SECURITY_HIGH; 4488f8776218SAndre Guedes else 4489f8776218SAndre Guedes conn->pending_sec_level = BT_SECURITY_MEDIUM; 4490a7a595f6SVinicius Costa Gomes 449189cbb4daSAndre Guedes conn->enc_key_size = ltk->enc_size; 4492a7a595f6SVinicius Costa Gomes 4493a7a595f6SVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); 4494a7a595f6SVinicius Costa Gomes 44955981a882SClaudio Takahasi /* Ref. Bluetooth Core SPEC pages 1975 and 2004. STK is a 44965981a882SClaudio Takahasi * temporary key used to encrypt a connection following 44975981a882SClaudio Takahasi * pairing. It is used during the Encrypted Session Setup to 44985981a882SClaudio Takahasi * distribute the keys. Later, security can be re-established 44995981a882SClaudio Takahasi * using a distributed LTK. 45005981a882SClaudio Takahasi */ 45012ceba539SJohan Hedberg if (ltk->type == SMP_STK) { 4502fe59a05fSJohan Hedberg set_bit(HCI_CONN_STK_ENCRYPT, &conn->flags); 4503c9839a11SVinicius Costa Gomes list_del(<k->list); 4504c9839a11SVinicius Costa Gomes kfree(ltk); 4505fe59a05fSJohan Hedberg } else { 4506fe59a05fSJohan Hedberg clear_bit(HCI_CONN_STK_ENCRYPT, &conn->flags); 4507c9839a11SVinicius Costa Gomes } 4508c9839a11SVinicius Costa Gomes 4509a7a595f6SVinicius Costa Gomes hci_dev_unlock(hdev); 4510bea710feSVinicius Costa Gomes 4511bea710feSVinicius Costa Gomes return; 4512bea710feSVinicius Costa Gomes 4513bea710feSVinicius Costa Gomes not_found: 4514bea710feSVinicius Costa Gomes neg.handle = ev->handle; 4515bea710feSVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg); 4516bea710feSVinicius Costa Gomes hci_dev_unlock(hdev); 4517a7a595f6SVinicius Costa Gomes } 4518a7a595f6SVinicius Costa Gomes 45198e75b46aSAndre Guedes static void send_conn_param_neg_reply(struct hci_dev *hdev, u16 handle, 45208e75b46aSAndre Guedes u8 reason) 45218e75b46aSAndre Guedes { 45228e75b46aSAndre Guedes struct hci_cp_le_conn_param_req_neg_reply cp; 45238e75b46aSAndre Guedes 45248e75b46aSAndre Guedes cp.handle = cpu_to_le16(handle); 45258e75b46aSAndre Guedes cp.reason = reason; 45268e75b46aSAndre Guedes 45278e75b46aSAndre Guedes hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY, sizeof(cp), 45288e75b46aSAndre Guedes &cp); 45298e75b46aSAndre Guedes } 45308e75b46aSAndre Guedes 45318e75b46aSAndre Guedes static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev, 45328e75b46aSAndre Guedes struct sk_buff *skb) 45338e75b46aSAndre Guedes { 45348e75b46aSAndre Guedes struct hci_ev_le_remote_conn_param_req *ev = (void *) skb->data; 45358e75b46aSAndre Guedes struct hci_cp_le_conn_param_req_reply cp; 45368e75b46aSAndre Guedes struct hci_conn *hcon; 45378e75b46aSAndre Guedes u16 handle, min, max, latency, timeout; 45388e75b46aSAndre Guedes 45398e75b46aSAndre Guedes handle = le16_to_cpu(ev->handle); 45408e75b46aSAndre Guedes min = le16_to_cpu(ev->interval_min); 45418e75b46aSAndre Guedes max = le16_to_cpu(ev->interval_max); 45428e75b46aSAndre Guedes latency = le16_to_cpu(ev->latency); 45438e75b46aSAndre Guedes timeout = le16_to_cpu(ev->timeout); 45448e75b46aSAndre Guedes 45458e75b46aSAndre Guedes hcon = hci_conn_hash_lookup_handle(hdev, handle); 45468e75b46aSAndre Guedes if (!hcon || hcon->state != BT_CONNECTED) 45478e75b46aSAndre Guedes return send_conn_param_neg_reply(hdev, handle, 45488e75b46aSAndre Guedes HCI_ERROR_UNKNOWN_CONN_ID); 45498e75b46aSAndre Guedes 45508e75b46aSAndre Guedes if (hci_check_conn_params(min, max, latency, timeout)) 45518e75b46aSAndre Guedes return send_conn_param_neg_reply(hdev, handle, 45528e75b46aSAndre Guedes HCI_ERROR_INVALID_LL_PARAMS); 45538e75b46aSAndre Guedes 455440bef302SJohan Hedberg if (hcon->role == HCI_ROLE_MASTER) { 4555348d50b8SJohan Hedberg struct hci_conn_params *params; 4556f4869e2aSJohan Hedberg u8 store_hint; 4557348d50b8SJohan Hedberg 4558348d50b8SJohan Hedberg hci_dev_lock(hdev); 4559348d50b8SJohan Hedberg 4560348d50b8SJohan Hedberg params = hci_conn_params_lookup(hdev, &hcon->dst, 4561348d50b8SJohan Hedberg hcon->dst_type); 4562348d50b8SJohan Hedberg if (params) { 4563348d50b8SJohan Hedberg params->conn_min_interval = min; 4564348d50b8SJohan Hedberg params->conn_max_interval = max; 4565348d50b8SJohan Hedberg params->conn_latency = latency; 4566348d50b8SJohan Hedberg params->supervision_timeout = timeout; 4567f4869e2aSJohan Hedberg store_hint = 0x01; 4568f4869e2aSJohan Hedberg } else{ 4569f4869e2aSJohan Hedberg store_hint = 0x00; 4570348d50b8SJohan Hedberg } 4571348d50b8SJohan Hedberg 4572348d50b8SJohan Hedberg hci_dev_unlock(hdev); 4573348d50b8SJohan Hedberg 4574f4869e2aSJohan Hedberg mgmt_new_conn_param(hdev, &hcon->dst, hcon->dst_type, 4575f4869e2aSJohan Hedberg store_hint, min, max, latency, timeout); 4576348d50b8SJohan Hedberg } 4577ffb5a827SAndre Guedes 45788e75b46aSAndre Guedes cp.handle = ev->handle; 45798e75b46aSAndre Guedes cp.interval_min = ev->interval_min; 45808e75b46aSAndre Guedes cp.interval_max = ev->interval_max; 45818e75b46aSAndre Guedes cp.latency = ev->latency; 45828e75b46aSAndre Guedes cp.timeout = ev->timeout; 45838e75b46aSAndre Guedes cp.min_ce_len = 0; 45848e75b46aSAndre Guedes cp.max_ce_len = 0; 45858e75b46aSAndre Guedes 45868e75b46aSAndre Guedes hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_REPLY, sizeof(cp), &cp); 45878e75b46aSAndre Guedes } 45888e75b46aSAndre Guedes 45896039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 4590fcd89c09SVille Tervo { 4591fcd89c09SVille Tervo struct hci_ev_le_meta *le_ev = (void *) skb->data; 4592fcd89c09SVille Tervo 4593fcd89c09SVille Tervo skb_pull(skb, sizeof(*le_ev)); 4594fcd89c09SVille Tervo 4595fcd89c09SVille Tervo switch (le_ev->subevent) { 4596fcd89c09SVille Tervo case HCI_EV_LE_CONN_COMPLETE: 4597fcd89c09SVille Tervo hci_le_conn_complete_evt(hdev, skb); 4598fcd89c09SVille Tervo break; 4599fcd89c09SVille Tervo 46001855d92dSMarcel Holtmann case HCI_EV_LE_CONN_UPDATE_COMPLETE: 46011855d92dSMarcel Holtmann hci_le_conn_update_complete_evt(hdev, skb); 46021855d92dSMarcel Holtmann break; 46031855d92dSMarcel Holtmann 46049aa04c91SAndre Guedes case HCI_EV_LE_ADVERTISING_REPORT: 46059aa04c91SAndre Guedes hci_le_adv_report_evt(hdev, skb); 46069aa04c91SAndre Guedes break; 46079aa04c91SAndre Guedes 4608a7a595f6SVinicius Costa Gomes case HCI_EV_LE_LTK_REQ: 4609a7a595f6SVinicius Costa Gomes hci_le_ltk_request_evt(hdev, skb); 4610a7a595f6SVinicius Costa Gomes break; 4611a7a595f6SVinicius Costa Gomes 46128e75b46aSAndre Guedes case HCI_EV_LE_REMOTE_CONN_PARAM_REQ: 46138e75b46aSAndre Guedes hci_le_remote_conn_param_req_evt(hdev, skb); 46148e75b46aSAndre Guedes break; 46158e75b46aSAndre Guedes 4616fcd89c09SVille Tervo default: 4617fcd89c09SVille Tervo break; 4618fcd89c09SVille Tervo } 4619fcd89c09SVille Tervo } 4620fcd89c09SVille Tervo 46219495b2eeSAndrei Emeltchenko static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb) 46229495b2eeSAndrei Emeltchenko { 46239495b2eeSAndrei Emeltchenko struct hci_ev_channel_selected *ev = (void *) skb->data; 46249495b2eeSAndrei Emeltchenko struct hci_conn *hcon; 46259495b2eeSAndrei Emeltchenko 46269495b2eeSAndrei Emeltchenko BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle); 46279495b2eeSAndrei Emeltchenko 46289495b2eeSAndrei Emeltchenko skb_pull(skb, sizeof(*ev)); 46299495b2eeSAndrei Emeltchenko 46309495b2eeSAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 46319495b2eeSAndrei Emeltchenko if (!hcon) 46329495b2eeSAndrei Emeltchenko return; 46339495b2eeSAndrei Emeltchenko 46349495b2eeSAndrei Emeltchenko amp_read_loc_assoc_final_data(hdev, hcon); 46359495b2eeSAndrei Emeltchenko } 46369495b2eeSAndrei Emeltchenko 46371da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 46381da177e4SLinus Torvalds { 4639a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 4640a9de9248SMarcel Holtmann __u8 event = hdr->evt; 46411da177e4SLinus Torvalds 4642b6ddb638SJohan Hedberg hci_dev_lock(hdev); 4643b6ddb638SJohan Hedberg 4644b6ddb638SJohan Hedberg /* Received events are (currently) only needed when a request is 4645b6ddb638SJohan Hedberg * ongoing so avoid unnecessary memory allocation. 4646b6ddb638SJohan Hedberg */ 4647899de765SMarcel Holtmann if (hci_req_pending(hdev)) { 4648b6ddb638SJohan Hedberg kfree_skb(hdev->recv_evt); 4649b6ddb638SJohan Hedberg hdev->recv_evt = skb_clone(skb, GFP_KERNEL); 4650b6ddb638SJohan Hedberg } 4651b6ddb638SJohan Hedberg 4652b6ddb638SJohan Hedberg hci_dev_unlock(hdev); 4653b6ddb638SJohan Hedberg 46541da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 46551da177e4SLinus Torvalds 465602350a72SJohan Hedberg if (hdev->sent_cmd && bt_cb(hdev->sent_cmd)->req.event == event) { 4657c1f23a2bSJohannes Berg struct hci_command_hdr *cmd_hdr = (void *) hdev->sent_cmd->data; 4658c1f23a2bSJohannes Berg u16 opcode = __le16_to_cpu(cmd_hdr->opcode); 465902350a72SJohan Hedberg 466002350a72SJohan Hedberg hci_req_cmd_complete(hdev, opcode, 0); 466102350a72SJohan Hedberg } 466202350a72SJohan Hedberg 4663a9de9248SMarcel Holtmann switch (event) { 46641da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 46651da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 46661da177e4SLinus Torvalds break; 46671da177e4SLinus Torvalds 46681da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 46691da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 46701da177e4SLinus Torvalds break; 46711da177e4SLinus Torvalds 4672a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 4673a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 467421d9e30eSMarcel Holtmann break; 467521d9e30eSMarcel Holtmann 46761da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 46771da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 46781da177e4SLinus Torvalds break; 46791da177e4SLinus Torvalds 46801da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 46811da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 46821da177e4SLinus Torvalds break; 46831da177e4SLinus Torvalds 46841da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 46851da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 46861da177e4SLinus Torvalds break; 46871da177e4SLinus Torvalds 4688a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 4689a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 4690a9de9248SMarcel Holtmann break; 4691a9de9248SMarcel Holtmann 46921da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 46931da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 46941da177e4SLinus Torvalds break; 46951da177e4SLinus Torvalds 4696a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 4697a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 4698a9de9248SMarcel Holtmann break; 4699a9de9248SMarcel Holtmann 4700a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 4701a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 4702a9de9248SMarcel Holtmann break; 4703a9de9248SMarcel Holtmann 4704a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 4705a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 4706a9de9248SMarcel Holtmann break; 4707a9de9248SMarcel Holtmann 4708a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 4709a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 4710a9de9248SMarcel Holtmann break; 4711a9de9248SMarcel Holtmann 4712a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 4713a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 4714a9de9248SMarcel Holtmann break; 4715a9de9248SMarcel Holtmann 4716a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 4717a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 4718a9de9248SMarcel Holtmann break; 4719a9de9248SMarcel Holtmann 4720a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 4721a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 47221da177e4SLinus Torvalds break; 47231da177e4SLinus Torvalds 47241da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 47251da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 47261da177e4SLinus Torvalds break; 47271da177e4SLinus Torvalds 47281da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 47291da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 47301da177e4SLinus Torvalds break; 47311da177e4SLinus Torvalds 47321da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 47331da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 47341da177e4SLinus Torvalds break; 47351da177e4SLinus Torvalds 47361da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 47371da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 47381da177e4SLinus Torvalds break; 47391da177e4SLinus Torvalds 4740a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 4741a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 4742a8746417SMarcel Holtmann break; 4743a8746417SMarcel Holtmann 474485a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 474585a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 474685a1e930SMarcel Holtmann break; 474785a1e930SMarcel Holtmann 4748a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 4749a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 4750a9de9248SMarcel Holtmann break; 4751a9de9248SMarcel Holtmann 4752a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 4753a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 4754a9de9248SMarcel Holtmann break; 4755a9de9248SMarcel Holtmann 4756a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 4757a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 4758a9de9248SMarcel Holtmann break; 4759a9de9248SMarcel Holtmann 4760a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 4761a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 47621da177e4SLinus Torvalds break; 47631da177e4SLinus Torvalds 47641c2e0041SJohan Hedberg case HCI_EV_KEY_REFRESH_COMPLETE: 47651c2e0041SJohan Hedberg hci_key_refresh_complete_evt(hdev, skb); 47661c2e0041SJohan Hedberg break; 47671c2e0041SJohan Hedberg 47680493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 47690493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 47700493684eSMarcel Holtmann break; 47710493684eSMarcel Holtmann 477203b555e1SJohan Hedberg case HCI_EV_IO_CAPA_REPLY: 477303b555e1SJohan Hedberg hci_io_capa_reply_evt(hdev, skb); 477403b555e1SJohan Hedberg break; 477503b555e1SJohan Hedberg 4776a5c29683SJohan Hedberg case HCI_EV_USER_CONFIRM_REQUEST: 4777a5c29683SJohan Hedberg hci_user_confirm_request_evt(hdev, skb); 4778a5c29683SJohan Hedberg break; 4779a5c29683SJohan Hedberg 47801143d458SBrian Gix case HCI_EV_USER_PASSKEY_REQUEST: 47811143d458SBrian Gix hci_user_passkey_request_evt(hdev, skb); 47821143d458SBrian Gix break; 47831143d458SBrian Gix 478492a25256SJohan Hedberg case HCI_EV_USER_PASSKEY_NOTIFY: 478592a25256SJohan Hedberg hci_user_passkey_notify_evt(hdev, skb); 478692a25256SJohan Hedberg break; 478792a25256SJohan Hedberg 478892a25256SJohan Hedberg case HCI_EV_KEYPRESS_NOTIFY: 478992a25256SJohan Hedberg hci_keypress_notify_evt(hdev, skb); 479092a25256SJohan Hedberg break; 479192a25256SJohan Hedberg 47920493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 47930493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 47940493684eSMarcel Holtmann break; 47950493684eSMarcel Holtmann 479641a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 479741a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 479841a96212SMarcel Holtmann break; 479941a96212SMarcel Holtmann 4800fcd89c09SVille Tervo case HCI_EV_LE_META: 4801fcd89c09SVille Tervo hci_le_meta_evt(hdev, skb); 4802fcd89c09SVille Tervo break; 4803fcd89c09SVille Tervo 48049495b2eeSAndrei Emeltchenko case HCI_EV_CHANNEL_SELECTED: 48059495b2eeSAndrei Emeltchenko hci_chan_selected_evt(hdev, skb); 48069495b2eeSAndrei Emeltchenko break; 48079495b2eeSAndrei Emeltchenko 48082763eda6SSzymon Janc case HCI_EV_REMOTE_OOB_DATA_REQUEST: 48092763eda6SSzymon Janc hci_remote_oob_data_request_evt(hdev, skb); 48102763eda6SSzymon Janc break; 48112763eda6SSzymon Janc 4812d5e91192SAndrei Emeltchenko case HCI_EV_PHY_LINK_COMPLETE: 4813d5e91192SAndrei Emeltchenko hci_phy_link_complete_evt(hdev, skb); 4814d5e91192SAndrei Emeltchenko break; 4815d5e91192SAndrei Emeltchenko 481627695fb4SAndrei Emeltchenko case HCI_EV_LOGICAL_LINK_COMPLETE: 481727695fb4SAndrei Emeltchenko hci_loglink_complete_evt(hdev, skb); 481827695fb4SAndrei Emeltchenko break; 481927695fb4SAndrei Emeltchenko 4820606e2a10SAndrei Emeltchenko case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE: 4821606e2a10SAndrei Emeltchenko hci_disconn_loglink_complete_evt(hdev, skb); 4822606e2a10SAndrei Emeltchenko break; 4823606e2a10SAndrei Emeltchenko 48249eef6b3aSAndrei Emeltchenko case HCI_EV_DISCONN_PHY_LINK_COMPLETE: 48259eef6b3aSAndrei Emeltchenko hci_disconn_phylink_complete_evt(hdev, skb); 48269eef6b3aSAndrei Emeltchenko break; 48279eef6b3aSAndrei Emeltchenko 482825e89e99SAndrei Emeltchenko case HCI_EV_NUM_COMP_BLOCKS: 482925e89e99SAndrei Emeltchenko hci_num_comp_blocks_evt(hdev, skb); 483025e89e99SAndrei Emeltchenko break; 483125e89e99SAndrei Emeltchenko 48321da177e4SLinus Torvalds default: 48339f1db00cSAndrei Emeltchenko BT_DBG("%s event 0x%2.2x", hdev->name, event); 48341da177e4SLinus Torvalds break; 48351da177e4SLinus Torvalds } 48361da177e4SLinus Torvalds 48371da177e4SLinus Torvalds kfree_skb(skb); 48381da177e4SLinus Torvalds hdev->stat.evt_rx++; 48391da177e4SLinus Torvalds } 4840