11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds BlueZ - Bluetooth protocol stack for Linux 32d0a0346SRon Shaffer Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved. 41da177e4SLinus Torvalds 51da177e4SLinus Torvalds Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> 61da177e4SLinus Torvalds 71da177e4SLinus Torvalds This program is free software; you can redistribute it and/or modify 81da177e4SLinus Torvalds it under the terms of the GNU General Public License version 2 as 91da177e4SLinus Torvalds published by the Free Software Foundation; 101da177e4SLinus Torvalds 111da177e4SLinus Torvalds THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 121da177e4SLinus Torvalds OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 131da177e4SLinus Torvalds FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 141da177e4SLinus Torvalds IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 151da177e4SLinus Torvalds CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 161da177e4SLinus Torvalds WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 171da177e4SLinus Torvalds ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 181da177e4SLinus Torvalds OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 211da177e4SLinus Torvalds COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 221da177e4SLinus Torvalds SOFTWARE IS DISCLAIMED. 231da177e4SLinus Torvalds */ 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds /* Bluetooth HCI event handling. */ 261da177e4SLinus Torvalds 271da177e4SLinus Torvalds #include <linux/module.h> 281da177e4SLinus Torvalds 291da177e4SLinus Torvalds #include <linux/types.h> 301da177e4SLinus Torvalds #include <linux/errno.h> 311da177e4SLinus Torvalds #include <linux/kernel.h> 321da177e4SLinus Torvalds #include <linux/slab.h> 331da177e4SLinus Torvalds #include <linux/poll.h> 341da177e4SLinus Torvalds #include <linux/fcntl.h> 351da177e4SLinus Torvalds #include <linux/init.h> 361da177e4SLinus Torvalds #include <linux/skbuff.h> 371da177e4SLinus Torvalds #include <linux/interrupt.h> 381da177e4SLinus Torvalds #include <linux/notifier.h> 391da177e4SLinus Torvalds #include <net/sock.h> 401da177e4SLinus Torvalds 411da177e4SLinus Torvalds #include <asm/system.h> 4270f23020SAndrei Emeltchenko #include <linux/uaccess.h> 431da177e4SLinus Torvalds #include <asm/unaligned.h> 441da177e4SLinus Torvalds 451da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h> 461da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h> 471da177e4SLinus Torvalds 48e6100a25SAndre Guedes static int enable_le; 49e6100a25SAndre Guedes 501da177e4SLinus Torvalds /* Handle HCI Event packets */ 511da177e4SLinus Torvalds 52a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb) 531da177e4SLinus Torvalds { 54a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 551da177e4SLinus Torvalds 56a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 571da177e4SLinus Torvalds 58e6d465cbSAndre Guedes if (status) { 59e6d465cbSAndre Guedes hci_dev_lock(hdev); 60e6d465cbSAndre Guedes mgmt_stop_discovery_failed(hdev, status); 61e6d465cbSAndre Guedes hci_dev_unlock(hdev); 62a9de9248SMarcel Holtmann return; 63e6d465cbSAndre Guedes } 641da177e4SLinus Torvalds 6589352e7dSAndre Guedes clear_bit(HCI_INQUIRY, &hdev->flags); 6689352e7dSAndre Guedes 6756e5cb86SJohan Hedberg hci_dev_lock(hdev); 68744cf19eSJohan Hedberg mgmt_discovering(hdev, 0); 6956e5cb86SJohan Hedberg hci_dev_unlock(hdev); 70a9de9248SMarcel Holtmann 7123bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status); 72a9de9248SMarcel Holtmann 73a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 741da177e4SLinus Torvalds } 756bd57416SMarcel Holtmann 76a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 771da177e4SLinus Torvalds { 78a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 79a9de9248SMarcel Holtmann 80a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 81a9de9248SMarcel Holtmann 82a9de9248SMarcel Holtmann if (status) 83a9de9248SMarcel Holtmann return; 84a9de9248SMarcel Holtmann 85a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 86a9de9248SMarcel Holtmann } 87a9de9248SMarcel Holtmann 88a9de9248SMarcel Holtmann static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb) 89a9de9248SMarcel Holtmann { 90a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 91a9de9248SMarcel Holtmann } 92a9de9248SMarcel Holtmann 93a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb) 94a9de9248SMarcel Holtmann { 95a9de9248SMarcel Holtmann struct hci_rp_role_discovery *rp = (void *) skb->data; 961da177e4SLinus Torvalds struct hci_conn *conn; 971da177e4SLinus Torvalds 98a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 991da177e4SLinus Torvalds 100a9de9248SMarcel Holtmann if (rp->status) 101a9de9248SMarcel Holtmann return; 1021da177e4SLinus Torvalds 1031da177e4SLinus Torvalds hci_dev_lock(hdev); 1041da177e4SLinus Torvalds 105a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 1061da177e4SLinus Torvalds if (conn) { 107a9de9248SMarcel Holtmann if (rp->role) 1081da177e4SLinus Torvalds conn->link_mode &= ~HCI_LM_MASTER; 1091da177e4SLinus Torvalds else 1101da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 1111da177e4SLinus Torvalds } 1121da177e4SLinus Torvalds 1131da177e4SLinus Torvalds hci_dev_unlock(hdev); 114a9de9248SMarcel Holtmann } 1151da177e4SLinus Torvalds 116e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 117e4e8e37cSMarcel Holtmann { 118e4e8e37cSMarcel Holtmann struct hci_rp_read_link_policy *rp = (void *) skb->data; 119e4e8e37cSMarcel Holtmann struct hci_conn *conn; 120e4e8e37cSMarcel Holtmann 121e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 122e4e8e37cSMarcel Holtmann 123e4e8e37cSMarcel Holtmann if (rp->status) 124e4e8e37cSMarcel Holtmann return; 125e4e8e37cSMarcel Holtmann 126e4e8e37cSMarcel Holtmann hci_dev_lock(hdev); 127e4e8e37cSMarcel Holtmann 128e4e8e37cSMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 129e4e8e37cSMarcel Holtmann if (conn) 130e4e8e37cSMarcel Holtmann conn->link_policy = __le16_to_cpu(rp->policy); 131e4e8e37cSMarcel Holtmann 132e4e8e37cSMarcel Holtmann hci_dev_unlock(hdev); 133e4e8e37cSMarcel Holtmann } 134e4e8e37cSMarcel Holtmann 135a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 136a9de9248SMarcel Holtmann { 137a9de9248SMarcel Holtmann struct hci_rp_write_link_policy *rp = (void *) skb->data; 138a9de9248SMarcel Holtmann struct hci_conn *conn; 139a9de9248SMarcel Holtmann void *sent; 140a9de9248SMarcel Holtmann 141a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 142a9de9248SMarcel Holtmann 143a9de9248SMarcel Holtmann if (rp->status) 144a9de9248SMarcel Holtmann return; 145a9de9248SMarcel Holtmann 146a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY); 14704837f64SMarcel Holtmann if (!sent) 148a9de9248SMarcel Holtmann return; 14904837f64SMarcel Holtmann 15004837f64SMarcel Holtmann hci_dev_lock(hdev); 15104837f64SMarcel Holtmann 152a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 153e4e8e37cSMarcel Holtmann if (conn) 15483985319SHarvey Harrison conn->link_policy = get_unaligned_le16(sent + 2); 15504837f64SMarcel Holtmann 15604837f64SMarcel Holtmann hci_dev_unlock(hdev); 1571da177e4SLinus Torvalds } 1581da177e4SLinus Torvalds 159e4e8e37cSMarcel Holtmann static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 160e4e8e37cSMarcel Holtmann { 161e4e8e37cSMarcel Holtmann struct hci_rp_read_def_link_policy *rp = (void *) skb->data; 162e4e8e37cSMarcel Holtmann 163e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 164e4e8e37cSMarcel Holtmann 165e4e8e37cSMarcel Holtmann if (rp->status) 166e4e8e37cSMarcel Holtmann return; 167e4e8e37cSMarcel Holtmann 168e4e8e37cSMarcel Holtmann hdev->link_policy = __le16_to_cpu(rp->policy); 169e4e8e37cSMarcel Holtmann } 170e4e8e37cSMarcel Holtmann 171e4e8e37cSMarcel Holtmann static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 172e4e8e37cSMarcel Holtmann { 173e4e8e37cSMarcel Holtmann __u8 status = *((__u8 *) skb->data); 174e4e8e37cSMarcel Holtmann void *sent; 175e4e8e37cSMarcel Holtmann 176e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 177e4e8e37cSMarcel Holtmann 178e4e8e37cSMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY); 179e4e8e37cSMarcel Holtmann if (!sent) 180e4e8e37cSMarcel Holtmann return; 181e4e8e37cSMarcel Holtmann 182e4e8e37cSMarcel Holtmann if (!status) 183e4e8e37cSMarcel Holtmann hdev->link_policy = get_unaligned_le16(sent); 184e4e8e37cSMarcel Holtmann 18523bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status); 186e4e8e37cSMarcel Holtmann } 187e4e8e37cSMarcel Holtmann 188a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) 1891da177e4SLinus Torvalds { 190a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 191a9de9248SMarcel Holtmann 192a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 193a9de9248SMarcel Holtmann 19410572132SGustavo F. Padovan clear_bit(HCI_RESET, &hdev->flags); 19510572132SGustavo F. Padovan 19623bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_RESET, status); 197a9de9248SMarcel Holtmann } 198a9de9248SMarcel Holtmann 199a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) 200a9de9248SMarcel Holtmann { 201a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 2021da177e4SLinus Torvalds void *sent; 2031da177e4SLinus Torvalds 204a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 2051da177e4SLinus Torvalds 206a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); 2071da177e4SLinus Torvalds if (!sent) 208a9de9248SMarcel Holtmann return; 2091da177e4SLinus Torvalds 21056e5cb86SJohan Hedberg hci_dev_lock(hdev); 21156e5cb86SJohan Hedberg 212b312b161SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 213744cf19eSJohan Hedberg mgmt_set_local_name_complete(hdev, sent, status); 214b312b161SJohan Hedberg 21556e5cb86SJohan Hedberg if (status == 0) 2161f6c6378SJohan Hedberg memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); 21756e5cb86SJohan Hedberg 21856e5cb86SJohan Hedberg hci_dev_unlock(hdev); 219a9de9248SMarcel Holtmann } 220a9de9248SMarcel Holtmann 221a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) 222a9de9248SMarcel Holtmann { 223a9de9248SMarcel Holtmann struct hci_rp_read_local_name *rp = (void *) skb->data; 224a9de9248SMarcel Holtmann 225a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 226a9de9248SMarcel Holtmann 227a9de9248SMarcel Holtmann if (rp->status) 228a9de9248SMarcel Holtmann return; 229a9de9248SMarcel Holtmann 2301f6c6378SJohan Hedberg memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); 231a9de9248SMarcel Holtmann } 232a9de9248SMarcel Holtmann 233a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) 234a9de9248SMarcel Holtmann { 235a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 236a9de9248SMarcel Holtmann void *sent; 237a9de9248SMarcel Holtmann 238a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 239a9de9248SMarcel Holtmann 240a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); 241a9de9248SMarcel Holtmann if (!sent) 242a9de9248SMarcel Holtmann return; 2431da177e4SLinus Torvalds 2441da177e4SLinus Torvalds if (!status) { 245a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 246a9de9248SMarcel Holtmann 2471da177e4SLinus Torvalds if (param == AUTH_ENABLED) 2481da177e4SLinus Torvalds set_bit(HCI_AUTH, &hdev->flags); 2491da177e4SLinus Torvalds else 2501da177e4SLinus Torvalds clear_bit(HCI_AUTH, &hdev->flags); 2511da177e4SLinus Torvalds } 252a9de9248SMarcel Holtmann 25323bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status); 254a9de9248SMarcel Holtmann } 2551da177e4SLinus Torvalds 256a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) 257a9de9248SMarcel Holtmann { 258a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 259a9de9248SMarcel Holtmann void *sent; 260a9de9248SMarcel Holtmann 261a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 262a9de9248SMarcel Holtmann 263a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); 2641da177e4SLinus Torvalds if (!sent) 265a9de9248SMarcel Holtmann return; 2661da177e4SLinus Torvalds 2671da177e4SLinus Torvalds if (!status) { 268a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 269a9de9248SMarcel Holtmann 2701da177e4SLinus Torvalds if (param) 2711da177e4SLinus Torvalds set_bit(HCI_ENCRYPT, &hdev->flags); 2721da177e4SLinus Torvalds else 2731da177e4SLinus Torvalds clear_bit(HCI_ENCRYPT, &hdev->flags); 2741da177e4SLinus Torvalds } 275a9de9248SMarcel Holtmann 27623bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status); 2771da177e4SLinus Torvalds } 2781da177e4SLinus Torvalds 279a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) 280a9de9248SMarcel Holtmann { 28136f7fc7eSJohan Hedberg __u8 param, status = *((__u8 *) skb->data); 28236f7fc7eSJohan Hedberg int old_pscan, old_iscan; 283a9de9248SMarcel Holtmann void *sent; 2841da177e4SLinus Torvalds 285a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 286a9de9248SMarcel Holtmann 287a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); 2881da177e4SLinus Torvalds if (!sent) 289a9de9248SMarcel Holtmann return; 2901da177e4SLinus Torvalds 29136f7fc7eSJohan Hedberg param = *((__u8 *) sent); 292a9de9248SMarcel Holtmann 29356e5cb86SJohan Hedberg hci_dev_lock(hdev); 29456e5cb86SJohan Hedberg 2952d7cee58SJohan Hedberg if (status != 0) { 296744cf19eSJohan Hedberg mgmt_write_scan_failed(hdev, param, status); 2972d7cee58SJohan Hedberg hdev->discov_timeout = 0; 2982d7cee58SJohan Hedberg goto done; 2992d7cee58SJohan Hedberg } 3002d7cee58SJohan Hedberg 3019fbcbb45SJohan Hedberg old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags); 3029fbcbb45SJohan Hedberg old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags); 303a9de9248SMarcel Holtmann 30473f22f62SJohan Hedberg if (param & SCAN_INQUIRY) { 3051da177e4SLinus Torvalds set_bit(HCI_ISCAN, &hdev->flags); 3069fbcbb45SJohan Hedberg if (!old_iscan) 307744cf19eSJohan Hedberg mgmt_discoverable(hdev, 1); 30816ab91abSJohan Hedberg if (hdev->discov_timeout > 0) { 30916ab91abSJohan Hedberg int to = msecs_to_jiffies(hdev->discov_timeout * 1000); 31016ab91abSJohan Hedberg queue_delayed_work(hdev->workqueue, &hdev->discov_off, 31116ab91abSJohan Hedberg to); 31216ab91abSJohan Hedberg } 3139fbcbb45SJohan Hedberg } else if (old_iscan) 314744cf19eSJohan Hedberg mgmt_discoverable(hdev, 0); 3151da177e4SLinus Torvalds 3169fbcbb45SJohan Hedberg if (param & SCAN_PAGE) { 3171da177e4SLinus Torvalds set_bit(HCI_PSCAN, &hdev->flags); 3189fbcbb45SJohan Hedberg if (!old_pscan) 319744cf19eSJohan Hedberg mgmt_connectable(hdev, 1); 3209fbcbb45SJohan Hedberg } else if (old_pscan) 321744cf19eSJohan Hedberg mgmt_connectable(hdev, 0); 322a9de9248SMarcel Holtmann 32336f7fc7eSJohan Hedberg done: 32456e5cb86SJohan Hedberg hci_dev_unlock(hdev); 32523bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status); 3261da177e4SLinus Torvalds } 3271da177e4SLinus Torvalds 328a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 329a9de9248SMarcel Holtmann { 330a9de9248SMarcel Holtmann struct hci_rp_read_class_of_dev *rp = (void *) skb->data; 331a9de9248SMarcel Holtmann 332a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 333a9de9248SMarcel Holtmann 334a9de9248SMarcel Holtmann if (rp->status) 335a9de9248SMarcel Holtmann return; 336a9de9248SMarcel Holtmann 337a9de9248SMarcel Holtmann memcpy(hdev->dev_class, rp->dev_class, 3); 338a9de9248SMarcel Holtmann 339a9de9248SMarcel Holtmann BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, 340a9de9248SMarcel Holtmann hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); 341a9de9248SMarcel Holtmann } 342a9de9248SMarcel Holtmann 343a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 344a9de9248SMarcel Holtmann { 345a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 346a9de9248SMarcel Holtmann void *sent; 347a9de9248SMarcel Holtmann 348a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 349a9de9248SMarcel Holtmann 350f383f275SMarcel Holtmann if (status) 351f383f275SMarcel Holtmann return; 352f383f275SMarcel Holtmann 353a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); 354a9de9248SMarcel Holtmann if (!sent) 355a9de9248SMarcel Holtmann return; 356a9de9248SMarcel Holtmann 357a9de9248SMarcel Holtmann memcpy(hdev->dev_class, sent, 3); 358a9de9248SMarcel Holtmann } 359a9de9248SMarcel Holtmann 360a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 361a9de9248SMarcel Holtmann { 362a9de9248SMarcel Holtmann struct hci_rp_read_voice_setting *rp = (void *) skb->data; 363a9de9248SMarcel Holtmann __u16 setting; 364a9de9248SMarcel Holtmann 365a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 366a9de9248SMarcel Holtmann 367a9de9248SMarcel Holtmann if (rp->status) 368a9de9248SMarcel Holtmann return; 369a9de9248SMarcel Holtmann 370a9de9248SMarcel Holtmann setting = __le16_to_cpu(rp->voice_setting); 371a9de9248SMarcel Holtmann 372a9de9248SMarcel Holtmann if (hdev->voice_setting == setting) 373a9de9248SMarcel Holtmann return; 374a9de9248SMarcel Holtmann 375a9de9248SMarcel Holtmann hdev->voice_setting = setting; 376a9de9248SMarcel Holtmann 377a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 378a9de9248SMarcel Holtmann 379a9de9248SMarcel Holtmann if (hdev->notify) { 380a9de9248SMarcel Holtmann tasklet_disable(&hdev->tx_task); 381a9de9248SMarcel Holtmann hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 382a9de9248SMarcel Holtmann tasklet_enable(&hdev->tx_task); 383a9de9248SMarcel Holtmann } 384a9de9248SMarcel Holtmann } 385a9de9248SMarcel Holtmann 386a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 387a9de9248SMarcel Holtmann { 388a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 389f383f275SMarcel Holtmann __u16 setting; 390a9de9248SMarcel Holtmann void *sent; 391a9de9248SMarcel Holtmann 392a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 393a9de9248SMarcel Holtmann 394f383f275SMarcel Holtmann if (status) 395f383f275SMarcel Holtmann return; 396f383f275SMarcel Holtmann 397a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); 398a9de9248SMarcel Holtmann if (!sent) 399a9de9248SMarcel Holtmann return; 400a9de9248SMarcel Holtmann 401f383f275SMarcel Holtmann setting = get_unaligned_le16(sent); 4021da177e4SLinus Torvalds 403f383f275SMarcel Holtmann if (hdev->voice_setting == setting) 404f383f275SMarcel Holtmann return; 405f383f275SMarcel Holtmann 4061da177e4SLinus Torvalds hdev->voice_setting = setting; 4071da177e4SLinus Torvalds 408a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 4091da177e4SLinus Torvalds 4101da177e4SLinus Torvalds if (hdev->notify) { 4111da177e4SLinus Torvalds tasklet_disable(&hdev->tx_task); 4121da177e4SLinus Torvalds hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 4131da177e4SLinus Torvalds tasklet_enable(&hdev->tx_task); 4141da177e4SLinus Torvalds } 4151da177e4SLinus Torvalds } 4161da177e4SLinus Torvalds 417a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 4181da177e4SLinus Torvalds { 419a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 4201da177e4SLinus Torvalds 421a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 4221da177e4SLinus Torvalds 42323bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status); 4241143e5a6SMarcel Holtmann } 4251143e5a6SMarcel Holtmann 426333140b5SMarcel Holtmann static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 427333140b5SMarcel Holtmann { 428333140b5SMarcel Holtmann struct hci_rp_read_ssp_mode *rp = (void *) skb->data; 429333140b5SMarcel Holtmann 430333140b5SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 431333140b5SMarcel Holtmann 432333140b5SMarcel Holtmann if (rp->status) 433333140b5SMarcel Holtmann return; 434333140b5SMarcel Holtmann 435333140b5SMarcel Holtmann hdev->ssp_mode = rp->mode; 436333140b5SMarcel Holtmann } 437333140b5SMarcel Holtmann 438333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 439333140b5SMarcel Holtmann { 440333140b5SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 441333140b5SMarcel Holtmann void *sent; 442333140b5SMarcel Holtmann 443333140b5SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 444333140b5SMarcel Holtmann 445333140b5SMarcel Holtmann if (status) 446333140b5SMarcel Holtmann return; 447333140b5SMarcel Holtmann 448333140b5SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); 449333140b5SMarcel Holtmann if (!sent) 450333140b5SMarcel Holtmann return; 451333140b5SMarcel Holtmann 452333140b5SMarcel Holtmann hdev->ssp_mode = *((__u8 *) sent); 453333140b5SMarcel Holtmann } 454333140b5SMarcel Holtmann 455d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev) 456d5859e22SJohan Hedberg { 457d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 458d5859e22SJohan Hedberg return 2; 459d5859e22SJohan Hedberg 460d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 461d5859e22SJohan Hedberg return 1; 462d5859e22SJohan Hedberg 463d5859e22SJohan Hedberg if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 && 464d5859e22SJohan Hedberg hdev->lmp_subver == 0x0757) 465d5859e22SJohan Hedberg return 1; 466d5859e22SJohan Hedberg 467d5859e22SJohan Hedberg if (hdev->manufacturer == 15) { 468d5859e22SJohan Hedberg if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963) 469d5859e22SJohan Hedberg return 1; 470d5859e22SJohan Hedberg if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963) 471d5859e22SJohan Hedberg return 1; 472d5859e22SJohan Hedberg if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965) 473d5859e22SJohan Hedberg return 1; 474d5859e22SJohan Hedberg } 475d5859e22SJohan Hedberg 476d5859e22SJohan Hedberg if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 && 477d5859e22SJohan Hedberg hdev->lmp_subver == 0x1805) 478d5859e22SJohan Hedberg return 1; 479d5859e22SJohan Hedberg 480d5859e22SJohan Hedberg return 0; 481d5859e22SJohan Hedberg } 482d5859e22SJohan Hedberg 483d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev) 484d5859e22SJohan Hedberg { 485d5859e22SJohan Hedberg u8 mode; 486d5859e22SJohan Hedberg 487d5859e22SJohan Hedberg mode = hci_get_inquiry_mode(hdev); 488d5859e22SJohan Hedberg 489d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode); 490d5859e22SJohan Hedberg } 491d5859e22SJohan Hedberg 492d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev) 493d5859e22SJohan Hedberg { 494d5859e22SJohan Hedberg /* The second byte is 0xff instead of 0x9f (two reserved bits 495d5859e22SJohan Hedberg * disabled) since a Broadcom 1.2 dongle doesn't respond to the 496d5859e22SJohan Hedberg * command otherwise */ 497d5859e22SJohan Hedberg u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 }; 498d5859e22SJohan Hedberg 4996de6c18dSVille Tervo /* CSR 1.1 dongles does not accept any bitfield so don't try to set 5006de6c18dSVille Tervo * any event mask for pre 1.2 devices */ 5016de6c18dSVille Tervo if (hdev->lmp_ver <= 1) 5026de6c18dSVille Tervo return; 5036de6c18dSVille Tervo 504d5859e22SJohan Hedberg events[4] |= 0x01; /* Flow Specification Complete */ 505d5859e22SJohan Hedberg events[4] |= 0x02; /* Inquiry Result with RSSI */ 506d5859e22SJohan Hedberg events[4] |= 0x04; /* Read Remote Extended Features Complete */ 507d5859e22SJohan Hedberg events[5] |= 0x08; /* Synchronous Connection Complete */ 508d5859e22SJohan Hedberg events[5] |= 0x10; /* Synchronous Connection Changed */ 509d5859e22SJohan Hedberg 510d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 511d5859e22SJohan Hedberg events[4] |= 0x04; /* Inquiry Result with RSSI */ 512d5859e22SJohan Hedberg 513d5859e22SJohan Hedberg if (hdev->features[5] & LMP_SNIFF_SUBR) 514d5859e22SJohan Hedberg events[5] |= 0x20; /* Sniff Subrating */ 515d5859e22SJohan Hedberg 516d5859e22SJohan Hedberg if (hdev->features[5] & LMP_PAUSE_ENC) 517d5859e22SJohan Hedberg events[5] |= 0x80; /* Encryption Key Refresh Complete */ 518d5859e22SJohan Hedberg 519d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 520d5859e22SJohan Hedberg events[5] |= 0x40; /* Extended Inquiry Result */ 521d5859e22SJohan Hedberg 522d5859e22SJohan Hedberg if (hdev->features[6] & LMP_NO_FLUSH) 523d5859e22SJohan Hedberg events[7] |= 0x01; /* Enhanced Flush Complete */ 524d5859e22SJohan Hedberg 525d5859e22SJohan Hedberg if (hdev->features[7] & LMP_LSTO) 526d5859e22SJohan Hedberg events[6] |= 0x80; /* Link Supervision Timeout Changed */ 527d5859e22SJohan Hedberg 528d5859e22SJohan Hedberg if (hdev->features[6] & LMP_SIMPLE_PAIR) { 529d5859e22SJohan Hedberg events[6] |= 0x01; /* IO Capability Request */ 530d5859e22SJohan Hedberg events[6] |= 0x02; /* IO Capability Response */ 531d5859e22SJohan Hedberg events[6] |= 0x04; /* User Confirmation Request */ 532d5859e22SJohan Hedberg events[6] |= 0x08; /* User Passkey Request */ 533d5859e22SJohan Hedberg events[6] |= 0x10; /* Remote OOB Data Request */ 534d5859e22SJohan Hedberg events[6] |= 0x20; /* Simple Pairing Complete */ 535d5859e22SJohan Hedberg events[7] |= 0x04; /* User Passkey Notification */ 536d5859e22SJohan Hedberg events[7] |= 0x08; /* Keypress Notification */ 537d5859e22SJohan Hedberg events[7] |= 0x10; /* Remote Host Supported 538d5859e22SJohan Hedberg * Features Notification */ 539d5859e22SJohan Hedberg } 540d5859e22SJohan Hedberg 541d5859e22SJohan Hedberg if (hdev->features[4] & LMP_LE) 542d5859e22SJohan Hedberg events[7] |= 0x20; /* LE Meta-Event */ 543d5859e22SJohan Hedberg 544d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); 545d5859e22SJohan Hedberg } 546d5859e22SJohan Hedberg 547e6100a25SAndre Guedes static void hci_set_le_support(struct hci_dev *hdev) 548e6100a25SAndre Guedes { 549e6100a25SAndre Guedes struct hci_cp_write_le_host_supported cp; 550e6100a25SAndre Guedes 551e6100a25SAndre Guedes memset(&cp, 0, sizeof(cp)); 552e6100a25SAndre Guedes 553e6100a25SAndre Guedes if (enable_le) { 554e6100a25SAndre Guedes cp.le = 1; 555e6100a25SAndre Guedes cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR); 556e6100a25SAndre Guedes } 557e6100a25SAndre Guedes 558e6100a25SAndre Guedes hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), &cp); 559e6100a25SAndre Guedes } 560e6100a25SAndre Guedes 561d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev) 562d5859e22SJohan Hedberg { 563d5859e22SJohan Hedberg hci_setup_event_mask(hdev); 564d5859e22SJohan Hedberg 565d5859e22SJohan Hedberg if (hdev->lmp_ver > 1) 566d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); 567d5859e22SJohan Hedberg 568d5859e22SJohan Hedberg if (hdev->features[6] & LMP_SIMPLE_PAIR) { 569d5859e22SJohan Hedberg u8 mode = 0x01; 570d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode); 571d5859e22SJohan Hedberg } 572d5859e22SJohan Hedberg 573d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 574d5859e22SJohan Hedberg hci_setup_inquiry_mode(hdev); 575d5859e22SJohan Hedberg 576d5859e22SJohan Hedberg if (hdev->features[7] & LMP_INQ_TX_PWR) 577d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL); 578971e3a4bSAndre Guedes 579971e3a4bSAndre Guedes if (hdev->features[7] & LMP_EXTFEATURES) { 580971e3a4bSAndre Guedes struct hci_cp_read_local_ext_features cp; 581971e3a4bSAndre Guedes 582971e3a4bSAndre Guedes cp.page = 0x01; 583971e3a4bSAndre Guedes hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, 584971e3a4bSAndre Guedes sizeof(cp), &cp); 585971e3a4bSAndre Guedes } 586e6100a25SAndre Guedes 587e6100a25SAndre Guedes if (hdev->features[4] & LMP_LE) 588e6100a25SAndre Guedes hci_set_le_support(hdev); 589d5859e22SJohan Hedberg } 590d5859e22SJohan Hedberg 591a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) 592a9de9248SMarcel Holtmann { 593a9de9248SMarcel Holtmann struct hci_rp_read_local_version *rp = (void *) skb->data; 5941143e5a6SMarcel Holtmann 595a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 5961143e5a6SMarcel Holtmann 597a9de9248SMarcel Holtmann if (rp->status) 598a9de9248SMarcel Holtmann return; 5991143e5a6SMarcel Holtmann 600a9de9248SMarcel Holtmann hdev->hci_ver = rp->hci_ver; 601e4e8e37cSMarcel Holtmann hdev->hci_rev = __le16_to_cpu(rp->hci_rev); 602d5859e22SJohan Hedberg hdev->lmp_ver = rp->lmp_ver; 603e4e8e37cSMarcel Holtmann hdev->manufacturer = __le16_to_cpu(rp->manufacturer); 604d5859e22SJohan Hedberg hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); 6051da177e4SLinus Torvalds 606a9de9248SMarcel Holtmann BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name, 607a9de9248SMarcel Holtmann hdev->manufacturer, 608a9de9248SMarcel Holtmann hdev->hci_ver, hdev->hci_rev); 609d5859e22SJohan Hedberg 610d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags)) 611d5859e22SJohan Hedberg hci_setup(hdev); 612d5859e22SJohan Hedberg } 613d5859e22SJohan Hedberg 614d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev) 615d5859e22SJohan Hedberg { 616d5859e22SJohan Hedberg u16 link_policy = 0; 617d5859e22SJohan Hedberg 618d5859e22SJohan Hedberg if (hdev->features[0] & LMP_RSWITCH) 619d5859e22SJohan Hedberg link_policy |= HCI_LP_RSWITCH; 620d5859e22SJohan Hedberg if (hdev->features[0] & LMP_HOLD) 621d5859e22SJohan Hedberg link_policy |= HCI_LP_HOLD; 622d5859e22SJohan Hedberg if (hdev->features[0] & LMP_SNIFF) 623d5859e22SJohan Hedberg link_policy |= HCI_LP_SNIFF; 624d5859e22SJohan Hedberg if (hdev->features[1] & LMP_PARK) 625d5859e22SJohan Hedberg link_policy |= HCI_LP_PARK; 626d5859e22SJohan Hedberg 627d5859e22SJohan Hedberg link_policy = cpu_to_le16(link_policy); 628d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, 629d5859e22SJohan Hedberg sizeof(link_policy), &link_policy); 6301da177e4SLinus Torvalds } 6311da177e4SLinus Torvalds 632a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb) 633a9de9248SMarcel Holtmann { 634a9de9248SMarcel Holtmann struct hci_rp_read_local_commands *rp = (void *) skb->data; 635a9de9248SMarcel Holtmann 636a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 637a9de9248SMarcel Holtmann 638a9de9248SMarcel Holtmann if (rp->status) 639d5859e22SJohan Hedberg goto done; 640a9de9248SMarcel Holtmann 641a9de9248SMarcel Holtmann memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); 642d5859e22SJohan Hedberg 643d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10)) 644d5859e22SJohan Hedberg hci_setup_link_policy(hdev); 645d5859e22SJohan Hedberg 646d5859e22SJohan Hedberg done: 647d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status); 648a9de9248SMarcel Holtmann } 649a9de9248SMarcel Holtmann 650a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb) 651a9de9248SMarcel Holtmann { 652a9de9248SMarcel Holtmann struct hci_rp_read_local_features *rp = (void *) skb->data; 653a9de9248SMarcel Holtmann 654a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 655a9de9248SMarcel Holtmann 656a9de9248SMarcel Holtmann if (rp->status) 657a9de9248SMarcel Holtmann return; 658a9de9248SMarcel Holtmann 659a9de9248SMarcel Holtmann memcpy(hdev->features, rp->features, 8); 6601da177e4SLinus Torvalds 6611da177e4SLinus Torvalds /* Adjust default settings according to features 6621da177e4SLinus Torvalds * supported by device. */ 663a9de9248SMarcel Holtmann 6641da177e4SLinus Torvalds if (hdev->features[0] & LMP_3SLOT) 6651da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM3 | HCI_DH3); 6661da177e4SLinus Torvalds 6671da177e4SLinus Torvalds if (hdev->features[0] & LMP_5SLOT) 6681da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM5 | HCI_DH5); 6691da177e4SLinus Torvalds 6705b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV2) { 6711da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV2); 6725b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV2); 6735b7f9909SMarcel Holtmann } 6741da177e4SLinus Torvalds 6755b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV3) { 6761da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV3); 6775b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV3); 6785b7f9909SMarcel Holtmann } 6795b7f9909SMarcel Holtmann 6805b7f9909SMarcel Holtmann if (hdev->features[3] & LMP_ESCO) 6815b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV3); 6825b7f9909SMarcel Holtmann 6835b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV4) 6845b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV4); 6855b7f9909SMarcel Holtmann 6865b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV5) 6875b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV5); 6881da177e4SLinus Torvalds 689efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_2M) 690efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV3); 691efc7688bSMarcel Holtmann 692efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_3M) 693efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_3EV3); 694efc7688bSMarcel Holtmann 695efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_3S_ESCO) 696efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); 697efc7688bSMarcel Holtmann 698a9de9248SMarcel Holtmann BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, 699a9de9248SMarcel Holtmann hdev->features[0], hdev->features[1], 700a9de9248SMarcel Holtmann hdev->features[2], hdev->features[3], 701a9de9248SMarcel Holtmann hdev->features[4], hdev->features[5], 702a9de9248SMarcel Holtmann hdev->features[6], hdev->features[7]); 7031da177e4SLinus Torvalds } 7041da177e4SLinus Torvalds 705971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev, 706971e3a4bSAndre Guedes struct sk_buff *skb) 707971e3a4bSAndre Guedes { 708971e3a4bSAndre Guedes struct hci_rp_read_local_ext_features *rp = (void *) skb->data; 709971e3a4bSAndre Guedes 710971e3a4bSAndre Guedes BT_DBG("%s status 0x%x", hdev->name, rp->status); 711971e3a4bSAndre Guedes 712971e3a4bSAndre Guedes if (rp->status) 713971e3a4bSAndre Guedes return; 714971e3a4bSAndre Guedes 715971e3a4bSAndre Guedes memcpy(hdev->extfeatures, rp->features, 8); 716971e3a4bSAndre Guedes 717971e3a4bSAndre Guedes hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status); 718971e3a4bSAndre Guedes } 719971e3a4bSAndre Guedes 7201e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, 7211e89cffbSAndrei Emeltchenko struct sk_buff *skb) 7221e89cffbSAndrei Emeltchenko { 7231e89cffbSAndrei Emeltchenko struct hci_rp_read_flow_control_mode *rp = (void *) skb->data; 7241e89cffbSAndrei Emeltchenko 7251e89cffbSAndrei Emeltchenko BT_DBG("%s status 0x%x", hdev->name, rp->status); 7261e89cffbSAndrei Emeltchenko 7271e89cffbSAndrei Emeltchenko if (rp->status) 7281e89cffbSAndrei Emeltchenko return; 7291e89cffbSAndrei Emeltchenko 7301e89cffbSAndrei Emeltchenko hdev->flow_ctl_mode = rp->mode; 7311e89cffbSAndrei Emeltchenko 7321e89cffbSAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status); 7331e89cffbSAndrei Emeltchenko } 7341e89cffbSAndrei Emeltchenko 735a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 736a9de9248SMarcel Holtmann { 737a9de9248SMarcel Holtmann struct hci_rp_read_buffer_size *rp = (void *) skb->data; 738a9de9248SMarcel Holtmann 739a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 740a9de9248SMarcel Holtmann 741a9de9248SMarcel Holtmann if (rp->status) 742a9de9248SMarcel Holtmann return; 743a9de9248SMarcel Holtmann 744a9de9248SMarcel Holtmann hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); 745a9de9248SMarcel Holtmann hdev->sco_mtu = rp->sco_mtu; 746a9de9248SMarcel Holtmann hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); 747a9de9248SMarcel Holtmann hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); 748da1f5198SMarcel Holtmann 749da1f5198SMarcel Holtmann if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { 750da1f5198SMarcel Holtmann hdev->sco_mtu = 64; 751da1f5198SMarcel Holtmann hdev->sco_pkts = 8; 752da1f5198SMarcel Holtmann } 753da1f5198SMarcel Holtmann 754da1f5198SMarcel Holtmann hdev->acl_cnt = hdev->acl_pkts; 755da1f5198SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 7561da177e4SLinus Torvalds 757a9de9248SMarcel Holtmann BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, 758a9de9248SMarcel Holtmann hdev->acl_mtu, hdev->acl_pkts, 759a9de9248SMarcel Holtmann hdev->sco_mtu, hdev->sco_pkts); 7601da177e4SLinus Torvalds } 7611da177e4SLinus Torvalds 762a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) 763a9de9248SMarcel Holtmann { 764a9de9248SMarcel Holtmann struct hci_rp_read_bd_addr *rp = (void *) skb->data; 7651da177e4SLinus Torvalds 766a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 767a9de9248SMarcel Holtmann 768a9de9248SMarcel Holtmann if (!rp->status) 769a9de9248SMarcel Holtmann bacpy(&hdev->bdaddr, &rp->bdaddr); 770a9de9248SMarcel Holtmann 77123bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status); 77223bb5763SJohan Hedberg } 77323bb5763SJohan Hedberg 77423bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb) 77523bb5763SJohan Hedberg { 77623bb5763SJohan Hedberg __u8 status = *((__u8 *) skb->data); 77723bb5763SJohan Hedberg 77823bb5763SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 77923bb5763SJohan Hedberg 78023bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status); 7811da177e4SLinus Torvalds } 7821da177e4SLinus Torvalds 783928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev, 784928abaa7SAndrei Emeltchenko struct sk_buff *skb) 785928abaa7SAndrei Emeltchenko { 786928abaa7SAndrei Emeltchenko struct hci_rp_read_local_amp_info *rp = (void *) skb->data; 787928abaa7SAndrei Emeltchenko 788928abaa7SAndrei Emeltchenko BT_DBG("%s status 0x%x", hdev->name, rp->status); 789928abaa7SAndrei Emeltchenko 790928abaa7SAndrei Emeltchenko if (rp->status) 791928abaa7SAndrei Emeltchenko return; 792928abaa7SAndrei Emeltchenko 793928abaa7SAndrei Emeltchenko hdev->amp_status = rp->amp_status; 794928abaa7SAndrei Emeltchenko hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); 795928abaa7SAndrei Emeltchenko hdev->amp_max_bw = __le32_to_cpu(rp->max_bw); 796928abaa7SAndrei Emeltchenko hdev->amp_min_latency = __le32_to_cpu(rp->min_latency); 797928abaa7SAndrei Emeltchenko hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu); 798928abaa7SAndrei Emeltchenko hdev->amp_type = rp->amp_type; 799928abaa7SAndrei Emeltchenko hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap); 800928abaa7SAndrei Emeltchenko hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size); 801928abaa7SAndrei Emeltchenko hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); 802928abaa7SAndrei Emeltchenko hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); 803928abaa7SAndrei Emeltchenko 804928abaa7SAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status); 805928abaa7SAndrei Emeltchenko } 806928abaa7SAndrei Emeltchenko 807b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, 808b0916ea0SJohan Hedberg struct sk_buff *skb) 809b0916ea0SJohan Hedberg { 810b0916ea0SJohan Hedberg __u8 status = *((__u8 *) skb->data); 811b0916ea0SJohan Hedberg 812b0916ea0SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 813b0916ea0SJohan Hedberg 814b0916ea0SJohan Hedberg hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status); 815b0916ea0SJohan Hedberg } 816b0916ea0SJohan Hedberg 817d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb) 818d5859e22SJohan Hedberg { 819d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 820d5859e22SJohan Hedberg 821d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 822d5859e22SJohan Hedberg 823d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status); 824d5859e22SJohan Hedberg } 825d5859e22SJohan Hedberg 826d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev, 827d5859e22SJohan Hedberg 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_WRITE_INQUIRY_MODE, status); 834d5859e22SJohan Hedberg } 835d5859e22SJohan Hedberg 836d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, 837d5859e22SJohan Hedberg struct sk_buff *skb) 838d5859e22SJohan Hedberg { 839d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 840d5859e22SJohan Hedberg 841d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 842d5859e22SJohan Hedberg 843d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status); 844d5859e22SJohan Hedberg } 845d5859e22SJohan Hedberg 846d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb) 847d5859e22SJohan Hedberg { 848d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 849d5859e22SJohan Hedberg 850d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 851d5859e22SJohan Hedberg 852d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status); 853d5859e22SJohan Hedberg } 854d5859e22SJohan Hedberg 855980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) 856980e1a53SJohan Hedberg { 857980e1a53SJohan Hedberg struct hci_rp_pin_code_reply *rp = (void *) skb->data; 858980e1a53SJohan Hedberg struct hci_cp_pin_code_reply *cp; 859980e1a53SJohan Hedberg struct hci_conn *conn; 860980e1a53SJohan Hedberg 861980e1a53SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 862980e1a53SJohan Hedberg 86356e5cb86SJohan Hedberg hci_dev_lock(hdev); 86456e5cb86SJohan Hedberg 865980e1a53SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 866744cf19eSJohan Hedberg mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); 867980e1a53SJohan Hedberg 868980e1a53SJohan Hedberg if (rp->status != 0) 86956e5cb86SJohan Hedberg goto unlock; 870980e1a53SJohan Hedberg 871980e1a53SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); 872980e1a53SJohan Hedberg if (!cp) 87356e5cb86SJohan Hedberg goto unlock; 874980e1a53SJohan Hedberg 875980e1a53SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 876980e1a53SJohan Hedberg if (conn) 877980e1a53SJohan Hedberg conn->pin_length = cp->pin_len; 87856e5cb86SJohan Hedberg 87956e5cb86SJohan Hedberg unlock: 88056e5cb86SJohan Hedberg hci_dev_unlock(hdev); 881980e1a53SJohan Hedberg } 882980e1a53SJohan Hedberg 883980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 884980e1a53SJohan Hedberg { 885980e1a53SJohan Hedberg struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data; 886980e1a53SJohan Hedberg 887980e1a53SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 888980e1a53SJohan Hedberg 88956e5cb86SJohan Hedberg hci_dev_lock(hdev); 89056e5cb86SJohan Hedberg 891980e1a53SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 892744cf19eSJohan Hedberg mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr, 893980e1a53SJohan Hedberg rp->status); 89456e5cb86SJohan Hedberg 89556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 896980e1a53SJohan Hedberg } 89756e5cb86SJohan Hedberg 8986ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, 8996ed58ec5SVille Tervo struct sk_buff *skb) 9006ed58ec5SVille Tervo { 9016ed58ec5SVille Tervo struct hci_rp_le_read_buffer_size *rp = (void *) skb->data; 9026ed58ec5SVille Tervo 9036ed58ec5SVille Tervo BT_DBG("%s status 0x%x", hdev->name, rp->status); 9046ed58ec5SVille Tervo 9056ed58ec5SVille Tervo if (rp->status) 9066ed58ec5SVille Tervo return; 9076ed58ec5SVille Tervo 9086ed58ec5SVille Tervo hdev->le_mtu = __le16_to_cpu(rp->le_mtu); 9096ed58ec5SVille Tervo hdev->le_pkts = rp->le_max_pkt; 9106ed58ec5SVille Tervo 9116ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 9126ed58ec5SVille Tervo 9136ed58ec5SVille Tervo BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); 9146ed58ec5SVille Tervo 9156ed58ec5SVille Tervo hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status); 9166ed58ec5SVille Tervo } 917980e1a53SJohan Hedberg 918a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) 919a5c29683SJohan Hedberg { 920a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 921a5c29683SJohan Hedberg 922a5c29683SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 923a5c29683SJohan Hedberg 92456e5cb86SJohan Hedberg hci_dev_lock(hdev); 92556e5cb86SJohan Hedberg 926a5c29683SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 927744cf19eSJohan Hedberg mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, 928a5c29683SJohan Hedberg rp->status); 92956e5cb86SJohan Hedberg 93056e5cb86SJohan Hedberg hci_dev_unlock(hdev); 931a5c29683SJohan Hedberg } 932a5c29683SJohan Hedberg 933a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, 934a5c29683SJohan Hedberg struct sk_buff *skb) 935a5c29683SJohan Hedberg { 936a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 937a5c29683SJohan Hedberg 938a5c29683SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 939a5c29683SJohan Hedberg 94056e5cb86SJohan Hedberg hci_dev_lock(hdev); 94156e5cb86SJohan Hedberg 942a5c29683SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 943744cf19eSJohan Hedberg mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr, 944a5c29683SJohan Hedberg rp->status); 94556e5cb86SJohan Hedberg 94656e5cb86SJohan Hedberg hci_dev_unlock(hdev); 947a5c29683SJohan Hedberg } 948a5c29683SJohan Hedberg 9491143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb) 9501143d458SBrian Gix { 9511143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 9521143d458SBrian Gix 9531143d458SBrian Gix BT_DBG("%s status 0x%x", hdev->name, rp->status); 9541143d458SBrian Gix 9551143d458SBrian Gix hci_dev_lock(hdev); 9561143d458SBrian Gix 9571143d458SBrian Gix if (test_bit(HCI_MGMT, &hdev->flags)) 9581143d458SBrian Gix mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, 9591143d458SBrian Gix rp->status); 9601143d458SBrian Gix 9611143d458SBrian Gix hci_dev_unlock(hdev); 9621143d458SBrian Gix } 9631143d458SBrian Gix 9641143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, 9651143d458SBrian Gix struct sk_buff *skb) 9661143d458SBrian Gix { 9671143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 9681143d458SBrian Gix 9691143d458SBrian Gix BT_DBG("%s status 0x%x", hdev->name, rp->status); 9701143d458SBrian Gix 9711143d458SBrian Gix hci_dev_lock(hdev); 9721143d458SBrian Gix 9731143d458SBrian Gix if (test_bit(HCI_MGMT, &hdev->flags)) 9741143d458SBrian Gix mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr, 9751143d458SBrian Gix rp->status); 9761143d458SBrian Gix 9771143d458SBrian Gix hci_dev_unlock(hdev); 9781143d458SBrian Gix } 9791143d458SBrian Gix 980c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, 981c35938b2SSzymon Janc struct sk_buff *skb) 982c35938b2SSzymon Janc { 983c35938b2SSzymon Janc struct hci_rp_read_local_oob_data *rp = (void *) skb->data; 984c35938b2SSzymon Janc 985c35938b2SSzymon Janc BT_DBG("%s status 0x%x", hdev->name, rp->status); 986c35938b2SSzymon Janc 98756e5cb86SJohan Hedberg hci_dev_lock(hdev); 988744cf19eSJohan Hedberg mgmt_read_local_oob_data_reply_complete(hdev, rp->hash, 989c35938b2SSzymon Janc rp->randomizer, rp->status); 99056e5cb86SJohan Hedberg hci_dev_unlock(hdev); 991c35938b2SSzymon Janc } 992c35938b2SSzymon Janc 993eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, 994eb9d91f5SAndre Guedes struct sk_buff *skb) 995eb9d91f5SAndre Guedes { 996eb9d91f5SAndre Guedes struct hci_cp_le_set_scan_enable *cp; 997eb9d91f5SAndre Guedes __u8 status = *((__u8 *) skb->data); 998eb9d91f5SAndre Guedes 999eb9d91f5SAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 1000eb9d91f5SAndre Guedes 1001eb9d91f5SAndre Guedes if (status) 1002eb9d91f5SAndre Guedes return; 1003eb9d91f5SAndre Guedes 1004eb9d91f5SAndre Guedes cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE); 1005eb9d91f5SAndre Guedes if (!cp) 1006eb9d91f5SAndre Guedes return; 1007eb9d91f5SAndre Guedes 100835815085SAndre Guedes if (cp->enable == 0x01) { 100935815085SAndre Guedes del_timer(&hdev->adv_timer); 1010a8f13c8cSAndre Guedes 1011a8f13c8cSAndre Guedes hci_dev_lock(hdev); 1012eb9d91f5SAndre Guedes hci_adv_entries_clear(hdev); 1013a8f13c8cSAndre Guedes hci_dev_unlock(hdev); 101435815085SAndre Guedes } else if (cp->enable == 0x00) { 101535815085SAndre Guedes mod_timer(&hdev->adv_timer, jiffies + ADV_CLEAR_TIMEOUT); 101635815085SAndre Guedes } 1017eb9d91f5SAndre Guedes } 1018eb9d91f5SAndre Guedes 1019a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb) 1020a7a595f6SVinicius Costa Gomes { 1021a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_reply *rp = (void *) skb->data; 1022a7a595f6SVinicius Costa Gomes 1023a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, rp->status); 1024a7a595f6SVinicius Costa Gomes 1025a7a595f6SVinicius Costa Gomes if (rp->status) 1026a7a595f6SVinicius Costa Gomes return; 1027a7a595f6SVinicius Costa Gomes 1028a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status); 1029a7a595f6SVinicius Costa Gomes } 1030a7a595f6SVinicius Costa Gomes 1031a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 1032a7a595f6SVinicius Costa Gomes { 1033a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data; 1034a7a595f6SVinicius Costa Gomes 1035a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, rp->status); 1036a7a595f6SVinicius Costa Gomes 1037a7a595f6SVinicius Costa Gomes if (rp->status) 1038a7a595f6SVinicius Costa Gomes return; 1039a7a595f6SVinicius Costa Gomes 1040a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status); 1041a7a595f6SVinicius Costa Gomes } 1042a7a595f6SVinicius Costa Gomes 1043f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev, 1044f9b49306SAndre Guedes struct sk_buff *skb) 1045f9b49306SAndre Guedes { 1046f9b49306SAndre Guedes struct hci_cp_read_local_ext_features cp; 1047f9b49306SAndre Guedes __u8 status = *((__u8 *) skb->data); 1048f9b49306SAndre Guedes 1049f9b49306SAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 1050f9b49306SAndre Guedes 1051f9b49306SAndre Guedes if (status) 1052f9b49306SAndre Guedes return; 1053f9b49306SAndre Guedes 1054f9b49306SAndre Guedes cp.page = 0x01; 1055f9b49306SAndre Guedes hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp); 1056f9b49306SAndre Guedes } 1057f9b49306SAndre Guedes 1058a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 1059a9de9248SMarcel Holtmann { 1060a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1061a9de9248SMarcel Holtmann 1062a9de9248SMarcel Holtmann if (status) { 106323bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 1064a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 106556e5cb86SJohan Hedberg hci_dev_lock(hdev); 1066164a6e78SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 10677a135109SAndre Guedes mgmt_start_discovery_failed(hdev, status); 106856e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1069314b2381SJohan Hedberg return; 1070314b2381SJohan Hedberg } 1071314b2381SJohan Hedberg 107289352e7dSAndre Guedes set_bit(HCI_INQUIRY, &hdev->flags); 107389352e7dSAndre Guedes 107456e5cb86SJohan Hedberg hci_dev_lock(hdev); 1075744cf19eSJohan Hedberg mgmt_discovering(hdev, 1); 107656e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1077a9de9248SMarcel Holtmann } 1078a9de9248SMarcel Holtmann 10791da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 10801da177e4SLinus Torvalds { 1081a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 10821da177e4SLinus Torvalds struct hci_conn *conn; 10831da177e4SLinus Torvalds 1084a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1085a9de9248SMarcel Holtmann 1086a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 10871da177e4SLinus Torvalds if (!cp) 10881da177e4SLinus Torvalds return; 10891da177e4SLinus Torvalds 10901da177e4SLinus Torvalds hci_dev_lock(hdev); 10911da177e4SLinus Torvalds 10921da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 10931da177e4SLinus Torvalds 1094a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn); 10951da177e4SLinus Torvalds 10961da177e4SLinus Torvalds if (status) { 10971da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 10984c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 10991da177e4SLinus Torvalds conn->state = BT_CLOSED; 11001da177e4SLinus Torvalds hci_proto_connect_cfm(conn, status); 11011da177e4SLinus Torvalds hci_conn_del(conn); 11024c67bc74SMarcel Holtmann } else 11034c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 11041da177e4SLinus Torvalds } 11051da177e4SLinus Torvalds } else { 11061da177e4SLinus Torvalds if (!conn) { 11071da177e4SLinus Torvalds conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); 11081da177e4SLinus Torvalds if (conn) { 11091da177e4SLinus Torvalds conn->out = 1; 11101da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 11111da177e4SLinus Torvalds } else 1112893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 11131da177e4SLinus Torvalds } 11141da177e4SLinus Torvalds } 11151da177e4SLinus Torvalds 11161da177e4SLinus Torvalds hci_dev_unlock(hdev); 11171da177e4SLinus Torvalds } 11181da177e4SLinus Torvalds 1119a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 11201da177e4SLinus Torvalds { 1121a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 11221da177e4SLinus Torvalds struct hci_conn *acl, *sco; 11231da177e4SLinus Torvalds __u16 handle; 11241da177e4SLinus Torvalds 1125b6a0dc82SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1126b6a0dc82SMarcel Holtmann 1127a9de9248SMarcel Holtmann if (!status) 1128a9de9248SMarcel Holtmann return; 1129a9de9248SMarcel Holtmann 1130a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 11311da177e4SLinus Torvalds if (!cp) 1132a9de9248SMarcel Holtmann return; 11331da177e4SLinus Torvalds 11341da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 11351da177e4SLinus Torvalds 1136a9de9248SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 11371da177e4SLinus Torvalds 11381da177e4SLinus Torvalds hci_dev_lock(hdev); 11391da177e4SLinus Torvalds 11401da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 11415a08ecceSAndrei Emeltchenko if (acl) { 11425a08ecceSAndrei Emeltchenko sco = acl->link; 11435a08ecceSAndrei Emeltchenko if (sco) { 11441da177e4SLinus Torvalds sco->state = BT_CLOSED; 11451da177e4SLinus Torvalds 11461da177e4SLinus Torvalds hci_proto_connect_cfm(sco, status); 11471da177e4SLinus Torvalds hci_conn_del(sco); 11481da177e4SLinus Torvalds } 11495a08ecceSAndrei Emeltchenko } 11501da177e4SLinus Torvalds 11511da177e4SLinus Torvalds hci_dev_unlock(hdev); 11521da177e4SLinus Torvalds } 11531da177e4SLinus Torvalds 1154f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 1155f8558555SMarcel Holtmann { 1156f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 1157f8558555SMarcel Holtmann struct hci_conn *conn; 1158f8558555SMarcel Holtmann 1159f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1160f8558555SMarcel Holtmann 1161f8558555SMarcel Holtmann if (!status) 1162f8558555SMarcel Holtmann return; 1163f8558555SMarcel Holtmann 1164f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 1165f8558555SMarcel Holtmann if (!cp) 1166f8558555SMarcel Holtmann return; 1167f8558555SMarcel Holtmann 1168f8558555SMarcel Holtmann hci_dev_lock(hdev); 1169f8558555SMarcel Holtmann 1170f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1171f8558555SMarcel Holtmann if (conn) { 1172f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1173f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1174f8558555SMarcel Holtmann hci_conn_put(conn); 1175f8558555SMarcel Holtmann } 1176f8558555SMarcel Holtmann } 1177f8558555SMarcel Holtmann 1178f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1179f8558555SMarcel Holtmann } 1180f8558555SMarcel Holtmann 1181f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 1182f8558555SMarcel Holtmann { 1183f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 1184f8558555SMarcel Holtmann struct hci_conn *conn; 1185f8558555SMarcel Holtmann 1186f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1187f8558555SMarcel Holtmann 1188f8558555SMarcel Holtmann if (!status) 1189f8558555SMarcel Holtmann return; 1190f8558555SMarcel Holtmann 1191f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 1192f8558555SMarcel Holtmann if (!cp) 1193f8558555SMarcel Holtmann return; 1194f8558555SMarcel Holtmann 1195f8558555SMarcel Holtmann hci_dev_lock(hdev); 1196f8558555SMarcel Holtmann 1197f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1198f8558555SMarcel Holtmann if (conn) { 1199f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1200f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1201f8558555SMarcel Holtmann hci_conn_put(conn); 1202f8558555SMarcel Holtmann } 1203f8558555SMarcel Holtmann } 1204f8558555SMarcel Holtmann 1205f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1206f8558555SMarcel Holtmann } 1207f8558555SMarcel Holtmann 1208127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev, 1209392599b9SJohan Hedberg struct hci_conn *conn) 1210392599b9SJohan Hedberg { 1211392599b9SJohan Hedberg if (conn->state != BT_CONFIG || !conn->out) 1212392599b9SJohan Hedberg return 0; 1213392599b9SJohan Hedberg 1214765c2a96SJohan Hedberg if (conn->pending_sec_level == BT_SECURITY_SDP) 1215392599b9SJohan Hedberg return 0; 1216392599b9SJohan Hedberg 1217392599b9SJohan Hedberg /* Only request authentication for SSP connections or non-SSP 1218e9bf2bf0SVinicius Costa Gomes * devices with sec_level HIGH or if MITM protection is requested */ 1219392599b9SJohan Hedberg if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) && 1220e9bf2bf0SVinicius Costa Gomes conn->pending_sec_level != BT_SECURITY_HIGH && 1221e9bf2bf0SVinicius Costa Gomes !(conn->auth_type & 0x01)) 1222392599b9SJohan Hedberg return 0; 1223392599b9SJohan Hedberg 1224392599b9SJohan Hedberg return 1; 1225392599b9SJohan Hedberg } 1226392599b9SJohan Hedberg 1227a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 12281da177e4SLinus Torvalds { 1229127178d2SJohan Hedberg struct hci_cp_remote_name_req *cp; 1230127178d2SJohan Hedberg struct hci_conn *conn; 1231127178d2SJohan Hedberg 1232a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1233127178d2SJohan Hedberg 1234127178d2SJohan Hedberg /* If successful wait for the name req complete event before 1235127178d2SJohan Hedberg * checking for the need to do authentication */ 1236127178d2SJohan Hedberg if (!status) 1237127178d2SJohan Hedberg return; 1238127178d2SJohan Hedberg 1239127178d2SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); 1240127178d2SJohan Hedberg if (!cp) 1241127178d2SJohan Hedberg return; 1242127178d2SJohan Hedberg 1243127178d2SJohan Hedberg hci_dev_lock(hdev); 1244127178d2SJohan Hedberg 1245127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 124679c6c70cSJohan Hedberg if (!conn) 124779c6c70cSJohan Hedberg goto unlock; 124879c6c70cSJohan Hedberg 124979c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 125079c6c70cSJohan Hedberg goto unlock; 125179c6c70cSJohan Hedberg 125279c6c70cSJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { 1253127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1254127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1255127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1256127178d2SJohan Hedberg } 1257127178d2SJohan Hedberg 125879c6c70cSJohan Hedberg unlock: 1259127178d2SJohan Hedberg hci_dev_unlock(hdev); 1260a9de9248SMarcel Holtmann } 12611da177e4SLinus Torvalds 1262769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 1263769be974SMarcel Holtmann { 1264769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 1265769be974SMarcel Holtmann struct hci_conn *conn; 1266769be974SMarcel Holtmann 1267769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1268769be974SMarcel Holtmann 1269769be974SMarcel Holtmann if (!status) 1270769be974SMarcel Holtmann return; 1271769be974SMarcel Holtmann 1272769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 1273769be974SMarcel Holtmann if (!cp) 1274769be974SMarcel Holtmann return; 1275769be974SMarcel Holtmann 1276769be974SMarcel Holtmann hci_dev_lock(hdev); 1277769be974SMarcel Holtmann 1278769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1279769be974SMarcel Holtmann if (conn) { 1280769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1281769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1282769be974SMarcel Holtmann hci_conn_put(conn); 1283769be974SMarcel Holtmann } 1284769be974SMarcel Holtmann } 1285769be974SMarcel Holtmann 1286769be974SMarcel Holtmann hci_dev_unlock(hdev); 1287769be974SMarcel Holtmann } 1288769be974SMarcel Holtmann 1289769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 1290769be974SMarcel Holtmann { 1291769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features *cp; 1292769be974SMarcel Holtmann struct hci_conn *conn; 1293769be974SMarcel Holtmann 1294769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1295769be974SMarcel Holtmann 1296769be974SMarcel Holtmann if (!status) 1297769be974SMarcel Holtmann return; 1298769be974SMarcel Holtmann 1299769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 1300769be974SMarcel Holtmann if (!cp) 1301769be974SMarcel Holtmann return; 1302769be974SMarcel Holtmann 1303769be974SMarcel Holtmann hci_dev_lock(hdev); 1304769be974SMarcel Holtmann 1305769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1306769be974SMarcel Holtmann if (conn) { 1307769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1308769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1309769be974SMarcel Holtmann hci_conn_put(conn); 1310769be974SMarcel Holtmann } 1311769be974SMarcel Holtmann } 1312769be974SMarcel Holtmann 1313769be974SMarcel Holtmann hci_dev_unlock(hdev); 1314769be974SMarcel Holtmann } 1315769be974SMarcel Holtmann 1316a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 1317a9de9248SMarcel Holtmann { 1318b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 1319b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 1320b6a0dc82SMarcel Holtmann __u16 handle; 1321b6a0dc82SMarcel Holtmann 1322a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1323b6a0dc82SMarcel Holtmann 1324b6a0dc82SMarcel Holtmann if (!status) 1325b6a0dc82SMarcel Holtmann return; 1326b6a0dc82SMarcel Holtmann 1327b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 1328b6a0dc82SMarcel Holtmann if (!cp) 1329b6a0dc82SMarcel Holtmann return; 1330b6a0dc82SMarcel Holtmann 1331b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 1332b6a0dc82SMarcel Holtmann 1333b6a0dc82SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 1334b6a0dc82SMarcel Holtmann 1335b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 1336b6a0dc82SMarcel Holtmann 1337b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 13385a08ecceSAndrei Emeltchenko if (acl) { 13395a08ecceSAndrei Emeltchenko sco = acl->link; 13405a08ecceSAndrei Emeltchenko if (sco) { 1341b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 1342b6a0dc82SMarcel Holtmann 1343b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(sco, status); 1344b6a0dc82SMarcel Holtmann hci_conn_del(sco); 1345b6a0dc82SMarcel Holtmann } 13465a08ecceSAndrei Emeltchenko } 1347b6a0dc82SMarcel Holtmann 1348b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 1349a9de9248SMarcel Holtmann } 1350a9de9248SMarcel Holtmann 1351a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 1352a9de9248SMarcel Holtmann { 1353a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 135404837f64SMarcel Holtmann struct hci_conn *conn; 135504837f64SMarcel Holtmann 1356a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1357a9de9248SMarcel Holtmann 1358a9de9248SMarcel Holtmann if (!status) 1359a9de9248SMarcel Holtmann return; 1360a9de9248SMarcel Holtmann 1361a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 136204837f64SMarcel Holtmann if (!cp) 1363a9de9248SMarcel Holtmann return; 136404837f64SMarcel Holtmann 136504837f64SMarcel Holtmann hci_dev_lock(hdev); 136604837f64SMarcel Holtmann 136704837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1368e73439d8SMarcel Holtmann if (conn) { 136904837f64SMarcel Holtmann clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); 137004837f64SMarcel Holtmann 1371e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 1372e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1373e73439d8SMarcel Holtmann } 1374e73439d8SMarcel Holtmann 137504837f64SMarcel Holtmann hci_dev_unlock(hdev); 137604837f64SMarcel Holtmann } 137704837f64SMarcel Holtmann 1378a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 1379a9de9248SMarcel Holtmann { 1380a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 138104837f64SMarcel Holtmann struct hci_conn *conn; 138204837f64SMarcel Holtmann 1383a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1384a9de9248SMarcel Holtmann 1385a9de9248SMarcel Holtmann if (!status) 1386a9de9248SMarcel Holtmann return; 1387a9de9248SMarcel Holtmann 1388a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 138904837f64SMarcel Holtmann if (!cp) 1390a9de9248SMarcel Holtmann return; 139104837f64SMarcel Holtmann 139204837f64SMarcel Holtmann hci_dev_lock(hdev); 139304837f64SMarcel Holtmann 139404837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1395e73439d8SMarcel Holtmann if (conn) { 139604837f64SMarcel Holtmann clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); 139704837f64SMarcel Holtmann 1398e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 1399e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1400e73439d8SMarcel Holtmann } 1401e73439d8SMarcel Holtmann 140204837f64SMarcel Holtmann hci_dev_unlock(hdev); 140304837f64SMarcel Holtmann } 140404837f64SMarcel Holtmann 1405fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) 1406fcd89c09SVille Tervo { 1407fcd89c09SVille Tervo struct hci_cp_le_create_conn *cp; 1408fcd89c09SVille Tervo struct hci_conn *conn; 1409fcd89c09SVille Tervo 1410fcd89c09SVille Tervo BT_DBG("%s status 0x%x", hdev->name, status); 1411fcd89c09SVille Tervo 1412fcd89c09SVille Tervo cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN); 1413fcd89c09SVille Tervo if (!cp) 1414fcd89c09SVille Tervo return; 1415fcd89c09SVille Tervo 1416fcd89c09SVille Tervo hci_dev_lock(hdev); 1417fcd89c09SVille Tervo 1418fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr); 1419fcd89c09SVille Tervo 1420fcd89c09SVille Tervo BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr), 1421fcd89c09SVille Tervo conn); 1422fcd89c09SVille Tervo 1423fcd89c09SVille Tervo if (status) { 1424fcd89c09SVille Tervo if (conn && conn->state == BT_CONNECT) { 1425fcd89c09SVille Tervo conn->state = BT_CLOSED; 1426fcd89c09SVille Tervo hci_proto_connect_cfm(conn, status); 1427fcd89c09SVille Tervo hci_conn_del(conn); 1428fcd89c09SVille Tervo } 1429fcd89c09SVille Tervo } else { 1430fcd89c09SVille Tervo if (!conn) { 1431fcd89c09SVille Tervo conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr); 143229b7988aSAndre Guedes if (conn) { 143329b7988aSAndre Guedes conn->dst_type = cp->peer_addr_type; 1434fcd89c09SVille Tervo conn->out = 1; 143529b7988aSAndre Guedes } else { 1436fcd89c09SVille Tervo BT_ERR("No memory for new connection"); 1437fcd89c09SVille Tervo } 1438fcd89c09SVille Tervo } 143929b7988aSAndre Guedes } 1440fcd89c09SVille Tervo 1441fcd89c09SVille Tervo hci_dev_unlock(hdev); 1442fcd89c09SVille Tervo } 1443fcd89c09SVille Tervo 1444a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) 1445a7a595f6SVinicius Costa Gomes { 1446a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, status); 1447a7a595f6SVinicius Costa Gomes } 1448a7a595f6SVinicius Costa Gomes 14491da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 14501da177e4SLinus Torvalds { 14511da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 14521da177e4SLinus Torvalds 14531da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, status); 14541da177e4SLinus Torvalds 145523bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 14566bd57416SMarcel Holtmann 1457a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 145889352e7dSAndre Guedes 145989352e7dSAndre Guedes if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) 146089352e7dSAndre Guedes return; 146189352e7dSAndre Guedes 146256e5cb86SJohan Hedberg hci_dev_lock(hdev); 1463744cf19eSJohan Hedberg mgmt_discovering(hdev, 0); 146456e5cb86SJohan Hedberg hci_dev_unlock(hdev); 14651da177e4SLinus Torvalds } 14661da177e4SLinus Torvalds 14671da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 14681da177e4SLinus Torvalds { 146945bb4bf0SMarcel Holtmann struct inquiry_data data; 1470a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 14711da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 14721da177e4SLinus Torvalds 14731da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 14741da177e4SLinus Torvalds 147545bb4bf0SMarcel Holtmann if (!num_rsp) 147645bb4bf0SMarcel Holtmann return; 147745bb4bf0SMarcel Holtmann 14781da177e4SLinus Torvalds hci_dev_lock(hdev); 147945bb4bf0SMarcel Holtmann 1480e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 14811da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 14821da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 14831da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 14841da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 14851da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 14861da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 14871da177e4SLinus Torvalds data.rssi = 0x00; 148841a96212SMarcel Holtmann data.ssp_mode = 0x00; 14891da177e4SLinus Torvalds hci_inquiry_cache_update(hdev, &data); 149048264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 14914c659c39SJohan Hedberg info->dev_class, 0, NULL); 14921da177e4SLinus Torvalds } 149345bb4bf0SMarcel Holtmann 14941da177e4SLinus Torvalds hci_dev_unlock(hdev); 14951da177e4SLinus Torvalds } 14961da177e4SLinus Torvalds 1497a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 14981da177e4SLinus Torvalds { 1499a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 1500a9de9248SMarcel Holtmann struct hci_conn *conn; 15011da177e4SLinus Torvalds 1502a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 150345bb4bf0SMarcel Holtmann 15041da177e4SLinus Torvalds hci_dev_lock(hdev); 150545bb4bf0SMarcel Holtmann 1506a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 15079499237aSMarcel Holtmann if (!conn) { 15089499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 15099499237aSMarcel Holtmann goto unlock; 15109499237aSMarcel Holtmann 15119499237aSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 1512a9de9248SMarcel Holtmann if (!conn) 1513a9de9248SMarcel Holtmann goto unlock; 151445bb4bf0SMarcel Holtmann 15159499237aSMarcel Holtmann conn->type = SCO_LINK; 15169499237aSMarcel Holtmann } 15179499237aSMarcel Holtmann 1518a9de9248SMarcel Holtmann if (!ev->status) { 1519a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 1520769be974SMarcel Holtmann 1521769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 1522769be974SMarcel Holtmann conn->state = BT_CONFIG; 1523769be974SMarcel Holtmann hci_conn_hold(conn); 1524052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 152548264f06SJohan Hedberg mgmt_connected(hdev, &ev->bdaddr, conn->type, 152648264f06SJohan Hedberg conn->dst_type); 1527769be974SMarcel Holtmann } else 1528a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 1529a9de9248SMarcel Holtmann 15309eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 15317d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 15327d0db0a3SMarcel Holtmann 1533a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 1534a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1535a9de9248SMarcel Holtmann 1536a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 1537a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1538a9de9248SMarcel Holtmann 1539a9de9248SMarcel Holtmann /* Get remote features */ 1540a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 1541a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 1542a9de9248SMarcel Holtmann cp.handle = ev->handle; 1543769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 1544769be974SMarcel Holtmann sizeof(cp), &cp); 154545bb4bf0SMarcel Holtmann } 1546a9de9248SMarcel Holtmann 1547a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 1548a8746417SMarcel Holtmann if (!conn->out && hdev->hci_ver < 3) { 1549a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 1550a9de9248SMarcel Holtmann cp.handle = ev->handle; 1551a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1552a8746417SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, 1553a8746417SMarcel Holtmann sizeof(cp), &cp); 1554a9de9248SMarcel Holtmann } 155517d5c04cSJohan Hedberg } else { 1556a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 155717d5c04cSJohan Hedberg if (conn->type == ACL_LINK) 1558744cf19eSJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 155948264f06SJohan Hedberg conn->dst_type, ev->status); 156017d5c04cSJohan Hedberg } 156145bb4bf0SMarcel Holtmann 1562e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 1563e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 156445bb4bf0SMarcel Holtmann 1565769be974SMarcel Holtmann if (ev->status) { 1566a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1567a9de9248SMarcel Holtmann hci_conn_del(conn); 1568c89b6e6bSMarcel Holtmann } else if (ev->link_type != ACL_LINK) 1569c89b6e6bSMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1570a9de9248SMarcel Holtmann 1571a9de9248SMarcel Holtmann unlock: 15721da177e4SLinus Torvalds hci_dev_unlock(hdev); 1573a9de9248SMarcel Holtmann 1574a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 15751da177e4SLinus Torvalds } 15761da177e4SLinus Torvalds 15771da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 15781da177e4SLinus Torvalds { 1579a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 15801da177e4SLinus Torvalds int mask = hdev->link_mode; 15811da177e4SLinus Torvalds 1582a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s type 0x%x", hdev->name, 15831da177e4SLinus Torvalds batostr(&ev->bdaddr), ev->link_type); 15841da177e4SLinus Torvalds 15851da177e4SLinus Torvalds mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); 15861da177e4SLinus Torvalds 1587138d22efSSzymon Janc if ((mask & HCI_LM_ACCEPT) && 1588138d22efSSzymon Janc !hci_blacklist_lookup(hdev, &ev->bdaddr)) { 15891da177e4SLinus Torvalds /* Connection accepted */ 1590c7bdd502SMarcel Holtmann struct inquiry_entry *ie; 15911da177e4SLinus Torvalds struct hci_conn *conn; 15921da177e4SLinus Torvalds 15931da177e4SLinus Torvalds hci_dev_lock(hdev); 1594b6a0dc82SMarcel Holtmann 1595cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 1596cc11b9c1SAndrei Emeltchenko if (ie) 1597c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 1598c7bdd502SMarcel Holtmann 15991da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 16001da177e4SLinus Torvalds if (!conn) { 1601cc11b9c1SAndrei Emeltchenko conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); 1602cc11b9c1SAndrei Emeltchenko if (!conn) { 1603893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 16041da177e4SLinus Torvalds hci_dev_unlock(hdev); 16051da177e4SLinus Torvalds return; 16061da177e4SLinus Torvalds } 16071da177e4SLinus Torvalds } 1608b6a0dc82SMarcel Holtmann 16091da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 16101da177e4SLinus Torvalds conn->state = BT_CONNECT; 1611b6a0dc82SMarcel Holtmann 16121da177e4SLinus Torvalds hci_dev_unlock(hdev); 16131da177e4SLinus Torvalds 1614b6a0dc82SMarcel Holtmann if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) { 1615b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 1616b6a0dc82SMarcel Holtmann 16171da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 16181da177e4SLinus Torvalds 16191da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 16201da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 16211da177e4SLinus Torvalds else 16221da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 16231da177e4SLinus Torvalds 1624b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, 1625b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1626b6a0dc82SMarcel Holtmann } else { 1627b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 1628b6a0dc82SMarcel Holtmann 1629b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 1630a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1631b6a0dc82SMarcel Holtmann 1632b6a0dc82SMarcel Holtmann cp.tx_bandwidth = cpu_to_le32(0x00001f40); 1633b6a0dc82SMarcel Holtmann cp.rx_bandwidth = cpu_to_le32(0x00001f40); 1634b6a0dc82SMarcel Holtmann cp.max_latency = cpu_to_le16(0xffff); 1635b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 1636b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 1637b6a0dc82SMarcel Holtmann 1638b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 1639b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1640b6a0dc82SMarcel Holtmann } 16411da177e4SLinus Torvalds } else { 16421da177e4SLinus Torvalds /* Connection rejected */ 16431da177e4SLinus Torvalds struct hci_cp_reject_conn_req cp; 16441da177e4SLinus Torvalds 16451da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 16469f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_REJ_BAD_ADDR; 1647a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 16481da177e4SLinus Torvalds } 16491da177e4SLinus Torvalds } 16501da177e4SLinus Torvalds 16511da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 16521da177e4SLinus Torvalds { 1653a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 165404837f64SMarcel Holtmann struct hci_conn *conn; 16551da177e4SLinus Torvalds 16561da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 16571da177e4SLinus Torvalds 16581da177e4SLinus Torvalds hci_dev_lock(hdev); 16591da177e4SLinus Torvalds 166004837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1661f7520543SJohan Hedberg if (!conn) 1662f7520543SJohan Hedberg goto unlock; 1663f7520543SJohan Hedberg 166437d9ef76SJohan Hedberg if (ev->status == 0) 16651da177e4SLinus Torvalds conn->state = BT_CLOSED; 16667d0db0a3SMarcel Holtmann 166737d9ef76SJohan Hedberg if (conn->type == ACL_LINK || conn->type == LE_LINK) { 166837d9ef76SJohan Hedberg if (ev->status != 0) 166937d9ef76SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, ev->status); 167037d9ef76SJohan Hedberg else 167148264f06SJohan Hedberg mgmt_disconnected(hdev, &conn->dst, conn->type, 167248264f06SJohan Hedberg conn->dst_type); 167337d9ef76SJohan Hedberg } 1674f7520543SJohan Hedberg 167537d9ef76SJohan Hedberg if (ev->status == 0) { 16762950f21aSMarcel Holtmann hci_proto_disconn_cfm(conn, ev->reason); 16771da177e4SLinus Torvalds hci_conn_del(conn); 167837d9ef76SJohan Hedberg } 16791da177e4SLinus Torvalds 1680f7520543SJohan Hedberg unlock: 16811da177e4SLinus Torvalds hci_dev_unlock(hdev); 16821da177e4SLinus Torvalds } 16831da177e4SLinus Torvalds 1684a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1685a9de9248SMarcel Holtmann { 1686a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 1687a9de9248SMarcel Holtmann struct hci_conn *conn; 1688a9de9248SMarcel Holtmann 1689a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1690a9de9248SMarcel Holtmann 1691a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1692a9de9248SMarcel Holtmann 1693a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1694d7556e20SWaldemar Rymarkiewicz if (!conn) 1695d7556e20SWaldemar Rymarkiewicz goto unlock; 1696d7556e20SWaldemar Rymarkiewicz 1697765c2a96SJohan Hedberg if (!ev->status) { 169819f8def0SWaldemar Rymarkiewicz if (!(conn->ssp_mode > 0 && hdev->ssp_mode > 0) && 1699d7556e20SWaldemar Rymarkiewicz test_bit(HCI_CONN_REAUTH_PEND, &conn->pend)) { 1700d7556e20SWaldemar Rymarkiewicz BT_INFO("re-auth of legacy device is not possible."); 170119f8def0SWaldemar Rymarkiewicz } else { 1702a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1703765c2a96SJohan Hedberg conn->sec_level = conn->pending_sec_level; 170419f8def0SWaldemar Rymarkiewicz } 17052a611692SJohan Hedberg } else { 1706744cf19eSJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, ev->status); 17072a611692SJohan Hedberg } 1708a9de9248SMarcel Holtmann 1709a9de9248SMarcel Holtmann clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); 171019f8def0SWaldemar Rymarkiewicz clear_bit(HCI_CONN_REAUTH_PEND, &conn->pend); 1711a9de9248SMarcel Holtmann 1712f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1713d7556e20SWaldemar Rymarkiewicz if (!ev->status && hdev->ssp_mode > 0 && conn->ssp_mode > 0) { 1714f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1715f8558555SMarcel Holtmann cp.handle = ev->handle; 1716f8558555SMarcel Holtmann cp.encrypt = 0x01; 1717d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1718d7556e20SWaldemar Rymarkiewicz &cp); 1719f8558555SMarcel Holtmann } else { 1720f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1721f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1722f8558555SMarcel Holtmann hci_conn_put(conn); 1723f8558555SMarcel Holtmann } 1724052b30b0SMarcel Holtmann } else { 1725a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 1726a9de9248SMarcel Holtmann 1727052b30b0SMarcel Holtmann hci_conn_hold(conn); 1728052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1729052b30b0SMarcel Holtmann hci_conn_put(conn); 1730052b30b0SMarcel Holtmann } 1731052b30b0SMarcel Holtmann 1732a9de9248SMarcel Holtmann if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) { 1733a9de9248SMarcel Holtmann if (!ev->status) { 1734a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1735f8558555SMarcel Holtmann cp.handle = ev->handle; 1736f8558555SMarcel Holtmann cp.encrypt = 0x01; 1737d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1738d7556e20SWaldemar Rymarkiewicz &cp); 1739a9de9248SMarcel Holtmann } else { 1740a9de9248SMarcel Holtmann clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); 1741a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 1742a9de9248SMarcel Holtmann } 1743a9de9248SMarcel Holtmann } 1744a9de9248SMarcel Holtmann 1745d7556e20SWaldemar Rymarkiewicz unlock: 1746a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1747a9de9248SMarcel Holtmann } 1748a9de9248SMarcel Holtmann 1749a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 1750a9de9248SMarcel Holtmann { 1751127178d2SJohan Hedberg struct hci_ev_remote_name *ev = (void *) skb->data; 1752127178d2SJohan Hedberg struct hci_conn *conn; 1753127178d2SJohan Hedberg 1754a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1755a9de9248SMarcel Holtmann 1756a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 1757127178d2SJohan Hedberg 1758127178d2SJohan Hedberg hci_dev_lock(hdev); 1759127178d2SJohan Hedberg 1760a88a9652SJohan Hedberg if (ev->status == 0 && test_bit(HCI_MGMT, &hdev->flags)) 1761744cf19eSJohan Hedberg mgmt_remote_name(hdev, &ev->bdaddr, ev->name); 1762a88a9652SJohan Hedberg 1763127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 176479c6c70cSJohan Hedberg if (!conn) 176579c6c70cSJohan Hedberg goto unlock; 176679c6c70cSJohan Hedberg 176779c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 176879c6c70cSJohan Hedberg goto unlock; 176979c6c70cSJohan Hedberg 177079c6c70cSJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { 1771127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1772127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1773127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1774127178d2SJohan Hedberg } 1775127178d2SJohan Hedberg 177679c6c70cSJohan Hedberg unlock: 1777127178d2SJohan Hedberg hci_dev_unlock(hdev); 1778a9de9248SMarcel Holtmann } 1779a9de9248SMarcel Holtmann 1780a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 1781a9de9248SMarcel Holtmann { 1782a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 1783a9de9248SMarcel Holtmann struct hci_conn *conn; 1784a9de9248SMarcel Holtmann 1785a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1786a9de9248SMarcel Holtmann 1787a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1788a9de9248SMarcel Holtmann 1789a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1790a9de9248SMarcel Holtmann if (conn) { 1791a9de9248SMarcel Holtmann if (!ev->status) { 1792ae293196SMarcel Holtmann if (ev->encrypt) { 1793ae293196SMarcel Holtmann /* Encryption implies authentication */ 1794ae293196SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1795a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1796da85e5e5SVinicius Costa Gomes conn->sec_level = conn->pending_sec_level; 1797ae293196SMarcel Holtmann } else 1798a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_ENCRYPT; 1799a9de9248SMarcel Holtmann } 1800a9de9248SMarcel Holtmann 1801a9de9248SMarcel Holtmann clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); 1802a9de9248SMarcel Holtmann 1803f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1804f8558555SMarcel Holtmann if (!ev->status) 1805f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1806f8558555SMarcel Holtmann 1807f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1808f8558555SMarcel Holtmann hci_conn_put(conn); 1809f8558555SMarcel Holtmann } else 1810a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 1811a9de9248SMarcel Holtmann } 1812a9de9248SMarcel Holtmann 1813a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1814a9de9248SMarcel Holtmann } 1815a9de9248SMarcel Holtmann 1816a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1817a9de9248SMarcel Holtmann { 1818a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 1819a9de9248SMarcel Holtmann struct hci_conn *conn; 1820a9de9248SMarcel Holtmann 1821a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1822a9de9248SMarcel Holtmann 1823a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1824a9de9248SMarcel Holtmann 1825a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1826a9de9248SMarcel Holtmann if (conn) { 1827a9de9248SMarcel Holtmann if (!ev->status) 1828a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_SECURE; 1829a9de9248SMarcel Holtmann 1830a9de9248SMarcel Holtmann clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); 1831a9de9248SMarcel Holtmann 1832a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 1833a9de9248SMarcel Holtmann } 1834a9de9248SMarcel Holtmann 1835a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1836a9de9248SMarcel Holtmann } 1837a9de9248SMarcel Holtmann 1838a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 1839a9de9248SMarcel Holtmann { 1840a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 1841a9de9248SMarcel Holtmann struct hci_conn *conn; 1842a9de9248SMarcel Holtmann 1843a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1844a9de9248SMarcel Holtmann 1845a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1846a9de9248SMarcel Holtmann 1847a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1848ccd556feSJohan Hedberg if (!conn) 1849ccd556feSJohan Hedberg goto unlock; 1850ccd556feSJohan Hedberg 1851769be974SMarcel Holtmann if (!ev->status) 1852a9de9248SMarcel Holtmann memcpy(conn->features, ev->features, 8); 1853a9de9248SMarcel Holtmann 1854ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 1855ccd556feSJohan Hedberg goto unlock; 1856ccd556feSJohan Hedberg 1857ccd556feSJohan Hedberg if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { 1858769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 1859769be974SMarcel Holtmann cp.handle = ev->handle; 1860769be974SMarcel Holtmann cp.page = 0x01; 1861ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 1862769be974SMarcel Holtmann sizeof(cp), &cp); 1863392599b9SJohan Hedberg goto unlock; 1864392599b9SJohan Hedberg } 1865392599b9SJohan Hedberg 1866127178d2SJohan Hedberg if (!ev->status) { 1867127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 1868127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 1869127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 1870127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 1871127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 1872127178d2SJohan Hedberg } 1873392599b9SJohan Hedberg 1874127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 1875769be974SMarcel Holtmann conn->state = BT_CONNECTED; 1876769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1877769be974SMarcel Holtmann hci_conn_put(conn); 1878769be974SMarcel Holtmann } 1879769be974SMarcel Holtmann 1880ccd556feSJohan Hedberg unlock: 1881a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1882a9de9248SMarcel Holtmann } 1883a9de9248SMarcel Holtmann 1884a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) 1885a9de9248SMarcel Holtmann { 1886a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1887a9de9248SMarcel Holtmann } 1888a9de9248SMarcel Holtmann 1889a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1890a9de9248SMarcel Holtmann { 1891a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1892a9de9248SMarcel Holtmann } 1893a9de9248SMarcel Holtmann 1894a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1895a9de9248SMarcel Holtmann { 1896a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 1897a9de9248SMarcel Holtmann __u16 opcode; 1898a9de9248SMarcel Holtmann 1899a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 1900a9de9248SMarcel Holtmann 1901a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 1902a9de9248SMarcel Holtmann 1903a9de9248SMarcel Holtmann switch (opcode) { 1904a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 1905a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 1906a9de9248SMarcel Holtmann break; 1907a9de9248SMarcel Holtmann 1908a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 1909a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 1910a9de9248SMarcel Holtmann break; 1911a9de9248SMarcel Holtmann 1912a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 1913a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 1914a9de9248SMarcel Holtmann break; 1915a9de9248SMarcel Holtmann 1916a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 1917a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 1918a9de9248SMarcel Holtmann break; 1919a9de9248SMarcel Holtmann 1920e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 1921e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 1922e4e8e37cSMarcel Holtmann break; 1923e4e8e37cSMarcel Holtmann 1924a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 1925a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 1926a9de9248SMarcel Holtmann break; 1927a9de9248SMarcel Holtmann 1928e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 1929e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 1930e4e8e37cSMarcel Holtmann break; 1931e4e8e37cSMarcel Holtmann 1932e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 1933e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 1934e4e8e37cSMarcel Holtmann break; 1935e4e8e37cSMarcel Holtmann 1936a9de9248SMarcel Holtmann case HCI_OP_RESET: 1937a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 1938a9de9248SMarcel Holtmann break; 1939a9de9248SMarcel Holtmann 1940a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 1941a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 1942a9de9248SMarcel Holtmann break; 1943a9de9248SMarcel Holtmann 1944a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 1945a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 1946a9de9248SMarcel Holtmann break; 1947a9de9248SMarcel Holtmann 1948a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 1949a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 1950a9de9248SMarcel Holtmann break; 1951a9de9248SMarcel Holtmann 1952a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 1953a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 1954a9de9248SMarcel Holtmann break; 1955a9de9248SMarcel Holtmann 1956a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 1957a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 1958a9de9248SMarcel Holtmann break; 1959a9de9248SMarcel Holtmann 1960a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 1961a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 1962a9de9248SMarcel Holtmann break; 1963a9de9248SMarcel Holtmann 1964a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 1965a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 1966a9de9248SMarcel Holtmann break; 1967a9de9248SMarcel Holtmann 1968a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 1969a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 1970a9de9248SMarcel Holtmann break; 1971a9de9248SMarcel Holtmann 1972a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 1973a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 1974a9de9248SMarcel Holtmann break; 1975a9de9248SMarcel Holtmann 1976a9de9248SMarcel Holtmann case HCI_OP_HOST_BUFFER_SIZE: 1977a9de9248SMarcel Holtmann hci_cc_host_buffer_size(hdev, skb); 1978a9de9248SMarcel Holtmann break; 1979a9de9248SMarcel Holtmann 1980333140b5SMarcel Holtmann case HCI_OP_READ_SSP_MODE: 1981333140b5SMarcel Holtmann hci_cc_read_ssp_mode(hdev, skb); 1982333140b5SMarcel Holtmann break; 1983333140b5SMarcel Holtmann 1984333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 1985333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 1986333140b5SMarcel Holtmann break; 1987333140b5SMarcel Holtmann 1988a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 1989a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 1990a9de9248SMarcel Holtmann break; 1991a9de9248SMarcel Holtmann 1992a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 1993a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 1994a9de9248SMarcel Holtmann break; 1995a9de9248SMarcel Holtmann 1996a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 1997a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 1998a9de9248SMarcel Holtmann break; 1999a9de9248SMarcel Holtmann 2000971e3a4bSAndre Guedes case HCI_OP_READ_LOCAL_EXT_FEATURES: 2001971e3a4bSAndre Guedes hci_cc_read_local_ext_features(hdev, skb); 2002971e3a4bSAndre Guedes break; 2003971e3a4bSAndre Guedes 2004a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 2005a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 2006a9de9248SMarcel Holtmann break; 2007a9de9248SMarcel Holtmann 2008a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 2009a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 2010a9de9248SMarcel Holtmann break; 2011a9de9248SMarcel Holtmann 201223bb5763SJohan Hedberg case HCI_OP_WRITE_CA_TIMEOUT: 201323bb5763SJohan Hedberg hci_cc_write_ca_timeout(hdev, skb); 201423bb5763SJohan Hedberg break; 201523bb5763SJohan Hedberg 20161e89cffbSAndrei Emeltchenko case HCI_OP_READ_FLOW_CONTROL_MODE: 20171e89cffbSAndrei Emeltchenko hci_cc_read_flow_control_mode(hdev, skb); 20181e89cffbSAndrei Emeltchenko break; 20191e89cffbSAndrei Emeltchenko 2020928abaa7SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_INFO: 2021928abaa7SAndrei Emeltchenko hci_cc_read_local_amp_info(hdev, skb); 2022928abaa7SAndrei Emeltchenko break; 2023928abaa7SAndrei Emeltchenko 2024b0916ea0SJohan Hedberg case HCI_OP_DELETE_STORED_LINK_KEY: 2025b0916ea0SJohan Hedberg hci_cc_delete_stored_link_key(hdev, skb); 2026b0916ea0SJohan Hedberg break; 2027b0916ea0SJohan Hedberg 2028d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_MASK: 2029d5859e22SJohan Hedberg hci_cc_set_event_mask(hdev, skb); 2030d5859e22SJohan Hedberg break; 2031d5859e22SJohan Hedberg 2032d5859e22SJohan Hedberg case HCI_OP_WRITE_INQUIRY_MODE: 2033d5859e22SJohan Hedberg hci_cc_write_inquiry_mode(hdev, skb); 2034d5859e22SJohan Hedberg break; 2035d5859e22SJohan Hedberg 2036d5859e22SJohan Hedberg case HCI_OP_READ_INQ_RSP_TX_POWER: 2037d5859e22SJohan Hedberg hci_cc_read_inq_rsp_tx_power(hdev, skb); 2038d5859e22SJohan Hedberg break; 2039d5859e22SJohan Hedberg 2040d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_FLT: 2041d5859e22SJohan Hedberg hci_cc_set_event_flt(hdev, skb); 2042d5859e22SJohan Hedberg break; 2043d5859e22SJohan Hedberg 2044980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_REPLY: 2045980e1a53SJohan Hedberg hci_cc_pin_code_reply(hdev, skb); 2046980e1a53SJohan Hedberg break; 2047980e1a53SJohan Hedberg 2048980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_NEG_REPLY: 2049980e1a53SJohan Hedberg hci_cc_pin_code_neg_reply(hdev, skb); 2050980e1a53SJohan Hedberg break; 2051980e1a53SJohan Hedberg 2052c35938b2SSzymon Janc case HCI_OP_READ_LOCAL_OOB_DATA: 2053c35938b2SSzymon Janc hci_cc_read_local_oob_data_reply(hdev, skb); 2054c35938b2SSzymon Janc break; 2055c35938b2SSzymon Janc 20566ed58ec5SVille Tervo case HCI_OP_LE_READ_BUFFER_SIZE: 20576ed58ec5SVille Tervo hci_cc_le_read_buffer_size(hdev, skb); 20586ed58ec5SVille Tervo break; 20596ed58ec5SVille Tervo 2060a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_REPLY: 2061a5c29683SJohan Hedberg hci_cc_user_confirm_reply(hdev, skb); 2062a5c29683SJohan Hedberg break; 2063a5c29683SJohan Hedberg 2064a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_NEG_REPLY: 2065a5c29683SJohan Hedberg hci_cc_user_confirm_neg_reply(hdev, skb); 2066a5c29683SJohan Hedberg break; 2067a5c29683SJohan Hedberg 20681143d458SBrian Gix case HCI_OP_USER_PASSKEY_REPLY: 20691143d458SBrian Gix hci_cc_user_passkey_reply(hdev, skb); 20701143d458SBrian Gix break; 20711143d458SBrian Gix 20721143d458SBrian Gix case HCI_OP_USER_PASSKEY_NEG_REPLY: 20731143d458SBrian Gix hci_cc_user_passkey_neg_reply(hdev, skb); 20741143d458SBrian Gix break; 20751143d458SBrian Gix 2076eb9d91f5SAndre Guedes case HCI_OP_LE_SET_SCAN_ENABLE: 2077eb9d91f5SAndre Guedes hci_cc_le_set_scan_enable(hdev, skb); 2078eb9d91f5SAndre Guedes break; 2079eb9d91f5SAndre Guedes 2080a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_REPLY: 2081a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_reply(hdev, skb); 2082a7a595f6SVinicius Costa Gomes break; 2083a7a595f6SVinicius Costa Gomes 2084a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_NEG_REPLY: 2085a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_neg_reply(hdev, skb); 2086a7a595f6SVinicius Costa Gomes break; 2087a7a595f6SVinicius Costa Gomes 2088f9b49306SAndre Guedes case HCI_OP_WRITE_LE_HOST_SUPPORTED: 2089f9b49306SAndre Guedes hci_cc_write_le_host_supported(hdev, skb); 2090f9b49306SAndre Guedes break; 2091f9b49306SAndre Guedes 2092a9de9248SMarcel Holtmann default: 2093a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 2094a9de9248SMarcel Holtmann break; 2095a9de9248SMarcel Holtmann } 2096a9de9248SMarcel Holtmann 20976bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 20986bd32326SVille Tervo del_timer(&hdev->cmd_timer); 20996bd32326SVille Tervo 2100a9de9248SMarcel Holtmann if (ev->ncmd) { 2101a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2102a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2103c78ae283SMarcel Holtmann tasklet_schedule(&hdev->cmd_task); 2104a9de9248SMarcel Holtmann } 2105a9de9248SMarcel Holtmann } 2106a9de9248SMarcel Holtmann 2107a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 2108a9de9248SMarcel Holtmann { 2109a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 2110a9de9248SMarcel Holtmann __u16 opcode; 2111a9de9248SMarcel Holtmann 2112a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2113a9de9248SMarcel Holtmann 2114a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2115a9de9248SMarcel Holtmann 2116a9de9248SMarcel Holtmann switch (opcode) { 2117a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 2118a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 2119a9de9248SMarcel Holtmann break; 2120a9de9248SMarcel Holtmann 2121a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 2122a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 2123a9de9248SMarcel Holtmann break; 2124a9de9248SMarcel Holtmann 2125a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 2126a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 2127a9de9248SMarcel Holtmann break; 2128a9de9248SMarcel Holtmann 2129f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 2130f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 2131f8558555SMarcel Holtmann break; 2132f8558555SMarcel Holtmann 2133f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 2134f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 2135f8558555SMarcel Holtmann break; 2136f8558555SMarcel Holtmann 2137a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 2138a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 2139a9de9248SMarcel Holtmann break; 2140a9de9248SMarcel Holtmann 2141769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 2142769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 2143769be974SMarcel Holtmann break; 2144769be974SMarcel Holtmann 2145769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 2146769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 2147769be974SMarcel Holtmann break; 2148769be974SMarcel Holtmann 2149a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 2150a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 2151a9de9248SMarcel Holtmann break; 2152a9de9248SMarcel Holtmann 2153a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 2154a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 2155a9de9248SMarcel Holtmann break; 2156a9de9248SMarcel Holtmann 2157a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 2158a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 2159a9de9248SMarcel Holtmann break; 2160a9de9248SMarcel Holtmann 21618962ee74SJohan Hedberg case HCI_OP_DISCONNECT: 21628962ee74SJohan Hedberg if (ev->status != 0) 216337d9ef76SJohan Hedberg mgmt_disconnect_failed(hdev, NULL, ev->status); 21648962ee74SJohan Hedberg break; 21658962ee74SJohan Hedberg 2166fcd89c09SVille Tervo case HCI_OP_LE_CREATE_CONN: 2167fcd89c09SVille Tervo hci_cs_le_create_conn(hdev, ev->status); 2168fcd89c09SVille Tervo break; 2169fcd89c09SVille Tervo 2170a7a595f6SVinicius Costa Gomes case HCI_OP_LE_START_ENC: 2171a7a595f6SVinicius Costa Gomes hci_cs_le_start_enc(hdev, ev->status); 2172a7a595f6SVinicius Costa Gomes break; 2173a7a595f6SVinicius Costa Gomes 2174a9de9248SMarcel Holtmann default: 2175a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 2176a9de9248SMarcel Holtmann break; 2177a9de9248SMarcel Holtmann } 2178a9de9248SMarcel Holtmann 21796bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 21806bd32326SVille Tervo del_timer(&hdev->cmd_timer); 21816bd32326SVille Tervo 218210572132SGustavo F. Padovan if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2183a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2184a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2185c78ae283SMarcel Holtmann tasklet_schedule(&hdev->cmd_task); 2186a9de9248SMarcel Holtmann } 2187a9de9248SMarcel Holtmann } 2188a9de9248SMarcel Holtmann 2189a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2190a9de9248SMarcel Holtmann { 2191a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 2192a9de9248SMarcel Holtmann struct hci_conn *conn; 2193a9de9248SMarcel Holtmann 2194a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2195a9de9248SMarcel Holtmann 2196a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2197a9de9248SMarcel Holtmann 2198a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2199a9de9248SMarcel Holtmann if (conn) { 2200a9de9248SMarcel Holtmann if (!ev->status) { 2201a9de9248SMarcel Holtmann if (ev->role) 2202a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_MASTER; 2203a9de9248SMarcel Holtmann else 2204a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_MASTER; 2205a9de9248SMarcel Holtmann } 2206a9de9248SMarcel Holtmann 2207a9de9248SMarcel Holtmann clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend); 2208a9de9248SMarcel Holtmann 2209a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 2210a9de9248SMarcel Holtmann } 2211a9de9248SMarcel Holtmann 2212a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2213a9de9248SMarcel Holtmann } 2214a9de9248SMarcel Holtmann 22151da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 22161da177e4SLinus Torvalds { 2217a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 22181ebb9252SMarcel Holtmann __le16 *ptr; 22191da177e4SLinus Torvalds int i; 22201da177e4SLinus Torvalds 22211da177e4SLinus Torvalds skb_pull(skb, sizeof(*ev)); 22221da177e4SLinus Torvalds 22231da177e4SLinus Torvalds BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 22241da177e4SLinus Torvalds 22251da177e4SLinus Torvalds if (skb->len < ev->num_hndl * 4) { 22261da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 22271da177e4SLinus Torvalds return; 22281da177e4SLinus Torvalds } 22291da177e4SLinus Torvalds 22301da177e4SLinus Torvalds tasklet_disable(&hdev->tx_task); 22311da177e4SLinus Torvalds 22321ebb9252SMarcel Holtmann for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) { 22331da177e4SLinus Torvalds struct hci_conn *conn; 22341da177e4SLinus Torvalds __u16 handle, count; 22351da177e4SLinus Torvalds 223683985319SHarvey Harrison handle = get_unaligned_le16(ptr++); 223783985319SHarvey Harrison count = get_unaligned_le16(ptr++); 22381da177e4SLinus Torvalds 22391da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 22401da177e4SLinus Torvalds if (conn) { 22411da177e4SLinus Torvalds conn->sent -= count; 22421da177e4SLinus Torvalds 22435b7f9909SMarcel Holtmann if (conn->type == ACL_LINK) { 224470f23020SAndrei Emeltchenko hdev->acl_cnt += count; 224570f23020SAndrei Emeltchenko if (hdev->acl_cnt > hdev->acl_pkts) 22461da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 22476ed58ec5SVille Tervo } else if (conn->type == LE_LINK) { 22486ed58ec5SVille Tervo if (hdev->le_pkts) { 22496ed58ec5SVille Tervo hdev->le_cnt += count; 22506ed58ec5SVille Tervo if (hdev->le_cnt > hdev->le_pkts) 22516ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 22526ed58ec5SVille Tervo } else { 22536ed58ec5SVille Tervo hdev->acl_cnt += count; 22546ed58ec5SVille Tervo if (hdev->acl_cnt > hdev->acl_pkts) 22556ed58ec5SVille Tervo hdev->acl_cnt = hdev->acl_pkts; 22566ed58ec5SVille Tervo } 22575b7f9909SMarcel Holtmann } else { 225870f23020SAndrei Emeltchenko hdev->sco_cnt += count; 225970f23020SAndrei Emeltchenko if (hdev->sco_cnt > hdev->sco_pkts) 22605b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 22611da177e4SLinus Torvalds } 22621da177e4SLinus Torvalds } 22631da177e4SLinus Torvalds } 2264a9de9248SMarcel Holtmann 2265c78ae283SMarcel Holtmann tasklet_schedule(&hdev->tx_task); 22661da177e4SLinus Torvalds 22671da177e4SLinus Torvalds tasklet_enable(&hdev->tx_task); 22681da177e4SLinus Torvalds } 22691da177e4SLinus Torvalds 227004837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 22711da177e4SLinus Torvalds { 2272a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 227304837f64SMarcel Holtmann struct hci_conn *conn; 22741da177e4SLinus Torvalds 22751da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 22761da177e4SLinus Torvalds 22771da177e4SLinus Torvalds hci_dev_lock(hdev); 22781da177e4SLinus Torvalds 227904837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 228004837f64SMarcel Holtmann if (conn) { 228104837f64SMarcel Holtmann conn->mode = ev->mode; 228204837f64SMarcel Holtmann conn->interval = __le16_to_cpu(ev->interval); 228304837f64SMarcel Holtmann 228404837f64SMarcel Holtmann if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) { 228504837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 228604837f64SMarcel Holtmann conn->power_save = 1; 228704837f64SMarcel Holtmann else 228804837f64SMarcel Holtmann conn->power_save = 0; 228904837f64SMarcel Holtmann } 2290e73439d8SMarcel Holtmann 2291e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 2292e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 229304837f64SMarcel Holtmann } 229404837f64SMarcel Holtmann 229504837f64SMarcel Holtmann hci_dev_unlock(hdev); 229604837f64SMarcel Holtmann } 229704837f64SMarcel Holtmann 22981da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 22991da177e4SLinus Torvalds { 2300052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 2301052b30b0SMarcel Holtmann struct hci_conn *conn; 2302052b30b0SMarcel Holtmann 2303a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2304052b30b0SMarcel Holtmann 2305052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2306052b30b0SMarcel Holtmann 2307052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2308b6f98044SWaldemar Rymarkiewicz if (!conn) 2309b6f98044SWaldemar Rymarkiewicz goto unlock; 2310b6f98044SWaldemar Rymarkiewicz 2311b6f98044SWaldemar Rymarkiewicz if (conn->state == BT_CONNECTED) { 2312052b30b0SMarcel Holtmann hci_conn_hold(conn); 2313052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 2314052b30b0SMarcel Holtmann hci_conn_put(conn); 2315052b30b0SMarcel Holtmann } 2316052b30b0SMarcel Holtmann 231703b555e1SJohan Hedberg if (!test_bit(HCI_PAIRABLE, &hdev->flags)) 231803b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 231903b555e1SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 2320582fbe9eSJohan Hedberg else if (test_bit(HCI_MGMT, &hdev->flags)) { 2321a770bb5aSWaldemar Rymarkiewicz u8 secure; 2322a770bb5aSWaldemar Rymarkiewicz 2323a770bb5aSWaldemar Rymarkiewicz if (conn->pending_sec_level == BT_SECURITY_HIGH) 2324a770bb5aSWaldemar Rymarkiewicz secure = 1; 2325a770bb5aSWaldemar Rymarkiewicz else 2326a770bb5aSWaldemar Rymarkiewicz secure = 0; 2327a770bb5aSWaldemar Rymarkiewicz 2328744cf19eSJohan Hedberg mgmt_pin_code_request(hdev, &ev->bdaddr, secure); 2329a770bb5aSWaldemar Rymarkiewicz } 2330980e1a53SJohan Hedberg 2331b6f98044SWaldemar Rymarkiewicz unlock: 2332052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 23331da177e4SLinus Torvalds } 23341da177e4SLinus Torvalds 23351da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 23361da177e4SLinus Torvalds { 233755ed8ca1SJohan Hedberg struct hci_ev_link_key_req *ev = (void *) skb->data; 233855ed8ca1SJohan Hedberg struct hci_cp_link_key_reply cp; 233955ed8ca1SJohan Hedberg struct hci_conn *conn; 234055ed8ca1SJohan Hedberg struct link_key *key; 234155ed8ca1SJohan Hedberg 2342a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 234355ed8ca1SJohan Hedberg 234455ed8ca1SJohan Hedberg if (!test_bit(HCI_LINK_KEYS, &hdev->flags)) 234555ed8ca1SJohan Hedberg return; 234655ed8ca1SJohan Hedberg 234755ed8ca1SJohan Hedberg hci_dev_lock(hdev); 234855ed8ca1SJohan Hedberg 234955ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, &ev->bdaddr); 235055ed8ca1SJohan Hedberg if (!key) { 235155ed8ca1SJohan Hedberg BT_DBG("%s link key not found for %s", hdev->name, 235255ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 235355ed8ca1SJohan Hedberg goto not_found; 235455ed8ca1SJohan Hedberg } 235555ed8ca1SJohan Hedberg 235655ed8ca1SJohan Hedberg BT_DBG("%s found key type %u for %s", hdev->name, key->type, 235755ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 235855ed8ca1SJohan Hedberg 2359b6020ba0SWaldemar Rymarkiewicz if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) && 2360b6020ba0SWaldemar Rymarkiewicz key->type == HCI_LK_DEBUG_COMBINATION) { 236155ed8ca1SJohan Hedberg BT_DBG("%s ignoring debug key", hdev->name); 236255ed8ca1SJohan Hedberg goto not_found; 236355ed8ca1SJohan Hedberg } 236455ed8ca1SJohan Hedberg 236555ed8ca1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 236660b83f57SWaldemar Rymarkiewicz if (conn) { 236760b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_UNAUTH_COMBINATION && 236860b83f57SWaldemar Rymarkiewicz conn->auth_type != 0xff && 236960b83f57SWaldemar Rymarkiewicz (conn->auth_type & 0x01)) { 237055ed8ca1SJohan Hedberg BT_DBG("%s ignoring unauthenticated key", hdev->name); 237155ed8ca1SJohan Hedberg goto not_found; 237255ed8ca1SJohan Hedberg } 237355ed8ca1SJohan Hedberg 237460b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && 237560b83f57SWaldemar Rymarkiewicz conn->pending_sec_level == BT_SECURITY_HIGH) { 237660b83f57SWaldemar Rymarkiewicz BT_DBG("%s ignoring key unauthenticated for high \ 237760b83f57SWaldemar Rymarkiewicz security", hdev->name); 237860b83f57SWaldemar Rymarkiewicz goto not_found; 237960b83f57SWaldemar Rymarkiewicz } 238060b83f57SWaldemar Rymarkiewicz 238160b83f57SWaldemar Rymarkiewicz conn->key_type = key->type; 238260b83f57SWaldemar Rymarkiewicz conn->pin_length = key->pin_len; 238360b83f57SWaldemar Rymarkiewicz } 238460b83f57SWaldemar Rymarkiewicz 238555ed8ca1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 238655ed8ca1SJohan Hedberg memcpy(cp.link_key, key->val, 16); 238755ed8ca1SJohan Hedberg 238855ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 238955ed8ca1SJohan Hedberg 239055ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 239155ed8ca1SJohan Hedberg 239255ed8ca1SJohan Hedberg return; 239355ed8ca1SJohan Hedberg 239455ed8ca1SJohan Hedberg not_found: 239555ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 239655ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 23971da177e4SLinus Torvalds } 23981da177e4SLinus Torvalds 23991da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 24001da177e4SLinus Torvalds { 2401052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 2402052b30b0SMarcel Holtmann struct hci_conn *conn; 240355ed8ca1SJohan Hedberg u8 pin_len = 0; 2404052b30b0SMarcel Holtmann 2405a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2406052b30b0SMarcel Holtmann 2407052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2408052b30b0SMarcel Holtmann 2409052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2410052b30b0SMarcel Holtmann if (conn) { 2411052b30b0SMarcel Holtmann hci_conn_hold(conn); 2412052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2413980e1a53SJohan Hedberg pin_len = conn->pin_length; 241413d39315SWaldemar Rymarkiewicz 241513d39315SWaldemar Rymarkiewicz if (ev->key_type != HCI_LK_CHANGED_COMBINATION) 241613d39315SWaldemar Rymarkiewicz conn->key_type = ev->key_type; 241713d39315SWaldemar Rymarkiewicz 2418052b30b0SMarcel Holtmann hci_conn_put(conn); 2419052b30b0SMarcel Holtmann } 2420052b30b0SMarcel Holtmann 242155ed8ca1SJohan Hedberg if (test_bit(HCI_LINK_KEYS, &hdev->flags)) 2422d25e28abSJohan Hedberg hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, 242355ed8ca1SJohan Hedberg ev->key_type, pin_len); 242455ed8ca1SJohan Hedberg 2425052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 24261da177e4SLinus Torvalds } 24271da177e4SLinus Torvalds 242804837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 242904837f64SMarcel Holtmann { 2430a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 243104837f64SMarcel Holtmann struct hci_conn *conn; 243204837f64SMarcel Holtmann 243304837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 243404837f64SMarcel Holtmann 243504837f64SMarcel Holtmann hci_dev_lock(hdev); 243604837f64SMarcel Holtmann 243704837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 24381da177e4SLinus Torvalds if (conn && !ev->status) { 24391da177e4SLinus Torvalds struct inquiry_entry *ie; 24401da177e4SLinus Torvalds 2441cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2442cc11b9c1SAndrei Emeltchenko if (ie) { 24431da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 24441da177e4SLinus Torvalds ie->timestamp = jiffies; 24451da177e4SLinus Torvalds } 24461da177e4SLinus Torvalds } 24471da177e4SLinus Torvalds 24481da177e4SLinus Torvalds hci_dev_unlock(hdev); 24491da177e4SLinus Torvalds } 24501da177e4SLinus Torvalds 2451a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2452a8746417SMarcel Holtmann { 2453a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 2454a8746417SMarcel Holtmann struct hci_conn *conn; 2455a8746417SMarcel Holtmann 2456a8746417SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2457a8746417SMarcel Holtmann 2458a8746417SMarcel Holtmann hci_dev_lock(hdev); 2459a8746417SMarcel Holtmann 2460a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2461a8746417SMarcel Holtmann if (conn && !ev->status) 2462a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 2463a8746417SMarcel Holtmann 2464a8746417SMarcel Holtmann hci_dev_unlock(hdev); 2465a8746417SMarcel Holtmann } 2466a8746417SMarcel Holtmann 246785a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 246885a1e930SMarcel Holtmann { 2469a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 247085a1e930SMarcel Holtmann struct inquiry_entry *ie; 247185a1e930SMarcel Holtmann 247285a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 247385a1e930SMarcel Holtmann 247485a1e930SMarcel Holtmann hci_dev_lock(hdev); 247585a1e930SMarcel Holtmann 2476cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2477cc11b9c1SAndrei Emeltchenko if (ie) { 247885a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 247985a1e930SMarcel Holtmann ie->timestamp = jiffies; 248085a1e930SMarcel Holtmann } 248185a1e930SMarcel Holtmann 248285a1e930SMarcel Holtmann hci_dev_unlock(hdev); 248385a1e930SMarcel Holtmann } 248485a1e930SMarcel Holtmann 2485a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb) 2486a9de9248SMarcel Holtmann { 2487a9de9248SMarcel Holtmann struct inquiry_data data; 2488a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2489a9de9248SMarcel Holtmann 2490a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2491a9de9248SMarcel Holtmann 2492a9de9248SMarcel Holtmann if (!num_rsp) 2493a9de9248SMarcel Holtmann return; 2494a9de9248SMarcel Holtmann 2495a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2496a9de9248SMarcel Holtmann 2497a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 2498138d22efSSzymon Janc struct inquiry_info_with_rssi_and_pscan_mode *info; 2499138d22efSSzymon Janc info = (void *) (skb->data + 1); 2500a9de9248SMarcel Holtmann 2501e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2502a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2503a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2504a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2505a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 2506a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2507a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2508a9de9248SMarcel Holtmann data.rssi = info->rssi; 250941a96212SMarcel Holtmann data.ssp_mode = 0x00; 2510a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 251148264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2512e17acd40SJohan Hedberg info->dev_class, info->rssi, 2513e17acd40SJohan Hedberg NULL); 2514a9de9248SMarcel Holtmann } 2515a9de9248SMarcel Holtmann } else { 2516a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 2517a9de9248SMarcel Holtmann 2518e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2519a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2520a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2521a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2522a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2523a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2524a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2525a9de9248SMarcel Holtmann data.rssi = info->rssi; 252641a96212SMarcel Holtmann data.ssp_mode = 0x00; 2527a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 252848264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2529e17acd40SJohan Hedberg info->dev_class, info->rssi, 2530e17acd40SJohan Hedberg NULL); 2531a9de9248SMarcel Holtmann } 2532a9de9248SMarcel Holtmann } 2533a9de9248SMarcel Holtmann 2534a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2535a9de9248SMarcel Holtmann } 2536a9de9248SMarcel Holtmann 2537a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 2538a9de9248SMarcel Holtmann { 253941a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 254041a96212SMarcel Holtmann struct hci_conn *conn; 254141a96212SMarcel Holtmann 2542a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 254341a96212SMarcel Holtmann 254441a96212SMarcel Holtmann hci_dev_lock(hdev); 254541a96212SMarcel Holtmann 254641a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2547ccd556feSJohan Hedberg if (!conn) 2548ccd556feSJohan Hedberg goto unlock; 2549ccd556feSJohan Hedberg 2550769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 255141a96212SMarcel Holtmann struct inquiry_entry *ie; 255241a96212SMarcel Holtmann 2553cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2554cc11b9c1SAndrei Emeltchenko if (ie) 255541a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 255641a96212SMarcel Holtmann 255741a96212SMarcel Holtmann conn->ssp_mode = (ev->features[0] & 0x01); 255841a96212SMarcel Holtmann } 255941a96212SMarcel Holtmann 2560ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2561ccd556feSJohan Hedberg goto unlock; 2562ccd556feSJohan Hedberg 2563127178d2SJohan Hedberg if (!ev->status) { 2564127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2565127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2566127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2567127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2568127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2569127178d2SJohan Hedberg } 2570392599b9SJohan Hedberg 2571127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2572769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2573769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2574769be974SMarcel Holtmann hci_conn_put(conn); 2575769be974SMarcel Holtmann } 2576769be974SMarcel Holtmann 2577ccd556feSJohan Hedberg unlock: 257841a96212SMarcel Holtmann hci_dev_unlock(hdev); 2579a9de9248SMarcel Holtmann } 2580a9de9248SMarcel Holtmann 2581a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2582a9de9248SMarcel Holtmann { 2583b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 2584b6a0dc82SMarcel Holtmann struct hci_conn *conn; 2585b6a0dc82SMarcel Holtmann 2586b6a0dc82SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2587b6a0dc82SMarcel Holtmann 2588b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 2589b6a0dc82SMarcel Holtmann 2590b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 25919dc0a3afSMarcel Holtmann if (!conn) { 25929dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 25939dc0a3afSMarcel Holtmann goto unlock; 25949dc0a3afSMarcel Holtmann 25959dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 2596b6a0dc82SMarcel Holtmann if (!conn) 2597b6a0dc82SMarcel Holtmann goto unlock; 2598b6a0dc82SMarcel Holtmann 25999dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 26009dc0a3afSMarcel Holtmann } 26019dc0a3afSMarcel Holtmann 2602732547f9SMarcel Holtmann switch (ev->status) { 2603732547f9SMarcel Holtmann case 0x00: 2604732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 2605732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 2606732547f9SMarcel Holtmann 26079eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 2608732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 2609732547f9SMarcel Holtmann break; 2610732547f9SMarcel Holtmann 2611705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 2612732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 26131038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 2614732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 2615732547f9SMarcel Holtmann if (conn->out && conn->attempt < 2) { 2616efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 2617efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 2618efc7688bSMarcel Holtmann hci_setup_sync(conn, conn->link->handle); 2619efc7688bSMarcel Holtmann goto unlock; 2620efc7688bSMarcel Holtmann } 2621732547f9SMarcel Holtmann /* fall through */ 2622efc7688bSMarcel Holtmann 2623732547f9SMarcel Holtmann default: 2624b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 2625732547f9SMarcel Holtmann break; 2626732547f9SMarcel Holtmann } 2627b6a0dc82SMarcel Holtmann 2628b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2629b6a0dc82SMarcel Holtmann if (ev->status) 2630b6a0dc82SMarcel Holtmann hci_conn_del(conn); 2631b6a0dc82SMarcel Holtmann 2632b6a0dc82SMarcel Holtmann unlock: 2633b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 2634a9de9248SMarcel Holtmann } 2635a9de9248SMarcel Holtmann 2636a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) 2637a9de9248SMarcel Holtmann { 2638a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2639a9de9248SMarcel Holtmann } 2640a9de9248SMarcel Holtmann 264104837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) 264204837f64SMarcel Holtmann { 2643a9de9248SMarcel Holtmann struct hci_ev_sniff_subrate *ev = (void *) skb->data; 264404837f64SMarcel Holtmann 264504837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 264604837f64SMarcel Holtmann } 264704837f64SMarcel Holtmann 2648a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 2649a9de9248SMarcel Holtmann { 2650a9de9248SMarcel Holtmann struct inquiry_data data; 2651a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 2652a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2653a9de9248SMarcel Holtmann 2654a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2655a9de9248SMarcel Holtmann 2656a9de9248SMarcel Holtmann if (!num_rsp) 2657a9de9248SMarcel Holtmann return; 2658a9de9248SMarcel Holtmann 2659a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2660a9de9248SMarcel Holtmann 2661e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2662a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2663a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2664a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2665a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2666a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2667a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2668a9de9248SMarcel Holtmann data.rssi = info->rssi; 266941a96212SMarcel Holtmann data.ssp_mode = 0x01; 2670a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 267148264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 26724c659c39SJohan Hedberg info->dev_class, info->rssi, info->data); 2673a9de9248SMarcel Holtmann } 2674a9de9248SMarcel Holtmann 2675a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2676a9de9248SMarcel Holtmann } 2677a9de9248SMarcel Holtmann 267817fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn) 267917fa4b9dSJohan Hedberg { 268017fa4b9dSJohan Hedberg /* If remote requests dedicated bonding follow that lead */ 268117fa4b9dSJohan Hedberg if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) { 268217fa4b9dSJohan Hedberg /* If both remote and local IO capabilities allow MITM 268317fa4b9dSJohan Hedberg * protection then require it, otherwise don't */ 268417fa4b9dSJohan Hedberg if (conn->remote_cap == 0x03 || conn->io_capability == 0x03) 268517fa4b9dSJohan Hedberg return 0x02; 268617fa4b9dSJohan Hedberg else 268717fa4b9dSJohan Hedberg return 0x03; 268817fa4b9dSJohan Hedberg } 268917fa4b9dSJohan Hedberg 269017fa4b9dSJohan Hedberg /* If remote requests no-bonding follow that lead */ 269117fa4b9dSJohan Hedberg if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01) 269258797bf7SWaldemar Rymarkiewicz return conn->remote_auth | (conn->auth_type & 0x01); 269317fa4b9dSJohan Hedberg 269417fa4b9dSJohan Hedberg return conn->auth_type; 269517fa4b9dSJohan Hedberg } 269617fa4b9dSJohan Hedberg 26970493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 26980493684eSMarcel Holtmann { 26990493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 27000493684eSMarcel Holtmann struct hci_conn *conn; 27010493684eSMarcel Holtmann 27020493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 27030493684eSMarcel Holtmann 27040493684eSMarcel Holtmann hci_dev_lock(hdev); 27050493684eSMarcel Holtmann 27060493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 270703b555e1SJohan Hedberg if (!conn) 270803b555e1SJohan Hedberg goto unlock; 270903b555e1SJohan Hedberg 27100493684eSMarcel Holtmann hci_conn_hold(conn); 27110493684eSMarcel Holtmann 271203b555e1SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->flags)) 271303b555e1SJohan Hedberg goto unlock; 271403b555e1SJohan Hedberg 271503b555e1SJohan Hedberg if (test_bit(HCI_PAIRABLE, &hdev->flags) || 271603b555e1SJohan Hedberg (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 271717fa4b9dSJohan Hedberg struct hci_cp_io_capability_reply cp; 271817fa4b9dSJohan Hedberg 271917fa4b9dSJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 272017fa4b9dSJohan Hedberg cp.capability = conn->io_capability; 27217cbc9bd9SJohan Hedberg conn->auth_type = hci_get_auth_req(conn); 27227cbc9bd9SJohan Hedberg cp.authentication = conn->auth_type; 272317fa4b9dSJohan Hedberg 2724ce85ee13SSzymon Janc if ((conn->out == 0x01 || conn->remote_oob == 0x01) && 2725ce85ee13SSzymon Janc hci_find_remote_oob_data(hdev, &conn->dst)) 2726ce85ee13SSzymon Janc cp.oob_data = 0x01; 2727ce85ee13SSzymon Janc else 2728ce85ee13SSzymon Janc cp.oob_data = 0x00; 2729ce85ee13SSzymon Janc 273017fa4b9dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, 273117fa4b9dSJohan Hedberg sizeof(cp), &cp); 273203b555e1SJohan Hedberg } else { 273303b555e1SJohan Hedberg struct hci_cp_io_capability_neg_reply cp; 273403b555e1SJohan Hedberg 273503b555e1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 27369f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED; 273703b555e1SJohan Hedberg 273803b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 273903b555e1SJohan Hedberg sizeof(cp), &cp); 274003b555e1SJohan Hedberg } 274103b555e1SJohan Hedberg 274203b555e1SJohan Hedberg unlock: 274303b555e1SJohan Hedberg hci_dev_unlock(hdev); 274403b555e1SJohan Hedberg } 274503b555e1SJohan Hedberg 274603b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 274703b555e1SJohan Hedberg { 274803b555e1SJohan Hedberg struct hci_ev_io_capa_reply *ev = (void *) skb->data; 274903b555e1SJohan Hedberg struct hci_conn *conn; 275003b555e1SJohan Hedberg 275103b555e1SJohan Hedberg BT_DBG("%s", hdev->name); 275203b555e1SJohan Hedberg 275303b555e1SJohan Hedberg hci_dev_lock(hdev); 275403b555e1SJohan Hedberg 275503b555e1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 275603b555e1SJohan Hedberg if (!conn) 275703b555e1SJohan Hedberg goto unlock; 275803b555e1SJohan Hedberg 275903b555e1SJohan Hedberg conn->remote_cap = ev->capability; 276003b555e1SJohan Hedberg conn->remote_oob = ev->oob_data; 276103b555e1SJohan Hedberg conn->remote_auth = ev->authentication; 276203b555e1SJohan Hedberg 276303b555e1SJohan Hedberg unlock: 27640493684eSMarcel Holtmann hci_dev_unlock(hdev); 27650493684eSMarcel Holtmann } 27660493684eSMarcel Holtmann 2767a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev, 2768a5c29683SJohan Hedberg struct sk_buff *skb) 2769a5c29683SJohan Hedberg { 2770a5c29683SJohan Hedberg struct hci_ev_user_confirm_req *ev = (void *) skb->data; 277155bc1a37SJohan Hedberg int loc_mitm, rem_mitm, confirm_hint = 0; 27727a828908SJohan Hedberg struct hci_conn *conn; 2773a5c29683SJohan Hedberg 2774a5c29683SJohan Hedberg BT_DBG("%s", hdev->name); 2775a5c29683SJohan Hedberg 2776a5c29683SJohan Hedberg hci_dev_lock(hdev); 2777a5c29683SJohan Hedberg 27787a828908SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->flags)) 27797a828908SJohan Hedberg goto unlock; 27807a828908SJohan Hedberg 27817a828908SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 27827a828908SJohan Hedberg if (!conn) 27837a828908SJohan Hedberg goto unlock; 27847a828908SJohan Hedberg 27857a828908SJohan Hedberg loc_mitm = (conn->auth_type & 0x01); 27867a828908SJohan Hedberg rem_mitm = (conn->remote_auth & 0x01); 27877a828908SJohan Hedberg 27887a828908SJohan Hedberg /* If we require MITM but the remote device can't provide that 27897a828908SJohan Hedberg * (it has NoInputNoOutput) then reject the confirmation 27907a828908SJohan Hedberg * request. The only exception is when we're dedicated bonding 27917a828908SJohan Hedberg * initiators (connect_cfm_cb set) since then we always have the MITM 27927a828908SJohan Hedberg * bit set. */ 27937a828908SJohan Hedberg if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) { 27947a828908SJohan Hedberg BT_DBG("Rejecting request: remote device can't provide MITM"); 27957a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, 27967a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 27977a828908SJohan Hedberg goto unlock; 27987a828908SJohan Hedberg } 27997a828908SJohan Hedberg 28007a828908SJohan Hedberg /* If no side requires MITM protection; auto-accept */ 28017a828908SJohan Hedberg if ((!loc_mitm || conn->remote_cap == 0x03) && 28027a828908SJohan Hedberg (!rem_mitm || conn->io_capability == 0x03)) { 280355bc1a37SJohan Hedberg 280455bc1a37SJohan Hedberg /* If we're not the initiators request authorization to 280555bc1a37SJohan Hedberg * proceed from user space (mgmt_user_confirm with 280655bc1a37SJohan Hedberg * confirm_hint set to 1). */ 280755bc1a37SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { 280855bc1a37SJohan Hedberg BT_DBG("Confirming auto-accept as acceptor"); 280955bc1a37SJohan Hedberg confirm_hint = 1; 281055bc1a37SJohan Hedberg goto confirm; 281155bc1a37SJohan Hedberg } 281255bc1a37SJohan Hedberg 28139f61656aSJohan Hedberg BT_DBG("Auto-accept of user confirmation with %ums delay", 28149f61656aSJohan Hedberg hdev->auto_accept_delay); 28159f61656aSJohan Hedberg 28169f61656aSJohan Hedberg if (hdev->auto_accept_delay > 0) { 28179f61656aSJohan Hedberg int delay = msecs_to_jiffies(hdev->auto_accept_delay); 28189f61656aSJohan Hedberg mod_timer(&conn->auto_accept_timer, jiffies + delay); 28199f61656aSJohan Hedberg goto unlock; 28209f61656aSJohan Hedberg } 28219f61656aSJohan Hedberg 28227a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, 28237a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 28247a828908SJohan Hedberg goto unlock; 28257a828908SJohan Hedberg } 28267a828908SJohan Hedberg 282755bc1a37SJohan Hedberg confirm: 2828744cf19eSJohan Hedberg mgmt_user_confirm_request(hdev, &ev->bdaddr, ev->passkey, 282955bc1a37SJohan Hedberg confirm_hint); 2830a5c29683SJohan Hedberg 28317a828908SJohan Hedberg unlock: 2832a5c29683SJohan Hedberg hci_dev_unlock(hdev); 2833a5c29683SJohan Hedberg } 2834a5c29683SJohan Hedberg 28351143d458SBrian Gix static inline void hci_user_passkey_request_evt(struct hci_dev *hdev, 28361143d458SBrian Gix struct sk_buff *skb) 28371143d458SBrian Gix { 28381143d458SBrian Gix struct hci_ev_user_passkey_req *ev = (void *) skb->data; 28391143d458SBrian Gix 28401143d458SBrian Gix BT_DBG("%s", hdev->name); 28411143d458SBrian Gix 28421143d458SBrian Gix hci_dev_lock(hdev); 28431143d458SBrian Gix 28441143d458SBrian Gix if (test_bit(HCI_MGMT, &hdev->flags)) 28451143d458SBrian Gix mgmt_user_passkey_request(hdev, &ev->bdaddr); 28461143d458SBrian Gix 28471143d458SBrian Gix hci_dev_unlock(hdev); 28481143d458SBrian Gix } 28491143d458SBrian Gix 28500493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 28510493684eSMarcel Holtmann { 28520493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 28530493684eSMarcel Holtmann struct hci_conn *conn; 28540493684eSMarcel Holtmann 28550493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 28560493684eSMarcel Holtmann 28570493684eSMarcel Holtmann hci_dev_lock(hdev); 28580493684eSMarcel Holtmann 28590493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 28602a611692SJohan Hedberg if (!conn) 28612a611692SJohan Hedberg goto unlock; 28622a611692SJohan Hedberg 28632a611692SJohan Hedberg /* To avoid duplicate auth_failed events to user space we check 28642a611692SJohan Hedberg * the HCI_CONN_AUTH_PEND flag which will be set if we 28652a611692SJohan Hedberg * initiated the authentication. A traditional auth_complete 28662a611692SJohan Hedberg * event gets always produced as initiator and is also mapped to 28672a611692SJohan Hedberg * the mgmt_auth_failed event */ 28682a611692SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0) 2869744cf19eSJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, ev->status); 28702a611692SJohan Hedberg 28710493684eSMarcel Holtmann hci_conn_put(conn); 28720493684eSMarcel Holtmann 28732a611692SJohan Hedberg unlock: 28740493684eSMarcel Holtmann hci_dev_unlock(hdev); 28750493684eSMarcel Holtmann } 28760493684eSMarcel Holtmann 287741a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 287841a96212SMarcel Holtmann { 287941a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 288041a96212SMarcel Holtmann struct inquiry_entry *ie; 288141a96212SMarcel Holtmann 288241a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 288341a96212SMarcel Holtmann 288441a96212SMarcel Holtmann hci_dev_lock(hdev); 288541a96212SMarcel Holtmann 2886cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2887cc11b9c1SAndrei Emeltchenko if (ie) 288841a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 288941a96212SMarcel Holtmann 289041a96212SMarcel Holtmann hci_dev_unlock(hdev); 289141a96212SMarcel Holtmann } 289241a96212SMarcel Holtmann 28932763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev, 28942763eda6SSzymon Janc struct sk_buff *skb) 28952763eda6SSzymon Janc { 28962763eda6SSzymon Janc struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; 28972763eda6SSzymon Janc struct oob_data *data; 28982763eda6SSzymon Janc 28992763eda6SSzymon Janc BT_DBG("%s", hdev->name); 29002763eda6SSzymon Janc 29012763eda6SSzymon Janc hci_dev_lock(hdev); 29022763eda6SSzymon Janc 2903e1ba1f15SSzymon Janc if (!test_bit(HCI_MGMT, &hdev->flags)) 2904e1ba1f15SSzymon Janc goto unlock; 2905e1ba1f15SSzymon Janc 29062763eda6SSzymon Janc data = hci_find_remote_oob_data(hdev, &ev->bdaddr); 29072763eda6SSzymon Janc if (data) { 29082763eda6SSzymon Janc struct hci_cp_remote_oob_data_reply cp; 29092763eda6SSzymon Janc 29102763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 29112763eda6SSzymon Janc memcpy(cp.hash, data->hash, sizeof(cp.hash)); 29122763eda6SSzymon Janc memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); 29132763eda6SSzymon Janc 29142763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), 29152763eda6SSzymon Janc &cp); 29162763eda6SSzymon Janc } else { 29172763eda6SSzymon Janc struct hci_cp_remote_oob_data_neg_reply cp; 29182763eda6SSzymon Janc 29192763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 29202763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), 29212763eda6SSzymon Janc &cp); 29222763eda6SSzymon Janc } 29232763eda6SSzymon Janc 2924e1ba1f15SSzymon Janc unlock: 29252763eda6SSzymon Janc hci_dev_unlock(hdev); 29262763eda6SSzymon Janc } 29272763eda6SSzymon Janc 2928fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2929fcd89c09SVille Tervo { 2930fcd89c09SVille Tervo struct hci_ev_le_conn_complete *ev = (void *) skb->data; 2931fcd89c09SVille Tervo struct hci_conn *conn; 2932fcd89c09SVille Tervo 2933fcd89c09SVille Tervo BT_DBG("%s status %d", hdev->name, ev->status); 2934fcd89c09SVille Tervo 2935fcd89c09SVille Tervo hci_dev_lock(hdev); 2936fcd89c09SVille Tervo 2937fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr); 2938b62f328bSVille Tervo if (!conn) { 2939b62f328bSVille Tervo conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); 2940b62f328bSVille Tervo if (!conn) { 2941b62f328bSVille Tervo BT_ERR("No memory for new connection"); 2942b62f328bSVille Tervo hci_dev_unlock(hdev); 2943b62f328bSVille Tervo return; 2944b62f328bSVille Tervo } 294529b7988aSAndre Guedes 294629b7988aSAndre Guedes conn->dst_type = ev->bdaddr_type; 2947b62f328bSVille Tervo } 2948fcd89c09SVille Tervo 2949fcd89c09SVille Tervo if (ev->status) { 295048264f06SJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 295148264f06SJohan Hedberg conn->dst_type, ev->status); 2952fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 2953fcd89c09SVille Tervo conn->state = BT_CLOSED; 2954fcd89c09SVille Tervo hci_conn_del(conn); 2955fcd89c09SVille Tervo goto unlock; 2956fcd89c09SVille Tervo } 2957fcd89c09SVille Tervo 295848264f06SJohan Hedberg mgmt_connected(hdev, &ev->bdaddr, conn->type, conn->dst_type); 295983bc71b4SVinicius Costa Gomes 29607b5c0d52SVinicius Costa Gomes conn->sec_level = BT_SECURITY_LOW; 2961fcd89c09SVille Tervo conn->handle = __le16_to_cpu(ev->handle); 2962fcd89c09SVille Tervo conn->state = BT_CONNECTED; 2963fcd89c09SVille Tervo 2964fcd89c09SVille Tervo hci_conn_hold_device(conn); 2965fcd89c09SVille Tervo hci_conn_add_sysfs(conn); 2966fcd89c09SVille Tervo 2967fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 2968fcd89c09SVille Tervo 2969fcd89c09SVille Tervo unlock: 2970fcd89c09SVille Tervo hci_dev_unlock(hdev); 2971fcd89c09SVille Tervo } 2972fcd89c09SVille Tervo 29739aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev, 29749aa04c91SAndre Guedes struct sk_buff *skb) 29759aa04c91SAndre Guedes { 2976e95beb41SAndre Guedes u8 num_reports = skb->data[0]; 2977e95beb41SAndre Guedes void *ptr = &skb->data[1]; 29789aa04c91SAndre Guedes 29799aa04c91SAndre Guedes hci_dev_lock(hdev); 29809aa04c91SAndre Guedes 2981e95beb41SAndre Guedes while (num_reports--) { 2982e95beb41SAndre Guedes struct hci_ev_le_advertising_info *ev = ptr; 2983e95beb41SAndre Guedes 29849aa04c91SAndre Guedes hci_add_adv_entry(hdev, ev); 29859aa04c91SAndre Guedes 2986e95beb41SAndre Guedes ptr += sizeof(*ev) + ev->length + 1; 29879aa04c91SAndre Guedes } 29889aa04c91SAndre Guedes 29899aa04c91SAndre Guedes hci_dev_unlock(hdev); 29909aa04c91SAndre Guedes } 29919aa04c91SAndre Guedes 2992a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev, 2993a7a595f6SVinicius Costa Gomes struct sk_buff *skb) 2994a7a595f6SVinicius Costa Gomes { 2995a7a595f6SVinicius Costa Gomes struct hci_ev_le_ltk_req *ev = (void *) skb->data; 2996a7a595f6SVinicius Costa Gomes struct hci_cp_le_ltk_reply cp; 2997bea710feSVinicius Costa Gomes struct hci_cp_le_ltk_neg_reply neg; 2998a7a595f6SVinicius Costa Gomes struct hci_conn *conn; 2999bea710feSVinicius Costa Gomes struct link_key *ltk; 3000a7a595f6SVinicius Costa Gomes 3001a7a595f6SVinicius Costa Gomes BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle)); 3002a7a595f6SVinicius Costa Gomes 3003a7a595f6SVinicius Costa Gomes hci_dev_lock(hdev); 3004a7a595f6SVinicius Costa Gomes 3005a7a595f6SVinicius Costa Gomes conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3006bea710feSVinicius Costa Gomes if (conn == NULL) 3007bea710feSVinicius Costa Gomes goto not_found; 3008a7a595f6SVinicius Costa Gomes 3009bea710feSVinicius Costa Gomes ltk = hci_find_ltk(hdev, ev->ediv, ev->random); 3010bea710feSVinicius Costa Gomes if (ltk == NULL) 3011bea710feSVinicius Costa Gomes goto not_found; 3012bea710feSVinicius Costa Gomes 3013bea710feSVinicius Costa Gomes memcpy(cp.ltk, ltk->val, sizeof(ltk->val)); 3014a7a595f6SVinicius Costa Gomes cp.handle = cpu_to_le16(conn->handle); 3015726b4ffcSVinicius Costa Gomes conn->pin_length = ltk->pin_len; 3016a7a595f6SVinicius Costa Gomes 3017a7a595f6SVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); 3018a7a595f6SVinicius Costa Gomes 3019a7a595f6SVinicius Costa Gomes hci_dev_unlock(hdev); 3020bea710feSVinicius Costa Gomes 3021bea710feSVinicius Costa Gomes return; 3022bea710feSVinicius Costa Gomes 3023bea710feSVinicius Costa Gomes not_found: 3024bea710feSVinicius Costa Gomes neg.handle = ev->handle; 3025bea710feSVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg); 3026bea710feSVinicius Costa Gomes hci_dev_unlock(hdev); 3027a7a595f6SVinicius Costa Gomes } 3028a7a595f6SVinicius Costa Gomes 3029fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 3030fcd89c09SVille Tervo { 3031fcd89c09SVille Tervo struct hci_ev_le_meta *le_ev = (void *) skb->data; 3032fcd89c09SVille Tervo 3033fcd89c09SVille Tervo skb_pull(skb, sizeof(*le_ev)); 3034fcd89c09SVille Tervo 3035fcd89c09SVille Tervo switch (le_ev->subevent) { 3036fcd89c09SVille Tervo case HCI_EV_LE_CONN_COMPLETE: 3037fcd89c09SVille Tervo hci_le_conn_complete_evt(hdev, skb); 3038fcd89c09SVille Tervo break; 3039fcd89c09SVille Tervo 30409aa04c91SAndre Guedes case HCI_EV_LE_ADVERTISING_REPORT: 30419aa04c91SAndre Guedes hci_le_adv_report_evt(hdev, skb); 30429aa04c91SAndre Guedes break; 30439aa04c91SAndre Guedes 3044a7a595f6SVinicius Costa Gomes case HCI_EV_LE_LTK_REQ: 3045a7a595f6SVinicius Costa Gomes hci_le_ltk_request_evt(hdev, skb); 3046a7a595f6SVinicius Costa Gomes break; 3047a7a595f6SVinicius Costa Gomes 3048fcd89c09SVille Tervo default: 3049fcd89c09SVille Tervo break; 3050fcd89c09SVille Tervo } 3051fcd89c09SVille Tervo } 3052fcd89c09SVille Tervo 30531da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 30541da177e4SLinus Torvalds { 3055a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 3056a9de9248SMarcel Holtmann __u8 event = hdr->evt; 30571da177e4SLinus Torvalds 30581da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 30591da177e4SLinus Torvalds 3060a9de9248SMarcel Holtmann switch (event) { 30611da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 30621da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 30631da177e4SLinus Torvalds break; 30641da177e4SLinus Torvalds 30651da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 30661da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 30671da177e4SLinus Torvalds break; 30681da177e4SLinus Torvalds 3069a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 3070a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 307121d9e30eSMarcel Holtmann break; 307221d9e30eSMarcel Holtmann 30731da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 30741da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 30751da177e4SLinus Torvalds break; 30761da177e4SLinus Torvalds 30771da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 30781da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 30791da177e4SLinus Torvalds break; 30801da177e4SLinus Torvalds 30811da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 30821da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 30831da177e4SLinus Torvalds break; 30841da177e4SLinus Torvalds 3085a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 3086a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 3087a9de9248SMarcel Holtmann break; 3088a9de9248SMarcel Holtmann 30891da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 30901da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 30911da177e4SLinus Torvalds break; 30921da177e4SLinus Torvalds 3093a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 3094a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 3095a9de9248SMarcel Holtmann break; 3096a9de9248SMarcel Holtmann 3097a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 3098a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 3099a9de9248SMarcel Holtmann break; 3100a9de9248SMarcel Holtmann 3101a9de9248SMarcel Holtmann case HCI_EV_REMOTE_VERSION: 3102a9de9248SMarcel Holtmann hci_remote_version_evt(hdev, skb); 3103a9de9248SMarcel Holtmann break; 3104a9de9248SMarcel Holtmann 3105a9de9248SMarcel Holtmann case HCI_EV_QOS_SETUP_COMPLETE: 3106a9de9248SMarcel Holtmann hci_qos_setup_complete_evt(hdev, skb); 3107a9de9248SMarcel Holtmann break; 3108a9de9248SMarcel Holtmann 3109a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 3110a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 3111a9de9248SMarcel Holtmann break; 3112a9de9248SMarcel Holtmann 3113a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 3114a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 3115a9de9248SMarcel Holtmann break; 3116a9de9248SMarcel Holtmann 3117a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 3118a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 3119a9de9248SMarcel Holtmann break; 3120a9de9248SMarcel Holtmann 3121a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 3122a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 3123a9de9248SMarcel Holtmann break; 3124a9de9248SMarcel Holtmann 3125a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 3126a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 31271da177e4SLinus Torvalds break; 31281da177e4SLinus Torvalds 31291da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 31301da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 31311da177e4SLinus Torvalds break; 31321da177e4SLinus Torvalds 31331da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 31341da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 31351da177e4SLinus Torvalds break; 31361da177e4SLinus Torvalds 31371da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 31381da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 31391da177e4SLinus Torvalds break; 31401da177e4SLinus Torvalds 31411da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 31421da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 31431da177e4SLinus Torvalds break; 31441da177e4SLinus Torvalds 3145a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 3146a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 3147a8746417SMarcel Holtmann break; 3148a8746417SMarcel Holtmann 314985a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 315085a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 315185a1e930SMarcel Holtmann break; 315285a1e930SMarcel Holtmann 3153a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 3154a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 3155a9de9248SMarcel Holtmann break; 3156a9de9248SMarcel Holtmann 3157a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 3158a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 3159a9de9248SMarcel Holtmann break; 3160a9de9248SMarcel Holtmann 3161a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 3162a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 3163a9de9248SMarcel Holtmann break; 3164a9de9248SMarcel Holtmann 3165a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_CHANGED: 3166a9de9248SMarcel Holtmann hci_sync_conn_changed_evt(hdev, skb); 3167a9de9248SMarcel Holtmann break; 3168a9de9248SMarcel Holtmann 316904837f64SMarcel Holtmann case HCI_EV_SNIFF_SUBRATE: 317004837f64SMarcel Holtmann hci_sniff_subrate_evt(hdev, skb); 317104837f64SMarcel Holtmann break; 317204837f64SMarcel Holtmann 3173a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 3174a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 31751da177e4SLinus Torvalds break; 31761da177e4SLinus Torvalds 31770493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 31780493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 31790493684eSMarcel Holtmann break; 31800493684eSMarcel Holtmann 318103b555e1SJohan Hedberg case HCI_EV_IO_CAPA_REPLY: 318203b555e1SJohan Hedberg hci_io_capa_reply_evt(hdev, skb); 318303b555e1SJohan Hedberg break; 318403b555e1SJohan Hedberg 3185a5c29683SJohan Hedberg case HCI_EV_USER_CONFIRM_REQUEST: 3186a5c29683SJohan Hedberg hci_user_confirm_request_evt(hdev, skb); 3187a5c29683SJohan Hedberg break; 3188a5c29683SJohan Hedberg 31891143d458SBrian Gix case HCI_EV_USER_PASSKEY_REQUEST: 31901143d458SBrian Gix hci_user_passkey_request_evt(hdev, skb); 31911143d458SBrian Gix break; 31921143d458SBrian Gix 31930493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 31940493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 31950493684eSMarcel Holtmann break; 31960493684eSMarcel Holtmann 319741a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 319841a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 319941a96212SMarcel Holtmann break; 320041a96212SMarcel Holtmann 3201fcd89c09SVille Tervo case HCI_EV_LE_META: 3202fcd89c09SVille Tervo hci_le_meta_evt(hdev, skb); 3203fcd89c09SVille Tervo break; 3204fcd89c09SVille Tervo 32052763eda6SSzymon Janc case HCI_EV_REMOTE_OOB_DATA_REQUEST: 32062763eda6SSzymon Janc hci_remote_oob_data_request_evt(hdev, skb); 32072763eda6SSzymon Janc break; 32082763eda6SSzymon Janc 32091da177e4SLinus Torvalds default: 3210a9de9248SMarcel Holtmann BT_DBG("%s event 0x%x", hdev->name, event); 32111da177e4SLinus Torvalds break; 32121da177e4SLinus Torvalds } 32131da177e4SLinus Torvalds 32141da177e4SLinus Torvalds kfree_skb(skb); 32151da177e4SLinus Torvalds hdev->stat.evt_rx++; 32161da177e4SLinus Torvalds } 32171da177e4SLinus Torvalds 32181da177e4SLinus Torvalds /* Generate internal stack event */ 32191da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data) 32201da177e4SLinus Torvalds { 32211da177e4SLinus Torvalds struct hci_event_hdr *hdr; 32221da177e4SLinus Torvalds struct hci_ev_stack_internal *ev; 32231da177e4SLinus Torvalds struct sk_buff *skb; 32241da177e4SLinus Torvalds 32251da177e4SLinus Torvalds skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC); 32261da177e4SLinus Torvalds if (!skb) 32271da177e4SLinus Torvalds return; 32281da177e4SLinus Torvalds 32291da177e4SLinus Torvalds hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE); 32301da177e4SLinus Torvalds hdr->evt = HCI_EV_STACK_INTERNAL; 32311da177e4SLinus Torvalds hdr->plen = sizeof(*ev) + dlen; 32321da177e4SLinus Torvalds 32331da177e4SLinus Torvalds ev = (void *) skb_put(skb, sizeof(*ev) + dlen); 32341da177e4SLinus Torvalds ev->type = type; 32351da177e4SLinus Torvalds memcpy(ev->data, data, dlen); 32361da177e4SLinus Torvalds 3237576c7d85SMarcel Holtmann bt_cb(skb)->incoming = 1; 3238a61bbcf2SPatrick McHardy __net_timestamp(skb); 3239576c7d85SMarcel Holtmann 32400d48d939SMarcel Holtmann bt_cb(skb)->pkt_type = HCI_EVENT_PKT; 32411da177e4SLinus Torvalds skb->dev = (void *) hdev; 3242eec8d2bcSJohan Hedberg hci_send_to_sock(hdev, skb, NULL); 32431da177e4SLinus Torvalds kfree_skb(skb); 32441da177e4SLinus Torvalds } 3245e6100a25SAndre Guedes 3246669bb396SGustavo F. Padovan module_param(enable_le, bool, 0644); 3247e6100a25SAndre Guedes MODULE_PARM_DESC(enable_le, "Enable LE support"); 3248