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 48e6100a25SAndre Guedes static int 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); 68744cf19eSJohan Hedberg mgmt_discovering(hdev, 0); 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); 197a9de9248SMarcel Holtmann } 198a9de9248SMarcel Holtmann 199a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) 200a9de9248SMarcel Holtmann { 201a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 2021da177e4SLinus Torvalds void *sent; 2031da177e4SLinus Torvalds 204a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 2051da177e4SLinus Torvalds 206a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); 2071da177e4SLinus Torvalds if (!sent) 208a9de9248SMarcel Holtmann return; 2091da177e4SLinus Torvalds 21056e5cb86SJohan Hedberg hci_dev_lock(hdev); 21156e5cb86SJohan Hedberg 212b312b161SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 213744cf19eSJohan Hedberg mgmt_set_local_name_complete(hdev, sent, status); 214b312b161SJohan Hedberg 21556e5cb86SJohan Hedberg if (status == 0) 2161f6c6378SJohan Hedberg memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); 21756e5cb86SJohan Hedberg 21856e5cb86SJohan Hedberg hci_dev_unlock(hdev); 219a9de9248SMarcel Holtmann } 220a9de9248SMarcel Holtmann 221a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) 222a9de9248SMarcel Holtmann { 223a9de9248SMarcel Holtmann struct hci_rp_read_local_name *rp = (void *) skb->data; 224a9de9248SMarcel Holtmann 225a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 226a9de9248SMarcel Holtmann 227a9de9248SMarcel Holtmann if (rp->status) 228a9de9248SMarcel Holtmann return; 229a9de9248SMarcel Holtmann 2301f6c6378SJohan Hedberg memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); 231a9de9248SMarcel Holtmann } 232a9de9248SMarcel Holtmann 233a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) 234a9de9248SMarcel Holtmann { 235a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 236a9de9248SMarcel Holtmann void *sent; 237a9de9248SMarcel Holtmann 238a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 239a9de9248SMarcel Holtmann 240a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); 241a9de9248SMarcel Holtmann if (!sent) 242a9de9248SMarcel Holtmann return; 2431da177e4SLinus Torvalds 2441da177e4SLinus Torvalds if (!status) { 245a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 246a9de9248SMarcel Holtmann 2471da177e4SLinus Torvalds if (param == AUTH_ENABLED) 2481da177e4SLinus Torvalds set_bit(HCI_AUTH, &hdev->flags); 2491da177e4SLinus Torvalds else 2501da177e4SLinus Torvalds clear_bit(HCI_AUTH, &hdev->flags); 2511da177e4SLinus Torvalds } 252a9de9248SMarcel Holtmann 25323bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status); 254a9de9248SMarcel Holtmann } 2551da177e4SLinus Torvalds 256a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) 257a9de9248SMarcel Holtmann { 258a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 259a9de9248SMarcel Holtmann void *sent; 260a9de9248SMarcel Holtmann 261a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 262a9de9248SMarcel Holtmann 263a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); 2641da177e4SLinus Torvalds if (!sent) 265a9de9248SMarcel Holtmann return; 2661da177e4SLinus Torvalds 2671da177e4SLinus Torvalds if (!status) { 268a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 269a9de9248SMarcel Holtmann 2701da177e4SLinus Torvalds if (param) 2711da177e4SLinus Torvalds set_bit(HCI_ENCRYPT, &hdev->flags); 2721da177e4SLinus Torvalds else 2731da177e4SLinus Torvalds clear_bit(HCI_ENCRYPT, &hdev->flags); 2741da177e4SLinus Torvalds } 275a9de9248SMarcel Holtmann 27623bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status); 2771da177e4SLinus Torvalds } 2781da177e4SLinus Torvalds 279a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) 280a9de9248SMarcel Holtmann { 28136f7fc7eSJohan Hedberg __u8 param, status = *((__u8 *) skb->data); 28236f7fc7eSJohan Hedberg int old_pscan, old_iscan; 283a9de9248SMarcel Holtmann void *sent; 2841da177e4SLinus Torvalds 285a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 286a9de9248SMarcel Holtmann 287a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); 2881da177e4SLinus Torvalds if (!sent) 289a9de9248SMarcel Holtmann return; 2901da177e4SLinus Torvalds 29136f7fc7eSJohan Hedberg param = *((__u8 *) sent); 292a9de9248SMarcel Holtmann 29356e5cb86SJohan Hedberg hci_dev_lock(hdev); 29456e5cb86SJohan Hedberg 2952d7cee58SJohan Hedberg if (status != 0) { 296744cf19eSJohan Hedberg mgmt_write_scan_failed(hdev, param, status); 2972d7cee58SJohan Hedberg hdev->discov_timeout = 0; 2982d7cee58SJohan Hedberg goto done; 2992d7cee58SJohan Hedberg } 3002d7cee58SJohan Hedberg 3019fbcbb45SJohan Hedberg old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags); 3029fbcbb45SJohan Hedberg old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags); 303a9de9248SMarcel Holtmann 30473f22f62SJohan Hedberg if (param & SCAN_INQUIRY) { 3051da177e4SLinus Torvalds set_bit(HCI_ISCAN, &hdev->flags); 3069fbcbb45SJohan Hedberg if (!old_iscan) 307744cf19eSJohan Hedberg mgmt_discoverable(hdev, 1); 30816ab91abSJohan Hedberg if (hdev->discov_timeout > 0) { 30916ab91abSJohan Hedberg int to = msecs_to_jiffies(hdev->discov_timeout * 1000); 31016ab91abSJohan Hedberg queue_delayed_work(hdev->workqueue, &hdev->discov_off, 31116ab91abSJohan Hedberg to); 31216ab91abSJohan Hedberg } 3139fbcbb45SJohan Hedberg } else if (old_iscan) 314744cf19eSJohan Hedberg mgmt_discoverable(hdev, 0); 3151da177e4SLinus Torvalds 3169fbcbb45SJohan Hedberg if (param & SCAN_PAGE) { 3171da177e4SLinus Torvalds set_bit(HCI_PSCAN, &hdev->flags); 3189fbcbb45SJohan Hedberg if (!old_pscan) 319744cf19eSJohan Hedberg mgmt_connectable(hdev, 1); 3209fbcbb45SJohan Hedberg } else if (old_pscan) 321744cf19eSJohan Hedberg mgmt_connectable(hdev, 0); 322a9de9248SMarcel Holtmann 32336f7fc7eSJohan Hedberg done: 32456e5cb86SJohan Hedberg hci_dev_unlock(hdev); 32523bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status); 3261da177e4SLinus Torvalds } 3271da177e4SLinus Torvalds 328a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 329a9de9248SMarcel Holtmann { 330a9de9248SMarcel Holtmann struct hci_rp_read_class_of_dev *rp = (void *) skb->data; 331a9de9248SMarcel Holtmann 332a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 333a9de9248SMarcel Holtmann 334a9de9248SMarcel Holtmann if (rp->status) 335a9de9248SMarcel Holtmann return; 336a9de9248SMarcel Holtmann 337a9de9248SMarcel Holtmann memcpy(hdev->dev_class, rp->dev_class, 3); 338a9de9248SMarcel Holtmann 339a9de9248SMarcel Holtmann BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, 340a9de9248SMarcel Holtmann hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); 341a9de9248SMarcel Holtmann } 342a9de9248SMarcel Holtmann 343a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 344a9de9248SMarcel Holtmann { 345a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 346a9de9248SMarcel Holtmann void *sent; 347a9de9248SMarcel Holtmann 348a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 349a9de9248SMarcel Holtmann 350f383f275SMarcel Holtmann if (status) 351f383f275SMarcel Holtmann return; 352f383f275SMarcel Holtmann 353a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); 354a9de9248SMarcel Holtmann if (!sent) 355a9de9248SMarcel Holtmann return; 356a9de9248SMarcel Holtmann 357a9de9248SMarcel Holtmann memcpy(hdev->dev_class, sent, 3); 358a9de9248SMarcel Holtmann } 359a9de9248SMarcel Holtmann 360a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 361a9de9248SMarcel Holtmann { 362a9de9248SMarcel Holtmann struct hci_rp_read_voice_setting *rp = (void *) skb->data; 363a9de9248SMarcel Holtmann __u16 setting; 364a9de9248SMarcel Holtmann 365a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 366a9de9248SMarcel Holtmann 367a9de9248SMarcel Holtmann if (rp->status) 368a9de9248SMarcel Holtmann return; 369a9de9248SMarcel Holtmann 370a9de9248SMarcel Holtmann setting = __le16_to_cpu(rp->voice_setting); 371a9de9248SMarcel Holtmann 372a9de9248SMarcel Holtmann if (hdev->voice_setting == setting) 373a9de9248SMarcel Holtmann return; 374a9de9248SMarcel Holtmann 375a9de9248SMarcel Holtmann hdev->voice_setting = setting; 376a9de9248SMarcel Holtmann 377a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 378a9de9248SMarcel Holtmann 379a9de9248SMarcel Holtmann if (hdev->notify) { 380a9de9248SMarcel Holtmann tasklet_disable(&hdev->tx_task); 381a9de9248SMarcel Holtmann hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 382a9de9248SMarcel Holtmann tasklet_enable(&hdev->tx_task); 383a9de9248SMarcel Holtmann } 384a9de9248SMarcel Holtmann } 385a9de9248SMarcel Holtmann 386a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 387a9de9248SMarcel Holtmann { 388a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 389f383f275SMarcel Holtmann __u16 setting; 390a9de9248SMarcel Holtmann void *sent; 391a9de9248SMarcel Holtmann 392a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 393a9de9248SMarcel Holtmann 394f383f275SMarcel Holtmann if (status) 395f383f275SMarcel Holtmann return; 396f383f275SMarcel Holtmann 397a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); 398a9de9248SMarcel Holtmann if (!sent) 399a9de9248SMarcel Holtmann return; 400a9de9248SMarcel Holtmann 401f383f275SMarcel Holtmann setting = get_unaligned_le16(sent); 4021da177e4SLinus Torvalds 403f383f275SMarcel Holtmann if (hdev->voice_setting == setting) 404f383f275SMarcel Holtmann return; 405f383f275SMarcel Holtmann 4061da177e4SLinus Torvalds hdev->voice_setting = setting; 4071da177e4SLinus Torvalds 408a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 4091da177e4SLinus Torvalds 4101da177e4SLinus Torvalds if (hdev->notify) { 4111da177e4SLinus Torvalds tasklet_disable(&hdev->tx_task); 4121da177e4SLinus Torvalds hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 4131da177e4SLinus Torvalds tasklet_enable(&hdev->tx_task); 4141da177e4SLinus Torvalds } 4151da177e4SLinus Torvalds } 4161da177e4SLinus Torvalds 417a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 4181da177e4SLinus Torvalds { 419a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 4201da177e4SLinus Torvalds 421a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 4221da177e4SLinus Torvalds 42323bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status); 4241143e5a6SMarcel Holtmann } 4251143e5a6SMarcel Holtmann 426333140b5SMarcel Holtmann static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 427333140b5SMarcel Holtmann { 428333140b5SMarcel Holtmann struct hci_rp_read_ssp_mode *rp = (void *) skb->data; 429333140b5SMarcel Holtmann 430333140b5SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 431333140b5SMarcel Holtmann 432333140b5SMarcel Holtmann if (rp->status) 433333140b5SMarcel Holtmann return; 434333140b5SMarcel Holtmann 435333140b5SMarcel Holtmann hdev->ssp_mode = rp->mode; 436333140b5SMarcel Holtmann } 437333140b5SMarcel Holtmann 438333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 439333140b5SMarcel Holtmann { 440333140b5SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 441333140b5SMarcel Holtmann void *sent; 442333140b5SMarcel Holtmann 443333140b5SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 444333140b5SMarcel Holtmann 445333140b5SMarcel Holtmann if (status) 446333140b5SMarcel Holtmann return; 447333140b5SMarcel Holtmann 448333140b5SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); 449333140b5SMarcel Holtmann if (!sent) 450333140b5SMarcel Holtmann return; 451333140b5SMarcel Holtmann 452333140b5SMarcel Holtmann hdev->ssp_mode = *((__u8 *) sent); 453333140b5SMarcel Holtmann } 454333140b5SMarcel Holtmann 455d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev) 456d5859e22SJohan Hedberg { 457d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 458d5859e22SJohan Hedberg return 2; 459d5859e22SJohan Hedberg 460d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 461d5859e22SJohan Hedberg return 1; 462d5859e22SJohan Hedberg 463d5859e22SJohan Hedberg if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 && 464d5859e22SJohan Hedberg hdev->lmp_subver == 0x0757) 465d5859e22SJohan Hedberg return 1; 466d5859e22SJohan Hedberg 467d5859e22SJohan Hedberg if (hdev->manufacturer == 15) { 468d5859e22SJohan Hedberg if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963) 469d5859e22SJohan Hedberg return 1; 470d5859e22SJohan Hedberg if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963) 471d5859e22SJohan Hedberg return 1; 472d5859e22SJohan Hedberg if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965) 473d5859e22SJohan Hedberg return 1; 474d5859e22SJohan Hedberg } 475d5859e22SJohan Hedberg 476d5859e22SJohan Hedberg if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 && 477d5859e22SJohan Hedberg hdev->lmp_subver == 0x1805) 478d5859e22SJohan Hedberg return 1; 479d5859e22SJohan Hedberg 480d5859e22SJohan Hedberg return 0; 481d5859e22SJohan Hedberg } 482d5859e22SJohan Hedberg 483d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev) 484d5859e22SJohan Hedberg { 485d5859e22SJohan Hedberg u8 mode; 486d5859e22SJohan Hedberg 487d5859e22SJohan Hedberg mode = hci_get_inquiry_mode(hdev); 488d5859e22SJohan Hedberg 489d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode); 490d5859e22SJohan Hedberg } 491d5859e22SJohan Hedberg 492d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev) 493d5859e22SJohan Hedberg { 494d5859e22SJohan Hedberg /* The second byte is 0xff instead of 0x9f (two reserved bits 495d5859e22SJohan Hedberg * disabled) since a Broadcom 1.2 dongle doesn't respond to the 496d5859e22SJohan Hedberg * command otherwise */ 497d5859e22SJohan Hedberg u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 }; 498d5859e22SJohan Hedberg 4996de6c18dSVille Tervo /* CSR 1.1 dongles does not accept any bitfield so don't try to set 5006de6c18dSVille Tervo * any event mask for pre 1.2 devices */ 5016de6c18dSVille Tervo if (hdev->lmp_ver <= 1) 5026de6c18dSVille Tervo return; 5036de6c18dSVille Tervo 504d5859e22SJohan Hedberg events[4] |= 0x01; /* Flow Specification Complete */ 505d5859e22SJohan Hedberg events[4] |= 0x02; /* Inquiry Result with RSSI */ 506d5859e22SJohan Hedberg events[4] |= 0x04; /* Read Remote Extended Features Complete */ 507d5859e22SJohan Hedberg events[5] |= 0x08; /* Synchronous Connection Complete */ 508d5859e22SJohan Hedberg events[5] |= 0x10; /* Synchronous Connection Changed */ 509d5859e22SJohan Hedberg 510d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 511d5859e22SJohan Hedberg events[4] |= 0x04; /* Inquiry Result with RSSI */ 512d5859e22SJohan Hedberg 513d5859e22SJohan Hedberg if (hdev->features[5] & LMP_SNIFF_SUBR) 514d5859e22SJohan Hedberg events[5] |= 0x20; /* Sniff Subrating */ 515d5859e22SJohan Hedberg 516d5859e22SJohan Hedberg if (hdev->features[5] & LMP_PAUSE_ENC) 517d5859e22SJohan Hedberg events[5] |= 0x80; /* Encryption Key Refresh Complete */ 518d5859e22SJohan Hedberg 519d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 520d5859e22SJohan Hedberg events[5] |= 0x40; /* Extended Inquiry Result */ 521d5859e22SJohan Hedberg 522d5859e22SJohan Hedberg if (hdev->features[6] & LMP_NO_FLUSH) 523d5859e22SJohan Hedberg events[7] |= 0x01; /* Enhanced Flush Complete */ 524d5859e22SJohan Hedberg 525d5859e22SJohan Hedberg if (hdev->features[7] & LMP_LSTO) 526d5859e22SJohan Hedberg events[6] |= 0x80; /* Link Supervision Timeout Changed */ 527d5859e22SJohan Hedberg 528d5859e22SJohan Hedberg if (hdev->features[6] & LMP_SIMPLE_PAIR) { 529d5859e22SJohan Hedberg events[6] |= 0x01; /* IO Capability Request */ 530d5859e22SJohan Hedberg events[6] |= 0x02; /* IO Capability Response */ 531d5859e22SJohan Hedberg events[6] |= 0x04; /* User Confirmation Request */ 532d5859e22SJohan Hedberg events[6] |= 0x08; /* User Passkey Request */ 533d5859e22SJohan Hedberg events[6] |= 0x10; /* Remote OOB Data Request */ 534d5859e22SJohan Hedberg events[6] |= 0x20; /* Simple Pairing Complete */ 535d5859e22SJohan Hedberg events[7] |= 0x04; /* User Passkey Notification */ 536d5859e22SJohan Hedberg events[7] |= 0x08; /* Keypress Notification */ 537d5859e22SJohan Hedberg events[7] |= 0x10; /* Remote Host Supported 538d5859e22SJohan Hedberg * Features Notification */ 539d5859e22SJohan Hedberg } 540d5859e22SJohan Hedberg 541d5859e22SJohan Hedberg if (hdev->features[4] & LMP_LE) 542d5859e22SJohan Hedberg events[7] |= 0x20; /* LE Meta-Event */ 543d5859e22SJohan Hedberg 544d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); 545d5859e22SJohan Hedberg } 546d5859e22SJohan Hedberg 547e6100a25SAndre Guedes static void hci_set_le_support(struct hci_dev *hdev) 548e6100a25SAndre Guedes { 549e6100a25SAndre Guedes struct hci_cp_write_le_host_supported cp; 550e6100a25SAndre Guedes 551e6100a25SAndre Guedes memset(&cp, 0, sizeof(cp)); 552e6100a25SAndre Guedes 553e6100a25SAndre Guedes if (enable_le) { 554e6100a25SAndre Guedes cp.le = 1; 555e6100a25SAndre Guedes cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR); 556e6100a25SAndre Guedes } 557e6100a25SAndre Guedes 558e6100a25SAndre Guedes hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), &cp); 559e6100a25SAndre Guedes } 560e6100a25SAndre Guedes 561d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev) 562d5859e22SJohan Hedberg { 563d5859e22SJohan Hedberg hci_setup_event_mask(hdev); 564d5859e22SJohan Hedberg 565d5859e22SJohan Hedberg if (hdev->lmp_ver > 1) 566d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); 567d5859e22SJohan Hedberg 568d5859e22SJohan Hedberg if (hdev->features[6] & LMP_SIMPLE_PAIR) { 569d5859e22SJohan Hedberg u8 mode = 0x01; 570d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode); 571d5859e22SJohan Hedberg } 572d5859e22SJohan Hedberg 573d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 574d5859e22SJohan Hedberg hci_setup_inquiry_mode(hdev); 575d5859e22SJohan Hedberg 576d5859e22SJohan Hedberg if (hdev->features[7] & LMP_INQ_TX_PWR) 577d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL); 578971e3a4bSAndre Guedes 579971e3a4bSAndre Guedes if (hdev->features[7] & LMP_EXTFEATURES) { 580971e3a4bSAndre Guedes struct hci_cp_read_local_ext_features cp; 581971e3a4bSAndre Guedes 582971e3a4bSAndre Guedes cp.page = 0x01; 583971e3a4bSAndre Guedes hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, 584971e3a4bSAndre Guedes sizeof(cp), &cp); 585971e3a4bSAndre Guedes } 586e6100a25SAndre Guedes 587e6100a25SAndre Guedes if (hdev->features[4] & LMP_LE) 588e6100a25SAndre Guedes hci_set_le_support(hdev); 589d5859e22SJohan Hedberg } 590d5859e22SJohan Hedberg 591a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) 592a9de9248SMarcel Holtmann { 593a9de9248SMarcel Holtmann struct hci_rp_read_local_version *rp = (void *) skb->data; 5941143e5a6SMarcel Holtmann 595a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 5961143e5a6SMarcel Holtmann 597a9de9248SMarcel Holtmann if (rp->status) 598a9de9248SMarcel Holtmann return; 5991143e5a6SMarcel Holtmann 600a9de9248SMarcel Holtmann hdev->hci_ver = rp->hci_ver; 601e4e8e37cSMarcel Holtmann hdev->hci_rev = __le16_to_cpu(rp->hci_rev); 602d5859e22SJohan Hedberg hdev->lmp_ver = rp->lmp_ver; 603e4e8e37cSMarcel Holtmann hdev->manufacturer = __le16_to_cpu(rp->manufacturer); 604d5859e22SJohan Hedberg hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); 6051da177e4SLinus Torvalds 606a9de9248SMarcel Holtmann BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name, 607a9de9248SMarcel Holtmann hdev->manufacturer, 608a9de9248SMarcel Holtmann hdev->hci_ver, hdev->hci_rev); 609d5859e22SJohan Hedberg 610d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags)) 611d5859e22SJohan Hedberg hci_setup(hdev); 612d5859e22SJohan Hedberg } 613d5859e22SJohan Hedberg 614d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev) 615d5859e22SJohan Hedberg { 616d5859e22SJohan Hedberg u16 link_policy = 0; 617d5859e22SJohan Hedberg 618d5859e22SJohan Hedberg if (hdev->features[0] & LMP_RSWITCH) 619d5859e22SJohan Hedberg link_policy |= HCI_LP_RSWITCH; 620d5859e22SJohan Hedberg if (hdev->features[0] & LMP_HOLD) 621d5859e22SJohan Hedberg link_policy |= HCI_LP_HOLD; 622d5859e22SJohan Hedberg if (hdev->features[0] & LMP_SNIFF) 623d5859e22SJohan Hedberg link_policy |= HCI_LP_SNIFF; 624d5859e22SJohan Hedberg if (hdev->features[1] & LMP_PARK) 625d5859e22SJohan Hedberg link_policy |= HCI_LP_PARK; 626d5859e22SJohan Hedberg 627d5859e22SJohan Hedberg link_policy = cpu_to_le16(link_policy); 628d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, 629d5859e22SJohan Hedberg sizeof(link_policy), &link_policy); 6301da177e4SLinus Torvalds } 6311da177e4SLinus Torvalds 632a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb) 633a9de9248SMarcel Holtmann { 634a9de9248SMarcel Holtmann struct hci_rp_read_local_commands *rp = (void *) skb->data; 635a9de9248SMarcel Holtmann 636a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 637a9de9248SMarcel Holtmann 638a9de9248SMarcel Holtmann if (rp->status) 639d5859e22SJohan Hedberg goto done; 640a9de9248SMarcel Holtmann 641a9de9248SMarcel Holtmann memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); 642d5859e22SJohan Hedberg 643d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10)) 644d5859e22SJohan Hedberg hci_setup_link_policy(hdev); 645d5859e22SJohan Hedberg 646d5859e22SJohan Hedberg done: 647d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status); 648a9de9248SMarcel Holtmann } 649a9de9248SMarcel Holtmann 650a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb) 651a9de9248SMarcel Holtmann { 652a9de9248SMarcel Holtmann struct hci_rp_read_local_features *rp = (void *) skb->data; 653a9de9248SMarcel Holtmann 654a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 655a9de9248SMarcel Holtmann 656a9de9248SMarcel Holtmann if (rp->status) 657a9de9248SMarcel Holtmann return; 658a9de9248SMarcel Holtmann 659a9de9248SMarcel Holtmann memcpy(hdev->features, rp->features, 8); 6601da177e4SLinus Torvalds 6611da177e4SLinus Torvalds /* Adjust default settings according to features 6621da177e4SLinus Torvalds * supported by device. */ 663a9de9248SMarcel Holtmann 6641da177e4SLinus Torvalds if (hdev->features[0] & LMP_3SLOT) 6651da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM3 | HCI_DH3); 6661da177e4SLinus Torvalds 6671da177e4SLinus Torvalds if (hdev->features[0] & LMP_5SLOT) 6681da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM5 | HCI_DH5); 6691da177e4SLinus Torvalds 6705b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV2) { 6711da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV2); 6725b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV2); 6735b7f9909SMarcel Holtmann } 6741da177e4SLinus Torvalds 6755b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV3) { 6761da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV3); 6775b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV3); 6785b7f9909SMarcel Holtmann } 6795b7f9909SMarcel Holtmann 6805b7f9909SMarcel Holtmann if (hdev->features[3] & LMP_ESCO) 6815b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV3); 6825b7f9909SMarcel Holtmann 6835b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV4) 6845b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV4); 6855b7f9909SMarcel Holtmann 6865b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV5) 6875b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV5); 6881da177e4SLinus Torvalds 689efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_2M) 690efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV3); 691efc7688bSMarcel Holtmann 692efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_3M) 693efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_3EV3); 694efc7688bSMarcel Holtmann 695efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_3S_ESCO) 696efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); 697efc7688bSMarcel Holtmann 698a9de9248SMarcel Holtmann BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, 699a9de9248SMarcel Holtmann hdev->features[0], hdev->features[1], 700a9de9248SMarcel Holtmann hdev->features[2], hdev->features[3], 701a9de9248SMarcel Holtmann hdev->features[4], hdev->features[5], 702a9de9248SMarcel Holtmann hdev->features[6], hdev->features[7]); 7031da177e4SLinus Torvalds } 7041da177e4SLinus Torvalds 705971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev, 706971e3a4bSAndre Guedes struct sk_buff *skb) 707971e3a4bSAndre Guedes { 708971e3a4bSAndre Guedes struct hci_rp_read_local_ext_features *rp = (void *) skb->data; 709971e3a4bSAndre Guedes 710971e3a4bSAndre Guedes BT_DBG("%s status 0x%x", hdev->name, rp->status); 711971e3a4bSAndre Guedes 712971e3a4bSAndre Guedes if (rp->status) 713971e3a4bSAndre Guedes return; 714971e3a4bSAndre Guedes 715971e3a4bSAndre Guedes memcpy(hdev->extfeatures, rp->features, 8); 716971e3a4bSAndre Guedes 717971e3a4bSAndre Guedes hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status); 718971e3a4bSAndre Guedes } 719971e3a4bSAndre Guedes 720a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 721a9de9248SMarcel Holtmann { 722a9de9248SMarcel Holtmann struct hci_rp_read_buffer_size *rp = (void *) skb->data; 723a9de9248SMarcel Holtmann 724a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 725a9de9248SMarcel Holtmann 726a9de9248SMarcel Holtmann if (rp->status) 727a9de9248SMarcel Holtmann return; 728a9de9248SMarcel Holtmann 729a9de9248SMarcel Holtmann hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); 730a9de9248SMarcel Holtmann hdev->sco_mtu = rp->sco_mtu; 731a9de9248SMarcel Holtmann hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); 732a9de9248SMarcel Holtmann hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); 733da1f5198SMarcel Holtmann 734da1f5198SMarcel Holtmann if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { 735da1f5198SMarcel Holtmann hdev->sco_mtu = 64; 736da1f5198SMarcel Holtmann hdev->sco_pkts = 8; 737da1f5198SMarcel Holtmann } 738da1f5198SMarcel Holtmann 739da1f5198SMarcel Holtmann hdev->acl_cnt = hdev->acl_pkts; 740da1f5198SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 7411da177e4SLinus Torvalds 742a9de9248SMarcel Holtmann BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, 743a9de9248SMarcel Holtmann hdev->acl_mtu, hdev->acl_pkts, 744a9de9248SMarcel Holtmann hdev->sco_mtu, hdev->sco_pkts); 7451da177e4SLinus Torvalds } 7461da177e4SLinus Torvalds 747a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) 748a9de9248SMarcel Holtmann { 749a9de9248SMarcel Holtmann struct hci_rp_read_bd_addr *rp = (void *) skb->data; 7501da177e4SLinus Torvalds 751a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 752a9de9248SMarcel Holtmann 753a9de9248SMarcel Holtmann if (!rp->status) 754a9de9248SMarcel Holtmann bacpy(&hdev->bdaddr, &rp->bdaddr); 755a9de9248SMarcel Holtmann 75623bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status); 75723bb5763SJohan Hedberg } 75823bb5763SJohan Hedberg 75923bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb) 76023bb5763SJohan Hedberg { 76123bb5763SJohan Hedberg __u8 status = *((__u8 *) skb->data); 76223bb5763SJohan Hedberg 76323bb5763SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 76423bb5763SJohan Hedberg 76523bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status); 7661da177e4SLinus Torvalds } 7671da177e4SLinus Torvalds 768928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev, 769928abaa7SAndrei Emeltchenko struct sk_buff *skb) 770928abaa7SAndrei Emeltchenko { 771928abaa7SAndrei Emeltchenko struct hci_rp_read_local_amp_info *rp = (void *) skb->data; 772928abaa7SAndrei Emeltchenko 773928abaa7SAndrei Emeltchenko BT_DBG("%s status 0x%x", hdev->name, rp->status); 774928abaa7SAndrei Emeltchenko 775928abaa7SAndrei Emeltchenko if (rp->status) 776928abaa7SAndrei Emeltchenko return; 777928abaa7SAndrei Emeltchenko 778928abaa7SAndrei Emeltchenko hdev->amp_status = rp->amp_status; 779928abaa7SAndrei Emeltchenko hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); 780928abaa7SAndrei Emeltchenko hdev->amp_max_bw = __le32_to_cpu(rp->max_bw); 781928abaa7SAndrei Emeltchenko hdev->amp_min_latency = __le32_to_cpu(rp->min_latency); 782928abaa7SAndrei Emeltchenko hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu); 783928abaa7SAndrei Emeltchenko hdev->amp_type = rp->amp_type; 784928abaa7SAndrei Emeltchenko hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap); 785928abaa7SAndrei Emeltchenko hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size); 786928abaa7SAndrei Emeltchenko hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); 787928abaa7SAndrei Emeltchenko hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); 788928abaa7SAndrei Emeltchenko 789928abaa7SAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status); 790928abaa7SAndrei Emeltchenko } 791928abaa7SAndrei Emeltchenko 792b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, 793b0916ea0SJohan Hedberg struct sk_buff *skb) 794b0916ea0SJohan Hedberg { 795b0916ea0SJohan Hedberg __u8 status = *((__u8 *) skb->data); 796b0916ea0SJohan Hedberg 797b0916ea0SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 798b0916ea0SJohan Hedberg 799b0916ea0SJohan Hedberg hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status); 800b0916ea0SJohan Hedberg } 801b0916ea0SJohan Hedberg 802d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb) 803d5859e22SJohan Hedberg { 804d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 805d5859e22SJohan Hedberg 806d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 807d5859e22SJohan Hedberg 808d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status); 809d5859e22SJohan Hedberg } 810d5859e22SJohan Hedberg 811d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev, 812d5859e22SJohan Hedberg struct sk_buff *skb) 813d5859e22SJohan Hedberg { 814d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 815d5859e22SJohan Hedberg 816d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 817d5859e22SJohan Hedberg 818d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status); 819d5859e22SJohan Hedberg } 820d5859e22SJohan Hedberg 821d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, 822d5859e22SJohan Hedberg struct sk_buff *skb) 823d5859e22SJohan Hedberg { 824d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 825d5859e22SJohan Hedberg 826d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 827d5859e22SJohan Hedberg 828d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status); 829d5859e22SJohan Hedberg } 830d5859e22SJohan Hedberg 831d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb) 832d5859e22SJohan Hedberg { 833d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 834d5859e22SJohan Hedberg 835d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 836d5859e22SJohan Hedberg 837d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status); 838d5859e22SJohan Hedberg } 839d5859e22SJohan Hedberg 840980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) 841980e1a53SJohan Hedberg { 842980e1a53SJohan Hedberg struct hci_rp_pin_code_reply *rp = (void *) skb->data; 843980e1a53SJohan Hedberg struct hci_cp_pin_code_reply *cp; 844980e1a53SJohan Hedberg struct hci_conn *conn; 845980e1a53SJohan Hedberg 846980e1a53SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 847980e1a53SJohan Hedberg 84856e5cb86SJohan Hedberg hci_dev_lock(hdev); 84956e5cb86SJohan Hedberg 850980e1a53SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 851744cf19eSJohan Hedberg mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); 852980e1a53SJohan Hedberg 853980e1a53SJohan Hedberg if (rp->status != 0) 85456e5cb86SJohan Hedberg goto unlock; 855980e1a53SJohan Hedberg 856980e1a53SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); 857980e1a53SJohan Hedberg if (!cp) 85856e5cb86SJohan Hedberg goto unlock; 859980e1a53SJohan Hedberg 860980e1a53SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 861980e1a53SJohan Hedberg if (conn) 862980e1a53SJohan Hedberg conn->pin_length = cp->pin_len; 86356e5cb86SJohan Hedberg 86456e5cb86SJohan Hedberg unlock: 86556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 866980e1a53SJohan Hedberg } 867980e1a53SJohan Hedberg 868980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 869980e1a53SJohan Hedberg { 870980e1a53SJohan Hedberg struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data; 871980e1a53SJohan Hedberg 872980e1a53SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 873980e1a53SJohan Hedberg 87456e5cb86SJohan Hedberg hci_dev_lock(hdev); 87556e5cb86SJohan Hedberg 876980e1a53SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 877744cf19eSJohan Hedberg mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr, 878980e1a53SJohan Hedberg rp->status); 87956e5cb86SJohan Hedberg 88056e5cb86SJohan Hedberg hci_dev_unlock(hdev); 881980e1a53SJohan Hedberg } 88256e5cb86SJohan Hedberg 8836ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, 8846ed58ec5SVille Tervo struct sk_buff *skb) 8856ed58ec5SVille Tervo { 8866ed58ec5SVille Tervo struct hci_rp_le_read_buffer_size *rp = (void *) skb->data; 8876ed58ec5SVille Tervo 8886ed58ec5SVille Tervo BT_DBG("%s status 0x%x", hdev->name, rp->status); 8896ed58ec5SVille Tervo 8906ed58ec5SVille Tervo if (rp->status) 8916ed58ec5SVille Tervo return; 8926ed58ec5SVille Tervo 8936ed58ec5SVille Tervo hdev->le_mtu = __le16_to_cpu(rp->le_mtu); 8946ed58ec5SVille Tervo hdev->le_pkts = rp->le_max_pkt; 8956ed58ec5SVille Tervo 8966ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 8976ed58ec5SVille Tervo 8986ed58ec5SVille Tervo BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); 8996ed58ec5SVille Tervo 9006ed58ec5SVille Tervo hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status); 9016ed58ec5SVille Tervo } 902980e1a53SJohan Hedberg 903a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) 904a5c29683SJohan Hedberg { 905a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 906a5c29683SJohan Hedberg 907a5c29683SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 908a5c29683SJohan Hedberg 90956e5cb86SJohan Hedberg hci_dev_lock(hdev); 91056e5cb86SJohan Hedberg 911a5c29683SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 912744cf19eSJohan Hedberg mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, 913a5c29683SJohan Hedberg rp->status); 91456e5cb86SJohan Hedberg 91556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 916a5c29683SJohan Hedberg } 917a5c29683SJohan Hedberg 918a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, 919a5c29683SJohan Hedberg struct sk_buff *skb) 920a5c29683SJohan Hedberg { 921a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 922a5c29683SJohan Hedberg 923a5c29683SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 924a5c29683SJohan Hedberg 92556e5cb86SJohan Hedberg hci_dev_lock(hdev); 92656e5cb86SJohan Hedberg 927a5c29683SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 928744cf19eSJohan Hedberg mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr, 929a5c29683SJohan Hedberg rp->status); 93056e5cb86SJohan Hedberg 93156e5cb86SJohan Hedberg hci_dev_unlock(hdev); 932a5c29683SJohan Hedberg } 933a5c29683SJohan Hedberg 934c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, 935c35938b2SSzymon Janc struct sk_buff *skb) 936c35938b2SSzymon Janc { 937c35938b2SSzymon Janc struct hci_rp_read_local_oob_data *rp = (void *) skb->data; 938c35938b2SSzymon Janc 939c35938b2SSzymon Janc BT_DBG("%s status 0x%x", hdev->name, rp->status); 940c35938b2SSzymon Janc 94156e5cb86SJohan Hedberg hci_dev_lock(hdev); 942744cf19eSJohan Hedberg mgmt_read_local_oob_data_reply_complete(hdev, rp->hash, 943c35938b2SSzymon Janc rp->randomizer, rp->status); 94456e5cb86SJohan Hedberg hci_dev_unlock(hdev); 945c35938b2SSzymon Janc } 946c35938b2SSzymon Janc 947eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, 948eb9d91f5SAndre Guedes struct sk_buff *skb) 949eb9d91f5SAndre Guedes { 950eb9d91f5SAndre Guedes struct hci_cp_le_set_scan_enable *cp; 951eb9d91f5SAndre Guedes __u8 status = *((__u8 *) skb->data); 952eb9d91f5SAndre Guedes 953eb9d91f5SAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 954eb9d91f5SAndre Guedes 955eb9d91f5SAndre Guedes if (status) 956eb9d91f5SAndre Guedes return; 957eb9d91f5SAndre Guedes 958eb9d91f5SAndre Guedes cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE); 959eb9d91f5SAndre Guedes if (!cp) 960eb9d91f5SAndre Guedes return; 961eb9d91f5SAndre Guedes 96235815085SAndre Guedes if (cp->enable == 0x01) { 96335815085SAndre Guedes del_timer(&hdev->adv_timer); 964a8f13c8cSAndre Guedes 965a8f13c8cSAndre Guedes hci_dev_lock(hdev); 966eb9d91f5SAndre Guedes hci_adv_entries_clear(hdev); 967a8f13c8cSAndre Guedes hci_dev_unlock(hdev); 96835815085SAndre Guedes } else if (cp->enable == 0x00) { 96935815085SAndre Guedes mod_timer(&hdev->adv_timer, jiffies + ADV_CLEAR_TIMEOUT); 97035815085SAndre Guedes } 971eb9d91f5SAndre Guedes } 972eb9d91f5SAndre Guedes 973a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb) 974a7a595f6SVinicius Costa Gomes { 975a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_reply *rp = (void *) skb->data; 976a7a595f6SVinicius Costa Gomes 977a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, rp->status); 978a7a595f6SVinicius Costa Gomes 979a7a595f6SVinicius Costa Gomes if (rp->status) 980a7a595f6SVinicius Costa Gomes return; 981a7a595f6SVinicius Costa Gomes 982a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status); 983a7a595f6SVinicius Costa Gomes } 984a7a595f6SVinicius Costa Gomes 985a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 986a7a595f6SVinicius Costa Gomes { 987a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data; 988a7a595f6SVinicius Costa Gomes 989a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, rp->status); 990a7a595f6SVinicius Costa Gomes 991a7a595f6SVinicius Costa Gomes if (rp->status) 992a7a595f6SVinicius Costa Gomes return; 993a7a595f6SVinicius Costa Gomes 994a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status); 995a7a595f6SVinicius Costa Gomes } 996a7a595f6SVinicius Costa Gomes 997f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev, 998f9b49306SAndre Guedes struct sk_buff *skb) 999f9b49306SAndre Guedes { 1000f9b49306SAndre Guedes struct hci_cp_read_local_ext_features cp; 1001f9b49306SAndre Guedes __u8 status = *((__u8 *) skb->data); 1002f9b49306SAndre Guedes 1003f9b49306SAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 1004f9b49306SAndre Guedes 1005f9b49306SAndre Guedes if (status) 1006f9b49306SAndre Guedes return; 1007f9b49306SAndre Guedes 1008f9b49306SAndre Guedes cp.page = 0x01; 1009f9b49306SAndre Guedes hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp); 1010f9b49306SAndre Guedes } 1011f9b49306SAndre Guedes 1012a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 1013a9de9248SMarcel Holtmann { 1014a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1015a9de9248SMarcel Holtmann 1016a9de9248SMarcel Holtmann if (status) { 101723bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 1018a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 101956e5cb86SJohan Hedberg hci_dev_lock(hdev); 1020164a6e78SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 10217a135109SAndre Guedes mgmt_start_discovery_failed(hdev, status); 102256e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1023314b2381SJohan Hedberg return; 1024314b2381SJohan Hedberg } 1025314b2381SJohan Hedberg 102689352e7dSAndre Guedes set_bit(HCI_INQUIRY, &hdev->flags); 102789352e7dSAndre Guedes 102856e5cb86SJohan Hedberg hci_dev_lock(hdev); 1029744cf19eSJohan Hedberg mgmt_discovering(hdev, 1); 103056e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1031a9de9248SMarcel Holtmann } 1032a9de9248SMarcel Holtmann 10331da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 10341da177e4SLinus Torvalds { 1035a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 10361da177e4SLinus Torvalds struct hci_conn *conn; 10371da177e4SLinus Torvalds 1038a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1039a9de9248SMarcel Holtmann 1040a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 10411da177e4SLinus Torvalds if (!cp) 10421da177e4SLinus Torvalds return; 10431da177e4SLinus Torvalds 10441da177e4SLinus Torvalds hci_dev_lock(hdev); 10451da177e4SLinus Torvalds 10461da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 10471da177e4SLinus Torvalds 1048a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn); 10491da177e4SLinus Torvalds 10501da177e4SLinus Torvalds if (status) { 10511da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 10524c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 10531da177e4SLinus Torvalds conn->state = BT_CLOSED; 10541da177e4SLinus Torvalds hci_proto_connect_cfm(conn, status); 10551da177e4SLinus Torvalds hci_conn_del(conn); 10564c67bc74SMarcel Holtmann } else 10574c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 10581da177e4SLinus Torvalds } 10591da177e4SLinus Torvalds } else { 10601da177e4SLinus Torvalds if (!conn) { 10611da177e4SLinus Torvalds conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); 10621da177e4SLinus Torvalds if (conn) { 10631da177e4SLinus Torvalds conn->out = 1; 10641da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 10651da177e4SLinus Torvalds } else 1066893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 10671da177e4SLinus Torvalds } 10681da177e4SLinus Torvalds } 10691da177e4SLinus Torvalds 10701da177e4SLinus Torvalds hci_dev_unlock(hdev); 10711da177e4SLinus Torvalds } 10721da177e4SLinus Torvalds 1073a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 10741da177e4SLinus Torvalds { 1075a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 10761da177e4SLinus Torvalds struct hci_conn *acl, *sco; 10771da177e4SLinus Torvalds __u16 handle; 10781da177e4SLinus Torvalds 1079b6a0dc82SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1080b6a0dc82SMarcel Holtmann 1081a9de9248SMarcel Holtmann if (!status) 1082a9de9248SMarcel Holtmann return; 1083a9de9248SMarcel Holtmann 1084a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 10851da177e4SLinus Torvalds if (!cp) 1086a9de9248SMarcel Holtmann return; 10871da177e4SLinus Torvalds 10881da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 10891da177e4SLinus Torvalds 1090a9de9248SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 10911da177e4SLinus Torvalds 10921da177e4SLinus Torvalds hci_dev_lock(hdev); 10931da177e4SLinus Torvalds 10941da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 10955a08ecceSAndrei Emeltchenko if (acl) { 10965a08ecceSAndrei Emeltchenko sco = acl->link; 10975a08ecceSAndrei Emeltchenko if (sco) { 10981da177e4SLinus Torvalds sco->state = BT_CLOSED; 10991da177e4SLinus Torvalds 11001da177e4SLinus Torvalds hci_proto_connect_cfm(sco, status); 11011da177e4SLinus Torvalds hci_conn_del(sco); 11021da177e4SLinus Torvalds } 11035a08ecceSAndrei Emeltchenko } 11041da177e4SLinus Torvalds 11051da177e4SLinus Torvalds hci_dev_unlock(hdev); 11061da177e4SLinus Torvalds } 11071da177e4SLinus Torvalds 1108f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 1109f8558555SMarcel Holtmann { 1110f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 1111f8558555SMarcel Holtmann struct hci_conn *conn; 1112f8558555SMarcel Holtmann 1113f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1114f8558555SMarcel Holtmann 1115f8558555SMarcel Holtmann if (!status) 1116f8558555SMarcel Holtmann return; 1117f8558555SMarcel Holtmann 1118f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 1119f8558555SMarcel Holtmann if (!cp) 1120f8558555SMarcel Holtmann return; 1121f8558555SMarcel Holtmann 1122f8558555SMarcel Holtmann hci_dev_lock(hdev); 1123f8558555SMarcel Holtmann 1124f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1125f8558555SMarcel Holtmann if (conn) { 1126f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1127f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1128f8558555SMarcel Holtmann hci_conn_put(conn); 1129f8558555SMarcel Holtmann } 1130f8558555SMarcel Holtmann } 1131f8558555SMarcel Holtmann 1132f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1133f8558555SMarcel Holtmann } 1134f8558555SMarcel Holtmann 1135f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 1136f8558555SMarcel Holtmann { 1137f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 1138f8558555SMarcel Holtmann struct hci_conn *conn; 1139f8558555SMarcel Holtmann 1140f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1141f8558555SMarcel Holtmann 1142f8558555SMarcel Holtmann if (!status) 1143f8558555SMarcel Holtmann return; 1144f8558555SMarcel Holtmann 1145f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 1146f8558555SMarcel Holtmann if (!cp) 1147f8558555SMarcel Holtmann return; 1148f8558555SMarcel Holtmann 1149f8558555SMarcel Holtmann hci_dev_lock(hdev); 1150f8558555SMarcel Holtmann 1151f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1152f8558555SMarcel Holtmann if (conn) { 1153f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1154f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1155f8558555SMarcel Holtmann hci_conn_put(conn); 1156f8558555SMarcel Holtmann } 1157f8558555SMarcel Holtmann } 1158f8558555SMarcel Holtmann 1159f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1160f8558555SMarcel Holtmann } 1161f8558555SMarcel Holtmann 1162127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev, 1163392599b9SJohan Hedberg struct hci_conn *conn) 1164392599b9SJohan Hedberg { 1165392599b9SJohan Hedberg if (conn->state != BT_CONFIG || !conn->out) 1166392599b9SJohan Hedberg return 0; 1167392599b9SJohan Hedberg 1168765c2a96SJohan Hedberg if (conn->pending_sec_level == BT_SECURITY_SDP) 1169392599b9SJohan Hedberg return 0; 1170392599b9SJohan Hedberg 1171392599b9SJohan Hedberg /* Only request authentication for SSP connections or non-SSP 1172e9bf2bf0SVinicius Costa Gomes * devices with sec_level HIGH or if MITM protection is requested */ 1173392599b9SJohan Hedberg if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) && 1174e9bf2bf0SVinicius Costa Gomes conn->pending_sec_level != BT_SECURITY_HIGH && 1175e9bf2bf0SVinicius Costa Gomes !(conn->auth_type & 0x01)) 1176392599b9SJohan Hedberg return 0; 1177392599b9SJohan Hedberg 1178392599b9SJohan Hedberg return 1; 1179392599b9SJohan Hedberg } 1180392599b9SJohan Hedberg 1181a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 11821da177e4SLinus Torvalds { 1183127178d2SJohan Hedberg struct hci_cp_remote_name_req *cp; 1184127178d2SJohan Hedberg struct hci_conn *conn; 1185127178d2SJohan Hedberg 1186a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1187127178d2SJohan Hedberg 1188127178d2SJohan Hedberg /* If successful wait for the name req complete event before 1189127178d2SJohan Hedberg * checking for the need to do authentication */ 1190127178d2SJohan Hedberg if (!status) 1191127178d2SJohan Hedberg return; 1192127178d2SJohan Hedberg 1193127178d2SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); 1194127178d2SJohan Hedberg if (!cp) 1195127178d2SJohan Hedberg return; 1196127178d2SJohan Hedberg 1197127178d2SJohan Hedberg hci_dev_lock(hdev); 1198127178d2SJohan Hedberg 1199127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 120079c6c70cSJohan Hedberg if (!conn) 120179c6c70cSJohan Hedberg goto unlock; 120279c6c70cSJohan Hedberg 120379c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 120479c6c70cSJohan Hedberg goto unlock; 120579c6c70cSJohan Hedberg 120679c6c70cSJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { 1207127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1208127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1209127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1210127178d2SJohan Hedberg } 1211127178d2SJohan Hedberg 121279c6c70cSJohan Hedberg unlock: 1213127178d2SJohan Hedberg hci_dev_unlock(hdev); 1214a9de9248SMarcel Holtmann } 12151da177e4SLinus Torvalds 1216769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 1217769be974SMarcel Holtmann { 1218769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 1219769be974SMarcel Holtmann struct hci_conn *conn; 1220769be974SMarcel Holtmann 1221769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1222769be974SMarcel Holtmann 1223769be974SMarcel Holtmann if (!status) 1224769be974SMarcel Holtmann return; 1225769be974SMarcel Holtmann 1226769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 1227769be974SMarcel Holtmann if (!cp) 1228769be974SMarcel Holtmann return; 1229769be974SMarcel Holtmann 1230769be974SMarcel Holtmann hci_dev_lock(hdev); 1231769be974SMarcel Holtmann 1232769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1233769be974SMarcel Holtmann if (conn) { 1234769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1235769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1236769be974SMarcel Holtmann hci_conn_put(conn); 1237769be974SMarcel Holtmann } 1238769be974SMarcel Holtmann } 1239769be974SMarcel Holtmann 1240769be974SMarcel Holtmann hci_dev_unlock(hdev); 1241769be974SMarcel Holtmann } 1242769be974SMarcel Holtmann 1243769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 1244769be974SMarcel Holtmann { 1245769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features *cp; 1246769be974SMarcel Holtmann struct hci_conn *conn; 1247769be974SMarcel Holtmann 1248769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1249769be974SMarcel Holtmann 1250769be974SMarcel Holtmann if (!status) 1251769be974SMarcel Holtmann return; 1252769be974SMarcel Holtmann 1253769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 1254769be974SMarcel Holtmann if (!cp) 1255769be974SMarcel Holtmann return; 1256769be974SMarcel Holtmann 1257769be974SMarcel Holtmann hci_dev_lock(hdev); 1258769be974SMarcel Holtmann 1259769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1260769be974SMarcel Holtmann if (conn) { 1261769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1262769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1263769be974SMarcel Holtmann hci_conn_put(conn); 1264769be974SMarcel Holtmann } 1265769be974SMarcel Holtmann } 1266769be974SMarcel Holtmann 1267769be974SMarcel Holtmann hci_dev_unlock(hdev); 1268769be974SMarcel Holtmann } 1269769be974SMarcel Holtmann 1270a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 1271a9de9248SMarcel Holtmann { 1272b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 1273b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 1274b6a0dc82SMarcel Holtmann __u16 handle; 1275b6a0dc82SMarcel Holtmann 1276a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1277b6a0dc82SMarcel Holtmann 1278b6a0dc82SMarcel Holtmann if (!status) 1279b6a0dc82SMarcel Holtmann return; 1280b6a0dc82SMarcel Holtmann 1281b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 1282b6a0dc82SMarcel Holtmann if (!cp) 1283b6a0dc82SMarcel Holtmann return; 1284b6a0dc82SMarcel Holtmann 1285b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 1286b6a0dc82SMarcel Holtmann 1287b6a0dc82SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 1288b6a0dc82SMarcel Holtmann 1289b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 1290b6a0dc82SMarcel Holtmann 1291b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 12925a08ecceSAndrei Emeltchenko if (acl) { 12935a08ecceSAndrei Emeltchenko sco = acl->link; 12945a08ecceSAndrei Emeltchenko if (sco) { 1295b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 1296b6a0dc82SMarcel Holtmann 1297b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(sco, status); 1298b6a0dc82SMarcel Holtmann hci_conn_del(sco); 1299b6a0dc82SMarcel Holtmann } 13005a08ecceSAndrei Emeltchenko } 1301b6a0dc82SMarcel Holtmann 1302b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 1303a9de9248SMarcel Holtmann } 1304a9de9248SMarcel Holtmann 1305a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 1306a9de9248SMarcel Holtmann { 1307a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 130804837f64SMarcel Holtmann struct hci_conn *conn; 130904837f64SMarcel Holtmann 1310a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1311a9de9248SMarcel Holtmann 1312a9de9248SMarcel Holtmann if (!status) 1313a9de9248SMarcel Holtmann return; 1314a9de9248SMarcel Holtmann 1315a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 131604837f64SMarcel Holtmann if (!cp) 1317a9de9248SMarcel Holtmann return; 131804837f64SMarcel Holtmann 131904837f64SMarcel Holtmann hci_dev_lock(hdev); 132004837f64SMarcel Holtmann 132104837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1322e73439d8SMarcel Holtmann if (conn) { 132304837f64SMarcel Holtmann clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); 132404837f64SMarcel Holtmann 1325e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 1326e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1327e73439d8SMarcel Holtmann } 1328e73439d8SMarcel Holtmann 132904837f64SMarcel Holtmann hci_dev_unlock(hdev); 133004837f64SMarcel Holtmann } 133104837f64SMarcel Holtmann 1332a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 1333a9de9248SMarcel Holtmann { 1334a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 133504837f64SMarcel Holtmann struct hci_conn *conn; 133604837f64SMarcel Holtmann 1337a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1338a9de9248SMarcel Holtmann 1339a9de9248SMarcel Holtmann if (!status) 1340a9de9248SMarcel Holtmann return; 1341a9de9248SMarcel Holtmann 1342a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 134304837f64SMarcel Holtmann if (!cp) 1344a9de9248SMarcel Holtmann return; 134504837f64SMarcel Holtmann 134604837f64SMarcel Holtmann hci_dev_lock(hdev); 134704837f64SMarcel Holtmann 134804837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1349e73439d8SMarcel Holtmann if (conn) { 135004837f64SMarcel Holtmann clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); 135104837f64SMarcel Holtmann 1352e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 1353e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1354e73439d8SMarcel Holtmann } 1355e73439d8SMarcel Holtmann 135604837f64SMarcel Holtmann hci_dev_unlock(hdev); 135704837f64SMarcel Holtmann } 135804837f64SMarcel Holtmann 1359fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) 1360fcd89c09SVille Tervo { 1361fcd89c09SVille Tervo struct hci_cp_le_create_conn *cp; 1362fcd89c09SVille Tervo struct hci_conn *conn; 1363fcd89c09SVille Tervo 1364fcd89c09SVille Tervo BT_DBG("%s status 0x%x", hdev->name, status); 1365fcd89c09SVille Tervo 1366fcd89c09SVille Tervo cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN); 1367fcd89c09SVille Tervo if (!cp) 1368fcd89c09SVille Tervo return; 1369fcd89c09SVille Tervo 1370fcd89c09SVille Tervo hci_dev_lock(hdev); 1371fcd89c09SVille Tervo 1372fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr); 1373fcd89c09SVille Tervo 1374fcd89c09SVille Tervo BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr), 1375fcd89c09SVille Tervo conn); 1376fcd89c09SVille Tervo 1377fcd89c09SVille Tervo if (status) { 1378fcd89c09SVille Tervo if (conn && conn->state == BT_CONNECT) { 1379fcd89c09SVille Tervo conn->state = BT_CLOSED; 1380fcd89c09SVille Tervo hci_proto_connect_cfm(conn, status); 1381fcd89c09SVille Tervo hci_conn_del(conn); 1382fcd89c09SVille Tervo } 1383fcd89c09SVille Tervo } else { 1384fcd89c09SVille Tervo if (!conn) { 1385fcd89c09SVille Tervo conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr); 138629b7988aSAndre Guedes if (conn) { 138729b7988aSAndre Guedes conn->dst_type = cp->peer_addr_type; 1388fcd89c09SVille Tervo conn->out = 1; 138929b7988aSAndre Guedes } else { 1390fcd89c09SVille Tervo BT_ERR("No memory for new connection"); 1391fcd89c09SVille Tervo } 1392fcd89c09SVille Tervo } 139329b7988aSAndre Guedes } 1394fcd89c09SVille Tervo 1395fcd89c09SVille Tervo hci_dev_unlock(hdev); 1396fcd89c09SVille Tervo } 1397fcd89c09SVille Tervo 1398a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) 1399a7a595f6SVinicius Costa Gomes { 1400a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, status); 1401a7a595f6SVinicius Costa Gomes } 1402a7a595f6SVinicius Costa Gomes 14031da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 14041da177e4SLinus Torvalds { 14051da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 14061da177e4SLinus Torvalds 14071da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, status); 14081da177e4SLinus Torvalds 140923bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 14106bd57416SMarcel Holtmann 1411a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 141289352e7dSAndre Guedes 141389352e7dSAndre Guedes if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) 141489352e7dSAndre Guedes return; 141589352e7dSAndre Guedes 141656e5cb86SJohan Hedberg hci_dev_lock(hdev); 1417744cf19eSJohan Hedberg mgmt_discovering(hdev, 0); 141856e5cb86SJohan Hedberg hci_dev_unlock(hdev); 14191da177e4SLinus Torvalds } 14201da177e4SLinus Torvalds 14211da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 14221da177e4SLinus Torvalds { 142345bb4bf0SMarcel Holtmann struct inquiry_data data; 1424a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 14251da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 14261da177e4SLinus Torvalds 14271da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 14281da177e4SLinus Torvalds 142945bb4bf0SMarcel Holtmann if (!num_rsp) 143045bb4bf0SMarcel Holtmann return; 143145bb4bf0SMarcel Holtmann 14321da177e4SLinus Torvalds hci_dev_lock(hdev); 143345bb4bf0SMarcel Holtmann 1434e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 14351da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 14361da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 14371da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 14381da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 14391da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 14401da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 14411da177e4SLinus Torvalds data.rssi = 0x00; 144241a96212SMarcel Holtmann data.ssp_mode = 0x00; 14431da177e4SLinus Torvalds hci_inquiry_cache_update(hdev, &data); 144448264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 14454c659c39SJohan Hedberg info->dev_class, 0, NULL); 14461da177e4SLinus Torvalds } 144745bb4bf0SMarcel Holtmann 14481da177e4SLinus Torvalds hci_dev_unlock(hdev); 14491da177e4SLinus Torvalds } 14501da177e4SLinus Torvalds 1451a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 14521da177e4SLinus Torvalds { 1453a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 1454a9de9248SMarcel Holtmann struct hci_conn *conn; 14551da177e4SLinus Torvalds 1456a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 145745bb4bf0SMarcel Holtmann 14581da177e4SLinus Torvalds hci_dev_lock(hdev); 145945bb4bf0SMarcel Holtmann 1460a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 14619499237aSMarcel Holtmann if (!conn) { 14629499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 14639499237aSMarcel Holtmann goto unlock; 14649499237aSMarcel Holtmann 14659499237aSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 1466a9de9248SMarcel Holtmann if (!conn) 1467a9de9248SMarcel Holtmann goto unlock; 146845bb4bf0SMarcel Holtmann 14699499237aSMarcel Holtmann conn->type = SCO_LINK; 14709499237aSMarcel Holtmann } 14719499237aSMarcel Holtmann 1472a9de9248SMarcel Holtmann if (!ev->status) { 1473a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 1474769be974SMarcel Holtmann 1475769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 1476769be974SMarcel Holtmann conn->state = BT_CONFIG; 1477769be974SMarcel Holtmann hci_conn_hold(conn); 1478052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 147948264f06SJohan Hedberg mgmt_connected(hdev, &ev->bdaddr, conn->type, 148048264f06SJohan Hedberg conn->dst_type); 1481769be974SMarcel Holtmann } else 1482a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 1483a9de9248SMarcel Holtmann 14849eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 14857d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 14867d0db0a3SMarcel Holtmann 1487a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 1488a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1489a9de9248SMarcel Holtmann 1490a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 1491a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1492a9de9248SMarcel Holtmann 1493a9de9248SMarcel Holtmann /* Get remote features */ 1494a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 1495a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 1496a9de9248SMarcel Holtmann cp.handle = ev->handle; 1497769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 1498769be974SMarcel Holtmann sizeof(cp), &cp); 149945bb4bf0SMarcel Holtmann } 1500a9de9248SMarcel Holtmann 1501a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 1502a8746417SMarcel Holtmann if (!conn->out && hdev->hci_ver < 3) { 1503a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 1504a9de9248SMarcel Holtmann cp.handle = ev->handle; 1505a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1506a8746417SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, 1507a8746417SMarcel Holtmann sizeof(cp), &cp); 1508a9de9248SMarcel Holtmann } 150917d5c04cSJohan Hedberg } else { 1510a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 151117d5c04cSJohan Hedberg if (conn->type == ACL_LINK) 1512744cf19eSJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 151348264f06SJohan Hedberg conn->dst_type, ev->status); 151417d5c04cSJohan Hedberg } 151545bb4bf0SMarcel Holtmann 1516e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 1517e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 151845bb4bf0SMarcel Holtmann 1519769be974SMarcel Holtmann if (ev->status) { 1520a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1521a9de9248SMarcel Holtmann hci_conn_del(conn); 1522c89b6e6bSMarcel Holtmann } else if (ev->link_type != ACL_LINK) 1523c89b6e6bSMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1524a9de9248SMarcel Holtmann 1525a9de9248SMarcel Holtmann unlock: 15261da177e4SLinus Torvalds hci_dev_unlock(hdev); 1527a9de9248SMarcel Holtmann 1528a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 15291da177e4SLinus Torvalds } 15301da177e4SLinus Torvalds 15311da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 15321da177e4SLinus Torvalds { 1533a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 15341da177e4SLinus Torvalds int mask = hdev->link_mode; 15351da177e4SLinus Torvalds 1536a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s type 0x%x", hdev->name, 15371da177e4SLinus Torvalds batostr(&ev->bdaddr), ev->link_type); 15381da177e4SLinus Torvalds 15391da177e4SLinus Torvalds mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); 15401da177e4SLinus Torvalds 1541138d22efSSzymon Janc if ((mask & HCI_LM_ACCEPT) && 1542138d22efSSzymon Janc !hci_blacklist_lookup(hdev, &ev->bdaddr)) { 15431da177e4SLinus Torvalds /* Connection accepted */ 1544c7bdd502SMarcel Holtmann struct inquiry_entry *ie; 15451da177e4SLinus Torvalds struct hci_conn *conn; 15461da177e4SLinus Torvalds 15471da177e4SLinus Torvalds hci_dev_lock(hdev); 1548b6a0dc82SMarcel Holtmann 1549cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 1550cc11b9c1SAndrei Emeltchenko if (ie) 1551c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 1552c7bdd502SMarcel Holtmann 15531da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 15541da177e4SLinus Torvalds if (!conn) { 1555cc11b9c1SAndrei Emeltchenko conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); 1556cc11b9c1SAndrei Emeltchenko if (!conn) { 1557893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 15581da177e4SLinus Torvalds hci_dev_unlock(hdev); 15591da177e4SLinus Torvalds return; 15601da177e4SLinus Torvalds } 15611da177e4SLinus Torvalds } 1562b6a0dc82SMarcel Holtmann 15631da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 15641da177e4SLinus Torvalds conn->state = BT_CONNECT; 1565b6a0dc82SMarcel Holtmann 15661da177e4SLinus Torvalds hci_dev_unlock(hdev); 15671da177e4SLinus Torvalds 1568b6a0dc82SMarcel Holtmann if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) { 1569b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 1570b6a0dc82SMarcel Holtmann 15711da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 15721da177e4SLinus Torvalds 15731da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 15741da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 15751da177e4SLinus Torvalds else 15761da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 15771da177e4SLinus Torvalds 1578b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, 1579b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1580b6a0dc82SMarcel Holtmann } else { 1581b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 1582b6a0dc82SMarcel Holtmann 1583b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 1584a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1585b6a0dc82SMarcel Holtmann 1586b6a0dc82SMarcel Holtmann cp.tx_bandwidth = cpu_to_le32(0x00001f40); 1587b6a0dc82SMarcel Holtmann cp.rx_bandwidth = cpu_to_le32(0x00001f40); 1588b6a0dc82SMarcel Holtmann cp.max_latency = cpu_to_le16(0xffff); 1589b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 1590b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 1591b6a0dc82SMarcel Holtmann 1592b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 1593b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1594b6a0dc82SMarcel Holtmann } 15951da177e4SLinus Torvalds } else { 15961da177e4SLinus Torvalds /* Connection rejected */ 15971da177e4SLinus Torvalds struct hci_cp_reject_conn_req cp; 15981da177e4SLinus Torvalds 15991da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 16009f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_REJ_BAD_ADDR; 1601a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 16021da177e4SLinus Torvalds } 16031da177e4SLinus Torvalds } 16041da177e4SLinus Torvalds 16051da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 16061da177e4SLinus Torvalds { 1607a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 160804837f64SMarcel Holtmann struct hci_conn *conn; 16091da177e4SLinus Torvalds 16101da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 16111da177e4SLinus Torvalds 16121da177e4SLinus Torvalds hci_dev_lock(hdev); 16131da177e4SLinus Torvalds 161404837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1615f7520543SJohan Hedberg if (!conn) 1616f7520543SJohan Hedberg goto unlock; 1617f7520543SJohan Hedberg 161837d9ef76SJohan Hedberg if (ev->status == 0) 16191da177e4SLinus Torvalds conn->state = BT_CLOSED; 16207d0db0a3SMarcel Holtmann 162137d9ef76SJohan Hedberg if (conn->type == ACL_LINK || conn->type == LE_LINK) { 162237d9ef76SJohan Hedberg if (ev->status != 0) 162337d9ef76SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, ev->status); 162437d9ef76SJohan Hedberg else 162548264f06SJohan Hedberg mgmt_disconnected(hdev, &conn->dst, conn->type, 162648264f06SJohan Hedberg conn->dst_type); 162737d9ef76SJohan Hedberg } 1628f7520543SJohan Hedberg 162937d9ef76SJohan Hedberg if (ev->status == 0) { 16302950f21aSMarcel Holtmann hci_proto_disconn_cfm(conn, ev->reason); 16311da177e4SLinus Torvalds hci_conn_del(conn); 163237d9ef76SJohan Hedberg } 16331da177e4SLinus Torvalds 1634f7520543SJohan Hedberg unlock: 16351da177e4SLinus Torvalds hci_dev_unlock(hdev); 16361da177e4SLinus Torvalds } 16371da177e4SLinus Torvalds 1638a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1639a9de9248SMarcel Holtmann { 1640a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 1641a9de9248SMarcel Holtmann struct hci_conn *conn; 1642a9de9248SMarcel Holtmann 1643a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1644a9de9248SMarcel Holtmann 1645a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1646a9de9248SMarcel Holtmann 1647a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1648d7556e20SWaldemar Rymarkiewicz if (!conn) 1649d7556e20SWaldemar Rymarkiewicz goto unlock; 1650d7556e20SWaldemar Rymarkiewicz 1651765c2a96SJohan Hedberg if (!ev->status) { 165219f8def0SWaldemar Rymarkiewicz if (!(conn->ssp_mode > 0 && hdev->ssp_mode > 0) && 1653d7556e20SWaldemar Rymarkiewicz test_bit(HCI_CONN_REAUTH_PEND, &conn->pend)) { 1654d7556e20SWaldemar Rymarkiewicz BT_INFO("re-auth of legacy device is not possible."); 165519f8def0SWaldemar Rymarkiewicz } else { 1656a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1657765c2a96SJohan Hedberg conn->sec_level = conn->pending_sec_level; 165819f8def0SWaldemar Rymarkiewicz } 16592a611692SJohan Hedberg } else { 1660744cf19eSJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, ev->status); 16612a611692SJohan Hedberg } 1662a9de9248SMarcel Holtmann 1663a9de9248SMarcel Holtmann clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); 166419f8def0SWaldemar Rymarkiewicz clear_bit(HCI_CONN_REAUTH_PEND, &conn->pend); 1665a9de9248SMarcel Holtmann 1666f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1667d7556e20SWaldemar Rymarkiewicz if (!ev->status && hdev->ssp_mode > 0 && conn->ssp_mode > 0) { 1668f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1669f8558555SMarcel Holtmann cp.handle = ev->handle; 1670f8558555SMarcel Holtmann cp.encrypt = 0x01; 1671d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1672d7556e20SWaldemar Rymarkiewicz &cp); 1673f8558555SMarcel Holtmann } else { 1674f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1675f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1676f8558555SMarcel Holtmann hci_conn_put(conn); 1677f8558555SMarcel Holtmann } 1678052b30b0SMarcel Holtmann } else { 1679a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 1680a9de9248SMarcel Holtmann 1681052b30b0SMarcel Holtmann hci_conn_hold(conn); 1682052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1683052b30b0SMarcel Holtmann hci_conn_put(conn); 1684052b30b0SMarcel Holtmann } 1685052b30b0SMarcel Holtmann 1686a9de9248SMarcel Holtmann if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) { 1687a9de9248SMarcel Holtmann if (!ev->status) { 1688a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1689f8558555SMarcel Holtmann cp.handle = ev->handle; 1690f8558555SMarcel Holtmann cp.encrypt = 0x01; 1691d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1692d7556e20SWaldemar Rymarkiewicz &cp); 1693a9de9248SMarcel Holtmann } else { 1694a9de9248SMarcel Holtmann clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); 1695a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 1696a9de9248SMarcel Holtmann } 1697a9de9248SMarcel Holtmann } 1698a9de9248SMarcel Holtmann 1699d7556e20SWaldemar Rymarkiewicz unlock: 1700a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1701a9de9248SMarcel Holtmann } 1702a9de9248SMarcel Holtmann 1703a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 1704a9de9248SMarcel Holtmann { 1705127178d2SJohan Hedberg struct hci_ev_remote_name *ev = (void *) skb->data; 1706127178d2SJohan Hedberg struct hci_conn *conn; 1707127178d2SJohan Hedberg 1708a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1709a9de9248SMarcel Holtmann 1710a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 1711127178d2SJohan Hedberg 1712127178d2SJohan Hedberg hci_dev_lock(hdev); 1713127178d2SJohan Hedberg 1714a88a9652SJohan Hedberg if (ev->status == 0 && test_bit(HCI_MGMT, &hdev->flags)) 1715744cf19eSJohan Hedberg mgmt_remote_name(hdev, &ev->bdaddr, ev->name); 1716a88a9652SJohan Hedberg 1717127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 171879c6c70cSJohan Hedberg if (!conn) 171979c6c70cSJohan Hedberg goto unlock; 172079c6c70cSJohan Hedberg 172179c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 172279c6c70cSJohan Hedberg goto unlock; 172379c6c70cSJohan Hedberg 172479c6c70cSJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { 1725127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1726127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1727127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1728127178d2SJohan Hedberg } 1729127178d2SJohan Hedberg 173079c6c70cSJohan Hedberg unlock: 1731127178d2SJohan Hedberg hci_dev_unlock(hdev); 1732a9de9248SMarcel Holtmann } 1733a9de9248SMarcel Holtmann 1734a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 1735a9de9248SMarcel Holtmann { 1736a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 1737a9de9248SMarcel Holtmann struct hci_conn *conn; 1738a9de9248SMarcel Holtmann 1739a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1740a9de9248SMarcel Holtmann 1741a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1742a9de9248SMarcel Holtmann 1743a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1744a9de9248SMarcel Holtmann if (conn) { 1745a9de9248SMarcel Holtmann if (!ev->status) { 1746ae293196SMarcel Holtmann if (ev->encrypt) { 1747ae293196SMarcel Holtmann /* Encryption implies authentication */ 1748ae293196SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1749a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1750da85e5e5SVinicius Costa Gomes conn->sec_level = conn->pending_sec_level; 1751ae293196SMarcel Holtmann } else 1752a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_ENCRYPT; 1753a9de9248SMarcel Holtmann } 1754a9de9248SMarcel Holtmann 1755a9de9248SMarcel Holtmann clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); 1756a9de9248SMarcel Holtmann 1757f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1758f8558555SMarcel Holtmann if (!ev->status) 1759f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1760f8558555SMarcel Holtmann 1761f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1762f8558555SMarcel Holtmann hci_conn_put(conn); 1763f8558555SMarcel Holtmann } else 1764a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 1765a9de9248SMarcel Holtmann } 1766a9de9248SMarcel Holtmann 1767a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1768a9de9248SMarcel Holtmann } 1769a9de9248SMarcel Holtmann 1770a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1771a9de9248SMarcel Holtmann { 1772a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 1773a9de9248SMarcel Holtmann struct hci_conn *conn; 1774a9de9248SMarcel Holtmann 1775a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1776a9de9248SMarcel Holtmann 1777a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1778a9de9248SMarcel Holtmann 1779a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1780a9de9248SMarcel Holtmann if (conn) { 1781a9de9248SMarcel Holtmann if (!ev->status) 1782a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_SECURE; 1783a9de9248SMarcel Holtmann 1784a9de9248SMarcel Holtmann clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); 1785a9de9248SMarcel Holtmann 1786a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 1787a9de9248SMarcel Holtmann } 1788a9de9248SMarcel Holtmann 1789a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1790a9de9248SMarcel Holtmann } 1791a9de9248SMarcel Holtmann 1792a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 1793a9de9248SMarcel Holtmann { 1794a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 1795a9de9248SMarcel Holtmann struct hci_conn *conn; 1796a9de9248SMarcel Holtmann 1797a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1798a9de9248SMarcel Holtmann 1799a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1800a9de9248SMarcel Holtmann 1801a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1802ccd556feSJohan Hedberg if (!conn) 1803ccd556feSJohan Hedberg goto unlock; 1804ccd556feSJohan Hedberg 1805769be974SMarcel Holtmann if (!ev->status) 1806a9de9248SMarcel Holtmann memcpy(conn->features, ev->features, 8); 1807a9de9248SMarcel Holtmann 1808ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 1809ccd556feSJohan Hedberg goto unlock; 1810ccd556feSJohan Hedberg 1811ccd556feSJohan Hedberg if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { 1812769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 1813769be974SMarcel Holtmann cp.handle = ev->handle; 1814769be974SMarcel Holtmann cp.page = 0x01; 1815ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 1816769be974SMarcel Holtmann sizeof(cp), &cp); 1817392599b9SJohan Hedberg goto unlock; 1818392599b9SJohan Hedberg } 1819392599b9SJohan Hedberg 1820127178d2SJohan Hedberg if (!ev->status) { 1821127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 1822127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 1823127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 1824127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 1825127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 1826127178d2SJohan Hedberg } 1827392599b9SJohan Hedberg 1828127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 1829769be974SMarcel Holtmann conn->state = BT_CONNECTED; 1830769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1831769be974SMarcel Holtmann hci_conn_put(conn); 1832769be974SMarcel Holtmann } 1833769be974SMarcel Holtmann 1834ccd556feSJohan Hedberg unlock: 1835a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1836a9de9248SMarcel Holtmann } 1837a9de9248SMarcel Holtmann 1838a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) 1839a9de9248SMarcel Holtmann { 1840a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1841a9de9248SMarcel Holtmann } 1842a9de9248SMarcel Holtmann 1843a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1844a9de9248SMarcel Holtmann { 1845a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1846a9de9248SMarcel Holtmann } 1847a9de9248SMarcel Holtmann 1848a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1849a9de9248SMarcel Holtmann { 1850a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 1851a9de9248SMarcel Holtmann __u16 opcode; 1852a9de9248SMarcel Holtmann 1853a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 1854a9de9248SMarcel Holtmann 1855a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 1856a9de9248SMarcel Holtmann 1857a9de9248SMarcel Holtmann switch (opcode) { 1858a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 1859a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 1860a9de9248SMarcel Holtmann break; 1861a9de9248SMarcel Holtmann 1862a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 1863a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 1864a9de9248SMarcel Holtmann break; 1865a9de9248SMarcel Holtmann 1866a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 1867a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 1868a9de9248SMarcel Holtmann break; 1869a9de9248SMarcel Holtmann 1870a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 1871a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 1872a9de9248SMarcel Holtmann break; 1873a9de9248SMarcel Holtmann 1874e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 1875e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 1876e4e8e37cSMarcel Holtmann break; 1877e4e8e37cSMarcel Holtmann 1878a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 1879a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 1880a9de9248SMarcel Holtmann break; 1881a9de9248SMarcel Holtmann 1882e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 1883e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 1884e4e8e37cSMarcel Holtmann break; 1885e4e8e37cSMarcel Holtmann 1886e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 1887e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 1888e4e8e37cSMarcel Holtmann break; 1889e4e8e37cSMarcel Holtmann 1890a9de9248SMarcel Holtmann case HCI_OP_RESET: 1891a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 1892a9de9248SMarcel Holtmann break; 1893a9de9248SMarcel Holtmann 1894a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 1895a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 1896a9de9248SMarcel Holtmann break; 1897a9de9248SMarcel Holtmann 1898a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 1899a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 1900a9de9248SMarcel Holtmann break; 1901a9de9248SMarcel Holtmann 1902a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 1903a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 1904a9de9248SMarcel Holtmann break; 1905a9de9248SMarcel Holtmann 1906a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 1907a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 1908a9de9248SMarcel Holtmann break; 1909a9de9248SMarcel Holtmann 1910a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 1911a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 1912a9de9248SMarcel Holtmann break; 1913a9de9248SMarcel Holtmann 1914a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 1915a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 1916a9de9248SMarcel Holtmann break; 1917a9de9248SMarcel Holtmann 1918a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 1919a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 1920a9de9248SMarcel Holtmann break; 1921a9de9248SMarcel Holtmann 1922a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 1923a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 1924a9de9248SMarcel Holtmann break; 1925a9de9248SMarcel Holtmann 1926a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 1927a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 1928a9de9248SMarcel Holtmann break; 1929a9de9248SMarcel Holtmann 1930a9de9248SMarcel Holtmann case HCI_OP_HOST_BUFFER_SIZE: 1931a9de9248SMarcel Holtmann hci_cc_host_buffer_size(hdev, skb); 1932a9de9248SMarcel Holtmann break; 1933a9de9248SMarcel Holtmann 1934333140b5SMarcel Holtmann case HCI_OP_READ_SSP_MODE: 1935333140b5SMarcel Holtmann hci_cc_read_ssp_mode(hdev, skb); 1936333140b5SMarcel Holtmann break; 1937333140b5SMarcel Holtmann 1938333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 1939333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 1940333140b5SMarcel Holtmann break; 1941333140b5SMarcel Holtmann 1942a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 1943a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 1944a9de9248SMarcel Holtmann break; 1945a9de9248SMarcel Holtmann 1946a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 1947a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 1948a9de9248SMarcel Holtmann break; 1949a9de9248SMarcel Holtmann 1950a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 1951a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 1952a9de9248SMarcel Holtmann break; 1953a9de9248SMarcel Holtmann 1954971e3a4bSAndre Guedes case HCI_OP_READ_LOCAL_EXT_FEATURES: 1955971e3a4bSAndre Guedes hci_cc_read_local_ext_features(hdev, skb); 1956971e3a4bSAndre Guedes break; 1957971e3a4bSAndre Guedes 1958a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 1959a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 1960a9de9248SMarcel Holtmann break; 1961a9de9248SMarcel Holtmann 1962a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 1963a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 1964a9de9248SMarcel Holtmann break; 1965a9de9248SMarcel Holtmann 196623bb5763SJohan Hedberg case HCI_OP_WRITE_CA_TIMEOUT: 196723bb5763SJohan Hedberg hci_cc_write_ca_timeout(hdev, skb); 196823bb5763SJohan Hedberg break; 196923bb5763SJohan Hedberg 1970928abaa7SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_INFO: 1971928abaa7SAndrei Emeltchenko hci_cc_read_local_amp_info(hdev, skb); 1972928abaa7SAndrei Emeltchenko break; 1973928abaa7SAndrei Emeltchenko 1974b0916ea0SJohan Hedberg case HCI_OP_DELETE_STORED_LINK_KEY: 1975b0916ea0SJohan Hedberg hci_cc_delete_stored_link_key(hdev, skb); 1976b0916ea0SJohan Hedberg break; 1977b0916ea0SJohan Hedberg 1978d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_MASK: 1979d5859e22SJohan Hedberg hci_cc_set_event_mask(hdev, skb); 1980d5859e22SJohan Hedberg break; 1981d5859e22SJohan Hedberg 1982d5859e22SJohan Hedberg case HCI_OP_WRITE_INQUIRY_MODE: 1983d5859e22SJohan Hedberg hci_cc_write_inquiry_mode(hdev, skb); 1984d5859e22SJohan Hedberg break; 1985d5859e22SJohan Hedberg 1986d5859e22SJohan Hedberg case HCI_OP_READ_INQ_RSP_TX_POWER: 1987d5859e22SJohan Hedberg hci_cc_read_inq_rsp_tx_power(hdev, skb); 1988d5859e22SJohan Hedberg break; 1989d5859e22SJohan Hedberg 1990d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_FLT: 1991d5859e22SJohan Hedberg hci_cc_set_event_flt(hdev, skb); 1992d5859e22SJohan Hedberg break; 1993d5859e22SJohan Hedberg 1994980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_REPLY: 1995980e1a53SJohan Hedberg hci_cc_pin_code_reply(hdev, skb); 1996980e1a53SJohan Hedberg break; 1997980e1a53SJohan Hedberg 1998980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_NEG_REPLY: 1999980e1a53SJohan Hedberg hci_cc_pin_code_neg_reply(hdev, skb); 2000980e1a53SJohan Hedberg break; 2001980e1a53SJohan Hedberg 2002c35938b2SSzymon Janc case HCI_OP_READ_LOCAL_OOB_DATA: 2003c35938b2SSzymon Janc hci_cc_read_local_oob_data_reply(hdev, skb); 2004c35938b2SSzymon Janc break; 2005c35938b2SSzymon Janc 20066ed58ec5SVille Tervo case HCI_OP_LE_READ_BUFFER_SIZE: 20076ed58ec5SVille Tervo hci_cc_le_read_buffer_size(hdev, skb); 20086ed58ec5SVille Tervo break; 20096ed58ec5SVille Tervo 2010a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_REPLY: 2011a5c29683SJohan Hedberg hci_cc_user_confirm_reply(hdev, skb); 2012a5c29683SJohan Hedberg break; 2013a5c29683SJohan Hedberg 2014a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_NEG_REPLY: 2015a5c29683SJohan Hedberg hci_cc_user_confirm_neg_reply(hdev, skb); 2016a5c29683SJohan Hedberg break; 2017a5c29683SJohan Hedberg 2018eb9d91f5SAndre Guedes case HCI_OP_LE_SET_SCAN_ENABLE: 2019eb9d91f5SAndre Guedes hci_cc_le_set_scan_enable(hdev, skb); 2020eb9d91f5SAndre Guedes break; 2021eb9d91f5SAndre Guedes 2022a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_REPLY: 2023a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_reply(hdev, skb); 2024a7a595f6SVinicius Costa Gomes break; 2025a7a595f6SVinicius Costa Gomes 2026a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_NEG_REPLY: 2027a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_neg_reply(hdev, skb); 2028a7a595f6SVinicius Costa Gomes break; 2029a7a595f6SVinicius Costa Gomes 2030f9b49306SAndre Guedes case HCI_OP_WRITE_LE_HOST_SUPPORTED: 2031f9b49306SAndre Guedes hci_cc_write_le_host_supported(hdev, skb); 2032f9b49306SAndre Guedes break; 2033f9b49306SAndre Guedes 2034a9de9248SMarcel Holtmann default: 2035a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 2036a9de9248SMarcel Holtmann break; 2037a9de9248SMarcel Holtmann } 2038a9de9248SMarcel Holtmann 20396bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 20406bd32326SVille Tervo del_timer(&hdev->cmd_timer); 20416bd32326SVille Tervo 2042a9de9248SMarcel Holtmann if (ev->ncmd) { 2043a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2044a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2045c78ae283SMarcel Holtmann tasklet_schedule(&hdev->cmd_task); 2046a9de9248SMarcel Holtmann } 2047a9de9248SMarcel Holtmann } 2048a9de9248SMarcel Holtmann 2049a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 2050a9de9248SMarcel Holtmann { 2051a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 2052a9de9248SMarcel Holtmann __u16 opcode; 2053a9de9248SMarcel Holtmann 2054a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2055a9de9248SMarcel Holtmann 2056a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2057a9de9248SMarcel Holtmann 2058a9de9248SMarcel Holtmann switch (opcode) { 2059a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 2060a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 2061a9de9248SMarcel Holtmann break; 2062a9de9248SMarcel Holtmann 2063a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 2064a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 2065a9de9248SMarcel Holtmann break; 2066a9de9248SMarcel Holtmann 2067a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 2068a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 2069a9de9248SMarcel Holtmann break; 2070a9de9248SMarcel Holtmann 2071f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 2072f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 2073f8558555SMarcel Holtmann break; 2074f8558555SMarcel Holtmann 2075f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 2076f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 2077f8558555SMarcel Holtmann break; 2078f8558555SMarcel Holtmann 2079a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 2080a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 2081a9de9248SMarcel Holtmann break; 2082a9de9248SMarcel Holtmann 2083769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 2084769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 2085769be974SMarcel Holtmann break; 2086769be974SMarcel Holtmann 2087769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 2088769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 2089769be974SMarcel Holtmann break; 2090769be974SMarcel Holtmann 2091a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 2092a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 2093a9de9248SMarcel Holtmann break; 2094a9de9248SMarcel Holtmann 2095a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 2096a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 2097a9de9248SMarcel Holtmann break; 2098a9de9248SMarcel Holtmann 2099a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 2100a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 2101a9de9248SMarcel Holtmann break; 2102a9de9248SMarcel Holtmann 21038962ee74SJohan Hedberg case HCI_OP_DISCONNECT: 21048962ee74SJohan Hedberg if (ev->status != 0) 210537d9ef76SJohan Hedberg mgmt_disconnect_failed(hdev, NULL, ev->status); 21068962ee74SJohan Hedberg break; 21078962ee74SJohan Hedberg 2108fcd89c09SVille Tervo case HCI_OP_LE_CREATE_CONN: 2109fcd89c09SVille Tervo hci_cs_le_create_conn(hdev, ev->status); 2110fcd89c09SVille Tervo break; 2111fcd89c09SVille Tervo 2112a7a595f6SVinicius Costa Gomes case HCI_OP_LE_START_ENC: 2113a7a595f6SVinicius Costa Gomes hci_cs_le_start_enc(hdev, ev->status); 2114a7a595f6SVinicius Costa Gomes break; 2115a7a595f6SVinicius Costa Gomes 2116a9de9248SMarcel Holtmann default: 2117a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 2118a9de9248SMarcel Holtmann break; 2119a9de9248SMarcel Holtmann } 2120a9de9248SMarcel Holtmann 21216bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 21226bd32326SVille Tervo del_timer(&hdev->cmd_timer); 21236bd32326SVille Tervo 212410572132SGustavo F. Padovan if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2125a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2126a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2127c78ae283SMarcel Holtmann tasklet_schedule(&hdev->cmd_task); 2128a9de9248SMarcel Holtmann } 2129a9de9248SMarcel Holtmann } 2130a9de9248SMarcel Holtmann 2131a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2132a9de9248SMarcel Holtmann { 2133a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 2134a9de9248SMarcel Holtmann struct hci_conn *conn; 2135a9de9248SMarcel Holtmann 2136a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2137a9de9248SMarcel Holtmann 2138a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2139a9de9248SMarcel Holtmann 2140a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2141a9de9248SMarcel Holtmann if (conn) { 2142a9de9248SMarcel Holtmann if (!ev->status) { 2143a9de9248SMarcel Holtmann if (ev->role) 2144a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_MASTER; 2145a9de9248SMarcel Holtmann else 2146a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_MASTER; 2147a9de9248SMarcel Holtmann } 2148a9de9248SMarcel Holtmann 2149a9de9248SMarcel Holtmann clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend); 2150a9de9248SMarcel Holtmann 2151a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 2152a9de9248SMarcel Holtmann } 2153a9de9248SMarcel Holtmann 2154a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2155a9de9248SMarcel Holtmann } 2156a9de9248SMarcel Holtmann 21571da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 21581da177e4SLinus Torvalds { 2159a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 21601ebb9252SMarcel Holtmann __le16 *ptr; 21611da177e4SLinus Torvalds int i; 21621da177e4SLinus Torvalds 21631da177e4SLinus Torvalds skb_pull(skb, sizeof(*ev)); 21641da177e4SLinus Torvalds 21651da177e4SLinus Torvalds BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 21661da177e4SLinus Torvalds 21671da177e4SLinus Torvalds if (skb->len < ev->num_hndl * 4) { 21681da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 21691da177e4SLinus Torvalds return; 21701da177e4SLinus Torvalds } 21711da177e4SLinus Torvalds 21721da177e4SLinus Torvalds tasklet_disable(&hdev->tx_task); 21731da177e4SLinus Torvalds 21741ebb9252SMarcel Holtmann for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) { 21751da177e4SLinus Torvalds struct hci_conn *conn; 21761da177e4SLinus Torvalds __u16 handle, count; 21771da177e4SLinus Torvalds 217883985319SHarvey Harrison handle = get_unaligned_le16(ptr++); 217983985319SHarvey Harrison count = get_unaligned_le16(ptr++); 21801da177e4SLinus Torvalds 21811da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 21821da177e4SLinus Torvalds if (conn) { 21831da177e4SLinus Torvalds conn->sent -= count; 21841da177e4SLinus Torvalds 21855b7f9909SMarcel Holtmann if (conn->type == ACL_LINK) { 218670f23020SAndrei Emeltchenko hdev->acl_cnt += count; 218770f23020SAndrei Emeltchenko if (hdev->acl_cnt > hdev->acl_pkts) 21881da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 21896ed58ec5SVille Tervo } else if (conn->type == LE_LINK) { 21906ed58ec5SVille Tervo if (hdev->le_pkts) { 21916ed58ec5SVille Tervo hdev->le_cnt += count; 21926ed58ec5SVille Tervo if (hdev->le_cnt > hdev->le_pkts) 21936ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 21946ed58ec5SVille Tervo } else { 21956ed58ec5SVille Tervo hdev->acl_cnt += count; 21966ed58ec5SVille Tervo if (hdev->acl_cnt > hdev->acl_pkts) 21976ed58ec5SVille Tervo hdev->acl_cnt = hdev->acl_pkts; 21986ed58ec5SVille Tervo } 21995b7f9909SMarcel Holtmann } else { 220070f23020SAndrei Emeltchenko hdev->sco_cnt += count; 220170f23020SAndrei Emeltchenko if (hdev->sco_cnt > hdev->sco_pkts) 22025b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 22031da177e4SLinus Torvalds } 22041da177e4SLinus Torvalds } 22051da177e4SLinus Torvalds } 2206a9de9248SMarcel Holtmann 2207c78ae283SMarcel Holtmann tasklet_schedule(&hdev->tx_task); 22081da177e4SLinus Torvalds 22091da177e4SLinus Torvalds tasklet_enable(&hdev->tx_task); 22101da177e4SLinus Torvalds } 22111da177e4SLinus Torvalds 221204837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 22131da177e4SLinus Torvalds { 2214a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 221504837f64SMarcel Holtmann struct hci_conn *conn; 22161da177e4SLinus Torvalds 22171da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 22181da177e4SLinus Torvalds 22191da177e4SLinus Torvalds hci_dev_lock(hdev); 22201da177e4SLinus Torvalds 222104837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 222204837f64SMarcel Holtmann if (conn) { 222304837f64SMarcel Holtmann conn->mode = ev->mode; 222404837f64SMarcel Holtmann conn->interval = __le16_to_cpu(ev->interval); 222504837f64SMarcel Holtmann 222604837f64SMarcel Holtmann if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) { 222704837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 222804837f64SMarcel Holtmann conn->power_save = 1; 222904837f64SMarcel Holtmann else 223004837f64SMarcel Holtmann conn->power_save = 0; 223104837f64SMarcel Holtmann } 2232e73439d8SMarcel Holtmann 2233e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 2234e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 223504837f64SMarcel Holtmann } 223604837f64SMarcel Holtmann 223704837f64SMarcel Holtmann hci_dev_unlock(hdev); 223804837f64SMarcel Holtmann } 223904837f64SMarcel Holtmann 22401da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 22411da177e4SLinus Torvalds { 2242052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 2243052b30b0SMarcel Holtmann struct hci_conn *conn; 2244052b30b0SMarcel Holtmann 2245a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2246052b30b0SMarcel Holtmann 2247052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2248052b30b0SMarcel Holtmann 2249052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2250b6f98044SWaldemar Rymarkiewicz if (!conn) 2251b6f98044SWaldemar Rymarkiewicz goto unlock; 2252b6f98044SWaldemar Rymarkiewicz 2253b6f98044SWaldemar Rymarkiewicz if (conn->state == BT_CONNECTED) { 2254052b30b0SMarcel Holtmann hci_conn_hold(conn); 2255052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 2256052b30b0SMarcel Holtmann hci_conn_put(conn); 2257052b30b0SMarcel Holtmann } 2258052b30b0SMarcel Holtmann 225903b555e1SJohan Hedberg if (!test_bit(HCI_PAIRABLE, &hdev->flags)) 226003b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 226103b555e1SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 2262582fbe9eSJohan Hedberg else if (test_bit(HCI_MGMT, &hdev->flags)) { 2263a770bb5aSWaldemar Rymarkiewicz u8 secure; 2264a770bb5aSWaldemar Rymarkiewicz 2265a770bb5aSWaldemar Rymarkiewicz if (conn->pending_sec_level == BT_SECURITY_HIGH) 2266a770bb5aSWaldemar Rymarkiewicz secure = 1; 2267a770bb5aSWaldemar Rymarkiewicz else 2268a770bb5aSWaldemar Rymarkiewicz secure = 0; 2269a770bb5aSWaldemar Rymarkiewicz 2270744cf19eSJohan Hedberg mgmt_pin_code_request(hdev, &ev->bdaddr, secure); 2271a770bb5aSWaldemar Rymarkiewicz } 2272980e1a53SJohan Hedberg 2273b6f98044SWaldemar Rymarkiewicz unlock: 2274052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 22751da177e4SLinus Torvalds } 22761da177e4SLinus Torvalds 22771da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 22781da177e4SLinus Torvalds { 227955ed8ca1SJohan Hedberg struct hci_ev_link_key_req *ev = (void *) skb->data; 228055ed8ca1SJohan Hedberg struct hci_cp_link_key_reply cp; 228155ed8ca1SJohan Hedberg struct hci_conn *conn; 228255ed8ca1SJohan Hedberg struct link_key *key; 228355ed8ca1SJohan Hedberg 2284a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 228555ed8ca1SJohan Hedberg 228655ed8ca1SJohan Hedberg if (!test_bit(HCI_LINK_KEYS, &hdev->flags)) 228755ed8ca1SJohan Hedberg return; 228855ed8ca1SJohan Hedberg 228955ed8ca1SJohan Hedberg hci_dev_lock(hdev); 229055ed8ca1SJohan Hedberg 229155ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, &ev->bdaddr); 229255ed8ca1SJohan Hedberg if (!key) { 229355ed8ca1SJohan Hedberg BT_DBG("%s link key not found for %s", hdev->name, 229455ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 229555ed8ca1SJohan Hedberg goto not_found; 229655ed8ca1SJohan Hedberg } 229755ed8ca1SJohan Hedberg 229855ed8ca1SJohan Hedberg BT_DBG("%s found key type %u for %s", hdev->name, key->type, 229955ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 230055ed8ca1SJohan Hedberg 2301b6020ba0SWaldemar Rymarkiewicz if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) && 2302b6020ba0SWaldemar Rymarkiewicz key->type == HCI_LK_DEBUG_COMBINATION) { 230355ed8ca1SJohan Hedberg BT_DBG("%s ignoring debug key", hdev->name); 230455ed8ca1SJohan Hedberg goto not_found; 230555ed8ca1SJohan Hedberg } 230655ed8ca1SJohan Hedberg 230755ed8ca1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 230860b83f57SWaldemar Rymarkiewicz if (conn) { 230960b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_UNAUTH_COMBINATION && 231060b83f57SWaldemar Rymarkiewicz conn->auth_type != 0xff && 231160b83f57SWaldemar Rymarkiewicz (conn->auth_type & 0x01)) { 231255ed8ca1SJohan Hedberg BT_DBG("%s ignoring unauthenticated key", hdev->name); 231355ed8ca1SJohan Hedberg goto not_found; 231455ed8ca1SJohan Hedberg } 231555ed8ca1SJohan Hedberg 231660b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && 231760b83f57SWaldemar Rymarkiewicz conn->pending_sec_level == BT_SECURITY_HIGH) { 231860b83f57SWaldemar Rymarkiewicz BT_DBG("%s ignoring key unauthenticated for high \ 231960b83f57SWaldemar Rymarkiewicz security", hdev->name); 232060b83f57SWaldemar Rymarkiewicz goto not_found; 232160b83f57SWaldemar Rymarkiewicz } 232260b83f57SWaldemar Rymarkiewicz 232360b83f57SWaldemar Rymarkiewicz conn->key_type = key->type; 232460b83f57SWaldemar Rymarkiewicz conn->pin_length = key->pin_len; 232560b83f57SWaldemar Rymarkiewicz } 232660b83f57SWaldemar Rymarkiewicz 232755ed8ca1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 232855ed8ca1SJohan Hedberg memcpy(cp.link_key, key->val, 16); 232955ed8ca1SJohan Hedberg 233055ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 233155ed8ca1SJohan Hedberg 233255ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 233355ed8ca1SJohan Hedberg 233455ed8ca1SJohan Hedberg return; 233555ed8ca1SJohan Hedberg 233655ed8ca1SJohan Hedberg not_found: 233755ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 233855ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 23391da177e4SLinus Torvalds } 23401da177e4SLinus Torvalds 23411da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 23421da177e4SLinus Torvalds { 2343052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 2344052b30b0SMarcel Holtmann struct hci_conn *conn; 234555ed8ca1SJohan Hedberg u8 pin_len = 0; 2346052b30b0SMarcel Holtmann 2347a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2348052b30b0SMarcel Holtmann 2349052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2350052b30b0SMarcel Holtmann 2351052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2352052b30b0SMarcel Holtmann if (conn) { 2353052b30b0SMarcel Holtmann hci_conn_hold(conn); 2354052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2355980e1a53SJohan Hedberg pin_len = conn->pin_length; 235613d39315SWaldemar Rymarkiewicz 235713d39315SWaldemar Rymarkiewicz if (ev->key_type != HCI_LK_CHANGED_COMBINATION) 235813d39315SWaldemar Rymarkiewicz conn->key_type = ev->key_type; 235913d39315SWaldemar Rymarkiewicz 2360052b30b0SMarcel Holtmann hci_conn_put(conn); 2361052b30b0SMarcel Holtmann } 2362052b30b0SMarcel Holtmann 236355ed8ca1SJohan Hedberg if (test_bit(HCI_LINK_KEYS, &hdev->flags)) 2364d25e28abSJohan Hedberg hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, 236555ed8ca1SJohan Hedberg ev->key_type, pin_len); 236655ed8ca1SJohan Hedberg 2367052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 23681da177e4SLinus Torvalds } 23691da177e4SLinus Torvalds 237004837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 237104837f64SMarcel Holtmann { 2372a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 237304837f64SMarcel Holtmann struct hci_conn *conn; 237404837f64SMarcel Holtmann 237504837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 237604837f64SMarcel Holtmann 237704837f64SMarcel Holtmann hci_dev_lock(hdev); 237804837f64SMarcel Holtmann 237904837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 23801da177e4SLinus Torvalds if (conn && !ev->status) { 23811da177e4SLinus Torvalds struct inquiry_entry *ie; 23821da177e4SLinus Torvalds 2383cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2384cc11b9c1SAndrei Emeltchenko if (ie) { 23851da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 23861da177e4SLinus Torvalds ie->timestamp = jiffies; 23871da177e4SLinus Torvalds } 23881da177e4SLinus Torvalds } 23891da177e4SLinus Torvalds 23901da177e4SLinus Torvalds hci_dev_unlock(hdev); 23911da177e4SLinus Torvalds } 23921da177e4SLinus Torvalds 2393a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2394a8746417SMarcel Holtmann { 2395a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 2396a8746417SMarcel Holtmann struct hci_conn *conn; 2397a8746417SMarcel Holtmann 2398a8746417SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2399a8746417SMarcel Holtmann 2400a8746417SMarcel Holtmann hci_dev_lock(hdev); 2401a8746417SMarcel Holtmann 2402a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2403a8746417SMarcel Holtmann if (conn && !ev->status) 2404a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 2405a8746417SMarcel Holtmann 2406a8746417SMarcel Holtmann hci_dev_unlock(hdev); 2407a8746417SMarcel Holtmann } 2408a8746417SMarcel Holtmann 240985a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 241085a1e930SMarcel Holtmann { 2411a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 241285a1e930SMarcel Holtmann struct inquiry_entry *ie; 241385a1e930SMarcel Holtmann 241485a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 241585a1e930SMarcel Holtmann 241685a1e930SMarcel Holtmann hci_dev_lock(hdev); 241785a1e930SMarcel Holtmann 2418cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2419cc11b9c1SAndrei Emeltchenko if (ie) { 242085a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 242185a1e930SMarcel Holtmann ie->timestamp = jiffies; 242285a1e930SMarcel Holtmann } 242385a1e930SMarcel Holtmann 242485a1e930SMarcel Holtmann hci_dev_unlock(hdev); 242585a1e930SMarcel Holtmann } 242685a1e930SMarcel Holtmann 2427a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb) 2428a9de9248SMarcel Holtmann { 2429a9de9248SMarcel Holtmann struct inquiry_data data; 2430a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2431a9de9248SMarcel Holtmann 2432a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2433a9de9248SMarcel Holtmann 2434a9de9248SMarcel Holtmann if (!num_rsp) 2435a9de9248SMarcel Holtmann return; 2436a9de9248SMarcel Holtmann 2437a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2438a9de9248SMarcel Holtmann 2439a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 2440138d22efSSzymon Janc struct inquiry_info_with_rssi_and_pscan_mode *info; 2441138d22efSSzymon Janc info = (void *) (skb->data + 1); 2442a9de9248SMarcel Holtmann 2443e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2444a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2445a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2446a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2447a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 2448a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2449a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2450a9de9248SMarcel Holtmann data.rssi = info->rssi; 245141a96212SMarcel Holtmann data.ssp_mode = 0x00; 2452a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 245348264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2454e17acd40SJohan Hedberg info->dev_class, info->rssi, 2455e17acd40SJohan Hedberg NULL); 2456a9de9248SMarcel Holtmann } 2457a9de9248SMarcel Holtmann } else { 2458a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 2459a9de9248SMarcel Holtmann 2460e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2461a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2462a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2463a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2464a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2465a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2466a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2467a9de9248SMarcel Holtmann data.rssi = info->rssi; 246841a96212SMarcel Holtmann data.ssp_mode = 0x00; 2469a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 247048264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2471e17acd40SJohan Hedberg info->dev_class, info->rssi, 2472e17acd40SJohan Hedberg NULL); 2473a9de9248SMarcel Holtmann } 2474a9de9248SMarcel Holtmann } 2475a9de9248SMarcel Holtmann 2476a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2477a9de9248SMarcel Holtmann } 2478a9de9248SMarcel Holtmann 2479a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 2480a9de9248SMarcel Holtmann { 248141a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 248241a96212SMarcel Holtmann struct hci_conn *conn; 248341a96212SMarcel Holtmann 2484a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 248541a96212SMarcel Holtmann 248641a96212SMarcel Holtmann hci_dev_lock(hdev); 248741a96212SMarcel Holtmann 248841a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2489ccd556feSJohan Hedberg if (!conn) 2490ccd556feSJohan Hedberg goto unlock; 2491ccd556feSJohan Hedberg 2492769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 249341a96212SMarcel Holtmann struct inquiry_entry *ie; 249441a96212SMarcel Holtmann 2495cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2496cc11b9c1SAndrei Emeltchenko if (ie) 249741a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 249841a96212SMarcel Holtmann 249941a96212SMarcel Holtmann conn->ssp_mode = (ev->features[0] & 0x01); 250041a96212SMarcel Holtmann } 250141a96212SMarcel Holtmann 2502ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2503ccd556feSJohan Hedberg goto unlock; 2504ccd556feSJohan Hedberg 2505127178d2SJohan Hedberg if (!ev->status) { 2506127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2507127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2508127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2509127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2510127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2511127178d2SJohan Hedberg } 2512392599b9SJohan Hedberg 2513127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2514769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2515769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2516769be974SMarcel Holtmann hci_conn_put(conn); 2517769be974SMarcel Holtmann } 2518769be974SMarcel Holtmann 2519ccd556feSJohan Hedberg unlock: 252041a96212SMarcel Holtmann hci_dev_unlock(hdev); 2521a9de9248SMarcel Holtmann } 2522a9de9248SMarcel Holtmann 2523a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2524a9de9248SMarcel Holtmann { 2525b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 2526b6a0dc82SMarcel Holtmann struct hci_conn *conn; 2527b6a0dc82SMarcel Holtmann 2528b6a0dc82SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2529b6a0dc82SMarcel Holtmann 2530b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 2531b6a0dc82SMarcel Holtmann 2532b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 25339dc0a3afSMarcel Holtmann if (!conn) { 25349dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 25359dc0a3afSMarcel Holtmann goto unlock; 25369dc0a3afSMarcel Holtmann 25379dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 2538b6a0dc82SMarcel Holtmann if (!conn) 2539b6a0dc82SMarcel Holtmann goto unlock; 2540b6a0dc82SMarcel Holtmann 25419dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 25429dc0a3afSMarcel Holtmann } 25439dc0a3afSMarcel Holtmann 2544732547f9SMarcel Holtmann switch (ev->status) { 2545732547f9SMarcel Holtmann case 0x00: 2546732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 2547732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 2548732547f9SMarcel Holtmann 25499eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 2550732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 2551732547f9SMarcel Holtmann break; 2552732547f9SMarcel Holtmann 2553705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 2554732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 25551038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 2556732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 2557732547f9SMarcel Holtmann if (conn->out && conn->attempt < 2) { 2558efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 2559efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 2560efc7688bSMarcel Holtmann hci_setup_sync(conn, conn->link->handle); 2561efc7688bSMarcel Holtmann goto unlock; 2562efc7688bSMarcel Holtmann } 2563732547f9SMarcel Holtmann /* fall through */ 2564efc7688bSMarcel Holtmann 2565732547f9SMarcel Holtmann default: 2566b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 2567732547f9SMarcel Holtmann break; 2568732547f9SMarcel Holtmann } 2569b6a0dc82SMarcel Holtmann 2570b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2571b6a0dc82SMarcel Holtmann if (ev->status) 2572b6a0dc82SMarcel Holtmann hci_conn_del(conn); 2573b6a0dc82SMarcel Holtmann 2574b6a0dc82SMarcel Holtmann unlock: 2575b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 2576a9de9248SMarcel Holtmann } 2577a9de9248SMarcel Holtmann 2578a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) 2579a9de9248SMarcel Holtmann { 2580a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2581a9de9248SMarcel Holtmann } 2582a9de9248SMarcel Holtmann 258304837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) 258404837f64SMarcel Holtmann { 2585a9de9248SMarcel Holtmann struct hci_ev_sniff_subrate *ev = (void *) skb->data; 258604837f64SMarcel Holtmann 258704837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 258804837f64SMarcel Holtmann } 258904837f64SMarcel Holtmann 2590a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 2591a9de9248SMarcel Holtmann { 2592a9de9248SMarcel Holtmann struct inquiry_data data; 2593a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 2594a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2595a9de9248SMarcel Holtmann 2596a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2597a9de9248SMarcel Holtmann 2598a9de9248SMarcel Holtmann if (!num_rsp) 2599a9de9248SMarcel Holtmann return; 2600a9de9248SMarcel Holtmann 2601a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2602a9de9248SMarcel Holtmann 2603e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2604a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2605a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2606a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2607a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2608a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2609a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2610a9de9248SMarcel Holtmann data.rssi = info->rssi; 261141a96212SMarcel Holtmann data.ssp_mode = 0x01; 2612a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 261348264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 26144c659c39SJohan Hedberg info->dev_class, info->rssi, info->data); 2615a9de9248SMarcel Holtmann } 2616a9de9248SMarcel Holtmann 2617a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2618a9de9248SMarcel Holtmann } 2619a9de9248SMarcel Holtmann 262017fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn) 262117fa4b9dSJohan Hedberg { 262217fa4b9dSJohan Hedberg /* If remote requests dedicated bonding follow that lead */ 262317fa4b9dSJohan Hedberg if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) { 262417fa4b9dSJohan Hedberg /* If both remote and local IO capabilities allow MITM 262517fa4b9dSJohan Hedberg * protection then require it, otherwise don't */ 262617fa4b9dSJohan Hedberg if (conn->remote_cap == 0x03 || conn->io_capability == 0x03) 262717fa4b9dSJohan Hedberg return 0x02; 262817fa4b9dSJohan Hedberg else 262917fa4b9dSJohan Hedberg return 0x03; 263017fa4b9dSJohan Hedberg } 263117fa4b9dSJohan Hedberg 263217fa4b9dSJohan Hedberg /* If remote requests no-bonding follow that lead */ 263317fa4b9dSJohan Hedberg if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01) 263458797bf7SWaldemar Rymarkiewicz return conn->remote_auth | (conn->auth_type & 0x01); 263517fa4b9dSJohan Hedberg 263617fa4b9dSJohan Hedberg return conn->auth_type; 263717fa4b9dSJohan Hedberg } 263817fa4b9dSJohan Hedberg 26390493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 26400493684eSMarcel Holtmann { 26410493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 26420493684eSMarcel Holtmann struct hci_conn *conn; 26430493684eSMarcel Holtmann 26440493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 26450493684eSMarcel Holtmann 26460493684eSMarcel Holtmann hci_dev_lock(hdev); 26470493684eSMarcel Holtmann 26480493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 264903b555e1SJohan Hedberg if (!conn) 265003b555e1SJohan Hedberg goto unlock; 265103b555e1SJohan Hedberg 26520493684eSMarcel Holtmann hci_conn_hold(conn); 26530493684eSMarcel Holtmann 265403b555e1SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->flags)) 265503b555e1SJohan Hedberg goto unlock; 265603b555e1SJohan Hedberg 265703b555e1SJohan Hedberg if (test_bit(HCI_PAIRABLE, &hdev->flags) || 265803b555e1SJohan Hedberg (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 265917fa4b9dSJohan Hedberg struct hci_cp_io_capability_reply cp; 266017fa4b9dSJohan Hedberg 266117fa4b9dSJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 266217fa4b9dSJohan Hedberg cp.capability = conn->io_capability; 26637cbc9bd9SJohan Hedberg conn->auth_type = hci_get_auth_req(conn); 26647cbc9bd9SJohan Hedberg cp.authentication = conn->auth_type; 266517fa4b9dSJohan Hedberg 2666ce85ee13SSzymon Janc if ((conn->out == 0x01 || conn->remote_oob == 0x01) && 2667ce85ee13SSzymon Janc hci_find_remote_oob_data(hdev, &conn->dst)) 2668ce85ee13SSzymon Janc cp.oob_data = 0x01; 2669ce85ee13SSzymon Janc else 2670ce85ee13SSzymon Janc cp.oob_data = 0x00; 2671ce85ee13SSzymon Janc 267217fa4b9dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, 267317fa4b9dSJohan Hedberg sizeof(cp), &cp); 267403b555e1SJohan Hedberg } else { 267503b555e1SJohan Hedberg struct hci_cp_io_capability_neg_reply cp; 267603b555e1SJohan Hedberg 267703b555e1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 26789f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED; 267903b555e1SJohan Hedberg 268003b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 268103b555e1SJohan Hedberg sizeof(cp), &cp); 268203b555e1SJohan Hedberg } 268303b555e1SJohan Hedberg 268403b555e1SJohan Hedberg unlock: 268503b555e1SJohan Hedberg hci_dev_unlock(hdev); 268603b555e1SJohan Hedberg } 268703b555e1SJohan Hedberg 268803b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 268903b555e1SJohan Hedberg { 269003b555e1SJohan Hedberg struct hci_ev_io_capa_reply *ev = (void *) skb->data; 269103b555e1SJohan Hedberg struct hci_conn *conn; 269203b555e1SJohan Hedberg 269303b555e1SJohan Hedberg BT_DBG("%s", hdev->name); 269403b555e1SJohan Hedberg 269503b555e1SJohan Hedberg hci_dev_lock(hdev); 269603b555e1SJohan Hedberg 269703b555e1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 269803b555e1SJohan Hedberg if (!conn) 269903b555e1SJohan Hedberg goto unlock; 270003b555e1SJohan Hedberg 270103b555e1SJohan Hedberg conn->remote_cap = ev->capability; 270203b555e1SJohan Hedberg conn->remote_oob = ev->oob_data; 270303b555e1SJohan Hedberg conn->remote_auth = ev->authentication; 270403b555e1SJohan Hedberg 270503b555e1SJohan Hedberg unlock: 27060493684eSMarcel Holtmann hci_dev_unlock(hdev); 27070493684eSMarcel Holtmann } 27080493684eSMarcel Holtmann 2709a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev, 2710a5c29683SJohan Hedberg struct sk_buff *skb) 2711a5c29683SJohan Hedberg { 2712a5c29683SJohan Hedberg struct hci_ev_user_confirm_req *ev = (void *) skb->data; 271355bc1a37SJohan Hedberg int loc_mitm, rem_mitm, confirm_hint = 0; 27147a828908SJohan Hedberg struct hci_conn *conn; 2715a5c29683SJohan Hedberg 2716a5c29683SJohan Hedberg BT_DBG("%s", hdev->name); 2717a5c29683SJohan Hedberg 2718a5c29683SJohan Hedberg hci_dev_lock(hdev); 2719a5c29683SJohan Hedberg 27207a828908SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->flags)) 27217a828908SJohan Hedberg goto unlock; 27227a828908SJohan Hedberg 27237a828908SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 27247a828908SJohan Hedberg if (!conn) 27257a828908SJohan Hedberg goto unlock; 27267a828908SJohan Hedberg 27277a828908SJohan Hedberg loc_mitm = (conn->auth_type & 0x01); 27287a828908SJohan Hedberg rem_mitm = (conn->remote_auth & 0x01); 27297a828908SJohan Hedberg 27307a828908SJohan Hedberg /* If we require MITM but the remote device can't provide that 27317a828908SJohan Hedberg * (it has NoInputNoOutput) then reject the confirmation 27327a828908SJohan Hedberg * request. The only exception is when we're dedicated bonding 27337a828908SJohan Hedberg * initiators (connect_cfm_cb set) since then we always have the MITM 27347a828908SJohan Hedberg * bit set. */ 27357a828908SJohan Hedberg if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) { 27367a828908SJohan Hedberg BT_DBG("Rejecting request: remote device can't provide MITM"); 27377a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, 27387a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 27397a828908SJohan Hedberg goto unlock; 27407a828908SJohan Hedberg } 27417a828908SJohan Hedberg 27427a828908SJohan Hedberg /* If no side requires MITM protection; auto-accept */ 27437a828908SJohan Hedberg if ((!loc_mitm || conn->remote_cap == 0x03) && 27447a828908SJohan Hedberg (!rem_mitm || conn->io_capability == 0x03)) { 274555bc1a37SJohan Hedberg 274655bc1a37SJohan Hedberg /* If we're not the initiators request authorization to 274755bc1a37SJohan Hedberg * proceed from user space (mgmt_user_confirm with 274855bc1a37SJohan Hedberg * confirm_hint set to 1). */ 274955bc1a37SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { 275055bc1a37SJohan Hedberg BT_DBG("Confirming auto-accept as acceptor"); 275155bc1a37SJohan Hedberg confirm_hint = 1; 275255bc1a37SJohan Hedberg goto confirm; 275355bc1a37SJohan Hedberg } 275455bc1a37SJohan Hedberg 27559f61656aSJohan Hedberg BT_DBG("Auto-accept of user confirmation with %ums delay", 27569f61656aSJohan Hedberg hdev->auto_accept_delay); 27579f61656aSJohan Hedberg 27589f61656aSJohan Hedberg if (hdev->auto_accept_delay > 0) { 27599f61656aSJohan Hedberg int delay = msecs_to_jiffies(hdev->auto_accept_delay); 27609f61656aSJohan Hedberg mod_timer(&conn->auto_accept_timer, jiffies + delay); 27619f61656aSJohan Hedberg goto unlock; 27629f61656aSJohan Hedberg } 27639f61656aSJohan Hedberg 27647a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, 27657a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 27667a828908SJohan Hedberg goto unlock; 27677a828908SJohan Hedberg } 27687a828908SJohan Hedberg 276955bc1a37SJohan Hedberg confirm: 2770744cf19eSJohan Hedberg mgmt_user_confirm_request(hdev, &ev->bdaddr, ev->passkey, 277155bc1a37SJohan Hedberg confirm_hint); 2772a5c29683SJohan Hedberg 27737a828908SJohan Hedberg unlock: 2774a5c29683SJohan Hedberg hci_dev_unlock(hdev); 2775a5c29683SJohan Hedberg } 2776a5c29683SJohan Hedberg 27770493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 27780493684eSMarcel Holtmann { 27790493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 27800493684eSMarcel Holtmann struct hci_conn *conn; 27810493684eSMarcel Holtmann 27820493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 27830493684eSMarcel Holtmann 27840493684eSMarcel Holtmann hci_dev_lock(hdev); 27850493684eSMarcel Holtmann 27860493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 27872a611692SJohan Hedberg if (!conn) 27882a611692SJohan Hedberg goto unlock; 27892a611692SJohan Hedberg 27902a611692SJohan Hedberg /* To avoid duplicate auth_failed events to user space we check 27912a611692SJohan Hedberg * the HCI_CONN_AUTH_PEND flag which will be set if we 27922a611692SJohan Hedberg * initiated the authentication. A traditional auth_complete 27932a611692SJohan Hedberg * event gets always produced as initiator and is also mapped to 27942a611692SJohan Hedberg * the mgmt_auth_failed event */ 27952a611692SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0) 2796744cf19eSJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, ev->status); 27972a611692SJohan Hedberg 27980493684eSMarcel Holtmann hci_conn_put(conn); 27990493684eSMarcel Holtmann 28002a611692SJohan Hedberg unlock: 28010493684eSMarcel Holtmann hci_dev_unlock(hdev); 28020493684eSMarcel Holtmann } 28030493684eSMarcel Holtmann 280441a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 280541a96212SMarcel Holtmann { 280641a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 280741a96212SMarcel Holtmann struct inquiry_entry *ie; 280841a96212SMarcel Holtmann 280941a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 281041a96212SMarcel Holtmann 281141a96212SMarcel Holtmann hci_dev_lock(hdev); 281241a96212SMarcel Holtmann 2813cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2814cc11b9c1SAndrei Emeltchenko if (ie) 281541a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 281641a96212SMarcel Holtmann 281741a96212SMarcel Holtmann hci_dev_unlock(hdev); 281841a96212SMarcel Holtmann } 281941a96212SMarcel Holtmann 28202763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev, 28212763eda6SSzymon Janc struct sk_buff *skb) 28222763eda6SSzymon Janc { 28232763eda6SSzymon Janc struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; 28242763eda6SSzymon Janc struct oob_data *data; 28252763eda6SSzymon Janc 28262763eda6SSzymon Janc BT_DBG("%s", hdev->name); 28272763eda6SSzymon Janc 28282763eda6SSzymon Janc hci_dev_lock(hdev); 28292763eda6SSzymon Janc 2830e1ba1f15SSzymon Janc if (!test_bit(HCI_MGMT, &hdev->flags)) 2831e1ba1f15SSzymon Janc goto unlock; 2832e1ba1f15SSzymon Janc 28332763eda6SSzymon Janc data = hci_find_remote_oob_data(hdev, &ev->bdaddr); 28342763eda6SSzymon Janc if (data) { 28352763eda6SSzymon Janc struct hci_cp_remote_oob_data_reply cp; 28362763eda6SSzymon Janc 28372763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 28382763eda6SSzymon Janc memcpy(cp.hash, data->hash, sizeof(cp.hash)); 28392763eda6SSzymon Janc memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); 28402763eda6SSzymon Janc 28412763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), 28422763eda6SSzymon Janc &cp); 28432763eda6SSzymon Janc } else { 28442763eda6SSzymon Janc struct hci_cp_remote_oob_data_neg_reply cp; 28452763eda6SSzymon Janc 28462763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 28472763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), 28482763eda6SSzymon Janc &cp); 28492763eda6SSzymon Janc } 28502763eda6SSzymon Janc 2851e1ba1f15SSzymon Janc unlock: 28522763eda6SSzymon Janc hci_dev_unlock(hdev); 28532763eda6SSzymon Janc } 28542763eda6SSzymon Janc 2855fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2856fcd89c09SVille Tervo { 2857fcd89c09SVille Tervo struct hci_ev_le_conn_complete *ev = (void *) skb->data; 2858fcd89c09SVille Tervo struct hci_conn *conn; 2859fcd89c09SVille Tervo 2860fcd89c09SVille Tervo BT_DBG("%s status %d", hdev->name, ev->status); 2861fcd89c09SVille Tervo 2862fcd89c09SVille Tervo hci_dev_lock(hdev); 2863fcd89c09SVille Tervo 2864fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr); 2865b62f328bSVille Tervo if (!conn) { 2866b62f328bSVille Tervo conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); 2867b62f328bSVille Tervo if (!conn) { 2868b62f328bSVille Tervo BT_ERR("No memory for new connection"); 2869b62f328bSVille Tervo hci_dev_unlock(hdev); 2870b62f328bSVille Tervo return; 2871b62f328bSVille Tervo } 287229b7988aSAndre Guedes 287329b7988aSAndre Guedes conn->dst_type = ev->bdaddr_type; 2874b62f328bSVille Tervo } 2875fcd89c09SVille Tervo 2876fcd89c09SVille Tervo if (ev->status) { 287748264f06SJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 287848264f06SJohan Hedberg conn->dst_type, ev->status); 2879fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 2880fcd89c09SVille Tervo conn->state = BT_CLOSED; 2881fcd89c09SVille Tervo hci_conn_del(conn); 2882fcd89c09SVille Tervo goto unlock; 2883fcd89c09SVille Tervo } 2884fcd89c09SVille Tervo 288548264f06SJohan Hedberg mgmt_connected(hdev, &ev->bdaddr, conn->type, conn->dst_type); 288683bc71b4SVinicius Costa Gomes 28877b5c0d52SVinicius Costa Gomes conn->sec_level = BT_SECURITY_LOW; 2888fcd89c09SVille Tervo conn->handle = __le16_to_cpu(ev->handle); 2889fcd89c09SVille Tervo conn->state = BT_CONNECTED; 2890fcd89c09SVille Tervo 2891fcd89c09SVille Tervo hci_conn_hold_device(conn); 2892fcd89c09SVille Tervo hci_conn_add_sysfs(conn); 2893fcd89c09SVille Tervo 2894fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 2895fcd89c09SVille Tervo 2896fcd89c09SVille Tervo unlock: 2897fcd89c09SVille Tervo hci_dev_unlock(hdev); 2898fcd89c09SVille Tervo } 2899fcd89c09SVille Tervo 29009aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev, 29019aa04c91SAndre Guedes struct sk_buff *skb) 29029aa04c91SAndre Guedes { 2903e95beb41SAndre Guedes u8 num_reports = skb->data[0]; 2904e95beb41SAndre Guedes void *ptr = &skb->data[1]; 29059aa04c91SAndre Guedes 29069aa04c91SAndre Guedes hci_dev_lock(hdev); 29079aa04c91SAndre Guedes 2908e95beb41SAndre Guedes while (num_reports--) { 2909e95beb41SAndre Guedes struct hci_ev_le_advertising_info *ev = ptr; 2910e95beb41SAndre Guedes 29119aa04c91SAndre Guedes hci_add_adv_entry(hdev, ev); 29129aa04c91SAndre Guedes 2913e95beb41SAndre Guedes ptr += sizeof(*ev) + ev->length + 1; 29149aa04c91SAndre Guedes } 29159aa04c91SAndre Guedes 29169aa04c91SAndre Guedes hci_dev_unlock(hdev); 29179aa04c91SAndre Guedes } 29189aa04c91SAndre Guedes 2919a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev, 2920a7a595f6SVinicius Costa Gomes struct sk_buff *skb) 2921a7a595f6SVinicius Costa Gomes { 2922a7a595f6SVinicius Costa Gomes struct hci_ev_le_ltk_req *ev = (void *) skb->data; 2923a7a595f6SVinicius Costa Gomes struct hci_cp_le_ltk_reply cp; 2924bea710feSVinicius Costa Gomes struct hci_cp_le_ltk_neg_reply neg; 2925a7a595f6SVinicius Costa Gomes struct hci_conn *conn; 2926bea710feSVinicius Costa Gomes struct link_key *ltk; 2927a7a595f6SVinicius Costa Gomes 2928a7a595f6SVinicius Costa Gomes BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle)); 2929a7a595f6SVinicius Costa Gomes 2930a7a595f6SVinicius Costa Gomes hci_dev_lock(hdev); 2931a7a595f6SVinicius Costa Gomes 2932a7a595f6SVinicius Costa Gomes conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2933bea710feSVinicius Costa Gomes if (conn == NULL) 2934bea710feSVinicius Costa Gomes goto not_found; 2935a7a595f6SVinicius Costa Gomes 2936bea710feSVinicius Costa Gomes ltk = hci_find_ltk(hdev, ev->ediv, ev->random); 2937bea710feSVinicius Costa Gomes if (ltk == NULL) 2938bea710feSVinicius Costa Gomes goto not_found; 2939bea710feSVinicius Costa Gomes 2940bea710feSVinicius Costa Gomes memcpy(cp.ltk, ltk->val, sizeof(ltk->val)); 2941a7a595f6SVinicius Costa Gomes cp.handle = cpu_to_le16(conn->handle); 2942726b4ffcSVinicius Costa Gomes conn->pin_length = ltk->pin_len; 2943a7a595f6SVinicius Costa Gomes 2944a7a595f6SVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); 2945a7a595f6SVinicius Costa Gomes 2946a7a595f6SVinicius Costa Gomes hci_dev_unlock(hdev); 2947bea710feSVinicius Costa Gomes 2948bea710feSVinicius Costa Gomes return; 2949bea710feSVinicius Costa Gomes 2950bea710feSVinicius Costa Gomes not_found: 2951bea710feSVinicius Costa Gomes neg.handle = ev->handle; 2952bea710feSVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg); 2953bea710feSVinicius Costa Gomes hci_dev_unlock(hdev); 2954a7a595f6SVinicius Costa Gomes } 2955a7a595f6SVinicius Costa Gomes 2956fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 2957fcd89c09SVille Tervo { 2958fcd89c09SVille Tervo struct hci_ev_le_meta *le_ev = (void *) skb->data; 2959fcd89c09SVille Tervo 2960fcd89c09SVille Tervo skb_pull(skb, sizeof(*le_ev)); 2961fcd89c09SVille Tervo 2962fcd89c09SVille Tervo switch (le_ev->subevent) { 2963fcd89c09SVille Tervo case HCI_EV_LE_CONN_COMPLETE: 2964fcd89c09SVille Tervo hci_le_conn_complete_evt(hdev, skb); 2965fcd89c09SVille Tervo break; 2966fcd89c09SVille Tervo 29679aa04c91SAndre Guedes case HCI_EV_LE_ADVERTISING_REPORT: 29689aa04c91SAndre Guedes hci_le_adv_report_evt(hdev, skb); 29699aa04c91SAndre Guedes break; 29709aa04c91SAndre Guedes 2971a7a595f6SVinicius Costa Gomes case HCI_EV_LE_LTK_REQ: 2972a7a595f6SVinicius Costa Gomes hci_le_ltk_request_evt(hdev, skb); 2973a7a595f6SVinicius Costa Gomes break; 2974a7a595f6SVinicius Costa Gomes 2975fcd89c09SVille Tervo default: 2976fcd89c09SVille Tervo break; 2977fcd89c09SVille Tervo } 2978fcd89c09SVille Tervo } 2979fcd89c09SVille Tervo 29801da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 29811da177e4SLinus Torvalds { 2982a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 2983a9de9248SMarcel Holtmann __u8 event = hdr->evt; 29841da177e4SLinus Torvalds 29851da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 29861da177e4SLinus Torvalds 2987a9de9248SMarcel Holtmann switch (event) { 29881da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 29891da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 29901da177e4SLinus Torvalds break; 29911da177e4SLinus Torvalds 29921da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 29931da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 29941da177e4SLinus Torvalds break; 29951da177e4SLinus Torvalds 2996a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 2997a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 299821d9e30eSMarcel Holtmann break; 299921d9e30eSMarcel Holtmann 30001da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 30011da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 30021da177e4SLinus Torvalds break; 30031da177e4SLinus Torvalds 30041da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 30051da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 30061da177e4SLinus Torvalds break; 30071da177e4SLinus Torvalds 30081da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 30091da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 30101da177e4SLinus Torvalds break; 30111da177e4SLinus Torvalds 3012a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 3013a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 3014a9de9248SMarcel Holtmann break; 3015a9de9248SMarcel Holtmann 30161da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 30171da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 30181da177e4SLinus Torvalds break; 30191da177e4SLinus Torvalds 3020a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 3021a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 3022a9de9248SMarcel Holtmann break; 3023a9de9248SMarcel Holtmann 3024a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 3025a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 3026a9de9248SMarcel Holtmann break; 3027a9de9248SMarcel Holtmann 3028a9de9248SMarcel Holtmann case HCI_EV_REMOTE_VERSION: 3029a9de9248SMarcel Holtmann hci_remote_version_evt(hdev, skb); 3030a9de9248SMarcel Holtmann break; 3031a9de9248SMarcel Holtmann 3032a9de9248SMarcel Holtmann case HCI_EV_QOS_SETUP_COMPLETE: 3033a9de9248SMarcel Holtmann hci_qos_setup_complete_evt(hdev, skb); 3034a9de9248SMarcel Holtmann break; 3035a9de9248SMarcel Holtmann 3036a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 3037a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 3038a9de9248SMarcel Holtmann break; 3039a9de9248SMarcel Holtmann 3040a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 3041a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 3042a9de9248SMarcel Holtmann break; 3043a9de9248SMarcel Holtmann 3044a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 3045a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 3046a9de9248SMarcel Holtmann break; 3047a9de9248SMarcel Holtmann 3048a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 3049a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 3050a9de9248SMarcel Holtmann break; 3051a9de9248SMarcel Holtmann 3052a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 3053a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 30541da177e4SLinus Torvalds break; 30551da177e4SLinus Torvalds 30561da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 30571da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 30581da177e4SLinus Torvalds break; 30591da177e4SLinus Torvalds 30601da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 30611da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 30621da177e4SLinus Torvalds break; 30631da177e4SLinus Torvalds 30641da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 30651da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 30661da177e4SLinus Torvalds break; 30671da177e4SLinus Torvalds 30681da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 30691da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 30701da177e4SLinus Torvalds break; 30711da177e4SLinus Torvalds 3072a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 3073a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 3074a8746417SMarcel Holtmann break; 3075a8746417SMarcel Holtmann 307685a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 307785a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 307885a1e930SMarcel Holtmann break; 307985a1e930SMarcel Holtmann 3080a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 3081a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 3082a9de9248SMarcel Holtmann break; 3083a9de9248SMarcel Holtmann 3084a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 3085a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 3086a9de9248SMarcel Holtmann break; 3087a9de9248SMarcel Holtmann 3088a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 3089a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 3090a9de9248SMarcel Holtmann break; 3091a9de9248SMarcel Holtmann 3092a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_CHANGED: 3093a9de9248SMarcel Holtmann hci_sync_conn_changed_evt(hdev, skb); 3094a9de9248SMarcel Holtmann break; 3095a9de9248SMarcel Holtmann 309604837f64SMarcel Holtmann case HCI_EV_SNIFF_SUBRATE: 309704837f64SMarcel Holtmann hci_sniff_subrate_evt(hdev, skb); 309804837f64SMarcel Holtmann break; 309904837f64SMarcel Holtmann 3100a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 3101a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 31021da177e4SLinus Torvalds break; 31031da177e4SLinus Torvalds 31040493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 31050493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 31060493684eSMarcel Holtmann break; 31070493684eSMarcel Holtmann 310803b555e1SJohan Hedberg case HCI_EV_IO_CAPA_REPLY: 310903b555e1SJohan Hedberg hci_io_capa_reply_evt(hdev, skb); 311003b555e1SJohan Hedberg break; 311103b555e1SJohan Hedberg 3112a5c29683SJohan Hedberg case HCI_EV_USER_CONFIRM_REQUEST: 3113a5c29683SJohan Hedberg hci_user_confirm_request_evt(hdev, skb); 3114a5c29683SJohan Hedberg break; 3115a5c29683SJohan Hedberg 31160493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 31170493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 31180493684eSMarcel Holtmann break; 31190493684eSMarcel Holtmann 312041a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 312141a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 312241a96212SMarcel Holtmann break; 312341a96212SMarcel Holtmann 3124fcd89c09SVille Tervo case HCI_EV_LE_META: 3125fcd89c09SVille Tervo hci_le_meta_evt(hdev, skb); 3126fcd89c09SVille Tervo break; 3127fcd89c09SVille Tervo 31282763eda6SSzymon Janc case HCI_EV_REMOTE_OOB_DATA_REQUEST: 31292763eda6SSzymon Janc hci_remote_oob_data_request_evt(hdev, skb); 31302763eda6SSzymon Janc break; 31312763eda6SSzymon Janc 31321da177e4SLinus Torvalds default: 3133a9de9248SMarcel Holtmann BT_DBG("%s event 0x%x", hdev->name, event); 31341da177e4SLinus Torvalds break; 31351da177e4SLinus Torvalds } 31361da177e4SLinus Torvalds 31371da177e4SLinus Torvalds kfree_skb(skb); 31381da177e4SLinus Torvalds hdev->stat.evt_rx++; 31391da177e4SLinus Torvalds } 31401da177e4SLinus Torvalds 31411da177e4SLinus Torvalds /* Generate internal stack event */ 31421da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data) 31431da177e4SLinus Torvalds { 31441da177e4SLinus Torvalds struct hci_event_hdr *hdr; 31451da177e4SLinus Torvalds struct hci_ev_stack_internal *ev; 31461da177e4SLinus Torvalds struct sk_buff *skb; 31471da177e4SLinus Torvalds 31481da177e4SLinus Torvalds skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC); 31491da177e4SLinus Torvalds if (!skb) 31501da177e4SLinus Torvalds return; 31511da177e4SLinus Torvalds 31521da177e4SLinus Torvalds hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE); 31531da177e4SLinus Torvalds hdr->evt = HCI_EV_STACK_INTERNAL; 31541da177e4SLinus Torvalds hdr->plen = sizeof(*ev) + dlen; 31551da177e4SLinus Torvalds 31561da177e4SLinus Torvalds ev = (void *) skb_put(skb, sizeof(*ev) + dlen); 31571da177e4SLinus Torvalds ev->type = type; 31581da177e4SLinus Torvalds memcpy(ev->data, data, dlen); 31591da177e4SLinus Torvalds 3160576c7d85SMarcel Holtmann bt_cb(skb)->incoming = 1; 3161a61bbcf2SPatrick McHardy __net_timestamp(skb); 3162576c7d85SMarcel Holtmann 31630d48d939SMarcel Holtmann bt_cb(skb)->pkt_type = HCI_EVENT_PKT; 31641da177e4SLinus Torvalds skb->dev = (void *) hdev; 3165eec8d2bcSJohan Hedberg hci_send_to_sock(hdev, skb, NULL); 31661da177e4SLinus Torvalds kfree_skb(skb); 31671da177e4SLinus Torvalds } 3168e6100a25SAndre Guedes 3169669bb396SGustavo F. Padovan module_param(enable_le, bool, 0644); 3170e6100a25SAndre Guedes MODULE_PARM_DESC(enable_le, "Enable LE support"); 3171