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 278c520a59SGustavo Padovan #include <linux/export.h> 281da177e4SLinus Torvalds #include <asm/unaligned.h> 291da177e4SLinus Torvalds 301da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h> 311da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h> 321da177e4SLinus Torvalds 331da177e4SLinus Torvalds /* Handle HCI Event packets */ 341da177e4SLinus Torvalds 35a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb) 361da177e4SLinus Torvalds { 37a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 381da177e4SLinus Torvalds 399f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 401da177e4SLinus Torvalds 41e6d465cbSAndre Guedes if (status) { 42e6d465cbSAndre Guedes hci_dev_lock(hdev); 43e6d465cbSAndre Guedes mgmt_stop_discovery_failed(hdev, status); 44e6d465cbSAndre Guedes hci_dev_unlock(hdev); 45a9de9248SMarcel Holtmann return; 46e6d465cbSAndre Guedes } 471da177e4SLinus Torvalds 4889352e7dSAndre Guedes clear_bit(HCI_INQUIRY, &hdev->flags); 4989352e7dSAndre Guedes 5056e5cb86SJohan Hedberg hci_dev_lock(hdev); 51ff9ef578SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 5256e5cb86SJohan Hedberg hci_dev_unlock(hdev); 53a9de9248SMarcel Holtmann 5423bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status); 55a9de9248SMarcel Holtmann 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) 1061da177e4SLinus Torvalds conn->link_mode &= ~HCI_LM_MASTER; 1071da177e4SLinus Torvalds else 1081da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 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 18523bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status); 186e4e8e37cSMarcel Holtmann } 187e4e8e37cSMarcel Holtmann 188a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) 1891da177e4SLinus Torvalds { 190a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 191a9de9248SMarcel Holtmann 1929f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 193a9de9248SMarcel Holtmann 19410572132SGustavo F. Padovan clear_bit(HCI_RESET, &hdev->flags); 19510572132SGustavo F. Padovan 19623bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_RESET, status); 197d23264a8SAndre Guedes 198a297e97cSJohan Hedberg /* Reset all non-persistent flags */ 199ae854a70SAndre Guedes hdev->dev_flags &= ~(BIT(HCI_LE_SCAN) | BIT(HCI_PENDING_CLASS) | 200ae854a70SAndre Guedes BIT(HCI_PERIODIC_INQ)); 20169775ff6SAndre Guedes 20269775ff6SAndre Guedes hdev->discovery.state = DISCOVERY_STOPPED; 203a9de9248SMarcel Holtmann } 204a9de9248SMarcel Holtmann 205a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) 206a9de9248SMarcel Holtmann { 207a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 2081da177e4SLinus Torvalds void *sent; 2091da177e4SLinus Torvalds 2109f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 2111da177e4SLinus Torvalds 212a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); 2131da177e4SLinus Torvalds if (!sent) 214a9de9248SMarcel Holtmann return; 2151da177e4SLinus Torvalds 21656e5cb86SJohan Hedberg hci_dev_lock(hdev); 21756e5cb86SJohan Hedberg 218f51d5b24SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 219f51d5b24SJohan Hedberg mgmt_set_local_name_complete(hdev, sent, status); 22028cc7bdeSJohan Hedberg else if (!status) 22128cc7bdeSJohan Hedberg memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); 222f51d5b24SJohan Hedberg 22356e5cb86SJohan Hedberg hci_dev_unlock(hdev); 2243159d384SJohan Hedberg 2253159d384SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status); 226a9de9248SMarcel Holtmann } 227a9de9248SMarcel Holtmann 228a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) 229a9de9248SMarcel Holtmann { 230a9de9248SMarcel Holtmann struct hci_rp_read_local_name *rp = (void *) skb->data; 231a9de9248SMarcel Holtmann 2329f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 233a9de9248SMarcel Holtmann 234a9de9248SMarcel Holtmann if (rp->status) 235a9de9248SMarcel Holtmann return; 236a9de9248SMarcel Holtmann 237db99b5fcSJohan Hedberg if (test_bit(HCI_SETUP, &hdev->dev_flags)) 2381f6c6378SJohan Hedberg memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); 239a9de9248SMarcel Holtmann } 240a9de9248SMarcel Holtmann 241a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) 242a9de9248SMarcel Holtmann { 243a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 244a9de9248SMarcel Holtmann void *sent; 245a9de9248SMarcel Holtmann 2469f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 247a9de9248SMarcel Holtmann 248a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); 249a9de9248SMarcel Holtmann if (!sent) 250a9de9248SMarcel Holtmann return; 2511da177e4SLinus Torvalds 2521da177e4SLinus Torvalds if (!status) { 253a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 254a9de9248SMarcel Holtmann 2551da177e4SLinus Torvalds if (param == AUTH_ENABLED) 2561da177e4SLinus Torvalds set_bit(HCI_AUTH, &hdev->flags); 2571da177e4SLinus Torvalds else 2581da177e4SLinus Torvalds clear_bit(HCI_AUTH, &hdev->flags); 2591da177e4SLinus Torvalds } 260a9de9248SMarcel Holtmann 26133ef95edSJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 26233ef95edSJohan Hedberg mgmt_auth_enable_complete(hdev, status); 26333ef95edSJohan Hedberg 26423bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status); 265a9de9248SMarcel Holtmann } 2661da177e4SLinus Torvalds 267a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) 268a9de9248SMarcel Holtmann { 269a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 270a9de9248SMarcel Holtmann void *sent; 271a9de9248SMarcel Holtmann 2729f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 273a9de9248SMarcel Holtmann 274a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); 2751da177e4SLinus Torvalds if (!sent) 276a9de9248SMarcel Holtmann return; 2771da177e4SLinus Torvalds 2781da177e4SLinus Torvalds if (!status) { 279a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 280a9de9248SMarcel Holtmann 2811da177e4SLinus Torvalds if (param) 2821da177e4SLinus Torvalds set_bit(HCI_ENCRYPT, &hdev->flags); 2831da177e4SLinus Torvalds else 2841da177e4SLinus Torvalds clear_bit(HCI_ENCRYPT, &hdev->flags); 2851da177e4SLinus Torvalds } 286a9de9248SMarcel Holtmann 28723bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status); 2881da177e4SLinus Torvalds } 2891da177e4SLinus Torvalds 290a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) 291a9de9248SMarcel Holtmann { 29236f7fc7eSJohan Hedberg __u8 param, status = *((__u8 *) skb->data); 29336f7fc7eSJohan Hedberg int old_pscan, old_iscan; 294a9de9248SMarcel Holtmann void *sent; 2951da177e4SLinus Torvalds 2969f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 297a9de9248SMarcel Holtmann 298a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); 2991da177e4SLinus Torvalds if (!sent) 300a9de9248SMarcel Holtmann return; 3011da177e4SLinus Torvalds 30236f7fc7eSJohan Hedberg param = *((__u8 *) sent); 303a9de9248SMarcel Holtmann 30456e5cb86SJohan Hedberg hci_dev_lock(hdev); 30556e5cb86SJohan Hedberg 3062d7cee58SJohan Hedberg if (status != 0) { 307744cf19eSJohan Hedberg mgmt_write_scan_failed(hdev, param, status); 3082d7cee58SJohan Hedberg hdev->discov_timeout = 0; 3092d7cee58SJohan Hedberg goto done; 3102d7cee58SJohan Hedberg } 3112d7cee58SJohan Hedberg 3129fbcbb45SJohan Hedberg old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags); 3139fbcbb45SJohan Hedberg old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags); 314a9de9248SMarcel Holtmann 31573f22f62SJohan Hedberg if (param & SCAN_INQUIRY) { 3161da177e4SLinus Torvalds set_bit(HCI_ISCAN, &hdev->flags); 3179fbcbb45SJohan Hedberg if (!old_iscan) 318744cf19eSJohan Hedberg mgmt_discoverable(hdev, 1); 31916ab91abSJohan Hedberg if (hdev->discov_timeout > 0) { 32016ab91abSJohan Hedberg int to = msecs_to_jiffies(hdev->discov_timeout * 1000); 32116ab91abSJohan Hedberg queue_delayed_work(hdev->workqueue, &hdev->discov_off, 32216ab91abSJohan Hedberg to); 32316ab91abSJohan Hedberg } 3249fbcbb45SJohan Hedberg } else if (old_iscan) 325744cf19eSJohan Hedberg mgmt_discoverable(hdev, 0); 3261da177e4SLinus Torvalds 3279fbcbb45SJohan Hedberg if (param & SCAN_PAGE) { 3281da177e4SLinus Torvalds set_bit(HCI_PSCAN, &hdev->flags); 3299fbcbb45SJohan Hedberg if (!old_pscan) 330744cf19eSJohan Hedberg mgmt_connectable(hdev, 1); 3319fbcbb45SJohan Hedberg } else if (old_pscan) 332744cf19eSJohan Hedberg mgmt_connectable(hdev, 0); 333a9de9248SMarcel Holtmann 33436f7fc7eSJohan Hedberg done: 33556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 33623bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status); 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 428a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 4291da177e4SLinus Torvalds { 430a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 4311da177e4SLinus Torvalds 4329f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 4331da177e4SLinus Torvalds 43423bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status); 4351143e5a6SMarcel Holtmann } 4361143e5a6SMarcel Holtmann 437333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 438333140b5SMarcel Holtmann { 439333140b5SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 440333140b5SMarcel Holtmann void *sent; 441333140b5SMarcel Holtmann 4429f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 443333140b5SMarcel Holtmann 444333140b5SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); 445333140b5SMarcel Holtmann if (!sent) 446333140b5SMarcel Holtmann return; 447333140b5SMarcel Holtmann 448c0ecddc2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 449c0ecddc2SJohan Hedberg mgmt_ssp_enable_complete(hdev, *((u8 *) sent), status); 450c0ecddc2SJohan Hedberg else if (!status) { 45184bde9d6SJohan Hedberg if (*((u8 *) sent)) 45284bde9d6SJohan Hedberg set_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 45384bde9d6SJohan Hedberg else 45484bde9d6SJohan Hedberg clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 455c0ecddc2SJohan Hedberg } 456333140b5SMarcel Holtmann } 457333140b5SMarcel Holtmann 458d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev) 459d5859e22SJohan Hedberg { 460d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 461d5859e22SJohan Hedberg return 2; 462d5859e22SJohan Hedberg 463d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 464d5859e22SJohan Hedberg return 1; 465d5859e22SJohan Hedberg 466d5859e22SJohan Hedberg if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 && 467d5859e22SJohan Hedberg hdev->lmp_subver == 0x0757) 468d5859e22SJohan Hedberg return 1; 469d5859e22SJohan Hedberg 470d5859e22SJohan Hedberg if (hdev->manufacturer == 15) { 471d5859e22SJohan Hedberg if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963) 472d5859e22SJohan Hedberg return 1; 473d5859e22SJohan Hedberg if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963) 474d5859e22SJohan Hedberg return 1; 475d5859e22SJohan Hedberg if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965) 476d5859e22SJohan Hedberg return 1; 477d5859e22SJohan Hedberg } 478d5859e22SJohan Hedberg 479d5859e22SJohan Hedberg if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 && 480d5859e22SJohan Hedberg hdev->lmp_subver == 0x1805) 481d5859e22SJohan Hedberg return 1; 482d5859e22SJohan Hedberg 483d5859e22SJohan Hedberg return 0; 484d5859e22SJohan Hedberg } 485d5859e22SJohan Hedberg 486d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev) 487d5859e22SJohan Hedberg { 488d5859e22SJohan Hedberg u8 mode; 489d5859e22SJohan Hedberg 490d5859e22SJohan Hedberg mode = hci_get_inquiry_mode(hdev); 491d5859e22SJohan Hedberg 492d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode); 493d5859e22SJohan Hedberg } 494d5859e22SJohan Hedberg 495d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev) 496d5859e22SJohan Hedberg { 497d5859e22SJohan Hedberg /* The second byte is 0xff instead of 0x9f (two reserved bits 498d5859e22SJohan Hedberg * disabled) since a Broadcom 1.2 dongle doesn't respond to the 499d5859e22SJohan Hedberg * command otherwise */ 500d5859e22SJohan Hedberg u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 }; 501d5859e22SJohan Hedberg 5026de6c18dSVille Tervo /* CSR 1.1 dongles does not accept any bitfield so don't try to set 5036de6c18dSVille Tervo * any event mask for pre 1.2 devices */ 5045a13b095SAndrei Emeltchenko if (hdev->hci_ver < BLUETOOTH_VER_1_2) 5056de6c18dSVille Tervo return; 5066de6c18dSVille Tervo 507d5859e22SJohan Hedberg events[4] |= 0x01; /* Flow Specification Complete */ 508d5859e22SJohan Hedberg events[4] |= 0x02; /* Inquiry Result with RSSI */ 509d5859e22SJohan Hedberg events[4] |= 0x04; /* Read Remote Extended Features Complete */ 510d5859e22SJohan Hedberg events[5] |= 0x08; /* Synchronous Connection Complete */ 511d5859e22SJohan Hedberg events[5] |= 0x10; /* Synchronous Connection Changed */ 512d5859e22SJohan Hedberg 513d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 514a24299e6SJohan Hedberg events[4] |= 0x02; /* Inquiry Result with RSSI */ 515d5859e22SJohan Hedberg 516d5859e22SJohan Hedberg if (hdev->features[5] & LMP_SNIFF_SUBR) 517d5859e22SJohan Hedberg events[5] |= 0x20; /* Sniff Subrating */ 518d5859e22SJohan Hedberg 519d5859e22SJohan Hedberg if (hdev->features[5] & LMP_PAUSE_ENC) 520d5859e22SJohan Hedberg events[5] |= 0x80; /* Encryption Key Refresh Complete */ 521d5859e22SJohan Hedberg 522d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 523d5859e22SJohan Hedberg events[5] |= 0x40; /* Extended Inquiry Result */ 524d5859e22SJohan Hedberg 525d5859e22SJohan Hedberg if (hdev->features[6] & LMP_NO_FLUSH) 526d5859e22SJohan Hedberg events[7] |= 0x01; /* Enhanced Flush Complete */ 527d5859e22SJohan Hedberg 528d5859e22SJohan Hedberg if (hdev->features[7] & LMP_LSTO) 529d5859e22SJohan Hedberg events[6] |= 0x80; /* Link Supervision Timeout Changed */ 530d5859e22SJohan Hedberg 5319a1a1996SAndre Guedes if (lmp_ssp_capable(hdev)) { 532d5859e22SJohan Hedberg events[6] |= 0x01; /* IO Capability Request */ 533d5859e22SJohan Hedberg events[6] |= 0x02; /* IO Capability Response */ 534d5859e22SJohan Hedberg events[6] |= 0x04; /* User Confirmation Request */ 535d5859e22SJohan Hedberg events[6] |= 0x08; /* User Passkey Request */ 536d5859e22SJohan Hedberg events[6] |= 0x10; /* Remote OOB Data Request */ 537d5859e22SJohan Hedberg events[6] |= 0x20; /* Simple Pairing Complete */ 538d5859e22SJohan Hedberg events[7] |= 0x04; /* User Passkey Notification */ 539d5859e22SJohan Hedberg events[7] |= 0x08; /* Keypress Notification */ 540d5859e22SJohan Hedberg events[7] |= 0x10; /* Remote Host Supported 541d5859e22SJohan Hedberg * Features Notification */ 542d5859e22SJohan Hedberg } 543d5859e22SJohan Hedberg 544c383ddc4SAndre Guedes if (lmp_le_capable(hdev)) 545d5859e22SJohan Hedberg events[7] |= 0x20; /* LE Meta-Event */ 546d5859e22SJohan Hedberg 547d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); 548d5859e22SJohan Hedberg } 549d5859e22SJohan Hedberg 550d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev) 551d5859e22SJohan Hedberg { 552e61ef499SAndrei Emeltchenko if (hdev->dev_type != HCI_BREDR) 553e61ef499SAndrei Emeltchenko return; 554e61ef499SAndrei Emeltchenko 555d5859e22SJohan Hedberg hci_setup_event_mask(hdev); 556d5859e22SJohan Hedberg 557d095c1ebSAndrei Emeltchenko if (hdev->hci_ver > BLUETOOTH_VER_1_1) 558d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); 559d5859e22SJohan Hedberg 5606d3c730fSGustavo Padovan if (lmp_ssp_capable(hdev)) { 56154d04dbbSJohan Hedberg if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { 562d5859e22SJohan Hedberg u8 mode = 0x01; 56354d04dbbSJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 56454d04dbbSJohan Hedberg sizeof(mode), &mode); 56554d04dbbSJohan Hedberg } else { 56654d04dbbSJohan Hedberg struct hci_cp_write_eir cp; 56754d04dbbSJohan Hedberg 56854d04dbbSJohan Hedberg memset(hdev->eir, 0, sizeof(hdev->eir)); 56954d04dbbSJohan Hedberg memset(&cp, 0, sizeof(cp)); 57054d04dbbSJohan Hedberg 57154d04dbbSJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp); 57254d04dbbSJohan Hedberg } 573d5859e22SJohan Hedberg } 574d5859e22SJohan Hedberg 575d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 576d5859e22SJohan Hedberg hci_setup_inquiry_mode(hdev); 577d5859e22SJohan Hedberg 578d5859e22SJohan Hedberg if (hdev->features[7] & LMP_INQ_TX_PWR) 579d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL); 580971e3a4bSAndre Guedes 581971e3a4bSAndre Guedes if (hdev->features[7] & LMP_EXTFEATURES) { 582971e3a4bSAndre Guedes struct hci_cp_read_local_ext_features cp; 583971e3a4bSAndre Guedes 584971e3a4bSAndre Guedes cp.page = 0x01; 58504124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), 58604124681SGustavo F. Padovan &cp); 587971e3a4bSAndre Guedes } 588e6100a25SAndre Guedes 58947990ea0SJohan Hedberg if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) { 59047990ea0SJohan Hedberg u8 enable = 1; 59104124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable), 59204124681SGustavo F. Padovan &enable); 59347990ea0SJohan Hedberg } 594d5859e22SJohan Hedberg } 595d5859e22SJohan Hedberg 596a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) 597a9de9248SMarcel Holtmann { 598a9de9248SMarcel Holtmann struct hci_rp_read_local_version *rp = (void *) skb->data; 5991143e5a6SMarcel Holtmann 6009f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 6011143e5a6SMarcel Holtmann 602a9de9248SMarcel Holtmann if (rp->status) 60328b8df77SAndrei Emeltchenko goto done; 6041143e5a6SMarcel Holtmann 605a9de9248SMarcel Holtmann hdev->hci_ver = rp->hci_ver; 606e4e8e37cSMarcel Holtmann hdev->hci_rev = __le16_to_cpu(rp->hci_rev); 607d5859e22SJohan Hedberg hdev->lmp_ver = rp->lmp_ver; 608e4e8e37cSMarcel Holtmann hdev->manufacturer = __le16_to_cpu(rp->manufacturer); 609d5859e22SJohan Hedberg hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); 6101da177e4SLinus Torvalds 6119f1db00cSAndrei Emeltchenko BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name, 612807deac2SGustavo Padovan hdev->manufacturer, hdev->hci_ver, hdev->hci_rev); 613d5859e22SJohan Hedberg 614d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags)) 615d5859e22SJohan Hedberg hci_setup(hdev); 61628b8df77SAndrei Emeltchenko 61728b8df77SAndrei Emeltchenko done: 61828b8df77SAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status); 619d5859e22SJohan Hedberg } 620d5859e22SJohan Hedberg 621d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev) 622d5859e22SJohan Hedberg { 623035100c8SAndrei Emeltchenko struct hci_cp_write_def_link_policy cp; 624d5859e22SJohan Hedberg u16 link_policy = 0; 625d5859e22SJohan Hedberg 6269f92ebf6SAndre Guedes if (lmp_rswitch_capable(hdev)) 627d5859e22SJohan Hedberg link_policy |= HCI_LP_RSWITCH; 628d5859e22SJohan Hedberg if (hdev->features[0] & LMP_HOLD) 629d5859e22SJohan Hedberg link_policy |= HCI_LP_HOLD; 6306eded100SAndre Guedes if (lmp_sniff_capable(hdev)) 631d5859e22SJohan Hedberg link_policy |= HCI_LP_SNIFF; 632d5859e22SJohan Hedberg if (hdev->features[1] & LMP_PARK) 633d5859e22SJohan Hedberg link_policy |= HCI_LP_PARK; 634d5859e22SJohan Hedberg 635035100c8SAndrei Emeltchenko cp.policy = cpu_to_le16(link_policy); 636035100c8SAndrei Emeltchenko hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp); 6371da177e4SLinus Torvalds } 6381da177e4SLinus Torvalds 6398fc9ced3SGustavo Padovan static void hci_cc_read_local_commands(struct hci_dev *hdev, 6408fc9ced3SGustavo Padovan struct sk_buff *skb) 641a9de9248SMarcel Holtmann { 642a9de9248SMarcel Holtmann struct hci_rp_read_local_commands *rp = (void *) skb->data; 643a9de9248SMarcel Holtmann 6449f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 645a9de9248SMarcel Holtmann 646a9de9248SMarcel Holtmann if (rp->status) 647d5859e22SJohan Hedberg goto done; 648a9de9248SMarcel Holtmann 649a9de9248SMarcel Holtmann memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); 650d5859e22SJohan Hedberg 651d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10)) 652d5859e22SJohan Hedberg hci_setup_link_policy(hdev); 653d5859e22SJohan Hedberg 654d5859e22SJohan Hedberg done: 655d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status); 656a9de9248SMarcel Holtmann } 657a9de9248SMarcel Holtmann 6588fc9ced3SGustavo Padovan static void hci_cc_read_local_features(struct hci_dev *hdev, 6598fc9ced3SGustavo Padovan struct sk_buff *skb) 660a9de9248SMarcel Holtmann { 661a9de9248SMarcel Holtmann struct hci_rp_read_local_features *rp = (void *) skb->data; 662a9de9248SMarcel Holtmann 6639f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 664a9de9248SMarcel Holtmann 665a9de9248SMarcel Holtmann if (rp->status) 666a9de9248SMarcel Holtmann return; 667a9de9248SMarcel Holtmann 668a9de9248SMarcel Holtmann memcpy(hdev->features, rp->features, 8); 6691da177e4SLinus Torvalds 6701da177e4SLinus Torvalds /* Adjust default settings according to features 6711da177e4SLinus Torvalds * supported by device. */ 672a9de9248SMarcel Holtmann 6731da177e4SLinus Torvalds if (hdev->features[0] & LMP_3SLOT) 6741da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM3 | HCI_DH3); 6751da177e4SLinus Torvalds 6761da177e4SLinus Torvalds if (hdev->features[0] & LMP_5SLOT) 6771da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM5 | HCI_DH5); 6781da177e4SLinus Torvalds 6795b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV2) { 6801da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV2); 6815b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV2); 6825b7f9909SMarcel Holtmann } 6831da177e4SLinus Torvalds 6845b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV3) { 6851da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV3); 6865b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV3); 6875b7f9909SMarcel Holtmann } 6885b7f9909SMarcel Holtmann 68945db810fSAndre Guedes if (lmp_esco_capable(hdev)) 6905b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV3); 6915b7f9909SMarcel Holtmann 6925b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV4) 6935b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV4); 6945b7f9909SMarcel Holtmann 6955b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV5) 6965b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV5); 6971da177e4SLinus Torvalds 698efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_2M) 699efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV3); 700efc7688bSMarcel Holtmann 701efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_3M) 702efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_3EV3); 703efc7688bSMarcel Holtmann 704efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_3S_ESCO) 705efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); 706efc7688bSMarcel Holtmann 707a9de9248SMarcel Holtmann BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, 708a9de9248SMarcel Holtmann hdev->features[0], hdev->features[1], 709a9de9248SMarcel Holtmann hdev->features[2], hdev->features[3], 710a9de9248SMarcel Holtmann hdev->features[4], hdev->features[5], 711a9de9248SMarcel Holtmann hdev->features[6], hdev->features[7]); 7121da177e4SLinus Torvalds } 7131da177e4SLinus Torvalds 7148f984dfaSJohan Hedberg static void hci_set_le_support(struct hci_dev *hdev) 7158f984dfaSJohan Hedberg { 7168f984dfaSJohan Hedberg struct hci_cp_write_le_host_supported cp; 7178f984dfaSJohan Hedberg 7188f984dfaSJohan Hedberg memset(&cp, 0, sizeof(cp)); 7198f984dfaSJohan Hedberg 7209d42820fSMarcel Holtmann if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { 7218f984dfaSJohan Hedberg cp.le = 1; 7228f984dfaSJohan Hedberg cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR); 7238f984dfaSJohan Hedberg } 7248f984dfaSJohan Hedberg 7258f984dfaSJohan Hedberg if (cp.le != !!(hdev->host_features[0] & LMP_HOST_LE)) 72604124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), 72704124681SGustavo F. Padovan &cp); 7288f984dfaSJohan Hedberg } 7298f984dfaSJohan Hedberg 730971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev, 731971e3a4bSAndre Guedes struct sk_buff *skb) 732971e3a4bSAndre Guedes { 733971e3a4bSAndre Guedes struct hci_rp_read_local_ext_features *rp = (void *) skb->data; 734971e3a4bSAndre Guedes 7359f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 736971e3a4bSAndre Guedes 737971e3a4bSAndre Guedes if (rp->status) 7388f984dfaSJohan Hedberg goto done; 739971e3a4bSAndre Guedes 740b5b32b65SAndre Guedes switch (rp->page) { 741b5b32b65SAndre Guedes case 0: 742b5b32b65SAndre Guedes memcpy(hdev->features, rp->features, 8); 743b5b32b65SAndre Guedes break; 744b5b32b65SAndre Guedes case 1: 74559e29406SAndre Guedes memcpy(hdev->host_features, rp->features, 8); 746b5b32b65SAndre Guedes break; 747b5b32b65SAndre Guedes } 748971e3a4bSAndre Guedes 749c383ddc4SAndre Guedes if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev)) 7508f984dfaSJohan Hedberg hci_set_le_support(hdev); 7518f984dfaSJohan Hedberg 7528f984dfaSJohan Hedberg done: 753971e3a4bSAndre Guedes hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status); 754971e3a4bSAndre Guedes } 755971e3a4bSAndre Guedes 7561e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, 7571e89cffbSAndrei Emeltchenko struct sk_buff *skb) 7581e89cffbSAndrei Emeltchenko { 7591e89cffbSAndrei Emeltchenko struct hci_rp_read_flow_control_mode *rp = (void *) skb->data; 7601e89cffbSAndrei Emeltchenko 7619f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 7621e89cffbSAndrei Emeltchenko 7631e89cffbSAndrei Emeltchenko if (rp->status) 7641e89cffbSAndrei Emeltchenko return; 7651e89cffbSAndrei Emeltchenko 7661e89cffbSAndrei Emeltchenko hdev->flow_ctl_mode = rp->mode; 7671e89cffbSAndrei Emeltchenko 7681e89cffbSAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status); 7691e89cffbSAndrei Emeltchenko } 7701e89cffbSAndrei Emeltchenko 771a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 772a9de9248SMarcel Holtmann { 773a9de9248SMarcel Holtmann struct hci_rp_read_buffer_size *rp = (void *) skb->data; 774a9de9248SMarcel Holtmann 7759f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 776a9de9248SMarcel Holtmann 777a9de9248SMarcel Holtmann if (rp->status) 778a9de9248SMarcel Holtmann return; 779a9de9248SMarcel Holtmann 780a9de9248SMarcel Holtmann hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); 781a9de9248SMarcel Holtmann hdev->sco_mtu = rp->sco_mtu; 782a9de9248SMarcel Holtmann hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); 783a9de9248SMarcel Holtmann hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); 784da1f5198SMarcel Holtmann 785da1f5198SMarcel Holtmann if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { 786da1f5198SMarcel Holtmann hdev->sco_mtu = 64; 787da1f5198SMarcel Holtmann hdev->sco_pkts = 8; 788da1f5198SMarcel Holtmann } 789da1f5198SMarcel Holtmann 790da1f5198SMarcel Holtmann hdev->acl_cnt = hdev->acl_pkts; 791da1f5198SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 7921da177e4SLinus Torvalds 793807deac2SGustavo Padovan BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu, 794807deac2SGustavo Padovan hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts); 7951da177e4SLinus Torvalds } 7961da177e4SLinus Torvalds 797a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) 798a9de9248SMarcel Holtmann { 799a9de9248SMarcel Holtmann struct hci_rp_read_bd_addr *rp = (void *) skb->data; 8001da177e4SLinus Torvalds 8019f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 802a9de9248SMarcel Holtmann 803a9de9248SMarcel Holtmann if (!rp->status) 804a9de9248SMarcel Holtmann bacpy(&hdev->bdaddr, &rp->bdaddr); 805a9de9248SMarcel Holtmann 80623bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status); 80723bb5763SJohan Hedberg } 80823bb5763SJohan Hedberg 809350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev, 810350ee4cfSAndrei Emeltchenko struct sk_buff *skb) 811350ee4cfSAndrei Emeltchenko { 812350ee4cfSAndrei Emeltchenko struct hci_rp_read_data_block_size *rp = (void *) skb->data; 813350ee4cfSAndrei Emeltchenko 8149f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 815350ee4cfSAndrei Emeltchenko 816350ee4cfSAndrei Emeltchenko if (rp->status) 817350ee4cfSAndrei Emeltchenko return; 818350ee4cfSAndrei Emeltchenko 819350ee4cfSAndrei Emeltchenko hdev->block_mtu = __le16_to_cpu(rp->max_acl_len); 820350ee4cfSAndrei Emeltchenko hdev->block_len = __le16_to_cpu(rp->block_len); 821350ee4cfSAndrei Emeltchenko hdev->num_blocks = __le16_to_cpu(rp->num_blocks); 822350ee4cfSAndrei Emeltchenko 823350ee4cfSAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 824350ee4cfSAndrei Emeltchenko 825350ee4cfSAndrei Emeltchenko BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu, 826350ee4cfSAndrei Emeltchenko hdev->block_cnt, hdev->block_len); 827350ee4cfSAndrei Emeltchenko 828350ee4cfSAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status); 829350ee4cfSAndrei Emeltchenko } 830350ee4cfSAndrei Emeltchenko 83123bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb) 83223bb5763SJohan Hedberg { 83323bb5763SJohan Hedberg __u8 status = *((__u8 *) skb->data); 83423bb5763SJohan Hedberg 8359f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 83623bb5763SJohan Hedberg 83723bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status); 8381da177e4SLinus Torvalds } 8391da177e4SLinus Torvalds 840928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev, 841928abaa7SAndrei Emeltchenko struct sk_buff *skb) 842928abaa7SAndrei Emeltchenko { 843928abaa7SAndrei Emeltchenko struct hci_rp_read_local_amp_info *rp = (void *) skb->data; 844928abaa7SAndrei Emeltchenko 8459f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 846928abaa7SAndrei Emeltchenko 847928abaa7SAndrei Emeltchenko if (rp->status) 848928abaa7SAndrei Emeltchenko return; 849928abaa7SAndrei Emeltchenko 850928abaa7SAndrei Emeltchenko hdev->amp_status = rp->amp_status; 851928abaa7SAndrei Emeltchenko hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); 852928abaa7SAndrei Emeltchenko hdev->amp_max_bw = __le32_to_cpu(rp->max_bw); 853928abaa7SAndrei Emeltchenko hdev->amp_min_latency = __le32_to_cpu(rp->min_latency); 854928abaa7SAndrei Emeltchenko hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu); 855928abaa7SAndrei Emeltchenko hdev->amp_type = rp->amp_type; 856928abaa7SAndrei Emeltchenko hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap); 857928abaa7SAndrei Emeltchenko hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size); 858928abaa7SAndrei Emeltchenko hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); 859928abaa7SAndrei Emeltchenko hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); 860928abaa7SAndrei Emeltchenko 861928abaa7SAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status); 862928abaa7SAndrei Emeltchenko } 863928abaa7SAndrei Emeltchenko 864b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, 865b0916ea0SJohan Hedberg struct sk_buff *skb) 866b0916ea0SJohan Hedberg { 867b0916ea0SJohan Hedberg __u8 status = *((__u8 *) skb->data); 868b0916ea0SJohan Hedberg 8699f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 870b0916ea0SJohan Hedberg 871b0916ea0SJohan Hedberg hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status); 872b0916ea0SJohan Hedberg } 873b0916ea0SJohan Hedberg 874d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb) 875d5859e22SJohan Hedberg { 876d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 877d5859e22SJohan Hedberg 8789f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 879d5859e22SJohan Hedberg 880d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status); 881d5859e22SJohan Hedberg } 882d5859e22SJohan Hedberg 883d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev, 884d5859e22SJohan Hedberg struct sk_buff *skb) 885d5859e22SJohan Hedberg { 886d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 887d5859e22SJohan Hedberg 8889f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 889d5859e22SJohan Hedberg 890d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status); 891d5859e22SJohan Hedberg } 892d5859e22SJohan Hedberg 893d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, 894d5859e22SJohan Hedberg struct sk_buff *skb) 895d5859e22SJohan Hedberg { 89691c4e9b1SMarcel Holtmann struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data; 897d5859e22SJohan Hedberg 8989f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 899d5859e22SJohan Hedberg 90091c4e9b1SMarcel Holtmann if (!rp->status) 90191c4e9b1SMarcel Holtmann hdev->inq_tx_power = rp->tx_power; 90291c4e9b1SMarcel Holtmann 90391c4e9b1SMarcel Holtmann hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status); 904d5859e22SJohan Hedberg } 905d5859e22SJohan Hedberg 906d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb) 907d5859e22SJohan Hedberg { 908d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 909d5859e22SJohan Hedberg 9109f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 911d5859e22SJohan Hedberg 912d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status); 913d5859e22SJohan Hedberg } 914d5859e22SJohan Hedberg 915980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) 916980e1a53SJohan Hedberg { 917980e1a53SJohan Hedberg struct hci_rp_pin_code_reply *rp = (void *) skb->data; 918980e1a53SJohan Hedberg struct hci_cp_pin_code_reply *cp; 919980e1a53SJohan Hedberg struct hci_conn *conn; 920980e1a53SJohan Hedberg 9219f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 922980e1a53SJohan Hedberg 92356e5cb86SJohan Hedberg hci_dev_lock(hdev); 92456e5cb86SJohan Hedberg 925a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 926744cf19eSJohan Hedberg mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); 927980e1a53SJohan Hedberg 928980e1a53SJohan Hedberg if (rp->status != 0) 92956e5cb86SJohan Hedberg goto unlock; 930980e1a53SJohan Hedberg 931980e1a53SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); 932980e1a53SJohan Hedberg if (!cp) 93356e5cb86SJohan Hedberg goto unlock; 934980e1a53SJohan Hedberg 935980e1a53SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 936980e1a53SJohan Hedberg if (conn) 937980e1a53SJohan Hedberg conn->pin_length = cp->pin_len; 93856e5cb86SJohan Hedberg 93956e5cb86SJohan Hedberg unlock: 94056e5cb86SJohan Hedberg hci_dev_unlock(hdev); 941980e1a53SJohan Hedberg } 942980e1a53SJohan Hedberg 943980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 944980e1a53SJohan Hedberg { 945980e1a53SJohan Hedberg struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data; 946980e1a53SJohan Hedberg 9479f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 948980e1a53SJohan Hedberg 94956e5cb86SJohan Hedberg hci_dev_lock(hdev); 95056e5cb86SJohan Hedberg 951a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 952744cf19eSJohan Hedberg mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr, 953980e1a53SJohan Hedberg rp->status); 95456e5cb86SJohan Hedberg 95556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 956980e1a53SJohan Hedberg } 95756e5cb86SJohan Hedberg 9586ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, 9596ed58ec5SVille Tervo struct sk_buff *skb) 9606ed58ec5SVille Tervo { 9616ed58ec5SVille Tervo struct hci_rp_le_read_buffer_size *rp = (void *) skb->data; 9626ed58ec5SVille Tervo 9639f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 9646ed58ec5SVille Tervo 9656ed58ec5SVille Tervo if (rp->status) 9666ed58ec5SVille Tervo return; 9676ed58ec5SVille Tervo 9686ed58ec5SVille Tervo hdev->le_mtu = __le16_to_cpu(rp->le_mtu); 9696ed58ec5SVille Tervo hdev->le_pkts = rp->le_max_pkt; 9706ed58ec5SVille Tervo 9716ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 9726ed58ec5SVille Tervo 9736ed58ec5SVille Tervo BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); 9746ed58ec5SVille Tervo 9756ed58ec5SVille Tervo hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status); 9766ed58ec5SVille Tervo } 977980e1a53SJohan Hedberg 978a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) 979a5c29683SJohan Hedberg { 980a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 981a5c29683SJohan Hedberg 9829f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 983a5c29683SJohan Hedberg 98456e5cb86SJohan Hedberg hci_dev_lock(hdev); 98556e5cb86SJohan Hedberg 986a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 98704124681SGustavo F. Padovan mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0, 98804124681SGustavo F. Padovan rp->status); 98956e5cb86SJohan Hedberg 99056e5cb86SJohan Hedberg hci_dev_unlock(hdev); 991a5c29683SJohan Hedberg } 992a5c29683SJohan Hedberg 993a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, 994a5c29683SJohan Hedberg struct sk_buff *skb) 995a5c29683SJohan Hedberg { 996a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 997a5c29683SJohan Hedberg 9989f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 999a5c29683SJohan Hedberg 100056e5cb86SJohan Hedberg hci_dev_lock(hdev); 100156e5cb86SJohan Hedberg 1002a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1003744cf19eSJohan Hedberg mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr, 100404124681SGustavo F. Padovan ACL_LINK, 0, rp->status); 100556e5cb86SJohan Hedberg 100656e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1007a5c29683SJohan Hedberg } 1008a5c29683SJohan Hedberg 10091143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb) 10101143d458SBrian Gix { 10111143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 10121143d458SBrian Gix 10139f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 10141143d458SBrian Gix 10151143d458SBrian Gix hci_dev_lock(hdev); 10161143d458SBrian Gix 1017a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1018272d90dfSJohan Hedberg mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 1019272d90dfSJohan Hedberg 0, rp->status); 10201143d458SBrian Gix 10211143d458SBrian Gix hci_dev_unlock(hdev); 10221143d458SBrian Gix } 10231143d458SBrian Gix 10241143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, 10251143d458SBrian Gix struct sk_buff *skb) 10261143d458SBrian Gix { 10271143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 10281143d458SBrian Gix 10299f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 10301143d458SBrian Gix 10311143d458SBrian Gix hci_dev_lock(hdev); 10321143d458SBrian Gix 1033a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 10341143d458SBrian Gix mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr, 103504124681SGustavo F. Padovan ACL_LINK, 0, rp->status); 10361143d458SBrian Gix 10371143d458SBrian Gix hci_dev_unlock(hdev); 10381143d458SBrian Gix } 10391143d458SBrian Gix 1040c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, 1041c35938b2SSzymon Janc struct sk_buff *skb) 1042c35938b2SSzymon Janc { 1043c35938b2SSzymon Janc struct hci_rp_read_local_oob_data *rp = (void *) skb->data; 1044c35938b2SSzymon Janc 10459f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1046c35938b2SSzymon Janc 104756e5cb86SJohan Hedberg hci_dev_lock(hdev); 1048744cf19eSJohan Hedberg mgmt_read_local_oob_data_reply_complete(hdev, rp->hash, 1049c35938b2SSzymon Janc rp->randomizer, rp->status); 105056e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1051c35938b2SSzymon Janc } 1052c35938b2SSzymon Janc 105307f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) 105407f7fa5dSAndre Guedes { 105507f7fa5dSAndre Guedes __u8 status = *((__u8 *) skb->data); 105607f7fa5dSAndre Guedes 10579f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 10587ba8b4beSAndre Guedes 10597ba8b4beSAndre Guedes hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status); 10603fd24153SAndre Guedes 10613fd24153SAndre Guedes if (status) { 10623fd24153SAndre Guedes hci_dev_lock(hdev); 10633fd24153SAndre Guedes mgmt_start_discovery_failed(hdev, status); 10643fd24153SAndre Guedes hci_dev_unlock(hdev); 10653fd24153SAndre Guedes return; 10663fd24153SAndre Guedes } 106707f7fa5dSAndre Guedes } 106807f7fa5dSAndre Guedes 1069eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, 1070eb9d91f5SAndre Guedes struct sk_buff *skb) 1071eb9d91f5SAndre Guedes { 1072eb9d91f5SAndre Guedes struct hci_cp_le_set_scan_enable *cp; 1073eb9d91f5SAndre Guedes __u8 status = *((__u8 *) skb->data); 1074eb9d91f5SAndre Guedes 10759f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1076eb9d91f5SAndre Guedes 1077eb9d91f5SAndre Guedes cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE); 1078eb9d91f5SAndre Guedes if (!cp) 1079eb9d91f5SAndre Guedes return; 1080eb9d91f5SAndre Guedes 108168a8aea4SAndrei Emeltchenko switch (cp->enable) { 108268a8aea4SAndrei Emeltchenko case LE_SCANNING_ENABLED: 10837ba8b4beSAndre Guedes hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status); 10847ba8b4beSAndre Guedes 10853fd24153SAndre Guedes if (status) { 10863fd24153SAndre Guedes hci_dev_lock(hdev); 10873fd24153SAndre Guedes mgmt_start_discovery_failed(hdev, status); 10883fd24153SAndre Guedes hci_dev_unlock(hdev); 10897ba8b4beSAndre Guedes return; 10903fd24153SAndre Guedes } 10917ba8b4beSAndre Guedes 1092d23264a8SAndre Guedes set_bit(HCI_LE_SCAN, &hdev->dev_flags); 1093d23264a8SAndre Guedes 1094a8f13c8cSAndre Guedes hci_dev_lock(hdev); 1095343f935bSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_FINDING); 1096a8f13c8cSAndre Guedes hci_dev_unlock(hdev); 109768a8aea4SAndrei Emeltchenko break; 109868a8aea4SAndrei Emeltchenko 109968a8aea4SAndrei Emeltchenko case LE_SCANNING_DISABLED: 1100c9ecc48eSAndre Guedes if (status) { 1101c9ecc48eSAndre Guedes hci_dev_lock(hdev); 1102c9ecc48eSAndre Guedes mgmt_stop_discovery_failed(hdev, status); 1103c9ecc48eSAndre Guedes hci_dev_unlock(hdev); 11047ba8b4beSAndre Guedes return; 1105c9ecc48eSAndre Guedes } 11067ba8b4beSAndre Guedes 1107d23264a8SAndre Guedes clear_bit(HCI_LE_SCAN, &hdev->dev_flags); 1108d23264a8SAndre Guedes 1109bc3dd33cSAndre Guedes if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED && 1110bc3dd33cSAndre Guedes hdev->discovery.state == DISCOVERY_FINDING) { 11115e0452c0SAndre Guedes mgmt_interleaved_discovery(hdev); 11125e0452c0SAndre Guedes } else { 1113c599008fSAndre Guedes hci_dev_lock(hdev); 1114c599008fSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 1115c599008fSAndre Guedes hci_dev_unlock(hdev); 11165e0452c0SAndre Guedes } 1117c599008fSAndre Guedes 111868a8aea4SAndrei Emeltchenko break; 111968a8aea4SAndrei Emeltchenko 112068a8aea4SAndrei Emeltchenko default: 112168a8aea4SAndrei Emeltchenko BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable); 112268a8aea4SAndrei Emeltchenko break; 112335815085SAndre Guedes } 1124eb9d91f5SAndre Guedes } 1125eb9d91f5SAndre Guedes 1126a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb) 1127a7a595f6SVinicius Costa Gomes { 1128a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_reply *rp = (void *) skb->data; 1129a7a595f6SVinicius Costa Gomes 11309f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1131a7a595f6SVinicius Costa Gomes 1132a7a595f6SVinicius Costa Gomes if (rp->status) 1133a7a595f6SVinicius Costa Gomes return; 1134a7a595f6SVinicius Costa Gomes 1135a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status); 1136a7a595f6SVinicius Costa Gomes } 1137a7a595f6SVinicius Costa Gomes 1138a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 1139a7a595f6SVinicius Costa Gomes { 1140a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data; 1141a7a595f6SVinicius Costa Gomes 11429f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1143a7a595f6SVinicius Costa Gomes 1144a7a595f6SVinicius Costa Gomes if (rp->status) 1145a7a595f6SVinicius Costa Gomes return; 1146a7a595f6SVinicius Costa Gomes 1147a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status); 1148a7a595f6SVinicius Costa Gomes } 1149a7a595f6SVinicius Costa Gomes 11506039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev, 1151f9b49306SAndre Guedes struct sk_buff *skb) 1152f9b49306SAndre Guedes { 115306199cf8SJohan Hedberg struct hci_cp_write_le_host_supported *sent; 1154f9b49306SAndre Guedes __u8 status = *((__u8 *) skb->data); 1155f9b49306SAndre Guedes 11569f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1157f9b49306SAndre Guedes 115806199cf8SJohan Hedberg sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED); 11598f984dfaSJohan Hedberg if (!sent) 1160f9b49306SAndre Guedes return; 1161f9b49306SAndre Guedes 11628f984dfaSJohan Hedberg if (!status) { 11638f984dfaSJohan Hedberg if (sent->le) 11648f984dfaSJohan Hedberg hdev->host_features[0] |= LMP_HOST_LE; 11658f984dfaSJohan Hedberg else 11668f984dfaSJohan Hedberg hdev->host_features[0] &= ~LMP_HOST_LE; 11678f984dfaSJohan Hedberg } 11688f984dfaSJohan Hedberg 11698f984dfaSJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags) && 11708f984dfaSJohan Hedberg !test_bit(HCI_INIT, &hdev->flags)) 11718f984dfaSJohan Hedberg mgmt_le_enable_complete(hdev, sent->le, status); 11728f984dfaSJohan Hedberg 11738f984dfaSJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status); 1174f9b49306SAndre Guedes } 1175f9b49306SAndre Guedes 11766039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 1177a9de9248SMarcel Holtmann { 11789f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1179a9de9248SMarcel Holtmann 1180a9de9248SMarcel Holtmann if (status) { 118123bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 1182a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 118356e5cb86SJohan Hedberg hci_dev_lock(hdev); 1184a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 11857a135109SAndre Guedes mgmt_start_discovery_failed(hdev, status); 118656e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1187314b2381SJohan Hedberg return; 1188314b2381SJohan Hedberg } 1189314b2381SJohan Hedberg 119089352e7dSAndre Guedes set_bit(HCI_INQUIRY, &hdev->flags); 119189352e7dSAndre Guedes 119256e5cb86SJohan Hedberg hci_dev_lock(hdev); 1193343f935bSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_FINDING); 119456e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1195a9de9248SMarcel Holtmann } 1196a9de9248SMarcel Holtmann 11976039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 11981da177e4SLinus Torvalds { 1199a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 12001da177e4SLinus Torvalds struct hci_conn *conn; 12011da177e4SLinus Torvalds 12029f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1203a9de9248SMarcel Holtmann 1204a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 12051da177e4SLinus Torvalds if (!cp) 12061da177e4SLinus Torvalds return; 12071da177e4SLinus Torvalds 12081da177e4SLinus Torvalds hci_dev_lock(hdev); 12091da177e4SLinus Torvalds 12101da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 12111da177e4SLinus Torvalds 12129f1db00cSAndrei Emeltchenko BT_DBG("%s bdaddr %s hcon %p", hdev->name, batostr(&cp->bdaddr), conn); 12131da177e4SLinus Torvalds 12141da177e4SLinus Torvalds if (status) { 12151da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 12164c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 12171da177e4SLinus Torvalds conn->state = BT_CLOSED; 12181da177e4SLinus Torvalds hci_proto_connect_cfm(conn, status); 12191da177e4SLinus Torvalds hci_conn_del(conn); 12204c67bc74SMarcel Holtmann } else 12214c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 12221da177e4SLinus Torvalds } 12231da177e4SLinus Torvalds } else { 12241da177e4SLinus Torvalds if (!conn) { 12251da177e4SLinus Torvalds conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); 12261da177e4SLinus Torvalds if (conn) { 1227a0c808b3SJohan Hedberg conn->out = true; 12281da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 12291da177e4SLinus Torvalds } else 1230893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 12311da177e4SLinus Torvalds } 12321da177e4SLinus Torvalds } 12331da177e4SLinus Torvalds 12341da177e4SLinus Torvalds hci_dev_unlock(hdev); 12351da177e4SLinus Torvalds } 12361da177e4SLinus Torvalds 1237a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 12381da177e4SLinus Torvalds { 1239a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 12401da177e4SLinus Torvalds struct hci_conn *acl, *sco; 12411da177e4SLinus Torvalds __u16 handle; 12421da177e4SLinus Torvalds 12439f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1244b6a0dc82SMarcel Holtmann 1245a9de9248SMarcel Holtmann if (!status) 1246a9de9248SMarcel Holtmann return; 1247a9de9248SMarcel Holtmann 1248a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 12491da177e4SLinus Torvalds if (!cp) 1250a9de9248SMarcel Holtmann return; 12511da177e4SLinus Torvalds 12521da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 12531da177e4SLinus Torvalds 12549f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, handle); 12551da177e4SLinus Torvalds 12561da177e4SLinus Torvalds hci_dev_lock(hdev); 12571da177e4SLinus Torvalds 12581da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 12595a08ecceSAndrei Emeltchenko if (acl) { 12605a08ecceSAndrei Emeltchenko sco = acl->link; 12615a08ecceSAndrei Emeltchenko if (sco) { 12621da177e4SLinus Torvalds sco->state = BT_CLOSED; 12631da177e4SLinus Torvalds 12641da177e4SLinus Torvalds hci_proto_connect_cfm(sco, status); 12651da177e4SLinus Torvalds hci_conn_del(sco); 12661da177e4SLinus Torvalds } 12675a08ecceSAndrei Emeltchenko } 12681da177e4SLinus Torvalds 12691da177e4SLinus Torvalds hci_dev_unlock(hdev); 12701da177e4SLinus Torvalds } 12711da177e4SLinus Torvalds 1272f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 1273f8558555SMarcel Holtmann { 1274f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 1275f8558555SMarcel Holtmann struct hci_conn *conn; 1276f8558555SMarcel Holtmann 12779f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1278f8558555SMarcel Holtmann 1279f8558555SMarcel Holtmann if (!status) 1280f8558555SMarcel Holtmann return; 1281f8558555SMarcel Holtmann 1282f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 1283f8558555SMarcel Holtmann if (!cp) 1284f8558555SMarcel Holtmann return; 1285f8558555SMarcel Holtmann 1286f8558555SMarcel Holtmann hci_dev_lock(hdev); 1287f8558555SMarcel Holtmann 1288f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1289f8558555SMarcel Holtmann if (conn) { 1290f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1291f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1292f8558555SMarcel Holtmann hci_conn_put(conn); 1293f8558555SMarcel Holtmann } 1294f8558555SMarcel Holtmann } 1295f8558555SMarcel Holtmann 1296f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1297f8558555SMarcel Holtmann } 1298f8558555SMarcel Holtmann 1299f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 1300f8558555SMarcel Holtmann { 1301f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 1302f8558555SMarcel Holtmann struct hci_conn *conn; 1303f8558555SMarcel Holtmann 13049f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1305f8558555SMarcel Holtmann 1306f8558555SMarcel Holtmann if (!status) 1307f8558555SMarcel Holtmann return; 1308f8558555SMarcel Holtmann 1309f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 1310f8558555SMarcel Holtmann if (!cp) 1311f8558555SMarcel Holtmann return; 1312f8558555SMarcel Holtmann 1313f8558555SMarcel Holtmann hci_dev_lock(hdev); 1314f8558555SMarcel Holtmann 1315f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1316f8558555SMarcel Holtmann if (conn) { 1317f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1318f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1319f8558555SMarcel Holtmann hci_conn_put(conn); 1320f8558555SMarcel Holtmann } 1321f8558555SMarcel Holtmann } 1322f8558555SMarcel Holtmann 1323f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1324f8558555SMarcel Holtmann } 1325f8558555SMarcel Holtmann 1326127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev, 1327392599b9SJohan Hedberg struct hci_conn *conn) 1328392599b9SJohan Hedberg { 1329392599b9SJohan Hedberg if (conn->state != BT_CONFIG || !conn->out) 1330392599b9SJohan Hedberg return 0; 1331392599b9SJohan Hedberg 1332765c2a96SJohan Hedberg if (conn->pending_sec_level == BT_SECURITY_SDP) 1333392599b9SJohan Hedberg return 0; 1334392599b9SJohan Hedberg 1335392599b9SJohan Hedberg /* Only request authentication for SSP connections or non-SSP 1336e9bf2bf0SVinicius Costa Gomes * devices with sec_level HIGH or if MITM protection is requested */ 1337807deac2SGustavo Padovan if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) && 1338807deac2SGustavo Padovan conn->pending_sec_level != BT_SECURITY_HIGH) 1339392599b9SJohan Hedberg return 0; 1340392599b9SJohan Hedberg 1341392599b9SJohan Hedberg return 1; 1342392599b9SJohan Hedberg } 1343392599b9SJohan Hedberg 13446039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev, 134500abfe44SGustavo F. Padovan struct inquiry_entry *e) 134630dc78e1SJohan Hedberg { 134730dc78e1SJohan Hedberg struct hci_cp_remote_name_req cp; 134830dc78e1SJohan Hedberg 134930dc78e1SJohan Hedberg memset(&cp, 0, sizeof(cp)); 135030dc78e1SJohan Hedberg 135130dc78e1SJohan Hedberg bacpy(&cp.bdaddr, &e->data.bdaddr); 135230dc78e1SJohan Hedberg cp.pscan_rep_mode = e->data.pscan_rep_mode; 135330dc78e1SJohan Hedberg cp.pscan_mode = e->data.pscan_mode; 135430dc78e1SJohan Hedberg cp.clock_offset = e->data.clock_offset; 135530dc78e1SJohan Hedberg 135630dc78e1SJohan Hedberg return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 135730dc78e1SJohan Hedberg } 135830dc78e1SJohan Hedberg 1359b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev) 136030dc78e1SJohan Hedberg { 136130dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 136230dc78e1SJohan Hedberg struct inquiry_entry *e; 136330dc78e1SJohan Hedberg 1364b644ba33SJohan Hedberg if (list_empty(&discov->resolve)) 1365b644ba33SJohan Hedberg return false; 1366b644ba33SJohan Hedberg 1367b644ba33SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 1368b644ba33SJohan Hedberg if (hci_resolve_name(hdev, e) == 0) { 1369b644ba33SJohan Hedberg e->name_state = NAME_PENDING; 1370b644ba33SJohan Hedberg return true; 1371b644ba33SJohan Hedberg } 1372b644ba33SJohan Hedberg 1373b644ba33SJohan Hedberg return false; 1374b644ba33SJohan Hedberg } 1375b644ba33SJohan Hedberg 1376b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn, 1377b644ba33SJohan Hedberg bdaddr_t *bdaddr, u8 *name, u8 name_len) 1378b644ba33SJohan Hedberg { 1379b644ba33SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 1380b644ba33SJohan Hedberg struct inquiry_entry *e; 1381b644ba33SJohan Hedberg 1382b644ba33SJohan Hedberg if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 138304124681SGustavo F. Padovan mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name, 138404124681SGustavo F. Padovan name_len, conn->dev_class); 1385b644ba33SJohan Hedberg 1386b644ba33SJohan Hedberg if (discov->state == DISCOVERY_STOPPED) 1387b644ba33SJohan Hedberg return; 1388b644ba33SJohan Hedberg 138930dc78e1SJohan Hedberg if (discov->state == DISCOVERY_STOPPING) 139030dc78e1SJohan Hedberg goto discov_complete; 139130dc78e1SJohan Hedberg 139230dc78e1SJohan Hedberg if (discov->state != DISCOVERY_RESOLVING) 139330dc78e1SJohan Hedberg return; 139430dc78e1SJohan Hedberg 139530dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING); 139630dc78e1SJohan Hedberg if (e) { 139730dc78e1SJohan Hedberg e->name_state = NAME_KNOWN; 139830dc78e1SJohan Hedberg list_del(&e->list); 1399b644ba33SJohan Hedberg if (name) 1400b644ba33SJohan Hedberg mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, 1401b644ba33SJohan Hedberg e->data.rssi, name, name_len); 140230dc78e1SJohan Hedberg } 140330dc78e1SJohan Hedberg 1404b644ba33SJohan Hedberg if (hci_resolve_next_name(hdev)) 140530dc78e1SJohan Hedberg return; 140630dc78e1SJohan Hedberg 140730dc78e1SJohan Hedberg discov_complete: 140830dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 140930dc78e1SJohan Hedberg } 141030dc78e1SJohan Hedberg 1411a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 14121da177e4SLinus Torvalds { 1413127178d2SJohan Hedberg struct hci_cp_remote_name_req *cp; 1414127178d2SJohan Hedberg struct hci_conn *conn; 1415127178d2SJohan Hedberg 14169f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1417127178d2SJohan Hedberg 1418127178d2SJohan Hedberg /* If successful wait for the name req complete event before 1419127178d2SJohan Hedberg * checking for the need to do authentication */ 1420127178d2SJohan Hedberg if (!status) 1421127178d2SJohan Hedberg return; 1422127178d2SJohan Hedberg 1423127178d2SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); 1424127178d2SJohan Hedberg if (!cp) 1425127178d2SJohan Hedberg return; 1426127178d2SJohan Hedberg 1427127178d2SJohan Hedberg hci_dev_lock(hdev); 1428127178d2SJohan Hedberg 1429127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 1430b644ba33SJohan Hedberg 1431b644ba33SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1432b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0); 1433b644ba33SJohan Hedberg 143479c6c70cSJohan Hedberg if (!conn) 143579c6c70cSJohan Hedberg goto unlock; 143679c6c70cSJohan Hedberg 143779c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 143879c6c70cSJohan Hedberg goto unlock; 143979c6c70cSJohan Hedberg 144051a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 1441127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1442127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1443127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1444127178d2SJohan Hedberg } 1445127178d2SJohan Hedberg 144679c6c70cSJohan Hedberg unlock: 1447127178d2SJohan Hedberg hci_dev_unlock(hdev); 1448a9de9248SMarcel Holtmann } 14491da177e4SLinus Torvalds 1450769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 1451769be974SMarcel Holtmann { 1452769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 1453769be974SMarcel Holtmann struct hci_conn *conn; 1454769be974SMarcel Holtmann 14559f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1456769be974SMarcel Holtmann 1457769be974SMarcel Holtmann if (!status) 1458769be974SMarcel Holtmann return; 1459769be974SMarcel Holtmann 1460769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 1461769be974SMarcel Holtmann if (!cp) 1462769be974SMarcel Holtmann return; 1463769be974SMarcel Holtmann 1464769be974SMarcel Holtmann hci_dev_lock(hdev); 1465769be974SMarcel Holtmann 1466769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1467769be974SMarcel Holtmann if (conn) { 1468769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1469769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1470769be974SMarcel Holtmann hci_conn_put(conn); 1471769be974SMarcel Holtmann } 1472769be974SMarcel Holtmann } 1473769be974SMarcel Holtmann 1474769be974SMarcel Holtmann hci_dev_unlock(hdev); 1475769be974SMarcel Holtmann } 1476769be974SMarcel Holtmann 1477769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 1478769be974SMarcel Holtmann { 1479769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features *cp; 1480769be974SMarcel Holtmann struct hci_conn *conn; 1481769be974SMarcel Holtmann 14829f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1483769be974SMarcel Holtmann 1484769be974SMarcel Holtmann if (!status) 1485769be974SMarcel Holtmann return; 1486769be974SMarcel Holtmann 1487769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 1488769be974SMarcel Holtmann if (!cp) 1489769be974SMarcel Holtmann return; 1490769be974SMarcel Holtmann 1491769be974SMarcel Holtmann hci_dev_lock(hdev); 1492769be974SMarcel Holtmann 1493769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1494769be974SMarcel Holtmann if (conn) { 1495769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1496769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1497769be974SMarcel Holtmann hci_conn_put(conn); 1498769be974SMarcel Holtmann } 1499769be974SMarcel Holtmann } 1500769be974SMarcel Holtmann 1501769be974SMarcel Holtmann hci_dev_unlock(hdev); 1502769be974SMarcel Holtmann } 1503769be974SMarcel Holtmann 1504a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 1505a9de9248SMarcel Holtmann { 1506b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 1507b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 1508b6a0dc82SMarcel Holtmann __u16 handle; 1509b6a0dc82SMarcel Holtmann 15109f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1511b6a0dc82SMarcel Holtmann 1512b6a0dc82SMarcel Holtmann if (!status) 1513b6a0dc82SMarcel Holtmann return; 1514b6a0dc82SMarcel Holtmann 1515b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 1516b6a0dc82SMarcel Holtmann if (!cp) 1517b6a0dc82SMarcel Holtmann return; 1518b6a0dc82SMarcel Holtmann 1519b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 1520b6a0dc82SMarcel Holtmann 15219f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, handle); 1522b6a0dc82SMarcel Holtmann 1523b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 1524b6a0dc82SMarcel Holtmann 1525b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 15265a08ecceSAndrei Emeltchenko if (acl) { 15275a08ecceSAndrei Emeltchenko sco = acl->link; 15285a08ecceSAndrei Emeltchenko if (sco) { 1529b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 1530b6a0dc82SMarcel Holtmann 1531b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(sco, status); 1532b6a0dc82SMarcel Holtmann hci_conn_del(sco); 1533b6a0dc82SMarcel Holtmann } 15345a08ecceSAndrei Emeltchenko } 1535b6a0dc82SMarcel Holtmann 1536b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 1537a9de9248SMarcel Holtmann } 1538a9de9248SMarcel Holtmann 1539a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 1540a9de9248SMarcel Holtmann { 1541a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 154204837f64SMarcel Holtmann struct hci_conn *conn; 154304837f64SMarcel Holtmann 15449f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1545a9de9248SMarcel Holtmann 1546a9de9248SMarcel Holtmann if (!status) 1547a9de9248SMarcel Holtmann return; 1548a9de9248SMarcel Holtmann 1549a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 155004837f64SMarcel Holtmann if (!cp) 1551a9de9248SMarcel Holtmann return; 155204837f64SMarcel Holtmann 155304837f64SMarcel Holtmann hci_dev_lock(hdev); 155404837f64SMarcel Holtmann 155504837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1556e73439d8SMarcel Holtmann if (conn) { 155751a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 155804837f64SMarcel Holtmann 155951a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1560e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1561e73439d8SMarcel Holtmann } 1562e73439d8SMarcel Holtmann 156304837f64SMarcel Holtmann hci_dev_unlock(hdev); 156404837f64SMarcel Holtmann } 156504837f64SMarcel Holtmann 1566a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 1567a9de9248SMarcel Holtmann { 1568a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 156904837f64SMarcel Holtmann struct hci_conn *conn; 157004837f64SMarcel Holtmann 15719f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1572a9de9248SMarcel Holtmann 1573a9de9248SMarcel Holtmann if (!status) 1574a9de9248SMarcel Holtmann return; 1575a9de9248SMarcel Holtmann 1576a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 157704837f64SMarcel Holtmann if (!cp) 1578a9de9248SMarcel Holtmann return; 157904837f64SMarcel Holtmann 158004837f64SMarcel Holtmann hci_dev_lock(hdev); 158104837f64SMarcel Holtmann 158204837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1583e73439d8SMarcel Holtmann if (conn) { 158451a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 158504837f64SMarcel Holtmann 158651a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1587e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1588e73439d8SMarcel Holtmann } 1589e73439d8SMarcel Holtmann 159004837f64SMarcel Holtmann hci_dev_unlock(hdev); 159104837f64SMarcel Holtmann } 159204837f64SMarcel Holtmann 159388c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) 159488c3df13SJohan Hedberg { 159588c3df13SJohan Hedberg struct hci_cp_disconnect *cp; 159688c3df13SJohan Hedberg struct hci_conn *conn; 159788c3df13SJohan Hedberg 159888c3df13SJohan Hedberg if (!status) 159988c3df13SJohan Hedberg return; 160088c3df13SJohan Hedberg 160188c3df13SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT); 160288c3df13SJohan Hedberg if (!cp) 160388c3df13SJohan Hedberg return; 160488c3df13SJohan Hedberg 160588c3df13SJohan Hedberg hci_dev_lock(hdev); 160688c3df13SJohan Hedberg 160788c3df13SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 160888c3df13SJohan Hedberg if (conn) 160988c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 161088c3df13SJohan Hedberg conn->dst_type, status); 161188c3df13SJohan Hedberg 161288c3df13SJohan Hedberg hci_dev_unlock(hdev); 161388c3df13SJohan Hedberg } 161488c3df13SJohan Hedberg 1615fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) 1616fcd89c09SVille Tervo { 1617fcd89c09SVille Tervo struct hci_cp_le_create_conn *cp; 1618fcd89c09SVille Tervo struct hci_conn *conn; 1619fcd89c09SVille Tervo 16209f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1621fcd89c09SVille Tervo 1622fcd89c09SVille Tervo cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN); 1623fcd89c09SVille Tervo if (!cp) 1624fcd89c09SVille Tervo return; 1625fcd89c09SVille Tervo 1626fcd89c09SVille Tervo hci_dev_lock(hdev); 1627fcd89c09SVille Tervo 1628fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr); 1629fcd89c09SVille Tervo 1630fcd89c09SVille Tervo BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr), 1631fcd89c09SVille Tervo conn); 1632fcd89c09SVille Tervo 1633fcd89c09SVille Tervo if (status) { 1634fcd89c09SVille Tervo if (conn && conn->state == BT_CONNECT) { 1635fcd89c09SVille Tervo conn->state = BT_CLOSED; 1636328c9248SHemant Gupta mgmt_connect_failed(hdev, &cp->peer_addr, conn->type, 1637328c9248SHemant Gupta conn->dst_type, status); 1638fcd89c09SVille Tervo hci_proto_connect_cfm(conn, status); 1639fcd89c09SVille Tervo hci_conn_del(conn); 1640fcd89c09SVille Tervo } 1641fcd89c09SVille Tervo } else { 1642fcd89c09SVille Tervo if (!conn) { 1643fcd89c09SVille Tervo conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr); 164429b7988aSAndre Guedes if (conn) { 164529b7988aSAndre Guedes conn->dst_type = cp->peer_addr_type; 1646a0c808b3SJohan Hedberg conn->out = true; 164729b7988aSAndre Guedes } else { 1648fcd89c09SVille Tervo BT_ERR("No memory for new connection"); 1649fcd89c09SVille Tervo } 1650fcd89c09SVille Tervo } 165129b7988aSAndre Guedes } 1652fcd89c09SVille Tervo 1653fcd89c09SVille Tervo hci_dev_unlock(hdev); 1654fcd89c09SVille Tervo } 1655fcd89c09SVille Tervo 1656a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) 1657a7a595f6SVinicius Costa Gomes { 16589f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1659a7a595f6SVinicius Costa Gomes } 1660a7a595f6SVinicius Costa Gomes 16616039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 16621da177e4SLinus Torvalds { 16631da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 166430dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 166530dc78e1SJohan Hedberg struct inquiry_entry *e; 16661da177e4SLinus Torvalds 16679f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 16681da177e4SLinus Torvalds 166923bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 16706bd57416SMarcel Holtmann 1671a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 167289352e7dSAndre Guedes 167389352e7dSAndre Guedes if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) 167489352e7dSAndre Guedes return; 167589352e7dSAndre Guedes 1676a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 167730dc78e1SJohan Hedberg return; 167830dc78e1SJohan Hedberg 167956e5cb86SJohan Hedberg hci_dev_lock(hdev); 168030dc78e1SJohan Hedberg 1681343f935bSAndre Guedes if (discov->state != DISCOVERY_FINDING) 168230dc78e1SJohan Hedberg goto unlock; 168330dc78e1SJohan Hedberg 168430dc78e1SJohan Hedberg if (list_empty(&discov->resolve)) { 1685ff9ef578SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 168630dc78e1SJohan Hedberg goto unlock; 168730dc78e1SJohan Hedberg } 168830dc78e1SJohan Hedberg 168930dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 169030dc78e1SJohan Hedberg if (e && hci_resolve_name(hdev, e) == 0) { 169130dc78e1SJohan Hedberg e->name_state = NAME_PENDING; 169230dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_RESOLVING); 169330dc78e1SJohan Hedberg } else { 169430dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 169530dc78e1SJohan Hedberg } 169630dc78e1SJohan Hedberg 169730dc78e1SJohan Hedberg unlock: 169856e5cb86SJohan Hedberg hci_dev_unlock(hdev); 16991da177e4SLinus Torvalds } 17001da177e4SLinus Torvalds 17016039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 17021da177e4SLinus Torvalds { 170345bb4bf0SMarcel Holtmann struct inquiry_data data; 1704a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 17051da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 17061da177e4SLinus Torvalds 17071da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 17081da177e4SLinus Torvalds 170945bb4bf0SMarcel Holtmann if (!num_rsp) 171045bb4bf0SMarcel Holtmann return; 171145bb4bf0SMarcel Holtmann 17121519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 17131519cc17SAndre Guedes return; 17141519cc17SAndre Guedes 17151da177e4SLinus Torvalds hci_dev_lock(hdev); 171645bb4bf0SMarcel Holtmann 1717e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 1718388fc8faSJohan Hedberg bool name_known, ssp; 17193175405bSJohan Hedberg 17201da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 17211da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 17221da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 17231da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 17241da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 17251da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 17261da177e4SLinus Torvalds data.rssi = 0x00; 172741a96212SMarcel Holtmann data.ssp_mode = 0x00; 17283175405bSJohan Hedberg 1729388fc8faSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp); 173048264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 173104124681SGustavo F. Padovan info->dev_class, 0, !name_known, ssp, NULL, 173204124681SGustavo F. Padovan 0); 17331da177e4SLinus Torvalds } 173445bb4bf0SMarcel Holtmann 17351da177e4SLinus Torvalds hci_dev_unlock(hdev); 17361da177e4SLinus Torvalds } 17371da177e4SLinus Torvalds 17386039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 17391da177e4SLinus Torvalds { 1740a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 1741a9de9248SMarcel Holtmann struct hci_conn *conn; 17421da177e4SLinus Torvalds 1743a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 174445bb4bf0SMarcel Holtmann 17451da177e4SLinus Torvalds hci_dev_lock(hdev); 174645bb4bf0SMarcel Holtmann 1747a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 17489499237aSMarcel Holtmann if (!conn) { 17499499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 17509499237aSMarcel Holtmann goto unlock; 17519499237aSMarcel Holtmann 17529499237aSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 1753a9de9248SMarcel Holtmann if (!conn) 1754a9de9248SMarcel Holtmann goto unlock; 175545bb4bf0SMarcel Holtmann 17569499237aSMarcel Holtmann conn->type = SCO_LINK; 17579499237aSMarcel Holtmann } 17589499237aSMarcel Holtmann 1759a9de9248SMarcel Holtmann if (!ev->status) { 1760a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 1761769be974SMarcel Holtmann 1762769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 1763769be974SMarcel Holtmann conn->state = BT_CONFIG; 1764769be974SMarcel Holtmann hci_conn_hold(conn); 1765052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1766769be974SMarcel Holtmann } else 1767a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 1768a9de9248SMarcel Holtmann 17699eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 17707d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 17717d0db0a3SMarcel Holtmann 1772a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 1773a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1774a9de9248SMarcel Holtmann 1775a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 1776a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1777a9de9248SMarcel Holtmann 1778a9de9248SMarcel Holtmann /* Get remote features */ 1779a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 1780a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 1781a9de9248SMarcel Holtmann cp.handle = ev->handle; 1782769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 1783769be974SMarcel Holtmann sizeof(cp), &cp); 178445bb4bf0SMarcel Holtmann } 1785a9de9248SMarcel Holtmann 1786a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 1787d095c1ebSAndrei Emeltchenko if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) { 1788a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 1789a9de9248SMarcel Holtmann cp.handle = ev->handle; 1790a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 179104124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp), 179204124681SGustavo F. Padovan &cp); 1793a9de9248SMarcel Holtmann } 179417d5c04cSJohan Hedberg } else { 1795a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 179617d5c04cSJohan Hedberg if (conn->type == ACL_LINK) 1797744cf19eSJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 179848264f06SJohan Hedberg conn->dst_type, ev->status); 179917d5c04cSJohan Hedberg } 180045bb4bf0SMarcel Holtmann 1801e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 1802e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 180345bb4bf0SMarcel Holtmann 1804769be974SMarcel Holtmann if (ev->status) { 1805a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1806a9de9248SMarcel Holtmann hci_conn_del(conn); 1807c89b6e6bSMarcel Holtmann } else if (ev->link_type != ACL_LINK) 1808c89b6e6bSMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1809a9de9248SMarcel Holtmann 1810a9de9248SMarcel Holtmann unlock: 18111da177e4SLinus Torvalds hci_dev_unlock(hdev); 1812a9de9248SMarcel Holtmann 1813a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 18141da177e4SLinus Torvalds } 18151da177e4SLinus Torvalds 18166039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 18171da177e4SLinus Torvalds { 1818a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 18191da177e4SLinus Torvalds int mask = hdev->link_mode; 18201da177e4SLinus Torvalds 1821807deac2SGustavo Padovan BT_DBG("%s bdaddr %s type 0x%x", hdev->name, batostr(&ev->bdaddr), 1822807deac2SGustavo Padovan ev->link_type); 18231da177e4SLinus Torvalds 18241da177e4SLinus Torvalds mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); 18251da177e4SLinus Torvalds 1826138d22efSSzymon Janc if ((mask & HCI_LM_ACCEPT) && 1827138d22efSSzymon Janc !hci_blacklist_lookup(hdev, &ev->bdaddr)) { 18281da177e4SLinus Torvalds /* Connection accepted */ 1829c7bdd502SMarcel Holtmann struct inquiry_entry *ie; 18301da177e4SLinus Torvalds struct hci_conn *conn; 18311da177e4SLinus Torvalds 18321da177e4SLinus Torvalds hci_dev_lock(hdev); 1833b6a0dc82SMarcel Holtmann 1834cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 1835cc11b9c1SAndrei Emeltchenko if (ie) 1836c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 1837c7bdd502SMarcel Holtmann 18388fc9ced3SGustavo Padovan conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, 18398fc9ced3SGustavo Padovan &ev->bdaddr); 18401da177e4SLinus Torvalds if (!conn) { 1841cc11b9c1SAndrei Emeltchenko conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); 1842cc11b9c1SAndrei Emeltchenko if (!conn) { 1843893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 18441da177e4SLinus Torvalds hci_dev_unlock(hdev); 18451da177e4SLinus Torvalds return; 18461da177e4SLinus Torvalds } 18471da177e4SLinus Torvalds } 1848b6a0dc82SMarcel Holtmann 18491da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 18501da177e4SLinus Torvalds conn->state = BT_CONNECT; 1851b6a0dc82SMarcel Holtmann 18521da177e4SLinus Torvalds hci_dev_unlock(hdev); 18531da177e4SLinus Torvalds 1854b6a0dc82SMarcel Holtmann if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) { 1855b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 1856b6a0dc82SMarcel Holtmann 18571da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 18581da177e4SLinus Torvalds 18591da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 18601da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 18611da177e4SLinus Torvalds else 18621da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 18631da177e4SLinus Torvalds 186404124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), 186504124681SGustavo F. Padovan &cp); 1866b6a0dc82SMarcel Holtmann } else { 1867b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 1868b6a0dc82SMarcel Holtmann 1869b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 1870a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1871b6a0dc82SMarcel Holtmann 187282781e63SAndrei Emeltchenko cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40); 187382781e63SAndrei Emeltchenko cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40); 187482781e63SAndrei Emeltchenko cp.max_latency = __constant_cpu_to_le16(0xffff); 1875b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 1876b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 1877b6a0dc82SMarcel Holtmann 1878b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 1879b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1880b6a0dc82SMarcel Holtmann } 18811da177e4SLinus Torvalds } else { 18821da177e4SLinus Torvalds /* Connection rejected */ 18831da177e4SLinus Torvalds struct hci_cp_reject_conn_req cp; 18841da177e4SLinus Torvalds 18851da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 18869f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_REJ_BAD_ADDR; 1887a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 18881da177e4SLinus Torvalds } 18891da177e4SLinus Torvalds } 18901da177e4SLinus Torvalds 18916039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 18921da177e4SLinus Torvalds { 1893a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 189404837f64SMarcel Holtmann struct hci_conn *conn; 18951da177e4SLinus Torvalds 18969f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 18971da177e4SLinus Torvalds 18981da177e4SLinus Torvalds hci_dev_lock(hdev); 18991da177e4SLinus Torvalds 190004837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1901f7520543SJohan Hedberg if (!conn) 1902f7520543SJohan Hedberg goto unlock; 1903f7520543SJohan Hedberg 190437d9ef76SJohan Hedberg if (ev->status == 0) 19051da177e4SLinus Torvalds conn->state = BT_CLOSED; 19067d0db0a3SMarcel Holtmann 1907b644ba33SJohan Hedberg if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) && 1908b644ba33SJohan Hedberg (conn->type == ACL_LINK || conn->type == LE_LINK)) { 190937d9ef76SJohan Hedberg if (ev->status != 0) 191088c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 191188c3df13SJohan Hedberg conn->dst_type, ev->status); 191237d9ef76SJohan Hedberg else 1913afc747a6SJohan Hedberg mgmt_device_disconnected(hdev, &conn->dst, conn->type, 191448264f06SJohan Hedberg conn->dst_type); 191537d9ef76SJohan Hedberg } 1916f7520543SJohan Hedberg 191737d9ef76SJohan Hedberg if (ev->status == 0) { 19186ec5bcadSVishal Agarwal if (conn->type == ACL_LINK && conn->flush_key) 19196ec5bcadSVishal Agarwal hci_remove_link_key(hdev, &conn->dst); 19202950f21aSMarcel Holtmann hci_proto_disconn_cfm(conn, ev->reason); 19211da177e4SLinus Torvalds hci_conn_del(conn); 192237d9ef76SJohan Hedberg } 19231da177e4SLinus Torvalds 1924f7520543SJohan Hedberg unlock: 19251da177e4SLinus Torvalds hci_dev_unlock(hdev); 19261da177e4SLinus Torvalds } 19271da177e4SLinus Torvalds 19286039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1929a9de9248SMarcel Holtmann { 1930a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 1931a9de9248SMarcel Holtmann struct hci_conn *conn; 1932a9de9248SMarcel Holtmann 19339f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 1934a9de9248SMarcel Holtmann 1935a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1936a9de9248SMarcel Holtmann 1937a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1938d7556e20SWaldemar Rymarkiewicz if (!conn) 1939d7556e20SWaldemar Rymarkiewicz goto unlock; 1940d7556e20SWaldemar Rymarkiewicz 1941765c2a96SJohan Hedberg if (!ev->status) { 1942aa64a8b5SJohan Hedberg if (!hci_conn_ssp_enabled(conn) && 194351a8efd7SJohan Hedberg test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) { 1944d7556e20SWaldemar Rymarkiewicz BT_INFO("re-auth of legacy device is not possible."); 194519f8def0SWaldemar Rymarkiewicz } else { 1946a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1947765c2a96SJohan Hedberg conn->sec_level = conn->pending_sec_level; 194819f8def0SWaldemar Rymarkiewicz } 19492a611692SJohan Hedberg } else { 1950bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 1951bab73cb6SJohan Hedberg ev->status); 19522a611692SJohan Hedberg } 1953a9de9248SMarcel Holtmann 195451a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 195551a8efd7SJohan Hedberg clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags); 1956a9de9248SMarcel Holtmann 1957f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1958aa64a8b5SJohan Hedberg if (!ev->status && hci_conn_ssp_enabled(conn)) { 1959f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1960f8558555SMarcel Holtmann cp.handle = ev->handle; 1961f8558555SMarcel Holtmann cp.encrypt = 0x01; 1962d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1963d7556e20SWaldemar Rymarkiewicz &cp); 1964f8558555SMarcel Holtmann } else { 1965f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1966f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1967f8558555SMarcel Holtmann hci_conn_put(conn); 1968f8558555SMarcel Holtmann } 1969052b30b0SMarcel Holtmann } else { 1970a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 1971a9de9248SMarcel Holtmann 1972052b30b0SMarcel Holtmann hci_conn_hold(conn); 1973052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1974052b30b0SMarcel Holtmann hci_conn_put(conn); 1975052b30b0SMarcel Holtmann } 1976052b30b0SMarcel Holtmann 197751a8efd7SJohan Hedberg if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) { 1978a9de9248SMarcel Holtmann if (!ev->status) { 1979a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1980f8558555SMarcel Holtmann cp.handle = ev->handle; 1981f8558555SMarcel Holtmann cp.encrypt = 0x01; 1982d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1983d7556e20SWaldemar Rymarkiewicz &cp); 1984a9de9248SMarcel Holtmann } else { 198551a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 1986a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 1987a9de9248SMarcel Holtmann } 1988a9de9248SMarcel Holtmann } 1989a9de9248SMarcel Holtmann 1990d7556e20SWaldemar Rymarkiewicz unlock: 1991a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1992a9de9248SMarcel Holtmann } 1993a9de9248SMarcel Holtmann 19946039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 1995a9de9248SMarcel Holtmann { 1996127178d2SJohan Hedberg struct hci_ev_remote_name *ev = (void *) skb->data; 1997127178d2SJohan Hedberg struct hci_conn *conn; 1998127178d2SJohan Hedberg 1999a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2000a9de9248SMarcel Holtmann 2001a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 2002127178d2SJohan Hedberg 2003127178d2SJohan Hedberg hci_dev_lock(hdev); 2004127178d2SJohan Hedberg 2005127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2006b644ba33SJohan Hedberg 2007b644ba33SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 2008b644ba33SJohan Hedberg goto check_auth; 2009b644ba33SJohan Hedberg 2010b644ba33SJohan Hedberg if (ev->status == 0) 2011b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name, 2012b644ba33SJohan Hedberg strnlen(ev->name, HCI_MAX_NAME_LENGTH)); 2013b644ba33SJohan Hedberg else 2014b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0); 2015b644ba33SJohan Hedberg 2016b644ba33SJohan Hedberg check_auth: 201779c6c70cSJohan Hedberg if (!conn) 201879c6c70cSJohan Hedberg goto unlock; 201979c6c70cSJohan Hedberg 202079c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 202179c6c70cSJohan Hedberg goto unlock; 202279c6c70cSJohan Hedberg 202351a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 2024127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 2025127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 2026127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 2027127178d2SJohan Hedberg } 2028127178d2SJohan Hedberg 202979c6c70cSJohan Hedberg unlock: 2030127178d2SJohan Hedberg hci_dev_unlock(hdev); 2031a9de9248SMarcel Holtmann } 2032a9de9248SMarcel Holtmann 20336039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2034a9de9248SMarcel Holtmann { 2035a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 2036a9de9248SMarcel Holtmann struct hci_conn *conn; 2037a9de9248SMarcel Holtmann 20389f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2039a9de9248SMarcel Holtmann 2040a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2041a9de9248SMarcel Holtmann 2042a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2043a9de9248SMarcel Holtmann if (conn) { 2044a9de9248SMarcel Holtmann if (!ev->status) { 2045ae293196SMarcel Holtmann if (ev->encrypt) { 2046ae293196SMarcel Holtmann /* Encryption implies authentication */ 2047ae293196SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 2048a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 2049da85e5e5SVinicius Costa Gomes conn->sec_level = conn->pending_sec_level; 2050ae293196SMarcel Holtmann } else 2051a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_ENCRYPT; 2052a9de9248SMarcel Holtmann } 2053a9de9248SMarcel Holtmann 205451a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 2055a9de9248SMarcel Holtmann 2056a7d7723aSGustavo Padovan if (ev->status && conn->state == BT_CONNECTED) { 2057d839c813SGustavo Padovan hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE); 2058a7d7723aSGustavo Padovan hci_conn_put(conn); 2059a7d7723aSGustavo Padovan goto unlock; 2060a7d7723aSGustavo Padovan } 2061a7d7723aSGustavo Padovan 2062f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 2063f8558555SMarcel Holtmann if (!ev->status) 2064f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 2065f8558555SMarcel Holtmann 2066f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2067f8558555SMarcel Holtmann hci_conn_put(conn); 2068f8558555SMarcel Holtmann } else 2069a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 2070a9de9248SMarcel Holtmann } 2071a9de9248SMarcel Holtmann 2072a7d7723aSGustavo Padovan unlock: 2073a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2074a9de9248SMarcel Holtmann } 2075a9de9248SMarcel Holtmann 20766039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev, 2077807deac2SGustavo Padovan struct sk_buff *skb) 2078a9de9248SMarcel Holtmann { 2079a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 2080a9de9248SMarcel Holtmann struct hci_conn *conn; 2081a9de9248SMarcel Holtmann 20829f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2083a9de9248SMarcel Holtmann 2084a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2085a9de9248SMarcel Holtmann 2086a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2087a9de9248SMarcel Holtmann if (conn) { 2088a9de9248SMarcel Holtmann if (!ev->status) 2089a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_SECURE; 2090a9de9248SMarcel Holtmann 209151a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 2092a9de9248SMarcel Holtmann 2093a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 2094a9de9248SMarcel Holtmann } 2095a9de9248SMarcel Holtmann 2096a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2097a9de9248SMarcel Holtmann } 2098a9de9248SMarcel Holtmann 20996039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev, 2100807deac2SGustavo Padovan struct sk_buff *skb) 2101a9de9248SMarcel Holtmann { 2102a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 2103a9de9248SMarcel Holtmann struct hci_conn *conn; 2104a9de9248SMarcel Holtmann 21059f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2106a9de9248SMarcel Holtmann 2107a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2108a9de9248SMarcel Holtmann 2109a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2110ccd556feSJohan Hedberg if (!conn) 2111ccd556feSJohan Hedberg goto unlock; 2112ccd556feSJohan Hedberg 2113769be974SMarcel Holtmann if (!ev->status) 2114a9de9248SMarcel Holtmann memcpy(conn->features, ev->features, 8); 2115a9de9248SMarcel Holtmann 2116ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2117ccd556feSJohan Hedberg goto unlock; 2118ccd556feSJohan Hedberg 2119ccd556feSJohan Hedberg if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { 2120769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 2121769be974SMarcel Holtmann cp.handle = ev->handle; 2122769be974SMarcel Holtmann cp.page = 0x01; 2123ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 2124769be974SMarcel Holtmann sizeof(cp), &cp); 2125392599b9SJohan Hedberg goto unlock; 2126392599b9SJohan Hedberg } 2127392599b9SJohan Hedberg 2128671267bfSJohan Hedberg if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { 2129127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2130127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2131127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2132127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2133127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2134b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 2135b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 213608c79b61SJohan Hedberg conn->dst_type, 0, NULL, 0, 2137b644ba33SJohan Hedberg conn->dev_class); 2138392599b9SJohan Hedberg 2139127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2140769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2141769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2142769be974SMarcel Holtmann hci_conn_put(conn); 2143769be974SMarcel Holtmann } 2144769be974SMarcel Holtmann 2145ccd556feSJohan Hedberg unlock: 2146a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2147a9de9248SMarcel Holtmann } 2148a9de9248SMarcel Holtmann 21496039aa73SGustavo Padovan static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) 21506039aa73SGustavo Padovan { 21516039aa73SGustavo Padovan BT_DBG("%s", hdev->name); 21526039aa73SGustavo Padovan } 21536039aa73SGustavo Padovan 21546039aa73SGustavo Padovan static void hci_qos_setup_complete_evt(struct hci_dev *hdev, 2155807deac2SGustavo Padovan struct sk_buff *skb) 2156a9de9248SMarcel Holtmann { 2157a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2158a9de9248SMarcel Holtmann } 2159a9de9248SMarcel Holtmann 21606039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2161a9de9248SMarcel Holtmann { 2162a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 2163a9de9248SMarcel Holtmann __u16 opcode; 2164a9de9248SMarcel Holtmann 2165a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2166a9de9248SMarcel Holtmann 2167a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2168a9de9248SMarcel Holtmann 2169a9de9248SMarcel Holtmann switch (opcode) { 2170a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 2171a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 2172a9de9248SMarcel Holtmann break; 2173a9de9248SMarcel Holtmann 21744d93483bSAndre Guedes case HCI_OP_PERIODIC_INQ: 21754d93483bSAndre Guedes hci_cc_periodic_inq(hdev, skb); 21764d93483bSAndre Guedes break; 21774d93483bSAndre Guedes 2178a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 2179a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 2180a9de9248SMarcel Holtmann break; 2181a9de9248SMarcel Holtmann 2182a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 2183a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 2184a9de9248SMarcel Holtmann break; 2185a9de9248SMarcel Holtmann 2186a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 2187a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 2188a9de9248SMarcel Holtmann break; 2189a9de9248SMarcel Holtmann 2190e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 2191e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 2192e4e8e37cSMarcel Holtmann break; 2193e4e8e37cSMarcel Holtmann 2194a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 2195a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 2196a9de9248SMarcel Holtmann break; 2197a9de9248SMarcel Holtmann 2198e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 2199e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 2200e4e8e37cSMarcel Holtmann break; 2201e4e8e37cSMarcel Holtmann 2202e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 2203e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 2204e4e8e37cSMarcel Holtmann break; 2205e4e8e37cSMarcel Holtmann 2206a9de9248SMarcel Holtmann case HCI_OP_RESET: 2207a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 2208a9de9248SMarcel Holtmann break; 2209a9de9248SMarcel Holtmann 2210a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 2211a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 2212a9de9248SMarcel Holtmann break; 2213a9de9248SMarcel Holtmann 2214a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 2215a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 2216a9de9248SMarcel Holtmann break; 2217a9de9248SMarcel Holtmann 2218a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 2219a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 2220a9de9248SMarcel Holtmann break; 2221a9de9248SMarcel Holtmann 2222a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 2223a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 2224a9de9248SMarcel Holtmann break; 2225a9de9248SMarcel Holtmann 2226a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 2227a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 2228a9de9248SMarcel Holtmann break; 2229a9de9248SMarcel Holtmann 2230a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 2231a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 2232a9de9248SMarcel Holtmann break; 2233a9de9248SMarcel Holtmann 2234a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 2235a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 2236a9de9248SMarcel Holtmann break; 2237a9de9248SMarcel Holtmann 2238a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 2239a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 2240a9de9248SMarcel Holtmann break; 2241a9de9248SMarcel Holtmann 2242a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 2243a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 2244a9de9248SMarcel Holtmann break; 2245a9de9248SMarcel Holtmann 2246a9de9248SMarcel Holtmann case HCI_OP_HOST_BUFFER_SIZE: 2247a9de9248SMarcel Holtmann hci_cc_host_buffer_size(hdev, skb); 2248a9de9248SMarcel Holtmann break; 2249a9de9248SMarcel Holtmann 2250333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 2251333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 2252333140b5SMarcel Holtmann break; 2253333140b5SMarcel Holtmann 2254a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 2255a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 2256a9de9248SMarcel Holtmann break; 2257a9de9248SMarcel Holtmann 2258a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 2259a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 2260a9de9248SMarcel Holtmann break; 2261a9de9248SMarcel Holtmann 2262a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 2263a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 2264a9de9248SMarcel Holtmann break; 2265a9de9248SMarcel Holtmann 2266971e3a4bSAndre Guedes case HCI_OP_READ_LOCAL_EXT_FEATURES: 2267971e3a4bSAndre Guedes hci_cc_read_local_ext_features(hdev, skb); 2268971e3a4bSAndre Guedes break; 2269971e3a4bSAndre Guedes 2270a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 2271a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 2272a9de9248SMarcel Holtmann break; 2273a9de9248SMarcel Holtmann 2274a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 2275a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 2276a9de9248SMarcel Holtmann break; 2277a9de9248SMarcel Holtmann 2278350ee4cfSAndrei Emeltchenko case HCI_OP_READ_DATA_BLOCK_SIZE: 2279350ee4cfSAndrei Emeltchenko hci_cc_read_data_block_size(hdev, skb); 2280350ee4cfSAndrei Emeltchenko break; 2281350ee4cfSAndrei Emeltchenko 228223bb5763SJohan Hedberg case HCI_OP_WRITE_CA_TIMEOUT: 228323bb5763SJohan Hedberg hci_cc_write_ca_timeout(hdev, skb); 228423bb5763SJohan Hedberg break; 228523bb5763SJohan Hedberg 22861e89cffbSAndrei Emeltchenko case HCI_OP_READ_FLOW_CONTROL_MODE: 22871e89cffbSAndrei Emeltchenko hci_cc_read_flow_control_mode(hdev, skb); 22881e89cffbSAndrei Emeltchenko break; 22891e89cffbSAndrei Emeltchenko 2290928abaa7SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_INFO: 2291928abaa7SAndrei Emeltchenko hci_cc_read_local_amp_info(hdev, skb); 2292928abaa7SAndrei Emeltchenko break; 2293928abaa7SAndrei Emeltchenko 2294b0916ea0SJohan Hedberg case HCI_OP_DELETE_STORED_LINK_KEY: 2295b0916ea0SJohan Hedberg hci_cc_delete_stored_link_key(hdev, skb); 2296b0916ea0SJohan Hedberg break; 2297b0916ea0SJohan Hedberg 2298d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_MASK: 2299d5859e22SJohan Hedberg hci_cc_set_event_mask(hdev, skb); 2300d5859e22SJohan Hedberg break; 2301d5859e22SJohan Hedberg 2302d5859e22SJohan Hedberg case HCI_OP_WRITE_INQUIRY_MODE: 2303d5859e22SJohan Hedberg hci_cc_write_inquiry_mode(hdev, skb); 2304d5859e22SJohan Hedberg break; 2305d5859e22SJohan Hedberg 2306d5859e22SJohan Hedberg case HCI_OP_READ_INQ_RSP_TX_POWER: 2307d5859e22SJohan Hedberg hci_cc_read_inq_rsp_tx_power(hdev, skb); 2308d5859e22SJohan Hedberg break; 2309d5859e22SJohan Hedberg 2310d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_FLT: 2311d5859e22SJohan Hedberg hci_cc_set_event_flt(hdev, skb); 2312d5859e22SJohan Hedberg break; 2313d5859e22SJohan Hedberg 2314980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_REPLY: 2315980e1a53SJohan Hedberg hci_cc_pin_code_reply(hdev, skb); 2316980e1a53SJohan Hedberg break; 2317980e1a53SJohan Hedberg 2318980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_NEG_REPLY: 2319980e1a53SJohan Hedberg hci_cc_pin_code_neg_reply(hdev, skb); 2320980e1a53SJohan Hedberg break; 2321980e1a53SJohan Hedberg 2322c35938b2SSzymon Janc case HCI_OP_READ_LOCAL_OOB_DATA: 2323c35938b2SSzymon Janc hci_cc_read_local_oob_data_reply(hdev, skb); 2324c35938b2SSzymon Janc break; 2325c35938b2SSzymon Janc 23266ed58ec5SVille Tervo case HCI_OP_LE_READ_BUFFER_SIZE: 23276ed58ec5SVille Tervo hci_cc_le_read_buffer_size(hdev, skb); 23286ed58ec5SVille Tervo break; 23296ed58ec5SVille Tervo 2330a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_REPLY: 2331a5c29683SJohan Hedberg hci_cc_user_confirm_reply(hdev, skb); 2332a5c29683SJohan Hedberg break; 2333a5c29683SJohan Hedberg 2334a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_NEG_REPLY: 2335a5c29683SJohan Hedberg hci_cc_user_confirm_neg_reply(hdev, skb); 2336a5c29683SJohan Hedberg break; 2337a5c29683SJohan Hedberg 23381143d458SBrian Gix case HCI_OP_USER_PASSKEY_REPLY: 23391143d458SBrian Gix hci_cc_user_passkey_reply(hdev, skb); 23401143d458SBrian Gix break; 23411143d458SBrian Gix 23421143d458SBrian Gix case HCI_OP_USER_PASSKEY_NEG_REPLY: 23431143d458SBrian Gix hci_cc_user_passkey_neg_reply(hdev, skb); 234416cde993SSzymon Janc break; 234507f7fa5dSAndre Guedes 234607f7fa5dSAndre Guedes case HCI_OP_LE_SET_SCAN_PARAM: 234707f7fa5dSAndre Guedes hci_cc_le_set_scan_param(hdev, skb); 23481143d458SBrian Gix break; 23491143d458SBrian Gix 2350eb9d91f5SAndre Guedes case HCI_OP_LE_SET_SCAN_ENABLE: 2351eb9d91f5SAndre Guedes hci_cc_le_set_scan_enable(hdev, skb); 2352eb9d91f5SAndre Guedes break; 2353eb9d91f5SAndre Guedes 2354a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_REPLY: 2355a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_reply(hdev, skb); 2356a7a595f6SVinicius Costa Gomes break; 2357a7a595f6SVinicius Costa Gomes 2358a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_NEG_REPLY: 2359a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_neg_reply(hdev, skb); 2360a7a595f6SVinicius Costa Gomes break; 2361a7a595f6SVinicius Costa Gomes 2362f9b49306SAndre Guedes case HCI_OP_WRITE_LE_HOST_SUPPORTED: 2363f9b49306SAndre Guedes hci_cc_write_le_host_supported(hdev, skb); 2364f9b49306SAndre Guedes break; 2365f9b49306SAndre Guedes 2366a9de9248SMarcel Holtmann default: 23679f1db00cSAndrei Emeltchenko BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); 2368a9de9248SMarcel Holtmann break; 2369a9de9248SMarcel Holtmann } 2370a9de9248SMarcel Holtmann 23716bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 23726bd32326SVille Tervo del_timer(&hdev->cmd_timer); 23736bd32326SVille Tervo 2374a9de9248SMarcel Holtmann if (ev->ncmd) { 2375a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2376a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2377c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2378a9de9248SMarcel Holtmann } 2379a9de9248SMarcel Holtmann } 2380a9de9248SMarcel Holtmann 23816039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 2382a9de9248SMarcel Holtmann { 2383a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 2384a9de9248SMarcel Holtmann __u16 opcode; 2385a9de9248SMarcel Holtmann 2386a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2387a9de9248SMarcel Holtmann 2388a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2389a9de9248SMarcel Holtmann 2390a9de9248SMarcel Holtmann switch (opcode) { 2391a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 2392a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 2393a9de9248SMarcel Holtmann break; 2394a9de9248SMarcel Holtmann 2395a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 2396a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 2397a9de9248SMarcel Holtmann break; 2398a9de9248SMarcel Holtmann 2399a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 2400a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 2401a9de9248SMarcel Holtmann break; 2402a9de9248SMarcel Holtmann 2403f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 2404f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 2405f8558555SMarcel Holtmann break; 2406f8558555SMarcel Holtmann 2407f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 2408f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 2409f8558555SMarcel Holtmann break; 2410f8558555SMarcel Holtmann 2411a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 2412a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 2413a9de9248SMarcel Holtmann break; 2414a9de9248SMarcel Holtmann 2415769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 2416769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 2417769be974SMarcel Holtmann break; 2418769be974SMarcel Holtmann 2419769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 2420769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 2421769be974SMarcel Holtmann break; 2422769be974SMarcel Holtmann 2423a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 2424a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 2425a9de9248SMarcel Holtmann break; 2426a9de9248SMarcel Holtmann 2427a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 2428a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 2429a9de9248SMarcel Holtmann break; 2430a9de9248SMarcel Holtmann 2431a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 2432a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 2433a9de9248SMarcel Holtmann break; 2434a9de9248SMarcel Holtmann 24358962ee74SJohan Hedberg case HCI_OP_DISCONNECT: 243688c3df13SJohan Hedberg hci_cs_disconnect(hdev, ev->status); 24378962ee74SJohan Hedberg break; 24388962ee74SJohan Hedberg 2439fcd89c09SVille Tervo case HCI_OP_LE_CREATE_CONN: 2440fcd89c09SVille Tervo hci_cs_le_create_conn(hdev, ev->status); 2441fcd89c09SVille Tervo break; 2442fcd89c09SVille Tervo 2443a7a595f6SVinicius Costa Gomes case HCI_OP_LE_START_ENC: 2444a7a595f6SVinicius Costa Gomes hci_cs_le_start_enc(hdev, ev->status); 2445a7a595f6SVinicius Costa Gomes break; 2446a7a595f6SVinicius Costa Gomes 2447a9de9248SMarcel Holtmann default: 24489f1db00cSAndrei Emeltchenko BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); 2449a9de9248SMarcel Holtmann break; 2450a9de9248SMarcel Holtmann } 2451a9de9248SMarcel Holtmann 24526bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 24536bd32326SVille Tervo del_timer(&hdev->cmd_timer); 24546bd32326SVille Tervo 245510572132SGustavo F. Padovan if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2456a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2457a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2458c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2459a9de9248SMarcel Holtmann } 2460a9de9248SMarcel Holtmann } 2461a9de9248SMarcel Holtmann 24626039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2463a9de9248SMarcel Holtmann { 2464a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 2465a9de9248SMarcel Holtmann struct hci_conn *conn; 2466a9de9248SMarcel Holtmann 24679f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2468a9de9248SMarcel Holtmann 2469a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2470a9de9248SMarcel Holtmann 2471a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2472a9de9248SMarcel Holtmann if (conn) { 2473a9de9248SMarcel Holtmann if (!ev->status) { 2474a9de9248SMarcel Holtmann if (ev->role) 2475a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_MASTER; 2476a9de9248SMarcel Holtmann else 2477a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_MASTER; 2478a9de9248SMarcel Holtmann } 2479a9de9248SMarcel Holtmann 248051a8efd7SJohan Hedberg clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); 2481a9de9248SMarcel Holtmann 2482a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 2483a9de9248SMarcel Holtmann } 2484a9de9248SMarcel Holtmann 2485a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2486a9de9248SMarcel Holtmann } 2487a9de9248SMarcel Holtmann 24886039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 24891da177e4SLinus Torvalds { 2490a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 24911da177e4SLinus Torvalds int i; 24921da177e4SLinus Torvalds 249332ac5b9bSAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) { 249432ac5b9bSAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 249532ac5b9bSAndrei Emeltchenko return; 249632ac5b9bSAndrei Emeltchenko } 249732ac5b9bSAndrei Emeltchenko 2498c5993de8SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 2499c5993de8SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_pkts_info)) { 25001da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 25011da177e4SLinus Torvalds return; 25021da177e4SLinus Torvalds } 25031da177e4SLinus Torvalds 2504c5993de8SAndrei Emeltchenko BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 2505c5993de8SAndrei Emeltchenko 2506613a1c0cSAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 2507613a1c0cSAndrei Emeltchenko struct hci_comp_pkts_info *info = &ev->handles[i]; 25081da177e4SLinus Torvalds struct hci_conn *conn; 25091da177e4SLinus Torvalds __u16 handle, count; 25101da177e4SLinus Torvalds 2511613a1c0cSAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 2512613a1c0cSAndrei Emeltchenko count = __le16_to_cpu(info->count); 25131da177e4SLinus Torvalds 25141da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 2515f4280918SAndrei Emeltchenko if (!conn) 2516f4280918SAndrei Emeltchenko continue; 2517f4280918SAndrei Emeltchenko 25181da177e4SLinus Torvalds conn->sent -= count; 25191da177e4SLinus Torvalds 2520f4280918SAndrei Emeltchenko switch (conn->type) { 2521f4280918SAndrei Emeltchenko case ACL_LINK: 252270f23020SAndrei Emeltchenko hdev->acl_cnt += count; 252370f23020SAndrei Emeltchenko if (hdev->acl_cnt > hdev->acl_pkts) 25241da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 2525f4280918SAndrei Emeltchenko break; 2526f4280918SAndrei Emeltchenko 2527f4280918SAndrei Emeltchenko case LE_LINK: 25286ed58ec5SVille Tervo if (hdev->le_pkts) { 25296ed58ec5SVille Tervo hdev->le_cnt += count; 25306ed58ec5SVille Tervo if (hdev->le_cnt > hdev->le_pkts) 25316ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 25326ed58ec5SVille Tervo } else { 25336ed58ec5SVille Tervo hdev->acl_cnt += count; 25346ed58ec5SVille Tervo if (hdev->acl_cnt > hdev->acl_pkts) 25356ed58ec5SVille Tervo hdev->acl_cnt = hdev->acl_pkts; 25366ed58ec5SVille Tervo } 2537f4280918SAndrei Emeltchenko break; 2538f4280918SAndrei Emeltchenko 2539f4280918SAndrei Emeltchenko case SCO_LINK: 254070f23020SAndrei Emeltchenko hdev->sco_cnt += count; 254170f23020SAndrei Emeltchenko if (hdev->sco_cnt > hdev->sco_pkts) 25425b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 2543f4280918SAndrei Emeltchenko break; 2544f4280918SAndrei Emeltchenko 2545f4280918SAndrei Emeltchenko default: 2546f4280918SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 2547f4280918SAndrei Emeltchenko break; 25481da177e4SLinus Torvalds } 25491da177e4SLinus Torvalds } 2550a9de9248SMarcel Holtmann 25513eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 25521da177e4SLinus Torvalds } 25531da177e4SLinus Torvalds 25546039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb) 255525e89e99SAndrei Emeltchenko { 255625e89e99SAndrei Emeltchenko struct hci_ev_num_comp_blocks *ev = (void *) skb->data; 255725e89e99SAndrei Emeltchenko int i; 255825e89e99SAndrei Emeltchenko 255925e89e99SAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) { 256025e89e99SAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 256125e89e99SAndrei Emeltchenko return; 256225e89e99SAndrei Emeltchenko } 256325e89e99SAndrei Emeltchenko 256425e89e99SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 256525e89e99SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_blocks_info)) { 256625e89e99SAndrei Emeltchenko BT_DBG("%s bad parameters", hdev->name); 256725e89e99SAndrei Emeltchenko return; 256825e89e99SAndrei Emeltchenko } 256925e89e99SAndrei Emeltchenko 257025e89e99SAndrei Emeltchenko BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks, 257125e89e99SAndrei Emeltchenko ev->num_hndl); 257225e89e99SAndrei Emeltchenko 257325e89e99SAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 257425e89e99SAndrei Emeltchenko struct hci_comp_blocks_info *info = &ev->handles[i]; 257525e89e99SAndrei Emeltchenko struct hci_conn *conn; 257625e89e99SAndrei Emeltchenko __u16 handle, block_count; 257725e89e99SAndrei Emeltchenko 257825e89e99SAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 257925e89e99SAndrei Emeltchenko block_count = __le16_to_cpu(info->blocks); 258025e89e99SAndrei Emeltchenko 258125e89e99SAndrei Emeltchenko conn = hci_conn_hash_lookup_handle(hdev, handle); 258225e89e99SAndrei Emeltchenko if (!conn) 258325e89e99SAndrei Emeltchenko continue; 258425e89e99SAndrei Emeltchenko 258525e89e99SAndrei Emeltchenko conn->sent -= block_count; 258625e89e99SAndrei Emeltchenko 258725e89e99SAndrei Emeltchenko switch (conn->type) { 258825e89e99SAndrei Emeltchenko case ACL_LINK: 258925e89e99SAndrei Emeltchenko hdev->block_cnt += block_count; 259025e89e99SAndrei Emeltchenko if (hdev->block_cnt > hdev->num_blocks) 259125e89e99SAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 259225e89e99SAndrei Emeltchenko break; 259325e89e99SAndrei Emeltchenko 259425e89e99SAndrei Emeltchenko default: 259525e89e99SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 259625e89e99SAndrei Emeltchenko break; 259725e89e99SAndrei Emeltchenko } 259825e89e99SAndrei Emeltchenko } 259925e89e99SAndrei Emeltchenko 260025e89e99SAndrei Emeltchenko queue_work(hdev->workqueue, &hdev->tx_work); 260125e89e99SAndrei Emeltchenko } 260225e89e99SAndrei Emeltchenko 26036039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 26041da177e4SLinus Torvalds { 2605a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 260604837f64SMarcel Holtmann struct hci_conn *conn; 26071da177e4SLinus Torvalds 26089f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 26091da177e4SLinus Torvalds 26101da177e4SLinus Torvalds hci_dev_lock(hdev); 26111da177e4SLinus Torvalds 261204837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 261304837f64SMarcel Holtmann if (conn) { 261404837f64SMarcel Holtmann conn->mode = ev->mode; 261504837f64SMarcel Holtmann conn->interval = __le16_to_cpu(ev->interval); 261604837f64SMarcel Holtmann 26178fc9ced3SGustavo Padovan if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, 26188fc9ced3SGustavo Padovan &conn->flags)) { 261904837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 262058a681efSJohan Hedberg set_bit(HCI_CONN_POWER_SAVE, &conn->flags); 262104837f64SMarcel Holtmann else 262258a681efSJohan Hedberg clear_bit(HCI_CONN_POWER_SAVE, &conn->flags); 262304837f64SMarcel Holtmann } 2624e73439d8SMarcel Holtmann 262551a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 2626e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 262704837f64SMarcel Holtmann } 262804837f64SMarcel Holtmann 262904837f64SMarcel Holtmann hci_dev_unlock(hdev); 263004837f64SMarcel Holtmann } 263104837f64SMarcel Holtmann 26326039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 26331da177e4SLinus Torvalds { 2634052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 2635052b30b0SMarcel Holtmann struct hci_conn *conn; 2636052b30b0SMarcel Holtmann 2637a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2638052b30b0SMarcel Holtmann 2639052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2640052b30b0SMarcel Holtmann 2641052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2642b6f98044SWaldemar Rymarkiewicz if (!conn) 2643b6f98044SWaldemar Rymarkiewicz goto unlock; 2644b6f98044SWaldemar Rymarkiewicz 2645b6f98044SWaldemar Rymarkiewicz if (conn->state == BT_CONNECTED) { 2646052b30b0SMarcel Holtmann hci_conn_hold(conn); 2647052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 2648052b30b0SMarcel Holtmann hci_conn_put(conn); 2649052b30b0SMarcel Holtmann } 2650052b30b0SMarcel Holtmann 2651a8b2d5c2SJohan Hedberg if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags)) 265203b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 265303b555e1SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 2654a8b2d5c2SJohan Hedberg else if (test_bit(HCI_MGMT, &hdev->dev_flags)) { 2655a770bb5aSWaldemar Rymarkiewicz u8 secure; 2656a770bb5aSWaldemar Rymarkiewicz 2657a770bb5aSWaldemar Rymarkiewicz if (conn->pending_sec_level == BT_SECURITY_HIGH) 2658a770bb5aSWaldemar Rymarkiewicz secure = 1; 2659a770bb5aSWaldemar Rymarkiewicz else 2660a770bb5aSWaldemar Rymarkiewicz secure = 0; 2661a770bb5aSWaldemar Rymarkiewicz 2662744cf19eSJohan Hedberg mgmt_pin_code_request(hdev, &ev->bdaddr, secure); 2663a770bb5aSWaldemar Rymarkiewicz } 2664980e1a53SJohan Hedberg 2665b6f98044SWaldemar Rymarkiewicz unlock: 2666052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 26671da177e4SLinus Torvalds } 26681da177e4SLinus Torvalds 26696039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 26701da177e4SLinus Torvalds { 267155ed8ca1SJohan Hedberg struct hci_ev_link_key_req *ev = (void *) skb->data; 267255ed8ca1SJohan Hedberg struct hci_cp_link_key_reply cp; 267355ed8ca1SJohan Hedberg struct hci_conn *conn; 267455ed8ca1SJohan Hedberg struct link_key *key; 267555ed8ca1SJohan Hedberg 2676a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 267755ed8ca1SJohan Hedberg 2678a8b2d5c2SJohan Hedberg if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) 267955ed8ca1SJohan Hedberg return; 268055ed8ca1SJohan Hedberg 268155ed8ca1SJohan Hedberg hci_dev_lock(hdev); 268255ed8ca1SJohan Hedberg 268355ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, &ev->bdaddr); 268455ed8ca1SJohan Hedberg if (!key) { 268555ed8ca1SJohan Hedberg BT_DBG("%s link key not found for %s", hdev->name, 268655ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 268755ed8ca1SJohan Hedberg goto not_found; 268855ed8ca1SJohan Hedberg } 268955ed8ca1SJohan Hedberg 269055ed8ca1SJohan Hedberg BT_DBG("%s found key type %u for %s", hdev->name, key->type, 269155ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 269255ed8ca1SJohan Hedberg 2693a8b2d5c2SJohan Hedberg if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) && 2694b6020ba0SWaldemar Rymarkiewicz key->type == HCI_LK_DEBUG_COMBINATION) { 269555ed8ca1SJohan Hedberg BT_DBG("%s ignoring debug key", hdev->name); 269655ed8ca1SJohan Hedberg goto not_found; 269755ed8ca1SJohan Hedberg } 269855ed8ca1SJohan Hedberg 269955ed8ca1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 270060b83f57SWaldemar Rymarkiewicz if (conn) { 270160b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_UNAUTH_COMBINATION && 2702807deac2SGustavo Padovan conn->auth_type != 0xff && (conn->auth_type & 0x01)) { 270355ed8ca1SJohan Hedberg BT_DBG("%s ignoring unauthenticated key", hdev->name); 270455ed8ca1SJohan Hedberg goto not_found; 270555ed8ca1SJohan Hedberg } 270655ed8ca1SJohan Hedberg 270760b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && 270860b83f57SWaldemar Rymarkiewicz conn->pending_sec_level == BT_SECURITY_HIGH) { 27098fc9ced3SGustavo Padovan BT_DBG("%s ignoring key unauthenticated for high security", 27108fc9ced3SGustavo Padovan hdev->name); 271160b83f57SWaldemar Rymarkiewicz goto not_found; 271260b83f57SWaldemar Rymarkiewicz } 271360b83f57SWaldemar Rymarkiewicz 271460b83f57SWaldemar Rymarkiewicz conn->key_type = key->type; 271560b83f57SWaldemar Rymarkiewicz conn->pin_length = key->pin_len; 271660b83f57SWaldemar Rymarkiewicz } 271760b83f57SWaldemar Rymarkiewicz 271855ed8ca1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 27199b3b4460SAndrei Emeltchenko memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE); 272055ed8ca1SJohan Hedberg 272155ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 272255ed8ca1SJohan Hedberg 272355ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 272455ed8ca1SJohan Hedberg 272555ed8ca1SJohan Hedberg return; 272655ed8ca1SJohan Hedberg 272755ed8ca1SJohan Hedberg not_found: 272855ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 272955ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 27301da177e4SLinus Torvalds } 27311da177e4SLinus Torvalds 27326039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 27331da177e4SLinus Torvalds { 2734052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 2735052b30b0SMarcel Holtmann struct hci_conn *conn; 273655ed8ca1SJohan Hedberg u8 pin_len = 0; 2737052b30b0SMarcel Holtmann 2738a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2739052b30b0SMarcel Holtmann 2740052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2741052b30b0SMarcel Holtmann 2742052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2743052b30b0SMarcel Holtmann if (conn) { 2744052b30b0SMarcel Holtmann hci_conn_hold(conn); 2745052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2746980e1a53SJohan Hedberg pin_len = conn->pin_length; 274713d39315SWaldemar Rymarkiewicz 274813d39315SWaldemar Rymarkiewicz if (ev->key_type != HCI_LK_CHANGED_COMBINATION) 274913d39315SWaldemar Rymarkiewicz conn->key_type = ev->key_type; 275013d39315SWaldemar Rymarkiewicz 2751052b30b0SMarcel Holtmann hci_conn_put(conn); 2752052b30b0SMarcel Holtmann } 2753052b30b0SMarcel Holtmann 2754a8b2d5c2SJohan Hedberg if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) 2755d25e28abSJohan Hedberg hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, 275655ed8ca1SJohan Hedberg ev->key_type, pin_len); 275755ed8ca1SJohan Hedberg 2758052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 27591da177e4SLinus Torvalds } 27601da177e4SLinus Torvalds 27616039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 276204837f64SMarcel Holtmann { 2763a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 276404837f64SMarcel Holtmann struct hci_conn *conn; 276504837f64SMarcel Holtmann 27669f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 276704837f64SMarcel Holtmann 276804837f64SMarcel Holtmann hci_dev_lock(hdev); 276904837f64SMarcel Holtmann 277004837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 27711da177e4SLinus Torvalds if (conn && !ev->status) { 27721da177e4SLinus Torvalds struct inquiry_entry *ie; 27731da177e4SLinus Torvalds 2774cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2775cc11b9c1SAndrei Emeltchenko if (ie) { 27761da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 27771da177e4SLinus Torvalds ie->timestamp = jiffies; 27781da177e4SLinus Torvalds } 27791da177e4SLinus Torvalds } 27801da177e4SLinus Torvalds 27811da177e4SLinus Torvalds hci_dev_unlock(hdev); 27821da177e4SLinus Torvalds } 27831da177e4SLinus Torvalds 27846039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2785a8746417SMarcel Holtmann { 2786a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 2787a8746417SMarcel Holtmann struct hci_conn *conn; 2788a8746417SMarcel Holtmann 27899f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2790a8746417SMarcel Holtmann 2791a8746417SMarcel Holtmann hci_dev_lock(hdev); 2792a8746417SMarcel Holtmann 2793a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2794a8746417SMarcel Holtmann if (conn && !ev->status) 2795a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 2796a8746417SMarcel Holtmann 2797a8746417SMarcel Holtmann hci_dev_unlock(hdev); 2798a8746417SMarcel Holtmann } 2799a8746417SMarcel Holtmann 28006039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 280185a1e930SMarcel Holtmann { 2802a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 280385a1e930SMarcel Holtmann struct inquiry_entry *ie; 280485a1e930SMarcel Holtmann 280585a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 280685a1e930SMarcel Holtmann 280785a1e930SMarcel Holtmann hci_dev_lock(hdev); 280885a1e930SMarcel Holtmann 2809cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2810cc11b9c1SAndrei Emeltchenko if (ie) { 281185a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 281285a1e930SMarcel Holtmann ie->timestamp = jiffies; 281385a1e930SMarcel Holtmann } 281485a1e930SMarcel Holtmann 281585a1e930SMarcel Holtmann hci_dev_unlock(hdev); 281685a1e930SMarcel Holtmann } 281785a1e930SMarcel Holtmann 28186039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, 2819807deac2SGustavo Padovan struct sk_buff *skb) 2820a9de9248SMarcel Holtmann { 2821a9de9248SMarcel Holtmann struct inquiry_data data; 2822a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2823388fc8faSJohan Hedberg bool name_known, ssp; 2824a9de9248SMarcel Holtmann 2825a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2826a9de9248SMarcel Holtmann 2827a9de9248SMarcel Holtmann if (!num_rsp) 2828a9de9248SMarcel Holtmann return; 2829a9de9248SMarcel Holtmann 28301519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 28311519cc17SAndre Guedes return; 28321519cc17SAndre Guedes 2833a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2834a9de9248SMarcel Holtmann 2835a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 2836138d22efSSzymon Janc struct inquiry_info_with_rssi_and_pscan_mode *info; 2837138d22efSSzymon Janc info = (void *) (skb->data + 1); 2838a9de9248SMarcel Holtmann 2839e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2840a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2841a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2842a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2843a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 2844a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2845a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2846a9de9248SMarcel Holtmann data.rssi = info->rssi; 284741a96212SMarcel Holtmann data.ssp_mode = 0x00; 28483175405bSJohan Hedberg 28493175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 2850388fc8faSJohan Hedberg false, &ssp); 285148264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2852e17acd40SJohan Hedberg info->dev_class, info->rssi, 2853388fc8faSJohan Hedberg !name_known, ssp, NULL, 0); 2854a9de9248SMarcel Holtmann } 2855a9de9248SMarcel Holtmann } else { 2856a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 2857a9de9248SMarcel Holtmann 2858e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2859a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2860a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2861a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2862a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2863a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2864a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2865a9de9248SMarcel Holtmann data.rssi = info->rssi; 286641a96212SMarcel Holtmann data.ssp_mode = 0x00; 28673175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 2868388fc8faSJohan Hedberg false, &ssp); 286948264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2870e17acd40SJohan Hedberg info->dev_class, info->rssi, 2871388fc8faSJohan Hedberg !name_known, ssp, NULL, 0); 2872a9de9248SMarcel Holtmann } 2873a9de9248SMarcel Holtmann } 2874a9de9248SMarcel Holtmann 2875a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2876a9de9248SMarcel Holtmann } 2877a9de9248SMarcel Holtmann 28786039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev, 2879807deac2SGustavo Padovan struct sk_buff *skb) 2880a9de9248SMarcel Holtmann { 288141a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 288241a96212SMarcel Holtmann struct hci_conn *conn; 288341a96212SMarcel Holtmann 2884a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 288541a96212SMarcel Holtmann 288641a96212SMarcel Holtmann hci_dev_lock(hdev); 288741a96212SMarcel Holtmann 288841a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2889ccd556feSJohan Hedberg if (!conn) 2890ccd556feSJohan Hedberg goto unlock; 2891ccd556feSJohan Hedberg 2892769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 289341a96212SMarcel Holtmann struct inquiry_entry *ie; 289441a96212SMarcel Holtmann 2895cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2896cc11b9c1SAndrei Emeltchenko if (ie) 289702b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 289841a96212SMarcel Holtmann 289902b7cc62SJohan Hedberg if (ev->features[0] & LMP_HOST_SSP) 290058a681efSJohan Hedberg set_bit(HCI_CONN_SSP_ENABLED, &conn->flags); 290141a96212SMarcel Holtmann } 290241a96212SMarcel Holtmann 2903ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2904ccd556feSJohan Hedberg goto unlock; 2905ccd556feSJohan Hedberg 2906671267bfSJohan Hedberg if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { 2907127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2908127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2909127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2910127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2911127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2912b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 2913b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 291408c79b61SJohan Hedberg conn->dst_type, 0, NULL, 0, 2915b644ba33SJohan Hedberg conn->dev_class); 2916392599b9SJohan Hedberg 2917127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2918769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2919769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2920769be974SMarcel Holtmann hci_conn_put(conn); 2921769be974SMarcel Holtmann } 2922769be974SMarcel Holtmann 2923ccd556feSJohan Hedberg unlock: 292441a96212SMarcel Holtmann hci_dev_unlock(hdev); 2925a9de9248SMarcel Holtmann } 2926a9de9248SMarcel Holtmann 29276039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev, 2928807deac2SGustavo Padovan struct sk_buff *skb) 2929a9de9248SMarcel Holtmann { 2930b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 2931b6a0dc82SMarcel Holtmann struct hci_conn *conn; 2932b6a0dc82SMarcel Holtmann 29339f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2934b6a0dc82SMarcel Holtmann 2935b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 2936b6a0dc82SMarcel Holtmann 2937b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 29389dc0a3afSMarcel Holtmann if (!conn) { 29399dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 29409dc0a3afSMarcel Holtmann goto unlock; 29419dc0a3afSMarcel Holtmann 29429dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 2943b6a0dc82SMarcel Holtmann if (!conn) 2944b6a0dc82SMarcel Holtmann goto unlock; 2945b6a0dc82SMarcel Holtmann 29469dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 29479dc0a3afSMarcel Holtmann } 29489dc0a3afSMarcel Holtmann 2949732547f9SMarcel Holtmann switch (ev->status) { 2950732547f9SMarcel Holtmann case 0x00: 2951732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 2952732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 2953732547f9SMarcel Holtmann 29549eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 2955732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 2956732547f9SMarcel Holtmann break; 2957732547f9SMarcel Holtmann 2958705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 2959732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 29601038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 2961732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 2962732547f9SMarcel Holtmann if (conn->out && conn->attempt < 2) { 2963efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 2964efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 2965efc7688bSMarcel Holtmann hci_setup_sync(conn, conn->link->handle); 2966efc7688bSMarcel Holtmann goto unlock; 2967efc7688bSMarcel Holtmann } 2968732547f9SMarcel Holtmann /* fall through */ 2969efc7688bSMarcel Holtmann 2970732547f9SMarcel Holtmann default: 2971b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 2972732547f9SMarcel Holtmann break; 2973732547f9SMarcel Holtmann } 2974b6a0dc82SMarcel Holtmann 2975b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2976b6a0dc82SMarcel Holtmann if (ev->status) 2977b6a0dc82SMarcel Holtmann hci_conn_del(conn); 2978b6a0dc82SMarcel Holtmann 2979b6a0dc82SMarcel Holtmann unlock: 2980b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 2981a9de9248SMarcel Holtmann } 2982a9de9248SMarcel Holtmann 29836039aa73SGustavo Padovan static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) 2984a9de9248SMarcel Holtmann { 2985a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2986a9de9248SMarcel Holtmann } 2987a9de9248SMarcel Holtmann 29886039aa73SGustavo Padovan static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) 298904837f64SMarcel Holtmann { 2990a9de9248SMarcel Holtmann struct hci_ev_sniff_subrate *ev = (void *) skb->data; 299104837f64SMarcel Holtmann 29929f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 299304837f64SMarcel Holtmann } 299404837f64SMarcel Holtmann 29956039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, 2996807deac2SGustavo Padovan struct sk_buff *skb) 2997a9de9248SMarcel Holtmann { 2998a9de9248SMarcel Holtmann struct inquiry_data data; 2999a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 3000a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 30019d939d94SVishal Agarwal size_t eir_len; 3002a9de9248SMarcel Holtmann 3003a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 3004a9de9248SMarcel Holtmann 3005a9de9248SMarcel Holtmann if (!num_rsp) 3006a9de9248SMarcel Holtmann return; 3007a9de9248SMarcel Holtmann 30081519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 30091519cc17SAndre Guedes return; 30101519cc17SAndre Guedes 3011a9de9248SMarcel Holtmann hci_dev_lock(hdev); 3012a9de9248SMarcel Holtmann 3013e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 3014388fc8faSJohan Hedberg bool name_known, ssp; 3015561aafbcSJohan Hedberg 3016a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 3017a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 3018a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 3019a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 3020a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 3021a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 3022a9de9248SMarcel Holtmann data.rssi = info->rssi; 302341a96212SMarcel Holtmann data.ssp_mode = 0x01; 3024561aafbcSJohan Hedberg 3025a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 30264ddb1930SJohan Hedberg name_known = eir_has_data_type(info->data, 30274ddb1930SJohan Hedberg sizeof(info->data), 30284ddb1930SJohan Hedberg EIR_NAME_COMPLETE); 3029561aafbcSJohan Hedberg else 3030561aafbcSJohan Hedberg name_known = true; 3031561aafbcSJohan Hedberg 3032388fc8faSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, name_known, 3033388fc8faSJohan Hedberg &ssp); 30349d939d94SVishal Agarwal eir_len = eir_get_length(info->data, sizeof(info->data)); 303548264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 303604124681SGustavo F. Padovan info->dev_class, info->rssi, !name_known, 30379d939d94SVishal Agarwal ssp, info->data, eir_len); 3038a9de9248SMarcel Holtmann } 3039a9de9248SMarcel Holtmann 3040a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 3041a9de9248SMarcel Holtmann } 3042a9de9248SMarcel Holtmann 30431c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev, 30441c2e0041SJohan Hedberg struct sk_buff *skb) 30451c2e0041SJohan Hedberg { 30461c2e0041SJohan Hedberg struct hci_ev_key_refresh_complete *ev = (void *) skb->data; 30471c2e0041SJohan Hedberg struct hci_conn *conn; 30481c2e0041SJohan Hedberg 30499f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status, 30501c2e0041SJohan Hedberg __le16_to_cpu(ev->handle)); 30511c2e0041SJohan Hedberg 30521c2e0041SJohan Hedberg hci_dev_lock(hdev); 30531c2e0041SJohan Hedberg 30541c2e0041SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 30551c2e0041SJohan Hedberg if (!conn) 30561c2e0041SJohan Hedberg goto unlock; 30571c2e0041SJohan Hedberg 30581c2e0041SJohan Hedberg if (!ev->status) 30591c2e0041SJohan Hedberg conn->sec_level = conn->pending_sec_level; 30601c2e0041SJohan Hedberg 30611c2e0041SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 30621c2e0041SJohan Hedberg 30631c2e0041SJohan Hedberg if (ev->status && conn->state == BT_CONNECTED) { 30641c2e0041SJohan Hedberg hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE); 30651c2e0041SJohan Hedberg hci_conn_put(conn); 30661c2e0041SJohan Hedberg goto unlock; 30671c2e0041SJohan Hedberg } 30681c2e0041SJohan Hedberg 30691c2e0041SJohan Hedberg if (conn->state == BT_CONFIG) { 30701c2e0041SJohan Hedberg if (!ev->status) 30711c2e0041SJohan Hedberg conn->state = BT_CONNECTED; 30721c2e0041SJohan Hedberg 30731c2e0041SJohan Hedberg hci_proto_connect_cfm(conn, ev->status); 30741c2e0041SJohan Hedberg hci_conn_put(conn); 30751c2e0041SJohan Hedberg } else { 30761c2e0041SJohan Hedberg hci_auth_cfm(conn, ev->status); 30771c2e0041SJohan Hedberg 30781c2e0041SJohan Hedberg hci_conn_hold(conn); 30791c2e0041SJohan Hedberg conn->disc_timeout = HCI_DISCONN_TIMEOUT; 30801c2e0041SJohan Hedberg hci_conn_put(conn); 30811c2e0041SJohan Hedberg } 30821c2e0041SJohan Hedberg 30831c2e0041SJohan Hedberg unlock: 30841c2e0041SJohan Hedberg hci_dev_unlock(hdev); 30851c2e0041SJohan Hedberg } 30861c2e0041SJohan Hedberg 30876039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn) 308817fa4b9dSJohan Hedberg { 308917fa4b9dSJohan Hedberg /* If remote requests dedicated bonding follow that lead */ 309017fa4b9dSJohan Hedberg if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) { 309117fa4b9dSJohan Hedberg /* If both remote and local IO capabilities allow MITM 309217fa4b9dSJohan Hedberg * protection then require it, otherwise don't */ 309317fa4b9dSJohan Hedberg if (conn->remote_cap == 0x03 || conn->io_capability == 0x03) 309417fa4b9dSJohan Hedberg return 0x02; 309517fa4b9dSJohan Hedberg else 309617fa4b9dSJohan Hedberg return 0x03; 309717fa4b9dSJohan Hedberg } 309817fa4b9dSJohan Hedberg 309917fa4b9dSJohan Hedberg /* If remote requests no-bonding follow that lead */ 310017fa4b9dSJohan Hedberg if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01) 310158797bf7SWaldemar Rymarkiewicz return conn->remote_auth | (conn->auth_type & 0x01); 310217fa4b9dSJohan Hedberg 310317fa4b9dSJohan Hedberg return conn->auth_type; 310417fa4b9dSJohan Hedberg } 310517fa4b9dSJohan Hedberg 31066039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 31070493684eSMarcel Holtmann { 31080493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 31090493684eSMarcel Holtmann struct hci_conn *conn; 31100493684eSMarcel Holtmann 31110493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 31120493684eSMarcel Holtmann 31130493684eSMarcel Holtmann hci_dev_lock(hdev); 31140493684eSMarcel Holtmann 31150493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 311603b555e1SJohan Hedberg if (!conn) 311703b555e1SJohan Hedberg goto unlock; 311803b555e1SJohan Hedberg 31190493684eSMarcel Holtmann hci_conn_hold(conn); 31200493684eSMarcel Holtmann 3121a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 312203b555e1SJohan Hedberg goto unlock; 312303b555e1SJohan Hedberg 3124a8b2d5c2SJohan Hedberg if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) || 312503b555e1SJohan Hedberg (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 312617fa4b9dSJohan Hedberg struct hci_cp_io_capability_reply cp; 312717fa4b9dSJohan Hedberg 312817fa4b9dSJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 31297a7f1e7cSHemant Gupta /* Change the IO capability from KeyboardDisplay 31307a7f1e7cSHemant Gupta * to DisplayYesNo as it is not supported by BT spec. */ 31317a7f1e7cSHemant Gupta cp.capability = (conn->io_capability == 0x04) ? 31327a7f1e7cSHemant Gupta 0x01 : conn->io_capability; 31337cbc9bd9SJohan Hedberg conn->auth_type = hci_get_auth_req(conn); 31347cbc9bd9SJohan Hedberg cp.authentication = conn->auth_type; 313517fa4b9dSJohan Hedberg 31368fc9ced3SGustavo Padovan if (hci_find_remote_oob_data(hdev, &conn->dst) && 31378fc9ced3SGustavo Padovan (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags))) 3138ce85ee13SSzymon Janc cp.oob_data = 0x01; 3139ce85ee13SSzymon Janc else 3140ce85ee13SSzymon Janc cp.oob_data = 0x00; 3141ce85ee13SSzymon Janc 314217fa4b9dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, 314317fa4b9dSJohan Hedberg sizeof(cp), &cp); 314403b555e1SJohan Hedberg } else { 314503b555e1SJohan Hedberg struct hci_cp_io_capability_neg_reply cp; 314603b555e1SJohan Hedberg 314703b555e1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 31489f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED; 314903b555e1SJohan Hedberg 315003b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 315103b555e1SJohan Hedberg sizeof(cp), &cp); 315203b555e1SJohan Hedberg } 315303b555e1SJohan Hedberg 315403b555e1SJohan Hedberg unlock: 315503b555e1SJohan Hedberg hci_dev_unlock(hdev); 315603b555e1SJohan Hedberg } 315703b555e1SJohan Hedberg 31586039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 315903b555e1SJohan Hedberg { 316003b555e1SJohan Hedberg struct hci_ev_io_capa_reply *ev = (void *) skb->data; 316103b555e1SJohan Hedberg struct hci_conn *conn; 316203b555e1SJohan Hedberg 316303b555e1SJohan Hedberg BT_DBG("%s", hdev->name); 316403b555e1SJohan Hedberg 316503b555e1SJohan Hedberg hci_dev_lock(hdev); 316603b555e1SJohan Hedberg 316703b555e1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 316803b555e1SJohan Hedberg if (!conn) 316903b555e1SJohan Hedberg goto unlock; 317003b555e1SJohan Hedberg 317103b555e1SJohan Hedberg conn->remote_cap = ev->capability; 317203b555e1SJohan Hedberg conn->remote_auth = ev->authentication; 317358a681efSJohan Hedberg if (ev->oob_data) 317458a681efSJohan Hedberg set_bit(HCI_CONN_REMOTE_OOB, &conn->flags); 317503b555e1SJohan Hedberg 317603b555e1SJohan Hedberg unlock: 31770493684eSMarcel Holtmann hci_dev_unlock(hdev); 31780493684eSMarcel Holtmann } 31790493684eSMarcel Holtmann 31806039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev, 3181a5c29683SJohan Hedberg struct sk_buff *skb) 3182a5c29683SJohan Hedberg { 3183a5c29683SJohan Hedberg struct hci_ev_user_confirm_req *ev = (void *) skb->data; 318455bc1a37SJohan Hedberg int loc_mitm, rem_mitm, confirm_hint = 0; 31857a828908SJohan Hedberg struct hci_conn *conn; 3186a5c29683SJohan Hedberg 3187a5c29683SJohan Hedberg BT_DBG("%s", hdev->name); 3188a5c29683SJohan Hedberg 3189a5c29683SJohan Hedberg hci_dev_lock(hdev); 3190a5c29683SJohan Hedberg 3191a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 31927a828908SJohan Hedberg goto unlock; 31937a828908SJohan Hedberg 31947a828908SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 31957a828908SJohan Hedberg if (!conn) 31967a828908SJohan Hedberg goto unlock; 31977a828908SJohan Hedberg 31987a828908SJohan Hedberg loc_mitm = (conn->auth_type & 0x01); 31997a828908SJohan Hedberg rem_mitm = (conn->remote_auth & 0x01); 32007a828908SJohan Hedberg 32017a828908SJohan Hedberg /* If we require MITM but the remote device can't provide that 32027a828908SJohan Hedberg * (it has NoInputNoOutput) then reject the confirmation 32037a828908SJohan Hedberg * request. The only exception is when we're dedicated bonding 32047a828908SJohan Hedberg * initiators (connect_cfm_cb set) since then we always have the MITM 32057a828908SJohan Hedberg * bit set. */ 32067a828908SJohan Hedberg if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) { 32077a828908SJohan Hedberg BT_DBG("Rejecting request: remote device can't provide MITM"); 32087a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, 32097a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 32107a828908SJohan Hedberg goto unlock; 32117a828908SJohan Hedberg } 32127a828908SJohan Hedberg 32137a828908SJohan Hedberg /* If no side requires MITM protection; auto-accept */ 32147a828908SJohan Hedberg if ((!loc_mitm || conn->remote_cap == 0x03) && 32157a828908SJohan Hedberg (!rem_mitm || conn->io_capability == 0x03)) { 321655bc1a37SJohan Hedberg 321755bc1a37SJohan Hedberg /* If we're not the initiators request authorization to 321855bc1a37SJohan Hedberg * proceed from user space (mgmt_user_confirm with 321955bc1a37SJohan Hedberg * confirm_hint set to 1). */ 322051a8efd7SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 322155bc1a37SJohan Hedberg BT_DBG("Confirming auto-accept as acceptor"); 322255bc1a37SJohan Hedberg confirm_hint = 1; 322355bc1a37SJohan Hedberg goto confirm; 322455bc1a37SJohan Hedberg } 322555bc1a37SJohan Hedberg 32269f61656aSJohan Hedberg BT_DBG("Auto-accept of user confirmation with %ums delay", 32279f61656aSJohan Hedberg hdev->auto_accept_delay); 32289f61656aSJohan Hedberg 32299f61656aSJohan Hedberg if (hdev->auto_accept_delay > 0) { 32309f61656aSJohan Hedberg int delay = msecs_to_jiffies(hdev->auto_accept_delay); 32319f61656aSJohan Hedberg mod_timer(&conn->auto_accept_timer, jiffies + delay); 32329f61656aSJohan Hedberg goto unlock; 32339f61656aSJohan Hedberg } 32349f61656aSJohan Hedberg 32357a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, 32367a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 32377a828908SJohan Hedberg goto unlock; 32387a828908SJohan Hedberg } 32397a828908SJohan Hedberg 324055bc1a37SJohan Hedberg confirm: 3241272d90dfSJohan Hedberg mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey, 324255bc1a37SJohan Hedberg confirm_hint); 3243a5c29683SJohan Hedberg 32447a828908SJohan Hedberg unlock: 3245a5c29683SJohan Hedberg hci_dev_unlock(hdev); 3246a5c29683SJohan Hedberg } 3247a5c29683SJohan Hedberg 32486039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev, 32491143d458SBrian Gix struct sk_buff *skb) 32501143d458SBrian Gix { 32511143d458SBrian Gix struct hci_ev_user_passkey_req *ev = (void *) skb->data; 32521143d458SBrian Gix 32531143d458SBrian Gix BT_DBG("%s", hdev->name); 32541143d458SBrian Gix 32551143d458SBrian Gix hci_dev_lock(hdev); 32561143d458SBrian Gix 3257a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 3258272d90dfSJohan Hedberg mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); 32591143d458SBrian Gix 32601143d458SBrian Gix hci_dev_unlock(hdev); 32611143d458SBrian Gix } 32621143d458SBrian Gix 32636039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev, 3264807deac2SGustavo Padovan struct sk_buff *skb) 32650493684eSMarcel Holtmann { 32660493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 32670493684eSMarcel Holtmann struct hci_conn *conn; 32680493684eSMarcel Holtmann 32690493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 32700493684eSMarcel Holtmann 32710493684eSMarcel Holtmann hci_dev_lock(hdev); 32720493684eSMarcel Holtmann 32730493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 32742a611692SJohan Hedberg if (!conn) 32752a611692SJohan Hedberg goto unlock; 32762a611692SJohan Hedberg 32772a611692SJohan Hedberg /* To avoid duplicate auth_failed events to user space we check 32782a611692SJohan Hedberg * the HCI_CONN_AUTH_PEND flag which will be set if we 32792a611692SJohan Hedberg * initiated the authentication. A traditional auth_complete 32802a611692SJohan Hedberg * event gets always produced as initiator and is also mapped to 32812a611692SJohan Hedberg * the mgmt_auth_failed event */ 328251a8efd7SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status != 0) 3283bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 3284bab73cb6SJohan Hedberg ev->status); 32852a611692SJohan Hedberg 32860493684eSMarcel Holtmann hci_conn_put(conn); 32870493684eSMarcel Holtmann 32882a611692SJohan Hedberg unlock: 32890493684eSMarcel Holtmann hci_dev_unlock(hdev); 32900493684eSMarcel Holtmann } 32910493684eSMarcel Holtmann 32926039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev, 3293807deac2SGustavo Padovan struct sk_buff *skb) 329441a96212SMarcel Holtmann { 329541a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 329641a96212SMarcel Holtmann struct inquiry_entry *ie; 329741a96212SMarcel Holtmann 329841a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 329941a96212SMarcel Holtmann 330041a96212SMarcel Holtmann hci_dev_lock(hdev); 330141a96212SMarcel Holtmann 3302cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 3303cc11b9c1SAndrei Emeltchenko if (ie) 330402b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 330541a96212SMarcel Holtmann 330641a96212SMarcel Holtmann hci_dev_unlock(hdev); 330741a96212SMarcel Holtmann } 330841a96212SMarcel Holtmann 33096039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev, 33102763eda6SSzymon Janc struct sk_buff *skb) 33112763eda6SSzymon Janc { 33122763eda6SSzymon Janc struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; 33132763eda6SSzymon Janc struct oob_data *data; 33142763eda6SSzymon Janc 33152763eda6SSzymon Janc BT_DBG("%s", hdev->name); 33162763eda6SSzymon Janc 33172763eda6SSzymon Janc hci_dev_lock(hdev); 33182763eda6SSzymon Janc 3319a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 3320e1ba1f15SSzymon Janc goto unlock; 3321e1ba1f15SSzymon Janc 33222763eda6SSzymon Janc data = hci_find_remote_oob_data(hdev, &ev->bdaddr); 33232763eda6SSzymon Janc if (data) { 33242763eda6SSzymon Janc struct hci_cp_remote_oob_data_reply cp; 33252763eda6SSzymon Janc 33262763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 33272763eda6SSzymon Janc memcpy(cp.hash, data->hash, sizeof(cp.hash)); 33282763eda6SSzymon Janc memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); 33292763eda6SSzymon Janc 33302763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), 33312763eda6SSzymon Janc &cp); 33322763eda6SSzymon Janc } else { 33332763eda6SSzymon Janc struct hci_cp_remote_oob_data_neg_reply cp; 33342763eda6SSzymon Janc 33352763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 33362763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), 33372763eda6SSzymon Janc &cp); 33382763eda6SSzymon Janc } 33392763eda6SSzymon Janc 3340e1ba1f15SSzymon Janc unlock: 33412763eda6SSzymon Janc hci_dev_unlock(hdev); 33422763eda6SSzymon Janc } 33432763eda6SSzymon Janc 33446039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 3345fcd89c09SVille Tervo { 3346fcd89c09SVille Tervo struct hci_ev_le_conn_complete *ev = (void *) skb->data; 3347fcd89c09SVille Tervo struct hci_conn *conn; 3348fcd89c09SVille Tervo 33499f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 3350fcd89c09SVille Tervo 3351fcd89c09SVille Tervo hci_dev_lock(hdev); 3352fcd89c09SVille Tervo 33534f72b329SAndrzej Kaczmarek if (ev->status) { 33544f72b329SAndrzej Kaczmarek conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); 33554f72b329SAndrzej Kaczmarek if (!conn) 33564f72b329SAndrzej Kaczmarek goto unlock; 33574f72b329SAndrzej Kaczmarek 33584f72b329SAndrzej Kaczmarek mgmt_connect_failed(hdev, &conn->dst, conn->type, 33594f72b329SAndrzej Kaczmarek conn->dst_type, ev->status); 33604f72b329SAndrzej Kaczmarek hci_proto_connect_cfm(conn, ev->status); 33614f72b329SAndrzej Kaczmarek conn->state = BT_CLOSED; 33624f72b329SAndrzej Kaczmarek hci_conn_del(conn); 33634f72b329SAndrzej Kaczmarek goto unlock; 33644f72b329SAndrzej Kaczmarek } 33654f72b329SAndrzej Kaczmarek 3366fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr); 3367b62f328bSVille Tervo if (!conn) { 3368b62f328bSVille Tervo conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); 3369b62f328bSVille Tervo if (!conn) { 3370b62f328bSVille Tervo BT_ERR("No memory for new connection"); 3371b62f328bSVille Tervo hci_dev_unlock(hdev); 3372b62f328bSVille Tervo return; 3373b62f328bSVille Tervo } 337429b7988aSAndre Guedes 337529b7988aSAndre Guedes conn->dst_type = ev->bdaddr_type; 3376b62f328bSVille Tervo } 3377fcd89c09SVille Tervo 3378b644ba33SJohan Hedberg if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 3379b644ba33SJohan Hedberg mgmt_device_connected(hdev, &ev->bdaddr, conn->type, 338095b23582SSzymon Janc conn->dst_type, 0, NULL, 0, NULL); 338183bc71b4SVinicius Costa Gomes 33827b5c0d52SVinicius Costa Gomes conn->sec_level = BT_SECURITY_LOW; 3383fcd89c09SVille Tervo conn->handle = __le16_to_cpu(ev->handle); 3384fcd89c09SVille Tervo conn->state = BT_CONNECTED; 3385fcd89c09SVille Tervo 3386fcd89c09SVille Tervo hci_conn_hold_device(conn); 3387fcd89c09SVille Tervo hci_conn_add_sysfs(conn); 3388fcd89c09SVille Tervo 3389fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 3390fcd89c09SVille Tervo 3391fcd89c09SVille Tervo unlock: 3392fcd89c09SVille Tervo hci_dev_unlock(hdev); 3393fcd89c09SVille Tervo } 3394fcd89c09SVille Tervo 33956039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) 33969aa04c91SAndre Guedes { 3397e95beb41SAndre Guedes u8 num_reports = skb->data[0]; 3398e95beb41SAndre Guedes void *ptr = &skb->data[1]; 33993c9e9195SAndre Guedes s8 rssi; 34009aa04c91SAndre Guedes 34019aa04c91SAndre Guedes hci_dev_lock(hdev); 34029aa04c91SAndre Guedes 3403e95beb41SAndre Guedes while (num_reports--) { 3404e95beb41SAndre Guedes struct hci_ev_le_advertising_info *ev = ptr; 3405e95beb41SAndre Guedes 34063c9e9195SAndre Guedes rssi = ev->data[ev->length]; 34073c9e9195SAndre Guedes mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type, 340804124681SGustavo F. Padovan NULL, rssi, 0, 1, ev->data, ev->length); 34093c9e9195SAndre Guedes 3410e95beb41SAndre Guedes ptr += sizeof(*ev) + ev->length + 1; 34119aa04c91SAndre Guedes } 34129aa04c91SAndre Guedes 34139aa04c91SAndre Guedes hci_dev_unlock(hdev); 34149aa04c91SAndre Guedes } 34159aa04c91SAndre Guedes 34166039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 3417a7a595f6SVinicius Costa Gomes { 3418a7a595f6SVinicius Costa Gomes struct hci_ev_le_ltk_req *ev = (void *) skb->data; 3419a7a595f6SVinicius Costa Gomes struct hci_cp_le_ltk_reply cp; 3420bea710feSVinicius Costa Gomes struct hci_cp_le_ltk_neg_reply neg; 3421a7a595f6SVinicius Costa Gomes struct hci_conn *conn; 3422c9839a11SVinicius Costa Gomes struct smp_ltk *ltk; 3423a7a595f6SVinicius Costa Gomes 34249f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle)); 3425a7a595f6SVinicius Costa Gomes 3426a7a595f6SVinicius Costa Gomes hci_dev_lock(hdev); 3427a7a595f6SVinicius Costa Gomes 3428a7a595f6SVinicius Costa Gomes conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3429bea710feSVinicius Costa Gomes if (conn == NULL) 3430bea710feSVinicius Costa Gomes goto not_found; 3431a7a595f6SVinicius Costa Gomes 3432bea710feSVinicius Costa Gomes ltk = hci_find_ltk(hdev, ev->ediv, ev->random); 3433bea710feSVinicius Costa Gomes if (ltk == NULL) 3434bea710feSVinicius Costa Gomes goto not_found; 3435bea710feSVinicius Costa Gomes 3436bea710feSVinicius Costa Gomes memcpy(cp.ltk, ltk->val, sizeof(ltk->val)); 3437a7a595f6SVinicius Costa Gomes cp.handle = cpu_to_le16(conn->handle); 3438c9839a11SVinicius Costa Gomes 3439c9839a11SVinicius Costa Gomes if (ltk->authenticated) 3440c9839a11SVinicius Costa Gomes conn->sec_level = BT_SECURITY_HIGH; 3441a7a595f6SVinicius Costa Gomes 3442a7a595f6SVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); 3443a7a595f6SVinicius Costa Gomes 3444c9839a11SVinicius Costa Gomes if (ltk->type & HCI_SMP_STK) { 3445c9839a11SVinicius Costa Gomes list_del(<k->list); 3446c9839a11SVinicius Costa Gomes kfree(ltk); 3447c9839a11SVinicius Costa Gomes } 3448c9839a11SVinicius Costa Gomes 3449a7a595f6SVinicius Costa Gomes hci_dev_unlock(hdev); 3450bea710feSVinicius Costa Gomes 3451bea710feSVinicius Costa Gomes return; 3452bea710feSVinicius Costa Gomes 3453bea710feSVinicius Costa Gomes not_found: 3454bea710feSVinicius Costa Gomes neg.handle = ev->handle; 3455bea710feSVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg); 3456bea710feSVinicius Costa Gomes hci_dev_unlock(hdev); 3457a7a595f6SVinicius Costa Gomes } 3458a7a595f6SVinicius Costa Gomes 34596039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 3460fcd89c09SVille Tervo { 3461fcd89c09SVille Tervo struct hci_ev_le_meta *le_ev = (void *) skb->data; 3462fcd89c09SVille Tervo 3463fcd89c09SVille Tervo skb_pull(skb, sizeof(*le_ev)); 3464fcd89c09SVille Tervo 3465fcd89c09SVille Tervo switch (le_ev->subevent) { 3466fcd89c09SVille Tervo case HCI_EV_LE_CONN_COMPLETE: 3467fcd89c09SVille Tervo hci_le_conn_complete_evt(hdev, skb); 3468fcd89c09SVille Tervo break; 3469fcd89c09SVille Tervo 34709aa04c91SAndre Guedes case HCI_EV_LE_ADVERTISING_REPORT: 34719aa04c91SAndre Guedes hci_le_adv_report_evt(hdev, skb); 34729aa04c91SAndre Guedes break; 34739aa04c91SAndre Guedes 3474a7a595f6SVinicius Costa Gomes case HCI_EV_LE_LTK_REQ: 3475a7a595f6SVinicius Costa Gomes hci_le_ltk_request_evt(hdev, skb); 3476a7a595f6SVinicius Costa Gomes break; 3477a7a595f6SVinicius Costa Gomes 3478fcd89c09SVille Tervo default: 3479fcd89c09SVille Tervo break; 3480fcd89c09SVille Tervo } 3481fcd89c09SVille Tervo } 3482fcd89c09SVille Tervo 34831da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 34841da177e4SLinus Torvalds { 3485a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 3486a9de9248SMarcel Holtmann __u8 event = hdr->evt; 34871da177e4SLinus Torvalds 34881da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 34891da177e4SLinus Torvalds 3490a9de9248SMarcel Holtmann switch (event) { 34911da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 34921da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 34931da177e4SLinus Torvalds break; 34941da177e4SLinus Torvalds 34951da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 34961da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 34971da177e4SLinus Torvalds break; 34981da177e4SLinus Torvalds 3499a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 3500a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 350121d9e30eSMarcel Holtmann break; 350221d9e30eSMarcel Holtmann 35031da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 35041da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 35051da177e4SLinus Torvalds break; 35061da177e4SLinus Torvalds 35071da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 35081da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 35091da177e4SLinus Torvalds break; 35101da177e4SLinus Torvalds 35111da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 35121da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 35131da177e4SLinus Torvalds break; 35141da177e4SLinus Torvalds 3515a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 3516a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 3517a9de9248SMarcel Holtmann break; 3518a9de9248SMarcel Holtmann 35191da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 35201da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 35211da177e4SLinus Torvalds break; 35221da177e4SLinus Torvalds 3523a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 3524a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 3525a9de9248SMarcel Holtmann break; 3526a9de9248SMarcel Holtmann 3527a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 3528a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 3529a9de9248SMarcel Holtmann break; 3530a9de9248SMarcel Holtmann 3531a9de9248SMarcel Holtmann case HCI_EV_REMOTE_VERSION: 3532a9de9248SMarcel Holtmann hci_remote_version_evt(hdev, skb); 3533a9de9248SMarcel Holtmann break; 3534a9de9248SMarcel Holtmann 3535a9de9248SMarcel Holtmann case HCI_EV_QOS_SETUP_COMPLETE: 3536a9de9248SMarcel Holtmann hci_qos_setup_complete_evt(hdev, skb); 3537a9de9248SMarcel Holtmann break; 3538a9de9248SMarcel Holtmann 3539a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 3540a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 3541a9de9248SMarcel Holtmann break; 3542a9de9248SMarcel Holtmann 3543a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 3544a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 3545a9de9248SMarcel Holtmann break; 3546a9de9248SMarcel Holtmann 3547a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 3548a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 3549a9de9248SMarcel Holtmann break; 3550a9de9248SMarcel Holtmann 3551a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 3552a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 3553a9de9248SMarcel Holtmann break; 3554a9de9248SMarcel Holtmann 3555a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 3556a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 35571da177e4SLinus Torvalds break; 35581da177e4SLinus Torvalds 35591da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 35601da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 35611da177e4SLinus Torvalds break; 35621da177e4SLinus Torvalds 35631da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 35641da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 35651da177e4SLinus Torvalds break; 35661da177e4SLinus Torvalds 35671da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 35681da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 35691da177e4SLinus Torvalds break; 35701da177e4SLinus Torvalds 35711da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 35721da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 35731da177e4SLinus Torvalds break; 35741da177e4SLinus Torvalds 3575a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 3576a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 3577a8746417SMarcel Holtmann break; 3578a8746417SMarcel Holtmann 357985a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 358085a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 358185a1e930SMarcel Holtmann break; 358285a1e930SMarcel Holtmann 3583a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 3584a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 3585a9de9248SMarcel Holtmann break; 3586a9de9248SMarcel Holtmann 3587a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 3588a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 3589a9de9248SMarcel Holtmann break; 3590a9de9248SMarcel Holtmann 3591a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 3592a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 3593a9de9248SMarcel Holtmann break; 3594a9de9248SMarcel Holtmann 3595a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_CHANGED: 3596a9de9248SMarcel Holtmann hci_sync_conn_changed_evt(hdev, skb); 3597a9de9248SMarcel Holtmann break; 3598a9de9248SMarcel Holtmann 359904837f64SMarcel Holtmann case HCI_EV_SNIFF_SUBRATE: 360004837f64SMarcel Holtmann hci_sniff_subrate_evt(hdev, skb); 360104837f64SMarcel Holtmann break; 360204837f64SMarcel Holtmann 3603a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 3604a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 36051da177e4SLinus Torvalds break; 36061da177e4SLinus Torvalds 36071c2e0041SJohan Hedberg case HCI_EV_KEY_REFRESH_COMPLETE: 36081c2e0041SJohan Hedberg hci_key_refresh_complete_evt(hdev, skb); 36091c2e0041SJohan Hedberg break; 36101c2e0041SJohan Hedberg 36110493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 36120493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 36130493684eSMarcel Holtmann break; 36140493684eSMarcel Holtmann 361503b555e1SJohan Hedberg case HCI_EV_IO_CAPA_REPLY: 361603b555e1SJohan Hedberg hci_io_capa_reply_evt(hdev, skb); 361703b555e1SJohan Hedberg break; 361803b555e1SJohan Hedberg 3619a5c29683SJohan Hedberg case HCI_EV_USER_CONFIRM_REQUEST: 3620a5c29683SJohan Hedberg hci_user_confirm_request_evt(hdev, skb); 3621a5c29683SJohan Hedberg break; 3622a5c29683SJohan Hedberg 36231143d458SBrian Gix case HCI_EV_USER_PASSKEY_REQUEST: 36241143d458SBrian Gix hci_user_passkey_request_evt(hdev, skb); 36251143d458SBrian Gix break; 36261143d458SBrian Gix 36270493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 36280493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 36290493684eSMarcel Holtmann break; 36300493684eSMarcel Holtmann 363141a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 363241a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 363341a96212SMarcel Holtmann break; 363441a96212SMarcel Holtmann 3635fcd89c09SVille Tervo case HCI_EV_LE_META: 3636fcd89c09SVille Tervo hci_le_meta_evt(hdev, skb); 3637fcd89c09SVille Tervo break; 3638fcd89c09SVille Tervo 36392763eda6SSzymon Janc case HCI_EV_REMOTE_OOB_DATA_REQUEST: 36402763eda6SSzymon Janc hci_remote_oob_data_request_evt(hdev, skb); 36412763eda6SSzymon Janc break; 36422763eda6SSzymon Janc 364325e89e99SAndrei Emeltchenko case HCI_EV_NUM_COMP_BLOCKS: 364425e89e99SAndrei Emeltchenko hci_num_comp_blocks_evt(hdev, skb); 364525e89e99SAndrei Emeltchenko break; 364625e89e99SAndrei Emeltchenko 36471da177e4SLinus Torvalds default: 36489f1db00cSAndrei Emeltchenko BT_DBG("%s event 0x%2.2x", hdev->name, event); 36491da177e4SLinus Torvalds break; 36501da177e4SLinus Torvalds } 36511da177e4SLinus Torvalds 36521da177e4SLinus Torvalds kfree_skb(skb); 36531da177e4SLinus Torvalds hdev->stat.evt_rx++; 36541da177e4SLinus Torvalds } 3655