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> 328e2a0d92SAndrei Emeltchenko #include <net/bluetooth/a2mp.h> 33903e4541SAndrei Emeltchenko #include <net/bluetooth/amp.h> 341da177e4SLinus Torvalds 351da177e4SLinus Torvalds /* Handle HCI Event packets */ 361da177e4SLinus Torvalds 37a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb) 381da177e4SLinus Torvalds { 39a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 401da177e4SLinus Torvalds 419f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 421da177e4SLinus Torvalds 43e6d465cbSAndre Guedes if (status) { 44e6d465cbSAndre Guedes hci_dev_lock(hdev); 45e6d465cbSAndre Guedes mgmt_stop_discovery_failed(hdev, status); 46e6d465cbSAndre Guedes hci_dev_unlock(hdev); 47a9de9248SMarcel Holtmann return; 48e6d465cbSAndre Guedes } 491da177e4SLinus Torvalds 5089352e7dSAndre Guedes clear_bit(HCI_INQUIRY, &hdev->flags); 5189352e7dSAndre Guedes 5256e5cb86SJohan Hedberg hci_dev_lock(hdev); 53ff9ef578SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 5456e5cb86SJohan Hedberg hci_dev_unlock(hdev); 55a9de9248SMarcel Holtmann 569238f36aSJohan Hedberg hci_req_cmd_complete(hdev, HCI_OP_INQUIRY, status); 57a9de9248SMarcel Holtmann 58a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 591da177e4SLinus Torvalds } 606bd57416SMarcel Holtmann 614d93483bSAndre Guedes static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 624d93483bSAndre Guedes { 634d93483bSAndre Guedes __u8 status = *((__u8 *) skb->data); 644d93483bSAndre Guedes 659f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 66ae854a70SAndre Guedes 67ae854a70SAndre Guedes if (status) 68ae854a70SAndre Guedes return; 69ae854a70SAndre Guedes 70ae854a70SAndre Guedes set_bit(HCI_PERIODIC_INQ, &hdev->dev_flags); 714d93483bSAndre Guedes } 724d93483bSAndre Guedes 73a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 741da177e4SLinus Torvalds { 75a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 76a9de9248SMarcel Holtmann 779f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 78a9de9248SMarcel Holtmann 79a9de9248SMarcel Holtmann if (status) 80a9de9248SMarcel Holtmann return; 81a9de9248SMarcel Holtmann 82ae854a70SAndre Guedes clear_bit(HCI_PERIODIC_INQ, &hdev->dev_flags); 83ae854a70SAndre Guedes 84a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 85a9de9248SMarcel Holtmann } 86a9de9248SMarcel Holtmann 87807deac2SGustavo Padovan static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, 88807deac2SGustavo Padovan struct sk_buff *skb) 89a9de9248SMarcel Holtmann { 90a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 91a9de9248SMarcel Holtmann } 92a9de9248SMarcel Holtmann 93a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb) 94a9de9248SMarcel Holtmann { 95a9de9248SMarcel Holtmann struct hci_rp_role_discovery *rp = (void *) skb->data; 961da177e4SLinus Torvalds struct hci_conn *conn; 971da177e4SLinus Torvalds 989f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 991da177e4SLinus Torvalds 100a9de9248SMarcel Holtmann if (rp->status) 101a9de9248SMarcel Holtmann return; 1021da177e4SLinus Torvalds 1031da177e4SLinus Torvalds hci_dev_lock(hdev); 1041da177e4SLinus Torvalds 105a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 1061da177e4SLinus Torvalds if (conn) { 107a9de9248SMarcel Holtmann if (rp->role) 1081da177e4SLinus Torvalds conn->link_mode &= ~HCI_LM_MASTER; 1091da177e4SLinus Torvalds else 1101da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 1111da177e4SLinus Torvalds } 1121da177e4SLinus Torvalds 1131da177e4SLinus Torvalds hci_dev_unlock(hdev); 114a9de9248SMarcel Holtmann } 1151da177e4SLinus Torvalds 116e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 117e4e8e37cSMarcel Holtmann { 118e4e8e37cSMarcel Holtmann struct hci_rp_read_link_policy *rp = (void *) skb->data; 119e4e8e37cSMarcel Holtmann struct hci_conn *conn; 120e4e8e37cSMarcel Holtmann 1219f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 122e4e8e37cSMarcel Holtmann 123e4e8e37cSMarcel Holtmann if (rp->status) 124e4e8e37cSMarcel Holtmann return; 125e4e8e37cSMarcel Holtmann 126e4e8e37cSMarcel Holtmann hci_dev_lock(hdev); 127e4e8e37cSMarcel Holtmann 128e4e8e37cSMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 129e4e8e37cSMarcel Holtmann if (conn) 130e4e8e37cSMarcel Holtmann conn->link_policy = __le16_to_cpu(rp->policy); 131e4e8e37cSMarcel Holtmann 132e4e8e37cSMarcel Holtmann hci_dev_unlock(hdev); 133e4e8e37cSMarcel Holtmann } 134e4e8e37cSMarcel Holtmann 135a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 136a9de9248SMarcel Holtmann { 137a9de9248SMarcel Holtmann struct hci_rp_write_link_policy *rp = (void *) skb->data; 138a9de9248SMarcel Holtmann struct hci_conn *conn; 139a9de9248SMarcel Holtmann void *sent; 140a9de9248SMarcel Holtmann 1419f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 142a9de9248SMarcel Holtmann 143a9de9248SMarcel Holtmann if (rp->status) 144a9de9248SMarcel Holtmann return; 145a9de9248SMarcel Holtmann 146a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY); 14704837f64SMarcel Holtmann if (!sent) 148a9de9248SMarcel Holtmann return; 14904837f64SMarcel Holtmann 15004837f64SMarcel Holtmann hci_dev_lock(hdev); 15104837f64SMarcel Holtmann 152a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 153e4e8e37cSMarcel Holtmann if (conn) 15483985319SHarvey Harrison conn->link_policy = get_unaligned_le16(sent + 2); 15504837f64SMarcel Holtmann 15604837f64SMarcel Holtmann hci_dev_unlock(hdev); 1571da177e4SLinus Torvalds } 1581da177e4SLinus Torvalds 159807deac2SGustavo Padovan static void hci_cc_read_def_link_policy(struct hci_dev *hdev, 160807deac2SGustavo Padovan struct sk_buff *skb) 161e4e8e37cSMarcel Holtmann { 162e4e8e37cSMarcel Holtmann struct hci_rp_read_def_link_policy *rp = (void *) skb->data; 163e4e8e37cSMarcel Holtmann 1649f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 165e4e8e37cSMarcel Holtmann 166e4e8e37cSMarcel Holtmann if (rp->status) 167e4e8e37cSMarcel Holtmann return; 168e4e8e37cSMarcel Holtmann 169e4e8e37cSMarcel Holtmann hdev->link_policy = __le16_to_cpu(rp->policy); 170e4e8e37cSMarcel Holtmann } 171e4e8e37cSMarcel Holtmann 172807deac2SGustavo Padovan static void hci_cc_write_def_link_policy(struct hci_dev *hdev, 173807deac2SGustavo Padovan struct sk_buff *skb) 174e4e8e37cSMarcel Holtmann { 175e4e8e37cSMarcel Holtmann __u8 status = *((__u8 *) skb->data); 176e4e8e37cSMarcel Holtmann void *sent; 177e4e8e37cSMarcel Holtmann 1789f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 179e4e8e37cSMarcel Holtmann 180e4e8e37cSMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY); 181e4e8e37cSMarcel Holtmann if (!sent) 182e4e8e37cSMarcel Holtmann return; 183e4e8e37cSMarcel Holtmann 184e4e8e37cSMarcel Holtmann if (!status) 185e4e8e37cSMarcel Holtmann hdev->link_policy = get_unaligned_le16(sent); 186e4e8e37cSMarcel Holtmann } 187e4e8e37cSMarcel Holtmann 188a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) 1891da177e4SLinus Torvalds { 190a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 191a9de9248SMarcel Holtmann 1929f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 193a9de9248SMarcel Holtmann 19410572132SGustavo F. Padovan clear_bit(HCI_RESET, &hdev->flags); 19510572132SGustavo F. Padovan 196a297e97cSJohan Hedberg /* Reset all non-persistent flags */ 1972cc6fb00SJohan Hedberg hdev->dev_flags &= ~HCI_PERSISTENT_MASK; 19869775ff6SAndre Guedes 19969775ff6SAndre Guedes hdev->discovery.state = DISCOVERY_STOPPED; 200bbaf444aSJohan Hedberg hdev->inq_tx_power = HCI_TX_POWER_INVALID; 201bbaf444aSJohan Hedberg hdev->adv_tx_power = HCI_TX_POWER_INVALID; 2023f0f524bSJohan Hedberg 2033f0f524bSJohan Hedberg memset(hdev->adv_data, 0, sizeof(hdev->adv_data)); 2043f0f524bSJohan Hedberg hdev->adv_data_len = 0; 205a9de9248SMarcel Holtmann } 206a9de9248SMarcel Holtmann 207a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) 208a9de9248SMarcel Holtmann { 209a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 2101da177e4SLinus Torvalds void *sent; 2111da177e4SLinus Torvalds 2129f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 2131da177e4SLinus Torvalds 214a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); 2151da177e4SLinus Torvalds if (!sent) 216a9de9248SMarcel Holtmann return; 2171da177e4SLinus Torvalds 21856e5cb86SJohan Hedberg hci_dev_lock(hdev); 21956e5cb86SJohan Hedberg 220f51d5b24SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 221f51d5b24SJohan Hedberg mgmt_set_local_name_complete(hdev, sent, status); 22228cc7bdeSJohan Hedberg else if (!status) 22328cc7bdeSJohan Hedberg memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); 224f51d5b24SJohan Hedberg 22556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 2263159d384SJohan Hedberg 2273f0f524bSJohan Hedberg if (!status && !test_bit(HCI_INIT, &hdev->flags)) 2283f0f524bSJohan Hedberg hci_update_ad(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); 271a9de9248SMarcel Holtmann void *sent; 272a9de9248SMarcel Holtmann 2739f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 274a9de9248SMarcel Holtmann 275a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); 2761da177e4SLinus Torvalds if (!sent) 277a9de9248SMarcel Holtmann return; 2781da177e4SLinus Torvalds 2791da177e4SLinus Torvalds if (!status) { 280a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 281a9de9248SMarcel Holtmann 2821da177e4SLinus Torvalds if (param) 2831da177e4SLinus Torvalds set_bit(HCI_ENCRYPT, &hdev->flags); 2841da177e4SLinus Torvalds else 2851da177e4SLinus Torvalds clear_bit(HCI_ENCRYPT, &hdev->flags); 2861da177e4SLinus Torvalds } 2871da177e4SLinus Torvalds } 2881da177e4SLinus Torvalds 289a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) 290a9de9248SMarcel Holtmann { 29136f7fc7eSJohan Hedberg __u8 param, status = *((__u8 *) skb->data); 29236f7fc7eSJohan Hedberg int old_pscan, old_iscan; 293a9de9248SMarcel Holtmann void *sent; 2941da177e4SLinus Torvalds 2959f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 296a9de9248SMarcel Holtmann 297a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); 2981da177e4SLinus Torvalds if (!sent) 299a9de9248SMarcel Holtmann return; 3001da177e4SLinus Torvalds 30136f7fc7eSJohan Hedberg param = *((__u8 *) sent); 302a9de9248SMarcel Holtmann 30356e5cb86SJohan Hedberg hci_dev_lock(hdev); 30456e5cb86SJohan Hedberg 305fa1bd918SMikel Astiz if (status) { 306744cf19eSJohan Hedberg mgmt_write_scan_failed(hdev, param, status); 3072d7cee58SJohan Hedberg hdev->discov_timeout = 0; 3082d7cee58SJohan Hedberg goto done; 3092d7cee58SJohan Hedberg } 3102d7cee58SJohan Hedberg 3119fbcbb45SJohan Hedberg old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags); 3129fbcbb45SJohan Hedberg old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags); 313a9de9248SMarcel Holtmann 31473f22f62SJohan Hedberg if (param & SCAN_INQUIRY) { 3151da177e4SLinus Torvalds set_bit(HCI_ISCAN, &hdev->flags); 3169fbcbb45SJohan Hedberg if (!old_iscan) 317744cf19eSJohan Hedberg mgmt_discoverable(hdev, 1); 31816ab91abSJohan Hedberg if (hdev->discov_timeout > 0) { 31916ab91abSJohan Hedberg int to = msecs_to_jiffies(hdev->discov_timeout * 1000); 32016ab91abSJohan Hedberg queue_delayed_work(hdev->workqueue, &hdev->discov_off, 32116ab91abSJohan Hedberg to); 32216ab91abSJohan Hedberg } 3239fbcbb45SJohan Hedberg } else if (old_iscan) 324744cf19eSJohan Hedberg mgmt_discoverable(hdev, 0); 3251da177e4SLinus Torvalds 3269fbcbb45SJohan Hedberg if (param & SCAN_PAGE) { 3271da177e4SLinus Torvalds set_bit(HCI_PSCAN, &hdev->flags); 3289fbcbb45SJohan Hedberg if (!old_pscan) 329744cf19eSJohan Hedberg mgmt_connectable(hdev, 1); 3309fbcbb45SJohan Hedberg } else if (old_pscan) 331744cf19eSJohan Hedberg mgmt_connectable(hdev, 0); 332a9de9248SMarcel Holtmann 33336f7fc7eSJohan Hedberg done: 33456e5cb86SJohan Hedberg hci_dev_unlock(hdev); 3351da177e4SLinus Torvalds } 3361da177e4SLinus Torvalds 337a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 338a9de9248SMarcel Holtmann { 339a9de9248SMarcel Holtmann struct hci_rp_read_class_of_dev *rp = (void *) skb->data; 340a9de9248SMarcel Holtmann 3419f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 342a9de9248SMarcel Holtmann 343a9de9248SMarcel Holtmann if (rp->status) 344a9de9248SMarcel Holtmann return; 345a9de9248SMarcel Holtmann 346a9de9248SMarcel Holtmann memcpy(hdev->dev_class, rp->dev_class, 3); 347a9de9248SMarcel Holtmann 348a9de9248SMarcel Holtmann BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, 349a9de9248SMarcel Holtmann hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); 350a9de9248SMarcel Holtmann } 351a9de9248SMarcel Holtmann 352a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 353a9de9248SMarcel Holtmann { 354a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 355a9de9248SMarcel Holtmann void *sent; 356a9de9248SMarcel Holtmann 3579f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 358a9de9248SMarcel Holtmann 359a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); 360a9de9248SMarcel Holtmann if (!sent) 361a9de9248SMarcel Holtmann return; 362a9de9248SMarcel Holtmann 3637f9a903cSMarcel Holtmann hci_dev_lock(hdev); 3647f9a903cSMarcel Holtmann 3657f9a903cSMarcel Holtmann if (status == 0) 366a9de9248SMarcel Holtmann memcpy(hdev->dev_class, sent, 3); 3677f9a903cSMarcel Holtmann 3687f9a903cSMarcel Holtmann if (test_bit(HCI_MGMT, &hdev->dev_flags)) 3697f9a903cSMarcel Holtmann mgmt_set_class_of_dev_complete(hdev, sent, status); 3707f9a903cSMarcel Holtmann 3717f9a903cSMarcel Holtmann hci_dev_unlock(hdev); 372a9de9248SMarcel Holtmann } 373a9de9248SMarcel Holtmann 374a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 375a9de9248SMarcel Holtmann { 376a9de9248SMarcel Holtmann struct hci_rp_read_voice_setting *rp = (void *) skb->data; 377a9de9248SMarcel Holtmann __u16 setting; 378a9de9248SMarcel Holtmann 3799f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 380a9de9248SMarcel Holtmann 381a9de9248SMarcel Holtmann if (rp->status) 382a9de9248SMarcel Holtmann return; 383a9de9248SMarcel Holtmann 384a9de9248SMarcel Holtmann setting = __le16_to_cpu(rp->voice_setting); 385a9de9248SMarcel Holtmann 386a9de9248SMarcel Holtmann if (hdev->voice_setting == setting) 387a9de9248SMarcel Holtmann return; 388a9de9248SMarcel Holtmann 389a9de9248SMarcel Holtmann hdev->voice_setting = setting; 390a9de9248SMarcel Holtmann 3919f1db00cSAndrei Emeltchenko BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting); 392a9de9248SMarcel Holtmann 3933c54711cSGustavo F. Padovan if (hdev->notify) 394a9de9248SMarcel Holtmann hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 395a9de9248SMarcel Holtmann } 396a9de9248SMarcel Holtmann 3978fc9ced3SGustavo Padovan static void hci_cc_write_voice_setting(struct hci_dev *hdev, 3988fc9ced3SGustavo Padovan struct sk_buff *skb) 399a9de9248SMarcel Holtmann { 400a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 401f383f275SMarcel Holtmann __u16 setting; 402a9de9248SMarcel Holtmann void *sent; 403a9de9248SMarcel Holtmann 4049f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 405a9de9248SMarcel Holtmann 406f383f275SMarcel Holtmann if (status) 407f383f275SMarcel Holtmann return; 408f383f275SMarcel Holtmann 409a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); 410a9de9248SMarcel Holtmann if (!sent) 411a9de9248SMarcel Holtmann return; 412a9de9248SMarcel Holtmann 413f383f275SMarcel Holtmann setting = get_unaligned_le16(sent); 4141da177e4SLinus Torvalds 415f383f275SMarcel Holtmann if (hdev->voice_setting == setting) 416f383f275SMarcel Holtmann return; 417f383f275SMarcel Holtmann 4181da177e4SLinus Torvalds hdev->voice_setting = setting; 4191da177e4SLinus Torvalds 4209f1db00cSAndrei Emeltchenko BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting); 4211da177e4SLinus Torvalds 4223c54711cSGustavo F. Padovan if (hdev->notify) 4231da177e4SLinus Torvalds hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 4241da177e4SLinus Torvalds } 4251da177e4SLinus Torvalds 426333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 427333140b5SMarcel Holtmann { 428333140b5SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 4295ed8eb2fSJohan Hedberg struct hci_cp_write_ssp_mode *sent; 430333140b5SMarcel Holtmann 4319f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 432333140b5SMarcel Holtmann 433333140b5SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); 434333140b5SMarcel Holtmann if (!sent) 435333140b5SMarcel Holtmann return; 436333140b5SMarcel Holtmann 4375ed8eb2fSJohan Hedberg if (!status) { 4385ed8eb2fSJohan Hedberg if (sent->mode) 4395ed8eb2fSJohan Hedberg hdev->host_features[0] |= LMP_HOST_SSP; 4405ed8eb2fSJohan Hedberg else 4415ed8eb2fSJohan Hedberg hdev->host_features[0] &= ~LMP_HOST_SSP; 4425ed8eb2fSJohan Hedberg } 4435ed8eb2fSJohan Hedberg 444c0ecddc2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 4455ed8eb2fSJohan Hedberg mgmt_ssp_enable_complete(hdev, sent->mode, status); 446c0ecddc2SJohan Hedberg else if (!status) { 4475ed8eb2fSJohan Hedberg if (sent->mode) 44884bde9d6SJohan Hedberg set_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 44984bde9d6SJohan Hedberg else 45084bde9d6SJohan Hedberg clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 451c0ecddc2SJohan Hedberg } 452333140b5SMarcel Holtmann } 453333140b5SMarcel Holtmann 454a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) 455a9de9248SMarcel Holtmann { 456a9de9248SMarcel Holtmann struct hci_rp_read_local_version *rp = (void *) skb->data; 4571143e5a6SMarcel Holtmann 4589f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 4591143e5a6SMarcel Holtmann 460a9de9248SMarcel Holtmann if (rp->status) 46142c6b129SJohan Hedberg return; 4621143e5a6SMarcel Holtmann 463a9de9248SMarcel Holtmann hdev->hci_ver = rp->hci_ver; 464e4e8e37cSMarcel Holtmann hdev->hci_rev = __le16_to_cpu(rp->hci_rev); 465d5859e22SJohan Hedberg hdev->lmp_ver = rp->lmp_ver; 466e4e8e37cSMarcel Holtmann hdev->manufacturer = __le16_to_cpu(rp->manufacturer); 467d5859e22SJohan Hedberg hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); 4681da177e4SLinus Torvalds 4699f1db00cSAndrei Emeltchenko BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name, 470807deac2SGustavo Padovan hdev->manufacturer, hdev->hci_ver, hdev->hci_rev); 471d5859e22SJohan Hedberg } 472d5859e22SJohan Hedberg 4738fc9ced3SGustavo Padovan static void hci_cc_read_local_commands(struct hci_dev *hdev, 4748fc9ced3SGustavo Padovan struct sk_buff *skb) 475a9de9248SMarcel Holtmann { 476a9de9248SMarcel Holtmann struct hci_rp_read_local_commands *rp = (void *) skb->data; 477a9de9248SMarcel Holtmann 4789f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 479a9de9248SMarcel Holtmann 4802177bab5SJohan Hedberg if (!rp->status) 481a9de9248SMarcel Holtmann memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); 482a9de9248SMarcel Holtmann } 483a9de9248SMarcel Holtmann 4848fc9ced3SGustavo Padovan static void hci_cc_read_local_features(struct hci_dev *hdev, 4858fc9ced3SGustavo Padovan struct sk_buff *skb) 486a9de9248SMarcel Holtmann { 487a9de9248SMarcel Holtmann struct hci_rp_read_local_features *rp = (void *) skb->data; 488a9de9248SMarcel Holtmann 4899f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 490a9de9248SMarcel Holtmann 491a9de9248SMarcel Holtmann if (rp->status) 492a9de9248SMarcel Holtmann return; 493a9de9248SMarcel Holtmann 494a9de9248SMarcel Holtmann memcpy(hdev->features, rp->features, 8); 4951da177e4SLinus Torvalds 4961da177e4SLinus Torvalds /* Adjust default settings according to features 4971da177e4SLinus Torvalds * supported by device. */ 498a9de9248SMarcel Holtmann 4991da177e4SLinus Torvalds if (hdev->features[0] & LMP_3SLOT) 5001da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM3 | HCI_DH3); 5011da177e4SLinus Torvalds 5021da177e4SLinus Torvalds if (hdev->features[0] & LMP_5SLOT) 5031da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM5 | HCI_DH5); 5041da177e4SLinus Torvalds 5055b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV2) { 5061da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV2); 5075b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV2); 5085b7f9909SMarcel Holtmann } 5091da177e4SLinus Torvalds 5105b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV3) { 5111da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV3); 5125b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV3); 5135b7f9909SMarcel Holtmann } 5145b7f9909SMarcel Holtmann 51545db810fSAndre Guedes if (lmp_esco_capable(hdev)) 5165b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV3); 5175b7f9909SMarcel Holtmann 5185b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV4) 5195b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV4); 5205b7f9909SMarcel Holtmann 5215b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV5) 5225b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV5); 5231da177e4SLinus Torvalds 524efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_2M) 525efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV3); 526efc7688bSMarcel Holtmann 527efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_3M) 528efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_3EV3); 529efc7688bSMarcel Holtmann 530efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_3S_ESCO) 531efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); 532efc7688bSMarcel Holtmann 533a9de9248SMarcel Holtmann BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, 534a9de9248SMarcel Holtmann hdev->features[0], hdev->features[1], 535a9de9248SMarcel Holtmann hdev->features[2], hdev->features[3], 536a9de9248SMarcel Holtmann hdev->features[4], hdev->features[5], 537a9de9248SMarcel Holtmann hdev->features[6], hdev->features[7]); 5381da177e4SLinus Torvalds } 5391da177e4SLinus Torvalds 540971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev, 541971e3a4bSAndre Guedes struct sk_buff *skb) 542971e3a4bSAndre Guedes { 543971e3a4bSAndre Guedes struct hci_rp_read_local_ext_features *rp = (void *) skb->data; 544971e3a4bSAndre Guedes 5459f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 546971e3a4bSAndre Guedes 547971e3a4bSAndre Guedes if (rp->status) 54842c6b129SJohan Hedberg return; 549971e3a4bSAndre Guedes 550b5b32b65SAndre Guedes switch (rp->page) { 551b5b32b65SAndre Guedes case 0: 552b5b32b65SAndre Guedes memcpy(hdev->features, rp->features, 8); 553b5b32b65SAndre Guedes break; 554b5b32b65SAndre Guedes case 1: 55559e29406SAndre Guedes memcpy(hdev->host_features, rp->features, 8); 556b5b32b65SAndre Guedes break; 557b5b32b65SAndre Guedes } 558971e3a4bSAndre Guedes } 559971e3a4bSAndre Guedes 5601e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, 5611e89cffbSAndrei Emeltchenko struct sk_buff *skb) 5621e89cffbSAndrei Emeltchenko { 5631e89cffbSAndrei Emeltchenko struct hci_rp_read_flow_control_mode *rp = (void *) skb->data; 5641e89cffbSAndrei Emeltchenko 5659f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 5661e89cffbSAndrei Emeltchenko 56742c6b129SJohan Hedberg if (!rp->status) 5681e89cffbSAndrei Emeltchenko hdev->flow_ctl_mode = rp->mode; 5691e89cffbSAndrei Emeltchenko } 5701e89cffbSAndrei Emeltchenko 571a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 572a9de9248SMarcel Holtmann { 573a9de9248SMarcel Holtmann struct hci_rp_read_buffer_size *rp = (void *) skb->data; 574a9de9248SMarcel Holtmann 5759f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 576a9de9248SMarcel Holtmann 577a9de9248SMarcel Holtmann if (rp->status) 578a9de9248SMarcel Holtmann return; 579a9de9248SMarcel Holtmann 580a9de9248SMarcel Holtmann hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); 581a9de9248SMarcel Holtmann hdev->sco_mtu = rp->sco_mtu; 582a9de9248SMarcel Holtmann hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); 583a9de9248SMarcel Holtmann hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); 584da1f5198SMarcel Holtmann 585da1f5198SMarcel Holtmann if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { 586da1f5198SMarcel Holtmann hdev->sco_mtu = 64; 587da1f5198SMarcel Holtmann hdev->sco_pkts = 8; 588da1f5198SMarcel Holtmann } 589da1f5198SMarcel Holtmann 590da1f5198SMarcel Holtmann hdev->acl_cnt = hdev->acl_pkts; 591da1f5198SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 5921da177e4SLinus Torvalds 593807deac2SGustavo Padovan BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu, 594807deac2SGustavo Padovan hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts); 5951da177e4SLinus Torvalds } 5961da177e4SLinus Torvalds 597a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) 598a9de9248SMarcel Holtmann { 599a9de9248SMarcel Holtmann struct hci_rp_read_bd_addr *rp = (void *) skb->data; 6001da177e4SLinus Torvalds 6019f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 602a9de9248SMarcel Holtmann 603a9de9248SMarcel Holtmann if (!rp->status) 604a9de9248SMarcel Holtmann bacpy(&hdev->bdaddr, &rp->bdaddr); 60523bb5763SJohan Hedberg } 60623bb5763SJohan Hedberg 607350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev, 608350ee4cfSAndrei Emeltchenko struct sk_buff *skb) 609350ee4cfSAndrei Emeltchenko { 610350ee4cfSAndrei Emeltchenko struct hci_rp_read_data_block_size *rp = (void *) skb->data; 611350ee4cfSAndrei Emeltchenko 6129f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 613350ee4cfSAndrei Emeltchenko 614350ee4cfSAndrei Emeltchenko if (rp->status) 615350ee4cfSAndrei Emeltchenko return; 616350ee4cfSAndrei Emeltchenko 617350ee4cfSAndrei Emeltchenko hdev->block_mtu = __le16_to_cpu(rp->max_acl_len); 618350ee4cfSAndrei Emeltchenko hdev->block_len = __le16_to_cpu(rp->block_len); 619350ee4cfSAndrei Emeltchenko hdev->num_blocks = __le16_to_cpu(rp->num_blocks); 620350ee4cfSAndrei Emeltchenko 621350ee4cfSAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 622350ee4cfSAndrei Emeltchenko 623350ee4cfSAndrei Emeltchenko BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu, 624350ee4cfSAndrei Emeltchenko hdev->block_cnt, hdev->block_len); 625350ee4cfSAndrei Emeltchenko } 626350ee4cfSAndrei Emeltchenko 627928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev, 628928abaa7SAndrei Emeltchenko struct sk_buff *skb) 629928abaa7SAndrei Emeltchenko { 630928abaa7SAndrei Emeltchenko struct hci_rp_read_local_amp_info *rp = (void *) skb->data; 631928abaa7SAndrei Emeltchenko 6329f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 633928abaa7SAndrei Emeltchenko 634928abaa7SAndrei Emeltchenko if (rp->status) 6358e2a0d92SAndrei Emeltchenko goto a2mp_rsp; 636928abaa7SAndrei Emeltchenko 637928abaa7SAndrei Emeltchenko hdev->amp_status = rp->amp_status; 638928abaa7SAndrei Emeltchenko hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); 639928abaa7SAndrei Emeltchenko hdev->amp_max_bw = __le32_to_cpu(rp->max_bw); 640928abaa7SAndrei Emeltchenko hdev->amp_min_latency = __le32_to_cpu(rp->min_latency); 641928abaa7SAndrei Emeltchenko hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu); 642928abaa7SAndrei Emeltchenko hdev->amp_type = rp->amp_type; 643928abaa7SAndrei Emeltchenko hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap); 644928abaa7SAndrei Emeltchenko hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size); 645928abaa7SAndrei Emeltchenko hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); 646928abaa7SAndrei Emeltchenko hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); 647928abaa7SAndrei Emeltchenko 6488e2a0d92SAndrei Emeltchenko a2mp_rsp: 6498e2a0d92SAndrei Emeltchenko a2mp_send_getinfo_rsp(hdev); 650928abaa7SAndrei Emeltchenko } 651928abaa7SAndrei Emeltchenko 652903e4541SAndrei Emeltchenko static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev, 653903e4541SAndrei Emeltchenko struct sk_buff *skb) 654903e4541SAndrei Emeltchenko { 655903e4541SAndrei Emeltchenko struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data; 656903e4541SAndrei Emeltchenko struct amp_assoc *assoc = &hdev->loc_assoc; 657903e4541SAndrei Emeltchenko size_t rem_len, frag_len; 658903e4541SAndrei Emeltchenko 659903e4541SAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 660903e4541SAndrei Emeltchenko 661903e4541SAndrei Emeltchenko if (rp->status) 662903e4541SAndrei Emeltchenko goto a2mp_rsp; 663903e4541SAndrei Emeltchenko 664903e4541SAndrei Emeltchenko frag_len = skb->len - sizeof(*rp); 665903e4541SAndrei Emeltchenko rem_len = __le16_to_cpu(rp->rem_len); 666903e4541SAndrei Emeltchenko 667903e4541SAndrei Emeltchenko if (rem_len > frag_len) { 6682e430be3SAndrei Emeltchenko BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len); 669903e4541SAndrei Emeltchenko 670903e4541SAndrei Emeltchenko memcpy(assoc->data + assoc->offset, rp->frag, frag_len); 671903e4541SAndrei Emeltchenko assoc->offset += frag_len; 672903e4541SAndrei Emeltchenko 673903e4541SAndrei Emeltchenko /* Read other fragments */ 674903e4541SAndrei Emeltchenko amp_read_loc_assoc_frag(hdev, rp->phy_handle); 675903e4541SAndrei Emeltchenko 676903e4541SAndrei Emeltchenko return; 677903e4541SAndrei Emeltchenko } 678903e4541SAndrei Emeltchenko 679903e4541SAndrei Emeltchenko memcpy(assoc->data + assoc->offset, rp->frag, rem_len); 680903e4541SAndrei Emeltchenko assoc->len = assoc->offset + rem_len; 681903e4541SAndrei Emeltchenko assoc->offset = 0; 682903e4541SAndrei Emeltchenko 683903e4541SAndrei Emeltchenko a2mp_rsp: 684903e4541SAndrei Emeltchenko /* Send A2MP Rsp when all fragments are received */ 685903e4541SAndrei Emeltchenko a2mp_send_getampassoc_rsp(hdev, rp->status); 6869495b2eeSAndrei Emeltchenko a2mp_send_create_phy_link_req(hdev, rp->status); 687903e4541SAndrei Emeltchenko } 688903e4541SAndrei Emeltchenko 689d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, 690d5859e22SJohan Hedberg struct sk_buff *skb) 691d5859e22SJohan Hedberg { 69291c4e9b1SMarcel Holtmann struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data; 693d5859e22SJohan Hedberg 6949f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 695d5859e22SJohan Hedberg 69691c4e9b1SMarcel Holtmann if (!rp->status) 69791c4e9b1SMarcel Holtmann hdev->inq_tx_power = rp->tx_power; 698d5859e22SJohan Hedberg } 699d5859e22SJohan Hedberg 700980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) 701980e1a53SJohan Hedberg { 702980e1a53SJohan Hedberg struct hci_rp_pin_code_reply *rp = (void *) skb->data; 703980e1a53SJohan Hedberg struct hci_cp_pin_code_reply *cp; 704980e1a53SJohan Hedberg struct hci_conn *conn; 705980e1a53SJohan Hedberg 7069f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 707980e1a53SJohan Hedberg 70856e5cb86SJohan Hedberg hci_dev_lock(hdev); 70956e5cb86SJohan Hedberg 710a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 711744cf19eSJohan Hedberg mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); 712980e1a53SJohan Hedberg 713fa1bd918SMikel Astiz if (rp->status) 71456e5cb86SJohan Hedberg goto unlock; 715980e1a53SJohan Hedberg 716980e1a53SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); 717980e1a53SJohan Hedberg if (!cp) 71856e5cb86SJohan Hedberg goto unlock; 719980e1a53SJohan Hedberg 720980e1a53SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 721980e1a53SJohan Hedberg if (conn) 722980e1a53SJohan Hedberg conn->pin_length = cp->pin_len; 72356e5cb86SJohan Hedberg 72456e5cb86SJohan Hedberg unlock: 72556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 726980e1a53SJohan Hedberg } 727980e1a53SJohan Hedberg 728980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 729980e1a53SJohan Hedberg { 730980e1a53SJohan Hedberg struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data; 731980e1a53SJohan Hedberg 7329f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 733980e1a53SJohan Hedberg 73456e5cb86SJohan Hedberg hci_dev_lock(hdev); 73556e5cb86SJohan Hedberg 736a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 737744cf19eSJohan Hedberg mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr, 738980e1a53SJohan Hedberg rp->status); 73956e5cb86SJohan Hedberg 74056e5cb86SJohan Hedberg hci_dev_unlock(hdev); 741980e1a53SJohan Hedberg } 74256e5cb86SJohan Hedberg 7436ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, 7446ed58ec5SVille Tervo struct sk_buff *skb) 7456ed58ec5SVille Tervo { 7466ed58ec5SVille Tervo struct hci_rp_le_read_buffer_size *rp = (void *) skb->data; 7476ed58ec5SVille Tervo 7489f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 7496ed58ec5SVille Tervo 7506ed58ec5SVille Tervo if (rp->status) 7516ed58ec5SVille Tervo return; 7526ed58ec5SVille Tervo 7536ed58ec5SVille Tervo hdev->le_mtu = __le16_to_cpu(rp->le_mtu); 7546ed58ec5SVille Tervo hdev->le_pkts = rp->le_max_pkt; 7556ed58ec5SVille Tervo 7566ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 7576ed58ec5SVille Tervo 7586ed58ec5SVille Tervo BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); 7596ed58ec5SVille Tervo } 760980e1a53SJohan Hedberg 76160e77321SJohan Hedberg static void hci_cc_le_read_local_features(struct hci_dev *hdev, 76260e77321SJohan Hedberg struct sk_buff *skb) 76360e77321SJohan Hedberg { 76460e77321SJohan Hedberg struct hci_rp_le_read_local_features *rp = (void *) skb->data; 76560e77321SJohan Hedberg 76660e77321SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 76760e77321SJohan Hedberg 76860e77321SJohan Hedberg if (!rp->status) 76960e77321SJohan Hedberg memcpy(hdev->le_features, rp->features, 8); 77060e77321SJohan Hedberg } 77160e77321SJohan Hedberg 7728fa19098SJohan Hedberg static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, 7738fa19098SJohan Hedberg struct sk_buff *skb) 7748fa19098SJohan Hedberg { 7758fa19098SJohan Hedberg struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data; 7768fa19098SJohan Hedberg 7778fa19098SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 7788fa19098SJohan Hedberg 7793f0f524bSJohan Hedberg if (!rp->status) { 7808fa19098SJohan Hedberg hdev->adv_tx_power = rp->tx_power; 7813f0f524bSJohan Hedberg if (!test_bit(HCI_INIT, &hdev->flags)) 7823f0f524bSJohan Hedberg hci_update_ad(hdev); 7833f0f524bSJohan Hedberg } 7848fa19098SJohan Hedberg } 7858fa19098SJohan Hedberg 786a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) 787a5c29683SJohan Hedberg { 788a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 789a5c29683SJohan Hedberg 7909f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 791a5c29683SJohan Hedberg 79256e5cb86SJohan Hedberg hci_dev_lock(hdev); 79356e5cb86SJohan Hedberg 794a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 79504124681SGustavo F. Padovan mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0, 79604124681SGustavo F. Padovan rp->status); 79756e5cb86SJohan Hedberg 79856e5cb86SJohan Hedberg hci_dev_unlock(hdev); 799a5c29683SJohan Hedberg } 800a5c29683SJohan Hedberg 801a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, 802a5c29683SJohan Hedberg struct sk_buff *skb) 803a5c29683SJohan Hedberg { 804a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 805a5c29683SJohan Hedberg 8069f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 807a5c29683SJohan Hedberg 80856e5cb86SJohan Hedberg hci_dev_lock(hdev); 80956e5cb86SJohan Hedberg 810a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 811744cf19eSJohan Hedberg mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr, 81204124681SGustavo F. Padovan ACL_LINK, 0, rp->status); 81356e5cb86SJohan Hedberg 81456e5cb86SJohan Hedberg hci_dev_unlock(hdev); 815a5c29683SJohan Hedberg } 816a5c29683SJohan Hedberg 8171143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb) 8181143d458SBrian Gix { 8191143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 8201143d458SBrian Gix 8219f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 8221143d458SBrian Gix 8231143d458SBrian Gix hci_dev_lock(hdev); 8241143d458SBrian Gix 825a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 826272d90dfSJohan Hedberg mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 827272d90dfSJohan Hedberg 0, rp->status); 8281143d458SBrian Gix 8291143d458SBrian Gix hci_dev_unlock(hdev); 8301143d458SBrian Gix } 8311143d458SBrian Gix 8321143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, 8331143d458SBrian Gix struct sk_buff *skb) 8341143d458SBrian Gix { 8351143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 8361143d458SBrian Gix 8379f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 8381143d458SBrian Gix 8391143d458SBrian Gix hci_dev_lock(hdev); 8401143d458SBrian Gix 841a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 8421143d458SBrian Gix mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr, 84304124681SGustavo F. Padovan ACL_LINK, 0, rp->status); 8441143d458SBrian Gix 8451143d458SBrian Gix hci_dev_unlock(hdev); 8461143d458SBrian Gix } 8471143d458SBrian Gix 848c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, 849c35938b2SSzymon Janc struct sk_buff *skb) 850c35938b2SSzymon Janc { 851c35938b2SSzymon Janc struct hci_rp_read_local_oob_data *rp = (void *) skb->data; 852c35938b2SSzymon Janc 8539f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 854c35938b2SSzymon Janc 85556e5cb86SJohan Hedberg hci_dev_lock(hdev); 856744cf19eSJohan Hedberg mgmt_read_local_oob_data_reply_complete(hdev, rp->hash, 857c35938b2SSzymon Janc rp->randomizer, rp->status); 85856e5cb86SJohan Hedberg hci_dev_unlock(hdev); 859c35938b2SSzymon Janc } 860c35938b2SSzymon Janc 861c1d5dc4aSJohan Hedberg static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb) 862c1d5dc4aSJohan Hedberg { 863c1d5dc4aSJohan Hedberg __u8 *sent, status = *((__u8 *) skb->data); 864c1d5dc4aSJohan Hedberg 865c1d5dc4aSJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 866c1d5dc4aSJohan Hedberg 867c1d5dc4aSJohan Hedberg sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE); 868c1d5dc4aSJohan Hedberg if (!sent) 869c1d5dc4aSJohan Hedberg return; 870c1d5dc4aSJohan Hedberg 871c1d5dc4aSJohan Hedberg hci_dev_lock(hdev); 872c1d5dc4aSJohan Hedberg 873c1d5dc4aSJohan Hedberg if (!status) { 874c1d5dc4aSJohan Hedberg if (*sent) 875c1d5dc4aSJohan Hedberg set_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags); 876c1d5dc4aSJohan Hedberg else 877c1d5dc4aSJohan Hedberg clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags); 878c1d5dc4aSJohan Hedberg } 879c1d5dc4aSJohan Hedberg 880c1d5dc4aSJohan Hedberg hci_dev_unlock(hdev); 881c1d5dc4aSJohan Hedberg 882c1d5dc4aSJohan Hedberg if (!test_bit(HCI_INIT, &hdev->flags)) 883c1d5dc4aSJohan Hedberg hci_update_ad(hdev); 884c1d5dc4aSJohan Hedberg } 885c1d5dc4aSJohan Hedberg 88607f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) 88707f7fa5dSAndre Guedes { 88807f7fa5dSAndre Guedes __u8 status = *((__u8 *) skb->data); 88907f7fa5dSAndre Guedes 8909f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 8917ba8b4beSAndre Guedes 8923fd24153SAndre Guedes if (status) { 8933fd24153SAndre Guedes hci_dev_lock(hdev); 8943fd24153SAndre Guedes mgmt_start_discovery_failed(hdev, status); 8953fd24153SAndre Guedes hci_dev_unlock(hdev); 8963fd24153SAndre Guedes return; 8973fd24153SAndre Guedes } 89807f7fa5dSAndre Guedes } 89907f7fa5dSAndre Guedes 900eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, 901eb9d91f5SAndre Guedes struct sk_buff *skb) 902eb9d91f5SAndre Guedes { 903eb9d91f5SAndre Guedes struct hci_cp_le_set_scan_enable *cp; 904eb9d91f5SAndre Guedes __u8 status = *((__u8 *) skb->data); 905eb9d91f5SAndre Guedes 9069f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 907eb9d91f5SAndre Guedes 908eb9d91f5SAndre Guedes cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE); 909eb9d91f5SAndre Guedes if (!cp) 910eb9d91f5SAndre Guedes return; 911eb9d91f5SAndre Guedes 91268a8aea4SAndrei Emeltchenko switch (cp->enable) { 91368a8aea4SAndrei Emeltchenko case LE_SCANNING_ENABLED: 9143fd24153SAndre Guedes if (status) { 9153fd24153SAndre Guedes hci_dev_lock(hdev); 9163fd24153SAndre Guedes mgmt_start_discovery_failed(hdev, status); 9173fd24153SAndre Guedes hci_dev_unlock(hdev); 9187ba8b4beSAndre Guedes return; 9193fd24153SAndre Guedes } 9207ba8b4beSAndre Guedes 921d23264a8SAndre Guedes set_bit(HCI_LE_SCAN, &hdev->dev_flags); 922d23264a8SAndre Guedes 923a8f13c8cSAndre Guedes hci_dev_lock(hdev); 924343f935bSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_FINDING); 925a8f13c8cSAndre Guedes hci_dev_unlock(hdev); 92668a8aea4SAndrei Emeltchenko break; 92768a8aea4SAndrei Emeltchenko 92868a8aea4SAndrei Emeltchenko case LE_SCANNING_DISABLED: 929c9ecc48eSAndre Guedes if (status) { 930c9ecc48eSAndre Guedes hci_dev_lock(hdev); 931c9ecc48eSAndre Guedes mgmt_stop_discovery_failed(hdev, status); 932c9ecc48eSAndre Guedes hci_dev_unlock(hdev); 9337ba8b4beSAndre Guedes return; 934c9ecc48eSAndre Guedes } 9357ba8b4beSAndre Guedes 936d23264a8SAndre Guedes clear_bit(HCI_LE_SCAN, &hdev->dev_flags); 937d23264a8SAndre Guedes 938bc3dd33cSAndre Guedes if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED && 939bc3dd33cSAndre Guedes hdev->discovery.state == DISCOVERY_FINDING) { 9405e0452c0SAndre Guedes mgmt_interleaved_discovery(hdev); 9415e0452c0SAndre Guedes } else { 942c599008fSAndre Guedes hci_dev_lock(hdev); 943c599008fSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 944c599008fSAndre Guedes hci_dev_unlock(hdev); 9455e0452c0SAndre Guedes } 946c599008fSAndre Guedes 94768a8aea4SAndrei Emeltchenko break; 94868a8aea4SAndrei Emeltchenko 94968a8aea4SAndrei Emeltchenko default: 95068a8aea4SAndrei Emeltchenko BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable); 95168a8aea4SAndrei Emeltchenko break; 95235815085SAndre Guedes } 953eb9d91f5SAndre Guedes } 954eb9d91f5SAndre Guedes 955cf1d081fSJohan Hedberg static void hci_cc_le_read_white_list_size(struct hci_dev *hdev, 956cf1d081fSJohan Hedberg struct sk_buff *skb) 957cf1d081fSJohan Hedberg { 958cf1d081fSJohan Hedberg struct hci_rp_le_read_white_list_size *rp = (void *) skb->data; 959cf1d081fSJohan Hedberg 960cf1d081fSJohan Hedberg BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size); 961cf1d081fSJohan Hedberg 962cf1d081fSJohan Hedberg if (!rp->status) 963cf1d081fSJohan Hedberg hdev->le_white_list_size = rp->size; 964cf1d081fSJohan Hedberg } 965cf1d081fSJohan Hedberg 9669b008c04SJohan Hedberg static void hci_cc_le_read_supported_states(struct hci_dev *hdev, 9679b008c04SJohan Hedberg struct sk_buff *skb) 9689b008c04SJohan Hedberg { 9699b008c04SJohan Hedberg struct hci_rp_le_read_supported_states *rp = (void *) skb->data; 9709b008c04SJohan Hedberg 9719b008c04SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 9729b008c04SJohan Hedberg 9739b008c04SJohan Hedberg if (!rp->status) 9749b008c04SJohan Hedberg memcpy(hdev->le_states, rp->le_states, 8); 9759b008c04SJohan Hedberg } 9769b008c04SJohan Hedberg 9776039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev, 978f9b49306SAndre Guedes struct sk_buff *skb) 979f9b49306SAndre Guedes { 98006199cf8SJohan Hedberg struct hci_cp_write_le_host_supported *sent; 981f9b49306SAndre Guedes __u8 status = *((__u8 *) skb->data); 982f9b49306SAndre Guedes 9839f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 984f9b49306SAndre Guedes 98506199cf8SJohan Hedberg sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED); 9868f984dfaSJohan Hedberg if (!sent) 987f9b49306SAndre Guedes return; 988f9b49306SAndre Guedes 9898f984dfaSJohan Hedberg if (!status) { 9908f984dfaSJohan Hedberg if (sent->le) 9918f984dfaSJohan Hedberg hdev->host_features[0] |= LMP_HOST_LE; 9928f984dfaSJohan Hedberg else 9938f984dfaSJohan Hedberg hdev->host_features[0] &= ~LMP_HOST_LE; 99453b2caabSJohan Hedberg 99553b2caabSJohan Hedberg if (sent->simul) 99653b2caabSJohan Hedberg hdev->host_features[0] |= LMP_HOST_LE_BREDR; 99753b2caabSJohan Hedberg else 99853b2caabSJohan Hedberg hdev->host_features[0] &= ~LMP_HOST_LE_BREDR; 9998f984dfaSJohan Hedberg } 10008f984dfaSJohan Hedberg 10018f984dfaSJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags) && 10028f984dfaSJohan Hedberg !test_bit(HCI_INIT, &hdev->flags)) 10038f984dfaSJohan Hedberg mgmt_le_enable_complete(hdev, sent->le, status); 1004f9b49306SAndre Guedes } 1005f9b49306SAndre Guedes 100693c284eeSAndrei Emeltchenko static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev, 100793c284eeSAndrei Emeltchenko struct sk_buff *skb) 100893c284eeSAndrei Emeltchenko { 100993c284eeSAndrei Emeltchenko struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data; 101093c284eeSAndrei Emeltchenko 101193c284eeSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x", 101293c284eeSAndrei Emeltchenko hdev->name, rp->status, rp->phy_handle); 101393c284eeSAndrei Emeltchenko 101493c284eeSAndrei Emeltchenko if (rp->status) 101593c284eeSAndrei Emeltchenko return; 101693c284eeSAndrei Emeltchenko 101793c284eeSAndrei Emeltchenko amp_write_rem_assoc_continue(hdev, rp->phy_handle); 101893c284eeSAndrei Emeltchenko } 101993c284eeSAndrei Emeltchenko 10206039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 1021a9de9248SMarcel Holtmann { 10229f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1023a9de9248SMarcel Holtmann 1024a9de9248SMarcel Holtmann if (status) { 1025a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 102656e5cb86SJohan Hedberg hci_dev_lock(hdev); 1027a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 10287a135109SAndre Guedes mgmt_start_discovery_failed(hdev, status); 102956e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1030314b2381SJohan Hedberg return; 1031314b2381SJohan Hedberg } 1032314b2381SJohan Hedberg 103389352e7dSAndre Guedes set_bit(HCI_INQUIRY, &hdev->flags); 103489352e7dSAndre Guedes 103556e5cb86SJohan Hedberg hci_dev_lock(hdev); 1036343f935bSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_FINDING); 103756e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1038a9de9248SMarcel Holtmann } 1039a9de9248SMarcel Holtmann 10406039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 10411da177e4SLinus Torvalds { 1042a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 10431da177e4SLinus Torvalds struct hci_conn *conn; 10441da177e4SLinus Torvalds 10459f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1046a9de9248SMarcel Holtmann 1047a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 10481da177e4SLinus Torvalds if (!cp) 10491da177e4SLinus Torvalds return; 10501da177e4SLinus Torvalds 10511da177e4SLinus Torvalds hci_dev_lock(hdev); 10521da177e4SLinus Torvalds 10531da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 10541da177e4SLinus Torvalds 10556ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn); 10561da177e4SLinus Torvalds 10571da177e4SLinus Torvalds if (status) { 10581da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 10594c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 10601da177e4SLinus Torvalds conn->state = BT_CLOSED; 10611da177e4SLinus Torvalds hci_proto_connect_cfm(conn, status); 10621da177e4SLinus Torvalds hci_conn_del(conn); 10634c67bc74SMarcel Holtmann } else 10644c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 10651da177e4SLinus Torvalds } 10661da177e4SLinus Torvalds } else { 10671da177e4SLinus Torvalds if (!conn) { 10681da177e4SLinus Torvalds conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); 10691da177e4SLinus Torvalds if (conn) { 1070a0c808b3SJohan Hedberg conn->out = true; 10711da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 10721da177e4SLinus Torvalds } else 1073893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 10741da177e4SLinus Torvalds } 10751da177e4SLinus Torvalds } 10761da177e4SLinus Torvalds 10771da177e4SLinus Torvalds hci_dev_unlock(hdev); 10781da177e4SLinus Torvalds } 10791da177e4SLinus Torvalds 1080a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 10811da177e4SLinus Torvalds { 1082a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 10831da177e4SLinus Torvalds struct hci_conn *acl, *sco; 10841da177e4SLinus Torvalds __u16 handle; 10851da177e4SLinus Torvalds 10869f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1087b6a0dc82SMarcel Holtmann 1088a9de9248SMarcel Holtmann if (!status) 1089a9de9248SMarcel Holtmann return; 1090a9de9248SMarcel Holtmann 1091a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 10921da177e4SLinus Torvalds if (!cp) 1093a9de9248SMarcel Holtmann return; 10941da177e4SLinus Torvalds 10951da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 10961da177e4SLinus Torvalds 10979f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, handle); 10981da177e4SLinus Torvalds 10991da177e4SLinus Torvalds hci_dev_lock(hdev); 11001da177e4SLinus Torvalds 11011da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 11025a08ecceSAndrei Emeltchenko if (acl) { 11035a08ecceSAndrei Emeltchenko sco = acl->link; 11045a08ecceSAndrei Emeltchenko if (sco) { 11051da177e4SLinus Torvalds sco->state = BT_CLOSED; 11061da177e4SLinus Torvalds 11071da177e4SLinus Torvalds hci_proto_connect_cfm(sco, status); 11081da177e4SLinus Torvalds hci_conn_del(sco); 11091da177e4SLinus Torvalds } 11105a08ecceSAndrei Emeltchenko } 11111da177e4SLinus Torvalds 11121da177e4SLinus Torvalds hci_dev_unlock(hdev); 11131da177e4SLinus Torvalds } 11141da177e4SLinus Torvalds 1115f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 1116f8558555SMarcel Holtmann { 1117f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 1118f8558555SMarcel Holtmann struct hci_conn *conn; 1119f8558555SMarcel Holtmann 11209f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1121f8558555SMarcel Holtmann 1122f8558555SMarcel Holtmann if (!status) 1123f8558555SMarcel Holtmann return; 1124f8558555SMarcel Holtmann 1125f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 1126f8558555SMarcel Holtmann if (!cp) 1127f8558555SMarcel Holtmann return; 1128f8558555SMarcel Holtmann 1129f8558555SMarcel Holtmann hci_dev_lock(hdev); 1130f8558555SMarcel Holtmann 1131f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1132f8558555SMarcel Holtmann if (conn) { 1133f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1134f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1135f8558555SMarcel Holtmann hci_conn_put(conn); 1136f8558555SMarcel Holtmann } 1137f8558555SMarcel Holtmann } 1138f8558555SMarcel Holtmann 1139f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1140f8558555SMarcel Holtmann } 1141f8558555SMarcel Holtmann 1142f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 1143f8558555SMarcel Holtmann { 1144f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 1145f8558555SMarcel Holtmann struct hci_conn *conn; 1146f8558555SMarcel Holtmann 11479f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1148f8558555SMarcel Holtmann 1149f8558555SMarcel Holtmann if (!status) 1150f8558555SMarcel Holtmann return; 1151f8558555SMarcel Holtmann 1152f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 1153f8558555SMarcel Holtmann if (!cp) 1154f8558555SMarcel Holtmann return; 1155f8558555SMarcel Holtmann 1156f8558555SMarcel Holtmann hci_dev_lock(hdev); 1157f8558555SMarcel Holtmann 1158f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1159f8558555SMarcel Holtmann if (conn) { 1160f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1161f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1162f8558555SMarcel Holtmann hci_conn_put(conn); 1163f8558555SMarcel Holtmann } 1164f8558555SMarcel Holtmann } 1165f8558555SMarcel Holtmann 1166f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1167f8558555SMarcel Holtmann } 1168f8558555SMarcel Holtmann 1169127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev, 1170392599b9SJohan Hedberg struct hci_conn *conn) 1171392599b9SJohan Hedberg { 1172392599b9SJohan Hedberg if (conn->state != BT_CONFIG || !conn->out) 1173392599b9SJohan Hedberg return 0; 1174392599b9SJohan Hedberg 1175765c2a96SJohan Hedberg if (conn->pending_sec_level == BT_SECURITY_SDP) 1176392599b9SJohan Hedberg return 0; 1177392599b9SJohan Hedberg 1178392599b9SJohan Hedberg /* Only request authentication for SSP connections or non-SSP 1179e9bf2bf0SVinicius Costa Gomes * devices with sec_level HIGH or if MITM protection is requested */ 1180807deac2SGustavo Padovan if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) && 1181807deac2SGustavo Padovan conn->pending_sec_level != BT_SECURITY_HIGH) 1182392599b9SJohan Hedberg return 0; 1183392599b9SJohan Hedberg 1184392599b9SJohan Hedberg return 1; 1185392599b9SJohan Hedberg } 1186392599b9SJohan Hedberg 11876039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev, 118800abfe44SGustavo F. Padovan struct inquiry_entry *e) 118930dc78e1SJohan Hedberg { 119030dc78e1SJohan Hedberg struct hci_cp_remote_name_req cp; 119130dc78e1SJohan Hedberg 119230dc78e1SJohan Hedberg memset(&cp, 0, sizeof(cp)); 119330dc78e1SJohan Hedberg 119430dc78e1SJohan Hedberg bacpy(&cp.bdaddr, &e->data.bdaddr); 119530dc78e1SJohan Hedberg cp.pscan_rep_mode = e->data.pscan_rep_mode; 119630dc78e1SJohan Hedberg cp.pscan_mode = e->data.pscan_mode; 119730dc78e1SJohan Hedberg cp.clock_offset = e->data.clock_offset; 119830dc78e1SJohan Hedberg 119930dc78e1SJohan Hedberg return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 120030dc78e1SJohan Hedberg } 120130dc78e1SJohan Hedberg 1202b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev) 120330dc78e1SJohan Hedberg { 120430dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 120530dc78e1SJohan Hedberg struct inquiry_entry *e; 120630dc78e1SJohan Hedberg 1207b644ba33SJohan Hedberg if (list_empty(&discov->resolve)) 1208b644ba33SJohan Hedberg return false; 1209b644ba33SJohan Hedberg 1210b644ba33SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 1211c810089cSRam Malovany if (!e) 1212c810089cSRam Malovany return false; 1213c810089cSRam Malovany 1214b644ba33SJohan Hedberg if (hci_resolve_name(hdev, e) == 0) { 1215b644ba33SJohan Hedberg e->name_state = NAME_PENDING; 1216b644ba33SJohan Hedberg return true; 1217b644ba33SJohan Hedberg } 1218b644ba33SJohan Hedberg 1219b644ba33SJohan Hedberg return false; 1220b644ba33SJohan Hedberg } 1221b644ba33SJohan Hedberg 1222b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn, 1223b644ba33SJohan Hedberg bdaddr_t *bdaddr, u8 *name, u8 name_len) 1224b644ba33SJohan Hedberg { 1225b644ba33SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 1226b644ba33SJohan Hedberg struct inquiry_entry *e; 1227b644ba33SJohan Hedberg 1228b644ba33SJohan Hedberg if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 122904124681SGustavo F. Padovan mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name, 123004124681SGustavo F. Padovan name_len, conn->dev_class); 1231b644ba33SJohan Hedberg 1232b644ba33SJohan Hedberg if (discov->state == DISCOVERY_STOPPED) 1233b644ba33SJohan Hedberg return; 1234b644ba33SJohan Hedberg 123530dc78e1SJohan Hedberg if (discov->state == DISCOVERY_STOPPING) 123630dc78e1SJohan Hedberg goto discov_complete; 123730dc78e1SJohan Hedberg 123830dc78e1SJohan Hedberg if (discov->state != DISCOVERY_RESOLVING) 123930dc78e1SJohan Hedberg return; 124030dc78e1SJohan Hedberg 124130dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING); 12427cc8380eSRam Malovany /* If the device was not found in a list of found devices names of which 12437cc8380eSRam Malovany * are pending. there is no need to continue resolving a next name as it 12447cc8380eSRam Malovany * will be done upon receiving another Remote Name Request Complete 12457cc8380eSRam Malovany * Event */ 12467cc8380eSRam Malovany if (!e) 12477cc8380eSRam Malovany return; 12487cc8380eSRam Malovany 124930dc78e1SJohan Hedberg list_del(&e->list); 12507cc8380eSRam Malovany if (name) { 12517cc8380eSRam Malovany e->name_state = NAME_KNOWN; 1252b644ba33SJohan Hedberg mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, 1253b644ba33SJohan Hedberg e->data.rssi, name, name_len); 1254c3e7c0d9SRam Malovany } else { 1255c3e7c0d9SRam Malovany e->name_state = NAME_NOT_KNOWN; 125630dc78e1SJohan Hedberg } 125730dc78e1SJohan Hedberg 1258b644ba33SJohan Hedberg if (hci_resolve_next_name(hdev)) 125930dc78e1SJohan Hedberg return; 126030dc78e1SJohan Hedberg 126130dc78e1SJohan Hedberg discov_complete: 126230dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 126330dc78e1SJohan Hedberg } 126430dc78e1SJohan Hedberg 1265a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 12661da177e4SLinus Torvalds { 1267127178d2SJohan Hedberg struct hci_cp_remote_name_req *cp; 1268127178d2SJohan Hedberg struct hci_conn *conn; 1269127178d2SJohan Hedberg 12709f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1271127178d2SJohan Hedberg 1272127178d2SJohan Hedberg /* If successful wait for the name req complete event before 1273127178d2SJohan Hedberg * checking for the need to do authentication */ 1274127178d2SJohan Hedberg if (!status) 1275127178d2SJohan Hedberg return; 1276127178d2SJohan Hedberg 1277127178d2SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); 1278127178d2SJohan Hedberg if (!cp) 1279127178d2SJohan Hedberg return; 1280127178d2SJohan Hedberg 1281127178d2SJohan Hedberg hci_dev_lock(hdev); 1282127178d2SJohan Hedberg 1283127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 1284b644ba33SJohan Hedberg 1285b644ba33SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1286b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0); 1287b644ba33SJohan Hedberg 128879c6c70cSJohan Hedberg if (!conn) 128979c6c70cSJohan Hedberg goto unlock; 129079c6c70cSJohan Hedberg 129179c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 129279c6c70cSJohan Hedberg goto unlock; 129379c6c70cSJohan Hedberg 129451a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 1295127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1296127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1297127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1298127178d2SJohan Hedberg } 1299127178d2SJohan Hedberg 130079c6c70cSJohan Hedberg unlock: 1301127178d2SJohan Hedberg hci_dev_unlock(hdev); 1302a9de9248SMarcel Holtmann } 13031da177e4SLinus Torvalds 1304769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 1305769be974SMarcel Holtmann { 1306769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 1307769be974SMarcel Holtmann struct hci_conn *conn; 1308769be974SMarcel Holtmann 13099f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1310769be974SMarcel Holtmann 1311769be974SMarcel Holtmann if (!status) 1312769be974SMarcel Holtmann return; 1313769be974SMarcel Holtmann 1314769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 1315769be974SMarcel Holtmann if (!cp) 1316769be974SMarcel Holtmann return; 1317769be974SMarcel Holtmann 1318769be974SMarcel Holtmann hci_dev_lock(hdev); 1319769be974SMarcel Holtmann 1320769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1321769be974SMarcel Holtmann if (conn) { 1322769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1323769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1324769be974SMarcel Holtmann hci_conn_put(conn); 1325769be974SMarcel Holtmann } 1326769be974SMarcel Holtmann } 1327769be974SMarcel Holtmann 1328769be974SMarcel Holtmann hci_dev_unlock(hdev); 1329769be974SMarcel Holtmann } 1330769be974SMarcel Holtmann 1331769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 1332769be974SMarcel Holtmann { 1333769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features *cp; 1334769be974SMarcel Holtmann struct hci_conn *conn; 1335769be974SMarcel Holtmann 13369f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1337769be974SMarcel Holtmann 1338769be974SMarcel Holtmann if (!status) 1339769be974SMarcel Holtmann return; 1340769be974SMarcel Holtmann 1341769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 1342769be974SMarcel Holtmann if (!cp) 1343769be974SMarcel Holtmann return; 1344769be974SMarcel Holtmann 1345769be974SMarcel Holtmann hci_dev_lock(hdev); 1346769be974SMarcel Holtmann 1347769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1348769be974SMarcel Holtmann if (conn) { 1349769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1350769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1351769be974SMarcel Holtmann hci_conn_put(conn); 1352769be974SMarcel Holtmann } 1353769be974SMarcel Holtmann } 1354769be974SMarcel Holtmann 1355769be974SMarcel Holtmann hci_dev_unlock(hdev); 1356769be974SMarcel Holtmann } 1357769be974SMarcel Holtmann 1358a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 1359a9de9248SMarcel Holtmann { 1360b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 1361b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 1362b6a0dc82SMarcel Holtmann __u16 handle; 1363b6a0dc82SMarcel Holtmann 13649f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1365b6a0dc82SMarcel Holtmann 1366b6a0dc82SMarcel Holtmann if (!status) 1367b6a0dc82SMarcel Holtmann return; 1368b6a0dc82SMarcel Holtmann 1369b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 1370b6a0dc82SMarcel Holtmann if (!cp) 1371b6a0dc82SMarcel Holtmann return; 1372b6a0dc82SMarcel Holtmann 1373b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 1374b6a0dc82SMarcel Holtmann 13759f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, handle); 1376b6a0dc82SMarcel Holtmann 1377b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 1378b6a0dc82SMarcel Holtmann 1379b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 13805a08ecceSAndrei Emeltchenko if (acl) { 13815a08ecceSAndrei Emeltchenko sco = acl->link; 13825a08ecceSAndrei Emeltchenko if (sco) { 1383b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 1384b6a0dc82SMarcel Holtmann 1385b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(sco, status); 1386b6a0dc82SMarcel Holtmann hci_conn_del(sco); 1387b6a0dc82SMarcel Holtmann } 13885a08ecceSAndrei Emeltchenko } 1389b6a0dc82SMarcel Holtmann 1390b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 1391a9de9248SMarcel Holtmann } 1392a9de9248SMarcel Holtmann 1393a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 1394a9de9248SMarcel Holtmann { 1395a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 139604837f64SMarcel Holtmann struct hci_conn *conn; 139704837f64SMarcel Holtmann 13989f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1399a9de9248SMarcel Holtmann 1400a9de9248SMarcel Holtmann if (!status) 1401a9de9248SMarcel Holtmann return; 1402a9de9248SMarcel Holtmann 1403a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 140404837f64SMarcel Holtmann if (!cp) 1405a9de9248SMarcel Holtmann return; 140604837f64SMarcel Holtmann 140704837f64SMarcel Holtmann hci_dev_lock(hdev); 140804837f64SMarcel Holtmann 140904837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1410e73439d8SMarcel Holtmann if (conn) { 141151a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 141204837f64SMarcel Holtmann 141351a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1414e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1415e73439d8SMarcel Holtmann } 1416e73439d8SMarcel Holtmann 141704837f64SMarcel Holtmann hci_dev_unlock(hdev); 141804837f64SMarcel Holtmann } 141904837f64SMarcel Holtmann 1420a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 1421a9de9248SMarcel Holtmann { 1422a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 142304837f64SMarcel Holtmann struct hci_conn *conn; 142404837f64SMarcel Holtmann 14259f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1426a9de9248SMarcel Holtmann 1427a9de9248SMarcel Holtmann if (!status) 1428a9de9248SMarcel Holtmann return; 1429a9de9248SMarcel Holtmann 1430a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 143104837f64SMarcel Holtmann if (!cp) 1432a9de9248SMarcel Holtmann return; 143304837f64SMarcel Holtmann 143404837f64SMarcel Holtmann hci_dev_lock(hdev); 143504837f64SMarcel Holtmann 143604837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1437e73439d8SMarcel Holtmann if (conn) { 143851a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 143904837f64SMarcel Holtmann 144051a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1441e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1442e73439d8SMarcel Holtmann } 1443e73439d8SMarcel Holtmann 144404837f64SMarcel Holtmann hci_dev_unlock(hdev); 144504837f64SMarcel Holtmann } 144604837f64SMarcel Holtmann 144788c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) 144888c3df13SJohan Hedberg { 144988c3df13SJohan Hedberg struct hci_cp_disconnect *cp; 145088c3df13SJohan Hedberg struct hci_conn *conn; 145188c3df13SJohan Hedberg 145288c3df13SJohan Hedberg if (!status) 145388c3df13SJohan Hedberg return; 145488c3df13SJohan Hedberg 145588c3df13SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT); 145688c3df13SJohan Hedberg if (!cp) 145788c3df13SJohan Hedberg return; 145888c3df13SJohan Hedberg 145988c3df13SJohan Hedberg hci_dev_lock(hdev); 146088c3df13SJohan Hedberg 146188c3df13SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 146288c3df13SJohan Hedberg if (conn) 146388c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 146488c3df13SJohan Hedberg conn->dst_type, status); 146588c3df13SJohan Hedberg 146688c3df13SJohan Hedberg hci_dev_unlock(hdev); 146788c3df13SJohan Hedberg } 146888c3df13SJohan Hedberg 1469fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) 1470fcd89c09SVille Tervo { 1471fcd89c09SVille Tervo struct hci_conn *conn; 1472fcd89c09SVille Tervo 14739f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1474fcd89c09SVille Tervo 1475f00a06acSAndre Guedes if (status) { 1476fcd89c09SVille Tervo hci_dev_lock(hdev); 1477fcd89c09SVille Tervo 14780c95ab78SAndre Guedes conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); 1479f00a06acSAndre Guedes if (!conn) { 1480f00a06acSAndre Guedes hci_dev_unlock(hdev); 1481f00a06acSAndre Guedes return; 1482f00a06acSAndre Guedes } 1483fcd89c09SVille Tervo 14846ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn); 1485fcd89c09SVille Tervo 1486fcd89c09SVille Tervo conn->state = BT_CLOSED; 14870c95ab78SAndre Guedes mgmt_connect_failed(hdev, &conn->dst, conn->type, 1488328c9248SHemant Gupta conn->dst_type, status); 1489fcd89c09SVille Tervo hci_proto_connect_cfm(conn, status); 1490fcd89c09SVille Tervo hci_conn_del(conn); 1491fcd89c09SVille Tervo 1492fcd89c09SVille Tervo hci_dev_unlock(hdev); 1493fcd89c09SVille Tervo } 1494f00a06acSAndre Guedes } 1495fcd89c09SVille Tervo 1496a02226d6SAndrei Emeltchenko static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status) 1497a02226d6SAndrei Emeltchenko { 149893c284eeSAndrei Emeltchenko struct hci_cp_create_phy_link *cp; 149993c284eeSAndrei Emeltchenko 1500a02226d6SAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 150193c284eeSAndrei Emeltchenko 150293c284eeSAndrei Emeltchenko cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK); 150393c284eeSAndrei Emeltchenko if (!cp) 150493c284eeSAndrei Emeltchenko return; 150593c284eeSAndrei Emeltchenko 1506e58917b9SAndrei Emeltchenko hci_dev_lock(hdev); 1507e58917b9SAndrei Emeltchenko 1508e58917b9SAndrei Emeltchenko if (status) { 1509e58917b9SAndrei Emeltchenko struct hci_conn *hcon; 1510e58917b9SAndrei Emeltchenko 1511e58917b9SAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle); 1512e58917b9SAndrei Emeltchenko if (hcon) 1513e58917b9SAndrei Emeltchenko hci_conn_del(hcon); 1514e58917b9SAndrei Emeltchenko } else { 151593c284eeSAndrei Emeltchenko amp_write_remote_assoc(hdev, cp->phy_handle); 1516a02226d6SAndrei Emeltchenko } 1517a02226d6SAndrei Emeltchenko 1518e58917b9SAndrei Emeltchenko hci_dev_unlock(hdev); 1519e58917b9SAndrei Emeltchenko } 1520e58917b9SAndrei Emeltchenko 15210b26ab9dSAndrei Emeltchenko static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status) 15220b26ab9dSAndrei Emeltchenko { 15230b26ab9dSAndrei Emeltchenko struct hci_cp_accept_phy_link *cp; 15240b26ab9dSAndrei Emeltchenko 15250b26ab9dSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 15260b26ab9dSAndrei Emeltchenko 15270b26ab9dSAndrei Emeltchenko if (status) 15280b26ab9dSAndrei Emeltchenko return; 15290b26ab9dSAndrei Emeltchenko 15300b26ab9dSAndrei Emeltchenko cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK); 15310b26ab9dSAndrei Emeltchenko if (!cp) 15320b26ab9dSAndrei Emeltchenko return; 15330b26ab9dSAndrei Emeltchenko 15340b26ab9dSAndrei Emeltchenko amp_write_remote_assoc(hdev, cp->phy_handle); 15350b26ab9dSAndrei Emeltchenko } 15360b26ab9dSAndrei Emeltchenko 15376039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 15381da177e4SLinus Torvalds { 15391da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 154030dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 154130dc78e1SJohan Hedberg struct inquiry_entry *e; 15421da177e4SLinus Torvalds 15439f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 15441da177e4SLinus Torvalds 15459238f36aSJohan Hedberg hci_req_cmd_complete(hdev, HCI_OP_INQUIRY, status); 15466bd57416SMarcel Holtmann 1547a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 154889352e7dSAndre Guedes 154989352e7dSAndre Guedes if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) 155089352e7dSAndre Guedes return; 155189352e7dSAndre Guedes 1552a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 155330dc78e1SJohan Hedberg return; 155430dc78e1SJohan Hedberg 155556e5cb86SJohan Hedberg hci_dev_lock(hdev); 155630dc78e1SJohan Hedberg 1557343f935bSAndre Guedes if (discov->state != DISCOVERY_FINDING) 155830dc78e1SJohan Hedberg goto unlock; 155930dc78e1SJohan Hedberg 156030dc78e1SJohan Hedberg if (list_empty(&discov->resolve)) { 1561ff9ef578SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 156230dc78e1SJohan Hedberg goto unlock; 156330dc78e1SJohan Hedberg } 156430dc78e1SJohan Hedberg 156530dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 156630dc78e1SJohan Hedberg if (e && hci_resolve_name(hdev, e) == 0) { 156730dc78e1SJohan Hedberg e->name_state = NAME_PENDING; 156830dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_RESOLVING); 156930dc78e1SJohan Hedberg } else { 157030dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 157130dc78e1SJohan Hedberg } 157230dc78e1SJohan Hedberg 157330dc78e1SJohan Hedberg unlock: 157456e5cb86SJohan Hedberg hci_dev_unlock(hdev); 15751da177e4SLinus Torvalds } 15761da177e4SLinus Torvalds 15776039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 15781da177e4SLinus Torvalds { 157945bb4bf0SMarcel Holtmann struct inquiry_data data; 1580a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 15811da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 15821da177e4SLinus Torvalds 15831da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 15841da177e4SLinus Torvalds 158545bb4bf0SMarcel Holtmann if (!num_rsp) 158645bb4bf0SMarcel Holtmann return; 158745bb4bf0SMarcel Holtmann 15881519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 15891519cc17SAndre Guedes return; 15901519cc17SAndre Guedes 15911da177e4SLinus Torvalds hci_dev_lock(hdev); 159245bb4bf0SMarcel Holtmann 1593e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 1594388fc8faSJohan Hedberg bool name_known, ssp; 15953175405bSJohan Hedberg 15961da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 15971da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 15981da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 15991da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 16001da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 16011da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 16021da177e4SLinus Torvalds data.rssi = 0x00; 160341a96212SMarcel Holtmann data.ssp_mode = 0x00; 16043175405bSJohan Hedberg 1605388fc8faSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp); 160648264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 160704124681SGustavo F. Padovan info->dev_class, 0, !name_known, ssp, NULL, 160804124681SGustavo F. Padovan 0); 16091da177e4SLinus Torvalds } 161045bb4bf0SMarcel Holtmann 16111da177e4SLinus Torvalds hci_dev_unlock(hdev); 16121da177e4SLinus Torvalds } 16131da177e4SLinus Torvalds 16146039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 16151da177e4SLinus Torvalds { 1616a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 1617a9de9248SMarcel Holtmann struct hci_conn *conn; 16181da177e4SLinus Torvalds 1619a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 162045bb4bf0SMarcel Holtmann 16211da177e4SLinus Torvalds hci_dev_lock(hdev); 162245bb4bf0SMarcel Holtmann 1623a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 16249499237aSMarcel Holtmann if (!conn) { 16259499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 16269499237aSMarcel Holtmann goto unlock; 16279499237aSMarcel Holtmann 16289499237aSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 1629a9de9248SMarcel Holtmann if (!conn) 1630a9de9248SMarcel Holtmann goto unlock; 163145bb4bf0SMarcel Holtmann 16329499237aSMarcel Holtmann conn->type = SCO_LINK; 16339499237aSMarcel Holtmann } 16349499237aSMarcel Holtmann 1635a9de9248SMarcel Holtmann if (!ev->status) { 1636a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 1637769be974SMarcel Holtmann 1638769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 1639769be974SMarcel Holtmann conn->state = BT_CONFIG; 1640769be974SMarcel Holtmann hci_conn_hold(conn); 1641a9ea3ed9SSzymon Janc 1642a9ea3ed9SSzymon Janc if (!conn->out && !hci_conn_ssp_enabled(conn) && 1643a9ea3ed9SSzymon Janc !hci_find_link_key(hdev, &ev->bdaddr)) 1644a9ea3ed9SSzymon Janc conn->disc_timeout = HCI_PAIRING_TIMEOUT; 1645a9ea3ed9SSzymon Janc else 1646052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1647769be974SMarcel Holtmann } else 1648a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 1649a9de9248SMarcel Holtmann 16509eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 16517d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 16527d0db0a3SMarcel Holtmann 1653a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 1654a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1655a9de9248SMarcel Holtmann 1656a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 1657a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1658a9de9248SMarcel Holtmann 1659a9de9248SMarcel Holtmann /* Get remote features */ 1660a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 1661a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 1662a9de9248SMarcel Holtmann cp.handle = ev->handle; 1663769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 1664769be974SMarcel Holtmann sizeof(cp), &cp); 166545bb4bf0SMarcel Holtmann } 1666a9de9248SMarcel Holtmann 1667a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 1668d095c1ebSAndrei Emeltchenko if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) { 1669a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 1670a9de9248SMarcel Holtmann cp.handle = ev->handle; 1671a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 167204124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp), 167304124681SGustavo F. Padovan &cp); 1674a9de9248SMarcel Holtmann } 167517d5c04cSJohan Hedberg } else { 1676a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 167717d5c04cSJohan Hedberg if (conn->type == ACL_LINK) 1678744cf19eSJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 167948264f06SJohan Hedberg conn->dst_type, ev->status); 168017d5c04cSJohan Hedberg } 168145bb4bf0SMarcel Holtmann 1682e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 1683e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 168445bb4bf0SMarcel Holtmann 1685769be974SMarcel Holtmann if (ev->status) { 1686a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1687a9de9248SMarcel Holtmann hci_conn_del(conn); 1688c89b6e6bSMarcel Holtmann } else if (ev->link_type != ACL_LINK) 1689c89b6e6bSMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1690a9de9248SMarcel Holtmann 1691a9de9248SMarcel Holtmann unlock: 16921da177e4SLinus Torvalds hci_dev_unlock(hdev); 1693a9de9248SMarcel Holtmann 1694a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 16951da177e4SLinus Torvalds } 16961da177e4SLinus Torvalds 169720714bfeSFrédéric Dalleau void hci_conn_accept(struct hci_conn *conn, int mask) 169820714bfeSFrédéric Dalleau { 169920714bfeSFrédéric Dalleau struct hci_dev *hdev = conn->hdev; 170020714bfeSFrédéric Dalleau 170120714bfeSFrédéric Dalleau BT_DBG("conn %p", conn); 170220714bfeSFrédéric Dalleau 170320714bfeSFrédéric Dalleau conn->state = BT_CONFIG; 170420714bfeSFrédéric Dalleau 170520714bfeSFrédéric Dalleau if (!lmp_esco_capable(hdev)) { 170620714bfeSFrédéric Dalleau struct hci_cp_accept_conn_req cp; 170720714bfeSFrédéric Dalleau 170820714bfeSFrédéric Dalleau bacpy(&cp.bdaddr, &conn->dst); 170920714bfeSFrédéric Dalleau 171020714bfeSFrédéric Dalleau if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 171120714bfeSFrédéric Dalleau cp.role = 0x00; /* Become master */ 171220714bfeSFrédéric Dalleau else 171320714bfeSFrédéric Dalleau cp.role = 0x01; /* Remain slave */ 171420714bfeSFrédéric Dalleau 171520714bfeSFrédéric Dalleau hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp); 171620714bfeSFrédéric Dalleau } else /* lmp_esco_capable(hdev)) */ { 171720714bfeSFrédéric Dalleau struct hci_cp_accept_sync_conn_req cp; 171820714bfeSFrédéric Dalleau 171920714bfeSFrédéric Dalleau bacpy(&cp.bdaddr, &conn->dst); 172020714bfeSFrédéric Dalleau cp.pkt_type = cpu_to_le16(conn->pkt_type); 172120714bfeSFrédéric Dalleau 172220714bfeSFrédéric Dalleau cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40); 172320714bfeSFrédéric Dalleau cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40); 172420714bfeSFrédéric Dalleau cp.max_latency = __constant_cpu_to_le16(0xffff); 172520714bfeSFrédéric Dalleau cp.content_format = cpu_to_le16(hdev->voice_setting); 172620714bfeSFrédéric Dalleau cp.retrans_effort = 0xff; 172720714bfeSFrédéric Dalleau 172820714bfeSFrédéric Dalleau hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 172920714bfeSFrédéric Dalleau sizeof(cp), &cp); 173020714bfeSFrédéric Dalleau } 173120714bfeSFrédéric Dalleau } 173220714bfeSFrédéric Dalleau 17336039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 17341da177e4SLinus Torvalds { 1735a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 17361da177e4SLinus Torvalds int mask = hdev->link_mode; 173720714bfeSFrédéric Dalleau __u8 flags = 0; 17381da177e4SLinus Torvalds 17396ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr, 1740807deac2SGustavo Padovan ev->link_type); 17411da177e4SLinus Torvalds 174220714bfeSFrédéric Dalleau mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type, 174320714bfeSFrédéric Dalleau &flags); 17441da177e4SLinus Torvalds 1745138d22efSSzymon Janc if ((mask & HCI_LM_ACCEPT) && 1746138d22efSSzymon Janc !hci_blacklist_lookup(hdev, &ev->bdaddr)) { 17471da177e4SLinus Torvalds /* Connection accepted */ 1748c7bdd502SMarcel Holtmann struct inquiry_entry *ie; 17491da177e4SLinus Torvalds struct hci_conn *conn; 17501da177e4SLinus Torvalds 17511da177e4SLinus Torvalds hci_dev_lock(hdev); 1752b6a0dc82SMarcel Holtmann 1753cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 1754cc11b9c1SAndrei Emeltchenko if (ie) 1755c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 1756c7bdd502SMarcel Holtmann 17578fc9ced3SGustavo Padovan conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, 17588fc9ced3SGustavo Padovan &ev->bdaddr); 17591da177e4SLinus Torvalds if (!conn) { 1760cc11b9c1SAndrei Emeltchenko conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); 1761cc11b9c1SAndrei Emeltchenko if (!conn) { 1762893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 17631da177e4SLinus Torvalds hci_dev_unlock(hdev); 17641da177e4SLinus Torvalds return; 17651da177e4SLinus Torvalds } 17661da177e4SLinus Torvalds } 1767b6a0dc82SMarcel Holtmann 17681da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 1769b6a0dc82SMarcel Holtmann 17701da177e4SLinus Torvalds hci_dev_unlock(hdev); 17711da177e4SLinus Torvalds 177220714bfeSFrédéric Dalleau if (ev->link_type == ACL_LINK || 177320714bfeSFrédéric Dalleau (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) { 1774b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 177520714bfeSFrédéric Dalleau conn->state = BT_CONNECT; 1776b6a0dc82SMarcel Holtmann 17771da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 17781da177e4SLinus Torvalds 17791da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 17801da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 17811da177e4SLinus Torvalds else 17821da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 17831da177e4SLinus Torvalds 178404124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), 178504124681SGustavo F. Padovan &cp); 178620714bfeSFrédéric Dalleau } else if (!(flags & HCI_PROTO_DEFER)) { 1787b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 178820714bfeSFrédéric Dalleau conn->state = BT_CONNECT; 1789b6a0dc82SMarcel Holtmann 1790b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 1791a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1792b6a0dc82SMarcel Holtmann 179382781e63SAndrei Emeltchenko cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40); 179482781e63SAndrei Emeltchenko cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40); 179582781e63SAndrei Emeltchenko cp.max_latency = __constant_cpu_to_le16(0xffff); 1796b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 1797b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 1798b6a0dc82SMarcel Holtmann 1799b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 1800b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 180120714bfeSFrédéric Dalleau } else { 180220714bfeSFrédéric Dalleau conn->state = BT_CONNECT2; 180320714bfeSFrédéric Dalleau hci_proto_connect_cfm(conn, 0); 180420714bfeSFrédéric Dalleau hci_conn_put(conn); 1805b6a0dc82SMarcel Holtmann } 18061da177e4SLinus Torvalds } else { 18071da177e4SLinus Torvalds /* Connection rejected */ 18081da177e4SLinus Torvalds struct hci_cp_reject_conn_req cp; 18091da177e4SLinus Torvalds 18101da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 18119f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_REJ_BAD_ADDR; 1812a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 18131da177e4SLinus Torvalds } 18141da177e4SLinus Torvalds } 18151da177e4SLinus Torvalds 1816f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err) 1817f0d6a0eaSMikel Astiz { 1818f0d6a0eaSMikel Astiz switch (err) { 1819f0d6a0eaSMikel Astiz case HCI_ERROR_CONNECTION_TIMEOUT: 1820f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_TIMEOUT; 1821f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_USER_TERM: 1822f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_LOW_RESOURCES: 1823f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_POWER_OFF: 1824f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_REMOTE; 1825f0d6a0eaSMikel Astiz case HCI_ERROR_LOCAL_HOST_TERM: 1826f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_LOCAL_HOST; 1827f0d6a0eaSMikel Astiz default: 1828f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_UNKNOWN; 1829f0d6a0eaSMikel Astiz } 1830f0d6a0eaSMikel Astiz } 1831f0d6a0eaSMikel Astiz 18326039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 18331da177e4SLinus Torvalds { 1834a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 183504837f64SMarcel Holtmann struct hci_conn *conn; 18361da177e4SLinus Torvalds 18379f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 18381da177e4SLinus Torvalds 18391da177e4SLinus Torvalds hci_dev_lock(hdev); 18401da177e4SLinus Torvalds 184104837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1842f7520543SJohan Hedberg if (!conn) 1843f7520543SJohan Hedberg goto unlock; 1844f7520543SJohan Hedberg 184537d9ef76SJohan Hedberg if (ev->status == 0) 18461da177e4SLinus Torvalds conn->state = BT_CLOSED; 18477d0db0a3SMarcel Holtmann 1848b644ba33SJohan Hedberg if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) && 1849b644ba33SJohan Hedberg (conn->type == ACL_LINK || conn->type == LE_LINK)) { 1850f0d6a0eaSMikel Astiz if (ev->status) { 185188c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 185288c3df13SJohan Hedberg conn->dst_type, ev->status); 1853f0d6a0eaSMikel Astiz } else { 1854f0d6a0eaSMikel Astiz u8 reason = hci_to_mgmt_reason(ev->reason); 1855f0d6a0eaSMikel Astiz 1856afc747a6SJohan Hedberg mgmt_device_disconnected(hdev, &conn->dst, conn->type, 1857f0d6a0eaSMikel Astiz conn->dst_type, reason); 1858f0d6a0eaSMikel Astiz } 185937d9ef76SJohan Hedberg } 1860f7520543SJohan Hedberg 186137d9ef76SJohan Hedberg if (ev->status == 0) { 18626ec5bcadSVishal Agarwal if (conn->type == ACL_LINK && conn->flush_key) 18636ec5bcadSVishal Agarwal hci_remove_link_key(hdev, &conn->dst); 18642950f21aSMarcel Holtmann hci_proto_disconn_cfm(conn, ev->reason); 18651da177e4SLinus Torvalds hci_conn_del(conn); 186637d9ef76SJohan Hedberg } 18671da177e4SLinus Torvalds 1868f7520543SJohan Hedberg unlock: 18691da177e4SLinus Torvalds hci_dev_unlock(hdev); 18701da177e4SLinus Torvalds } 18711da177e4SLinus Torvalds 18726039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1873a9de9248SMarcel Holtmann { 1874a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 1875a9de9248SMarcel Holtmann struct hci_conn *conn; 1876a9de9248SMarcel Holtmann 18779f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 1878a9de9248SMarcel Holtmann 1879a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1880a9de9248SMarcel Holtmann 1881a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1882d7556e20SWaldemar Rymarkiewicz if (!conn) 1883d7556e20SWaldemar Rymarkiewicz goto unlock; 1884d7556e20SWaldemar Rymarkiewicz 1885765c2a96SJohan Hedberg if (!ev->status) { 1886aa64a8b5SJohan Hedberg if (!hci_conn_ssp_enabled(conn) && 188751a8efd7SJohan Hedberg test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) { 1888d7556e20SWaldemar Rymarkiewicz BT_INFO("re-auth of legacy device is not possible."); 188919f8def0SWaldemar Rymarkiewicz } else { 1890a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1891765c2a96SJohan Hedberg conn->sec_level = conn->pending_sec_level; 189219f8def0SWaldemar Rymarkiewicz } 18932a611692SJohan Hedberg } else { 1894bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 1895bab73cb6SJohan Hedberg ev->status); 18962a611692SJohan Hedberg } 1897a9de9248SMarcel Holtmann 189851a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 189951a8efd7SJohan Hedberg clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags); 1900a9de9248SMarcel Holtmann 1901f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1902aa64a8b5SJohan Hedberg if (!ev->status && hci_conn_ssp_enabled(conn)) { 1903f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1904f8558555SMarcel Holtmann cp.handle = ev->handle; 1905f8558555SMarcel Holtmann cp.encrypt = 0x01; 1906d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1907d7556e20SWaldemar Rymarkiewicz &cp); 1908f8558555SMarcel Holtmann } else { 1909f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1910f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1911f8558555SMarcel Holtmann hci_conn_put(conn); 1912f8558555SMarcel Holtmann } 1913052b30b0SMarcel Holtmann } else { 1914a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 1915a9de9248SMarcel Holtmann 1916052b30b0SMarcel Holtmann hci_conn_hold(conn); 1917052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1918052b30b0SMarcel Holtmann hci_conn_put(conn); 1919052b30b0SMarcel Holtmann } 1920052b30b0SMarcel Holtmann 192151a8efd7SJohan Hedberg if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) { 1922a9de9248SMarcel Holtmann if (!ev->status) { 1923a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1924f8558555SMarcel Holtmann cp.handle = ev->handle; 1925f8558555SMarcel Holtmann cp.encrypt = 0x01; 1926d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1927d7556e20SWaldemar Rymarkiewicz &cp); 1928a9de9248SMarcel Holtmann } else { 192951a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 1930a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 1931a9de9248SMarcel Holtmann } 1932a9de9248SMarcel Holtmann } 1933a9de9248SMarcel Holtmann 1934d7556e20SWaldemar Rymarkiewicz unlock: 1935a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1936a9de9248SMarcel Holtmann } 1937a9de9248SMarcel Holtmann 19386039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 1939a9de9248SMarcel Holtmann { 1940127178d2SJohan Hedberg struct hci_ev_remote_name *ev = (void *) skb->data; 1941127178d2SJohan Hedberg struct hci_conn *conn; 1942127178d2SJohan Hedberg 1943a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1944a9de9248SMarcel Holtmann 1945a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 1946127178d2SJohan Hedberg 1947127178d2SJohan Hedberg hci_dev_lock(hdev); 1948127178d2SJohan Hedberg 1949127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 1950b644ba33SJohan Hedberg 1951b644ba33SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 1952b644ba33SJohan Hedberg goto check_auth; 1953b644ba33SJohan Hedberg 1954b644ba33SJohan Hedberg if (ev->status == 0) 1955b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name, 1956b644ba33SJohan Hedberg strnlen(ev->name, HCI_MAX_NAME_LENGTH)); 1957b644ba33SJohan Hedberg else 1958b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0); 1959b644ba33SJohan Hedberg 1960b644ba33SJohan Hedberg check_auth: 196179c6c70cSJohan Hedberg if (!conn) 196279c6c70cSJohan Hedberg goto unlock; 196379c6c70cSJohan Hedberg 196479c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 196579c6c70cSJohan Hedberg goto unlock; 196679c6c70cSJohan Hedberg 196751a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 1968127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1969127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1970127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1971127178d2SJohan Hedberg } 1972127178d2SJohan Hedberg 197379c6c70cSJohan Hedberg unlock: 1974127178d2SJohan Hedberg hci_dev_unlock(hdev); 1975a9de9248SMarcel Holtmann } 1976a9de9248SMarcel Holtmann 19776039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 1978a9de9248SMarcel Holtmann { 1979a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 1980a9de9248SMarcel Holtmann struct hci_conn *conn; 1981a9de9248SMarcel Holtmann 19829f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 1983a9de9248SMarcel Holtmann 1984a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1985a9de9248SMarcel Holtmann 1986a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1987a9de9248SMarcel Holtmann if (conn) { 1988a9de9248SMarcel Holtmann if (!ev->status) { 1989ae293196SMarcel Holtmann if (ev->encrypt) { 1990ae293196SMarcel Holtmann /* Encryption implies authentication */ 1991ae293196SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1992a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1993da85e5e5SVinicius Costa Gomes conn->sec_level = conn->pending_sec_level; 1994ae293196SMarcel Holtmann } else 1995a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_ENCRYPT; 1996a9de9248SMarcel Holtmann } 1997a9de9248SMarcel Holtmann 199851a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 1999a9de9248SMarcel Holtmann 2000a7d7723aSGustavo Padovan if (ev->status && conn->state == BT_CONNECTED) { 2001bed71748SAndre Guedes hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); 2002a7d7723aSGustavo Padovan hci_conn_put(conn); 2003a7d7723aSGustavo Padovan goto unlock; 2004a7d7723aSGustavo Padovan } 2005a7d7723aSGustavo Padovan 2006f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 2007f8558555SMarcel Holtmann if (!ev->status) 2008f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 2009f8558555SMarcel Holtmann 2010f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2011f8558555SMarcel Holtmann hci_conn_put(conn); 2012f8558555SMarcel Holtmann } else 2013a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 2014a9de9248SMarcel Holtmann } 2015a9de9248SMarcel Holtmann 2016a7d7723aSGustavo Padovan unlock: 2017a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2018a9de9248SMarcel Holtmann } 2019a9de9248SMarcel Holtmann 20206039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev, 2021807deac2SGustavo Padovan struct sk_buff *skb) 2022a9de9248SMarcel Holtmann { 2023a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 2024a9de9248SMarcel Holtmann struct hci_conn *conn; 2025a9de9248SMarcel Holtmann 20269f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2027a9de9248SMarcel Holtmann 2028a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2029a9de9248SMarcel Holtmann 2030a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2031a9de9248SMarcel Holtmann if (conn) { 2032a9de9248SMarcel Holtmann if (!ev->status) 2033a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_SECURE; 2034a9de9248SMarcel Holtmann 203551a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 2036a9de9248SMarcel Holtmann 2037a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 2038a9de9248SMarcel Holtmann } 2039a9de9248SMarcel Holtmann 2040a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2041a9de9248SMarcel Holtmann } 2042a9de9248SMarcel Holtmann 20436039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev, 2044807deac2SGustavo Padovan struct sk_buff *skb) 2045a9de9248SMarcel Holtmann { 2046a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 2047a9de9248SMarcel Holtmann struct hci_conn *conn; 2048a9de9248SMarcel Holtmann 20499f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2050a9de9248SMarcel Holtmann 2051a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2052a9de9248SMarcel Holtmann 2053a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2054ccd556feSJohan Hedberg if (!conn) 2055ccd556feSJohan Hedberg goto unlock; 2056ccd556feSJohan Hedberg 2057769be974SMarcel Holtmann if (!ev->status) 2058a9de9248SMarcel Holtmann memcpy(conn->features, ev->features, 8); 2059a9de9248SMarcel Holtmann 2060ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2061ccd556feSJohan Hedberg goto unlock; 2062ccd556feSJohan Hedberg 2063ccd556feSJohan Hedberg if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { 2064769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 2065769be974SMarcel Holtmann cp.handle = ev->handle; 2066769be974SMarcel Holtmann cp.page = 0x01; 2067ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 2068769be974SMarcel Holtmann sizeof(cp), &cp); 2069392599b9SJohan Hedberg goto unlock; 2070392599b9SJohan Hedberg } 2071392599b9SJohan Hedberg 2072671267bfSJohan Hedberg if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { 2073127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2074127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2075127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2076127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2077127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2078b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 2079b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 208008c79b61SJohan Hedberg conn->dst_type, 0, NULL, 0, 2081b644ba33SJohan Hedberg conn->dev_class); 2082392599b9SJohan Hedberg 2083127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2084769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2085769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2086769be974SMarcel Holtmann hci_conn_put(conn); 2087769be974SMarcel Holtmann } 2088769be974SMarcel Holtmann 2089ccd556feSJohan Hedberg unlock: 2090a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2091a9de9248SMarcel Holtmann } 2092a9de9248SMarcel Holtmann 20936039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2094a9de9248SMarcel Holtmann { 2095a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 20969238f36aSJohan Hedberg u8 status = skb->data[sizeof(*ev)]; 2097a9de9248SMarcel Holtmann __u16 opcode; 2098a9de9248SMarcel Holtmann 2099a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2100a9de9248SMarcel Holtmann 2101a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2102a9de9248SMarcel Holtmann 2103a9de9248SMarcel Holtmann switch (opcode) { 2104a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 2105a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 2106a9de9248SMarcel Holtmann break; 2107a9de9248SMarcel Holtmann 21084d93483bSAndre Guedes case HCI_OP_PERIODIC_INQ: 21094d93483bSAndre Guedes hci_cc_periodic_inq(hdev, skb); 21104d93483bSAndre Guedes break; 21114d93483bSAndre Guedes 2112a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 2113a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 2114a9de9248SMarcel Holtmann break; 2115a9de9248SMarcel Holtmann 2116a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 2117a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 2118a9de9248SMarcel Holtmann break; 2119a9de9248SMarcel Holtmann 2120a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 2121a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 2122a9de9248SMarcel Holtmann break; 2123a9de9248SMarcel Holtmann 2124e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 2125e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 2126e4e8e37cSMarcel Holtmann break; 2127e4e8e37cSMarcel Holtmann 2128a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 2129a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 2130a9de9248SMarcel Holtmann break; 2131a9de9248SMarcel Holtmann 2132e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 2133e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 2134e4e8e37cSMarcel Holtmann break; 2135e4e8e37cSMarcel Holtmann 2136e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 2137e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 2138e4e8e37cSMarcel Holtmann break; 2139e4e8e37cSMarcel Holtmann 2140a9de9248SMarcel Holtmann case HCI_OP_RESET: 2141a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 2142a9de9248SMarcel Holtmann break; 2143a9de9248SMarcel Holtmann 2144a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 2145a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 2146a9de9248SMarcel Holtmann break; 2147a9de9248SMarcel Holtmann 2148a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 2149a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 2150a9de9248SMarcel Holtmann break; 2151a9de9248SMarcel Holtmann 2152a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 2153a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 2154a9de9248SMarcel Holtmann break; 2155a9de9248SMarcel Holtmann 2156a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 2157a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 2158a9de9248SMarcel Holtmann break; 2159a9de9248SMarcel Holtmann 2160a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 2161a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 2162a9de9248SMarcel Holtmann break; 2163a9de9248SMarcel Holtmann 2164a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 2165a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 2166a9de9248SMarcel Holtmann break; 2167a9de9248SMarcel Holtmann 2168a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 2169a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 2170a9de9248SMarcel Holtmann break; 2171a9de9248SMarcel Holtmann 2172a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 2173a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 2174a9de9248SMarcel Holtmann break; 2175a9de9248SMarcel Holtmann 2176a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 2177a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 2178a9de9248SMarcel Holtmann break; 2179a9de9248SMarcel Holtmann 2180333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 2181333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 2182333140b5SMarcel Holtmann break; 2183333140b5SMarcel Holtmann 2184a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 2185a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 2186a9de9248SMarcel Holtmann break; 2187a9de9248SMarcel Holtmann 2188a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 2189a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 2190a9de9248SMarcel Holtmann break; 2191a9de9248SMarcel Holtmann 2192a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 2193a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 2194a9de9248SMarcel Holtmann break; 2195a9de9248SMarcel Holtmann 2196971e3a4bSAndre Guedes case HCI_OP_READ_LOCAL_EXT_FEATURES: 2197971e3a4bSAndre Guedes hci_cc_read_local_ext_features(hdev, skb); 2198971e3a4bSAndre Guedes break; 2199971e3a4bSAndre Guedes 2200a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 2201a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 2202a9de9248SMarcel Holtmann break; 2203a9de9248SMarcel Holtmann 2204a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 2205a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 2206a9de9248SMarcel Holtmann break; 2207a9de9248SMarcel Holtmann 2208350ee4cfSAndrei Emeltchenko case HCI_OP_READ_DATA_BLOCK_SIZE: 2209350ee4cfSAndrei Emeltchenko hci_cc_read_data_block_size(hdev, skb); 2210350ee4cfSAndrei Emeltchenko break; 2211350ee4cfSAndrei Emeltchenko 22121e89cffbSAndrei Emeltchenko case HCI_OP_READ_FLOW_CONTROL_MODE: 22131e89cffbSAndrei Emeltchenko hci_cc_read_flow_control_mode(hdev, skb); 22141e89cffbSAndrei Emeltchenko break; 22151e89cffbSAndrei Emeltchenko 2216928abaa7SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_INFO: 2217928abaa7SAndrei Emeltchenko hci_cc_read_local_amp_info(hdev, skb); 2218928abaa7SAndrei Emeltchenko break; 2219928abaa7SAndrei Emeltchenko 2220903e4541SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_ASSOC: 2221903e4541SAndrei Emeltchenko hci_cc_read_local_amp_assoc(hdev, skb); 2222903e4541SAndrei Emeltchenko break; 2223903e4541SAndrei Emeltchenko 2224d5859e22SJohan Hedberg case HCI_OP_READ_INQ_RSP_TX_POWER: 2225d5859e22SJohan Hedberg hci_cc_read_inq_rsp_tx_power(hdev, skb); 2226d5859e22SJohan Hedberg break; 2227d5859e22SJohan Hedberg 2228980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_REPLY: 2229980e1a53SJohan Hedberg hci_cc_pin_code_reply(hdev, skb); 2230980e1a53SJohan Hedberg break; 2231980e1a53SJohan Hedberg 2232980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_NEG_REPLY: 2233980e1a53SJohan Hedberg hci_cc_pin_code_neg_reply(hdev, skb); 2234980e1a53SJohan Hedberg break; 2235980e1a53SJohan Hedberg 2236c35938b2SSzymon Janc case HCI_OP_READ_LOCAL_OOB_DATA: 2237c35938b2SSzymon Janc hci_cc_read_local_oob_data_reply(hdev, skb); 2238c35938b2SSzymon Janc break; 2239c35938b2SSzymon Janc 22406ed58ec5SVille Tervo case HCI_OP_LE_READ_BUFFER_SIZE: 22416ed58ec5SVille Tervo hci_cc_le_read_buffer_size(hdev, skb); 22426ed58ec5SVille Tervo break; 22436ed58ec5SVille Tervo 224460e77321SJohan Hedberg case HCI_OP_LE_READ_LOCAL_FEATURES: 224560e77321SJohan Hedberg hci_cc_le_read_local_features(hdev, skb); 224660e77321SJohan Hedberg break; 224760e77321SJohan Hedberg 22488fa19098SJohan Hedberg case HCI_OP_LE_READ_ADV_TX_POWER: 22498fa19098SJohan Hedberg hci_cc_le_read_adv_tx_power(hdev, skb); 22508fa19098SJohan Hedberg break; 22518fa19098SJohan Hedberg 2252a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_REPLY: 2253a5c29683SJohan Hedberg hci_cc_user_confirm_reply(hdev, skb); 2254a5c29683SJohan Hedberg break; 2255a5c29683SJohan Hedberg 2256a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_NEG_REPLY: 2257a5c29683SJohan Hedberg hci_cc_user_confirm_neg_reply(hdev, skb); 2258a5c29683SJohan Hedberg break; 2259a5c29683SJohan Hedberg 22601143d458SBrian Gix case HCI_OP_USER_PASSKEY_REPLY: 22611143d458SBrian Gix hci_cc_user_passkey_reply(hdev, skb); 22621143d458SBrian Gix break; 22631143d458SBrian Gix 22641143d458SBrian Gix case HCI_OP_USER_PASSKEY_NEG_REPLY: 22651143d458SBrian Gix hci_cc_user_passkey_neg_reply(hdev, skb); 226616cde993SSzymon Janc break; 226707f7fa5dSAndre Guedes 226807f7fa5dSAndre Guedes case HCI_OP_LE_SET_SCAN_PARAM: 226907f7fa5dSAndre Guedes hci_cc_le_set_scan_param(hdev, skb); 22701143d458SBrian Gix break; 22711143d458SBrian Gix 2272c1d5dc4aSJohan Hedberg case HCI_OP_LE_SET_ADV_ENABLE: 2273c1d5dc4aSJohan Hedberg hci_cc_le_set_adv_enable(hdev, skb); 2274c1d5dc4aSJohan Hedberg break; 2275c1d5dc4aSJohan Hedberg 2276eb9d91f5SAndre Guedes case HCI_OP_LE_SET_SCAN_ENABLE: 2277eb9d91f5SAndre Guedes hci_cc_le_set_scan_enable(hdev, skb); 2278eb9d91f5SAndre Guedes break; 2279eb9d91f5SAndre Guedes 2280cf1d081fSJohan Hedberg case HCI_OP_LE_READ_WHITE_LIST_SIZE: 2281cf1d081fSJohan Hedberg hci_cc_le_read_white_list_size(hdev, skb); 2282cf1d081fSJohan Hedberg break; 2283cf1d081fSJohan Hedberg 22849b008c04SJohan Hedberg case HCI_OP_LE_READ_SUPPORTED_STATES: 22859b008c04SJohan Hedberg hci_cc_le_read_supported_states(hdev, skb); 22869b008c04SJohan Hedberg break; 22879b008c04SJohan Hedberg 2288f9b49306SAndre Guedes case HCI_OP_WRITE_LE_HOST_SUPPORTED: 2289f9b49306SAndre Guedes hci_cc_write_le_host_supported(hdev, skb); 2290f9b49306SAndre Guedes break; 2291f9b49306SAndre Guedes 229293c284eeSAndrei Emeltchenko case HCI_OP_WRITE_REMOTE_AMP_ASSOC: 229393c284eeSAndrei Emeltchenko hci_cc_write_remote_amp_assoc(hdev, skb); 229493c284eeSAndrei Emeltchenko break; 229593c284eeSAndrei Emeltchenko 2296a9de9248SMarcel Holtmann default: 22979f1db00cSAndrei Emeltchenko BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); 2298a9de9248SMarcel Holtmann break; 2299a9de9248SMarcel Holtmann } 2300a9de9248SMarcel Holtmann 2301ad82cdd1SJohan Hedberg if (opcode != HCI_OP_NOP) 23026bd32326SVille Tervo del_timer(&hdev->cmd_timer); 23036bd32326SVille Tervo 2304ad82cdd1SJohan Hedberg hci_req_cmd_complete(hdev, opcode, status); 23059238f36aSJohan Hedberg 2306dbccd791SSzymon Janc if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2307a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2308a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2309c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2310a9de9248SMarcel Holtmann } 2311a9de9248SMarcel Holtmann } 2312a9de9248SMarcel Holtmann 23136039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 2314a9de9248SMarcel Holtmann { 2315a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 2316a9de9248SMarcel Holtmann __u16 opcode; 2317a9de9248SMarcel Holtmann 2318a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2319a9de9248SMarcel Holtmann 2320a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2321a9de9248SMarcel Holtmann 2322a9de9248SMarcel Holtmann switch (opcode) { 2323a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 2324a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 2325a9de9248SMarcel Holtmann break; 2326a9de9248SMarcel Holtmann 2327a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 2328a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 2329a9de9248SMarcel Holtmann break; 2330a9de9248SMarcel Holtmann 2331a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 2332a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 2333a9de9248SMarcel Holtmann break; 2334a9de9248SMarcel Holtmann 2335f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 2336f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 2337f8558555SMarcel Holtmann break; 2338f8558555SMarcel Holtmann 2339f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 2340f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 2341f8558555SMarcel Holtmann break; 2342f8558555SMarcel Holtmann 2343a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 2344a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 2345a9de9248SMarcel Holtmann break; 2346a9de9248SMarcel Holtmann 2347769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 2348769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 2349769be974SMarcel Holtmann break; 2350769be974SMarcel Holtmann 2351769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 2352769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 2353769be974SMarcel Holtmann break; 2354769be974SMarcel Holtmann 2355a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 2356a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 2357a9de9248SMarcel Holtmann break; 2358a9de9248SMarcel Holtmann 2359a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 2360a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 2361a9de9248SMarcel Holtmann break; 2362a9de9248SMarcel Holtmann 2363a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 2364a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 2365a9de9248SMarcel Holtmann break; 2366a9de9248SMarcel Holtmann 23678962ee74SJohan Hedberg case HCI_OP_DISCONNECT: 236888c3df13SJohan Hedberg hci_cs_disconnect(hdev, ev->status); 23698962ee74SJohan Hedberg break; 23708962ee74SJohan Hedberg 2371fcd89c09SVille Tervo case HCI_OP_LE_CREATE_CONN: 2372fcd89c09SVille Tervo hci_cs_le_create_conn(hdev, ev->status); 2373fcd89c09SVille Tervo break; 2374fcd89c09SVille Tervo 2375a02226d6SAndrei Emeltchenko case HCI_OP_CREATE_PHY_LINK: 2376a02226d6SAndrei Emeltchenko hci_cs_create_phylink(hdev, ev->status); 2377a02226d6SAndrei Emeltchenko break; 2378a02226d6SAndrei Emeltchenko 23790b26ab9dSAndrei Emeltchenko case HCI_OP_ACCEPT_PHY_LINK: 23800b26ab9dSAndrei Emeltchenko hci_cs_accept_phylink(hdev, ev->status); 23810b26ab9dSAndrei Emeltchenko break; 23820b26ab9dSAndrei Emeltchenko 2383a9de9248SMarcel Holtmann default: 23849f1db00cSAndrei Emeltchenko BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); 2385a9de9248SMarcel Holtmann break; 2386a9de9248SMarcel Holtmann } 2387a9de9248SMarcel Holtmann 2388ad82cdd1SJohan Hedberg if (opcode != HCI_OP_NOP) 23896bd32326SVille Tervo del_timer(&hdev->cmd_timer); 23906bd32326SVille Tervo 2391ad82cdd1SJohan Hedberg hci_req_cmd_status(hdev, opcode, ev->status); 23929238f36aSJohan Hedberg 239310572132SGustavo F. Padovan if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2394a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2395a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2396c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2397a9de9248SMarcel Holtmann } 2398a9de9248SMarcel Holtmann } 2399a9de9248SMarcel Holtmann 24006039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2401a9de9248SMarcel Holtmann { 2402a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 2403a9de9248SMarcel Holtmann struct hci_conn *conn; 2404a9de9248SMarcel Holtmann 24059f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2406a9de9248SMarcel Holtmann 2407a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2408a9de9248SMarcel Holtmann 2409a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2410a9de9248SMarcel Holtmann if (conn) { 2411a9de9248SMarcel Holtmann if (!ev->status) { 2412a9de9248SMarcel Holtmann if (ev->role) 2413a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_MASTER; 2414a9de9248SMarcel Holtmann else 2415a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_MASTER; 2416a9de9248SMarcel Holtmann } 2417a9de9248SMarcel Holtmann 241851a8efd7SJohan Hedberg clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); 2419a9de9248SMarcel Holtmann 2420a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 2421a9de9248SMarcel Holtmann } 2422a9de9248SMarcel Holtmann 2423a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2424a9de9248SMarcel Holtmann } 2425a9de9248SMarcel Holtmann 24266039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 24271da177e4SLinus Torvalds { 2428a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 24291da177e4SLinus Torvalds int i; 24301da177e4SLinus Torvalds 243132ac5b9bSAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) { 243232ac5b9bSAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 243332ac5b9bSAndrei Emeltchenko return; 243432ac5b9bSAndrei Emeltchenko } 243532ac5b9bSAndrei Emeltchenko 2436c5993de8SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 2437c5993de8SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_pkts_info)) { 24381da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 24391da177e4SLinus Torvalds return; 24401da177e4SLinus Torvalds } 24411da177e4SLinus Torvalds 2442c5993de8SAndrei Emeltchenko BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 2443c5993de8SAndrei Emeltchenko 2444613a1c0cSAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 2445613a1c0cSAndrei Emeltchenko struct hci_comp_pkts_info *info = &ev->handles[i]; 24461da177e4SLinus Torvalds struct hci_conn *conn; 24471da177e4SLinus Torvalds __u16 handle, count; 24481da177e4SLinus Torvalds 2449613a1c0cSAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 2450613a1c0cSAndrei Emeltchenko count = __le16_to_cpu(info->count); 24511da177e4SLinus Torvalds 24521da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 2453f4280918SAndrei Emeltchenko if (!conn) 2454f4280918SAndrei Emeltchenko continue; 2455f4280918SAndrei Emeltchenko 24561da177e4SLinus Torvalds conn->sent -= count; 24571da177e4SLinus Torvalds 2458f4280918SAndrei Emeltchenko switch (conn->type) { 2459f4280918SAndrei Emeltchenko case ACL_LINK: 246070f23020SAndrei Emeltchenko hdev->acl_cnt += count; 246170f23020SAndrei Emeltchenko if (hdev->acl_cnt > hdev->acl_pkts) 24621da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 2463f4280918SAndrei Emeltchenko break; 2464f4280918SAndrei Emeltchenko 2465f4280918SAndrei Emeltchenko case LE_LINK: 24666ed58ec5SVille Tervo if (hdev->le_pkts) { 24676ed58ec5SVille Tervo hdev->le_cnt += count; 24686ed58ec5SVille Tervo if (hdev->le_cnt > hdev->le_pkts) 24696ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 24706ed58ec5SVille Tervo } else { 24716ed58ec5SVille Tervo hdev->acl_cnt += count; 24726ed58ec5SVille Tervo if (hdev->acl_cnt > hdev->acl_pkts) 24736ed58ec5SVille Tervo hdev->acl_cnt = hdev->acl_pkts; 24746ed58ec5SVille Tervo } 2475f4280918SAndrei Emeltchenko break; 2476f4280918SAndrei Emeltchenko 2477f4280918SAndrei Emeltchenko case SCO_LINK: 247870f23020SAndrei Emeltchenko hdev->sco_cnt += count; 247970f23020SAndrei Emeltchenko if (hdev->sco_cnt > hdev->sco_pkts) 24805b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 2481f4280918SAndrei Emeltchenko break; 2482f4280918SAndrei Emeltchenko 2483f4280918SAndrei Emeltchenko default: 2484f4280918SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 2485f4280918SAndrei Emeltchenko break; 24861da177e4SLinus Torvalds } 24871da177e4SLinus Torvalds } 2488a9de9248SMarcel Holtmann 24893eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 24901da177e4SLinus Torvalds } 24911da177e4SLinus Torvalds 249276ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev, 249376ef7cf7SAndrei Emeltchenko __u16 handle) 249476ef7cf7SAndrei Emeltchenko { 249576ef7cf7SAndrei Emeltchenko struct hci_chan *chan; 249676ef7cf7SAndrei Emeltchenko 249776ef7cf7SAndrei Emeltchenko switch (hdev->dev_type) { 249876ef7cf7SAndrei Emeltchenko case HCI_BREDR: 249976ef7cf7SAndrei Emeltchenko return hci_conn_hash_lookup_handle(hdev, handle); 250076ef7cf7SAndrei Emeltchenko case HCI_AMP: 250176ef7cf7SAndrei Emeltchenko chan = hci_chan_lookup_handle(hdev, handle); 250276ef7cf7SAndrei Emeltchenko if (chan) 250376ef7cf7SAndrei Emeltchenko return chan->conn; 250476ef7cf7SAndrei Emeltchenko break; 250576ef7cf7SAndrei Emeltchenko default: 250676ef7cf7SAndrei Emeltchenko BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type); 250776ef7cf7SAndrei Emeltchenko break; 250876ef7cf7SAndrei Emeltchenko } 250976ef7cf7SAndrei Emeltchenko 251076ef7cf7SAndrei Emeltchenko return NULL; 251176ef7cf7SAndrei Emeltchenko } 251276ef7cf7SAndrei Emeltchenko 25136039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb) 251425e89e99SAndrei Emeltchenko { 251525e89e99SAndrei Emeltchenko struct hci_ev_num_comp_blocks *ev = (void *) skb->data; 251625e89e99SAndrei Emeltchenko int i; 251725e89e99SAndrei Emeltchenko 251825e89e99SAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) { 251925e89e99SAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 252025e89e99SAndrei Emeltchenko return; 252125e89e99SAndrei Emeltchenko } 252225e89e99SAndrei Emeltchenko 252325e89e99SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 252425e89e99SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_blocks_info)) { 252525e89e99SAndrei Emeltchenko BT_DBG("%s bad parameters", hdev->name); 252625e89e99SAndrei Emeltchenko return; 252725e89e99SAndrei Emeltchenko } 252825e89e99SAndrei Emeltchenko 252925e89e99SAndrei Emeltchenko BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks, 253025e89e99SAndrei Emeltchenko ev->num_hndl); 253125e89e99SAndrei Emeltchenko 253225e89e99SAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 253325e89e99SAndrei Emeltchenko struct hci_comp_blocks_info *info = &ev->handles[i]; 253476ef7cf7SAndrei Emeltchenko struct hci_conn *conn = NULL; 253525e89e99SAndrei Emeltchenko __u16 handle, block_count; 253625e89e99SAndrei Emeltchenko 253725e89e99SAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 253825e89e99SAndrei Emeltchenko block_count = __le16_to_cpu(info->blocks); 253925e89e99SAndrei Emeltchenko 254076ef7cf7SAndrei Emeltchenko conn = __hci_conn_lookup_handle(hdev, handle); 254125e89e99SAndrei Emeltchenko if (!conn) 254225e89e99SAndrei Emeltchenko continue; 254325e89e99SAndrei Emeltchenko 254425e89e99SAndrei Emeltchenko conn->sent -= block_count; 254525e89e99SAndrei Emeltchenko 254625e89e99SAndrei Emeltchenko switch (conn->type) { 254725e89e99SAndrei Emeltchenko case ACL_LINK: 2548bd1eb66bSAndrei Emeltchenko case AMP_LINK: 254925e89e99SAndrei Emeltchenko hdev->block_cnt += block_count; 255025e89e99SAndrei Emeltchenko if (hdev->block_cnt > hdev->num_blocks) 255125e89e99SAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 255225e89e99SAndrei Emeltchenko break; 255325e89e99SAndrei Emeltchenko 255425e89e99SAndrei Emeltchenko default: 255525e89e99SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 255625e89e99SAndrei Emeltchenko break; 255725e89e99SAndrei Emeltchenko } 255825e89e99SAndrei Emeltchenko } 255925e89e99SAndrei Emeltchenko 256025e89e99SAndrei Emeltchenko queue_work(hdev->workqueue, &hdev->tx_work); 256125e89e99SAndrei Emeltchenko } 256225e89e99SAndrei Emeltchenko 25636039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 25641da177e4SLinus Torvalds { 2565a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 256604837f64SMarcel Holtmann struct hci_conn *conn; 25671da177e4SLinus Torvalds 25689f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 25691da177e4SLinus Torvalds 25701da177e4SLinus Torvalds hci_dev_lock(hdev); 25711da177e4SLinus Torvalds 257204837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 257304837f64SMarcel Holtmann if (conn) { 257404837f64SMarcel Holtmann conn->mode = ev->mode; 257504837f64SMarcel Holtmann conn->interval = __le16_to_cpu(ev->interval); 257604837f64SMarcel Holtmann 25778fc9ced3SGustavo Padovan if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, 25788fc9ced3SGustavo Padovan &conn->flags)) { 257904837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 258058a681efSJohan Hedberg set_bit(HCI_CONN_POWER_SAVE, &conn->flags); 258104837f64SMarcel Holtmann else 258258a681efSJohan Hedberg clear_bit(HCI_CONN_POWER_SAVE, &conn->flags); 258304837f64SMarcel Holtmann } 2584e73439d8SMarcel Holtmann 258551a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 2586e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 258704837f64SMarcel Holtmann } 258804837f64SMarcel Holtmann 258904837f64SMarcel Holtmann hci_dev_unlock(hdev); 259004837f64SMarcel Holtmann } 259104837f64SMarcel Holtmann 25926039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 25931da177e4SLinus Torvalds { 2594052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 2595052b30b0SMarcel Holtmann struct hci_conn *conn; 2596052b30b0SMarcel Holtmann 2597a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2598052b30b0SMarcel Holtmann 2599052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2600052b30b0SMarcel Holtmann 2601052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2602b6f98044SWaldemar Rymarkiewicz if (!conn) 2603b6f98044SWaldemar Rymarkiewicz goto unlock; 2604b6f98044SWaldemar Rymarkiewicz 2605b6f98044SWaldemar Rymarkiewicz if (conn->state == BT_CONNECTED) { 2606052b30b0SMarcel Holtmann hci_conn_hold(conn); 2607052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 2608052b30b0SMarcel Holtmann hci_conn_put(conn); 2609052b30b0SMarcel Holtmann } 2610052b30b0SMarcel Holtmann 2611a8b2d5c2SJohan Hedberg if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags)) 261203b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 261303b555e1SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 2614a8b2d5c2SJohan Hedberg else if (test_bit(HCI_MGMT, &hdev->dev_flags)) { 2615a770bb5aSWaldemar Rymarkiewicz u8 secure; 2616a770bb5aSWaldemar Rymarkiewicz 2617a770bb5aSWaldemar Rymarkiewicz if (conn->pending_sec_level == BT_SECURITY_HIGH) 2618a770bb5aSWaldemar Rymarkiewicz secure = 1; 2619a770bb5aSWaldemar Rymarkiewicz else 2620a770bb5aSWaldemar Rymarkiewicz secure = 0; 2621a770bb5aSWaldemar Rymarkiewicz 2622744cf19eSJohan Hedberg mgmt_pin_code_request(hdev, &ev->bdaddr, secure); 2623a770bb5aSWaldemar Rymarkiewicz } 2624980e1a53SJohan Hedberg 2625b6f98044SWaldemar Rymarkiewicz unlock: 2626052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 26271da177e4SLinus Torvalds } 26281da177e4SLinus Torvalds 26296039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 26301da177e4SLinus Torvalds { 263155ed8ca1SJohan Hedberg struct hci_ev_link_key_req *ev = (void *) skb->data; 263255ed8ca1SJohan Hedberg struct hci_cp_link_key_reply cp; 263355ed8ca1SJohan Hedberg struct hci_conn *conn; 263455ed8ca1SJohan Hedberg struct link_key *key; 263555ed8ca1SJohan Hedberg 2636a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 263755ed8ca1SJohan Hedberg 2638a8b2d5c2SJohan Hedberg if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) 263955ed8ca1SJohan Hedberg return; 264055ed8ca1SJohan Hedberg 264155ed8ca1SJohan Hedberg hci_dev_lock(hdev); 264255ed8ca1SJohan Hedberg 264355ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, &ev->bdaddr); 264455ed8ca1SJohan Hedberg if (!key) { 26456ed93dc6SAndrei Emeltchenko BT_DBG("%s link key not found for %pMR", hdev->name, 26466ed93dc6SAndrei Emeltchenko &ev->bdaddr); 264755ed8ca1SJohan Hedberg goto not_found; 264855ed8ca1SJohan Hedberg } 264955ed8ca1SJohan Hedberg 26506ed93dc6SAndrei Emeltchenko BT_DBG("%s found key type %u for %pMR", hdev->name, key->type, 26516ed93dc6SAndrei Emeltchenko &ev->bdaddr); 265255ed8ca1SJohan Hedberg 2653a8b2d5c2SJohan Hedberg if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) && 2654b6020ba0SWaldemar Rymarkiewicz key->type == HCI_LK_DEBUG_COMBINATION) { 265555ed8ca1SJohan Hedberg BT_DBG("%s ignoring debug key", hdev->name); 265655ed8ca1SJohan Hedberg goto not_found; 265755ed8ca1SJohan Hedberg } 265855ed8ca1SJohan Hedberg 265955ed8ca1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 266060b83f57SWaldemar Rymarkiewicz if (conn) { 266160b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_UNAUTH_COMBINATION && 2662807deac2SGustavo Padovan conn->auth_type != 0xff && (conn->auth_type & 0x01)) { 266355ed8ca1SJohan Hedberg BT_DBG("%s ignoring unauthenticated key", hdev->name); 266455ed8ca1SJohan Hedberg goto not_found; 266555ed8ca1SJohan Hedberg } 266655ed8ca1SJohan Hedberg 266760b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && 266860b83f57SWaldemar Rymarkiewicz conn->pending_sec_level == BT_SECURITY_HIGH) { 26698fc9ced3SGustavo Padovan BT_DBG("%s ignoring key unauthenticated for high security", 26708fc9ced3SGustavo Padovan hdev->name); 267160b83f57SWaldemar Rymarkiewicz goto not_found; 267260b83f57SWaldemar Rymarkiewicz } 267360b83f57SWaldemar Rymarkiewicz 267460b83f57SWaldemar Rymarkiewicz conn->key_type = key->type; 267560b83f57SWaldemar Rymarkiewicz conn->pin_length = key->pin_len; 267660b83f57SWaldemar Rymarkiewicz } 267760b83f57SWaldemar Rymarkiewicz 267855ed8ca1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 26799b3b4460SAndrei Emeltchenko memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE); 268055ed8ca1SJohan Hedberg 268155ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 268255ed8ca1SJohan Hedberg 268355ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 268455ed8ca1SJohan Hedberg 268555ed8ca1SJohan Hedberg return; 268655ed8ca1SJohan Hedberg 268755ed8ca1SJohan Hedberg not_found: 268855ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 268955ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 26901da177e4SLinus Torvalds } 26911da177e4SLinus Torvalds 26926039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 26931da177e4SLinus Torvalds { 2694052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 2695052b30b0SMarcel Holtmann struct hci_conn *conn; 269655ed8ca1SJohan Hedberg u8 pin_len = 0; 2697052b30b0SMarcel Holtmann 2698a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2699052b30b0SMarcel Holtmann 2700052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2701052b30b0SMarcel Holtmann 2702052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2703052b30b0SMarcel Holtmann if (conn) { 2704052b30b0SMarcel Holtmann hci_conn_hold(conn); 2705052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2706980e1a53SJohan Hedberg pin_len = conn->pin_length; 270713d39315SWaldemar Rymarkiewicz 270813d39315SWaldemar Rymarkiewicz if (ev->key_type != HCI_LK_CHANGED_COMBINATION) 270913d39315SWaldemar Rymarkiewicz conn->key_type = ev->key_type; 271013d39315SWaldemar Rymarkiewicz 2711052b30b0SMarcel Holtmann hci_conn_put(conn); 2712052b30b0SMarcel Holtmann } 2713052b30b0SMarcel Holtmann 2714a8b2d5c2SJohan Hedberg if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) 2715d25e28abSJohan Hedberg hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, 271655ed8ca1SJohan Hedberg ev->key_type, pin_len); 271755ed8ca1SJohan Hedberg 2718052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 27191da177e4SLinus Torvalds } 27201da177e4SLinus Torvalds 27216039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 272204837f64SMarcel Holtmann { 2723a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 272404837f64SMarcel Holtmann struct hci_conn *conn; 272504837f64SMarcel Holtmann 27269f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 272704837f64SMarcel Holtmann 272804837f64SMarcel Holtmann hci_dev_lock(hdev); 272904837f64SMarcel Holtmann 273004837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 27311da177e4SLinus Torvalds if (conn && !ev->status) { 27321da177e4SLinus Torvalds struct inquiry_entry *ie; 27331da177e4SLinus Torvalds 2734cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2735cc11b9c1SAndrei Emeltchenko if (ie) { 27361da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 27371da177e4SLinus Torvalds ie->timestamp = jiffies; 27381da177e4SLinus Torvalds } 27391da177e4SLinus Torvalds } 27401da177e4SLinus Torvalds 27411da177e4SLinus Torvalds hci_dev_unlock(hdev); 27421da177e4SLinus Torvalds } 27431da177e4SLinus Torvalds 27446039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2745a8746417SMarcel Holtmann { 2746a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 2747a8746417SMarcel Holtmann struct hci_conn *conn; 2748a8746417SMarcel Holtmann 27499f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2750a8746417SMarcel Holtmann 2751a8746417SMarcel Holtmann hci_dev_lock(hdev); 2752a8746417SMarcel Holtmann 2753a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2754a8746417SMarcel Holtmann if (conn && !ev->status) 2755a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 2756a8746417SMarcel Holtmann 2757a8746417SMarcel Holtmann hci_dev_unlock(hdev); 2758a8746417SMarcel Holtmann } 2759a8746417SMarcel Holtmann 27606039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 276185a1e930SMarcel Holtmann { 2762a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 276385a1e930SMarcel Holtmann struct inquiry_entry *ie; 276485a1e930SMarcel Holtmann 276585a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 276685a1e930SMarcel Holtmann 276785a1e930SMarcel Holtmann hci_dev_lock(hdev); 276885a1e930SMarcel Holtmann 2769cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2770cc11b9c1SAndrei Emeltchenko if (ie) { 277185a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 277285a1e930SMarcel Holtmann ie->timestamp = jiffies; 277385a1e930SMarcel Holtmann } 277485a1e930SMarcel Holtmann 277585a1e930SMarcel Holtmann hci_dev_unlock(hdev); 277685a1e930SMarcel Holtmann } 277785a1e930SMarcel Holtmann 27786039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, 2779807deac2SGustavo Padovan struct sk_buff *skb) 2780a9de9248SMarcel Holtmann { 2781a9de9248SMarcel Holtmann struct inquiry_data data; 2782a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2783388fc8faSJohan Hedberg bool name_known, ssp; 2784a9de9248SMarcel Holtmann 2785a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2786a9de9248SMarcel Holtmann 2787a9de9248SMarcel Holtmann if (!num_rsp) 2788a9de9248SMarcel Holtmann return; 2789a9de9248SMarcel Holtmann 27901519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 27911519cc17SAndre Guedes return; 27921519cc17SAndre Guedes 2793a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2794a9de9248SMarcel Holtmann 2795a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 2796138d22efSSzymon Janc struct inquiry_info_with_rssi_and_pscan_mode *info; 2797138d22efSSzymon Janc info = (void *) (skb->data + 1); 2798a9de9248SMarcel Holtmann 2799e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2800a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2801a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2802a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2803a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 2804a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2805a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2806a9de9248SMarcel Holtmann data.rssi = info->rssi; 280741a96212SMarcel Holtmann data.ssp_mode = 0x00; 28083175405bSJohan Hedberg 28093175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 2810388fc8faSJohan Hedberg false, &ssp); 281148264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2812e17acd40SJohan Hedberg info->dev_class, info->rssi, 2813388fc8faSJohan Hedberg !name_known, ssp, NULL, 0); 2814a9de9248SMarcel Holtmann } 2815a9de9248SMarcel Holtmann } else { 2816a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 2817a9de9248SMarcel Holtmann 2818e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2819a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2820a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2821a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2822a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2823a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2824a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2825a9de9248SMarcel Holtmann data.rssi = info->rssi; 282641a96212SMarcel Holtmann data.ssp_mode = 0x00; 28273175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 2828388fc8faSJohan Hedberg false, &ssp); 282948264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2830e17acd40SJohan Hedberg info->dev_class, info->rssi, 2831388fc8faSJohan Hedberg !name_known, ssp, NULL, 0); 2832a9de9248SMarcel Holtmann } 2833a9de9248SMarcel Holtmann } 2834a9de9248SMarcel Holtmann 2835a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2836a9de9248SMarcel Holtmann } 2837a9de9248SMarcel Holtmann 28386039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev, 2839807deac2SGustavo Padovan struct sk_buff *skb) 2840a9de9248SMarcel Holtmann { 284141a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 284241a96212SMarcel Holtmann struct hci_conn *conn; 284341a96212SMarcel Holtmann 2844a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 284541a96212SMarcel Holtmann 284641a96212SMarcel Holtmann hci_dev_lock(hdev); 284741a96212SMarcel Holtmann 284841a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2849ccd556feSJohan Hedberg if (!conn) 2850ccd556feSJohan Hedberg goto unlock; 2851ccd556feSJohan Hedberg 2852769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 285341a96212SMarcel Holtmann struct inquiry_entry *ie; 285441a96212SMarcel Holtmann 2855cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2856cc11b9c1SAndrei Emeltchenko if (ie) 285702b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 285841a96212SMarcel Holtmann 285902b7cc62SJohan Hedberg if (ev->features[0] & LMP_HOST_SSP) 286058a681efSJohan Hedberg set_bit(HCI_CONN_SSP_ENABLED, &conn->flags); 286141a96212SMarcel Holtmann } 286241a96212SMarcel Holtmann 2863ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2864ccd556feSJohan Hedberg goto unlock; 2865ccd556feSJohan Hedberg 2866671267bfSJohan Hedberg if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { 2867127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2868127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2869127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2870127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2871127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2872b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 2873b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 287408c79b61SJohan Hedberg conn->dst_type, 0, NULL, 0, 2875b644ba33SJohan Hedberg conn->dev_class); 2876392599b9SJohan Hedberg 2877127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2878769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2879769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2880769be974SMarcel Holtmann hci_conn_put(conn); 2881769be974SMarcel Holtmann } 2882769be974SMarcel Holtmann 2883ccd556feSJohan Hedberg unlock: 288441a96212SMarcel Holtmann hci_dev_unlock(hdev); 2885a9de9248SMarcel Holtmann } 2886a9de9248SMarcel Holtmann 28876039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev, 2888807deac2SGustavo Padovan struct sk_buff *skb) 2889a9de9248SMarcel Holtmann { 2890b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 2891b6a0dc82SMarcel Holtmann struct hci_conn *conn; 2892b6a0dc82SMarcel Holtmann 28939f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2894b6a0dc82SMarcel Holtmann 2895b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 2896b6a0dc82SMarcel Holtmann 2897b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 28989dc0a3afSMarcel Holtmann if (!conn) { 28999dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 29009dc0a3afSMarcel Holtmann goto unlock; 29019dc0a3afSMarcel Holtmann 29029dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 2903b6a0dc82SMarcel Holtmann if (!conn) 2904b6a0dc82SMarcel Holtmann goto unlock; 2905b6a0dc82SMarcel Holtmann 29069dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 29079dc0a3afSMarcel Holtmann } 29089dc0a3afSMarcel Holtmann 2909732547f9SMarcel Holtmann switch (ev->status) { 2910732547f9SMarcel Holtmann case 0x00: 2911732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 2912732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 2913732547f9SMarcel Holtmann 29149eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 2915732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 2916732547f9SMarcel Holtmann break; 2917732547f9SMarcel Holtmann 2918705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 2919732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 29201038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 2921732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 2922732547f9SMarcel Holtmann if (conn->out && conn->attempt < 2) { 2923efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 2924efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 2925efc7688bSMarcel Holtmann hci_setup_sync(conn, conn->link->handle); 2926efc7688bSMarcel Holtmann goto unlock; 2927efc7688bSMarcel Holtmann } 2928732547f9SMarcel Holtmann /* fall through */ 2929efc7688bSMarcel Holtmann 2930732547f9SMarcel Holtmann default: 2931b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 2932732547f9SMarcel Holtmann break; 2933732547f9SMarcel Holtmann } 2934b6a0dc82SMarcel Holtmann 2935b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2936b6a0dc82SMarcel Holtmann if (ev->status) 2937b6a0dc82SMarcel Holtmann hci_conn_del(conn); 2938b6a0dc82SMarcel Holtmann 2939b6a0dc82SMarcel Holtmann unlock: 2940b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 2941a9de9248SMarcel Holtmann } 2942a9de9248SMarcel Holtmann 29436039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, 2944807deac2SGustavo Padovan struct sk_buff *skb) 2945a9de9248SMarcel Holtmann { 2946a9de9248SMarcel Holtmann struct inquiry_data data; 2947a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 2948a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 29499d939d94SVishal Agarwal size_t eir_len; 2950a9de9248SMarcel Holtmann 2951a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2952a9de9248SMarcel Holtmann 2953a9de9248SMarcel Holtmann if (!num_rsp) 2954a9de9248SMarcel Holtmann return; 2955a9de9248SMarcel Holtmann 29561519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 29571519cc17SAndre Guedes return; 29581519cc17SAndre Guedes 2959a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2960a9de9248SMarcel Holtmann 2961e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2962388fc8faSJohan Hedberg bool name_known, ssp; 2963561aafbcSJohan Hedberg 2964a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2965a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2966a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2967a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2968a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2969a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2970a9de9248SMarcel Holtmann data.rssi = info->rssi; 297141a96212SMarcel Holtmann data.ssp_mode = 0x01; 2972561aafbcSJohan Hedberg 2973a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 29744ddb1930SJohan Hedberg name_known = eir_has_data_type(info->data, 29754ddb1930SJohan Hedberg sizeof(info->data), 29764ddb1930SJohan Hedberg EIR_NAME_COMPLETE); 2977561aafbcSJohan Hedberg else 2978561aafbcSJohan Hedberg name_known = true; 2979561aafbcSJohan Hedberg 2980388fc8faSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, name_known, 2981388fc8faSJohan Hedberg &ssp); 29829d939d94SVishal Agarwal eir_len = eir_get_length(info->data, sizeof(info->data)); 298348264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 298404124681SGustavo F. Padovan info->dev_class, info->rssi, !name_known, 29859d939d94SVishal Agarwal ssp, info->data, eir_len); 2986a9de9248SMarcel Holtmann } 2987a9de9248SMarcel Holtmann 2988a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2989a9de9248SMarcel Holtmann } 2990a9de9248SMarcel Holtmann 29911c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev, 29921c2e0041SJohan Hedberg struct sk_buff *skb) 29931c2e0041SJohan Hedberg { 29941c2e0041SJohan Hedberg struct hci_ev_key_refresh_complete *ev = (void *) skb->data; 29951c2e0041SJohan Hedberg struct hci_conn *conn; 29961c2e0041SJohan Hedberg 29979f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status, 29981c2e0041SJohan Hedberg __le16_to_cpu(ev->handle)); 29991c2e0041SJohan Hedberg 30001c2e0041SJohan Hedberg hci_dev_lock(hdev); 30011c2e0041SJohan Hedberg 30021c2e0041SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 30031c2e0041SJohan Hedberg if (!conn) 30041c2e0041SJohan Hedberg goto unlock; 30051c2e0041SJohan Hedberg 30061c2e0041SJohan Hedberg if (!ev->status) 30071c2e0041SJohan Hedberg conn->sec_level = conn->pending_sec_level; 30081c2e0041SJohan Hedberg 30091c2e0041SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 30101c2e0041SJohan Hedberg 30111c2e0041SJohan Hedberg if (ev->status && conn->state == BT_CONNECTED) { 3012bed71748SAndre Guedes hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); 30131c2e0041SJohan Hedberg hci_conn_put(conn); 30141c2e0041SJohan Hedberg goto unlock; 30151c2e0041SJohan Hedberg } 30161c2e0041SJohan Hedberg 30171c2e0041SJohan Hedberg if (conn->state == BT_CONFIG) { 30181c2e0041SJohan Hedberg if (!ev->status) 30191c2e0041SJohan Hedberg conn->state = BT_CONNECTED; 30201c2e0041SJohan Hedberg 30211c2e0041SJohan Hedberg hci_proto_connect_cfm(conn, ev->status); 30221c2e0041SJohan Hedberg hci_conn_put(conn); 30231c2e0041SJohan Hedberg } else { 30241c2e0041SJohan Hedberg hci_auth_cfm(conn, ev->status); 30251c2e0041SJohan Hedberg 30261c2e0041SJohan Hedberg hci_conn_hold(conn); 30271c2e0041SJohan Hedberg conn->disc_timeout = HCI_DISCONN_TIMEOUT; 30281c2e0041SJohan Hedberg hci_conn_put(conn); 30291c2e0041SJohan Hedberg } 30301c2e0041SJohan Hedberg 30311c2e0041SJohan Hedberg unlock: 30321c2e0041SJohan Hedberg hci_dev_unlock(hdev); 30331c2e0041SJohan Hedberg } 30341c2e0041SJohan Hedberg 30356039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn) 303617fa4b9dSJohan Hedberg { 303717fa4b9dSJohan Hedberg /* If remote requests dedicated bonding follow that lead */ 303817fa4b9dSJohan Hedberg if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) { 303917fa4b9dSJohan Hedberg /* If both remote and local IO capabilities allow MITM 304017fa4b9dSJohan Hedberg * protection then require it, otherwise don't */ 304117fa4b9dSJohan Hedberg if (conn->remote_cap == 0x03 || conn->io_capability == 0x03) 304217fa4b9dSJohan Hedberg return 0x02; 304317fa4b9dSJohan Hedberg else 304417fa4b9dSJohan Hedberg return 0x03; 304517fa4b9dSJohan Hedberg } 304617fa4b9dSJohan Hedberg 304717fa4b9dSJohan Hedberg /* If remote requests no-bonding follow that lead */ 304817fa4b9dSJohan Hedberg if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01) 304958797bf7SWaldemar Rymarkiewicz return conn->remote_auth | (conn->auth_type & 0x01); 305017fa4b9dSJohan Hedberg 305117fa4b9dSJohan Hedberg return conn->auth_type; 305217fa4b9dSJohan Hedberg } 305317fa4b9dSJohan Hedberg 30546039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 30550493684eSMarcel Holtmann { 30560493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 30570493684eSMarcel Holtmann struct hci_conn *conn; 30580493684eSMarcel Holtmann 30590493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 30600493684eSMarcel Holtmann 30610493684eSMarcel Holtmann hci_dev_lock(hdev); 30620493684eSMarcel Holtmann 30630493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 306403b555e1SJohan Hedberg if (!conn) 306503b555e1SJohan Hedberg goto unlock; 306603b555e1SJohan Hedberg 30670493684eSMarcel Holtmann hci_conn_hold(conn); 30680493684eSMarcel Holtmann 3069a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 307003b555e1SJohan Hedberg goto unlock; 307103b555e1SJohan Hedberg 3072a8b2d5c2SJohan Hedberg if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) || 307303b555e1SJohan Hedberg (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 307417fa4b9dSJohan Hedberg struct hci_cp_io_capability_reply cp; 307517fa4b9dSJohan Hedberg 307617fa4b9dSJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 30777a7f1e7cSHemant Gupta /* Change the IO capability from KeyboardDisplay 30787a7f1e7cSHemant Gupta * to DisplayYesNo as it is not supported by BT spec. */ 30797a7f1e7cSHemant Gupta cp.capability = (conn->io_capability == 0x04) ? 30807a7f1e7cSHemant Gupta 0x01 : conn->io_capability; 30817cbc9bd9SJohan Hedberg conn->auth_type = hci_get_auth_req(conn); 30827cbc9bd9SJohan Hedberg cp.authentication = conn->auth_type; 308317fa4b9dSJohan Hedberg 30848fc9ced3SGustavo Padovan if (hci_find_remote_oob_data(hdev, &conn->dst) && 30858fc9ced3SGustavo Padovan (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags))) 3086ce85ee13SSzymon Janc cp.oob_data = 0x01; 3087ce85ee13SSzymon Janc else 3088ce85ee13SSzymon Janc cp.oob_data = 0x00; 3089ce85ee13SSzymon Janc 309017fa4b9dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, 309117fa4b9dSJohan Hedberg sizeof(cp), &cp); 309203b555e1SJohan Hedberg } else { 309303b555e1SJohan Hedberg struct hci_cp_io_capability_neg_reply cp; 309403b555e1SJohan Hedberg 309503b555e1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 30969f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED; 309703b555e1SJohan Hedberg 309803b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 309903b555e1SJohan Hedberg sizeof(cp), &cp); 310003b555e1SJohan Hedberg } 310103b555e1SJohan Hedberg 310203b555e1SJohan Hedberg unlock: 310303b555e1SJohan Hedberg hci_dev_unlock(hdev); 310403b555e1SJohan Hedberg } 310503b555e1SJohan Hedberg 31066039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 310703b555e1SJohan Hedberg { 310803b555e1SJohan Hedberg struct hci_ev_io_capa_reply *ev = (void *) skb->data; 310903b555e1SJohan Hedberg struct hci_conn *conn; 311003b555e1SJohan Hedberg 311103b555e1SJohan Hedberg BT_DBG("%s", hdev->name); 311203b555e1SJohan Hedberg 311303b555e1SJohan Hedberg hci_dev_lock(hdev); 311403b555e1SJohan Hedberg 311503b555e1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 311603b555e1SJohan Hedberg if (!conn) 311703b555e1SJohan Hedberg goto unlock; 311803b555e1SJohan Hedberg 311903b555e1SJohan Hedberg conn->remote_cap = ev->capability; 312003b555e1SJohan Hedberg conn->remote_auth = ev->authentication; 312158a681efSJohan Hedberg if (ev->oob_data) 312258a681efSJohan Hedberg set_bit(HCI_CONN_REMOTE_OOB, &conn->flags); 312303b555e1SJohan Hedberg 312403b555e1SJohan Hedberg unlock: 31250493684eSMarcel Holtmann hci_dev_unlock(hdev); 31260493684eSMarcel Holtmann } 31270493684eSMarcel Holtmann 31286039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev, 3129a5c29683SJohan Hedberg struct sk_buff *skb) 3130a5c29683SJohan Hedberg { 3131a5c29683SJohan Hedberg struct hci_ev_user_confirm_req *ev = (void *) skb->data; 313255bc1a37SJohan Hedberg int loc_mitm, rem_mitm, confirm_hint = 0; 31337a828908SJohan Hedberg struct hci_conn *conn; 3134a5c29683SJohan Hedberg 3135a5c29683SJohan Hedberg BT_DBG("%s", hdev->name); 3136a5c29683SJohan Hedberg 3137a5c29683SJohan Hedberg hci_dev_lock(hdev); 3138a5c29683SJohan Hedberg 3139a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 31407a828908SJohan Hedberg goto unlock; 31417a828908SJohan Hedberg 31427a828908SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 31437a828908SJohan Hedberg if (!conn) 31447a828908SJohan Hedberg goto unlock; 31457a828908SJohan Hedberg 31467a828908SJohan Hedberg loc_mitm = (conn->auth_type & 0x01); 31477a828908SJohan Hedberg rem_mitm = (conn->remote_auth & 0x01); 31487a828908SJohan Hedberg 31497a828908SJohan Hedberg /* If we require MITM but the remote device can't provide that 31507a828908SJohan Hedberg * (it has NoInputNoOutput) then reject the confirmation 31517a828908SJohan Hedberg * request. The only exception is when we're dedicated bonding 31527a828908SJohan Hedberg * initiators (connect_cfm_cb set) since then we always have the MITM 31537a828908SJohan Hedberg * bit set. */ 31547a828908SJohan Hedberg if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) { 31557a828908SJohan Hedberg BT_DBG("Rejecting request: remote device can't provide MITM"); 31567a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, 31577a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 31587a828908SJohan Hedberg goto unlock; 31597a828908SJohan Hedberg } 31607a828908SJohan Hedberg 31617a828908SJohan Hedberg /* If no side requires MITM protection; auto-accept */ 31627a828908SJohan Hedberg if ((!loc_mitm || conn->remote_cap == 0x03) && 31637a828908SJohan Hedberg (!rem_mitm || conn->io_capability == 0x03)) { 316455bc1a37SJohan Hedberg 316555bc1a37SJohan Hedberg /* If we're not the initiators request authorization to 316655bc1a37SJohan Hedberg * proceed from user space (mgmt_user_confirm with 316755bc1a37SJohan Hedberg * confirm_hint set to 1). */ 316851a8efd7SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 316955bc1a37SJohan Hedberg BT_DBG("Confirming auto-accept as acceptor"); 317055bc1a37SJohan Hedberg confirm_hint = 1; 317155bc1a37SJohan Hedberg goto confirm; 317255bc1a37SJohan Hedberg } 317355bc1a37SJohan Hedberg 31749f61656aSJohan Hedberg BT_DBG("Auto-accept of user confirmation with %ums delay", 31759f61656aSJohan Hedberg hdev->auto_accept_delay); 31769f61656aSJohan Hedberg 31779f61656aSJohan Hedberg if (hdev->auto_accept_delay > 0) { 31789f61656aSJohan Hedberg int delay = msecs_to_jiffies(hdev->auto_accept_delay); 31799f61656aSJohan Hedberg mod_timer(&conn->auto_accept_timer, jiffies + delay); 31809f61656aSJohan Hedberg goto unlock; 31819f61656aSJohan Hedberg } 31829f61656aSJohan Hedberg 31837a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, 31847a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 31857a828908SJohan Hedberg goto unlock; 31867a828908SJohan Hedberg } 31877a828908SJohan Hedberg 318855bc1a37SJohan Hedberg confirm: 3189272d90dfSJohan Hedberg mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey, 319055bc1a37SJohan Hedberg confirm_hint); 3191a5c29683SJohan Hedberg 31927a828908SJohan Hedberg unlock: 3193a5c29683SJohan Hedberg hci_dev_unlock(hdev); 3194a5c29683SJohan Hedberg } 3195a5c29683SJohan Hedberg 31966039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev, 31971143d458SBrian Gix struct sk_buff *skb) 31981143d458SBrian Gix { 31991143d458SBrian Gix struct hci_ev_user_passkey_req *ev = (void *) skb->data; 32001143d458SBrian Gix 32011143d458SBrian Gix BT_DBG("%s", hdev->name); 32021143d458SBrian Gix 3203a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 3204272d90dfSJohan Hedberg mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); 32051143d458SBrian Gix } 32061143d458SBrian Gix 320792a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev, 320892a25256SJohan Hedberg struct sk_buff *skb) 320992a25256SJohan Hedberg { 321092a25256SJohan Hedberg struct hci_ev_user_passkey_notify *ev = (void *) skb->data; 321192a25256SJohan Hedberg struct hci_conn *conn; 321292a25256SJohan Hedberg 321392a25256SJohan Hedberg BT_DBG("%s", hdev->name); 321492a25256SJohan Hedberg 321592a25256SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 321692a25256SJohan Hedberg if (!conn) 321792a25256SJohan Hedberg return; 321892a25256SJohan Hedberg 321992a25256SJohan Hedberg conn->passkey_notify = __le32_to_cpu(ev->passkey); 322092a25256SJohan Hedberg conn->passkey_entered = 0; 322192a25256SJohan Hedberg 322292a25256SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 322392a25256SJohan Hedberg mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, 322492a25256SJohan Hedberg conn->dst_type, conn->passkey_notify, 322592a25256SJohan Hedberg conn->passkey_entered); 322692a25256SJohan Hedberg } 322792a25256SJohan Hedberg 322892a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 322992a25256SJohan Hedberg { 323092a25256SJohan Hedberg struct hci_ev_keypress_notify *ev = (void *) skb->data; 323192a25256SJohan Hedberg struct hci_conn *conn; 323292a25256SJohan Hedberg 323392a25256SJohan Hedberg BT_DBG("%s", hdev->name); 323492a25256SJohan Hedberg 323592a25256SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 323692a25256SJohan Hedberg if (!conn) 323792a25256SJohan Hedberg return; 323892a25256SJohan Hedberg 323992a25256SJohan Hedberg switch (ev->type) { 324092a25256SJohan Hedberg case HCI_KEYPRESS_STARTED: 324192a25256SJohan Hedberg conn->passkey_entered = 0; 324292a25256SJohan Hedberg return; 324392a25256SJohan Hedberg 324492a25256SJohan Hedberg case HCI_KEYPRESS_ENTERED: 324592a25256SJohan Hedberg conn->passkey_entered++; 324692a25256SJohan Hedberg break; 324792a25256SJohan Hedberg 324892a25256SJohan Hedberg case HCI_KEYPRESS_ERASED: 324992a25256SJohan Hedberg conn->passkey_entered--; 325092a25256SJohan Hedberg break; 325192a25256SJohan Hedberg 325292a25256SJohan Hedberg case HCI_KEYPRESS_CLEARED: 325392a25256SJohan Hedberg conn->passkey_entered = 0; 325492a25256SJohan Hedberg break; 325592a25256SJohan Hedberg 325692a25256SJohan Hedberg case HCI_KEYPRESS_COMPLETED: 325792a25256SJohan Hedberg return; 325892a25256SJohan Hedberg } 325992a25256SJohan Hedberg 326092a25256SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 326192a25256SJohan Hedberg mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, 326292a25256SJohan Hedberg conn->dst_type, conn->passkey_notify, 326392a25256SJohan Hedberg conn->passkey_entered); 326492a25256SJohan Hedberg } 326592a25256SJohan Hedberg 32666039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev, 3267807deac2SGustavo Padovan struct sk_buff *skb) 32680493684eSMarcel Holtmann { 32690493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 32700493684eSMarcel Holtmann struct hci_conn *conn; 32710493684eSMarcel Holtmann 32720493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 32730493684eSMarcel Holtmann 32740493684eSMarcel Holtmann hci_dev_lock(hdev); 32750493684eSMarcel Holtmann 32760493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 32772a611692SJohan Hedberg if (!conn) 32782a611692SJohan Hedberg goto unlock; 32792a611692SJohan Hedberg 32802a611692SJohan Hedberg /* To avoid duplicate auth_failed events to user space we check 32812a611692SJohan Hedberg * the HCI_CONN_AUTH_PEND flag which will be set if we 32822a611692SJohan Hedberg * initiated the authentication. A traditional auth_complete 32832a611692SJohan Hedberg * event gets always produced as initiator and is also mapped to 32842a611692SJohan Hedberg * the mgmt_auth_failed event */ 3285fa1bd918SMikel Astiz if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status) 3286bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 3287bab73cb6SJohan Hedberg ev->status); 32882a611692SJohan Hedberg 32890493684eSMarcel Holtmann hci_conn_put(conn); 32900493684eSMarcel Holtmann 32912a611692SJohan Hedberg unlock: 32920493684eSMarcel Holtmann hci_dev_unlock(hdev); 32930493684eSMarcel Holtmann } 32940493684eSMarcel Holtmann 32956039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev, 3296807deac2SGustavo Padovan struct sk_buff *skb) 329741a96212SMarcel Holtmann { 329841a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 329941a96212SMarcel Holtmann struct inquiry_entry *ie; 330041a96212SMarcel Holtmann 330141a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 330241a96212SMarcel Holtmann 330341a96212SMarcel Holtmann hci_dev_lock(hdev); 330441a96212SMarcel Holtmann 3305cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 3306cc11b9c1SAndrei Emeltchenko if (ie) 330702b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 330841a96212SMarcel Holtmann 330941a96212SMarcel Holtmann hci_dev_unlock(hdev); 331041a96212SMarcel Holtmann } 331141a96212SMarcel Holtmann 33126039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev, 33132763eda6SSzymon Janc struct sk_buff *skb) 33142763eda6SSzymon Janc { 33152763eda6SSzymon Janc struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; 33162763eda6SSzymon Janc struct oob_data *data; 33172763eda6SSzymon Janc 33182763eda6SSzymon Janc BT_DBG("%s", hdev->name); 33192763eda6SSzymon Janc 33202763eda6SSzymon Janc hci_dev_lock(hdev); 33212763eda6SSzymon Janc 3322a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 3323e1ba1f15SSzymon Janc goto unlock; 3324e1ba1f15SSzymon Janc 33252763eda6SSzymon Janc data = hci_find_remote_oob_data(hdev, &ev->bdaddr); 33262763eda6SSzymon Janc if (data) { 33272763eda6SSzymon Janc struct hci_cp_remote_oob_data_reply cp; 33282763eda6SSzymon Janc 33292763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 33302763eda6SSzymon Janc memcpy(cp.hash, data->hash, sizeof(cp.hash)); 33312763eda6SSzymon Janc memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); 33322763eda6SSzymon Janc 33332763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), 33342763eda6SSzymon Janc &cp); 33352763eda6SSzymon Janc } else { 33362763eda6SSzymon Janc struct hci_cp_remote_oob_data_neg_reply cp; 33372763eda6SSzymon Janc 33382763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 33392763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), 33402763eda6SSzymon Janc &cp); 33412763eda6SSzymon Janc } 33422763eda6SSzymon Janc 3343e1ba1f15SSzymon Janc unlock: 33442763eda6SSzymon Janc hci_dev_unlock(hdev); 33452763eda6SSzymon Janc } 33462763eda6SSzymon Janc 3347d5e91192SAndrei Emeltchenko static void hci_phy_link_complete_evt(struct hci_dev *hdev, 3348d5e91192SAndrei Emeltchenko struct sk_buff *skb) 3349d5e91192SAndrei Emeltchenko { 3350d5e91192SAndrei Emeltchenko struct hci_ev_phy_link_complete *ev = (void *) skb->data; 3351d5e91192SAndrei Emeltchenko struct hci_conn *hcon, *bredr_hcon; 3352d5e91192SAndrei Emeltchenko 3353d5e91192SAndrei Emeltchenko BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle, 3354d5e91192SAndrei Emeltchenko ev->status); 3355d5e91192SAndrei Emeltchenko 3356d5e91192SAndrei Emeltchenko hci_dev_lock(hdev); 3357d5e91192SAndrei Emeltchenko 3358d5e91192SAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 3359d5e91192SAndrei Emeltchenko if (!hcon) { 3360d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 3361d5e91192SAndrei Emeltchenko return; 3362d5e91192SAndrei Emeltchenko } 3363d5e91192SAndrei Emeltchenko 3364d5e91192SAndrei Emeltchenko if (ev->status) { 3365d5e91192SAndrei Emeltchenko hci_conn_del(hcon); 3366d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 3367d5e91192SAndrei Emeltchenko return; 3368d5e91192SAndrei Emeltchenko } 3369d5e91192SAndrei Emeltchenko 3370d5e91192SAndrei Emeltchenko bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon; 3371d5e91192SAndrei Emeltchenko 3372d5e91192SAndrei Emeltchenko hcon->state = BT_CONNECTED; 3373d5e91192SAndrei Emeltchenko bacpy(&hcon->dst, &bredr_hcon->dst); 3374d5e91192SAndrei Emeltchenko 3375d5e91192SAndrei Emeltchenko hci_conn_hold(hcon); 3376d5e91192SAndrei Emeltchenko hcon->disc_timeout = HCI_DISCONN_TIMEOUT; 3377d5e91192SAndrei Emeltchenko hci_conn_put(hcon); 3378d5e91192SAndrei Emeltchenko 3379d5e91192SAndrei Emeltchenko hci_conn_hold_device(hcon); 3380d5e91192SAndrei Emeltchenko hci_conn_add_sysfs(hcon); 3381d5e91192SAndrei Emeltchenko 3382cf70ff22SAndrei Emeltchenko amp_physical_cfm(bredr_hcon, hcon); 3383cf70ff22SAndrei Emeltchenko 3384d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 3385d5e91192SAndrei Emeltchenko } 3386d5e91192SAndrei Emeltchenko 338727695fb4SAndrei Emeltchenko static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 338827695fb4SAndrei Emeltchenko { 338927695fb4SAndrei Emeltchenko struct hci_ev_logical_link_complete *ev = (void *) skb->data; 339027695fb4SAndrei Emeltchenko struct hci_conn *hcon; 339127695fb4SAndrei Emeltchenko struct hci_chan *hchan; 339227695fb4SAndrei Emeltchenko struct amp_mgr *mgr; 339327695fb4SAndrei Emeltchenko 339427695fb4SAndrei Emeltchenko BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x", 339527695fb4SAndrei Emeltchenko hdev->name, le16_to_cpu(ev->handle), ev->phy_handle, 339627695fb4SAndrei Emeltchenko ev->status); 339727695fb4SAndrei Emeltchenko 339827695fb4SAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 339927695fb4SAndrei Emeltchenko if (!hcon) 340027695fb4SAndrei Emeltchenko return; 340127695fb4SAndrei Emeltchenko 340227695fb4SAndrei Emeltchenko /* Create AMP hchan */ 340327695fb4SAndrei Emeltchenko hchan = hci_chan_create(hcon); 340427695fb4SAndrei Emeltchenko if (!hchan) 340527695fb4SAndrei Emeltchenko return; 340627695fb4SAndrei Emeltchenko 340727695fb4SAndrei Emeltchenko hchan->handle = le16_to_cpu(ev->handle); 340827695fb4SAndrei Emeltchenko 340927695fb4SAndrei Emeltchenko BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan); 341027695fb4SAndrei Emeltchenko 341127695fb4SAndrei Emeltchenko mgr = hcon->amp_mgr; 341227695fb4SAndrei Emeltchenko if (mgr && mgr->bredr_chan) { 341327695fb4SAndrei Emeltchenko struct l2cap_chan *bredr_chan = mgr->bredr_chan; 341427695fb4SAndrei Emeltchenko 341527695fb4SAndrei Emeltchenko l2cap_chan_lock(bredr_chan); 341627695fb4SAndrei Emeltchenko 341727695fb4SAndrei Emeltchenko bredr_chan->conn->mtu = hdev->block_mtu; 341827695fb4SAndrei Emeltchenko l2cap_logical_cfm(bredr_chan, hchan, 0); 341927695fb4SAndrei Emeltchenko hci_conn_hold(hcon); 342027695fb4SAndrei Emeltchenko 342127695fb4SAndrei Emeltchenko l2cap_chan_unlock(bredr_chan); 342227695fb4SAndrei Emeltchenko } 342327695fb4SAndrei Emeltchenko } 342427695fb4SAndrei Emeltchenko 3425606e2a10SAndrei Emeltchenko static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev, 3426606e2a10SAndrei Emeltchenko struct sk_buff *skb) 3427606e2a10SAndrei Emeltchenko { 3428606e2a10SAndrei Emeltchenko struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data; 3429606e2a10SAndrei Emeltchenko struct hci_chan *hchan; 3430606e2a10SAndrei Emeltchenko 3431606e2a10SAndrei Emeltchenko BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name, 3432606e2a10SAndrei Emeltchenko le16_to_cpu(ev->handle), ev->status); 3433606e2a10SAndrei Emeltchenko 3434606e2a10SAndrei Emeltchenko if (ev->status) 3435606e2a10SAndrei Emeltchenko return; 3436606e2a10SAndrei Emeltchenko 3437606e2a10SAndrei Emeltchenko hci_dev_lock(hdev); 3438606e2a10SAndrei Emeltchenko 3439606e2a10SAndrei Emeltchenko hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle)); 3440606e2a10SAndrei Emeltchenko if (!hchan) 3441606e2a10SAndrei Emeltchenko goto unlock; 3442606e2a10SAndrei Emeltchenko 3443606e2a10SAndrei Emeltchenko amp_destroy_logical_link(hchan, ev->reason); 3444606e2a10SAndrei Emeltchenko 3445606e2a10SAndrei Emeltchenko unlock: 3446606e2a10SAndrei Emeltchenko hci_dev_unlock(hdev); 3447606e2a10SAndrei Emeltchenko } 3448606e2a10SAndrei Emeltchenko 34499eef6b3aSAndrei Emeltchenko static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev, 34509eef6b3aSAndrei Emeltchenko struct sk_buff *skb) 34519eef6b3aSAndrei Emeltchenko { 34529eef6b3aSAndrei Emeltchenko struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data; 34539eef6b3aSAndrei Emeltchenko struct hci_conn *hcon; 34549eef6b3aSAndrei Emeltchenko 34559eef6b3aSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 34569eef6b3aSAndrei Emeltchenko 34579eef6b3aSAndrei Emeltchenko if (ev->status) 34589eef6b3aSAndrei Emeltchenko return; 34599eef6b3aSAndrei Emeltchenko 34609eef6b3aSAndrei Emeltchenko hci_dev_lock(hdev); 34619eef6b3aSAndrei Emeltchenko 34629eef6b3aSAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 34639eef6b3aSAndrei Emeltchenko if (hcon) { 34649eef6b3aSAndrei Emeltchenko hcon->state = BT_CLOSED; 34659eef6b3aSAndrei Emeltchenko hci_conn_del(hcon); 34669eef6b3aSAndrei Emeltchenko } 34679eef6b3aSAndrei Emeltchenko 34689eef6b3aSAndrei Emeltchenko hci_dev_unlock(hdev); 34699eef6b3aSAndrei Emeltchenko } 34709eef6b3aSAndrei Emeltchenko 34716039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 3472fcd89c09SVille Tervo { 3473fcd89c09SVille Tervo struct hci_ev_le_conn_complete *ev = (void *) skb->data; 3474fcd89c09SVille Tervo struct hci_conn *conn; 3475fcd89c09SVille Tervo 34769f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 3477fcd89c09SVille Tervo 3478fcd89c09SVille Tervo hci_dev_lock(hdev); 3479fcd89c09SVille Tervo 34804f72b329SAndrzej Kaczmarek conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); 3481b62f328bSVille Tervo if (!conn) { 3482b62f328bSVille Tervo conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); 3483b62f328bSVille Tervo if (!conn) { 3484b62f328bSVille Tervo BT_ERR("No memory for new connection"); 3485230fd16aSAndre Guedes goto unlock; 3486b62f328bSVille Tervo } 348729b7988aSAndre Guedes 348829b7988aSAndre Guedes conn->dst_type = ev->bdaddr_type; 3489b9b343d2SAndre Guedes 3490b9b343d2SAndre Guedes if (ev->role == LE_CONN_ROLE_MASTER) { 3491b9b343d2SAndre Guedes conn->out = true; 3492b9b343d2SAndre Guedes conn->link_mode |= HCI_LM_MASTER; 3493b9b343d2SAndre Guedes } 3494b62f328bSVille Tervo } 3495fcd89c09SVille Tervo 3496cd17decbSAndre Guedes if (ev->status) { 3497cd17decbSAndre Guedes mgmt_connect_failed(hdev, &conn->dst, conn->type, 3498cd17decbSAndre Guedes conn->dst_type, ev->status); 3499cd17decbSAndre Guedes hci_proto_connect_cfm(conn, ev->status); 3500cd17decbSAndre Guedes conn->state = BT_CLOSED; 3501cd17decbSAndre Guedes hci_conn_del(conn); 3502cd17decbSAndre Guedes goto unlock; 3503cd17decbSAndre Guedes } 3504cd17decbSAndre Guedes 3505b644ba33SJohan Hedberg if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 3506b644ba33SJohan Hedberg mgmt_device_connected(hdev, &ev->bdaddr, conn->type, 350795b23582SSzymon Janc conn->dst_type, 0, NULL, 0, NULL); 350883bc71b4SVinicius Costa Gomes 35097b5c0d52SVinicius Costa Gomes conn->sec_level = BT_SECURITY_LOW; 3510fcd89c09SVille Tervo conn->handle = __le16_to_cpu(ev->handle); 3511fcd89c09SVille Tervo conn->state = BT_CONNECTED; 3512fcd89c09SVille Tervo 3513fcd89c09SVille Tervo hci_conn_hold_device(conn); 3514fcd89c09SVille Tervo hci_conn_add_sysfs(conn); 3515fcd89c09SVille Tervo 3516fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 3517fcd89c09SVille Tervo 3518fcd89c09SVille Tervo unlock: 3519fcd89c09SVille Tervo hci_dev_unlock(hdev); 3520fcd89c09SVille Tervo } 3521fcd89c09SVille Tervo 35226039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) 35239aa04c91SAndre Guedes { 3524e95beb41SAndre Guedes u8 num_reports = skb->data[0]; 3525e95beb41SAndre Guedes void *ptr = &skb->data[1]; 35263c9e9195SAndre Guedes s8 rssi; 35279aa04c91SAndre Guedes 3528e95beb41SAndre Guedes while (num_reports--) { 3529e95beb41SAndre Guedes struct hci_ev_le_advertising_info *ev = ptr; 3530e95beb41SAndre Guedes 35313c9e9195SAndre Guedes rssi = ev->data[ev->length]; 35323c9e9195SAndre Guedes mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type, 353304124681SGustavo F. Padovan NULL, rssi, 0, 1, ev->data, ev->length); 35343c9e9195SAndre Guedes 3535e95beb41SAndre Guedes ptr += sizeof(*ev) + ev->length + 1; 35369aa04c91SAndre Guedes } 35379aa04c91SAndre Guedes } 35389aa04c91SAndre Guedes 35396039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 3540a7a595f6SVinicius Costa Gomes { 3541a7a595f6SVinicius Costa Gomes struct hci_ev_le_ltk_req *ev = (void *) skb->data; 3542a7a595f6SVinicius Costa Gomes struct hci_cp_le_ltk_reply cp; 3543bea710feSVinicius Costa Gomes struct hci_cp_le_ltk_neg_reply neg; 3544a7a595f6SVinicius Costa Gomes struct hci_conn *conn; 3545c9839a11SVinicius Costa Gomes struct smp_ltk *ltk; 3546a7a595f6SVinicius Costa Gomes 35479f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle)); 3548a7a595f6SVinicius Costa Gomes 3549a7a595f6SVinicius Costa Gomes hci_dev_lock(hdev); 3550a7a595f6SVinicius Costa Gomes 3551a7a595f6SVinicius Costa Gomes conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3552bea710feSVinicius Costa Gomes if (conn == NULL) 3553bea710feSVinicius Costa Gomes goto not_found; 3554a7a595f6SVinicius Costa Gomes 3555bea710feSVinicius Costa Gomes ltk = hci_find_ltk(hdev, ev->ediv, ev->random); 3556bea710feSVinicius Costa Gomes if (ltk == NULL) 3557bea710feSVinicius Costa Gomes goto not_found; 3558bea710feSVinicius Costa Gomes 3559bea710feSVinicius Costa Gomes memcpy(cp.ltk, ltk->val, sizeof(ltk->val)); 3560a7a595f6SVinicius Costa Gomes cp.handle = cpu_to_le16(conn->handle); 3561c9839a11SVinicius Costa Gomes 3562c9839a11SVinicius Costa Gomes if (ltk->authenticated) 3563c9839a11SVinicius Costa Gomes conn->sec_level = BT_SECURITY_HIGH; 3564a7a595f6SVinicius Costa Gomes 3565a7a595f6SVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); 3566a7a595f6SVinicius Costa Gomes 3567c9839a11SVinicius Costa Gomes if (ltk->type & HCI_SMP_STK) { 3568c9839a11SVinicius Costa Gomes list_del(<k->list); 3569c9839a11SVinicius Costa Gomes kfree(ltk); 3570c9839a11SVinicius Costa Gomes } 3571c9839a11SVinicius Costa Gomes 3572a7a595f6SVinicius Costa Gomes hci_dev_unlock(hdev); 3573bea710feSVinicius Costa Gomes 3574bea710feSVinicius Costa Gomes return; 3575bea710feSVinicius Costa Gomes 3576bea710feSVinicius Costa Gomes not_found: 3577bea710feSVinicius Costa Gomes neg.handle = ev->handle; 3578bea710feSVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg); 3579bea710feSVinicius Costa Gomes hci_dev_unlock(hdev); 3580a7a595f6SVinicius Costa Gomes } 3581a7a595f6SVinicius Costa Gomes 35826039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 3583fcd89c09SVille Tervo { 3584fcd89c09SVille Tervo struct hci_ev_le_meta *le_ev = (void *) skb->data; 3585fcd89c09SVille Tervo 3586fcd89c09SVille Tervo skb_pull(skb, sizeof(*le_ev)); 3587fcd89c09SVille Tervo 3588fcd89c09SVille Tervo switch (le_ev->subevent) { 3589fcd89c09SVille Tervo case HCI_EV_LE_CONN_COMPLETE: 3590fcd89c09SVille Tervo hci_le_conn_complete_evt(hdev, skb); 3591fcd89c09SVille Tervo break; 3592fcd89c09SVille Tervo 35939aa04c91SAndre Guedes case HCI_EV_LE_ADVERTISING_REPORT: 35949aa04c91SAndre Guedes hci_le_adv_report_evt(hdev, skb); 35959aa04c91SAndre Guedes break; 35969aa04c91SAndre Guedes 3597a7a595f6SVinicius Costa Gomes case HCI_EV_LE_LTK_REQ: 3598a7a595f6SVinicius Costa Gomes hci_le_ltk_request_evt(hdev, skb); 3599a7a595f6SVinicius Costa Gomes break; 3600a7a595f6SVinicius Costa Gomes 3601fcd89c09SVille Tervo default: 3602fcd89c09SVille Tervo break; 3603fcd89c09SVille Tervo } 3604fcd89c09SVille Tervo } 3605fcd89c09SVille Tervo 36069495b2eeSAndrei Emeltchenko static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb) 36079495b2eeSAndrei Emeltchenko { 36089495b2eeSAndrei Emeltchenko struct hci_ev_channel_selected *ev = (void *) skb->data; 36099495b2eeSAndrei Emeltchenko struct hci_conn *hcon; 36109495b2eeSAndrei Emeltchenko 36119495b2eeSAndrei Emeltchenko BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle); 36129495b2eeSAndrei Emeltchenko 36139495b2eeSAndrei Emeltchenko skb_pull(skb, sizeof(*ev)); 36149495b2eeSAndrei Emeltchenko 36159495b2eeSAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 36169495b2eeSAndrei Emeltchenko if (!hcon) 36179495b2eeSAndrei Emeltchenko return; 36189495b2eeSAndrei Emeltchenko 36199495b2eeSAndrei Emeltchenko amp_read_loc_assoc_final_data(hdev, hcon); 36209495b2eeSAndrei Emeltchenko } 36219495b2eeSAndrei Emeltchenko 36221da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 36231da177e4SLinus Torvalds { 3624a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 3625a9de9248SMarcel Holtmann __u8 event = hdr->evt; 36261da177e4SLinus Torvalds 36271da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 36281da177e4SLinus Torvalds 3629a9de9248SMarcel Holtmann switch (event) { 36301da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 36311da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 36321da177e4SLinus Torvalds break; 36331da177e4SLinus Torvalds 36341da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 36351da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 36361da177e4SLinus Torvalds break; 36371da177e4SLinus Torvalds 3638a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 3639a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 364021d9e30eSMarcel Holtmann break; 364121d9e30eSMarcel Holtmann 36421da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 36431da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 36441da177e4SLinus Torvalds break; 36451da177e4SLinus Torvalds 36461da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 36471da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 36481da177e4SLinus Torvalds break; 36491da177e4SLinus Torvalds 36501da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 36511da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 36521da177e4SLinus Torvalds break; 36531da177e4SLinus Torvalds 3654a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 3655a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 3656a9de9248SMarcel Holtmann break; 3657a9de9248SMarcel Holtmann 36581da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 36591da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 36601da177e4SLinus Torvalds break; 36611da177e4SLinus Torvalds 3662a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 3663a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 3664a9de9248SMarcel Holtmann break; 3665a9de9248SMarcel Holtmann 3666a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 3667a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 3668a9de9248SMarcel Holtmann break; 3669a9de9248SMarcel Holtmann 3670a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 3671a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 3672a9de9248SMarcel Holtmann break; 3673a9de9248SMarcel Holtmann 3674a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 3675a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 3676a9de9248SMarcel Holtmann break; 3677a9de9248SMarcel Holtmann 3678a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 3679a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 3680a9de9248SMarcel Holtmann break; 3681a9de9248SMarcel Holtmann 3682a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 3683a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 3684a9de9248SMarcel Holtmann break; 3685a9de9248SMarcel Holtmann 3686a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 3687a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 36881da177e4SLinus Torvalds break; 36891da177e4SLinus Torvalds 36901da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 36911da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 36921da177e4SLinus Torvalds break; 36931da177e4SLinus Torvalds 36941da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 36951da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 36961da177e4SLinus Torvalds break; 36971da177e4SLinus Torvalds 36981da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 36991da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 37001da177e4SLinus Torvalds break; 37011da177e4SLinus Torvalds 37021da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 37031da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 37041da177e4SLinus Torvalds break; 37051da177e4SLinus Torvalds 3706a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 3707a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 3708a8746417SMarcel Holtmann break; 3709a8746417SMarcel Holtmann 371085a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 371185a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 371285a1e930SMarcel Holtmann break; 371385a1e930SMarcel Holtmann 3714a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 3715a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 3716a9de9248SMarcel Holtmann break; 3717a9de9248SMarcel Holtmann 3718a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 3719a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 3720a9de9248SMarcel Holtmann break; 3721a9de9248SMarcel Holtmann 3722a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 3723a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 3724a9de9248SMarcel Holtmann break; 3725a9de9248SMarcel Holtmann 3726a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 3727a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 37281da177e4SLinus Torvalds break; 37291da177e4SLinus Torvalds 37301c2e0041SJohan Hedberg case HCI_EV_KEY_REFRESH_COMPLETE: 37311c2e0041SJohan Hedberg hci_key_refresh_complete_evt(hdev, skb); 37321c2e0041SJohan Hedberg break; 37331c2e0041SJohan Hedberg 37340493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 37350493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 37360493684eSMarcel Holtmann break; 37370493684eSMarcel Holtmann 373803b555e1SJohan Hedberg case HCI_EV_IO_CAPA_REPLY: 373903b555e1SJohan Hedberg hci_io_capa_reply_evt(hdev, skb); 374003b555e1SJohan Hedberg break; 374103b555e1SJohan Hedberg 3742a5c29683SJohan Hedberg case HCI_EV_USER_CONFIRM_REQUEST: 3743a5c29683SJohan Hedberg hci_user_confirm_request_evt(hdev, skb); 3744a5c29683SJohan Hedberg break; 3745a5c29683SJohan Hedberg 37461143d458SBrian Gix case HCI_EV_USER_PASSKEY_REQUEST: 37471143d458SBrian Gix hci_user_passkey_request_evt(hdev, skb); 37481143d458SBrian Gix break; 37491143d458SBrian Gix 375092a25256SJohan Hedberg case HCI_EV_USER_PASSKEY_NOTIFY: 375192a25256SJohan Hedberg hci_user_passkey_notify_evt(hdev, skb); 375292a25256SJohan Hedberg break; 375392a25256SJohan Hedberg 375492a25256SJohan Hedberg case HCI_EV_KEYPRESS_NOTIFY: 375592a25256SJohan Hedberg hci_keypress_notify_evt(hdev, skb); 375692a25256SJohan Hedberg break; 375792a25256SJohan Hedberg 37580493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 37590493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 37600493684eSMarcel Holtmann break; 37610493684eSMarcel Holtmann 376241a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 376341a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 376441a96212SMarcel Holtmann break; 376541a96212SMarcel Holtmann 3766fcd89c09SVille Tervo case HCI_EV_LE_META: 3767fcd89c09SVille Tervo hci_le_meta_evt(hdev, skb); 3768fcd89c09SVille Tervo break; 3769fcd89c09SVille Tervo 37709495b2eeSAndrei Emeltchenko case HCI_EV_CHANNEL_SELECTED: 37719495b2eeSAndrei Emeltchenko hci_chan_selected_evt(hdev, skb); 37729495b2eeSAndrei Emeltchenko break; 37739495b2eeSAndrei Emeltchenko 37742763eda6SSzymon Janc case HCI_EV_REMOTE_OOB_DATA_REQUEST: 37752763eda6SSzymon Janc hci_remote_oob_data_request_evt(hdev, skb); 37762763eda6SSzymon Janc break; 37772763eda6SSzymon Janc 3778d5e91192SAndrei Emeltchenko case HCI_EV_PHY_LINK_COMPLETE: 3779d5e91192SAndrei Emeltchenko hci_phy_link_complete_evt(hdev, skb); 3780d5e91192SAndrei Emeltchenko break; 3781d5e91192SAndrei Emeltchenko 378227695fb4SAndrei Emeltchenko case HCI_EV_LOGICAL_LINK_COMPLETE: 378327695fb4SAndrei Emeltchenko hci_loglink_complete_evt(hdev, skb); 378427695fb4SAndrei Emeltchenko break; 378527695fb4SAndrei Emeltchenko 3786606e2a10SAndrei Emeltchenko case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE: 3787606e2a10SAndrei Emeltchenko hci_disconn_loglink_complete_evt(hdev, skb); 3788606e2a10SAndrei Emeltchenko break; 3789606e2a10SAndrei Emeltchenko 37909eef6b3aSAndrei Emeltchenko case HCI_EV_DISCONN_PHY_LINK_COMPLETE: 37919eef6b3aSAndrei Emeltchenko hci_disconn_phylink_complete_evt(hdev, skb); 37929eef6b3aSAndrei Emeltchenko break; 37939eef6b3aSAndrei Emeltchenko 379425e89e99SAndrei Emeltchenko case HCI_EV_NUM_COMP_BLOCKS: 379525e89e99SAndrei Emeltchenko hci_num_comp_blocks_evt(hdev, skb); 379625e89e99SAndrei Emeltchenko break; 379725e89e99SAndrei Emeltchenko 37981da177e4SLinus Torvalds default: 37999f1db00cSAndrei Emeltchenko BT_DBG("%s event 0x%2.2x", hdev->name, event); 38001da177e4SLinus Torvalds break; 38011da177e4SLinus Torvalds } 38021da177e4SLinus Torvalds 38031da177e4SLinus Torvalds kfree_skb(skb); 38041da177e4SLinus Torvalds hdev->stat.evt_rx++; 38051da177e4SLinus Torvalds } 3806