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 58a9de9248SMarcel Holtmann if (status) 59a9de9248SMarcel Holtmann return; 601da177e4SLinus Torvalds 6189352e7dSAndre Guedes clear_bit(HCI_INQUIRY, &hdev->flags); 6289352e7dSAndre Guedes 6356e5cb86SJohan Hedberg hci_dev_lock(hdev); 64744cf19eSJohan Hedberg mgmt_discovering(hdev, 0); 6556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 66a9de9248SMarcel Holtmann 6723bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status); 68a9de9248SMarcel Holtmann 69a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 701da177e4SLinus Torvalds } 716bd57416SMarcel Holtmann 72a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 731da177e4SLinus Torvalds { 74a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 75a9de9248SMarcel Holtmann 76a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 77a9de9248SMarcel Holtmann 78a9de9248SMarcel Holtmann if (status) 79a9de9248SMarcel Holtmann return; 80a9de9248SMarcel Holtmann 81a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 82a9de9248SMarcel Holtmann } 83a9de9248SMarcel Holtmann 84a9de9248SMarcel Holtmann static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb) 85a9de9248SMarcel Holtmann { 86a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 87a9de9248SMarcel Holtmann } 88a9de9248SMarcel Holtmann 89a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb) 90a9de9248SMarcel Holtmann { 91a9de9248SMarcel Holtmann struct hci_rp_role_discovery *rp = (void *) skb->data; 921da177e4SLinus Torvalds struct hci_conn *conn; 931da177e4SLinus Torvalds 94a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 951da177e4SLinus Torvalds 96a9de9248SMarcel Holtmann if (rp->status) 97a9de9248SMarcel Holtmann return; 981da177e4SLinus Torvalds 991da177e4SLinus Torvalds hci_dev_lock(hdev); 1001da177e4SLinus Torvalds 101a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 1021da177e4SLinus Torvalds if (conn) { 103a9de9248SMarcel Holtmann if (rp->role) 1041da177e4SLinus Torvalds conn->link_mode &= ~HCI_LM_MASTER; 1051da177e4SLinus Torvalds else 1061da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 1071da177e4SLinus Torvalds } 1081da177e4SLinus Torvalds 1091da177e4SLinus Torvalds hci_dev_unlock(hdev); 110a9de9248SMarcel Holtmann } 1111da177e4SLinus Torvalds 112e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 113e4e8e37cSMarcel Holtmann { 114e4e8e37cSMarcel Holtmann struct hci_rp_read_link_policy *rp = (void *) skb->data; 115e4e8e37cSMarcel Holtmann struct hci_conn *conn; 116e4e8e37cSMarcel Holtmann 117e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 118e4e8e37cSMarcel Holtmann 119e4e8e37cSMarcel Holtmann if (rp->status) 120e4e8e37cSMarcel Holtmann return; 121e4e8e37cSMarcel Holtmann 122e4e8e37cSMarcel Holtmann hci_dev_lock(hdev); 123e4e8e37cSMarcel Holtmann 124e4e8e37cSMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 125e4e8e37cSMarcel Holtmann if (conn) 126e4e8e37cSMarcel Holtmann conn->link_policy = __le16_to_cpu(rp->policy); 127e4e8e37cSMarcel Holtmann 128e4e8e37cSMarcel Holtmann hci_dev_unlock(hdev); 129e4e8e37cSMarcel Holtmann } 130e4e8e37cSMarcel Holtmann 131a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 132a9de9248SMarcel Holtmann { 133a9de9248SMarcel Holtmann struct hci_rp_write_link_policy *rp = (void *) skb->data; 134a9de9248SMarcel Holtmann struct hci_conn *conn; 135a9de9248SMarcel Holtmann void *sent; 136a9de9248SMarcel Holtmann 137a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 138a9de9248SMarcel Holtmann 139a9de9248SMarcel Holtmann if (rp->status) 140a9de9248SMarcel Holtmann return; 141a9de9248SMarcel Holtmann 142a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY); 14304837f64SMarcel Holtmann if (!sent) 144a9de9248SMarcel Holtmann return; 14504837f64SMarcel Holtmann 14604837f64SMarcel Holtmann hci_dev_lock(hdev); 14704837f64SMarcel Holtmann 148a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 149e4e8e37cSMarcel Holtmann if (conn) 15083985319SHarvey Harrison conn->link_policy = get_unaligned_le16(sent + 2); 15104837f64SMarcel Holtmann 15204837f64SMarcel Holtmann hci_dev_unlock(hdev); 1531da177e4SLinus Torvalds } 1541da177e4SLinus Torvalds 155e4e8e37cSMarcel Holtmann static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 156e4e8e37cSMarcel Holtmann { 157e4e8e37cSMarcel Holtmann struct hci_rp_read_def_link_policy *rp = (void *) skb->data; 158e4e8e37cSMarcel Holtmann 159e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 160e4e8e37cSMarcel Holtmann 161e4e8e37cSMarcel Holtmann if (rp->status) 162e4e8e37cSMarcel Holtmann return; 163e4e8e37cSMarcel Holtmann 164e4e8e37cSMarcel Holtmann hdev->link_policy = __le16_to_cpu(rp->policy); 165e4e8e37cSMarcel Holtmann } 166e4e8e37cSMarcel Holtmann 167e4e8e37cSMarcel Holtmann static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 168e4e8e37cSMarcel Holtmann { 169e4e8e37cSMarcel Holtmann __u8 status = *((__u8 *) skb->data); 170e4e8e37cSMarcel Holtmann void *sent; 171e4e8e37cSMarcel Holtmann 172e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 173e4e8e37cSMarcel Holtmann 174e4e8e37cSMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY); 175e4e8e37cSMarcel Holtmann if (!sent) 176e4e8e37cSMarcel Holtmann return; 177e4e8e37cSMarcel Holtmann 178e4e8e37cSMarcel Holtmann if (!status) 179e4e8e37cSMarcel Holtmann hdev->link_policy = get_unaligned_le16(sent); 180e4e8e37cSMarcel Holtmann 18123bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status); 182e4e8e37cSMarcel Holtmann } 183e4e8e37cSMarcel Holtmann 184a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) 1851da177e4SLinus Torvalds { 186a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 187a9de9248SMarcel Holtmann 188a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 189a9de9248SMarcel Holtmann 19010572132SGustavo F. Padovan clear_bit(HCI_RESET, &hdev->flags); 19110572132SGustavo F. Padovan 19223bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_RESET, status); 193a9de9248SMarcel Holtmann } 194a9de9248SMarcel Holtmann 195a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) 196a9de9248SMarcel Holtmann { 197a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 1981da177e4SLinus Torvalds void *sent; 1991da177e4SLinus Torvalds 200a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 2011da177e4SLinus Torvalds 202a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); 2031da177e4SLinus Torvalds if (!sent) 204a9de9248SMarcel Holtmann return; 2051da177e4SLinus Torvalds 20656e5cb86SJohan Hedberg hci_dev_lock(hdev); 20756e5cb86SJohan Hedberg 208b312b161SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 209744cf19eSJohan Hedberg mgmt_set_local_name_complete(hdev, sent, status); 210b312b161SJohan Hedberg 21156e5cb86SJohan Hedberg if (status == 0) 2121f6c6378SJohan Hedberg memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); 21356e5cb86SJohan Hedberg 21456e5cb86SJohan Hedberg hci_dev_unlock(hdev); 215a9de9248SMarcel Holtmann } 216a9de9248SMarcel Holtmann 217a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) 218a9de9248SMarcel Holtmann { 219a9de9248SMarcel Holtmann struct hci_rp_read_local_name *rp = (void *) skb->data; 220a9de9248SMarcel Holtmann 221a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 222a9de9248SMarcel Holtmann 223a9de9248SMarcel Holtmann if (rp->status) 224a9de9248SMarcel Holtmann return; 225a9de9248SMarcel Holtmann 2261f6c6378SJohan Hedberg memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); 227a9de9248SMarcel Holtmann } 228a9de9248SMarcel Holtmann 229a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) 230a9de9248SMarcel Holtmann { 231a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 232a9de9248SMarcel Holtmann void *sent; 233a9de9248SMarcel Holtmann 234a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 235a9de9248SMarcel Holtmann 236a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); 237a9de9248SMarcel Holtmann if (!sent) 238a9de9248SMarcel Holtmann return; 2391da177e4SLinus Torvalds 2401da177e4SLinus Torvalds if (!status) { 241a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 242a9de9248SMarcel Holtmann 2431da177e4SLinus Torvalds if (param == AUTH_ENABLED) 2441da177e4SLinus Torvalds set_bit(HCI_AUTH, &hdev->flags); 2451da177e4SLinus Torvalds else 2461da177e4SLinus Torvalds clear_bit(HCI_AUTH, &hdev->flags); 2471da177e4SLinus Torvalds } 248a9de9248SMarcel Holtmann 24923bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status); 250a9de9248SMarcel Holtmann } 2511da177e4SLinus Torvalds 252a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) 253a9de9248SMarcel Holtmann { 254a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 255a9de9248SMarcel Holtmann void *sent; 256a9de9248SMarcel Holtmann 257a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 258a9de9248SMarcel Holtmann 259a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); 2601da177e4SLinus Torvalds if (!sent) 261a9de9248SMarcel Holtmann return; 2621da177e4SLinus Torvalds 2631da177e4SLinus Torvalds if (!status) { 264a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 265a9de9248SMarcel Holtmann 2661da177e4SLinus Torvalds if (param) 2671da177e4SLinus Torvalds set_bit(HCI_ENCRYPT, &hdev->flags); 2681da177e4SLinus Torvalds else 2691da177e4SLinus Torvalds clear_bit(HCI_ENCRYPT, &hdev->flags); 2701da177e4SLinus Torvalds } 271a9de9248SMarcel Holtmann 27223bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status); 2731da177e4SLinus Torvalds } 2741da177e4SLinus Torvalds 275a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) 276a9de9248SMarcel Holtmann { 27736f7fc7eSJohan Hedberg __u8 param, status = *((__u8 *) skb->data); 27836f7fc7eSJohan Hedberg int old_pscan, old_iscan; 279a9de9248SMarcel Holtmann void *sent; 2801da177e4SLinus Torvalds 281a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 282a9de9248SMarcel Holtmann 283a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); 2841da177e4SLinus Torvalds if (!sent) 285a9de9248SMarcel Holtmann return; 2861da177e4SLinus Torvalds 28736f7fc7eSJohan Hedberg param = *((__u8 *) sent); 288a9de9248SMarcel Holtmann 28956e5cb86SJohan Hedberg hci_dev_lock(hdev); 29056e5cb86SJohan Hedberg 2912d7cee58SJohan Hedberg if (status != 0) { 292744cf19eSJohan Hedberg mgmt_write_scan_failed(hdev, param, status); 2932d7cee58SJohan Hedberg hdev->discov_timeout = 0; 2942d7cee58SJohan Hedberg goto done; 2952d7cee58SJohan Hedberg } 2962d7cee58SJohan Hedberg 2979fbcbb45SJohan Hedberg old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags); 2989fbcbb45SJohan Hedberg old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags); 299a9de9248SMarcel Holtmann 30073f22f62SJohan Hedberg if (param & SCAN_INQUIRY) { 3011da177e4SLinus Torvalds set_bit(HCI_ISCAN, &hdev->flags); 3029fbcbb45SJohan Hedberg if (!old_iscan) 303744cf19eSJohan Hedberg mgmt_discoverable(hdev, 1); 30416ab91abSJohan Hedberg if (hdev->discov_timeout > 0) { 30516ab91abSJohan Hedberg int to = msecs_to_jiffies(hdev->discov_timeout * 1000); 30616ab91abSJohan Hedberg queue_delayed_work(hdev->workqueue, &hdev->discov_off, 30716ab91abSJohan Hedberg to); 30816ab91abSJohan Hedberg } 3099fbcbb45SJohan Hedberg } else if (old_iscan) 310744cf19eSJohan Hedberg mgmt_discoverable(hdev, 0); 3111da177e4SLinus Torvalds 3129fbcbb45SJohan Hedberg if (param & SCAN_PAGE) { 3131da177e4SLinus Torvalds set_bit(HCI_PSCAN, &hdev->flags); 3149fbcbb45SJohan Hedberg if (!old_pscan) 315744cf19eSJohan Hedberg mgmt_connectable(hdev, 1); 3169fbcbb45SJohan Hedberg } else if (old_pscan) 317744cf19eSJohan Hedberg mgmt_connectable(hdev, 0); 318a9de9248SMarcel Holtmann 31936f7fc7eSJohan Hedberg done: 32056e5cb86SJohan Hedberg hci_dev_unlock(hdev); 32123bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status); 3221da177e4SLinus Torvalds } 3231da177e4SLinus Torvalds 324a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 325a9de9248SMarcel Holtmann { 326a9de9248SMarcel Holtmann struct hci_rp_read_class_of_dev *rp = (void *) skb->data; 327a9de9248SMarcel Holtmann 328a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 329a9de9248SMarcel Holtmann 330a9de9248SMarcel Holtmann if (rp->status) 331a9de9248SMarcel Holtmann return; 332a9de9248SMarcel Holtmann 333a9de9248SMarcel Holtmann memcpy(hdev->dev_class, rp->dev_class, 3); 334a9de9248SMarcel Holtmann 335a9de9248SMarcel Holtmann BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, 336a9de9248SMarcel Holtmann hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); 337a9de9248SMarcel Holtmann } 338a9de9248SMarcel Holtmann 339a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 340a9de9248SMarcel Holtmann { 341a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 342a9de9248SMarcel Holtmann void *sent; 343a9de9248SMarcel Holtmann 344a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 345a9de9248SMarcel Holtmann 346f383f275SMarcel Holtmann if (status) 347f383f275SMarcel Holtmann return; 348f383f275SMarcel Holtmann 349a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); 350a9de9248SMarcel Holtmann if (!sent) 351a9de9248SMarcel Holtmann return; 352a9de9248SMarcel Holtmann 353a9de9248SMarcel Holtmann memcpy(hdev->dev_class, sent, 3); 354a9de9248SMarcel Holtmann } 355a9de9248SMarcel Holtmann 356a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 357a9de9248SMarcel Holtmann { 358a9de9248SMarcel Holtmann struct hci_rp_read_voice_setting *rp = (void *) skb->data; 359a9de9248SMarcel Holtmann __u16 setting; 360a9de9248SMarcel Holtmann 361a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 362a9de9248SMarcel Holtmann 363a9de9248SMarcel Holtmann if (rp->status) 364a9de9248SMarcel Holtmann return; 365a9de9248SMarcel Holtmann 366a9de9248SMarcel Holtmann setting = __le16_to_cpu(rp->voice_setting); 367a9de9248SMarcel Holtmann 368a9de9248SMarcel Holtmann if (hdev->voice_setting == setting) 369a9de9248SMarcel Holtmann return; 370a9de9248SMarcel Holtmann 371a9de9248SMarcel Holtmann hdev->voice_setting = setting; 372a9de9248SMarcel Holtmann 373a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 374a9de9248SMarcel Holtmann 375a9de9248SMarcel Holtmann if (hdev->notify) { 376a9de9248SMarcel Holtmann tasklet_disable(&hdev->tx_task); 377a9de9248SMarcel Holtmann hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 378a9de9248SMarcel Holtmann tasklet_enable(&hdev->tx_task); 379a9de9248SMarcel Holtmann } 380a9de9248SMarcel Holtmann } 381a9de9248SMarcel Holtmann 382a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 383a9de9248SMarcel Holtmann { 384a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 385f383f275SMarcel Holtmann __u16 setting; 386a9de9248SMarcel Holtmann void *sent; 387a9de9248SMarcel Holtmann 388a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 389a9de9248SMarcel Holtmann 390f383f275SMarcel Holtmann if (status) 391f383f275SMarcel Holtmann return; 392f383f275SMarcel Holtmann 393a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); 394a9de9248SMarcel Holtmann if (!sent) 395a9de9248SMarcel Holtmann return; 396a9de9248SMarcel Holtmann 397f383f275SMarcel Holtmann setting = get_unaligned_le16(sent); 3981da177e4SLinus Torvalds 399f383f275SMarcel Holtmann if (hdev->voice_setting == setting) 400f383f275SMarcel Holtmann return; 401f383f275SMarcel Holtmann 4021da177e4SLinus Torvalds hdev->voice_setting = setting; 4031da177e4SLinus Torvalds 404a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 4051da177e4SLinus Torvalds 4061da177e4SLinus Torvalds if (hdev->notify) { 4071da177e4SLinus Torvalds tasklet_disable(&hdev->tx_task); 4081da177e4SLinus Torvalds hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 4091da177e4SLinus Torvalds tasklet_enable(&hdev->tx_task); 4101da177e4SLinus Torvalds } 4111da177e4SLinus Torvalds } 4121da177e4SLinus Torvalds 413a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 4141da177e4SLinus Torvalds { 415a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 4161da177e4SLinus Torvalds 417a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 4181da177e4SLinus Torvalds 41923bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status); 4201143e5a6SMarcel Holtmann } 4211143e5a6SMarcel Holtmann 422333140b5SMarcel Holtmann static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 423333140b5SMarcel Holtmann { 424333140b5SMarcel Holtmann struct hci_rp_read_ssp_mode *rp = (void *) skb->data; 425333140b5SMarcel Holtmann 426333140b5SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 427333140b5SMarcel Holtmann 428333140b5SMarcel Holtmann if (rp->status) 429333140b5SMarcel Holtmann return; 430333140b5SMarcel Holtmann 431333140b5SMarcel Holtmann hdev->ssp_mode = rp->mode; 432333140b5SMarcel Holtmann } 433333140b5SMarcel Holtmann 434333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 435333140b5SMarcel Holtmann { 436333140b5SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 437333140b5SMarcel Holtmann void *sent; 438333140b5SMarcel Holtmann 439333140b5SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 440333140b5SMarcel Holtmann 441333140b5SMarcel Holtmann if (status) 442333140b5SMarcel Holtmann return; 443333140b5SMarcel Holtmann 444333140b5SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); 445333140b5SMarcel Holtmann if (!sent) 446333140b5SMarcel Holtmann return; 447333140b5SMarcel Holtmann 448333140b5SMarcel Holtmann hdev->ssp_mode = *((__u8 *) sent); 449333140b5SMarcel Holtmann } 450333140b5SMarcel Holtmann 451d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev) 452d5859e22SJohan Hedberg { 453d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 454d5859e22SJohan Hedberg return 2; 455d5859e22SJohan Hedberg 456d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 457d5859e22SJohan Hedberg return 1; 458d5859e22SJohan Hedberg 459d5859e22SJohan Hedberg if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 && 460d5859e22SJohan Hedberg hdev->lmp_subver == 0x0757) 461d5859e22SJohan Hedberg return 1; 462d5859e22SJohan Hedberg 463d5859e22SJohan Hedberg if (hdev->manufacturer == 15) { 464d5859e22SJohan Hedberg if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963) 465d5859e22SJohan Hedberg return 1; 466d5859e22SJohan Hedberg if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963) 467d5859e22SJohan Hedberg return 1; 468d5859e22SJohan Hedberg if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965) 469d5859e22SJohan Hedberg return 1; 470d5859e22SJohan Hedberg } 471d5859e22SJohan Hedberg 472d5859e22SJohan Hedberg if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 && 473d5859e22SJohan Hedberg hdev->lmp_subver == 0x1805) 474d5859e22SJohan Hedberg return 1; 475d5859e22SJohan Hedberg 476d5859e22SJohan Hedberg return 0; 477d5859e22SJohan Hedberg } 478d5859e22SJohan Hedberg 479d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev) 480d5859e22SJohan Hedberg { 481d5859e22SJohan Hedberg u8 mode; 482d5859e22SJohan Hedberg 483d5859e22SJohan Hedberg mode = hci_get_inquiry_mode(hdev); 484d5859e22SJohan Hedberg 485d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode); 486d5859e22SJohan Hedberg } 487d5859e22SJohan Hedberg 488d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev) 489d5859e22SJohan Hedberg { 490d5859e22SJohan Hedberg /* The second byte is 0xff instead of 0x9f (two reserved bits 491d5859e22SJohan Hedberg * disabled) since a Broadcom 1.2 dongle doesn't respond to the 492d5859e22SJohan Hedberg * command otherwise */ 493d5859e22SJohan Hedberg u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 }; 494d5859e22SJohan Hedberg 4956de6c18dSVille Tervo /* CSR 1.1 dongles does not accept any bitfield so don't try to set 4966de6c18dSVille Tervo * any event mask for pre 1.2 devices */ 4976de6c18dSVille Tervo if (hdev->lmp_ver <= 1) 4986de6c18dSVille Tervo return; 4996de6c18dSVille Tervo 500d5859e22SJohan Hedberg events[4] |= 0x01; /* Flow Specification Complete */ 501d5859e22SJohan Hedberg events[4] |= 0x02; /* Inquiry Result with RSSI */ 502d5859e22SJohan Hedberg events[4] |= 0x04; /* Read Remote Extended Features Complete */ 503d5859e22SJohan Hedberg events[5] |= 0x08; /* Synchronous Connection Complete */ 504d5859e22SJohan Hedberg events[5] |= 0x10; /* Synchronous Connection Changed */ 505d5859e22SJohan Hedberg 506d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 507d5859e22SJohan Hedberg events[4] |= 0x04; /* Inquiry Result with RSSI */ 508d5859e22SJohan Hedberg 509d5859e22SJohan Hedberg if (hdev->features[5] & LMP_SNIFF_SUBR) 510d5859e22SJohan Hedberg events[5] |= 0x20; /* Sniff Subrating */ 511d5859e22SJohan Hedberg 512d5859e22SJohan Hedberg if (hdev->features[5] & LMP_PAUSE_ENC) 513d5859e22SJohan Hedberg events[5] |= 0x80; /* Encryption Key Refresh Complete */ 514d5859e22SJohan Hedberg 515d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 516d5859e22SJohan Hedberg events[5] |= 0x40; /* Extended Inquiry Result */ 517d5859e22SJohan Hedberg 518d5859e22SJohan Hedberg if (hdev->features[6] & LMP_NO_FLUSH) 519d5859e22SJohan Hedberg events[7] |= 0x01; /* Enhanced Flush Complete */ 520d5859e22SJohan Hedberg 521d5859e22SJohan Hedberg if (hdev->features[7] & LMP_LSTO) 522d5859e22SJohan Hedberg events[6] |= 0x80; /* Link Supervision Timeout Changed */ 523d5859e22SJohan Hedberg 524d5859e22SJohan Hedberg if (hdev->features[6] & LMP_SIMPLE_PAIR) { 525d5859e22SJohan Hedberg events[6] |= 0x01; /* IO Capability Request */ 526d5859e22SJohan Hedberg events[6] |= 0x02; /* IO Capability Response */ 527d5859e22SJohan Hedberg events[6] |= 0x04; /* User Confirmation Request */ 528d5859e22SJohan Hedberg events[6] |= 0x08; /* User Passkey Request */ 529d5859e22SJohan Hedberg events[6] |= 0x10; /* Remote OOB Data Request */ 530d5859e22SJohan Hedberg events[6] |= 0x20; /* Simple Pairing Complete */ 531d5859e22SJohan Hedberg events[7] |= 0x04; /* User Passkey Notification */ 532d5859e22SJohan Hedberg events[7] |= 0x08; /* Keypress Notification */ 533d5859e22SJohan Hedberg events[7] |= 0x10; /* Remote Host Supported 534d5859e22SJohan Hedberg * Features Notification */ 535d5859e22SJohan Hedberg } 536d5859e22SJohan Hedberg 537d5859e22SJohan Hedberg if (hdev->features[4] & LMP_LE) 538d5859e22SJohan Hedberg events[7] |= 0x20; /* LE Meta-Event */ 539d5859e22SJohan Hedberg 540d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); 541d5859e22SJohan Hedberg } 542d5859e22SJohan Hedberg 543e6100a25SAndre Guedes static void hci_set_le_support(struct hci_dev *hdev) 544e6100a25SAndre Guedes { 545e6100a25SAndre Guedes struct hci_cp_write_le_host_supported cp; 546e6100a25SAndre Guedes 547e6100a25SAndre Guedes memset(&cp, 0, sizeof(cp)); 548e6100a25SAndre Guedes 549e6100a25SAndre Guedes if (enable_le) { 550e6100a25SAndre Guedes cp.le = 1; 551e6100a25SAndre Guedes cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR); 552e6100a25SAndre Guedes } 553e6100a25SAndre Guedes 554e6100a25SAndre Guedes hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), &cp); 555e6100a25SAndre Guedes } 556e6100a25SAndre Guedes 557d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev) 558d5859e22SJohan Hedberg { 559d5859e22SJohan Hedberg hci_setup_event_mask(hdev); 560d5859e22SJohan Hedberg 561d5859e22SJohan Hedberg if (hdev->lmp_ver > 1) 562d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); 563d5859e22SJohan Hedberg 564d5859e22SJohan Hedberg if (hdev->features[6] & LMP_SIMPLE_PAIR) { 565d5859e22SJohan Hedberg u8 mode = 0x01; 566d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode); 567d5859e22SJohan Hedberg } 568d5859e22SJohan Hedberg 569d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 570d5859e22SJohan Hedberg hci_setup_inquiry_mode(hdev); 571d5859e22SJohan Hedberg 572d5859e22SJohan Hedberg if (hdev->features[7] & LMP_INQ_TX_PWR) 573d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL); 574971e3a4bSAndre Guedes 575971e3a4bSAndre Guedes if (hdev->features[7] & LMP_EXTFEATURES) { 576971e3a4bSAndre Guedes struct hci_cp_read_local_ext_features cp; 577971e3a4bSAndre Guedes 578971e3a4bSAndre Guedes cp.page = 0x01; 579971e3a4bSAndre Guedes hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, 580971e3a4bSAndre Guedes sizeof(cp), &cp); 581971e3a4bSAndre Guedes } 582e6100a25SAndre Guedes 583e6100a25SAndre Guedes if (hdev->features[4] & LMP_LE) 584e6100a25SAndre Guedes hci_set_le_support(hdev); 585d5859e22SJohan Hedberg } 586d5859e22SJohan Hedberg 587a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) 588a9de9248SMarcel Holtmann { 589a9de9248SMarcel Holtmann struct hci_rp_read_local_version *rp = (void *) skb->data; 5901143e5a6SMarcel Holtmann 591a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 5921143e5a6SMarcel Holtmann 593a9de9248SMarcel Holtmann if (rp->status) 594a9de9248SMarcel Holtmann return; 5951143e5a6SMarcel Holtmann 596a9de9248SMarcel Holtmann hdev->hci_ver = rp->hci_ver; 597e4e8e37cSMarcel Holtmann hdev->hci_rev = __le16_to_cpu(rp->hci_rev); 598d5859e22SJohan Hedberg hdev->lmp_ver = rp->lmp_ver; 599e4e8e37cSMarcel Holtmann hdev->manufacturer = __le16_to_cpu(rp->manufacturer); 600d5859e22SJohan Hedberg hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); 6011da177e4SLinus Torvalds 602a9de9248SMarcel Holtmann BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name, 603a9de9248SMarcel Holtmann hdev->manufacturer, 604a9de9248SMarcel Holtmann hdev->hci_ver, hdev->hci_rev); 605d5859e22SJohan Hedberg 606d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags)) 607d5859e22SJohan Hedberg hci_setup(hdev); 608d5859e22SJohan Hedberg } 609d5859e22SJohan Hedberg 610d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev) 611d5859e22SJohan Hedberg { 612d5859e22SJohan Hedberg u16 link_policy = 0; 613d5859e22SJohan Hedberg 614d5859e22SJohan Hedberg if (hdev->features[0] & LMP_RSWITCH) 615d5859e22SJohan Hedberg link_policy |= HCI_LP_RSWITCH; 616d5859e22SJohan Hedberg if (hdev->features[0] & LMP_HOLD) 617d5859e22SJohan Hedberg link_policy |= HCI_LP_HOLD; 618d5859e22SJohan Hedberg if (hdev->features[0] & LMP_SNIFF) 619d5859e22SJohan Hedberg link_policy |= HCI_LP_SNIFF; 620d5859e22SJohan Hedberg if (hdev->features[1] & LMP_PARK) 621d5859e22SJohan Hedberg link_policy |= HCI_LP_PARK; 622d5859e22SJohan Hedberg 623d5859e22SJohan Hedberg link_policy = cpu_to_le16(link_policy); 624d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, 625d5859e22SJohan Hedberg sizeof(link_policy), &link_policy); 6261da177e4SLinus Torvalds } 6271da177e4SLinus Torvalds 628a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb) 629a9de9248SMarcel Holtmann { 630a9de9248SMarcel Holtmann struct hci_rp_read_local_commands *rp = (void *) skb->data; 631a9de9248SMarcel Holtmann 632a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 633a9de9248SMarcel Holtmann 634a9de9248SMarcel Holtmann if (rp->status) 635d5859e22SJohan Hedberg goto done; 636a9de9248SMarcel Holtmann 637a9de9248SMarcel Holtmann memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); 638d5859e22SJohan Hedberg 639d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10)) 640d5859e22SJohan Hedberg hci_setup_link_policy(hdev); 641d5859e22SJohan Hedberg 642d5859e22SJohan Hedberg done: 643d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status); 644a9de9248SMarcel Holtmann } 645a9de9248SMarcel Holtmann 646a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb) 647a9de9248SMarcel Holtmann { 648a9de9248SMarcel Holtmann struct hci_rp_read_local_features *rp = (void *) skb->data; 649a9de9248SMarcel Holtmann 650a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 651a9de9248SMarcel Holtmann 652a9de9248SMarcel Holtmann if (rp->status) 653a9de9248SMarcel Holtmann return; 654a9de9248SMarcel Holtmann 655a9de9248SMarcel Holtmann memcpy(hdev->features, rp->features, 8); 6561da177e4SLinus Torvalds 6571da177e4SLinus Torvalds /* Adjust default settings according to features 6581da177e4SLinus Torvalds * supported by device. */ 659a9de9248SMarcel Holtmann 6601da177e4SLinus Torvalds if (hdev->features[0] & LMP_3SLOT) 6611da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM3 | HCI_DH3); 6621da177e4SLinus Torvalds 6631da177e4SLinus Torvalds if (hdev->features[0] & LMP_5SLOT) 6641da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM5 | HCI_DH5); 6651da177e4SLinus Torvalds 6665b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV2) { 6671da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV2); 6685b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV2); 6695b7f9909SMarcel Holtmann } 6701da177e4SLinus Torvalds 6715b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV3) { 6721da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV3); 6735b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV3); 6745b7f9909SMarcel Holtmann } 6755b7f9909SMarcel Holtmann 6765b7f9909SMarcel Holtmann if (hdev->features[3] & LMP_ESCO) 6775b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV3); 6785b7f9909SMarcel Holtmann 6795b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV4) 6805b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV4); 6815b7f9909SMarcel Holtmann 6825b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV5) 6835b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV5); 6841da177e4SLinus Torvalds 685efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_2M) 686efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV3); 687efc7688bSMarcel Holtmann 688efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_3M) 689efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_3EV3); 690efc7688bSMarcel Holtmann 691efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_3S_ESCO) 692efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); 693efc7688bSMarcel Holtmann 694a9de9248SMarcel Holtmann BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, 695a9de9248SMarcel Holtmann hdev->features[0], hdev->features[1], 696a9de9248SMarcel Holtmann hdev->features[2], hdev->features[3], 697a9de9248SMarcel Holtmann hdev->features[4], hdev->features[5], 698a9de9248SMarcel Holtmann hdev->features[6], hdev->features[7]); 6991da177e4SLinus Torvalds } 7001da177e4SLinus Torvalds 701971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev, 702971e3a4bSAndre Guedes struct sk_buff *skb) 703971e3a4bSAndre Guedes { 704971e3a4bSAndre Guedes struct hci_rp_read_local_ext_features *rp = (void *) skb->data; 705971e3a4bSAndre Guedes 706971e3a4bSAndre Guedes BT_DBG("%s status 0x%x", hdev->name, rp->status); 707971e3a4bSAndre Guedes 708971e3a4bSAndre Guedes if (rp->status) 709971e3a4bSAndre Guedes return; 710971e3a4bSAndre Guedes 711971e3a4bSAndre Guedes memcpy(hdev->extfeatures, rp->features, 8); 712971e3a4bSAndre Guedes 713971e3a4bSAndre Guedes hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status); 714971e3a4bSAndre Guedes } 715971e3a4bSAndre Guedes 716a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 717a9de9248SMarcel Holtmann { 718a9de9248SMarcel Holtmann struct hci_rp_read_buffer_size *rp = (void *) skb->data; 719a9de9248SMarcel Holtmann 720a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 721a9de9248SMarcel Holtmann 722a9de9248SMarcel Holtmann if (rp->status) 723a9de9248SMarcel Holtmann return; 724a9de9248SMarcel Holtmann 725a9de9248SMarcel Holtmann hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); 726a9de9248SMarcel Holtmann hdev->sco_mtu = rp->sco_mtu; 727a9de9248SMarcel Holtmann hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); 728a9de9248SMarcel Holtmann hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); 729da1f5198SMarcel Holtmann 730da1f5198SMarcel Holtmann if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { 731da1f5198SMarcel Holtmann hdev->sco_mtu = 64; 732da1f5198SMarcel Holtmann hdev->sco_pkts = 8; 733da1f5198SMarcel Holtmann } 734da1f5198SMarcel Holtmann 735da1f5198SMarcel Holtmann hdev->acl_cnt = hdev->acl_pkts; 736da1f5198SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 7371da177e4SLinus Torvalds 738a9de9248SMarcel Holtmann BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, 739a9de9248SMarcel Holtmann hdev->acl_mtu, hdev->acl_pkts, 740a9de9248SMarcel Holtmann hdev->sco_mtu, hdev->sco_pkts); 7411da177e4SLinus Torvalds } 7421da177e4SLinus Torvalds 743a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) 744a9de9248SMarcel Holtmann { 745a9de9248SMarcel Holtmann struct hci_rp_read_bd_addr *rp = (void *) skb->data; 7461da177e4SLinus Torvalds 747a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 748a9de9248SMarcel Holtmann 749a9de9248SMarcel Holtmann if (!rp->status) 750a9de9248SMarcel Holtmann bacpy(&hdev->bdaddr, &rp->bdaddr); 751a9de9248SMarcel Holtmann 75223bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status); 75323bb5763SJohan Hedberg } 75423bb5763SJohan Hedberg 75523bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb) 75623bb5763SJohan Hedberg { 75723bb5763SJohan Hedberg __u8 status = *((__u8 *) skb->data); 75823bb5763SJohan Hedberg 75923bb5763SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 76023bb5763SJohan Hedberg 76123bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status); 7621da177e4SLinus Torvalds } 7631da177e4SLinus Torvalds 764928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev, 765928abaa7SAndrei Emeltchenko struct sk_buff *skb) 766928abaa7SAndrei Emeltchenko { 767928abaa7SAndrei Emeltchenko struct hci_rp_read_local_amp_info *rp = (void *) skb->data; 768928abaa7SAndrei Emeltchenko 769928abaa7SAndrei Emeltchenko BT_DBG("%s status 0x%x", hdev->name, rp->status); 770928abaa7SAndrei Emeltchenko 771928abaa7SAndrei Emeltchenko if (rp->status) 772928abaa7SAndrei Emeltchenko return; 773928abaa7SAndrei Emeltchenko 774928abaa7SAndrei Emeltchenko hdev->amp_status = rp->amp_status; 775928abaa7SAndrei Emeltchenko hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); 776928abaa7SAndrei Emeltchenko hdev->amp_max_bw = __le32_to_cpu(rp->max_bw); 777928abaa7SAndrei Emeltchenko hdev->amp_min_latency = __le32_to_cpu(rp->min_latency); 778928abaa7SAndrei Emeltchenko hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu); 779928abaa7SAndrei Emeltchenko hdev->amp_type = rp->amp_type; 780928abaa7SAndrei Emeltchenko hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap); 781928abaa7SAndrei Emeltchenko hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size); 782928abaa7SAndrei Emeltchenko hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); 783928abaa7SAndrei Emeltchenko hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); 784928abaa7SAndrei Emeltchenko 785928abaa7SAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status); 786928abaa7SAndrei Emeltchenko } 787928abaa7SAndrei Emeltchenko 788b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, 789b0916ea0SJohan Hedberg struct sk_buff *skb) 790b0916ea0SJohan Hedberg { 791b0916ea0SJohan Hedberg __u8 status = *((__u8 *) skb->data); 792b0916ea0SJohan Hedberg 793b0916ea0SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 794b0916ea0SJohan Hedberg 795b0916ea0SJohan Hedberg hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status); 796b0916ea0SJohan Hedberg } 797b0916ea0SJohan Hedberg 798d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb) 799d5859e22SJohan Hedberg { 800d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 801d5859e22SJohan Hedberg 802d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 803d5859e22SJohan Hedberg 804d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status); 805d5859e22SJohan Hedberg } 806d5859e22SJohan Hedberg 807d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev, 808d5859e22SJohan Hedberg struct sk_buff *skb) 809d5859e22SJohan Hedberg { 810d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 811d5859e22SJohan Hedberg 812d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 813d5859e22SJohan Hedberg 814d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status); 815d5859e22SJohan Hedberg } 816d5859e22SJohan Hedberg 817d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, 818d5859e22SJohan Hedberg struct sk_buff *skb) 819d5859e22SJohan Hedberg { 820d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 821d5859e22SJohan Hedberg 822d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 823d5859e22SJohan Hedberg 824d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status); 825d5859e22SJohan Hedberg } 826d5859e22SJohan Hedberg 827d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb) 828d5859e22SJohan Hedberg { 829d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 830d5859e22SJohan Hedberg 831d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 832d5859e22SJohan Hedberg 833d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status); 834d5859e22SJohan Hedberg } 835d5859e22SJohan Hedberg 836980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) 837980e1a53SJohan Hedberg { 838980e1a53SJohan Hedberg struct hci_rp_pin_code_reply *rp = (void *) skb->data; 839980e1a53SJohan Hedberg struct hci_cp_pin_code_reply *cp; 840980e1a53SJohan Hedberg struct hci_conn *conn; 841980e1a53SJohan Hedberg 842980e1a53SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 843980e1a53SJohan Hedberg 84456e5cb86SJohan Hedberg hci_dev_lock(hdev); 84556e5cb86SJohan Hedberg 846980e1a53SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 847744cf19eSJohan Hedberg mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); 848980e1a53SJohan Hedberg 849980e1a53SJohan Hedberg if (rp->status != 0) 85056e5cb86SJohan Hedberg goto unlock; 851980e1a53SJohan Hedberg 852980e1a53SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); 853980e1a53SJohan Hedberg if (!cp) 85456e5cb86SJohan Hedberg goto unlock; 855980e1a53SJohan Hedberg 856980e1a53SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 857980e1a53SJohan Hedberg if (conn) 858980e1a53SJohan Hedberg conn->pin_length = cp->pin_len; 85956e5cb86SJohan Hedberg 86056e5cb86SJohan Hedberg unlock: 86156e5cb86SJohan Hedberg hci_dev_unlock(hdev); 862980e1a53SJohan Hedberg } 863980e1a53SJohan Hedberg 864980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 865980e1a53SJohan Hedberg { 866980e1a53SJohan Hedberg struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data; 867980e1a53SJohan Hedberg 868980e1a53SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 869980e1a53SJohan Hedberg 87056e5cb86SJohan Hedberg hci_dev_lock(hdev); 87156e5cb86SJohan Hedberg 872980e1a53SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 873744cf19eSJohan Hedberg mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr, 874980e1a53SJohan Hedberg rp->status); 87556e5cb86SJohan Hedberg 87656e5cb86SJohan Hedberg hci_dev_unlock(hdev); 877980e1a53SJohan Hedberg } 87856e5cb86SJohan Hedberg 8796ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, 8806ed58ec5SVille Tervo struct sk_buff *skb) 8816ed58ec5SVille Tervo { 8826ed58ec5SVille Tervo struct hci_rp_le_read_buffer_size *rp = (void *) skb->data; 8836ed58ec5SVille Tervo 8846ed58ec5SVille Tervo BT_DBG("%s status 0x%x", hdev->name, rp->status); 8856ed58ec5SVille Tervo 8866ed58ec5SVille Tervo if (rp->status) 8876ed58ec5SVille Tervo return; 8886ed58ec5SVille Tervo 8896ed58ec5SVille Tervo hdev->le_mtu = __le16_to_cpu(rp->le_mtu); 8906ed58ec5SVille Tervo hdev->le_pkts = rp->le_max_pkt; 8916ed58ec5SVille Tervo 8926ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 8936ed58ec5SVille Tervo 8946ed58ec5SVille Tervo BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); 8956ed58ec5SVille Tervo 8966ed58ec5SVille Tervo hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status); 8976ed58ec5SVille Tervo } 898980e1a53SJohan Hedberg 899a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) 900a5c29683SJohan Hedberg { 901a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 902a5c29683SJohan Hedberg 903a5c29683SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 904a5c29683SJohan Hedberg 90556e5cb86SJohan Hedberg hci_dev_lock(hdev); 90656e5cb86SJohan Hedberg 907a5c29683SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 908744cf19eSJohan Hedberg mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, 909a5c29683SJohan Hedberg rp->status); 91056e5cb86SJohan Hedberg 91156e5cb86SJohan Hedberg hci_dev_unlock(hdev); 912a5c29683SJohan Hedberg } 913a5c29683SJohan Hedberg 914a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, 915a5c29683SJohan Hedberg struct sk_buff *skb) 916a5c29683SJohan Hedberg { 917a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 918a5c29683SJohan Hedberg 919a5c29683SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 920a5c29683SJohan Hedberg 92156e5cb86SJohan Hedberg hci_dev_lock(hdev); 92256e5cb86SJohan Hedberg 923a5c29683SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 924744cf19eSJohan Hedberg mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr, 925a5c29683SJohan Hedberg rp->status); 92656e5cb86SJohan Hedberg 92756e5cb86SJohan Hedberg hci_dev_unlock(hdev); 928a5c29683SJohan Hedberg } 929a5c29683SJohan Hedberg 930c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, 931c35938b2SSzymon Janc struct sk_buff *skb) 932c35938b2SSzymon Janc { 933c35938b2SSzymon Janc struct hci_rp_read_local_oob_data *rp = (void *) skb->data; 934c35938b2SSzymon Janc 935c35938b2SSzymon Janc BT_DBG("%s status 0x%x", hdev->name, rp->status); 936c35938b2SSzymon Janc 93756e5cb86SJohan Hedberg hci_dev_lock(hdev); 938744cf19eSJohan Hedberg mgmt_read_local_oob_data_reply_complete(hdev, rp->hash, 939c35938b2SSzymon Janc rp->randomizer, rp->status); 94056e5cb86SJohan Hedberg hci_dev_unlock(hdev); 941c35938b2SSzymon Janc } 942c35938b2SSzymon Janc 943eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, 944eb9d91f5SAndre Guedes struct sk_buff *skb) 945eb9d91f5SAndre Guedes { 946eb9d91f5SAndre Guedes struct hci_cp_le_set_scan_enable *cp; 947eb9d91f5SAndre Guedes __u8 status = *((__u8 *) skb->data); 948eb9d91f5SAndre Guedes 949eb9d91f5SAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 950eb9d91f5SAndre Guedes 951eb9d91f5SAndre Guedes if (status) 952eb9d91f5SAndre Guedes return; 953eb9d91f5SAndre Guedes 954eb9d91f5SAndre Guedes cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE); 955eb9d91f5SAndre Guedes if (!cp) 956eb9d91f5SAndre Guedes return; 957eb9d91f5SAndre Guedes 95835815085SAndre Guedes if (cp->enable == 0x01) { 95935815085SAndre Guedes del_timer(&hdev->adv_timer); 960a8f13c8cSAndre Guedes 961a8f13c8cSAndre Guedes hci_dev_lock(hdev); 962eb9d91f5SAndre Guedes hci_adv_entries_clear(hdev); 963a8f13c8cSAndre Guedes hci_dev_unlock(hdev); 96435815085SAndre Guedes } else if (cp->enable == 0x00) { 96535815085SAndre Guedes mod_timer(&hdev->adv_timer, jiffies + ADV_CLEAR_TIMEOUT); 96635815085SAndre Guedes } 967eb9d91f5SAndre Guedes } 968eb9d91f5SAndre Guedes 969a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb) 970a7a595f6SVinicius Costa Gomes { 971a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_reply *rp = (void *) skb->data; 972a7a595f6SVinicius Costa Gomes 973a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, rp->status); 974a7a595f6SVinicius Costa Gomes 975a7a595f6SVinicius Costa Gomes if (rp->status) 976a7a595f6SVinicius Costa Gomes return; 977a7a595f6SVinicius Costa Gomes 978a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status); 979a7a595f6SVinicius Costa Gomes } 980a7a595f6SVinicius Costa Gomes 981a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 982a7a595f6SVinicius Costa Gomes { 983a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data; 984a7a595f6SVinicius Costa Gomes 985a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, rp->status); 986a7a595f6SVinicius Costa Gomes 987a7a595f6SVinicius Costa Gomes if (rp->status) 988a7a595f6SVinicius Costa Gomes return; 989a7a595f6SVinicius Costa Gomes 990a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status); 991a7a595f6SVinicius Costa Gomes } 992a7a595f6SVinicius Costa Gomes 993f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev, 994f9b49306SAndre Guedes struct sk_buff *skb) 995f9b49306SAndre Guedes { 996f9b49306SAndre Guedes struct hci_cp_read_local_ext_features cp; 997f9b49306SAndre Guedes __u8 status = *((__u8 *) skb->data); 998f9b49306SAndre Guedes 999f9b49306SAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 1000f9b49306SAndre Guedes 1001f9b49306SAndre Guedes if (status) 1002f9b49306SAndre Guedes return; 1003f9b49306SAndre Guedes 1004f9b49306SAndre Guedes cp.page = 0x01; 1005f9b49306SAndre Guedes hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp); 1006f9b49306SAndre Guedes } 1007f9b49306SAndre Guedes 1008a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 1009a9de9248SMarcel Holtmann { 1010a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1011a9de9248SMarcel Holtmann 1012a9de9248SMarcel Holtmann if (status) { 101323bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 1014a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 101556e5cb86SJohan Hedberg hci_dev_lock(hdev); 1016164a6e78SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 1017744cf19eSJohan Hedberg mgmt_inquiry_failed(hdev, status); 101856e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1019314b2381SJohan Hedberg return; 1020314b2381SJohan Hedberg } 1021314b2381SJohan Hedberg 102289352e7dSAndre Guedes set_bit(HCI_INQUIRY, &hdev->flags); 102389352e7dSAndre Guedes 102456e5cb86SJohan Hedberg hci_dev_lock(hdev); 1025744cf19eSJohan Hedberg mgmt_discovering(hdev, 1); 102656e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1027a9de9248SMarcel Holtmann } 1028a9de9248SMarcel Holtmann 10291da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 10301da177e4SLinus Torvalds { 1031a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 10321da177e4SLinus Torvalds struct hci_conn *conn; 10331da177e4SLinus Torvalds 1034a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1035a9de9248SMarcel Holtmann 1036a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 10371da177e4SLinus Torvalds if (!cp) 10381da177e4SLinus Torvalds return; 10391da177e4SLinus Torvalds 10401da177e4SLinus Torvalds hci_dev_lock(hdev); 10411da177e4SLinus Torvalds 10421da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 10431da177e4SLinus Torvalds 1044a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn); 10451da177e4SLinus Torvalds 10461da177e4SLinus Torvalds if (status) { 10471da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 10484c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 10491da177e4SLinus Torvalds conn->state = BT_CLOSED; 10501da177e4SLinus Torvalds hci_proto_connect_cfm(conn, status); 10511da177e4SLinus Torvalds hci_conn_del(conn); 10524c67bc74SMarcel Holtmann } else 10534c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 10541da177e4SLinus Torvalds } 10551da177e4SLinus Torvalds } else { 10561da177e4SLinus Torvalds if (!conn) { 10571da177e4SLinus Torvalds conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); 10581da177e4SLinus Torvalds if (conn) { 10591da177e4SLinus Torvalds conn->out = 1; 10601da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 10611da177e4SLinus Torvalds } else 1062893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 10631da177e4SLinus Torvalds } 10641da177e4SLinus Torvalds } 10651da177e4SLinus Torvalds 10661da177e4SLinus Torvalds hci_dev_unlock(hdev); 10671da177e4SLinus Torvalds } 10681da177e4SLinus Torvalds 1069a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 10701da177e4SLinus Torvalds { 1071a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 10721da177e4SLinus Torvalds struct hci_conn *acl, *sco; 10731da177e4SLinus Torvalds __u16 handle; 10741da177e4SLinus Torvalds 1075b6a0dc82SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1076b6a0dc82SMarcel Holtmann 1077a9de9248SMarcel Holtmann if (!status) 1078a9de9248SMarcel Holtmann return; 1079a9de9248SMarcel Holtmann 1080a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 10811da177e4SLinus Torvalds if (!cp) 1082a9de9248SMarcel Holtmann return; 10831da177e4SLinus Torvalds 10841da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 10851da177e4SLinus Torvalds 1086a9de9248SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 10871da177e4SLinus Torvalds 10881da177e4SLinus Torvalds hci_dev_lock(hdev); 10891da177e4SLinus Torvalds 10901da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 10915a08ecceSAndrei Emeltchenko if (acl) { 10925a08ecceSAndrei Emeltchenko sco = acl->link; 10935a08ecceSAndrei Emeltchenko if (sco) { 10941da177e4SLinus Torvalds sco->state = BT_CLOSED; 10951da177e4SLinus Torvalds 10961da177e4SLinus Torvalds hci_proto_connect_cfm(sco, status); 10971da177e4SLinus Torvalds hci_conn_del(sco); 10981da177e4SLinus Torvalds } 10995a08ecceSAndrei Emeltchenko } 11001da177e4SLinus Torvalds 11011da177e4SLinus Torvalds hci_dev_unlock(hdev); 11021da177e4SLinus Torvalds } 11031da177e4SLinus Torvalds 1104f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 1105f8558555SMarcel Holtmann { 1106f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 1107f8558555SMarcel Holtmann struct hci_conn *conn; 1108f8558555SMarcel Holtmann 1109f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1110f8558555SMarcel Holtmann 1111f8558555SMarcel Holtmann if (!status) 1112f8558555SMarcel Holtmann return; 1113f8558555SMarcel Holtmann 1114f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 1115f8558555SMarcel Holtmann if (!cp) 1116f8558555SMarcel Holtmann return; 1117f8558555SMarcel Holtmann 1118f8558555SMarcel Holtmann hci_dev_lock(hdev); 1119f8558555SMarcel Holtmann 1120f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1121f8558555SMarcel Holtmann if (conn) { 1122f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1123f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1124f8558555SMarcel Holtmann hci_conn_put(conn); 1125f8558555SMarcel Holtmann } 1126f8558555SMarcel Holtmann } 1127f8558555SMarcel Holtmann 1128f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1129f8558555SMarcel Holtmann } 1130f8558555SMarcel Holtmann 1131f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 1132f8558555SMarcel Holtmann { 1133f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 1134f8558555SMarcel Holtmann struct hci_conn *conn; 1135f8558555SMarcel Holtmann 1136f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1137f8558555SMarcel Holtmann 1138f8558555SMarcel Holtmann if (!status) 1139f8558555SMarcel Holtmann return; 1140f8558555SMarcel Holtmann 1141f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 1142f8558555SMarcel Holtmann if (!cp) 1143f8558555SMarcel Holtmann return; 1144f8558555SMarcel Holtmann 1145f8558555SMarcel Holtmann hci_dev_lock(hdev); 1146f8558555SMarcel Holtmann 1147f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1148f8558555SMarcel Holtmann if (conn) { 1149f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1150f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1151f8558555SMarcel Holtmann hci_conn_put(conn); 1152f8558555SMarcel Holtmann } 1153f8558555SMarcel Holtmann } 1154f8558555SMarcel Holtmann 1155f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1156f8558555SMarcel Holtmann } 1157f8558555SMarcel Holtmann 1158127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev, 1159392599b9SJohan Hedberg struct hci_conn *conn) 1160392599b9SJohan Hedberg { 1161392599b9SJohan Hedberg if (conn->state != BT_CONFIG || !conn->out) 1162392599b9SJohan Hedberg return 0; 1163392599b9SJohan Hedberg 1164765c2a96SJohan Hedberg if (conn->pending_sec_level == BT_SECURITY_SDP) 1165392599b9SJohan Hedberg return 0; 1166392599b9SJohan Hedberg 1167392599b9SJohan Hedberg /* Only request authentication for SSP connections or non-SSP 1168e9bf2bf0SVinicius Costa Gomes * devices with sec_level HIGH or if MITM protection is requested */ 1169392599b9SJohan Hedberg if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) && 1170e9bf2bf0SVinicius Costa Gomes conn->pending_sec_level != BT_SECURITY_HIGH && 1171e9bf2bf0SVinicius Costa Gomes !(conn->auth_type & 0x01)) 1172392599b9SJohan Hedberg return 0; 1173392599b9SJohan Hedberg 1174392599b9SJohan Hedberg return 1; 1175392599b9SJohan Hedberg } 1176392599b9SJohan Hedberg 1177a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 11781da177e4SLinus Torvalds { 1179127178d2SJohan Hedberg struct hci_cp_remote_name_req *cp; 1180127178d2SJohan Hedberg struct hci_conn *conn; 1181127178d2SJohan Hedberg 1182a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1183127178d2SJohan Hedberg 1184127178d2SJohan Hedberg /* If successful wait for the name req complete event before 1185127178d2SJohan Hedberg * checking for the need to do authentication */ 1186127178d2SJohan Hedberg if (!status) 1187127178d2SJohan Hedberg return; 1188127178d2SJohan Hedberg 1189127178d2SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); 1190127178d2SJohan Hedberg if (!cp) 1191127178d2SJohan Hedberg return; 1192127178d2SJohan Hedberg 1193127178d2SJohan Hedberg hci_dev_lock(hdev); 1194127178d2SJohan Hedberg 1195127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 119679c6c70cSJohan Hedberg if (!conn) 119779c6c70cSJohan Hedberg goto unlock; 119879c6c70cSJohan Hedberg 119979c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 120079c6c70cSJohan Hedberg goto unlock; 120179c6c70cSJohan Hedberg 120279c6c70cSJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { 1203127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1204127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1205127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1206127178d2SJohan Hedberg } 1207127178d2SJohan Hedberg 120879c6c70cSJohan Hedberg unlock: 1209127178d2SJohan Hedberg hci_dev_unlock(hdev); 1210a9de9248SMarcel Holtmann } 12111da177e4SLinus Torvalds 1212769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 1213769be974SMarcel Holtmann { 1214769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 1215769be974SMarcel Holtmann struct hci_conn *conn; 1216769be974SMarcel Holtmann 1217769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1218769be974SMarcel Holtmann 1219769be974SMarcel Holtmann if (!status) 1220769be974SMarcel Holtmann return; 1221769be974SMarcel Holtmann 1222769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 1223769be974SMarcel Holtmann if (!cp) 1224769be974SMarcel Holtmann return; 1225769be974SMarcel Holtmann 1226769be974SMarcel Holtmann hci_dev_lock(hdev); 1227769be974SMarcel Holtmann 1228769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1229769be974SMarcel Holtmann if (conn) { 1230769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1231769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1232769be974SMarcel Holtmann hci_conn_put(conn); 1233769be974SMarcel Holtmann } 1234769be974SMarcel Holtmann } 1235769be974SMarcel Holtmann 1236769be974SMarcel Holtmann hci_dev_unlock(hdev); 1237769be974SMarcel Holtmann } 1238769be974SMarcel Holtmann 1239769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 1240769be974SMarcel Holtmann { 1241769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features *cp; 1242769be974SMarcel Holtmann struct hci_conn *conn; 1243769be974SMarcel Holtmann 1244769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1245769be974SMarcel Holtmann 1246769be974SMarcel Holtmann if (!status) 1247769be974SMarcel Holtmann return; 1248769be974SMarcel Holtmann 1249769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 1250769be974SMarcel Holtmann if (!cp) 1251769be974SMarcel Holtmann return; 1252769be974SMarcel Holtmann 1253769be974SMarcel Holtmann hci_dev_lock(hdev); 1254769be974SMarcel Holtmann 1255769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1256769be974SMarcel Holtmann if (conn) { 1257769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1258769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1259769be974SMarcel Holtmann hci_conn_put(conn); 1260769be974SMarcel Holtmann } 1261769be974SMarcel Holtmann } 1262769be974SMarcel Holtmann 1263769be974SMarcel Holtmann hci_dev_unlock(hdev); 1264769be974SMarcel Holtmann } 1265769be974SMarcel Holtmann 1266a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 1267a9de9248SMarcel Holtmann { 1268b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 1269b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 1270b6a0dc82SMarcel Holtmann __u16 handle; 1271b6a0dc82SMarcel Holtmann 1272a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1273b6a0dc82SMarcel Holtmann 1274b6a0dc82SMarcel Holtmann if (!status) 1275b6a0dc82SMarcel Holtmann return; 1276b6a0dc82SMarcel Holtmann 1277b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 1278b6a0dc82SMarcel Holtmann if (!cp) 1279b6a0dc82SMarcel Holtmann return; 1280b6a0dc82SMarcel Holtmann 1281b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 1282b6a0dc82SMarcel Holtmann 1283b6a0dc82SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 1284b6a0dc82SMarcel Holtmann 1285b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 1286b6a0dc82SMarcel Holtmann 1287b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 12885a08ecceSAndrei Emeltchenko if (acl) { 12895a08ecceSAndrei Emeltchenko sco = acl->link; 12905a08ecceSAndrei Emeltchenko if (sco) { 1291b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 1292b6a0dc82SMarcel Holtmann 1293b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(sco, status); 1294b6a0dc82SMarcel Holtmann hci_conn_del(sco); 1295b6a0dc82SMarcel Holtmann } 12965a08ecceSAndrei Emeltchenko } 1297b6a0dc82SMarcel Holtmann 1298b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 1299a9de9248SMarcel Holtmann } 1300a9de9248SMarcel Holtmann 1301a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 1302a9de9248SMarcel Holtmann { 1303a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 130404837f64SMarcel Holtmann struct hci_conn *conn; 130504837f64SMarcel Holtmann 1306a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1307a9de9248SMarcel Holtmann 1308a9de9248SMarcel Holtmann if (!status) 1309a9de9248SMarcel Holtmann return; 1310a9de9248SMarcel Holtmann 1311a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 131204837f64SMarcel Holtmann if (!cp) 1313a9de9248SMarcel Holtmann return; 131404837f64SMarcel Holtmann 131504837f64SMarcel Holtmann hci_dev_lock(hdev); 131604837f64SMarcel Holtmann 131704837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1318e73439d8SMarcel Holtmann if (conn) { 131904837f64SMarcel Holtmann clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); 132004837f64SMarcel Holtmann 1321e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 1322e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1323e73439d8SMarcel Holtmann } 1324e73439d8SMarcel Holtmann 132504837f64SMarcel Holtmann hci_dev_unlock(hdev); 132604837f64SMarcel Holtmann } 132704837f64SMarcel Holtmann 1328a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 1329a9de9248SMarcel Holtmann { 1330a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 133104837f64SMarcel Holtmann struct hci_conn *conn; 133204837f64SMarcel Holtmann 1333a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1334a9de9248SMarcel Holtmann 1335a9de9248SMarcel Holtmann if (!status) 1336a9de9248SMarcel Holtmann return; 1337a9de9248SMarcel Holtmann 1338a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 133904837f64SMarcel Holtmann if (!cp) 1340a9de9248SMarcel Holtmann return; 134104837f64SMarcel Holtmann 134204837f64SMarcel Holtmann hci_dev_lock(hdev); 134304837f64SMarcel Holtmann 134404837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1345e73439d8SMarcel Holtmann if (conn) { 134604837f64SMarcel Holtmann clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); 134704837f64SMarcel Holtmann 1348e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 1349e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1350e73439d8SMarcel Holtmann } 1351e73439d8SMarcel Holtmann 135204837f64SMarcel Holtmann hci_dev_unlock(hdev); 135304837f64SMarcel Holtmann } 135404837f64SMarcel Holtmann 1355fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) 1356fcd89c09SVille Tervo { 1357fcd89c09SVille Tervo struct hci_cp_le_create_conn *cp; 1358fcd89c09SVille Tervo struct hci_conn *conn; 1359fcd89c09SVille Tervo 1360fcd89c09SVille Tervo BT_DBG("%s status 0x%x", hdev->name, status); 1361fcd89c09SVille Tervo 1362fcd89c09SVille Tervo cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN); 1363fcd89c09SVille Tervo if (!cp) 1364fcd89c09SVille Tervo return; 1365fcd89c09SVille Tervo 1366fcd89c09SVille Tervo hci_dev_lock(hdev); 1367fcd89c09SVille Tervo 1368fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr); 1369fcd89c09SVille Tervo 1370fcd89c09SVille Tervo BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr), 1371fcd89c09SVille Tervo conn); 1372fcd89c09SVille Tervo 1373fcd89c09SVille Tervo if (status) { 1374fcd89c09SVille Tervo if (conn && conn->state == BT_CONNECT) { 1375fcd89c09SVille Tervo conn->state = BT_CLOSED; 1376fcd89c09SVille Tervo hci_proto_connect_cfm(conn, status); 1377fcd89c09SVille Tervo hci_conn_del(conn); 1378fcd89c09SVille Tervo } 1379fcd89c09SVille Tervo } else { 1380fcd89c09SVille Tervo if (!conn) { 1381fcd89c09SVille Tervo conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr); 138229b7988aSAndre Guedes if (conn) { 138329b7988aSAndre Guedes conn->dst_type = cp->peer_addr_type; 1384fcd89c09SVille Tervo conn->out = 1; 138529b7988aSAndre Guedes } else { 1386fcd89c09SVille Tervo BT_ERR("No memory for new connection"); 1387fcd89c09SVille Tervo } 1388fcd89c09SVille Tervo } 138929b7988aSAndre Guedes } 1390fcd89c09SVille Tervo 1391fcd89c09SVille Tervo hci_dev_unlock(hdev); 1392fcd89c09SVille Tervo } 1393fcd89c09SVille Tervo 1394a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) 1395a7a595f6SVinicius Costa Gomes { 1396a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, status); 1397a7a595f6SVinicius Costa Gomes } 1398a7a595f6SVinicius Costa Gomes 13991da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 14001da177e4SLinus Torvalds { 14011da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 14021da177e4SLinus Torvalds 14031da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, status); 14041da177e4SLinus Torvalds 140523bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 14066bd57416SMarcel Holtmann 1407a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 140889352e7dSAndre Guedes 140989352e7dSAndre Guedes if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) 141089352e7dSAndre Guedes return; 141189352e7dSAndre Guedes 141256e5cb86SJohan Hedberg hci_dev_lock(hdev); 1413744cf19eSJohan Hedberg mgmt_discovering(hdev, 0); 141456e5cb86SJohan Hedberg hci_dev_unlock(hdev); 14151da177e4SLinus Torvalds } 14161da177e4SLinus Torvalds 14171da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 14181da177e4SLinus Torvalds { 141945bb4bf0SMarcel Holtmann struct inquiry_data data; 1420a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 14211da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 14221da177e4SLinus Torvalds 14231da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 14241da177e4SLinus Torvalds 142545bb4bf0SMarcel Holtmann if (!num_rsp) 142645bb4bf0SMarcel Holtmann return; 142745bb4bf0SMarcel Holtmann 14281da177e4SLinus Torvalds hci_dev_lock(hdev); 142945bb4bf0SMarcel Holtmann 1430e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 14311da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 14321da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 14331da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 14341da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 14351da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 14361da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 14371da177e4SLinus Torvalds data.rssi = 0x00; 143841a96212SMarcel Holtmann data.ssp_mode = 0x00; 14391da177e4SLinus Torvalds hci_inquiry_cache_update(hdev, &data); 144048264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 14414c659c39SJohan Hedberg info->dev_class, 0, NULL); 14421da177e4SLinus Torvalds } 144345bb4bf0SMarcel Holtmann 14441da177e4SLinus Torvalds hci_dev_unlock(hdev); 14451da177e4SLinus Torvalds } 14461da177e4SLinus Torvalds 1447a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 14481da177e4SLinus Torvalds { 1449a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 1450a9de9248SMarcel Holtmann struct hci_conn *conn; 14511da177e4SLinus Torvalds 1452a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 145345bb4bf0SMarcel Holtmann 14541da177e4SLinus Torvalds hci_dev_lock(hdev); 145545bb4bf0SMarcel Holtmann 1456a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 14579499237aSMarcel Holtmann if (!conn) { 14589499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 14599499237aSMarcel Holtmann goto unlock; 14609499237aSMarcel Holtmann 14619499237aSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 1462a9de9248SMarcel Holtmann if (!conn) 1463a9de9248SMarcel Holtmann goto unlock; 146445bb4bf0SMarcel Holtmann 14659499237aSMarcel Holtmann conn->type = SCO_LINK; 14669499237aSMarcel Holtmann } 14679499237aSMarcel Holtmann 1468a9de9248SMarcel Holtmann if (!ev->status) { 1469a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 1470769be974SMarcel Holtmann 1471769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 1472769be974SMarcel Holtmann conn->state = BT_CONFIG; 1473769be974SMarcel Holtmann hci_conn_hold(conn); 1474052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 147548264f06SJohan Hedberg mgmt_connected(hdev, &ev->bdaddr, conn->type, 147648264f06SJohan Hedberg conn->dst_type); 1477769be974SMarcel Holtmann } else 1478a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 1479a9de9248SMarcel Holtmann 14809eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 14817d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 14827d0db0a3SMarcel Holtmann 1483a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 1484a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1485a9de9248SMarcel Holtmann 1486a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 1487a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1488a9de9248SMarcel Holtmann 1489a9de9248SMarcel Holtmann /* Get remote features */ 1490a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 1491a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 1492a9de9248SMarcel Holtmann cp.handle = ev->handle; 1493769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 1494769be974SMarcel Holtmann sizeof(cp), &cp); 149545bb4bf0SMarcel Holtmann } 1496a9de9248SMarcel Holtmann 1497a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 1498a8746417SMarcel Holtmann if (!conn->out && hdev->hci_ver < 3) { 1499a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 1500a9de9248SMarcel Holtmann cp.handle = ev->handle; 1501a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1502a8746417SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, 1503a8746417SMarcel Holtmann sizeof(cp), &cp); 1504a9de9248SMarcel Holtmann } 150517d5c04cSJohan Hedberg } else { 1506a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 150717d5c04cSJohan Hedberg if (conn->type == ACL_LINK) 1508744cf19eSJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 150948264f06SJohan Hedberg conn->dst_type, ev->status); 151017d5c04cSJohan Hedberg } 151145bb4bf0SMarcel Holtmann 1512e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 1513e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 151445bb4bf0SMarcel Holtmann 1515769be974SMarcel Holtmann if (ev->status) { 1516a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1517a9de9248SMarcel Holtmann hci_conn_del(conn); 1518c89b6e6bSMarcel Holtmann } else if (ev->link_type != ACL_LINK) 1519c89b6e6bSMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1520a9de9248SMarcel Holtmann 1521a9de9248SMarcel Holtmann unlock: 15221da177e4SLinus Torvalds hci_dev_unlock(hdev); 1523a9de9248SMarcel Holtmann 1524a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 15251da177e4SLinus Torvalds } 15261da177e4SLinus Torvalds 15271da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 15281da177e4SLinus Torvalds { 1529a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 15301da177e4SLinus Torvalds int mask = hdev->link_mode; 15311da177e4SLinus Torvalds 1532a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s type 0x%x", hdev->name, 15331da177e4SLinus Torvalds batostr(&ev->bdaddr), ev->link_type); 15341da177e4SLinus Torvalds 15351da177e4SLinus Torvalds mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); 15361da177e4SLinus Torvalds 1537138d22efSSzymon Janc if ((mask & HCI_LM_ACCEPT) && 1538138d22efSSzymon Janc !hci_blacklist_lookup(hdev, &ev->bdaddr)) { 15391da177e4SLinus Torvalds /* Connection accepted */ 1540c7bdd502SMarcel Holtmann struct inquiry_entry *ie; 15411da177e4SLinus Torvalds struct hci_conn *conn; 15421da177e4SLinus Torvalds 15431da177e4SLinus Torvalds hci_dev_lock(hdev); 1544b6a0dc82SMarcel Holtmann 1545cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 1546cc11b9c1SAndrei Emeltchenko if (ie) 1547c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 1548c7bdd502SMarcel Holtmann 15491da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 15501da177e4SLinus Torvalds if (!conn) { 1551cc11b9c1SAndrei Emeltchenko conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); 1552cc11b9c1SAndrei Emeltchenko if (!conn) { 1553893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 15541da177e4SLinus Torvalds hci_dev_unlock(hdev); 15551da177e4SLinus Torvalds return; 15561da177e4SLinus Torvalds } 15571da177e4SLinus Torvalds } 1558b6a0dc82SMarcel Holtmann 15591da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 15601da177e4SLinus Torvalds conn->state = BT_CONNECT; 1561b6a0dc82SMarcel Holtmann 15621da177e4SLinus Torvalds hci_dev_unlock(hdev); 15631da177e4SLinus Torvalds 1564b6a0dc82SMarcel Holtmann if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) { 1565b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 1566b6a0dc82SMarcel Holtmann 15671da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 15681da177e4SLinus Torvalds 15691da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 15701da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 15711da177e4SLinus Torvalds else 15721da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 15731da177e4SLinus Torvalds 1574b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, 1575b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1576b6a0dc82SMarcel Holtmann } else { 1577b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 1578b6a0dc82SMarcel Holtmann 1579b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 1580a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1581b6a0dc82SMarcel Holtmann 1582b6a0dc82SMarcel Holtmann cp.tx_bandwidth = cpu_to_le32(0x00001f40); 1583b6a0dc82SMarcel Holtmann cp.rx_bandwidth = cpu_to_le32(0x00001f40); 1584b6a0dc82SMarcel Holtmann cp.max_latency = cpu_to_le16(0xffff); 1585b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 1586b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 1587b6a0dc82SMarcel Holtmann 1588b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 1589b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1590b6a0dc82SMarcel Holtmann } 15911da177e4SLinus Torvalds } else { 15921da177e4SLinus Torvalds /* Connection rejected */ 15931da177e4SLinus Torvalds struct hci_cp_reject_conn_req cp; 15941da177e4SLinus Torvalds 15951da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 15969f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_REJ_BAD_ADDR; 1597a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 15981da177e4SLinus Torvalds } 15991da177e4SLinus Torvalds } 16001da177e4SLinus Torvalds 16011da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 16021da177e4SLinus Torvalds { 1603a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 160404837f64SMarcel Holtmann struct hci_conn *conn; 16051da177e4SLinus Torvalds 16061da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 16071da177e4SLinus Torvalds 16081da177e4SLinus Torvalds hci_dev_lock(hdev); 16091da177e4SLinus Torvalds 161004837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1611f7520543SJohan Hedberg if (!conn) 1612f7520543SJohan Hedberg goto unlock; 1613f7520543SJohan Hedberg 161437d9ef76SJohan Hedberg if (ev->status == 0) 16151da177e4SLinus Torvalds conn->state = BT_CLOSED; 16167d0db0a3SMarcel Holtmann 161737d9ef76SJohan Hedberg if (conn->type == ACL_LINK || conn->type == LE_LINK) { 161837d9ef76SJohan Hedberg if (ev->status != 0) 161937d9ef76SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, ev->status); 162037d9ef76SJohan Hedberg else 162148264f06SJohan Hedberg mgmt_disconnected(hdev, &conn->dst, conn->type, 162248264f06SJohan Hedberg conn->dst_type); 162337d9ef76SJohan Hedberg } 1624f7520543SJohan Hedberg 162537d9ef76SJohan Hedberg if (ev->status == 0) { 16262950f21aSMarcel Holtmann hci_proto_disconn_cfm(conn, ev->reason); 16271da177e4SLinus Torvalds hci_conn_del(conn); 162837d9ef76SJohan Hedberg } 16291da177e4SLinus Torvalds 1630f7520543SJohan Hedberg unlock: 16311da177e4SLinus Torvalds hci_dev_unlock(hdev); 16321da177e4SLinus Torvalds } 16331da177e4SLinus Torvalds 1634a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1635a9de9248SMarcel Holtmann { 1636a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 1637a9de9248SMarcel Holtmann struct hci_conn *conn; 1638a9de9248SMarcel Holtmann 1639a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1640a9de9248SMarcel Holtmann 1641a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1642a9de9248SMarcel Holtmann 1643a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1644d7556e20SWaldemar Rymarkiewicz if (!conn) 1645d7556e20SWaldemar Rymarkiewicz goto unlock; 1646d7556e20SWaldemar Rymarkiewicz 1647765c2a96SJohan Hedberg if (!ev->status) { 164819f8def0SWaldemar Rymarkiewicz if (!(conn->ssp_mode > 0 && hdev->ssp_mode > 0) && 1649d7556e20SWaldemar Rymarkiewicz test_bit(HCI_CONN_REAUTH_PEND, &conn->pend)) { 1650d7556e20SWaldemar Rymarkiewicz BT_INFO("re-auth of legacy device is not possible."); 165119f8def0SWaldemar Rymarkiewicz } else { 1652a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1653765c2a96SJohan Hedberg conn->sec_level = conn->pending_sec_level; 165419f8def0SWaldemar Rymarkiewicz } 16552a611692SJohan Hedberg } else { 1656744cf19eSJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, ev->status); 16572a611692SJohan Hedberg } 1658a9de9248SMarcel Holtmann 1659a9de9248SMarcel Holtmann clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); 166019f8def0SWaldemar Rymarkiewicz clear_bit(HCI_CONN_REAUTH_PEND, &conn->pend); 1661a9de9248SMarcel Holtmann 1662f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1663d7556e20SWaldemar Rymarkiewicz if (!ev->status && hdev->ssp_mode > 0 && conn->ssp_mode > 0) { 1664f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1665f8558555SMarcel Holtmann cp.handle = ev->handle; 1666f8558555SMarcel Holtmann cp.encrypt = 0x01; 1667d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1668d7556e20SWaldemar Rymarkiewicz &cp); 1669f8558555SMarcel Holtmann } else { 1670f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1671f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1672f8558555SMarcel Holtmann hci_conn_put(conn); 1673f8558555SMarcel Holtmann } 1674052b30b0SMarcel Holtmann } else { 1675a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 1676a9de9248SMarcel Holtmann 1677052b30b0SMarcel Holtmann hci_conn_hold(conn); 1678052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1679052b30b0SMarcel Holtmann hci_conn_put(conn); 1680052b30b0SMarcel Holtmann } 1681052b30b0SMarcel Holtmann 1682a9de9248SMarcel Holtmann if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) { 1683a9de9248SMarcel Holtmann if (!ev->status) { 1684a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1685f8558555SMarcel Holtmann cp.handle = ev->handle; 1686f8558555SMarcel Holtmann cp.encrypt = 0x01; 1687d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1688d7556e20SWaldemar Rymarkiewicz &cp); 1689a9de9248SMarcel Holtmann } else { 1690a9de9248SMarcel Holtmann clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); 1691a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 1692a9de9248SMarcel Holtmann } 1693a9de9248SMarcel Holtmann } 1694a9de9248SMarcel Holtmann 1695d7556e20SWaldemar Rymarkiewicz unlock: 1696a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1697a9de9248SMarcel Holtmann } 1698a9de9248SMarcel Holtmann 1699a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 1700a9de9248SMarcel Holtmann { 1701127178d2SJohan Hedberg struct hci_ev_remote_name *ev = (void *) skb->data; 1702127178d2SJohan Hedberg struct hci_conn *conn; 1703127178d2SJohan Hedberg 1704a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1705a9de9248SMarcel Holtmann 1706a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 1707127178d2SJohan Hedberg 1708127178d2SJohan Hedberg hci_dev_lock(hdev); 1709127178d2SJohan Hedberg 1710a88a9652SJohan Hedberg if (ev->status == 0 && test_bit(HCI_MGMT, &hdev->flags)) 1711744cf19eSJohan Hedberg mgmt_remote_name(hdev, &ev->bdaddr, ev->name); 1712a88a9652SJohan Hedberg 1713127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 171479c6c70cSJohan Hedberg if (!conn) 171579c6c70cSJohan Hedberg goto unlock; 171679c6c70cSJohan Hedberg 171779c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 171879c6c70cSJohan Hedberg goto unlock; 171979c6c70cSJohan Hedberg 172079c6c70cSJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { 1721127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1722127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1723127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1724127178d2SJohan Hedberg } 1725127178d2SJohan Hedberg 172679c6c70cSJohan Hedberg unlock: 1727127178d2SJohan Hedberg hci_dev_unlock(hdev); 1728a9de9248SMarcel Holtmann } 1729a9de9248SMarcel Holtmann 1730a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 1731a9de9248SMarcel Holtmann { 1732a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 1733a9de9248SMarcel Holtmann struct hci_conn *conn; 1734a9de9248SMarcel Holtmann 1735a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1736a9de9248SMarcel Holtmann 1737a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1738a9de9248SMarcel Holtmann 1739a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1740a9de9248SMarcel Holtmann if (conn) { 1741a9de9248SMarcel Holtmann if (!ev->status) { 1742ae293196SMarcel Holtmann if (ev->encrypt) { 1743ae293196SMarcel Holtmann /* Encryption implies authentication */ 1744ae293196SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1745a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1746da85e5e5SVinicius Costa Gomes conn->sec_level = conn->pending_sec_level; 1747ae293196SMarcel Holtmann } else 1748a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_ENCRYPT; 1749a9de9248SMarcel Holtmann } 1750a9de9248SMarcel Holtmann 1751a9de9248SMarcel Holtmann clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); 1752a9de9248SMarcel Holtmann 1753f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1754f8558555SMarcel Holtmann if (!ev->status) 1755f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1756f8558555SMarcel Holtmann 1757f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1758f8558555SMarcel Holtmann hci_conn_put(conn); 1759f8558555SMarcel Holtmann } else 1760a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 1761a9de9248SMarcel Holtmann } 1762a9de9248SMarcel Holtmann 1763a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1764a9de9248SMarcel Holtmann } 1765a9de9248SMarcel Holtmann 1766a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1767a9de9248SMarcel Holtmann { 1768a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 1769a9de9248SMarcel Holtmann struct hci_conn *conn; 1770a9de9248SMarcel Holtmann 1771a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1772a9de9248SMarcel Holtmann 1773a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1774a9de9248SMarcel Holtmann 1775a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1776a9de9248SMarcel Holtmann if (conn) { 1777a9de9248SMarcel Holtmann if (!ev->status) 1778a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_SECURE; 1779a9de9248SMarcel Holtmann 1780a9de9248SMarcel Holtmann clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); 1781a9de9248SMarcel Holtmann 1782a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 1783a9de9248SMarcel Holtmann } 1784a9de9248SMarcel Holtmann 1785a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1786a9de9248SMarcel Holtmann } 1787a9de9248SMarcel Holtmann 1788a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 1789a9de9248SMarcel Holtmann { 1790a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 1791a9de9248SMarcel Holtmann struct hci_conn *conn; 1792a9de9248SMarcel Holtmann 1793a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1794a9de9248SMarcel Holtmann 1795a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1796a9de9248SMarcel Holtmann 1797a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1798ccd556feSJohan Hedberg if (!conn) 1799ccd556feSJohan Hedberg goto unlock; 1800ccd556feSJohan Hedberg 1801769be974SMarcel Holtmann if (!ev->status) 1802a9de9248SMarcel Holtmann memcpy(conn->features, ev->features, 8); 1803a9de9248SMarcel Holtmann 1804ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 1805ccd556feSJohan Hedberg goto unlock; 1806ccd556feSJohan Hedberg 1807ccd556feSJohan Hedberg if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { 1808769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 1809769be974SMarcel Holtmann cp.handle = ev->handle; 1810769be974SMarcel Holtmann cp.page = 0x01; 1811ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 1812769be974SMarcel Holtmann sizeof(cp), &cp); 1813392599b9SJohan Hedberg goto unlock; 1814392599b9SJohan Hedberg } 1815392599b9SJohan Hedberg 1816127178d2SJohan Hedberg if (!ev->status) { 1817127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 1818127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 1819127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 1820127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 1821127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 1822127178d2SJohan Hedberg } 1823392599b9SJohan Hedberg 1824127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 1825769be974SMarcel Holtmann conn->state = BT_CONNECTED; 1826769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1827769be974SMarcel Holtmann hci_conn_put(conn); 1828769be974SMarcel Holtmann } 1829769be974SMarcel Holtmann 1830ccd556feSJohan Hedberg unlock: 1831a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1832a9de9248SMarcel Holtmann } 1833a9de9248SMarcel Holtmann 1834a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) 1835a9de9248SMarcel Holtmann { 1836a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1837a9de9248SMarcel Holtmann } 1838a9de9248SMarcel Holtmann 1839a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1840a9de9248SMarcel Holtmann { 1841a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1842a9de9248SMarcel Holtmann } 1843a9de9248SMarcel Holtmann 1844a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1845a9de9248SMarcel Holtmann { 1846a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 1847a9de9248SMarcel Holtmann __u16 opcode; 1848a9de9248SMarcel Holtmann 1849a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 1850a9de9248SMarcel Holtmann 1851a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 1852a9de9248SMarcel Holtmann 1853a9de9248SMarcel Holtmann switch (opcode) { 1854a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 1855a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 1856a9de9248SMarcel Holtmann break; 1857a9de9248SMarcel Holtmann 1858a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 1859a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 1860a9de9248SMarcel Holtmann break; 1861a9de9248SMarcel Holtmann 1862a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 1863a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 1864a9de9248SMarcel Holtmann break; 1865a9de9248SMarcel Holtmann 1866a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 1867a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 1868a9de9248SMarcel Holtmann break; 1869a9de9248SMarcel Holtmann 1870e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 1871e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 1872e4e8e37cSMarcel Holtmann break; 1873e4e8e37cSMarcel Holtmann 1874a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 1875a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 1876a9de9248SMarcel Holtmann break; 1877a9de9248SMarcel Holtmann 1878e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 1879e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 1880e4e8e37cSMarcel Holtmann break; 1881e4e8e37cSMarcel Holtmann 1882e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 1883e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 1884e4e8e37cSMarcel Holtmann break; 1885e4e8e37cSMarcel Holtmann 1886a9de9248SMarcel Holtmann case HCI_OP_RESET: 1887a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 1888a9de9248SMarcel Holtmann break; 1889a9de9248SMarcel Holtmann 1890a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 1891a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 1892a9de9248SMarcel Holtmann break; 1893a9de9248SMarcel Holtmann 1894a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 1895a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 1896a9de9248SMarcel Holtmann break; 1897a9de9248SMarcel Holtmann 1898a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 1899a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 1900a9de9248SMarcel Holtmann break; 1901a9de9248SMarcel Holtmann 1902a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 1903a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 1904a9de9248SMarcel Holtmann break; 1905a9de9248SMarcel Holtmann 1906a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 1907a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 1908a9de9248SMarcel Holtmann break; 1909a9de9248SMarcel Holtmann 1910a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 1911a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 1912a9de9248SMarcel Holtmann break; 1913a9de9248SMarcel Holtmann 1914a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 1915a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 1916a9de9248SMarcel Holtmann break; 1917a9de9248SMarcel Holtmann 1918a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 1919a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 1920a9de9248SMarcel Holtmann break; 1921a9de9248SMarcel Holtmann 1922a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 1923a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 1924a9de9248SMarcel Holtmann break; 1925a9de9248SMarcel Holtmann 1926a9de9248SMarcel Holtmann case HCI_OP_HOST_BUFFER_SIZE: 1927a9de9248SMarcel Holtmann hci_cc_host_buffer_size(hdev, skb); 1928a9de9248SMarcel Holtmann break; 1929a9de9248SMarcel Holtmann 1930333140b5SMarcel Holtmann case HCI_OP_READ_SSP_MODE: 1931333140b5SMarcel Holtmann hci_cc_read_ssp_mode(hdev, skb); 1932333140b5SMarcel Holtmann break; 1933333140b5SMarcel Holtmann 1934333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 1935333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 1936333140b5SMarcel Holtmann break; 1937333140b5SMarcel Holtmann 1938a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 1939a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 1940a9de9248SMarcel Holtmann break; 1941a9de9248SMarcel Holtmann 1942a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 1943a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 1944a9de9248SMarcel Holtmann break; 1945a9de9248SMarcel Holtmann 1946a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 1947a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 1948a9de9248SMarcel Holtmann break; 1949a9de9248SMarcel Holtmann 1950971e3a4bSAndre Guedes case HCI_OP_READ_LOCAL_EXT_FEATURES: 1951971e3a4bSAndre Guedes hci_cc_read_local_ext_features(hdev, skb); 1952971e3a4bSAndre Guedes break; 1953971e3a4bSAndre Guedes 1954a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 1955a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 1956a9de9248SMarcel Holtmann break; 1957a9de9248SMarcel Holtmann 1958a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 1959a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 1960a9de9248SMarcel Holtmann break; 1961a9de9248SMarcel Holtmann 196223bb5763SJohan Hedberg case HCI_OP_WRITE_CA_TIMEOUT: 196323bb5763SJohan Hedberg hci_cc_write_ca_timeout(hdev, skb); 196423bb5763SJohan Hedberg break; 196523bb5763SJohan Hedberg 1966928abaa7SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_INFO: 1967928abaa7SAndrei Emeltchenko hci_cc_read_local_amp_info(hdev, skb); 1968928abaa7SAndrei Emeltchenko break; 1969928abaa7SAndrei Emeltchenko 1970b0916ea0SJohan Hedberg case HCI_OP_DELETE_STORED_LINK_KEY: 1971b0916ea0SJohan Hedberg hci_cc_delete_stored_link_key(hdev, skb); 1972b0916ea0SJohan Hedberg break; 1973b0916ea0SJohan Hedberg 1974d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_MASK: 1975d5859e22SJohan Hedberg hci_cc_set_event_mask(hdev, skb); 1976d5859e22SJohan Hedberg break; 1977d5859e22SJohan Hedberg 1978d5859e22SJohan Hedberg case HCI_OP_WRITE_INQUIRY_MODE: 1979d5859e22SJohan Hedberg hci_cc_write_inquiry_mode(hdev, skb); 1980d5859e22SJohan Hedberg break; 1981d5859e22SJohan Hedberg 1982d5859e22SJohan Hedberg case HCI_OP_READ_INQ_RSP_TX_POWER: 1983d5859e22SJohan Hedberg hci_cc_read_inq_rsp_tx_power(hdev, skb); 1984d5859e22SJohan Hedberg break; 1985d5859e22SJohan Hedberg 1986d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_FLT: 1987d5859e22SJohan Hedberg hci_cc_set_event_flt(hdev, skb); 1988d5859e22SJohan Hedberg break; 1989d5859e22SJohan Hedberg 1990980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_REPLY: 1991980e1a53SJohan Hedberg hci_cc_pin_code_reply(hdev, skb); 1992980e1a53SJohan Hedberg break; 1993980e1a53SJohan Hedberg 1994980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_NEG_REPLY: 1995980e1a53SJohan Hedberg hci_cc_pin_code_neg_reply(hdev, skb); 1996980e1a53SJohan Hedberg break; 1997980e1a53SJohan Hedberg 1998c35938b2SSzymon Janc case HCI_OP_READ_LOCAL_OOB_DATA: 1999c35938b2SSzymon Janc hci_cc_read_local_oob_data_reply(hdev, skb); 2000c35938b2SSzymon Janc break; 2001c35938b2SSzymon Janc 20026ed58ec5SVille Tervo case HCI_OP_LE_READ_BUFFER_SIZE: 20036ed58ec5SVille Tervo hci_cc_le_read_buffer_size(hdev, skb); 20046ed58ec5SVille Tervo break; 20056ed58ec5SVille Tervo 2006a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_REPLY: 2007a5c29683SJohan Hedberg hci_cc_user_confirm_reply(hdev, skb); 2008a5c29683SJohan Hedberg break; 2009a5c29683SJohan Hedberg 2010a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_NEG_REPLY: 2011a5c29683SJohan Hedberg hci_cc_user_confirm_neg_reply(hdev, skb); 2012a5c29683SJohan Hedberg break; 2013a5c29683SJohan Hedberg 2014eb9d91f5SAndre Guedes case HCI_OP_LE_SET_SCAN_ENABLE: 2015eb9d91f5SAndre Guedes hci_cc_le_set_scan_enable(hdev, skb); 2016eb9d91f5SAndre Guedes break; 2017eb9d91f5SAndre Guedes 2018a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_REPLY: 2019a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_reply(hdev, skb); 2020a7a595f6SVinicius Costa Gomes break; 2021a7a595f6SVinicius Costa Gomes 2022a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_NEG_REPLY: 2023a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_neg_reply(hdev, skb); 2024a7a595f6SVinicius Costa Gomes break; 2025a7a595f6SVinicius Costa Gomes 2026f9b49306SAndre Guedes case HCI_OP_WRITE_LE_HOST_SUPPORTED: 2027f9b49306SAndre Guedes hci_cc_write_le_host_supported(hdev, skb); 2028f9b49306SAndre Guedes break; 2029f9b49306SAndre Guedes 2030a9de9248SMarcel Holtmann default: 2031a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 2032a9de9248SMarcel Holtmann break; 2033a9de9248SMarcel Holtmann } 2034a9de9248SMarcel Holtmann 20356bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 20366bd32326SVille Tervo del_timer(&hdev->cmd_timer); 20376bd32326SVille Tervo 2038a9de9248SMarcel Holtmann if (ev->ncmd) { 2039a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2040a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2041c78ae283SMarcel Holtmann tasklet_schedule(&hdev->cmd_task); 2042a9de9248SMarcel Holtmann } 2043a9de9248SMarcel Holtmann } 2044a9de9248SMarcel Holtmann 2045a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 2046a9de9248SMarcel Holtmann { 2047a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 2048a9de9248SMarcel Holtmann __u16 opcode; 2049a9de9248SMarcel Holtmann 2050a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2051a9de9248SMarcel Holtmann 2052a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2053a9de9248SMarcel Holtmann 2054a9de9248SMarcel Holtmann switch (opcode) { 2055a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 2056a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 2057a9de9248SMarcel Holtmann break; 2058a9de9248SMarcel Holtmann 2059a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 2060a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 2061a9de9248SMarcel Holtmann break; 2062a9de9248SMarcel Holtmann 2063a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 2064a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 2065a9de9248SMarcel Holtmann break; 2066a9de9248SMarcel Holtmann 2067f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 2068f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 2069f8558555SMarcel Holtmann break; 2070f8558555SMarcel Holtmann 2071f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 2072f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 2073f8558555SMarcel Holtmann break; 2074f8558555SMarcel Holtmann 2075a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 2076a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 2077a9de9248SMarcel Holtmann break; 2078a9de9248SMarcel Holtmann 2079769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 2080769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 2081769be974SMarcel Holtmann break; 2082769be974SMarcel Holtmann 2083769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 2084769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 2085769be974SMarcel Holtmann break; 2086769be974SMarcel Holtmann 2087a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 2088a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 2089a9de9248SMarcel Holtmann break; 2090a9de9248SMarcel Holtmann 2091a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 2092a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 2093a9de9248SMarcel Holtmann break; 2094a9de9248SMarcel Holtmann 2095a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 2096a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 2097a9de9248SMarcel Holtmann break; 2098a9de9248SMarcel Holtmann 20998962ee74SJohan Hedberg case HCI_OP_DISCONNECT: 21008962ee74SJohan Hedberg if (ev->status != 0) 210137d9ef76SJohan Hedberg mgmt_disconnect_failed(hdev, NULL, ev->status); 21028962ee74SJohan Hedberg break; 21038962ee74SJohan Hedberg 2104fcd89c09SVille Tervo case HCI_OP_LE_CREATE_CONN: 2105fcd89c09SVille Tervo hci_cs_le_create_conn(hdev, ev->status); 2106fcd89c09SVille Tervo break; 2107fcd89c09SVille Tervo 2108a7a595f6SVinicius Costa Gomes case HCI_OP_LE_START_ENC: 2109a7a595f6SVinicius Costa Gomes hci_cs_le_start_enc(hdev, ev->status); 2110a7a595f6SVinicius Costa Gomes break; 2111a7a595f6SVinicius Costa Gomes 2112a9de9248SMarcel Holtmann default: 2113a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 2114a9de9248SMarcel Holtmann break; 2115a9de9248SMarcel Holtmann } 2116a9de9248SMarcel Holtmann 21176bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 21186bd32326SVille Tervo del_timer(&hdev->cmd_timer); 21196bd32326SVille Tervo 212010572132SGustavo F. Padovan if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2121a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2122a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2123c78ae283SMarcel Holtmann tasklet_schedule(&hdev->cmd_task); 2124a9de9248SMarcel Holtmann } 2125a9de9248SMarcel Holtmann } 2126a9de9248SMarcel Holtmann 2127a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2128a9de9248SMarcel Holtmann { 2129a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 2130a9de9248SMarcel Holtmann struct hci_conn *conn; 2131a9de9248SMarcel Holtmann 2132a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2133a9de9248SMarcel Holtmann 2134a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2135a9de9248SMarcel Holtmann 2136a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2137a9de9248SMarcel Holtmann if (conn) { 2138a9de9248SMarcel Holtmann if (!ev->status) { 2139a9de9248SMarcel Holtmann if (ev->role) 2140a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_MASTER; 2141a9de9248SMarcel Holtmann else 2142a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_MASTER; 2143a9de9248SMarcel Holtmann } 2144a9de9248SMarcel Holtmann 2145a9de9248SMarcel Holtmann clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend); 2146a9de9248SMarcel Holtmann 2147a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 2148a9de9248SMarcel Holtmann } 2149a9de9248SMarcel Holtmann 2150a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2151a9de9248SMarcel Holtmann } 2152a9de9248SMarcel Holtmann 21531da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 21541da177e4SLinus Torvalds { 2155a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 21561ebb9252SMarcel Holtmann __le16 *ptr; 21571da177e4SLinus Torvalds int i; 21581da177e4SLinus Torvalds 21591da177e4SLinus Torvalds skb_pull(skb, sizeof(*ev)); 21601da177e4SLinus Torvalds 21611da177e4SLinus Torvalds BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 21621da177e4SLinus Torvalds 21631da177e4SLinus Torvalds if (skb->len < ev->num_hndl * 4) { 21641da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 21651da177e4SLinus Torvalds return; 21661da177e4SLinus Torvalds } 21671da177e4SLinus Torvalds 21681da177e4SLinus Torvalds tasklet_disable(&hdev->tx_task); 21691da177e4SLinus Torvalds 21701ebb9252SMarcel Holtmann for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) { 21711da177e4SLinus Torvalds struct hci_conn *conn; 21721da177e4SLinus Torvalds __u16 handle, count; 21731da177e4SLinus Torvalds 217483985319SHarvey Harrison handle = get_unaligned_le16(ptr++); 217583985319SHarvey Harrison count = get_unaligned_le16(ptr++); 21761da177e4SLinus Torvalds 21771da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 21781da177e4SLinus Torvalds if (conn) { 21791da177e4SLinus Torvalds conn->sent -= count; 21801da177e4SLinus Torvalds 21815b7f9909SMarcel Holtmann if (conn->type == ACL_LINK) { 218270f23020SAndrei Emeltchenko hdev->acl_cnt += count; 218370f23020SAndrei Emeltchenko if (hdev->acl_cnt > hdev->acl_pkts) 21841da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 21856ed58ec5SVille Tervo } else if (conn->type == LE_LINK) { 21866ed58ec5SVille Tervo if (hdev->le_pkts) { 21876ed58ec5SVille Tervo hdev->le_cnt += count; 21886ed58ec5SVille Tervo if (hdev->le_cnt > hdev->le_pkts) 21896ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 21906ed58ec5SVille Tervo } else { 21916ed58ec5SVille Tervo hdev->acl_cnt += count; 21926ed58ec5SVille Tervo if (hdev->acl_cnt > hdev->acl_pkts) 21936ed58ec5SVille Tervo hdev->acl_cnt = hdev->acl_pkts; 21946ed58ec5SVille Tervo } 21955b7f9909SMarcel Holtmann } else { 219670f23020SAndrei Emeltchenko hdev->sco_cnt += count; 219770f23020SAndrei Emeltchenko if (hdev->sco_cnt > hdev->sco_pkts) 21985b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 21991da177e4SLinus Torvalds } 22001da177e4SLinus Torvalds } 22011da177e4SLinus Torvalds } 2202a9de9248SMarcel Holtmann 2203c78ae283SMarcel Holtmann tasklet_schedule(&hdev->tx_task); 22041da177e4SLinus Torvalds 22051da177e4SLinus Torvalds tasklet_enable(&hdev->tx_task); 22061da177e4SLinus Torvalds } 22071da177e4SLinus Torvalds 220804837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 22091da177e4SLinus Torvalds { 2210a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 221104837f64SMarcel Holtmann struct hci_conn *conn; 22121da177e4SLinus Torvalds 22131da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 22141da177e4SLinus Torvalds 22151da177e4SLinus Torvalds hci_dev_lock(hdev); 22161da177e4SLinus Torvalds 221704837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 221804837f64SMarcel Holtmann if (conn) { 221904837f64SMarcel Holtmann conn->mode = ev->mode; 222004837f64SMarcel Holtmann conn->interval = __le16_to_cpu(ev->interval); 222104837f64SMarcel Holtmann 222204837f64SMarcel Holtmann if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) { 222304837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 222404837f64SMarcel Holtmann conn->power_save = 1; 222504837f64SMarcel Holtmann else 222604837f64SMarcel Holtmann conn->power_save = 0; 222704837f64SMarcel Holtmann } 2228e73439d8SMarcel Holtmann 2229e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 2230e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 223104837f64SMarcel Holtmann } 223204837f64SMarcel Holtmann 223304837f64SMarcel Holtmann hci_dev_unlock(hdev); 223404837f64SMarcel Holtmann } 223504837f64SMarcel Holtmann 22361da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 22371da177e4SLinus Torvalds { 2238052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 2239052b30b0SMarcel Holtmann struct hci_conn *conn; 2240052b30b0SMarcel Holtmann 2241a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2242052b30b0SMarcel Holtmann 2243052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2244052b30b0SMarcel Holtmann 2245052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2246b6f98044SWaldemar Rymarkiewicz if (!conn) 2247b6f98044SWaldemar Rymarkiewicz goto unlock; 2248b6f98044SWaldemar Rymarkiewicz 2249b6f98044SWaldemar Rymarkiewicz if (conn->state == BT_CONNECTED) { 2250052b30b0SMarcel Holtmann hci_conn_hold(conn); 2251052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 2252052b30b0SMarcel Holtmann hci_conn_put(conn); 2253052b30b0SMarcel Holtmann } 2254052b30b0SMarcel Holtmann 225503b555e1SJohan Hedberg if (!test_bit(HCI_PAIRABLE, &hdev->flags)) 225603b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 225703b555e1SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 2258582fbe9eSJohan Hedberg else if (test_bit(HCI_MGMT, &hdev->flags)) { 2259a770bb5aSWaldemar Rymarkiewicz u8 secure; 2260a770bb5aSWaldemar Rymarkiewicz 2261a770bb5aSWaldemar Rymarkiewicz if (conn->pending_sec_level == BT_SECURITY_HIGH) 2262a770bb5aSWaldemar Rymarkiewicz secure = 1; 2263a770bb5aSWaldemar Rymarkiewicz else 2264a770bb5aSWaldemar Rymarkiewicz secure = 0; 2265a770bb5aSWaldemar Rymarkiewicz 2266744cf19eSJohan Hedberg mgmt_pin_code_request(hdev, &ev->bdaddr, secure); 2267a770bb5aSWaldemar Rymarkiewicz } 2268980e1a53SJohan Hedberg 2269b6f98044SWaldemar Rymarkiewicz unlock: 2270052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 22711da177e4SLinus Torvalds } 22721da177e4SLinus Torvalds 22731da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 22741da177e4SLinus Torvalds { 227555ed8ca1SJohan Hedberg struct hci_ev_link_key_req *ev = (void *) skb->data; 227655ed8ca1SJohan Hedberg struct hci_cp_link_key_reply cp; 227755ed8ca1SJohan Hedberg struct hci_conn *conn; 227855ed8ca1SJohan Hedberg struct link_key *key; 227955ed8ca1SJohan Hedberg 2280a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 228155ed8ca1SJohan Hedberg 228255ed8ca1SJohan Hedberg if (!test_bit(HCI_LINK_KEYS, &hdev->flags)) 228355ed8ca1SJohan Hedberg return; 228455ed8ca1SJohan Hedberg 228555ed8ca1SJohan Hedberg hci_dev_lock(hdev); 228655ed8ca1SJohan Hedberg 228755ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, &ev->bdaddr); 228855ed8ca1SJohan Hedberg if (!key) { 228955ed8ca1SJohan Hedberg BT_DBG("%s link key not found for %s", hdev->name, 229055ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 229155ed8ca1SJohan Hedberg goto not_found; 229255ed8ca1SJohan Hedberg } 229355ed8ca1SJohan Hedberg 229455ed8ca1SJohan Hedberg BT_DBG("%s found key type %u for %s", hdev->name, key->type, 229555ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 229655ed8ca1SJohan Hedberg 2297b6020ba0SWaldemar Rymarkiewicz if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) && 2298b6020ba0SWaldemar Rymarkiewicz key->type == HCI_LK_DEBUG_COMBINATION) { 229955ed8ca1SJohan Hedberg BT_DBG("%s ignoring debug key", hdev->name); 230055ed8ca1SJohan Hedberg goto not_found; 230155ed8ca1SJohan Hedberg } 230255ed8ca1SJohan Hedberg 230355ed8ca1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 230460b83f57SWaldemar Rymarkiewicz if (conn) { 230560b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_UNAUTH_COMBINATION && 230660b83f57SWaldemar Rymarkiewicz conn->auth_type != 0xff && 230760b83f57SWaldemar Rymarkiewicz (conn->auth_type & 0x01)) { 230855ed8ca1SJohan Hedberg BT_DBG("%s ignoring unauthenticated key", hdev->name); 230955ed8ca1SJohan Hedberg goto not_found; 231055ed8ca1SJohan Hedberg } 231155ed8ca1SJohan Hedberg 231260b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && 231360b83f57SWaldemar Rymarkiewicz conn->pending_sec_level == BT_SECURITY_HIGH) { 231460b83f57SWaldemar Rymarkiewicz BT_DBG("%s ignoring key unauthenticated for high \ 231560b83f57SWaldemar Rymarkiewicz security", hdev->name); 231660b83f57SWaldemar Rymarkiewicz goto not_found; 231760b83f57SWaldemar Rymarkiewicz } 231860b83f57SWaldemar Rymarkiewicz 231960b83f57SWaldemar Rymarkiewicz conn->key_type = key->type; 232060b83f57SWaldemar Rymarkiewicz conn->pin_length = key->pin_len; 232160b83f57SWaldemar Rymarkiewicz } 232260b83f57SWaldemar Rymarkiewicz 232355ed8ca1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 232455ed8ca1SJohan Hedberg memcpy(cp.link_key, key->val, 16); 232555ed8ca1SJohan Hedberg 232655ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 232755ed8ca1SJohan Hedberg 232855ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 232955ed8ca1SJohan Hedberg 233055ed8ca1SJohan Hedberg return; 233155ed8ca1SJohan Hedberg 233255ed8ca1SJohan Hedberg not_found: 233355ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 233455ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 23351da177e4SLinus Torvalds } 23361da177e4SLinus Torvalds 23371da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 23381da177e4SLinus Torvalds { 2339052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 2340052b30b0SMarcel Holtmann struct hci_conn *conn; 234155ed8ca1SJohan Hedberg u8 pin_len = 0; 2342052b30b0SMarcel Holtmann 2343a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2344052b30b0SMarcel Holtmann 2345052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2346052b30b0SMarcel Holtmann 2347052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2348052b30b0SMarcel Holtmann if (conn) { 2349052b30b0SMarcel Holtmann hci_conn_hold(conn); 2350052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2351980e1a53SJohan Hedberg pin_len = conn->pin_length; 235213d39315SWaldemar Rymarkiewicz 235313d39315SWaldemar Rymarkiewicz if (ev->key_type != HCI_LK_CHANGED_COMBINATION) 235413d39315SWaldemar Rymarkiewicz conn->key_type = ev->key_type; 235513d39315SWaldemar Rymarkiewicz 2356052b30b0SMarcel Holtmann hci_conn_put(conn); 2357052b30b0SMarcel Holtmann } 2358052b30b0SMarcel Holtmann 235955ed8ca1SJohan Hedberg if (test_bit(HCI_LINK_KEYS, &hdev->flags)) 2360d25e28abSJohan Hedberg hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, 236155ed8ca1SJohan Hedberg ev->key_type, pin_len); 236255ed8ca1SJohan Hedberg 2363052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 23641da177e4SLinus Torvalds } 23651da177e4SLinus Torvalds 236604837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 236704837f64SMarcel Holtmann { 2368a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 236904837f64SMarcel Holtmann struct hci_conn *conn; 237004837f64SMarcel Holtmann 237104837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 237204837f64SMarcel Holtmann 237304837f64SMarcel Holtmann hci_dev_lock(hdev); 237404837f64SMarcel Holtmann 237504837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 23761da177e4SLinus Torvalds if (conn && !ev->status) { 23771da177e4SLinus Torvalds struct inquiry_entry *ie; 23781da177e4SLinus Torvalds 2379cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2380cc11b9c1SAndrei Emeltchenko if (ie) { 23811da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 23821da177e4SLinus Torvalds ie->timestamp = jiffies; 23831da177e4SLinus Torvalds } 23841da177e4SLinus Torvalds } 23851da177e4SLinus Torvalds 23861da177e4SLinus Torvalds hci_dev_unlock(hdev); 23871da177e4SLinus Torvalds } 23881da177e4SLinus Torvalds 2389a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2390a8746417SMarcel Holtmann { 2391a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 2392a8746417SMarcel Holtmann struct hci_conn *conn; 2393a8746417SMarcel Holtmann 2394a8746417SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2395a8746417SMarcel Holtmann 2396a8746417SMarcel Holtmann hci_dev_lock(hdev); 2397a8746417SMarcel Holtmann 2398a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2399a8746417SMarcel Holtmann if (conn && !ev->status) 2400a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 2401a8746417SMarcel Holtmann 2402a8746417SMarcel Holtmann hci_dev_unlock(hdev); 2403a8746417SMarcel Holtmann } 2404a8746417SMarcel Holtmann 240585a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 240685a1e930SMarcel Holtmann { 2407a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 240885a1e930SMarcel Holtmann struct inquiry_entry *ie; 240985a1e930SMarcel Holtmann 241085a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 241185a1e930SMarcel Holtmann 241285a1e930SMarcel Holtmann hci_dev_lock(hdev); 241385a1e930SMarcel Holtmann 2414cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2415cc11b9c1SAndrei Emeltchenko if (ie) { 241685a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 241785a1e930SMarcel Holtmann ie->timestamp = jiffies; 241885a1e930SMarcel Holtmann } 241985a1e930SMarcel Holtmann 242085a1e930SMarcel Holtmann hci_dev_unlock(hdev); 242185a1e930SMarcel Holtmann } 242285a1e930SMarcel Holtmann 2423a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb) 2424a9de9248SMarcel Holtmann { 2425a9de9248SMarcel Holtmann struct inquiry_data data; 2426a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2427a9de9248SMarcel Holtmann 2428a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2429a9de9248SMarcel Holtmann 2430a9de9248SMarcel Holtmann if (!num_rsp) 2431a9de9248SMarcel Holtmann return; 2432a9de9248SMarcel Holtmann 2433a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2434a9de9248SMarcel Holtmann 2435a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 2436138d22efSSzymon Janc struct inquiry_info_with_rssi_and_pscan_mode *info; 2437138d22efSSzymon Janc info = (void *) (skb->data + 1); 2438a9de9248SMarcel Holtmann 2439e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2440a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2441a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2442a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2443a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 2444a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2445a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2446a9de9248SMarcel Holtmann data.rssi = info->rssi; 244741a96212SMarcel Holtmann data.ssp_mode = 0x00; 2448a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 244948264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2450e17acd40SJohan Hedberg info->dev_class, info->rssi, 2451e17acd40SJohan Hedberg NULL); 2452a9de9248SMarcel Holtmann } 2453a9de9248SMarcel Holtmann } else { 2454a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 2455a9de9248SMarcel Holtmann 2456e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2457a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2458a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2459a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2460a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2461a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2462a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2463a9de9248SMarcel Holtmann data.rssi = info->rssi; 246441a96212SMarcel Holtmann data.ssp_mode = 0x00; 2465a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 246648264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2467e17acd40SJohan Hedberg info->dev_class, info->rssi, 2468e17acd40SJohan Hedberg NULL); 2469a9de9248SMarcel Holtmann } 2470a9de9248SMarcel Holtmann } 2471a9de9248SMarcel Holtmann 2472a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2473a9de9248SMarcel Holtmann } 2474a9de9248SMarcel Holtmann 2475a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 2476a9de9248SMarcel Holtmann { 247741a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 247841a96212SMarcel Holtmann struct hci_conn *conn; 247941a96212SMarcel Holtmann 2480a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 248141a96212SMarcel Holtmann 248241a96212SMarcel Holtmann hci_dev_lock(hdev); 248341a96212SMarcel Holtmann 248441a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2485ccd556feSJohan Hedberg if (!conn) 2486ccd556feSJohan Hedberg goto unlock; 2487ccd556feSJohan Hedberg 2488769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 248941a96212SMarcel Holtmann struct inquiry_entry *ie; 249041a96212SMarcel Holtmann 2491cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2492cc11b9c1SAndrei Emeltchenko if (ie) 249341a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 249441a96212SMarcel Holtmann 249541a96212SMarcel Holtmann conn->ssp_mode = (ev->features[0] & 0x01); 249641a96212SMarcel Holtmann } 249741a96212SMarcel Holtmann 2498ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2499ccd556feSJohan Hedberg goto unlock; 2500ccd556feSJohan Hedberg 2501127178d2SJohan Hedberg if (!ev->status) { 2502127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2503127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2504127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2505127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2506127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2507127178d2SJohan Hedberg } 2508392599b9SJohan Hedberg 2509127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2510769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2511769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2512769be974SMarcel Holtmann hci_conn_put(conn); 2513769be974SMarcel Holtmann } 2514769be974SMarcel Holtmann 2515ccd556feSJohan Hedberg unlock: 251641a96212SMarcel Holtmann hci_dev_unlock(hdev); 2517a9de9248SMarcel Holtmann } 2518a9de9248SMarcel Holtmann 2519a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2520a9de9248SMarcel Holtmann { 2521b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 2522b6a0dc82SMarcel Holtmann struct hci_conn *conn; 2523b6a0dc82SMarcel Holtmann 2524b6a0dc82SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2525b6a0dc82SMarcel Holtmann 2526b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 2527b6a0dc82SMarcel Holtmann 2528b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 25299dc0a3afSMarcel Holtmann if (!conn) { 25309dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 25319dc0a3afSMarcel Holtmann goto unlock; 25329dc0a3afSMarcel Holtmann 25339dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 2534b6a0dc82SMarcel Holtmann if (!conn) 2535b6a0dc82SMarcel Holtmann goto unlock; 2536b6a0dc82SMarcel Holtmann 25379dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 25389dc0a3afSMarcel Holtmann } 25399dc0a3afSMarcel Holtmann 2540732547f9SMarcel Holtmann switch (ev->status) { 2541732547f9SMarcel Holtmann case 0x00: 2542732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 2543732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 2544732547f9SMarcel Holtmann 25459eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 2546732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 2547732547f9SMarcel Holtmann break; 2548732547f9SMarcel Holtmann 2549705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 2550732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 25511038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 2552732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 2553732547f9SMarcel Holtmann if (conn->out && conn->attempt < 2) { 2554efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 2555efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 2556efc7688bSMarcel Holtmann hci_setup_sync(conn, conn->link->handle); 2557efc7688bSMarcel Holtmann goto unlock; 2558efc7688bSMarcel Holtmann } 2559732547f9SMarcel Holtmann /* fall through */ 2560efc7688bSMarcel Holtmann 2561732547f9SMarcel Holtmann default: 2562b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 2563732547f9SMarcel Holtmann break; 2564732547f9SMarcel Holtmann } 2565b6a0dc82SMarcel Holtmann 2566b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2567b6a0dc82SMarcel Holtmann if (ev->status) 2568b6a0dc82SMarcel Holtmann hci_conn_del(conn); 2569b6a0dc82SMarcel Holtmann 2570b6a0dc82SMarcel Holtmann unlock: 2571b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 2572a9de9248SMarcel Holtmann } 2573a9de9248SMarcel Holtmann 2574a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) 2575a9de9248SMarcel Holtmann { 2576a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2577a9de9248SMarcel Holtmann } 2578a9de9248SMarcel Holtmann 257904837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) 258004837f64SMarcel Holtmann { 2581a9de9248SMarcel Holtmann struct hci_ev_sniff_subrate *ev = (void *) skb->data; 258204837f64SMarcel Holtmann 258304837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 258404837f64SMarcel Holtmann } 258504837f64SMarcel Holtmann 2586a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 2587a9de9248SMarcel Holtmann { 2588a9de9248SMarcel Holtmann struct inquiry_data data; 2589a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 2590a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2591a9de9248SMarcel Holtmann 2592a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2593a9de9248SMarcel Holtmann 2594a9de9248SMarcel Holtmann if (!num_rsp) 2595a9de9248SMarcel Holtmann return; 2596a9de9248SMarcel Holtmann 2597a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2598a9de9248SMarcel Holtmann 2599e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2600a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2601a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2602a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2603a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2604a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2605a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2606a9de9248SMarcel Holtmann data.rssi = info->rssi; 260741a96212SMarcel Holtmann data.ssp_mode = 0x01; 2608a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 260948264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 26104c659c39SJohan Hedberg info->dev_class, info->rssi, info->data); 2611a9de9248SMarcel Holtmann } 2612a9de9248SMarcel Holtmann 2613a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2614a9de9248SMarcel Holtmann } 2615a9de9248SMarcel Holtmann 261617fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn) 261717fa4b9dSJohan Hedberg { 261817fa4b9dSJohan Hedberg /* If remote requests dedicated bonding follow that lead */ 261917fa4b9dSJohan Hedberg if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) { 262017fa4b9dSJohan Hedberg /* If both remote and local IO capabilities allow MITM 262117fa4b9dSJohan Hedberg * protection then require it, otherwise don't */ 262217fa4b9dSJohan Hedberg if (conn->remote_cap == 0x03 || conn->io_capability == 0x03) 262317fa4b9dSJohan Hedberg return 0x02; 262417fa4b9dSJohan Hedberg else 262517fa4b9dSJohan Hedberg return 0x03; 262617fa4b9dSJohan Hedberg } 262717fa4b9dSJohan Hedberg 262817fa4b9dSJohan Hedberg /* If remote requests no-bonding follow that lead */ 262917fa4b9dSJohan Hedberg if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01) 263058797bf7SWaldemar Rymarkiewicz return conn->remote_auth | (conn->auth_type & 0x01); 263117fa4b9dSJohan Hedberg 263217fa4b9dSJohan Hedberg return conn->auth_type; 263317fa4b9dSJohan Hedberg } 263417fa4b9dSJohan Hedberg 26350493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 26360493684eSMarcel Holtmann { 26370493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 26380493684eSMarcel Holtmann struct hci_conn *conn; 26390493684eSMarcel Holtmann 26400493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 26410493684eSMarcel Holtmann 26420493684eSMarcel Holtmann hci_dev_lock(hdev); 26430493684eSMarcel Holtmann 26440493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 264503b555e1SJohan Hedberg if (!conn) 264603b555e1SJohan Hedberg goto unlock; 264703b555e1SJohan Hedberg 26480493684eSMarcel Holtmann hci_conn_hold(conn); 26490493684eSMarcel Holtmann 265003b555e1SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->flags)) 265103b555e1SJohan Hedberg goto unlock; 265203b555e1SJohan Hedberg 265303b555e1SJohan Hedberg if (test_bit(HCI_PAIRABLE, &hdev->flags) || 265403b555e1SJohan Hedberg (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 265517fa4b9dSJohan Hedberg struct hci_cp_io_capability_reply cp; 265617fa4b9dSJohan Hedberg 265717fa4b9dSJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 265817fa4b9dSJohan Hedberg cp.capability = conn->io_capability; 26597cbc9bd9SJohan Hedberg conn->auth_type = hci_get_auth_req(conn); 26607cbc9bd9SJohan Hedberg cp.authentication = conn->auth_type; 266117fa4b9dSJohan Hedberg 2662ce85ee13SSzymon Janc if ((conn->out == 0x01 || conn->remote_oob == 0x01) && 2663ce85ee13SSzymon Janc hci_find_remote_oob_data(hdev, &conn->dst)) 2664ce85ee13SSzymon Janc cp.oob_data = 0x01; 2665ce85ee13SSzymon Janc else 2666ce85ee13SSzymon Janc cp.oob_data = 0x00; 2667ce85ee13SSzymon Janc 266817fa4b9dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, 266917fa4b9dSJohan Hedberg sizeof(cp), &cp); 267003b555e1SJohan Hedberg } else { 267103b555e1SJohan Hedberg struct hci_cp_io_capability_neg_reply cp; 267203b555e1SJohan Hedberg 267303b555e1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 26749f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED; 267503b555e1SJohan Hedberg 267603b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 267703b555e1SJohan Hedberg sizeof(cp), &cp); 267803b555e1SJohan Hedberg } 267903b555e1SJohan Hedberg 268003b555e1SJohan Hedberg unlock: 268103b555e1SJohan Hedberg hci_dev_unlock(hdev); 268203b555e1SJohan Hedberg } 268303b555e1SJohan Hedberg 268403b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 268503b555e1SJohan Hedberg { 268603b555e1SJohan Hedberg struct hci_ev_io_capa_reply *ev = (void *) skb->data; 268703b555e1SJohan Hedberg struct hci_conn *conn; 268803b555e1SJohan Hedberg 268903b555e1SJohan Hedberg BT_DBG("%s", hdev->name); 269003b555e1SJohan Hedberg 269103b555e1SJohan Hedberg hci_dev_lock(hdev); 269203b555e1SJohan Hedberg 269303b555e1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 269403b555e1SJohan Hedberg if (!conn) 269503b555e1SJohan Hedberg goto unlock; 269603b555e1SJohan Hedberg 269703b555e1SJohan Hedberg conn->remote_cap = ev->capability; 269803b555e1SJohan Hedberg conn->remote_oob = ev->oob_data; 269903b555e1SJohan Hedberg conn->remote_auth = ev->authentication; 270003b555e1SJohan Hedberg 270103b555e1SJohan Hedberg unlock: 27020493684eSMarcel Holtmann hci_dev_unlock(hdev); 27030493684eSMarcel Holtmann } 27040493684eSMarcel Holtmann 2705a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev, 2706a5c29683SJohan Hedberg struct sk_buff *skb) 2707a5c29683SJohan Hedberg { 2708a5c29683SJohan Hedberg struct hci_ev_user_confirm_req *ev = (void *) skb->data; 270955bc1a37SJohan Hedberg int loc_mitm, rem_mitm, confirm_hint = 0; 27107a828908SJohan Hedberg struct hci_conn *conn; 2711a5c29683SJohan Hedberg 2712a5c29683SJohan Hedberg BT_DBG("%s", hdev->name); 2713a5c29683SJohan Hedberg 2714a5c29683SJohan Hedberg hci_dev_lock(hdev); 2715a5c29683SJohan Hedberg 27167a828908SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->flags)) 27177a828908SJohan Hedberg goto unlock; 27187a828908SJohan Hedberg 27197a828908SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 27207a828908SJohan Hedberg if (!conn) 27217a828908SJohan Hedberg goto unlock; 27227a828908SJohan Hedberg 27237a828908SJohan Hedberg loc_mitm = (conn->auth_type & 0x01); 27247a828908SJohan Hedberg rem_mitm = (conn->remote_auth & 0x01); 27257a828908SJohan Hedberg 27267a828908SJohan Hedberg /* If we require MITM but the remote device can't provide that 27277a828908SJohan Hedberg * (it has NoInputNoOutput) then reject the confirmation 27287a828908SJohan Hedberg * request. The only exception is when we're dedicated bonding 27297a828908SJohan Hedberg * initiators (connect_cfm_cb set) since then we always have the MITM 27307a828908SJohan Hedberg * bit set. */ 27317a828908SJohan Hedberg if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) { 27327a828908SJohan Hedberg BT_DBG("Rejecting request: remote device can't provide MITM"); 27337a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, 27347a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 27357a828908SJohan Hedberg goto unlock; 27367a828908SJohan Hedberg } 27377a828908SJohan Hedberg 27387a828908SJohan Hedberg /* If no side requires MITM protection; auto-accept */ 27397a828908SJohan Hedberg if ((!loc_mitm || conn->remote_cap == 0x03) && 27407a828908SJohan Hedberg (!rem_mitm || conn->io_capability == 0x03)) { 274155bc1a37SJohan Hedberg 274255bc1a37SJohan Hedberg /* If we're not the initiators request authorization to 274355bc1a37SJohan Hedberg * proceed from user space (mgmt_user_confirm with 274455bc1a37SJohan Hedberg * confirm_hint set to 1). */ 274555bc1a37SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { 274655bc1a37SJohan Hedberg BT_DBG("Confirming auto-accept as acceptor"); 274755bc1a37SJohan Hedberg confirm_hint = 1; 274855bc1a37SJohan Hedberg goto confirm; 274955bc1a37SJohan Hedberg } 275055bc1a37SJohan Hedberg 27519f61656aSJohan Hedberg BT_DBG("Auto-accept of user confirmation with %ums delay", 27529f61656aSJohan Hedberg hdev->auto_accept_delay); 27539f61656aSJohan Hedberg 27549f61656aSJohan Hedberg if (hdev->auto_accept_delay > 0) { 27559f61656aSJohan Hedberg int delay = msecs_to_jiffies(hdev->auto_accept_delay); 27569f61656aSJohan Hedberg mod_timer(&conn->auto_accept_timer, jiffies + delay); 27579f61656aSJohan Hedberg goto unlock; 27589f61656aSJohan Hedberg } 27599f61656aSJohan Hedberg 27607a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, 27617a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 27627a828908SJohan Hedberg goto unlock; 27637a828908SJohan Hedberg } 27647a828908SJohan Hedberg 276555bc1a37SJohan Hedberg confirm: 2766744cf19eSJohan Hedberg mgmt_user_confirm_request(hdev, &ev->bdaddr, ev->passkey, 276755bc1a37SJohan Hedberg confirm_hint); 2768a5c29683SJohan Hedberg 27697a828908SJohan Hedberg unlock: 2770a5c29683SJohan Hedberg hci_dev_unlock(hdev); 2771a5c29683SJohan Hedberg } 2772a5c29683SJohan Hedberg 27730493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 27740493684eSMarcel Holtmann { 27750493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 27760493684eSMarcel Holtmann struct hci_conn *conn; 27770493684eSMarcel Holtmann 27780493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 27790493684eSMarcel Holtmann 27800493684eSMarcel Holtmann hci_dev_lock(hdev); 27810493684eSMarcel Holtmann 27820493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 27832a611692SJohan Hedberg if (!conn) 27842a611692SJohan Hedberg goto unlock; 27852a611692SJohan Hedberg 27862a611692SJohan Hedberg /* To avoid duplicate auth_failed events to user space we check 27872a611692SJohan Hedberg * the HCI_CONN_AUTH_PEND flag which will be set if we 27882a611692SJohan Hedberg * initiated the authentication. A traditional auth_complete 27892a611692SJohan Hedberg * event gets always produced as initiator and is also mapped to 27902a611692SJohan Hedberg * the mgmt_auth_failed event */ 27912a611692SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0) 2792744cf19eSJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, ev->status); 27932a611692SJohan Hedberg 27940493684eSMarcel Holtmann hci_conn_put(conn); 27950493684eSMarcel Holtmann 27962a611692SJohan Hedberg unlock: 27970493684eSMarcel Holtmann hci_dev_unlock(hdev); 27980493684eSMarcel Holtmann } 27990493684eSMarcel Holtmann 280041a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 280141a96212SMarcel Holtmann { 280241a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 280341a96212SMarcel Holtmann struct inquiry_entry *ie; 280441a96212SMarcel Holtmann 280541a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 280641a96212SMarcel Holtmann 280741a96212SMarcel Holtmann hci_dev_lock(hdev); 280841a96212SMarcel Holtmann 2809cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2810cc11b9c1SAndrei Emeltchenko if (ie) 281141a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 281241a96212SMarcel Holtmann 281341a96212SMarcel Holtmann hci_dev_unlock(hdev); 281441a96212SMarcel Holtmann } 281541a96212SMarcel Holtmann 28162763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev, 28172763eda6SSzymon Janc struct sk_buff *skb) 28182763eda6SSzymon Janc { 28192763eda6SSzymon Janc struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; 28202763eda6SSzymon Janc struct oob_data *data; 28212763eda6SSzymon Janc 28222763eda6SSzymon Janc BT_DBG("%s", hdev->name); 28232763eda6SSzymon Janc 28242763eda6SSzymon Janc hci_dev_lock(hdev); 28252763eda6SSzymon Janc 2826e1ba1f15SSzymon Janc if (!test_bit(HCI_MGMT, &hdev->flags)) 2827e1ba1f15SSzymon Janc goto unlock; 2828e1ba1f15SSzymon Janc 28292763eda6SSzymon Janc data = hci_find_remote_oob_data(hdev, &ev->bdaddr); 28302763eda6SSzymon Janc if (data) { 28312763eda6SSzymon Janc struct hci_cp_remote_oob_data_reply cp; 28322763eda6SSzymon Janc 28332763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 28342763eda6SSzymon Janc memcpy(cp.hash, data->hash, sizeof(cp.hash)); 28352763eda6SSzymon Janc memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); 28362763eda6SSzymon Janc 28372763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), 28382763eda6SSzymon Janc &cp); 28392763eda6SSzymon Janc } else { 28402763eda6SSzymon Janc struct hci_cp_remote_oob_data_neg_reply cp; 28412763eda6SSzymon Janc 28422763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 28432763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), 28442763eda6SSzymon Janc &cp); 28452763eda6SSzymon Janc } 28462763eda6SSzymon Janc 2847e1ba1f15SSzymon Janc unlock: 28482763eda6SSzymon Janc hci_dev_unlock(hdev); 28492763eda6SSzymon Janc } 28502763eda6SSzymon Janc 2851fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2852fcd89c09SVille Tervo { 2853fcd89c09SVille Tervo struct hci_ev_le_conn_complete *ev = (void *) skb->data; 2854fcd89c09SVille Tervo struct hci_conn *conn; 2855fcd89c09SVille Tervo 2856fcd89c09SVille Tervo BT_DBG("%s status %d", hdev->name, ev->status); 2857fcd89c09SVille Tervo 2858fcd89c09SVille Tervo hci_dev_lock(hdev); 2859fcd89c09SVille Tervo 2860fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr); 2861b62f328bSVille Tervo if (!conn) { 2862b62f328bSVille Tervo conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); 2863b62f328bSVille Tervo if (!conn) { 2864b62f328bSVille Tervo BT_ERR("No memory for new connection"); 2865b62f328bSVille Tervo hci_dev_unlock(hdev); 2866b62f328bSVille Tervo return; 2867b62f328bSVille Tervo } 286829b7988aSAndre Guedes 286929b7988aSAndre Guedes conn->dst_type = ev->bdaddr_type; 2870b62f328bSVille Tervo } 2871fcd89c09SVille Tervo 2872fcd89c09SVille Tervo if (ev->status) { 287348264f06SJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 287448264f06SJohan Hedberg conn->dst_type, ev->status); 2875fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 2876fcd89c09SVille Tervo conn->state = BT_CLOSED; 2877fcd89c09SVille Tervo hci_conn_del(conn); 2878fcd89c09SVille Tervo goto unlock; 2879fcd89c09SVille Tervo } 2880fcd89c09SVille Tervo 288148264f06SJohan Hedberg mgmt_connected(hdev, &ev->bdaddr, conn->type, conn->dst_type); 288283bc71b4SVinicius Costa Gomes 28837b5c0d52SVinicius Costa Gomes conn->sec_level = BT_SECURITY_LOW; 2884fcd89c09SVille Tervo conn->handle = __le16_to_cpu(ev->handle); 2885fcd89c09SVille Tervo conn->state = BT_CONNECTED; 2886fcd89c09SVille Tervo 2887fcd89c09SVille Tervo hci_conn_hold_device(conn); 2888fcd89c09SVille Tervo hci_conn_add_sysfs(conn); 2889fcd89c09SVille Tervo 2890fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 2891fcd89c09SVille Tervo 2892fcd89c09SVille Tervo unlock: 2893fcd89c09SVille Tervo hci_dev_unlock(hdev); 2894fcd89c09SVille Tervo } 2895fcd89c09SVille Tervo 28969aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev, 28979aa04c91SAndre Guedes struct sk_buff *skb) 28989aa04c91SAndre Guedes { 2899e95beb41SAndre Guedes u8 num_reports = skb->data[0]; 2900e95beb41SAndre Guedes void *ptr = &skb->data[1]; 29019aa04c91SAndre Guedes 29029aa04c91SAndre Guedes hci_dev_lock(hdev); 29039aa04c91SAndre Guedes 2904e95beb41SAndre Guedes while (num_reports--) { 2905e95beb41SAndre Guedes struct hci_ev_le_advertising_info *ev = ptr; 2906e95beb41SAndre Guedes 29079aa04c91SAndre Guedes hci_add_adv_entry(hdev, ev); 29089aa04c91SAndre Guedes 2909e95beb41SAndre Guedes ptr += sizeof(*ev) + ev->length + 1; 29109aa04c91SAndre Guedes } 29119aa04c91SAndre Guedes 29129aa04c91SAndre Guedes hci_dev_unlock(hdev); 29139aa04c91SAndre Guedes } 29149aa04c91SAndre Guedes 2915a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev, 2916a7a595f6SVinicius Costa Gomes struct sk_buff *skb) 2917a7a595f6SVinicius Costa Gomes { 2918a7a595f6SVinicius Costa Gomes struct hci_ev_le_ltk_req *ev = (void *) skb->data; 2919a7a595f6SVinicius Costa Gomes struct hci_cp_le_ltk_reply cp; 2920bea710feSVinicius Costa Gomes struct hci_cp_le_ltk_neg_reply neg; 2921a7a595f6SVinicius Costa Gomes struct hci_conn *conn; 2922bea710feSVinicius Costa Gomes struct link_key *ltk; 2923a7a595f6SVinicius Costa Gomes 2924a7a595f6SVinicius Costa Gomes BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle)); 2925a7a595f6SVinicius Costa Gomes 2926a7a595f6SVinicius Costa Gomes hci_dev_lock(hdev); 2927a7a595f6SVinicius Costa Gomes 2928a7a595f6SVinicius Costa Gomes conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2929bea710feSVinicius Costa Gomes if (conn == NULL) 2930bea710feSVinicius Costa Gomes goto not_found; 2931a7a595f6SVinicius Costa Gomes 2932bea710feSVinicius Costa Gomes ltk = hci_find_ltk(hdev, ev->ediv, ev->random); 2933bea710feSVinicius Costa Gomes if (ltk == NULL) 2934bea710feSVinicius Costa Gomes goto not_found; 2935bea710feSVinicius Costa Gomes 2936bea710feSVinicius Costa Gomes memcpy(cp.ltk, ltk->val, sizeof(ltk->val)); 2937a7a595f6SVinicius Costa Gomes cp.handle = cpu_to_le16(conn->handle); 2938726b4ffcSVinicius Costa Gomes conn->pin_length = ltk->pin_len; 2939a7a595f6SVinicius Costa Gomes 2940a7a595f6SVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); 2941a7a595f6SVinicius Costa Gomes 2942a7a595f6SVinicius Costa Gomes hci_dev_unlock(hdev); 2943bea710feSVinicius Costa Gomes 2944bea710feSVinicius Costa Gomes return; 2945bea710feSVinicius Costa Gomes 2946bea710feSVinicius Costa Gomes not_found: 2947bea710feSVinicius Costa Gomes neg.handle = ev->handle; 2948bea710feSVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg); 2949bea710feSVinicius Costa Gomes hci_dev_unlock(hdev); 2950a7a595f6SVinicius Costa Gomes } 2951a7a595f6SVinicius Costa Gomes 2952fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 2953fcd89c09SVille Tervo { 2954fcd89c09SVille Tervo struct hci_ev_le_meta *le_ev = (void *) skb->data; 2955fcd89c09SVille Tervo 2956fcd89c09SVille Tervo skb_pull(skb, sizeof(*le_ev)); 2957fcd89c09SVille Tervo 2958fcd89c09SVille Tervo switch (le_ev->subevent) { 2959fcd89c09SVille Tervo case HCI_EV_LE_CONN_COMPLETE: 2960fcd89c09SVille Tervo hci_le_conn_complete_evt(hdev, skb); 2961fcd89c09SVille Tervo break; 2962fcd89c09SVille Tervo 29639aa04c91SAndre Guedes case HCI_EV_LE_ADVERTISING_REPORT: 29649aa04c91SAndre Guedes hci_le_adv_report_evt(hdev, skb); 29659aa04c91SAndre Guedes break; 29669aa04c91SAndre Guedes 2967a7a595f6SVinicius Costa Gomes case HCI_EV_LE_LTK_REQ: 2968a7a595f6SVinicius Costa Gomes hci_le_ltk_request_evt(hdev, skb); 2969a7a595f6SVinicius Costa Gomes break; 2970a7a595f6SVinicius Costa Gomes 2971fcd89c09SVille Tervo default: 2972fcd89c09SVille Tervo break; 2973fcd89c09SVille Tervo } 2974fcd89c09SVille Tervo } 2975fcd89c09SVille Tervo 29761da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 29771da177e4SLinus Torvalds { 2978a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 2979a9de9248SMarcel Holtmann __u8 event = hdr->evt; 29801da177e4SLinus Torvalds 29811da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 29821da177e4SLinus Torvalds 2983a9de9248SMarcel Holtmann switch (event) { 29841da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 29851da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 29861da177e4SLinus Torvalds break; 29871da177e4SLinus Torvalds 29881da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 29891da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 29901da177e4SLinus Torvalds break; 29911da177e4SLinus Torvalds 2992a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 2993a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 299421d9e30eSMarcel Holtmann break; 299521d9e30eSMarcel Holtmann 29961da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 29971da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 29981da177e4SLinus Torvalds break; 29991da177e4SLinus Torvalds 30001da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 30011da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 30021da177e4SLinus Torvalds break; 30031da177e4SLinus Torvalds 30041da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 30051da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 30061da177e4SLinus Torvalds break; 30071da177e4SLinus Torvalds 3008a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 3009a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 3010a9de9248SMarcel Holtmann break; 3011a9de9248SMarcel Holtmann 30121da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 30131da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 30141da177e4SLinus Torvalds break; 30151da177e4SLinus Torvalds 3016a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 3017a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 3018a9de9248SMarcel Holtmann break; 3019a9de9248SMarcel Holtmann 3020a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 3021a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 3022a9de9248SMarcel Holtmann break; 3023a9de9248SMarcel Holtmann 3024a9de9248SMarcel Holtmann case HCI_EV_REMOTE_VERSION: 3025a9de9248SMarcel Holtmann hci_remote_version_evt(hdev, skb); 3026a9de9248SMarcel Holtmann break; 3027a9de9248SMarcel Holtmann 3028a9de9248SMarcel Holtmann case HCI_EV_QOS_SETUP_COMPLETE: 3029a9de9248SMarcel Holtmann hci_qos_setup_complete_evt(hdev, skb); 3030a9de9248SMarcel Holtmann break; 3031a9de9248SMarcel Holtmann 3032a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 3033a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 3034a9de9248SMarcel Holtmann break; 3035a9de9248SMarcel Holtmann 3036a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 3037a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 3038a9de9248SMarcel Holtmann break; 3039a9de9248SMarcel Holtmann 3040a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 3041a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 3042a9de9248SMarcel Holtmann break; 3043a9de9248SMarcel Holtmann 3044a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 3045a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 3046a9de9248SMarcel Holtmann break; 3047a9de9248SMarcel Holtmann 3048a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 3049a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 30501da177e4SLinus Torvalds break; 30511da177e4SLinus Torvalds 30521da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 30531da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 30541da177e4SLinus Torvalds break; 30551da177e4SLinus Torvalds 30561da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 30571da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 30581da177e4SLinus Torvalds break; 30591da177e4SLinus Torvalds 30601da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 30611da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 30621da177e4SLinus Torvalds break; 30631da177e4SLinus Torvalds 30641da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 30651da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 30661da177e4SLinus Torvalds break; 30671da177e4SLinus Torvalds 3068a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 3069a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 3070a8746417SMarcel Holtmann break; 3071a8746417SMarcel Holtmann 307285a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 307385a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 307485a1e930SMarcel Holtmann break; 307585a1e930SMarcel Holtmann 3076a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 3077a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 3078a9de9248SMarcel Holtmann break; 3079a9de9248SMarcel Holtmann 3080a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 3081a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 3082a9de9248SMarcel Holtmann break; 3083a9de9248SMarcel Holtmann 3084a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 3085a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 3086a9de9248SMarcel Holtmann break; 3087a9de9248SMarcel Holtmann 3088a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_CHANGED: 3089a9de9248SMarcel Holtmann hci_sync_conn_changed_evt(hdev, skb); 3090a9de9248SMarcel Holtmann break; 3091a9de9248SMarcel Holtmann 309204837f64SMarcel Holtmann case HCI_EV_SNIFF_SUBRATE: 309304837f64SMarcel Holtmann hci_sniff_subrate_evt(hdev, skb); 309404837f64SMarcel Holtmann break; 309504837f64SMarcel Holtmann 3096a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 3097a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 30981da177e4SLinus Torvalds break; 30991da177e4SLinus Torvalds 31000493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 31010493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 31020493684eSMarcel Holtmann break; 31030493684eSMarcel Holtmann 310403b555e1SJohan Hedberg case HCI_EV_IO_CAPA_REPLY: 310503b555e1SJohan Hedberg hci_io_capa_reply_evt(hdev, skb); 310603b555e1SJohan Hedberg break; 310703b555e1SJohan Hedberg 3108a5c29683SJohan Hedberg case HCI_EV_USER_CONFIRM_REQUEST: 3109a5c29683SJohan Hedberg hci_user_confirm_request_evt(hdev, skb); 3110a5c29683SJohan Hedberg break; 3111a5c29683SJohan Hedberg 31120493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 31130493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 31140493684eSMarcel Holtmann break; 31150493684eSMarcel Holtmann 311641a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 311741a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 311841a96212SMarcel Holtmann break; 311941a96212SMarcel Holtmann 3120fcd89c09SVille Tervo case HCI_EV_LE_META: 3121fcd89c09SVille Tervo hci_le_meta_evt(hdev, skb); 3122fcd89c09SVille Tervo break; 3123fcd89c09SVille Tervo 31242763eda6SSzymon Janc case HCI_EV_REMOTE_OOB_DATA_REQUEST: 31252763eda6SSzymon Janc hci_remote_oob_data_request_evt(hdev, skb); 31262763eda6SSzymon Janc break; 31272763eda6SSzymon Janc 31281da177e4SLinus Torvalds default: 3129a9de9248SMarcel Holtmann BT_DBG("%s event 0x%x", hdev->name, event); 31301da177e4SLinus Torvalds break; 31311da177e4SLinus Torvalds } 31321da177e4SLinus Torvalds 31331da177e4SLinus Torvalds kfree_skb(skb); 31341da177e4SLinus Torvalds hdev->stat.evt_rx++; 31351da177e4SLinus Torvalds } 31361da177e4SLinus Torvalds 31371da177e4SLinus Torvalds /* Generate internal stack event */ 31381da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data) 31391da177e4SLinus Torvalds { 31401da177e4SLinus Torvalds struct hci_event_hdr *hdr; 31411da177e4SLinus Torvalds struct hci_ev_stack_internal *ev; 31421da177e4SLinus Torvalds struct sk_buff *skb; 31431da177e4SLinus Torvalds 31441da177e4SLinus Torvalds skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC); 31451da177e4SLinus Torvalds if (!skb) 31461da177e4SLinus Torvalds return; 31471da177e4SLinus Torvalds 31481da177e4SLinus Torvalds hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE); 31491da177e4SLinus Torvalds hdr->evt = HCI_EV_STACK_INTERNAL; 31501da177e4SLinus Torvalds hdr->plen = sizeof(*ev) + dlen; 31511da177e4SLinus Torvalds 31521da177e4SLinus Torvalds ev = (void *) skb_put(skb, sizeof(*ev) + dlen); 31531da177e4SLinus Torvalds ev->type = type; 31541da177e4SLinus Torvalds memcpy(ev->data, data, dlen); 31551da177e4SLinus Torvalds 3156576c7d85SMarcel Holtmann bt_cb(skb)->incoming = 1; 3157a61bbcf2SPatrick McHardy __net_timestamp(skb); 3158576c7d85SMarcel Holtmann 31590d48d939SMarcel Holtmann bt_cb(skb)->pkt_type = HCI_EVENT_PKT; 31601da177e4SLinus Torvalds skb->dev = (void *) hdev; 3161eec8d2bcSJohan Hedberg hci_send_to_sock(hdev, skb, NULL); 31621da177e4SLinus Torvalds kfree_skb(skb); 31631da177e4SLinus Torvalds } 3164e6100a25SAndre Guedes 3165669bb396SGustavo F. Padovan module_param(enable_le, bool, 0644); 3166e6100a25SAndre Guedes MODULE_PARM_DESC(enable_le, "Enable LE support"); 3167