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 714971e3a4bSAndre Guedes memcpy(hdev->extfeatures, rp->features, 8); 715971e3a4bSAndre Guedes 716971e3a4bSAndre Guedes hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status); 717971e3a4bSAndre Guedes } 718971e3a4bSAndre Guedes 7191e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, 7201e89cffbSAndrei Emeltchenko struct sk_buff *skb) 7211e89cffbSAndrei Emeltchenko { 7221e89cffbSAndrei Emeltchenko struct hci_rp_read_flow_control_mode *rp = (void *) skb->data; 7231e89cffbSAndrei Emeltchenko 7241e89cffbSAndrei Emeltchenko BT_DBG("%s status 0x%x", hdev->name, rp->status); 7251e89cffbSAndrei Emeltchenko 7261e89cffbSAndrei Emeltchenko if (rp->status) 7271e89cffbSAndrei Emeltchenko return; 7281e89cffbSAndrei Emeltchenko 7291e89cffbSAndrei Emeltchenko hdev->flow_ctl_mode = rp->mode; 7301e89cffbSAndrei Emeltchenko 7311e89cffbSAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status); 7321e89cffbSAndrei Emeltchenko } 7331e89cffbSAndrei Emeltchenko 734a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 735a9de9248SMarcel Holtmann { 736a9de9248SMarcel Holtmann struct hci_rp_read_buffer_size *rp = (void *) skb->data; 737a9de9248SMarcel Holtmann 738a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 739a9de9248SMarcel Holtmann 740a9de9248SMarcel Holtmann if (rp->status) 741a9de9248SMarcel Holtmann return; 742a9de9248SMarcel Holtmann 743a9de9248SMarcel Holtmann hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); 744a9de9248SMarcel Holtmann hdev->sco_mtu = rp->sco_mtu; 745a9de9248SMarcel Holtmann hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); 746a9de9248SMarcel Holtmann hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); 747da1f5198SMarcel Holtmann 748da1f5198SMarcel Holtmann if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { 749da1f5198SMarcel Holtmann hdev->sco_mtu = 64; 750da1f5198SMarcel Holtmann hdev->sco_pkts = 8; 751da1f5198SMarcel Holtmann } 752da1f5198SMarcel Holtmann 753da1f5198SMarcel Holtmann hdev->acl_cnt = hdev->acl_pkts; 754da1f5198SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 7551da177e4SLinus Torvalds 756a9de9248SMarcel Holtmann BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, 757a9de9248SMarcel Holtmann hdev->acl_mtu, hdev->acl_pkts, 758a9de9248SMarcel Holtmann hdev->sco_mtu, hdev->sco_pkts); 7591da177e4SLinus Torvalds } 7601da177e4SLinus Torvalds 761a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) 762a9de9248SMarcel Holtmann { 763a9de9248SMarcel Holtmann struct hci_rp_read_bd_addr *rp = (void *) skb->data; 7641da177e4SLinus Torvalds 765a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 766a9de9248SMarcel Holtmann 767a9de9248SMarcel Holtmann if (!rp->status) 768a9de9248SMarcel Holtmann bacpy(&hdev->bdaddr, &rp->bdaddr); 769a9de9248SMarcel Holtmann 77023bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status); 77123bb5763SJohan Hedberg } 77223bb5763SJohan Hedberg 773350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev, 774350ee4cfSAndrei Emeltchenko struct sk_buff *skb) 775350ee4cfSAndrei Emeltchenko { 776350ee4cfSAndrei Emeltchenko struct hci_rp_read_data_block_size *rp = (void *) skb->data; 777350ee4cfSAndrei Emeltchenko 778350ee4cfSAndrei Emeltchenko BT_DBG("%s status 0x%x", hdev->name, rp->status); 779350ee4cfSAndrei Emeltchenko 780350ee4cfSAndrei Emeltchenko if (rp->status) 781350ee4cfSAndrei Emeltchenko return; 782350ee4cfSAndrei Emeltchenko 783350ee4cfSAndrei Emeltchenko hdev->block_mtu = __le16_to_cpu(rp->max_acl_len); 784350ee4cfSAndrei Emeltchenko hdev->block_len = __le16_to_cpu(rp->block_len); 785350ee4cfSAndrei Emeltchenko hdev->num_blocks = __le16_to_cpu(rp->num_blocks); 786350ee4cfSAndrei Emeltchenko 787350ee4cfSAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 788350ee4cfSAndrei Emeltchenko 789350ee4cfSAndrei Emeltchenko BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu, 790350ee4cfSAndrei Emeltchenko hdev->block_cnt, hdev->block_len); 791350ee4cfSAndrei Emeltchenko 792350ee4cfSAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status); 793350ee4cfSAndrei Emeltchenko } 794350ee4cfSAndrei Emeltchenko 79523bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb) 79623bb5763SJohan Hedberg { 79723bb5763SJohan Hedberg __u8 status = *((__u8 *) skb->data); 79823bb5763SJohan Hedberg 79923bb5763SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 80023bb5763SJohan Hedberg 80123bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status); 8021da177e4SLinus Torvalds } 8031da177e4SLinus Torvalds 804928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev, 805928abaa7SAndrei Emeltchenko struct sk_buff *skb) 806928abaa7SAndrei Emeltchenko { 807928abaa7SAndrei Emeltchenko struct hci_rp_read_local_amp_info *rp = (void *) skb->data; 808928abaa7SAndrei Emeltchenko 809928abaa7SAndrei Emeltchenko BT_DBG("%s status 0x%x", hdev->name, rp->status); 810928abaa7SAndrei Emeltchenko 811928abaa7SAndrei Emeltchenko if (rp->status) 812928abaa7SAndrei Emeltchenko return; 813928abaa7SAndrei Emeltchenko 814928abaa7SAndrei Emeltchenko hdev->amp_status = rp->amp_status; 815928abaa7SAndrei Emeltchenko hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); 816928abaa7SAndrei Emeltchenko hdev->amp_max_bw = __le32_to_cpu(rp->max_bw); 817928abaa7SAndrei Emeltchenko hdev->amp_min_latency = __le32_to_cpu(rp->min_latency); 818928abaa7SAndrei Emeltchenko hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu); 819928abaa7SAndrei Emeltchenko hdev->amp_type = rp->amp_type; 820928abaa7SAndrei Emeltchenko hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap); 821928abaa7SAndrei Emeltchenko hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size); 822928abaa7SAndrei Emeltchenko hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); 823928abaa7SAndrei Emeltchenko hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); 824928abaa7SAndrei Emeltchenko 825928abaa7SAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status); 826928abaa7SAndrei Emeltchenko } 827928abaa7SAndrei Emeltchenko 828b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, 829b0916ea0SJohan Hedberg struct sk_buff *skb) 830b0916ea0SJohan Hedberg { 831b0916ea0SJohan Hedberg __u8 status = *((__u8 *) skb->data); 832b0916ea0SJohan Hedberg 833b0916ea0SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 834b0916ea0SJohan Hedberg 835b0916ea0SJohan Hedberg hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status); 836b0916ea0SJohan Hedberg } 837b0916ea0SJohan Hedberg 838d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb) 839d5859e22SJohan Hedberg { 840d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 841d5859e22SJohan Hedberg 842d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 843d5859e22SJohan Hedberg 844d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status); 845d5859e22SJohan Hedberg } 846d5859e22SJohan Hedberg 847d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev, 848d5859e22SJohan Hedberg struct sk_buff *skb) 849d5859e22SJohan Hedberg { 850d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 851d5859e22SJohan Hedberg 852d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 853d5859e22SJohan Hedberg 854d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status); 855d5859e22SJohan Hedberg } 856d5859e22SJohan Hedberg 857d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, 858d5859e22SJohan Hedberg struct sk_buff *skb) 859d5859e22SJohan Hedberg { 860d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 861d5859e22SJohan Hedberg 862d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 863d5859e22SJohan Hedberg 864d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status); 865d5859e22SJohan Hedberg } 866d5859e22SJohan Hedberg 867d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb) 868d5859e22SJohan Hedberg { 869d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 870d5859e22SJohan Hedberg 871d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 872d5859e22SJohan Hedberg 873d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status); 874d5859e22SJohan Hedberg } 875d5859e22SJohan Hedberg 876980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) 877980e1a53SJohan Hedberg { 878980e1a53SJohan Hedberg struct hci_rp_pin_code_reply *rp = (void *) skb->data; 879980e1a53SJohan Hedberg struct hci_cp_pin_code_reply *cp; 880980e1a53SJohan Hedberg struct hci_conn *conn; 881980e1a53SJohan Hedberg 882980e1a53SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 883980e1a53SJohan Hedberg 88456e5cb86SJohan Hedberg hci_dev_lock(hdev); 88556e5cb86SJohan Hedberg 886980e1a53SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 887744cf19eSJohan Hedberg mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); 888980e1a53SJohan Hedberg 889980e1a53SJohan Hedberg if (rp->status != 0) 89056e5cb86SJohan Hedberg goto unlock; 891980e1a53SJohan Hedberg 892980e1a53SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); 893980e1a53SJohan Hedberg if (!cp) 89456e5cb86SJohan Hedberg goto unlock; 895980e1a53SJohan Hedberg 896980e1a53SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 897980e1a53SJohan Hedberg if (conn) 898980e1a53SJohan Hedberg conn->pin_length = cp->pin_len; 89956e5cb86SJohan Hedberg 90056e5cb86SJohan Hedberg unlock: 90156e5cb86SJohan Hedberg hci_dev_unlock(hdev); 902980e1a53SJohan Hedberg } 903980e1a53SJohan Hedberg 904980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 905980e1a53SJohan Hedberg { 906980e1a53SJohan Hedberg struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data; 907980e1a53SJohan Hedberg 908980e1a53SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 909980e1a53SJohan Hedberg 91056e5cb86SJohan Hedberg hci_dev_lock(hdev); 91156e5cb86SJohan Hedberg 912980e1a53SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 913744cf19eSJohan Hedberg mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr, 914980e1a53SJohan Hedberg rp->status); 91556e5cb86SJohan Hedberg 91656e5cb86SJohan Hedberg hci_dev_unlock(hdev); 917980e1a53SJohan Hedberg } 91856e5cb86SJohan Hedberg 9196ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, 9206ed58ec5SVille Tervo struct sk_buff *skb) 9216ed58ec5SVille Tervo { 9226ed58ec5SVille Tervo struct hci_rp_le_read_buffer_size *rp = (void *) skb->data; 9236ed58ec5SVille Tervo 9246ed58ec5SVille Tervo BT_DBG("%s status 0x%x", hdev->name, rp->status); 9256ed58ec5SVille Tervo 9266ed58ec5SVille Tervo if (rp->status) 9276ed58ec5SVille Tervo return; 9286ed58ec5SVille Tervo 9296ed58ec5SVille Tervo hdev->le_mtu = __le16_to_cpu(rp->le_mtu); 9306ed58ec5SVille Tervo hdev->le_pkts = rp->le_max_pkt; 9316ed58ec5SVille Tervo 9326ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 9336ed58ec5SVille Tervo 9346ed58ec5SVille Tervo BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); 9356ed58ec5SVille Tervo 9366ed58ec5SVille Tervo hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status); 9376ed58ec5SVille Tervo } 938980e1a53SJohan Hedberg 939a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) 940a5c29683SJohan Hedberg { 941a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 942a5c29683SJohan Hedberg 943a5c29683SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 944a5c29683SJohan Hedberg 94556e5cb86SJohan Hedberg hci_dev_lock(hdev); 94656e5cb86SJohan Hedberg 947a5c29683SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 948744cf19eSJohan Hedberg mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, 949a5c29683SJohan Hedberg rp->status); 95056e5cb86SJohan Hedberg 95156e5cb86SJohan Hedberg hci_dev_unlock(hdev); 952a5c29683SJohan Hedberg } 953a5c29683SJohan Hedberg 954a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, 955a5c29683SJohan Hedberg struct sk_buff *skb) 956a5c29683SJohan Hedberg { 957a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 958a5c29683SJohan Hedberg 959a5c29683SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 960a5c29683SJohan Hedberg 96156e5cb86SJohan Hedberg hci_dev_lock(hdev); 96256e5cb86SJohan Hedberg 963a5c29683SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 964744cf19eSJohan Hedberg mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr, 965a5c29683SJohan Hedberg rp->status); 96656e5cb86SJohan Hedberg 96756e5cb86SJohan Hedberg hci_dev_unlock(hdev); 968a5c29683SJohan Hedberg } 969a5c29683SJohan Hedberg 9701143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb) 9711143d458SBrian Gix { 9721143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 9731143d458SBrian Gix 9741143d458SBrian Gix BT_DBG("%s status 0x%x", hdev->name, rp->status); 9751143d458SBrian Gix 9761143d458SBrian Gix hci_dev_lock(hdev); 9771143d458SBrian Gix 9781143d458SBrian Gix if (test_bit(HCI_MGMT, &hdev->flags)) 9791143d458SBrian Gix mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, 9801143d458SBrian Gix rp->status); 9811143d458SBrian Gix 9821143d458SBrian Gix hci_dev_unlock(hdev); 9831143d458SBrian Gix } 9841143d458SBrian Gix 9851143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, 9861143d458SBrian Gix struct sk_buff *skb) 9871143d458SBrian Gix { 9881143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 9891143d458SBrian Gix 9901143d458SBrian Gix BT_DBG("%s status 0x%x", hdev->name, rp->status); 9911143d458SBrian Gix 9921143d458SBrian Gix hci_dev_lock(hdev); 9931143d458SBrian Gix 9941143d458SBrian Gix if (test_bit(HCI_MGMT, &hdev->flags)) 9951143d458SBrian Gix mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr, 9961143d458SBrian Gix rp->status); 9971143d458SBrian Gix 9981143d458SBrian Gix hci_dev_unlock(hdev); 9991143d458SBrian Gix } 10001143d458SBrian Gix 1001c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, 1002c35938b2SSzymon Janc struct sk_buff *skb) 1003c35938b2SSzymon Janc { 1004c35938b2SSzymon Janc struct hci_rp_read_local_oob_data *rp = (void *) skb->data; 1005c35938b2SSzymon Janc 1006c35938b2SSzymon Janc BT_DBG("%s status 0x%x", hdev->name, rp->status); 1007c35938b2SSzymon Janc 100856e5cb86SJohan Hedberg hci_dev_lock(hdev); 1009744cf19eSJohan Hedberg mgmt_read_local_oob_data_reply_complete(hdev, rp->hash, 1010c35938b2SSzymon Janc rp->randomizer, rp->status); 101156e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1012c35938b2SSzymon Janc } 1013c35938b2SSzymon Janc 101407f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) 101507f7fa5dSAndre Guedes { 101607f7fa5dSAndre Guedes __u8 status = *((__u8 *) skb->data); 101707f7fa5dSAndre Guedes 101807f7fa5dSAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 101907f7fa5dSAndre Guedes } 102007f7fa5dSAndre Guedes 1021eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, 1022eb9d91f5SAndre Guedes struct sk_buff *skb) 1023eb9d91f5SAndre Guedes { 1024eb9d91f5SAndre Guedes struct hci_cp_le_set_scan_enable *cp; 1025eb9d91f5SAndre Guedes __u8 status = *((__u8 *) skb->data); 1026eb9d91f5SAndre Guedes 1027eb9d91f5SAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 1028eb9d91f5SAndre Guedes 1029eb9d91f5SAndre Guedes if (status) 1030eb9d91f5SAndre Guedes return; 1031eb9d91f5SAndre Guedes 1032eb9d91f5SAndre Guedes cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE); 1033eb9d91f5SAndre Guedes if (!cp) 1034eb9d91f5SAndre Guedes return; 1035eb9d91f5SAndre Guedes 103635815085SAndre Guedes if (cp->enable == 0x01) { 1037d23264a8SAndre Guedes set_bit(HCI_LE_SCAN, &hdev->dev_flags); 1038d23264a8SAndre Guedes 1039db323f2fSGustavo F. Padovan cancel_delayed_work_sync(&hdev->adv_work); 1040a8f13c8cSAndre Guedes 1041a8f13c8cSAndre Guedes hci_dev_lock(hdev); 1042eb9d91f5SAndre Guedes hci_adv_entries_clear(hdev); 1043a8f13c8cSAndre Guedes hci_dev_unlock(hdev); 104435815085SAndre Guedes } else if (cp->enable == 0x00) { 1045d23264a8SAndre Guedes clear_bit(HCI_LE_SCAN, &hdev->dev_flags); 1046d23264a8SAndre Guedes 1047db323f2fSGustavo F. Padovan cancel_delayed_work_sync(&hdev->adv_work); 1048db323f2fSGustavo F. Padovan queue_delayed_work(hdev->workqueue, &hdev->adv_work, 1049db323f2fSGustavo F. Padovan jiffies + ADV_CLEAR_TIMEOUT); 105035815085SAndre Guedes } 1051eb9d91f5SAndre Guedes } 1052eb9d91f5SAndre Guedes 1053a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb) 1054a7a595f6SVinicius Costa Gomes { 1055a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_reply *rp = (void *) skb->data; 1056a7a595f6SVinicius Costa Gomes 1057a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, rp->status); 1058a7a595f6SVinicius Costa Gomes 1059a7a595f6SVinicius Costa Gomes if (rp->status) 1060a7a595f6SVinicius Costa Gomes return; 1061a7a595f6SVinicius Costa Gomes 1062a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status); 1063a7a595f6SVinicius Costa Gomes } 1064a7a595f6SVinicius Costa Gomes 1065a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 1066a7a595f6SVinicius Costa Gomes { 1067a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data; 1068a7a595f6SVinicius Costa Gomes 1069a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, rp->status); 1070a7a595f6SVinicius Costa Gomes 1071a7a595f6SVinicius Costa Gomes if (rp->status) 1072a7a595f6SVinicius Costa Gomes return; 1073a7a595f6SVinicius Costa Gomes 1074a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status); 1075a7a595f6SVinicius Costa Gomes } 1076a7a595f6SVinicius Costa Gomes 1077f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev, 1078f9b49306SAndre Guedes struct sk_buff *skb) 1079f9b49306SAndre Guedes { 1080f9b49306SAndre Guedes struct hci_cp_read_local_ext_features cp; 1081f9b49306SAndre Guedes __u8 status = *((__u8 *) skb->data); 1082f9b49306SAndre Guedes 1083f9b49306SAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 1084f9b49306SAndre Guedes 1085f9b49306SAndre Guedes if (status) 1086f9b49306SAndre Guedes return; 1087f9b49306SAndre Guedes 1088f9b49306SAndre Guedes cp.page = 0x01; 1089f9b49306SAndre Guedes hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp); 1090f9b49306SAndre Guedes } 1091f9b49306SAndre Guedes 1092a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 1093a9de9248SMarcel Holtmann { 1094a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1095a9de9248SMarcel Holtmann 1096a9de9248SMarcel Holtmann if (status) { 109723bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 1098a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 109956e5cb86SJohan Hedberg hci_dev_lock(hdev); 1100164a6e78SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 11017a135109SAndre Guedes mgmt_start_discovery_failed(hdev, status); 110256e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1103314b2381SJohan Hedberg return; 1104314b2381SJohan Hedberg } 1105314b2381SJohan Hedberg 110689352e7dSAndre Guedes set_bit(HCI_INQUIRY, &hdev->flags); 110789352e7dSAndre Guedes 110856e5cb86SJohan Hedberg hci_dev_lock(hdev); 1109744cf19eSJohan Hedberg mgmt_discovering(hdev, 1); 111056e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1111a9de9248SMarcel Holtmann } 1112a9de9248SMarcel Holtmann 11131da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 11141da177e4SLinus Torvalds { 1115a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 11161da177e4SLinus Torvalds struct hci_conn *conn; 11171da177e4SLinus Torvalds 1118a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1119a9de9248SMarcel Holtmann 1120a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 11211da177e4SLinus Torvalds if (!cp) 11221da177e4SLinus Torvalds return; 11231da177e4SLinus Torvalds 11241da177e4SLinus Torvalds hci_dev_lock(hdev); 11251da177e4SLinus Torvalds 11261da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 11271da177e4SLinus Torvalds 1128a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn); 11291da177e4SLinus Torvalds 11301da177e4SLinus Torvalds if (status) { 11311da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 11324c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 11331da177e4SLinus Torvalds conn->state = BT_CLOSED; 11341da177e4SLinus Torvalds hci_proto_connect_cfm(conn, status); 11351da177e4SLinus Torvalds hci_conn_del(conn); 11364c67bc74SMarcel Holtmann } else 11374c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 11381da177e4SLinus Torvalds } 11391da177e4SLinus Torvalds } else { 11401da177e4SLinus Torvalds if (!conn) { 11411da177e4SLinus Torvalds conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); 11421da177e4SLinus Torvalds if (conn) { 11431da177e4SLinus Torvalds conn->out = 1; 11441da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 11451da177e4SLinus Torvalds } else 1146893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 11471da177e4SLinus Torvalds } 11481da177e4SLinus Torvalds } 11491da177e4SLinus Torvalds 11501da177e4SLinus Torvalds hci_dev_unlock(hdev); 11511da177e4SLinus Torvalds } 11521da177e4SLinus Torvalds 1153a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 11541da177e4SLinus Torvalds { 1155a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 11561da177e4SLinus Torvalds struct hci_conn *acl, *sco; 11571da177e4SLinus Torvalds __u16 handle; 11581da177e4SLinus Torvalds 1159b6a0dc82SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1160b6a0dc82SMarcel Holtmann 1161a9de9248SMarcel Holtmann if (!status) 1162a9de9248SMarcel Holtmann return; 1163a9de9248SMarcel Holtmann 1164a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 11651da177e4SLinus Torvalds if (!cp) 1166a9de9248SMarcel Holtmann return; 11671da177e4SLinus Torvalds 11681da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 11691da177e4SLinus Torvalds 1170a9de9248SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 11711da177e4SLinus Torvalds 11721da177e4SLinus Torvalds hci_dev_lock(hdev); 11731da177e4SLinus Torvalds 11741da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 11755a08ecceSAndrei Emeltchenko if (acl) { 11765a08ecceSAndrei Emeltchenko sco = acl->link; 11775a08ecceSAndrei Emeltchenko if (sco) { 11781da177e4SLinus Torvalds sco->state = BT_CLOSED; 11791da177e4SLinus Torvalds 11801da177e4SLinus Torvalds hci_proto_connect_cfm(sco, status); 11811da177e4SLinus Torvalds hci_conn_del(sco); 11821da177e4SLinus Torvalds } 11835a08ecceSAndrei Emeltchenko } 11841da177e4SLinus Torvalds 11851da177e4SLinus Torvalds hci_dev_unlock(hdev); 11861da177e4SLinus Torvalds } 11871da177e4SLinus Torvalds 1188f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 1189f8558555SMarcel Holtmann { 1190f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 1191f8558555SMarcel Holtmann struct hci_conn *conn; 1192f8558555SMarcel Holtmann 1193f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1194f8558555SMarcel Holtmann 1195f8558555SMarcel Holtmann if (!status) 1196f8558555SMarcel Holtmann return; 1197f8558555SMarcel Holtmann 1198f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 1199f8558555SMarcel Holtmann if (!cp) 1200f8558555SMarcel Holtmann return; 1201f8558555SMarcel Holtmann 1202f8558555SMarcel Holtmann hci_dev_lock(hdev); 1203f8558555SMarcel Holtmann 1204f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1205f8558555SMarcel Holtmann if (conn) { 1206f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1207f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1208f8558555SMarcel Holtmann hci_conn_put(conn); 1209f8558555SMarcel Holtmann } 1210f8558555SMarcel Holtmann } 1211f8558555SMarcel Holtmann 1212f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1213f8558555SMarcel Holtmann } 1214f8558555SMarcel Holtmann 1215f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 1216f8558555SMarcel Holtmann { 1217f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 1218f8558555SMarcel Holtmann struct hci_conn *conn; 1219f8558555SMarcel Holtmann 1220f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1221f8558555SMarcel Holtmann 1222f8558555SMarcel Holtmann if (!status) 1223f8558555SMarcel Holtmann return; 1224f8558555SMarcel Holtmann 1225f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 1226f8558555SMarcel Holtmann if (!cp) 1227f8558555SMarcel Holtmann return; 1228f8558555SMarcel Holtmann 1229f8558555SMarcel Holtmann hci_dev_lock(hdev); 1230f8558555SMarcel Holtmann 1231f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1232f8558555SMarcel Holtmann if (conn) { 1233f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1234f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1235f8558555SMarcel Holtmann hci_conn_put(conn); 1236f8558555SMarcel Holtmann } 1237f8558555SMarcel Holtmann } 1238f8558555SMarcel Holtmann 1239f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1240f8558555SMarcel Holtmann } 1241f8558555SMarcel Holtmann 1242127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev, 1243392599b9SJohan Hedberg struct hci_conn *conn) 1244392599b9SJohan Hedberg { 1245392599b9SJohan Hedberg if (conn->state != BT_CONFIG || !conn->out) 1246392599b9SJohan Hedberg return 0; 1247392599b9SJohan Hedberg 1248765c2a96SJohan Hedberg if (conn->pending_sec_level == BT_SECURITY_SDP) 1249392599b9SJohan Hedberg return 0; 1250392599b9SJohan Hedberg 1251392599b9SJohan Hedberg /* Only request authentication for SSP connections or non-SSP 1252e9bf2bf0SVinicius Costa Gomes * devices with sec_level HIGH or if MITM protection is requested */ 1253392599b9SJohan Hedberg if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) && 1254e9bf2bf0SVinicius Costa Gomes conn->pending_sec_level != BT_SECURITY_HIGH && 1255e9bf2bf0SVinicius Costa Gomes !(conn->auth_type & 0x01)) 1256392599b9SJohan Hedberg return 0; 1257392599b9SJohan Hedberg 1258392599b9SJohan Hedberg return 1; 1259392599b9SJohan Hedberg } 1260392599b9SJohan Hedberg 1261a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 12621da177e4SLinus Torvalds { 1263127178d2SJohan Hedberg struct hci_cp_remote_name_req *cp; 1264127178d2SJohan Hedberg struct hci_conn *conn; 1265127178d2SJohan Hedberg 1266a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1267127178d2SJohan Hedberg 1268127178d2SJohan Hedberg /* If successful wait for the name req complete event before 1269127178d2SJohan Hedberg * checking for the need to do authentication */ 1270127178d2SJohan Hedberg if (!status) 1271127178d2SJohan Hedberg return; 1272127178d2SJohan Hedberg 1273127178d2SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); 1274127178d2SJohan Hedberg if (!cp) 1275127178d2SJohan Hedberg return; 1276127178d2SJohan Hedberg 1277127178d2SJohan Hedberg hci_dev_lock(hdev); 1278127178d2SJohan Hedberg 1279127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 128079c6c70cSJohan Hedberg if (!conn) 128179c6c70cSJohan Hedberg goto unlock; 128279c6c70cSJohan Hedberg 128379c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 128479c6c70cSJohan Hedberg goto unlock; 128579c6c70cSJohan Hedberg 128679c6c70cSJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { 1287127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1288127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1289127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1290127178d2SJohan Hedberg } 1291127178d2SJohan Hedberg 129279c6c70cSJohan Hedberg unlock: 1293127178d2SJohan Hedberg hci_dev_unlock(hdev); 1294a9de9248SMarcel Holtmann } 12951da177e4SLinus Torvalds 1296769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 1297769be974SMarcel Holtmann { 1298769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 1299769be974SMarcel Holtmann struct hci_conn *conn; 1300769be974SMarcel Holtmann 1301769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1302769be974SMarcel Holtmann 1303769be974SMarcel Holtmann if (!status) 1304769be974SMarcel Holtmann return; 1305769be974SMarcel Holtmann 1306769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 1307769be974SMarcel Holtmann if (!cp) 1308769be974SMarcel Holtmann return; 1309769be974SMarcel Holtmann 1310769be974SMarcel Holtmann hci_dev_lock(hdev); 1311769be974SMarcel Holtmann 1312769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1313769be974SMarcel Holtmann if (conn) { 1314769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1315769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1316769be974SMarcel Holtmann hci_conn_put(conn); 1317769be974SMarcel Holtmann } 1318769be974SMarcel Holtmann } 1319769be974SMarcel Holtmann 1320769be974SMarcel Holtmann hci_dev_unlock(hdev); 1321769be974SMarcel Holtmann } 1322769be974SMarcel Holtmann 1323769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 1324769be974SMarcel Holtmann { 1325769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features *cp; 1326769be974SMarcel Holtmann struct hci_conn *conn; 1327769be974SMarcel Holtmann 1328769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1329769be974SMarcel Holtmann 1330769be974SMarcel Holtmann if (!status) 1331769be974SMarcel Holtmann return; 1332769be974SMarcel Holtmann 1333769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 1334769be974SMarcel Holtmann if (!cp) 1335769be974SMarcel Holtmann return; 1336769be974SMarcel Holtmann 1337769be974SMarcel Holtmann hci_dev_lock(hdev); 1338769be974SMarcel Holtmann 1339769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1340769be974SMarcel Holtmann if (conn) { 1341769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1342769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1343769be974SMarcel Holtmann hci_conn_put(conn); 1344769be974SMarcel Holtmann } 1345769be974SMarcel Holtmann } 1346769be974SMarcel Holtmann 1347769be974SMarcel Holtmann hci_dev_unlock(hdev); 1348769be974SMarcel Holtmann } 1349769be974SMarcel Holtmann 1350a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 1351a9de9248SMarcel Holtmann { 1352b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 1353b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 1354b6a0dc82SMarcel Holtmann __u16 handle; 1355b6a0dc82SMarcel Holtmann 1356a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1357b6a0dc82SMarcel Holtmann 1358b6a0dc82SMarcel Holtmann if (!status) 1359b6a0dc82SMarcel Holtmann return; 1360b6a0dc82SMarcel Holtmann 1361b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 1362b6a0dc82SMarcel Holtmann if (!cp) 1363b6a0dc82SMarcel Holtmann return; 1364b6a0dc82SMarcel Holtmann 1365b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 1366b6a0dc82SMarcel Holtmann 1367b6a0dc82SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 1368b6a0dc82SMarcel Holtmann 1369b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 1370b6a0dc82SMarcel Holtmann 1371b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 13725a08ecceSAndrei Emeltchenko if (acl) { 13735a08ecceSAndrei Emeltchenko sco = acl->link; 13745a08ecceSAndrei Emeltchenko if (sco) { 1375b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 1376b6a0dc82SMarcel Holtmann 1377b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(sco, status); 1378b6a0dc82SMarcel Holtmann hci_conn_del(sco); 1379b6a0dc82SMarcel Holtmann } 13805a08ecceSAndrei Emeltchenko } 1381b6a0dc82SMarcel Holtmann 1382b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 1383a9de9248SMarcel Holtmann } 1384a9de9248SMarcel Holtmann 1385a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 1386a9de9248SMarcel Holtmann { 1387a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 138804837f64SMarcel Holtmann struct hci_conn *conn; 138904837f64SMarcel Holtmann 1390a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1391a9de9248SMarcel Holtmann 1392a9de9248SMarcel Holtmann if (!status) 1393a9de9248SMarcel Holtmann return; 1394a9de9248SMarcel Holtmann 1395a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 139604837f64SMarcel Holtmann if (!cp) 1397a9de9248SMarcel Holtmann return; 139804837f64SMarcel Holtmann 139904837f64SMarcel Holtmann hci_dev_lock(hdev); 140004837f64SMarcel Holtmann 140104837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1402e73439d8SMarcel Holtmann if (conn) { 140304837f64SMarcel Holtmann clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); 140404837f64SMarcel Holtmann 1405e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 1406e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1407e73439d8SMarcel Holtmann } 1408e73439d8SMarcel Holtmann 140904837f64SMarcel Holtmann hci_dev_unlock(hdev); 141004837f64SMarcel Holtmann } 141104837f64SMarcel Holtmann 1412a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 1413a9de9248SMarcel Holtmann { 1414a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 141504837f64SMarcel Holtmann struct hci_conn *conn; 141604837f64SMarcel Holtmann 1417a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1418a9de9248SMarcel Holtmann 1419a9de9248SMarcel Holtmann if (!status) 1420a9de9248SMarcel Holtmann return; 1421a9de9248SMarcel Holtmann 1422a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 142304837f64SMarcel Holtmann if (!cp) 1424a9de9248SMarcel Holtmann return; 142504837f64SMarcel Holtmann 142604837f64SMarcel Holtmann hci_dev_lock(hdev); 142704837f64SMarcel Holtmann 142804837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1429e73439d8SMarcel Holtmann if (conn) { 143004837f64SMarcel Holtmann clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); 143104837f64SMarcel Holtmann 1432e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 1433e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1434e73439d8SMarcel Holtmann } 1435e73439d8SMarcel Holtmann 143604837f64SMarcel Holtmann hci_dev_unlock(hdev); 143704837f64SMarcel Holtmann } 143804837f64SMarcel Holtmann 1439fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) 1440fcd89c09SVille Tervo { 1441fcd89c09SVille Tervo struct hci_cp_le_create_conn *cp; 1442fcd89c09SVille Tervo struct hci_conn *conn; 1443fcd89c09SVille Tervo 1444fcd89c09SVille Tervo BT_DBG("%s status 0x%x", hdev->name, status); 1445fcd89c09SVille Tervo 1446fcd89c09SVille Tervo cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN); 1447fcd89c09SVille Tervo if (!cp) 1448fcd89c09SVille Tervo return; 1449fcd89c09SVille Tervo 1450fcd89c09SVille Tervo hci_dev_lock(hdev); 1451fcd89c09SVille Tervo 1452fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr); 1453fcd89c09SVille Tervo 1454fcd89c09SVille Tervo BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr), 1455fcd89c09SVille Tervo conn); 1456fcd89c09SVille Tervo 1457fcd89c09SVille Tervo if (status) { 1458fcd89c09SVille Tervo if (conn && conn->state == BT_CONNECT) { 1459fcd89c09SVille Tervo conn->state = BT_CLOSED; 1460fcd89c09SVille Tervo hci_proto_connect_cfm(conn, status); 1461fcd89c09SVille Tervo hci_conn_del(conn); 1462fcd89c09SVille Tervo } 1463fcd89c09SVille Tervo } else { 1464fcd89c09SVille Tervo if (!conn) { 1465fcd89c09SVille Tervo conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr); 146629b7988aSAndre Guedes if (conn) { 146729b7988aSAndre Guedes conn->dst_type = cp->peer_addr_type; 1468fcd89c09SVille Tervo conn->out = 1; 146929b7988aSAndre Guedes } else { 1470fcd89c09SVille Tervo BT_ERR("No memory for new connection"); 1471fcd89c09SVille Tervo } 1472fcd89c09SVille Tervo } 147329b7988aSAndre Guedes } 1474fcd89c09SVille Tervo 1475fcd89c09SVille Tervo hci_dev_unlock(hdev); 1476fcd89c09SVille Tervo } 1477fcd89c09SVille Tervo 1478a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) 1479a7a595f6SVinicius Costa Gomes { 1480a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, status); 1481a7a595f6SVinicius Costa Gomes } 1482a7a595f6SVinicius Costa Gomes 14831da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 14841da177e4SLinus Torvalds { 14851da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 14861da177e4SLinus Torvalds 14871da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, status); 14881da177e4SLinus Torvalds 148923bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 14906bd57416SMarcel Holtmann 1491a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 149289352e7dSAndre Guedes 149389352e7dSAndre Guedes if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) 149489352e7dSAndre Guedes return; 149589352e7dSAndre Guedes 149656e5cb86SJohan Hedberg hci_dev_lock(hdev); 1497744cf19eSJohan Hedberg mgmt_discovering(hdev, 0); 149856e5cb86SJohan Hedberg hci_dev_unlock(hdev); 14991da177e4SLinus Torvalds } 15001da177e4SLinus Torvalds 15011da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 15021da177e4SLinus Torvalds { 150345bb4bf0SMarcel Holtmann struct inquiry_data data; 1504a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 15051da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 15061da177e4SLinus Torvalds 15071da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 15081da177e4SLinus Torvalds 150945bb4bf0SMarcel Holtmann if (!num_rsp) 151045bb4bf0SMarcel Holtmann return; 151145bb4bf0SMarcel Holtmann 15121da177e4SLinus Torvalds hci_dev_lock(hdev); 151345bb4bf0SMarcel Holtmann 1514e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 15151da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 15161da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 15171da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 15181da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 15191da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 15201da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 15211da177e4SLinus Torvalds data.rssi = 0x00; 152241a96212SMarcel Holtmann data.ssp_mode = 0x00; 15231da177e4SLinus Torvalds hci_inquiry_cache_update(hdev, &data); 152448264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 15254c659c39SJohan Hedberg info->dev_class, 0, NULL); 15261da177e4SLinus Torvalds } 152745bb4bf0SMarcel Holtmann 15281da177e4SLinus Torvalds hci_dev_unlock(hdev); 15291da177e4SLinus Torvalds } 15301da177e4SLinus Torvalds 1531a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 15321da177e4SLinus Torvalds { 1533a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 1534a9de9248SMarcel Holtmann struct hci_conn *conn; 15351da177e4SLinus Torvalds 1536a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 153745bb4bf0SMarcel Holtmann 15381da177e4SLinus Torvalds hci_dev_lock(hdev); 153945bb4bf0SMarcel Holtmann 1540a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 15419499237aSMarcel Holtmann if (!conn) { 15429499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 15439499237aSMarcel Holtmann goto unlock; 15449499237aSMarcel Holtmann 15459499237aSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 1546a9de9248SMarcel Holtmann if (!conn) 1547a9de9248SMarcel Holtmann goto unlock; 154845bb4bf0SMarcel Holtmann 15499499237aSMarcel Holtmann conn->type = SCO_LINK; 15509499237aSMarcel Holtmann } 15519499237aSMarcel Holtmann 1552a9de9248SMarcel Holtmann if (!ev->status) { 1553a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 1554769be974SMarcel Holtmann 1555769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 1556769be974SMarcel Holtmann conn->state = BT_CONFIG; 1557769be974SMarcel Holtmann hci_conn_hold(conn); 1558052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 155948264f06SJohan Hedberg mgmt_connected(hdev, &ev->bdaddr, conn->type, 156048264f06SJohan Hedberg conn->dst_type); 1561769be974SMarcel Holtmann } else 1562a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 1563a9de9248SMarcel Holtmann 15649eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 15657d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 15667d0db0a3SMarcel Holtmann 1567a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 1568a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1569a9de9248SMarcel Holtmann 1570a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 1571a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1572a9de9248SMarcel Holtmann 1573a9de9248SMarcel Holtmann /* Get remote features */ 1574a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 1575a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 1576a9de9248SMarcel Holtmann cp.handle = ev->handle; 1577769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 1578769be974SMarcel Holtmann sizeof(cp), &cp); 157945bb4bf0SMarcel Holtmann } 1580a9de9248SMarcel Holtmann 1581a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 1582d095c1ebSAndrei Emeltchenko if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) { 1583a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 1584a9de9248SMarcel Holtmann cp.handle = ev->handle; 1585a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1586a8746417SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, 1587a8746417SMarcel Holtmann sizeof(cp), &cp); 1588a9de9248SMarcel Holtmann } 158917d5c04cSJohan Hedberg } else { 1590a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 159117d5c04cSJohan Hedberg if (conn->type == ACL_LINK) 1592744cf19eSJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 159348264f06SJohan Hedberg conn->dst_type, ev->status); 159417d5c04cSJohan Hedberg } 159545bb4bf0SMarcel Holtmann 1596e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 1597e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 159845bb4bf0SMarcel Holtmann 1599769be974SMarcel Holtmann if (ev->status) { 1600a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1601a9de9248SMarcel Holtmann hci_conn_del(conn); 1602c89b6e6bSMarcel Holtmann } else if (ev->link_type != ACL_LINK) 1603c89b6e6bSMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1604a9de9248SMarcel Holtmann 1605a9de9248SMarcel Holtmann unlock: 16061da177e4SLinus Torvalds hci_dev_unlock(hdev); 1607a9de9248SMarcel Holtmann 1608a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 16091da177e4SLinus Torvalds } 16101da177e4SLinus Torvalds 16111da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 16121da177e4SLinus Torvalds { 1613a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 16141da177e4SLinus Torvalds int mask = hdev->link_mode; 16151da177e4SLinus Torvalds 1616a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s type 0x%x", hdev->name, 16171da177e4SLinus Torvalds batostr(&ev->bdaddr), ev->link_type); 16181da177e4SLinus Torvalds 16191da177e4SLinus Torvalds mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); 16201da177e4SLinus Torvalds 1621138d22efSSzymon Janc if ((mask & HCI_LM_ACCEPT) && 1622138d22efSSzymon Janc !hci_blacklist_lookup(hdev, &ev->bdaddr)) { 16231da177e4SLinus Torvalds /* Connection accepted */ 1624c7bdd502SMarcel Holtmann struct inquiry_entry *ie; 16251da177e4SLinus Torvalds struct hci_conn *conn; 16261da177e4SLinus Torvalds 16271da177e4SLinus Torvalds hci_dev_lock(hdev); 1628b6a0dc82SMarcel Holtmann 1629cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 1630cc11b9c1SAndrei Emeltchenko if (ie) 1631c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 1632c7bdd502SMarcel Holtmann 16331da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 16341da177e4SLinus Torvalds if (!conn) { 1635cc11b9c1SAndrei Emeltchenko conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); 1636cc11b9c1SAndrei Emeltchenko if (!conn) { 1637893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 16381da177e4SLinus Torvalds hci_dev_unlock(hdev); 16391da177e4SLinus Torvalds return; 16401da177e4SLinus Torvalds } 16411da177e4SLinus Torvalds } 1642b6a0dc82SMarcel Holtmann 16431da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 16441da177e4SLinus Torvalds conn->state = BT_CONNECT; 1645b6a0dc82SMarcel Holtmann 16461da177e4SLinus Torvalds hci_dev_unlock(hdev); 16471da177e4SLinus Torvalds 1648b6a0dc82SMarcel Holtmann if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) { 1649b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 1650b6a0dc82SMarcel Holtmann 16511da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 16521da177e4SLinus Torvalds 16531da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 16541da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 16551da177e4SLinus Torvalds else 16561da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 16571da177e4SLinus Torvalds 1658b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, 1659b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1660b6a0dc82SMarcel Holtmann } else { 1661b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 1662b6a0dc82SMarcel Holtmann 1663b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 1664a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1665b6a0dc82SMarcel Holtmann 1666b6a0dc82SMarcel Holtmann cp.tx_bandwidth = cpu_to_le32(0x00001f40); 1667b6a0dc82SMarcel Holtmann cp.rx_bandwidth = cpu_to_le32(0x00001f40); 1668b6a0dc82SMarcel Holtmann cp.max_latency = cpu_to_le16(0xffff); 1669b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 1670b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 1671b6a0dc82SMarcel Holtmann 1672b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 1673b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1674b6a0dc82SMarcel Holtmann } 16751da177e4SLinus Torvalds } else { 16761da177e4SLinus Torvalds /* Connection rejected */ 16771da177e4SLinus Torvalds struct hci_cp_reject_conn_req cp; 16781da177e4SLinus Torvalds 16791da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 16809f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_REJ_BAD_ADDR; 1681a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 16821da177e4SLinus Torvalds } 16831da177e4SLinus Torvalds } 16841da177e4SLinus Torvalds 16851da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 16861da177e4SLinus Torvalds { 1687a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 168804837f64SMarcel Holtmann struct hci_conn *conn; 16891da177e4SLinus Torvalds 16901da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 16911da177e4SLinus Torvalds 16921da177e4SLinus Torvalds hci_dev_lock(hdev); 16931da177e4SLinus Torvalds 169404837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1695f7520543SJohan Hedberg if (!conn) 1696f7520543SJohan Hedberg goto unlock; 1697f7520543SJohan Hedberg 169837d9ef76SJohan Hedberg if (ev->status == 0) 16991da177e4SLinus Torvalds conn->state = BT_CLOSED; 17007d0db0a3SMarcel Holtmann 170137d9ef76SJohan Hedberg if (conn->type == ACL_LINK || conn->type == LE_LINK) { 170237d9ef76SJohan Hedberg if (ev->status != 0) 170337d9ef76SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, ev->status); 170437d9ef76SJohan Hedberg else 170548264f06SJohan Hedberg mgmt_disconnected(hdev, &conn->dst, conn->type, 170648264f06SJohan Hedberg conn->dst_type); 170737d9ef76SJohan Hedberg } 1708f7520543SJohan Hedberg 170937d9ef76SJohan Hedberg if (ev->status == 0) { 17102950f21aSMarcel Holtmann hci_proto_disconn_cfm(conn, ev->reason); 17111da177e4SLinus Torvalds hci_conn_del(conn); 171237d9ef76SJohan Hedberg } 17131da177e4SLinus Torvalds 1714f7520543SJohan Hedberg unlock: 17151da177e4SLinus Torvalds hci_dev_unlock(hdev); 17161da177e4SLinus Torvalds } 17171da177e4SLinus Torvalds 1718a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1719a9de9248SMarcel Holtmann { 1720a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 1721a9de9248SMarcel Holtmann struct hci_conn *conn; 1722a9de9248SMarcel Holtmann 1723a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1724a9de9248SMarcel Holtmann 1725a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1726a9de9248SMarcel Holtmann 1727a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1728d7556e20SWaldemar Rymarkiewicz if (!conn) 1729d7556e20SWaldemar Rymarkiewicz goto unlock; 1730d7556e20SWaldemar Rymarkiewicz 1731765c2a96SJohan Hedberg if (!ev->status) { 173219f8def0SWaldemar Rymarkiewicz if (!(conn->ssp_mode > 0 && hdev->ssp_mode > 0) && 1733d7556e20SWaldemar Rymarkiewicz test_bit(HCI_CONN_REAUTH_PEND, &conn->pend)) { 1734d7556e20SWaldemar Rymarkiewicz BT_INFO("re-auth of legacy device is not possible."); 173519f8def0SWaldemar Rymarkiewicz } else { 1736a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1737765c2a96SJohan Hedberg conn->sec_level = conn->pending_sec_level; 173819f8def0SWaldemar Rymarkiewicz } 17392a611692SJohan Hedberg } else { 1740744cf19eSJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, ev->status); 17412a611692SJohan Hedberg } 1742a9de9248SMarcel Holtmann 1743a9de9248SMarcel Holtmann clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); 174419f8def0SWaldemar Rymarkiewicz clear_bit(HCI_CONN_REAUTH_PEND, &conn->pend); 1745a9de9248SMarcel Holtmann 1746f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1747d7556e20SWaldemar Rymarkiewicz if (!ev->status && hdev->ssp_mode > 0 && conn->ssp_mode > 0) { 1748f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1749f8558555SMarcel Holtmann cp.handle = ev->handle; 1750f8558555SMarcel Holtmann cp.encrypt = 0x01; 1751d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1752d7556e20SWaldemar Rymarkiewicz &cp); 1753f8558555SMarcel Holtmann } else { 1754f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1755f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1756f8558555SMarcel Holtmann hci_conn_put(conn); 1757f8558555SMarcel Holtmann } 1758052b30b0SMarcel Holtmann } else { 1759a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 1760a9de9248SMarcel Holtmann 1761052b30b0SMarcel Holtmann hci_conn_hold(conn); 1762052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1763052b30b0SMarcel Holtmann hci_conn_put(conn); 1764052b30b0SMarcel Holtmann } 1765052b30b0SMarcel Holtmann 1766a9de9248SMarcel Holtmann if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) { 1767a9de9248SMarcel Holtmann if (!ev->status) { 1768a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1769f8558555SMarcel Holtmann cp.handle = ev->handle; 1770f8558555SMarcel Holtmann cp.encrypt = 0x01; 1771d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1772d7556e20SWaldemar Rymarkiewicz &cp); 1773a9de9248SMarcel Holtmann } else { 1774a9de9248SMarcel Holtmann clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); 1775a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 1776a9de9248SMarcel Holtmann } 1777a9de9248SMarcel Holtmann } 1778a9de9248SMarcel Holtmann 1779d7556e20SWaldemar Rymarkiewicz unlock: 1780a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1781a9de9248SMarcel Holtmann } 1782a9de9248SMarcel Holtmann 1783a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 1784a9de9248SMarcel Holtmann { 1785127178d2SJohan Hedberg struct hci_ev_remote_name *ev = (void *) skb->data; 1786127178d2SJohan Hedberg struct hci_conn *conn; 1787127178d2SJohan Hedberg 1788a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1789a9de9248SMarcel Holtmann 1790a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 1791127178d2SJohan Hedberg 1792127178d2SJohan Hedberg hci_dev_lock(hdev); 1793127178d2SJohan Hedberg 1794a88a9652SJohan Hedberg if (ev->status == 0 && test_bit(HCI_MGMT, &hdev->flags)) 1795744cf19eSJohan Hedberg mgmt_remote_name(hdev, &ev->bdaddr, ev->name); 1796a88a9652SJohan Hedberg 1797127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 179879c6c70cSJohan Hedberg if (!conn) 179979c6c70cSJohan Hedberg goto unlock; 180079c6c70cSJohan Hedberg 180179c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 180279c6c70cSJohan Hedberg goto unlock; 180379c6c70cSJohan Hedberg 180479c6c70cSJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { 1805127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1806127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1807127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1808127178d2SJohan Hedberg } 1809127178d2SJohan Hedberg 181079c6c70cSJohan Hedberg unlock: 1811127178d2SJohan Hedberg hci_dev_unlock(hdev); 1812a9de9248SMarcel Holtmann } 1813a9de9248SMarcel Holtmann 1814a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 1815a9de9248SMarcel Holtmann { 1816a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 1817a9de9248SMarcel Holtmann struct hci_conn *conn; 1818a9de9248SMarcel Holtmann 1819a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1820a9de9248SMarcel Holtmann 1821a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1822a9de9248SMarcel Holtmann 1823a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1824a9de9248SMarcel Holtmann if (conn) { 1825a9de9248SMarcel Holtmann if (!ev->status) { 1826ae293196SMarcel Holtmann if (ev->encrypt) { 1827ae293196SMarcel Holtmann /* Encryption implies authentication */ 1828ae293196SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1829a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1830da85e5e5SVinicius Costa Gomes conn->sec_level = conn->pending_sec_level; 1831ae293196SMarcel Holtmann } else 1832a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_ENCRYPT; 1833a9de9248SMarcel Holtmann } 1834a9de9248SMarcel Holtmann 1835a9de9248SMarcel Holtmann clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); 1836a9de9248SMarcel Holtmann 1837f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1838f8558555SMarcel Holtmann if (!ev->status) 1839f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1840f8558555SMarcel Holtmann 1841f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1842f8558555SMarcel Holtmann hci_conn_put(conn); 1843f8558555SMarcel Holtmann } else 1844a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 1845a9de9248SMarcel Holtmann } 1846a9de9248SMarcel Holtmann 1847a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1848a9de9248SMarcel Holtmann } 1849a9de9248SMarcel Holtmann 1850a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1851a9de9248SMarcel Holtmann { 1852a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 1853a9de9248SMarcel Holtmann struct hci_conn *conn; 1854a9de9248SMarcel Holtmann 1855a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1856a9de9248SMarcel Holtmann 1857a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1858a9de9248SMarcel Holtmann 1859a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1860a9de9248SMarcel Holtmann if (conn) { 1861a9de9248SMarcel Holtmann if (!ev->status) 1862a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_SECURE; 1863a9de9248SMarcel Holtmann 1864a9de9248SMarcel Holtmann clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); 1865a9de9248SMarcel Holtmann 1866a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 1867a9de9248SMarcel Holtmann } 1868a9de9248SMarcel Holtmann 1869a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1870a9de9248SMarcel Holtmann } 1871a9de9248SMarcel Holtmann 1872a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 1873a9de9248SMarcel Holtmann { 1874a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 1875a9de9248SMarcel Holtmann struct hci_conn *conn; 1876a9de9248SMarcel Holtmann 1877a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1878a9de9248SMarcel Holtmann 1879a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1880a9de9248SMarcel Holtmann 1881a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1882ccd556feSJohan Hedberg if (!conn) 1883ccd556feSJohan Hedberg goto unlock; 1884ccd556feSJohan Hedberg 1885769be974SMarcel Holtmann if (!ev->status) 1886a9de9248SMarcel Holtmann memcpy(conn->features, ev->features, 8); 1887a9de9248SMarcel Holtmann 1888ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 1889ccd556feSJohan Hedberg goto unlock; 1890ccd556feSJohan Hedberg 1891ccd556feSJohan Hedberg if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { 1892769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 1893769be974SMarcel Holtmann cp.handle = ev->handle; 1894769be974SMarcel Holtmann cp.page = 0x01; 1895ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 1896769be974SMarcel Holtmann sizeof(cp), &cp); 1897392599b9SJohan Hedberg goto unlock; 1898392599b9SJohan Hedberg } 1899392599b9SJohan Hedberg 1900127178d2SJohan Hedberg if (!ev->status) { 1901127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 1902127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 1903127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 1904127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 1905127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 1906127178d2SJohan Hedberg } 1907392599b9SJohan Hedberg 1908127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 1909769be974SMarcel Holtmann conn->state = BT_CONNECTED; 1910769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1911769be974SMarcel Holtmann hci_conn_put(conn); 1912769be974SMarcel Holtmann } 1913769be974SMarcel Holtmann 1914ccd556feSJohan Hedberg unlock: 1915a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1916a9de9248SMarcel Holtmann } 1917a9de9248SMarcel Holtmann 1918a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) 1919a9de9248SMarcel Holtmann { 1920a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1921a9de9248SMarcel Holtmann } 1922a9de9248SMarcel Holtmann 1923a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1924a9de9248SMarcel Holtmann { 1925a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1926a9de9248SMarcel Holtmann } 1927a9de9248SMarcel Holtmann 1928a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1929a9de9248SMarcel Holtmann { 1930a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 1931a9de9248SMarcel Holtmann __u16 opcode; 1932a9de9248SMarcel Holtmann 1933a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 1934a9de9248SMarcel Holtmann 1935a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 1936a9de9248SMarcel Holtmann 1937a9de9248SMarcel Holtmann switch (opcode) { 1938a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 1939a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 1940a9de9248SMarcel Holtmann break; 1941a9de9248SMarcel Holtmann 1942a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 1943a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 1944a9de9248SMarcel Holtmann break; 1945a9de9248SMarcel Holtmann 1946a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 1947a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 1948a9de9248SMarcel Holtmann break; 1949a9de9248SMarcel Holtmann 1950a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 1951a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 1952a9de9248SMarcel Holtmann break; 1953a9de9248SMarcel Holtmann 1954e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 1955e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 1956e4e8e37cSMarcel Holtmann break; 1957e4e8e37cSMarcel Holtmann 1958a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 1959a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 1960a9de9248SMarcel Holtmann break; 1961a9de9248SMarcel Holtmann 1962e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 1963e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 1964e4e8e37cSMarcel Holtmann break; 1965e4e8e37cSMarcel Holtmann 1966e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 1967e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 1968e4e8e37cSMarcel Holtmann break; 1969e4e8e37cSMarcel Holtmann 1970a9de9248SMarcel Holtmann case HCI_OP_RESET: 1971a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 1972a9de9248SMarcel Holtmann break; 1973a9de9248SMarcel Holtmann 1974a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 1975a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 1976a9de9248SMarcel Holtmann break; 1977a9de9248SMarcel Holtmann 1978a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 1979a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 1980a9de9248SMarcel Holtmann break; 1981a9de9248SMarcel Holtmann 1982a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 1983a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 1984a9de9248SMarcel Holtmann break; 1985a9de9248SMarcel Holtmann 1986a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 1987a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 1988a9de9248SMarcel Holtmann break; 1989a9de9248SMarcel Holtmann 1990a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 1991a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 1992a9de9248SMarcel Holtmann break; 1993a9de9248SMarcel Holtmann 1994a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 1995a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 1996a9de9248SMarcel Holtmann break; 1997a9de9248SMarcel Holtmann 1998a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 1999a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 2000a9de9248SMarcel Holtmann break; 2001a9de9248SMarcel Holtmann 2002a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 2003a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 2004a9de9248SMarcel Holtmann break; 2005a9de9248SMarcel Holtmann 2006a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 2007a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 2008a9de9248SMarcel Holtmann break; 2009a9de9248SMarcel Holtmann 2010a9de9248SMarcel Holtmann case HCI_OP_HOST_BUFFER_SIZE: 2011a9de9248SMarcel Holtmann hci_cc_host_buffer_size(hdev, skb); 2012a9de9248SMarcel Holtmann break; 2013a9de9248SMarcel Holtmann 2014333140b5SMarcel Holtmann case HCI_OP_READ_SSP_MODE: 2015333140b5SMarcel Holtmann hci_cc_read_ssp_mode(hdev, skb); 2016333140b5SMarcel Holtmann break; 2017333140b5SMarcel Holtmann 2018333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 2019333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 2020333140b5SMarcel Holtmann break; 2021333140b5SMarcel Holtmann 2022a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 2023a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 2024a9de9248SMarcel Holtmann break; 2025a9de9248SMarcel Holtmann 2026a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 2027a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 2028a9de9248SMarcel Holtmann break; 2029a9de9248SMarcel Holtmann 2030a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 2031a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 2032a9de9248SMarcel Holtmann break; 2033a9de9248SMarcel Holtmann 2034971e3a4bSAndre Guedes case HCI_OP_READ_LOCAL_EXT_FEATURES: 2035971e3a4bSAndre Guedes hci_cc_read_local_ext_features(hdev, skb); 2036971e3a4bSAndre Guedes break; 2037971e3a4bSAndre Guedes 2038a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 2039a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 2040a9de9248SMarcel Holtmann break; 2041a9de9248SMarcel Holtmann 2042a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 2043a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 2044a9de9248SMarcel Holtmann break; 2045a9de9248SMarcel Holtmann 2046350ee4cfSAndrei Emeltchenko case HCI_OP_READ_DATA_BLOCK_SIZE: 2047350ee4cfSAndrei Emeltchenko hci_cc_read_data_block_size(hdev, skb); 2048350ee4cfSAndrei Emeltchenko break; 2049350ee4cfSAndrei Emeltchenko 205023bb5763SJohan Hedberg case HCI_OP_WRITE_CA_TIMEOUT: 205123bb5763SJohan Hedberg hci_cc_write_ca_timeout(hdev, skb); 205223bb5763SJohan Hedberg break; 205323bb5763SJohan Hedberg 20541e89cffbSAndrei Emeltchenko case HCI_OP_READ_FLOW_CONTROL_MODE: 20551e89cffbSAndrei Emeltchenko hci_cc_read_flow_control_mode(hdev, skb); 20561e89cffbSAndrei Emeltchenko break; 20571e89cffbSAndrei Emeltchenko 2058928abaa7SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_INFO: 2059928abaa7SAndrei Emeltchenko hci_cc_read_local_amp_info(hdev, skb); 2060928abaa7SAndrei Emeltchenko break; 2061928abaa7SAndrei Emeltchenko 2062b0916ea0SJohan Hedberg case HCI_OP_DELETE_STORED_LINK_KEY: 2063b0916ea0SJohan Hedberg hci_cc_delete_stored_link_key(hdev, skb); 2064b0916ea0SJohan Hedberg break; 2065b0916ea0SJohan Hedberg 2066d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_MASK: 2067d5859e22SJohan Hedberg hci_cc_set_event_mask(hdev, skb); 2068d5859e22SJohan Hedberg break; 2069d5859e22SJohan Hedberg 2070d5859e22SJohan Hedberg case HCI_OP_WRITE_INQUIRY_MODE: 2071d5859e22SJohan Hedberg hci_cc_write_inquiry_mode(hdev, skb); 2072d5859e22SJohan Hedberg break; 2073d5859e22SJohan Hedberg 2074d5859e22SJohan Hedberg case HCI_OP_READ_INQ_RSP_TX_POWER: 2075d5859e22SJohan Hedberg hci_cc_read_inq_rsp_tx_power(hdev, skb); 2076d5859e22SJohan Hedberg break; 2077d5859e22SJohan Hedberg 2078d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_FLT: 2079d5859e22SJohan Hedberg hci_cc_set_event_flt(hdev, skb); 2080d5859e22SJohan Hedberg break; 2081d5859e22SJohan Hedberg 2082980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_REPLY: 2083980e1a53SJohan Hedberg hci_cc_pin_code_reply(hdev, skb); 2084980e1a53SJohan Hedberg break; 2085980e1a53SJohan Hedberg 2086980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_NEG_REPLY: 2087980e1a53SJohan Hedberg hci_cc_pin_code_neg_reply(hdev, skb); 2088980e1a53SJohan Hedberg break; 2089980e1a53SJohan Hedberg 2090c35938b2SSzymon Janc case HCI_OP_READ_LOCAL_OOB_DATA: 2091c35938b2SSzymon Janc hci_cc_read_local_oob_data_reply(hdev, skb); 2092c35938b2SSzymon Janc break; 2093c35938b2SSzymon Janc 20946ed58ec5SVille Tervo case HCI_OP_LE_READ_BUFFER_SIZE: 20956ed58ec5SVille Tervo hci_cc_le_read_buffer_size(hdev, skb); 20966ed58ec5SVille Tervo break; 20976ed58ec5SVille Tervo 2098a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_REPLY: 2099a5c29683SJohan Hedberg hci_cc_user_confirm_reply(hdev, skb); 2100a5c29683SJohan Hedberg break; 2101a5c29683SJohan Hedberg 2102a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_NEG_REPLY: 2103a5c29683SJohan Hedberg hci_cc_user_confirm_neg_reply(hdev, skb); 2104a5c29683SJohan Hedberg break; 2105a5c29683SJohan Hedberg 21061143d458SBrian Gix case HCI_OP_USER_PASSKEY_REPLY: 21071143d458SBrian Gix hci_cc_user_passkey_reply(hdev, skb); 21081143d458SBrian Gix break; 21091143d458SBrian Gix 21101143d458SBrian Gix case HCI_OP_USER_PASSKEY_NEG_REPLY: 21111143d458SBrian Gix hci_cc_user_passkey_neg_reply(hdev, skb); 211207f7fa5dSAndre Guedes 211307f7fa5dSAndre Guedes case HCI_OP_LE_SET_SCAN_PARAM: 211407f7fa5dSAndre Guedes hci_cc_le_set_scan_param(hdev, skb); 21151143d458SBrian Gix break; 21161143d458SBrian Gix 2117eb9d91f5SAndre Guedes case HCI_OP_LE_SET_SCAN_ENABLE: 2118eb9d91f5SAndre Guedes hci_cc_le_set_scan_enable(hdev, skb); 2119eb9d91f5SAndre Guedes break; 2120eb9d91f5SAndre Guedes 2121a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_REPLY: 2122a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_reply(hdev, skb); 2123a7a595f6SVinicius Costa Gomes break; 2124a7a595f6SVinicius Costa Gomes 2125a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_NEG_REPLY: 2126a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_neg_reply(hdev, skb); 2127a7a595f6SVinicius Costa Gomes break; 2128a7a595f6SVinicius Costa Gomes 2129f9b49306SAndre Guedes case HCI_OP_WRITE_LE_HOST_SUPPORTED: 2130f9b49306SAndre Guedes hci_cc_write_le_host_supported(hdev, skb); 2131f9b49306SAndre Guedes break; 2132f9b49306SAndre Guedes 2133a9de9248SMarcel Holtmann default: 2134a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 2135a9de9248SMarcel Holtmann break; 2136a9de9248SMarcel Holtmann } 2137a9de9248SMarcel Holtmann 21386bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 21396bd32326SVille Tervo del_timer(&hdev->cmd_timer); 21406bd32326SVille Tervo 2141a9de9248SMarcel Holtmann if (ev->ncmd) { 2142a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2143a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2144c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2145a9de9248SMarcel Holtmann } 2146a9de9248SMarcel Holtmann } 2147a9de9248SMarcel Holtmann 2148a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 2149a9de9248SMarcel Holtmann { 2150a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 2151a9de9248SMarcel Holtmann __u16 opcode; 2152a9de9248SMarcel Holtmann 2153a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2154a9de9248SMarcel Holtmann 2155a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2156a9de9248SMarcel Holtmann 2157a9de9248SMarcel Holtmann switch (opcode) { 2158a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 2159a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 2160a9de9248SMarcel Holtmann break; 2161a9de9248SMarcel Holtmann 2162a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 2163a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 2164a9de9248SMarcel Holtmann break; 2165a9de9248SMarcel Holtmann 2166a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 2167a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 2168a9de9248SMarcel Holtmann break; 2169a9de9248SMarcel Holtmann 2170f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 2171f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 2172f8558555SMarcel Holtmann break; 2173f8558555SMarcel Holtmann 2174f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 2175f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 2176f8558555SMarcel Holtmann break; 2177f8558555SMarcel Holtmann 2178a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 2179a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 2180a9de9248SMarcel Holtmann break; 2181a9de9248SMarcel Holtmann 2182769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 2183769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 2184769be974SMarcel Holtmann break; 2185769be974SMarcel Holtmann 2186769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 2187769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 2188769be974SMarcel Holtmann break; 2189769be974SMarcel Holtmann 2190a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 2191a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 2192a9de9248SMarcel Holtmann break; 2193a9de9248SMarcel Holtmann 2194a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 2195a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 2196a9de9248SMarcel Holtmann break; 2197a9de9248SMarcel Holtmann 2198a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 2199a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 2200a9de9248SMarcel Holtmann break; 2201a9de9248SMarcel Holtmann 22028962ee74SJohan Hedberg case HCI_OP_DISCONNECT: 22038962ee74SJohan Hedberg if (ev->status != 0) 220437d9ef76SJohan Hedberg mgmt_disconnect_failed(hdev, NULL, ev->status); 22058962ee74SJohan Hedberg break; 22068962ee74SJohan Hedberg 2207fcd89c09SVille Tervo case HCI_OP_LE_CREATE_CONN: 2208fcd89c09SVille Tervo hci_cs_le_create_conn(hdev, ev->status); 2209fcd89c09SVille Tervo break; 2210fcd89c09SVille Tervo 2211a7a595f6SVinicius Costa Gomes case HCI_OP_LE_START_ENC: 2212a7a595f6SVinicius Costa Gomes hci_cs_le_start_enc(hdev, ev->status); 2213a7a595f6SVinicius Costa Gomes break; 2214a7a595f6SVinicius Costa Gomes 2215a9de9248SMarcel Holtmann default: 2216a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 2217a9de9248SMarcel Holtmann break; 2218a9de9248SMarcel Holtmann } 2219a9de9248SMarcel Holtmann 22206bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 22216bd32326SVille Tervo del_timer(&hdev->cmd_timer); 22226bd32326SVille Tervo 222310572132SGustavo F. Padovan if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2224a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2225a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2226c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2227a9de9248SMarcel Holtmann } 2228a9de9248SMarcel Holtmann } 2229a9de9248SMarcel Holtmann 2230a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2231a9de9248SMarcel Holtmann { 2232a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 2233a9de9248SMarcel Holtmann struct hci_conn *conn; 2234a9de9248SMarcel Holtmann 2235a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2236a9de9248SMarcel Holtmann 2237a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2238a9de9248SMarcel Holtmann 2239a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2240a9de9248SMarcel Holtmann if (conn) { 2241a9de9248SMarcel Holtmann if (!ev->status) { 2242a9de9248SMarcel Holtmann if (ev->role) 2243a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_MASTER; 2244a9de9248SMarcel Holtmann else 2245a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_MASTER; 2246a9de9248SMarcel Holtmann } 2247a9de9248SMarcel Holtmann 2248a9de9248SMarcel Holtmann clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend); 2249a9de9248SMarcel Holtmann 2250a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 2251a9de9248SMarcel Holtmann } 2252a9de9248SMarcel Holtmann 2253a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2254a9de9248SMarcel Holtmann } 2255a9de9248SMarcel Holtmann 22561da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 22571da177e4SLinus Torvalds { 2258a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 22591ebb9252SMarcel Holtmann __le16 *ptr; 22601da177e4SLinus Torvalds int i; 22611da177e4SLinus Torvalds 22621da177e4SLinus Torvalds skb_pull(skb, sizeof(*ev)); 22631da177e4SLinus Torvalds 22641da177e4SLinus Torvalds BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 22651da177e4SLinus Torvalds 22661da177e4SLinus Torvalds if (skb->len < ev->num_hndl * 4) { 22671da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 22681da177e4SLinus Torvalds return; 22691da177e4SLinus Torvalds } 22701da177e4SLinus Torvalds 22711ebb9252SMarcel Holtmann for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) { 22721da177e4SLinus Torvalds struct hci_conn *conn; 22731da177e4SLinus Torvalds __u16 handle, count; 22741da177e4SLinus Torvalds 227583985319SHarvey Harrison handle = get_unaligned_le16(ptr++); 227683985319SHarvey Harrison count = get_unaligned_le16(ptr++); 22771da177e4SLinus Torvalds 22781da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 2279f4280918SAndrei Emeltchenko if (!conn) 2280f4280918SAndrei Emeltchenko continue; 2281f4280918SAndrei Emeltchenko 22821da177e4SLinus Torvalds conn->sent -= count; 22831da177e4SLinus Torvalds 2284f4280918SAndrei Emeltchenko switch (conn->type) { 2285f4280918SAndrei Emeltchenko case ACL_LINK: 228670f23020SAndrei Emeltchenko hdev->acl_cnt += count; 228770f23020SAndrei Emeltchenko if (hdev->acl_cnt > hdev->acl_pkts) 22881da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 2289f4280918SAndrei Emeltchenko break; 2290f4280918SAndrei Emeltchenko 2291f4280918SAndrei Emeltchenko case LE_LINK: 22926ed58ec5SVille Tervo if (hdev->le_pkts) { 22936ed58ec5SVille Tervo hdev->le_cnt += count; 22946ed58ec5SVille Tervo if (hdev->le_cnt > hdev->le_pkts) 22956ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 22966ed58ec5SVille Tervo } else { 22976ed58ec5SVille Tervo hdev->acl_cnt += count; 22986ed58ec5SVille Tervo if (hdev->acl_cnt > hdev->acl_pkts) 22996ed58ec5SVille Tervo hdev->acl_cnt = hdev->acl_pkts; 23006ed58ec5SVille Tervo } 2301f4280918SAndrei Emeltchenko break; 2302f4280918SAndrei Emeltchenko 2303f4280918SAndrei Emeltchenko case SCO_LINK: 230470f23020SAndrei Emeltchenko hdev->sco_cnt += count; 230570f23020SAndrei Emeltchenko if (hdev->sco_cnt > hdev->sco_pkts) 23065b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 2307f4280918SAndrei Emeltchenko break; 2308f4280918SAndrei Emeltchenko 2309f4280918SAndrei Emeltchenko default: 2310f4280918SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 2311f4280918SAndrei Emeltchenko break; 23121da177e4SLinus Torvalds } 23131da177e4SLinus Torvalds } 2314a9de9248SMarcel Holtmann 23153eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 23161da177e4SLinus Torvalds } 23171da177e4SLinus Torvalds 231804837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 23191da177e4SLinus Torvalds { 2320a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 232104837f64SMarcel Holtmann struct hci_conn *conn; 23221da177e4SLinus Torvalds 23231da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 23241da177e4SLinus Torvalds 23251da177e4SLinus Torvalds hci_dev_lock(hdev); 23261da177e4SLinus Torvalds 232704837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 232804837f64SMarcel Holtmann if (conn) { 232904837f64SMarcel Holtmann conn->mode = ev->mode; 233004837f64SMarcel Holtmann conn->interval = __le16_to_cpu(ev->interval); 233104837f64SMarcel Holtmann 233204837f64SMarcel Holtmann if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) { 233304837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 233404837f64SMarcel Holtmann conn->power_save = 1; 233504837f64SMarcel Holtmann else 233604837f64SMarcel Holtmann conn->power_save = 0; 233704837f64SMarcel Holtmann } 2338e73439d8SMarcel Holtmann 2339e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 2340e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 234104837f64SMarcel Holtmann } 234204837f64SMarcel Holtmann 234304837f64SMarcel Holtmann hci_dev_unlock(hdev); 234404837f64SMarcel Holtmann } 234504837f64SMarcel Holtmann 23461da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 23471da177e4SLinus Torvalds { 2348052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 2349052b30b0SMarcel Holtmann struct hci_conn *conn; 2350052b30b0SMarcel Holtmann 2351a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2352052b30b0SMarcel Holtmann 2353052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2354052b30b0SMarcel Holtmann 2355052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2356b6f98044SWaldemar Rymarkiewicz if (!conn) 2357b6f98044SWaldemar Rymarkiewicz goto unlock; 2358b6f98044SWaldemar Rymarkiewicz 2359b6f98044SWaldemar Rymarkiewicz if (conn->state == BT_CONNECTED) { 2360052b30b0SMarcel Holtmann hci_conn_hold(conn); 2361052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 2362052b30b0SMarcel Holtmann hci_conn_put(conn); 2363052b30b0SMarcel Holtmann } 2364052b30b0SMarcel Holtmann 236503b555e1SJohan Hedberg if (!test_bit(HCI_PAIRABLE, &hdev->flags)) 236603b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 236703b555e1SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 2368582fbe9eSJohan Hedberg else if (test_bit(HCI_MGMT, &hdev->flags)) { 2369a770bb5aSWaldemar Rymarkiewicz u8 secure; 2370a770bb5aSWaldemar Rymarkiewicz 2371a770bb5aSWaldemar Rymarkiewicz if (conn->pending_sec_level == BT_SECURITY_HIGH) 2372a770bb5aSWaldemar Rymarkiewicz secure = 1; 2373a770bb5aSWaldemar Rymarkiewicz else 2374a770bb5aSWaldemar Rymarkiewicz secure = 0; 2375a770bb5aSWaldemar Rymarkiewicz 2376744cf19eSJohan Hedberg mgmt_pin_code_request(hdev, &ev->bdaddr, secure); 2377a770bb5aSWaldemar Rymarkiewicz } 2378980e1a53SJohan Hedberg 2379b6f98044SWaldemar Rymarkiewicz unlock: 2380052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 23811da177e4SLinus Torvalds } 23821da177e4SLinus Torvalds 23831da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 23841da177e4SLinus Torvalds { 238555ed8ca1SJohan Hedberg struct hci_ev_link_key_req *ev = (void *) skb->data; 238655ed8ca1SJohan Hedberg struct hci_cp_link_key_reply cp; 238755ed8ca1SJohan Hedberg struct hci_conn *conn; 238855ed8ca1SJohan Hedberg struct link_key *key; 238955ed8ca1SJohan Hedberg 2390a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 239155ed8ca1SJohan Hedberg 239255ed8ca1SJohan Hedberg if (!test_bit(HCI_LINK_KEYS, &hdev->flags)) 239355ed8ca1SJohan Hedberg return; 239455ed8ca1SJohan Hedberg 239555ed8ca1SJohan Hedberg hci_dev_lock(hdev); 239655ed8ca1SJohan Hedberg 239755ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, &ev->bdaddr); 239855ed8ca1SJohan Hedberg if (!key) { 239955ed8ca1SJohan Hedberg BT_DBG("%s link key not found for %s", hdev->name, 240055ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 240155ed8ca1SJohan Hedberg goto not_found; 240255ed8ca1SJohan Hedberg } 240355ed8ca1SJohan Hedberg 240455ed8ca1SJohan Hedberg BT_DBG("%s found key type %u for %s", hdev->name, key->type, 240555ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 240655ed8ca1SJohan Hedberg 2407b6020ba0SWaldemar Rymarkiewicz if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) && 2408b6020ba0SWaldemar Rymarkiewicz key->type == HCI_LK_DEBUG_COMBINATION) { 240955ed8ca1SJohan Hedberg BT_DBG("%s ignoring debug key", hdev->name); 241055ed8ca1SJohan Hedberg goto not_found; 241155ed8ca1SJohan Hedberg } 241255ed8ca1SJohan Hedberg 241355ed8ca1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 241460b83f57SWaldemar Rymarkiewicz if (conn) { 241560b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_UNAUTH_COMBINATION && 241660b83f57SWaldemar Rymarkiewicz conn->auth_type != 0xff && 241760b83f57SWaldemar Rymarkiewicz (conn->auth_type & 0x01)) { 241855ed8ca1SJohan Hedberg BT_DBG("%s ignoring unauthenticated key", hdev->name); 241955ed8ca1SJohan Hedberg goto not_found; 242055ed8ca1SJohan Hedberg } 242155ed8ca1SJohan Hedberg 242260b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && 242360b83f57SWaldemar Rymarkiewicz conn->pending_sec_level == BT_SECURITY_HIGH) { 242460b83f57SWaldemar Rymarkiewicz BT_DBG("%s ignoring key unauthenticated for high \ 242560b83f57SWaldemar Rymarkiewicz security", hdev->name); 242660b83f57SWaldemar Rymarkiewicz goto not_found; 242760b83f57SWaldemar Rymarkiewicz } 242860b83f57SWaldemar Rymarkiewicz 242960b83f57SWaldemar Rymarkiewicz conn->key_type = key->type; 243060b83f57SWaldemar Rymarkiewicz conn->pin_length = key->pin_len; 243160b83f57SWaldemar Rymarkiewicz } 243260b83f57SWaldemar Rymarkiewicz 243355ed8ca1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 243455ed8ca1SJohan Hedberg memcpy(cp.link_key, key->val, 16); 243555ed8ca1SJohan Hedberg 243655ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 243755ed8ca1SJohan Hedberg 243855ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 243955ed8ca1SJohan Hedberg 244055ed8ca1SJohan Hedberg return; 244155ed8ca1SJohan Hedberg 244255ed8ca1SJohan Hedberg not_found: 244355ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 244455ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 24451da177e4SLinus Torvalds } 24461da177e4SLinus Torvalds 24471da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 24481da177e4SLinus Torvalds { 2449052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 2450052b30b0SMarcel Holtmann struct hci_conn *conn; 245155ed8ca1SJohan Hedberg u8 pin_len = 0; 2452052b30b0SMarcel Holtmann 2453a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2454052b30b0SMarcel Holtmann 2455052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2456052b30b0SMarcel Holtmann 2457052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2458052b30b0SMarcel Holtmann if (conn) { 2459052b30b0SMarcel Holtmann hci_conn_hold(conn); 2460052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2461980e1a53SJohan Hedberg pin_len = conn->pin_length; 246213d39315SWaldemar Rymarkiewicz 246313d39315SWaldemar Rymarkiewicz if (ev->key_type != HCI_LK_CHANGED_COMBINATION) 246413d39315SWaldemar Rymarkiewicz conn->key_type = ev->key_type; 246513d39315SWaldemar Rymarkiewicz 2466052b30b0SMarcel Holtmann hci_conn_put(conn); 2467052b30b0SMarcel Holtmann } 2468052b30b0SMarcel Holtmann 246955ed8ca1SJohan Hedberg if (test_bit(HCI_LINK_KEYS, &hdev->flags)) 2470d25e28abSJohan Hedberg hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, 247155ed8ca1SJohan Hedberg ev->key_type, pin_len); 247255ed8ca1SJohan Hedberg 2473052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 24741da177e4SLinus Torvalds } 24751da177e4SLinus Torvalds 247604837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 247704837f64SMarcel Holtmann { 2478a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 247904837f64SMarcel Holtmann struct hci_conn *conn; 248004837f64SMarcel Holtmann 248104837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 248204837f64SMarcel Holtmann 248304837f64SMarcel Holtmann hci_dev_lock(hdev); 248404837f64SMarcel Holtmann 248504837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 24861da177e4SLinus Torvalds if (conn && !ev->status) { 24871da177e4SLinus Torvalds struct inquiry_entry *ie; 24881da177e4SLinus Torvalds 2489cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2490cc11b9c1SAndrei Emeltchenko if (ie) { 24911da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 24921da177e4SLinus Torvalds ie->timestamp = jiffies; 24931da177e4SLinus Torvalds } 24941da177e4SLinus Torvalds } 24951da177e4SLinus Torvalds 24961da177e4SLinus Torvalds hci_dev_unlock(hdev); 24971da177e4SLinus Torvalds } 24981da177e4SLinus Torvalds 2499a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2500a8746417SMarcel Holtmann { 2501a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 2502a8746417SMarcel Holtmann struct hci_conn *conn; 2503a8746417SMarcel Holtmann 2504a8746417SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2505a8746417SMarcel Holtmann 2506a8746417SMarcel Holtmann hci_dev_lock(hdev); 2507a8746417SMarcel Holtmann 2508a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2509a8746417SMarcel Holtmann if (conn && !ev->status) 2510a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 2511a8746417SMarcel Holtmann 2512a8746417SMarcel Holtmann hci_dev_unlock(hdev); 2513a8746417SMarcel Holtmann } 2514a8746417SMarcel Holtmann 251585a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 251685a1e930SMarcel Holtmann { 2517a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 251885a1e930SMarcel Holtmann struct inquiry_entry *ie; 251985a1e930SMarcel Holtmann 252085a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 252185a1e930SMarcel Holtmann 252285a1e930SMarcel Holtmann hci_dev_lock(hdev); 252385a1e930SMarcel Holtmann 2524cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2525cc11b9c1SAndrei Emeltchenko if (ie) { 252685a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 252785a1e930SMarcel Holtmann ie->timestamp = jiffies; 252885a1e930SMarcel Holtmann } 252985a1e930SMarcel Holtmann 253085a1e930SMarcel Holtmann hci_dev_unlock(hdev); 253185a1e930SMarcel Holtmann } 253285a1e930SMarcel Holtmann 2533a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb) 2534a9de9248SMarcel Holtmann { 2535a9de9248SMarcel Holtmann struct inquiry_data data; 2536a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2537a9de9248SMarcel Holtmann 2538a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2539a9de9248SMarcel Holtmann 2540a9de9248SMarcel Holtmann if (!num_rsp) 2541a9de9248SMarcel Holtmann return; 2542a9de9248SMarcel Holtmann 2543a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2544a9de9248SMarcel Holtmann 2545a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 2546138d22efSSzymon Janc struct inquiry_info_with_rssi_and_pscan_mode *info; 2547138d22efSSzymon Janc info = (void *) (skb->data + 1); 2548a9de9248SMarcel Holtmann 2549e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2550a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2551a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2552a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2553a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 2554a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2555a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2556a9de9248SMarcel Holtmann data.rssi = info->rssi; 255741a96212SMarcel Holtmann data.ssp_mode = 0x00; 2558a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 255948264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2560e17acd40SJohan Hedberg info->dev_class, info->rssi, 2561e17acd40SJohan Hedberg NULL); 2562a9de9248SMarcel Holtmann } 2563a9de9248SMarcel Holtmann } else { 2564a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *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 = 0x00; 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 } 2581a9de9248SMarcel Holtmann 2582a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2583a9de9248SMarcel Holtmann } 2584a9de9248SMarcel Holtmann 2585a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 2586a9de9248SMarcel Holtmann { 258741a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 258841a96212SMarcel Holtmann struct hci_conn *conn; 258941a96212SMarcel Holtmann 2590a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 259141a96212SMarcel Holtmann 259241a96212SMarcel Holtmann hci_dev_lock(hdev); 259341a96212SMarcel Holtmann 259441a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2595ccd556feSJohan Hedberg if (!conn) 2596ccd556feSJohan Hedberg goto unlock; 2597ccd556feSJohan Hedberg 2598769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 259941a96212SMarcel Holtmann struct inquiry_entry *ie; 260041a96212SMarcel Holtmann 2601cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2602cc11b9c1SAndrei Emeltchenko if (ie) 260341a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 260441a96212SMarcel Holtmann 260541a96212SMarcel Holtmann conn->ssp_mode = (ev->features[0] & 0x01); 260641a96212SMarcel Holtmann } 260741a96212SMarcel Holtmann 2608ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2609ccd556feSJohan Hedberg goto unlock; 2610ccd556feSJohan Hedberg 2611127178d2SJohan Hedberg if (!ev->status) { 2612127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2613127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2614127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2615127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2616127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2617127178d2SJohan Hedberg } 2618392599b9SJohan Hedberg 2619127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2620769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2621769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2622769be974SMarcel Holtmann hci_conn_put(conn); 2623769be974SMarcel Holtmann } 2624769be974SMarcel Holtmann 2625ccd556feSJohan Hedberg unlock: 262641a96212SMarcel Holtmann hci_dev_unlock(hdev); 2627a9de9248SMarcel Holtmann } 2628a9de9248SMarcel Holtmann 2629a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2630a9de9248SMarcel Holtmann { 2631b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 2632b6a0dc82SMarcel Holtmann struct hci_conn *conn; 2633b6a0dc82SMarcel Holtmann 2634b6a0dc82SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2635b6a0dc82SMarcel Holtmann 2636b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 2637b6a0dc82SMarcel Holtmann 2638b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 26399dc0a3afSMarcel Holtmann if (!conn) { 26409dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 26419dc0a3afSMarcel Holtmann goto unlock; 26429dc0a3afSMarcel Holtmann 26439dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 2644b6a0dc82SMarcel Holtmann if (!conn) 2645b6a0dc82SMarcel Holtmann goto unlock; 2646b6a0dc82SMarcel Holtmann 26479dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 26489dc0a3afSMarcel Holtmann } 26499dc0a3afSMarcel Holtmann 2650732547f9SMarcel Holtmann switch (ev->status) { 2651732547f9SMarcel Holtmann case 0x00: 2652732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 2653732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 2654732547f9SMarcel Holtmann 26559eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 2656732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 2657732547f9SMarcel Holtmann break; 2658732547f9SMarcel Holtmann 2659705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 2660732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 26611038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 2662732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 2663732547f9SMarcel Holtmann if (conn->out && conn->attempt < 2) { 2664efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 2665efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 2666efc7688bSMarcel Holtmann hci_setup_sync(conn, conn->link->handle); 2667efc7688bSMarcel Holtmann goto unlock; 2668efc7688bSMarcel Holtmann } 2669732547f9SMarcel Holtmann /* fall through */ 2670efc7688bSMarcel Holtmann 2671732547f9SMarcel Holtmann default: 2672b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 2673732547f9SMarcel Holtmann break; 2674732547f9SMarcel Holtmann } 2675b6a0dc82SMarcel Holtmann 2676b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2677b6a0dc82SMarcel Holtmann if (ev->status) 2678b6a0dc82SMarcel Holtmann hci_conn_del(conn); 2679b6a0dc82SMarcel Holtmann 2680b6a0dc82SMarcel Holtmann unlock: 2681b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 2682a9de9248SMarcel Holtmann } 2683a9de9248SMarcel Holtmann 2684a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) 2685a9de9248SMarcel Holtmann { 2686a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2687a9de9248SMarcel Holtmann } 2688a9de9248SMarcel Holtmann 268904837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) 269004837f64SMarcel Holtmann { 2691a9de9248SMarcel Holtmann struct hci_ev_sniff_subrate *ev = (void *) skb->data; 269204837f64SMarcel Holtmann 269304837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 269404837f64SMarcel Holtmann } 269504837f64SMarcel Holtmann 2696a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 2697a9de9248SMarcel Holtmann { 2698a9de9248SMarcel Holtmann struct inquiry_data data; 2699a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 2700a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2701a9de9248SMarcel Holtmann 2702a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2703a9de9248SMarcel Holtmann 2704a9de9248SMarcel Holtmann if (!num_rsp) 2705a9de9248SMarcel Holtmann return; 2706a9de9248SMarcel Holtmann 2707a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2708a9de9248SMarcel Holtmann 2709e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2710a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2711a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2712a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2713a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2714a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2715a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2716a9de9248SMarcel Holtmann data.rssi = info->rssi; 271741a96212SMarcel Holtmann data.ssp_mode = 0x01; 2718a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 271948264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 27204c659c39SJohan Hedberg info->dev_class, info->rssi, info->data); 2721a9de9248SMarcel Holtmann } 2722a9de9248SMarcel Holtmann 2723a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2724a9de9248SMarcel Holtmann } 2725a9de9248SMarcel Holtmann 272617fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn) 272717fa4b9dSJohan Hedberg { 272817fa4b9dSJohan Hedberg /* If remote requests dedicated bonding follow that lead */ 272917fa4b9dSJohan Hedberg if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) { 273017fa4b9dSJohan Hedberg /* If both remote and local IO capabilities allow MITM 273117fa4b9dSJohan Hedberg * protection then require it, otherwise don't */ 273217fa4b9dSJohan Hedberg if (conn->remote_cap == 0x03 || conn->io_capability == 0x03) 273317fa4b9dSJohan Hedberg return 0x02; 273417fa4b9dSJohan Hedberg else 273517fa4b9dSJohan Hedberg return 0x03; 273617fa4b9dSJohan Hedberg } 273717fa4b9dSJohan Hedberg 273817fa4b9dSJohan Hedberg /* If remote requests no-bonding follow that lead */ 273917fa4b9dSJohan Hedberg if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01) 274058797bf7SWaldemar Rymarkiewicz return conn->remote_auth | (conn->auth_type & 0x01); 274117fa4b9dSJohan Hedberg 274217fa4b9dSJohan Hedberg return conn->auth_type; 274317fa4b9dSJohan Hedberg } 274417fa4b9dSJohan Hedberg 27450493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 27460493684eSMarcel Holtmann { 27470493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 27480493684eSMarcel Holtmann struct hci_conn *conn; 27490493684eSMarcel Holtmann 27500493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 27510493684eSMarcel Holtmann 27520493684eSMarcel Holtmann hci_dev_lock(hdev); 27530493684eSMarcel Holtmann 27540493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 275503b555e1SJohan Hedberg if (!conn) 275603b555e1SJohan Hedberg goto unlock; 275703b555e1SJohan Hedberg 27580493684eSMarcel Holtmann hci_conn_hold(conn); 27590493684eSMarcel Holtmann 276003b555e1SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->flags)) 276103b555e1SJohan Hedberg goto unlock; 276203b555e1SJohan Hedberg 276303b555e1SJohan Hedberg if (test_bit(HCI_PAIRABLE, &hdev->flags) || 276403b555e1SJohan Hedberg (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 276517fa4b9dSJohan Hedberg struct hci_cp_io_capability_reply cp; 276617fa4b9dSJohan Hedberg 276717fa4b9dSJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 276817fa4b9dSJohan Hedberg cp.capability = conn->io_capability; 27697cbc9bd9SJohan Hedberg conn->auth_type = hci_get_auth_req(conn); 27707cbc9bd9SJohan Hedberg cp.authentication = conn->auth_type; 277117fa4b9dSJohan Hedberg 2772ce85ee13SSzymon Janc if ((conn->out == 0x01 || conn->remote_oob == 0x01) && 2773ce85ee13SSzymon Janc hci_find_remote_oob_data(hdev, &conn->dst)) 2774ce85ee13SSzymon Janc cp.oob_data = 0x01; 2775ce85ee13SSzymon Janc else 2776ce85ee13SSzymon Janc cp.oob_data = 0x00; 2777ce85ee13SSzymon Janc 277817fa4b9dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, 277917fa4b9dSJohan Hedberg sizeof(cp), &cp); 278003b555e1SJohan Hedberg } else { 278103b555e1SJohan Hedberg struct hci_cp_io_capability_neg_reply cp; 278203b555e1SJohan Hedberg 278303b555e1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 27849f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED; 278503b555e1SJohan Hedberg 278603b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 278703b555e1SJohan Hedberg sizeof(cp), &cp); 278803b555e1SJohan Hedberg } 278903b555e1SJohan Hedberg 279003b555e1SJohan Hedberg unlock: 279103b555e1SJohan Hedberg hci_dev_unlock(hdev); 279203b555e1SJohan Hedberg } 279303b555e1SJohan Hedberg 279403b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 279503b555e1SJohan Hedberg { 279603b555e1SJohan Hedberg struct hci_ev_io_capa_reply *ev = (void *) skb->data; 279703b555e1SJohan Hedberg struct hci_conn *conn; 279803b555e1SJohan Hedberg 279903b555e1SJohan Hedberg BT_DBG("%s", hdev->name); 280003b555e1SJohan Hedberg 280103b555e1SJohan Hedberg hci_dev_lock(hdev); 280203b555e1SJohan Hedberg 280303b555e1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 280403b555e1SJohan Hedberg if (!conn) 280503b555e1SJohan Hedberg goto unlock; 280603b555e1SJohan Hedberg 280703b555e1SJohan Hedberg conn->remote_cap = ev->capability; 280803b555e1SJohan Hedberg conn->remote_oob = ev->oob_data; 280903b555e1SJohan Hedberg conn->remote_auth = ev->authentication; 281003b555e1SJohan Hedberg 281103b555e1SJohan Hedberg unlock: 28120493684eSMarcel Holtmann hci_dev_unlock(hdev); 28130493684eSMarcel Holtmann } 28140493684eSMarcel Holtmann 2815a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev, 2816a5c29683SJohan Hedberg struct sk_buff *skb) 2817a5c29683SJohan Hedberg { 2818a5c29683SJohan Hedberg struct hci_ev_user_confirm_req *ev = (void *) skb->data; 281955bc1a37SJohan Hedberg int loc_mitm, rem_mitm, confirm_hint = 0; 28207a828908SJohan Hedberg struct hci_conn *conn; 2821a5c29683SJohan Hedberg 2822a5c29683SJohan Hedberg BT_DBG("%s", hdev->name); 2823a5c29683SJohan Hedberg 2824a5c29683SJohan Hedberg hci_dev_lock(hdev); 2825a5c29683SJohan Hedberg 28267a828908SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->flags)) 28277a828908SJohan Hedberg goto unlock; 28287a828908SJohan Hedberg 28297a828908SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 28307a828908SJohan Hedberg if (!conn) 28317a828908SJohan Hedberg goto unlock; 28327a828908SJohan Hedberg 28337a828908SJohan Hedberg loc_mitm = (conn->auth_type & 0x01); 28347a828908SJohan Hedberg rem_mitm = (conn->remote_auth & 0x01); 28357a828908SJohan Hedberg 28367a828908SJohan Hedberg /* If we require MITM but the remote device can't provide that 28377a828908SJohan Hedberg * (it has NoInputNoOutput) then reject the confirmation 28387a828908SJohan Hedberg * request. The only exception is when we're dedicated bonding 28397a828908SJohan Hedberg * initiators (connect_cfm_cb set) since then we always have the MITM 28407a828908SJohan Hedberg * bit set. */ 28417a828908SJohan Hedberg if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) { 28427a828908SJohan Hedberg BT_DBG("Rejecting request: remote device can't provide MITM"); 28437a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, 28447a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 28457a828908SJohan Hedberg goto unlock; 28467a828908SJohan Hedberg } 28477a828908SJohan Hedberg 28487a828908SJohan Hedberg /* If no side requires MITM protection; auto-accept */ 28497a828908SJohan Hedberg if ((!loc_mitm || conn->remote_cap == 0x03) && 28507a828908SJohan Hedberg (!rem_mitm || conn->io_capability == 0x03)) { 285155bc1a37SJohan Hedberg 285255bc1a37SJohan Hedberg /* If we're not the initiators request authorization to 285355bc1a37SJohan Hedberg * proceed from user space (mgmt_user_confirm with 285455bc1a37SJohan Hedberg * confirm_hint set to 1). */ 285555bc1a37SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { 285655bc1a37SJohan Hedberg BT_DBG("Confirming auto-accept as acceptor"); 285755bc1a37SJohan Hedberg confirm_hint = 1; 285855bc1a37SJohan Hedberg goto confirm; 285955bc1a37SJohan Hedberg } 286055bc1a37SJohan Hedberg 28619f61656aSJohan Hedberg BT_DBG("Auto-accept of user confirmation with %ums delay", 28629f61656aSJohan Hedberg hdev->auto_accept_delay); 28639f61656aSJohan Hedberg 28649f61656aSJohan Hedberg if (hdev->auto_accept_delay > 0) { 28659f61656aSJohan Hedberg int delay = msecs_to_jiffies(hdev->auto_accept_delay); 28669f61656aSJohan Hedberg mod_timer(&conn->auto_accept_timer, jiffies + delay); 28679f61656aSJohan Hedberg goto unlock; 28689f61656aSJohan Hedberg } 28699f61656aSJohan Hedberg 28707a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, 28717a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 28727a828908SJohan Hedberg goto unlock; 28737a828908SJohan Hedberg } 28747a828908SJohan Hedberg 287555bc1a37SJohan Hedberg confirm: 2876744cf19eSJohan Hedberg mgmt_user_confirm_request(hdev, &ev->bdaddr, ev->passkey, 287755bc1a37SJohan Hedberg confirm_hint); 2878a5c29683SJohan Hedberg 28797a828908SJohan Hedberg unlock: 2880a5c29683SJohan Hedberg hci_dev_unlock(hdev); 2881a5c29683SJohan Hedberg } 2882a5c29683SJohan Hedberg 28831143d458SBrian Gix static inline void hci_user_passkey_request_evt(struct hci_dev *hdev, 28841143d458SBrian Gix struct sk_buff *skb) 28851143d458SBrian Gix { 28861143d458SBrian Gix struct hci_ev_user_passkey_req *ev = (void *) skb->data; 28871143d458SBrian Gix 28881143d458SBrian Gix BT_DBG("%s", hdev->name); 28891143d458SBrian Gix 28901143d458SBrian Gix hci_dev_lock(hdev); 28911143d458SBrian Gix 28921143d458SBrian Gix if (test_bit(HCI_MGMT, &hdev->flags)) 28931143d458SBrian Gix mgmt_user_passkey_request(hdev, &ev->bdaddr); 28941143d458SBrian Gix 28951143d458SBrian Gix hci_dev_unlock(hdev); 28961143d458SBrian Gix } 28971143d458SBrian Gix 28980493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 28990493684eSMarcel Holtmann { 29000493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 29010493684eSMarcel Holtmann struct hci_conn *conn; 29020493684eSMarcel Holtmann 29030493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 29040493684eSMarcel Holtmann 29050493684eSMarcel Holtmann hci_dev_lock(hdev); 29060493684eSMarcel Holtmann 29070493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 29082a611692SJohan Hedberg if (!conn) 29092a611692SJohan Hedberg goto unlock; 29102a611692SJohan Hedberg 29112a611692SJohan Hedberg /* To avoid duplicate auth_failed events to user space we check 29122a611692SJohan Hedberg * the HCI_CONN_AUTH_PEND flag which will be set if we 29132a611692SJohan Hedberg * initiated the authentication. A traditional auth_complete 29142a611692SJohan Hedberg * event gets always produced as initiator and is also mapped to 29152a611692SJohan Hedberg * the mgmt_auth_failed event */ 29162a611692SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0) 2917744cf19eSJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, ev->status); 29182a611692SJohan Hedberg 29190493684eSMarcel Holtmann hci_conn_put(conn); 29200493684eSMarcel Holtmann 29212a611692SJohan Hedberg unlock: 29220493684eSMarcel Holtmann hci_dev_unlock(hdev); 29230493684eSMarcel Holtmann } 29240493684eSMarcel Holtmann 292541a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 292641a96212SMarcel Holtmann { 292741a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 292841a96212SMarcel Holtmann struct inquiry_entry *ie; 292941a96212SMarcel Holtmann 293041a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 293141a96212SMarcel Holtmann 293241a96212SMarcel Holtmann hci_dev_lock(hdev); 293341a96212SMarcel Holtmann 2934cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2935cc11b9c1SAndrei Emeltchenko if (ie) 293641a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 293741a96212SMarcel Holtmann 293841a96212SMarcel Holtmann hci_dev_unlock(hdev); 293941a96212SMarcel Holtmann } 294041a96212SMarcel Holtmann 29412763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev, 29422763eda6SSzymon Janc struct sk_buff *skb) 29432763eda6SSzymon Janc { 29442763eda6SSzymon Janc struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; 29452763eda6SSzymon Janc struct oob_data *data; 29462763eda6SSzymon Janc 29472763eda6SSzymon Janc BT_DBG("%s", hdev->name); 29482763eda6SSzymon Janc 29492763eda6SSzymon Janc hci_dev_lock(hdev); 29502763eda6SSzymon Janc 2951e1ba1f15SSzymon Janc if (!test_bit(HCI_MGMT, &hdev->flags)) 2952e1ba1f15SSzymon Janc goto unlock; 2953e1ba1f15SSzymon Janc 29542763eda6SSzymon Janc data = hci_find_remote_oob_data(hdev, &ev->bdaddr); 29552763eda6SSzymon Janc if (data) { 29562763eda6SSzymon Janc struct hci_cp_remote_oob_data_reply cp; 29572763eda6SSzymon Janc 29582763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 29592763eda6SSzymon Janc memcpy(cp.hash, data->hash, sizeof(cp.hash)); 29602763eda6SSzymon Janc memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); 29612763eda6SSzymon Janc 29622763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), 29632763eda6SSzymon Janc &cp); 29642763eda6SSzymon Janc } else { 29652763eda6SSzymon Janc struct hci_cp_remote_oob_data_neg_reply cp; 29662763eda6SSzymon Janc 29672763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 29682763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), 29692763eda6SSzymon Janc &cp); 29702763eda6SSzymon Janc } 29712763eda6SSzymon Janc 2972e1ba1f15SSzymon Janc unlock: 29732763eda6SSzymon Janc hci_dev_unlock(hdev); 29742763eda6SSzymon Janc } 29752763eda6SSzymon Janc 2976fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2977fcd89c09SVille Tervo { 2978fcd89c09SVille Tervo struct hci_ev_le_conn_complete *ev = (void *) skb->data; 2979fcd89c09SVille Tervo struct hci_conn *conn; 2980fcd89c09SVille Tervo 2981fcd89c09SVille Tervo BT_DBG("%s status %d", hdev->name, ev->status); 2982fcd89c09SVille Tervo 2983fcd89c09SVille Tervo hci_dev_lock(hdev); 2984fcd89c09SVille Tervo 2985fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr); 2986b62f328bSVille Tervo if (!conn) { 2987b62f328bSVille Tervo conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); 2988b62f328bSVille Tervo if (!conn) { 2989b62f328bSVille Tervo BT_ERR("No memory for new connection"); 2990b62f328bSVille Tervo hci_dev_unlock(hdev); 2991b62f328bSVille Tervo return; 2992b62f328bSVille Tervo } 299329b7988aSAndre Guedes 299429b7988aSAndre Guedes conn->dst_type = ev->bdaddr_type; 2995b62f328bSVille Tervo } 2996fcd89c09SVille Tervo 2997fcd89c09SVille Tervo if (ev->status) { 299848264f06SJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 299948264f06SJohan Hedberg conn->dst_type, ev->status); 3000fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 3001fcd89c09SVille Tervo conn->state = BT_CLOSED; 3002fcd89c09SVille Tervo hci_conn_del(conn); 3003fcd89c09SVille Tervo goto unlock; 3004fcd89c09SVille Tervo } 3005fcd89c09SVille Tervo 300648264f06SJohan Hedberg mgmt_connected(hdev, &ev->bdaddr, conn->type, conn->dst_type); 300783bc71b4SVinicius Costa Gomes 30087b5c0d52SVinicius Costa Gomes conn->sec_level = BT_SECURITY_LOW; 3009fcd89c09SVille Tervo conn->handle = __le16_to_cpu(ev->handle); 3010fcd89c09SVille Tervo conn->state = BT_CONNECTED; 3011fcd89c09SVille Tervo 3012fcd89c09SVille Tervo hci_conn_hold_device(conn); 3013fcd89c09SVille Tervo hci_conn_add_sysfs(conn); 3014fcd89c09SVille Tervo 3015fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 3016fcd89c09SVille Tervo 3017fcd89c09SVille Tervo unlock: 3018fcd89c09SVille Tervo hci_dev_unlock(hdev); 3019fcd89c09SVille Tervo } 3020fcd89c09SVille Tervo 30219aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev, 30229aa04c91SAndre Guedes struct sk_buff *skb) 30239aa04c91SAndre Guedes { 3024e95beb41SAndre Guedes u8 num_reports = skb->data[0]; 3025e95beb41SAndre Guedes void *ptr = &skb->data[1]; 30269aa04c91SAndre Guedes 30279aa04c91SAndre Guedes hci_dev_lock(hdev); 30289aa04c91SAndre Guedes 3029e95beb41SAndre Guedes while (num_reports--) { 3030e95beb41SAndre Guedes struct hci_ev_le_advertising_info *ev = ptr; 3031e95beb41SAndre Guedes 30329aa04c91SAndre Guedes hci_add_adv_entry(hdev, ev); 30339aa04c91SAndre Guedes 3034e95beb41SAndre Guedes ptr += sizeof(*ev) + ev->length + 1; 30359aa04c91SAndre Guedes } 30369aa04c91SAndre Guedes 30379aa04c91SAndre Guedes hci_dev_unlock(hdev); 30389aa04c91SAndre Guedes } 30399aa04c91SAndre Guedes 3040a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev, 3041a7a595f6SVinicius Costa Gomes struct sk_buff *skb) 3042a7a595f6SVinicius Costa Gomes { 3043a7a595f6SVinicius Costa Gomes struct hci_ev_le_ltk_req *ev = (void *) skb->data; 3044a7a595f6SVinicius Costa Gomes struct hci_cp_le_ltk_reply cp; 3045bea710feSVinicius Costa Gomes struct hci_cp_le_ltk_neg_reply neg; 3046a7a595f6SVinicius Costa Gomes struct hci_conn *conn; 3047bea710feSVinicius Costa Gomes struct link_key *ltk; 3048a7a595f6SVinicius Costa Gomes 3049a7a595f6SVinicius Costa Gomes BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle)); 3050a7a595f6SVinicius Costa Gomes 3051a7a595f6SVinicius Costa Gomes hci_dev_lock(hdev); 3052a7a595f6SVinicius Costa Gomes 3053a7a595f6SVinicius Costa Gomes conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3054bea710feSVinicius Costa Gomes if (conn == NULL) 3055bea710feSVinicius Costa Gomes goto not_found; 3056a7a595f6SVinicius Costa Gomes 3057bea710feSVinicius Costa Gomes ltk = hci_find_ltk(hdev, ev->ediv, ev->random); 3058bea710feSVinicius Costa Gomes if (ltk == NULL) 3059bea710feSVinicius Costa Gomes goto not_found; 3060bea710feSVinicius Costa Gomes 3061bea710feSVinicius Costa Gomes memcpy(cp.ltk, ltk->val, sizeof(ltk->val)); 3062a7a595f6SVinicius Costa Gomes cp.handle = cpu_to_le16(conn->handle); 3063726b4ffcSVinicius Costa Gomes conn->pin_length = ltk->pin_len; 3064a7a595f6SVinicius Costa Gomes 3065a7a595f6SVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); 3066a7a595f6SVinicius Costa Gomes 3067a7a595f6SVinicius Costa Gomes hci_dev_unlock(hdev); 3068bea710feSVinicius Costa Gomes 3069bea710feSVinicius Costa Gomes return; 3070bea710feSVinicius Costa Gomes 3071bea710feSVinicius Costa Gomes not_found: 3072bea710feSVinicius Costa Gomes neg.handle = ev->handle; 3073bea710feSVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg); 3074bea710feSVinicius Costa Gomes hci_dev_unlock(hdev); 3075a7a595f6SVinicius Costa Gomes } 3076a7a595f6SVinicius Costa Gomes 3077fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 3078fcd89c09SVille Tervo { 3079fcd89c09SVille Tervo struct hci_ev_le_meta *le_ev = (void *) skb->data; 3080fcd89c09SVille Tervo 3081fcd89c09SVille Tervo skb_pull(skb, sizeof(*le_ev)); 3082fcd89c09SVille Tervo 3083fcd89c09SVille Tervo switch (le_ev->subevent) { 3084fcd89c09SVille Tervo case HCI_EV_LE_CONN_COMPLETE: 3085fcd89c09SVille Tervo hci_le_conn_complete_evt(hdev, skb); 3086fcd89c09SVille Tervo break; 3087fcd89c09SVille Tervo 30889aa04c91SAndre Guedes case HCI_EV_LE_ADVERTISING_REPORT: 30899aa04c91SAndre Guedes hci_le_adv_report_evt(hdev, skb); 30909aa04c91SAndre Guedes break; 30919aa04c91SAndre Guedes 3092a7a595f6SVinicius Costa Gomes case HCI_EV_LE_LTK_REQ: 3093a7a595f6SVinicius Costa Gomes hci_le_ltk_request_evt(hdev, skb); 3094a7a595f6SVinicius Costa Gomes break; 3095a7a595f6SVinicius Costa Gomes 3096fcd89c09SVille Tervo default: 3097fcd89c09SVille Tervo break; 3098fcd89c09SVille Tervo } 3099fcd89c09SVille Tervo } 3100fcd89c09SVille Tervo 31011da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 31021da177e4SLinus Torvalds { 3103a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 3104a9de9248SMarcel Holtmann __u8 event = hdr->evt; 31051da177e4SLinus Torvalds 31061da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 31071da177e4SLinus Torvalds 3108a9de9248SMarcel Holtmann switch (event) { 31091da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 31101da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 31111da177e4SLinus Torvalds break; 31121da177e4SLinus Torvalds 31131da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 31141da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 31151da177e4SLinus Torvalds break; 31161da177e4SLinus Torvalds 3117a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 3118a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 311921d9e30eSMarcel Holtmann break; 312021d9e30eSMarcel Holtmann 31211da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 31221da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 31231da177e4SLinus Torvalds break; 31241da177e4SLinus Torvalds 31251da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 31261da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 31271da177e4SLinus Torvalds break; 31281da177e4SLinus Torvalds 31291da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 31301da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 31311da177e4SLinus Torvalds break; 31321da177e4SLinus Torvalds 3133a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 3134a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 3135a9de9248SMarcel Holtmann break; 3136a9de9248SMarcel Holtmann 31371da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 31381da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 31391da177e4SLinus Torvalds break; 31401da177e4SLinus Torvalds 3141a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 3142a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 3143a9de9248SMarcel Holtmann break; 3144a9de9248SMarcel Holtmann 3145a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 3146a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 3147a9de9248SMarcel Holtmann break; 3148a9de9248SMarcel Holtmann 3149a9de9248SMarcel Holtmann case HCI_EV_REMOTE_VERSION: 3150a9de9248SMarcel Holtmann hci_remote_version_evt(hdev, skb); 3151a9de9248SMarcel Holtmann break; 3152a9de9248SMarcel Holtmann 3153a9de9248SMarcel Holtmann case HCI_EV_QOS_SETUP_COMPLETE: 3154a9de9248SMarcel Holtmann hci_qos_setup_complete_evt(hdev, skb); 3155a9de9248SMarcel Holtmann break; 3156a9de9248SMarcel Holtmann 3157a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 3158a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 3159a9de9248SMarcel Holtmann break; 3160a9de9248SMarcel Holtmann 3161a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 3162a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 3163a9de9248SMarcel Holtmann break; 3164a9de9248SMarcel Holtmann 3165a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 3166a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 3167a9de9248SMarcel Holtmann break; 3168a9de9248SMarcel Holtmann 3169a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 3170a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 3171a9de9248SMarcel Holtmann break; 3172a9de9248SMarcel Holtmann 3173a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 3174a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 31751da177e4SLinus Torvalds break; 31761da177e4SLinus Torvalds 31771da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 31781da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 31791da177e4SLinus Torvalds break; 31801da177e4SLinus Torvalds 31811da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 31821da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 31831da177e4SLinus Torvalds break; 31841da177e4SLinus Torvalds 31851da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 31861da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 31871da177e4SLinus Torvalds break; 31881da177e4SLinus Torvalds 31891da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 31901da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 31911da177e4SLinus Torvalds break; 31921da177e4SLinus Torvalds 3193a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 3194a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 3195a8746417SMarcel Holtmann break; 3196a8746417SMarcel Holtmann 319785a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 319885a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 319985a1e930SMarcel Holtmann break; 320085a1e930SMarcel Holtmann 3201a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 3202a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 3203a9de9248SMarcel Holtmann break; 3204a9de9248SMarcel Holtmann 3205a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 3206a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 3207a9de9248SMarcel Holtmann break; 3208a9de9248SMarcel Holtmann 3209a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 3210a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 3211a9de9248SMarcel Holtmann break; 3212a9de9248SMarcel Holtmann 3213a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_CHANGED: 3214a9de9248SMarcel Holtmann hci_sync_conn_changed_evt(hdev, skb); 3215a9de9248SMarcel Holtmann break; 3216a9de9248SMarcel Holtmann 321704837f64SMarcel Holtmann case HCI_EV_SNIFF_SUBRATE: 321804837f64SMarcel Holtmann hci_sniff_subrate_evt(hdev, skb); 321904837f64SMarcel Holtmann break; 322004837f64SMarcel Holtmann 3221a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 3222a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 32231da177e4SLinus Torvalds break; 32241da177e4SLinus Torvalds 32250493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 32260493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 32270493684eSMarcel Holtmann break; 32280493684eSMarcel Holtmann 322903b555e1SJohan Hedberg case HCI_EV_IO_CAPA_REPLY: 323003b555e1SJohan Hedberg hci_io_capa_reply_evt(hdev, skb); 323103b555e1SJohan Hedberg break; 323203b555e1SJohan Hedberg 3233a5c29683SJohan Hedberg case HCI_EV_USER_CONFIRM_REQUEST: 3234a5c29683SJohan Hedberg hci_user_confirm_request_evt(hdev, skb); 3235a5c29683SJohan Hedberg break; 3236a5c29683SJohan Hedberg 32371143d458SBrian Gix case HCI_EV_USER_PASSKEY_REQUEST: 32381143d458SBrian Gix hci_user_passkey_request_evt(hdev, skb); 32391143d458SBrian Gix break; 32401143d458SBrian Gix 32410493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 32420493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 32430493684eSMarcel Holtmann break; 32440493684eSMarcel Holtmann 324541a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 324641a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 324741a96212SMarcel Holtmann break; 324841a96212SMarcel Holtmann 3249fcd89c09SVille Tervo case HCI_EV_LE_META: 3250fcd89c09SVille Tervo hci_le_meta_evt(hdev, skb); 3251fcd89c09SVille Tervo break; 3252fcd89c09SVille Tervo 32532763eda6SSzymon Janc case HCI_EV_REMOTE_OOB_DATA_REQUEST: 32542763eda6SSzymon Janc hci_remote_oob_data_request_evt(hdev, skb); 32552763eda6SSzymon Janc break; 32562763eda6SSzymon Janc 32571da177e4SLinus Torvalds default: 3258a9de9248SMarcel Holtmann BT_DBG("%s event 0x%x", hdev->name, event); 32591da177e4SLinus Torvalds break; 32601da177e4SLinus Torvalds } 32611da177e4SLinus Torvalds 32621da177e4SLinus Torvalds kfree_skb(skb); 32631da177e4SLinus Torvalds hdev->stat.evt_rx++; 32641da177e4SLinus Torvalds } 32651da177e4SLinus Torvalds 32661da177e4SLinus Torvalds /* Generate internal stack event */ 32671da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data) 32681da177e4SLinus Torvalds { 32691da177e4SLinus Torvalds struct hci_event_hdr *hdr; 32701da177e4SLinus Torvalds struct hci_ev_stack_internal *ev; 32711da177e4SLinus Torvalds struct sk_buff *skb; 32721da177e4SLinus Torvalds 32731da177e4SLinus Torvalds skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC); 32741da177e4SLinus Torvalds if (!skb) 32751da177e4SLinus Torvalds return; 32761da177e4SLinus Torvalds 32771da177e4SLinus Torvalds hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE); 32781da177e4SLinus Torvalds hdr->evt = HCI_EV_STACK_INTERNAL; 32791da177e4SLinus Torvalds hdr->plen = sizeof(*ev) + dlen; 32801da177e4SLinus Torvalds 32811da177e4SLinus Torvalds ev = (void *) skb_put(skb, sizeof(*ev) + dlen); 32821da177e4SLinus Torvalds ev->type = type; 32831da177e4SLinus Torvalds memcpy(ev->data, data, dlen); 32841da177e4SLinus Torvalds 3285576c7d85SMarcel Holtmann bt_cb(skb)->incoming = 1; 3286a61bbcf2SPatrick McHardy __net_timestamp(skb); 3287576c7d85SMarcel Holtmann 32880d48d939SMarcel Holtmann bt_cb(skb)->pkt_type = HCI_EVENT_PKT; 32891da177e4SLinus Torvalds skb->dev = (void *) hdev; 3290eec8d2bcSJohan Hedberg hci_send_to_sock(hdev, skb, NULL); 32911da177e4SLinus Torvalds kfree_skb(skb); 32921da177e4SLinus Torvalds } 3293e6100a25SAndre Guedes 3294669bb396SGustavo F. Padovan module_param(enable_le, bool, 0644); 3295e6100a25SAndre Guedes MODULE_PARM_DESC(enable_le, "Enable LE support"); 3296