11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds BlueZ - Bluetooth protocol stack for Linux 32d0a0346SRon Shaffer Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved. 41da177e4SLinus Torvalds 51da177e4SLinus Torvalds Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> 61da177e4SLinus Torvalds 71da177e4SLinus Torvalds This program is free software; you can redistribute it and/or modify 81da177e4SLinus Torvalds it under the terms of the GNU General Public License version 2 as 91da177e4SLinus Torvalds published by the Free Software Foundation; 101da177e4SLinus Torvalds 111da177e4SLinus Torvalds THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 121da177e4SLinus Torvalds OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 131da177e4SLinus Torvalds FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 141da177e4SLinus Torvalds IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 151da177e4SLinus Torvalds CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 161da177e4SLinus Torvalds WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 171da177e4SLinus Torvalds ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 181da177e4SLinus Torvalds OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 211da177e4SLinus Torvalds COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 221da177e4SLinus Torvalds SOFTWARE IS DISCLAIMED. 231da177e4SLinus Torvalds */ 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds /* Bluetooth HCI event handling. */ 261da177e4SLinus Torvalds 271da177e4SLinus Torvalds #include <linux/module.h> 281da177e4SLinus Torvalds 291da177e4SLinus Torvalds #include <linux/types.h> 301da177e4SLinus Torvalds #include <linux/errno.h> 311da177e4SLinus Torvalds #include <linux/kernel.h> 321da177e4SLinus Torvalds #include <linux/slab.h> 331da177e4SLinus Torvalds #include <linux/poll.h> 341da177e4SLinus Torvalds #include <linux/fcntl.h> 351da177e4SLinus Torvalds #include <linux/init.h> 361da177e4SLinus Torvalds #include <linux/skbuff.h> 371da177e4SLinus Torvalds #include <linux/interrupt.h> 381da177e4SLinus Torvalds #include <linux/notifier.h> 391da177e4SLinus Torvalds #include <net/sock.h> 401da177e4SLinus Torvalds 411da177e4SLinus Torvalds #include <asm/system.h> 4270f23020SAndrei Emeltchenko #include <linux/uaccess.h> 431da177e4SLinus Torvalds #include <asm/unaligned.h> 441da177e4SLinus Torvalds 451da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h> 461da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h> 471da177e4SLinus Torvalds 48eb939922SRusty Russell static bool enable_le; 49e6100a25SAndre Guedes 501da177e4SLinus Torvalds /* Handle HCI Event packets */ 511da177e4SLinus Torvalds 52a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb) 531da177e4SLinus Torvalds { 54a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 551da177e4SLinus Torvalds 56a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 571da177e4SLinus Torvalds 58e6d465cbSAndre Guedes if (status) { 59e6d465cbSAndre Guedes hci_dev_lock(hdev); 60e6d465cbSAndre Guedes mgmt_stop_discovery_failed(hdev, status); 61e6d465cbSAndre Guedes hci_dev_unlock(hdev); 62a9de9248SMarcel Holtmann return; 63e6d465cbSAndre Guedes } 641da177e4SLinus Torvalds 6589352e7dSAndre Guedes clear_bit(HCI_INQUIRY, &hdev->flags); 6689352e7dSAndre Guedes 6756e5cb86SJohan Hedberg hci_dev_lock(hdev); 68ff9ef578SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 6956e5cb86SJohan Hedberg hci_dev_unlock(hdev); 70a9de9248SMarcel Holtmann 7123bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status); 72a9de9248SMarcel Holtmann 73a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 741da177e4SLinus Torvalds } 756bd57416SMarcel Holtmann 76a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 771da177e4SLinus Torvalds { 78a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 79a9de9248SMarcel Holtmann 80a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 81a9de9248SMarcel Holtmann 82a9de9248SMarcel Holtmann if (status) 83a9de9248SMarcel Holtmann return; 84a9de9248SMarcel Holtmann 85a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 86a9de9248SMarcel Holtmann } 87a9de9248SMarcel Holtmann 88a9de9248SMarcel Holtmann static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb) 89a9de9248SMarcel Holtmann { 90a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 91a9de9248SMarcel Holtmann } 92a9de9248SMarcel Holtmann 93a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb) 94a9de9248SMarcel Holtmann { 95a9de9248SMarcel Holtmann struct hci_rp_role_discovery *rp = (void *) skb->data; 961da177e4SLinus Torvalds struct hci_conn *conn; 971da177e4SLinus Torvalds 98a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 991da177e4SLinus Torvalds 100a9de9248SMarcel Holtmann if (rp->status) 101a9de9248SMarcel Holtmann return; 1021da177e4SLinus Torvalds 1031da177e4SLinus Torvalds hci_dev_lock(hdev); 1041da177e4SLinus Torvalds 105a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 1061da177e4SLinus Torvalds if (conn) { 107a9de9248SMarcel Holtmann if (rp->role) 1081da177e4SLinus Torvalds conn->link_mode &= ~HCI_LM_MASTER; 1091da177e4SLinus Torvalds else 1101da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 1111da177e4SLinus Torvalds } 1121da177e4SLinus Torvalds 1131da177e4SLinus Torvalds hci_dev_unlock(hdev); 114a9de9248SMarcel Holtmann } 1151da177e4SLinus Torvalds 116e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 117e4e8e37cSMarcel Holtmann { 118e4e8e37cSMarcel Holtmann struct hci_rp_read_link_policy *rp = (void *) skb->data; 119e4e8e37cSMarcel Holtmann struct hci_conn *conn; 120e4e8e37cSMarcel Holtmann 121e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 122e4e8e37cSMarcel Holtmann 123e4e8e37cSMarcel Holtmann if (rp->status) 124e4e8e37cSMarcel Holtmann return; 125e4e8e37cSMarcel Holtmann 126e4e8e37cSMarcel Holtmann hci_dev_lock(hdev); 127e4e8e37cSMarcel Holtmann 128e4e8e37cSMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 129e4e8e37cSMarcel Holtmann if (conn) 130e4e8e37cSMarcel Holtmann conn->link_policy = __le16_to_cpu(rp->policy); 131e4e8e37cSMarcel Holtmann 132e4e8e37cSMarcel Holtmann hci_dev_unlock(hdev); 133e4e8e37cSMarcel Holtmann } 134e4e8e37cSMarcel Holtmann 135a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 136a9de9248SMarcel Holtmann { 137a9de9248SMarcel Holtmann struct hci_rp_write_link_policy *rp = (void *) skb->data; 138a9de9248SMarcel Holtmann struct hci_conn *conn; 139a9de9248SMarcel Holtmann void *sent; 140a9de9248SMarcel Holtmann 141a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 142a9de9248SMarcel Holtmann 143a9de9248SMarcel Holtmann if (rp->status) 144a9de9248SMarcel Holtmann return; 145a9de9248SMarcel Holtmann 146a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY); 14704837f64SMarcel Holtmann if (!sent) 148a9de9248SMarcel Holtmann return; 14904837f64SMarcel Holtmann 15004837f64SMarcel Holtmann hci_dev_lock(hdev); 15104837f64SMarcel Holtmann 152a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 153e4e8e37cSMarcel Holtmann if (conn) 15483985319SHarvey Harrison conn->link_policy = get_unaligned_le16(sent + 2); 15504837f64SMarcel Holtmann 15604837f64SMarcel Holtmann hci_dev_unlock(hdev); 1571da177e4SLinus Torvalds } 1581da177e4SLinus Torvalds 159e4e8e37cSMarcel Holtmann static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 160e4e8e37cSMarcel Holtmann { 161e4e8e37cSMarcel Holtmann struct hci_rp_read_def_link_policy *rp = (void *) skb->data; 162e4e8e37cSMarcel Holtmann 163e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 164e4e8e37cSMarcel Holtmann 165e4e8e37cSMarcel Holtmann if (rp->status) 166e4e8e37cSMarcel Holtmann return; 167e4e8e37cSMarcel Holtmann 168e4e8e37cSMarcel Holtmann hdev->link_policy = __le16_to_cpu(rp->policy); 169e4e8e37cSMarcel Holtmann } 170e4e8e37cSMarcel Holtmann 171e4e8e37cSMarcel Holtmann static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 172e4e8e37cSMarcel Holtmann { 173e4e8e37cSMarcel Holtmann __u8 status = *((__u8 *) skb->data); 174e4e8e37cSMarcel Holtmann void *sent; 175e4e8e37cSMarcel Holtmann 176e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", 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 192a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", 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 1987005ff17SJohan Hedberg /* Reset all flags, except persistent ones */ 19995947a39SHemant Gupta hdev->dev_flags &= BIT(HCI_MGMT) | BIT(HCI_SETUP) | BIT(HCI_AUTO_OFF) | 20095947a39SHemant Gupta BIT(HCI_LINK_KEYS) | BIT(HCI_DEBUG_KEYS); 201a9de9248SMarcel Holtmann } 202a9de9248SMarcel Holtmann 203a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) 204a9de9248SMarcel Holtmann { 205a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 2061da177e4SLinus Torvalds void *sent; 2071da177e4SLinus Torvalds 208a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 2091da177e4SLinus Torvalds 210a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); 2111da177e4SLinus Torvalds if (!sent) 212a9de9248SMarcel Holtmann return; 2131da177e4SLinus Torvalds 21456e5cb86SJohan Hedberg hci_dev_lock(hdev); 21556e5cb86SJohan Hedberg 216a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 217744cf19eSJohan Hedberg mgmt_set_local_name_complete(hdev, sent, status); 218b312b161SJohan Hedberg 21956e5cb86SJohan Hedberg if (status == 0) 2201f6c6378SJohan Hedberg memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); 22156e5cb86SJohan Hedberg 22256e5cb86SJohan Hedberg hci_dev_unlock(hdev); 223a9de9248SMarcel Holtmann } 224a9de9248SMarcel Holtmann 225a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) 226a9de9248SMarcel Holtmann { 227a9de9248SMarcel Holtmann struct hci_rp_read_local_name *rp = (void *) skb->data; 228a9de9248SMarcel Holtmann 229a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 230a9de9248SMarcel Holtmann 231a9de9248SMarcel Holtmann if (rp->status) 232a9de9248SMarcel Holtmann return; 233a9de9248SMarcel Holtmann 2341f6c6378SJohan Hedberg memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); 235a9de9248SMarcel Holtmann } 236a9de9248SMarcel Holtmann 237a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) 238a9de9248SMarcel Holtmann { 239a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 240a9de9248SMarcel Holtmann void *sent; 241a9de9248SMarcel Holtmann 242a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 243a9de9248SMarcel Holtmann 244a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); 245a9de9248SMarcel Holtmann if (!sent) 246a9de9248SMarcel Holtmann return; 2471da177e4SLinus Torvalds 2481da177e4SLinus Torvalds if (!status) { 249a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 250a9de9248SMarcel Holtmann 2511da177e4SLinus Torvalds if (param == AUTH_ENABLED) 2521da177e4SLinus Torvalds set_bit(HCI_AUTH, &hdev->flags); 2531da177e4SLinus Torvalds else 2541da177e4SLinus Torvalds clear_bit(HCI_AUTH, &hdev->flags); 2551da177e4SLinus Torvalds } 256a9de9248SMarcel Holtmann 25723bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status); 258a9de9248SMarcel Holtmann } 2591da177e4SLinus Torvalds 260a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) 261a9de9248SMarcel Holtmann { 262a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 263a9de9248SMarcel Holtmann void *sent; 264a9de9248SMarcel Holtmann 265a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 266a9de9248SMarcel Holtmann 267a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); 2681da177e4SLinus Torvalds if (!sent) 269a9de9248SMarcel Holtmann return; 2701da177e4SLinus Torvalds 2711da177e4SLinus Torvalds if (!status) { 272a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 273a9de9248SMarcel Holtmann 2741da177e4SLinus Torvalds if (param) 2751da177e4SLinus Torvalds set_bit(HCI_ENCRYPT, &hdev->flags); 2761da177e4SLinus Torvalds else 2771da177e4SLinus Torvalds clear_bit(HCI_ENCRYPT, &hdev->flags); 2781da177e4SLinus Torvalds } 279a9de9248SMarcel Holtmann 28023bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status); 2811da177e4SLinus Torvalds } 2821da177e4SLinus Torvalds 283a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) 284a9de9248SMarcel Holtmann { 28536f7fc7eSJohan Hedberg __u8 param, status = *((__u8 *) skb->data); 28636f7fc7eSJohan Hedberg int old_pscan, old_iscan; 287a9de9248SMarcel Holtmann void *sent; 2881da177e4SLinus Torvalds 289a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 290a9de9248SMarcel Holtmann 291a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); 2921da177e4SLinus Torvalds if (!sent) 293a9de9248SMarcel Holtmann return; 2941da177e4SLinus Torvalds 29536f7fc7eSJohan Hedberg param = *((__u8 *) sent); 296a9de9248SMarcel Holtmann 29756e5cb86SJohan Hedberg hci_dev_lock(hdev); 29856e5cb86SJohan Hedberg 2992d7cee58SJohan Hedberg if (status != 0) { 300744cf19eSJohan Hedberg mgmt_write_scan_failed(hdev, param, status); 3012d7cee58SJohan Hedberg hdev->discov_timeout = 0; 3022d7cee58SJohan Hedberg goto done; 3032d7cee58SJohan Hedberg } 3042d7cee58SJohan Hedberg 3059fbcbb45SJohan Hedberg old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags); 3069fbcbb45SJohan Hedberg old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags); 307a9de9248SMarcel Holtmann 30873f22f62SJohan Hedberg if (param & SCAN_INQUIRY) { 3091da177e4SLinus Torvalds set_bit(HCI_ISCAN, &hdev->flags); 3109fbcbb45SJohan Hedberg if (!old_iscan) 311744cf19eSJohan Hedberg mgmt_discoverable(hdev, 1); 31216ab91abSJohan Hedberg if (hdev->discov_timeout > 0) { 31316ab91abSJohan Hedberg int to = msecs_to_jiffies(hdev->discov_timeout * 1000); 31416ab91abSJohan Hedberg queue_delayed_work(hdev->workqueue, &hdev->discov_off, 31516ab91abSJohan Hedberg to); 31616ab91abSJohan Hedberg } 3179fbcbb45SJohan Hedberg } else if (old_iscan) 318744cf19eSJohan Hedberg mgmt_discoverable(hdev, 0); 3191da177e4SLinus Torvalds 3209fbcbb45SJohan Hedberg if (param & SCAN_PAGE) { 3211da177e4SLinus Torvalds set_bit(HCI_PSCAN, &hdev->flags); 3229fbcbb45SJohan Hedberg if (!old_pscan) 323744cf19eSJohan Hedberg mgmt_connectable(hdev, 1); 3249fbcbb45SJohan Hedberg } else if (old_pscan) 325744cf19eSJohan Hedberg mgmt_connectable(hdev, 0); 326a9de9248SMarcel Holtmann 32736f7fc7eSJohan Hedberg done: 32856e5cb86SJohan Hedberg hci_dev_unlock(hdev); 32923bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status); 3301da177e4SLinus Torvalds } 3311da177e4SLinus Torvalds 332a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 333a9de9248SMarcel Holtmann { 334a9de9248SMarcel Holtmann struct hci_rp_read_class_of_dev *rp = (void *) skb->data; 335a9de9248SMarcel Holtmann 336a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 337a9de9248SMarcel Holtmann 338a9de9248SMarcel Holtmann if (rp->status) 339a9de9248SMarcel Holtmann return; 340a9de9248SMarcel Holtmann 341a9de9248SMarcel Holtmann memcpy(hdev->dev_class, rp->dev_class, 3); 342a9de9248SMarcel Holtmann 343a9de9248SMarcel Holtmann BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, 344a9de9248SMarcel Holtmann hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); 345a9de9248SMarcel Holtmann } 346a9de9248SMarcel Holtmann 347a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 348a9de9248SMarcel Holtmann { 349a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 350a9de9248SMarcel Holtmann void *sent; 351a9de9248SMarcel Holtmann 352a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 353a9de9248SMarcel Holtmann 354f383f275SMarcel Holtmann if (status) 355f383f275SMarcel Holtmann return; 356f383f275SMarcel Holtmann 357a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); 358a9de9248SMarcel Holtmann if (!sent) 359a9de9248SMarcel Holtmann return; 360a9de9248SMarcel Holtmann 361a9de9248SMarcel Holtmann memcpy(hdev->dev_class, sent, 3); 362a9de9248SMarcel Holtmann } 363a9de9248SMarcel Holtmann 364a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 365a9de9248SMarcel Holtmann { 366a9de9248SMarcel Holtmann struct hci_rp_read_voice_setting *rp = (void *) skb->data; 367a9de9248SMarcel Holtmann __u16 setting; 368a9de9248SMarcel Holtmann 369a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 370a9de9248SMarcel Holtmann 371a9de9248SMarcel Holtmann if (rp->status) 372a9de9248SMarcel Holtmann return; 373a9de9248SMarcel Holtmann 374a9de9248SMarcel Holtmann setting = __le16_to_cpu(rp->voice_setting); 375a9de9248SMarcel Holtmann 376a9de9248SMarcel Holtmann if (hdev->voice_setting == setting) 377a9de9248SMarcel Holtmann return; 378a9de9248SMarcel Holtmann 379a9de9248SMarcel Holtmann hdev->voice_setting = setting; 380a9de9248SMarcel Holtmann 381a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 382a9de9248SMarcel Holtmann 3833c54711cSGustavo F. Padovan if (hdev->notify) 384a9de9248SMarcel Holtmann hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 385a9de9248SMarcel Holtmann } 386a9de9248SMarcel Holtmann 387a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 388a9de9248SMarcel Holtmann { 389a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 390f383f275SMarcel Holtmann __u16 setting; 391a9de9248SMarcel Holtmann void *sent; 392a9de9248SMarcel Holtmann 393a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 394a9de9248SMarcel Holtmann 395f383f275SMarcel Holtmann if (status) 396f383f275SMarcel Holtmann return; 397f383f275SMarcel Holtmann 398a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); 399a9de9248SMarcel Holtmann if (!sent) 400a9de9248SMarcel Holtmann return; 401a9de9248SMarcel Holtmann 402f383f275SMarcel Holtmann setting = get_unaligned_le16(sent); 4031da177e4SLinus Torvalds 404f383f275SMarcel Holtmann if (hdev->voice_setting == setting) 405f383f275SMarcel Holtmann return; 406f383f275SMarcel Holtmann 4071da177e4SLinus Torvalds hdev->voice_setting = setting; 4081da177e4SLinus Torvalds 409a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 4101da177e4SLinus Torvalds 4113c54711cSGustavo F. Padovan if (hdev->notify) 4121da177e4SLinus Torvalds hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 4131da177e4SLinus Torvalds } 4141da177e4SLinus Torvalds 415a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 4161da177e4SLinus Torvalds { 417a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 4181da177e4SLinus Torvalds 419a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 4201da177e4SLinus Torvalds 42123bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status); 4221143e5a6SMarcel Holtmann } 4231143e5a6SMarcel Holtmann 424333140b5SMarcel Holtmann static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 425333140b5SMarcel Holtmann { 426333140b5SMarcel Holtmann struct hci_rp_read_ssp_mode *rp = (void *) skb->data; 427333140b5SMarcel Holtmann 428333140b5SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 429333140b5SMarcel Holtmann 430333140b5SMarcel Holtmann if (rp->status) 431333140b5SMarcel Holtmann return; 432333140b5SMarcel Holtmann 43384bde9d6SJohan Hedberg if (rp->mode) 43484bde9d6SJohan Hedberg set_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 43584bde9d6SJohan Hedberg else 43684bde9d6SJohan Hedberg clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 437333140b5SMarcel Holtmann } 438333140b5SMarcel Holtmann 439333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 440333140b5SMarcel Holtmann { 441333140b5SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 442333140b5SMarcel Holtmann void *sent; 443333140b5SMarcel Holtmann 444333140b5SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 445333140b5SMarcel Holtmann 446333140b5SMarcel Holtmann if (status) 447333140b5SMarcel Holtmann return; 448333140b5SMarcel Holtmann 449333140b5SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); 450333140b5SMarcel Holtmann if (!sent) 451333140b5SMarcel Holtmann return; 452333140b5SMarcel Holtmann 45384bde9d6SJohan Hedberg if (*((u8 *) sent)) 45484bde9d6SJohan Hedberg set_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 45584bde9d6SJohan Hedberg else 45684bde9d6SJohan Hedberg clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 457333140b5SMarcel Holtmann } 458333140b5SMarcel Holtmann 459d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev) 460d5859e22SJohan Hedberg { 461d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 462d5859e22SJohan Hedberg return 2; 463d5859e22SJohan Hedberg 464d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 465d5859e22SJohan Hedberg return 1; 466d5859e22SJohan Hedberg 467d5859e22SJohan Hedberg if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 && 468d5859e22SJohan Hedberg hdev->lmp_subver == 0x0757) 469d5859e22SJohan Hedberg return 1; 470d5859e22SJohan Hedberg 471d5859e22SJohan Hedberg if (hdev->manufacturer == 15) { 472d5859e22SJohan Hedberg if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963) 473d5859e22SJohan Hedberg return 1; 474d5859e22SJohan Hedberg if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963) 475d5859e22SJohan Hedberg return 1; 476d5859e22SJohan Hedberg if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965) 477d5859e22SJohan Hedberg return 1; 478d5859e22SJohan Hedberg } 479d5859e22SJohan Hedberg 480d5859e22SJohan Hedberg if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 && 481d5859e22SJohan Hedberg hdev->lmp_subver == 0x1805) 482d5859e22SJohan Hedberg return 1; 483d5859e22SJohan Hedberg 484d5859e22SJohan Hedberg return 0; 485d5859e22SJohan Hedberg } 486d5859e22SJohan Hedberg 487d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev) 488d5859e22SJohan Hedberg { 489d5859e22SJohan Hedberg u8 mode; 490d5859e22SJohan Hedberg 491d5859e22SJohan Hedberg mode = hci_get_inquiry_mode(hdev); 492d5859e22SJohan Hedberg 493d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode); 494d5859e22SJohan Hedberg } 495d5859e22SJohan Hedberg 496d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev) 497d5859e22SJohan Hedberg { 498d5859e22SJohan Hedberg /* The second byte is 0xff instead of 0x9f (two reserved bits 499d5859e22SJohan Hedberg * disabled) since a Broadcom 1.2 dongle doesn't respond to the 500d5859e22SJohan Hedberg * command otherwise */ 501d5859e22SJohan Hedberg u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 }; 502d5859e22SJohan Hedberg 5036de6c18dSVille Tervo /* CSR 1.1 dongles does not accept any bitfield so don't try to set 5046de6c18dSVille Tervo * any event mask for pre 1.2 devices */ 5055a13b095SAndrei Emeltchenko if (hdev->hci_ver < BLUETOOTH_VER_1_2) 5066de6c18dSVille Tervo return; 5076de6c18dSVille Tervo 508d5859e22SJohan Hedberg events[4] |= 0x01; /* Flow Specification Complete */ 509d5859e22SJohan Hedberg events[4] |= 0x02; /* Inquiry Result with RSSI */ 510d5859e22SJohan Hedberg events[4] |= 0x04; /* Read Remote Extended Features Complete */ 511d5859e22SJohan Hedberg events[5] |= 0x08; /* Synchronous Connection Complete */ 512d5859e22SJohan Hedberg events[5] |= 0x10; /* Synchronous Connection Changed */ 513d5859e22SJohan Hedberg 514d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 515d5859e22SJohan Hedberg events[4] |= 0x04; /* Inquiry Result with RSSI */ 516d5859e22SJohan Hedberg 517d5859e22SJohan Hedberg if (hdev->features[5] & LMP_SNIFF_SUBR) 518d5859e22SJohan Hedberg events[5] |= 0x20; /* Sniff Subrating */ 519d5859e22SJohan Hedberg 520d5859e22SJohan Hedberg if (hdev->features[5] & LMP_PAUSE_ENC) 521d5859e22SJohan Hedberg events[5] |= 0x80; /* Encryption Key Refresh Complete */ 522d5859e22SJohan Hedberg 523d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 524d5859e22SJohan Hedberg events[5] |= 0x40; /* Extended Inquiry Result */ 525d5859e22SJohan Hedberg 526d5859e22SJohan Hedberg if (hdev->features[6] & LMP_NO_FLUSH) 527d5859e22SJohan Hedberg events[7] |= 0x01; /* Enhanced Flush Complete */ 528d5859e22SJohan Hedberg 529d5859e22SJohan Hedberg if (hdev->features[7] & LMP_LSTO) 530d5859e22SJohan Hedberg events[6] |= 0x80; /* Link Supervision Timeout Changed */ 531d5859e22SJohan Hedberg 532d5859e22SJohan Hedberg if (hdev->features[6] & LMP_SIMPLE_PAIR) { 533d5859e22SJohan Hedberg events[6] |= 0x01; /* IO Capability Request */ 534d5859e22SJohan Hedberg events[6] |= 0x02; /* IO Capability Response */ 535d5859e22SJohan Hedberg events[6] |= 0x04; /* User Confirmation Request */ 536d5859e22SJohan Hedberg events[6] |= 0x08; /* User Passkey Request */ 537d5859e22SJohan Hedberg events[6] |= 0x10; /* Remote OOB Data Request */ 538d5859e22SJohan Hedberg events[6] |= 0x20; /* Simple Pairing Complete */ 539d5859e22SJohan Hedberg events[7] |= 0x04; /* User Passkey Notification */ 540d5859e22SJohan Hedberg events[7] |= 0x08; /* Keypress Notification */ 541d5859e22SJohan Hedberg events[7] |= 0x10; /* Remote Host Supported 542d5859e22SJohan Hedberg * Features Notification */ 543d5859e22SJohan Hedberg } 544d5859e22SJohan Hedberg 545d5859e22SJohan Hedberg if (hdev->features[4] & LMP_LE) 546d5859e22SJohan Hedberg events[7] |= 0x20; /* LE Meta-Event */ 547d5859e22SJohan Hedberg 548d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); 549d5859e22SJohan Hedberg } 550d5859e22SJohan Hedberg 551e6100a25SAndre Guedes static void hci_set_le_support(struct hci_dev *hdev) 552e6100a25SAndre Guedes { 553e6100a25SAndre Guedes struct hci_cp_write_le_host_supported cp; 554e6100a25SAndre Guedes 555e6100a25SAndre Guedes memset(&cp, 0, sizeof(cp)); 556e6100a25SAndre Guedes 557e6100a25SAndre Guedes if (enable_le) { 558e6100a25SAndre Guedes cp.le = 1; 559e6100a25SAndre Guedes cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR); 560e6100a25SAndre Guedes } 561e6100a25SAndre Guedes 562e6100a25SAndre Guedes hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), &cp); 563e6100a25SAndre Guedes } 564e6100a25SAndre Guedes 565d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev) 566d5859e22SJohan Hedberg { 567e61ef499SAndrei Emeltchenko if (hdev->dev_type != HCI_BREDR) 568e61ef499SAndrei Emeltchenko return; 569e61ef499SAndrei Emeltchenko 570d5859e22SJohan Hedberg hci_setup_event_mask(hdev); 571d5859e22SJohan Hedberg 572d095c1ebSAndrei Emeltchenko if (hdev->hci_ver > BLUETOOTH_VER_1_1) 573d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); 574d5859e22SJohan Hedberg 575d5859e22SJohan Hedberg if (hdev->features[6] & LMP_SIMPLE_PAIR) { 576d5859e22SJohan Hedberg u8 mode = 0x01; 577d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode); 578d5859e22SJohan Hedberg } 579d5859e22SJohan Hedberg 580d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 581d5859e22SJohan Hedberg hci_setup_inquiry_mode(hdev); 582d5859e22SJohan Hedberg 583d5859e22SJohan Hedberg if (hdev->features[7] & LMP_INQ_TX_PWR) 584d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL); 585971e3a4bSAndre Guedes 586971e3a4bSAndre Guedes if (hdev->features[7] & LMP_EXTFEATURES) { 587971e3a4bSAndre Guedes struct hci_cp_read_local_ext_features cp; 588971e3a4bSAndre Guedes 589971e3a4bSAndre Guedes cp.page = 0x01; 590971e3a4bSAndre Guedes hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, 591971e3a4bSAndre Guedes sizeof(cp), &cp); 592971e3a4bSAndre Guedes } 593e6100a25SAndre Guedes 594e6100a25SAndre Guedes if (hdev->features[4] & LMP_LE) 595e6100a25SAndre Guedes hci_set_le_support(hdev); 596d5859e22SJohan Hedberg } 597d5859e22SJohan Hedberg 598a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) 599a9de9248SMarcel Holtmann { 600a9de9248SMarcel Holtmann struct hci_rp_read_local_version *rp = (void *) skb->data; 6011143e5a6SMarcel Holtmann 602a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 6031143e5a6SMarcel Holtmann 604a9de9248SMarcel Holtmann if (rp->status) 605a9de9248SMarcel Holtmann return; 6061143e5a6SMarcel Holtmann 607a9de9248SMarcel Holtmann hdev->hci_ver = rp->hci_ver; 608e4e8e37cSMarcel Holtmann hdev->hci_rev = __le16_to_cpu(rp->hci_rev); 609d5859e22SJohan Hedberg hdev->lmp_ver = rp->lmp_ver; 610e4e8e37cSMarcel Holtmann hdev->manufacturer = __le16_to_cpu(rp->manufacturer); 611d5859e22SJohan Hedberg hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); 6121da177e4SLinus Torvalds 613a9de9248SMarcel Holtmann BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name, 614a9de9248SMarcel Holtmann hdev->manufacturer, 615a9de9248SMarcel Holtmann hdev->hci_ver, hdev->hci_rev); 616d5859e22SJohan Hedberg 617d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags)) 618d5859e22SJohan Hedberg hci_setup(hdev); 619d5859e22SJohan Hedberg } 620d5859e22SJohan Hedberg 621d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev) 622d5859e22SJohan Hedberg { 623d5859e22SJohan Hedberg u16 link_policy = 0; 624d5859e22SJohan Hedberg 625d5859e22SJohan Hedberg if (hdev->features[0] & LMP_RSWITCH) 626d5859e22SJohan Hedberg link_policy |= HCI_LP_RSWITCH; 627d5859e22SJohan Hedberg if (hdev->features[0] & LMP_HOLD) 628d5859e22SJohan Hedberg link_policy |= HCI_LP_HOLD; 629d5859e22SJohan Hedberg if (hdev->features[0] & LMP_SNIFF) 630d5859e22SJohan Hedberg link_policy |= HCI_LP_SNIFF; 631d5859e22SJohan Hedberg if (hdev->features[1] & LMP_PARK) 632d5859e22SJohan Hedberg link_policy |= HCI_LP_PARK; 633d5859e22SJohan Hedberg 634d5859e22SJohan Hedberg link_policy = cpu_to_le16(link_policy); 635d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, 636d5859e22SJohan Hedberg sizeof(link_policy), &link_policy); 6371da177e4SLinus Torvalds } 6381da177e4SLinus Torvalds 639a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb) 640a9de9248SMarcel Holtmann { 641a9de9248SMarcel Holtmann struct hci_rp_read_local_commands *rp = (void *) skb->data; 642a9de9248SMarcel Holtmann 643a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 644a9de9248SMarcel Holtmann 645a9de9248SMarcel Holtmann if (rp->status) 646d5859e22SJohan Hedberg goto done; 647a9de9248SMarcel Holtmann 648a9de9248SMarcel Holtmann memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); 649d5859e22SJohan Hedberg 650d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10)) 651d5859e22SJohan Hedberg hci_setup_link_policy(hdev); 652d5859e22SJohan Hedberg 653d5859e22SJohan Hedberg done: 654d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status); 655a9de9248SMarcel Holtmann } 656a9de9248SMarcel Holtmann 657a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb) 658a9de9248SMarcel Holtmann { 659a9de9248SMarcel Holtmann struct hci_rp_read_local_features *rp = (void *) skb->data; 660a9de9248SMarcel Holtmann 661a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 662a9de9248SMarcel Holtmann 663a9de9248SMarcel Holtmann if (rp->status) 664a9de9248SMarcel Holtmann return; 665a9de9248SMarcel Holtmann 666a9de9248SMarcel Holtmann memcpy(hdev->features, rp->features, 8); 6671da177e4SLinus Torvalds 6681da177e4SLinus Torvalds /* Adjust default settings according to features 6691da177e4SLinus Torvalds * supported by device. */ 670a9de9248SMarcel Holtmann 6711da177e4SLinus Torvalds if (hdev->features[0] & LMP_3SLOT) 6721da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM3 | HCI_DH3); 6731da177e4SLinus Torvalds 6741da177e4SLinus Torvalds if (hdev->features[0] & LMP_5SLOT) 6751da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM5 | HCI_DH5); 6761da177e4SLinus Torvalds 6775b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV2) { 6781da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV2); 6795b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV2); 6805b7f9909SMarcel Holtmann } 6811da177e4SLinus Torvalds 6825b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV3) { 6831da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV3); 6845b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV3); 6855b7f9909SMarcel Holtmann } 6865b7f9909SMarcel Holtmann 6875b7f9909SMarcel Holtmann if (hdev->features[3] & LMP_ESCO) 6885b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV3); 6895b7f9909SMarcel Holtmann 6905b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV4) 6915b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV4); 6925b7f9909SMarcel Holtmann 6935b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV5) 6945b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV5); 6951da177e4SLinus Torvalds 696efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_2M) 697efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV3); 698efc7688bSMarcel Holtmann 699efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_3M) 700efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_3EV3); 701efc7688bSMarcel Holtmann 702efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_3S_ESCO) 703efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); 704efc7688bSMarcel Holtmann 705a9de9248SMarcel Holtmann BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, 706a9de9248SMarcel Holtmann hdev->features[0], hdev->features[1], 707a9de9248SMarcel Holtmann hdev->features[2], hdev->features[3], 708a9de9248SMarcel Holtmann hdev->features[4], hdev->features[5], 709a9de9248SMarcel Holtmann hdev->features[6], hdev->features[7]); 7101da177e4SLinus Torvalds } 7111da177e4SLinus Torvalds 712971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev, 713971e3a4bSAndre Guedes struct sk_buff *skb) 714971e3a4bSAndre Guedes { 715971e3a4bSAndre Guedes struct hci_rp_read_local_ext_features *rp = (void *) skb->data; 716971e3a4bSAndre Guedes 717971e3a4bSAndre Guedes BT_DBG("%s status 0x%x", hdev->name, rp->status); 718971e3a4bSAndre Guedes 719971e3a4bSAndre Guedes if (rp->status) 720971e3a4bSAndre Guedes return; 721971e3a4bSAndre Guedes 722b5b32b65SAndre Guedes switch (rp->page) { 723b5b32b65SAndre Guedes case 0: 724b5b32b65SAndre Guedes memcpy(hdev->features, rp->features, 8); 725b5b32b65SAndre Guedes break; 726b5b32b65SAndre Guedes case 1: 72759e29406SAndre Guedes memcpy(hdev->host_features, rp->features, 8); 728b5b32b65SAndre Guedes break; 729b5b32b65SAndre Guedes } 730971e3a4bSAndre Guedes 731971e3a4bSAndre Guedes hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status); 732971e3a4bSAndre Guedes } 733971e3a4bSAndre Guedes 7341e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, 7351e89cffbSAndrei Emeltchenko struct sk_buff *skb) 7361e89cffbSAndrei Emeltchenko { 7371e89cffbSAndrei Emeltchenko struct hci_rp_read_flow_control_mode *rp = (void *) skb->data; 7381e89cffbSAndrei Emeltchenko 7391e89cffbSAndrei Emeltchenko BT_DBG("%s status 0x%x", hdev->name, rp->status); 7401e89cffbSAndrei Emeltchenko 7411e89cffbSAndrei Emeltchenko if (rp->status) 7421e89cffbSAndrei Emeltchenko return; 7431e89cffbSAndrei Emeltchenko 7441e89cffbSAndrei Emeltchenko hdev->flow_ctl_mode = rp->mode; 7451e89cffbSAndrei Emeltchenko 7461e89cffbSAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status); 7471e89cffbSAndrei Emeltchenko } 7481e89cffbSAndrei Emeltchenko 749a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 750a9de9248SMarcel Holtmann { 751a9de9248SMarcel Holtmann struct hci_rp_read_buffer_size *rp = (void *) skb->data; 752a9de9248SMarcel Holtmann 753a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 754a9de9248SMarcel Holtmann 755a9de9248SMarcel Holtmann if (rp->status) 756a9de9248SMarcel Holtmann return; 757a9de9248SMarcel Holtmann 758a9de9248SMarcel Holtmann hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); 759a9de9248SMarcel Holtmann hdev->sco_mtu = rp->sco_mtu; 760a9de9248SMarcel Holtmann hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); 761a9de9248SMarcel Holtmann hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); 762da1f5198SMarcel Holtmann 763da1f5198SMarcel Holtmann if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { 764da1f5198SMarcel Holtmann hdev->sco_mtu = 64; 765da1f5198SMarcel Holtmann hdev->sco_pkts = 8; 766da1f5198SMarcel Holtmann } 767da1f5198SMarcel Holtmann 768da1f5198SMarcel Holtmann hdev->acl_cnt = hdev->acl_pkts; 769da1f5198SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 7701da177e4SLinus Torvalds 771a9de9248SMarcel Holtmann BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, 772a9de9248SMarcel Holtmann hdev->acl_mtu, hdev->acl_pkts, 773a9de9248SMarcel Holtmann hdev->sco_mtu, hdev->sco_pkts); 7741da177e4SLinus Torvalds } 7751da177e4SLinus Torvalds 776a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) 777a9de9248SMarcel Holtmann { 778a9de9248SMarcel Holtmann struct hci_rp_read_bd_addr *rp = (void *) skb->data; 7791da177e4SLinus Torvalds 780a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 781a9de9248SMarcel Holtmann 782a9de9248SMarcel Holtmann if (!rp->status) 783a9de9248SMarcel Holtmann bacpy(&hdev->bdaddr, &rp->bdaddr); 784a9de9248SMarcel Holtmann 78523bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status); 78623bb5763SJohan Hedberg } 78723bb5763SJohan Hedberg 788350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev, 789350ee4cfSAndrei Emeltchenko struct sk_buff *skb) 790350ee4cfSAndrei Emeltchenko { 791350ee4cfSAndrei Emeltchenko struct hci_rp_read_data_block_size *rp = (void *) skb->data; 792350ee4cfSAndrei Emeltchenko 793350ee4cfSAndrei Emeltchenko BT_DBG("%s status 0x%x", hdev->name, rp->status); 794350ee4cfSAndrei Emeltchenko 795350ee4cfSAndrei Emeltchenko if (rp->status) 796350ee4cfSAndrei Emeltchenko return; 797350ee4cfSAndrei Emeltchenko 798350ee4cfSAndrei Emeltchenko hdev->block_mtu = __le16_to_cpu(rp->max_acl_len); 799350ee4cfSAndrei Emeltchenko hdev->block_len = __le16_to_cpu(rp->block_len); 800350ee4cfSAndrei Emeltchenko hdev->num_blocks = __le16_to_cpu(rp->num_blocks); 801350ee4cfSAndrei Emeltchenko 802350ee4cfSAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 803350ee4cfSAndrei Emeltchenko 804350ee4cfSAndrei Emeltchenko BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu, 805350ee4cfSAndrei Emeltchenko hdev->block_cnt, hdev->block_len); 806350ee4cfSAndrei Emeltchenko 807350ee4cfSAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status); 808350ee4cfSAndrei Emeltchenko } 809350ee4cfSAndrei Emeltchenko 81023bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb) 81123bb5763SJohan Hedberg { 81223bb5763SJohan Hedberg __u8 status = *((__u8 *) skb->data); 81323bb5763SJohan Hedberg 81423bb5763SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 81523bb5763SJohan Hedberg 81623bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status); 8171da177e4SLinus Torvalds } 8181da177e4SLinus Torvalds 819928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev, 820928abaa7SAndrei Emeltchenko struct sk_buff *skb) 821928abaa7SAndrei Emeltchenko { 822928abaa7SAndrei Emeltchenko struct hci_rp_read_local_amp_info *rp = (void *) skb->data; 823928abaa7SAndrei Emeltchenko 824928abaa7SAndrei Emeltchenko BT_DBG("%s status 0x%x", hdev->name, rp->status); 825928abaa7SAndrei Emeltchenko 826928abaa7SAndrei Emeltchenko if (rp->status) 827928abaa7SAndrei Emeltchenko return; 828928abaa7SAndrei Emeltchenko 829928abaa7SAndrei Emeltchenko hdev->amp_status = rp->amp_status; 830928abaa7SAndrei Emeltchenko hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); 831928abaa7SAndrei Emeltchenko hdev->amp_max_bw = __le32_to_cpu(rp->max_bw); 832928abaa7SAndrei Emeltchenko hdev->amp_min_latency = __le32_to_cpu(rp->min_latency); 833928abaa7SAndrei Emeltchenko hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu); 834928abaa7SAndrei Emeltchenko hdev->amp_type = rp->amp_type; 835928abaa7SAndrei Emeltchenko hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap); 836928abaa7SAndrei Emeltchenko hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size); 837928abaa7SAndrei Emeltchenko hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); 838928abaa7SAndrei Emeltchenko hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); 839928abaa7SAndrei Emeltchenko 840928abaa7SAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status); 841928abaa7SAndrei Emeltchenko } 842928abaa7SAndrei Emeltchenko 843b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, 844b0916ea0SJohan Hedberg struct sk_buff *skb) 845b0916ea0SJohan Hedberg { 846b0916ea0SJohan Hedberg __u8 status = *((__u8 *) skb->data); 847b0916ea0SJohan Hedberg 848b0916ea0SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 849b0916ea0SJohan Hedberg 850b0916ea0SJohan Hedberg hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status); 851b0916ea0SJohan Hedberg } 852b0916ea0SJohan Hedberg 853d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb) 854d5859e22SJohan Hedberg { 855d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 856d5859e22SJohan Hedberg 857d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 858d5859e22SJohan Hedberg 859d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status); 860d5859e22SJohan Hedberg } 861d5859e22SJohan Hedberg 862d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev, 863d5859e22SJohan Hedberg struct sk_buff *skb) 864d5859e22SJohan Hedberg { 865d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 866d5859e22SJohan Hedberg 867d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 868d5859e22SJohan Hedberg 869d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status); 870d5859e22SJohan Hedberg } 871d5859e22SJohan Hedberg 872d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, 873d5859e22SJohan Hedberg struct sk_buff *skb) 874d5859e22SJohan Hedberg { 875d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 876d5859e22SJohan Hedberg 877d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 878d5859e22SJohan Hedberg 879d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status); 880d5859e22SJohan Hedberg } 881d5859e22SJohan Hedberg 882d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb) 883d5859e22SJohan Hedberg { 884d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 885d5859e22SJohan Hedberg 886d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 887d5859e22SJohan Hedberg 888d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status); 889d5859e22SJohan Hedberg } 890d5859e22SJohan Hedberg 891980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) 892980e1a53SJohan Hedberg { 893980e1a53SJohan Hedberg struct hci_rp_pin_code_reply *rp = (void *) skb->data; 894980e1a53SJohan Hedberg struct hci_cp_pin_code_reply *cp; 895980e1a53SJohan Hedberg struct hci_conn *conn; 896980e1a53SJohan Hedberg 897980e1a53SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 898980e1a53SJohan Hedberg 89956e5cb86SJohan Hedberg hci_dev_lock(hdev); 90056e5cb86SJohan Hedberg 901a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 902744cf19eSJohan Hedberg mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); 903980e1a53SJohan Hedberg 904980e1a53SJohan Hedberg if (rp->status != 0) 90556e5cb86SJohan Hedberg goto unlock; 906980e1a53SJohan Hedberg 907980e1a53SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); 908980e1a53SJohan Hedberg if (!cp) 90956e5cb86SJohan Hedberg goto unlock; 910980e1a53SJohan Hedberg 911980e1a53SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 912980e1a53SJohan Hedberg if (conn) 913980e1a53SJohan Hedberg conn->pin_length = cp->pin_len; 91456e5cb86SJohan Hedberg 91556e5cb86SJohan Hedberg unlock: 91656e5cb86SJohan Hedberg hci_dev_unlock(hdev); 917980e1a53SJohan Hedberg } 918980e1a53SJohan Hedberg 919980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 920980e1a53SJohan Hedberg { 921980e1a53SJohan Hedberg struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data; 922980e1a53SJohan Hedberg 923980e1a53SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 924980e1a53SJohan Hedberg 92556e5cb86SJohan Hedberg hci_dev_lock(hdev); 92656e5cb86SJohan Hedberg 927a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 928744cf19eSJohan Hedberg mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr, 929980e1a53SJohan Hedberg rp->status); 93056e5cb86SJohan Hedberg 93156e5cb86SJohan Hedberg hci_dev_unlock(hdev); 932980e1a53SJohan Hedberg } 93356e5cb86SJohan Hedberg 9346ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, 9356ed58ec5SVille Tervo struct sk_buff *skb) 9366ed58ec5SVille Tervo { 9376ed58ec5SVille Tervo struct hci_rp_le_read_buffer_size *rp = (void *) skb->data; 9386ed58ec5SVille Tervo 9396ed58ec5SVille Tervo BT_DBG("%s status 0x%x", hdev->name, rp->status); 9406ed58ec5SVille Tervo 9416ed58ec5SVille Tervo if (rp->status) 9426ed58ec5SVille Tervo return; 9436ed58ec5SVille Tervo 9446ed58ec5SVille Tervo hdev->le_mtu = __le16_to_cpu(rp->le_mtu); 9456ed58ec5SVille Tervo hdev->le_pkts = rp->le_max_pkt; 9466ed58ec5SVille Tervo 9476ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 9486ed58ec5SVille Tervo 9496ed58ec5SVille Tervo BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); 9506ed58ec5SVille Tervo 9516ed58ec5SVille Tervo hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status); 9526ed58ec5SVille Tervo } 953980e1a53SJohan Hedberg 954a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) 955a5c29683SJohan Hedberg { 956a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 957a5c29683SJohan Hedberg 958a5c29683SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 959a5c29683SJohan Hedberg 96056e5cb86SJohan Hedberg hci_dev_lock(hdev); 96156e5cb86SJohan Hedberg 962a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 963744cf19eSJohan Hedberg mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, 964a5c29683SJohan Hedberg rp->status); 96556e5cb86SJohan Hedberg 96656e5cb86SJohan Hedberg hci_dev_unlock(hdev); 967a5c29683SJohan Hedberg } 968a5c29683SJohan Hedberg 969a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, 970a5c29683SJohan Hedberg struct sk_buff *skb) 971a5c29683SJohan Hedberg { 972a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 973a5c29683SJohan Hedberg 974a5c29683SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 975a5c29683SJohan Hedberg 97656e5cb86SJohan Hedberg hci_dev_lock(hdev); 97756e5cb86SJohan Hedberg 978a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 979744cf19eSJohan Hedberg mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr, 980a5c29683SJohan Hedberg rp->status); 98156e5cb86SJohan Hedberg 98256e5cb86SJohan Hedberg hci_dev_unlock(hdev); 983a5c29683SJohan Hedberg } 984a5c29683SJohan Hedberg 9851143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb) 9861143d458SBrian Gix { 9871143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 9881143d458SBrian Gix 9891143d458SBrian Gix BT_DBG("%s status 0x%x", hdev->name, rp->status); 9901143d458SBrian Gix 9911143d458SBrian Gix hci_dev_lock(hdev); 9921143d458SBrian Gix 993a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 9941143d458SBrian Gix mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, 9951143d458SBrian Gix rp->status); 9961143d458SBrian Gix 9971143d458SBrian Gix hci_dev_unlock(hdev); 9981143d458SBrian Gix } 9991143d458SBrian Gix 10001143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, 10011143d458SBrian Gix struct sk_buff *skb) 10021143d458SBrian Gix { 10031143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 10041143d458SBrian Gix 10051143d458SBrian Gix BT_DBG("%s status 0x%x", hdev->name, rp->status); 10061143d458SBrian Gix 10071143d458SBrian Gix hci_dev_lock(hdev); 10081143d458SBrian Gix 1009a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 10101143d458SBrian Gix mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr, 10111143d458SBrian Gix rp->status); 10121143d458SBrian Gix 10131143d458SBrian Gix hci_dev_unlock(hdev); 10141143d458SBrian Gix } 10151143d458SBrian Gix 1016c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, 1017c35938b2SSzymon Janc struct sk_buff *skb) 1018c35938b2SSzymon Janc { 1019c35938b2SSzymon Janc struct hci_rp_read_local_oob_data *rp = (void *) skb->data; 1020c35938b2SSzymon Janc 1021c35938b2SSzymon Janc BT_DBG("%s status 0x%x", hdev->name, rp->status); 1022c35938b2SSzymon Janc 102356e5cb86SJohan Hedberg hci_dev_lock(hdev); 1024744cf19eSJohan Hedberg mgmt_read_local_oob_data_reply_complete(hdev, rp->hash, 1025c35938b2SSzymon Janc rp->randomizer, rp->status); 102656e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1027c35938b2SSzymon Janc } 1028c35938b2SSzymon Janc 102907f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) 103007f7fa5dSAndre Guedes { 103107f7fa5dSAndre Guedes __u8 status = *((__u8 *) skb->data); 103207f7fa5dSAndre Guedes 103307f7fa5dSAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 103407f7fa5dSAndre Guedes } 103507f7fa5dSAndre Guedes 1036eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, 1037eb9d91f5SAndre Guedes struct sk_buff *skb) 1038eb9d91f5SAndre Guedes { 1039eb9d91f5SAndre Guedes struct hci_cp_le_set_scan_enable *cp; 1040eb9d91f5SAndre Guedes __u8 status = *((__u8 *) skb->data); 1041eb9d91f5SAndre Guedes 1042eb9d91f5SAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 1043eb9d91f5SAndre Guedes 1044eb9d91f5SAndre Guedes if (status) 1045eb9d91f5SAndre Guedes return; 1046eb9d91f5SAndre Guedes 1047eb9d91f5SAndre Guedes cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE); 1048eb9d91f5SAndre Guedes if (!cp) 1049eb9d91f5SAndre Guedes return; 1050eb9d91f5SAndre Guedes 105168a8aea4SAndrei Emeltchenko switch (cp->enable) { 105268a8aea4SAndrei Emeltchenko case LE_SCANNING_ENABLED: 1053d23264a8SAndre Guedes set_bit(HCI_LE_SCAN, &hdev->dev_flags); 1054d23264a8SAndre Guedes 1055db323f2fSGustavo F. Padovan cancel_delayed_work_sync(&hdev->adv_work); 1056a8f13c8cSAndre Guedes 1057a8f13c8cSAndre Guedes hci_dev_lock(hdev); 1058eb9d91f5SAndre Guedes hci_adv_entries_clear(hdev); 1059c599008fSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_LE_SCAN); 1060a8f13c8cSAndre Guedes hci_dev_unlock(hdev); 106168a8aea4SAndrei Emeltchenko break; 106268a8aea4SAndrei Emeltchenko 106368a8aea4SAndrei Emeltchenko case LE_SCANNING_DISABLED: 1064d23264a8SAndre Guedes clear_bit(HCI_LE_SCAN, &hdev->dev_flags); 1065d23264a8SAndre Guedes 1066c599008fSAndre Guedes hci_dev_lock(hdev); 1067c599008fSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 1068c599008fSAndre Guedes hci_dev_unlock(hdev); 1069c599008fSAndre Guedes 1070d084329eSAndre Guedes schedule_delayed_work(&hdev->adv_work, ADV_CLEAR_TIMEOUT); 107168a8aea4SAndrei Emeltchenko break; 107268a8aea4SAndrei Emeltchenko 107368a8aea4SAndrei Emeltchenko default: 107468a8aea4SAndrei Emeltchenko BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable); 107568a8aea4SAndrei Emeltchenko break; 107635815085SAndre Guedes } 1077eb9d91f5SAndre Guedes } 1078eb9d91f5SAndre Guedes 1079a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb) 1080a7a595f6SVinicius Costa Gomes { 1081a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_reply *rp = (void *) skb->data; 1082a7a595f6SVinicius Costa Gomes 1083a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, rp->status); 1084a7a595f6SVinicius Costa Gomes 1085a7a595f6SVinicius Costa Gomes if (rp->status) 1086a7a595f6SVinicius Costa Gomes return; 1087a7a595f6SVinicius Costa Gomes 1088a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status); 1089a7a595f6SVinicius Costa Gomes } 1090a7a595f6SVinicius Costa Gomes 1091a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 1092a7a595f6SVinicius Costa Gomes { 1093a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data; 1094a7a595f6SVinicius Costa Gomes 1095a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, rp->status); 1096a7a595f6SVinicius Costa Gomes 1097a7a595f6SVinicius Costa Gomes if (rp->status) 1098a7a595f6SVinicius Costa Gomes return; 1099a7a595f6SVinicius Costa Gomes 1100a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status); 1101a7a595f6SVinicius Costa Gomes } 1102a7a595f6SVinicius Costa Gomes 1103f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev, 1104f9b49306SAndre Guedes struct sk_buff *skb) 1105f9b49306SAndre Guedes { 1106f9b49306SAndre Guedes struct hci_cp_read_local_ext_features cp; 1107f9b49306SAndre Guedes __u8 status = *((__u8 *) skb->data); 1108f9b49306SAndre Guedes 1109f9b49306SAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 1110f9b49306SAndre Guedes 1111f9b49306SAndre Guedes if (status) 1112f9b49306SAndre Guedes return; 1113f9b49306SAndre Guedes 1114f9b49306SAndre Guedes cp.page = 0x01; 1115f9b49306SAndre Guedes hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp); 1116f9b49306SAndre Guedes } 1117f9b49306SAndre Guedes 1118a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 1119a9de9248SMarcel Holtmann { 1120a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1121a9de9248SMarcel Holtmann 1122a9de9248SMarcel Holtmann if (status) { 112323bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 1124a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 112556e5cb86SJohan Hedberg hci_dev_lock(hdev); 1126a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 11277a135109SAndre Guedes mgmt_start_discovery_failed(hdev, status); 112856e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1129314b2381SJohan Hedberg return; 1130314b2381SJohan Hedberg } 1131314b2381SJohan Hedberg 113289352e7dSAndre Guedes set_bit(HCI_INQUIRY, &hdev->flags); 113389352e7dSAndre Guedes 113456e5cb86SJohan Hedberg hci_dev_lock(hdev); 113530dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_INQUIRY); 113656e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1137a9de9248SMarcel Holtmann } 1138a9de9248SMarcel Holtmann 11391da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 11401da177e4SLinus Torvalds { 1141a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 11421da177e4SLinus Torvalds struct hci_conn *conn; 11431da177e4SLinus Torvalds 1144a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1145a9de9248SMarcel Holtmann 1146a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 11471da177e4SLinus Torvalds if (!cp) 11481da177e4SLinus Torvalds return; 11491da177e4SLinus Torvalds 11501da177e4SLinus Torvalds hci_dev_lock(hdev); 11511da177e4SLinus Torvalds 11521da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 11531da177e4SLinus Torvalds 1154a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn); 11551da177e4SLinus Torvalds 11561da177e4SLinus Torvalds if (status) { 11571da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 11584c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 11591da177e4SLinus Torvalds conn->state = BT_CLOSED; 11601da177e4SLinus Torvalds hci_proto_connect_cfm(conn, status); 11611da177e4SLinus Torvalds hci_conn_del(conn); 11624c67bc74SMarcel Holtmann } else 11634c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 11641da177e4SLinus Torvalds } 11651da177e4SLinus Torvalds } else { 11661da177e4SLinus Torvalds if (!conn) { 11671da177e4SLinus Torvalds conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); 11681da177e4SLinus Torvalds if (conn) { 1169a0c808b3SJohan Hedberg conn->out = true; 11701da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 11711da177e4SLinus Torvalds } else 1172893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 11731da177e4SLinus Torvalds } 11741da177e4SLinus Torvalds } 11751da177e4SLinus Torvalds 11761da177e4SLinus Torvalds hci_dev_unlock(hdev); 11771da177e4SLinus Torvalds } 11781da177e4SLinus Torvalds 1179a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 11801da177e4SLinus Torvalds { 1181a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 11821da177e4SLinus Torvalds struct hci_conn *acl, *sco; 11831da177e4SLinus Torvalds __u16 handle; 11841da177e4SLinus Torvalds 1185b6a0dc82SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1186b6a0dc82SMarcel Holtmann 1187a9de9248SMarcel Holtmann if (!status) 1188a9de9248SMarcel Holtmann return; 1189a9de9248SMarcel Holtmann 1190a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 11911da177e4SLinus Torvalds if (!cp) 1192a9de9248SMarcel Holtmann return; 11931da177e4SLinus Torvalds 11941da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 11951da177e4SLinus Torvalds 1196a9de9248SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 11971da177e4SLinus Torvalds 11981da177e4SLinus Torvalds hci_dev_lock(hdev); 11991da177e4SLinus Torvalds 12001da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 12015a08ecceSAndrei Emeltchenko if (acl) { 12025a08ecceSAndrei Emeltchenko sco = acl->link; 12035a08ecceSAndrei Emeltchenko if (sco) { 12041da177e4SLinus Torvalds sco->state = BT_CLOSED; 12051da177e4SLinus Torvalds 12061da177e4SLinus Torvalds hci_proto_connect_cfm(sco, status); 12071da177e4SLinus Torvalds hci_conn_del(sco); 12081da177e4SLinus Torvalds } 12095a08ecceSAndrei Emeltchenko } 12101da177e4SLinus Torvalds 12111da177e4SLinus Torvalds hci_dev_unlock(hdev); 12121da177e4SLinus Torvalds } 12131da177e4SLinus Torvalds 1214f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 1215f8558555SMarcel Holtmann { 1216f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 1217f8558555SMarcel Holtmann struct hci_conn *conn; 1218f8558555SMarcel Holtmann 1219f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1220f8558555SMarcel Holtmann 1221f8558555SMarcel Holtmann if (!status) 1222f8558555SMarcel Holtmann return; 1223f8558555SMarcel Holtmann 1224f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 1225f8558555SMarcel Holtmann if (!cp) 1226f8558555SMarcel Holtmann return; 1227f8558555SMarcel Holtmann 1228f8558555SMarcel Holtmann hci_dev_lock(hdev); 1229f8558555SMarcel Holtmann 1230f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1231f8558555SMarcel Holtmann if (conn) { 1232f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1233f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1234f8558555SMarcel Holtmann hci_conn_put(conn); 1235f8558555SMarcel Holtmann } 1236f8558555SMarcel Holtmann } 1237f8558555SMarcel Holtmann 1238f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1239f8558555SMarcel Holtmann } 1240f8558555SMarcel Holtmann 1241f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 1242f8558555SMarcel Holtmann { 1243f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 1244f8558555SMarcel Holtmann struct hci_conn *conn; 1245f8558555SMarcel Holtmann 1246f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1247f8558555SMarcel Holtmann 1248f8558555SMarcel Holtmann if (!status) 1249f8558555SMarcel Holtmann return; 1250f8558555SMarcel Holtmann 1251f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 1252f8558555SMarcel Holtmann if (!cp) 1253f8558555SMarcel Holtmann return; 1254f8558555SMarcel Holtmann 1255f8558555SMarcel Holtmann hci_dev_lock(hdev); 1256f8558555SMarcel Holtmann 1257f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1258f8558555SMarcel Holtmann if (conn) { 1259f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1260f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1261f8558555SMarcel Holtmann hci_conn_put(conn); 1262f8558555SMarcel Holtmann } 1263f8558555SMarcel Holtmann } 1264f8558555SMarcel Holtmann 1265f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1266f8558555SMarcel Holtmann } 1267f8558555SMarcel Holtmann 1268127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev, 1269392599b9SJohan Hedberg struct hci_conn *conn) 1270392599b9SJohan Hedberg { 1271392599b9SJohan Hedberg if (conn->state != BT_CONFIG || !conn->out) 1272392599b9SJohan Hedberg return 0; 1273392599b9SJohan Hedberg 1274765c2a96SJohan Hedberg if (conn->pending_sec_level == BT_SECURITY_SDP) 1275392599b9SJohan Hedberg return 0; 1276392599b9SJohan Hedberg 1277392599b9SJohan Hedberg /* Only request authentication for SSP connections or non-SSP 1278e9bf2bf0SVinicius Costa Gomes * devices with sec_level HIGH or if MITM protection is requested */ 1279aa64a8b5SJohan Hedberg if (!hci_conn_ssp_enabled(conn) && 1280e9bf2bf0SVinicius Costa Gomes conn->pending_sec_level != BT_SECURITY_HIGH && 1281e9bf2bf0SVinicius Costa Gomes !(conn->auth_type & 0x01)) 1282392599b9SJohan Hedberg return 0; 1283392599b9SJohan Hedberg 1284392599b9SJohan Hedberg return 1; 1285392599b9SJohan Hedberg } 1286392599b9SJohan Hedberg 128730dc78e1SJohan Hedberg static inline int hci_resolve_name(struct hci_dev *hdev, struct inquiry_entry *e) 128830dc78e1SJohan Hedberg { 128930dc78e1SJohan Hedberg struct hci_cp_remote_name_req cp; 129030dc78e1SJohan Hedberg 129130dc78e1SJohan Hedberg memset(&cp, 0, sizeof(cp)); 129230dc78e1SJohan Hedberg 129330dc78e1SJohan Hedberg bacpy(&cp.bdaddr, &e->data.bdaddr); 129430dc78e1SJohan Hedberg cp.pscan_rep_mode = e->data.pscan_rep_mode; 129530dc78e1SJohan Hedberg cp.pscan_mode = e->data.pscan_mode; 129630dc78e1SJohan Hedberg cp.clock_offset = e->data.clock_offset; 129730dc78e1SJohan Hedberg 129830dc78e1SJohan Hedberg return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 129930dc78e1SJohan Hedberg } 130030dc78e1SJohan Hedberg 1301b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev) 130230dc78e1SJohan Hedberg { 130330dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 130430dc78e1SJohan Hedberg struct inquiry_entry *e; 130530dc78e1SJohan Hedberg 1306b644ba33SJohan Hedberg if (list_empty(&discov->resolve)) 1307b644ba33SJohan Hedberg return false; 1308b644ba33SJohan Hedberg 1309b644ba33SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 1310b644ba33SJohan Hedberg if (hci_resolve_name(hdev, e) == 0) { 1311b644ba33SJohan Hedberg e->name_state = NAME_PENDING; 1312b644ba33SJohan Hedberg return true; 1313b644ba33SJohan Hedberg } 1314b644ba33SJohan Hedberg 1315b644ba33SJohan Hedberg return false; 1316b644ba33SJohan Hedberg } 1317b644ba33SJohan Hedberg 1318b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn, 1319b644ba33SJohan Hedberg bdaddr_t *bdaddr, u8 *name, u8 name_len) 1320b644ba33SJohan Hedberg { 1321b644ba33SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 1322b644ba33SJohan Hedberg struct inquiry_entry *e; 1323b644ba33SJohan Hedberg 1324b644ba33SJohan Hedberg if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 1325b644ba33SJohan Hedberg mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 1326b644ba33SJohan Hedberg name, name_len, conn->dev_class); 1327b644ba33SJohan Hedberg 1328b644ba33SJohan Hedberg if (discov->state == DISCOVERY_STOPPED) 1329b644ba33SJohan Hedberg return; 1330b644ba33SJohan Hedberg 133130dc78e1SJohan Hedberg if (discov->state == DISCOVERY_STOPPING) 133230dc78e1SJohan Hedberg goto discov_complete; 133330dc78e1SJohan Hedberg 133430dc78e1SJohan Hedberg if (discov->state != DISCOVERY_RESOLVING) 133530dc78e1SJohan Hedberg return; 133630dc78e1SJohan Hedberg 133730dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING); 133830dc78e1SJohan Hedberg if (e) { 133930dc78e1SJohan Hedberg e->name_state = NAME_KNOWN; 134030dc78e1SJohan Hedberg list_del(&e->list); 1341b644ba33SJohan Hedberg if (name) 1342b644ba33SJohan Hedberg mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, 1343b644ba33SJohan Hedberg e->data.rssi, name, name_len); 134430dc78e1SJohan Hedberg } 134530dc78e1SJohan Hedberg 1346b644ba33SJohan Hedberg if (hci_resolve_next_name(hdev)) 134730dc78e1SJohan Hedberg return; 134830dc78e1SJohan Hedberg 134930dc78e1SJohan Hedberg discov_complete: 135030dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 135130dc78e1SJohan Hedberg } 135230dc78e1SJohan Hedberg 1353a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 13541da177e4SLinus Torvalds { 1355127178d2SJohan Hedberg struct hci_cp_remote_name_req *cp; 1356127178d2SJohan Hedberg struct hci_conn *conn; 1357127178d2SJohan Hedberg 1358a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1359127178d2SJohan Hedberg 1360127178d2SJohan Hedberg /* If successful wait for the name req complete event before 1361127178d2SJohan Hedberg * checking for the need to do authentication */ 1362127178d2SJohan Hedberg if (!status) 1363127178d2SJohan Hedberg return; 1364127178d2SJohan Hedberg 1365127178d2SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); 1366127178d2SJohan Hedberg if (!cp) 1367127178d2SJohan Hedberg return; 1368127178d2SJohan Hedberg 1369127178d2SJohan Hedberg hci_dev_lock(hdev); 1370127178d2SJohan Hedberg 1371127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 1372b644ba33SJohan Hedberg 1373b644ba33SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1374b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0); 1375b644ba33SJohan Hedberg 137679c6c70cSJohan Hedberg if (!conn) 137779c6c70cSJohan Hedberg goto unlock; 137879c6c70cSJohan Hedberg 137979c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 138079c6c70cSJohan Hedberg goto unlock; 138179c6c70cSJohan Hedberg 138251a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 1383127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1384127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1385127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1386127178d2SJohan Hedberg } 1387127178d2SJohan Hedberg 138879c6c70cSJohan Hedberg unlock: 1389127178d2SJohan Hedberg hci_dev_unlock(hdev); 1390a9de9248SMarcel Holtmann } 13911da177e4SLinus Torvalds 1392769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 1393769be974SMarcel Holtmann { 1394769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 1395769be974SMarcel Holtmann struct hci_conn *conn; 1396769be974SMarcel Holtmann 1397769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1398769be974SMarcel Holtmann 1399769be974SMarcel Holtmann if (!status) 1400769be974SMarcel Holtmann return; 1401769be974SMarcel Holtmann 1402769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 1403769be974SMarcel Holtmann if (!cp) 1404769be974SMarcel Holtmann return; 1405769be974SMarcel Holtmann 1406769be974SMarcel Holtmann hci_dev_lock(hdev); 1407769be974SMarcel Holtmann 1408769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1409769be974SMarcel Holtmann if (conn) { 1410769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1411769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1412769be974SMarcel Holtmann hci_conn_put(conn); 1413769be974SMarcel Holtmann } 1414769be974SMarcel Holtmann } 1415769be974SMarcel Holtmann 1416769be974SMarcel Holtmann hci_dev_unlock(hdev); 1417769be974SMarcel Holtmann } 1418769be974SMarcel Holtmann 1419769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 1420769be974SMarcel Holtmann { 1421769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features *cp; 1422769be974SMarcel Holtmann struct hci_conn *conn; 1423769be974SMarcel Holtmann 1424769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1425769be974SMarcel Holtmann 1426769be974SMarcel Holtmann if (!status) 1427769be974SMarcel Holtmann return; 1428769be974SMarcel Holtmann 1429769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 1430769be974SMarcel Holtmann if (!cp) 1431769be974SMarcel Holtmann return; 1432769be974SMarcel Holtmann 1433769be974SMarcel Holtmann hci_dev_lock(hdev); 1434769be974SMarcel Holtmann 1435769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1436769be974SMarcel Holtmann if (conn) { 1437769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1438769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1439769be974SMarcel Holtmann hci_conn_put(conn); 1440769be974SMarcel Holtmann } 1441769be974SMarcel Holtmann } 1442769be974SMarcel Holtmann 1443769be974SMarcel Holtmann hci_dev_unlock(hdev); 1444769be974SMarcel Holtmann } 1445769be974SMarcel Holtmann 1446a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 1447a9de9248SMarcel Holtmann { 1448b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 1449b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 1450b6a0dc82SMarcel Holtmann __u16 handle; 1451b6a0dc82SMarcel Holtmann 1452a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1453b6a0dc82SMarcel Holtmann 1454b6a0dc82SMarcel Holtmann if (!status) 1455b6a0dc82SMarcel Holtmann return; 1456b6a0dc82SMarcel Holtmann 1457b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 1458b6a0dc82SMarcel Holtmann if (!cp) 1459b6a0dc82SMarcel Holtmann return; 1460b6a0dc82SMarcel Holtmann 1461b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 1462b6a0dc82SMarcel Holtmann 1463b6a0dc82SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 1464b6a0dc82SMarcel Holtmann 1465b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 1466b6a0dc82SMarcel Holtmann 1467b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 14685a08ecceSAndrei Emeltchenko if (acl) { 14695a08ecceSAndrei Emeltchenko sco = acl->link; 14705a08ecceSAndrei Emeltchenko if (sco) { 1471b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 1472b6a0dc82SMarcel Holtmann 1473b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(sco, status); 1474b6a0dc82SMarcel Holtmann hci_conn_del(sco); 1475b6a0dc82SMarcel Holtmann } 14765a08ecceSAndrei Emeltchenko } 1477b6a0dc82SMarcel Holtmann 1478b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 1479a9de9248SMarcel Holtmann } 1480a9de9248SMarcel Holtmann 1481a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 1482a9de9248SMarcel Holtmann { 1483a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 148404837f64SMarcel Holtmann struct hci_conn *conn; 148504837f64SMarcel Holtmann 1486a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1487a9de9248SMarcel Holtmann 1488a9de9248SMarcel Holtmann if (!status) 1489a9de9248SMarcel Holtmann return; 1490a9de9248SMarcel Holtmann 1491a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 149204837f64SMarcel Holtmann if (!cp) 1493a9de9248SMarcel Holtmann return; 149404837f64SMarcel Holtmann 149504837f64SMarcel Holtmann hci_dev_lock(hdev); 149604837f64SMarcel Holtmann 149704837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1498e73439d8SMarcel Holtmann if (conn) { 149951a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 150004837f64SMarcel Holtmann 150151a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1502e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1503e73439d8SMarcel Holtmann } 1504e73439d8SMarcel Holtmann 150504837f64SMarcel Holtmann hci_dev_unlock(hdev); 150604837f64SMarcel Holtmann } 150704837f64SMarcel Holtmann 1508a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 1509a9de9248SMarcel Holtmann { 1510a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 151104837f64SMarcel Holtmann struct hci_conn *conn; 151204837f64SMarcel Holtmann 1513a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1514a9de9248SMarcel Holtmann 1515a9de9248SMarcel Holtmann if (!status) 1516a9de9248SMarcel Holtmann return; 1517a9de9248SMarcel Holtmann 1518a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 151904837f64SMarcel Holtmann if (!cp) 1520a9de9248SMarcel Holtmann return; 152104837f64SMarcel Holtmann 152204837f64SMarcel Holtmann hci_dev_lock(hdev); 152304837f64SMarcel Holtmann 152404837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1525e73439d8SMarcel Holtmann if (conn) { 152651a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 152704837f64SMarcel Holtmann 152851a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1529e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1530e73439d8SMarcel Holtmann } 1531e73439d8SMarcel Holtmann 153204837f64SMarcel Holtmann hci_dev_unlock(hdev); 153304837f64SMarcel Holtmann } 153404837f64SMarcel Holtmann 1535fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) 1536fcd89c09SVille Tervo { 1537fcd89c09SVille Tervo struct hci_cp_le_create_conn *cp; 1538fcd89c09SVille Tervo struct hci_conn *conn; 1539fcd89c09SVille Tervo 1540fcd89c09SVille Tervo BT_DBG("%s status 0x%x", hdev->name, status); 1541fcd89c09SVille Tervo 1542fcd89c09SVille Tervo cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN); 1543fcd89c09SVille Tervo if (!cp) 1544fcd89c09SVille Tervo return; 1545fcd89c09SVille Tervo 1546fcd89c09SVille Tervo hci_dev_lock(hdev); 1547fcd89c09SVille Tervo 1548fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr); 1549fcd89c09SVille Tervo 1550fcd89c09SVille Tervo BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr), 1551fcd89c09SVille Tervo conn); 1552fcd89c09SVille Tervo 1553fcd89c09SVille Tervo if (status) { 1554fcd89c09SVille Tervo if (conn && conn->state == BT_CONNECT) { 1555fcd89c09SVille Tervo conn->state = BT_CLOSED; 1556fcd89c09SVille Tervo hci_proto_connect_cfm(conn, status); 1557fcd89c09SVille Tervo hci_conn_del(conn); 1558fcd89c09SVille Tervo } 1559fcd89c09SVille Tervo } else { 1560fcd89c09SVille Tervo if (!conn) { 1561fcd89c09SVille Tervo conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr); 156229b7988aSAndre Guedes if (conn) { 156329b7988aSAndre Guedes conn->dst_type = cp->peer_addr_type; 1564a0c808b3SJohan Hedberg conn->out = true; 156529b7988aSAndre Guedes } else { 1566fcd89c09SVille Tervo BT_ERR("No memory for new connection"); 1567fcd89c09SVille Tervo } 1568fcd89c09SVille Tervo } 156929b7988aSAndre Guedes } 1570fcd89c09SVille Tervo 1571fcd89c09SVille Tervo hci_dev_unlock(hdev); 1572fcd89c09SVille Tervo } 1573fcd89c09SVille Tervo 1574a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) 1575a7a595f6SVinicius Costa Gomes { 1576a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, status); 1577a7a595f6SVinicius Costa Gomes } 1578a7a595f6SVinicius Costa Gomes 15791da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 15801da177e4SLinus Torvalds { 15811da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 158230dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 158330dc78e1SJohan Hedberg struct inquiry_entry *e; 15841da177e4SLinus Torvalds 15851da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, status); 15861da177e4SLinus Torvalds 158723bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 15886bd57416SMarcel Holtmann 1589a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 159089352e7dSAndre Guedes 159189352e7dSAndre Guedes if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) 159289352e7dSAndre Guedes return; 159389352e7dSAndre Guedes 1594a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 159530dc78e1SJohan Hedberg return; 159630dc78e1SJohan Hedberg 159756e5cb86SJohan Hedberg hci_dev_lock(hdev); 159830dc78e1SJohan Hedberg 159930dc78e1SJohan Hedberg if (discov->state != DISCOVERY_INQUIRY) 160030dc78e1SJohan Hedberg goto unlock; 160130dc78e1SJohan Hedberg 160230dc78e1SJohan Hedberg if (list_empty(&discov->resolve)) { 1603ff9ef578SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 160430dc78e1SJohan Hedberg goto unlock; 160530dc78e1SJohan Hedberg } 160630dc78e1SJohan Hedberg 160730dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 160830dc78e1SJohan Hedberg if (e && hci_resolve_name(hdev, e) == 0) { 160930dc78e1SJohan Hedberg e->name_state = NAME_PENDING; 161030dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_RESOLVING); 161130dc78e1SJohan Hedberg } else { 161230dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 161330dc78e1SJohan Hedberg } 161430dc78e1SJohan Hedberg 161530dc78e1SJohan Hedberg unlock: 161656e5cb86SJohan Hedberg hci_dev_unlock(hdev); 16171da177e4SLinus Torvalds } 16181da177e4SLinus Torvalds 16191da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 16201da177e4SLinus Torvalds { 162145bb4bf0SMarcel Holtmann struct inquiry_data data; 1622a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 16231da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 16241da177e4SLinus Torvalds 16251da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 16261da177e4SLinus Torvalds 162745bb4bf0SMarcel Holtmann if (!num_rsp) 162845bb4bf0SMarcel Holtmann return; 162945bb4bf0SMarcel Holtmann 16301da177e4SLinus Torvalds hci_dev_lock(hdev); 163145bb4bf0SMarcel Holtmann 1632e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 16333175405bSJohan Hedberg bool name_known; 16343175405bSJohan Hedberg 16351da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 16361da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 16371da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 16381da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 16391da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 16401da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 16411da177e4SLinus Torvalds data.rssi = 0x00; 164241a96212SMarcel Holtmann data.ssp_mode = 0x00; 16433175405bSJohan Hedberg 16443175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, false); 164548264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 16467d262f86SAndre Guedes info->dev_class, 0, !name_known, 16477d262f86SAndre Guedes NULL, 0); 16481da177e4SLinus Torvalds } 164945bb4bf0SMarcel Holtmann 16501da177e4SLinus Torvalds hci_dev_unlock(hdev); 16511da177e4SLinus Torvalds } 16521da177e4SLinus Torvalds 1653a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 16541da177e4SLinus Torvalds { 1655a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 1656a9de9248SMarcel Holtmann struct hci_conn *conn; 16571da177e4SLinus Torvalds 1658a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 165945bb4bf0SMarcel Holtmann 16601da177e4SLinus Torvalds hci_dev_lock(hdev); 166145bb4bf0SMarcel Holtmann 1662a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 16639499237aSMarcel Holtmann if (!conn) { 16649499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 16659499237aSMarcel Holtmann goto unlock; 16669499237aSMarcel Holtmann 16679499237aSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 1668a9de9248SMarcel Holtmann if (!conn) 1669a9de9248SMarcel Holtmann goto unlock; 167045bb4bf0SMarcel Holtmann 16719499237aSMarcel Holtmann conn->type = SCO_LINK; 16729499237aSMarcel Holtmann } 16739499237aSMarcel Holtmann 1674a9de9248SMarcel Holtmann if (!ev->status) { 1675a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 1676769be974SMarcel Holtmann 1677769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 1678769be974SMarcel Holtmann conn->state = BT_CONFIG; 1679769be974SMarcel Holtmann hci_conn_hold(conn); 1680052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1681769be974SMarcel Holtmann } else 1682a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 1683a9de9248SMarcel Holtmann 16849eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 16857d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 16867d0db0a3SMarcel Holtmann 1687a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 1688a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1689a9de9248SMarcel Holtmann 1690a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 1691a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1692a9de9248SMarcel Holtmann 1693a9de9248SMarcel Holtmann /* Get remote features */ 1694a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 1695a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 1696a9de9248SMarcel Holtmann cp.handle = ev->handle; 1697769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 1698769be974SMarcel Holtmann sizeof(cp), &cp); 169945bb4bf0SMarcel Holtmann } 1700a9de9248SMarcel Holtmann 1701a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 1702d095c1ebSAndrei Emeltchenko if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) { 1703a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 1704a9de9248SMarcel Holtmann cp.handle = ev->handle; 1705a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1706a8746417SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, 1707a8746417SMarcel Holtmann sizeof(cp), &cp); 1708a9de9248SMarcel Holtmann } 170917d5c04cSJohan Hedberg } else { 1710a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 171117d5c04cSJohan Hedberg if (conn->type == ACL_LINK) 1712744cf19eSJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 171348264f06SJohan Hedberg conn->dst_type, ev->status); 171417d5c04cSJohan Hedberg } 171545bb4bf0SMarcel Holtmann 1716e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 1717e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 171845bb4bf0SMarcel Holtmann 1719769be974SMarcel Holtmann if (ev->status) { 1720a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1721a9de9248SMarcel Holtmann hci_conn_del(conn); 1722c89b6e6bSMarcel Holtmann } else if (ev->link_type != ACL_LINK) 1723c89b6e6bSMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1724a9de9248SMarcel Holtmann 1725a9de9248SMarcel Holtmann unlock: 17261da177e4SLinus Torvalds hci_dev_unlock(hdev); 1727a9de9248SMarcel Holtmann 1728a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 17291da177e4SLinus Torvalds } 17301da177e4SLinus Torvalds 17311da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 17321da177e4SLinus Torvalds { 1733a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 17341da177e4SLinus Torvalds int mask = hdev->link_mode; 17351da177e4SLinus Torvalds 1736a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s type 0x%x", hdev->name, 17371da177e4SLinus Torvalds batostr(&ev->bdaddr), ev->link_type); 17381da177e4SLinus Torvalds 17391da177e4SLinus Torvalds mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); 17401da177e4SLinus Torvalds 1741138d22efSSzymon Janc if ((mask & HCI_LM_ACCEPT) && 1742138d22efSSzymon Janc !hci_blacklist_lookup(hdev, &ev->bdaddr)) { 17431da177e4SLinus Torvalds /* Connection accepted */ 1744c7bdd502SMarcel Holtmann struct inquiry_entry *ie; 17451da177e4SLinus Torvalds struct hci_conn *conn; 17461da177e4SLinus Torvalds 17471da177e4SLinus Torvalds hci_dev_lock(hdev); 1748b6a0dc82SMarcel Holtmann 1749cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 1750cc11b9c1SAndrei Emeltchenko if (ie) 1751c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 1752c7bdd502SMarcel Holtmann 17531da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 17541da177e4SLinus Torvalds if (!conn) { 1755cc11b9c1SAndrei Emeltchenko conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); 1756cc11b9c1SAndrei Emeltchenko if (!conn) { 1757893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 17581da177e4SLinus Torvalds hci_dev_unlock(hdev); 17591da177e4SLinus Torvalds return; 17601da177e4SLinus Torvalds } 17611da177e4SLinus Torvalds } 1762b6a0dc82SMarcel Holtmann 17631da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 17641da177e4SLinus Torvalds conn->state = BT_CONNECT; 1765b6a0dc82SMarcel Holtmann 17661da177e4SLinus Torvalds hci_dev_unlock(hdev); 17671da177e4SLinus Torvalds 1768b6a0dc82SMarcel Holtmann if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) { 1769b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 1770b6a0dc82SMarcel Holtmann 17711da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 17721da177e4SLinus Torvalds 17731da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 17741da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 17751da177e4SLinus Torvalds else 17761da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 17771da177e4SLinus Torvalds 1778b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, 1779b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1780b6a0dc82SMarcel Holtmann } else { 1781b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 1782b6a0dc82SMarcel Holtmann 1783b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 1784a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1785b6a0dc82SMarcel Holtmann 1786b6a0dc82SMarcel Holtmann cp.tx_bandwidth = cpu_to_le32(0x00001f40); 1787b6a0dc82SMarcel Holtmann cp.rx_bandwidth = cpu_to_le32(0x00001f40); 1788b6a0dc82SMarcel Holtmann cp.max_latency = cpu_to_le16(0xffff); 1789b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 1790b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 1791b6a0dc82SMarcel Holtmann 1792b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 1793b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1794b6a0dc82SMarcel Holtmann } 17951da177e4SLinus Torvalds } else { 17961da177e4SLinus Torvalds /* Connection rejected */ 17971da177e4SLinus Torvalds struct hci_cp_reject_conn_req cp; 17981da177e4SLinus Torvalds 17991da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 18009f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_REJ_BAD_ADDR; 1801a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 18021da177e4SLinus Torvalds } 18031da177e4SLinus Torvalds } 18041da177e4SLinus Torvalds 18051da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 18061da177e4SLinus Torvalds { 1807a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 180804837f64SMarcel Holtmann struct hci_conn *conn; 18091da177e4SLinus Torvalds 18101da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 18111da177e4SLinus Torvalds 18121da177e4SLinus Torvalds hci_dev_lock(hdev); 18131da177e4SLinus Torvalds 181404837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1815f7520543SJohan Hedberg if (!conn) 1816f7520543SJohan Hedberg goto unlock; 1817f7520543SJohan Hedberg 181837d9ef76SJohan Hedberg if (ev->status == 0) 18191da177e4SLinus Torvalds conn->state = BT_CLOSED; 18207d0db0a3SMarcel Holtmann 1821b644ba33SJohan Hedberg if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) && 1822b644ba33SJohan Hedberg (conn->type == ACL_LINK || conn->type == LE_LINK)) { 182337d9ef76SJohan Hedberg if (ev->status != 0) 182437d9ef76SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, ev->status); 182537d9ef76SJohan Hedberg else 1826afc747a6SJohan Hedberg mgmt_device_disconnected(hdev, &conn->dst, conn->type, 182748264f06SJohan Hedberg conn->dst_type); 182837d9ef76SJohan Hedberg } 1829f7520543SJohan Hedberg 183037d9ef76SJohan Hedberg if (ev->status == 0) { 18312950f21aSMarcel Holtmann hci_proto_disconn_cfm(conn, ev->reason); 18321da177e4SLinus Torvalds hci_conn_del(conn); 183337d9ef76SJohan Hedberg } 18341da177e4SLinus Torvalds 1835f7520543SJohan Hedberg unlock: 18361da177e4SLinus Torvalds hci_dev_unlock(hdev); 18371da177e4SLinus Torvalds } 18381da177e4SLinus Torvalds 1839a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1840a9de9248SMarcel Holtmann { 1841a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 1842a9de9248SMarcel Holtmann struct hci_conn *conn; 1843a9de9248SMarcel Holtmann 1844a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1845a9de9248SMarcel Holtmann 1846a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1847a9de9248SMarcel Holtmann 1848a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1849d7556e20SWaldemar Rymarkiewicz if (!conn) 1850d7556e20SWaldemar Rymarkiewicz goto unlock; 1851d7556e20SWaldemar Rymarkiewicz 1852765c2a96SJohan Hedberg if (!ev->status) { 1853aa64a8b5SJohan Hedberg if (!hci_conn_ssp_enabled(conn) && 185451a8efd7SJohan Hedberg test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) { 1855d7556e20SWaldemar Rymarkiewicz BT_INFO("re-auth of legacy device is not possible."); 185619f8def0SWaldemar Rymarkiewicz } else { 1857a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1858765c2a96SJohan Hedberg conn->sec_level = conn->pending_sec_level; 185919f8def0SWaldemar Rymarkiewicz } 18602a611692SJohan Hedberg } else { 1861744cf19eSJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, ev->status); 18622a611692SJohan Hedberg } 1863a9de9248SMarcel Holtmann 186451a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 186551a8efd7SJohan Hedberg clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags); 1866a9de9248SMarcel Holtmann 1867f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1868aa64a8b5SJohan Hedberg if (!ev->status && hci_conn_ssp_enabled(conn)) { 1869f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1870f8558555SMarcel Holtmann cp.handle = ev->handle; 1871f8558555SMarcel Holtmann cp.encrypt = 0x01; 1872d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1873d7556e20SWaldemar Rymarkiewicz &cp); 1874f8558555SMarcel Holtmann } else { 1875f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1876f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1877f8558555SMarcel Holtmann hci_conn_put(conn); 1878f8558555SMarcel Holtmann } 1879052b30b0SMarcel Holtmann } else { 1880a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 1881a9de9248SMarcel Holtmann 1882052b30b0SMarcel Holtmann hci_conn_hold(conn); 1883052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1884052b30b0SMarcel Holtmann hci_conn_put(conn); 1885052b30b0SMarcel Holtmann } 1886052b30b0SMarcel Holtmann 188751a8efd7SJohan Hedberg if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) { 1888a9de9248SMarcel Holtmann if (!ev->status) { 1889a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1890f8558555SMarcel Holtmann cp.handle = ev->handle; 1891f8558555SMarcel Holtmann cp.encrypt = 0x01; 1892d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1893d7556e20SWaldemar Rymarkiewicz &cp); 1894a9de9248SMarcel Holtmann } else { 189551a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 1896a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 1897a9de9248SMarcel Holtmann } 1898a9de9248SMarcel Holtmann } 1899a9de9248SMarcel Holtmann 1900d7556e20SWaldemar Rymarkiewicz unlock: 1901a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1902a9de9248SMarcel Holtmann } 1903a9de9248SMarcel Holtmann 1904a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 1905a9de9248SMarcel Holtmann { 1906127178d2SJohan Hedberg struct hci_ev_remote_name *ev = (void *) skb->data; 1907127178d2SJohan Hedberg struct hci_conn *conn; 1908127178d2SJohan Hedberg 1909a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1910a9de9248SMarcel Holtmann 1911a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 1912127178d2SJohan Hedberg 1913127178d2SJohan Hedberg hci_dev_lock(hdev); 1914127178d2SJohan Hedberg 1915127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 1916b644ba33SJohan Hedberg 1917b644ba33SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 1918b644ba33SJohan Hedberg goto check_auth; 1919b644ba33SJohan Hedberg 1920b644ba33SJohan Hedberg if (ev->status == 0) 1921b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name, 1922b644ba33SJohan Hedberg strnlen(ev->name, HCI_MAX_NAME_LENGTH)); 1923b644ba33SJohan Hedberg else 1924b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0); 1925b644ba33SJohan Hedberg 1926b644ba33SJohan Hedberg check_auth: 192779c6c70cSJohan Hedberg if (!conn) 192879c6c70cSJohan Hedberg goto unlock; 192979c6c70cSJohan Hedberg 193079c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 193179c6c70cSJohan Hedberg goto unlock; 193279c6c70cSJohan Hedberg 193351a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 1934127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1935127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1936127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1937127178d2SJohan Hedberg } 1938127178d2SJohan Hedberg 193979c6c70cSJohan Hedberg unlock: 1940127178d2SJohan Hedberg hci_dev_unlock(hdev); 1941a9de9248SMarcel Holtmann } 1942a9de9248SMarcel Holtmann 1943a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 1944a9de9248SMarcel Holtmann { 1945a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 1946a9de9248SMarcel Holtmann struct hci_conn *conn; 1947a9de9248SMarcel Holtmann 1948a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1949a9de9248SMarcel Holtmann 1950a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1951a9de9248SMarcel Holtmann 1952a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1953a9de9248SMarcel Holtmann if (conn) { 1954a9de9248SMarcel Holtmann if (!ev->status) { 1955ae293196SMarcel Holtmann if (ev->encrypt) { 1956ae293196SMarcel Holtmann /* Encryption implies authentication */ 1957ae293196SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1958a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1959da85e5e5SVinicius Costa Gomes conn->sec_level = conn->pending_sec_level; 1960ae293196SMarcel Holtmann } else 1961a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_ENCRYPT; 1962a9de9248SMarcel Holtmann } 1963a9de9248SMarcel Holtmann 196451a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 1965a9de9248SMarcel Holtmann 1966f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1967f8558555SMarcel Holtmann if (!ev->status) 1968f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1969f8558555SMarcel Holtmann 1970f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1971f8558555SMarcel Holtmann hci_conn_put(conn); 1972f8558555SMarcel Holtmann } else 1973a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 1974a9de9248SMarcel Holtmann } 1975a9de9248SMarcel Holtmann 1976a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1977a9de9248SMarcel Holtmann } 1978a9de9248SMarcel Holtmann 1979a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1980a9de9248SMarcel Holtmann { 1981a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 1982a9de9248SMarcel Holtmann struct hci_conn *conn; 1983a9de9248SMarcel Holtmann 1984a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1985a9de9248SMarcel Holtmann 1986a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1987a9de9248SMarcel Holtmann 1988a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1989a9de9248SMarcel Holtmann if (conn) { 1990a9de9248SMarcel Holtmann if (!ev->status) 1991a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_SECURE; 1992a9de9248SMarcel Holtmann 199351a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 1994a9de9248SMarcel Holtmann 1995a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 1996a9de9248SMarcel Holtmann } 1997a9de9248SMarcel Holtmann 1998a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1999a9de9248SMarcel Holtmann } 2000a9de9248SMarcel Holtmann 2001a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 2002a9de9248SMarcel Holtmann { 2003a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 2004a9de9248SMarcel Holtmann struct hci_conn *conn; 2005a9de9248SMarcel Holtmann 2006a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2007a9de9248SMarcel Holtmann 2008a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2009a9de9248SMarcel Holtmann 2010a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2011ccd556feSJohan Hedberg if (!conn) 2012ccd556feSJohan Hedberg goto unlock; 2013ccd556feSJohan Hedberg 2014769be974SMarcel Holtmann if (!ev->status) 2015a9de9248SMarcel Holtmann memcpy(conn->features, ev->features, 8); 2016a9de9248SMarcel Holtmann 2017ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2018ccd556feSJohan Hedberg goto unlock; 2019ccd556feSJohan Hedberg 2020ccd556feSJohan Hedberg if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { 2021769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 2022769be974SMarcel Holtmann cp.handle = ev->handle; 2023769be974SMarcel Holtmann cp.page = 0x01; 2024ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 2025769be974SMarcel Holtmann sizeof(cp), &cp); 2026392599b9SJohan Hedberg goto unlock; 2027392599b9SJohan Hedberg } 2028392599b9SJohan Hedberg 2029127178d2SJohan Hedberg if (!ev->status) { 2030127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2031127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2032127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2033127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2034127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2035b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 2036b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 2037b644ba33SJohan Hedberg conn->dst_type, NULL, 0, 2038b644ba33SJohan Hedberg conn->dev_class); 2039392599b9SJohan Hedberg 2040127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2041769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2042769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2043769be974SMarcel Holtmann hci_conn_put(conn); 2044769be974SMarcel Holtmann } 2045769be974SMarcel Holtmann 2046ccd556feSJohan Hedberg unlock: 2047a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2048a9de9248SMarcel Holtmann } 2049a9de9248SMarcel Holtmann 2050a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) 2051a9de9248SMarcel Holtmann { 2052a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2053a9de9248SMarcel Holtmann } 2054a9de9248SMarcel Holtmann 2055a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2056a9de9248SMarcel Holtmann { 2057a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2058a9de9248SMarcel Holtmann } 2059a9de9248SMarcel Holtmann 2060a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2061a9de9248SMarcel Holtmann { 2062a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 2063a9de9248SMarcel Holtmann __u16 opcode; 2064a9de9248SMarcel Holtmann 2065a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2066a9de9248SMarcel Holtmann 2067a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2068a9de9248SMarcel Holtmann 2069a9de9248SMarcel Holtmann switch (opcode) { 2070a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 2071a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 2072a9de9248SMarcel Holtmann break; 2073a9de9248SMarcel Holtmann 2074a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 2075a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 2076a9de9248SMarcel Holtmann break; 2077a9de9248SMarcel Holtmann 2078a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 2079a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 2080a9de9248SMarcel Holtmann break; 2081a9de9248SMarcel Holtmann 2082a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 2083a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 2084a9de9248SMarcel Holtmann break; 2085a9de9248SMarcel Holtmann 2086e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 2087e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 2088e4e8e37cSMarcel Holtmann break; 2089e4e8e37cSMarcel Holtmann 2090a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 2091a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 2092a9de9248SMarcel Holtmann break; 2093a9de9248SMarcel Holtmann 2094e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 2095e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 2096e4e8e37cSMarcel Holtmann break; 2097e4e8e37cSMarcel Holtmann 2098e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 2099e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 2100e4e8e37cSMarcel Holtmann break; 2101e4e8e37cSMarcel Holtmann 2102a9de9248SMarcel Holtmann case HCI_OP_RESET: 2103a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 2104a9de9248SMarcel Holtmann break; 2105a9de9248SMarcel Holtmann 2106a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 2107a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 2108a9de9248SMarcel Holtmann break; 2109a9de9248SMarcel Holtmann 2110a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 2111a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 2112a9de9248SMarcel Holtmann break; 2113a9de9248SMarcel Holtmann 2114a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 2115a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 2116a9de9248SMarcel Holtmann break; 2117a9de9248SMarcel Holtmann 2118a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 2119a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 2120a9de9248SMarcel Holtmann break; 2121a9de9248SMarcel Holtmann 2122a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 2123a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 2124a9de9248SMarcel Holtmann break; 2125a9de9248SMarcel Holtmann 2126a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 2127a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 2128a9de9248SMarcel Holtmann break; 2129a9de9248SMarcel Holtmann 2130a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 2131a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 2132a9de9248SMarcel Holtmann break; 2133a9de9248SMarcel Holtmann 2134a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 2135a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 2136a9de9248SMarcel Holtmann break; 2137a9de9248SMarcel Holtmann 2138a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 2139a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 2140a9de9248SMarcel Holtmann break; 2141a9de9248SMarcel Holtmann 2142a9de9248SMarcel Holtmann case HCI_OP_HOST_BUFFER_SIZE: 2143a9de9248SMarcel Holtmann hci_cc_host_buffer_size(hdev, skb); 2144a9de9248SMarcel Holtmann break; 2145a9de9248SMarcel Holtmann 2146333140b5SMarcel Holtmann case HCI_OP_READ_SSP_MODE: 2147333140b5SMarcel Holtmann hci_cc_read_ssp_mode(hdev, skb); 2148333140b5SMarcel Holtmann break; 2149333140b5SMarcel Holtmann 2150333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 2151333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 2152333140b5SMarcel Holtmann break; 2153333140b5SMarcel Holtmann 2154a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 2155a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 2156a9de9248SMarcel Holtmann break; 2157a9de9248SMarcel Holtmann 2158a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 2159a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 2160a9de9248SMarcel Holtmann break; 2161a9de9248SMarcel Holtmann 2162a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 2163a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 2164a9de9248SMarcel Holtmann break; 2165a9de9248SMarcel Holtmann 2166971e3a4bSAndre Guedes case HCI_OP_READ_LOCAL_EXT_FEATURES: 2167971e3a4bSAndre Guedes hci_cc_read_local_ext_features(hdev, skb); 2168971e3a4bSAndre Guedes break; 2169971e3a4bSAndre Guedes 2170a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 2171a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 2172a9de9248SMarcel Holtmann break; 2173a9de9248SMarcel Holtmann 2174a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 2175a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 2176a9de9248SMarcel Holtmann break; 2177a9de9248SMarcel Holtmann 2178350ee4cfSAndrei Emeltchenko case HCI_OP_READ_DATA_BLOCK_SIZE: 2179350ee4cfSAndrei Emeltchenko hci_cc_read_data_block_size(hdev, skb); 2180350ee4cfSAndrei Emeltchenko break; 2181350ee4cfSAndrei Emeltchenko 218223bb5763SJohan Hedberg case HCI_OP_WRITE_CA_TIMEOUT: 218323bb5763SJohan Hedberg hci_cc_write_ca_timeout(hdev, skb); 218423bb5763SJohan Hedberg break; 218523bb5763SJohan Hedberg 21861e89cffbSAndrei Emeltchenko case HCI_OP_READ_FLOW_CONTROL_MODE: 21871e89cffbSAndrei Emeltchenko hci_cc_read_flow_control_mode(hdev, skb); 21881e89cffbSAndrei Emeltchenko break; 21891e89cffbSAndrei Emeltchenko 2190928abaa7SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_INFO: 2191928abaa7SAndrei Emeltchenko hci_cc_read_local_amp_info(hdev, skb); 2192928abaa7SAndrei Emeltchenko break; 2193928abaa7SAndrei Emeltchenko 2194b0916ea0SJohan Hedberg case HCI_OP_DELETE_STORED_LINK_KEY: 2195b0916ea0SJohan Hedberg hci_cc_delete_stored_link_key(hdev, skb); 2196b0916ea0SJohan Hedberg break; 2197b0916ea0SJohan Hedberg 2198d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_MASK: 2199d5859e22SJohan Hedberg hci_cc_set_event_mask(hdev, skb); 2200d5859e22SJohan Hedberg break; 2201d5859e22SJohan Hedberg 2202d5859e22SJohan Hedberg case HCI_OP_WRITE_INQUIRY_MODE: 2203d5859e22SJohan Hedberg hci_cc_write_inquiry_mode(hdev, skb); 2204d5859e22SJohan Hedberg break; 2205d5859e22SJohan Hedberg 2206d5859e22SJohan Hedberg case HCI_OP_READ_INQ_RSP_TX_POWER: 2207d5859e22SJohan Hedberg hci_cc_read_inq_rsp_tx_power(hdev, skb); 2208d5859e22SJohan Hedberg break; 2209d5859e22SJohan Hedberg 2210d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_FLT: 2211d5859e22SJohan Hedberg hci_cc_set_event_flt(hdev, skb); 2212d5859e22SJohan Hedberg break; 2213d5859e22SJohan Hedberg 2214980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_REPLY: 2215980e1a53SJohan Hedberg hci_cc_pin_code_reply(hdev, skb); 2216980e1a53SJohan Hedberg break; 2217980e1a53SJohan Hedberg 2218980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_NEG_REPLY: 2219980e1a53SJohan Hedberg hci_cc_pin_code_neg_reply(hdev, skb); 2220980e1a53SJohan Hedberg break; 2221980e1a53SJohan Hedberg 2222c35938b2SSzymon Janc case HCI_OP_READ_LOCAL_OOB_DATA: 2223c35938b2SSzymon Janc hci_cc_read_local_oob_data_reply(hdev, skb); 2224c35938b2SSzymon Janc break; 2225c35938b2SSzymon Janc 22266ed58ec5SVille Tervo case HCI_OP_LE_READ_BUFFER_SIZE: 22276ed58ec5SVille Tervo hci_cc_le_read_buffer_size(hdev, skb); 22286ed58ec5SVille Tervo break; 22296ed58ec5SVille Tervo 2230a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_REPLY: 2231a5c29683SJohan Hedberg hci_cc_user_confirm_reply(hdev, skb); 2232a5c29683SJohan Hedberg break; 2233a5c29683SJohan Hedberg 2234a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_NEG_REPLY: 2235a5c29683SJohan Hedberg hci_cc_user_confirm_neg_reply(hdev, skb); 2236a5c29683SJohan Hedberg break; 2237a5c29683SJohan Hedberg 22381143d458SBrian Gix case HCI_OP_USER_PASSKEY_REPLY: 22391143d458SBrian Gix hci_cc_user_passkey_reply(hdev, skb); 22401143d458SBrian Gix break; 22411143d458SBrian Gix 22421143d458SBrian Gix case HCI_OP_USER_PASSKEY_NEG_REPLY: 22431143d458SBrian Gix hci_cc_user_passkey_neg_reply(hdev, skb); 224407f7fa5dSAndre Guedes 224507f7fa5dSAndre Guedes case HCI_OP_LE_SET_SCAN_PARAM: 224607f7fa5dSAndre Guedes hci_cc_le_set_scan_param(hdev, skb); 22471143d458SBrian Gix break; 22481143d458SBrian Gix 2249eb9d91f5SAndre Guedes case HCI_OP_LE_SET_SCAN_ENABLE: 2250eb9d91f5SAndre Guedes hci_cc_le_set_scan_enable(hdev, skb); 2251eb9d91f5SAndre Guedes break; 2252eb9d91f5SAndre Guedes 2253a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_REPLY: 2254a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_reply(hdev, skb); 2255a7a595f6SVinicius Costa Gomes break; 2256a7a595f6SVinicius Costa Gomes 2257a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_NEG_REPLY: 2258a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_neg_reply(hdev, skb); 2259a7a595f6SVinicius Costa Gomes break; 2260a7a595f6SVinicius Costa Gomes 2261f9b49306SAndre Guedes case HCI_OP_WRITE_LE_HOST_SUPPORTED: 2262f9b49306SAndre Guedes hci_cc_write_le_host_supported(hdev, skb); 2263f9b49306SAndre Guedes break; 2264f9b49306SAndre Guedes 2265a9de9248SMarcel Holtmann default: 2266a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 2267a9de9248SMarcel Holtmann break; 2268a9de9248SMarcel Holtmann } 2269a9de9248SMarcel Holtmann 22706bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 22716bd32326SVille Tervo del_timer(&hdev->cmd_timer); 22726bd32326SVille Tervo 2273a9de9248SMarcel Holtmann if (ev->ncmd) { 2274a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2275a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2276c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2277a9de9248SMarcel Holtmann } 2278a9de9248SMarcel Holtmann } 2279a9de9248SMarcel Holtmann 2280a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 2281a9de9248SMarcel Holtmann { 2282a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 2283a9de9248SMarcel Holtmann __u16 opcode; 2284a9de9248SMarcel Holtmann 2285a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2286a9de9248SMarcel Holtmann 2287a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2288a9de9248SMarcel Holtmann 2289a9de9248SMarcel Holtmann switch (opcode) { 2290a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 2291a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 2292a9de9248SMarcel Holtmann break; 2293a9de9248SMarcel Holtmann 2294a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 2295a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 2296a9de9248SMarcel Holtmann break; 2297a9de9248SMarcel Holtmann 2298a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 2299a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 2300a9de9248SMarcel Holtmann break; 2301a9de9248SMarcel Holtmann 2302f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 2303f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 2304f8558555SMarcel Holtmann break; 2305f8558555SMarcel Holtmann 2306f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 2307f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 2308f8558555SMarcel Holtmann break; 2309f8558555SMarcel Holtmann 2310a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 2311a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 2312a9de9248SMarcel Holtmann break; 2313a9de9248SMarcel Holtmann 2314769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 2315769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 2316769be974SMarcel Holtmann break; 2317769be974SMarcel Holtmann 2318769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 2319769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 2320769be974SMarcel Holtmann break; 2321769be974SMarcel Holtmann 2322a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 2323a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 2324a9de9248SMarcel Holtmann break; 2325a9de9248SMarcel Holtmann 2326a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 2327a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 2328a9de9248SMarcel Holtmann break; 2329a9de9248SMarcel Holtmann 2330a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 2331a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 2332a9de9248SMarcel Holtmann break; 2333a9de9248SMarcel Holtmann 23348962ee74SJohan Hedberg case HCI_OP_DISCONNECT: 23358962ee74SJohan Hedberg if (ev->status != 0) 233637d9ef76SJohan Hedberg mgmt_disconnect_failed(hdev, NULL, ev->status); 23378962ee74SJohan Hedberg break; 23388962ee74SJohan Hedberg 2339fcd89c09SVille Tervo case HCI_OP_LE_CREATE_CONN: 2340fcd89c09SVille Tervo hci_cs_le_create_conn(hdev, ev->status); 2341fcd89c09SVille Tervo break; 2342fcd89c09SVille Tervo 2343a7a595f6SVinicius Costa Gomes case HCI_OP_LE_START_ENC: 2344a7a595f6SVinicius Costa Gomes hci_cs_le_start_enc(hdev, ev->status); 2345a7a595f6SVinicius Costa Gomes break; 2346a7a595f6SVinicius Costa Gomes 2347a9de9248SMarcel Holtmann default: 2348a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 2349a9de9248SMarcel Holtmann break; 2350a9de9248SMarcel Holtmann } 2351a9de9248SMarcel Holtmann 23526bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 23536bd32326SVille Tervo del_timer(&hdev->cmd_timer); 23546bd32326SVille Tervo 235510572132SGustavo F. Padovan if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2356a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2357a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2358c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2359a9de9248SMarcel Holtmann } 2360a9de9248SMarcel Holtmann } 2361a9de9248SMarcel Holtmann 2362a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2363a9de9248SMarcel Holtmann { 2364a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 2365a9de9248SMarcel Holtmann struct hci_conn *conn; 2366a9de9248SMarcel Holtmann 2367a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2368a9de9248SMarcel Holtmann 2369a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2370a9de9248SMarcel Holtmann 2371a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2372a9de9248SMarcel Holtmann if (conn) { 2373a9de9248SMarcel Holtmann if (!ev->status) { 2374a9de9248SMarcel Holtmann if (ev->role) 2375a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_MASTER; 2376a9de9248SMarcel Holtmann else 2377a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_MASTER; 2378a9de9248SMarcel Holtmann } 2379a9de9248SMarcel Holtmann 238051a8efd7SJohan Hedberg clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); 2381a9de9248SMarcel Holtmann 2382a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 2383a9de9248SMarcel Holtmann } 2384a9de9248SMarcel Holtmann 2385a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2386a9de9248SMarcel Holtmann } 2387a9de9248SMarcel Holtmann 23881da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 23891da177e4SLinus Torvalds { 2390a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 23911da177e4SLinus Torvalds int i; 23921da177e4SLinus Torvalds 239332ac5b9bSAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) { 239432ac5b9bSAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 239532ac5b9bSAndrei Emeltchenko return; 239632ac5b9bSAndrei Emeltchenko } 239732ac5b9bSAndrei Emeltchenko 2398c5993de8SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 2399c5993de8SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_pkts_info)) { 24001da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 24011da177e4SLinus Torvalds return; 24021da177e4SLinus Torvalds } 24031da177e4SLinus Torvalds 2404c5993de8SAndrei Emeltchenko BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 2405c5993de8SAndrei Emeltchenko 2406613a1c0cSAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 2407613a1c0cSAndrei Emeltchenko struct hci_comp_pkts_info *info = &ev->handles[i]; 24081da177e4SLinus Torvalds struct hci_conn *conn; 24091da177e4SLinus Torvalds __u16 handle, count; 24101da177e4SLinus Torvalds 2411613a1c0cSAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 2412613a1c0cSAndrei Emeltchenko count = __le16_to_cpu(info->count); 24131da177e4SLinus Torvalds 24141da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 2415f4280918SAndrei Emeltchenko if (!conn) 2416f4280918SAndrei Emeltchenko continue; 2417f4280918SAndrei Emeltchenko 24181da177e4SLinus Torvalds conn->sent -= count; 24191da177e4SLinus Torvalds 2420f4280918SAndrei Emeltchenko switch (conn->type) { 2421f4280918SAndrei Emeltchenko case ACL_LINK: 242270f23020SAndrei Emeltchenko hdev->acl_cnt += count; 242370f23020SAndrei Emeltchenko if (hdev->acl_cnt > hdev->acl_pkts) 24241da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 2425f4280918SAndrei Emeltchenko break; 2426f4280918SAndrei Emeltchenko 2427f4280918SAndrei Emeltchenko case LE_LINK: 24286ed58ec5SVille Tervo if (hdev->le_pkts) { 24296ed58ec5SVille Tervo hdev->le_cnt += count; 24306ed58ec5SVille Tervo if (hdev->le_cnt > hdev->le_pkts) 24316ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 24326ed58ec5SVille Tervo } else { 24336ed58ec5SVille Tervo hdev->acl_cnt += count; 24346ed58ec5SVille Tervo if (hdev->acl_cnt > hdev->acl_pkts) 24356ed58ec5SVille Tervo hdev->acl_cnt = hdev->acl_pkts; 24366ed58ec5SVille Tervo } 2437f4280918SAndrei Emeltchenko break; 2438f4280918SAndrei Emeltchenko 2439f4280918SAndrei Emeltchenko case SCO_LINK: 244070f23020SAndrei Emeltchenko hdev->sco_cnt += count; 244170f23020SAndrei Emeltchenko if (hdev->sco_cnt > hdev->sco_pkts) 24425b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 2443f4280918SAndrei Emeltchenko break; 2444f4280918SAndrei Emeltchenko 2445f4280918SAndrei Emeltchenko default: 2446f4280918SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 2447f4280918SAndrei Emeltchenko break; 24481da177e4SLinus Torvalds } 24491da177e4SLinus Torvalds } 2450a9de9248SMarcel Holtmann 24513eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 24521da177e4SLinus Torvalds } 24531da177e4SLinus Torvalds 245425e89e99SAndrei Emeltchenko static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev, 245525e89e99SAndrei Emeltchenko struct sk_buff *skb) 245625e89e99SAndrei Emeltchenko { 245725e89e99SAndrei Emeltchenko struct hci_ev_num_comp_blocks *ev = (void *) skb->data; 245825e89e99SAndrei Emeltchenko int i; 245925e89e99SAndrei Emeltchenko 246025e89e99SAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) { 246125e89e99SAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 246225e89e99SAndrei Emeltchenko return; 246325e89e99SAndrei Emeltchenko } 246425e89e99SAndrei Emeltchenko 246525e89e99SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 246625e89e99SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_blocks_info)) { 246725e89e99SAndrei Emeltchenko BT_DBG("%s bad parameters", hdev->name); 246825e89e99SAndrei Emeltchenko return; 246925e89e99SAndrei Emeltchenko } 247025e89e99SAndrei Emeltchenko 247125e89e99SAndrei Emeltchenko BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks, 247225e89e99SAndrei Emeltchenko ev->num_hndl); 247325e89e99SAndrei Emeltchenko 247425e89e99SAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 247525e89e99SAndrei Emeltchenko struct hci_comp_blocks_info *info = &ev->handles[i]; 247625e89e99SAndrei Emeltchenko struct hci_conn *conn; 247725e89e99SAndrei Emeltchenko __u16 handle, block_count; 247825e89e99SAndrei Emeltchenko 247925e89e99SAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 248025e89e99SAndrei Emeltchenko block_count = __le16_to_cpu(info->blocks); 248125e89e99SAndrei Emeltchenko 248225e89e99SAndrei Emeltchenko conn = hci_conn_hash_lookup_handle(hdev, handle); 248325e89e99SAndrei Emeltchenko if (!conn) 248425e89e99SAndrei Emeltchenko continue; 248525e89e99SAndrei Emeltchenko 248625e89e99SAndrei Emeltchenko conn->sent -= block_count; 248725e89e99SAndrei Emeltchenko 248825e89e99SAndrei Emeltchenko switch (conn->type) { 248925e89e99SAndrei Emeltchenko case ACL_LINK: 249025e89e99SAndrei Emeltchenko hdev->block_cnt += block_count; 249125e89e99SAndrei Emeltchenko if (hdev->block_cnt > hdev->num_blocks) 249225e89e99SAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 249325e89e99SAndrei Emeltchenko break; 249425e89e99SAndrei Emeltchenko 249525e89e99SAndrei Emeltchenko default: 249625e89e99SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 249725e89e99SAndrei Emeltchenko break; 249825e89e99SAndrei Emeltchenko } 249925e89e99SAndrei Emeltchenko } 250025e89e99SAndrei Emeltchenko 250125e89e99SAndrei Emeltchenko queue_work(hdev->workqueue, &hdev->tx_work); 250225e89e99SAndrei Emeltchenko } 250325e89e99SAndrei Emeltchenko 250404837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 25051da177e4SLinus Torvalds { 2506a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 250704837f64SMarcel Holtmann struct hci_conn *conn; 25081da177e4SLinus Torvalds 25091da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 25101da177e4SLinus Torvalds 25111da177e4SLinus Torvalds hci_dev_lock(hdev); 25121da177e4SLinus Torvalds 251304837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 251404837f64SMarcel Holtmann if (conn) { 251504837f64SMarcel Holtmann conn->mode = ev->mode; 251604837f64SMarcel Holtmann conn->interval = __le16_to_cpu(ev->interval); 251704837f64SMarcel Holtmann 251851a8efd7SJohan Hedberg if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) { 251904837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 252058a681efSJohan Hedberg set_bit(HCI_CONN_POWER_SAVE, &conn->flags); 252104837f64SMarcel Holtmann else 252258a681efSJohan Hedberg clear_bit(HCI_CONN_POWER_SAVE, &conn->flags); 252304837f64SMarcel Holtmann } 2524e73439d8SMarcel Holtmann 252551a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 2526e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 252704837f64SMarcel Holtmann } 252804837f64SMarcel Holtmann 252904837f64SMarcel Holtmann hci_dev_unlock(hdev); 253004837f64SMarcel Holtmann } 253104837f64SMarcel Holtmann 25321da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 25331da177e4SLinus Torvalds { 2534052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 2535052b30b0SMarcel Holtmann struct hci_conn *conn; 2536052b30b0SMarcel Holtmann 2537a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2538052b30b0SMarcel Holtmann 2539052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2540052b30b0SMarcel Holtmann 2541052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2542b6f98044SWaldemar Rymarkiewicz if (!conn) 2543b6f98044SWaldemar Rymarkiewicz goto unlock; 2544b6f98044SWaldemar Rymarkiewicz 2545b6f98044SWaldemar Rymarkiewicz if (conn->state == BT_CONNECTED) { 2546052b30b0SMarcel Holtmann hci_conn_hold(conn); 2547052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 2548052b30b0SMarcel Holtmann hci_conn_put(conn); 2549052b30b0SMarcel Holtmann } 2550052b30b0SMarcel Holtmann 2551a8b2d5c2SJohan Hedberg if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags)) 255203b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 255303b555e1SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 2554a8b2d5c2SJohan Hedberg else if (test_bit(HCI_MGMT, &hdev->dev_flags)) { 2555a770bb5aSWaldemar Rymarkiewicz u8 secure; 2556a770bb5aSWaldemar Rymarkiewicz 2557a770bb5aSWaldemar Rymarkiewicz if (conn->pending_sec_level == BT_SECURITY_HIGH) 2558a770bb5aSWaldemar Rymarkiewicz secure = 1; 2559a770bb5aSWaldemar Rymarkiewicz else 2560a770bb5aSWaldemar Rymarkiewicz secure = 0; 2561a770bb5aSWaldemar Rymarkiewicz 2562744cf19eSJohan Hedberg mgmt_pin_code_request(hdev, &ev->bdaddr, secure); 2563a770bb5aSWaldemar Rymarkiewicz } 2564980e1a53SJohan Hedberg 2565b6f98044SWaldemar Rymarkiewicz unlock: 2566052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 25671da177e4SLinus Torvalds } 25681da177e4SLinus Torvalds 25691da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 25701da177e4SLinus Torvalds { 257155ed8ca1SJohan Hedberg struct hci_ev_link_key_req *ev = (void *) skb->data; 257255ed8ca1SJohan Hedberg struct hci_cp_link_key_reply cp; 257355ed8ca1SJohan Hedberg struct hci_conn *conn; 257455ed8ca1SJohan Hedberg struct link_key *key; 257555ed8ca1SJohan Hedberg 2576a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 257755ed8ca1SJohan Hedberg 2578a8b2d5c2SJohan Hedberg if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) 257955ed8ca1SJohan Hedberg return; 258055ed8ca1SJohan Hedberg 258155ed8ca1SJohan Hedberg hci_dev_lock(hdev); 258255ed8ca1SJohan Hedberg 258355ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, &ev->bdaddr); 258455ed8ca1SJohan Hedberg if (!key) { 258555ed8ca1SJohan Hedberg BT_DBG("%s link key not found for %s", hdev->name, 258655ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 258755ed8ca1SJohan Hedberg goto not_found; 258855ed8ca1SJohan Hedberg } 258955ed8ca1SJohan Hedberg 259055ed8ca1SJohan Hedberg BT_DBG("%s found key type %u for %s", hdev->name, key->type, 259155ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 259255ed8ca1SJohan Hedberg 2593a8b2d5c2SJohan Hedberg if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) && 2594b6020ba0SWaldemar Rymarkiewicz key->type == HCI_LK_DEBUG_COMBINATION) { 259555ed8ca1SJohan Hedberg BT_DBG("%s ignoring debug key", hdev->name); 259655ed8ca1SJohan Hedberg goto not_found; 259755ed8ca1SJohan Hedberg } 259855ed8ca1SJohan Hedberg 259955ed8ca1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 260060b83f57SWaldemar Rymarkiewicz if (conn) { 260160b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_UNAUTH_COMBINATION && 260260b83f57SWaldemar Rymarkiewicz conn->auth_type != 0xff && 260360b83f57SWaldemar Rymarkiewicz (conn->auth_type & 0x01)) { 260455ed8ca1SJohan Hedberg BT_DBG("%s ignoring unauthenticated key", hdev->name); 260555ed8ca1SJohan Hedberg goto not_found; 260655ed8ca1SJohan Hedberg } 260755ed8ca1SJohan Hedberg 260860b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && 260960b83f57SWaldemar Rymarkiewicz conn->pending_sec_level == BT_SECURITY_HIGH) { 261060b83f57SWaldemar Rymarkiewicz BT_DBG("%s ignoring key unauthenticated for high \ 261160b83f57SWaldemar Rymarkiewicz security", hdev->name); 261260b83f57SWaldemar Rymarkiewicz goto not_found; 261360b83f57SWaldemar Rymarkiewicz } 261460b83f57SWaldemar Rymarkiewicz 261560b83f57SWaldemar Rymarkiewicz conn->key_type = key->type; 261660b83f57SWaldemar Rymarkiewicz conn->pin_length = key->pin_len; 261760b83f57SWaldemar Rymarkiewicz } 261860b83f57SWaldemar Rymarkiewicz 261955ed8ca1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 262055ed8ca1SJohan Hedberg memcpy(cp.link_key, key->val, 16); 262155ed8ca1SJohan Hedberg 262255ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 262355ed8ca1SJohan Hedberg 262455ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 262555ed8ca1SJohan Hedberg 262655ed8ca1SJohan Hedberg return; 262755ed8ca1SJohan Hedberg 262855ed8ca1SJohan Hedberg not_found: 262955ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 263055ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 26311da177e4SLinus Torvalds } 26321da177e4SLinus Torvalds 26331da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 26341da177e4SLinus Torvalds { 2635052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 2636052b30b0SMarcel Holtmann struct hci_conn *conn; 263755ed8ca1SJohan Hedberg u8 pin_len = 0; 2638052b30b0SMarcel Holtmann 2639a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2640052b30b0SMarcel Holtmann 2641052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2642052b30b0SMarcel Holtmann 2643052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2644052b30b0SMarcel Holtmann if (conn) { 2645052b30b0SMarcel Holtmann hci_conn_hold(conn); 2646052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2647980e1a53SJohan Hedberg pin_len = conn->pin_length; 264813d39315SWaldemar Rymarkiewicz 264913d39315SWaldemar Rymarkiewicz if (ev->key_type != HCI_LK_CHANGED_COMBINATION) 265013d39315SWaldemar Rymarkiewicz conn->key_type = ev->key_type; 265113d39315SWaldemar Rymarkiewicz 2652052b30b0SMarcel Holtmann hci_conn_put(conn); 2653052b30b0SMarcel Holtmann } 2654052b30b0SMarcel Holtmann 2655a8b2d5c2SJohan Hedberg if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) 2656d25e28abSJohan Hedberg hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, 265755ed8ca1SJohan Hedberg ev->key_type, pin_len); 265855ed8ca1SJohan Hedberg 2659052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 26601da177e4SLinus Torvalds } 26611da177e4SLinus Torvalds 266204837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 266304837f64SMarcel Holtmann { 2664a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 266504837f64SMarcel Holtmann struct hci_conn *conn; 266604837f64SMarcel Holtmann 266704837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 266804837f64SMarcel Holtmann 266904837f64SMarcel Holtmann hci_dev_lock(hdev); 267004837f64SMarcel Holtmann 267104837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 26721da177e4SLinus Torvalds if (conn && !ev->status) { 26731da177e4SLinus Torvalds struct inquiry_entry *ie; 26741da177e4SLinus Torvalds 2675cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2676cc11b9c1SAndrei Emeltchenko if (ie) { 26771da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 26781da177e4SLinus Torvalds ie->timestamp = jiffies; 26791da177e4SLinus Torvalds } 26801da177e4SLinus Torvalds } 26811da177e4SLinus Torvalds 26821da177e4SLinus Torvalds hci_dev_unlock(hdev); 26831da177e4SLinus Torvalds } 26841da177e4SLinus Torvalds 2685a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2686a8746417SMarcel Holtmann { 2687a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 2688a8746417SMarcel Holtmann struct hci_conn *conn; 2689a8746417SMarcel Holtmann 2690a8746417SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2691a8746417SMarcel Holtmann 2692a8746417SMarcel Holtmann hci_dev_lock(hdev); 2693a8746417SMarcel Holtmann 2694a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2695a8746417SMarcel Holtmann if (conn && !ev->status) 2696a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 2697a8746417SMarcel Holtmann 2698a8746417SMarcel Holtmann hci_dev_unlock(hdev); 2699a8746417SMarcel Holtmann } 2700a8746417SMarcel Holtmann 270185a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 270285a1e930SMarcel Holtmann { 2703a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 270485a1e930SMarcel Holtmann struct inquiry_entry *ie; 270585a1e930SMarcel Holtmann 270685a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 270785a1e930SMarcel Holtmann 270885a1e930SMarcel Holtmann hci_dev_lock(hdev); 270985a1e930SMarcel Holtmann 2710cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2711cc11b9c1SAndrei Emeltchenko if (ie) { 271285a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 271385a1e930SMarcel Holtmann ie->timestamp = jiffies; 271485a1e930SMarcel Holtmann } 271585a1e930SMarcel Holtmann 271685a1e930SMarcel Holtmann hci_dev_unlock(hdev); 271785a1e930SMarcel Holtmann } 271885a1e930SMarcel Holtmann 2719a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb) 2720a9de9248SMarcel Holtmann { 2721a9de9248SMarcel Holtmann struct inquiry_data data; 2722a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 27233175405bSJohan Hedberg bool name_known; 2724a9de9248SMarcel Holtmann 2725a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2726a9de9248SMarcel Holtmann 2727a9de9248SMarcel Holtmann if (!num_rsp) 2728a9de9248SMarcel Holtmann return; 2729a9de9248SMarcel Holtmann 2730a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2731a9de9248SMarcel Holtmann 2732a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 2733138d22efSSzymon Janc struct inquiry_info_with_rssi_and_pscan_mode *info; 2734138d22efSSzymon Janc info = (void *) (skb->data + 1); 2735a9de9248SMarcel Holtmann 2736e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2737a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2738a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2739a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2740a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 2741a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2742a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2743a9de9248SMarcel Holtmann data.rssi = info->rssi; 274441a96212SMarcel Holtmann data.ssp_mode = 0x00; 27453175405bSJohan Hedberg 27463175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 27473175405bSJohan Hedberg false); 274848264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2749e17acd40SJohan Hedberg info->dev_class, info->rssi, 27507d262f86SAndre Guedes !name_known, NULL, 0); 2751a9de9248SMarcel Holtmann } 2752a9de9248SMarcel Holtmann } else { 2753a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 2754a9de9248SMarcel Holtmann 2755e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2756a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2757a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2758a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2759a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2760a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2761a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2762a9de9248SMarcel Holtmann data.rssi = info->rssi; 276341a96212SMarcel Holtmann data.ssp_mode = 0x00; 27643175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 27653175405bSJohan Hedberg false); 276648264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2767e17acd40SJohan Hedberg info->dev_class, info->rssi, 27687d262f86SAndre Guedes !name_known, NULL, 0); 2769a9de9248SMarcel Holtmann } 2770a9de9248SMarcel Holtmann } 2771a9de9248SMarcel Holtmann 2772a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2773a9de9248SMarcel Holtmann } 2774a9de9248SMarcel Holtmann 2775a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 2776a9de9248SMarcel Holtmann { 277741a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 277841a96212SMarcel Holtmann struct hci_conn *conn; 277941a96212SMarcel Holtmann 2780a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 278141a96212SMarcel Holtmann 278241a96212SMarcel Holtmann hci_dev_lock(hdev); 278341a96212SMarcel Holtmann 278441a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2785ccd556feSJohan Hedberg if (!conn) 2786ccd556feSJohan Hedberg goto unlock; 2787ccd556feSJohan Hedberg 2788769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 278941a96212SMarcel Holtmann struct inquiry_entry *ie; 279041a96212SMarcel Holtmann 2791cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2792cc11b9c1SAndrei Emeltchenko if (ie) 279341a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 279441a96212SMarcel Holtmann 279558a681efSJohan Hedberg if (ev->features[0] & 0x01) 279658a681efSJohan Hedberg set_bit(HCI_CONN_SSP_ENABLED, &conn->flags); 279741a96212SMarcel Holtmann } 279841a96212SMarcel Holtmann 2799ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2800ccd556feSJohan Hedberg goto unlock; 2801ccd556feSJohan Hedberg 2802127178d2SJohan Hedberg if (!ev->status) { 2803127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2804127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2805127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2806127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2807127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2808b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 2809b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 2810b644ba33SJohan Hedberg conn->dst_type, NULL, 0, 2811b644ba33SJohan Hedberg conn->dev_class); 2812392599b9SJohan Hedberg 2813127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2814769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2815769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2816769be974SMarcel Holtmann hci_conn_put(conn); 2817769be974SMarcel Holtmann } 2818769be974SMarcel Holtmann 2819ccd556feSJohan Hedberg unlock: 282041a96212SMarcel Holtmann hci_dev_unlock(hdev); 2821a9de9248SMarcel Holtmann } 2822a9de9248SMarcel Holtmann 2823a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2824a9de9248SMarcel Holtmann { 2825b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 2826b6a0dc82SMarcel Holtmann struct hci_conn *conn; 2827b6a0dc82SMarcel Holtmann 2828b6a0dc82SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2829b6a0dc82SMarcel Holtmann 2830b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 2831b6a0dc82SMarcel Holtmann 2832b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 28339dc0a3afSMarcel Holtmann if (!conn) { 28349dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 28359dc0a3afSMarcel Holtmann goto unlock; 28369dc0a3afSMarcel Holtmann 28379dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 2838b6a0dc82SMarcel Holtmann if (!conn) 2839b6a0dc82SMarcel Holtmann goto unlock; 2840b6a0dc82SMarcel Holtmann 28419dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 28429dc0a3afSMarcel Holtmann } 28439dc0a3afSMarcel Holtmann 2844732547f9SMarcel Holtmann switch (ev->status) { 2845732547f9SMarcel Holtmann case 0x00: 2846732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 2847732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 2848732547f9SMarcel Holtmann 28499eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 2850732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 2851732547f9SMarcel Holtmann break; 2852732547f9SMarcel Holtmann 2853705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 2854732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 28551038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 2856732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 2857732547f9SMarcel Holtmann if (conn->out && conn->attempt < 2) { 2858efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 2859efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 2860efc7688bSMarcel Holtmann hci_setup_sync(conn, conn->link->handle); 2861efc7688bSMarcel Holtmann goto unlock; 2862efc7688bSMarcel Holtmann } 2863732547f9SMarcel Holtmann /* fall through */ 2864efc7688bSMarcel Holtmann 2865732547f9SMarcel Holtmann default: 2866b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 2867732547f9SMarcel Holtmann break; 2868732547f9SMarcel Holtmann } 2869b6a0dc82SMarcel Holtmann 2870b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2871b6a0dc82SMarcel Holtmann if (ev->status) 2872b6a0dc82SMarcel Holtmann hci_conn_del(conn); 2873b6a0dc82SMarcel Holtmann 2874b6a0dc82SMarcel Holtmann unlock: 2875b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 2876a9de9248SMarcel Holtmann } 2877a9de9248SMarcel Holtmann 2878a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) 2879a9de9248SMarcel Holtmann { 2880a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2881a9de9248SMarcel Holtmann } 2882a9de9248SMarcel Holtmann 288304837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) 288404837f64SMarcel Holtmann { 2885a9de9248SMarcel Holtmann struct hci_ev_sniff_subrate *ev = (void *) skb->data; 288604837f64SMarcel Holtmann 288704837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 288804837f64SMarcel Holtmann } 288904837f64SMarcel Holtmann 2890a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 2891a9de9248SMarcel Holtmann { 2892a9de9248SMarcel Holtmann struct inquiry_data data; 2893a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 2894a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2895a9de9248SMarcel Holtmann 2896a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2897a9de9248SMarcel Holtmann 2898a9de9248SMarcel Holtmann if (!num_rsp) 2899a9de9248SMarcel Holtmann return; 2900a9de9248SMarcel Holtmann 2901a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2902a9de9248SMarcel Holtmann 2903e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2904561aafbcSJohan Hedberg bool name_known; 2905561aafbcSJohan Hedberg 2906a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2907a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2908a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2909a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2910a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2911a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2912a9de9248SMarcel Holtmann data.rssi = info->rssi; 291341a96212SMarcel Holtmann data.ssp_mode = 0x01; 2914561aafbcSJohan Hedberg 2915a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 29164ddb1930SJohan Hedberg name_known = eir_has_data_type(info->data, 29174ddb1930SJohan Hedberg sizeof(info->data), 29184ddb1930SJohan Hedberg EIR_NAME_COMPLETE); 2919561aafbcSJohan Hedberg else 2920561aafbcSJohan Hedberg name_known = true; 2921561aafbcSJohan Hedberg 29223175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, name_known); 292348264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2924561aafbcSJohan Hedberg info->dev_class, info->rssi, 29257d262f86SAndre Guedes !name_known, info->data, 29267d262f86SAndre Guedes sizeof(info->data)); 2927a9de9248SMarcel Holtmann } 2928a9de9248SMarcel Holtmann 2929a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2930a9de9248SMarcel Holtmann } 2931a9de9248SMarcel Holtmann 293217fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn) 293317fa4b9dSJohan Hedberg { 293417fa4b9dSJohan Hedberg /* If remote requests dedicated bonding follow that lead */ 293517fa4b9dSJohan Hedberg if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) { 293617fa4b9dSJohan Hedberg /* If both remote and local IO capabilities allow MITM 293717fa4b9dSJohan Hedberg * protection then require it, otherwise don't */ 293817fa4b9dSJohan Hedberg if (conn->remote_cap == 0x03 || conn->io_capability == 0x03) 293917fa4b9dSJohan Hedberg return 0x02; 294017fa4b9dSJohan Hedberg else 294117fa4b9dSJohan Hedberg return 0x03; 294217fa4b9dSJohan Hedberg } 294317fa4b9dSJohan Hedberg 294417fa4b9dSJohan Hedberg /* If remote requests no-bonding follow that lead */ 294517fa4b9dSJohan Hedberg if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01) 294658797bf7SWaldemar Rymarkiewicz return conn->remote_auth | (conn->auth_type & 0x01); 294717fa4b9dSJohan Hedberg 294817fa4b9dSJohan Hedberg return conn->auth_type; 294917fa4b9dSJohan Hedberg } 295017fa4b9dSJohan Hedberg 29510493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 29520493684eSMarcel Holtmann { 29530493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 29540493684eSMarcel Holtmann struct hci_conn *conn; 29550493684eSMarcel Holtmann 29560493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 29570493684eSMarcel Holtmann 29580493684eSMarcel Holtmann hci_dev_lock(hdev); 29590493684eSMarcel Holtmann 29600493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 296103b555e1SJohan Hedberg if (!conn) 296203b555e1SJohan Hedberg goto unlock; 296303b555e1SJohan Hedberg 29640493684eSMarcel Holtmann hci_conn_hold(conn); 29650493684eSMarcel Holtmann 2966a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 296703b555e1SJohan Hedberg goto unlock; 296803b555e1SJohan Hedberg 2969a8b2d5c2SJohan Hedberg if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) || 297003b555e1SJohan Hedberg (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 297117fa4b9dSJohan Hedberg struct hci_cp_io_capability_reply cp; 297217fa4b9dSJohan Hedberg 297317fa4b9dSJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 29747a7f1e7cSHemant Gupta /* Change the IO capability from KeyboardDisplay 29757a7f1e7cSHemant Gupta * to DisplayYesNo as it is not supported by BT spec. */ 29767a7f1e7cSHemant Gupta cp.capability = (conn->io_capability == 0x04) ? 29777a7f1e7cSHemant Gupta 0x01 : conn->io_capability; 29787cbc9bd9SJohan Hedberg conn->auth_type = hci_get_auth_req(conn); 29797cbc9bd9SJohan Hedberg cp.authentication = conn->auth_type; 298017fa4b9dSJohan Hedberg 298158a681efSJohan Hedberg if ((conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)) && 2982ce85ee13SSzymon Janc hci_find_remote_oob_data(hdev, &conn->dst)) 2983ce85ee13SSzymon Janc cp.oob_data = 0x01; 2984ce85ee13SSzymon Janc else 2985ce85ee13SSzymon Janc cp.oob_data = 0x00; 2986ce85ee13SSzymon Janc 298717fa4b9dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, 298817fa4b9dSJohan Hedberg sizeof(cp), &cp); 298903b555e1SJohan Hedberg } else { 299003b555e1SJohan Hedberg struct hci_cp_io_capability_neg_reply cp; 299103b555e1SJohan Hedberg 299203b555e1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 29939f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED; 299403b555e1SJohan Hedberg 299503b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 299603b555e1SJohan Hedberg sizeof(cp), &cp); 299703b555e1SJohan Hedberg } 299803b555e1SJohan Hedberg 299903b555e1SJohan Hedberg unlock: 300003b555e1SJohan Hedberg hci_dev_unlock(hdev); 300103b555e1SJohan Hedberg } 300203b555e1SJohan Hedberg 300303b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 300403b555e1SJohan Hedberg { 300503b555e1SJohan Hedberg struct hci_ev_io_capa_reply *ev = (void *) skb->data; 300603b555e1SJohan Hedberg struct hci_conn *conn; 300703b555e1SJohan Hedberg 300803b555e1SJohan Hedberg BT_DBG("%s", hdev->name); 300903b555e1SJohan Hedberg 301003b555e1SJohan Hedberg hci_dev_lock(hdev); 301103b555e1SJohan Hedberg 301203b555e1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 301303b555e1SJohan Hedberg if (!conn) 301403b555e1SJohan Hedberg goto unlock; 301503b555e1SJohan Hedberg 301603b555e1SJohan Hedberg conn->remote_cap = ev->capability; 301703b555e1SJohan Hedberg conn->remote_auth = ev->authentication; 301858a681efSJohan Hedberg if (ev->oob_data) 301958a681efSJohan Hedberg set_bit(HCI_CONN_REMOTE_OOB, &conn->flags); 302003b555e1SJohan Hedberg 302103b555e1SJohan Hedberg unlock: 30220493684eSMarcel Holtmann hci_dev_unlock(hdev); 30230493684eSMarcel Holtmann } 30240493684eSMarcel Holtmann 3025a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev, 3026a5c29683SJohan Hedberg struct sk_buff *skb) 3027a5c29683SJohan Hedberg { 3028a5c29683SJohan Hedberg struct hci_ev_user_confirm_req *ev = (void *) skb->data; 302955bc1a37SJohan Hedberg int loc_mitm, rem_mitm, confirm_hint = 0; 30307a828908SJohan Hedberg struct hci_conn *conn; 3031a5c29683SJohan Hedberg 3032a5c29683SJohan Hedberg BT_DBG("%s", hdev->name); 3033a5c29683SJohan Hedberg 3034a5c29683SJohan Hedberg hci_dev_lock(hdev); 3035a5c29683SJohan Hedberg 3036a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 30377a828908SJohan Hedberg goto unlock; 30387a828908SJohan Hedberg 30397a828908SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 30407a828908SJohan Hedberg if (!conn) 30417a828908SJohan Hedberg goto unlock; 30427a828908SJohan Hedberg 30437a828908SJohan Hedberg loc_mitm = (conn->auth_type & 0x01); 30447a828908SJohan Hedberg rem_mitm = (conn->remote_auth & 0x01); 30457a828908SJohan Hedberg 30467a828908SJohan Hedberg /* If we require MITM but the remote device can't provide that 30477a828908SJohan Hedberg * (it has NoInputNoOutput) then reject the confirmation 30487a828908SJohan Hedberg * request. The only exception is when we're dedicated bonding 30497a828908SJohan Hedberg * initiators (connect_cfm_cb set) since then we always have the MITM 30507a828908SJohan Hedberg * bit set. */ 30517a828908SJohan Hedberg if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) { 30527a828908SJohan Hedberg BT_DBG("Rejecting request: remote device can't provide MITM"); 30537a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, 30547a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 30557a828908SJohan Hedberg goto unlock; 30567a828908SJohan Hedberg } 30577a828908SJohan Hedberg 30587a828908SJohan Hedberg /* If no side requires MITM protection; auto-accept */ 30597a828908SJohan Hedberg if ((!loc_mitm || conn->remote_cap == 0x03) && 30607a828908SJohan Hedberg (!rem_mitm || conn->io_capability == 0x03)) { 306155bc1a37SJohan Hedberg 306255bc1a37SJohan Hedberg /* If we're not the initiators request authorization to 306355bc1a37SJohan Hedberg * proceed from user space (mgmt_user_confirm with 306455bc1a37SJohan Hedberg * confirm_hint set to 1). */ 306551a8efd7SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 306655bc1a37SJohan Hedberg BT_DBG("Confirming auto-accept as acceptor"); 306755bc1a37SJohan Hedberg confirm_hint = 1; 306855bc1a37SJohan Hedberg goto confirm; 306955bc1a37SJohan Hedberg } 307055bc1a37SJohan Hedberg 30719f61656aSJohan Hedberg BT_DBG("Auto-accept of user confirmation with %ums delay", 30729f61656aSJohan Hedberg hdev->auto_accept_delay); 30739f61656aSJohan Hedberg 30749f61656aSJohan Hedberg if (hdev->auto_accept_delay > 0) { 30759f61656aSJohan Hedberg int delay = msecs_to_jiffies(hdev->auto_accept_delay); 30769f61656aSJohan Hedberg mod_timer(&conn->auto_accept_timer, jiffies + delay); 30779f61656aSJohan Hedberg goto unlock; 30789f61656aSJohan Hedberg } 30799f61656aSJohan Hedberg 30807a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, 30817a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 30827a828908SJohan Hedberg goto unlock; 30837a828908SJohan Hedberg } 30847a828908SJohan Hedberg 308555bc1a37SJohan Hedberg confirm: 3086744cf19eSJohan Hedberg mgmt_user_confirm_request(hdev, &ev->bdaddr, ev->passkey, 308755bc1a37SJohan Hedberg confirm_hint); 3088a5c29683SJohan Hedberg 30897a828908SJohan Hedberg unlock: 3090a5c29683SJohan Hedberg hci_dev_unlock(hdev); 3091a5c29683SJohan Hedberg } 3092a5c29683SJohan Hedberg 30931143d458SBrian Gix static inline void hci_user_passkey_request_evt(struct hci_dev *hdev, 30941143d458SBrian Gix struct sk_buff *skb) 30951143d458SBrian Gix { 30961143d458SBrian Gix struct hci_ev_user_passkey_req *ev = (void *) skb->data; 30971143d458SBrian Gix 30981143d458SBrian Gix BT_DBG("%s", hdev->name); 30991143d458SBrian Gix 31001143d458SBrian Gix hci_dev_lock(hdev); 31011143d458SBrian Gix 3102a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 31031143d458SBrian Gix mgmt_user_passkey_request(hdev, &ev->bdaddr); 31041143d458SBrian Gix 31051143d458SBrian Gix hci_dev_unlock(hdev); 31061143d458SBrian Gix } 31071143d458SBrian Gix 31080493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 31090493684eSMarcel Holtmann { 31100493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 31110493684eSMarcel Holtmann struct hci_conn *conn; 31120493684eSMarcel Holtmann 31130493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 31140493684eSMarcel Holtmann 31150493684eSMarcel Holtmann hci_dev_lock(hdev); 31160493684eSMarcel Holtmann 31170493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 31182a611692SJohan Hedberg if (!conn) 31192a611692SJohan Hedberg goto unlock; 31202a611692SJohan Hedberg 31212a611692SJohan Hedberg /* To avoid duplicate auth_failed events to user space we check 31222a611692SJohan Hedberg * the HCI_CONN_AUTH_PEND flag which will be set if we 31232a611692SJohan Hedberg * initiated the authentication. A traditional auth_complete 31242a611692SJohan Hedberg * event gets always produced as initiator and is also mapped to 31252a611692SJohan Hedberg * the mgmt_auth_failed event */ 312651a8efd7SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status != 0) 3127744cf19eSJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, ev->status); 31282a611692SJohan Hedberg 31290493684eSMarcel Holtmann hci_conn_put(conn); 31300493684eSMarcel Holtmann 31312a611692SJohan Hedberg unlock: 31320493684eSMarcel Holtmann hci_dev_unlock(hdev); 31330493684eSMarcel Holtmann } 31340493684eSMarcel Holtmann 313541a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 313641a96212SMarcel Holtmann { 313741a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 313841a96212SMarcel Holtmann struct inquiry_entry *ie; 313941a96212SMarcel Holtmann 314041a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 314141a96212SMarcel Holtmann 314241a96212SMarcel Holtmann hci_dev_lock(hdev); 314341a96212SMarcel Holtmann 3144cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 3145cc11b9c1SAndrei Emeltchenko if (ie) 314641a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 314741a96212SMarcel Holtmann 314841a96212SMarcel Holtmann hci_dev_unlock(hdev); 314941a96212SMarcel Holtmann } 315041a96212SMarcel Holtmann 31512763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev, 31522763eda6SSzymon Janc struct sk_buff *skb) 31532763eda6SSzymon Janc { 31542763eda6SSzymon Janc struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; 31552763eda6SSzymon Janc struct oob_data *data; 31562763eda6SSzymon Janc 31572763eda6SSzymon Janc BT_DBG("%s", hdev->name); 31582763eda6SSzymon Janc 31592763eda6SSzymon Janc hci_dev_lock(hdev); 31602763eda6SSzymon Janc 3161a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 3162e1ba1f15SSzymon Janc goto unlock; 3163e1ba1f15SSzymon Janc 31642763eda6SSzymon Janc data = hci_find_remote_oob_data(hdev, &ev->bdaddr); 31652763eda6SSzymon Janc if (data) { 31662763eda6SSzymon Janc struct hci_cp_remote_oob_data_reply cp; 31672763eda6SSzymon Janc 31682763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 31692763eda6SSzymon Janc memcpy(cp.hash, data->hash, sizeof(cp.hash)); 31702763eda6SSzymon Janc memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); 31712763eda6SSzymon Janc 31722763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), 31732763eda6SSzymon Janc &cp); 31742763eda6SSzymon Janc } else { 31752763eda6SSzymon Janc struct hci_cp_remote_oob_data_neg_reply cp; 31762763eda6SSzymon Janc 31772763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 31782763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), 31792763eda6SSzymon Janc &cp); 31802763eda6SSzymon Janc } 31812763eda6SSzymon Janc 3182e1ba1f15SSzymon Janc unlock: 31832763eda6SSzymon Janc hci_dev_unlock(hdev); 31842763eda6SSzymon Janc } 31852763eda6SSzymon Janc 3186fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 3187fcd89c09SVille Tervo { 3188fcd89c09SVille Tervo struct hci_ev_le_conn_complete *ev = (void *) skb->data; 3189fcd89c09SVille Tervo struct hci_conn *conn; 3190fcd89c09SVille Tervo 3191fcd89c09SVille Tervo BT_DBG("%s status %d", hdev->name, ev->status); 3192fcd89c09SVille Tervo 3193fcd89c09SVille Tervo hci_dev_lock(hdev); 3194fcd89c09SVille Tervo 3195fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr); 3196b62f328bSVille Tervo if (!conn) { 3197b62f328bSVille Tervo conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); 3198b62f328bSVille Tervo if (!conn) { 3199b62f328bSVille Tervo BT_ERR("No memory for new connection"); 3200b62f328bSVille Tervo hci_dev_unlock(hdev); 3201b62f328bSVille Tervo return; 3202b62f328bSVille Tervo } 320329b7988aSAndre Guedes 320429b7988aSAndre Guedes conn->dst_type = ev->bdaddr_type; 3205b62f328bSVille Tervo } 3206fcd89c09SVille Tervo 3207fcd89c09SVille Tervo if (ev->status) { 320848264f06SJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 320948264f06SJohan Hedberg conn->dst_type, ev->status); 3210fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 3211fcd89c09SVille Tervo conn->state = BT_CLOSED; 3212fcd89c09SVille Tervo hci_conn_del(conn); 3213fcd89c09SVille Tervo goto unlock; 3214fcd89c09SVille Tervo } 3215fcd89c09SVille Tervo 3216b644ba33SJohan Hedberg if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 3217b644ba33SJohan Hedberg mgmt_device_connected(hdev, &ev->bdaddr, conn->type, 3218b644ba33SJohan Hedberg conn->dst_type, NULL, 0, 0); 321983bc71b4SVinicius Costa Gomes 32207b5c0d52SVinicius Costa Gomes conn->sec_level = BT_SECURITY_LOW; 3221fcd89c09SVille Tervo conn->handle = __le16_to_cpu(ev->handle); 3222fcd89c09SVille Tervo conn->state = BT_CONNECTED; 3223fcd89c09SVille Tervo 3224fcd89c09SVille Tervo hci_conn_hold_device(conn); 3225fcd89c09SVille Tervo hci_conn_add_sysfs(conn); 3226fcd89c09SVille Tervo 3227fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 3228fcd89c09SVille Tervo 3229fcd89c09SVille Tervo unlock: 3230fcd89c09SVille Tervo hci_dev_unlock(hdev); 3231fcd89c09SVille Tervo } 3232fcd89c09SVille Tervo 32339aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev, 32349aa04c91SAndre Guedes struct sk_buff *skb) 32359aa04c91SAndre Guedes { 3236e95beb41SAndre Guedes u8 num_reports = skb->data[0]; 3237e95beb41SAndre Guedes void *ptr = &skb->data[1]; 32383c9e9195SAndre Guedes s8 rssi; 32399aa04c91SAndre Guedes 32409aa04c91SAndre Guedes hci_dev_lock(hdev); 32419aa04c91SAndre Guedes 3242e95beb41SAndre Guedes while (num_reports--) { 3243e95beb41SAndre Guedes struct hci_ev_le_advertising_info *ev = ptr; 3244e95beb41SAndre Guedes 32459aa04c91SAndre Guedes hci_add_adv_entry(hdev, ev); 32469aa04c91SAndre Guedes 32473c9e9195SAndre Guedes rssi = ev->data[ev->length]; 32483c9e9195SAndre Guedes mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type, 32493c9e9195SAndre Guedes NULL, rssi, 0, ev->data, ev->length); 32503c9e9195SAndre Guedes 3251e95beb41SAndre Guedes ptr += sizeof(*ev) + ev->length + 1; 32529aa04c91SAndre Guedes } 32539aa04c91SAndre Guedes 32549aa04c91SAndre Guedes hci_dev_unlock(hdev); 32559aa04c91SAndre Guedes } 32569aa04c91SAndre Guedes 3257a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev, 3258a7a595f6SVinicius Costa Gomes struct sk_buff *skb) 3259a7a595f6SVinicius Costa Gomes { 3260a7a595f6SVinicius Costa Gomes struct hci_ev_le_ltk_req *ev = (void *) skb->data; 3261a7a595f6SVinicius Costa Gomes struct hci_cp_le_ltk_reply cp; 3262bea710feSVinicius Costa Gomes struct hci_cp_le_ltk_neg_reply neg; 3263a7a595f6SVinicius Costa Gomes struct hci_conn *conn; 3264c9839a11SVinicius Costa Gomes struct smp_ltk *ltk; 3265a7a595f6SVinicius Costa Gomes 3266a7a595f6SVinicius Costa Gomes BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle)); 3267a7a595f6SVinicius Costa Gomes 3268a7a595f6SVinicius Costa Gomes hci_dev_lock(hdev); 3269a7a595f6SVinicius Costa Gomes 3270a7a595f6SVinicius Costa Gomes conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3271bea710feSVinicius Costa Gomes if (conn == NULL) 3272bea710feSVinicius Costa Gomes goto not_found; 3273a7a595f6SVinicius Costa Gomes 3274bea710feSVinicius Costa Gomes ltk = hci_find_ltk(hdev, ev->ediv, ev->random); 3275bea710feSVinicius Costa Gomes if (ltk == NULL) 3276bea710feSVinicius Costa Gomes goto not_found; 3277bea710feSVinicius Costa Gomes 3278bea710feSVinicius Costa Gomes memcpy(cp.ltk, ltk->val, sizeof(ltk->val)); 3279a7a595f6SVinicius Costa Gomes cp.handle = cpu_to_le16(conn->handle); 3280c9839a11SVinicius Costa Gomes 3281c9839a11SVinicius Costa Gomes if (ltk->authenticated) 3282c9839a11SVinicius Costa Gomes conn->sec_level = BT_SECURITY_HIGH; 3283a7a595f6SVinicius Costa Gomes 3284a7a595f6SVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); 3285a7a595f6SVinicius Costa Gomes 3286c9839a11SVinicius Costa Gomes if (ltk->type & HCI_SMP_STK) { 3287c9839a11SVinicius Costa Gomes list_del(<k->list); 3288c9839a11SVinicius Costa Gomes kfree(ltk); 3289c9839a11SVinicius Costa Gomes } 3290c9839a11SVinicius Costa Gomes 3291a7a595f6SVinicius Costa Gomes hci_dev_unlock(hdev); 3292bea710feSVinicius Costa Gomes 3293bea710feSVinicius Costa Gomes return; 3294bea710feSVinicius Costa Gomes 3295bea710feSVinicius Costa Gomes not_found: 3296bea710feSVinicius Costa Gomes neg.handle = ev->handle; 3297bea710feSVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg); 3298bea710feSVinicius Costa Gomes hci_dev_unlock(hdev); 3299a7a595f6SVinicius Costa Gomes } 3300a7a595f6SVinicius Costa Gomes 3301fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 3302fcd89c09SVille Tervo { 3303fcd89c09SVille Tervo struct hci_ev_le_meta *le_ev = (void *) skb->data; 3304fcd89c09SVille Tervo 3305fcd89c09SVille Tervo skb_pull(skb, sizeof(*le_ev)); 3306fcd89c09SVille Tervo 3307fcd89c09SVille Tervo switch (le_ev->subevent) { 3308fcd89c09SVille Tervo case HCI_EV_LE_CONN_COMPLETE: 3309fcd89c09SVille Tervo hci_le_conn_complete_evt(hdev, skb); 3310fcd89c09SVille Tervo break; 3311fcd89c09SVille Tervo 33129aa04c91SAndre Guedes case HCI_EV_LE_ADVERTISING_REPORT: 33139aa04c91SAndre Guedes hci_le_adv_report_evt(hdev, skb); 33149aa04c91SAndre Guedes break; 33159aa04c91SAndre Guedes 3316a7a595f6SVinicius Costa Gomes case HCI_EV_LE_LTK_REQ: 3317a7a595f6SVinicius Costa Gomes hci_le_ltk_request_evt(hdev, skb); 3318a7a595f6SVinicius Costa Gomes break; 3319a7a595f6SVinicius Costa Gomes 3320fcd89c09SVille Tervo default: 3321fcd89c09SVille Tervo break; 3322fcd89c09SVille Tervo } 3323fcd89c09SVille Tervo } 3324fcd89c09SVille Tervo 33251da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 33261da177e4SLinus Torvalds { 3327a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 3328a9de9248SMarcel Holtmann __u8 event = hdr->evt; 33291da177e4SLinus Torvalds 33301da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 33311da177e4SLinus Torvalds 3332a9de9248SMarcel Holtmann switch (event) { 33331da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 33341da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 33351da177e4SLinus Torvalds break; 33361da177e4SLinus Torvalds 33371da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 33381da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 33391da177e4SLinus Torvalds break; 33401da177e4SLinus Torvalds 3341a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 3342a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 334321d9e30eSMarcel Holtmann break; 334421d9e30eSMarcel Holtmann 33451da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 33461da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 33471da177e4SLinus Torvalds break; 33481da177e4SLinus Torvalds 33491da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 33501da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 33511da177e4SLinus Torvalds break; 33521da177e4SLinus Torvalds 33531da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 33541da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 33551da177e4SLinus Torvalds break; 33561da177e4SLinus Torvalds 3357a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 3358a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 3359a9de9248SMarcel Holtmann break; 3360a9de9248SMarcel Holtmann 33611da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 33621da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 33631da177e4SLinus Torvalds break; 33641da177e4SLinus Torvalds 3365a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 3366a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 3367a9de9248SMarcel Holtmann break; 3368a9de9248SMarcel Holtmann 3369a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 3370a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 3371a9de9248SMarcel Holtmann break; 3372a9de9248SMarcel Holtmann 3373a9de9248SMarcel Holtmann case HCI_EV_REMOTE_VERSION: 3374a9de9248SMarcel Holtmann hci_remote_version_evt(hdev, skb); 3375a9de9248SMarcel Holtmann break; 3376a9de9248SMarcel Holtmann 3377a9de9248SMarcel Holtmann case HCI_EV_QOS_SETUP_COMPLETE: 3378a9de9248SMarcel Holtmann hci_qos_setup_complete_evt(hdev, skb); 3379a9de9248SMarcel Holtmann break; 3380a9de9248SMarcel Holtmann 3381a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 3382a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 3383a9de9248SMarcel Holtmann break; 3384a9de9248SMarcel Holtmann 3385a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 3386a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 3387a9de9248SMarcel Holtmann break; 3388a9de9248SMarcel Holtmann 3389a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 3390a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 3391a9de9248SMarcel Holtmann break; 3392a9de9248SMarcel Holtmann 3393a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 3394a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 3395a9de9248SMarcel Holtmann break; 3396a9de9248SMarcel Holtmann 3397a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 3398a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 33991da177e4SLinus Torvalds break; 34001da177e4SLinus Torvalds 34011da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 34021da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 34031da177e4SLinus Torvalds break; 34041da177e4SLinus Torvalds 34051da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 34061da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 34071da177e4SLinus Torvalds break; 34081da177e4SLinus Torvalds 34091da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 34101da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 34111da177e4SLinus Torvalds break; 34121da177e4SLinus Torvalds 34131da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 34141da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 34151da177e4SLinus Torvalds break; 34161da177e4SLinus Torvalds 3417a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 3418a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 3419a8746417SMarcel Holtmann break; 3420a8746417SMarcel Holtmann 342185a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 342285a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 342385a1e930SMarcel Holtmann break; 342485a1e930SMarcel Holtmann 3425a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 3426a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 3427a9de9248SMarcel Holtmann break; 3428a9de9248SMarcel Holtmann 3429a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 3430a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 3431a9de9248SMarcel Holtmann break; 3432a9de9248SMarcel Holtmann 3433a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 3434a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 3435a9de9248SMarcel Holtmann break; 3436a9de9248SMarcel Holtmann 3437a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_CHANGED: 3438a9de9248SMarcel Holtmann hci_sync_conn_changed_evt(hdev, skb); 3439a9de9248SMarcel Holtmann break; 3440a9de9248SMarcel Holtmann 344104837f64SMarcel Holtmann case HCI_EV_SNIFF_SUBRATE: 344204837f64SMarcel Holtmann hci_sniff_subrate_evt(hdev, skb); 344304837f64SMarcel Holtmann break; 344404837f64SMarcel Holtmann 3445a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 3446a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 34471da177e4SLinus Torvalds break; 34481da177e4SLinus Torvalds 34490493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 34500493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 34510493684eSMarcel Holtmann break; 34520493684eSMarcel Holtmann 345303b555e1SJohan Hedberg case HCI_EV_IO_CAPA_REPLY: 345403b555e1SJohan Hedberg hci_io_capa_reply_evt(hdev, skb); 345503b555e1SJohan Hedberg break; 345603b555e1SJohan Hedberg 3457a5c29683SJohan Hedberg case HCI_EV_USER_CONFIRM_REQUEST: 3458a5c29683SJohan Hedberg hci_user_confirm_request_evt(hdev, skb); 3459a5c29683SJohan Hedberg break; 3460a5c29683SJohan Hedberg 34611143d458SBrian Gix case HCI_EV_USER_PASSKEY_REQUEST: 34621143d458SBrian Gix hci_user_passkey_request_evt(hdev, skb); 34631143d458SBrian Gix break; 34641143d458SBrian Gix 34650493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 34660493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 34670493684eSMarcel Holtmann break; 34680493684eSMarcel Holtmann 346941a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 347041a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 347141a96212SMarcel Holtmann break; 347241a96212SMarcel Holtmann 3473fcd89c09SVille Tervo case HCI_EV_LE_META: 3474fcd89c09SVille Tervo hci_le_meta_evt(hdev, skb); 3475fcd89c09SVille Tervo break; 3476fcd89c09SVille Tervo 34772763eda6SSzymon Janc case HCI_EV_REMOTE_OOB_DATA_REQUEST: 34782763eda6SSzymon Janc hci_remote_oob_data_request_evt(hdev, skb); 34792763eda6SSzymon Janc break; 34802763eda6SSzymon Janc 348125e89e99SAndrei Emeltchenko case HCI_EV_NUM_COMP_BLOCKS: 348225e89e99SAndrei Emeltchenko hci_num_comp_blocks_evt(hdev, skb); 348325e89e99SAndrei Emeltchenko break; 348425e89e99SAndrei Emeltchenko 34851da177e4SLinus Torvalds default: 3486a9de9248SMarcel Holtmann BT_DBG("%s event 0x%x", hdev->name, event); 34871da177e4SLinus Torvalds break; 34881da177e4SLinus Torvalds } 34891da177e4SLinus Torvalds 34901da177e4SLinus Torvalds kfree_skb(skb); 34911da177e4SLinus Torvalds hdev->stat.evt_rx++; 34921da177e4SLinus Torvalds } 34931da177e4SLinus Torvalds 34941da177e4SLinus Torvalds /* Generate internal stack event */ 34951da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data) 34961da177e4SLinus Torvalds { 34971da177e4SLinus Torvalds struct hci_event_hdr *hdr; 34981da177e4SLinus Torvalds struct hci_ev_stack_internal *ev; 34991da177e4SLinus Torvalds struct sk_buff *skb; 35001da177e4SLinus Torvalds 35011da177e4SLinus Torvalds skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC); 35021da177e4SLinus Torvalds if (!skb) 35031da177e4SLinus Torvalds return; 35041da177e4SLinus Torvalds 35051da177e4SLinus Torvalds hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE); 35061da177e4SLinus Torvalds hdr->evt = HCI_EV_STACK_INTERNAL; 35071da177e4SLinus Torvalds hdr->plen = sizeof(*ev) + dlen; 35081da177e4SLinus Torvalds 35091da177e4SLinus Torvalds ev = (void *) skb_put(skb, sizeof(*ev) + dlen); 35101da177e4SLinus Torvalds ev->type = type; 35111da177e4SLinus Torvalds memcpy(ev->data, data, dlen); 35121da177e4SLinus Torvalds 3513576c7d85SMarcel Holtmann bt_cb(skb)->incoming = 1; 3514a61bbcf2SPatrick McHardy __net_timestamp(skb); 3515576c7d85SMarcel Holtmann 35160d48d939SMarcel Holtmann bt_cb(skb)->pkt_type = HCI_EVENT_PKT; 35171da177e4SLinus Torvalds skb->dev = (void *) hdev; 3518eec8d2bcSJohan Hedberg hci_send_to_sock(hdev, skb, NULL); 35191da177e4SLinus Torvalds kfree_skb(skb); 35201da177e4SLinus Torvalds } 3521e6100a25SAndre Guedes 3522669bb396SGustavo F. Padovan module_param(enable_le, bool, 0644); 3523e6100a25SAndre Guedes MODULE_PARM_DESC(enable_le, "Enable LE support"); 3524