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); 197d23264a8SAndre Guedes 198d23264a8SAndre Guedes hdev->dev_flags = 0; 199a9de9248SMarcel Holtmann } 200a9de9248SMarcel Holtmann 201a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) 202a9de9248SMarcel Holtmann { 203a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 2041da177e4SLinus Torvalds void *sent; 2051da177e4SLinus Torvalds 206a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 2071da177e4SLinus Torvalds 208a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); 2091da177e4SLinus Torvalds if (!sent) 210a9de9248SMarcel Holtmann return; 2111da177e4SLinus Torvalds 21256e5cb86SJohan Hedberg hci_dev_lock(hdev); 21356e5cb86SJohan Hedberg 214b312b161SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 215744cf19eSJohan Hedberg mgmt_set_local_name_complete(hdev, sent, status); 216b312b161SJohan Hedberg 21756e5cb86SJohan Hedberg if (status == 0) 2181f6c6378SJohan Hedberg memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); 21956e5cb86SJohan Hedberg 22056e5cb86SJohan Hedberg hci_dev_unlock(hdev); 221a9de9248SMarcel Holtmann } 222a9de9248SMarcel Holtmann 223a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) 224a9de9248SMarcel Holtmann { 225a9de9248SMarcel Holtmann struct hci_rp_read_local_name *rp = (void *) skb->data; 226a9de9248SMarcel Holtmann 227a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 228a9de9248SMarcel Holtmann 229a9de9248SMarcel Holtmann if (rp->status) 230a9de9248SMarcel Holtmann return; 231a9de9248SMarcel Holtmann 2321f6c6378SJohan Hedberg memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); 233a9de9248SMarcel Holtmann } 234a9de9248SMarcel Holtmann 235a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) 236a9de9248SMarcel Holtmann { 237a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 238a9de9248SMarcel Holtmann void *sent; 239a9de9248SMarcel Holtmann 240a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 241a9de9248SMarcel Holtmann 242a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); 243a9de9248SMarcel Holtmann if (!sent) 244a9de9248SMarcel Holtmann return; 2451da177e4SLinus Torvalds 2461da177e4SLinus Torvalds if (!status) { 247a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 248a9de9248SMarcel Holtmann 2491da177e4SLinus Torvalds if (param == AUTH_ENABLED) 2501da177e4SLinus Torvalds set_bit(HCI_AUTH, &hdev->flags); 2511da177e4SLinus Torvalds else 2521da177e4SLinus Torvalds clear_bit(HCI_AUTH, &hdev->flags); 2531da177e4SLinus Torvalds } 254a9de9248SMarcel Holtmann 25523bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status); 256a9de9248SMarcel Holtmann } 2571da177e4SLinus Torvalds 258a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) 259a9de9248SMarcel Holtmann { 260a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 261a9de9248SMarcel Holtmann void *sent; 262a9de9248SMarcel Holtmann 263a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 264a9de9248SMarcel Holtmann 265a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); 2661da177e4SLinus Torvalds if (!sent) 267a9de9248SMarcel Holtmann return; 2681da177e4SLinus Torvalds 2691da177e4SLinus Torvalds if (!status) { 270a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 271a9de9248SMarcel Holtmann 2721da177e4SLinus Torvalds if (param) 2731da177e4SLinus Torvalds set_bit(HCI_ENCRYPT, &hdev->flags); 2741da177e4SLinus Torvalds else 2751da177e4SLinus Torvalds clear_bit(HCI_ENCRYPT, &hdev->flags); 2761da177e4SLinus Torvalds } 277a9de9248SMarcel Holtmann 27823bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status); 2791da177e4SLinus Torvalds } 2801da177e4SLinus Torvalds 281a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) 282a9de9248SMarcel Holtmann { 28336f7fc7eSJohan Hedberg __u8 param, status = *((__u8 *) skb->data); 28436f7fc7eSJohan Hedberg int old_pscan, old_iscan; 285a9de9248SMarcel Holtmann void *sent; 2861da177e4SLinus Torvalds 287a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 288a9de9248SMarcel Holtmann 289a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); 2901da177e4SLinus Torvalds if (!sent) 291a9de9248SMarcel Holtmann return; 2921da177e4SLinus Torvalds 29336f7fc7eSJohan Hedberg param = *((__u8 *) sent); 294a9de9248SMarcel Holtmann 29556e5cb86SJohan Hedberg hci_dev_lock(hdev); 29656e5cb86SJohan Hedberg 2972d7cee58SJohan Hedberg if (status != 0) { 298744cf19eSJohan Hedberg mgmt_write_scan_failed(hdev, param, status); 2992d7cee58SJohan Hedberg hdev->discov_timeout = 0; 3002d7cee58SJohan Hedberg goto done; 3012d7cee58SJohan Hedberg } 3022d7cee58SJohan Hedberg 3039fbcbb45SJohan Hedberg old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags); 3049fbcbb45SJohan Hedberg old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags); 305a9de9248SMarcel Holtmann 30673f22f62SJohan Hedberg if (param & SCAN_INQUIRY) { 3071da177e4SLinus Torvalds set_bit(HCI_ISCAN, &hdev->flags); 3089fbcbb45SJohan Hedberg if (!old_iscan) 309744cf19eSJohan Hedberg mgmt_discoverable(hdev, 1); 31016ab91abSJohan Hedberg if (hdev->discov_timeout > 0) { 31116ab91abSJohan Hedberg int to = msecs_to_jiffies(hdev->discov_timeout * 1000); 31216ab91abSJohan Hedberg queue_delayed_work(hdev->workqueue, &hdev->discov_off, 31316ab91abSJohan Hedberg to); 31416ab91abSJohan Hedberg } 3159fbcbb45SJohan Hedberg } else if (old_iscan) 316744cf19eSJohan Hedberg mgmt_discoverable(hdev, 0); 3171da177e4SLinus Torvalds 3189fbcbb45SJohan Hedberg if (param & SCAN_PAGE) { 3191da177e4SLinus Torvalds set_bit(HCI_PSCAN, &hdev->flags); 3209fbcbb45SJohan Hedberg if (!old_pscan) 321744cf19eSJohan Hedberg mgmt_connectable(hdev, 1); 3229fbcbb45SJohan Hedberg } else if (old_pscan) 323744cf19eSJohan Hedberg mgmt_connectable(hdev, 0); 324a9de9248SMarcel Holtmann 32536f7fc7eSJohan Hedberg done: 32656e5cb86SJohan Hedberg hci_dev_unlock(hdev); 32723bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status); 3281da177e4SLinus Torvalds } 3291da177e4SLinus Torvalds 330a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 331a9de9248SMarcel Holtmann { 332a9de9248SMarcel Holtmann struct hci_rp_read_class_of_dev *rp = (void *) skb->data; 333a9de9248SMarcel Holtmann 334a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 335a9de9248SMarcel Holtmann 336a9de9248SMarcel Holtmann if (rp->status) 337a9de9248SMarcel Holtmann return; 338a9de9248SMarcel Holtmann 339a9de9248SMarcel Holtmann memcpy(hdev->dev_class, rp->dev_class, 3); 340a9de9248SMarcel Holtmann 341a9de9248SMarcel Holtmann BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, 342a9de9248SMarcel Holtmann hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); 343a9de9248SMarcel Holtmann } 344a9de9248SMarcel Holtmann 345a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 346a9de9248SMarcel Holtmann { 347a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 348a9de9248SMarcel Holtmann void *sent; 349a9de9248SMarcel Holtmann 350a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 351a9de9248SMarcel Holtmann 352f383f275SMarcel Holtmann if (status) 353f383f275SMarcel Holtmann return; 354f383f275SMarcel Holtmann 355a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); 356a9de9248SMarcel Holtmann if (!sent) 357a9de9248SMarcel Holtmann return; 358a9de9248SMarcel Holtmann 359a9de9248SMarcel Holtmann memcpy(hdev->dev_class, sent, 3); 360a9de9248SMarcel Holtmann } 361a9de9248SMarcel Holtmann 362a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 363a9de9248SMarcel Holtmann { 364a9de9248SMarcel Holtmann struct hci_rp_read_voice_setting *rp = (void *) skb->data; 365a9de9248SMarcel Holtmann __u16 setting; 366a9de9248SMarcel Holtmann 367a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 368a9de9248SMarcel Holtmann 369a9de9248SMarcel Holtmann if (rp->status) 370a9de9248SMarcel Holtmann return; 371a9de9248SMarcel Holtmann 372a9de9248SMarcel Holtmann setting = __le16_to_cpu(rp->voice_setting); 373a9de9248SMarcel Holtmann 374a9de9248SMarcel Holtmann if (hdev->voice_setting == setting) 375a9de9248SMarcel Holtmann return; 376a9de9248SMarcel Holtmann 377a9de9248SMarcel Holtmann hdev->voice_setting = setting; 378a9de9248SMarcel Holtmann 379a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 380a9de9248SMarcel Holtmann 3813c54711cSGustavo F. Padovan if (hdev->notify) 382a9de9248SMarcel Holtmann hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 383a9de9248SMarcel Holtmann } 384a9de9248SMarcel Holtmann 385a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 386a9de9248SMarcel Holtmann { 387a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 388f383f275SMarcel Holtmann __u16 setting; 389a9de9248SMarcel Holtmann void *sent; 390a9de9248SMarcel Holtmann 391a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 392a9de9248SMarcel Holtmann 393f383f275SMarcel Holtmann if (status) 394f383f275SMarcel Holtmann return; 395f383f275SMarcel Holtmann 396a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); 397a9de9248SMarcel Holtmann if (!sent) 398a9de9248SMarcel Holtmann return; 399a9de9248SMarcel Holtmann 400f383f275SMarcel Holtmann setting = get_unaligned_le16(sent); 4011da177e4SLinus Torvalds 402f383f275SMarcel Holtmann if (hdev->voice_setting == setting) 403f383f275SMarcel Holtmann return; 404f383f275SMarcel Holtmann 4051da177e4SLinus Torvalds hdev->voice_setting = setting; 4061da177e4SLinus Torvalds 407a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 4081da177e4SLinus Torvalds 4093c54711cSGustavo F. Padovan if (hdev->notify) 4101da177e4SLinus Torvalds hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 4111da177e4SLinus Torvalds } 4121da177e4SLinus Torvalds 413a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 4141da177e4SLinus Torvalds { 415a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 4161da177e4SLinus Torvalds 417a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 4181da177e4SLinus Torvalds 41923bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status); 4201143e5a6SMarcel Holtmann } 4211143e5a6SMarcel Holtmann 422333140b5SMarcel Holtmann static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 423333140b5SMarcel Holtmann { 424333140b5SMarcel Holtmann struct hci_rp_read_ssp_mode *rp = (void *) skb->data; 425333140b5SMarcel Holtmann 426333140b5SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 427333140b5SMarcel Holtmann 428333140b5SMarcel Holtmann if (rp->status) 429333140b5SMarcel Holtmann return; 430333140b5SMarcel Holtmann 431333140b5SMarcel Holtmann hdev->ssp_mode = rp->mode; 432333140b5SMarcel Holtmann } 433333140b5SMarcel Holtmann 434333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 435333140b5SMarcel Holtmann { 436333140b5SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 437333140b5SMarcel Holtmann void *sent; 438333140b5SMarcel Holtmann 439333140b5SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 440333140b5SMarcel Holtmann 441333140b5SMarcel Holtmann if (status) 442333140b5SMarcel Holtmann return; 443333140b5SMarcel Holtmann 444333140b5SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); 445333140b5SMarcel Holtmann if (!sent) 446333140b5SMarcel Holtmann return; 447333140b5SMarcel Holtmann 448333140b5SMarcel Holtmann hdev->ssp_mode = *((__u8 *) sent); 449333140b5SMarcel Holtmann } 450333140b5SMarcel Holtmann 451d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev) 452d5859e22SJohan Hedberg { 453d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 454d5859e22SJohan Hedberg return 2; 455d5859e22SJohan Hedberg 456d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 457d5859e22SJohan Hedberg return 1; 458d5859e22SJohan Hedberg 459d5859e22SJohan Hedberg if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 && 460d5859e22SJohan Hedberg hdev->lmp_subver == 0x0757) 461d5859e22SJohan Hedberg return 1; 462d5859e22SJohan Hedberg 463d5859e22SJohan Hedberg if (hdev->manufacturer == 15) { 464d5859e22SJohan Hedberg if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963) 465d5859e22SJohan Hedberg return 1; 466d5859e22SJohan Hedberg if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963) 467d5859e22SJohan Hedberg return 1; 468d5859e22SJohan Hedberg if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965) 469d5859e22SJohan Hedberg return 1; 470d5859e22SJohan Hedberg } 471d5859e22SJohan Hedberg 472d5859e22SJohan Hedberg if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 && 473d5859e22SJohan Hedberg hdev->lmp_subver == 0x1805) 474d5859e22SJohan Hedberg return 1; 475d5859e22SJohan Hedberg 476d5859e22SJohan Hedberg return 0; 477d5859e22SJohan Hedberg } 478d5859e22SJohan Hedberg 479d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev) 480d5859e22SJohan Hedberg { 481d5859e22SJohan Hedberg u8 mode; 482d5859e22SJohan Hedberg 483d5859e22SJohan Hedberg mode = hci_get_inquiry_mode(hdev); 484d5859e22SJohan Hedberg 485d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode); 486d5859e22SJohan Hedberg } 487d5859e22SJohan Hedberg 488d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev) 489d5859e22SJohan Hedberg { 490d5859e22SJohan Hedberg /* The second byte is 0xff instead of 0x9f (two reserved bits 491d5859e22SJohan Hedberg * disabled) since a Broadcom 1.2 dongle doesn't respond to the 492d5859e22SJohan Hedberg * command otherwise */ 493d5859e22SJohan Hedberg u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 }; 494d5859e22SJohan Hedberg 4956de6c18dSVille Tervo /* CSR 1.1 dongles does not accept any bitfield so don't try to set 4966de6c18dSVille Tervo * any event mask for pre 1.2 devices */ 4975a13b095SAndrei Emeltchenko if (hdev->hci_ver < BLUETOOTH_VER_1_2) 4986de6c18dSVille Tervo return; 4996de6c18dSVille Tervo 500d5859e22SJohan Hedberg events[4] |= 0x01; /* Flow Specification Complete */ 501d5859e22SJohan Hedberg events[4] |= 0x02; /* Inquiry Result with RSSI */ 502d5859e22SJohan Hedberg events[4] |= 0x04; /* Read Remote Extended Features Complete */ 503d5859e22SJohan Hedberg events[5] |= 0x08; /* Synchronous Connection Complete */ 504d5859e22SJohan Hedberg events[5] |= 0x10; /* Synchronous Connection Changed */ 505d5859e22SJohan Hedberg 506d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 507d5859e22SJohan Hedberg events[4] |= 0x04; /* Inquiry Result with RSSI */ 508d5859e22SJohan Hedberg 509d5859e22SJohan Hedberg if (hdev->features[5] & LMP_SNIFF_SUBR) 510d5859e22SJohan Hedberg events[5] |= 0x20; /* Sniff Subrating */ 511d5859e22SJohan Hedberg 512d5859e22SJohan Hedberg if (hdev->features[5] & LMP_PAUSE_ENC) 513d5859e22SJohan Hedberg events[5] |= 0x80; /* Encryption Key Refresh Complete */ 514d5859e22SJohan Hedberg 515d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 516d5859e22SJohan Hedberg events[5] |= 0x40; /* Extended Inquiry Result */ 517d5859e22SJohan Hedberg 518d5859e22SJohan Hedberg if (hdev->features[6] & LMP_NO_FLUSH) 519d5859e22SJohan Hedberg events[7] |= 0x01; /* Enhanced Flush Complete */ 520d5859e22SJohan Hedberg 521d5859e22SJohan Hedberg if (hdev->features[7] & LMP_LSTO) 522d5859e22SJohan Hedberg events[6] |= 0x80; /* Link Supervision Timeout Changed */ 523d5859e22SJohan Hedberg 524d5859e22SJohan Hedberg if (hdev->features[6] & LMP_SIMPLE_PAIR) { 525d5859e22SJohan Hedberg events[6] |= 0x01; /* IO Capability Request */ 526d5859e22SJohan Hedberg events[6] |= 0x02; /* IO Capability Response */ 527d5859e22SJohan Hedberg events[6] |= 0x04; /* User Confirmation Request */ 528d5859e22SJohan Hedberg events[6] |= 0x08; /* User Passkey Request */ 529d5859e22SJohan Hedberg events[6] |= 0x10; /* Remote OOB Data Request */ 530d5859e22SJohan Hedberg events[6] |= 0x20; /* Simple Pairing Complete */ 531d5859e22SJohan Hedberg events[7] |= 0x04; /* User Passkey Notification */ 532d5859e22SJohan Hedberg events[7] |= 0x08; /* Keypress Notification */ 533d5859e22SJohan Hedberg events[7] |= 0x10; /* Remote Host Supported 534d5859e22SJohan Hedberg * Features Notification */ 535d5859e22SJohan Hedberg } 536d5859e22SJohan Hedberg 537d5859e22SJohan Hedberg if (hdev->features[4] & LMP_LE) 538d5859e22SJohan Hedberg events[7] |= 0x20; /* LE Meta-Event */ 539d5859e22SJohan Hedberg 540d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); 541d5859e22SJohan Hedberg } 542d5859e22SJohan Hedberg 543e6100a25SAndre Guedes static void hci_set_le_support(struct hci_dev *hdev) 544e6100a25SAndre Guedes { 545e6100a25SAndre Guedes struct hci_cp_write_le_host_supported cp; 546e6100a25SAndre Guedes 547e6100a25SAndre Guedes memset(&cp, 0, sizeof(cp)); 548e6100a25SAndre Guedes 549e6100a25SAndre Guedes if (enable_le) { 550e6100a25SAndre Guedes cp.le = 1; 551e6100a25SAndre Guedes cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR); 552e6100a25SAndre Guedes } 553e6100a25SAndre Guedes 554e6100a25SAndre Guedes hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), &cp); 555e6100a25SAndre Guedes } 556e6100a25SAndre Guedes 557d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev) 558d5859e22SJohan Hedberg { 559e61ef499SAndrei Emeltchenko if (hdev->dev_type != HCI_BREDR) 560e61ef499SAndrei Emeltchenko return; 561e61ef499SAndrei Emeltchenko 562d5859e22SJohan Hedberg hci_setup_event_mask(hdev); 563d5859e22SJohan Hedberg 564d095c1ebSAndrei Emeltchenko if (hdev->hci_ver > BLUETOOTH_VER_1_1) 565d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); 566d5859e22SJohan Hedberg 567d5859e22SJohan Hedberg if (hdev->features[6] & LMP_SIMPLE_PAIR) { 568d5859e22SJohan Hedberg u8 mode = 0x01; 569d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode); 570d5859e22SJohan Hedberg } 571d5859e22SJohan Hedberg 572d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 573d5859e22SJohan Hedberg hci_setup_inquiry_mode(hdev); 574d5859e22SJohan Hedberg 575d5859e22SJohan Hedberg if (hdev->features[7] & LMP_INQ_TX_PWR) 576d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL); 577971e3a4bSAndre Guedes 578971e3a4bSAndre Guedes if (hdev->features[7] & LMP_EXTFEATURES) { 579971e3a4bSAndre Guedes struct hci_cp_read_local_ext_features cp; 580971e3a4bSAndre Guedes 581971e3a4bSAndre Guedes cp.page = 0x01; 582971e3a4bSAndre Guedes hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, 583971e3a4bSAndre Guedes sizeof(cp), &cp); 584971e3a4bSAndre Guedes } 585e6100a25SAndre Guedes 586e6100a25SAndre Guedes if (hdev->features[4] & LMP_LE) 587e6100a25SAndre Guedes hci_set_le_support(hdev); 588d5859e22SJohan Hedberg } 589d5859e22SJohan Hedberg 590a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) 591a9de9248SMarcel Holtmann { 592a9de9248SMarcel Holtmann struct hci_rp_read_local_version *rp = (void *) skb->data; 5931143e5a6SMarcel Holtmann 594a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 5951143e5a6SMarcel Holtmann 596a9de9248SMarcel Holtmann if (rp->status) 597a9de9248SMarcel Holtmann return; 5981143e5a6SMarcel Holtmann 599a9de9248SMarcel Holtmann hdev->hci_ver = rp->hci_ver; 600e4e8e37cSMarcel Holtmann hdev->hci_rev = __le16_to_cpu(rp->hci_rev); 601d5859e22SJohan Hedberg hdev->lmp_ver = rp->lmp_ver; 602e4e8e37cSMarcel Holtmann hdev->manufacturer = __le16_to_cpu(rp->manufacturer); 603d5859e22SJohan Hedberg hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); 6041da177e4SLinus Torvalds 605a9de9248SMarcel Holtmann BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name, 606a9de9248SMarcel Holtmann hdev->manufacturer, 607a9de9248SMarcel Holtmann hdev->hci_ver, hdev->hci_rev); 608d5859e22SJohan Hedberg 609d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags)) 610d5859e22SJohan Hedberg hci_setup(hdev); 611d5859e22SJohan Hedberg } 612d5859e22SJohan Hedberg 613d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev) 614d5859e22SJohan Hedberg { 615d5859e22SJohan Hedberg u16 link_policy = 0; 616d5859e22SJohan Hedberg 617d5859e22SJohan Hedberg if (hdev->features[0] & LMP_RSWITCH) 618d5859e22SJohan Hedberg link_policy |= HCI_LP_RSWITCH; 619d5859e22SJohan Hedberg if (hdev->features[0] & LMP_HOLD) 620d5859e22SJohan Hedberg link_policy |= HCI_LP_HOLD; 621d5859e22SJohan Hedberg if (hdev->features[0] & LMP_SNIFF) 622d5859e22SJohan Hedberg link_policy |= HCI_LP_SNIFF; 623d5859e22SJohan Hedberg if (hdev->features[1] & LMP_PARK) 624d5859e22SJohan Hedberg link_policy |= HCI_LP_PARK; 625d5859e22SJohan Hedberg 626d5859e22SJohan Hedberg link_policy = cpu_to_le16(link_policy); 627d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, 628d5859e22SJohan Hedberg sizeof(link_policy), &link_policy); 6291da177e4SLinus Torvalds } 6301da177e4SLinus Torvalds 631a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb) 632a9de9248SMarcel Holtmann { 633a9de9248SMarcel Holtmann struct hci_rp_read_local_commands *rp = (void *) skb->data; 634a9de9248SMarcel Holtmann 635a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 636a9de9248SMarcel Holtmann 637a9de9248SMarcel Holtmann if (rp->status) 638d5859e22SJohan Hedberg goto done; 639a9de9248SMarcel Holtmann 640a9de9248SMarcel Holtmann memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); 641d5859e22SJohan Hedberg 642d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10)) 643d5859e22SJohan Hedberg hci_setup_link_policy(hdev); 644d5859e22SJohan Hedberg 645d5859e22SJohan Hedberg done: 646d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status); 647a9de9248SMarcel Holtmann } 648a9de9248SMarcel Holtmann 649a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb) 650a9de9248SMarcel Holtmann { 651a9de9248SMarcel Holtmann struct hci_rp_read_local_features *rp = (void *) skb->data; 652a9de9248SMarcel Holtmann 653a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 654a9de9248SMarcel Holtmann 655a9de9248SMarcel Holtmann if (rp->status) 656a9de9248SMarcel Holtmann return; 657a9de9248SMarcel Holtmann 658a9de9248SMarcel Holtmann memcpy(hdev->features, rp->features, 8); 6591da177e4SLinus Torvalds 6601da177e4SLinus Torvalds /* Adjust default settings according to features 6611da177e4SLinus Torvalds * supported by device. */ 662a9de9248SMarcel Holtmann 6631da177e4SLinus Torvalds if (hdev->features[0] & LMP_3SLOT) 6641da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM3 | HCI_DH3); 6651da177e4SLinus Torvalds 6661da177e4SLinus Torvalds if (hdev->features[0] & LMP_5SLOT) 6671da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM5 | HCI_DH5); 6681da177e4SLinus Torvalds 6695b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV2) { 6701da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV2); 6715b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV2); 6725b7f9909SMarcel Holtmann } 6731da177e4SLinus Torvalds 6745b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV3) { 6751da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV3); 6765b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV3); 6775b7f9909SMarcel Holtmann } 6785b7f9909SMarcel Holtmann 6795b7f9909SMarcel Holtmann if (hdev->features[3] & LMP_ESCO) 6805b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV3); 6815b7f9909SMarcel Holtmann 6825b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV4) 6835b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV4); 6845b7f9909SMarcel Holtmann 6855b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV5) 6865b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV5); 6871da177e4SLinus Torvalds 688efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_2M) 689efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV3); 690efc7688bSMarcel Holtmann 691efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_3M) 692efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_3EV3); 693efc7688bSMarcel Holtmann 694efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_3S_ESCO) 695efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); 696efc7688bSMarcel Holtmann 697a9de9248SMarcel Holtmann BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, 698a9de9248SMarcel Holtmann hdev->features[0], hdev->features[1], 699a9de9248SMarcel Holtmann hdev->features[2], hdev->features[3], 700a9de9248SMarcel Holtmann hdev->features[4], hdev->features[5], 701a9de9248SMarcel Holtmann hdev->features[6], hdev->features[7]); 7021da177e4SLinus Torvalds } 7031da177e4SLinus Torvalds 704971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev, 705971e3a4bSAndre Guedes struct sk_buff *skb) 706971e3a4bSAndre Guedes { 707971e3a4bSAndre Guedes struct hci_rp_read_local_ext_features *rp = (void *) skb->data; 708971e3a4bSAndre Guedes 709971e3a4bSAndre Guedes BT_DBG("%s status 0x%x", hdev->name, rp->status); 710971e3a4bSAndre Guedes 711971e3a4bSAndre Guedes if (rp->status) 712971e3a4bSAndre Guedes return; 713971e3a4bSAndre Guedes 714b5b32b65SAndre Guedes switch (rp->page) { 715b5b32b65SAndre Guedes case 0: 716b5b32b65SAndre Guedes memcpy(hdev->features, rp->features, 8); 717b5b32b65SAndre Guedes break; 718b5b32b65SAndre Guedes case 1: 71959e29406SAndre Guedes memcpy(hdev->host_features, rp->features, 8); 720b5b32b65SAndre Guedes break; 721b5b32b65SAndre Guedes } 722971e3a4bSAndre Guedes 723971e3a4bSAndre Guedes hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status); 724971e3a4bSAndre Guedes } 725971e3a4bSAndre Guedes 7261e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, 7271e89cffbSAndrei Emeltchenko struct sk_buff *skb) 7281e89cffbSAndrei Emeltchenko { 7291e89cffbSAndrei Emeltchenko struct hci_rp_read_flow_control_mode *rp = (void *) skb->data; 7301e89cffbSAndrei Emeltchenko 7311e89cffbSAndrei Emeltchenko BT_DBG("%s status 0x%x", hdev->name, rp->status); 7321e89cffbSAndrei Emeltchenko 7331e89cffbSAndrei Emeltchenko if (rp->status) 7341e89cffbSAndrei Emeltchenko return; 7351e89cffbSAndrei Emeltchenko 7361e89cffbSAndrei Emeltchenko hdev->flow_ctl_mode = rp->mode; 7371e89cffbSAndrei Emeltchenko 7381e89cffbSAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status); 7391e89cffbSAndrei Emeltchenko } 7401e89cffbSAndrei Emeltchenko 741a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 742a9de9248SMarcel Holtmann { 743a9de9248SMarcel Holtmann struct hci_rp_read_buffer_size *rp = (void *) skb->data; 744a9de9248SMarcel Holtmann 745a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 746a9de9248SMarcel Holtmann 747a9de9248SMarcel Holtmann if (rp->status) 748a9de9248SMarcel Holtmann return; 749a9de9248SMarcel Holtmann 750a9de9248SMarcel Holtmann hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); 751a9de9248SMarcel Holtmann hdev->sco_mtu = rp->sco_mtu; 752a9de9248SMarcel Holtmann hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); 753a9de9248SMarcel Holtmann hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); 754da1f5198SMarcel Holtmann 755da1f5198SMarcel Holtmann if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { 756da1f5198SMarcel Holtmann hdev->sco_mtu = 64; 757da1f5198SMarcel Holtmann hdev->sco_pkts = 8; 758da1f5198SMarcel Holtmann } 759da1f5198SMarcel Holtmann 760da1f5198SMarcel Holtmann hdev->acl_cnt = hdev->acl_pkts; 761da1f5198SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 7621da177e4SLinus Torvalds 763a9de9248SMarcel Holtmann BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, 764a9de9248SMarcel Holtmann hdev->acl_mtu, hdev->acl_pkts, 765a9de9248SMarcel Holtmann hdev->sco_mtu, hdev->sco_pkts); 7661da177e4SLinus Torvalds } 7671da177e4SLinus Torvalds 768a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) 769a9de9248SMarcel Holtmann { 770a9de9248SMarcel Holtmann struct hci_rp_read_bd_addr *rp = (void *) skb->data; 7711da177e4SLinus Torvalds 772a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 773a9de9248SMarcel Holtmann 774a9de9248SMarcel Holtmann if (!rp->status) 775a9de9248SMarcel Holtmann bacpy(&hdev->bdaddr, &rp->bdaddr); 776a9de9248SMarcel Holtmann 77723bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status); 77823bb5763SJohan Hedberg } 77923bb5763SJohan Hedberg 780350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev, 781350ee4cfSAndrei Emeltchenko struct sk_buff *skb) 782350ee4cfSAndrei Emeltchenko { 783350ee4cfSAndrei Emeltchenko struct hci_rp_read_data_block_size *rp = (void *) skb->data; 784350ee4cfSAndrei Emeltchenko 785350ee4cfSAndrei Emeltchenko BT_DBG("%s status 0x%x", hdev->name, rp->status); 786350ee4cfSAndrei Emeltchenko 787350ee4cfSAndrei Emeltchenko if (rp->status) 788350ee4cfSAndrei Emeltchenko return; 789350ee4cfSAndrei Emeltchenko 790350ee4cfSAndrei Emeltchenko hdev->block_mtu = __le16_to_cpu(rp->max_acl_len); 791350ee4cfSAndrei Emeltchenko hdev->block_len = __le16_to_cpu(rp->block_len); 792350ee4cfSAndrei Emeltchenko hdev->num_blocks = __le16_to_cpu(rp->num_blocks); 793350ee4cfSAndrei Emeltchenko 794350ee4cfSAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 795350ee4cfSAndrei Emeltchenko 796350ee4cfSAndrei Emeltchenko BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu, 797350ee4cfSAndrei Emeltchenko hdev->block_cnt, hdev->block_len); 798350ee4cfSAndrei Emeltchenko 799350ee4cfSAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status); 800350ee4cfSAndrei Emeltchenko } 801350ee4cfSAndrei Emeltchenko 80223bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb) 80323bb5763SJohan Hedberg { 80423bb5763SJohan Hedberg __u8 status = *((__u8 *) skb->data); 80523bb5763SJohan Hedberg 80623bb5763SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 80723bb5763SJohan Hedberg 80823bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status); 8091da177e4SLinus Torvalds } 8101da177e4SLinus Torvalds 811928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev, 812928abaa7SAndrei Emeltchenko struct sk_buff *skb) 813928abaa7SAndrei Emeltchenko { 814928abaa7SAndrei Emeltchenko struct hci_rp_read_local_amp_info *rp = (void *) skb->data; 815928abaa7SAndrei Emeltchenko 816928abaa7SAndrei Emeltchenko BT_DBG("%s status 0x%x", hdev->name, rp->status); 817928abaa7SAndrei Emeltchenko 818928abaa7SAndrei Emeltchenko if (rp->status) 819928abaa7SAndrei Emeltchenko return; 820928abaa7SAndrei Emeltchenko 821928abaa7SAndrei Emeltchenko hdev->amp_status = rp->amp_status; 822928abaa7SAndrei Emeltchenko hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); 823928abaa7SAndrei Emeltchenko hdev->amp_max_bw = __le32_to_cpu(rp->max_bw); 824928abaa7SAndrei Emeltchenko hdev->amp_min_latency = __le32_to_cpu(rp->min_latency); 825928abaa7SAndrei Emeltchenko hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu); 826928abaa7SAndrei Emeltchenko hdev->amp_type = rp->amp_type; 827928abaa7SAndrei Emeltchenko hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap); 828928abaa7SAndrei Emeltchenko hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size); 829928abaa7SAndrei Emeltchenko hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); 830928abaa7SAndrei Emeltchenko hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); 831928abaa7SAndrei Emeltchenko 832928abaa7SAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status); 833928abaa7SAndrei Emeltchenko } 834928abaa7SAndrei Emeltchenko 835b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, 836b0916ea0SJohan Hedberg struct sk_buff *skb) 837b0916ea0SJohan Hedberg { 838b0916ea0SJohan Hedberg __u8 status = *((__u8 *) skb->data); 839b0916ea0SJohan Hedberg 840b0916ea0SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 841b0916ea0SJohan Hedberg 842b0916ea0SJohan Hedberg hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status); 843b0916ea0SJohan Hedberg } 844b0916ea0SJohan Hedberg 845d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb) 846d5859e22SJohan Hedberg { 847d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 848d5859e22SJohan Hedberg 849d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 850d5859e22SJohan Hedberg 851d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status); 852d5859e22SJohan Hedberg } 853d5859e22SJohan Hedberg 854d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev, 855d5859e22SJohan Hedberg struct sk_buff *skb) 856d5859e22SJohan Hedberg { 857d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 858d5859e22SJohan Hedberg 859d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 860d5859e22SJohan Hedberg 861d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status); 862d5859e22SJohan Hedberg } 863d5859e22SJohan Hedberg 864d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, 865d5859e22SJohan Hedberg struct sk_buff *skb) 866d5859e22SJohan Hedberg { 867d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 868d5859e22SJohan Hedberg 869d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 870d5859e22SJohan Hedberg 871d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status); 872d5859e22SJohan Hedberg } 873d5859e22SJohan Hedberg 874d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb) 875d5859e22SJohan Hedberg { 876d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 877d5859e22SJohan Hedberg 878d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 879d5859e22SJohan Hedberg 880d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status); 881d5859e22SJohan Hedberg } 882d5859e22SJohan Hedberg 883980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) 884980e1a53SJohan Hedberg { 885980e1a53SJohan Hedberg struct hci_rp_pin_code_reply *rp = (void *) skb->data; 886980e1a53SJohan Hedberg struct hci_cp_pin_code_reply *cp; 887980e1a53SJohan Hedberg struct hci_conn *conn; 888980e1a53SJohan Hedberg 889980e1a53SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 890980e1a53SJohan Hedberg 89156e5cb86SJohan Hedberg hci_dev_lock(hdev); 89256e5cb86SJohan Hedberg 893980e1a53SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 894744cf19eSJohan Hedberg mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); 895980e1a53SJohan Hedberg 896980e1a53SJohan Hedberg if (rp->status != 0) 89756e5cb86SJohan Hedberg goto unlock; 898980e1a53SJohan Hedberg 899980e1a53SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); 900980e1a53SJohan Hedberg if (!cp) 90156e5cb86SJohan Hedberg goto unlock; 902980e1a53SJohan Hedberg 903980e1a53SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 904980e1a53SJohan Hedberg if (conn) 905980e1a53SJohan Hedberg conn->pin_length = cp->pin_len; 90656e5cb86SJohan Hedberg 90756e5cb86SJohan Hedberg unlock: 90856e5cb86SJohan Hedberg hci_dev_unlock(hdev); 909980e1a53SJohan Hedberg } 910980e1a53SJohan Hedberg 911980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 912980e1a53SJohan Hedberg { 913980e1a53SJohan Hedberg struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data; 914980e1a53SJohan Hedberg 915980e1a53SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 916980e1a53SJohan Hedberg 91756e5cb86SJohan Hedberg hci_dev_lock(hdev); 91856e5cb86SJohan Hedberg 919980e1a53SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 920744cf19eSJohan Hedberg mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr, 921980e1a53SJohan Hedberg rp->status); 92256e5cb86SJohan Hedberg 92356e5cb86SJohan Hedberg hci_dev_unlock(hdev); 924980e1a53SJohan Hedberg } 92556e5cb86SJohan Hedberg 9266ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, 9276ed58ec5SVille Tervo struct sk_buff *skb) 9286ed58ec5SVille Tervo { 9296ed58ec5SVille Tervo struct hci_rp_le_read_buffer_size *rp = (void *) skb->data; 9306ed58ec5SVille Tervo 9316ed58ec5SVille Tervo BT_DBG("%s status 0x%x", hdev->name, rp->status); 9326ed58ec5SVille Tervo 9336ed58ec5SVille Tervo if (rp->status) 9346ed58ec5SVille Tervo return; 9356ed58ec5SVille Tervo 9366ed58ec5SVille Tervo hdev->le_mtu = __le16_to_cpu(rp->le_mtu); 9376ed58ec5SVille Tervo hdev->le_pkts = rp->le_max_pkt; 9386ed58ec5SVille Tervo 9396ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 9406ed58ec5SVille Tervo 9416ed58ec5SVille Tervo BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); 9426ed58ec5SVille Tervo 9436ed58ec5SVille Tervo hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status); 9446ed58ec5SVille Tervo } 945980e1a53SJohan Hedberg 946a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) 947a5c29683SJohan Hedberg { 948a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 949a5c29683SJohan Hedberg 950a5c29683SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 951a5c29683SJohan Hedberg 95256e5cb86SJohan Hedberg hci_dev_lock(hdev); 95356e5cb86SJohan Hedberg 954a5c29683SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 955744cf19eSJohan Hedberg mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, 956a5c29683SJohan Hedberg rp->status); 95756e5cb86SJohan Hedberg 95856e5cb86SJohan Hedberg hci_dev_unlock(hdev); 959a5c29683SJohan Hedberg } 960a5c29683SJohan Hedberg 961a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, 962a5c29683SJohan Hedberg struct sk_buff *skb) 963a5c29683SJohan Hedberg { 964a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 965a5c29683SJohan Hedberg 966a5c29683SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 967a5c29683SJohan Hedberg 96856e5cb86SJohan Hedberg hci_dev_lock(hdev); 96956e5cb86SJohan Hedberg 970a5c29683SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 971744cf19eSJohan Hedberg mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr, 972a5c29683SJohan Hedberg rp->status); 97356e5cb86SJohan Hedberg 97456e5cb86SJohan Hedberg hci_dev_unlock(hdev); 975a5c29683SJohan Hedberg } 976a5c29683SJohan Hedberg 9771143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb) 9781143d458SBrian Gix { 9791143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 9801143d458SBrian Gix 9811143d458SBrian Gix BT_DBG("%s status 0x%x", hdev->name, rp->status); 9821143d458SBrian Gix 9831143d458SBrian Gix hci_dev_lock(hdev); 9841143d458SBrian Gix 9851143d458SBrian Gix if (test_bit(HCI_MGMT, &hdev->flags)) 9861143d458SBrian Gix mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, 9871143d458SBrian Gix rp->status); 9881143d458SBrian Gix 9891143d458SBrian Gix hci_dev_unlock(hdev); 9901143d458SBrian Gix } 9911143d458SBrian Gix 9921143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, 9931143d458SBrian Gix struct sk_buff *skb) 9941143d458SBrian Gix { 9951143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 9961143d458SBrian Gix 9971143d458SBrian Gix BT_DBG("%s status 0x%x", hdev->name, rp->status); 9981143d458SBrian Gix 9991143d458SBrian Gix hci_dev_lock(hdev); 10001143d458SBrian Gix 10011143d458SBrian Gix if (test_bit(HCI_MGMT, &hdev->flags)) 10021143d458SBrian Gix mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr, 10031143d458SBrian Gix rp->status); 10041143d458SBrian Gix 10051143d458SBrian Gix hci_dev_unlock(hdev); 10061143d458SBrian Gix } 10071143d458SBrian Gix 1008c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, 1009c35938b2SSzymon Janc struct sk_buff *skb) 1010c35938b2SSzymon Janc { 1011c35938b2SSzymon Janc struct hci_rp_read_local_oob_data *rp = (void *) skb->data; 1012c35938b2SSzymon Janc 1013c35938b2SSzymon Janc BT_DBG("%s status 0x%x", hdev->name, rp->status); 1014c35938b2SSzymon Janc 101556e5cb86SJohan Hedberg hci_dev_lock(hdev); 1016744cf19eSJohan Hedberg mgmt_read_local_oob_data_reply_complete(hdev, rp->hash, 1017c35938b2SSzymon Janc rp->randomizer, rp->status); 101856e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1019c35938b2SSzymon Janc } 1020c35938b2SSzymon Janc 102107f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) 102207f7fa5dSAndre Guedes { 102307f7fa5dSAndre Guedes __u8 status = *((__u8 *) skb->data); 102407f7fa5dSAndre Guedes 102507f7fa5dSAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 102607f7fa5dSAndre Guedes } 102707f7fa5dSAndre Guedes 1028eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, 1029eb9d91f5SAndre Guedes struct sk_buff *skb) 1030eb9d91f5SAndre Guedes { 1031eb9d91f5SAndre Guedes struct hci_cp_le_set_scan_enable *cp; 1032eb9d91f5SAndre Guedes __u8 status = *((__u8 *) skb->data); 1033eb9d91f5SAndre Guedes 1034eb9d91f5SAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 1035eb9d91f5SAndre Guedes 1036eb9d91f5SAndre Guedes if (status) 1037eb9d91f5SAndre Guedes return; 1038eb9d91f5SAndre Guedes 1039eb9d91f5SAndre Guedes cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE); 1040eb9d91f5SAndre Guedes if (!cp) 1041eb9d91f5SAndre Guedes return; 1042eb9d91f5SAndre Guedes 104368a8aea4SAndrei Emeltchenko switch (cp->enable) { 104468a8aea4SAndrei Emeltchenko case LE_SCANNING_ENABLED: 1045d23264a8SAndre Guedes set_bit(HCI_LE_SCAN, &hdev->dev_flags); 1046d23264a8SAndre Guedes 1047db323f2fSGustavo F. Padovan cancel_delayed_work_sync(&hdev->adv_work); 1048a8f13c8cSAndre Guedes 1049a8f13c8cSAndre Guedes hci_dev_lock(hdev); 1050eb9d91f5SAndre Guedes hci_adv_entries_clear(hdev); 1051a8f13c8cSAndre Guedes hci_dev_unlock(hdev); 105268a8aea4SAndrei Emeltchenko break; 105368a8aea4SAndrei Emeltchenko 105468a8aea4SAndrei Emeltchenko case LE_SCANNING_DISABLED: 1055d23264a8SAndre Guedes clear_bit(HCI_LE_SCAN, &hdev->dev_flags); 1056d23264a8SAndre Guedes 1057d084329eSAndre Guedes schedule_delayed_work(&hdev->adv_work, ADV_CLEAR_TIMEOUT); 105868a8aea4SAndrei Emeltchenko break; 105968a8aea4SAndrei Emeltchenko 106068a8aea4SAndrei Emeltchenko default: 106168a8aea4SAndrei Emeltchenko BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable); 106268a8aea4SAndrei Emeltchenko break; 106335815085SAndre Guedes } 1064eb9d91f5SAndre Guedes } 1065eb9d91f5SAndre Guedes 1066a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb) 1067a7a595f6SVinicius Costa Gomes { 1068a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_reply *rp = (void *) skb->data; 1069a7a595f6SVinicius Costa Gomes 1070a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, rp->status); 1071a7a595f6SVinicius Costa Gomes 1072a7a595f6SVinicius Costa Gomes if (rp->status) 1073a7a595f6SVinicius Costa Gomes return; 1074a7a595f6SVinicius Costa Gomes 1075a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status); 1076a7a595f6SVinicius Costa Gomes } 1077a7a595f6SVinicius Costa Gomes 1078a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 1079a7a595f6SVinicius Costa Gomes { 1080a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data; 1081a7a595f6SVinicius Costa Gomes 1082a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, rp->status); 1083a7a595f6SVinicius Costa Gomes 1084a7a595f6SVinicius Costa Gomes if (rp->status) 1085a7a595f6SVinicius Costa Gomes return; 1086a7a595f6SVinicius Costa Gomes 1087a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status); 1088a7a595f6SVinicius Costa Gomes } 1089a7a595f6SVinicius Costa Gomes 1090f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev, 1091f9b49306SAndre Guedes struct sk_buff *skb) 1092f9b49306SAndre Guedes { 1093f9b49306SAndre Guedes struct hci_cp_read_local_ext_features cp; 1094f9b49306SAndre Guedes __u8 status = *((__u8 *) skb->data); 1095f9b49306SAndre Guedes 1096f9b49306SAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 1097f9b49306SAndre Guedes 1098f9b49306SAndre Guedes if (status) 1099f9b49306SAndre Guedes return; 1100f9b49306SAndre Guedes 1101f9b49306SAndre Guedes cp.page = 0x01; 1102f9b49306SAndre Guedes hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp); 1103f9b49306SAndre Guedes } 1104f9b49306SAndre Guedes 1105a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 1106a9de9248SMarcel Holtmann { 1107a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1108a9de9248SMarcel Holtmann 1109a9de9248SMarcel Holtmann if (status) { 111023bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 1111a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 111256e5cb86SJohan Hedberg hci_dev_lock(hdev); 1113164a6e78SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 11147a135109SAndre Guedes mgmt_start_discovery_failed(hdev, status); 111556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1116314b2381SJohan Hedberg return; 1117314b2381SJohan Hedberg } 1118314b2381SJohan Hedberg 111989352e7dSAndre Guedes set_bit(HCI_INQUIRY, &hdev->flags); 112089352e7dSAndre Guedes 112156e5cb86SJohan Hedberg hci_dev_lock(hdev); 1122744cf19eSJohan Hedberg mgmt_discovering(hdev, 1); 112356e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1124a9de9248SMarcel Holtmann } 1125a9de9248SMarcel Holtmann 11261da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 11271da177e4SLinus Torvalds { 1128a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 11291da177e4SLinus Torvalds struct hci_conn *conn; 11301da177e4SLinus Torvalds 1131a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1132a9de9248SMarcel Holtmann 1133a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 11341da177e4SLinus Torvalds if (!cp) 11351da177e4SLinus Torvalds return; 11361da177e4SLinus Torvalds 11371da177e4SLinus Torvalds hci_dev_lock(hdev); 11381da177e4SLinus Torvalds 11391da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 11401da177e4SLinus Torvalds 1141a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn); 11421da177e4SLinus Torvalds 11431da177e4SLinus Torvalds if (status) { 11441da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 11454c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 11461da177e4SLinus Torvalds conn->state = BT_CLOSED; 11471da177e4SLinus Torvalds hci_proto_connect_cfm(conn, status); 11481da177e4SLinus Torvalds hci_conn_del(conn); 11494c67bc74SMarcel Holtmann } else 11504c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 11511da177e4SLinus Torvalds } 11521da177e4SLinus Torvalds } else { 11531da177e4SLinus Torvalds if (!conn) { 11541da177e4SLinus Torvalds conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); 11551da177e4SLinus Torvalds if (conn) { 11561da177e4SLinus Torvalds conn->out = 1; 11571da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 11581da177e4SLinus Torvalds } else 1159893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 11601da177e4SLinus Torvalds } 11611da177e4SLinus Torvalds } 11621da177e4SLinus Torvalds 11631da177e4SLinus Torvalds hci_dev_unlock(hdev); 11641da177e4SLinus Torvalds } 11651da177e4SLinus Torvalds 1166a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 11671da177e4SLinus Torvalds { 1168a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 11691da177e4SLinus Torvalds struct hci_conn *acl, *sco; 11701da177e4SLinus Torvalds __u16 handle; 11711da177e4SLinus Torvalds 1172b6a0dc82SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1173b6a0dc82SMarcel Holtmann 1174a9de9248SMarcel Holtmann if (!status) 1175a9de9248SMarcel Holtmann return; 1176a9de9248SMarcel Holtmann 1177a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 11781da177e4SLinus Torvalds if (!cp) 1179a9de9248SMarcel Holtmann return; 11801da177e4SLinus Torvalds 11811da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 11821da177e4SLinus Torvalds 1183a9de9248SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 11841da177e4SLinus Torvalds 11851da177e4SLinus Torvalds hci_dev_lock(hdev); 11861da177e4SLinus Torvalds 11871da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 11885a08ecceSAndrei Emeltchenko if (acl) { 11895a08ecceSAndrei Emeltchenko sco = acl->link; 11905a08ecceSAndrei Emeltchenko if (sco) { 11911da177e4SLinus Torvalds sco->state = BT_CLOSED; 11921da177e4SLinus Torvalds 11931da177e4SLinus Torvalds hci_proto_connect_cfm(sco, status); 11941da177e4SLinus Torvalds hci_conn_del(sco); 11951da177e4SLinus Torvalds } 11965a08ecceSAndrei Emeltchenko } 11971da177e4SLinus Torvalds 11981da177e4SLinus Torvalds hci_dev_unlock(hdev); 11991da177e4SLinus Torvalds } 12001da177e4SLinus Torvalds 1201f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 1202f8558555SMarcel Holtmann { 1203f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 1204f8558555SMarcel Holtmann struct hci_conn *conn; 1205f8558555SMarcel Holtmann 1206f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1207f8558555SMarcel Holtmann 1208f8558555SMarcel Holtmann if (!status) 1209f8558555SMarcel Holtmann return; 1210f8558555SMarcel Holtmann 1211f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 1212f8558555SMarcel Holtmann if (!cp) 1213f8558555SMarcel Holtmann return; 1214f8558555SMarcel Holtmann 1215f8558555SMarcel Holtmann hci_dev_lock(hdev); 1216f8558555SMarcel Holtmann 1217f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1218f8558555SMarcel Holtmann if (conn) { 1219f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1220f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1221f8558555SMarcel Holtmann hci_conn_put(conn); 1222f8558555SMarcel Holtmann } 1223f8558555SMarcel Holtmann } 1224f8558555SMarcel Holtmann 1225f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1226f8558555SMarcel Holtmann } 1227f8558555SMarcel Holtmann 1228f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 1229f8558555SMarcel Holtmann { 1230f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 1231f8558555SMarcel Holtmann struct hci_conn *conn; 1232f8558555SMarcel Holtmann 1233f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1234f8558555SMarcel Holtmann 1235f8558555SMarcel Holtmann if (!status) 1236f8558555SMarcel Holtmann return; 1237f8558555SMarcel Holtmann 1238f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 1239f8558555SMarcel Holtmann if (!cp) 1240f8558555SMarcel Holtmann return; 1241f8558555SMarcel Holtmann 1242f8558555SMarcel Holtmann hci_dev_lock(hdev); 1243f8558555SMarcel Holtmann 1244f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1245f8558555SMarcel Holtmann if (conn) { 1246f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1247f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1248f8558555SMarcel Holtmann hci_conn_put(conn); 1249f8558555SMarcel Holtmann } 1250f8558555SMarcel Holtmann } 1251f8558555SMarcel Holtmann 1252f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1253f8558555SMarcel Holtmann } 1254f8558555SMarcel Holtmann 1255127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev, 1256392599b9SJohan Hedberg struct hci_conn *conn) 1257392599b9SJohan Hedberg { 1258392599b9SJohan Hedberg if (conn->state != BT_CONFIG || !conn->out) 1259392599b9SJohan Hedberg return 0; 1260392599b9SJohan Hedberg 1261765c2a96SJohan Hedberg if (conn->pending_sec_level == BT_SECURITY_SDP) 1262392599b9SJohan Hedberg return 0; 1263392599b9SJohan Hedberg 1264392599b9SJohan Hedberg /* Only request authentication for SSP connections or non-SSP 1265e9bf2bf0SVinicius Costa Gomes * devices with sec_level HIGH or if MITM protection is requested */ 1266392599b9SJohan Hedberg if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) && 1267e9bf2bf0SVinicius Costa Gomes conn->pending_sec_level != BT_SECURITY_HIGH && 1268e9bf2bf0SVinicius Costa Gomes !(conn->auth_type & 0x01)) 1269392599b9SJohan Hedberg return 0; 1270392599b9SJohan Hedberg 1271392599b9SJohan Hedberg return 1; 1272392599b9SJohan Hedberg } 1273392599b9SJohan Hedberg 1274a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 12751da177e4SLinus Torvalds { 1276127178d2SJohan Hedberg struct hci_cp_remote_name_req *cp; 1277127178d2SJohan Hedberg struct hci_conn *conn; 1278127178d2SJohan Hedberg 1279a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1280127178d2SJohan Hedberg 1281127178d2SJohan Hedberg /* If successful wait for the name req complete event before 1282127178d2SJohan Hedberg * checking for the need to do authentication */ 1283127178d2SJohan Hedberg if (!status) 1284127178d2SJohan Hedberg return; 1285127178d2SJohan Hedberg 1286127178d2SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); 1287127178d2SJohan Hedberg if (!cp) 1288127178d2SJohan Hedberg return; 1289127178d2SJohan Hedberg 1290127178d2SJohan Hedberg hci_dev_lock(hdev); 1291127178d2SJohan Hedberg 1292127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 129379c6c70cSJohan Hedberg if (!conn) 129479c6c70cSJohan Hedberg goto unlock; 129579c6c70cSJohan Hedberg 129679c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 129779c6c70cSJohan Hedberg goto unlock; 129879c6c70cSJohan Hedberg 129979c6c70cSJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { 1300127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1301127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1302127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1303127178d2SJohan Hedberg } 1304127178d2SJohan Hedberg 130579c6c70cSJohan Hedberg unlock: 1306127178d2SJohan Hedberg hci_dev_unlock(hdev); 1307a9de9248SMarcel Holtmann } 13081da177e4SLinus Torvalds 1309769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 1310769be974SMarcel Holtmann { 1311769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 1312769be974SMarcel Holtmann struct hci_conn *conn; 1313769be974SMarcel Holtmann 1314769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1315769be974SMarcel Holtmann 1316769be974SMarcel Holtmann if (!status) 1317769be974SMarcel Holtmann return; 1318769be974SMarcel Holtmann 1319769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 1320769be974SMarcel Holtmann if (!cp) 1321769be974SMarcel Holtmann return; 1322769be974SMarcel Holtmann 1323769be974SMarcel Holtmann hci_dev_lock(hdev); 1324769be974SMarcel Holtmann 1325769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1326769be974SMarcel Holtmann if (conn) { 1327769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1328769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1329769be974SMarcel Holtmann hci_conn_put(conn); 1330769be974SMarcel Holtmann } 1331769be974SMarcel Holtmann } 1332769be974SMarcel Holtmann 1333769be974SMarcel Holtmann hci_dev_unlock(hdev); 1334769be974SMarcel Holtmann } 1335769be974SMarcel Holtmann 1336769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 1337769be974SMarcel Holtmann { 1338769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features *cp; 1339769be974SMarcel Holtmann struct hci_conn *conn; 1340769be974SMarcel Holtmann 1341769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1342769be974SMarcel Holtmann 1343769be974SMarcel Holtmann if (!status) 1344769be974SMarcel Holtmann return; 1345769be974SMarcel Holtmann 1346769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 1347769be974SMarcel Holtmann if (!cp) 1348769be974SMarcel Holtmann return; 1349769be974SMarcel Holtmann 1350769be974SMarcel Holtmann hci_dev_lock(hdev); 1351769be974SMarcel Holtmann 1352769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1353769be974SMarcel Holtmann if (conn) { 1354769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1355769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1356769be974SMarcel Holtmann hci_conn_put(conn); 1357769be974SMarcel Holtmann } 1358769be974SMarcel Holtmann } 1359769be974SMarcel Holtmann 1360769be974SMarcel Holtmann hci_dev_unlock(hdev); 1361769be974SMarcel Holtmann } 1362769be974SMarcel Holtmann 1363a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 1364a9de9248SMarcel Holtmann { 1365b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 1366b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 1367b6a0dc82SMarcel Holtmann __u16 handle; 1368b6a0dc82SMarcel Holtmann 1369a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1370b6a0dc82SMarcel Holtmann 1371b6a0dc82SMarcel Holtmann if (!status) 1372b6a0dc82SMarcel Holtmann return; 1373b6a0dc82SMarcel Holtmann 1374b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 1375b6a0dc82SMarcel Holtmann if (!cp) 1376b6a0dc82SMarcel Holtmann return; 1377b6a0dc82SMarcel Holtmann 1378b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 1379b6a0dc82SMarcel Holtmann 1380b6a0dc82SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 1381b6a0dc82SMarcel Holtmann 1382b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 1383b6a0dc82SMarcel Holtmann 1384b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 13855a08ecceSAndrei Emeltchenko if (acl) { 13865a08ecceSAndrei Emeltchenko sco = acl->link; 13875a08ecceSAndrei Emeltchenko if (sco) { 1388b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 1389b6a0dc82SMarcel Holtmann 1390b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(sco, status); 1391b6a0dc82SMarcel Holtmann hci_conn_del(sco); 1392b6a0dc82SMarcel Holtmann } 13935a08ecceSAndrei Emeltchenko } 1394b6a0dc82SMarcel Holtmann 1395b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 1396a9de9248SMarcel Holtmann } 1397a9de9248SMarcel Holtmann 1398a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 1399a9de9248SMarcel Holtmann { 1400a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 140104837f64SMarcel Holtmann struct hci_conn *conn; 140204837f64SMarcel Holtmann 1403a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1404a9de9248SMarcel Holtmann 1405a9de9248SMarcel Holtmann if (!status) 1406a9de9248SMarcel Holtmann return; 1407a9de9248SMarcel Holtmann 1408a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 140904837f64SMarcel Holtmann if (!cp) 1410a9de9248SMarcel Holtmann return; 141104837f64SMarcel Holtmann 141204837f64SMarcel Holtmann hci_dev_lock(hdev); 141304837f64SMarcel Holtmann 141404837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1415e73439d8SMarcel Holtmann if (conn) { 141604837f64SMarcel Holtmann clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); 141704837f64SMarcel Holtmann 1418e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 1419e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1420e73439d8SMarcel Holtmann } 1421e73439d8SMarcel Holtmann 142204837f64SMarcel Holtmann hci_dev_unlock(hdev); 142304837f64SMarcel Holtmann } 142404837f64SMarcel Holtmann 1425a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 1426a9de9248SMarcel Holtmann { 1427a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 142804837f64SMarcel Holtmann struct hci_conn *conn; 142904837f64SMarcel Holtmann 1430a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1431a9de9248SMarcel Holtmann 1432a9de9248SMarcel Holtmann if (!status) 1433a9de9248SMarcel Holtmann return; 1434a9de9248SMarcel Holtmann 1435a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 143604837f64SMarcel Holtmann if (!cp) 1437a9de9248SMarcel Holtmann return; 143804837f64SMarcel Holtmann 143904837f64SMarcel Holtmann hci_dev_lock(hdev); 144004837f64SMarcel Holtmann 144104837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1442e73439d8SMarcel Holtmann if (conn) { 144304837f64SMarcel Holtmann clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); 144404837f64SMarcel Holtmann 1445e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 1446e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1447e73439d8SMarcel Holtmann } 1448e73439d8SMarcel Holtmann 144904837f64SMarcel Holtmann hci_dev_unlock(hdev); 145004837f64SMarcel Holtmann } 145104837f64SMarcel Holtmann 1452fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) 1453fcd89c09SVille Tervo { 1454fcd89c09SVille Tervo struct hci_cp_le_create_conn *cp; 1455fcd89c09SVille Tervo struct hci_conn *conn; 1456fcd89c09SVille Tervo 1457fcd89c09SVille Tervo BT_DBG("%s status 0x%x", hdev->name, status); 1458fcd89c09SVille Tervo 1459fcd89c09SVille Tervo cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN); 1460fcd89c09SVille Tervo if (!cp) 1461fcd89c09SVille Tervo return; 1462fcd89c09SVille Tervo 1463fcd89c09SVille Tervo hci_dev_lock(hdev); 1464fcd89c09SVille Tervo 1465fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr); 1466fcd89c09SVille Tervo 1467fcd89c09SVille Tervo BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr), 1468fcd89c09SVille Tervo conn); 1469fcd89c09SVille Tervo 1470fcd89c09SVille Tervo if (status) { 1471fcd89c09SVille Tervo if (conn && conn->state == BT_CONNECT) { 1472fcd89c09SVille Tervo conn->state = BT_CLOSED; 1473fcd89c09SVille Tervo hci_proto_connect_cfm(conn, status); 1474fcd89c09SVille Tervo hci_conn_del(conn); 1475fcd89c09SVille Tervo } 1476fcd89c09SVille Tervo } else { 1477fcd89c09SVille Tervo if (!conn) { 1478fcd89c09SVille Tervo conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr); 147929b7988aSAndre Guedes if (conn) { 148029b7988aSAndre Guedes conn->dst_type = cp->peer_addr_type; 1481fcd89c09SVille Tervo conn->out = 1; 148229b7988aSAndre Guedes } else { 1483fcd89c09SVille Tervo BT_ERR("No memory for new connection"); 1484fcd89c09SVille Tervo } 1485fcd89c09SVille Tervo } 148629b7988aSAndre Guedes } 1487fcd89c09SVille Tervo 1488fcd89c09SVille Tervo hci_dev_unlock(hdev); 1489fcd89c09SVille Tervo } 1490fcd89c09SVille Tervo 1491a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) 1492a7a595f6SVinicius Costa Gomes { 1493a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, status); 1494a7a595f6SVinicius Costa Gomes } 1495a7a595f6SVinicius Costa Gomes 14961da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 14971da177e4SLinus Torvalds { 14981da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 14991da177e4SLinus Torvalds 15001da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, status); 15011da177e4SLinus Torvalds 150223bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 15036bd57416SMarcel Holtmann 1504a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 150589352e7dSAndre Guedes 150689352e7dSAndre Guedes if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) 150789352e7dSAndre Guedes return; 150889352e7dSAndre Guedes 150956e5cb86SJohan Hedberg hci_dev_lock(hdev); 1510744cf19eSJohan Hedberg mgmt_discovering(hdev, 0); 151156e5cb86SJohan Hedberg hci_dev_unlock(hdev); 15121da177e4SLinus Torvalds } 15131da177e4SLinus Torvalds 15141da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 15151da177e4SLinus Torvalds { 151645bb4bf0SMarcel Holtmann struct inquiry_data data; 1517a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 15181da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 15191da177e4SLinus Torvalds 15201da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 15211da177e4SLinus Torvalds 152245bb4bf0SMarcel Holtmann if (!num_rsp) 152345bb4bf0SMarcel Holtmann return; 152445bb4bf0SMarcel Holtmann 15251da177e4SLinus Torvalds hci_dev_lock(hdev); 152645bb4bf0SMarcel Holtmann 1527e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 15281da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 15291da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 15301da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 15311da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 15321da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 15331da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 15341da177e4SLinus Torvalds data.rssi = 0x00; 153541a96212SMarcel Holtmann data.ssp_mode = 0x00; 15361da177e4SLinus Torvalds hci_inquiry_cache_update(hdev, &data); 153748264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 15384c659c39SJohan Hedberg info->dev_class, 0, NULL); 15391da177e4SLinus Torvalds } 154045bb4bf0SMarcel Holtmann 15411da177e4SLinus Torvalds hci_dev_unlock(hdev); 15421da177e4SLinus Torvalds } 15431da177e4SLinus Torvalds 1544a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 15451da177e4SLinus Torvalds { 1546a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 1547a9de9248SMarcel Holtmann struct hci_conn *conn; 15481da177e4SLinus Torvalds 1549a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 155045bb4bf0SMarcel Holtmann 15511da177e4SLinus Torvalds hci_dev_lock(hdev); 155245bb4bf0SMarcel Holtmann 1553a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 15549499237aSMarcel Holtmann if (!conn) { 15559499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 15569499237aSMarcel Holtmann goto unlock; 15579499237aSMarcel Holtmann 15589499237aSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 1559a9de9248SMarcel Holtmann if (!conn) 1560a9de9248SMarcel Holtmann goto unlock; 156145bb4bf0SMarcel Holtmann 15629499237aSMarcel Holtmann conn->type = SCO_LINK; 15639499237aSMarcel Holtmann } 15649499237aSMarcel Holtmann 1565a9de9248SMarcel Holtmann if (!ev->status) { 1566a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 1567769be974SMarcel Holtmann 1568769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 1569769be974SMarcel Holtmann conn->state = BT_CONFIG; 1570769be974SMarcel Holtmann hci_conn_hold(conn); 1571052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 157248264f06SJohan Hedberg mgmt_connected(hdev, &ev->bdaddr, conn->type, 157348264f06SJohan Hedberg conn->dst_type); 1574769be974SMarcel Holtmann } else 1575a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 1576a9de9248SMarcel Holtmann 15779eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 15787d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 15797d0db0a3SMarcel Holtmann 1580a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 1581a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1582a9de9248SMarcel Holtmann 1583a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 1584a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1585a9de9248SMarcel Holtmann 1586a9de9248SMarcel Holtmann /* Get remote features */ 1587a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 1588a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 1589a9de9248SMarcel Holtmann cp.handle = ev->handle; 1590769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 1591769be974SMarcel Holtmann sizeof(cp), &cp); 159245bb4bf0SMarcel Holtmann } 1593a9de9248SMarcel Holtmann 1594a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 1595d095c1ebSAndrei Emeltchenko if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) { 1596a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 1597a9de9248SMarcel Holtmann cp.handle = ev->handle; 1598a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1599a8746417SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, 1600a8746417SMarcel Holtmann sizeof(cp), &cp); 1601a9de9248SMarcel Holtmann } 160217d5c04cSJohan Hedberg } else { 1603a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 160417d5c04cSJohan Hedberg if (conn->type == ACL_LINK) 1605744cf19eSJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 160648264f06SJohan Hedberg conn->dst_type, ev->status); 160717d5c04cSJohan Hedberg } 160845bb4bf0SMarcel Holtmann 1609e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 1610e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 161145bb4bf0SMarcel Holtmann 1612769be974SMarcel Holtmann if (ev->status) { 1613a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1614a9de9248SMarcel Holtmann hci_conn_del(conn); 1615c89b6e6bSMarcel Holtmann } else if (ev->link_type != ACL_LINK) 1616c89b6e6bSMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1617a9de9248SMarcel Holtmann 1618a9de9248SMarcel Holtmann unlock: 16191da177e4SLinus Torvalds hci_dev_unlock(hdev); 1620a9de9248SMarcel Holtmann 1621a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 16221da177e4SLinus Torvalds } 16231da177e4SLinus Torvalds 16241da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 16251da177e4SLinus Torvalds { 1626a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 16271da177e4SLinus Torvalds int mask = hdev->link_mode; 16281da177e4SLinus Torvalds 1629a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s type 0x%x", hdev->name, 16301da177e4SLinus Torvalds batostr(&ev->bdaddr), ev->link_type); 16311da177e4SLinus Torvalds 16321da177e4SLinus Torvalds mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); 16331da177e4SLinus Torvalds 1634138d22efSSzymon Janc if ((mask & HCI_LM_ACCEPT) && 1635138d22efSSzymon Janc !hci_blacklist_lookup(hdev, &ev->bdaddr)) { 16361da177e4SLinus Torvalds /* Connection accepted */ 1637c7bdd502SMarcel Holtmann struct inquiry_entry *ie; 16381da177e4SLinus Torvalds struct hci_conn *conn; 16391da177e4SLinus Torvalds 16401da177e4SLinus Torvalds hci_dev_lock(hdev); 1641b6a0dc82SMarcel Holtmann 1642cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 1643cc11b9c1SAndrei Emeltchenko if (ie) 1644c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 1645c7bdd502SMarcel Holtmann 16461da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 16471da177e4SLinus Torvalds if (!conn) { 1648cc11b9c1SAndrei Emeltchenko conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); 1649cc11b9c1SAndrei Emeltchenko if (!conn) { 1650893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 16511da177e4SLinus Torvalds hci_dev_unlock(hdev); 16521da177e4SLinus Torvalds return; 16531da177e4SLinus Torvalds } 16541da177e4SLinus Torvalds } 1655b6a0dc82SMarcel Holtmann 16561da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 16571da177e4SLinus Torvalds conn->state = BT_CONNECT; 1658b6a0dc82SMarcel Holtmann 16591da177e4SLinus Torvalds hci_dev_unlock(hdev); 16601da177e4SLinus Torvalds 1661b6a0dc82SMarcel Holtmann if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) { 1662b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 1663b6a0dc82SMarcel Holtmann 16641da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 16651da177e4SLinus Torvalds 16661da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 16671da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 16681da177e4SLinus Torvalds else 16691da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 16701da177e4SLinus Torvalds 1671b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, 1672b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1673b6a0dc82SMarcel Holtmann } else { 1674b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 1675b6a0dc82SMarcel Holtmann 1676b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 1677a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1678b6a0dc82SMarcel Holtmann 1679b6a0dc82SMarcel Holtmann cp.tx_bandwidth = cpu_to_le32(0x00001f40); 1680b6a0dc82SMarcel Holtmann cp.rx_bandwidth = cpu_to_le32(0x00001f40); 1681b6a0dc82SMarcel Holtmann cp.max_latency = cpu_to_le16(0xffff); 1682b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 1683b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 1684b6a0dc82SMarcel Holtmann 1685b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 1686b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1687b6a0dc82SMarcel Holtmann } 16881da177e4SLinus Torvalds } else { 16891da177e4SLinus Torvalds /* Connection rejected */ 16901da177e4SLinus Torvalds struct hci_cp_reject_conn_req cp; 16911da177e4SLinus Torvalds 16921da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 16939f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_REJ_BAD_ADDR; 1694a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 16951da177e4SLinus Torvalds } 16961da177e4SLinus Torvalds } 16971da177e4SLinus Torvalds 16981da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 16991da177e4SLinus Torvalds { 1700a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 170104837f64SMarcel Holtmann struct hci_conn *conn; 17021da177e4SLinus Torvalds 17031da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 17041da177e4SLinus Torvalds 17051da177e4SLinus Torvalds hci_dev_lock(hdev); 17061da177e4SLinus Torvalds 170704837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1708f7520543SJohan Hedberg if (!conn) 1709f7520543SJohan Hedberg goto unlock; 1710f7520543SJohan Hedberg 171137d9ef76SJohan Hedberg if (ev->status == 0) 17121da177e4SLinus Torvalds conn->state = BT_CLOSED; 17137d0db0a3SMarcel Holtmann 171437d9ef76SJohan Hedberg if (conn->type == ACL_LINK || conn->type == LE_LINK) { 171537d9ef76SJohan Hedberg if (ev->status != 0) 171637d9ef76SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, ev->status); 171737d9ef76SJohan Hedberg else 171848264f06SJohan Hedberg mgmt_disconnected(hdev, &conn->dst, conn->type, 171948264f06SJohan Hedberg conn->dst_type); 172037d9ef76SJohan Hedberg } 1721f7520543SJohan Hedberg 172237d9ef76SJohan Hedberg if (ev->status == 0) { 17232950f21aSMarcel Holtmann hci_proto_disconn_cfm(conn, ev->reason); 17241da177e4SLinus Torvalds hci_conn_del(conn); 172537d9ef76SJohan Hedberg } 17261da177e4SLinus Torvalds 1727f7520543SJohan Hedberg unlock: 17281da177e4SLinus Torvalds hci_dev_unlock(hdev); 17291da177e4SLinus Torvalds } 17301da177e4SLinus Torvalds 1731a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1732a9de9248SMarcel Holtmann { 1733a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 1734a9de9248SMarcel Holtmann struct hci_conn *conn; 1735a9de9248SMarcel Holtmann 1736a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1737a9de9248SMarcel Holtmann 1738a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1739a9de9248SMarcel Holtmann 1740a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1741d7556e20SWaldemar Rymarkiewicz if (!conn) 1742d7556e20SWaldemar Rymarkiewicz goto unlock; 1743d7556e20SWaldemar Rymarkiewicz 1744765c2a96SJohan Hedberg if (!ev->status) { 174519f8def0SWaldemar Rymarkiewicz if (!(conn->ssp_mode > 0 && hdev->ssp_mode > 0) && 1746d7556e20SWaldemar Rymarkiewicz test_bit(HCI_CONN_REAUTH_PEND, &conn->pend)) { 1747d7556e20SWaldemar Rymarkiewicz BT_INFO("re-auth of legacy device is not possible."); 174819f8def0SWaldemar Rymarkiewicz } else { 1749a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1750765c2a96SJohan Hedberg conn->sec_level = conn->pending_sec_level; 175119f8def0SWaldemar Rymarkiewicz } 17522a611692SJohan Hedberg } else { 1753744cf19eSJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, ev->status); 17542a611692SJohan Hedberg } 1755a9de9248SMarcel Holtmann 1756a9de9248SMarcel Holtmann clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); 175719f8def0SWaldemar Rymarkiewicz clear_bit(HCI_CONN_REAUTH_PEND, &conn->pend); 1758a9de9248SMarcel Holtmann 1759f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1760d7556e20SWaldemar Rymarkiewicz if (!ev->status && hdev->ssp_mode > 0 && conn->ssp_mode > 0) { 1761f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1762f8558555SMarcel Holtmann cp.handle = ev->handle; 1763f8558555SMarcel Holtmann cp.encrypt = 0x01; 1764d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1765d7556e20SWaldemar Rymarkiewicz &cp); 1766f8558555SMarcel Holtmann } else { 1767f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1768f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1769f8558555SMarcel Holtmann hci_conn_put(conn); 1770f8558555SMarcel Holtmann } 1771052b30b0SMarcel Holtmann } else { 1772a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 1773a9de9248SMarcel Holtmann 1774052b30b0SMarcel Holtmann hci_conn_hold(conn); 1775052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1776052b30b0SMarcel Holtmann hci_conn_put(conn); 1777052b30b0SMarcel Holtmann } 1778052b30b0SMarcel Holtmann 1779a9de9248SMarcel Holtmann if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) { 1780a9de9248SMarcel Holtmann if (!ev->status) { 1781a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1782f8558555SMarcel Holtmann cp.handle = ev->handle; 1783f8558555SMarcel Holtmann cp.encrypt = 0x01; 1784d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1785d7556e20SWaldemar Rymarkiewicz &cp); 1786a9de9248SMarcel Holtmann } else { 1787a9de9248SMarcel Holtmann clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); 1788a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 1789a9de9248SMarcel Holtmann } 1790a9de9248SMarcel Holtmann } 1791a9de9248SMarcel Holtmann 1792d7556e20SWaldemar Rymarkiewicz unlock: 1793a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1794a9de9248SMarcel Holtmann } 1795a9de9248SMarcel Holtmann 1796a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 1797a9de9248SMarcel Holtmann { 1798127178d2SJohan Hedberg struct hci_ev_remote_name *ev = (void *) skb->data; 1799127178d2SJohan Hedberg struct hci_conn *conn; 1800127178d2SJohan Hedberg 1801a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1802a9de9248SMarcel Holtmann 1803a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 1804127178d2SJohan Hedberg 1805127178d2SJohan Hedberg hci_dev_lock(hdev); 1806127178d2SJohan Hedberg 1807a88a9652SJohan Hedberg if (ev->status == 0 && test_bit(HCI_MGMT, &hdev->flags)) 1808744cf19eSJohan Hedberg mgmt_remote_name(hdev, &ev->bdaddr, ev->name); 1809a88a9652SJohan Hedberg 1810127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 181179c6c70cSJohan Hedberg if (!conn) 181279c6c70cSJohan Hedberg goto unlock; 181379c6c70cSJohan Hedberg 181479c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 181579c6c70cSJohan Hedberg goto unlock; 181679c6c70cSJohan Hedberg 181779c6c70cSJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { 1818127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1819127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1820127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1821127178d2SJohan Hedberg } 1822127178d2SJohan Hedberg 182379c6c70cSJohan Hedberg unlock: 1824127178d2SJohan Hedberg hci_dev_unlock(hdev); 1825a9de9248SMarcel Holtmann } 1826a9de9248SMarcel Holtmann 1827a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 1828a9de9248SMarcel Holtmann { 1829a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 1830a9de9248SMarcel Holtmann struct hci_conn *conn; 1831a9de9248SMarcel Holtmann 1832a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1833a9de9248SMarcel Holtmann 1834a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1835a9de9248SMarcel Holtmann 1836a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1837a9de9248SMarcel Holtmann if (conn) { 1838a9de9248SMarcel Holtmann if (!ev->status) { 1839ae293196SMarcel Holtmann if (ev->encrypt) { 1840ae293196SMarcel Holtmann /* Encryption implies authentication */ 1841ae293196SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1842a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1843da85e5e5SVinicius Costa Gomes conn->sec_level = conn->pending_sec_level; 1844ae293196SMarcel Holtmann } else 1845a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_ENCRYPT; 1846a9de9248SMarcel Holtmann } 1847a9de9248SMarcel Holtmann 1848a9de9248SMarcel Holtmann clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); 1849a9de9248SMarcel Holtmann 1850f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1851f8558555SMarcel Holtmann if (!ev->status) 1852f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1853f8558555SMarcel Holtmann 1854f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1855f8558555SMarcel Holtmann hci_conn_put(conn); 1856f8558555SMarcel Holtmann } else 1857a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 1858a9de9248SMarcel Holtmann } 1859a9de9248SMarcel Holtmann 1860a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1861a9de9248SMarcel Holtmann } 1862a9de9248SMarcel Holtmann 1863a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1864a9de9248SMarcel Holtmann { 1865a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 1866a9de9248SMarcel Holtmann struct hci_conn *conn; 1867a9de9248SMarcel Holtmann 1868a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1869a9de9248SMarcel Holtmann 1870a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1871a9de9248SMarcel Holtmann 1872a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1873a9de9248SMarcel Holtmann if (conn) { 1874a9de9248SMarcel Holtmann if (!ev->status) 1875a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_SECURE; 1876a9de9248SMarcel Holtmann 1877a9de9248SMarcel Holtmann clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); 1878a9de9248SMarcel Holtmann 1879a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 1880a9de9248SMarcel Holtmann } 1881a9de9248SMarcel Holtmann 1882a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1883a9de9248SMarcel Holtmann } 1884a9de9248SMarcel Holtmann 1885a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 1886a9de9248SMarcel Holtmann { 1887a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 1888a9de9248SMarcel Holtmann struct hci_conn *conn; 1889a9de9248SMarcel Holtmann 1890a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1891a9de9248SMarcel Holtmann 1892a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1893a9de9248SMarcel Holtmann 1894a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1895ccd556feSJohan Hedberg if (!conn) 1896ccd556feSJohan Hedberg goto unlock; 1897ccd556feSJohan Hedberg 1898769be974SMarcel Holtmann if (!ev->status) 1899a9de9248SMarcel Holtmann memcpy(conn->features, ev->features, 8); 1900a9de9248SMarcel Holtmann 1901ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 1902ccd556feSJohan Hedberg goto unlock; 1903ccd556feSJohan Hedberg 1904ccd556feSJohan Hedberg if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { 1905769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 1906769be974SMarcel Holtmann cp.handle = ev->handle; 1907769be974SMarcel Holtmann cp.page = 0x01; 1908ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 1909769be974SMarcel Holtmann sizeof(cp), &cp); 1910392599b9SJohan Hedberg goto unlock; 1911392599b9SJohan Hedberg } 1912392599b9SJohan Hedberg 1913127178d2SJohan Hedberg if (!ev->status) { 1914127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 1915127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 1916127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 1917127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 1918127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 1919127178d2SJohan Hedberg } 1920392599b9SJohan Hedberg 1921127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 1922769be974SMarcel Holtmann conn->state = BT_CONNECTED; 1923769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1924769be974SMarcel Holtmann hci_conn_put(conn); 1925769be974SMarcel Holtmann } 1926769be974SMarcel Holtmann 1927ccd556feSJohan Hedberg unlock: 1928a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1929a9de9248SMarcel Holtmann } 1930a9de9248SMarcel Holtmann 1931a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) 1932a9de9248SMarcel Holtmann { 1933a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1934a9de9248SMarcel Holtmann } 1935a9de9248SMarcel Holtmann 1936a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1937a9de9248SMarcel Holtmann { 1938a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1939a9de9248SMarcel Holtmann } 1940a9de9248SMarcel Holtmann 1941a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1942a9de9248SMarcel Holtmann { 1943a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 1944a9de9248SMarcel Holtmann __u16 opcode; 1945a9de9248SMarcel Holtmann 1946a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 1947a9de9248SMarcel Holtmann 1948a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 1949a9de9248SMarcel Holtmann 1950a9de9248SMarcel Holtmann switch (opcode) { 1951a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 1952a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 1953a9de9248SMarcel Holtmann break; 1954a9de9248SMarcel Holtmann 1955a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 1956a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 1957a9de9248SMarcel Holtmann break; 1958a9de9248SMarcel Holtmann 1959a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 1960a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 1961a9de9248SMarcel Holtmann break; 1962a9de9248SMarcel Holtmann 1963a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 1964a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 1965a9de9248SMarcel Holtmann break; 1966a9de9248SMarcel Holtmann 1967e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 1968e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 1969e4e8e37cSMarcel Holtmann break; 1970e4e8e37cSMarcel Holtmann 1971a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 1972a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 1973a9de9248SMarcel Holtmann break; 1974a9de9248SMarcel Holtmann 1975e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 1976e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 1977e4e8e37cSMarcel Holtmann break; 1978e4e8e37cSMarcel Holtmann 1979e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 1980e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 1981e4e8e37cSMarcel Holtmann break; 1982e4e8e37cSMarcel Holtmann 1983a9de9248SMarcel Holtmann case HCI_OP_RESET: 1984a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 1985a9de9248SMarcel Holtmann break; 1986a9de9248SMarcel Holtmann 1987a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 1988a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 1989a9de9248SMarcel Holtmann break; 1990a9de9248SMarcel Holtmann 1991a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 1992a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 1993a9de9248SMarcel Holtmann break; 1994a9de9248SMarcel Holtmann 1995a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 1996a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 1997a9de9248SMarcel Holtmann break; 1998a9de9248SMarcel Holtmann 1999a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 2000a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 2001a9de9248SMarcel Holtmann break; 2002a9de9248SMarcel Holtmann 2003a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 2004a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 2005a9de9248SMarcel Holtmann break; 2006a9de9248SMarcel Holtmann 2007a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 2008a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 2009a9de9248SMarcel Holtmann break; 2010a9de9248SMarcel Holtmann 2011a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 2012a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 2013a9de9248SMarcel Holtmann break; 2014a9de9248SMarcel Holtmann 2015a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 2016a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 2017a9de9248SMarcel Holtmann break; 2018a9de9248SMarcel Holtmann 2019a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 2020a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 2021a9de9248SMarcel Holtmann break; 2022a9de9248SMarcel Holtmann 2023a9de9248SMarcel Holtmann case HCI_OP_HOST_BUFFER_SIZE: 2024a9de9248SMarcel Holtmann hci_cc_host_buffer_size(hdev, skb); 2025a9de9248SMarcel Holtmann break; 2026a9de9248SMarcel Holtmann 2027333140b5SMarcel Holtmann case HCI_OP_READ_SSP_MODE: 2028333140b5SMarcel Holtmann hci_cc_read_ssp_mode(hdev, skb); 2029333140b5SMarcel Holtmann break; 2030333140b5SMarcel Holtmann 2031333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 2032333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 2033333140b5SMarcel Holtmann break; 2034333140b5SMarcel Holtmann 2035a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 2036a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 2037a9de9248SMarcel Holtmann break; 2038a9de9248SMarcel Holtmann 2039a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 2040a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 2041a9de9248SMarcel Holtmann break; 2042a9de9248SMarcel Holtmann 2043a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 2044a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 2045a9de9248SMarcel Holtmann break; 2046a9de9248SMarcel Holtmann 2047971e3a4bSAndre Guedes case HCI_OP_READ_LOCAL_EXT_FEATURES: 2048971e3a4bSAndre Guedes hci_cc_read_local_ext_features(hdev, skb); 2049971e3a4bSAndre Guedes break; 2050971e3a4bSAndre Guedes 2051a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 2052a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 2053a9de9248SMarcel Holtmann break; 2054a9de9248SMarcel Holtmann 2055a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 2056a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 2057a9de9248SMarcel Holtmann break; 2058a9de9248SMarcel Holtmann 2059350ee4cfSAndrei Emeltchenko case HCI_OP_READ_DATA_BLOCK_SIZE: 2060350ee4cfSAndrei Emeltchenko hci_cc_read_data_block_size(hdev, skb); 2061350ee4cfSAndrei Emeltchenko break; 2062350ee4cfSAndrei Emeltchenko 206323bb5763SJohan Hedberg case HCI_OP_WRITE_CA_TIMEOUT: 206423bb5763SJohan Hedberg hci_cc_write_ca_timeout(hdev, skb); 206523bb5763SJohan Hedberg break; 206623bb5763SJohan Hedberg 20671e89cffbSAndrei Emeltchenko case HCI_OP_READ_FLOW_CONTROL_MODE: 20681e89cffbSAndrei Emeltchenko hci_cc_read_flow_control_mode(hdev, skb); 20691e89cffbSAndrei Emeltchenko break; 20701e89cffbSAndrei Emeltchenko 2071928abaa7SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_INFO: 2072928abaa7SAndrei Emeltchenko hci_cc_read_local_amp_info(hdev, skb); 2073928abaa7SAndrei Emeltchenko break; 2074928abaa7SAndrei Emeltchenko 2075b0916ea0SJohan Hedberg case HCI_OP_DELETE_STORED_LINK_KEY: 2076b0916ea0SJohan Hedberg hci_cc_delete_stored_link_key(hdev, skb); 2077b0916ea0SJohan Hedberg break; 2078b0916ea0SJohan Hedberg 2079d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_MASK: 2080d5859e22SJohan Hedberg hci_cc_set_event_mask(hdev, skb); 2081d5859e22SJohan Hedberg break; 2082d5859e22SJohan Hedberg 2083d5859e22SJohan Hedberg case HCI_OP_WRITE_INQUIRY_MODE: 2084d5859e22SJohan Hedberg hci_cc_write_inquiry_mode(hdev, skb); 2085d5859e22SJohan Hedberg break; 2086d5859e22SJohan Hedberg 2087d5859e22SJohan Hedberg case HCI_OP_READ_INQ_RSP_TX_POWER: 2088d5859e22SJohan Hedberg hci_cc_read_inq_rsp_tx_power(hdev, skb); 2089d5859e22SJohan Hedberg break; 2090d5859e22SJohan Hedberg 2091d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_FLT: 2092d5859e22SJohan Hedberg hci_cc_set_event_flt(hdev, skb); 2093d5859e22SJohan Hedberg break; 2094d5859e22SJohan Hedberg 2095980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_REPLY: 2096980e1a53SJohan Hedberg hci_cc_pin_code_reply(hdev, skb); 2097980e1a53SJohan Hedberg break; 2098980e1a53SJohan Hedberg 2099980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_NEG_REPLY: 2100980e1a53SJohan Hedberg hci_cc_pin_code_neg_reply(hdev, skb); 2101980e1a53SJohan Hedberg break; 2102980e1a53SJohan Hedberg 2103c35938b2SSzymon Janc case HCI_OP_READ_LOCAL_OOB_DATA: 2104c35938b2SSzymon Janc hci_cc_read_local_oob_data_reply(hdev, skb); 2105c35938b2SSzymon Janc break; 2106c35938b2SSzymon Janc 21076ed58ec5SVille Tervo case HCI_OP_LE_READ_BUFFER_SIZE: 21086ed58ec5SVille Tervo hci_cc_le_read_buffer_size(hdev, skb); 21096ed58ec5SVille Tervo break; 21106ed58ec5SVille Tervo 2111a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_REPLY: 2112a5c29683SJohan Hedberg hci_cc_user_confirm_reply(hdev, skb); 2113a5c29683SJohan Hedberg break; 2114a5c29683SJohan Hedberg 2115a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_NEG_REPLY: 2116a5c29683SJohan Hedberg hci_cc_user_confirm_neg_reply(hdev, skb); 2117a5c29683SJohan Hedberg break; 2118a5c29683SJohan Hedberg 21191143d458SBrian Gix case HCI_OP_USER_PASSKEY_REPLY: 21201143d458SBrian Gix hci_cc_user_passkey_reply(hdev, skb); 21211143d458SBrian Gix break; 21221143d458SBrian Gix 21231143d458SBrian Gix case HCI_OP_USER_PASSKEY_NEG_REPLY: 21241143d458SBrian Gix hci_cc_user_passkey_neg_reply(hdev, skb); 212507f7fa5dSAndre Guedes 212607f7fa5dSAndre Guedes case HCI_OP_LE_SET_SCAN_PARAM: 212707f7fa5dSAndre Guedes hci_cc_le_set_scan_param(hdev, skb); 21281143d458SBrian Gix break; 21291143d458SBrian Gix 2130eb9d91f5SAndre Guedes case HCI_OP_LE_SET_SCAN_ENABLE: 2131eb9d91f5SAndre Guedes hci_cc_le_set_scan_enable(hdev, skb); 2132eb9d91f5SAndre Guedes break; 2133eb9d91f5SAndre Guedes 2134a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_REPLY: 2135a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_reply(hdev, skb); 2136a7a595f6SVinicius Costa Gomes break; 2137a7a595f6SVinicius Costa Gomes 2138a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_NEG_REPLY: 2139a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_neg_reply(hdev, skb); 2140a7a595f6SVinicius Costa Gomes break; 2141a7a595f6SVinicius Costa Gomes 2142f9b49306SAndre Guedes case HCI_OP_WRITE_LE_HOST_SUPPORTED: 2143f9b49306SAndre Guedes hci_cc_write_le_host_supported(hdev, skb); 2144f9b49306SAndre Guedes break; 2145f9b49306SAndre Guedes 2146a9de9248SMarcel Holtmann default: 2147a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 2148a9de9248SMarcel Holtmann break; 2149a9de9248SMarcel Holtmann } 2150a9de9248SMarcel Holtmann 21516bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 21526bd32326SVille Tervo del_timer(&hdev->cmd_timer); 21536bd32326SVille Tervo 2154a9de9248SMarcel Holtmann if (ev->ncmd) { 2155a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2156a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2157c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2158a9de9248SMarcel Holtmann } 2159a9de9248SMarcel Holtmann } 2160a9de9248SMarcel Holtmann 2161a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 2162a9de9248SMarcel Holtmann { 2163a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 2164a9de9248SMarcel Holtmann __u16 opcode; 2165a9de9248SMarcel Holtmann 2166a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2167a9de9248SMarcel Holtmann 2168a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2169a9de9248SMarcel Holtmann 2170a9de9248SMarcel Holtmann switch (opcode) { 2171a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 2172a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 2173a9de9248SMarcel Holtmann break; 2174a9de9248SMarcel Holtmann 2175a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 2176a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 2177a9de9248SMarcel Holtmann break; 2178a9de9248SMarcel Holtmann 2179a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 2180a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 2181a9de9248SMarcel Holtmann break; 2182a9de9248SMarcel Holtmann 2183f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 2184f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 2185f8558555SMarcel Holtmann break; 2186f8558555SMarcel Holtmann 2187f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 2188f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 2189f8558555SMarcel Holtmann break; 2190f8558555SMarcel Holtmann 2191a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 2192a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 2193a9de9248SMarcel Holtmann break; 2194a9de9248SMarcel Holtmann 2195769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 2196769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 2197769be974SMarcel Holtmann break; 2198769be974SMarcel Holtmann 2199769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 2200769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 2201769be974SMarcel Holtmann break; 2202769be974SMarcel Holtmann 2203a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 2204a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 2205a9de9248SMarcel Holtmann break; 2206a9de9248SMarcel Holtmann 2207a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 2208a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 2209a9de9248SMarcel Holtmann break; 2210a9de9248SMarcel Holtmann 2211a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 2212a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 2213a9de9248SMarcel Holtmann break; 2214a9de9248SMarcel Holtmann 22158962ee74SJohan Hedberg case HCI_OP_DISCONNECT: 22168962ee74SJohan Hedberg if (ev->status != 0) 221737d9ef76SJohan Hedberg mgmt_disconnect_failed(hdev, NULL, ev->status); 22188962ee74SJohan Hedberg break; 22198962ee74SJohan Hedberg 2220fcd89c09SVille Tervo case HCI_OP_LE_CREATE_CONN: 2221fcd89c09SVille Tervo hci_cs_le_create_conn(hdev, ev->status); 2222fcd89c09SVille Tervo break; 2223fcd89c09SVille Tervo 2224a7a595f6SVinicius Costa Gomes case HCI_OP_LE_START_ENC: 2225a7a595f6SVinicius Costa Gomes hci_cs_le_start_enc(hdev, ev->status); 2226a7a595f6SVinicius Costa Gomes break; 2227a7a595f6SVinicius Costa Gomes 2228a9de9248SMarcel Holtmann default: 2229a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 2230a9de9248SMarcel Holtmann break; 2231a9de9248SMarcel Holtmann } 2232a9de9248SMarcel Holtmann 22336bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 22346bd32326SVille Tervo del_timer(&hdev->cmd_timer); 22356bd32326SVille Tervo 223610572132SGustavo F. Padovan if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2237a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2238a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2239c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2240a9de9248SMarcel Holtmann } 2241a9de9248SMarcel Holtmann } 2242a9de9248SMarcel Holtmann 2243a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2244a9de9248SMarcel Holtmann { 2245a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 2246a9de9248SMarcel Holtmann struct hci_conn *conn; 2247a9de9248SMarcel Holtmann 2248a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2249a9de9248SMarcel Holtmann 2250a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2251a9de9248SMarcel Holtmann 2252a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2253a9de9248SMarcel Holtmann if (conn) { 2254a9de9248SMarcel Holtmann if (!ev->status) { 2255a9de9248SMarcel Holtmann if (ev->role) 2256a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_MASTER; 2257a9de9248SMarcel Holtmann else 2258a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_MASTER; 2259a9de9248SMarcel Holtmann } 2260a9de9248SMarcel Holtmann 2261a9de9248SMarcel Holtmann clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend); 2262a9de9248SMarcel Holtmann 2263a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 2264a9de9248SMarcel Holtmann } 2265a9de9248SMarcel Holtmann 2266a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2267a9de9248SMarcel Holtmann } 2268a9de9248SMarcel Holtmann 22691da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 22701da177e4SLinus Torvalds { 2271a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 22721da177e4SLinus Torvalds int i; 22731da177e4SLinus Torvalds 227432ac5b9bSAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) { 227532ac5b9bSAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 227632ac5b9bSAndrei Emeltchenko return; 227732ac5b9bSAndrei Emeltchenko } 227832ac5b9bSAndrei Emeltchenko 2279c5993de8SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 2280c5993de8SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_pkts_info)) { 22811da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 22821da177e4SLinus Torvalds return; 22831da177e4SLinus Torvalds } 22841da177e4SLinus Torvalds 2285c5993de8SAndrei Emeltchenko BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 2286c5993de8SAndrei Emeltchenko 2287613a1c0cSAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 2288613a1c0cSAndrei Emeltchenko struct hci_comp_pkts_info *info = &ev->handles[i]; 22891da177e4SLinus Torvalds struct hci_conn *conn; 22901da177e4SLinus Torvalds __u16 handle, count; 22911da177e4SLinus Torvalds 2292613a1c0cSAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 2293613a1c0cSAndrei Emeltchenko count = __le16_to_cpu(info->count); 22941da177e4SLinus Torvalds 22951da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 2296f4280918SAndrei Emeltchenko if (!conn) 2297f4280918SAndrei Emeltchenko continue; 2298f4280918SAndrei Emeltchenko 22991da177e4SLinus Torvalds conn->sent -= count; 23001da177e4SLinus Torvalds 2301f4280918SAndrei Emeltchenko switch (conn->type) { 2302f4280918SAndrei Emeltchenko case ACL_LINK: 230370f23020SAndrei Emeltchenko hdev->acl_cnt += count; 230470f23020SAndrei Emeltchenko if (hdev->acl_cnt > hdev->acl_pkts) 23051da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 2306f4280918SAndrei Emeltchenko break; 2307f4280918SAndrei Emeltchenko 2308f4280918SAndrei Emeltchenko case LE_LINK: 23096ed58ec5SVille Tervo if (hdev->le_pkts) { 23106ed58ec5SVille Tervo hdev->le_cnt += count; 23116ed58ec5SVille Tervo if (hdev->le_cnt > hdev->le_pkts) 23126ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 23136ed58ec5SVille Tervo } else { 23146ed58ec5SVille Tervo hdev->acl_cnt += count; 23156ed58ec5SVille Tervo if (hdev->acl_cnt > hdev->acl_pkts) 23166ed58ec5SVille Tervo hdev->acl_cnt = hdev->acl_pkts; 23176ed58ec5SVille Tervo } 2318f4280918SAndrei Emeltchenko break; 2319f4280918SAndrei Emeltchenko 2320f4280918SAndrei Emeltchenko case SCO_LINK: 232170f23020SAndrei Emeltchenko hdev->sco_cnt += count; 232270f23020SAndrei Emeltchenko if (hdev->sco_cnt > hdev->sco_pkts) 23235b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 2324f4280918SAndrei Emeltchenko break; 2325f4280918SAndrei Emeltchenko 2326f4280918SAndrei Emeltchenko default: 2327f4280918SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 2328f4280918SAndrei Emeltchenko break; 23291da177e4SLinus Torvalds } 23301da177e4SLinus Torvalds } 2331a9de9248SMarcel Holtmann 23323eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 23331da177e4SLinus Torvalds } 23341da177e4SLinus Torvalds 233504837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 23361da177e4SLinus Torvalds { 2337a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 233804837f64SMarcel Holtmann struct hci_conn *conn; 23391da177e4SLinus Torvalds 23401da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 23411da177e4SLinus Torvalds 23421da177e4SLinus Torvalds hci_dev_lock(hdev); 23431da177e4SLinus Torvalds 234404837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 234504837f64SMarcel Holtmann if (conn) { 234604837f64SMarcel Holtmann conn->mode = ev->mode; 234704837f64SMarcel Holtmann conn->interval = __le16_to_cpu(ev->interval); 234804837f64SMarcel Holtmann 234904837f64SMarcel Holtmann if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) { 235004837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 235104837f64SMarcel Holtmann conn->power_save = 1; 235204837f64SMarcel Holtmann else 235304837f64SMarcel Holtmann conn->power_save = 0; 235404837f64SMarcel Holtmann } 2355e73439d8SMarcel Holtmann 2356e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 2357e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 235804837f64SMarcel Holtmann } 235904837f64SMarcel Holtmann 236004837f64SMarcel Holtmann hci_dev_unlock(hdev); 236104837f64SMarcel Holtmann } 236204837f64SMarcel Holtmann 23631da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 23641da177e4SLinus Torvalds { 2365052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 2366052b30b0SMarcel Holtmann struct hci_conn *conn; 2367052b30b0SMarcel Holtmann 2368a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2369052b30b0SMarcel Holtmann 2370052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2371052b30b0SMarcel Holtmann 2372052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2373b6f98044SWaldemar Rymarkiewicz if (!conn) 2374b6f98044SWaldemar Rymarkiewicz goto unlock; 2375b6f98044SWaldemar Rymarkiewicz 2376b6f98044SWaldemar Rymarkiewicz if (conn->state == BT_CONNECTED) { 2377052b30b0SMarcel Holtmann hci_conn_hold(conn); 2378052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 2379052b30b0SMarcel Holtmann hci_conn_put(conn); 2380052b30b0SMarcel Holtmann } 2381052b30b0SMarcel Holtmann 238203b555e1SJohan Hedberg if (!test_bit(HCI_PAIRABLE, &hdev->flags)) 238303b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 238403b555e1SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 2385582fbe9eSJohan Hedberg else if (test_bit(HCI_MGMT, &hdev->flags)) { 2386a770bb5aSWaldemar Rymarkiewicz u8 secure; 2387a770bb5aSWaldemar Rymarkiewicz 2388a770bb5aSWaldemar Rymarkiewicz if (conn->pending_sec_level == BT_SECURITY_HIGH) 2389a770bb5aSWaldemar Rymarkiewicz secure = 1; 2390a770bb5aSWaldemar Rymarkiewicz else 2391a770bb5aSWaldemar Rymarkiewicz secure = 0; 2392a770bb5aSWaldemar Rymarkiewicz 2393744cf19eSJohan Hedberg mgmt_pin_code_request(hdev, &ev->bdaddr, secure); 2394a770bb5aSWaldemar Rymarkiewicz } 2395980e1a53SJohan Hedberg 2396b6f98044SWaldemar Rymarkiewicz unlock: 2397052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 23981da177e4SLinus Torvalds } 23991da177e4SLinus Torvalds 24001da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 24011da177e4SLinus Torvalds { 240255ed8ca1SJohan Hedberg struct hci_ev_link_key_req *ev = (void *) skb->data; 240355ed8ca1SJohan Hedberg struct hci_cp_link_key_reply cp; 240455ed8ca1SJohan Hedberg struct hci_conn *conn; 240555ed8ca1SJohan Hedberg struct link_key *key; 240655ed8ca1SJohan Hedberg 2407a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 240855ed8ca1SJohan Hedberg 240955ed8ca1SJohan Hedberg if (!test_bit(HCI_LINK_KEYS, &hdev->flags)) 241055ed8ca1SJohan Hedberg return; 241155ed8ca1SJohan Hedberg 241255ed8ca1SJohan Hedberg hci_dev_lock(hdev); 241355ed8ca1SJohan Hedberg 241455ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, &ev->bdaddr); 241555ed8ca1SJohan Hedberg if (!key) { 241655ed8ca1SJohan Hedberg BT_DBG("%s link key not found for %s", hdev->name, 241755ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 241855ed8ca1SJohan Hedberg goto not_found; 241955ed8ca1SJohan Hedberg } 242055ed8ca1SJohan Hedberg 242155ed8ca1SJohan Hedberg BT_DBG("%s found key type %u for %s", hdev->name, key->type, 242255ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 242355ed8ca1SJohan Hedberg 2424b6020ba0SWaldemar Rymarkiewicz if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) && 2425b6020ba0SWaldemar Rymarkiewicz key->type == HCI_LK_DEBUG_COMBINATION) { 242655ed8ca1SJohan Hedberg BT_DBG("%s ignoring debug key", hdev->name); 242755ed8ca1SJohan Hedberg goto not_found; 242855ed8ca1SJohan Hedberg } 242955ed8ca1SJohan Hedberg 243055ed8ca1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 243160b83f57SWaldemar Rymarkiewicz if (conn) { 243260b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_UNAUTH_COMBINATION && 243360b83f57SWaldemar Rymarkiewicz conn->auth_type != 0xff && 243460b83f57SWaldemar Rymarkiewicz (conn->auth_type & 0x01)) { 243555ed8ca1SJohan Hedberg BT_DBG("%s ignoring unauthenticated key", hdev->name); 243655ed8ca1SJohan Hedberg goto not_found; 243755ed8ca1SJohan Hedberg } 243855ed8ca1SJohan Hedberg 243960b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && 244060b83f57SWaldemar Rymarkiewicz conn->pending_sec_level == BT_SECURITY_HIGH) { 244160b83f57SWaldemar Rymarkiewicz BT_DBG("%s ignoring key unauthenticated for high \ 244260b83f57SWaldemar Rymarkiewicz security", hdev->name); 244360b83f57SWaldemar Rymarkiewicz goto not_found; 244460b83f57SWaldemar Rymarkiewicz } 244560b83f57SWaldemar Rymarkiewicz 244660b83f57SWaldemar Rymarkiewicz conn->key_type = key->type; 244760b83f57SWaldemar Rymarkiewicz conn->pin_length = key->pin_len; 244860b83f57SWaldemar Rymarkiewicz } 244960b83f57SWaldemar Rymarkiewicz 245055ed8ca1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 245155ed8ca1SJohan Hedberg memcpy(cp.link_key, key->val, 16); 245255ed8ca1SJohan Hedberg 245355ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 245455ed8ca1SJohan Hedberg 245555ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 245655ed8ca1SJohan Hedberg 245755ed8ca1SJohan Hedberg return; 245855ed8ca1SJohan Hedberg 245955ed8ca1SJohan Hedberg not_found: 246055ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 246155ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 24621da177e4SLinus Torvalds } 24631da177e4SLinus Torvalds 24641da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 24651da177e4SLinus Torvalds { 2466052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 2467052b30b0SMarcel Holtmann struct hci_conn *conn; 246855ed8ca1SJohan Hedberg u8 pin_len = 0; 2469052b30b0SMarcel Holtmann 2470a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2471052b30b0SMarcel Holtmann 2472052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2473052b30b0SMarcel Holtmann 2474052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2475052b30b0SMarcel Holtmann if (conn) { 2476052b30b0SMarcel Holtmann hci_conn_hold(conn); 2477052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2478980e1a53SJohan Hedberg pin_len = conn->pin_length; 247913d39315SWaldemar Rymarkiewicz 248013d39315SWaldemar Rymarkiewicz if (ev->key_type != HCI_LK_CHANGED_COMBINATION) 248113d39315SWaldemar Rymarkiewicz conn->key_type = ev->key_type; 248213d39315SWaldemar Rymarkiewicz 2483052b30b0SMarcel Holtmann hci_conn_put(conn); 2484052b30b0SMarcel Holtmann } 2485052b30b0SMarcel Holtmann 248655ed8ca1SJohan Hedberg if (test_bit(HCI_LINK_KEYS, &hdev->flags)) 2487d25e28abSJohan Hedberg hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, 248855ed8ca1SJohan Hedberg ev->key_type, pin_len); 248955ed8ca1SJohan Hedberg 2490052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 24911da177e4SLinus Torvalds } 24921da177e4SLinus Torvalds 249304837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 249404837f64SMarcel Holtmann { 2495a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 249604837f64SMarcel Holtmann struct hci_conn *conn; 249704837f64SMarcel Holtmann 249804837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 249904837f64SMarcel Holtmann 250004837f64SMarcel Holtmann hci_dev_lock(hdev); 250104837f64SMarcel Holtmann 250204837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 25031da177e4SLinus Torvalds if (conn && !ev->status) { 25041da177e4SLinus Torvalds struct inquiry_entry *ie; 25051da177e4SLinus Torvalds 2506cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2507cc11b9c1SAndrei Emeltchenko if (ie) { 25081da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 25091da177e4SLinus Torvalds ie->timestamp = jiffies; 25101da177e4SLinus Torvalds } 25111da177e4SLinus Torvalds } 25121da177e4SLinus Torvalds 25131da177e4SLinus Torvalds hci_dev_unlock(hdev); 25141da177e4SLinus Torvalds } 25151da177e4SLinus Torvalds 2516a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2517a8746417SMarcel Holtmann { 2518a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 2519a8746417SMarcel Holtmann struct hci_conn *conn; 2520a8746417SMarcel Holtmann 2521a8746417SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2522a8746417SMarcel Holtmann 2523a8746417SMarcel Holtmann hci_dev_lock(hdev); 2524a8746417SMarcel Holtmann 2525a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2526a8746417SMarcel Holtmann if (conn && !ev->status) 2527a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 2528a8746417SMarcel Holtmann 2529a8746417SMarcel Holtmann hci_dev_unlock(hdev); 2530a8746417SMarcel Holtmann } 2531a8746417SMarcel Holtmann 253285a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 253385a1e930SMarcel Holtmann { 2534a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 253585a1e930SMarcel Holtmann struct inquiry_entry *ie; 253685a1e930SMarcel Holtmann 253785a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 253885a1e930SMarcel Holtmann 253985a1e930SMarcel Holtmann hci_dev_lock(hdev); 254085a1e930SMarcel Holtmann 2541cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2542cc11b9c1SAndrei Emeltchenko if (ie) { 254385a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 254485a1e930SMarcel Holtmann ie->timestamp = jiffies; 254585a1e930SMarcel Holtmann } 254685a1e930SMarcel Holtmann 254785a1e930SMarcel Holtmann hci_dev_unlock(hdev); 254885a1e930SMarcel Holtmann } 254985a1e930SMarcel Holtmann 2550a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb) 2551a9de9248SMarcel Holtmann { 2552a9de9248SMarcel Holtmann struct inquiry_data data; 2553a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2554a9de9248SMarcel Holtmann 2555a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2556a9de9248SMarcel Holtmann 2557a9de9248SMarcel Holtmann if (!num_rsp) 2558a9de9248SMarcel Holtmann return; 2559a9de9248SMarcel Holtmann 2560a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2561a9de9248SMarcel Holtmann 2562a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 2563138d22efSSzymon Janc struct inquiry_info_with_rssi_and_pscan_mode *info; 2564138d22efSSzymon Janc info = (void *) (skb->data + 1); 2565a9de9248SMarcel Holtmann 2566e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2567a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2568a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2569a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2570a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 2571a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2572a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2573a9de9248SMarcel Holtmann data.rssi = info->rssi; 257441a96212SMarcel Holtmann data.ssp_mode = 0x00; 2575a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 257648264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2577e17acd40SJohan Hedberg info->dev_class, info->rssi, 2578e17acd40SJohan Hedberg NULL); 2579a9de9248SMarcel Holtmann } 2580a9de9248SMarcel Holtmann } else { 2581a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 2582a9de9248SMarcel Holtmann 2583e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2584a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2585a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2586a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2587a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2588a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2589a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2590a9de9248SMarcel Holtmann data.rssi = info->rssi; 259141a96212SMarcel Holtmann data.ssp_mode = 0x00; 2592a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 259348264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2594e17acd40SJohan Hedberg info->dev_class, info->rssi, 2595e17acd40SJohan Hedberg NULL); 2596a9de9248SMarcel Holtmann } 2597a9de9248SMarcel Holtmann } 2598a9de9248SMarcel Holtmann 2599a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2600a9de9248SMarcel Holtmann } 2601a9de9248SMarcel Holtmann 2602a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 2603a9de9248SMarcel Holtmann { 260441a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 260541a96212SMarcel Holtmann struct hci_conn *conn; 260641a96212SMarcel Holtmann 2607a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 260841a96212SMarcel Holtmann 260941a96212SMarcel Holtmann hci_dev_lock(hdev); 261041a96212SMarcel Holtmann 261141a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2612ccd556feSJohan Hedberg if (!conn) 2613ccd556feSJohan Hedberg goto unlock; 2614ccd556feSJohan Hedberg 2615769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 261641a96212SMarcel Holtmann struct inquiry_entry *ie; 261741a96212SMarcel Holtmann 2618cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2619cc11b9c1SAndrei Emeltchenko if (ie) 262041a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 262141a96212SMarcel Holtmann 262241a96212SMarcel Holtmann conn->ssp_mode = (ev->features[0] & 0x01); 262341a96212SMarcel Holtmann } 262441a96212SMarcel Holtmann 2625ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2626ccd556feSJohan Hedberg goto unlock; 2627ccd556feSJohan Hedberg 2628127178d2SJohan Hedberg if (!ev->status) { 2629127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2630127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2631127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2632127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2633127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2634127178d2SJohan Hedberg } 2635392599b9SJohan Hedberg 2636127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2637769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2638769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2639769be974SMarcel Holtmann hci_conn_put(conn); 2640769be974SMarcel Holtmann } 2641769be974SMarcel Holtmann 2642ccd556feSJohan Hedberg unlock: 264341a96212SMarcel Holtmann hci_dev_unlock(hdev); 2644a9de9248SMarcel Holtmann } 2645a9de9248SMarcel Holtmann 2646a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2647a9de9248SMarcel Holtmann { 2648b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 2649b6a0dc82SMarcel Holtmann struct hci_conn *conn; 2650b6a0dc82SMarcel Holtmann 2651b6a0dc82SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2652b6a0dc82SMarcel Holtmann 2653b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 2654b6a0dc82SMarcel Holtmann 2655b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 26569dc0a3afSMarcel Holtmann if (!conn) { 26579dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 26589dc0a3afSMarcel Holtmann goto unlock; 26599dc0a3afSMarcel Holtmann 26609dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 2661b6a0dc82SMarcel Holtmann if (!conn) 2662b6a0dc82SMarcel Holtmann goto unlock; 2663b6a0dc82SMarcel Holtmann 26649dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 26659dc0a3afSMarcel Holtmann } 26669dc0a3afSMarcel Holtmann 2667732547f9SMarcel Holtmann switch (ev->status) { 2668732547f9SMarcel Holtmann case 0x00: 2669732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 2670732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 2671732547f9SMarcel Holtmann 26729eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 2673732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 2674732547f9SMarcel Holtmann break; 2675732547f9SMarcel Holtmann 2676705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 2677732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 26781038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 2679732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 2680732547f9SMarcel Holtmann if (conn->out && conn->attempt < 2) { 2681efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 2682efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 2683efc7688bSMarcel Holtmann hci_setup_sync(conn, conn->link->handle); 2684efc7688bSMarcel Holtmann goto unlock; 2685efc7688bSMarcel Holtmann } 2686732547f9SMarcel Holtmann /* fall through */ 2687efc7688bSMarcel Holtmann 2688732547f9SMarcel Holtmann default: 2689b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 2690732547f9SMarcel Holtmann break; 2691732547f9SMarcel Holtmann } 2692b6a0dc82SMarcel Holtmann 2693b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2694b6a0dc82SMarcel Holtmann if (ev->status) 2695b6a0dc82SMarcel Holtmann hci_conn_del(conn); 2696b6a0dc82SMarcel Holtmann 2697b6a0dc82SMarcel Holtmann unlock: 2698b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 2699a9de9248SMarcel Holtmann } 2700a9de9248SMarcel Holtmann 2701a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) 2702a9de9248SMarcel Holtmann { 2703a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2704a9de9248SMarcel Holtmann } 2705a9de9248SMarcel Holtmann 270604837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) 270704837f64SMarcel Holtmann { 2708a9de9248SMarcel Holtmann struct hci_ev_sniff_subrate *ev = (void *) skb->data; 270904837f64SMarcel Holtmann 271004837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 271104837f64SMarcel Holtmann } 271204837f64SMarcel Holtmann 2713a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 2714a9de9248SMarcel Holtmann { 2715a9de9248SMarcel Holtmann struct inquiry_data data; 2716a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 2717a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2718a9de9248SMarcel Holtmann 2719a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2720a9de9248SMarcel Holtmann 2721a9de9248SMarcel Holtmann if (!num_rsp) 2722a9de9248SMarcel Holtmann return; 2723a9de9248SMarcel Holtmann 2724a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2725a9de9248SMarcel Holtmann 2726e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2727a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2728a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2729a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2730a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2731a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2732a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2733a9de9248SMarcel Holtmann data.rssi = info->rssi; 273441a96212SMarcel Holtmann data.ssp_mode = 0x01; 2735a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 273648264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 27374c659c39SJohan Hedberg info->dev_class, info->rssi, info->data); 2738a9de9248SMarcel Holtmann } 2739a9de9248SMarcel Holtmann 2740a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2741a9de9248SMarcel Holtmann } 2742a9de9248SMarcel Holtmann 274317fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn) 274417fa4b9dSJohan Hedberg { 274517fa4b9dSJohan Hedberg /* If remote requests dedicated bonding follow that lead */ 274617fa4b9dSJohan Hedberg if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) { 274717fa4b9dSJohan Hedberg /* If both remote and local IO capabilities allow MITM 274817fa4b9dSJohan Hedberg * protection then require it, otherwise don't */ 274917fa4b9dSJohan Hedberg if (conn->remote_cap == 0x03 || conn->io_capability == 0x03) 275017fa4b9dSJohan Hedberg return 0x02; 275117fa4b9dSJohan Hedberg else 275217fa4b9dSJohan Hedberg return 0x03; 275317fa4b9dSJohan Hedberg } 275417fa4b9dSJohan Hedberg 275517fa4b9dSJohan Hedberg /* If remote requests no-bonding follow that lead */ 275617fa4b9dSJohan Hedberg if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01) 275758797bf7SWaldemar Rymarkiewicz return conn->remote_auth | (conn->auth_type & 0x01); 275817fa4b9dSJohan Hedberg 275917fa4b9dSJohan Hedberg return conn->auth_type; 276017fa4b9dSJohan Hedberg } 276117fa4b9dSJohan Hedberg 27620493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 27630493684eSMarcel Holtmann { 27640493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 27650493684eSMarcel Holtmann struct hci_conn *conn; 27660493684eSMarcel Holtmann 27670493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 27680493684eSMarcel Holtmann 27690493684eSMarcel Holtmann hci_dev_lock(hdev); 27700493684eSMarcel Holtmann 27710493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 277203b555e1SJohan Hedberg if (!conn) 277303b555e1SJohan Hedberg goto unlock; 277403b555e1SJohan Hedberg 27750493684eSMarcel Holtmann hci_conn_hold(conn); 27760493684eSMarcel Holtmann 277703b555e1SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->flags)) 277803b555e1SJohan Hedberg goto unlock; 277903b555e1SJohan Hedberg 278003b555e1SJohan Hedberg if (test_bit(HCI_PAIRABLE, &hdev->flags) || 278103b555e1SJohan Hedberg (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 278217fa4b9dSJohan Hedberg struct hci_cp_io_capability_reply cp; 278317fa4b9dSJohan Hedberg 278417fa4b9dSJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 278517fa4b9dSJohan Hedberg cp.capability = conn->io_capability; 27867cbc9bd9SJohan Hedberg conn->auth_type = hci_get_auth_req(conn); 27877cbc9bd9SJohan Hedberg cp.authentication = conn->auth_type; 278817fa4b9dSJohan Hedberg 2789ce85ee13SSzymon Janc if ((conn->out == 0x01 || conn->remote_oob == 0x01) && 2790ce85ee13SSzymon Janc hci_find_remote_oob_data(hdev, &conn->dst)) 2791ce85ee13SSzymon Janc cp.oob_data = 0x01; 2792ce85ee13SSzymon Janc else 2793ce85ee13SSzymon Janc cp.oob_data = 0x00; 2794ce85ee13SSzymon Janc 279517fa4b9dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, 279617fa4b9dSJohan Hedberg sizeof(cp), &cp); 279703b555e1SJohan Hedberg } else { 279803b555e1SJohan Hedberg struct hci_cp_io_capability_neg_reply cp; 279903b555e1SJohan Hedberg 280003b555e1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 28019f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED; 280203b555e1SJohan Hedberg 280303b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 280403b555e1SJohan Hedberg sizeof(cp), &cp); 280503b555e1SJohan Hedberg } 280603b555e1SJohan Hedberg 280703b555e1SJohan Hedberg unlock: 280803b555e1SJohan Hedberg hci_dev_unlock(hdev); 280903b555e1SJohan Hedberg } 281003b555e1SJohan Hedberg 281103b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 281203b555e1SJohan Hedberg { 281303b555e1SJohan Hedberg struct hci_ev_io_capa_reply *ev = (void *) skb->data; 281403b555e1SJohan Hedberg struct hci_conn *conn; 281503b555e1SJohan Hedberg 281603b555e1SJohan Hedberg BT_DBG("%s", hdev->name); 281703b555e1SJohan Hedberg 281803b555e1SJohan Hedberg hci_dev_lock(hdev); 281903b555e1SJohan Hedberg 282003b555e1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 282103b555e1SJohan Hedberg if (!conn) 282203b555e1SJohan Hedberg goto unlock; 282303b555e1SJohan Hedberg 282403b555e1SJohan Hedberg conn->remote_cap = ev->capability; 282503b555e1SJohan Hedberg conn->remote_oob = ev->oob_data; 282603b555e1SJohan Hedberg conn->remote_auth = ev->authentication; 282703b555e1SJohan Hedberg 282803b555e1SJohan Hedberg unlock: 28290493684eSMarcel Holtmann hci_dev_unlock(hdev); 28300493684eSMarcel Holtmann } 28310493684eSMarcel Holtmann 2832a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev, 2833a5c29683SJohan Hedberg struct sk_buff *skb) 2834a5c29683SJohan Hedberg { 2835a5c29683SJohan Hedberg struct hci_ev_user_confirm_req *ev = (void *) skb->data; 283655bc1a37SJohan Hedberg int loc_mitm, rem_mitm, confirm_hint = 0; 28377a828908SJohan Hedberg struct hci_conn *conn; 2838a5c29683SJohan Hedberg 2839a5c29683SJohan Hedberg BT_DBG("%s", hdev->name); 2840a5c29683SJohan Hedberg 2841a5c29683SJohan Hedberg hci_dev_lock(hdev); 2842a5c29683SJohan Hedberg 28437a828908SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->flags)) 28447a828908SJohan Hedberg goto unlock; 28457a828908SJohan Hedberg 28467a828908SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 28477a828908SJohan Hedberg if (!conn) 28487a828908SJohan Hedberg goto unlock; 28497a828908SJohan Hedberg 28507a828908SJohan Hedberg loc_mitm = (conn->auth_type & 0x01); 28517a828908SJohan Hedberg rem_mitm = (conn->remote_auth & 0x01); 28527a828908SJohan Hedberg 28537a828908SJohan Hedberg /* If we require MITM but the remote device can't provide that 28547a828908SJohan Hedberg * (it has NoInputNoOutput) then reject the confirmation 28557a828908SJohan Hedberg * request. The only exception is when we're dedicated bonding 28567a828908SJohan Hedberg * initiators (connect_cfm_cb set) since then we always have the MITM 28577a828908SJohan Hedberg * bit set. */ 28587a828908SJohan Hedberg if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) { 28597a828908SJohan Hedberg BT_DBG("Rejecting request: remote device can't provide MITM"); 28607a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, 28617a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 28627a828908SJohan Hedberg goto unlock; 28637a828908SJohan Hedberg } 28647a828908SJohan Hedberg 28657a828908SJohan Hedberg /* If no side requires MITM protection; auto-accept */ 28667a828908SJohan Hedberg if ((!loc_mitm || conn->remote_cap == 0x03) && 28677a828908SJohan Hedberg (!rem_mitm || conn->io_capability == 0x03)) { 286855bc1a37SJohan Hedberg 286955bc1a37SJohan Hedberg /* If we're not the initiators request authorization to 287055bc1a37SJohan Hedberg * proceed from user space (mgmt_user_confirm with 287155bc1a37SJohan Hedberg * confirm_hint set to 1). */ 287255bc1a37SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { 287355bc1a37SJohan Hedberg BT_DBG("Confirming auto-accept as acceptor"); 287455bc1a37SJohan Hedberg confirm_hint = 1; 287555bc1a37SJohan Hedberg goto confirm; 287655bc1a37SJohan Hedberg } 287755bc1a37SJohan Hedberg 28789f61656aSJohan Hedberg BT_DBG("Auto-accept of user confirmation with %ums delay", 28799f61656aSJohan Hedberg hdev->auto_accept_delay); 28809f61656aSJohan Hedberg 28819f61656aSJohan Hedberg if (hdev->auto_accept_delay > 0) { 28829f61656aSJohan Hedberg int delay = msecs_to_jiffies(hdev->auto_accept_delay); 28839f61656aSJohan Hedberg mod_timer(&conn->auto_accept_timer, jiffies + delay); 28849f61656aSJohan Hedberg goto unlock; 28859f61656aSJohan Hedberg } 28869f61656aSJohan Hedberg 28877a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, 28887a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 28897a828908SJohan Hedberg goto unlock; 28907a828908SJohan Hedberg } 28917a828908SJohan Hedberg 289255bc1a37SJohan Hedberg confirm: 2893744cf19eSJohan Hedberg mgmt_user_confirm_request(hdev, &ev->bdaddr, ev->passkey, 289455bc1a37SJohan Hedberg confirm_hint); 2895a5c29683SJohan Hedberg 28967a828908SJohan Hedberg unlock: 2897a5c29683SJohan Hedberg hci_dev_unlock(hdev); 2898a5c29683SJohan Hedberg } 2899a5c29683SJohan Hedberg 29001143d458SBrian Gix static inline void hci_user_passkey_request_evt(struct hci_dev *hdev, 29011143d458SBrian Gix struct sk_buff *skb) 29021143d458SBrian Gix { 29031143d458SBrian Gix struct hci_ev_user_passkey_req *ev = (void *) skb->data; 29041143d458SBrian Gix 29051143d458SBrian Gix BT_DBG("%s", hdev->name); 29061143d458SBrian Gix 29071143d458SBrian Gix hci_dev_lock(hdev); 29081143d458SBrian Gix 29091143d458SBrian Gix if (test_bit(HCI_MGMT, &hdev->flags)) 29101143d458SBrian Gix mgmt_user_passkey_request(hdev, &ev->bdaddr); 29111143d458SBrian Gix 29121143d458SBrian Gix hci_dev_unlock(hdev); 29131143d458SBrian Gix } 29141143d458SBrian Gix 29150493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 29160493684eSMarcel Holtmann { 29170493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 29180493684eSMarcel Holtmann struct hci_conn *conn; 29190493684eSMarcel Holtmann 29200493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 29210493684eSMarcel Holtmann 29220493684eSMarcel Holtmann hci_dev_lock(hdev); 29230493684eSMarcel Holtmann 29240493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 29252a611692SJohan Hedberg if (!conn) 29262a611692SJohan Hedberg goto unlock; 29272a611692SJohan Hedberg 29282a611692SJohan Hedberg /* To avoid duplicate auth_failed events to user space we check 29292a611692SJohan Hedberg * the HCI_CONN_AUTH_PEND flag which will be set if we 29302a611692SJohan Hedberg * initiated the authentication. A traditional auth_complete 29312a611692SJohan Hedberg * event gets always produced as initiator and is also mapped to 29322a611692SJohan Hedberg * the mgmt_auth_failed event */ 29332a611692SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0) 2934744cf19eSJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, ev->status); 29352a611692SJohan Hedberg 29360493684eSMarcel Holtmann hci_conn_put(conn); 29370493684eSMarcel Holtmann 29382a611692SJohan Hedberg unlock: 29390493684eSMarcel Holtmann hci_dev_unlock(hdev); 29400493684eSMarcel Holtmann } 29410493684eSMarcel Holtmann 294241a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 294341a96212SMarcel Holtmann { 294441a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 294541a96212SMarcel Holtmann struct inquiry_entry *ie; 294641a96212SMarcel Holtmann 294741a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 294841a96212SMarcel Holtmann 294941a96212SMarcel Holtmann hci_dev_lock(hdev); 295041a96212SMarcel Holtmann 2951cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2952cc11b9c1SAndrei Emeltchenko if (ie) 295341a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 295441a96212SMarcel Holtmann 295541a96212SMarcel Holtmann hci_dev_unlock(hdev); 295641a96212SMarcel Holtmann } 295741a96212SMarcel Holtmann 29582763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev, 29592763eda6SSzymon Janc struct sk_buff *skb) 29602763eda6SSzymon Janc { 29612763eda6SSzymon Janc struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; 29622763eda6SSzymon Janc struct oob_data *data; 29632763eda6SSzymon Janc 29642763eda6SSzymon Janc BT_DBG("%s", hdev->name); 29652763eda6SSzymon Janc 29662763eda6SSzymon Janc hci_dev_lock(hdev); 29672763eda6SSzymon Janc 2968e1ba1f15SSzymon Janc if (!test_bit(HCI_MGMT, &hdev->flags)) 2969e1ba1f15SSzymon Janc goto unlock; 2970e1ba1f15SSzymon Janc 29712763eda6SSzymon Janc data = hci_find_remote_oob_data(hdev, &ev->bdaddr); 29722763eda6SSzymon Janc if (data) { 29732763eda6SSzymon Janc struct hci_cp_remote_oob_data_reply cp; 29742763eda6SSzymon Janc 29752763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 29762763eda6SSzymon Janc memcpy(cp.hash, data->hash, sizeof(cp.hash)); 29772763eda6SSzymon Janc memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); 29782763eda6SSzymon Janc 29792763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), 29802763eda6SSzymon Janc &cp); 29812763eda6SSzymon Janc } else { 29822763eda6SSzymon Janc struct hci_cp_remote_oob_data_neg_reply cp; 29832763eda6SSzymon Janc 29842763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 29852763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), 29862763eda6SSzymon Janc &cp); 29872763eda6SSzymon Janc } 29882763eda6SSzymon Janc 2989e1ba1f15SSzymon Janc unlock: 29902763eda6SSzymon Janc hci_dev_unlock(hdev); 29912763eda6SSzymon Janc } 29922763eda6SSzymon Janc 2993fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2994fcd89c09SVille Tervo { 2995fcd89c09SVille Tervo struct hci_ev_le_conn_complete *ev = (void *) skb->data; 2996fcd89c09SVille Tervo struct hci_conn *conn; 2997fcd89c09SVille Tervo 2998fcd89c09SVille Tervo BT_DBG("%s status %d", hdev->name, ev->status); 2999fcd89c09SVille Tervo 3000fcd89c09SVille Tervo hci_dev_lock(hdev); 3001fcd89c09SVille Tervo 3002fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr); 3003b62f328bSVille Tervo if (!conn) { 3004b62f328bSVille Tervo conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); 3005b62f328bSVille Tervo if (!conn) { 3006b62f328bSVille Tervo BT_ERR("No memory for new connection"); 3007b62f328bSVille Tervo hci_dev_unlock(hdev); 3008b62f328bSVille Tervo return; 3009b62f328bSVille Tervo } 301029b7988aSAndre Guedes 301129b7988aSAndre Guedes conn->dst_type = ev->bdaddr_type; 3012b62f328bSVille Tervo } 3013fcd89c09SVille Tervo 3014fcd89c09SVille Tervo if (ev->status) { 301548264f06SJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 301648264f06SJohan Hedberg conn->dst_type, ev->status); 3017fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 3018fcd89c09SVille Tervo conn->state = BT_CLOSED; 3019fcd89c09SVille Tervo hci_conn_del(conn); 3020fcd89c09SVille Tervo goto unlock; 3021fcd89c09SVille Tervo } 3022fcd89c09SVille Tervo 302348264f06SJohan Hedberg mgmt_connected(hdev, &ev->bdaddr, conn->type, conn->dst_type); 302483bc71b4SVinicius Costa Gomes 30257b5c0d52SVinicius Costa Gomes conn->sec_level = BT_SECURITY_LOW; 3026fcd89c09SVille Tervo conn->handle = __le16_to_cpu(ev->handle); 3027fcd89c09SVille Tervo conn->state = BT_CONNECTED; 3028fcd89c09SVille Tervo 3029fcd89c09SVille Tervo hci_conn_hold_device(conn); 3030fcd89c09SVille Tervo hci_conn_add_sysfs(conn); 3031fcd89c09SVille Tervo 3032fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 3033fcd89c09SVille Tervo 3034fcd89c09SVille Tervo unlock: 3035fcd89c09SVille Tervo hci_dev_unlock(hdev); 3036fcd89c09SVille Tervo } 3037fcd89c09SVille Tervo 30389aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev, 30399aa04c91SAndre Guedes struct sk_buff *skb) 30409aa04c91SAndre Guedes { 3041e95beb41SAndre Guedes u8 num_reports = skb->data[0]; 3042e95beb41SAndre Guedes void *ptr = &skb->data[1]; 30439aa04c91SAndre Guedes 30449aa04c91SAndre Guedes hci_dev_lock(hdev); 30459aa04c91SAndre Guedes 3046e95beb41SAndre Guedes while (num_reports--) { 3047e95beb41SAndre Guedes struct hci_ev_le_advertising_info *ev = ptr; 3048e95beb41SAndre Guedes 30499aa04c91SAndre Guedes hci_add_adv_entry(hdev, ev); 30509aa04c91SAndre Guedes 3051e95beb41SAndre Guedes ptr += sizeof(*ev) + ev->length + 1; 30529aa04c91SAndre Guedes } 30539aa04c91SAndre Guedes 30549aa04c91SAndre Guedes hci_dev_unlock(hdev); 30559aa04c91SAndre Guedes } 30569aa04c91SAndre Guedes 3057a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev, 3058a7a595f6SVinicius Costa Gomes struct sk_buff *skb) 3059a7a595f6SVinicius Costa Gomes { 3060a7a595f6SVinicius Costa Gomes struct hci_ev_le_ltk_req *ev = (void *) skb->data; 3061a7a595f6SVinicius Costa Gomes struct hci_cp_le_ltk_reply cp; 3062bea710feSVinicius Costa Gomes struct hci_cp_le_ltk_neg_reply neg; 3063a7a595f6SVinicius Costa Gomes struct hci_conn *conn; 3064bea710feSVinicius Costa Gomes struct link_key *ltk; 3065a7a595f6SVinicius Costa Gomes 3066a7a595f6SVinicius Costa Gomes BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle)); 3067a7a595f6SVinicius Costa Gomes 3068a7a595f6SVinicius Costa Gomes hci_dev_lock(hdev); 3069a7a595f6SVinicius Costa Gomes 3070a7a595f6SVinicius Costa Gomes conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3071bea710feSVinicius Costa Gomes if (conn == NULL) 3072bea710feSVinicius Costa Gomes goto not_found; 3073a7a595f6SVinicius Costa Gomes 3074bea710feSVinicius Costa Gomes ltk = hci_find_ltk(hdev, ev->ediv, ev->random); 3075bea710feSVinicius Costa Gomes if (ltk == NULL) 3076bea710feSVinicius Costa Gomes goto not_found; 3077bea710feSVinicius Costa Gomes 3078bea710feSVinicius Costa Gomes memcpy(cp.ltk, ltk->val, sizeof(ltk->val)); 3079a7a595f6SVinicius Costa Gomes cp.handle = cpu_to_le16(conn->handle); 3080726b4ffcSVinicius Costa Gomes conn->pin_length = ltk->pin_len; 3081a7a595f6SVinicius Costa Gomes 3082a7a595f6SVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); 3083a7a595f6SVinicius Costa Gomes 3084a7a595f6SVinicius Costa Gomes hci_dev_unlock(hdev); 3085bea710feSVinicius Costa Gomes 3086bea710feSVinicius Costa Gomes return; 3087bea710feSVinicius Costa Gomes 3088bea710feSVinicius Costa Gomes not_found: 3089bea710feSVinicius Costa Gomes neg.handle = ev->handle; 3090bea710feSVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg); 3091bea710feSVinicius Costa Gomes hci_dev_unlock(hdev); 3092a7a595f6SVinicius Costa Gomes } 3093a7a595f6SVinicius Costa Gomes 3094fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 3095fcd89c09SVille Tervo { 3096fcd89c09SVille Tervo struct hci_ev_le_meta *le_ev = (void *) skb->data; 3097fcd89c09SVille Tervo 3098fcd89c09SVille Tervo skb_pull(skb, sizeof(*le_ev)); 3099fcd89c09SVille Tervo 3100fcd89c09SVille Tervo switch (le_ev->subevent) { 3101fcd89c09SVille Tervo case HCI_EV_LE_CONN_COMPLETE: 3102fcd89c09SVille Tervo hci_le_conn_complete_evt(hdev, skb); 3103fcd89c09SVille Tervo break; 3104fcd89c09SVille Tervo 31059aa04c91SAndre Guedes case HCI_EV_LE_ADVERTISING_REPORT: 31069aa04c91SAndre Guedes hci_le_adv_report_evt(hdev, skb); 31079aa04c91SAndre Guedes break; 31089aa04c91SAndre Guedes 3109a7a595f6SVinicius Costa Gomes case HCI_EV_LE_LTK_REQ: 3110a7a595f6SVinicius Costa Gomes hci_le_ltk_request_evt(hdev, skb); 3111a7a595f6SVinicius Costa Gomes break; 3112a7a595f6SVinicius Costa Gomes 3113fcd89c09SVille Tervo default: 3114fcd89c09SVille Tervo break; 3115fcd89c09SVille Tervo } 3116fcd89c09SVille Tervo } 3117fcd89c09SVille Tervo 31181da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 31191da177e4SLinus Torvalds { 3120a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 3121a9de9248SMarcel Holtmann __u8 event = hdr->evt; 31221da177e4SLinus Torvalds 31231da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 31241da177e4SLinus Torvalds 3125a9de9248SMarcel Holtmann switch (event) { 31261da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 31271da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 31281da177e4SLinus Torvalds break; 31291da177e4SLinus Torvalds 31301da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 31311da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 31321da177e4SLinus Torvalds break; 31331da177e4SLinus Torvalds 3134a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 3135a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 313621d9e30eSMarcel Holtmann break; 313721d9e30eSMarcel Holtmann 31381da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 31391da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 31401da177e4SLinus Torvalds break; 31411da177e4SLinus Torvalds 31421da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 31431da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 31441da177e4SLinus Torvalds break; 31451da177e4SLinus Torvalds 31461da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 31471da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 31481da177e4SLinus Torvalds break; 31491da177e4SLinus Torvalds 3150a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 3151a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 3152a9de9248SMarcel Holtmann break; 3153a9de9248SMarcel Holtmann 31541da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 31551da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 31561da177e4SLinus Torvalds break; 31571da177e4SLinus Torvalds 3158a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 3159a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 3160a9de9248SMarcel Holtmann break; 3161a9de9248SMarcel Holtmann 3162a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 3163a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 3164a9de9248SMarcel Holtmann break; 3165a9de9248SMarcel Holtmann 3166a9de9248SMarcel Holtmann case HCI_EV_REMOTE_VERSION: 3167a9de9248SMarcel Holtmann hci_remote_version_evt(hdev, skb); 3168a9de9248SMarcel Holtmann break; 3169a9de9248SMarcel Holtmann 3170a9de9248SMarcel Holtmann case HCI_EV_QOS_SETUP_COMPLETE: 3171a9de9248SMarcel Holtmann hci_qos_setup_complete_evt(hdev, skb); 3172a9de9248SMarcel Holtmann break; 3173a9de9248SMarcel Holtmann 3174a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 3175a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 3176a9de9248SMarcel Holtmann break; 3177a9de9248SMarcel Holtmann 3178a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 3179a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 3180a9de9248SMarcel Holtmann break; 3181a9de9248SMarcel Holtmann 3182a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 3183a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 3184a9de9248SMarcel Holtmann break; 3185a9de9248SMarcel Holtmann 3186a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 3187a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 3188a9de9248SMarcel Holtmann break; 3189a9de9248SMarcel Holtmann 3190a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 3191a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 31921da177e4SLinus Torvalds break; 31931da177e4SLinus Torvalds 31941da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 31951da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 31961da177e4SLinus Torvalds break; 31971da177e4SLinus Torvalds 31981da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 31991da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 32001da177e4SLinus Torvalds break; 32011da177e4SLinus Torvalds 32021da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 32031da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 32041da177e4SLinus Torvalds break; 32051da177e4SLinus Torvalds 32061da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 32071da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 32081da177e4SLinus Torvalds break; 32091da177e4SLinus Torvalds 3210a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 3211a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 3212a8746417SMarcel Holtmann break; 3213a8746417SMarcel Holtmann 321485a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 321585a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 321685a1e930SMarcel Holtmann break; 321785a1e930SMarcel Holtmann 3218a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 3219a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 3220a9de9248SMarcel Holtmann break; 3221a9de9248SMarcel Holtmann 3222a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 3223a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 3224a9de9248SMarcel Holtmann break; 3225a9de9248SMarcel Holtmann 3226a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 3227a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 3228a9de9248SMarcel Holtmann break; 3229a9de9248SMarcel Holtmann 3230a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_CHANGED: 3231a9de9248SMarcel Holtmann hci_sync_conn_changed_evt(hdev, skb); 3232a9de9248SMarcel Holtmann break; 3233a9de9248SMarcel Holtmann 323404837f64SMarcel Holtmann case HCI_EV_SNIFF_SUBRATE: 323504837f64SMarcel Holtmann hci_sniff_subrate_evt(hdev, skb); 323604837f64SMarcel Holtmann break; 323704837f64SMarcel Holtmann 3238a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 3239a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 32401da177e4SLinus Torvalds break; 32411da177e4SLinus Torvalds 32420493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 32430493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 32440493684eSMarcel Holtmann break; 32450493684eSMarcel Holtmann 324603b555e1SJohan Hedberg case HCI_EV_IO_CAPA_REPLY: 324703b555e1SJohan Hedberg hci_io_capa_reply_evt(hdev, skb); 324803b555e1SJohan Hedberg break; 324903b555e1SJohan Hedberg 3250a5c29683SJohan Hedberg case HCI_EV_USER_CONFIRM_REQUEST: 3251a5c29683SJohan Hedberg hci_user_confirm_request_evt(hdev, skb); 3252a5c29683SJohan Hedberg break; 3253a5c29683SJohan Hedberg 32541143d458SBrian Gix case HCI_EV_USER_PASSKEY_REQUEST: 32551143d458SBrian Gix hci_user_passkey_request_evt(hdev, skb); 32561143d458SBrian Gix break; 32571143d458SBrian Gix 32580493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 32590493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 32600493684eSMarcel Holtmann break; 32610493684eSMarcel Holtmann 326241a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 326341a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 326441a96212SMarcel Holtmann break; 326541a96212SMarcel Holtmann 3266fcd89c09SVille Tervo case HCI_EV_LE_META: 3267fcd89c09SVille Tervo hci_le_meta_evt(hdev, skb); 3268fcd89c09SVille Tervo break; 3269fcd89c09SVille Tervo 32702763eda6SSzymon Janc case HCI_EV_REMOTE_OOB_DATA_REQUEST: 32712763eda6SSzymon Janc hci_remote_oob_data_request_evt(hdev, skb); 32722763eda6SSzymon Janc break; 32732763eda6SSzymon Janc 32741da177e4SLinus Torvalds default: 3275a9de9248SMarcel Holtmann BT_DBG("%s event 0x%x", hdev->name, event); 32761da177e4SLinus Torvalds break; 32771da177e4SLinus Torvalds } 32781da177e4SLinus Torvalds 32791da177e4SLinus Torvalds kfree_skb(skb); 32801da177e4SLinus Torvalds hdev->stat.evt_rx++; 32811da177e4SLinus Torvalds } 32821da177e4SLinus Torvalds 32831da177e4SLinus Torvalds /* Generate internal stack event */ 32841da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data) 32851da177e4SLinus Torvalds { 32861da177e4SLinus Torvalds struct hci_event_hdr *hdr; 32871da177e4SLinus Torvalds struct hci_ev_stack_internal *ev; 32881da177e4SLinus Torvalds struct sk_buff *skb; 32891da177e4SLinus Torvalds 32901da177e4SLinus Torvalds skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC); 32911da177e4SLinus Torvalds if (!skb) 32921da177e4SLinus Torvalds return; 32931da177e4SLinus Torvalds 32941da177e4SLinus Torvalds hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE); 32951da177e4SLinus Torvalds hdr->evt = HCI_EV_STACK_INTERNAL; 32961da177e4SLinus Torvalds hdr->plen = sizeof(*ev) + dlen; 32971da177e4SLinus Torvalds 32981da177e4SLinus Torvalds ev = (void *) skb_put(skb, sizeof(*ev) + dlen); 32991da177e4SLinus Torvalds ev->type = type; 33001da177e4SLinus Torvalds memcpy(ev->data, data, dlen); 33011da177e4SLinus Torvalds 3302576c7d85SMarcel Holtmann bt_cb(skb)->incoming = 1; 3303a61bbcf2SPatrick McHardy __net_timestamp(skb); 3304576c7d85SMarcel Holtmann 33050d48d939SMarcel Holtmann bt_cb(skb)->pkt_type = HCI_EVENT_PKT; 33061da177e4SLinus Torvalds skb->dev = (void *) hdev; 3307eec8d2bcSJohan Hedberg hci_send_to_sock(hdev, skb, NULL); 33081da177e4SLinus Torvalds kfree_skb(skb); 33091da177e4SLinus Torvalds } 3310e6100a25SAndre Guedes 3311669bb396SGustavo F. Padovan module_param(enable_le, bool, 0644); 3312e6100a25SAndre Guedes MODULE_PARM_DESC(enable_le, "Enable LE support"); 3313