11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds BlueZ - Bluetooth protocol stack for Linux 32d0a0346SRon Shaffer Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved. 41da177e4SLinus Torvalds 51da177e4SLinus Torvalds Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> 61da177e4SLinus Torvalds 71da177e4SLinus Torvalds This program is free software; you can redistribute it and/or modify 81da177e4SLinus Torvalds it under the terms of the GNU General Public License version 2 as 91da177e4SLinus Torvalds published by the Free Software Foundation; 101da177e4SLinus Torvalds 111da177e4SLinus Torvalds THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 121da177e4SLinus Torvalds OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 131da177e4SLinus Torvalds FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 141da177e4SLinus Torvalds IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 151da177e4SLinus Torvalds CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 161da177e4SLinus Torvalds WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 171da177e4SLinus Torvalds ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 181da177e4SLinus Torvalds OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 211da177e4SLinus Torvalds COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 221da177e4SLinus Torvalds SOFTWARE IS DISCLAIMED. 231da177e4SLinus Torvalds */ 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds /* Bluetooth HCI event handling. */ 261da177e4SLinus Torvalds 271da177e4SLinus Torvalds #include <asm/unaligned.h> 281da177e4SLinus Torvalds 291da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h> 301da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h> 31f0d6a0eaSMikel Astiz #include <net/bluetooth/mgmt.h> 327ef9fbf0SMarcel Holtmann 337024728eSMarcel Holtmann #include "a2mp.h" 347ef9fbf0SMarcel Holtmann #include "amp.h" 352ceba539SJohan Hedberg #include "smp.h" 361da177e4SLinus Torvalds 371da177e4SLinus Torvalds /* Handle HCI Event packets */ 381da177e4SLinus Torvalds 39a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb) 401da177e4SLinus Torvalds { 41a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 421da177e4SLinus Torvalds 439f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 441da177e4SLinus Torvalds 4582f4785cSAndre Guedes if (status) 46a9de9248SMarcel Holtmann return; 471da177e4SLinus Torvalds 4889352e7dSAndre Guedes clear_bit(HCI_INQUIRY, &hdev->flags); 494e857c58SPeter Zijlstra smp_mb__after_atomic(); /* wake_up_bit advises about this barrier */ 503e13fa1eSAndre Guedes wake_up_bit(&hdev->flags, HCI_INQUIRY); 5189352e7dSAndre Guedes 5250143a43SJohan Hedberg hci_dev_lock(hdev); 5350143a43SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 5450143a43SJohan Hedberg hci_dev_unlock(hdev); 5550143a43SJohan Hedberg 56a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 571da177e4SLinus Torvalds } 586bd57416SMarcel Holtmann 594d93483bSAndre Guedes static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 604d93483bSAndre Guedes { 614d93483bSAndre Guedes __u8 status = *((__u8 *) skb->data); 624d93483bSAndre Guedes 639f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 64ae854a70SAndre Guedes 65ae854a70SAndre Guedes if (status) 66ae854a70SAndre Guedes return; 67ae854a70SAndre Guedes 68ae854a70SAndre Guedes set_bit(HCI_PERIODIC_INQ, &hdev->dev_flags); 694d93483bSAndre Guedes } 704d93483bSAndre Guedes 71a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 721da177e4SLinus Torvalds { 73a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 74a9de9248SMarcel Holtmann 759f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 76a9de9248SMarcel Holtmann 77a9de9248SMarcel Holtmann if (status) 78a9de9248SMarcel Holtmann return; 79a9de9248SMarcel Holtmann 80ae854a70SAndre Guedes clear_bit(HCI_PERIODIC_INQ, &hdev->dev_flags); 81ae854a70SAndre Guedes 82a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 83a9de9248SMarcel Holtmann } 84a9de9248SMarcel Holtmann 85807deac2SGustavo Padovan static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, 86807deac2SGustavo Padovan struct sk_buff *skb) 87a9de9248SMarcel Holtmann { 88a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 89a9de9248SMarcel Holtmann } 90a9de9248SMarcel Holtmann 91a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb) 92a9de9248SMarcel Holtmann { 93a9de9248SMarcel Holtmann struct hci_rp_role_discovery *rp = (void *) skb->data; 941da177e4SLinus Torvalds struct hci_conn *conn; 951da177e4SLinus Torvalds 969f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 971da177e4SLinus Torvalds 98a9de9248SMarcel Holtmann if (rp->status) 99a9de9248SMarcel Holtmann return; 1001da177e4SLinus Torvalds 1011da177e4SLinus Torvalds hci_dev_lock(hdev); 1021da177e4SLinus Torvalds 103a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 1041da177e4SLinus Torvalds if (conn) { 105a9de9248SMarcel Holtmann if (rp->role) 1064dae2798SJohan Hedberg clear_bit(HCI_CONN_MASTER, &conn->flags); 1071da177e4SLinus Torvalds else 1084dae2798SJohan Hedberg set_bit(HCI_CONN_MASTER, &conn->flags); 1091da177e4SLinus Torvalds } 1101da177e4SLinus Torvalds 1111da177e4SLinus Torvalds hci_dev_unlock(hdev); 112a9de9248SMarcel Holtmann } 1131da177e4SLinus Torvalds 114e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 115e4e8e37cSMarcel Holtmann { 116e4e8e37cSMarcel Holtmann struct hci_rp_read_link_policy *rp = (void *) skb->data; 117e4e8e37cSMarcel Holtmann struct hci_conn *conn; 118e4e8e37cSMarcel Holtmann 1199f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 120e4e8e37cSMarcel Holtmann 121e4e8e37cSMarcel Holtmann if (rp->status) 122e4e8e37cSMarcel Holtmann return; 123e4e8e37cSMarcel Holtmann 124e4e8e37cSMarcel Holtmann hci_dev_lock(hdev); 125e4e8e37cSMarcel Holtmann 126e4e8e37cSMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 127e4e8e37cSMarcel Holtmann if (conn) 128e4e8e37cSMarcel Holtmann conn->link_policy = __le16_to_cpu(rp->policy); 129e4e8e37cSMarcel Holtmann 130e4e8e37cSMarcel Holtmann hci_dev_unlock(hdev); 131e4e8e37cSMarcel Holtmann } 132e4e8e37cSMarcel Holtmann 133a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 134a9de9248SMarcel Holtmann { 135a9de9248SMarcel Holtmann struct hci_rp_write_link_policy *rp = (void *) skb->data; 136a9de9248SMarcel Holtmann struct hci_conn *conn; 137a9de9248SMarcel Holtmann void *sent; 138a9de9248SMarcel Holtmann 1399f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 140a9de9248SMarcel Holtmann 141a9de9248SMarcel Holtmann if (rp->status) 142a9de9248SMarcel Holtmann return; 143a9de9248SMarcel Holtmann 144a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY); 14504837f64SMarcel Holtmann if (!sent) 146a9de9248SMarcel Holtmann return; 14704837f64SMarcel Holtmann 14804837f64SMarcel Holtmann hci_dev_lock(hdev); 14904837f64SMarcel Holtmann 150a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 151e4e8e37cSMarcel Holtmann if (conn) 15283985319SHarvey Harrison conn->link_policy = get_unaligned_le16(sent + 2); 15304837f64SMarcel Holtmann 15404837f64SMarcel Holtmann hci_dev_unlock(hdev); 1551da177e4SLinus Torvalds } 1561da177e4SLinus Torvalds 157807deac2SGustavo Padovan static void hci_cc_read_def_link_policy(struct hci_dev *hdev, 158807deac2SGustavo Padovan struct sk_buff *skb) 159e4e8e37cSMarcel Holtmann { 160e4e8e37cSMarcel Holtmann struct hci_rp_read_def_link_policy *rp = (void *) skb->data; 161e4e8e37cSMarcel Holtmann 1629f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 163e4e8e37cSMarcel Holtmann 164e4e8e37cSMarcel Holtmann if (rp->status) 165e4e8e37cSMarcel Holtmann return; 166e4e8e37cSMarcel Holtmann 167e4e8e37cSMarcel Holtmann hdev->link_policy = __le16_to_cpu(rp->policy); 168e4e8e37cSMarcel Holtmann } 169e4e8e37cSMarcel Holtmann 170807deac2SGustavo Padovan static void hci_cc_write_def_link_policy(struct hci_dev *hdev, 171807deac2SGustavo Padovan struct sk_buff *skb) 172e4e8e37cSMarcel Holtmann { 173e4e8e37cSMarcel Holtmann __u8 status = *((__u8 *) skb->data); 174e4e8e37cSMarcel Holtmann void *sent; 175e4e8e37cSMarcel Holtmann 1769f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 177e4e8e37cSMarcel Holtmann 178e4e8e37cSMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY); 179e4e8e37cSMarcel Holtmann if (!sent) 180e4e8e37cSMarcel Holtmann return; 181e4e8e37cSMarcel Holtmann 182e4e8e37cSMarcel Holtmann if (!status) 183e4e8e37cSMarcel Holtmann hdev->link_policy = get_unaligned_le16(sent); 184e4e8e37cSMarcel Holtmann } 185e4e8e37cSMarcel Holtmann 186a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) 1871da177e4SLinus Torvalds { 188a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 189a9de9248SMarcel Holtmann 1909f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 191a9de9248SMarcel Holtmann 19210572132SGustavo F. Padovan clear_bit(HCI_RESET, &hdev->flags); 19310572132SGustavo F. Padovan 194a297e97cSJohan Hedberg /* Reset all non-persistent flags */ 1952cc6fb00SJohan Hedberg hdev->dev_flags &= ~HCI_PERSISTENT_MASK; 19669775ff6SAndre Guedes 19769775ff6SAndre Guedes hdev->discovery.state = DISCOVERY_STOPPED; 198bbaf444aSJohan Hedberg hdev->inq_tx_power = HCI_TX_POWER_INVALID; 199bbaf444aSJohan Hedberg hdev->adv_tx_power = HCI_TX_POWER_INVALID; 2003f0f524bSJohan Hedberg 2013f0f524bSJohan Hedberg memset(hdev->adv_data, 0, sizeof(hdev->adv_data)); 2023f0f524bSJohan Hedberg hdev->adv_data_len = 0; 203f8e808bdSMarcel Holtmann 204f8e808bdSMarcel Holtmann memset(hdev->scan_rsp_data, 0, sizeof(hdev->scan_rsp_data)); 205f8e808bdSMarcel Holtmann hdev->scan_rsp_data_len = 0; 20606f5b778SMarcel Holtmann 207533553f8SMarcel Holtmann hdev->le_scan_type = LE_SCAN_PASSIVE; 208533553f8SMarcel Holtmann 20906f5b778SMarcel Holtmann hdev->ssp_debug_mode = 0; 210a9de9248SMarcel Holtmann } 211a9de9248SMarcel Holtmann 212a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) 213a9de9248SMarcel Holtmann { 214a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 2151da177e4SLinus Torvalds void *sent; 2161da177e4SLinus Torvalds 2179f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 2181da177e4SLinus Torvalds 219a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); 2201da177e4SLinus Torvalds if (!sent) 221a9de9248SMarcel Holtmann return; 2221da177e4SLinus Torvalds 22356e5cb86SJohan Hedberg hci_dev_lock(hdev); 22456e5cb86SJohan Hedberg 225f51d5b24SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 226f51d5b24SJohan Hedberg mgmt_set_local_name_complete(hdev, sent, status); 22728cc7bdeSJohan Hedberg else if (!status) 22828cc7bdeSJohan Hedberg memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); 229f51d5b24SJohan Hedberg 23056e5cb86SJohan Hedberg hci_dev_unlock(hdev); 231a9de9248SMarcel Holtmann } 232a9de9248SMarcel Holtmann 233a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) 234a9de9248SMarcel Holtmann { 235a9de9248SMarcel Holtmann struct hci_rp_read_local_name *rp = (void *) skb->data; 236a9de9248SMarcel Holtmann 2379f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 238a9de9248SMarcel Holtmann 239a9de9248SMarcel Holtmann if (rp->status) 240a9de9248SMarcel Holtmann return; 241a9de9248SMarcel Holtmann 242db99b5fcSJohan Hedberg if (test_bit(HCI_SETUP, &hdev->dev_flags)) 2431f6c6378SJohan Hedberg memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); 244a9de9248SMarcel Holtmann } 245a9de9248SMarcel Holtmann 246a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) 247a9de9248SMarcel Holtmann { 248a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 249a9de9248SMarcel Holtmann void *sent; 250a9de9248SMarcel Holtmann 2519f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 252a9de9248SMarcel Holtmann 253a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); 254a9de9248SMarcel Holtmann if (!sent) 255a9de9248SMarcel Holtmann return; 2561da177e4SLinus Torvalds 2571da177e4SLinus Torvalds if (!status) { 258a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 259a9de9248SMarcel Holtmann 2601da177e4SLinus Torvalds if (param == AUTH_ENABLED) 2611da177e4SLinus Torvalds set_bit(HCI_AUTH, &hdev->flags); 2621da177e4SLinus Torvalds else 2631da177e4SLinus Torvalds clear_bit(HCI_AUTH, &hdev->flags); 2641da177e4SLinus Torvalds } 265a9de9248SMarcel Holtmann 26633ef95edSJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 26733ef95edSJohan Hedberg mgmt_auth_enable_complete(hdev, status); 268a9de9248SMarcel Holtmann } 2691da177e4SLinus Torvalds 270a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) 271a9de9248SMarcel Holtmann { 272a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 273a9de9248SMarcel Holtmann void *sent; 274a9de9248SMarcel Holtmann 2759f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 276a9de9248SMarcel Holtmann 277a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); 2781da177e4SLinus Torvalds if (!sent) 279a9de9248SMarcel Holtmann return; 2801da177e4SLinus Torvalds 2811da177e4SLinus Torvalds if (!status) { 282a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 283a9de9248SMarcel Holtmann 2841da177e4SLinus Torvalds if (param) 2851da177e4SLinus Torvalds set_bit(HCI_ENCRYPT, &hdev->flags); 2861da177e4SLinus Torvalds else 2871da177e4SLinus Torvalds clear_bit(HCI_ENCRYPT, &hdev->flags); 2881da177e4SLinus Torvalds } 2891da177e4SLinus Torvalds } 2901da177e4SLinus Torvalds 291a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) 292a9de9248SMarcel Holtmann { 29336f7fc7eSJohan Hedberg __u8 param, status = *((__u8 *) skb->data); 29436f7fc7eSJohan Hedberg int old_pscan, old_iscan; 295a9de9248SMarcel Holtmann void *sent; 2961da177e4SLinus Torvalds 2979f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 298a9de9248SMarcel Holtmann 299a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); 3001da177e4SLinus Torvalds if (!sent) 301a9de9248SMarcel Holtmann return; 3021da177e4SLinus Torvalds 30336f7fc7eSJohan Hedberg param = *((__u8 *) sent); 304a9de9248SMarcel Holtmann 30556e5cb86SJohan Hedberg hci_dev_lock(hdev); 30656e5cb86SJohan Hedberg 307fa1bd918SMikel Astiz if (status) { 308744cf19eSJohan Hedberg mgmt_write_scan_failed(hdev, param, status); 3092d7cee58SJohan Hedberg hdev->discov_timeout = 0; 3102d7cee58SJohan Hedberg goto done; 3112d7cee58SJohan Hedberg } 3122d7cee58SJohan Hedberg 3130663ca2aSJohan Hedberg /* We need to ensure that we set this back on if someone changed 3140663ca2aSJohan Hedberg * the scan mode through a raw HCI socket. 3150663ca2aSJohan Hedberg */ 3160663ca2aSJohan Hedberg set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags); 3170663ca2aSJohan Hedberg 3189fbcbb45SJohan Hedberg old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags); 3199fbcbb45SJohan Hedberg old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags); 320a9de9248SMarcel Holtmann 32173f22f62SJohan Hedberg if (param & SCAN_INQUIRY) { 3221da177e4SLinus Torvalds set_bit(HCI_ISCAN, &hdev->flags); 3239fbcbb45SJohan Hedberg if (!old_iscan) 324744cf19eSJohan Hedberg mgmt_discoverable(hdev, 1); 3259fbcbb45SJohan Hedberg } else if (old_iscan) 326744cf19eSJohan Hedberg mgmt_discoverable(hdev, 0); 3271da177e4SLinus Torvalds 3289fbcbb45SJohan Hedberg if (param & SCAN_PAGE) { 3291da177e4SLinus Torvalds set_bit(HCI_PSCAN, &hdev->flags); 3309fbcbb45SJohan Hedberg if (!old_pscan) 331744cf19eSJohan Hedberg mgmt_connectable(hdev, 1); 3329fbcbb45SJohan Hedberg } else if (old_pscan) 333744cf19eSJohan Hedberg mgmt_connectable(hdev, 0); 334a9de9248SMarcel Holtmann 33536f7fc7eSJohan Hedberg done: 33656e5cb86SJohan Hedberg hci_dev_unlock(hdev); 3371da177e4SLinus Torvalds } 3381da177e4SLinus Torvalds 339a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 340a9de9248SMarcel Holtmann { 341a9de9248SMarcel Holtmann struct hci_rp_read_class_of_dev *rp = (void *) skb->data; 342a9de9248SMarcel Holtmann 3439f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 344a9de9248SMarcel Holtmann 345a9de9248SMarcel Holtmann if (rp->status) 346a9de9248SMarcel Holtmann return; 347a9de9248SMarcel Holtmann 348a9de9248SMarcel Holtmann memcpy(hdev->dev_class, rp->dev_class, 3); 349a9de9248SMarcel Holtmann 350a9de9248SMarcel Holtmann BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, 351a9de9248SMarcel Holtmann hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); 352a9de9248SMarcel Holtmann } 353a9de9248SMarcel Holtmann 354a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 355a9de9248SMarcel Holtmann { 356a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 357a9de9248SMarcel Holtmann void *sent; 358a9de9248SMarcel Holtmann 3599f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 360a9de9248SMarcel Holtmann 361a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); 362a9de9248SMarcel Holtmann if (!sent) 363a9de9248SMarcel Holtmann return; 364a9de9248SMarcel Holtmann 3657f9a903cSMarcel Holtmann hci_dev_lock(hdev); 3667f9a903cSMarcel Holtmann 3677f9a903cSMarcel Holtmann if (status == 0) 368a9de9248SMarcel Holtmann memcpy(hdev->dev_class, sent, 3); 3697f9a903cSMarcel Holtmann 3707f9a903cSMarcel Holtmann if (test_bit(HCI_MGMT, &hdev->dev_flags)) 3717f9a903cSMarcel Holtmann mgmt_set_class_of_dev_complete(hdev, sent, status); 3727f9a903cSMarcel Holtmann 3737f9a903cSMarcel Holtmann hci_dev_unlock(hdev); 374a9de9248SMarcel Holtmann } 375a9de9248SMarcel Holtmann 376a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 377a9de9248SMarcel Holtmann { 378a9de9248SMarcel Holtmann struct hci_rp_read_voice_setting *rp = (void *) skb->data; 379a9de9248SMarcel Holtmann __u16 setting; 380a9de9248SMarcel Holtmann 3819f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 382a9de9248SMarcel Holtmann 383a9de9248SMarcel Holtmann if (rp->status) 384a9de9248SMarcel Holtmann return; 385a9de9248SMarcel Holtmann 386a9de9248SMarcel Holtmann setting = __le16_to_cpu(rp->voice_setting); 387a9de9248SMarcel Holtmann 388a9de9248SMarcel Holtmann if (hdev->voice_setting == setting) 389a9de9248SMarcel Holtmann return; 390a9de9248SMarcel Holtmann 391a9de9248SMarcel Holtmann hdev->voice_setting = setting; 392a9de9248SMarcel Holtmann 3939f1db00cSAndrei Emeltchenko BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting); 394a9de9248SMarcel Holtmann 3953c54711cSGustavo F. Padovan if (hdev->notify) 396a9de9248SMarcel Holtmann hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 397a9de9248SMarcel Holtmann } 398a9de9248SMarcel Holtmann 3998fc9ced3SGustavo Padovan static void hci_cc_write_voice_setting(struct hci_dev *hdev, 4008fc9ced3SGustavo Padovan struct sk_buff *skb) 401a9de9248SMarcel Holtmann { 402a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 403f383f275SMarcel Holtmann __u16 setting; 404a9de9248SMarcel Holtmann void *sent; 405a9de9248SMarcel Holtmann 4069f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 407a9de9248SMarcel Holtmann 408f383f275SMarcel Holtmann if (status) 409f383f275SMarcel Holtmann return; 410f383f275SMarcel Holtmann 411a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); 412a9de9248SMarcel Holtmann if (!sent) 413a9de9248SMarcel Holtmann return; 414a9de9248SMarcel Holtmann 415f383f275SMarcel Holtmann setting = get_unaligned_le16(sent); 4161da177e4SLinus Torvalds 417f383f275SMarcel Holtmann if (hdev->voice_setting == setting) 418f383f275SMarcel Holtmann return; 419f383f275SMarcel Holtmann 4201da177e4SLinus Torvalds hdev->voice_setting = setting; 4211da177e4SLinus Torvalds 4229f1db00cSAndrei Emeltchenko BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting); 4231da177e4SLinus Torvalds 4243c54711cSGustavo F. Padovan if (hdev->notify) 4251da177e4SLinus Torvalds hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 4261da177e4SLinus Torvalds } 4271da177e4SLinus Torvalds 428b4cb9fb2SMarcel Holtmann static void hci_cc_read_num_supported_iac(struct hci_dev *hdev, 429b4cb9fb2SMarcel Holtmann struct sk_buff *skb) 430b4cb9fb2SMarcel Holtmann { 431b4cb9fb2SMarcel Holtmann struct hci_rp_read_num_supported_iac *rp = (void *) skb->data; 432b4cb9fb2SMarcel Holtmann 433b4cb9fb2SMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 434b4cb9fb2SMarcel Holtmann 435b4cb9fb2SMarcel Holtmann if (rp->status) 436b4cb9fb2SMarcel Holtmann return; 437b4cb9fb2SMarcel Holtmann 438b4cb9fb2SMarcel Holtmann hdev->num_iac = rp->num_iac; 439b4cb9fb2SMarcel Holtmann 440b4cb9fb2SMarcel Holtmann BT_DBG("%s num iac %d", hdev->name, hdev->num_iac); 441b4cb9fb2SMarcel Holtmann } 442b4cb9fb2SMarcel Holtmann 443333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 444333140b5SMarcel Holtmann { 445333140b5SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 4465ed8eb2fSJohan Hedberg struct hci_cp_write_ssp_mode *sent; 447333140b5SMarcel Holtmann 4489f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 449333140b5SMarcel Holtmann 450333140b5SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); 451333140b5SMarcel Holtmann if (!sent) 452333140b5SMarcel Holtmann return; 453333140b5SMarcel Holtmann 4545ed8eb2fSJohan Hedberg if (!status) { 4555ed8eb2fSJohan Hedberg if (sent->mode) 456cad718edSJohan Hedberg hdev->features[1][0] |= LMP_HOST_SSP; 4575ed8eb2fSJohan Hedberg else 458cad718edSJohan Hedberg hdev->features[1][0] &= ~LMP_HOST_SSP; 4595ed8eb2fSJohan Hedberg } 4605ed8eb2fSJohan Hedberg 461c0ecddc2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 4625ed8eb2fSJohan Hedberg mgmt_ssp_enable_complete(hdev, sent->mode, status); 463c0ecddc2SJohan Hedberg else if (!status) { 4645ed8eb2fSJohan Hedberg if (sent->mode) 46584bde9d6SJohan Hedberg set_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 46684bde9d6SJohan Hedberg else 46784bde9d6SJohan Hedberg clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 468c0ecddc2SJohan Hedberg } 469333140b5SMarcel Holtmann } 470333140b5SMarcel Holtmann 471eac83dc6SMarcel Holtmann static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb) 472eac83dc6SMarcel Holtmann { 473eac83dc6SMarcel Holtmann u8 status = *((u8 *) skb->data); 474eac83dc6SMarcel Holtmann struct hci_cp_write_sc_support *sent; 475eac83dc6SMarcel Holtmann 476eac83dc6SMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, status); 477eac83dc6SMarcel Holtmann 478eac83dc6SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SC_SUPPORT); 479eac83dc6SMarcel Holtmann if (!sent) 480eac83dc6SMarcel Holtmann return; 481eac83dc6SMarcel Holtmann 482eac83dc6SMarcel Holtmann if (!status) { 483eac83dc6SMarcel Holtmann if (sent->support) 484eac83dc6SMarcel Holtmann hdev->features[1][0] |= LMP_HOST_SC; 485eac83dc6SMarcel Holtmann else 486eac83dc6SMarcel Holtmann hdev->features[1][0] &= ~LMP_HOST_SC; 487eac83dc6SMarcel Holtmann } 488eac83dc6SMarcel Holtmann 489eac83dc6SMarcel Holtmann if (test_bit(HCI_MGMT, &hdev->dev_flags)) 490eac83dc6SMarcel Holtmann mgmt_sc_enable_complete(hdev, sent->support, status); 491eac83dc6SMarcel Holtmann else if (!status) { 492eac83dc6SMarcel Holtmann if (sent->support) 493eac83dc6SMarcel Holtmann set_bit(HCI_SC_ENABLED, &hdev->dev_flags); 494eac83dc6SMarcel Holtmann else 495eac83dc6SMarcel Holtmann clear_bit(HCI_SC_ENABLED, &hdev->dev_flags); 496eac83dc6SMarcel Holtmann } 497eac83dc6SMarcel Holtmann } 498eac83dc6SMarcel Holtmann 499a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) 500a9de9248SMarcel Holtmann { 501a9de9248SMarcel Holtmann struct hci_rp_read_local_version *rp = (void *) skb->data; 5021143e5a6SMarcel Holtmann 5039f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 5041143e5a6SMarcel Holtmann 505a9de9248SMarcel Holtmann if (rp->status) 50642c6b129SJohan Hedberg return; 5071143e5a6SMarcel Holtmann 5080d5551f5SMarcel Holtmann if (test_bit(HCI_SETUP, &hdev->dev_flags)) { 509a9de9248SMarcel Holtmann hdev->hci_ver = rp->hci_ver; 510e4e8e37cSMarcel Holtmann hdev->hci_rev = __le16_to_cpu(rp->hci_rev); 511d5859e22SJohan Hedberg hdev->lmp_ver = rp->lmp_ver; 512e4e8e37cSMarcel Holtmann hdev->manufacturer = __le16_to_cpu(rp->manufacturer); 513d5859e22SJohan Hedberg hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); 5140d5551f5SMarcel Holtmann } 515d5859e22SJohan Hedberg } 516d5859e22SJohan Hedberg 5178fc9ced3SGustavo Padovan static void hci_cc_read_local_commands(struct hci_dev *hdev, 5188fc9ced3SGustavo Padovan struct sk_buff *skb) 519a9de9248SMarcel Holtmann { 520a9de9248SMarcel Holtmann struct hci_rp_read_local_commands *rp = (void *) skb->data; 521a9de9248SMarcel Holtmann 5229f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 523a9de9248SMarcel Holtmann 5246a070e6eSMarcel Holtmann if (rp->status) 5256a070e6eSMarcel Holtmann return; 5266a070e6eSMarcel Holtmann 5276a070e6eSMarcel Holtmann if (test_bit(HCI_SETUP, &hdev->dev_flags)) 528a9de9248SMarcel Holtmann memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); 529a9de9248SMarcel Holtmann } 530a9de9248SMarcel Holtmann 5318fc9ced3SGustavo Padovan static void hci_cc_read_local_features(struct hci_dev *hdev, 5328fc9ced3SGustavo Padovan struct sk_buff *skb) 533a9de9248SMarcel Holtmann { 534a9de9248SMarcel Holtmann struct hci_rp_read_local_features *rp = (void *) skb->data; 535a9de9248SMarcel Holtmann 5369f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 537a9de9248SMarcel Holtmann 538a9de9248SMarcel Holtmann if (rp->status) 539a9de9248SMarcel Holtmann return; 540a9de9248SMarcel Holtmann 541a9de9248SMarcel Holtmann memcpy(hdev->features, rp->features, 8); 5421da177e4SLinus Torvalds 5431da177e4SLinus Torvalds /* Adjust default settings according to features 5441da177e4SLinus Torvalds * supported by device. */ 545a9de9248SMarcel Holtmann 546cad718edSJohan Hedberg if (hdev->features[0][0] & LMP_3SLOT) 5471da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM3 | HCI_DH3); 5481da177e4SLinus Torvalds 549cad718edSJohan Hedberg if (hdev->features[0][0] & LMP_5SLOT) 5501da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM5 | HCI_DH5); 5511da177e4SLinus Torvalds 552cad718edSJohan Hedberg if (hdev->features[0][1] & LMP_HV2) { 5531da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV2); 5545b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV2); 5555b7f9909SMarcel Holtmann } 5561da177e4SLinus Torvalds 557cad718edSJohan Hedberg if (hdev->features[0][1] & LMP_HV3) { 5581da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV3); 5595b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV3); 5605b7f9909SMarcel Holtmann } 5615b7f9909SMarcel Holtmann 56245db810fSAndre Guedes if (lmp_esco_capable(hdev)) 5635b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV3); 5645b7f9909SMarcel Holtmann 565cad718edSJohan Hedberg if (hdev->features[0][4] & LMP_EV4) 5665b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV4); 5675b7f9909SMarcel Holtmann 568cad718edSJohan Hedberg if (hdev->features[0][4] & LMP_EV5) 5695b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV5); 5701da177e4SLinus Torvalds 571cad718edSJohan Hedberg if (hdev->features[0][5] & LMP_EDR_ESCO_2M) 572efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV3); 573efc7688bSMarcel Holtmann 574cad718edSJohan Hedberg if (hdev->features[0][5] & LMP_EDR_ESCO_3M) 575efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_3EV3); 576efc7688bSMarcel Holtmann 577cad718edSJohan Hedberg if (hdev->features[0][5] & LMP_EDR_3S_ESCO) 578efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); 5791da177e4SLinus Torvalds } 5801da177e4SLinus Torvalds 581971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev, 582971e3a4bSAndre Guedes struct sk_buff *skb) 583971e3a4bSAndre Guedes { 584971e3a4bSAndre Guedes struct hci_rp_read_local_ext_features *rp = (void *) skb->data; 585971e3a4bSAndre Guedes 5869f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 587971e3a4bSAndre Guedes 588971e3a4bSAndre Guedes if (rp->status) 58942c6b129SJohan Hedberg return; 590971e3a4bSAndre Guedes 59157af75a8SMarcel Holtmann if (hdev->max_page < rp->max_page) 592d2c5d77fSJohan Hedberg hdev->max_page = rp->max_page; 593d2c5d77fSJohan Hedberg 594cad718edSJohan Hedberg if (rp->page < HCI_MAX_PAGES) 595cad718edSJohan Hedberg memcpy(hdev->features[rp->page], rp->features, 8); 596971e3a4bSAndre Guedes } 597971e3a4bSAndre Guedes 5981e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, 5991e89cffbSAndrei Emeltchenko struct sk_buff *skb) 6001e89cffbSAndrei Emeltchenko { 6011e89cffbSAndrei Emeltchenko struct hci_rp_read_flow_control_mode *rp = (void *) skb->data; 6021e89cffbSAndrei Emeltchenko 6039f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 6041e89cffbSAndrei Emeltchenko 60542c6b129SJohan Hedberg if (!rp->status) 6061e89cffbSAndrei Emeltchenko hdev->flow_ctl_mode = rp->mode; 6071e89cffbSAndrei Emeltchenko } 6081e89cffbSAndrei Emeltchenko 609a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 610a9de9248SMarcel Holtmann { 611a9de9248SMarcel Holtmann struct hci_rp_read_buffer_size *rp = (void *) skb->data; 612a9de9248SMarcel Holtmann 6139f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 614a9de9248SMarcel Holtmann 615a9de9248SMarcel Holtmann if (rp->status) 616a9de9248SMarcel Holtmann return; 617a9de9248SMarcel Holtmann 618a9de9248SMarcel Holtmann hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); 619a9de9248SMarcel Holtmann hdev->sco_mtu = rp->sco_mtu; 620a9de9248SMarcel Holtmann hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); 621a9de9248SMarcel Holtmann hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); 622da1f5198SMarcel Holtmann 623da1f5198SMarcel Holtmann if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { 624da1f5198SMarcel Holtmann hdev->sco_mtu = 64; 625da1f5198SMarcel Holtmann hdev->sco_pkts = 8; 626da1f5198SMarcel Holtmann } 627da1f5198SMarcel Holtmann 628da1f5198SMarcel Holtmann hdev->acl_cnt = hdev->acl_pkts; 629da1f5198SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 6301da177e4SLinus Torvalds 631807deac2SGustavo Padovan BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu, 632807deac2SGustavo Padovan hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts); 6331da177e4SLinus Torvalds } 6341da177e4SLinus Torvalds 635a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) 636a9de9248SMarcel Holtmann { 637a9de9248SMarcel Holtmann struct hci_rp_read_bd_addr *rp = (void *) skb->data; 6381da177e4SLinus Torvalds 6399f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 640a9de9248SMarcel Holtmann 641a9de9248SMarcel Holtmann if (!rp->status) 642a9de9248SMarcel Holtmann bacpy(&hdev->bdaddr, &rp->bdaddr); 64323bb5763SJohan Hedberg } 64423bb5763SJohan Hedberg 645f332ec66SJohan Hedberg static void hci_cc_read_page_scan_activity(struct hci_dev *hdev, 646f332ec66SJohan Hedberg struct sk_buff *skb) 647f332ec66SJohan Hedberg { 648f332ec66SJohan Hedberg struct hci_rp_read_page_scan_activity *rp = (void *) skb->data; 649f332ec66SJohan Hedberg 650f332ec66SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 651f332ec66SJohan Hedberg 652f332ec66SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags) && !rp->status) { 653f332ec66SJohan Hedberg hdev->page_scan_interval = __le16_to_cpu(rp->interval); 654f332ec66SJohan Hedberg hdev->page_scan_window = __le16_to_cpu(rp->window); 655f332ec66SJohan Hedberg } 656f332ec66SJohan Hedberg } 657f332ec66SJohan Hedberg 6584a3ee763SJohan Hedberg static void hci_cc_write_page_scan_activity(struct hci_dev *hdev, 6594a3ee763SJohan Hedberg struct sk_buff *skb) 6604a3ee763SJohan Hedberg { 6614a3ee763SJohan Hedberg u8 status = *((u8 *) skb->data); 6624a3ee763SJohan Hedberg struct hci_cp_write_page_scan_activity *sent; 6634a3ee763SJohan Hedberg 6644a3ee763SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 6654a3ee763SJohan Hedberg 6664a3ee763SJohan Hedberg if (status) 6674a3ee763SJohan Hedberg return; 6684a3ee763SJohan Hedberg 6694a3ee763SJohan Hedberg sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY); 6704a3ee763SJohan Hedberg if (!sent) 6714a3ee763SJohan Hedberg return; 6724a3ee763SJohan Hedberg 6734a3ee763SJohan Hedberg hdev->page_scan_interval = __le16_to_cpu(sent->interval); 6744a3ee763SJohan Hedberg hdev->page_scan_window = __le16_to_cpu(sent->window); 6754a3ee763SJohan Hedberg } 6764a3ee763SJohan Hedberg 677f332ec66SJohan Hedberg static void hci_cc_read_page_scan_type(struct hci_dev *hdev, 678f332ec66SJohan Hedberg struct sk_buff *skb) 679f332ec66SJohan Hedberg { 680f332ec66SJohan Hedberg struct hci_rp_read_page_scan_type *rp = (void *) skb->data; 681f332ec66SJohan Hedberg 682f332ec66SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 683f332ec66SJohan Hedberg 684f332ec66SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags) && !rp->status) 685f332ec66SJohan Hedberg hdev->page_scan_type = rp->type; 686f332ec66SJohan Hedberg } 687f332ec66SJohan Hedberg 6884a3ee763SJohan Hedberg static void hci_cc_write_page_scan_type(struct hci_dev *hdev, 6894a3ee763SJohan Hedberg struct sk_buff *skb) 6904a3ee763SJohan Hedberg { 6914a3ee763SJohan Hedberg u8 status = *((u8 *) skb->data); 6924a3ee763SJohan Hedberg u8 *type; 6934a3ee763SJohan Hedberg 6944a3ee763SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 6954a3ee763SJohan Hedberg 6964a3ee763SJohan Hedberg if (status) 6974a3ee763SJohan Hedberg return; 6984a3ee763SJohan Hedberg 6994a3ee763SJohan Hedberg type = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE); 7004a3ee763SJohan Hedberg if (type) 7014a3ee763SJohan Hedberg hdev->page_scan_type = *type; 7024a3ee763SJohan Hedberg } 7034a3ee763SJohan Hedberg 704350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev, 705350ee4cfSAndrei Emeltchenko struct sk_buff *skb) 706350ee4cfSAndrei Emeltchenko { 707350ee4cfSAndrei Emeltchenko struct hci_rp_read_data_block_size *rp = (void *) skb->data; 708350ee4cfSAndrei Emeltchenko 7099f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 710350ee4cfSAndrei Emeltchenko 711350ee4cfSAndrei Emeltchenko if (rp->status) 712350ee4cfSAndrei Emeltchenko return; 713350ee4cfSAndrei Emeltchenko 714350ee4cfSAndrei Emeltchenko hdev->block_mtu = __le16_to_cpu(rp->max_acl_len); 715350ee4cfSAndrei Emeltchenko hdev->block_len = __le16_to_cpu(rp->block_len); 716350ee4cfSAndrei Emeltchenko hdev->num_blocks = __le16_to_cpu(rp->num_blocks); 717350ee4cfSAndrei Emeltchenko 718350ee4cfSAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 719350ee4cfSAndrei Emeltchenko 720350ee4cfSAndrei Emeltchenko BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu, 721350ee4cfSAndrei Emeltchenko hdev->block_cnt, hdev->block_len); 722350ee4cfSAndrei Emeltchenko } 723350ee4cfSAndrei Emeltchenko 72433f35721SJohan Hedberg static void hci_cc_read_clock(struct hci_dev *hdev, struct sk_buff *skb) 72533f35721SJohan Hedberg { 72633f35721SJohan Hedberg struct hci_rp_read_clock *rp = (void *) skb->data; 72733f35721SJohan Hedberg struct hci_cp_read_clock *cp; 72833f35721SJohan Hedberg struct hci_conn *conn; 72933f35721SJohan Hedberg 73033f35721SJohan Hedberg BT_DBG("%s", hdev->name); 73133f35721SJohan Hedberg 73233f35721SJohan Hedberg if (skb->len < sizeof(*rp)) 73333f35721SJohan Hedberg return; 73433f35721SJohan Hedberg 73533f35721SJohan Hedberg if (rp->status) 73633f35721SJohan Hedberg return; 73733f35721SJohan Hedberg 73833f35721SJohan Hedberg hci_dev_lock(hdev); 73933f35721SJohan Hedberg 74033f35721SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK); 74133f35721SJohan Hedberg if (!cp) 74233f35721SJohan Hedberg goto unlock; 74333f35721SJohan Hedberg 74433f35721SJohan Hedberg if (cp->which == 0x00) { 74533f35721SJohan Hedberg hdev->clock = le32_to_cpu(rp->clock); 74633f35721SJohan Hedberg goto unlock; 74733f35721SJohan Hedberg } 74833f35721SJohan Hedberg 74933f35721SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 75033f35721SJohan Hedberg if (conn) { 75133f35721SJohan Hedberg conn->clock = le32_to_cpu(rp->clock); 75233f35721SJohan Hedberg conn->clock_accuracy = le16_to_cpu(rp->accuracy); 75333f35721SJohan Hedberg } 75433f35721SJohan Hedberg 75533f35721SJohan Hedberg unlock: 75633f35721SJohan Hedberg hci_dev_unlock(hdev); 75733f35721SJohan Hedberg } 75833f35721SJohan Hedberg 759928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev, 760928abaa7SAndrei Emeltchenko struct sk_buff *skb) 761928abaa7SAndrei Emeltchenko { 762928abaa7SAndrei Emeltchenko struct hci_rp_read_local_amp_info *rp = (void *) skb->data; 763928abaa7SAndrei Emeltchenko 7649f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 765928abaa7SAndrei Emeltchenko 766928abaa7SAndrei Emeltchenko if (rp->status) 7678e2a0d92SAndrei Emeltchenko goto a2mp_rsp; 768928abaa7SAndrei Emeltchenko 769928abaa7SAndrei Emeltchenko hdev->amp_status = rp->amp_status; 770928abaa7SAndrei Emeltchenko hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); 771928abaa7SAndrei Emeltchenko hdev->amp_max_bw = __le32_to_cpu(rp->max_bw); 772928abaa7SAndrei Emeltchenko hdev->amp_min_latency = __le32_to_cpu(rp->min_latency); 773928abaa7SAndrei Emeltchenko hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu); 774928abaa7SAndrei Emeltchenko hdev->amp_type = rp->amp_type; 775928abaa7SAndrei Emeltchenko hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap); 776928abaa7SAndrei Emeltchenko hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size); 777928abaa7SAndrei Emeltchenko hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); 778928abaa7SAndrei Emeltchenko hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); 779928abaa7SAndrei Emeltchenko 7808e2a0d92SAndrei Emeltchenko a2mp_rsp: 7818e2a0d92SAndrei Emeltchenko a2mp_send_getinfo_rsp(hdev); 782928abaa7SAndrei Emeltchenko } 783928abaa7SAndrei Emeltchenko 784903e4541SAndrei Emeltchenko static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev, 785903e4541SAndrei Emeltchenko struct sk_buff *skb) 786903e4541SAndrei Emeltchenko { 787903e4541SAndrei Emeltchenko struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data; 788903e4541SAndrei Emeltchenko struct amp_assoc *assoc = &hdev->loc_assoc; 789903e4541SAndrei Emeltchenko size_t rem_len, frag_len; 790903e4541SAndrei Emeltchenko 791903e4541SAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 792903e4541SAndrei Emeltchenko 793903e4541SAndrei Emeltchenko if (rp->status) 794903e4541SAndrei Emeltchenko goto a2mp_rsp; 795903e4541SAndrei Emeltchenko 796903e4541SAndrei Emeltchenko frag_len = skb->len - sizeof(*rp); 797903e4541SAndrei Emeltchenko rem_len = __le16_to_cpu(rp->rem_len); 798903e4541SAndrei Emeltchenko 799903e4541SAndrei Emeltchenko if (rem_len > frag_len) { 8002e430be3SAndrei Emeltchenko BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len); 801903e4541SAndrei Emeltchenko 802903e4541SAndrei Emeltchenko memcpy(assoc->data + assoc->offset, rp->frag, frag_len); 803903e4541SAndrei Emeltchenko assoc->offset += frag_len; 804903e4541SAndrei Emeltchenko 805903e4541SAndrei Emeltchenko /* Read other fragments */ 806903e4541SAndrei Emeltchenko amp_read_loc_assoc_frag(hdev, rp->phy_handle); 807903e4541SAndrei Emeltchenko 808903e4541SAndrei Emeltchenko return; 809903e4541SAndrei Emeltchenko } 810903e4541SAndrei Emeltchenko 811903e4541SAndrei Emeltchenko memcpy(assoc->data + assoc->offset, rp->frag, rem_len); 812903e4541SAndrei Emeltchenko assoc->len = assoc->offset + rem_len; 813903e4541SAndrei Emeltchenko assoc->offset = 0; 814903e4541SAndrei Emeltchenko 815903e4541SAndrei Emeltchenko a2mp_rsp: 816903e4541SAndrei Emeltchenko /* Send A2MP Rsp when all fragments are received */ 817903e4541SAndrei Emeltchenko a2mp_send_getampassoc_rsp(hdev, rp->status); 8189495b2eeSAndrei Emeltchenko a2mp_send_create_phy_link_req(hdev, rp->status); 819903e4541SAndrei Emeltchenko } 820903e4541SAndrei Emeltchenko 821d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, 822d5859e22SJohan Hedberg struct sk_buff *skb) 823d5859e22SJohan Hedberg { 82491c4e9b1SMarcel Holtmann struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data; 825d5859e22SJohan Hedberg 8269f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 827d5859e22SJohan Hedberg 82891c4e9b1SMarcel Holtmann if (!rp->status) 82991c4e9b1SMarcel Holtmann hdev->inq_tx_power = rp->tx_power; 830d5859e22SJohan Hedberg } 831d5859e22SJohan Hedberg 832980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) 833980e1a53SJohan Hedberg { 834980e1a53SJohan Hedberg struct hci_rp_pin_code_reply *rp = (void *) skb->data; 835980e1a53SJohan Hedberg struct hci_cp_pin_code_reply *cp; 836980e1a53SJohan Hedberg struct hci_conn *conn; 837980e1a53SJohan Hedberg 8389f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 839980e1a53SJohan Hedberg 84056e5cb86SJohan Hedberg hci_dev_lock(hdev); 84156e5cb86SJohan Hedberg 842a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 843744cf19eSJohan Hedberg mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); 844980e1a53SJohan Hedberg 845fa1bd918SMikel Astiz if (rp->status) 84656e5cb86SJohan Hedberg goto unlock; 847980e1a53SJohan Hedberg 848980e1a53SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); 849980e1a53SJohan Hedberg if (!cp) 85056e5cb86SJohan Hedberg goto unlock; 851980e1a53SJohan Hedberg 852980e1a53SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 853980e1a53SJohan Hedberg if (conn) 854980e1a53SJohan Hedberg conn->pin_length = cp->pin_len; 85556e5cb86SJohan Hedberg 85656e5cb86SJohan Hedberg unlock: 85756e5cb86SJohan Hedberg hci_dev_unlock(hdev); 858980e1a53SJohan Hedberg } 859980e1a53SJohan Hedberg 860980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 861980e1a53SJohan Hedberg { 862980e1a53SJohan Hedberg struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data; 863980e1a53SJohan Hedberg 8649f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 865980e1a53SJohan Hedberg 86656e5cb86SJohan Hedberg hci_dev_lock(hdev); 86756e5cb86SJohan Hedberg 868a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 869744cf19eSJohan Hedberg mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr, 870980e1a53SJohan Hedberg rp->status); 87156e5cb86SJohan Hedberg 87256e5cb86SJohan Hedberg hci_dev_unlock(hdev); 873980e1a53SJohan Hedberg } 87456e5cb86SJohan Hedberg 8756ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, 8766ed58ec5SVille Tervo struct sk_buff *skb) 8776ed58ec5SVille Tervo { 8786ed58ec5SVille Tervo struct hci_rp_le_read_buffer_size *rp = (void *) skb->data; 8796ed58ec5SVille Tervo 8809f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 8816ed58ec5SVille Tervo 8826ed58ec5SVille Tervo if (rp->status) 8836ed58ec5SVille Tervo return; 8846ed58ec5SVille Tervo 8856ed58ec5SVille Tervo hdev->le_mtu = __le16_to_cpu(rp->le_mtu); 8866ed58ec5SVille Tervo hdev->le_pkts = rp->le_max_pkt; 8876ed58ec5SVille Tervo 8886ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 8896ed58ec5SVille Tervo 8906ed58ec5SVille Tervo BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); 8916ed58ec5SVille Tervo } 892980e1a53SJohan Hedberg 89360e77321SJohan Hedberg static void hci_cc_le_read_local_features(struct hci_dev *hdev, 89460e77321SJohan Hedberg struct sk_buff *skb) 89560e77321SJohan Hedberg { 89660e77321SJohan Hedberg struct hci_rp_le_read_local_features *rp = (void *) skb->data; 89760e77321SJohan Hedberg 89860e77321SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 89960e77321SJohan Hedberg 90060e77321SJohan Hedberg if (!rp->status) 90160e77321SJohan Hedberg memcpy(hdev->le_features, rp->features, 8); 90260e77321SJohan Hedberg } 90360e77321SJohan Hedberg 9048fa19098SJohan Hedberg static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, 9058fa19098SJohan Hedberg struct sk_buff *skb) 9068fa19098SJohan Hedberg { 9078fa19098SJohan Hedberg struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data; 9088fa19098SJohan Hedberg 9098fa19098SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 9108fa19098SJohan Hedberg 91104b4edcbSJohan Hedberg if (!rp->status) 9128fa19098SJohan Hedberg hdev->adv_tx_power = rp->tx_power; 9138fa19098SJohan Hedberg } 9148fa19098SJohan Hedberg 915a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) 916a5c29683SJohan Hedberg { 917a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 918a5c29683SJohan Hedberg 9199f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 920a5c29683SJohan Hedberg 92156e5cb86SJohan Hedberg hci_dev_lock(hdev); 92256e5cb86SJohan Hedberg 923a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 92404124681SGustavo F. Padovan mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0, 92504124681SGustavo F. Padovan rp->status); 92656e5cb86SJohan Hedberg 92756e5cb86SJohan Hedberg hci_dev_unlock(hdev); 928a5c29683SJohan Hedberg } 929a5c29683SJohan Hedberg 930a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, 931a5c29683SJohan Hedberg struct sk_buff *skb) 932a5c29683SJohan Hedberg { 933a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 934a5c29683SJohan Hedberg 9359f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 936a5c29683SJohan Hedberg 93756e5cb86SJohan Hedberg hci_dev_lock(hdev); 93856e5cb86SJohan Hedberg 939a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 940744cf19eSJohan Hedberg mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr, 94104124681SGustavo F. Padovan ACL_LINK, 0, rp->status); 94256e5cb86SJohan Hedberg 94356e5cb86SJohan Hedberg hci_dev_unlock(hdev); 944a5c29683SJohan Hedberg } 945a5c29683SJohan Hedberg 9461143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb) 9471143d458SBrian Gix { 9481143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 9491143d458SBrian Gix 9509f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 9511143d458SBrian Gix 9521143d458SBrian Gix hci_dev_lock(hdev); 9531143d458SBrian Gix 954a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 955272d90dfSJohan Hedberg mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 956272d90dfSJohan Hedberg 0, rp->status); 9571143d458SBrian Gix 9581143d458SBrian Gix hci_dev_unlock(hdev); 9591143d458SBrian Gix } 9601143d458SBrian Gix 9611143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, 9621143d458SBrian Gix struct sk_buff *skb) 9631143d458SBrian Gix { 9641143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 9651143d458SBrian Gix 9669f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 9671143d458SBrian Gix 9681143d458SBrian Gix hci_dev_lock(hdev); 9691143d458SBrian Gix 970a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 9711143d458SBrian Gix mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr, 97204124681SGustavo F. Padovan ACL_LINK, 0, rp->status); 9731143d458SBrian Gix 9741143d458SBrian Gix hci_dev_unlock(hdev); 9751143d458SBrian Gix } 9761143d458SBrian Gix 9774d2d2796SMarcel Holtmann static void hci_cc_read_local_oob_data(struct hci_dev *hdev, 978c35938b2SSzymon Janc struct sk_buff *skb) 979c35938b2SSzymon Janc { 980c35938b2SSzymon Janc struct hci_rp_read_local_oob_data *rp = (void *) skb->data; 981c35938b2SSzymon Janc 9829f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 983c35938b2SSzymon Janc 98456e5cb86SJohan Hedberg hci_dev_lock(hdev); 9854d2d2796SMarcel Holtmann mgmt_read_local_oob_data_complete(hdev, rp->hash, rp->randomizer, 9864d2d2796SMarcel Holtmann NULL, NULL, rp->status); 9874d2d2796SMarcel Holtmann hci_dev_unlock(hdev); 9884d2d2796SMarcel Holtmann } 9894d2d2796SMarcel Holtmann 9904d2d2796SMarcel Holtmann static void hci_cc_read_local_oob_ext_data(struct hci_dev *hdev, 9914d2d2796SMarcel Holtmann struct sk_buff *skb) 9924d2d2796SMarcel Holtmann { 9934d2d2796SMarcel Holtmann struct hci_rp_read_local_oob_ext_data *rp = (void *) skb->data; 9944d2d2796SMarcel Holtmann 9954d2d2796SMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 9964d2d2796SMarcel Holtmann 9974d2d2796SMarcel Holtmann hci_dev_lock(hdev); 9984d2d2796SMarcel Holtmann mgmt_read_local_oob_data_complete(hdev, rp->hash192, rp->randomizer192, 9994d2d2796SMarcel Holtmann rp->hash256, rp->randomizer256, 10004d2d2796SMarcel Holtmann rp->status); 100156e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1002c35938b2SSzymon Janc } 1003c35938b2SSzymon Janc 10047a4cd51dSMarcel Holtmann 10057a4cd51dSMarcel Holtmann static void hci_cc_le_set_random_addr(struct hci_dev *hdev, struct sk_buff *skb) 10067a4cd51dSMarcel Holtmann { 10077a4cd51dSMarcel Holtmann __u8 status = *((__u8 *) skb->data); 10087a4cd51dSMarcel Holtmann bdaddr_t *sent; 10097a4cd51dSMarcel Holtmann 10107a4cd51dSMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, status); 10117a4cd51dSMarcel Holtmann 10127a4cd51dSMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_RANDOM_ADDR); 10137a4cd51dSMarcel Holtmann if (!sent) 10147a4cd51dSMarcel Holtmann return; 10157a4cd51dSMarcel Holtmann 10167a4cd51dSMarcel Holtmann hci_dev_lock(hdev); 10177a4cd51dSMarcel Holtmann 10187a4cd51dSMarcel Holtmann if (!status) 10197a4cd51dSMarcel Holtmann bacpy(&hdev->random_addr, sent); 10207a4cd51dSMarcel Holtmann 10217a4cd51dSMarcel Holtmann hci_dev_unlock(hdev); 10227a4cd51dSMarcel Holtmann } 10237a4cd51dSMarcel Holtmann 1024c1d5dc4aSJohan Hedberg static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb) 1025c1d5dc4aSJohan Hedberg { 1026c1d5dc4aSJohan Hedberg __u8 *sent, status = *((__u8 *) skb->data); 1027c1d5dc4aSJohan Hedberg 1028c1d5dc4aSJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 1029c1d5dc4aSJohan Hedberg 1030c1d5dc4aSJohan Hedberg sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE); 1031c1d5dc4aSJohan Hedberg if (!sent) 1032c1d5dc4aSJohan Hedberg return; 1033c1d5dc4aSJohan Hedberg 10343c857757SJohan Hedberg if (status) 10353c857757SJohan Hedberg return; 10363c857757SJohan Hedberg 1037c1d5dc4aSJohan Hedberg hci_dev_lock(hdev); 1038c1d5dc4aSJohan Hedberg 10393c857757SJohan Hedberg /* If we're doing connection initation as peripheral. Set a 10403c857757SJohan Hedberg * timeout in case something goes wrong. 10413c857757SJohan Hedberg */ 10423c857757SJohan Hedberg if (*sent) { 10433c857757SJohan Hedberg struct hci_conn *conn; 10443c857757SJohan Hedberg 10453c857757SJohan Hedberg conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); 10463c857757SJohan Hedberg if (conn) 10473c857757SJohan Hedberg queue_delayed_work(hdev->workqueue, 10483c857757SJohan Hedberg &conn->le_conn_timeout, 10493c857757SJohan Hedberg HCI_LE_CONN_TIMEOUT); 10503c857757SJohan Hedberg } 10513c857757SJohan Hedberg 1052778b235aSJohan Hedberg mgmt_advertising(hdev, *sent); 1053c1d5dc4aSJohan Hedberg 105404b4edcbSJohan Hedberg hci_dev_unlock(hdev); 1055c1d5dc4aSJohan Hedberg } 1056c1d5dc4aSJohan Hedberg 1057533553f8SMarcel Holtmann static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) 1058533553f8SMarcel Holtmann { 1059533553f8SMarcel Holtmann struct hci_cp_le_set_scan_param *cp; 1060533553f8SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 1061533553f8SMarcel Holtmann 1062533553f8SMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, status); 1063533553f8SMarcel Holtmann 1064533553f8SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_PARAM); 1065533553f8SMarcel Holtmann if (!cp) 1066533553f8SMarcel Holtmann return; 1067533553f8SMarcel Holtmann 1068533553f8SMarcel Holtmann hci_dev_lock(hdev); 1069533553f8SMarcel Holtmann 1070533553f8SMarcel Holtmann if (!status) 1071533553f8SMarcel Holtmann hdev->le_scan_type = cp->type; 1072533553f8SMarcel Holtmann 1073533553f8SMarcel Holtmann hci_dev_unlock(hdev); 1074533553f8SMarcel Holtmann } 1075533553f8SMarcel Holtmann 1076b9a6328fSJohan Hedberg static bool has_pending_adv_report(struct hci_dev *hdev) 1077b9a6328fSJohan Hedberg { 1078b9a6328fSJohan Hedberg struct discovery_state *d = &hdev->discovery; 1079b9a6328fSJohan Hedberg 1080b9a6328fSJohan Hedberg return bacmp(&d->last_adv_addr, BDADDR_ANY); 1081b9a6328fSJohan Hedberg } 1082b9a6328fSJohan Hedberg 1083b9a6328fSJohan Hedberg static void clear_pending_adv_report(struct hci_dev *hdev) 1084b9a6328fSJohan Hedberg { 1085b9a6328fSJohan Hedberg struct discovery_state *d = &hdev->discovery; 1086b9a6328fSJohan Hedberg 1087b9a6328fSJohan Hedberg bacpy(&d->last_adv_addr, BDADDR_ANY); 1088b9a6328fSJohan Hedberg d->last_adv_data_len = 0; 1089b9a6328fSJohan Hedberg } 1090b9a6328fSJohan Hedberg 1091b9a6328fSJohan Hedberg static void store_pending_adv_report(struct hci_dev *hdev, bdaddr_t *bdaddr, 1092c70a7e4cSMarcel Holtmann u8 bdaddr_type, s8 rssi, u32 flags, 1093c70a7e4cSMarcel Holtmann u8 *data, u8 len) 1094b9a6328fSJohan Hedberg { 1095b9a6328fSJohan Hedberg struct discovery_state *d = &hdev->discovery; 1096b9a6328fSJohan Hedberg 1097b9a6328fSJohan Hedberg bacpy(&d->last_adv_addr, bdaddr); 1098b9a6328fSJohan Hedberg d->last_adv_addr_type = bdaddr_type; 1099ff5cd29fSJohan Hedberg d->last_adv_rssi = rssi; 1100c70a7e4cSMarcel Holtmann d->last_adv_flags = flags; 1101b9a6328fSJohan Hedberg memcpy(d->last_adv_data, data, len); 1102b9a6328fSJohan Hedberg d->last_adv_data_len = len; 1103b9a6328fSJohan Hedberg } 1104b9a6328fSJohan Hedberg 1105eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, 1106eb9d91f5SAndre Guedes struct sk_buff *skb) 1107eb9d91f5SAndre Guedes { 1108eb9d91f5SAndre Guedes struct hci_cp_le_set_scan_enable *cp; 1109eb9d91f5SAndre Guedes __u8 status = *((__u8 *) skb->data); 1110eb9d91f5SAndre Guedes 11119f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1112eb9d91f5SAndre Guedes 1113eb9d91f5SAndre Guedes cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE); 1114eb9d91f5SAndre Guedes if (!cp) 1115eb9d91f5SAndre Guedes return; 1116eb9d91f5SAndre Guedes 1117fef5234aSAndre Guedes if (status) 11187ba8b4beSAndre Guedes return; 11197ba8b4beSAndre Guedes 11203fd319b8SAndre Guedes switch (cp->enable) { 11213fd319b8SAndre Guedes case LE_SCAN_ENABLE: 1122d23264a8SAndre Guedes set_bit(HCI_LE_SCAN, &hdev->dev_flags); 1123b9a6328fSJohan Hedberg if (hdev->le_scan_type == LE_SCAN_ACTIVE) 1124b9a6328fSJohan Hedberg clear_pending_adv_report(hdev); 112568a8aea4SAndrei Emeltchenko break; 112668a8aea4SAndrei Emeltchenko 112776a388beSAndre Guedes case LE_SCAN_DISABLE: 1128b9a6328fSJohan Hedberg /* We do this here instead of when setting DISCOVERY_STOPPED 1129b9a6328fSJohan Hedberg * since the latter would potentially require waiting for 1130b9a6328fSJohan Hedberg * inquiry to stop too. 1131b9a6328fSJohan Hedberg */ 1132b9a6328fSJohan Hedberg if (has_pending_adv_report(hdev)) { 1133b9a6328fSJohan Hedberg struct discovery_state *d = &hdev->discovery; 1134b9a6328fSJohan Hedberg 1135b9a6328fSJohan Hedberg mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK, 1136ab0aa433SJohan Hedberg d->last_adv_addr_type, NULL, 1137c70a7e4cSMarcel Holtmann d->last_adv_rssi, d->last_adv_flags, 1138ab0aa433SJohan Hedberg d->last_adv_data, 1139b9a6328fSJohan Hedberg d->last_adv_data_len, NULL, 0); 1140b9a6328fSJohan Hedberg } 1141b9a6328fSJohan Hedberg 1142317ac8cbSJohan Hedberg /* Cancel this timer so that we don't try to disable scanning 1143317ac8cbSJohan Hedberg * when it's already disabled. 1144317ac8cbSJohan Hedberg */ 1145317ac8cbSJohan Hedberg cancel_delayed_work(&hdev->le_scan_disable); 1146317ac8cbSJohan Hedberg 1147d23264a8SAndre Guedes clear_bit(HCI_LE_SCAN, &hdev->dev_flags); 114881ad6fd9SJohan Hedberg /* The HCI_LE_SCAN_INTERRUPTED flag indicates that we 114981ad6fd9SJohan Hedberg * interrupted scanning due to a connect request. Mark 115081ad6fd9SJohan Hedberg * therefore discovery as stopped. 115181ad6fd9SJohan Hedberg */ 115281ad6fd9SJohan Hedberg if (test_and_clear_bit(HCI_LE_SCAN_INTERRUPTED, 115381ad6fd9SJohan Hedberg &hdev->dev_flags)) 115481ad6fd9SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 115568a8aea4SAndrei Emeltchenko break; 115668a8aea4SAndrei Emeltchenko 115768a8aea4SAndrei Emeltchenko default: 115868a8aea4SAndrei Emeltchenko BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable); 115968a8aea4SAndrei Emeltchenko break; 116035815085SAndre Guedes } 1161eb9d91f5SAndre Guedes } 1162eb9d91f5SAndre Guedes 1163cf1d081fSJohan Hedberg static void hci_cc_le_read_white_list_size(struct hci_dev *hdev, 1164cf1d081fSJohan Hedberg struct sk_buff *skb) 1165cf1d081fSJohan Hedberg { 1166cf1d081fSJohan Hedberg struct hci_rp_le_read_white_list_size *rp = (void *) skb->data; 1167cf1d081fSJohan Hedberg 1168cf1d081fSJohan Hedberg BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size); 1169cf1d081fSJohan Hedberg 1170cf1d081fSJohan Hedberg if (!rp->status) 1171cf1d081fSJohan Hedberg hdev->le_white_list_size = rp->size; 1172cf1d081fSJohan Hedberg } 1173cf1d081fSJohan Hedberg 11740f36b589SMarcel Holtmann static void hci_cc_le_clear_white_list(struct hci_dev *hdev, 11750f36b589SMarcel Holtmann struct sk_buff *skb) 11760f36b589SMarcel Holtmann { 11770f36b589SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 11780f36b589SMarcel Holtmann 11790f36b589SMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, status); 11800f36b589SMarcel Holtmann 11810f36b589SMarcel Holtmann if (!status) 11820f36b589SMarcel Holtmann hci_white_list_clear(hdev); 11830f36b589SMarcel Holtmann } 11840f36b589SMarcel Holtmann 11850f36b589SMarcel Holtmann static void hci_cc_le_add_to_white_list(struct hci_dev *hdev, 11860f36b589SMarcel Holtmann struct sk_buff *skb) 11870f36b589SMarcel Holtmann { 11880f36b589SMarcel Holtmann struct hci_cp_le_add_to_white_list *sent; 11890f36b589SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 11900f36b589SMarcel Holtmann 11910f36b589SMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, status); 11920f36b589SMarcel Holtmann 11930f36b589SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_WHITE_LIST); 11940f36b589SMarcel Holtmann if (!sent) 11950f36b589SMarcel Holtmann return; 11960f36b589SMarcel Holtmann 11970f36b589SMarcel Holtmann if (!status) 11980f36b589SMarcel Holtmann hci_white_list_add(hdev, &sent->bdaddr, sent->bdaddr_type); 11990f36b589SMarcel Holtmann } 12000f36b589SMarcel Holtmann 12010f36b589SMarcel Holtmann static void hci_cc_le_del_from_white_list(struct hci_dev *hdev, 12020f36b589SMarcel Holtmann struct sk_buff *skb) 12030f36b589SMarcel Holtmann { 12040f36b589SMarcel Holtmann struct hci_cp_le_del_from_white_list *sent; 12050f36b589SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 12060f36b589SMarcel Holtmann 12070f36b589SMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, status); 12080f36b589SMarcel Holtmann 12090f36b589SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_LE_DEL_FROM_WHITE_LIST); 12100f36b589SMarcel Holtmann if (!sent) 12110f36b589SMarcel Holtmann return; 12120f36b589SMarcel Holtmann 12130f36b589SMarcel Holtmann if (!status) 12140f36b589SMarcel Holtmann hci_white_list_del(hdev, &sent->bdaddr, sent->bdaddr_type); 12150f36b589SMarcel Holtmann } 12160f36b589SMarcel Holtmann 12179b008c04SJohan Hedberg static void hci_cc_le_read_supported_states(struct hci_dev *hdev, 12189b008c04SJohan Hedberg struct sk_buff *skb) 12199b008c04SJohan Hedberg { 12209b008c04SJohan Hedberg struct hci_rp_le_read_supported_states *rp = (void *) skb->data; 12219b008c04SJohan Hedberg 12229b008c04SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 12239b008c04SJohan Hedberg 12249b008c04SJohan Hedberg if (!rp->status) 12259b008c04SJohan Hedberg memcpy(hdev->le_states, rp->le_states, 8); 12269b008c04SJohan Hedberg } 12279b008c04SJohan Hedberg 12286039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev, 1229f9b49306SAndre Guedes struct sk_buff *skb) 1230f9b49306SAndre Guedes { 123106199cf8SJohan Hedberg struct hci_cp_write_le_host_supported *sent; 1232f9b49306SAndre Guedes __u8 status = *((__u8 *) skb->data); 1233f9b49306SAndre Guedes 12349f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1235f9b49306SAndre Guedes 123606199cf8SJohan Hedberg sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED); 12378f984dfaSJohan Hedberg if (!sent) 1238f9b49306SAndre Guedes return; 1239f9b49306SAndre Guedes 12408f984dfaSJohan Hedberg if (!status) { 1241416a4ae5SJohan Hedberg if (sent->le) { 1242cad718edSJohan Hedberg hdev->features[1][0] |= LMP_HOST_LE; 1243416a4ae5SJohan Hedberg set_bit(HCI_LE_ENABLED, &hdev->dev_flags); 1244416a4ae5SJohan Hedberg } else { 1245cad718edSJohan Hedberg hdev->features[1][0] &= ~LMP_HOST_LE; 1246416a4ae5SJohan Hedberg clear_bit(HCI_LE_ENABLED, &hdev->dev_flags); 1247f3d3444aSJohan Hedberg clear_bit(HCI_ADVERTISING, &hdev->dev_flags); 1248416a4ae5SJohan Hedberg } 124953b2caabSJohan Hedberg 125053b2caabSJohan Hedberg if (sent->simul) 1251cad718edSJohan Hedberg hdev->features[1][0] |= LMP_HOST_LE_BREDR; 125253b2caabSJohan Hedberg else 1253cad718edSJohan Hedberg hdev->features[1][0] &= ~LMP_HOST_LE_BREDR; 12548f984dfaSJohan Hedberg } 1255f9b49306SAndre Guedes } 1256f9b49306SAndre Guedes 125756ed2cb8SJohan Hedberg static void hci_cc_set_adv_param(struct hci_dev *hdev, struct sk_buff *skb) 125856ed2cb8SJohan Hedberg { 125956ed2cb8SJohan Hedberg struct hci_cp_le_set_adv_param *cp; 126056ed2cb8SJohan Hedberg u8 status = *((u8 *) skb->data); 126156ed2cb8SJohan Hedberg 126256ed2cb8SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 126356ed2cb8SJohan Hedberg 126456ed2cb8SJohan Hedberg if (status) 126556ed2cb8SJohan Hedberg return; 126656ed2cb8SJohan Hedberg 126756ed2cb8SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_PARAM); 126856ed2cb8SJohan Hedberg if (!cp) 126956ed2cb8SJohan Hedberg return; 127056ed2cb8SJohan Hedberg 127156ed2cb8SJohan Hedberg hci_dev_lock(hdev); 127256ed2cb8SJohan Hedberg hdev->adv_addr_type = cp->own_address_type; 127356ed2cb8SJohan Hedberg hci_dev_unlock(hdev); 127456ed2cb8SJohan Hedberg } 127556ed2cb8SJohan Hedberg 127693c284eeSAndrei Emeltchenko static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev, 127793c284eeSAndrei Emeltchenko struct sk_buff *skb) 127893c284eeSAndrei Emeltchenko { 127993c284eeSAndrei Emeltchenko struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data; 128093c284eeSAndrei Emeltchenko 128193c284eeSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x", 128293c284eeSAndrei Emeltchenko hdev->name, rp->status, rp->phy_handle); 128393c284eeSAndrei Emeltchenko 128493c284eeSAndrei Emeltchenko if (rp->status) 128593c284eeSAndrei Emeltchenko return; 128693c284eeSAndrei Emeltchenko 128793c284eeSAndrei Emeltchenko amp_write_rem_assoc_continue(hdev, rp->phy_handle); 128893c284eeSAndrei Emeltchenko } 128993c284eeSAndrei Emeltchenko 12905ae76a94SAndrzej Kaczmarek static void hci_cc_read_rssi(struct hci_dev *hdev, struct sk_buff *skb) 12915ae76a94SAndrzej Kaczmarek { 12925ae76a94SAndrzej Kaczmarek struct hci_rp_read_rssi *rp = (void *) skb->data; 12935ae76a94SAndrzej Kaczmarek struct hci_conn *conn; 12945ae76a94SAndrzej Kaczmarek 12955ae76a94SAndrzej Kaczmarek BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 12965ae76a94SAndrzej Kaczmarek 12975ae76a94SAndrzej Kaczmarek if (rp->status) 12985ae76a94SAndrzej Kaczmarek return; 12995ae76a94SAndrzej Kaczmarek 13005ae76a94SAndrzej Kaczmarek hci_dev_lock(hdev); 13015ae76a94SAndrzej Kaczmarek 13025ae76a94SAndrzej Kaczmarek conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 13035ae76a94SAndrzej Kaczmarek if (conn) 13045ae76a94SAndrzej Kaczmarek conn->rssi = rp->rssi; 13055ae76a94SAndrzej Kaczmarek 13065ae76a94SAndrzej Kaczmarek hci_dev_unlock(hdev); 13075ae76a94SAndrzej Kaczmarek } 13085ae76a94SAndrzej Kaczmarek 13095a134faeSAndrzej Kaczmarek static void hci_cc_read_tx_power(struct hci_dev *hdev, struct sk_buff *skb) 13105a134faeSAndrzej Kaczmarek { 13115a134faeSAndrzej Kaczmarek struct hci_cp_read_tx_power *sent; 13125a134faeSAndrzej Kaczmarek struct hci_rp_read_tx_power *rp = (void *) skb->data; 13135a134faeSAndrzej Kaczmarek struct hci_conn *conn; 13145a134faeSAndrzej Kaczmarek 13155a134faeSAndrzej Kaczmarek BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 13165a134faeSAndrzej Kaczmarek 13175a134faeSAndrzej Kaczmarek if (rp->status) 13185a134faeSAndrzej Kaczmarek return; 13195a134faeSAndrzej Kaczmarek 13205a134faeSAndrzej Kaczmarek sent = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER); 13215a134faeSAndrzej Kaczmarek if (!sent) 13225a134faeSAndrzej Kaczmarek return; 13235a134faeSAndrzej Kaczmarek 13245a134faeSAndrzej Kaczmarek hci_dev_lock(hdev); 13255a134faeSAndrzej Kaczmarek 13265a134faeSAndrzej Kaczmarek conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 1327d0455ed9SAndrzej Kaczmarek if (!conn) 1328d0455ed9SAndrzej Kaczmarek goto unlock; 13295a134faeSAndrzej Kaczmarek 1330d0455ed9SAndrzej Kaczmarek switch (sent->type) { 1331d0455ed9SAndrzej Kaczmarek case 0x00: 1332d0455ed9SAndrzej Kaczmarek conn->tx_power = rp->tx_power; 1333d0455ed9SAndrzej Kaczmarek break; 1334d0455ed9SAndrzej Kaczmarek case 0x01: 1335d0455ed9SAndrzej Kaczmarek conn->max_tx_power = rp->tx_power; 1336d0455ed9SAndrzej Kaczmarek break; 1337d0455ed9SAndrzej Kaczmarek } 1338d0455ed9SAndrzej Kaczmarek 1339d0455ed9SAndrzej Kaczmarek unlock: 13405a134faeSAndrzej Kaczmarek hci_dev_unlock(hdev); 13415a134faeSAndrzej Kaczmarek } 13425a134faeSAndrzej Kaczmarek 13436039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 1344a9de9248SMarcel Holtmann { 13459f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1346a9de9248SMarcel Holtmann 1347a9de9248SMarcel Holtmann if (status) { 1348a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 1349314b2381SJohan Hedberg return; 1350314b2381SJohan Hedberg } 1351314b2381SJohan Hedberg 135289352e7dSAndre Guedes set_bit(HCI_INQUIRY, &hdev->flags); 1353a9de9248SMarcel Holtmann } 1354a9de9248SMarcel Holtmann 13556039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 13561da177e4SLinus Torvalds { 1357a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 13581da177e4SLinus Torvalds struct hci_conn *conn; 13591da177e4SLinus Torvalds 13609f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1361a9de9248SMarcel Holtmann 1362a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 13631da177e4SLinus Torvalds if (!cp) 13641da177e4SLinus Torvalds return; 13651da177e4SLinus Torvalds 13661da177e4SLinus Torvalds hci_dev_lock(hdev); 13671da177e4SLinus Torvalds 13681da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 13691da177e4SLinus Torvalds 13706ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn); 13711da177e4SLinus Torvalds 13721da177e4SLinus Torvalds if (status) { 13731da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 13744c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 13751da177e4SLinus Torvalds conn->state = BT_CLOSED; 13761da177e4SLinus Torvalds hci_proto_connect_cfm(conn, status); 13771da177e4SLinus Torvalds hci_conn_del(conn); 13784c67bc74SMarcel Holtmann } else 13794c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 13801da177e4SLinus Torvalds } 13811da177e4SLinus Torvalds } else { 13821da177e4SLinus Torvalds if (!conn) { 13831da177e4SLinus Torvalds conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); 13841da177e4SLinus Torvalds if (conn) { 1385a0c808b3SJohan Hedberg conn->out = true; 13864dae2798SJohan Hedberg set_bit(HCI_CONN_MASTER, &conn->flags); 13871da177e4SLinus Torvalds } else 1388893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 13891da177e4SLinus Torvalds } 13901da177e4SLinus Torvalds } 13911da177e4SLinus Torvalds 13921da177e4SLinus Torvalds hci_dev_unlock(hdev); 13931da177e4SLinus Torvalds } 13941da177e4SLinus Torvalds 1395a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 13961da177e4SLinus Torvalds { 1397a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 13981da177e4SLinus Torvalds struct hci_conn *acl, *sco; 13991da177e4SLinus Torvalds __u16 handle; 14001da177e4SLinus Torvalds 14019f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1402b6a0dc82SMarcel Holtmann 1403a9de9248SMarcel Holtmann if (!status) 1404a9de9248SMarcel Holtmann return; 1405a9de9248SMarcel Holtmann 1406a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 14071da177e4SLinus Torvalds if (!cp) 1408a9de9248SMarcel Holtmann return; 14091da177e4SLinus Torvalds 14101da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 14111da177e4SLinus Torvalds 14129f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, handle); 14131da177e4SLinus Torvalds 14141da177e4SLinus Torvalds hci_dev_lock(hdev); 14151da177e4SLinus Torvalds 14161da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 14175a08ecceSAndrei Emeltchenko if (acl) { 14185a08ecceSAndrei Emeltchenko sco = acl->link; 14195a08ecceSAndrei Emeltchenko if (sco) { 14201da177e4SLinus Torvalds sco->state = BT_CLOSED; 14211da177e4SLinus Torvalds 14221da177e4SLinus Torvalds hci_proto_connect_cfm(sco, status); 14231da177e4SLinus Torvalds hci_conn_del(sco); 14241da177e4SLinus Torvalds } 14255a08ecceSAndrei Emeltchenko } 14261da177e4SLinus Torvalds 14271da177e4SLinus Torvalds hci_dev_unlock(hdev); 14281da177e4SLinus Torvalds } 14291da177e4SLinus Torvalds 1430f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 1431f8558555SMarcel Holtmann { 1432f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 1433f8558555SMarcel Holtmann struct hci_conn *conn; 1434f8558555SMarcel Holtmann 14359f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1436f8558555SMarcel Holtmann 1437f8558555SMarcel Holtmann if (!status) 1438f8558555SMarcel Holtmann return; 1439f8558555SMarcel Holtmann 1440f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 1441f8558555SMarcel Holtmann if (!cp) 1442f8558555SMarcel Holtmann return; 1443f8558555SMarcel Holtmann 1444f8558555SMarcel Holtmann hci_dev_lock(hdev); 1445f8558555SMarcel Holtmann 1446f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1447f8558555SMarcel Holtmann if (conn) { 1448f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1449f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 145076a68ba0SDavid Herrmann hci_conn_drop(conn); 1451f8558555SMarcel Holtmann } 1452f8558555SMarcel Holtmann } 1453f8558555SMarcel Holtmann 1454f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1455f8558555SMarcel Holtmann } 1456f8558555SMarcel Holtmann 1457f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 1458f8558555SMarcel Holtmann { 1459f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 1460f8558555SMarcel Holtmann struct hci_conn *conn; 1461f8558555SMarcel Holtmann 14629f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1463f8558555SMarcel Holtmann 1464f8558555SMarcel Holtmann if (!status) 1465f8558555SMarcel Holtmann return; 1466f8558555SMarcel Holtmann 1467f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 1468f8558555SMarcel Holtmann if (!cp) 1469f8558555SMarcel Holtmann return; 1470f8558555SMarcel Holtmann 1471f8558555SMarcel Holtmann hci_dev_lock(hdev); 1472f8558555SMarcel Holtmann 1473f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1474f8558555SMarcel Holtmann if (conn) { 1475f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1476f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 147776a68ba0SDavid Herrmann hci_conn_drop(conn); 1478f8558555SMarcel Holtmann } 1479f8558555SMarcel Holtmann } 1480f8558555SMarcel Holtmann 1481f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1482f8558555SMarcel Holtmann } 1483f8558555SMarcel Holtmann 1484127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev, 1485392599b9SJohan Hedberg struct hci_conn *conn) 1486392599b9SJohan Hedberg { 1487392599b9SJohan Hedberg if (conn->state != BT_CONFIG || !conn->out) 1488392599b9SJohan Hedberg return 0; 1489392599b9SJohan Hedberg 1490765c2a96SJohan Hedberg if (conn->pending_sec_level == BT_SECURITY_SDP) 1491392599b9SJohan Hedberg return 0; 1492392599b9SJohan Hedberg 1493392599b9SJohan Hedberg /* Only request authentication for SSP connections or non-SSP 1494264b8b4eSJohan Hedberg * devices with sec_level MEDIUM or HIGH or if MITM protection 1495264b8b4eSJohan Hedberg * is requested. 1496264b8b4eSJohan Hedberg */ 1497807deac2SGustavo Padovan if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) && 14987e3691e1SJohan Hedberg conn->pending_sec_level != BT_SECURITY_FIPS && 1499264b8b4eSJohan Hedberg conn->pending_sec_level != BT_SECURITY_HIGH && 1500264b8b4eSJohan Hedberg conn->pending_sec_level != BT_SECURITY_MEDIUM) 1501392599b9SJohan Hedberg return 0; 1502392599b9SJohan Hedberg 1503392599b9SJohan Hedberg return 1; 1504392599b9SJohan Hedberg } 1505392599b9SJohan Hedberg 15066039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev, 150700abfe44SGustavo F. Padovan struct inquiry_entry *e) 150830dc78e1SJohan Hedberg { 150930dc78e1SJohan Hedberg struct hci_cp_remote_name_req cp; 151030dc78e1SJohan Hedberg 151130dc78e1SJohan Hedberg memset(&cp, 0, sizeof(cp)); 151230dc78e1SJohan Hedberg 151330dc78e1SJohan Hedberg bacpy(&cp.bdaddr, &e->data.bdaddr); 151430dc78e1SJohan Hedberg cp.pscan_rep_mode = e->data.pscan_rep_mode; 151530dc78e1SJohan Hedberg cp.pscan_mode = e->data.pscan_mode; 151630dc78e1SJohan Hedberg cp.clock_offset = e->data.clock_offset; 151730dc78e1SJohan Hedberg 151830dc78e1SJohan Hedberg return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 151930dc78e1SJohan Hedberg } 152030dc78e1SJohan Hedberg 1521b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev) 152230dc78e1SJohan Hedberg { 152330dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 152430dc78e1SJohan Hedberg struct inquiry_entry *e; 152530dc78e1SJohan Hedberg 1526b644ba33SJohan Hedberg if (list_empty(&discov->resolve)) 1527b644ba33SJohan Hedberg return false; 1528b644ba33SJohan Hedberg 1529b644ba33SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 1530c810089cSRam Malovany if (!e) 1531c810089cSRam Malovany return false; 1532c810089cSRam Malovany 1533b644ba33SJohan Hedberg if (hci_resolve_name(hdev, e) == 0) { 1534b644ba33SJohan Hedberg e->name_state = NAME_PENDING; 1535b644ba33SJohan Hedberg return true; 1536b644ba33SJohan Hedberg } 1537b644ba33SJohan Hedberg 1538b644ba33SJohan Hedberg return false; 1539b644ba33SJohan Hedberg } 1540b644ba33SJohan Hedberg 1541b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn, 1542b644ba33SJohan Hedberg bdaddr_t *bdaddr, u8 *name, u8 name_len) 1543b644ba33SJohan Hedberg { 1544b644ba33SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 1545b644ba33SJohan Hedberg struct inquiry_entry *e; 1546b644ba33SJohan Hedberg 1547b644ba33SJohan Hedberg if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 154804124681SGustavo F. Padovan mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name, 154904124681SGustavo F. Padovan name_len, conn->dev_class); 1550b644ba33SJohan Hedberg 1551b644ba33SJohan Hedberg if (discov->state == DISCOVERY_STOPPED) 1552b644ba33SJohan Hedberg return; 1553b644ba33SJohan Hedberg 155430dc78e1SJohan Hedberg if (discov->state == DISCOVERY_STOPPING) 155530dc78e1SJohan Hedberg goto discov_complete; 155630dc78e1SJohan Hedberg 155730dc78e1SJohan Hedberg if (discov->state != DISCOVERY_RESOLVING) 155830dc78e1SJohan Hedberg return; 155930dc78e1SJohan Hedberg 156030dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING); 15617cc8380eSRam Malovany /* If the device was not found in a list of found devices names of which 15627cc8380eSRam Malovany * are pending. there is no need to continue resolving a next name as it 15637cc8380eSRam Malovany * will be done upon receiving another Remote Name Request Complete 15647cc8380eSRam Malovany * Event */ 15657cc8380eSRam Malovany if (!e) 15667cc8380eSRam Malovany return; 15677cc8380eSRam Malovany 156830dc78e1SJohan Hedberg list_del(&e->list); 15697cc8380eSRam Malovany if (name) { 15707cc8380eSRam Malovany e->name_state = NAME_KNOWN; 1571b644ba33SJohan Hedberg mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, 1572b644ba33SJohan Hedberg e->data.rssi, name, name_len); 1573c3e7c0d9SRam Malovany } else { 1574c3e7c0d9SRam Malovany e->name_state = NAME_NOT_KNOWN; 157530dc78e1SJohan Hedberg } 157630dc78e1SJohan Hedberg 1577b644ba33SJohan Hedberg if (hci_resolve_next_name(hdev)) 157830dc78e1SJohan Hedberg return; 157930dc78e1SJohan Hedberg 158030dc78e1SJohan Hedberg discov_complete: 158130dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 158230dc78e1SJohan Hedberg } 158330dc78e1SJohan Hedberg 1584a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 15851da177e4SLinus Torvalds { 1586127178d2SJohan Hedberg struct hci_cp_remote_name_req *cp; 1587127178d2SJohan Hedberg struct hci_conn *conn; 1588127178d2SJohan Hedberg 15899f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1590127178d2SJohan Hedberg 1591127178d2SJohan Hedberg /* If successful wait for the name req complete event before 1592127178d2SJohan Hedberg * checking for the need to do authentication */ 1593127178d2SJohan Hedberg if (!status) 1594127178d2SJohan Hedberg return; 1595127178d2SJohan Hedberg 1596127178d2SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); 1597127178d2SJohan Hedberg if (!cp) 1598127178d2SJohan Hedberg return; 1599127178d2SJohan Hedberg 1600127178d2SJohan Hedberg hci_dev_lock(hdev); 1601127178d2SJohan Hedberg 1602127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 1603b644ba33SJohan Hedberg 1604b644ba33SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1605b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0); 1606b644ba33SJohan Hedberg 160779c6c70cSJohan Hedberg if (!conn) 160879c6c70cSJohan Hedberg goto unlock; 160979c6c70cSJohan Hedberg 161079c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 161179c6c70cSJohan Hedberg goto unlock; 161279c6c70cSJohan Hedberg 161351a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 1614c1f23a2bSJohannes Berg struct hci_cp_auth_requested auth_cp; 1615c1f23a2bSJohannes Berg 1616c1f23a2bSJohannes Berg auth_cp.handle = __cpu_to_le16(conn->handle); 1617c1f23a2bSJohannes Berg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, 1618c1f23a2bSJohannes Berg sizeof(auth_cp), &auth_cp); 1619127178d2SJohan Hedberg } 1620127178d2SJohan Hedberg 162179c6c70cSJohan Hedberg unlock: 1622127178d2SJohan Hedberg hci_dev_unlock(hdev); 1623a9de9248SMarcel Holtmann } 16241da177e4SLinus Torvalds 1625769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 1626769be974SMarcel Holtmann { 1627769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 1628769be974SMarcel Holtmann struct hci_conn *conn; 1629769be974SMarcel Holtmann 16309f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1631769be974SMarcel Holtmann 1632769be974SMarcel Holtmann if (!status) 1633769be974SMarcel Holtmann return; 1634769be974SMarcel Holtmann 1635769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 1636769be974SMarcel Holtmann if (!cp) 1637769be974SMarcel Holtmann return; 1638769be974SMarcel Holtmann 1639769be974SMarcel Holtmann hci_dev_lock(hdev); 1640769be974SMarcel Holtmann 1641769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1642769be974SMarcel Holtmann if (conn) { 1643769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1644769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 164576a68ba0SDavid Herrmann hci_conn_drop(conn); 1646769be974SMarcel Holtmann } 1647769be974SMarcel Holtmann } 1648769be974SMarcel Holtmann 1649769be974SMarcel Holtmann hci_dev_unlock(hdev); 1650769be974SMarcel Holtmann } 1651769be974SMarcel Holtmann 1652769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 1653769be974SMarcel Holtmann { 1654769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features *cp; 1655769be974SMarcel Holtmann struct hci_conn *conn; 1656769be974SMarcel Holtmann 16579f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1658769be974SMarcel Holtmann 1659769be974SMarcel Holtmann if (!status) 1660769be974SMarcel Holtmann return; 1661769be974SMarcel Holtmann 1662769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 1663769be974SMarcel Holtmann if (!cp) 1664769be974SMarcel Holtmann return; 1665769be974SMarcel Holtmann 1666769be974SMarcel Holtmann hci_dev_lock(hdev); 1667769be974SMarcel Holtmann 1668769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1669769be974SMarcel Holtmann if (conn) { 1670769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1671769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 167276a68ba0SDavid Herrmann hci_conn_drop(conn); 1673769be974SMarcel Holtmann } 1674769be974SMarcel Holtmann } 1675769be974SMarcel Holtmann 1676769be974SMarcel Holtmann hci_dev_unlock(hdev); 1677769be974SMarcel Holtmann } 1678769be974SMarcel Holtmann 1679a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 1680a9de9248SMarcel Holtmann { 1681b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 1682b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 1683b6a0dc82SMarcel Holtmann __u16 handle; 1684b6a0dc82SMarcel Holtmann 16859f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1686b6a0dc82SMarcel Holtmann 1687b6a0dc82SMarcel Holtmann if (!status) 1688b6a0dc82SMarcel Holtmann return; 1689b6a0dc82SMarcel Holtmann 1690b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 1691b6a0dc82SMarcel Holtmann if (!cp) 1692b6a0dc82SMarcel Holtmann return; 1693b6a0dc82SMarcel Holtmann 1694b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 1695b6a0dc82SMarcel Holtmann 16969f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, handle); 1697b6a0dc82SMarcel Holtmann 1698b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 1699b6a0dc82SMarcel Holtmann 1700b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 17015a08ecceSAndrei Emeltchenko if (acl) { 17025a08ecceSAndrei Emeltchenko sco = acl->link; 17035a08ecceSAndrei Emeltchenko if (sco) { 1704b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 1705b6a0dc82SMarcel Holtmann 1706b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(sco, status); 1707b6a0dc82SMarcel Holtmann hci_conn_del(sco); 1708b6a0dc82SMarcel Holtmann } 17095a08ecceSAndrei Emeltchenko } 1710b6a0dc82SMarcel Holtmann 1711b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 1712a9de9248SMarcel Holtmann } 1713a9de9248SMarcel Holtmann 1714a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 1715a9de9248SMarcel Holtmann { 1716a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 171704837f64SMarcel Holtmann struct hci_conn *conn; 171804837f64SMarcel Holtmann 17199f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1720a9de9248SMarcel Holtmann 1721a9de9248SMarcel Holtmann if (!status) 1722a9de9248SMarcel Holtmann return; 1723a9de9248SMarcel Holtmann 1724a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 172504837f64SMarcel Holtmann if (!cp) 1726a9de9248SMarcel Holtmann return; 172704837f64SMarcel Holtmann 172804837f64SMarcel Holtmann hci_dev_lock(hdev); 172904837f64SMarcel Holtmann 173004837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1731e73439d8SMarcel Holtmann if (conn) { 173251a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 173304837f64SMarcel Holtmann 173451a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1735e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1736e73439d8SMarcel Holtmann } 1737e73439d8SMarcel Holtmann 173804837f64SMarcel Holtmann hci_dev_unlock(hdev); 173904837f64SMarcel Holtmann } 174004837f64SMarcel Holtmann 1741a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 1742a9de9248SMarcel Holtmann { 1743a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 174404837f64SMarcel Holtmann struct hci_conn *conn; 174504837f64SMarcel Holtmann 17469f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1747a9de9248SMarcel Holtmann 1748a9de9248SMarcel Holtmann if (!status) 1749a9de9248SMarcel Holtmann return; 1750a9de9248SMarcel Holtmann 1751a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 175204837f64SMarcel Holtmann if (!cp) 1753a9de9248SMarcel Holtmann return; 175404837f64SMarcel Holtmann 175504837f64SMarcel Holtmann hci_dev_lock(hdev); 175604837f64SMarcel Holtmann 175704837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1758e73439d8SMarcel Holtmann if (conn) { 175951a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 176004837f64SMarcel Holtmann 176151a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1762e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1763e73439d8SMarcel Holtmann } 1764e73439d8SMarcel Holtmann 176504837f64SMarcel Holtmann hci_dev_unlock(hdev); 176604837f64SMarcel Holtmann } 176704837f64SMarcel Holtmann 176888c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) 176988c3df13SJohan Hedberg { 177088c3df13SJohan Hedberg struct hci_cp_disconnect *cp; 177188c3df13SJohan Hedberg struct hci_conn *conn; 177288c3df13SJohan Hedberg 177388c3df13SJohan Hedberg if (!status) 177488c3df13SJohan Hedberg return; 177588c3df13SJohan Hedberg 177688c3df13SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT); 177788c3df13SJohan Hedberg if (!cp) 177888c3df13SJohan Hedberg return; 177988c3df13SJohan Hedberg 178088c3df13SJohan Hedberg hci_dev_lock(hdev); 178188c3df13SJohan Hedberg 178288c3df13SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 178388c3df13SJohan Hedberg if (conn) 178488c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 178588c3df13SJohan Hedberg conn->dst_type, status); 178688c3df13SJohan Hedberg 178788c3df13SJohan Hedberg hci_dev_unlock(hdev); 178888c3df13SJohan Hedberg } 178988c3df13SJohan Hedberg 1790a02226d6SAndrei Emeltchenko static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status) 1791a02226d6SAndrei Emeltchenko { 179293c284eeSAndrei Emeltchenko struct hci_cp_create_phy_link *cp; 179393c284eeSAndrei Emeltchenko 1794a02226d6SAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 179593c284eeSAndrei Emeltchenko 179693c284eeSAndrei Emeltchenko cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK); 179793c284eeSAndrei Emeltchenko if (!cp) 179893c284eeSAndrei Emeltchenko return; 179993c284eeSAndrei Emeltchenko 1800e58917b9SAndrei Emeltchenko hci_dev_lock(hdev); 1801e58917b9SAndrei Emeltchenko 1802e58917b9SAndrei Emeltchenko if (status) { 1803e58917b9SAndrei Emeltchenko struct hci_conn *hcon; 1804e58917b9SAndrei Emeltchenko 1805e58917b9SAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle); 1806e58917b9SAndrei Emeltchenko if (hcon) 1807e58917b9SAndrei Emeltchenko hci_conn_del(hcon); 1808e58917b9SAndrei Emeltchenko } else { 180993c284eeSAndrei Emeltchenko amp_write_remote_assoc(hdev, cp->phy_handle); 1810a02226d6SAndrei Emeltchenko } 1811a02226d6SAndrei Emeltchenko 1812e58917b9SAndrei Emeltchenko hci_dev_unlock(hdev); 1813e58917b9SAndrei Emeltchenko } 1814e58917b9SAndrei Emeltchenko 18150b26ab9dSAndrei Emeltchenko static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status) 18160b26ab9dSAndrei Emeltchenko { 18170b26ab9dSAndrei Emeltchenko struct hci_cp_accept_phy_link *cp; 18180b26ab9dSAndrei Emeltchenko 18190b26ab9dSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 18200b26ab9dSAndrei Emeltchenko 18210b26ab9dSAndrei Emeltchenko if (status) 18220b26ab9dSAndrei Emeltchenko return; 18230b26ab9dSAndrei Emeltchenko 18240b26ab9dSAndrei Emeltchenko cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK); 18250b26ab9dSAndrei Emeltchenko if (!cp) 18260b26ab9dSAndrei Emeltchenko return; 18270b26ab9dSAndrei Emeltchenko 18280b26ab9dSAndrei Emeltchenko amp_write_remote_assoc(hdev, cp->phy_handle); 18290b26ab9dSAndrei Emeltchenko } 18300b26ab9dSAndrei Emeltchenko 1831cb1d68f7SJohan Hedberg static void hci_cs_le_create_conn(struct hci_dev *hdev, u8 status) 1832cb1d68f7SJohan Hedberg { 1833cb1d68f7SJohan Hedberg struct hci_cp_le_create_conn *cp; 1834cb1d68f7SJohan Hedberg struct hci_conn *conn; 1835cb1d68f7SJohan Hedberg 1836cb1d68f7SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 1837cb1d68f7SJohan Hedberg 1838cb1d68f7SJohan Hedberg /* All connection failure handling is taken care of by the 1839cb1d68f7SJohan Hedberg * hci_le_conn_failed function which is triggered by the HCI 1840cb1d68f7SJohan Hedberg * request completion callbacks used for connecting. 1841cb1d68f7SJohan Hedberg */ 1842cb1d68f7SJohan Hedberg if (status) 1843cb1d68f7SJohan Hedberg return; 1844cb1d68f7SJohan Hedberg 1845cb1d68f7SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN); 1846cb1d68f7SJohan Hedberg if (!cp) 1847cb1d68f7SJohan Hedberg return; 1848cb1d68f7SJohan Hedberg 1849cb1d68f7SJohan Hedberg hci_dev_lock(hdev); 1850cb1d68f7SJohan Hedberg 1851cb1d68f7SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr); 1852cb1d68f7SJohan Hedberg if (!conn) 1853cb1d68f7SJohan Hedberg goto unlock; 1854cb1d68f7SJohan Hedberg 1855cb1d68f7SJohan Hedberg /* Store the initiator and responder address information which 1856cb1d68f7SJohan Hedberg * is needed for SMP. These values will not change during the 1857cb1d68f7SJohan Hedberg * lifetime of the connection. 1858cb1d68f7SJohan Hedberg */ 1859cb1d68f7SJohan Hedberg conn->init_addr_type = cp->own_address_type; 1860cb1d68f7SJohan Hedberg if (cp->own_address_type == ADDR_LE_DEV_RANDOM) 1861cb1d68f7SJohan Hedberg bacpy(&conn->init_addr, &hdev->random_addr); 1862cb1d68f7SJohan Hedberg else 1863cb1d68f7SJohan Hedberg bacpy(&conn->init_addr, &hdev->bdaddr); 1864cb1d68f7SJohan Hedberg 1865cb1d68f7SJohan Hedberg conn->resp_addr_type = cp->peer_addr_type; 1866cb1d68f7SJohan Hedberg bacpy(&conn->resp_addr, &cp->peer_addr); 1867cb1d68f7SJohan Hedberg 18689489eca4SJohan Hedberg /* We don't want the connection attempt to stick around 18699489eca4SJohan Hedberg * indefinitely since LE doesn't have a page timeout concept 18709489eca4SJohan Hedberg * like BR/EDR. Set a timer for any connection that doesn't use 18719489eca4SJohan Hedberg * the white list for connecting. 18729489eca4SJohan Hedberg */ 18739489eca4SJohan Hedberg if (cp->filter_policy == HCI_LE_USE_PEER_ADDR) 18749489eca4SJohan Hedberg queue_delayed_work(conn->hdev->workqueue, 18759489eca4SJohan Hedberg &conn->le_conn_timeout, 18769489eca4SJohan Hedberg HCI_LE_CONN_TIMEOUT); 18779489eca4SJohan Hedberg 1878cb1d68f7SJohan Hedberg unlock: 1879cb1d68f7SJohan Hedberg hci_dev_unlock(hdev); 1880cb1d68f7SJohan Hedberg } 1881cb1d68f7SJohan Hedberg 188281d0c8adSJohan Hedberg static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) 188381d0c8adSJohan Hedberg { 188481d0c8adSJohan Hedberg struct hci_cp_le_start_enc *cp; 188581d0c8adSJohan Hedberg struct hci_conn *conn; 188681d0c8adSJohan Hedberg 188781d0c8adSJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 188881d0c8adSJohan Hedberg 188981d0c8adSJohan Hedberg if (!status) 189081d0c8adSJohan Hedberg return; 189181d0c8adSJohan Hedberg 189281d0c8adSJohan Hedberg hci_dev_lock(hdev); 189381d0c8adSJohan Hedberg 189481d0c8adSJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_LE_START_ENC); 189581d0c8adSJohan Hedberg if (!cp) 189681d0c8adSJohan Hedberg goto unlock; 189781d0c8adSJohan Hedberg 189881d0c8adSJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 189981d0c8adSJohan Hedberg if (!conn) 190081d0c8adSJohan Hedberg goto unlock; 190181d0c8adSJohan Hedberg 190281d0c8adSJohan Hedberg if (conn->state != BT_CONNECTED) 190381d0c8adSJohan Hedberg goto unlock; 190481d0c8adSJohan Hedberg 190581d0c8adSJohan Hedberg hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); 190681d0c8adSJohan Hedberg hci_conn_drop(conn); 190781d0c8adSJohan Hedberg 190881d0c8adSJohan Hedberg unlock: 190981d0c8adSJohan Hedberg hci_dev_unlock(hdev); 191081d0c8adSJohan Hedberg } 191181d0c8adSJohan Hedberg 19126039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 19131da177e4SLinus Torvalds { 19141da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 191530dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 191630dc78e1SJohan Hedberg struct inquiry_entry *e; 19171da177e4SLinus Torvalds 19189f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 19191da177e4SLinus Torvalds 1920a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 192189352e7dSAndre Guedes 192289352e7dSAndre Guedes if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) 192389352e7dSAndre Guedes return; 192489352e7dSAndre Guedes 19254e857c58SPeter Zijlstra smp_mb__after_atomic(); /* wake_up_bit advises about this barrier */ 19263e13fa1eSAndre Guedes wake_up_bit(&hdev->flags, HCI_INQUIRY); 19273e13fa1eSAndre Guedes 1928a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 192930dc78e1SJohan Hedberg return; 193030dc78e1SJohan Hedberg 193156e5cb86SJohan Hedberg hci_dev_lock(hdev); 193230dc78e1SJohan Hedberg 1933343f935bSAndre Guedes if (discov->state != DISCOVERY_FINDING) 193430dc78e1SJohan Hedberg goto unlock; 193530dc78e1SJohan Hedberg 193630dc78e1SJohan Hedberg if (list_empty(&discov->resolve)) { 1937ff9ef578SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 193830dc78e1SJohan Hedberg goto unlock; 193930dc78e1SJohan Hedberg } 194030dc78e1SJohan Hedberg 194130dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 194230dc78e1SJohan Hedberg if (e && hci_resolve_name(hdev, e) == 0) { 194330dc78e1SJohan Hedberg e->name_state = NAME_PENDING; 194430dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_RESOLVING); 194530dc78e1SJohan Hedberg } else { 194630dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 194730dc78e1SJohan Hedberg } 194830dc78e1SJohan Hedberg 194930dc78e1SJohan Hedberg unlock: 195056e5cb86SJohan Hedberg hci_dev_unlock(hdev); 19511da177e4SLinus Torvalds } 19521da177e4SLinus Torvalds 19536039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 19541da177e4SLinus Torvalds { 195545bb4bf0SMarcel Holtmann struct inquiry_data data; 1956a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 19571da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 19581da177e4SLinus Torvalds 19591da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 19601da177e4SLinus Torvalds 196145bb4bf0SMarcel Holtmann if (!num_rsp) 196245bb4bf0SMarcel Holtmann return; 196345bb4bf0SMarcel Holtmann 19641519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 19651519cc17SAndre Guedes return; 19661519cc17SAndre Guedes 19671da177e4SLinus Torvalds hci_dev_lock(hdev); 196845bb4bf0SMarcel Holtmann 1969e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 1970af58925cSMarcel Holtmann u32 flags; 19713175405bSJohan Hedberg 19721da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 19731da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 19741da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 19751da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 19761da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 19771da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 19781da177e4SLinus Torvalds data.rssi = 0x00; 197941a96212SMarcel Holtmann data.ssp_mode = 0x00; 19803175405bSJohan Hedberg 1981af58925cSMarcel Holtmann flags = hci_inquiry_cache_update(hdev, &data, false); 1982af58925cSMarcel Holtmann 198348264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 1984af58925cSMarcel Holtmann info->dev_class, 0, flags, NULL, 0, NULL, 0); 19851da177e4SLinus Torvalds } 198645bb4bf0SMarcel Holtmann 19871da177e4SLinus Torvalds hci_dev_unlock(hdev); 19881da177e4SLinus Torvalds } 19891da177e4SLinus Torvalds 19906039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 19911da177e4SLinus Torvalds { 1992a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 1993a9de9248SMarcel Holtmann struct hci_conn *conn; 19941da177e4SLinus Torvalds 1995a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 199645bb4bf0SMarcel Holtmann 19971da177e4SLinus Torvalds hci_dev_lock(hdev); 199845bb4bf0SMarcel Holtmann 1999a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 20009499237aSMarcel Holtmann if (!conn) { 20019499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 20029499237aSMarcel Holtmann goto unlock; 20039499237aSMarcel Holtmann 20049499237aSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 2005a9de9248SMarcel Holtmann if (!conn) 2006a9de9248SMarcel Holtmann goto unlock; 200745bb4bf0SMarcel Holtmann 20089499237aSMarcel Holtmann conn->type = SCO_LINK; 20099499237aSMarcel Holtmann } 20109499237aSMarcel Holtmann 2011a9de9248SMarcel Holtmann if (!ev->status) { 2012a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 2013769be974SMarcel Holtmann 2014769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 2015769be974SMarcel Holtmann conn->state = BT_CONFIG; 2016769be974SMarcel Holtmann hci_conn_hold(conn); 2017a9ea3ed9SSzymon Janc 2018a9ea3ed9SSzymon Janc if (!conn->out && !hci_conn_ssp_enabled(conn) && 2019a9ea3ed9SSzymon Janc !hci_find_link_key(hdev, &ev->bdaddr)) 2020a9ea3ed9SSzymon Janc conn->disc_timeout = HCI_PAIRING_TIMEOUT; 2021a9ea3ed9SSzymon Janc else 2022052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2023769be974SMarcel Holtmann } else 2024a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 2025a9de9248SMarcel Holtmann 20267d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 20277d0db0a3SMarcel Holtmann 2028a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 20294dae2798SJohan Hedberg set_bit(HCI_CONN_AUTH, &conn->flags); 2030a9de9248SMarcel Holtmann 2031a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 20324dae2798SJohan Hedberg set_bit(HCI_CONN_ENCRYPT, &conn->flags); 2033a9de9248SMarcel Holtmann 2034a9de9248SMarcel Holtmann /* Get remote features */ 2035a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 2036a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 2037a9de9248SMarcel Holtmann cp.handle = ev->handle; 2038769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 2039769be974SMarcel Holtmann sizeof(cp), &cp); 204045bb4bf0SMarcel Holtmann } 2041a9de9248SMarcel Holtmann 2042a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 2043d095c1ebSAndrei Emeltchenko if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) { 2044a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 2045a9de9248SMarcel Holtmann cp.handle = ev->handle; 2046a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 204704124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp), 204804124681SGustavo F. Padovan &cp); 2049a9de9248SMarcel Holtmann } 205017d5c04cSJohan Hedberg } else { 2051a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 205217d5c04cSJohan Hedberg if (conn->type == ACL_LINK) 205364c7b77cSMarcel Holtmann mgmt_connect_failed(hdev, &conn->dst, conn->type, 205448264f06SJohan Hedberg conn->dst_type, ev->status); 205517d5c04cSJohan Hedberg } 205645bb4bf0SMarcel Holtmann 2057e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 2058e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 205945bb4bf0SMarcel Holtmann 2060769be974SMarcel Holtmann if (ev->status) { 2061a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2062a9de9248SMarcel Holtmann hci_conn_del(conn); 2063c89b6e6bSMarcel Holtmann } else if (ev->link_type != ACL_LINK) 2064c89b6e6bSMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2065a9de9248SMarcel Holtmann 2066a9de9248SMarcel Holtmann unlock: 20671da177e4SLinus Torvalds hci_dev_unlock(hdev); 2068a9de9248SMarcel Holtmann 2069a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 20701da177e4SLinus Torvalds } 20711da177e4SLinus Torvalds 20726039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 20731da177e4SLinus Torvalds { 2074a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 20751da177e4SLinus Torvalds int mask = hdev->link_mode; 207620714bfeSFrédéric Dalleau __u8 flags = 0; 20771da177e4SLinus Torvalds 20786ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr, 2079807deac2SGustavo Padovan ev->link_type); 20801da177e4SLinus Torvalds 208120714bfeSFrédéric Dalleau mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type, 208220714bfeSFrédéric Dalleau &flags); 20831da177e4SLinus Torvalds 2084138d22efSSzymon Janc if ((mask & HCI_LM_ACCEPT) && 2085b9ee0a78SMarcel Holtmann !hci_blacklist_lookup(hdev, &ev->bdaddr, BDADDR_BREDR)) { 20861da177e4SLinus Torvalds /* Connection accepted */ 2087c7bdd502SMarcel Holtmann struct inquiry_entry *ie; 20881da177e4SLinus Torvalds struct hci_conn *conn; 20891da177e4SLinus Torvalds 20901da177e4SLinus Torvalds hci_dev_lock(hdev); 2091b6a0dc82SMarcel Holtmann 2092cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2093cc11b9c1SAndrei Emeltchenko if (ie) 2094c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 2095c7bdd502SMarcel Holtmann 20968fc9ced3SGustavo Padovan conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, 20978fc9ced3SGustavo Padovan &ev->bdaddr); 20981da177e4SLinus Torvalds if (!conn) { 2099cc11b9c1SAndrei Emeltchenko conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); 2100cc11b9c1SAndrei Emeltchenko if (!conn) { 2101893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 21021da177e4SLinus Torvalds hci_dev_unlock(hdev); 21031da177e4SLinus Torvalds return; 21041da177e4SLinus Torvalds } 21051da177e4SLinus Torvalds } 2106b6a0dc82SMarcel Holtmann 21071da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 2108b6a0dc82SMarcel Holtmann 21091da177e4SLinus Torvalds hci_dev_unlock(hdev); 21101da177e4SLinus Torvalds 211120714bfeSFrédéric Dalleau if (ev->link_type == ACL_LINK || 211220714bfeSFrédéric Dalleau (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) { 2113b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 211420714bfeSFrédéric Dalleau conn->state = BT_CONNECT; 2115b6a0dc82SMarcel Holtmann 21161da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 21171da177e4SLinus Torvalds 21181da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 21191da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 21201da177e4SLinus Torvalds else 21211da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 21221da177e4SLinus Torvalds 212304124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), 212404124681SGustavo F. Padovan &cp); 212520714bfeSFrédéric Dalleau } else if (!(flags & HCI_PROTO_DEFER)) { 2126b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 212720714bfeSFrédéric Dalleau conn->state = BT_CONNECT; 2128b6a0dc82SMarcel Holtmann 2129b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 2130a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 2131b6a0dc82SMarcel Holtmann 2132dcf4adbfSJoe Perches cp.tx_bandwidth = cpu_to_le32(0x00001f40); 2133dcf4adbfSJoe Perches cp.rx_bandwidth = cpu_to_le32(0x00001f40); 2134dcf4adbfSJoe Perches cp.max_latency = cpu_to_le16(0xffff); 2135b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 2136b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 2137b6a0dc82SMarcel Holtmann 2138b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 2139b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 214020714bfeSFrédéric Dalleau } else { 214120714bfeSFrédéric Dalleau conn->state = BT_CONNECT2; 214220714bfeSFrédéric Dalleau hci_proto_connect_cfm(conn, 0); 2143b6a0dc82SMarcel Holtmann } 21441da177e4SLinus Torvalds } else { 21451da177e4SLinus Torvalds /* Connection rejected */ 21461da177e4SLinus Torvalds struct hci_cp_reject_conn_req cp; 21471da177e4SLinus Torvalds 21481da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 21499f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_REJ_BAD_ADDR; 2150a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 21511da177e4SLinus Torvalds } 21521da177e4SLinus Torvalds } 21531da177e4SLinus Torvalds 2154f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err) 2155f0d6a0eaSMikel Astiz { 2156f0d6a0eaSMikel Astiz switch (err) { 2157f0d6a0eaSMikel Astiz case HCI_ERROR_CONNECTION_TIMEOUT: 2158f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_TIMEOUT; 2159f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_USER_TERM: 2160f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_LOW_RESOURCES: 2161f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_POWER_OFF: 2162f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_REMOTE; 2163f0d6a0eaSMikel Astiz case HCI_ERROR_LOCAL_HOST_TERM: 2164f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_LOCAL_HOST; 2165f0d6a0eaSMikel Astiz default: 2166f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_UNKNOWN; 2167f0d6a0eaSMikel Astiz } 2168f0d6a0eaSMikel Astiz } 2169f0d6a0eaSMikel Astiz 21706039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 21711da177e4SLinus Torvalds { 2172a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 2173abf54a50SAndre Guedes u8 reason = hci_to_mgmt_reason(ev->reason); 21749fcb18efSAndre Guedes struct hci_conn_params *params; 217504837f64SMarcel Holtmann struct hci_conn *conn; 217612d4a3b2SJohan Hedberg bool mgmt_connected; 21773846220bSAndre Guedes u8 type; 21781da177e4SLinus Torvalds 21799f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 21801da177e4SLinus Torvalds 21811da177e4SLinus Torvalds hci_dev_lock(hdev); 21821da177e4SLinus Torvalds 218304837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2184f7520543SJohan Hedberg if (!conn) 2185f7520543SJohan Hedberg goto unlock; 2186f7520543SJohan Hedberg 2187f0d6a0eaSMikel Astiz if (ev->status) { 218888c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 218988c3df13SJohan Hedberg conn->dst_type, ev->status); 2190abf54a50SAndre Guedes goto unlock; 2191abf54a50SAndre Guedes } 2192f0d6a0eaSMikel Astiz 21933846220bSAndre Guedes conn->state = BT_CLOSED; 21943846220bSAndre Guedes 219512d4a3b2SJohan Hedberg mgmt_connected = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags); 219612d4a3b2SJohan Hedberg mgmt_device_disconnected(hdev, &conn->dst, conn->type, conn->dst_type, 219712d4a3b2SJohan Hedberg reason, mgmt_connected); 2198f7520543SJohan Hedberg 2199af6a9c32SJohan Hedberg if (conn->type == ACL_LINK && 2200af6a9c32SJohan Hedberg test_bit(HCI_CONN_FLUSH_KEY, &conn->flags)) 22016ec5bcadSVishal Agarwal hci_remove_link_key(hdev, &conn->dst); 22023846220bSAndre Guedes 22039fcb18efSAndre Guedes params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type); 22049fcb18efSAndre Guedes if (params) { 22059fcb18efSAndre Guedes switch (params->auto_connect) { 22069fcb18efSAndre Guedes case HCI_AUTO_CONN_LINK_LOSS: 22079fcb18efSAndre Guedes if (ev->reason != HCI_ERROR_CONNECTION_TIMEOUT) 22089fcb18efSAndre Guedes break; 22099fcb18efSAndre Guedes /* Fall through */ 22109fcb18efSAndre Guedes 22119fcb18efSAndre Guedes case HCI_AUTO_CONN_ALWAYS: 22129fcb18efSAndre Guedes hci_pend_le_conn_add(hdev, &conn->dst, conn->dst_type); 22139fcb18efSAndre Guedes break; 22149fcb18efSAndre Guedes 22159fcb18efSAndre Guedes default: 22169fcb18efSAndre Guedes break; 22179fcb18efSAndre Guedes } 22189fcb18efSAndre Guedes } 22199fcb18efSAndre Guedes 22203846220bSAndre Guedes type = conn->type; 22213846220bSAndre Guedes 22222950f21aSMarcel Holtmann hci_proto_disconn_cfm(conn, ev->reason); 22231da177e4SLinus Torvalds hci_conn_del(conn); 22242210246cSJohan Hedberg 22252210246cSJohan Hedberg /* Re-enable advertising if necessary, since it might 22262210246cSJohan Hedberg * have been disabled by the connection. From the 22272210246cSJohan Hedberg * HCI_LE_Set_Advertise_Enable command description in 22282210246cSJohan Hedberg * the core specification (v4.0): 22292210246cSJohan Hedberg * "The Controller shall continue advertising until the Host 22302210246cSJohan Hedberg * issues an LE_Set_Advertise_Enable command with 22312210246cSJohan Hedberg * Advertising_Enable set to 0x00 (Advertising is disabled) 22322210246cSJohan Hedberg * or until a connection is created or until the Advertising 22332210246cSJohan Hedberg * is timed out due to Directed Advertising." 22342210246cSJohan Hedberg */ 22352210246cSJohan Hedberg if (type == LE_LINK) 22365976e608SMarcel Holtmann mgmt_reenable_advertising(hdev); 22371da177e4SLinus Torvalds 2238f7520543SJohan Hedberg unlock: 22391da177e4SLinus Torvalds hci_dev_unlock(hdev); 22401da177e4SLinus Torvalds } 22411da177e4SLinus Torvalds 22426039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2243a9de9248SMarcel Holtmann { 2244a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 2245a9de9248SMarcel Holtmann struct hci_conn *conn; 2246a9de9248SMarcel Holtmann 22479f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2248a9de9248SMarcel Holtmann 2249a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2250a9de9248SMarcel Holtmann 2251a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2252d7556e20SWaldemar Rymarkiewicz if (!conn) 2253d7556e20SWaldemar Rymarkiewicz goto unlock; 2254d7556e20SWaldemar Rymarkiewicz 2255765c2a96SJohan Hedberg if (!ev->status) { 2256aa64a8b5SJohan Hedberg if (!hci_conn_ssp_enabled(conn) && 225751a8efd7SJohan Hedberg test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) { 2258d7556e20SWaldemar Rymarkiewicz BT_INFO("re-auth of legacy device is not possible."); 225919f8def0SWaldemar Rymarkiewicz } else { 22604dae2798SJohan Hedberg set_bit(HCI_CONN_AUTH, &conn->flags); 2261765c2a96SJohan Hedberg conn->sec_level = conn->pending_sec_level; 226219f8def0SWaldemar Rymarkiewicz } 22632a611692SJohan Hedberg } else { 2264bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 2265bab73cb6SJohan Hedberg ev->status); 22662a611692SJohan Hedberg } 2267a9de9248SMarcel Holtmann 226851a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 226951a8efd7SJohan Hedberg clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags); 2270a9de9248SMarcel Holtmann 2271f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 2272aa64a8b5SJohan Hedberg if (!ev->status && hci_conn_ssp_enabled(conn)) { 2273f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 2274f8558555SMarcel Holtmann cp.handle = ev->handle; 2275f8558555SMarcel Holtmann cp.encrypt = 0x01; 2276d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 2277d7556e20SWaldemar Rymarkiewicz &cp); 2278f8558555SMarcel Holtmann } else { 2279f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 2280f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 228176a68ba0SDavid Herrmann hci_conn_drop(conn); 2282f8558555SMarcel Holtmann } 2283052b30b0SMarcel Holtmann } else { 2284a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 2285a9de9248SMarcel Holtmann 2286052b30b0SMarcel Holtmann hci_conn_hold(conn); 2287052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 228876a68ba0SDavid Herrmann hci_conn_drop(conn); 2289052b30b0SMarcel Holtmann } 2290052b30b0SMarcel Holtmann 229151a8efd7SJohan Hedberg if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) { 2292a9de9248SMarcel Holtmann if (!ev->status) { 2293a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 2294f8558555SMarcel Holtmann cp.handle = ev->handle; 2295f8558555SMarcel Holtmann cp.encrypt = 0x01; 2296d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 2297d7556e20SWaldemar Rymarkiewicz &cp); 2298a9de9248SMarcel Holtmann } else { 229951a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 2300a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 2301a9de9248SMarcel Holtmann } 2302a9de9248SMarcel Holtmann } 2303a9de9248SMarcel Holtmann 2304d7556e20SWaldemar Rymarkiewicz unlock: 2305a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2306a9de9248SMarcel Holtmann } 2307a9de9248SMarcel Holtmann 23086039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 2309a9de9248SMarcel Holtmann { 2310127178d2SJohan Hedberg struct hci_ev_remote_name *ev = (void *) skb->data; 2311127178d2SJohan Hedberg struct hci_conn *conn; 2312127178d2SJohan Hedberg 2313a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2314a9de9248SMarcel Holtmann 2315a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 2316127178d2SJohan Hedberg 2317127178d2SJohan Hedberg hci_dev_lock(hdev); 2318127178d2SJohan Hedberg 2319127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2320b644ba33SJohan Hedberg 2321b644ba33SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 2322b644ba33SJohan Hedberg goto check_auth; 2323b644ba33SJohan Hedberg 2324b644ba33SJohan Hedberg if (ev->status == 0) 2325b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name, 2326b644ba33SJohan Hedberg strnlen(ev->name, HCI_MAX_NAME_LENGTH)); 2327b644ba33SJohan Hedberg else 2328b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0); 2329b644ba33SJohan Hedberg 2330b644ba33SJohan Hedberg check_auth: 233179c6c70cSJohan Hedberg if (!conn) 233279c6c70cSJohan Hedberg goto unlock; 233379c6c70cSJohan Hedberg 233479c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 233579c6c70cSJohan Hedberg goto unlock; 233679c6c70cSJohan Hedberg 233751a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 2338127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 2339127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 2340127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 2341127178d2SJohan Hedberg } 2342127178d2SJohan Hedberg 234379c6c70cSJohan Hedberg unlock: 2344127178d2SJohan Hedberg hci_dev_unlock(hdev); 2345a9de9248SMarcel Holtmann } 2346a9de9248SMarcel Holtmann 23476039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2348a9de9248SMarcel Holtmann { 2349a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 2350a9de9248SMarcel Holtmann struct hci_conn *conn; 2351a9de9248SMarcel Holtmann 23529f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2353a9de9248SMarcel Holtmann 2354a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2355a9de9248SMarcel Holtmann 2356a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2357dc8357ccSMarcel Holtmann if (!conn) 2358dc8357ccSMarcel Holtmann goto unlock; 2359dc8357ccSMarcel Holtmann 2360a9de9248SMarcel Holtmann if (!ev->status) { 2361ae293196SMarcel Holtmann if (ev->encrypt) { 2362ae293196SMarcel Holtmann /* Encryption implies authentication */ 23634dae2798SJohan Hedberg set_bit(HCI_CONN_AUTH, &conn->flags); 23644dae2798SJohan Hedberg set_bit(HCI_CONN_ENCRYPT, &conn->flags); 2365da85e5e5SVinicius Costa Gomes conn->sec_level = conn->pending_sec_level; 2366abf76badSMarcel Holtmann 2367914a6ffeSMarcel Holtmann /* P-256 authentication key implies FIPS */ 2368914a6ffeSMarcel Holtmann if (conn->key_type == HCI_LK_AUTH_COMBINATION_P256) 23694dae2798SJohan Hedberg set_bit(HCI_CONN_FIPS, &conn->flags); 2370914a6ffeSMarcel Holtmann 2371abf76badSMarcel Holtmann if ((conn->type == ACL_LINK && ev->encrypt == 0x02) || 2372abf76badSMarcel Holtmann conn->type == LE_LINK) 2373abf76badSMarcel Holtmann set_bit(HCI_CONN_AES_CCM, &conn->flags); 2374abf76badSMarcel Holtmann } else { 23754dae2798SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT, &conn->flags); 2376abf76badSMarcel Holtmann clear_bit(HCI_CONN_AES_CCM, &conn->flags); 2377abf76badSMarcel Holtmann } 2378a9de9248SMarcel Holtmann } 2379a9de9248SMarcel Holtmann 238051a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 2381a9de9248SMarcel Holtmann 2382a7d7723aSGustavo Padovan if (ev->status && conn->state == BT_CONNECTED) { 2383bed71748SAndre Guedes hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); 238476a68ba0SDavid Herrmann hci_conn_drop(conn); 2385a7d7723aSGustavo Padovan goto unlock; 2386a7d7723aSGustavo Padovan } 2387a7d7723aSGustavo Padovan 2388f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 2389f8558555SMarcel Holtmann if (!ev->status) 2390f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 2391f8558555SMarcel Holtmann 239240b552aaSMarcel Holtmann /* In Secure Connections Only mode, do not allow any 239340b552aaSMarcel Holtmann * connections that are not encrypted with AES-CCM 239440b552aaSMarcel Holtmann * using a P-256 authenticated combination key. 239540b552aaSMarcel Holtmann */ 239640b552aaSMarcel Holtmann if (test_bit(HCI_SC_ONLY, &hdev->dev_flags) && 239740b552aaSMarcel Holtmann (!test_bit(HCI_CONN_AES_CCM, &conn->flags) || 239840b552aaSMarcel Holtmann conn->key_type != HCI_LK_AUTH_COMBINATION_P256)) { 239940b552aaSMarcel Holtmann hci_proto_connect_cfm(conn, HCI_ERROR_AUTH_FAILURE); 240040b552aaSMarcel Holtmann hci_conn_drop(conn); 240140b552aaSMarcel Holtmann goto unlock; 240240b552aaSMarcel Holtmann } 240340b552aaSMarcel Holtmann 2404f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 240576a68ba0SDavid Herrmann hci_conn_drop(conn); 2406f8558555SMarcel Holtmann } else 2407a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 2408a9de9248SMarcel Holtmann 2409a7d7723aSGustavo Padovan unlock: 2410a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2411a9de9248SMarcel Holtmann } 2412a9de9248SMarcel Holtmann 24136039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev, 2414807deac2SGustavo Padovan struct sk_buff *skb) 2415a9de9248SMarcel Holtmann { 2416a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 2417a9de9248SMarcel Holtmann struct hci_conn *conn; 2418a9de9248SMarcel Holtmann 24199f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2420a9de9248SMarcel Holtmann 2421a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2422a9de9248SMarcel Holtmann 2423a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2424a9de9248SMarcel Holtmann if (conn) { 2425a9de9248SMarcel Holtmann if (!ev->status) 24264dae2798SJohan Hedberg set_bit(HCI_CONN_SECURE, &conn->flags); 2427a9de9248SMarcel Holtmann 242851a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 2429a9de9248SMarcel Holtmann 2430a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 2431a9de9248SMarcel Holtmann } 2432a9de9248SMarcel Holtmann 2433a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2434a9de9248SMarcel Holtmann } 2435a9de9248SMarcel Holtmann 24366039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev, 2437807deac2SGustavo Padovan struct sk_buff *skb) 2438a9de9248SMarcel Holtmann { 2439a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 2440a9de9248SMarcel Holtmann struct hci_conn *conn; 2441a9de9248SMarcel Holtmann 24429f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2443a9de9248SMarcel Holtmann 2444a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2445a9de9248SMarcel Holtmann 2446a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2447ccd556feSJohan Hedberg if (!conn) 2448ccd556feSJohan Hedberg goto unlock; 2449ccd556feSJohan Hedberg 2450769be974SMarcel Holtmann if (!ev->status) 2451cad718edSJohan Hedberg memcpy(conn->features[0], ev->features, 8); 2452a9de9248SMarcel Holtmann 2453ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2454ccd556feSJohan Hedberg goto unlock; 2455ccd556feSJohan Hedberg 2456ccd556feSJohan Hedberg if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { 2457769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 2458769be974SMarcel Holtmann cp.handle = ev->handle; 2459769be974SMarcel Holtmann cp.page = 0x01; 2460ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 2461769be974SMarcel Holtmann sizeof(cp), &cp); 2462392599b9SJohan Hedberg goto unlock; 2463392599b9SJohan Hedberg } 2464392599b9SJohan Hedberg 2465671267bfSJohan Hedberg if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { 2466127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2467127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2468127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2469127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2470127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2471b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 2472b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 247308c79b61SJohan Hedberg conn->dst_type, 0, NULL, 0, 2474b644ba33SJohan Hedberg conn->dev_class); 2475392599b9SJohan Hedberg 2476127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2477769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2478769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 247976a68ba0SDavid Herrmann hci_conn_drop(conn); 2480769be974SMarcel Holtmann } 2481769be974SMarcel Holtmann 2482ccd556feSJohan Hedberg unlock: 2483a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2484a9de9248SMarcel Holtmann } 2485a9de9248SMarcel Holtmann 24866039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2487a9de9248SMarcel Holtmann { 2488a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 24899238f36aSJohan Hedberg u8 status = skb->data[sizeof(*ev)]; 2490a9de9248SMarcel Holtmann __u16 opcode; 2491a9de9248SMarcel Holtmann 2492a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2493a9de9248SMarcel Holtmann 2494a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2495a9de9248SMarcel Holtmann 2496a9de9248SMarcel Holtmann switch (opcode) { 2497a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 2498a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 2499a9de9248SMarcel Holtmann break; 2500a9de9248SMarcel Holtmann 25014d93483bSAndre Guedes case HCI_OP_PERIODIC_INQ: 25024d93483bSAndre Guedes hci_cc_periodic_inq(hdev, skb); 25034d93483bSAndre Guedes break; 25044d93483bSAndre Guedes 2505a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 2506a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 2507a9de9248SMarcel Holtmann break; 2508a9de9248SMarcel Holtmann 2509a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 2510a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 2511a9de9248SMarcel Holtmann break; 2512a9de9248SMarcel Holtmann 2513a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 2514a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 2515a9de9248SMarcel Holtmann break; 2516a9de9248SMarcel Holtmann 2517e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 2518e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 2519e4e8e37cSMarcel Holtmann break; 2520e4e8e37cSMarcel Holtmann 2521a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 2522a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 2523a9de9248SMarcel Holtmann break; 2524a9de9248SMarcel Holtmann 2525e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 2526e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 2527e4e8e37cSMarcel Holtmann break; 2528e4e8e37cSMarcel Holtmann 2529e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 2530e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 2531e4e8e37cSMarcel Holtmann break; 2532e4e8e37cSMarcel Holtmann 2533a9de9248SMarcel Holtmann case HCI_OP_RESET: 2534a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 2535a9de9248SMarcel Holtmann break; 2536a9de9248SMarcel Holtmann 2537a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 2538a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 2539a9de9248SMarcel Holtmann break; 2540a9de9248SMarcel Holtmann 2541a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 2542a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 2543a9de9248SMarcel Holtmann break; 2544a9de9248SMarcel Holtmann 2545a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 2546a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 2547a9de9248SMarcel Holtmann break; 2548a9de9248SMarcel Holtmann 2549a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 2550a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 2551a9de9248SMarcel Holtmann break; 2552a9de9248SMarcel Holtmann 2553a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 2554a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 2555a9de9248SMarcel Holtmann break; 2556a9de9248SMarcel Holtmann 2557a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 2558a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 2559a9de9248SMarcel Holtmann break; 2560a9de9248SMarcel Holtmann 2561a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 2562a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 2563a9de9248SMarcel Holtmann break; 2564a9de9248SMarcel Holtmann 2565a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 2566a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 2567a9de9248SMarcel Holtmann break; 2568a9de9248SMarcel Holtmann 2569a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 2570a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 2571a9de9248SMarcel Holtmann break; 2572a9de9248SMarcel Holtmann 2573b4cb9fb2SMarcel Holtmann case HCI_OP_READ_NUM_SUPPORTED_IAC: 2574b4cb9fb2SMarcel Holtmann hci_cc_read_num_supported_iac(hdev, skb); 2575b4cb9fb2SMarcel Holtmann break; 2576b4cb9fb2SMarcel Holtmann 2577333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 2578333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 2579333140b5SMarcel Holtmann break; 2580333140b5SMarcel Holtmann 2581eac83dc6SMarcel Holtmann case HCI_OP_WRITE_SC_SUPPORT: 2582eac83dc6SMarcel Holtmann hci_cc_write_sc_support(hdev, skb); 2583eac83dc6SMarcel Holtmann break; 2584eac83dc6SMarcel Holtmann 2585a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 2586a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 2587a9de9248SMarcel Holtmann break; 2588a9de9248SMarcel Holtmann 2589a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 2590a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 2591a9de9248SMarcel Holtmann break; 2592a9de9248SMarcel Holtmann 2593a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 2594a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 2595a9de9248SMarcel Holtmann break; 2596a9de9248SMarcel Holtmann 2597971e3a4bSAndre Guedes case HCI_OP_READ_LOCAL_EXT_FEATURES: 2598971e3a4bSAndre Guedes hci_cc_read_local_ext_features(hdev, skb); 2599971e3a4bSAndre Guedes break; 2600971e3a4bSAndre Guedes 2601a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 2602a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 2603a9de9248SMarcel Holtmann break; 2604a9de9248SMarcel Holtmann 2605a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 2606a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 2607a9de9248SMarcel Holtmann break; 2608a9de9248SMarcel Holtmann 2609f332ec66SJohan Hedberg case HCI_OP_READ_PAGE_SCAN_ACTIVITY: 2610f332ec66SJohan Hedberg hci_cc_read_page_scan_activity(hdev, skb); 2611f332ec66SJohan Hedberg break; 2612f332ec66SJohan Hedberg 26134a3ee763SJohan Hedberg case HCI_OP_WRITE_PAGE_SCAN_ACTIVITY: 26144a3ee763SJohan Hedberg hci_cc_write_page_scan_activity(hdev, skb); 26154a3ee763SJohan Hedberg break; 26164a3ee763SJohan Hedberg 2617f332ec66SJohan Hedberg case HCI_OP_READ_PAGE_SCAN_TYPE: 2618f332ec66SJohan Hedberg hci_cc_read_page_scan_type(hdev, skb); 2619f332ec66SJohan Hedberg break; 2620f332ec66SJohan Hedberg 26214a3ee763SJohan Hedberg case HCI_OP_WRITE_PAGE_SCAN_TYPE: 26224a3ee763SJohan Hedberg hci_cc_write_page_scan_type(hdev, skb); 26234a3ee763SJohan Hedberg break; 26244a3ee763SJohan Hedberg 2625350ee4cfSAndrei Emeltchenko case HCI_OP_READ_DATA_BLOCK_SIZE: 2626350ee4cfSAndrei Emeltchenko hci_cc_read_data_block_size(hdev, skb); 2627350ee4cfSAndrei Emeltchenko break; 2628350ee4cfSAndrei Emeltchenko 26291e89cffbSAndrei Emeltchenko case HCI_OP_READ_FLOW_CONTROL_MODE: 26301e89cffbSAndrei Emeltchenko hci_cc_read_flow_control_mode(hdev, skb); 26311e89cffbSAndrei Emeltchenko break; 26321e89cffbSAndrei Emeltchenko 2633928abaa7SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_INFO: 2634928abaa7SAndrei Emeltchenko hci_cc_read_local_amp_info(hdev, skb); 2635928abaa7SAndrei Emeltchenko break; 2636928abaa7SAndrei Emeltchenko 263733f35721SJohan Hedberg case HCI_OP_READ_CLOCK: 263833f35721SJohan Hedberg hci_cc_read_clock(hdev, skb); 263933f35721SJohan Hedberg break; 264033f35721SJohan Hedberg 2641903e4541SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_ASSOC: 2642903e4541SAndrei Emeltchenko hci_cc_read_local_amp_assoc(hdev, skb); 2643903e4541SAndrei Emeltchenko break; 2644903e4541SAndrei Emeltchenko 2645d5859e22SJohan Hedberg case HCI_OP_READ_INQ_RSP_TX_POWER: 2646d5859e22SJohan Hedberg hci_cc_read_inq_rsp_tx_power(hdev, skb); 2647d5859e22SJohan Hedberg break; 2648d5859e22SJohan Hedberg 2649980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_REPLY: 2650980e1a53SJohan Hedberg hci_cc_pin_code_reply(hdev, skb); 2651980e1a53SJohan Hedberg break; 2652980e1a53SJohan Hedberg 2653980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_NEG_REPLY: 2654980e1a53SJohan Hedberg hci_cc_pin_code_neg_reply(hdev, skb); 2655980e1a53SJohan Hedberg break; 2656980e1a53SJohan Hedberg 2657c35938b2SSzymon Janc case HCI_OP_READ_LOCAL_OOB_DATA: 26584d2d2796SMarcel Holtmann hci_cc_read_local_oob_data(hdev, skb); 26594d2d2796SMarcel Holtmann break; 26604d2d2796SMarcel Holtmann 26614d2d2796SMarcel Holtmann case HCI_OP_READ_LOCAL_OOB_EXT_DATA: 26624d2d2796SMarcel Holtmann hci_cc_read_local_oob_ext_data(hdev, skb); 2663c35938b2SSzymon Janc break; 2664c35938b2SSzymon Janc 26656ed58ec5SVille Tervo case HCI_OP_LE_READ_BUFFER_SIZE: 26666ed58ec5SVille Tervo hci_cc_le_read_buffer_size(hdev, skb); 26676ed58ec5SVille Tervo break; 26686ed58ec5SVille Tervo 266960e77321SJohan Hedberg case HCI_OP_LE_READ_LOCAL_FEATURES: 267060e77321SJohan Hedberg hci_cc_le_read_local_features(hdev, skb); 267160e77321SJohan Hedberg break; 267260e77321SJohan Hedberg 26738fa19098SJohan Hedberg case HCI_OP_LE_READ_ADV_TX_POWER: 26748fa19098SJohan Hedberg hci_cc_le_read_adv_tx_power(hdev, skb); 26758fa19098SJohan Hedberg break; 26768fa19098SJohan Hedberg 2677a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_REPLY: 2678a5c29683SJohan Hedberg hci_cc_user_confirm_reply(hdev, skb); 2679a5c29683SJohan Hedberg break; 2680a5c29683SJohan Hedberg 2681a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_NEG_REPLY: 2682a5c29683SJohan Hedberg hci_cc_user_confirm_neg_reply(hdev, skb); 2683a5c29683SJohan Hedberg break; 2684a5c29683SJohan Hedberg 26851143d458SBrian Gix case HCI_OP_USER_PASSKEY_REPLY: 26861143d458SBrian Gix hci_cc_user_passkey_reply(hdev, skb); 26871143d458SBrian Gix break; 26881143d458SBrian Gix 26891143d458SBrian Gix case HCI_OP_USER_PASSKEY_NEG_REPLY: 26901143d458SBrian Gix hci_cc_user_passkey_neg_reply(hdev, skb); 269116cde993SSzymon Janc break; 269207f7fa5dSAndre Guedes 26937a4cd51dSMarcel Holtmann case HCI_OP_LE_SET_RANDOM_ADDR: 26947a4cd51dSMarcel Holtmann hci_cc_le_set_random_addr(hdev, skb); 26957a4cd51dSMarcel Holtmann break; 26967a4cd51dSMarcel Holtmann 2697c1d5dc4aSJohan Hedberg case HCI_OP_LE_SET_ADV_ENABLE: 2698c1d5dc4aSJohan Hedberg hci_cc_le_set_adv_enable(hdev, skb); 2699c1d5dc4aSJohan Hedberg break; 2700c1d5dc4aSJohan Hedberg 2701533553f8SMarcel Holtmann case HCI_OP_LE_SET_SCAN_PARAM: 2702533553f8SMarcel Holtmann hci_cc_le_set_scan_param(hdev, skb); 2703533553f8SMarcel Holtmann break; 2704533553f8SMarcel Holtmann 2705eb9d91f5SAndre Guedes case HCI_OP_LE_SET_SCAN_ENABLE: 2706eb9d91f5SAndre Guedes hci_cc_le_set_scan_enable(hdev, skb); 2707eb9d91f5SAndre Guedes break; 2708eb9d91f5SAndre Guedes 2709cf1d081fSJohan Hedberg case HCI_OP_LE_READ_WHITE_LIST_SIZE: 2710cf1d081fSJohan Hedberg hci_cc_le_read_white_list_size(hdev, skb); 2711cf1d081fSJohan Hedberg break; 2712cf1d081fSJohan Hedberg 27130f36b589SMarcel Holtmann case HCI_OP_LE_CLEAR_WHITE_LIST: 27140f36b589SMarcel Holtmann hci_cc_le_clear_white_list(hdev, skb); 27150f36b589SMarcel Holtmann break; 27160f36b589SMarcel Holtmann 27170f36b589SMarcel Holtmann case HCI_OP_LE_ADD_TO_WHITE_LIST: 27180f36b589SMarcel Holtmann hci_cc_le_add_to_white_list(hdev, skb); 27190f36b589SMarcel Holtmann break; 27200f36b589SMarcel Holtmann 27210f36b589SMarcel Holtmann case HCI_OP_LE_DEL_FROM_WHITE_LIST: 27220f36b589SMarcel Holtmann hci_cc_le_del_from_white_list(hdev, skb); 27230f36b589SMarcel Holtmann break; 27240f36b589SMarcel Holtmann 27259b008c04SJohan Hedberg case HCI_OP_LE_READ_SUPPORTED_STATES: 27269b008c04SJohan Hedberg hci_cc_le_read_supported_states(hdev, skb); 27279b008c04SJohan Hedberg break; 27289b008c04SJohan Hedberg 2729f9b49306SAndre Guedes case HCI_OP_WRITE_LE_HOST_SUPPORTED: 2730f9b49306SAndre Guedes hci_cc_write_le_host_supported(hdev, skb); 2731f9b49306SAndre Guedes break; 2732f9b49306SAndre Guedes 273356ed2cb8SJohan Hedberg case HCI_OP_LE_SET_ADV_PARAM: 273456ed2cb8SJohan Hedberg hci_cc_set_adv_param(hdev, skb); 273556ed2cb8SJohan Hedberg break; 273656ed2cb8SJohan Hedberg 273793c284eeSAndrei Emeltchenko case HCI_OP_WRITE_REMOTE_AMP_ASSOC: 273893c284eeSAndrei Emeltchenko hci_cc_write_remote_amp_assoc(hdev, skb); 273993c284eeSAndrei Emeltchenko break; 274093c284eeSAndrei Emeltchenko 27415ae76a94SAndrzej Kaczmarek case HCI_OP_READ_RSSI: 27425ae76a94SAndrzej Kaczmarek hci_cc_read_rssi(hdev, skb); 27435ae76a94SAndrzej Kaczmarek break; 27445ae76a94SAndrzej Kaczmarek 27455a134faeSAndrzej Kaczmarek case HCI_OP_READ_TX_POWER: 27465a134faeSAndrzej Kaczmarek hci_cc_read_tx_power(hdev, skb); 27475a134faeSAndrzej Kaczmarek break; 27485a134faeSAndrzej Kaczmarek 2749a9de9248SMarcel Holtmann default: 27509f1db00cSAndrei Emeltchenko BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); 2751a9de9248SMarcel Holtmann break; 2752a9de9248SMarcel Holtmann } 2753a9de9248SMarcel Holtmann 2754ad82cdd1SJohan Hedberg if (opcode != HCI_OP_NOP) 275565cc2b49SMarcel Holtmann cancel_delayed_work(&hdev->cmd_timer); 27566bd32326SVille Tervo 2757ad82cdd1SJohan Hedberg hci_req_cmd_complete(hdev, opcode, status); 27589238f36aSJohan Hedberg 2759dbccd791SSzymon Janc if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2760a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2761a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2762c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2763a9de9248SMarcel Holtmann } 2764a9de9248SMarcel Holtmann } 2765a9de9248SMarcel Holtmann 27666039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 2767a9de9248SMarcel Holtmann { 2768a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 2769a9de9248SMarcel Holtmann __u16 opcode; 2770a9de9248SMarcel Holtmann 2771a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2772a9de9248SMarcel Holtmann 2773a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2774a9de9248SMarcel Holtmann 2775a9de9248SMarcel Holtmann switch (opcode) { 2776a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 2777a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 2778a9de9248SMarcel Holtmann break; 2779a9de9248SMarcel Holtmann 2780a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 2781a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 2782a9de9248SMarcel Holtmann break; 2783a9de9248SMarcel Holtmann 2784a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 2785a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 2786a9de9248SMarcel Holtmann break; 2787a9de9248SMarcel Holtmann 2788f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 2789f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 2790f8558555SMarcel Holtmann break; 2791f8558555SMarcel Holtmann 2792f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 2793f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 2794f8558555SMarcel Holtmann break; 2795f8558555SMarcel Holtmann 2796a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 2797a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 2798a9de9248SMarcel Holtmann break; 2799a9de9248SMarcel Holtmann 2800769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 2801769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 2802769be974SMarcel Holtmann break; 2803769be974SMarcel Holtmann 2804769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 2805769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 2806769be974SMarcel Holtmann break; 2807769be974SMarcel Holtmann 2808a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 2809a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 2810a9de9248SMarcel Holtmann break; 2811a9de9248SMarcel Holtmann 2812a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 2813a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 2814a9de9248SMarcel Holtmann break; 2815a9de9248SMarcel Holtmann 2816a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 2817a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 2818a9de9248SMarcel Holtmann break; 2819a9de9248SMarcel Holtmann 28208962ee74SJohan Hedberg case HCI_OP_DISCONNECT: 282188c3df13SJohan Hedberg hci_cs_disconnect(hdev, ev->status); 28228962ee74SJohan Hedberg break; 28238962ee74SJohan Hedberg 2824a02226d6SAndrei Emeltchenko case HCI_OP_CREATE_PHY_LINK: 2825a02226d6SAndrei Emeltchenko hci_cs_create_phylink(hdev, ev->status); 2826a02226d6SAndrei Emeltchenko break; 2827a02226d6SAndrei Emeltchenko 28280b26ab9dSAndrei Emeltchenko case HCI_OP_ACCEPT_PHY_LINK: 28290b26ab9dSAndrei Emeltchenko hci_cs_accept_phylink(hdev, ev->status); 28300b26ab9dSAndrei Emeltchenko break; 28310b26ab9dSAndrei Emeltchenko 2832cb1d68f7SJohan Hedberg case HCI_OP_LE_CREATE_CONN: 2833cb1d68f7SJohan Hedberg hci_cs_le_create_conn(hdev, ev->status); 2834cb1d68f7SJohan Hedberg break; 2835cb1d68f7SJohan Hedberg 283681d0c8adSJohan Hedberg case HCI_OP_LE_START_ENC: 283781d0c8adSJohan Hedberg hci_cs_le_start_enc(hdev, ev->status); 283881d0c8adSJohan Hedberg break; 283981d0c8adSJohan Hedberg 2840a9de9248SMarcel Holtmann default: 28419f1db00cSAndrei Emeltchenko BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); 2842a9de9248SMarcel Holtmann break; 2843a9de9248SMarcel Holtmann } 2844a9de9248SMarcel Holtmann 2845ad82cdd1SJohan Hedberg if (opcode != HCI_OP_NOP) 284665cc2b49SMarcel Holtmann cancel_delayed_work(&hdev->cmd_timer); 28476bd32326SVille Tervo 284802350a72SJohan Hedberg if (ev->status || 284902350a72SJohan Hedberg (hdev->sent_cmd && !bt_cb(hdev->sent_cmd)->req.event)) 285033720450SAndre Guedes hci_req_cmd_complete(hdev, opcode, ev->status); 28519238f36aSJohan Hedberg 285210572132SGustavo F. Padovan if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2853a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2854a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2855c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2856a9de9248SMarcel Holtmann } 2857a9de9248SMarcel Holtmann } 2858a9de9248SMarcel Holtmann 28596039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2860a9de9248SMarcel Holtmann { 2861a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 2862a9de9248SMarcel Holtmann struct hci_conn *conn; 2863a9de9248SMarcel Holtmann 28649f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2865a9de9248SMarcel Holtmann 2866a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2867a9de9248SMarcel Holtmann 2868a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2869a9de9248SMarcel Holtmann if (conn) { 2870a9de9248SMarcel Holtmann if (!ev->status) { 2871a9de9248SMarcel Holtmann if (ev->role) 28724dae2798SJohan Hedberg clear_bit(HCI_CONN_MASTER, &conn->flags); 2873a9de9248SMarcel Holtmann else 28744dae2798SJohan Hedberg set_bit(HCI_CONN_MASTER, &conn->flags); 2875a9de9248SMarcel Holtmann } 2876a9de9248SMarcel Holtmann 287751a8efd7SJohan Hedberg clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); 2878a9de9248SMarcel Holtmann 2879a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 2880a9de9248SMarcel Holtmann } 2881a9de9248SMarcel Holtmann 2882a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2883a9de9248SMarcel Holtmann } 2884a9de9248SMarcel Holtmann 28856039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 28861da177e4SLinus Torvalds { 2887a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 28881da177e4SLinus Torvalds int i; 28891da177e4SLinus Torvalds 289032ac5b9bSAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) { 289132ac5b9bSAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 289232ac5b9bSAndrei Emeltchenko return; 289332ac5b9bSAndrei Emeltchenko } 289432ac5b9bSAndrei Emeltchenko 2895c5993de8SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 2896c5993de8SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_pkts_info)) { 28971da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 28981da177e4SLinus Torvalds return; 28991da177e4SLinus Torvalds } 29001da177e4SLinus Torvalds 2901c5993de8SAndrei Emeltchenko BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 2902c5993de8SAndrei Emeltchenko 2903613a1c0cSAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 2904613a1c0cSAndrei Emeltchenko struct hci_comp_pkts_info *info = &ev->handles[i]; 29051da177e4SLinus Torvalds struct hci_conn *conn; 29061da177e4SLinus Torvalds __u16 handle, count; 29071da177e4SLinus Torvalds 2908613a1c0cSAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 2909613a1c0cSAndrei Emeltchenko count = __le16_to_cpu(info->count); 29101da177e4SLinus Torvalds 29111da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 2912f4280918SAndrei Emeltchenko if (!conn) 2913f4280918SAndrei Emeltchenko continue; 2914f4280918SAndrei Emeltchenko 29151da177e4SLinus Torvalds conn->sent -= count; 29161da177e4SLinus Torvalds 2917f4280918SAndrei Emeltchenko switch (conn->type) { 2918f4280918SAndrei Emeltchenko case ACL_LINK: 291970f23020SAndrei Emeltchenko hdev->acl_cnt += count; 292070f23020SAndrei Emeltchenko if (hdev->acl_cnt > hdev->acl_pkts) 29211da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 2922f4280918SAndrei Emeltchenko break; 2923f4280918SAndrei Emeltchenko 2924f4280918SAndrei Emeltchenko case LE_LINK: 29256ed58ec5SVille Tervo if (hdev->le_pkts) { 29266ed58ec5SVille Tervo hdev->le_cnt += count; 29276ed58ec5SVille Tervo if (hdev->le_cnt > hdev->le_pkts) 29286ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 29296ed58ec5SVille Tervo } else { 29306ed58ec5SVille Tervo hdev->acl_cnt += count; 29316ed58ec5SVille Tervo if (hdev->acl_cnt > hdev->acl_pkts) 29326ed58ec5SVille Tervo hdev->acl_cnt = hdev->acl_pkts; 29336ed58ec5SVille Tervo } 2934f4280918SAndrei Emeltchenko break; 2935f4280918SAndrei Emeltchenko 2936f4280918SAndrei Emeltchenko case SCO_LINK: 293770f23020SAndrei Emeltchenko hdev->sco_cnt += count; 293870f23020SAndrei Emeltchenko if (hdev->sco_cnt > hdev->sco_pkts) 29395b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 2940f4280918SAndrei Emeltchenko break; 2941f4280918SAndrei Emeltchenko 2942f4280918SAndrei Emeltchenko default: 2943f4280918SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 2944f4280918SAndrei Emeltchenko break; 29451da177e4SLinus Torvalds } 29461da177e4SLinus Torvalds } 2947a9de9248SMarcel Holtmann 29483eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 29491da177e4SLinus Torvalds } 29501da177e4SLinus Torvalds 295176ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev, 295276ef7cf7SAndrei Emeltchenko __u16 handle) 295376ef7cf7SAndrei Emeltchenko { 295476ef7cf7SAndrei Emeltchenko struct hci_chan *chan; 295576ef7cf7SAndrei Emeltchenko 295676ef7cf7SAndrei Emeltchenko switch (hdev->dev_type) { 295776ef7cf7SAndrei Emeltchenko case HCI_BREDR: 295876ef7cf7SAndrei Emeltchenko return hci_conn_hash_lookup_handle(hdev, handle); 295976ef7cf7SAndrei Emeltchenko case HCI_AMP: 296076ef7cf7SAndrei Emeltchenko chan = hci_chan_lookup_handle(hdev, handle); 296176ef7cf7SAndrei Emeltchenko if (chan) 296276ef7cf7SAndrei Emeltchenko return chan->conn; 296376ef7cf7SAndrei Emeltchenko break; 296476ef7cf7SAndrei Emeltchenko default: 296576ef7cf7SAndrei Emeltchenko BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type); 296676ef7cf7SAndrei Emeltchenko break; 296776ef7cf7SAndrei Emeltchenko } 296876ef7cf7SAndrei Emeltchenko 296976ef7cf7SAndrei Emeltchenko return NULL; 297076ef7cf7SAndrei Emeltchenko } 297176ef7cf7SAndrei Emeltchenko 29726039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb) 297325e89e99SAndrei Emeltchenko { 297425e89e99SAndrei Emeltchenko struct hci_ev_num_comp_blocks *ev = (void *) skb->data; 297525e89e99SAndrei Emeltchenko int i; 297625e89e99SAndrei Emeltchenko 297725e89e99SAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) { 297825e89e99SAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 297925e89e99SAndrei Emeltchenko return; 298025e89e99SAndrei Emeltchenko } 298125e89e99SAndrei Emeltchenko 298225e89e99SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 298325e89e99SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_blocks_info)) { 298425e89e99SAndrei Emeltchenko BT_DBG("%s bad parameters", hdev->name); 298525e89e99SAndrei Emeltchenko return; 298625e89e99SAndrei Emeltchenko } 298725e89e99SAndrei Emeltchenko 298825e89e99SAndrei Emeltchenko BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks, 298925e89e99SAndrei Emeltchenko ev->num_hndl); 299025e89e99SAndrei Emeltchenko 299125e89e99SAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 299225e89e99SAndrei Emeltchenko struct hci_comp_blocks_info *info = &ev->handles[i]; 299376ef7cf7SAndrei Emeltchenko struct hci_conn *conn = NULL; 299425e89e99SAndrei Emeltchenko __u16 handle, block_count; 299525e89e99SAndrei Emeltchenko 299625e89e99SAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 299725e89e99SAndrei Emeltchenko block_count = __le16_to_cpu(info->blocks); 299825e89e99SAndrei Emeltchenko 299976ef7cf7SAndrei Emeltchenko conn = __hci_conn_lookup_handle(hdev, handle); 300025e89e99SAndrei Emeltchenko if (!conn) 300125e89e99SAndrei Emeltchenko continue; 300225e89e99SAndrei Emeltchenko 300325e89e99SAndrei Emeltchenko conn->sent -= block_count; 300425e89e99SAndrei Emeltchenko 300525e89e99SAndrei Emeltchenko switch (conn->type) { 300625e89e99SAndrei Emeltchenko case ACL_LINK: 3007bd1eb66bSAndrei Emeltchenko case AMP_LINK: 300825e89e99SAndrei Emeltchenko hdev->block_cnt += block_count; 300925e89e99SAndrei Emeltchenko if (hdev->block_cnt > hdev->num_blocks) 301025e89e99SAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 301125e89e99SAndrei Emeltchenko break; 301225e89e99SAndrei Emeltchenko 301325e89e99SAndrei Emeltchenko default: 301425e89e99SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 301525e89e99SAndrei Emeltchenko break; 301625e89e99SAndrei Emeltchenko } 301725e89e99SAndrei Emeltchenko } 301825e89e99SAndrei Emeltchenko 301925e89e99SAndrei Emeltchenko queue_work(hdev->workqueue, &hdev->tx_work); 302025e89e99SAndrei Emeltchenko } 302125e89e99SAndrei Emeltchenko 30226039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 30231da177e4SLinus Torvalds { 3024a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 302504837f64SMarcel Holtmann struct hci_conn *conn; 30261da177e4SLinus Torvalds 30279f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 30281da177e4SLinus Torvalds 30291da177e4SLinus Torvalds hci_dev_lock(hdev); 30301da177e4SLinus Torvalds 303104837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 303204837f64SMarcel Holtmann if (conn) { 303304837f64SMarcel Holtmann conn->mode = ev->mode; 303404837f64SMarcel Holtmann 30358fc9ced3SGustavo Padovan if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, 30368fc9ced3SGustavo Padovan &conn->flags)) { 303704837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 303858a681efSJohan Hedberg set_bit(HCI_CONN_POWER_SAVE, &conn->flags); 303904837f64SMarcel Holtmann else 304058a681efSJohan Hedberg clear_bit(HCI_CONN_POWER_SAVE, &conn->flags); 304104837f64SMarcel Holtmann } 3042e73439d8SMarcel Holtmann 304351a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 3044e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 304504837f64SMarcel Holtmann } 304604837f64SMarcel Holtmann 304704837f64SMarcel Holtmann hci_dev_unlock(hdev); 304804837f64SMarcel Holtmann } 304904837f64SMarcel Holtmann 30506039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 30511da177e4SLinus Torvalds { 3052052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 3053052b30b0SMarcel Holtmann struct hci_conn *conn; 3054052b30b0SMarcel Holtmann 3055a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 3056052b30b0SMarcel Holtmann 3057052b30b0SMarcel Holtmann hci_dev_lock(hdev); 3058052b30b0SMarcel Holtmann 3059052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 3060b6f98044SWaldemar Rymarkiewicz if (!conn) 3061b6f98044SWaldemar Rymarkiewicz goto unlock; 3062b6f98044SWaldemar Rymarkiewicz 3063b6f98044SWaldemar Rymarkiewicz if (conn->state == BT_CONNECTED) { 3064052b30b0SMarcel Holtmann hci_conn_hold(conn); 3065052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 306676a68ba0SDavid Herrmann hci_conn_drop(conn); 3067052b30b0SMarcel Holtmann } 3068052b30b0SMarcel Holtmann 3069a8b2d5c2SJohan Hedberg if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags)) 307003b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 307103b555e1SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 3072a8b2d5c2SJohan Hedberg else if (test_bit(HCI_MGMT, &hdev->dev_flags)) { 3073a770bb5aSWaldemar Rymarkiewicz u8 secure; 3074a770bb5aSWaldemar Rymarkiewicz 3075a770bb5aSWaldemar Rymarkiewicz if (conn->pending_sec_level == BT_SECURITY_HIGH) 3076a770bb5aSWaldemar Rymarkiewicz secure = 1; 3077a770bb5aSWaldemar Rymarkiewicz else 3078a770bb5aSWaldemar Rymarkiewicz secure = 0; 3079a770bb5aSWaldemar Rymarkiewicz 3080744cf19eSJohan Hedberg mgmt_pin_code_request(hdev, &ev->bdaddr, secure); 3081a770bb5aSWaldemar Rymarkiewicz } 3082980e1a53SJohan Hedberg 3083b6f98044SWaldemar Rymarkiewicz unlock: 3084052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 30851da177e4SLinus Torvalds } 30861da177e4SLinus Torvalds 30876039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 30881da177e4SLinus Torvalds { 308955ed8ca1SJohan Hedberg struct hci_ev_link_key_req *ev = (void *) skb->data; 309055ed8ca1SJohan Hedberg struct hci_cp_link_key_reply cp; 309155ed8ca1SJohan Hedberg struct hci_conn *conn; 309255ed8ca1SJohan Hedberg struct link_key *key; 309355ed8ca1SJohan Hedberg 3094a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 309555ed8ca1SJohan Hedberg 3096034cbea0SAndrei Emeltchenko if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 309755ed8ca1SJohan Hedberg return; 309855ed8ca1SJohan Hedberg 309955ed8ca1SJohan Hedberg hci_dev_lock(hdev); 310055ed8ca1SJohan Hedberg 310155ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, &ev->bdaddr); 310255ed8ca1SJohan Hedberg if (!key) { 31036ed93dc6SAndrei Emeltchenko BT_DBG("%s link key not found for %pMR", hdev->name, 31046ed93dc6SAndrei Emeltchenko &ev->bdaddr); 310555ed8ca1SJohan Hedberg goto not_found; 310655ed8ca1SJohan Hedberg } 310755ed8ca1SJohan Hedberg 31086ed93dc6SAndrei Emeltchenko BT_DBG("%s found key type %u for %pMR", hdev->name, key->type, 31096ed93dc6SAndrei Emeltchenko &ev->bdaddr); 311055ed8ca1SJohan Hedberg 311155ed8ca1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 311260b83f57SWaldemar Rymarkiewicz if (conn) { 311366138ce8SMarcel Holtmann if ((key->type == HCI_LK_UNAUTH_COMBINATION_P192 || 311466138ce8SMarcel Holtmann key->type == HCI_LK_UNAUTH_COMBINATION_P256) && 3115807deac2SGustavo Padovan conn->auth_type != 0xff && (conn->auth_type & 0x01)) { 311655ed8ca1SJohan Hedberg BT_DBG("%s ignoring unauthenticated key", hdev->name); 311755ed8ca1SJohan Hedberg goto not_found; 311855ed8ca1SJohan Hedberg } 311955ed8ca1SJohan Hedberg 312060b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && 3121f3fb0b58SJohan Hedberg (conn->pending_sec_level == BT_SECURITY_HIGH || 3122f3fb0b58SJohan Hedberg conn->pending_sec_level == BT_SECURITY_FIPS)) { 31238fc9ced3SGustavo Padovan BT_DBG("%s ignoring key unauthenticated for high security", 31248fc9ced3SGustavo Padovan hdev->name); 312560b83f57SWaldemar Rymarkiewicz goto not_found; 312660b83f57SWaldemar Rymarkiewicz } 312760b83f57SWaldemar Rymarkiewicz 312860b83f57SWaldemar Rymarkiewicz conn->key_type = key->type; 312960b83f57SWaldemar Rymarkiewicz conn->pin_length = key->pin_len; 313060b83f57SWaldemar Rymarkiewicz } 313160b83f57SWaldemar Rymarkiewicz 313255ed8ca1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 31339b3b4460SAndrei Emeltchenko memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE); 313455ed8ca1SJohan Hedberg 313555ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 313655ed8ca1SJohan Hedberg 313755ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 313855ed8ca1SJohan Hedberg 313955ed8ca1SJohan Hedberg return; 314055ed8ca1SJohan Hedberg 314155ed8ca1SJohan Hedberg not_found: 314255ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 314355ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 31441da177e4SLinus Torvalds } 31451da177e4SLinus Torvalds 31466039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 31471da177e4SLinus Torvalds { 3148052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 3149052b30b0SMarcel Holtmann struct hci_conn *conn; 31507652ff6aSJohan Hedberg struct link_key *key; 31517652ff6aSJohan Hedberg bool persistent; 315255ed8ca1SJohan Hedberg u8 pin_len = 0; 3153052b30b0SMarcel Holtmann 3154a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 3155052b30b0SMarcel Holtmann 3156052b30b0SMarcel Holtmann hci_dev_lock(hdev); 3157052b30b0SMarcel Holtmann 3158052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 3159052b30b0SMarcel Holtmann if (conn) { 3160052b30b0SMarcel Holtmann hci_conn_hold(conn); 3161052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 3162980e1a53SJohan Hedberg pin_len = conn->pin_length; 316313d39315SWaldemar Rymarkiewicz 316413d39315SWaldemar Rymarkiewicz if (ev->key_type != HCI_LK_CHANGED_COMBINATION) 316513d39315SWaldemar Rymarkiewicz conn->key_type = ev->key_type; 316613d39315SWaldemar Rymarkiewicz 316776a68ba0SDavid Herrmann hci_conn_drop(conn); 3168052b30b0SMarcel Holtmann } 3169052b30b0SMarcel Holtmann 31707652ff6aSJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 31717652ff6aSJohan Hedberg goto unlock; 317255ed8ca1SJohan Hedberg 31737652ff6aSJohan Hedberg key = hci_add_link_key(hdev, conn, &ev->bdaddr, ev->link_key, 31747652ff6aSJohan Hedberg ev->key_type, pin_len, &persistent); 31757652ff6aSJohan Hedberg if (!key) 31767652ff6aSJohan Hedberg goto unlock; 31777652ff6aSJohan Hedberg 31787652ff6aSJohan Hedberg mgmt_new_link_key(hdev, key, persistent); 31797652ff6aSJohan Hedberg 31806d5650c4SJohan Hedberg /* Keep debug keys around only if the HCI_KEEP_DEBUG_KEYS flag 31816d5650c4SJohan Hedberg * is set. If it's not set simply remove the key from the kernel 31826d5650c4SJohan Hedberg * list (we've still notified user space about it but with 31836d5650c4SJohan Hedberg * store_hint being 0). 31846d5650c4SJohan Hedberg */ 31856d5650c4SJohan Hedberg if (key->type == HCI_LK_DEBUG_COMBINATION && 31866d5650c4SJohan Hedberg !test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags)) { 31876d5650c4SJohan Hedberg list_del(&key->list); 31886d5650c4SJohan Hedberg kfree(key); 31896d5650c4SJohan Hedberg } else if (conn) { 3190af6a9c32SJohan Hedberg if (persistent) 3191af6a9c32SJohan Hedberg clear_bit(HCI_CONN_FLUSH_KEY, &conn->flags); 3192af6a9c32SJohan Hedberg else 3193af6a9c32SJohan Hedberg set_bit(HCI_CONN_FLUSH_KEY, &conn->flags); 31946d5650c4SJohan Hedberg } 31957652ff6aSJohan Hedberg 31967652ff6aSJohan Hedberg unlock: 3197052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 31981da177e4SLinus Torvalds } 31991da177e4SLinus Torvalds 32006039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 320104837f64SMarcel Holtmann { 3202a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 320304837f64SMarcel Holtmann struct hci_conn *conn; 320404837f64SMarcel Holtmann 32059f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 320604837f64SMarcel Holtmann 320704837f64SMarcel Holtmann hci_dev_lock(hdev); 320804837f64SMarcel Holtmann 320904837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 32101da177e4SLinus Torvalds if (conn && !ev->status) { 32111da177e4SLinus Torvalds struct inquiry_entry *ie; 32121da177e4SLinus Torvalds 3213cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 3214cc11b9c1SAndrei Emeltchenko if (ie) { 32151da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 32161da177e4SLinus Torvalds ie->timestamp = jiffies; 32171da177e4SLinus Torvalds } 32181da177e4SLinus Torvalds } 32191da177e4SLinus Torvalds 32201da177e4SLinus Torvalds hci_dev_unlock(hdev); 32211da177e4SLinus Torvalds } 32221da177e4SLinus Torvalds 32236039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 3224a8746417SMarcel Holtmann { 3225a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 3226a8746417SMarcel Holtmann struct hci_conn *conn; 3227a8746417SMarcel Holtmann 32289f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 3229a8746417SMarcel Holtmann 3230a8746417SMarcel Holtmann hci_dev_lock(hdev); 3231a8746417SMarcel Holtmann 3232a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3233a8746417SMarcel Holtmann if (conn && !ev->status) 3234a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 3235a8746417SMarcel Holtmann 3236a8746417SMarcel Holtmann hci_dev_unlock(hdev); 3237a8746417SMarcel Holtmann } 3238a8746417SMarcel Holtmann 32396039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 324085a1e930SMarcel Holtmann { 3241a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 324285a1e930SMarcel Holtmann struct inquiry_entry *ie; 324385a1e930SMarcel Holtmann 324485a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 324585a1e930SMarcel Holtmann 324685a1e930SMarcel Holtmann hci_dev_lock(hdev); 324785a1e930SMarcel Holtmann 3248cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 3249cc11b9c1SAndrei Emeltchenko if (ie) { 325085a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 325185a1e930SMarcel Holtmann ie->timestamp = jiffies; 325285a1e930SMarcel Holtmann } 325385a1e930SMarcel Holtmann 325485a1e930SMarcel Holtmann hci_dev_unlock(hdev); 325585a1e930SMarcel Holtmann } 325685a1e930SMarcel Holtmann 32576039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, 3258807deac2SGustavo Padovan struct sk_buff *skb) 3259a9de9248SMarcel Holtmann { 3260a9de9248SMarcel Holtmann struct inquiry_data data; 3261a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 3262a9de9248SMarcel Holtmann 3263a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 3264a9de9248SMarcel Holtmann 3265a9de9248SMarcel Holtmann if (!num_rsp) 3266a9de9248SMarcel Holtmann return; 3267a9de9248SMarcel Holtmann 32681519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 32691519cc17SAndre Guedes return; 32701519cc17SAndre Guedes 3271a9de9248SMarcel Holtmann hci_dev_lock(hdev); 3272a9de9248SMarcel Holtmann 3273a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 3274138d22efSSzymon Janc struct inquiry_info_with_rssi_and_pscan_mode *info; 3275138d22efSSzymon Janc info = (void *) (skb->data + 1); 3276a9de9248SMarcel Holtmann 3277e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 3278af58925cSMarcel Holtmann u32 flags; 3279af58925cSMarcel Holtmann 3280a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 3281a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 3282a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 3283a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 3284a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 3285a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 3286a9de9248SMarcel Holtmann data.rssi = info->rssi; 328741a96212SMarcel Holtmann data.ssp_mode = 0x00; 32883175405bSJohan Hedberg 3289af58925cSMarcel Holtmann flags = hci_inquiry_cache_update(hdev, &data, false); 3290af58925cSMarcel Holtmann 329148264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 3292e17acd40SJohan Hedberg info->dev_class, info->rssi, 3293af58925cSMarcel Holtmann flags, NULL, 0, NULL, 0); 3294a9de9248SMarcel Holtmann } 3295a9de9248SMarcel Holtmann } else { 3296a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 3297a9de9248SMarcel Holtmann 3298e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 3299af58925cSMarcel Holtmann u32 flags; 3300af58925cSMarcel Holtmann 3301a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 3302a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 3303a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 3304a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 3305a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 3306a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 3307a9de9248SMarcel Holtmann data.rssi = info->rssi; 330841a96212SMarcel Holtmann data.ssp_mode = 0x00; 3309af58925cSMarcel Holtmann 3310af58925cSMarcel Holtmann flags = hci_inquiry_cache_update(hdev, &data, false); 3311af58925cSMarcel Holtmann 331248264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 3313e17acd40SJohan Hedberg info->dev_class, info->rssi, 3314af58925cSMarcel Holtmann flags, NULL, 0, NULL, 0); 3315a9de9248SMarcel Holtmann } 3316a9de9248SMarcel Holtmann } 3317a9de9248SMarcel Holtmann 3318a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 3319a9de9248SMarcel Holtmann } 3320a9de9248SMarcel Holtmann 33216039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev, 3322807deac2SGustavo Padovan struct sk_buff *skb) 3323a9de9248SMarcel Holtmann { 332441a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 332541a96212SMarcel Holtmann struct hci_conn *conn; 332641a96212SMarcel Holtmann 3327a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 332841a96212SMarcel Holtmann 332941a96212SMarcel Holtmann hci_dev_lock(hdev); 333041a96212SMarcel Holtmann 333141a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3332ccd556feSJohan Hedberg if (!conn) 3333ccd556feSJohan Hedberg goto unlock; 3334ccd556feSJohan Hedberg 3335cad718edSJohan Hedberg if (ev->page < HCI_MAX_PAGES) 3336cad718edSJohan Hedberg memcpy(conn->features[ev->page], ev->features, 8); 3337cad718edSJohan Hedberg 3338769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 333941a96212SMarcel Holtmann struct inquiry_entry *ie; 334041a96212SMarcel Holtmann 3341cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 3342cc11b9c1SAndrei Emeltchenko if (ie) 334302b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 334441a96212SMarcel Holtmann 3345bbb0eadaSJaganath Kanakkassery if (ev->features[0] & LMP_HOST_SSP) { 334658a681efSJohan Hedberg set_bit(HCI_CONN_SSP_ENABLED, &conn->flags); 3347bbb0eadaSJaganath Kanakkassery } else { 3348bbb0eadaSJaganath Kanakkassery /* It is mandatory by the Bluetooth specification that 3349bbb0eadaSJaganath Kanakkassery * Extended Inquiry Results are only used when Secure 3350bbb0eadaSJaganath Kanakkassery * Simple Pairing is enabled, but some devices violate 3351bbb0eadaSJaganath Kanakkassery * this. 3352bbb0eadaSJaganath Kanakkassery * 3353bbb0eadaSJaganath Kanakkassery * To make these devices work, the internal SSP 3354bbb0eadaSJaganath Kanakkassery * enabled flag needs to be cleared if the remote host 3355bbb0eadaSJaganath Kanakkassery * features do not indicate SSP support */ 3356bbb0eadaSJaganath Kanakkassery clear_bit(HCI_CONN_SSP_ENABLED, &conn->flags); 3357bbb0eadaSJaganath Kanakkassery } 3358eb9a8f3fSMarcel Holtmann 3359eb9a8f3fSMarcel Holtmann if (ev->features[0] & LMP_HOST_SC) 3360eb9a8f3fSMarcel Holtmann set_bit(HCI_CONN_SC_ENABLED, &conn->flags); 336141a96212SMarcel Holtmann } 336241a96212SMarcel Holtmann 3363ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 3364ccd556feSJohan Hedberg goto unlock; 3365ccd556feSJohan Hedberg 3366671267bfSJohan Hedberg if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { 3367127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 3368127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 3369127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 3370127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 3371127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 3372b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 3373b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 337408c79b61SJohan Hedberg conn->dst_type, 0, NULL, 0, 3375b644ba33SJohan Hedberg conn->dev_class); 3376392599b9SJohan Hedberg 3377127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 3378769be974SMarcel Holtmann conn->state = BT_CONNECTED; 3379769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 338076a68ba0SDavid Herrmann hci_conn_drop(conn); 3381769be974SMarcel Holtmann } 3382769be974SMarcel Holtmann 3383ccd556feSJohan Hedberg unlock: 338441a96212SMarcel Holtmann hci_dev_unlock(hdev); 3385a9de9248SMarcel Holtmann } 3386a9de9248SMarcel Holtmann 33876039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev, 3388807deac2SGustavo Padovan struct sk_buff *skb) 3389a9de9248SMarcel Holtmann { 3390b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 3391b6a0dc82SMarcel Holtmann struct hci_conn *conn; 3392b6a0dc82SMarcel Holtmann 33939f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 3394b6a0dc82SMarcel Holtmann 3395b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 3396b6a0dc82SMarcel Holtmann 3397b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 33989dc0a3afSMarcel Holtmann if (!conn) { 33999dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 34009dc0a3afSMarcel Holtmann goto unlock; 34019dc0a3afSMarcel Holtmann 34029dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 3403b6a0dc82SMarcel Holtmann if (!conn) 3404b6a0dc82SMarcel Holtmann goto unlock; 3405b6a0dc82SMarcel Holtmann 34069dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 34079dc0a3afSMarcel Holtmann } 34089dc0a3afSMarcel Holtmann 3409732547f9SMarcel Holtmann switch (ev->status) { 3410732547f9SMarcel Holtmann case 0x00: 3411732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 3412732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 3413732547f9SMarcel Holtmann 3414732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 3415732547f9SMarcel Holtmann break; 3416732547f9SMarcel Holtmann 341781218d20SNick Pelly case 0x10: /* Connection Accept Timeout */ 34181a4c958cSFrédéric Dalleau case 0x0d: /* Connection Rejected due to Limited Resources */ 3419705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 3420732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 34211038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 3422732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 342327539bc4SAndrew Earl case 0x20: /* Unsupported LMP Parameter value */ 34242dea632fSFrédéric Dalleau if (conn->out) { 3425efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 3426efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 34272dea632fSFrédéric Dalleau if (hci_setup_sync(conn, conn->link->handle)) 3428efc7688bSMarcel Holtmann goto unlock; 3429efc7688bSMarcel Holtmann } 3430732547f9SMarcel Holtmann /* fall through */ 3431efc7688bSMarcel Holtmann 3432732547f9SMarcel Holtmann default: 3433b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 3434732547f9SMarcel Holtmann break; 3435732547f9SMarcel Holtmann } 3436b6a0dc82SMarcel Holtmann 3437b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 3438b6a0dc82SMarcel Holtmann if (ev->status) 3439b6a0dc82SMarcel Holtmann hci_conn_del(conn); 3440b6a0dc82SMarcel Holtmann 3441b6a0dc82SMarcel Holtmann unlock: 3442b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 3443a9de9248SMarcel Holtmann } 3444a9de9248SMarcel Holtmann 3445efdcf8e3SMarcel Holtmann static inline size_t eir_get_length(u8 *eir, size_t eir_len) 3446efdcf8e3SMarcel Holtmann { 3447efdcf8e3SMarcel Holtmann size_t parsed = 0; 3448efdcf8e3SMarcel Holtmann 3449efdcf8e3SMarcel Holtmann while (parsed < eir_len) { 3450efdcf8e3SMarcel Holtmann u8 field_len = eir[0]; 3451efdcf8e3SMarcel Holtmann 3452efdcf8e3SMarcel Holtmann if (field_len == 0) 3453efdcf8e3SMarcel Holtmann return parsed; 3454efdcf8e3SMarcel Holtmann 3455efdcf8e3SMarcel Holtmann parsed += field_len + 1; 3456efdcf8e3SMarcel Holtmann eir += field_len + 1; 3457efdcf8e3SMarcel Holtmann } 3458efdcf8e3SMarcel Holtmann 3459efdcf8e3SMarcel Holtmann return eir_len; 3460efdcf8e3SMarcel Holtmann } 3461efdcf8e3SMarcel Holtmann 34626039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, 3463807deac2SGustavo Padovan struct sk_buff *skb) 3464a9de9248SMarcel Holtmann { 3465a9de9248SMarcel Holtmann struct inquiry_data data; 3466a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 3467a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 34689d939d94SVishal Agarwal size_t eir_len; 3469a9de9248SMarcel Holtmann 3470a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 3471a9de9248SMarcel Holtmann 3472a9de9248SMarcel Holtmann if (!num_rsp) 3473a9de9248SMarcel Holtmann return; 3474a9de9248SMarcel Holtmann 34751519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 34761519cc17SAndre Guedes return; 34771519cc17SAndre Guedes 3478a9de9248SMarcel Holtmann hci_dev_lock(hdev); 3479a9de9248SMarcel Holtmann 3480e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 3481af58925cSMarcel Holtmann u32 flags; 3482af58925cSMarcel Holtmann bool name_known; 3483561aafbcSJohan Hedberg 3484a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 3485a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 3486a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 3487a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 3488a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 3489a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 3490a9de9248SMarcel Holtmann data.rssi = info->rssi; 349141a96212SMarcel Holtmann data.ssp_mode = 0x01; 3492561aafbcSJohan Hedberg 3493a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 34944ddb1930SJohan Hedberg name_known = eir_has_data_type(info->data, 34954ddb1930SJohan Hedberg sizeof(info->data), 34964ddb1930SJohan Hedberg EIR_NAME_COMPLETE); 3497561aafbcSJohan Hedberg else 3498561aafbcSJohan Hedberg name_known = true; 3499561aafbcSJohan Hedberg 3500af58925cSMarcel Holtmann flags = hci_inquiry_cache_update(hdev, &data, name_known); 3501af58925cSMarcel Holtmann 35029d939d94SVishal Agarwal eir_len = eir_get_length(info->data, sizeof(info->data)); 3503af58925cSMarcel Holtmann 350448264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 3505af58925cSMarcel Holtmann info->dev_class, info->rssi, 3506af58925cSMarcel Holtmann flags, info->data, eir_len, NULL, 0); 3507a9de9248SMarcel Holtmann } 3508a9de9248SMarcel Holtmann 3509a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 3510a9de9248SMarcel Holtmann } 3511a9de9248SMarcel Holtmann 35121c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev, 35131c2e0041SJohan Hedberg struct sk_buff *skb) 35141c2e0041SJohan Hedberg { 35151c2e0041SJohan Hedberg struct hci_ev_key_refresh_complete *ev = (void *) skb->data; 35161c2e0041SJohan Hedberg struct hci_conn *conn; 35171c2e0041SJohan Hedberg 35189f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status, 35191c2e0041SJohan Hedberg __le16_to_cpu(ev->handle)); 35201c2e0041SJohan Hedberg 35211c2e0041SJohan Hedberg hci_dev_lock(hdev); 35221c2e0041SJohan Hedberg 35231c2e0041SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 35241c2e0041SJohan Hedberg if (!conn) 35251c2e0041SJohan Hedberg goto unlock; 35261c2e0041SJohan Hedberg 35279eb1fbfaSJohan Hedberg /* For BR/EDR the necessary steps are taken through the 35289eb1fbfaSJohan Hedberg * auth_complete event. 35299eb1fbfaSJohan Hedberg */ 35309eb1fbfaSJohan Hedberg if (conn->type != LE_LINK) 35319eb1fbfaSJohan Hedberg goto unlock; 35329eb1fbfaSJohan Hedberg 35331c2e0041SJohan Hedberg if (!ev->status) 35341c2e0041SJohan Hedberg conn->sec_level = conn->pending_sec_level; 35351c2e0041SJohan Hedberg 35361c2e0041SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 35371c2e0041SJohan Hedberg 35381c2e0041SJohan Hedberg if (ev->status && conn->state == BT_CONNECTED) { 3539bed71748SAndre Guedes hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); 354076a68ba0SDavid Herrmann hci_conn_drop(conn); 35411c2e0041SJohan Hedberg goto unlock; 35421c2e0041SJohan Hedberg } 35431c2e0041SJohan Hedberg 35441c2e0041SJohan Hedberg if (conn->state == BT_CONFIG) { 35451c2e0041SJohan Hedberg if (!ev->status) 35461c2e0041SJohan Hedberg conn->state = BT_CONNECTED; 35471c2e0041SJohan Hedberg 35481c2e0041SJohan Hedberg hci_proto_connect_cfm(conn, ev->status); 354976a68ba0SDavid Herrmann hci_conn_drop(conn); 35501c2e0041SJohan Hedberg } else { 35511c2e0041SJohan Hedberg hci_auth_cfm(conn, ev->status); 35521c2e0041SJohan Hedberg 35531c2e0041SJohan Hedberg hci_conn_hold(conn); 35541c2e0041SJohan Hedberg conn->disc_timeout = HCI_DISCONN_TIMEOUT; 355576a68ba0SDavid Herrmann hci_conn_drop(conn); 35561c2e0041SJohan Hedberg } 35571c2e0041SJohan Hedberg 35581c2e0041SJohan Hedberg unlock: 35591c2e0041SJohan Hedberg hci_dev_unlock(hdev); 35601c2e0041SJohan Hedberg } 35611c2e0041SJohan Hedberg 35626039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn) 356317fa4b9dSJohan Hedberg { 356417fa4b9dSJohan Hedberg /* If remote requests no-bonding follow that lead */ 3565acabae96SMikel Astiz if (conn->remote_auth == HCI_AT_NO_BONDING || 3566acabae96SMikel Astiz conn->remote_auth == HCI_AT_NO_BONDING_MITM) 356758797bf7SWaldemar Rymarkiewicz return conn->remote_auth | (conn->auth_type & 0x01); 356817fa4b9dSJohan Hedberg 3569b7f94c88SMikel Astiz /* If both remote and local have enough IO capabilities, require 3570b7f94c88SMikel Astiz * MITM protection 3571b7f94c88SMikel Astiz */ 3572b7f94c88SMikel Astiz if (conn->remote_cap != HCI_IO_NO_INPUT_OUTPUT && 3573b7f94c88SMikel Astiz conn->io_capability != HCI_IO_NO_INPUT_OUTPUT) 3574b7f94c88SMikel Astiz return conn->remote_auth | 0x01; 3575b7f94c88SMikel Astiz 35767e74170aSTimo Mueller /* No MITM protection possible so ignore remote requirement */ 35777e74170aSTimo Mueller return (conn->remote_auth & ~0x01) | (conn->auth_type & 0x01); 357817fa4b9dSJohan Hedberg } 357917fa4b9dSJohan Hedberg 35806039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 35810493684eSMarcel Holtmann { 35820493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 35830493684eSMarcel Holtmann struct hci_conn *conn; 35840493684eSMarcel Holtmann 35850493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 35860493684eSMarcel Holtmann 35870493684eSMarcel Holtmann hci_dev_lock(hdev); 35880493684eSMarcel Holtmann 35890493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 359003b555e1SJohan Hedberg if (!conn) 359103b555e1SJohan Hedberg goto unlock; 359203b555e1SJohan Hedberg 35930493684eSMarcel Holtmann hci_conn_hold(conn); 35940493684eSMarcel Holtmann 3595a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 359603b555e1SJohan Hedberg goto unlock; 359703b555e1SJohan Hedberg 3598a8b2d5c2SJohan Hedberg if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) || 359903b555e1SJohan Hedberg (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 360017fa4b9dSJohan Hedberg struct hci_cp_io_capability_reply cp; 360117fa4b9dSJohan Hedberg 360217fa4b9dSJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 36037a7f1e7cSHemant Gupta /* Change the IO capability from KeyboardDisplay 36047a7f1e7cSHemant Gupta * to DisplayYesNo as it is not supported by BT spec. */ 36057a7f1e7cSHemant Gupta cp.capability = (conn->io_capability == 0x04) ? 3606a767631aSMikel Astiz HCI_IO_DISPLAY_YESNO : conn->io_capability; 3607b7f94c88SMikel Astiz 3608b7f94c88SMikel Astiz /* If we are initiators, there is no remote information yet */ 3609b7f94c88SMikel Astiz if (conn->remote_auth == 0xff) { 3610b7f94c88SMikel Astiz cp.authentication = conn->auth_type; 36116fd6b915SMikel Astiz 3612b16c6604SMikel Astiz /* Request MITM protection if our IO caps allow it 36134ad51a75SJohan Hedberg * except for the no-bonding case. 36144ad51a75SJohan Hedberg * conn->auth_type is not updated here since 36154ad51a75SJohan Hedberg * that might cause the user confirmation to be 36164ad51a75SJohan Hedberg * rejected in case the remote doesn't have the 36174ad51a75SJohan Hedberg * IO capabilities for MITM. 3618b16c6604SMikel Astiz */ 36196fd6b915SMikel Astiz if (conn->io_capability != HCI_IO_NO_INPUT_OUTPUT && 3620b16c6604SMikel Astiz cp.authentication != HCI_AT_NO_BONDING) 36216fd6b915SMikel Astiz cp.authentication |= 0x01; 3622b7f94c88SMikel Astiz } else { 36237cbc9bd9SJohan Hedberg conn->auth_type = hci_get_auth_req(conn); 36247cbc9bd9SJohan Hedberg cp.authentication = conn->auth_type; 3625b7f94c88SMikel Astiz } 362617fa4b9dSJohan Hedberg 36278fc9ced3SGustavo Padovan if (hci_find_remote_oob_data(hdev, &conn->dst) && 36288fc9ced3SGustavo Padovan (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags))) 3629ce85ee13SSzymon Janc cp.oob_data = 0x01; 3630ce85ee13SSzymon Janc else 3631ce85ee13SSzymon Janc cp.oob_data = 0x00; 3632ce85ee13SSzymon Janc 363317fa4b9dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, 363417fa4b9dSJohan Hedberg sizeof(cp), &cp); 363503b555e1SJohan Hedberg } else { 363603b555e1SJohan Hedberg struct hci_cp_io_capability_neg_reply cp; 363703b555e1SJohan Hedberg 363803b555e1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 36399f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED; 364003b555e1SJohan Hedberg 364103b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 364203b555e1SJohan Hedberg sizeof(cp), &cp); 364303b555e1SJohan Hedberg } 364403b555e1SJohan Hedberg 364503b555e1SJohan Hedberg unlock: 364603b555e1SJohan Hedberg hci_dev_unlock(hdev); 364703b555e1SJohan Hedberg } 364803b555e1SJohan Hedberg 36496039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 365003b555e1SJohan Hedberg { 365103b555e1SJohan Hedberg struct hci_ev_io_capa_reply *ev = (void *) skb->data; 365203b555e1SJohan Hedberg struct hci_conn *conn; 365303b555e1SJohan Hedberg 365403b555e1SJohan Hedberg BT_DBG("%s", hdev->name); 365503b555e1SJohan Hedberg 365603b555e1SJohan Hedberg hci_dev_lock(hdev); 365703b555e1SJohan Hedberg 365803b555e1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 365903b555e1SJohan Hedberg if (!conn) 366003b555e1SJohan Hedberg goto unlock; 366103b555e1SJohan Hedberg 366203b555e1SJohan Hedberg conn->remote_cap = ev->capability; 366303b555e1SJohan Hedberg conn->remote_auth = ev->authentication; 366458a681efSJohan Hedberg if (ev->oob_data) 366558a681efSJohan Hedberg set_bit(HCI_CONN_REMOTE_OOB, &conn->flags); 366603b555e1SJohan Hedberg 366703b555e1SJohan Hedberg unlock: 36680493684eSMarcel Holtmann hci_dev_unlock(hdev); 36690493684eSMarcel Holtmann } 36700493684eSMarcel Holtmann 36716039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev, 3672a5c29683SJohan Hedberg struct sk_buff *skb) 3673a5c29683SJohan Hedberg { 3674a5c29683SJohan Hedberg struct hci_ev_user_confirm_req *ev = (void *) skb->data; 367555bc1a37SJohan Hedberg int loc_mitm, rem_mitm, confirm_hint = 0; 36767a828908SJohan Hedberg struct hci_conn *conn; 3677a5c29683SJohan Hedberg 3678a5c29683SJohan Hedberg BT_DBG("%s", hdev->name); 3679a5c29683SJohan Hedberg 3680a5c29683SJohan Hedberg hci_dev_lock(hdev); 3681a5c29683SJohan Hedberg 3682a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 36837a828908SJohan Hedberg goto unlock; 36847a828908SJohan Hedberg 36857a828908SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 36867a828908SJohan Hedberg if (!conn) 36877a828908SJohan Hedberg goto unlock; 36887a828908SJohan Hedberg 36897a828908SJohan Hedberg loc_mitm = (conn->auth_type & 0x01); 36907a828908SJohan Hedberg rem_mitm = (conn->remote_auth & 0x01); 36917a828908SJohan Hedberg 36927a828908SJohan Hedberg /* If we require MITM but the remote device can't provide that 36936fd6b915SMikel Astiz * (it has NoInputNoOutput) then reject the confirmation request 36946fd6b915SMikel Astiz */ 36956fd6b915SMikel Astiz if (loc_mitm && conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) { 36967a828908SJohan Hedberg BT_DBG("Rejecting request: remote device can't provide MITM"); 36977a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, 36987a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 36997a828908SJohan Hedberg goto unlock; 37007a828908SJohan Hedberg } 37017a828908SJohan Hedberg 37027a828908SJohan Hedberg /* If no side requires MITM protection; auto-accept */ 3703a767631aSMikel Astiz if ((!loc_mitm || conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) && 3704a767631aSMikel Astiz (!rem_mitm || conn->io_capability == HCI_IO_NO_INPUT_OUTPUT)) { 370555bc1a37SJohan Hedberg 370655bc1a37SJohan Hedberg /* If we're not the initiators request authorization to 370755bc1a37SJohan Hedberg * proceed from user space (mgmt_user_confirm with 3708ba15a58bSJohan Hedberg * confirm_hint set to 1). The exception is if neither 3709ba15a58bSJohan Hedberg * side had MITM in which case we do auto-accept. 3710ba15a58bSJohan Hedberg */ 3711ba15a58bSJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && 3712ba15a58bSJohan Hedberg (loc_mitm || rem_mitm)) { 371355bc1a37SJohan Hedberg BT_DBG("Confirming auto-accept as acceptor"); 371455bc1a37SJohan Hedberg confirm_hint = 1; 371555bc1a37SJohan Hedberg goto confirm; 371655bc1a37SJohan Hedberg } 371755bc1a37SJohan Hedberg 37189f61656aSJohan Hedberg BT_DBG("Auto-accept of user confirmation with %ums delay", 37199f61656aSJohan Hedberg hdev->auto_accept_delay); 37209f61656aSJohan Hedberg 37219f61656aSJohan Hedberg if (hdev->auto_accept_delay > 0) { 37229f61656aSJohan Hedberg int delay = msecs_to_jiffies(hdev->auto_accept_delay); 37237bc18d9dSJohan Hedberg queue_delayed_work(conn->hdev->workqueue, 37247bc18d9dSJohan Hedberg &conn->auto_accept_work, delay); 37259f61656aSJohan Hedberg goto unlock; 37269f61656aSJohan Hedberg } 37279f61656aSJohan Hedberg 37287a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, 37297a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 37307a828908SJohan Hedberg goto unlock; 37317a828908SJohan Hedberg } 37327a828908SJohan Hedberg 373355bc1a37SJohan Hedberg confirm: 373439adbffeSJohan Hedberg mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, 373539adbffeSJohan Hedberg le32_to_cpu(ev->passkey), confirm_hint); 3736a5c29683SJohan Hedberg 37377a828908SJohan Hedberg unlock: 3738a5c29683SJohan Hedberg hci_dev_unlock(hdev); 3739a5c29683SJohan Hedberg } 3740a5c29683SJohan Hedberg 37416039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev, 37421143d458SBrian Gix struct sk_buff *skb) 37431143d458SBrian Gix { 37441143d458SBrian Gix struct hci_ev_user_passkey_req *ev = (void *) skb->data; 37451143d458SBrian Gix 37461143d458SBrian Gix BT_DBG("%s", hdev->name); 37471143d458SBrian Gix 3748a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 3749272d90dfSJohan Hedberg mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); 37501143d458SBrian Gix } 37511143d458SBrian Gix 375292a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev, 375392a25256SJohan Hedberg struct sk_buff *skb) 375492a25256SJohan Hedberg { 375592a25256SJohan Hedberg struct hci_ev_user_passkey_notify *ev = (void *) skb->data; 375692a25256SJohan Hedberg struct hci_conn *conn; 375792a25256SJohan Hedberg 375892a25256SJohan Hedberg BT_DBG("%s", hdev->name); 375992a25256SJohan Hedberg 376092a25256SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 376192a25256SJohan Hedberg if (!conn) 376292a25256SJohan Hedberg return; 376392a25256SJohan Hedberg 376492a25256SJohan Hedberg conn->passkey_notify = __le32_to_cpu(ev->passkey); 376592a25256SJohan Hedberg conn->passkey_entered = 0; 376692a25256SJohan Hedberg 376792a25256SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 376892a25256SJohan Hedberg mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, 376992a25256SJohan Hedberg conn->dst_type, conn->passkey_notify, 377092a25256SJohan Hedberg conn->passkey_entered); 377192a25256SJohan Hedberg } 377292a25256SJohan Hedberg 377392a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 377492a25256SJohan Hedberg { 377592a25256SJohan Hedberg struct hci_ev_keypress_notify *ev = (void *) skb->data; 377692a25256SJohan Hedberg struct hci_conn *conn; 377792a25256SJohan Hedberg 377892a25256SJohan Hedberg BT_DBG("%s", hdev->name); 377992a25256SJohan Hedberg 378092a25256SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 378192a25256SJohan Hedberg if (!conn) 378292a25256SJohan Hedberg return; 378392a25256SJohan Hedberg 378492a25256SJohan Hedberg switch (ev->type) { 378592a25256SJohan Hedberg case HCI_KEYPRESS_STARTED: 378692a25256SJohan Hedberg conn->passkey_entered = 0; 378792a25256SJohan Hedberg return; 378892a25256SJohan Hedberg 378992a25256SJohan Hedberg case HCI_KEYPRESS_ENTERED: 379092a25256SJohan Hedberg conn->passkey_entered++; 379192a25256SJohan Hedberg break; 379292a25256SJohan Hedberg 379392a25256SJohan Hedberg case HCI_KEYPRESS_ERASED: 379492a25256SJohan Hedberg conn->passkey_entered--; 379592a25256SJohan Hedberg break; 379692a25256SJohan Hedberg 379792a25256SJohan Hedberg case HCI_KEYPRESS_CLEARED: 379892a25256SJohan Hedberg conn->passkey_entered = 0; 379992a25256SJohan Hedberg break; 380092a25256SJohan Hedberg 380192a25256SJohan Hedberg case HCI_KEYPRESS_COMPLETED: 380292a25256SJohan Hedberg return; 380392a25256SJohan Hedberg } 380492a25256SJohan Hedberg 380592a25256SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 380692a25256SJohan Hedberg mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, 380792a25256SJohan Hedberg conn->dst_type, conn->passkey_notify, 380892a25256SJohan Hedberg conn->passkey_entered); 380992a25256SJohan Hedberg } 381092a25256SJohan Hedberg 38116039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev, 3812807deac2SGustavo Padovan struct sk_buff *skb) 38130493684eSMarcel Holtmann { 38140493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 38150493684eSMarcel Holtmann struct hci_conn *conn; 38160493684eSMarcel Holtmann 38170493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 38180493684eSMarcel Holtmann 38190493684eSMarcel Holtmann hci_dev_lock(hdev); 38200493684eSMarcel Holtmann 38210493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 38222a611692SJohan Hedberg if (!conn) 38232a611692SJohan Hedberg goto unlock; 38242a611692SJohan Hedberg 38252a611692SJohan Hedberg /* To avoid duplicate auth_failed events to user space we check 38262a611692SJohan Hedberg * the HCI_CONN_AUTH_PEND flag which will be set if we 38272a611692SJohan Hedberg * initiated the authentication. A traditional auth_complete 38282a611692SJohan Hedberg * event gets always produced as initiator and is also mapped to 38292a611692SJohan Hedberg * the mgmt_auth_failed event */ 3830fa1bd918SMikel Astiz if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status) 3831bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 3832bab73cb6SJohan Hedberg ev->status); 38332a611692SJohan Hedberg 383476a68ba0SDavid Herrmann hci_conn_drop(conn); 38350493684eSMarcel Holtmann 38362a611692SJohan Hedberg unlock: 38370493684eSMarcel Holtmann hci_dev_unlock(hdev); 38380493684eSMarcel Holtmann } 38390493684eSMarcel Holtmann 38406039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev, 3841807deac2SGustavo Padovan struct sk_buff *skb) 384241a96212SMarcel Holtmann { 384341a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 384441a96212SMarcel Holtmann struct inquiry_entry *ie; 3845cad718edSJohan Hedberg struct hci_conn *conn; 384641a96212SMarcel Holtmann 384741a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 384841a96212SMarcel Holtmann 384941a96212SMarcel Holtmann hci_dev_lock(hdev); 385041a96212SMarcel Holtmann 3851cad718edSJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 3852cad718edSJohan Hedberg if (conn) 3853cad718edSJohan Hedberg memcpy(conn->features[1], ev->features, 8); 3854cad718edSJohan Hedberg 3855cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 3856cc11b9c1SAndrei Emeltchenko if (ie) 385702b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 385841a96212SMarcel Holtmann 385941a96212SMarcel Holtmann hci_dev_unlock(hdev); 386041a96212SMarcel Holtmann } 386141a96212SMarcel Holtmann 38626039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev, 38632763eda6SSzymon Janc struct sk_buff *skb) 38642763eda6SSzymon Janc { 38652763eda6SSzymon Janc struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; 38662763eda6SSzymon Janc struct oob_data *data; 38672763eda6SSzymon Janc 38682763eda6SSzymon Janc BT_DBG("%s", hdev->name); 38692763eda6SSzymon Janc 38702763eda6SSzymon Janc hci_dev_lock(hdev); 38712763eda6SSzymon Janc 3872a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 3873e1ba1f15SSzymon Janc goto unlock; 3874e1ba1f15SSzymon Janc 38752763eda6SSzymon Janc data = hci_find_remote_oob_data(hdev, &ev->bdaddr); 38762763eda6SSzymon Janc if (data) { 3877519ca9d0SMarcel Holtmann if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) { 3878519ca9d0SMarcel Holtmann struct hci_cp_remote_oob_ext_data_reply cp; 3879519ca9d0SMarcel Holtmann 3880519ca9d0SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 3881519ca9d0SMarcel Holtmann memcpy(cp.hash192, data->hash192, sizeof(cp.hash192)); 3882519ca9d0SMarcel Holtmann memcpy(cp.randomizer192, data->randomizer192, 3883519ca9d0SMarcel Holtmann sizeof(cp.randomizer192)); 3884519ca9d0SMarcel Holtmann memcpy(cp.hash256, data->hash256, sizeof(cp.hash256)); 3885519ca9d0SMarcel Holtmann memcpy(cp.randomizer256, data->randomizer256, 3886519ca9d0SMarcel Holtmann sizeof(cp.randomizer256)); 3887519ca9d0SMarcel Holtmann 3888519ca9d0SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_EXT_DATA_REPLY, 3889519ca9d0SMarcel Holtmann sizeof(cp), &cp); 3890519ca9d0SMarcel Holtmann } else { 38912763eda6SSzymon Janc struct hci_cp_remote_oob_data_reply cp; 38922763eda6SSzymon Janc 38932763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 3894519ca9d0SMarcel Holtmann memcpy(cp.hash, data->hash192, sizeof(cp.hash)); 3895519ca9d0SMarcel Holtmann memcpy(cp.randomizer, data->randomizer192, 3896519ca9d0SMarcel Holtmann sizeof(cp.randomizer)); 38972763eda6SSzymon Janc 3898519ca9d0SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, 3899519ca9d0SMarcel Holtmann sizeof(cp), &cp); 3900519ca9d0SMarcel Holtmann } 39012763eda6SSzymon Janc } else { 39022763eda6SSzymon Janc struct hci_cp_remote_oob_data_neg_reply cp; 39032763eda6SSzymon Janc 39042763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 3905519ca9d0SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, 3906519ca9d0SMarcel Holtmann sizeof(cp), &cp); 39072763eda6SSzymon Janc } 39082763eda6SSzymon Janc 3909e1ba1f15SSzymon Janc unlock: 39102763eda6SSzymon Janc hci_dev_unlock(hdev); 39112763eda6SSzymon Janc } 39122763eda6SSzymon Janc 3913d5e91192SAndrei Emeltchenko static void hci_phy_link_complete_evt(struct hci_dev *hdev, 3914d5e91192SAndrei Emeltchenko struct sk_buff *skb) 3915d5e91192SAndrei Emeltchenko { 3916d5e91192SAndrei Emeltchenko struct hci_ev_phy_link_complete *ev = (void *) skb->data; 3917d5e91192SAndrei Emeltchenko struct hci_conn *hcon, *bredr_hcon; 3918d5e91192SAndrei Emeltchenko 3919d5e91192SAndrei Emeltchenko BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle, 3920d5e91192SAndrei Emeltchenko ev->status); 3921d5e91192SAndrei Emeltchenko 3922d5e91192SAndrei Emeltchenko hci_dev_lock(hdev); 3923d5e91192SAndrei Emeltchenko 3924d5e91192SAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 3925d5e91192SAndrei Emeltchenko if (!hcon) { 3926d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 3927d5e91192SAndrei Emeltchenko return; 3928d5e91192SAndrei Emeltchenko } 3929d5e91192SAndrei Emeltchenko 3930d5e91192SAndrei Emeltchenko if (ev->status) { 3931d5e91192SAndrei Emeltchenko hci_conn_del(hcon); 3932d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 3933d5e91192SAndrei Emeltchenko return; 3934d5e91192SAndrei Emeltchenko } 3935d5e91192SAndrei Emeltchenko 3936d5e91192SAndrei Emeltchenko bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon; 3937d5e91192SAndrei Emeltchenko 3938d5e91192SAndrei Emeltchenko hcon->state = BT_CONNECTED; 3939d5e91192SAndrei Emeltchenko bacpy(&hcon->dst, &bredr_hcon->dst); 3940d5e91192SAndrei Emeltchenko 3941d5e91192SAndrei Emeltchenko hci_conn_hold(hcon); 3942d5e91192SAndrei Emeltchenko hcon->disc_timeout = HCI_DISCONN_TIMEOUT; 394376a68ba0SDavid Herrmann hci_conn_drop(hcon); 3944d5e91192SAndrei Emeltchenko 3945d5e91192SAndrei Emeltchenko hci_conn_add_sysfs(hcon); 3946d5e91192SAndrei Emeltchenko 3947cf70ff22SAndrei Emeltchenko amp_physical_cfm(bredr_hcon, hcon); 3948cf70ff22SAndrei Emeltchenko 3949d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 3950d5e91192SAndrei Emeltchenko } 3951d5e91192SAndrei Emeltchenko 395227695fb4SAndrei Emeltchenko static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 395327695fb4SAndrei Emeltchenko { 395427695fb4SAndrei Emeltchenko struct hci_ev_logical_link_complete *ev = (void *) skb->data; 395527695fb4SAndrei Emeltchenko struct hci_conn *hcon; 395627695fb4SAndrei Emeltchenko struct hci_chan *hchan; 395727695fb4SAndrei Emeltchenko struct amp_mgr *mgr; 395827695fb4SAndrei Emeltchenko 395927695fb4SAndrei Emeltchenko BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x", 396027695fb4SAndrei Emeltchenko hdev->name, le16_to_cpu(ev->handle), ev->phy_handle, 396127695fb4SAndrei Emeltchenko ev->status); 396227695fb4SAndrei Emeltchenko 396327695fb4SAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 396427695fb4SAndrei Emeltchenko if (!hcon) 396527695fb4SAndrei Emeltchenko return; 396627695fb4SAndrei Emeltchenko 396727695fb4SAndrei Emeltchenko /* Create AMP hchan */ 396827695fb4SAndrei Emeltchenko hchan = hci_chan_create(hcon); 396927695fb4SAndrei Emeltchenko if (!hchan) 397027695fb4SAndrei Emeltchenko return; 397127695fb4SAndrei Emeltchenko 397227695fb4SAndrei Emeltchenko hchan->handle = le16_to_cpu(ev->handle); 397327695fb4SAndrei Emeltchenko 397427695fb4SAndrei Emeltchenko BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan); 397527695fb4SAndrei Emeltchenko 397627695fb4SAndrei Emeltchenko mgr = hcon->amp_mgr; 397727695fb4SAndrei Emeltchenko if (mgr && mgr->bredr_chan) { 397827695fb4SAndrei Emeltchenko struct l2cap_chan *bredr_chan = mgr->bredr_chan; 397927695fb4SAndrei Emeltchenko 398027695fb4SAndrei Emeltchenko l2cap_chan_lock(bredr_chan); 398127695fb4SAndrei Emeltchenko 398227695fb4SAndrei Emeltchenko bredr_chan->conn->mtu = hdev->block_mtu; 398327695fb4SAndrei Emeltchenko l2cap_logical_cfm(bredr_chan, hchan, 0); 398427695fb4SAndrei Emeltchenko hci_conn_hold(hcon); 398527695fb4SAndrei Emeltchenko 398627695fb4SAndrei Emeltchenko l2cap_chan_unlock(bredr_chan); 398727695fb4SAndrei Emeltchenko } 398827695fb4SAndrei Emeltchenko } 398927695fb4SAndrei Emeltchenko 3990606e2a10SAndrei Emeltchenko static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev, 3991606e2a10SAndrei Emeltchenko struct sk_buff *skb) 3992606e2a10SAndrei Emeltchenko { 3993606e2a10SAndrei Emeltchenko struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data; 3994606e2a10SAndrei Emeltchenko struct hci_chan *hchan; 3995606e2a10SAndrei Emeltchenko 3996606e2a10SAndrei Emeltchenko BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name, 3997606e2a10SAndrei Emeltchenko le16_to_cpu(ev->handle), ev->status); 3998606e2a10SAndrei Emeltchenko 3999606e2a10SAndrei Emeltchenko if (ev->status) 4000606e2a10SAndrei Emeltchenko return; 4001606e2a10SAndrei Emeltchenko 4002606e2a10SAndrei Emeltchenko hci_dev_lock(hdev); 4003606e2a10SAndrei Emeltchenko 4004606e2a10SAndrei Emeltchenko hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle)); 4005606e2a10SAndrei Emeltchenko if (!hchan) 4006606e2a10SAndrei Emeltchenko goto unlock; 4007606e2a10SAndrei Emeltchenko 4008606e2a10SAndrei Emeltchenko amp_destroy_logical_link(hchan, ev->reason); 4009606e2a10SAndrei Emeltchenko 4010606e2a10SAndrei Emeltchenko unlock: 4011606e2a10SAndrei Emeltchenko hci_dev_unlock(hdev); 4012606e2a10SAndrei Emeltchenko } 4013606e2a10SAndrei Emeltchenko 40149eef6b3aSAndrei Emeltchenko static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev, 40159eef6b3aSAndrei Emeltchenko struct sk_buff *skb) 40169eef6b3aSAndrei Emeltchenko { 40179eef6b3aSAndrei Emeltchenko struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data; 40189eef6b3aSAndrei Emeltchenko struct hci_conn *hcon; 40199eef6b3aSAndrei Emeltchenko 40209eef6b3aSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 40219eef6b3aSAndrei Emeltchenko 40229eef6b3aSAndrei Emeltchenko if (ev->status) 40239eef6b3aSAndrei Emeltchenko return; 40249eef6b3aSAndrei Emeltchenko 40259eef6b3aSAndrei Emeltchenko hci_dev_lock(hdev); 40269eef6b3aSAndrei Emeltchenko 40279eef6b3aSAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 40289eef6b3aSAndrei Emeltchenko if (hcon) { 40299eef6b3aSAndrei Emeltchenko hcon->state = BT_CLOSED; 40309eef6b3aSAndrei Emeltchenko hci_conn_del(hcon); 40319eef6b3aSAndrei Emeltchenko } 40329eef6b3aSAndrei Emeltchenko 40339eef6b3aSAndrei Emeltchenko hci_dev_unlock(hdev); 40349eef6b3aSAndrei Emeltchenko } 40359eef6b3aSAndrei Emeltchenko 40366039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 4037fcd89c09SVille Tervo { 4038fcd89c09SVille Tervo struct hci_ev_le_conn_complete *ev = (void *) skb->data; 4039fcd89c09SVille Tervo struct hci_conn *conn; 404068d6f6deSJohan Hedberg struct smp_irk *irk; 4041fcd89c09SVille Tervo 40429f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 4043fcd89c09SVille Tervo 4044fcd89c09SVille Tervo hci_dev_lock(hdev); 4045fcd89c09SVille Tervo 40464f72b329SAndrzej Kaczmarek conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); 4047b62f328bSVille Tervo if (!conn) { 4048b62f328bSVille Tervo conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); 4049b62f328bSVille Tervo if (!conn) { 4050b62f328bSVille Tervo BT_ERR("No memory for new connection"); 4051230fd16aSAndre Guedes goto unlock; 4052b62f328bSVille Tervo } 405329b7988aSAndre Guedes 405429b7988aSAndre Guedes conn->dst_type = ev->bdaddr_type; 4055b9b343d2SAndre Guedes 4056b9b343d2SAndre Guedes if (ev->role == LE_CONN_ROLE_MASTER) { 4057b9b343d2SAndre Guedes conn->out = true; 40584dae2798SJohan Hedberg set_bit(HCI_CONN_MASTER, &conn->flags); 4059b9b343d2SAndre Guedes } 4060cb1d68f7SJohan Hedberg 4061cb1d68f7SJohan Hedberg /* If we didn't have a hci_conn object previously 4062cb1d68f7SJohan Hedberg * but we're in master role this must be something 4063cb1d68f7SJohan Hedberg * initiated using a white list. Since white list based 4064cb1d68f7SJohan Hedberg * connections are not "first class citizens" we don't 4065cb1d68f7SJohan Hedberg * have full tracking of them. Therefore, we go ahead 4066cb1d68f7SJohan Hedberg * with a "best effort" approach of determining the 4067cb1d68f7SJohan Hedberg * initiator address based on the HCI_PRIVACY flag. 4068cb1d68f7SJohan Hedberg */ 4069cb1d68f7SJohan Hedberg if (conn->out) { 4070cb1d68f7SJohan Hedberg conn->resp_addr_type = ev->bdaddr_type; 4071cb1d68f7SJohan Hedberg bacpy(&conn->resp_addr, &ev->bdaddr); 4072cb1d68f7SJohan Hedberg if (test_bit(HCI_PRIVACY, &hdev->dev_flags)) { 4073cb1d68f7SJohan Hedberg conn->init_addr_type = ADDR_LE_DEV_RANDOM; 4074cb1d68f7SJohan Hedberg bacpy(&conn->init_addr, &hdev->rpa); 4075cb1d68f7SJohan Hedberg } else { 4076cb1d68f7SJohan Hedberg hci_copy_identity_address(hdev, 4077cb1d68f7SJohan Hedberg &conn->init_addr, 4078cb1d68f7SJohan Hedberg &conn->init_addr_type); 4079cb1d68f7SJohan Hedberg } 408080c24ab8SJohan Hedberg } 4081cb1d68f7SJohan Hedberg } else { 408280c24ab8SJohan Hedberg cancel_delayed_work(&conn->le_conn_timeout); 408380c24ab8SJohan Hedberg } 408480c24ab8SJohan Hedberg 408580c24ab8SJohan Hedberg if (!conn->out) { 4086cb1d68f7SJohan Hedberg /* Set the responder (our side) address type based on 4087cb1d68f7SJohan Hedberg * the advertising address type. 4088cb1d68f7SJohan Hedberg */ 4089cb1d68f7SJohan Hedberg conn->resp_addr_type = hdev->adv_addr_type; 4090cb1d68f7SJohan Hedberg if (hdev->adv_addr_type == ADDR_LE_DEV_RANDOM) 4091cb1d68f7SJohan Hedberg bacpy(&conn->resp_addr, &hdev->random_addr); 4092cb1d68f7SJohan Hedberg else 4093cb1d68f7SJohan Hedberg bacpy(&conn->resp_addr, &hdev->bdaddr); 4094cb1d68f7SJohan Hedberg 4095cb1d68f7SJohan Hedberg conn->init_addr_type = ev->bdaddr_type; 4096cb1d68f7SJohan Hedberg bacpy(&conn->init_addr, &ev->bdaddr); 4097a720d735SMarcel Holtmann 4098a720d735SMarcel Holtmann /* For incoming connections, set the default minimum 4099a720d735SMarcel Holtmann * and maximum connection interval. They will be used 4100a720d735SMarcel Holtmann * to check if the parameters are in range and if not 4101a720d735SMarcel Holtmann * trigger the connection update procedure. 4102a720d735SMarcel Holtmann */ 4103a720d735SMarcel Holtmann conn->le_conn_min_interval = hdev->le_conn_min_interval; 4104a720d735SMarcel Holtmann conn->le_conn_max_interval = hdev->le_conn_max_interval; 4105cb1d68f7SJohan Hedberg } 41067be2edbbSJohan Hedberg 4107edb4b466SMarcel Holtmann /* Lookup the identity address from the stored connection 4108edb4b466SMarcel Holtmann * address and address type. 4109edb4b466SMarcel Holtmann * 4110edb4b466SMarcel Holtmann * When establishing connections to an identity address, the 4111edb4b466SMarcel Holtmann * connection procedure will store the resolvable random 4112edb4b466SMarcel Holtmann * address first. Now if it can be converted back into the 4113edb4b466SMarcel Holtmann * identity address, start using the identity address from 4114edb4b466SMarcel Holtmann * now on. 4115edb4b466SMarcel Holtmann */ 4116edb4b466SMarcel Holtmann irk = hci_get_irk(hdev, &conn->dst, conn->dst_type); 411768d6f6deSJohan Hedberg if (irk) { 411868d6f6deSJohan Hedberg bacpy(&conn->dst, &irk->bdaddr); 411968d6f6deSJohan Hedberg conn->dst_type = irk->addr_type; 412068d6f6deSJohan Hedberg } 412168d6f6deSJohan Hedberg 4122cd17decbSAndre Guedes if (ev->status) { 412306c053fbSAndre Guedes hci_le_conn_failed(conn, ev->status); 4124cd17decbSAndre Guedes goto unlock; 4125cd17decbSAndre Guedes } 4126cd17decbSAndre Guedes 4127b644ba33SJohan Hedberg if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 412801fdb0fcSMarcel Holtmann mgmt_device_connected(hdev, &conn->dst, conn->type, 412995b23582SSzymon Janc conn->dst_type, 0, NULL, 0, NULL); 413083bc71b4SVinicius Costa Gomes 41317b5c0d52SVinicius Costa Gomes conn->sec_level = BT_SECURITY_LOW; 4132fcd89c09SVille Tervo conn->handle = __le16_to_cpu(ev->handle); 4133fcd89c09SVille Tervo conn->state = BT_CONNECTED; 4134fcd89c09SVille Tervo 4135e04fde60SMarcel Holtmann conn->le_conn_interval = le16_to_cpu(ev->interval); 4136e04fde60SMarcel Holtmann conn->le_conn_latency = le16_to_cpu(ev->latency); 4137e04fde60SMarcel Holtmann conn->le_supv_timeout = le16_to_cpu(ev->supervision_timeout); 4138e04fde60SMarcel Holtmann 4139fcd89c09SVille Tervo hci_conn_add_sysfs(conn); 4140fcd89c09SVille Tervo 4141fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 4142fcd89c09SVille Tervo 4143a4790dbdSAndre Guedes hci_pend_le_conn_del(hdev, &conn->dst, conn->dst_type); 4144a4790dbdSAndre Guedes 4145fcd89c09SVille Tervo unlock: 4146fcd89c09SVille Tervo hci_dev_unlock(hdev); 4147fcd89c09SVille Tervo } 4148fcd89c09SVille Tervo 41491855d92dSMarcel Holtmann static void hci_le_conn_update_complete_evt(struct hci_dev *hdev, 41501855d92dSMarcel Holtmann struct sk_buff *skb) 41511855d92dSMarcel Holtmann { 41521855d92dSMarcel Holtmann struct hci_ev_le_conn_update_complete *ev = (void *) skb->data; 41531855d92dSMarcel Holtmann struct hci_conn *conn; 41541855d92dSMarcel Holtmann 41551855d92dSMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 41561855d92dSMarcel Holtmann 41571855d92dSMarcel Holtmann if (ev->status) 41581855d92dSMarcel Holtmann return; 41591855d92dSMarcel Holtmann 41601855d92dSMarcel Holtmann hci_dev_lock(hdev); 41611855d92dSMarcel Holtmann 41621855d92dSMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 41631855d92dSMarcel Holtmann if (conn) { 41641855d92dSMarcel Holtmann conn->le_conn_interval = le16_to_cpu(ev->interval); 41651855d92dSMarcel Holtmann conn->le_conn_latency = le16_to_cpu(ev->latency); 41661855d92dSMarcel Holtmann conn->le_supv_timeout = le16_to_cpu(ev->supervision_timeout); 41671855d92dSMarcel Holtmann } 41681855d92dSMarcel Holtmann 41691855d92dSMarcel Holtmann hci_dev_unlock(hdev); 41701855d92dSMarcel Holtmann } 41711855d92dSMarcel Holtmann 4172a4790dbdSAndre Guedes /* This function requires the caller holds hdev->lock */ 4173a4790dbdSAndre Guedes static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr, 4174a4790dbdSAndre Guedes u8 addr_type) 4175a4790dbdSAndre Guedes { 4176a4790dbdSAndre Guedes struct hci_conn *conn; 41775b906a84SAndre Guedes struct smp_irk *irk; 41785b906a84SAndre Guedes 41795b906a84SAndre Guedes /* If this is a resolvable address, we should resolve it and then 41805b906a84SAndre Guedes * update address and address type variables. 41815b906a84SAndre Guedes */ 41825b906a84SAndre Guedes irk = hci_get_irk(hdev, addr, addr_type); 41835b906a84SAndre Guedes if (irk) { 41845b906a84SAndre Guedes addr = &irk->bdaddr; 41855b906a84SAndre Guedes addr_type = irk->addr_type; 41865b906a84SAndre Guedes } 4187a4790dbdSAndre Guedes 4188a4790dbdSAndre Guedes if (!hci_pend_le_conn_lookup(hdev, addr, addr_type)) 4189a4790dbdSAndre Guedes return; 4190a4790dbdSAndre Guedes 4191a4790dbdSAndre Guedes conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW, 4192a4790dbdSAndre Guedes HCI_AT_NO_BONDING); 4193a4790dbdSAndre Guedes if (!IS_ERR(conn)) 4194a4790dbdSAndre Guedes return; 4195a4790dbdSAndre Guedes 4196a4790dbdSAndre Guedes switch (PTR_ERR(conn)) { 4197a4790dbdSAndre Guedes case -EBUSY: 4198a4790dbdSAndre Guedes /* If hci_connect() returns -EBUSY it means there is already 4199a4790dbdSAndre Guedes * an LE connection attempt going on. Since controllers don't 4200a4790dbdSAndre Guedes * support more than one connection attempt at the time, we 4201a4790dbdSAndre Guedes * don't consider this an error case. 4202a4790dbdSAndre Guedes */ 4203a4790dbdSAndre Guedes break; 4204a4790dbdSAndre Guedes default: 4205a4790dbdSAndre Guedes BT_DBG("Failed to connect: err %ld", PTR_ERR(conn)); 4206a4790dbdSAndre Guedes } 4207a4790dbdSAndre Guedes } 4208a4790dbdSAndre Guedes 42094af605d8SJohan Hedberg static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, 42104af605d8SJohan Hedberg u8 bdaddr_type, s8 rssi, u8 *data, u8 len) 42114af605d8SJohan Hedberg { 4212b9a6328fSJohan Hedberg struct discovery_state *d = &hdev->discovery; 4213474ee066SJohan Hedberg bool match; 4214c70a7e4cSMarcel Holtmann u32 flags; 4215b9a6328fSJohan Hedberg 4216ca5c4be7SJohan Hedberg /* Passive scanning shouldn't trigger any device found events */ 4217ca5c4be7SJohan Hedberg if (hdev->le_scan_type == LE_SCAN_PASSIVE) { 42184af605d8SJohan Hedberg if (type == LE_ADV_IND || type == LE_ADV_DIRECT_IND) 42194af605d8SJohan Hedberg check_pending_le_conn(hdev, bdaddr, bdaddr_type); 4220ca5c4be7SJohan Hedberg return; 4221ca5c4be7SJohan Hedberg } 42224af605d8SJohan Hedberg 4223c70a7e4cSMarcel Holtmann /* When receiving non-connectable or scannable undirected 4224c70a7e4cSMarcel Holtmann * advertising reports, this means that the remote device is 4225c70a7e4cSMarcel Holtmann * not connectable and then clearly indicate this in the 4226c70a7e4cSMarcel Holtmann * device found event. 4227c70a7e4cSMarcel Holtmann * 4228c70a7e4cSMarcel Holtmann * When receiving a scan response, then there is no way to 4229c70a7e4cSMarcel Holtmann * know if the remote device is connectable or not. However 4230c70a7e4cSMarcel Holtmann * since scan responses are merged with a previously seen 4231c70a7e4cSMarcel Holtmann * advertising report, the flags field from that report 4232c70a7e4cSMarcel Holtmann * will be used. 4233c70a7e4cSMarcel Holtmann * 4234c70a7e4cSMarcel Holtmann * In the really unlikely case that a controller get confused 4235c70a7e4cSMarcel Holtmann * and just sends a scan response event, then it is marked as 4236c70a7e4cSMarcel Holtmann * not connectable as well. 4237c70a7e4cSMarcel Holtmann */ 4238c70a7e4cSMarcel Holtmann if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND || 4239c70a7e4cSMarcel Holtmann type == LE_ADV_SCAN_RSP) 4240c70a7e4cSMarcel Holtmann flags = MGMT_DEV_FOUND_NOT_CONNECTABLE; 4241c70a7e4cSMarcel Holtmann else 4242c70a7e4cSMarcel Holtmann flags = 0; 4243c70a7e4cSMarcel Holtmann 4244b9a6328fSJohan Hedberg /* If there's nothing pending either store the data from this 4245b9a6328fSJohan Hedberg * event or send an immediate device found event if the data 4246b9a6328fSJohan Hedberg * should not be stored for later. 4247b9a6328fSJohan Hedberg */ 4248b9a6328fSJohan Hedberg if (!has_pending_adv_report(hdev)) { 4249b9a6328fSJohan Hedberg /* If the report will trigger a SCAN_REQ store it for 4250b9a6328fSJohan Hedberg * later merging. 4251b9a6328fSJohan Hedberg */ 4252b9a6328fSJohan Hedberg if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) { 4253b9a6328fSJohan Hedberg store_pending_adv_report(hdev, bdaddr, bdaddr_type, 4254c70a7e4cSMarcel Holtmann rssi, flags, data, len); 4255b9a6328fSJohan Hedberg return; 4256b9a6328fSJohan Hedberg } 4257b9a6328fSJohan Hedberg 4258b9a6328fSJohan Hedberg mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL, 4259c70a7e4cSMarcel Holtmann rssi, flags, data, len, NULL, 0); 4260b9a6328fSJohan Hedberg return; 4261b9a6328fSJohan Hedberg } 4262b9a6328fSJohan Hedberg 4263474ee066SJohan Hedberg /* Check if the pending report is for the same device as the new one */ 4264474ee066SJohan Hedberg match = (!bacmp(bdaddr, &d->last_adv_addr) && 4265474ee066SJohan Hedberg bdaddr_type == d->last_adv_addr_type); 4266474ee066SJohan Hedberg 4267b9a6328fSJohan Hedberg /* If the pending data doesn't match this report or this isn't a 4268b9a6328fSJohan Hedberg * scan response (e.g. we got a duplicate ADV_IND) then force 4269b9a6328fSJohan Hedberg * sending of the pending data. 4270b9a6328fSJohan Hedberg */ 4271474ee066SJohan Hedberg if (type != LE_ADV_SCAN_RSP || !match) { 4272474ee066SJohan Hedberg /* Send out whatever is in the cache, but skip duplicates */ 4273474ee066SJohan Hedberg if (!match) 4274b9a6328fSJohan Hedberg mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK, 4275ff5cd29fSJohan Hedberg d->last_adv_addr_type, NULL, 4276c70a7e4cSMarcel Holtmann d->last_adv_rssi, d->last_adv_flags, 4277ff5cd29fSJohan Hedberg d->last_adv_data, 4278474ee066SJohan Hedberg d->last_adv_data_len, NULL, 0); 4279b9a6328fSJohan Hedberg 4280b9a6328fSJohan Hedberg /* If the new report will trigger a SCAN_REQ store it for 4281b9a6328fSJohan Hedberg * later merging. 4282b9a6328fSJohan Hedberg */ 4283b9a6328fSJohan Hedberg if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) { 4284b9a6328fSJohan Hedberg store_pending_adv_report(hdev, bdaddr, bdaddr_type, 4285c70a7e4cSMarcel Holtmann rssi, flags, data, len); 4286b9a6328fSJohan Hedberg return; 4287b9a6328fSJohan Hedberg } 4288b9a6328fSJohan Hedberg 4289b9a6328fSJohan Hedberg /* The advertising reports cannot be merged, so clear 4290b9a6328fSJohan Hedberg * the pending report and send out a device found event. 4291b9a6328fSJohan Hedberg */ 4292b9a6328fSJohan Hedberg clear_pending_adv_report(hdev); 42935c5b93e4SJohan Hedberg mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL, 4294c70a7e4cSMarcel Holtmann rssi, flags, data, len, NULL, 0); 4295b9a6328fSJohan Hedberg return; 4296b9a6328fSJohan Hedberg } 4297b9a6328fSJohan Hedberg 4298b9a6328fSJohan Hedberg /* If we get here we've got a pending ADV_IND or ADV_SCAN_IND and 4299b9a6328fSJohan Hedberg * the new event is a SCAN_RSP. We can therefore proceed with 4300b9a6328fSJohan Hedberg * sending a merged device found event. 4301b9a6328fSJohan Hedberg */ 4302b9a6328fSJohan Hedberg mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK, 4303c70a7e4cSMarcel Holtmann d->last_adv_addr_type, NULL, rssi, d->last_adv_flags, 430442bd6a56SMarcel Holtmann d->last_adv_data, d->last_adv_data_len, data, len); 4305b9a6328fSJohan Hedberg clear_pending_adv_report(hdev); 43064af605d8SJohan Hedberg } 43074af605d8SJohan Hedberg 43086039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) 43099aa04c91SAndre Guedes { 4310e95beb41SAndre Guedes u8 num_reports = skb->data[0]; 4311e95beb41SAndre Guedes void *ptr = &skb->data[1]; 43129aa04c91SAndre Guedes 4313a4790dbdSAndre Guedes hci_dev_lock(hdev); 4314a4790dbdSAndre Guedes 4315e95beb41SAndre Guedes while (num_reports--) { 4316e95beb41SAndre Guedes struct hci_ev_le_advertising_info *ev = ptr; 43174af605d8SJohan Hedberg s8 rssi; 4318a4790dbdSAndre Guedes 43193c9e9195SAndre Guedes rssi = ev->data[ev->length]; 43204af605d8SJohan Hedberg process_adv_report(hdev, ev->evt_type, &ev->bdaddr, 43214af605d8SJohan Hedberg ev->bdaddr_type, rssi, ev->data, ev->length); 43223c9e9195SAndre Guedes 4323e95beb41SAndre Guedes ptr += sizeof(*ev) + ev->length + 1; 43249aa04c91SAndre Guedes } 4325a4790dbdSAndre Guedes 4326a4790dbdSAndre Guedes hci_dev_unlock(hdev); 43279aa04c91SAndre Guedes } 43289aa04c91SAndre Guedes 43296039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 4330a7a595f6SVinicius Costa Gomes { 4331a7a595f6SVinicius Costa Gomes struct hci_ev_le_ltk_req *ev = (void *) skb->data; 4332a7a595f6SVinicius Costa Gomes struct hci_cp_le_ltk_reply cp; 4333bea710feSVinicius Costa Gomes struct hci_cp_le_ltk_neg_reply neg; 4334a7a595f6SVinicius Costa Gomes struct hci_conn *conn; 4335c9839a11SVinicius Costa Gomes struct smp_ltk *ltk; 4336a7a595f6SVinicius Costa Gomes 43379f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle)); 4338a7a595f6SVinicius Costa Gomes 4339a7a595f6SVinicius Costa Gomes hci_dev_lock(hdev); 4340a7a595f6SVinicius Costa Gomes 4341a7a595f6SVinicius Costa Gomes conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 4342bea710feSVinicius Costa Gomes if (conn == NULL) 4343bea710feSVinicius Costa Gomes goto not_found; 4344a7a595f6SVinicius Costa Gomes 4345fe39c7b2SMarcel Holtmann ltk = hci_find_ltk(hdev, ev->ediv, ev->rand, conn->out); 4346bea710feSVinicius Costa Gomes if (ltk == NULL) 4347bea710feSVinicius Costa Gomes goto not_found; 4348bea710feSVinicius Costa Gomes 4349bea710feSVinicius Costa Gomes memcpy(cp.ltk, ltk->val, sizeof(ltk->val)); 4350a7a595f6SVinicius Costa Gomes cp.handle = cpu_to_le16(conn->handle); 4351c9839a11SVinicius Costa Gomes 4352c9839a11SVinicius Costa Gomes if (ltk->authenticated) 4353f8776218SAndre Guedes conn->pending_sec_level = BT_SECURITY_HIGH; 4354f8776218SAndre Guedes else 4355f8776218SAndre Guedes conn->pending_sec_level = BT_SECURITY_MEDIUM; 4356a7a595f6SVinicius Costa Gomes 435789cbb4daSAndre Guedes conn->enc_key_size = ltk->enc_size; 4358a7a595f6SVinicius Costa Gomes 4359a7a595f6SVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); 4360a7a595f6SVinicius Costa Gomes 43615981a882SClaudio Takahasi /* Ref. Bluetooth Core SPEC pages 1975 and 2004. STK is a 43625981a882SClaudio Takahasi * temporary key used to encrypt a connection following 43635981a882SClaudio Takahasi * pairing. It is used during the Encrypted Session Setup to 43645981a882SClaudio Takahasi * distribute the keys. Later, security can be re-established 43655981a882SClaudio Takahasi * using a distributed LTK. 43665981a882SClaudio Takahasi */ 43672ceba539SJohan Hedberg if (ltk->type == SMP_STK) { 4368fe59a05fSJohan Hedberg set_bit(HCI_CONN_STK_ENCRYPT, &conn->flags); 4369c9839a11SVinicius Costa Gomes list_del(<k->list); 4370c9839a11SVinicius Costa Gomes kfree(ltk); 4371fe59a05fSJohan Hedberg } else { 4372fe59a05fSJohan Hedberg clear_bit(HCI_CONN_STK_ENCRYPT, &conn->flags); 4373c9839a11SVinicius Costa Gomes } 4374c9839a11SVinicius Costa Gomes 4375a7a595f6SVinicius Costa Gomes hci_dev_unlock(hdev); 4376bea710feSVinicius Costa Gomes 4377bea710feSVinicius Costa Gomes return; 4378bea710feSVinicius Costa Gomes 4379bea710feSVinicius Costa Gomes not_found: 4380bea710feSVinicius Costa Gomes neg.handle = ev->handle; 4381bea710feSVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg); 4382bea710feSVinicius Costa Gomes hci_dev_unlock(hdev); 4383a7a595f6SVinicius Costa Gomes } 4384a7a595f6SVinicius Costa Gomes 4385*8e75b46aSAndre Guedes static void send_conn_param_neg_reply(struct hci_dev *hdev, u16 handle, 4386*8e75b46aSAndre Guedes u8 reason) 4387*8e75b46aSAndre Guedes { 4388*8e75b46aSAndre Guedes struct hci_cp_le_conn_param_req_neg_reply cp; 4389*8e75b46aSAndre Guedes 4390*8e75b46aSAndre Guedes cp.handle = cpu_to_le16(handle); 4391*8e75b46aSAndre Guedes cp.reason = reason; 4392*8e75b46aSAndre Guedes 4393*8e75b46aSAndre Guedes hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY, sizeof(cp), 4394*8e75b46aSAndre Guedes &cp); 4395*8e75b46aSAndre Guedes } 4396*8e75b46aSAndre Guedes 4397*8e75b46aSAndre Guedes static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev, 4398*8e75b46aSAndre Guedes struct sk_buff *skb) 4399*8e75b46aSAndre Guedes { 4400*8e75b46aSAndre Guedes struct hci_ev_le_remote_conn_param_req *ev = (void *) skb->data; 4401*8e75b46aSAndre Guedes struct hci_cp_le_conn_param_req_reply cp; 4402*8e75b46aSAndre Guedes struct hci_conn *hcon; 4403*8e75b46aSAndre Guedes u16 handle, min, max, latency, timeout; 4404*8e75b46aSAndre Guedes 4405*8e75b46aSAndre Guedes handle = le16_to_cpu(ev->handle); 4406*8e75b46aSAndre Guedes min = le16_to_cpu(ev->interval_min); 4407*8e75b46aSAndre Guedes max = le16_to_cpu(ev->interval_max); 4408*8e75b46aSAndre Guedes latency = le16_to_cpu(ev->latency); 4409*8e75b46aSAndre Guedes timeout = le16_to_cpu(ev->timeout); 4410*8e75b46aSAndre Guedes 4411*8e75b46aSAndre Guedes hcon = hci_conn_hash_lookup_handle(hdev, handle); 4412*8e75b46aSAndre Guedes if (!hcon || hcon->state != BT_CONNECTED) 4413*8e75b46aSAndre Guedes return send_conn_param_neg_reply(hdev, handle, 4414*8e75b46aSAndre Guedes HCI_ERROR_UNKNOWN_CONN_ID); 4415*8e75b46aSAndre Guedes 4416*8e75b46aSAndre Guedes if (hci_check_conn_params(min, max, latency, timeout)) 4417*8e75b46aSAndre Guedes return send_conn_param_neg_reply(hdev, handle, 4418*8e75b46aSAndre Guedes HCI_ERROR_INVALID_LL_PARAMS); 4419*8e75b46aSAndre Guedes 4420*8e75b46aSAndre Guedes cp.handle = ev->handle; 4421*8e75b46aSAndre Guedes cp.interval_min = ev->interval_min; 4422*8e75b46aSAndre Guedes cp.interval_max = ev->interval_max; 4423*8e75b46aSAndre Guedes cp.latency = ev->latency; 4424*8e75b46aSAndre Guedes cp.timeout = ev->timeout; 4425*8e75b46aSAndre Guedes cp.min_ce_len = 0; 4426*8e75b46aSAndre Guedes cp.max_ce_len = 0; 4427*8e75b46aSAndre Guedes 4428*8e75b46aSAndre Guedes hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_REPLY, sizeof(cp), &cp); 4429*8e75b46aSAndre Guedes } 4430*8e75b46aSAndre Guedes 44316039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 4432fcd89c09SVille Tervo { 4433fcd89c09SVille Tervo struct hci_ev_le_meta *le_ev = (void *) skb->data; 4434fcd89c09SVille Tervo 4435fcd89c09SVille Tervo skb_pull(skb, sizeof(*le_ev)); 4436fcd89c09SVille Tervo 4437fcd89c09SVille Tervo switch (le_ev->subevent) { 4438fcd89c09SVille Tervo case HCI_EV_LE_CONN_COMPLETE: 4439fcd89c09SVille Tervo hci_le_conn_complete_evt(hdev, skb); 4440fcd89c09SVille Tervo break; 4441fcd89c09SVille Tervo 44421855d92dSMarcel Holtmann case HCI_EV_LE_CONN_UPDATE_COMPLETE: 44431855d92dSMarcel Holtmann hci_le_conn_update_complete_evt(hdev, skb); 44441855d92dSMarcel Holtmann break; 44451855d92dSMarcel Holtmann 44469aa04c91SAndre Guedes case HCI_EV_LE_ADVERTISING_REPORT: 44479aa04c91SAndre Guedes hci_le_adv_report_evt(hdev, skb); 44489aa04c91SAndre Guedes break; 44499aa04c91SAndre Guedes 4450a7a595f6SVinicius Costa Gomes case HCI_EV_LE_LTK_REQ: 4451a7a595f6SVinicius Costa Gomes hci_le_ltk_request_evt(hdev, skb); 4452a7a595f6SVinicius Costa Gomes break; 4453a7a595f6SVinicius Costa Gomes 4454*8e75b46aSAndre Guedes case HCI_EV_LE_REMOTE_CONN_PARAM_REQ: 4455*8e75b46aSAndre Guedes hci_le_remote_conn_param_req_evt(hdev, skb); 4456*8e75b46aSAndre Guedes break; 4457*8e75b46aSAndre Guedes 4458fcd89c09SVille Tervo default: 4459fcd89c09SVille Tervo break; 4460fcd89c09SVille Tervo } 4461fcd89c09SVille Tervo } 4462fcd89c09SVille Tervo 44639495b2eeSAndrei Emeltchenko static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb) 44649495b2eeSAndrei Emeltchenko { 44659495b2eeSAndrei Emeltchenko struct hci_ev_channel_selected *ev = (void *) skb->data; 44669495b2eeSAndrei Emeltchenko struct hci_conn *hcon; 44679495b2eeSAndrei Emeltchenko 44689495b2eeSAndrei Emeltchenko BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle); 44699495b2eeSAndrei Emeltchenko 44709495b2eeSAndrei Emeltchenko skb_pull(skb, sizeof(*ev)); 44719495b2eeSAndrei Emeltchenko 44729495b2eeSAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 44739495b2eeSAndrei Emeltchenko if (!hcon) 44749495b2eeSAndrei Emeltchenko return; 44759495b2eeSAndrei Emeltchenko 44769495b2eeSAndrei Emeltchenko amp_read_loc_assoc_final_data(hdev, hcon); 44779495b2eeSAndrei Emeltchenko } 44789495b2eeSAndrei Emeltchenko 44791da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 44801da177e4SLinus Torvalds { 4481a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 4482a9de9248SMarcel Holtmann __u8 event = hdr->evt; 44831da177e4SLinus Torvalds 4484b6ddb638SJohan Hedberg hci_dev_lock(hdev); 4485b6ddb638SJohan Hedberg 4486b6ddb638SJohan Hedberg /* Received events are (currently) only needed when a request is 4487b6ddb638SJohan Hedberg * ongoing so avoid unnecessary memory allocation. 4488b6ddb638SJohan Hedberg */ 4489b6ddb638SJohan Hedberg if (hdev->req_status == HCI_REQ_PEND) { 4490b6ddb638SJohan Hedberg kfree_skb(hdev->recv_evt); 4491b6ddb638SJohan Hedberg hdev->recv_evt = skb_clone(skb, GFP_KERNEL); 4492b6ddb638SJohan Hedberg } 4493b6ddb638SJohan Hedberg 4494b6ddb638SJohan Hedberg hci_dev_unlock(hdev); 4495b6ddb638SJohan Hedberg 44961da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 44971da177e4SLinus Torvalds 449802350a72SJohan Hedberg if (hdev->sent_cmd && bt_cb(hdev->sent_cmd)->req.event == event) { 4499c1f23a2bSJohannes Berg struct hci_command_hdr *cmd_hdr = (void *) hdev->sent_cmd->data; 4500c1f23a2bSJohannes Berg u16 opcode = __le16_to_cpu(cmd_hdr->opcode); 450102350a72SJohan Hedberg 450202350a72SJohan Hedberg hci_req_cmd_complete(hdev, opcode, 0); 450302350a72SJohan Hedberg } 450402350a72SJohan Hedberg 4505a9de9248SMarcel Holtmann switch (event) { 45061da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 45071da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 45081da177e4SLinus Torvalds break; 45091da177e4SLinus Torvalds 45101da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 45111da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 45121da177e4SLinus Torvalds break; 45131da177e4SLinus Torvalds 4514a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 4515a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 451621d9e30eSMarcel Holtmann break; 451721d9e30eSMarcel Holtmann 45181da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 45191da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 45201da177e4SLinus Torvalds break; 45211da177e4SLinus Torvalds 45221da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 45231da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 45241da177e4SLinus Torvalds break; 45251da177e4SLinus Torvalds 45261da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 45271da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 45281da177e4SLinus Torvalds break; 45291da177e4SLinus Torvalds 4530a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 4531a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 4532a9de9248SMarcel Holtmann break; 4533a9de9248SMarcel Holtmann 45341da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 45351da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 45361da177e4SLinus Torvalds break; 45371da177e4SLinus Torvalds 4538a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 4539a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 4540a9de9248SMarcel Holtmann break; 4541a9de9248SMarcel Holtmann 4542a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 4543a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 4544a9de9248SMarcel Holtmann break; 4545a9de9248SMarcel Holtmann 4546a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 4547a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 4548a9de9248SMarcel Holtmann break; 4549a9de9248SMarcel Holtmann 4550a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 4551a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 4552a9de9248SMarcel Holtmann break; 4553a9de9248SMarcel Holtmann 4554a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 4555a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 4556a9de9248SMarcel Holtmann break; 4557a9de9248SMarcel Holtmann 4558a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 4559a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 4560a9de9248SMarcel Holtmann break; 4561a9de9248SMarcel Holtmann 4562a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 4563a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 45641da177e4SLinus Torvalds break; 45651da177e4SLinus Torvalds 45661da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 45671da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 45681da177e4SLinus Torvalds break; 45691da177e4SLinus Torvalds 45701da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 45711da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 45721da177e4SLinus Torvalds break; 45731da177e4SLinus Torvalds 45741da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 45751da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 45761da177e4SLinus Torvalds break; 45771da177e4SLinus Torvalds 45781da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 45791da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 45801da177e4SLinus Torvalds break; 45811da177e4SLinus Torvalds 4582a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 4583a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 4584a8746417SMarcel Holtmann break; 4585a8746417SMarcel Holtmann 458685a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 458785a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 458885a1e930SMarcel Holtmann break; 458985a1e930SMarcel Holtmann 4590a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 4591a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 4592a9de9248SMarcel Holtmann break; 4593a9de9248SMarcel Holtmann 4594a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 4595a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 4596a9de9248SMarcel Holtmann break; 4597a9de9248SMarcel Holtmann 4598a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 4599a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 4600a9de9248SMarcel Holtmann break; 4601a9de9248SMarcel Holtmann 4602a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 4603a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 46041da177e4SLinus Torvalds break; 46051da177e4SLinus Torvalds 46061c2e0041SJohan Hedberg case HCI_EV_KEY_REFRESH_COMPLETE: 46071c2e0041SJohan Hedberg hci_key_refresh_complete_evt(hdev, skb); 46081c2e0041SJohan Hedberg break; 46091c2e0041SJohan Hedberg 46100493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 46110493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 46120493684eSMarcel Holtmann break; 46130493684eSMarcel Holtmann 461403b555e1SJohan Hedberg case HCI_EV_IO_CAPA_REPLY: 461503b555e1SJohan Hedberg hci_io_capa_reply_evt(hdev, skb); 461603b555e1SJohan Hedberg break; 461703b555e1SJohan Hedberg 4618a5c29683SJohan Hedberg case HCI_EV_USER_CONFIRM_REQUEST: 4619a5c29683SJohan Hedberg hci_user_confirm_request_evt(hdev, skb); 4620a5c29683SJohan Hedberg break; 4621a5c29683SJohan Hedberg 46221143d458SBrian Gix case HCI_EV_USER_PASSKEY_REQUEST: 46231143d458SBrian Gix hci_user_passkey_request_evt(hdev, skb); 46241143d458SBrian Gix break; 46251143d458SBrian Gix 462692a25256SJohan Hedberg case HCI_EV_USER_PASSKEY_NOTIFY: 462792a25256SJohan Hedberg hci_user_passkey_notify_evt(hdev, skb); 462892a25256SJohan Hedberg break; 462992a25256SJohan Hedberg 463092a25256SJohan Hedberg case HCI_EV_KEYPRESS_NOTIFY: 463192a25256SJohan Hedberg hci_keypress_notify_evt(hdev, skb); 463292a25256SJohan Hedberg break; 463392a25256SJohan Hedberg 46340493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 46350493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 46360493684eSMarcel Holtmann break; 46370493684eSMarcel Holtmann 463841a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 463941a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 464041a96212SMarcel Holtmann break; 464141a96212SMarcel Holtmann 4642fcd89c09SVille Tervo case HCI_EV_LE_META: 4643fcd89c09SVille Tervo hci_le_meta_evt(hdev, skb); 4644fcd89c09SVille Tervo break; 4645fcd89c09SVille Tervo 46469495b2eeSAndrei Emeltchenko case HCI_EV_CHANNEL_SELECTED: 46479495b2eeSAndrei Emeltchenko hci_chan_selected_evt(hdev, skb); 46489495b2eeSAndrei Emeltchenko break; 46499495b2eeSAndrei Emeltchenko 46502763eda6SSzymon Janc case HCI_EV_REMOTE_OOB_DATA_REQUEST: 46512763eda6SSzymon Janc hci_remote_oob_data_request_evt(hdev, skb); 46522763eda6SSzymon Janc break; 46532763eda6SSzymon Janc 4654d5e91192SAndrei Emeltchenko case HCI_EV_PHY_LINK_COMPLETE: 4655d5e91192SAndrei Emeltchenko hci_phy_link_complete_evt(hdev, skb); 4656d5e91192SAndrei Emeltchenko break; 4657d5e91192SAndrei Emeltchenko 465827695fb4SAndrei Emeltchenko case HCI_EV_LOGICAL_LINK_COMPLETE: 465927695fb4SAndrei Emeltchenko hci_loglink_complete_evt(hdev, skb); 466027695fb4SAndrei Emeltchenko break; 466127695fb4SAndrei Emeltchenko 4662606e2a10SAndrei Emeltchenko case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE: 4663606e2a10SAndrei Emeltchenko hci_disconn_loglink_complete_evt(hdev, skb); 4664606e2a10SAndrei Emeltchenko break; 4665606e2a10SAndrei Emeltchenko 46669eef6b3aSAndrei Emeltchenko case HCI_EV_DISCONN_PHY_LINK_COMPLETE: 46679eef6b3aSAndrei Emeltchenko hci_disconn_phylink_complete_evt(hdev, skb); 46689eef6b3aSAndrei Emeltchenko break; 46699eef6b3aSAndrei Emeltchenko 467025e89e99SAndrei Emeltchenko case HCI_EV_NUM_COMP_BLOCKS: 467125e89e99SAndrei Emeltchenko hci_num_comp_blocks_evt(hdev, skb); 467225e89e99SAndrei Emeltchenko break; 467325e89e99SAndrei Emeltchenko 46741da177e4SLinus Torvalds default: 46759f1db00cSAndrei Emeltchenko BT_DBG("%s event 0x%2.2x", hdev->name, event); 46761da177e4SLinus Torvalds break; 46771da177e4SLinus Torvalds } 46781da177e4SLinus Torvalds 46791da177e4SLinus Torvalds kfree_skb(skb); 46801da177e4SLinus Torvalds hdev->stat.evt_rx++; 46811da177e4SLinus Torvalds } 4682