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 <net/sock.h> 391da177e4SLinus Torvalds 401da177e4SLinus Torvalds #include <asm/system.h> 4170f23020SAndrei Emeltchenko #include <linux/uaccess.h> 421da177e4SLinus Torvalds #include <asm/unaligned.h> 431da177e4SLinus Torvalds 441da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h> 451da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h> 461da177e4SLinus Torvalds 471da177e4SLinus Torvalds /* Handle HCI Event packets */ 481da177e4SLinus Torvalds 49a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb) 501da177e4SLinus Torvalds { 51a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 521da177e4SLinus Torvalds 53a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 541da177e4SLinus Torvalds 55e6d465cbSAndre Guedes if (status) { 56e6d465cbSAndre Guedes hci_dev_lock(hdev); 57e6d465cbSAndre Guedes mgmt_stop_discovery_failed(hdev, status); 58e6d465cbSAndre Guedes hci_dev_unlock(hdev); 59a9de9248SMarcel Holtmann return; 60e6d465cbSAndre Guedes } 611da177e4SLinus Torvalds 6289352e7dSAndre Guedes clear_bit(HCI_INQUIRY, &hdev->flags); 6389352e7dSAndre Guedes 6456e5cb86SJohan Hedberg hci_dev_lock(hdev); 65ff9ef578SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 6656e5cb86SJohan Hedberg hci_dev_unlock(hdev); 67a9de9248SMarcel Holtmann 6823bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status); 69a9de9248SMarcel Holtmann 70a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 711da177e4SLinus Torvalds } 726bd57416SMarcel Holtmann 73a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 741da177e4SLinus Torvalds { 75a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 76a9de9248SMarcel Holtmann 77a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 78a9de9248SMarcel Holtmann 79a9de9248SMarcel Holtmann if (status) 80a9de9248SMarcel Holtmann return; 81a9de9248SMarcel Holtmann 82a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 83a9de9248SMarcel Holtmann } 84a9de9248SMarcel Holtmann 85a9de9248SMarcel Holtmann static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb) 86a9de9248SMarcel Holtmann { 87a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 88a9de9248SMarcel Holtmann } 89a9de9248SMarcel Holtmann 90a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb) 91a9de9248SMarcel Holtmann { 92a9de9248SMarcel Holtmann struct hci_rp_role_discovery *rp = (void *) skb->data; 931da177e4SLinus Torvalds struct hci_conn *conn; 941da177e4SLinus Torvalds 95a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 961da177e4SLinus Torvalds 97a9de9248SMarcel Holtmann if (rp->status) 98a9de9248SMarcel Holtmann return; 991da177e4SLinus Torvalds 1001da177e4SLinus Torvalds hci_dev_lock(hdev); 1011da177e4SLinus Torvalds 102a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 1031da177e4SLinus Torvalds if (conn) { 104a9de9248SMarcel Holtmann if (rp->role) 1051da177e4SLinus Torvalds conn->link_mode &= ~HCI_LM_MASTER; 1061da177e4SLinus Torvalds else 1071da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 1081da177e4SLinus Torvalds } 1091da177e4SLinus Torvalds 1101da177e4SLinus Torvalds hci_dev_unlock(hdev); 111a9de9248SMarcel Holtmann } 1121da177e4SLinus Torvalds 113e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 114e4e8e37cSMarcel Holtmann { 115e4e8e37cSMarcel Holtmann struct hci_rp_read_link_policy *rp = (void *) skb->data; 116e4e8e37cSMarcel Holtmann struct hci_conn *conn; 117e4e8e37cSMarcel Holtmann 118e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 119e4e8e37cSMarcel Holtmann 120e4e8e37cSMarcel Holtmann if (rp->status) 121e4e8e37cSMarcel Holtmann return; 122e4e8e37cSMarcel Holtmann 123e4e8e37cSMarcel Holtmann hci_dev_lock(hdev); 124e4e8e37cSMarcel Holtmann 125e4e8e37cSMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 126e4e8e37cSMarcel Holtmann if (conn) 127e4e8e37cSMarcel Holtmann conn->link_policy = __le16_to_cpu(rp->policy); 128e4e8e37cSMarcel Holtmann 129e4e8e37cSMarcel Holtmann hci_dev_unlock(hdev); 130e4e8e37cSMarcel Holtmann } 131e4e8e37cSMarcel Holtmann 132a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 133a9de9248SMarcel Holtmann { 134a9de9248SMarcel Holtmann struct hci_rp_write_link_policy *rp = (void *) skb->data; 135a9de9248SMarcel Holtmann struct hci_conn *conn; 136a9de9248SMarcel Holtmann void *sent; 137a9de9248SMarcel Holtmann 138a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 139a9de9248SMarcel Holtmann 140a9de9248SMarcel Holtmann if (rp->status) 141a9de9248SMarcel Holtmann return; 142a9de9248SMarcel Holtmann 143a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY); 14404837f64SMarcel Holtmann if (!sent) 145a9de9248SMarcel Holtmann return; 14604837f64SMarcel Holtmann 14704837f64SMarcel Holtmann hci_dev_lock(hdev); 14804837f64SMarcel Holtmann 149a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 150e4e8e37cSMarcel Holtmann if (conn) 15183985319SHarvey Harrison conn->link_policy = get_unaligned_le16(sent + 2); 15204837f64SMarcel Holtmann 15304837f64SMarcel Holtmann hci_dev_unlock(hdev); 1541da177e4SLinus Torvalds } 1551da177e4SLinus Torvalds 156e4e8e37cSMarcel Holtmann static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 157e4e8e37cSMarcel Holtmann { 158e4e8e37cSMarcel Holtmann struct hci_rp_read_def_link_policy *rp = (void *) skb->data; 159e4e8e37cSMarcel Holtmann 160e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 161e4e8e37cSMarcel Holtmann 162e4e8e37cSMarcel Holtmann if (rp->status) 163e4e8e37cSMarcel Holtmann return; 164e4e8e37cSMarcel Holtmann 165e4e8e37cSMarcel Holtmann hdev->link_policy = __le16_to_cpu(rp->policy); 166e4e8e37cSMarcel Holtmann } 167e4e8e37cSMarcel Holtmann 168e4e8e37cSMarcel Holtmann static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 169e4e8e37cSMarcel Holtmann { 170e4e8e37cSMarcel Holtmann __u8 status = *((__u8 *) skb->data); 171e4e8e37cSMarcel Holtmann void *sent; 172e4e8e37cSMarcel Holtmann 173e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 174e4e8e37cSMarcel Holtmann 175e4e8e37cSMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY); 176e4e8e37cSMarcel Holtmann if (!sent) 177e4e8e37cSMarcel Holtmann return; 178e4e8e37cSMarcel Holtmann 179e4e8e37cSMarcel Holtmann if (!status) 180e4e8e37cSMarcel Holtmann hdev->link_policy = get_unaligned_le16(sent); 181e4e8e37cSMarcel Holtmann 18223bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status); 183e4e8e37cSMarcel Holtmann } 184e4e8e37cSMarcel Holtmann 185a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) 1861da177e4SLinus Torvalds { 187a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 188a9de9248SMarcel Holtmann 189a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 190a9de9248SMarcel Holtmann 19110572132SGustavo F. Padovan clear_bit(HCI_RESET, &hdev->flags); 19210572132SGustavo F. Padovan 19323bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_RESET, status); 194d23264a8SAndre Guedes 195a297e97cSJohan Hedberg /* Reset all non-persistent flags */ 196a297e97cSJohan Hedberg hdev->dev_flags &= ~(BIT(HCI_LE_SCAN)); 197a9de9248SMarcel Holtmann } 198a9de9248SMarcel Holtmann 199a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) 200a9de9248SMarcel Holtmann { 201a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 2021da177e4SLinus Torvalds void *sent; 2031da177e4SLinus Torvalds 204a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 2051da177e4SLinus Torvalds 206a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); 2071da177e4SLinus Torvalds if (!sent) 208a9de9248SMarcel Holtmann return; 2091da177e4SLinus Torvalds 21056e5cb86SJohan Hedberg hci_dev_lock(hdev); 21156e5cb86SJohan Hedberg 21256e5cb86SJohan Hedberg if (status == 0) 2131f6c6378SJohan Hedberg memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); 21456e5cb86SJohan Hedberg 215f51d5b24SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 216f51d5b24SJohan Hedberg mgmt_set_local_name_complete(hdev, sent, status); 217f51d5b24SJohan Hedberg 21856e5cb86SJohan Hedberg hci_dev_unlock(hdev); 219a9de9248SMarcel Holtmann } 220a9de9248SMarcel Holtmann 221a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) 222a9de9248SMarcel Holtmann { 223a9de9248SMarcel Holtmann struct hci_rp_read_local_name *rp = (void *) skb->data; 224a9de9248SMarcel Holtmann 225a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 226a9de9248SMarcel Holtmann 227a9de9248SMarcel Holtmann if (rp->status) 228a9de9248SMarcel Holtmann return; 229a9de9248SMarcel Holtmann 230db99b5fcSJohan Hedberg if (test_bit(HCI_SETUP, &hdev->dev_flags)) 2311f6c6378SJohan Hedberg memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); 232a9de9248SMarcel Holtmann } 233a9de9248SMarcel Holtmann 234a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) 235a9de9248SMarcel Holtmann { 236a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 237a9de9248SMarcel Holtmann void *sent; 238a9de9248SMarcel Holtmann 239a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 240a9de9248SMarcel Holtmann 241a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); 242a9de9248SMarcel Holtmann if (!sent) 243a9de9248SMarcel Holtmann return; 2441da177e4SLinus Torvalds 2451da177e4SLinus Torvalds if (!status) { 246a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 247a9de9248SMarcel Holtmann 2481da177e4SLinus Torvalds if (param == AUTH_ENABLED) 2491da177e4SLinus Torvalds set_bit(HCI_AUTH, &hdev->flags); 2501da177e4SLinus Torvalds else 2511da177e4SLinus Torvalds clear_bit(HCI_AUTH, &hdev->flags); 2521da177e4SLinus Torvalds } 253a9de9248SMarcel Holtmann 25433ef95edSJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 25533ef95edSJohan Hedberg mgmt_auth_enable_complete(hdev, status); 25633ef95edSJohan Hedberg 25723bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status); 258a9de9248SMarcel Holtmann } 2591da177e4SLinus Torvalds 260a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) 261a9de9248SMarcel Holtmann { 262a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 263a9de9248SMarcel Holtmann void *sent; 264a9de9248SMarcel Holtmann 265a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 266a9de9248SMarcel Holtmann 267a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); 2681da177e4SLinus Torvalds if (!sent) 269a9de9248SMarcel Holtmann return; 2701da177e4SLinus Torvalds 2711da177e4SLinus Torvalds if (!status) { 272a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 273a9de9248SMarcel Holtmann 2741da177e4SLinus Torvalds if (param) 2751da177e4SLinus Torvalds set_bit(HCI_ENCRYPT, &hdev->flags); 2761da177e4SLinus Torvalds else 2771da177e4SLinus Torvalds clear_bit(HCI_ENCRYPT, &hdev->flags); 2781da177e4SLinus Torvalds } 279a9de9248SMarcel Holtmann 28023bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status); 2811da177e4SLinus Torvalds } 2821da177e4SLinus Torvalds 283a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) 284a9de9248SMarcel Holtmann { 28536f7fc7eSJohan Hedberg __u8 param, status = *((__u8 *) skb->data); 28636f7fc7eSJohan Hedberg int old_pscan, old_iscan; 287a9de9248SMarcel Holtmann void *sent; 2881da177e4SLinus Torvalds 289a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 290a9de9248SMarcel Holtmann 291a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); 2921da177e4SLinus Torvalds if (!sent) 293a9de9248SMarcel Holtmann return; 2941da177e4SLinus Torvalds 29536f7fc7eSJohan Hedberg param = *((__u8 *) sent); 296a9de9248SMarcel Holtmann 29756e5cb86SJohan Hedberg hci_dev_lock(hdev); 29856e5cb86SJohan Hedberg 2992d7cee58SJohan Hedberg if (status != 0) { 300744cf19eSJohan Hedberg mgmt_write_scan_failed(hdev, param, status); 3012d7cee58SJohan Hedberg hdev->discov_timeout = 0; 3022d7cee58SJohan Hedberg goto done; 3032d7cee58SJohan Hedberg } 3042d7cee58SJohan Hedberg 3059fbcbb45SJohan Hedberg old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags); 3069fbcbb45SJohan Hedberg old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags); 307a9de9248SMarcel Holtmann 30873f22f62SJohan Hedberg if (param & SCAN_INQUIRY) { 3091da177e4SLinus Torvalds set_bit(HCI_ISCAN, &hdev->flags); 3109fbcbb45SJohan Hedberg if (!old_iscan) 311744cf19eSJohan Hedberg mgmt_discoverable(hdev, 1); 31216ab91abSJohan Hedberg if (hdev->discov_timeout > 0) { 31316ab91abSJohan Hedberg int to = msecs_to_jiffies(hdev->discov_timeout * 1000); 31416ab91abSJohan Hedberg queue_delayed_work(hdev->workqueue, &hdev->discov_off, 31516ab91abSJohan Hedberg to); 31616ab91abSJohan Hedberg } 3179fbcbb45SJohan Hedberg } else if (old_iscan) 318744cf19eSJohan Hedberg mgmt_discoverable(hdev, 0); 3191da177e4SLinus Torvalds 3209fbcbb45SJohan Hedberg if (param & SCAN_PAGE) { 3211da177e4SLinus Torvalds set_bit(HCI_PSCAN, &hdev->flags); 3229fbcbb45SJohan Hedberg if (!old_pscan) 323744cf19eSJohan Hedberg mgmt_connectable(hdev, 1); 3249fbcbb45SJohan Hedberg } else if (old_pscan) 325744cf19eSJohan Hedberg mgmt_connectable(hdev, 0); 326a9de9248SMarcel Holtmann 32736f7fc7eSJohan Hedberg done: 32856e5cb86SJohan Hedberg hci_dev_unlock(hdev); 32923bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status); 3301da177e4SLinus Torvalds } 3311da177e4SLinus Torvalds 332a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 333a9de9248SMarcel Holtmann { 334a9de9248SMarcel Holtmann struct hci_rp_read_class_of_dev *rp = (void *) skb->data; 335a9de9248SMarcel Holtmann 336a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 337a9de9248SMarcel Holtmann 338a9de9248SMarcel Holtmann if (rp->status) 339a9de9248SMarcel Holtmann return; 340a9de9248SMarcel Holtmann 341a9de9248SMarcel Holtmann memcpy(hdev->dev_class, rp->dev_class, 3); 342a9de9248SMarcel Holtmann 343a9de9248SMarcel Holtmann BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, 344a9de9248SMarcel Holtmann hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); 345a9de9248SMarcel Holtmann } 346a9de9248SMarcel Holtmann 347a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 348a9de9248SMarcel Holtmann { 349a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 350a9de9248SMarcel Holtmann void *sent; 351a9de9248SMarcel Holtmann 352a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 353a9de9248SMarcel Holtmann 354a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); 355a9de9248SMarcel Holtmann if (!sent) 356a9de9248SMarcel Holtmann return; 357a9de9248SMarcel Holtmann 3587f9a903cSMarcel Holtmann hci_dev_lock(hdev); 3597f9a903cSMarcel Holtmann 3607f9a903cSMarcel Holtmann if (status == 0) 361a9de9248SMarcel Holtmann memcpy(hdev->dev_class, sent, 3); 3627f9a903cSMarcel Holtmann 3637f9a903cSMarcel Holtmann if (test_bit(HCI_MGMT, &hdev->dev_flags)) 3647f9a903cSMarcel Holtmann mgmt_set_class_of_dev_complete(hdev, sent, status); 3657f9a903cSMarcel Holtmann 3667f9a903cSMarcel Holtmann hci_dev_unlock(hdev); 367a9de9248SMarcel Holtmann } 368a9de9248SMarcel Holtmann 369a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 370a9de9248SMarcel Holtmann { 371a9de9248SMarcel Holtmann struct hci_rp_read_voice_setting *rp = (void *) skb->data; 372a9de9248SMarcel Holtmann __u16 setting; 373a9de9248SMarcel Holtmann 374a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 375a9de9248SMarcel Holtmann 376a9de9248SMarcel Holtmann if (rp->status) 377a9de9248SMarcel Holtmann return; 378a9de9248SMarcel Holtmann 379a9de9248SMarcel Holtmann setting = __le16_to_cpu(rp->voice_setting); 380a9de9248SMarcel Holtmann 381a9de9248SMarcel Holtmann if (hdev->voice_setting == setting) 382a9de9248SMarcel Holtmann return; 383a9de9248SMarcel Holtmann 384a9de9248SMarcel Holtmann hdev->voice_setting = setting; 385a9de9248SMarcel Holtmann 386a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 387a9de9248SMarcel Holtmann 3883c54711cSGustavo F. Padovan if (hdev->notify) 389a9de9248SMarcel Holtmann hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 390a9de9248SMarcel Holtmann } 391a9de9248SMarcel Holtmann 392a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 393a9de9248SMarcel Holtmann { 394a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 395f383f275SMarcel Holtmann __u16 setting; 396a9de9248SMarcel Holtmann void *sent; 397a9de9248SMarcel Holtmann 398a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 399a9de9248SMarcel Holtmann 400f383f275SMarcel Holtmann if (status) 401f383f275SMarcel Holtmann return; 402f383f275SMarcel Holtmann 403a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); 404a9de9248SMarcel Holtmann if (!sent) 405a9de9248SMarcel Holtmann return; 406a9de9248SMarcel Holtmann 407f383f275SMarcel Holtmann setting = get_unaligned_le16(sent); 4081da177e4SLinus Torvalds 409f383f275SMarcel Holtmann if (hdev->voice_setting == setting) 410f383f275SMarcel Holtmann return; 411f383f275SMarcel Holtmann 4121da177e4SLinus Torvalds hdev->voice_setting = setting; 4131da177e4SLinus Torvalds 414a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 4151da177e4SLinus Torvalds 4163c54711cSGustavo F. Padovan if (hdev->notify) 4171da177e4SLinus Torvalds hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 4181da177e4SLinus Torvalds } 4191da177e4SLinus Torvalds 420a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 4211da177e4SLinus Torvalds { 422a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 4231da177e4SLinus Torvalds 424a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 4251da177e4SLinus Torvalds 42623bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status); 4271143e5a6SMarcel Holtmann } 4281143e5a6SMarcel Holtmann 429333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 430333140b5SMarcel Holtmann { 431333140b5SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 432333140b5SMarcel Holtmann void *sent; 433333140b5SMarcel Holtmann 434333140b5SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 435333140b5SMarcel Holtmann 436333140b5SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); 437333140b5SMarcel Holtmann if (!sent) 438333140b5SMarcel Holtmann return; 439333140b5SMarcel Holtmann 440c0ecddc2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 441c0ecddc2SJohan Hedberg mgmt_ssp_enable_complete(hdev, *((u8 *) sent), status); 442c0ecddc2SJohan Hedberg else if (!status) { 44384bde9d6SJohan Hedberg if (*((u8 *) sent)) 44484bde9d6SJohan Hedberg set_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 44584bde9d6SJohan Hedberg else 44684bde9d6SJohan Hedberg clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 447c0ecddc2SJohan Hedberg } 448333140b5SMarcel Holtmann } 449333140b5SMarcel Holtmann 450d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev) 451d5859e22SJohan Hedberg { 452d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 453d5859e22SJohan Hedberg return 2; 454d5859e22SJohan Hedberg 455d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 456d5859e22SJohan Hedberg return 1; 457d5859e22SJohan Hedberg 458d5859e22SJohan Hedberg if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 && 459d5859e22SJohan Hedberg hdev->lmp_subver == 0x0757) 460d5859e22SJohan Hedberg return 1; 461d5859e22SJohan Hedberg 462d5859e22SJohan Hedberg if (hdev->manufacturer == 15) { 463d5859e22SJohan Hedberg if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963) 464d5859e22SJohan Hedberg return 1; 465d5859e22SJohan Hedberg if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963) 466d5859e22SJohan Hedberg return 1; 467d5859e22SJohan Hedberg if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965) 468d5859e22SJohan Hedberg return 1; 469d5859e22SJohan Hedberg } 470d5859e22SJohan Hedberg 471d5859e22SJohan Hedberg if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 && 472d5859e22SJohan Hedberg hdev->lmp_subver == 0x1805) 473d5859e22SJohan Hedberg return 1; 474d5859e22SJohan Hedberg 475d5859e22SJohan Hedberg return 0; 476d5859e22SJohan Hedberg } 477d5859e22SJohan Hedberg 478d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev) 479d5859e22SJohan Hedberg { 480d5859e22SJohan Hedberg u8 mode; 481d5859e22SJohan Hedberg 482d5859e22SJohan Hedberg mode = hci_get_inquiry_mode(hdev); 483d5859e22SJohan Hedberg 484d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode); 485d5859e22SJohan Hedberg } 486d5859e22SJohan Hedberg 487d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev) 488d5859e22SJohan Hedberg { 489d5859e22SJohan Hedberg /* The second byte is 0xff instead of 0x9f (two reserved bits 490d5859e22SJohan Hedberg * disabled) since a Broadcom 1.2 dongle doesn't respond to the 491d5859e22SJohan Hedberg * command otherwise */ 492d5859e22SJohan Hedberg u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 }; 493d5859e22SJohan Hedberg 4946de6c18dSVille Tervo /* CSR 1.1 dongles does not accept any bitfield so don't try to set 4956de6c18dSVille Tervo * any event mask for pre 1.2 devices */ 4965a13b095SAndrei Emeltchenko if (hdev->hci_ver < BLUETOOTH_VER_1_2) 4976de6c18dSVille Tervo return; 4986de6c18dSVille Tervo 499d5859e22SJohan Hedberg events[4] |= 0x01; /* Flow Specification Complete */ 500d5859e22SJohan Hedberg events[4] |= 0x02; /* Inquiry Result with RSSI */ 501d5859e22SJohan Hedberg events[4] |= 0x04; /* Read Remote Extended Features Complete */ 502d5859e22SJohan Hedberg events[5] |= 0x08; /* Synchronous Connection Complete */ 503d5859e22SJohan Hedberg events[5] |= 0x10; /* Synchronous Connection Changed */ 504d5859e22SJohan Hedberg 505d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 506d5859e22SJohan Hedberg events[4] |= 0x04; /* Inquiry Result with RSSI */ 507d5859e22SJohan Hedberg 508d5859e22SJohan Hedberg if (hdev->features[5] & LMP_SNIFF_SUBR) 509d5859e22SJohan Hedberg events[5] |= 0x20; /* Sniff Subrating */ 510d5859e22SJohan Hedberg 511d5859e22SJohan Hedberg if (hdev->features[5] & LMP_PAUSE_ENC) 512d5859e22SJohan Hedberg events[5] |= 0x80; /* Encryption Key Refresh Complete */ 513d5859e22SJohan Hedberg 514d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 515d5859e22SJohan Hedberg events[5] |= 0x40; /* Extended Inquiry Result */ 516d5859e22SJohan Hedberg 517d5859e22SJohan Hedberg if (hdev->features[6] & LMP_NO_FLUSH) 518d5859e22SJohan Hedberg events[7] |= 0x01; /* Enhanced Flush Complete */ 519d5859e22SJohan Hedberg 520d5859e22SJohan Hedberg if (hdev->features[7] & LMP_LSTO) 521d5859e22SJohan Hedberg events[6] |= 0x80; /* Link Supervision Timeout Changed */ 522d5859e22SJohan Hedberg 523d5859e22SJohan Hedberg if (hdev->features[6] & LMP_SIMPLE_PAIR) { 524d5859e22SJohan Hedberg events[6] |= 0x01; /* IO Capability Request */ 525d5859e22SJohan Hedberg events[6] |= 0x02; /* IO Capability Response */ 526d5859e22SJohan Hedberg events[6] |= 0x04; /* User Confirmation Request */ 527d5859e22SJohan Hedberg events[6] |= 0x08; /* User Passkey Request */ 528d5859e22SJohan Hedberg events[6] |= 0x10; /* Remote OOB Data Request */ 529d5859e22SJohan Hedberg events[6] |= 0x20; /* Simple Pairing Complete */ 530d5859e22SJohan Hedberg events[7] |= 0x04; /* User Passkey Notification */ 531d5859e22SJohan Hedberg events[7] |= 0x08; /* Keypress Notification */ 532d5859e22SJohan Hedberg events[7] |= 0x10; /* Remote Host Supported 533d5859e22SJohan Hedberg * Features Notification */ 534d5859e22SJohan Hedberg } 535d5859e22SJohan Hedberg 536d5859e22SJohan Hedberg if (hdev->features[4] & LMP_LE) 537d5859e22SJohan Hedberg events[7] |= 0x20; /* LE Meta-Event */ 538d5859e22SJohan Hedberg 539d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); 540d5859e22SJohan Hedberg } 541d5859e22SJohan Hedberg 542e6100a25SAndre Guedes static void hci_set_le_support(struct hci_dev *hdev) 543e6100a25SAndre Guedes { 544e6100a25SAndre Guedes struct hci_cp_write_le_host_supported cp; 545e6100a25SAndre Guedes 546e6100a25SAndre Guedes memset(&cp, 0, sizeof(cp)); 547e6100a25SAndre Guedes 54806199cf8SJohan Hedberg if (enable_le && test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { 549e6100a25SAndre Guedes cp.le = 1; 550e6100a25SAndre Guedes cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR); 551e6100a25SAndre Guedes } 552e6100a25SAndre Guedes 553e6100a25SAndre Guedes hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), &cp); 554e6100a25SAndre Guedes } 555e6100a25SAndre Guedes 556d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev) 557d5859e22SJohan Hedberg { 558e61ef499SAndrei Emeltchenko if (hdev->dev_type != HCI_BREDR) 559e61ef499SAndrei Emeltchenko return; 560e61ef499SAndrei Emeltchenko 561d5859e22SJohan Hedberg hci_setup_event_mask(hdev); 562d5859e22SJohan Hedberg 563d095c1ebSAndrei Emeltchenko if (hdev->hci_ver > BLUETOOTH_VER_1_1) 564d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); 565d5859e22SJohan Hedberg 56654d04dbbSJohan Hedberg if (hdev->features[6] & LMP_SIMPLE_PAIR) { 56754d04dbbSJohan Hedberg if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { 568d5859e22SJohan Hedberg u8 mode = 0x01; 56954d04dbbSJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 57054d04dbbSJohan Hedberg sizeof(mode), &mode); 57154d04dbbSJohan Hedberg } else { 57254d04dbbSJohan Hedberg struct hci_cp_write_eir cp; 57354d04dbbSJohan Hedberg 57454d04dbbSJohan Hedberg memset(hdev->eir, 0, sizeof(hdev->eir)); 57554d04dbbSJohan Hedberg memset(&cp, 0, sizeof(cp)); 57654d04dbbSJohan Hedberg 57754d04dbbSJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp); 57854d04dbbSJohan Hedberg } 579d5859e22SJohan Hedberg } 580d5859e22SJohan Hedberg 581d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 582d5859e22SJohan Hedberg hci_setup_inquiry_mode(hdev); 583d5859e22SJohan Hedberg 584d5859e22SJohan Hedberg if (hdev->features[7] & LMP_INQ_TX_PWR) 585d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL); 586971e3a4bSAndre Guedes 587971e3a4bSAndre Guedes if (hdev->features[7] & LMP_EXTFEATURES) { 588971e3a4bSAndre Guedes struct hci_cp_read_local_ext_features cp; 589971e3a4bSAndre Guedes 590971e3a4bSAndre Guedes cp.page = 0x01; 591971e3a4bSAndre Guedes hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, 592971e3a4bSAndre Guedes sizeof(cp), &cp); 593971e3a4bSAndre Guedes } 594e6100a25SAndre Guedes 59547990ea0SJohan Hedberg if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) { 59647990ea0SJohan Hedberg u8 enable = 1; 59747990ea0SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, 59847990ea0SJohan Hedberg sizeof(enable), &enable); 59947990ea0SJohan Hedberg } 60047990ea0SJohan Hedberg 601e6100a25SAndre Guedes if (hdev->features[4] & LMP_LE) 602e6100a25SAndre Guedes hci_set_le_support(hdev); 603d5859e22SJohan Hedberg } 604d5859e22SJohan Hedberg 605a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) 606a9de9248SMarcel Holtmann { 607a9de9248SMarcel Holtmann struct hci_rp_read_local_version *rp = (void *) skb->data; 6081143e5a6SMarcel Holtmann 609a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 6101143e5a6SMarcel Holtmann 611a9de9248SMarcel Holtmann if (rp->status) 612a9de9248SMarcel Holtmann return; 6131143e5a6SMarcel Holtmann 614a9de9248SMarcel Holtmann hdev->hci_ver = rp->hci_ver; 615e4e8e37cSMarcel Holtmann hdev->hci_rev = __le16_to_cpu(rp->hci_rev); 616d5859e22SJohan Hedberg hdev->lmp_ver = rp->lmp_ver; 617e4e8e37cSMarcel Holtmann hdev->manufacturer = __le16_to_cpu(rp->manufacturer); 618d5859e22SJohan Hedberg hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); 6191da177e4SLinus Torvalds 620a9de9248SMarcel Holtmann BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name, 621a9de9248SMarcel Holtmann hdev->manufacturer, 622a9de9248SMarcel Holtmann hdev->hci_ver, hdev->hci_rev); 623d5859e22SJohan Hedberg 624d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags)) 625d5859e22SJohan Hedberg hci_setup(hdev); 626d5859e22SJohan Hedberg } 627d5859e22SJohan Hedberg 628d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev) 629d5859e22SJohan Hedberg { 630d5859e22SJohan Hedberg u16 link_policy = 0; 631d5859e22SJohan Hedberg 632d5859e22SJohan Hedberg if (hdev->features[0] & LMP_RSWITCH) 633d5859e22SJohan Hedberg link_policy |= HCI_LP_RSWITCH; 634d5859e22SJohan Hedberg if (hdev->features[0] & LMP_HOLD) 635d5859e22SJohan Hedberg link_policy |= HCI_LP_HOLD; 636d5859e22SJohan Hedberg if (hdev->features[0] & LMP_SNIFF) 637d5859e22SJohan Hedberg link_policy |= HCI_LP_SNIFF; 638d5859e22SJohan Hedberg if (hdev->features[1] & LMP_PARK) 639d5859e22SJohan Hedberg link_policy |= HCI_LP_PARK; 640d5859e22SJohan Hedberg 641d5859e22SJohan Hedberg link_policy = cpu_to_le16(link_policy); 642d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, 643d5859e22SJohan Hedberg sizeof(link_policy), &link_policy); 6441da177e4SLinus Torvalds } 6451da177e4SLinus Torvalds 646a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb) 647a9de9248SMarcel Holtmann { 648a9de9248SMarcel Holtmann struct hci_rp_read_local_commands *rp = (void *) skb->data; 649a9de9248SMarcel Holtmann 650a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 651a9de9248SMarcel Holtmann 652a9de9248SMarcel Holtmann if (rp->status) 653d5859e22SJohan Hedberg goto done; 654a9de9248SMarcel Holtmann 655a9de9248SMarcel Holtmann memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); 656d5859e22SJohan Hedberg 657d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10)) 658d5859e22SJohan Hedberg hci_setup_link_policy(hdev); 659d5859e22SJohan Hedberg 660d5859e22SJohan Hedberg done: 661d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status); 662a9de9248SMarcel Holtmann } 663a9de9248SMarcel Holtmann 664a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb) 665a9de9248SMarcel Holtmann { 666a9de9248SMarcel Holtmann struct hci_rp_read_local_features *rp = (void *) skb->data; 667a9de9248SMarcel Holtmann 668a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 669a9de9248SMarcel Holtmann 670a9de9248SMarcel Holtmann if (rp->status) 671a9de9248SMarcel Holtmann return; 672a9de9248SMarcel Holtmann 673a9de9248SMarcel Holtmann memcpy(hdev->features, rp->features, 8); 6741da177e4SLinus Torvalds 6751da177e4SLinus Torvalds /* Adjust default settings according to features 6761da177e4SLinus Torvalds * supported by device. */ 677a9de9248SMarcel Holtmann 6781da177e4SLinus Torvalds if (hdev->features[0] & LMP_3SLOT) 6791da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM3 | HCI_DH3); 6801da177e4SLinus Torvalds 6811da177e4SLinus Torvalds if (hdev->features[0] & LMP_5SLOT) 6821da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM5 | HCI_DH5); 6831da177e4SLinus Torvalds 6845b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV2) { 6851da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV2); 6865b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV2); 6875b7f9909SMarcel Holtmann } 6881da177e4SLinus Torvalds 6895b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV3) { 6901da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV3); 6915b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV3); 6925b7f9909SMarcel Holtmann } 6935b7f9909SMarcel Holtmann 6945b7f9909SMarcel Holtmann if (hdev->features[3] & LMP_ESCO) 6955b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV3); 6965b7f9909SMarcel Holtmann 6975b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV4) 6985b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV4); 6995b7f9909SMarcel Holtmann 7005b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV5) 7015b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV5); 7021da177e4SLinus Torvalds 703efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_2M) 704efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV3); 705efc7688bSMarcel Holtmann 706efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_3M) 707efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_3EV3); 708efc7688bSMarcel Holtmann 709efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_3S_ESCO) 710efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); 711efc7688bSMarcel Holtmann 712a9de9248SMarcel Holtmann BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, 713a9de9248SMarcel Holtmann hdev->features[0], hdev->features[1], 714a9de9248SMarcel Holtmann hdev->features[2], hdev->features[3], 715a9de9248SMarcel Holtmann hdev->features[4], hdev->features[5], 716a9de9248SMarcel Holtmann hdev->features[6], hdev->features[7]); 7171da177e4SLinus Torvalds } 7181da177e4SLinus Torvalds 719971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev, 720971e3a4bSAndre Guedes struct sk_buff *skb) 721971e3a4bSAndre Guedes { 722971e3a4bSAndre Guedes struct hci_rp_read_local_ext_features *rp = (void *) skb->data; 723971e3a4bSAndre Guedes 724971e3a4bSAndre Guedes BT_DBG("%s status 0x%x", hdev->name, rp->status); 725971e3a4bSAndre Guedes 726971e3a4bSAndre Guedes if (rp->status) 727971e3a4bSAndre Guedes return; 728971e3a4bSAndre Guedes 729b5b32b65SAndre Guedes switch (rp->page) { 730b5b32b65SAndre Guedes case 0: 731b5b32b65SAndre Guedes memcpy(hdev->features, rp->features, 8); 732b5b32b65SAndre Guedes break; 733b5b32b65SAndre Guedes case 1: 73459e29406SAndre Guedes memcpy(hdev->host_features, rp->features, 8); 735b5b32b65SAndre Guedes break; 736b5b32b65SAndre Guedes } 737971e3a4bSAndre Guedes 738971e3a4bSAndre Guedes hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status); 739971e3a4bSAndre Guedes } 740971e3a4bSAndre Guedes 7411e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, 7421e89cffbSAndrei Emeltchenko struct sk_buff *skb) 7431e89cffbSAndrei Emeltchenko { 7441e89cffbSAndrei Emeltchenko struct hci_rp_read_flow_control_mode *rp = (void *) skb->data; 7451e89cffbSAndrei Emeltchenko 7461e89cffbSAndrei Emeltchenko BT_DBG("%s status 0x%x", hdev->name, rp->status); 7471e89cffbSAndrei Emeltchenko 7481e89cffbSAndrei Emeltchenko if (rp->status) 7491e89cffbSAndrei Emeltchenko return; 7501e89cffbSAndrei Emeltchenko 7511e89cffbSAndrei Emeltchenko hdev->flow_ctl_mode = rp->mode; 7521e89cffbSAndrei Emeltchenko 7531e89cffbSAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status); 7541e89cffbSAndrei Emeltchenko } 7551e89cffbSAndrei Emeltchenko 756a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 757a9de9248SMarcel Holtmann { 758a9de9248SMarcel Holtmann struct hci_rp_read_buffer_size *rp = (void *) skb->data; 759a9de9248SMarcel Holtmann 760a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 761a9de9248SMarcel Holtmann 762a9de9248SMarcel Holtmann if (rp->status) 763a9de9248SMarcel Holtmann return; 764a9de9248SMarcel Holtmann 765a9de9248SMarcel Holtmann hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); 766a9de9248SMarcel Holtmann hdev->sco_mtu = rp->sco_mtu; 767a9de9248SMarcel Holtmann hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); 768a9de9248SMarcel Holtmann hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); 769da1f5198SMarcel Holtmann 770da1f5198SMarcel Holtmann if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { 771da1f5198SMarcel Holtmann hdev->sco_mtu = 64; 772da1f5198SMarcel Holtmann hdev->sco_pkts = 8; 773da1f5198SMarcel Holtmann } 774da1f5198SMarcel Holtmann 775da1f5198SMarcel Holtmann hdev->acl_cnt = hdev->acl_pkts; 776da1f5198SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 7771da177e4SLinus Torvalds 778a9de9248SMarcel Holtmann BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, 779a9de9248SMarcel Holtmann hdev->acl_mtu, hdev->acl_pkts, 780a9de9248SMarcel Holtmann hdev->sco_mtu, hdev->sco_pkts); 7811da177e4SLinus Torvalds } 7821da177e4SLinus Torvalds 783a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) 784a9de9248SMarcel Holtmann { 785a9de9248SMarcel Holtmann struct hci_rp_read_bd_addr *rp = (void *) skb->data; 7861da177e4SLinus Torvalds 787a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 788a9de9248SMarcel Holtmann 789a9de9248SMarcel Holtmann if (!rp->status) 790a9de9248SMarcel Holtmann bacpy(&hdev->bdaddr, &rp->bdaddr); 791a9de9248SMarcel Holtmann 79223bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status); 79323bb5763SJohan Hedberg } 79423bb5763SJohan Hedberg 795350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev, 796350ee4cfSAndrei Emeltchenko struct sk_buff *skb) 797350ee4cfSAndrei Emeltchenko { 798350ee4cfSAndrei Emeltchenko struct hci_rp_read_data_block_size *rp = (void *) skb->data; 799350ee4cfSAndrei Emeltchenko 800350ee4cfSAndrei Emeltchenko BT_DBG("%s status 0x%x", hdev->name, rp->status); 801350ee4cfSAndrei Emeltchenko 802350ee4cfSAndrei Emeltchenko if (rp->status) 803350ee4cfSAndrei Emeltchenko return; 804350ee4cfSAndrei Emeltchenko 805350ee4cfSAndrei Emeltchenko hdev->block_mtu = __le16_to_cpu(rp->max_acl_len); 806350ee4cfSAndrei Emeltchenko hdev->block_len = __le16_to_cpu(rp->block_len); 807350ee4cfSAndrei Emeltchenko hdev->num_blocks = __le16_to_cpu(rp->num_blocks); 808350ee4cfSAndrei Emeltchenko 809350ee4cfSAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 810350ee4cfSAndrei Emeltchenko 811350ee4cfSAndrei Emeltchenko BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu, 812350ee4cfSAndrei Emeltchenko hdev->block_cnt, hdev->block_len); 813350ee4cfSAndrei Emeltchenko 814350ee4cfSAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status); 815350ee4cfSAndrei Emeltchenko } 816350ee4cfSAndrei Emeltchenko 81723bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb) 81823bb5763SJohan Hedberg { 81923bb5763SJohan Hedberg __u8 status = *((__u8 *) skb->data); 82023bb5763SJohan Hedberg 82123bb5763SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 82223bb5763SJohan Hedberg 82323bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status); 8241da177e4SLinus Torvalds } 8251da177e4SLinus Torvalds 826928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev, 827928abaa7SAndrei Emeltchenko struct sk_buff *skb) 828928abaa7SAndrei Emeltchenko { 829928abaa7SAndrei Emeltchenko struct hci_rp_read_local_amp_info *rp = (void *) skb->data; 830928abaa7SAndrei Emeltchenko 831928abaa7SAndrei Emeltchenko BT_DBG("%s status 0x%x", hdev->name, rp->status); 832928abaa7SAndrei Emeltchenko 833928abaa7SAndrei Emeltchenko if (rp->status) 834928abaa7SAndrei Emeltchenko return; 835928abaa7SAndrei Emeltchenko 836928abaa7SAndrei Emeltchenko hdev->amp_status = rp->amp_status; 837928abaa7SAndrei Emeltchenko hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); 838928abaa7SAndrei Emeltchenko hdev->amp_max_bw = __le32_to_cpu(rp->max_bw); 839928abaa7SAndrei Emeltchenko hdev->amp_min_latency = __le32_to_cpu(rp->min_latency); 840928abaa7SAndrei Emeltchenko hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu); 841928abaa7SAndrei Emeltchenko hdev->amp_type = rp->amp_type; 842928abaa7SAndrei Emeltchenko hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap); 843928abaa7SAndrei Emeltchenko hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size); 844928abaa7SAndrei Emeltchenko hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); 845928abaa7SAndrei Emeltchenko hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); 846928abaa7SAndrei Emeltchenko 847928abaa7SAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status); 848928abaa7SAndrei Emeltchenko } 849928abaa7SAndrei Emeltchenko 850b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, 851b0916ea0SJohan Hedberg struct sk_buff *skb) 852b0916ea0SJohan Hedberg { 853b0916ea0SJohan Hedberg __u8 status = *((__u8 *) skb->data); 854b0916ea0SJohan Hedberg 855b0916ea0SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 856b0916ea0SJohan Hedberg 857b0916ea0SJohan Hedberg hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status); 858b0916ea0SJohan Hedberg } 859b0916ea0SJohan Hedberg 860d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb) 861d5859e22SJohan Hedberg { 862d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 863d5859e22SJohan Hedberg 864d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 865d5859e22SJohan Hedberg 866d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status); 867d5859e22SJohan Hedberg } 868d5859e22SJohan Hedberg 869d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev, 870d5859e22SJohan Hedberg struct sk_buff *skb) 871d5859e22SJohan Hedberg { 872d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 873d5859e22SJohan Hedberg 874d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 875d5859e22SJohan Hedberg 876d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status); 877d5859e22SJohan Hedberg } 878d5859e22SJohan Hedberg 879d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, 880d5859e22SJohan Hedberg struct sk_buff *skb) 881d5859e22SJohan Hedberg { 882d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 883d5859e22SJohan Hedberg 884d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 885d5859e22SJohan Hedberg 886d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status); 887d5859e22SJohan Hedberg } 888d5859e22SJohan Hedberg 889d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb) 890d5859e22SJohan Hedberg { 891d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 892d5859e22SJohan Hedberg 893d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 894d5859e22SJohan Hedberg 895d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status); 896d5859e22SJohan Hedberg } 897d5859e22SJohan Hedberg 898980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) 899980e1a53SJohan Hedberg { 900980e1a53SJohan Hedberg struct hci_rp_pin_code_reply *rp = (void *) skb->data; 901980e1a53SJohan Hedberg struct hci_cp_pin_code_reply *cp; 902980e1a53SJohan Hedberg struct hci_conn *conn; 903980e1a53SJohan Hedberg 904980e1a53SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 905980e1a53SJohan Hedberg 90656e5cb86SJohan Hedberg hci_dev_lock(hdev); 90756e5cb86SJohan Hedberg 908a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 909744cf19eSJohan Hedberg mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); 910980e1a53SJohan Hedberg 911980e1a53SJohan Hedberg if (rp->status != 0) 91256e5cb86SJohan Hedberg goto unlock; 913980e1a53SJohan Hedberg 914980e1a53SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); 915980e1a53SJohan Hedberg if (!cp) 91656e5cb86SJohan Hedberg goto unlock; 917980e1a53SJohan Hedberg 918980e1a53SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 919980e1a53SJohan Hedberg if (conn) 920980e1a53SJohan Hedberg conn->pin_length = cp->pin_len; 92156e5cb86SJohan Hedberg 92256e5cb86SJohan Hedberg unlock: 92356e5cb86SJohan Hedberg hci_dev_unlock(hdev); 924980e1a53SJohan Hedberg } 925980e1a53SJohan Hedberg 926980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 927980e1a53SJohan Hedberg { 928980e1a53SJohan Hedberg struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data; 929980e1a53SJohan Hedberg 930980e1a53SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 931980e1a53SJohan Hedberg 93256e5cb86SJohan Hedberg hci_dev_lock(hdev); 93356e5cb86SJohan Hedberg 934a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 935744cf19eSJohan Hedberg mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr, 936980e1a53SJohan Hedberg rp->status); 93756e5cb86SJohan Hedberg 93856e5cb86SJohan Hedberg hci_dev_unlock(hdev); 939980e1a53SJohan Hedberg } 94056e5cb86SJohan Hedberg 9416ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, 9426ed58ec5SVille Tervo struct sk_buff *skb) 9436ed58ec5SVille Tervo { 9446ed58ec5SVille Tervo struct hci_rp_le_read_buffer_size *rp = (void *) skb->data; 9456ed58ec5SVille Tervo 9466ed58ec5SVille Tervo BT_DBG("%s status 0x%x", hdev->name, rp->status); 9476ed58ec5SVille Tervo 9486ed58ec5SVille Tervo if (rp->status) 9496ed58ec5SVille Tervo return; 9506ed58ec5SVille Tervo 9516ed58ec5SVille Tervo hdev->le_mtu = __le16_to_cpu(rp->le_mtu); 9526ed58ec5SVille Tervo hdev->le_pkts = rp->le_max_pkt; 9536ed58ec5SVille Tervo 9546ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 9556ed58ec5SVille Tervo 9566ed58ec5SVille Tervo BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); 9576ed58ec5SVille Tervo 9586ed58ec5SVille Tervo hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status); 9596ed58ec5SVille Tervo } 960980e1a53SJohan Hedberg 961a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) 962a5c29683SJohan Hedberg { 963a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 964a5c29683SJohan Hedberg 965a5c29683SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 966a5c29683SJohan Hedberg 96756e5cb86SJohan Hedberg hci_dev_lock(hdev); 96856e5cb86SJohan Hedberg 969a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 970272d90dfSJohan Hedberg mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 971272d90dfSJohan Hedberg 0, rp->status); 97256e5cb86SJohan Hedberg 97356e5cb86SJohan Hedberg hci_dev_unlock(hdev); 974a5c29683SJohan Hedberg } 975a5c29683SJohan Hedberg 976a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, 977a5c29683SJohan Hedberg struct sk_buff *skb) 978a5c29683SJohan Hedberg { 979a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 980a5c29683SJohan Hedberg 981a5c29683SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 982a5c29683SJohan Hedberg 98356e5cb86SJohan Hedberg hci_dev_lock(hdev); 98456e5cb86SJohan Hedberg 985a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 986744cf19eSJohan Hedberg mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr, 987272d90dfSJohan Hedberg ACL_LINK, 0, 988a5c29683SJohan Hedberg rp->status); 98956e5cb86SJohan Hedberg 99056e5cb86SJohan Hedberg hci_dev_unlock(hdev); 991a5c29683SJohan Hedberg } 992a5c29683SJohan Hedberg 9931143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb) 9941143d458SBrian Gix { 9951143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 9961143d458SBrian Gix 9971143d458SBrian Gix BT_DBG("%s status 0x%x", hdev->name, rp->status); 9981143d458SBrian Gix 9991143d458SBrian Gix hci_dev_lock(hdev); 10001143d458SBrian Gix 1001a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1002272d90dfSJohan Hedberg mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 1003272d90dfSJohan Hedberg 0, rp->status); 10041143d458SBrian Gix 10051143d458SBrian Gix hci_dev_unlock(hdev); 10061143d458SBrian Gix } 10071143d458SBrian Gix 10081143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, 10091143d458SBrian Gix struct sk_buff *skb) 10101143d458SBrian Gix { 10111143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 10121143d458SBrian Gix 10131143d458SBrian Gix BT_DBG("%s status 0x%x", hdev->name, rp->status); 10141143d458SBrian Gix 10151143d458SBrian Gix hci_dev_lock(hdev); 10161143d458SBrian Gix 1017a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 10181143d458SBrian Gix mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr, 1019272d90dfSJohan Hedberg ACL_LINK, 0, 10201143d458SBrian Gix rp->status); 10211143d458SBrian Gix 10221143d458SBrian Gix hci_dev_unlock(hdev); 10231143d458SBrian Gix } 10241143d458SBrian Gix 1025c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, 1026c35938b2SSzymon Janc struct sk_buff *skb) 1027c35938b2SSzymon Janc { 1028c35938b2SSzymon Janc struct hci_rp_read_local_oob_data *rp = (void *) skb->data; 1029c35938b2SSzymon Janc 1030c35938b2SSzymon Janc BT_DBG("%s status 0x%x", hdev->name, rp->status); 1031c35938b2SSzymon Janc 103256e5cb86SJohan Hedberg hci_dev_lock(hdev); 1033744cf19eSJohan Hedberg mgmt_read_local_oob_data_reply_complete(hdev, rp->hash, 1034c35938b2SSzymon Janc rp->randomizer, rp->status); 103556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1036c35938b2SSzymon Janc } 1037c35938b2SSzymon Janc 103807f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) 103907f7fa5dSAndre Guedes { 104007f7fa5dSAndre Guedes __u8 status = *((__u8 *) skb->data); 104107f7fa5dSAndre Guedes 104207f7fa5dSAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 10437ba8b4beSAndre Guedes 10447ba8b4beSAndre Guedes hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status); 10453fd24153SAndre Guedes 10463fd24153SAndre Guedes if (status) { 10473fd24153SAndre Guedes hci_dev_lock(hdev); 10483fd24153SAndre Guedes mgmt_start_discovery_failed(hdev, status); 10493fd24153SAndre Guedes hci_dev_unlock(hdev); 10503fd24153SAndre Guedes return; 10513fd24153SAndre Guedes } 105207f7fa5dSAndre Guedes } 105307f7fa5dSAndre Guedes 1054eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, 1055eb9d91f5SAndre Guedes struct sk_buff *skb) 1056eb9d91f5SAndre Guedes { 1057eb9d91f5SAndre Guedes struct hci_cp_le_set_scan_enable *cp; 1058eb9d91f5SAndre Guedes __u8 status = *((__u8 *) skb->data); 1059eb9d91f5SAndre Guedes 1060eb9d91f5SAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 1061eb9d91f5SAndre Guedes 1062eb9d91f5SAndre Guedes cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE); 1063eb9d91f5SAndre Guedes if (!cp) 1064eb9d91f5SAndre Guedes return; 1065eb9d91f5SAndre Guedes 106668a8aea4SAndrei Emeltchenko switch (cp->enable) { 106768a8aea4SAndrei Emeltchenko case LE_SCANNING_ENABLED: 10687ba8b4beSAndre Guedes hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status); 10697ba8b4beSAndre Guedes 10703fd24153SAndre Guedes if (status) { 10713fd24153SAndre Guedes hci_dev_lock(hdev); 10723fd24153SAndre Guedes mgmt_start_discovery_failed(hdev, status); 10733fd24153SAndre Guedes hci_dev_unlock(hdev); 10747ba8b4beSAndre Guedes return; 10753fd24153SAndre Guedes } 10767ba8b4beSAndre Guedes 1077d23264a8SAndre Guedes set_bit(HCI_LE_SCAN, &hdev->dev_flags); 1078d23264a8SAndre Guedes 1079db323f2fSGustavo F. Padovan cancel_delayed_work_sync(&hdev->adv_work); 1080a8f13c8cSAndre Guedes 1081a8f13c8cSAndre Guedes hci_dev_lock(hdev); 1082eb9d91f5SAndre Guedes hci_adv_entries_clear(hdev); 1083343f935bSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_FINDING); 1084a8f13c8cSAndre Guedes hci_dev_unlock(hdev); 108568a8aea4SAndrei Emeltchenko break; 108668a8aea4SAndrei Emeltchenko 108768a8aea4SAndrei Emeltchenko case LE_SCANNING_DISABLED: 10887ba8b4beSAndre Guedes if (status) 10897ba8b4beSAndre Guedes return; 10907ba8b4beSAndre Guedes 1091d23264a8SAndre Guedes clear_bit(HCI_LE_SCAN, &hdev->dev_flags); 1092d23264a8SAndre Guedes 10935e0452c0SAndre Guedes schedule_delayed_work(&hdev->adv_work, ADV_CLEAR_TIMEOUT); 10945e0452c0SAndre Guedes 10955e0452c0SAndre Guedes if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED) { 10965e0452c0SAndre Guedes mgmt_interleaved_discovery(hdev); 10975e0452c0SAndre Guedes } else { 1098c599008fSAndre Guedes hci_dev_lock(hdev); 1099c599008fSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 1100c599008fSAndre Guedes hci_dev_unlock(hdev); 11015e0452c0SAndre Guedes } 1102c599008fSAndre Guedes 110368a8aea4SAndrei Emeltchenko break; 110468a8aea4SAndrei Emeltchenko 110568a8aea4SAndrei Emeltchenko default: 110668a8aea4SAndrei Emeltchenko BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable); 110768a8aea4SAndrei Emeltchenko break; 110835815085SAndre Guedes } 1109eb9d91f5SAndre Guedes } 1110eb9d91f5SAndre Guedes 1111a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb) 1112a7a595f6SVinicius Costa Gomes { 1113a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_reply *rp = (void *) skb->data; 1114a7a595f6SVinicius Costa Gomes 1115a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, rp->status); 1116a7a595f6SVinicius Costa Gomes 1117a7a595f6SVinicius Costa Gomes if (rp->status) 1118a7a595f6SVinicius Costa Gomes return; 1119a7a595f6SVinicius Costa Gomes 1120a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status); 1121a7a595f6SVinicius Costa Gomes } 1122a7a595f6SVinicius Costa Gomes 1123a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 1124a7a595f6SVinicius Costa Gomes { 1125a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data; 1126a7a595f6SVinicius Costa Gomes 1127a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, rp->status); 1128a7a595f6SVinicius Costa Gomes 1129a7a595f6SVinicius Costa Gomes if (rp->status) 1130a7a595f6SVinicius Costa Gomes return; 1131a7a595f6SVinicius Costa Gomes 1132a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status); 1133a7a595f6SVinicius Costa Gomes } 1134a7a595f6SVinicius Costa Gomes 1135f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev, 1136f9b49306SAndre Guedes struct sk_buff *skb) 1137f9b49306SAndre Guedes { 1138f9b49306SAndre Guedes struct hci_cp_read_local_ext_features cp; 113906199cf8SJohan Hedberg struct hci_cp_write_le_host_supported *sent; 1140f9b49306SAndre Guedes __u8 status = *((__u8 *) skb->data); 1141f9b49306SAndre Guedes 1142f9b49306SAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 1143f9b49306SAndre Guedes 114406199cf8SJohan Hedberg sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED); 114506199cf8SJohan Hedberg if (sent && test_bit(HCI_MGMT, &hdev->dev_flags)) 114606199cf8SJohan Hedberg mgmt_le_enable_complete(hdev, sent->le, status); 114706199cf8SJohan Hedberg 1148f9b49306SAndre Guedes if (status) 1149f9b49306SAndre Guedes return; 1150f9b49306SAndre Guedes 1151f9b49306SAndre Guedes cp.page = 0x01; 1152f9b49306SAndre Guedes hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp); 1153f9b49306SAndre Guedes } 1154f9b49306SAndre Guedes 1155a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 1156a9de9248SMarcel Holtmann { 1157a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1158a9de9248SMarcel Holtmann 1159a9de9248SMarcel Holtmann if (status) { 116023bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 1161a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 116256e5cb86SJohan Hedberg hci_dev_lock(hdev); 1163a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 11647a135109SAndre Guedes mgmt_start_discovery_failed(hdev, status); 116556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1166314b2381SJohan Hedberg return; 1167314b2381SJohan Hedberg } 1168314b2381SJohan Hedberg 116989352e7dSAndre Guedes set_bit(HCI_INQUIRY, &hdev->flags); 117089352e7dSAndre Guedes 117156e5cb86SJohan Hedberg hci_dev_lock(hdev); 1172343f935bSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_FINDING); 117356e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1174a9de9248SMarcel Holtmann } 1175a9de9248SMarcel Holtmann 11761da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 11771da177e4SLinus Torvalds { 1178a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 11791da177e4SLinus Torvalds struct hci_conn *conn; 11801da177e4SLinus Torvalds 1181a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1182a9de9248SMarcel Holtmann 1183a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 11841da177e4SLinus Torvalds if (!cp) 11851da177e4SLinus Torvalds return; 11861da177e4SLinus Torvalds 11871da177e4SLinus Torvalds hci_dev_lock(hdev); 11881da177e4SLinus Torvalds 11891da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 11901da177e4SLinus Torvalds 1191a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn); 11921da177e4SLinus Torvalds 11931da177e4SLinus Torvalds if (status) { 11941da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 11954c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 11961da177e4SLinus Torvalds conn->state = BT_CLOSED; 11971da177e4SLinus Torvalds hci_proto_connect_cfm(conn, status); 11981da177e4SLinus Torvalds hci_conn_del(conn); 11994c67bc74SMarcel Holtmann } else 12004c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 12011da177e4SLinus Torvalds } 12021da177e4SLinus Torvalds } else { 12031da177e4SLinus Torvalds if (!conn) { 12041da177e4SLinus Torvalds conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); 12051da177e4SLinus Torvalds if (conn) { 1206a0c808b3SJohan Hedberg conn->out = true; 12071da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 12081da177e4SLinus Torvalds } else 1209893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 12101da177e4SLinus Torvalds } 12111da177e4SLinus Torvalds } 12121da177e4SLinus Torvalds 12131da177e4SLinus Torvalds hci_dev_unlock(hdev); 12141da177e4SLinus Torvalds } 12151da177e4SLinus Torvalds 1216a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 12171da177e4SLinus Torvalds { 1218a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 12191da177e4SLinus Torvalds struct hci_conn *acl, *sco; 12201da177e4SLinus Torvalds __u16 handle; 12211da177e4SLinus Torvalds 1222b6a0dc82SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1223b6a0dc82SMarcel Holtmann 1224a9de9248SMarcel Holtmann if (!status) 1225a9de9248SMarcel Holtmann return; 1226a9de9248SMarcel Holtmann 1227a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 12281da177e4SLinus Torvalds if (!cp) 1229a9de9248SMarcel Holtmann return; 12301da177e4SLinus Torvalds 12311da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 12321da177e4SLinus Torvalds 1233a9de9248SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 12341da177e4SLinus Torvalds 12351da177e4SLinus Torvalds hci_dev_lock(hdev); 12361da177e4SLinus Torvalds 12371da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 12385a08ecceSAndrei Emeltchenko if (acl) { 12395a08ecceSAndrei Emeltchenko sco = acl->link; 12405a08ecceSAndrei Emeltchenko if (sco) { 12411da177e4SLinus Torvalds sco->state = BT_CLOSED; 12421da177e4SLinus Torvalds 12431da177e4SLinus Torvalds hci_proto_connect_cfm(sco, status); 12441da177e4SLinus Torvalds hci_conn_del(sco); 12451da177e4SLinus Torvalds } 12465a08ecceSAndrei Emeltchenko } 12471da177e4SLinus Torvalds 12481da177e4SLinus Torvalds hci_dev_unlock(hdev); 12491da177e4SLinus Torvalds } 12501da177e4SLinus Torvalds 1251f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 1252f8558555SMarcel Holtmann { 1253f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 1254f8558555SMarcel Holtmann struct hci_conn *conn; 1255f8558555SMarcel Holtmann 1256f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1257f8558555SMarcel Holtmann 1258f8558555SMarcel Holtmann if (!status) 1259f8558555SMarcel Holtmann return; 1260f8558555SMarcel Holtmann 1261f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 1262f8558555SMarcel Holtmann if (!cp) 1263f8558555SMarcel Holtmann return; 1264f8558555SMarcel Holtmann 1265f8558555SMarcel Holtmann hci_dev_lock(hdev); 1266f8558555SMarcel Holtmann 1267f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1268f8558555SMarcel Holtmann if (conn) { 1269f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1270f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1271f8558555SMarcel Holtmann hci_conn_put(conn); 1272f8558555SMarcel Holtmann } 1273f8558555SMarcel Holtmann } 1274f8558555SMarcel Holtmann 1275f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1276f8558555SMarcel Holtmann } 1277f8558555SMarcel Holtmann 1278f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 1279f8558555SMarcel Holtmann { 1280f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 1281f8558555SMarcel Holtmann struct hci_conn *conn; 1282f8558555SMarcel Holtmann 1283f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1284f8558555SMarcel Holtmann 1285f8558555SMarcel Holtmann if (!status) 1286f8558555SMarcel Holtmann return; 1287f8558555SMarcel Holtmann 1288f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 1289f8558555SMarcel Holtmann if (!cp) 1290f8558555SMarcel Holtmann return; 1291f8558555SMarcel Holtmann 1292f8558555SMarcel Holtmann hci_dev_lock(hdev); 1293f8558555SMarcel Holtmann 1294f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1295f8558555SMarcel Holtmann if (conn) { 1296f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1297f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1298f8558555SMarcel Holtmann hci_conn_put(conn); 1299f8558555SMarcel Holtmann } 1300f8558555SMarcel Holtmann } 1301f8558555SMarcel Holtmann 1302f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1303f8558555SMarcel Holtmann } 1304f8558555SMarcel Holtmann 1305127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev, 1306392599b9SJohan Hedberg struct hci_conn *conn) 1307392599b9SJohan Hedberg { 1308392599b9SJohan Hedberg if (conn->state != BT_CONFIG || !conn->out) 1309392599b9SJohan Hedberg return 0; 1310392599b9SJohan Hedberg 1311765c2a96SJohan Hedberg if (conn->pending_sec_level == BT_SECURITY_SDP) 1312392599b9SJohan Hedberg return 0; 1313392599b9SJohan Hedberg 1314392599b9SJohan Hedberg /* Only request authentication for SSP connections or non-SSP 1315e9bf2bf0SVinicius Costa Gomes * devices with sec_level HIGH or if MITM protection is requested */ 1316aa64a8b5SJohan Hedberg if (!hci_conn_ssp_enabled(conn) && 1317e9bf2bf0SVinicius Costa Gomes conn->pending_sec_level != BT_SECURITY_HIGH && 1318e9bf2bf0SVinicius Costa Gomes !(conn->auth_type & 0x01)) 1319392599b9SJohan Hedberg return 0; 1320392599b9SJohan Hedberg 1321392599b9SJohan Hedberg return 1; 1322392599b9SJohan Hedberg } 1323392599b9SJohan Hedberg 132430dc78e1SJohan Hedberg static inline int hci_resolve_name(struct hci_dev *hdev, struct inquiry_entry *e) 132530dc78e1SJohan Hedberg { 132630dc78e1SJohan Hedberg struct hci_cp_remote_name_req cp; 132730dc78e1SJohan Hedberg 132830dc78e1SJohan Hedberg memset(&cp, 0, sizeof(cp)); 132930dc78e1SJohan Hedberg 133030dc78e1SJohan Hedberg bacpy(&cp.bdaddr, &e->data.bdaddr); 133130dc78e1SJohan Hedberg cp.pscan_rep_mode = e->data.pscan_rep_mode; 133230dc78e1SJohan Hedberg cp.pscan_mode = e->data.pscan_mode; 133330dc78e1SJohan Hedberg cp.clock_offset = e->data.clock_offset; 133430dc78e1SJohan Hedberg 133530dc78e1SJohan Hedberg return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 133630dc78e1SJohan Hedberg } 133730dc78e1SJohan Hedberg 1338b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev) 133930dc78e1SJohan Hedberg { 134030dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 134130dc78e1SJohan Hedberg struct inquiry_entry *e; 134230dc78e1SJohan Hedberg 1343b644ba33SJohan Hedberg if (list_empty(&discov->resolve)) 1344b644ba33SJohan Hedberg return false; 1345b644ba33SJohan Hedberg 1346b644ba33SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 1347b644ba33SJohan Hedberg if (hci_resolve_name(hdev, e) == 0) { 1348b644ba33SJohan Hedberg e->name_state = NAME_PENDING; 1349b644ba33SJohan Hedberg return true; 1350b644ba33SJohan Hedberg } 1351b644ba33SJohan Hedberg 1352b644ba33SJohan Hedberg return false; 1353b644ba33SJohan Hedberg } 1354b644ba33SJohan Hedberg 1355b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn, 1356b644ba33SJohan Hedberg bdaddr_t *bdaddr, u8 *name, u8 name_len) 1357b644ba33SJohan Hedberg { 1358b644ba33SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 1359b644ba33SJohan Hedberg struct inquiry_entry *e; 1360b644ba33SJohan Hedberg 1361b644ba33SJohan Hedberg if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 1362b644ba33SJohan Hedberg mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 1363b644ba33SJohan Hedberg name, name_len, conn->dev_class); 1364b644ba33SJohan Hedberg 1365b644ba33SJohan Hedberg if (discov->state == DISCOVERY_STOPPED) 1366b644ba33SJohan Hedberg return; 1367b644ba33SJohan Hedberg 136830dc78e1SJohan Hedberg if (discov->state == DISCOVERY_STOPPING) 136930dc78e1SJohan Hedberg goto discov_complete; 137030dc78e1SJohan Hedberg 137130dc78e1SJohan Hedberg if (discov->state != DISCOVERY_RESOLVING) 137230dc78e1SJohan Hedberg return; 137330dc78e1SJohan Hedberg 137430dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING); 137530dc78e1SJohan Hedberg if (e) { 137630dc78e1SJohan Hedberg e->name_state = NAME_KNOWN; 137730dc78e1SJohan Hedberg list_del(&e->list); 1378b644ba33SJohan Hedberg if (name) 1379b644ba33SJohan Hedberg mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, 1380b644ba33SJohan Hedberg e->data.rssi, name, name_len); 138130dc78e1SJohan Hedberg } 138230dc78e1SJohan Hedberg 1383b644ba33SJohan Hedberg if (hci_resolve_next_name(hdev)) 138430dc78e1SJohan Hedberg return; 138530dc78e1SJohan Hedberg 138630dc78e1SJohan Hedberg discov_complete: 138730dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 138830dc78e1SJohan Hedberg } 138930dc78e1SJohan Hedberg 1390a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 13911da177e4SLinus Torvalds { 1392127178d2SJohan Hedberg struct hci_cp_remote_name_req *cp; 1393127178d2SJohan Hedberg struct hci_conn *conn; 1394127178d2SJohan Hedberg 1395a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1396127178d2SJohan Hedberg 1397127178d2SJohan Hedberg /* If successful wait for the name req complete event before 1398127178d2SJohan Hedberg * checking for the need to do authentication */ 1399127178d2SJohan Hedberg if (!status) 1400127178d2SJohan Hedberg return; 1401127178d2SJohan Hedberg 1402127178d2SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); 1403127178d2SJohan Hedberg if (!cp) 1404127178d2SJohan Hedberg return; 1405127178d2SJohan Hedberg 1406127178d2SJohan Hedberg hci_dev_lock(hdev); 1407127178d2SJohan Hedberg 1408127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 1409b644ba33SJohan Hedberg 1410b644ba33SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1411b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0); 1412b644ba33SJohan Hedberg 141379c6c70cSJohan Hedberg if (!conn) 141479c6c70cSJohan Hedberg goto unlock; 141579c6c70cSJohan Hedberg 141679c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 141779c6c70cSJohan Hedberg goto unlock; 141879c6c70cSJohan Hedberg 141951a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 1420127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1421127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1422127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1423127178d2SJohan Hedberg } 1424127178d2SJohan Hedberg 142579c6c70cSJohan Hedberg unlock: 1426127178d2SJohan Hedberg hci_dev_unlock(hdev); 1427a9de9248SMarcel Holtmann } 14281da177e4SLinus Torvalds 1429769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 1430769be974SMarcel Holtmann { 1431769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 1432769be974SMarcel Holtmann struct hci_conn *conn; 1433769be974SMarcel Holtmann 1434769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1435769be974SMarcel Holtmann 1436769be974SMarcel Holtmann if (!status) 1437769be974SMarcel Holtmann return; 1438769be974SMarcel Holtmann 1439769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 1440769be974SMarcel Holtmann if (!cp) 1441769be974SMarcel Holtmann return; 1442769be974SMarcel Holtmann 1443769be974SMarcel Holtmann hci_dev_lock(hdev); 1444769be974SMarcel Holtmann 1445769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1446769be974SMarcel Holtmann if (conn) { 1447769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1448769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1449769be974SMarcel Holtmann hci_conn_put(conn); 1450769be974SMarcel Holtmann } 1451769be974SMarcel Holtmann } 1452769be974SMarcel Holtmann 1453769be974SMarcel Holtmann hci_dev_unlock(hdev); 1454769be974SMarcel Holtmann } 1455769be974SMarcel Holtmann 1456769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 1457769be974SMarcel Holtmann { 1458769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features *cp; 1459769be974SMarcel Holtmann struct hci_conn *conn; 1460769be974SMarcel Holtmann 1461769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1462769be974SMarcel Holtmann 1463769be974SMarcel Holtmann if (!status) 1464769be974SMarcel Holtmann return; 1465769be974SMarcel Holtmann 1466769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 1467769be974SMarcel Holtmann if (!cp) 1468769be974SMarcel Holtmann return; 1469769be974SMarcel Holtmann 1470769be974SMarcel Holtmann hci_dev_lock(hdev); 1471769be974SMarcel Holtmann 1472769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1473769be974SMarcel Holtmann if (conn) { 1474769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1475769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1476769be974SMarcel Holtmann hci_conn_put(conn); 1477769be974SMarcel Holtmann } 1478769be974SMarcel Holtmann } 1479769be974SMarcel Holtmann 1480769be974SMarcel Holtmann hci_dev_unlock(hdev); 1481769be974SMarcel Holtmann } 1482769be974SMarcel Holtmann 1483a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 1484a9de9248SMarcel Holtmann { 1485b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 1486b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 1487b6a0dc82SMarcel Holtmann __u16 handle; 1488b6a0dc82SMarcel Holtmann 1489a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1490b6a0dc82SMarcel Holtmann 1491b6a0dc82SMarcel Holtmann if (!status) 1492b6a0dc82SMarcel Holtmann return; 1493b6a0dc82SMarcel Holtmann 1494b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 1495b6a0dc82SMarcel Holtmann if (!cp) 1496b6a0dc82SMarcel Holtmann return; 1497b6a0dc82SMarcel Holtmann 1498b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 1499b6a0dc82SMarcel Holtmann 1500b6a0dc82SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 1501b6a0dc82SMarcel Holtmann 1502b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 1503b6a0dc82SMarcel Holtmann 1504b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 15055a08ecceSAndrei Emeltchenko if (acl) { 15065a08ecceSAndrei Emeltchenko sco = acl->link; 15075a08ecceSAndrei Emeltchenko if (sco) { 1508b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 1509b6a0dc82SMarcel Holtmann 1510b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(sco, status); 1511b6a0dc82SMarcel Holtmann hci_conn_del(sco); 1512b6a0dc82SMarcel Holtmann } 15135a08ecceSAndrei Emeltchenko } 1514b6a0dc82SMarcel Holtmann 1515b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 1516a9de9248SMarcel Holtmann } 1517a9de9248SMarcel Holtmann 1518a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 1519a9de9248SMarcel Holtmann { 1520a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 152104837f64SMarcel Holtmann struct hci_conn *conn; 152204837f64SMarcel Holtmann 1523a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1524a9de9248SMarcel Holtmann 1525a9de9248SMarcel Holtmann if (!status) 1526a9de9248SMarcel Holtmann return; 1527a9de9248SMarcel Holtmann 1528a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 152904837f64SMarcel Holtmann if (!cp) 1530a9de9248SMarcel Holtmann return; 153104837f64SMarcel Holtmann 153204837f64SMarcel Holtmann hci_dev_lock(hdev); 153304837f64SMarcel Holtmann 153404837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1535e73439d8SMarcel Holtmann if (conn) { 153651a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 153704837f64SMarcel Holtmann 153851a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1539e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1540e73439d8SMarcel Holtmann } 1541e73439d8SMarcel Holtmann 154204837f64SMarcel Holtmann hci_dev_unlock(hdev); 154304837f64SMarcel Holtmann } 154404837f64SMarcel Holtmann 1545a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 1546a9de9248SMarcel Holtmann { 1547a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 154804837f64SMarcel Holtmann struct hci_conn *conn; 154904837f64SMarcel Holtmann 1550a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1551a9de9248SMarcel Holtmann 1552a9de9248SMarcel Holtmann if (!status) 1553a9de9248SMarcel Holtmann return; 1554a9de9248SMarcel Holtmann 1555a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 155604837f64SMarcel Holtmann if (!cp) 1557a9de9248SMarcel Holtmann return; 155804837f64SMarcel Holtmann 155904837f64SMarcel Holtmann hci_dev_lock(hdev); 156004837f64SMarcel Holtmann 156104837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1562e73439d8SMarcel Holtmann if (conn) { 156351a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 156404837f64SMarcel Holtmann 156551a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1566e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1567e73439d8SMarcel Holtmann } 1568e73439d8SMarcel Holtmann 156904837f64SMarcel Holtmann hci_dev_unlock(hdev); 157004837f64SMarcel Holtmann } 157104837f64SMarcel Holtmann 157288c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) 157388c3df13SJohan Hedberg { 157488c3df13SJohan Hedberg struct hci_cp_disconnect *cp; 157588c3df13SJohan Hedberg struct hci_conn *conn; 157688c3df13SJohan Hedberg 157788c3df13SJohan Hedberg if (!status) 157888c3df13SJohan Hedberg return; 157988c3df13SJohan Hedberg 158088c3df13SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT); 158188c3df13SJohan Hedberg if (!cp) 158288c3df13SJohan Hedberg return; 158388c3df13SJohan Hedberg 158488c3df13SJohan Hedberg hci_dev_lock(hdev); 158588c3df13SJohan Hedberg 158688c3df13SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 158788c3df13SJohan Hedberg if (conn) 158888c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 158988c3df13SJohan Hedberg conn->dst_type, status); 159088c3df13SJohan Hedberg 159188c3df13SJohan Hedberg hci_dev_unlock(hdev); 159288c3df13SJohan Hedberg } 159388c3df13SJohan Hedberg 1594fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) 1595fcd89c09SVille Tervo { 1596fcd89c09SVille Tervo struct hci_cp_le_create_conn *cp; 1597fcd89c09SVille Tervo struct hci_conn *conn; 1598fcd89c09SVille Tervo 1599fcd89c09SVille Tervo BT_DBG("%s status 0x%x", hdev->name, status); 1600fcd89c09SVille Tervo 1601fcd89c09SVille Tervo cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN); 1602fcd89c09SVille Tervo if (!cp) 1603fcd89c09SVille Tervo return; 1604fcd89c09SVille Tervo 1605fcd89c09SVille Tervo hci_dev_lock(hdev); 1606fcd89c09SVille Tervo 1607fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr); 1608fcd89c09SVille Tervo 1609fcd89c09SVille Tervo BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr), 1610fcd89c09SVille Tervo conn); 1611fcd89c09SVille Tervo 1612fcd89c09SVille Tervo if (status) { 1613fcd89c09SVille Tervo if (conn && conn->state == BT_CONNECT) { 1614fcd89c09SVille Tervo conn->state = BT_CLOSED; 1615fcd89c09SVille Tervo hci_proto_connect_cfm(conn, status); 1616fcd89c09SVille Tervo hci_conn_del(conn); 1617fcd89c09SVille Tervo } 1618fcd89c09SVille Tervo } else { 1619fcd89c09SVille Tervo if (!conn) { 1620fcd89c09SVille Tervo conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr); 162129b7988aSAndre Guedes if (conn) { 162229b7988aSAndre Guedes conn->dst_type = cp->peer_addr_type; 1623a0c808b3SJohan Hedberg conn->out = true; 162429b7988aSAndre Guedes } else { 1625fcd89c09SVille Tervo BT_ERR("No memory for new connection"); 1626fcd89c09SVille Tervo } 1627fcd89c09SVille Tervo } 162829b7988aSAndre Guedes } 1629fcd89c09SVille Tervo 1630fcd89c09SVille Tervo hci_dev_unlock(hdev); 1631fcd89c09SVille Tervo } 1632fcd89c09SVille Tervo 1633a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) 1634a7a595f6SVinicius Costa Gomes { 1635a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, status); 1636a7a595f6SVinicius Costa Gomes } 1637a7a595f6SVinicius Costa Gomes 16381da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 16391da177e4SLinus Torvalds { 16401da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 164130dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 164230dc78e1SJohan Hedberg struct inquiry_entry *e; 16431da177e4SLinus Torvalds 16441da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, status); 16451da177e4SLinus Torvalds 164623bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 16476bd57416SMarcel Holtmann 1648a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 164989352e7dSAndre Guedes 165089352e7dSAndre Guedes if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) 165189352e7dSAndre Guedes return; 165289352e7dSAndre Guedes 1653a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 165430dc78e1SJohan Hedberg return; 165530dc78e1SJohan Hedberg 165656e5cb86SJohan Hedberg hci_dev_lock(hdev); 165730dc78e1SJohan Hedberg 1658343f935bSAndre Guedes if (discov->state != DISCOVERY_FINDING) 165930dc78e1SJohan Hedberg goto unlock; 166030dc78e1SJohan Hedberg 166130dc78e1SJohan Hedberg if (list_empty(&discov->resolve)) { 1662ff9ef578SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 166330dc78e1SJohan Hedberg goto unlock; 166430dc78e1SJohan Hedberg } 166530dc78e1SJohan Hedberg 166630dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 166730dc78e1SJohan Hedberg if (e && hci_resolve_name(hdev, e) == 0) { 166830dc78e1SJohan Hedberg e->name_state = NAME_PENDING; 166930dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_RESOLVING); 167030dc78e1SJohan Hedberg } else { 167130dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 167230dc78e1SJohan Hedberg } 167330dc78e1SJohan Hedberg 167430dc78e1SJohan Hedberg unlock: 167556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 16761da177e4SLinus Torvalds } 16771da177e4SLinus Torvalds 16781da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 16791da177e4SLinus Torvalds { 168045bb4bf0SMarcel Holtmann struct inquiry_data data; 1681a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 16821da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 16831da177e4SLinus Torvalds 16841da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 16851da177e4SLinus Torvalds 168645bb4bf0SMarcel Holtmann if (!num_rsp) 168745bb4bf0SMarcel Holtmann return; 168845bb4bf0SMarcel Holtmann 16891da177e4SLinus Torvalds hci_dev_lock(hdev); 169045bb4bf0SMarcel Holtmann 1691e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 16923175405bSJohan Hedberg bool name_known; 16933175405bSJohan Hedberg 16941da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 16951da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 16961da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 16971da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 16981da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 16991da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 17001da177e4SLinus Torvalds data.rssi = 0x00; 170141a96212SMarcel Holtmann data.ssp_mode = 0x00; 17023175405bSJohan Hedberg 17033175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, false); 170448264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 17057d262f86SAndre Guedes info->dev_class, 0, !name_known, 17067d262f86SAndre Guedes NULL, 0); 17071da177e4SLinus Torvalds } 170845bb4bf0SMarcel Holtmann 17091da177e4SLinus Torvalds hci_dev_unlock(hdev); 17101da177e4SLinus Torvalds } 17111da177e4SLinus Torvalds 1712a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 17131da177e4SLinus Torvalds { 1714a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 1715a9de9248SMarcel Holtmann struct hci_conn *conn; 17161da177e4SLinus Torvalds 1717a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 171845bb4bf0SMarcel Holtmann 17191da177e4SLinus Torvalds hci_dev_lock(hdev); 172045bb4bf0SMarcel Holtmann 1721a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 17229499237aSMarcel Holtmann if (!conn) { 17239499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 17249499237aSMarcel Holtmann goto unlock; 17259499237aSMarcel Holtmann 17269499237aSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 1727a9de9248SMarcel Holtmann if (!conn) 1728a9de9248SMarcel Holtmann goto unlock; 172945bb4bf0SMarcel Holtmann 17309499237aSMarcel Holtmann conn->type = SCO_LINK; 17319499237aSMarcel Holtmann } 17329499237aSMarcel Holtmann 1733a9de9248SMarcel Holtmann if (!ev->status) { 1734a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 1735769be974SMarcel Holtmann 1736769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 1737769be974SMarcel Holtmann conn->state = BT_CONFIG; 1738769be974SMarcel Holtmann hci_conn_hold(conn); 1739052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1740769be974SMarcel Holtmann } else 1741a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 1742a9de9248SMarcel Holtmann 17439eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 17447d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 17457d0db0a3SMarcel Holtmann 1746a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 1747a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1748a9de9248SMarcel Holtmann 1749a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 1750a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1751a9de9248SMarcel Holtmann 1752a9de9248SMarcel Holtmann /* Get remote features */ 1753a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 1754a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 1755a9de9248SMarcel Holtmann cp.handle = ev->handle; 1756769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 1757769be974SMarcel Holtmann sizeof(cp), &cp); 175845bb4bf0SMarcel Holtmann } 1759a9de9248SMarcel Holtmann 1760a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 1761d095c1ebSAndrei Emeltchenko if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) { 1762a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 1763a9de9248SMarcel Holtmann cp.handle = ev->handle; 1764a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1765a8746417SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, 1766a8746417SMarcel Holtmann sizeof(cp), &cp); 1767a9de9248SMarcel Holtmann } 176817d5c04cSJohan Hedberg } else { 1769a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 177017d5c04cSJohan Hedberg if (conn->type == ACL_LINK) 1771744cf19eSJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 177248264f06SJohan Hedberg conn->dst_type, ev->status); 177317d5c04cSJohan Hedberg } 177445bb4bf0SMarcel Holtmann 1775e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 1776e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 177745bb4bf0SMarcel Holtmann 1778769be974SMarcel Holtmann if (ev->status) { 1779a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1780a9de9248SMarcel Holtmann hci_conn_del(conn); 1781c89b6e6bSMarcel Holtmann } else if (ev->link_type != ACL_LINK) 1782c89b6e6bSMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1783a9de9248SMarcel Holtmann 1784a9de9248SMarcel Holtmann unlock: 17851da177e4SLinus Torvalds hci_dev_unlock(hdev); 1786a9de9248SMarcel Holtmann 1787a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 17881da177e4SLinus Torvalds } 17891da177e4SLinus Torvalds 17901da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 17911da177e4SLinus Torvalds { 1792a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 17931da177e4SLinus Torvalds int mask = hdev->link_mode; 17941da177e4SLinus Torvalds 1795a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s type 0x%x", hdev->name, 17961da177e4SLinus Torvalds batostr(&ev->bdaddr), ev->link_type); 17971da177e4SLinus Torvalds 17981da177e4SLinus Torvalds mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); 17991da177e4SLinus Torvalds 1800138d22efSSzymon Janc if ((mask & HCI_LM_ACCEPT) && 1801138d22efSSzymon Janc !hci_blacklist_lookup(hdev, &ev->bdaddr)) { 18021da177e4SLinus Torvalds /* Connection accepted */ 1803c7bdd502SMarcel Holtmann struct inquiry_entry *ie; 18041da177e4SLinus Torvalds struct hci_conn *conn; 18051da177e4SLinus Torvalds 18061da177e4SLinus Torvalds hci_dev_lock(hdev); 1807b6a0dc82SMarcel Holtmann 1808cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 1809cc11b9c1SAndrei Emeltchenko if (ie) 1810c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 1811c7bdd502SMarcel Holtmann 18121da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 18131da177e4SLinus Torvalds if (!conn) { 1814cc11b9c1SAndrei Emeltchenko conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); 1815cc11b9c1SAndrei Emeltchenko if (!conn) { 1816893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 18171da177e4SLinus Torvalds hci_dev_unlock(hdev); 18181da177e4SLinus Torvalds return; 18191da177e4SLinus Torvalds } 18201da177e4SLinus Torvalds } 1821b6a0dc82SMarcel Holtmann 18221da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 18231da177e4SLinus Torvalds conn->state = BT_CONNECT; 1824b6a0dc82SMarcel Holtmann 18251da177e4SLinus Torvalds hci_dev_unlock(hdev); 18261da177e4SLinus Torvalds 1827b6a0dc82SMarcel Holtmann if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) { 1828b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 1829b6a0dc82SMarcel Holtmann 18301da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 18311da177e4SLinus Torvalds 18321da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 18331da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 18341da177e4SLinus Torvalds else 18351da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 18361da177e4SLinus Torvalds 1837b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, 1838b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1839b6a0dc82SMarcel Holtmann } else { 1840b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 1841b6a0dc82SMarcel Holtmann 1842b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 1843a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1844b6a0dc82SMarcel Holtmann 1845b6a0dc82SMarcel Holtmann cp.tx_bandwidth = cpu_to_le32(0x00001f40); 1846b6a0dc82SMarcel Holtmann cp.rx_bandwidth = cpu_to_le32(0x00001f40); 1847b6a0dc82SMarcel Holtmann cp.max_latency = cpu_to_le16(0xffff); 1848b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 1849b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 1850b6a0dc82SMarcel Holtmann 1851b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 1852b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1853b6a0dc82SMarcel Holtmann } 18541da177e4SLinus Torvalds } else { 18551da177e4SLinus Torvalds /* Connection rejected */ 18561da177e4SLinus Torvalds struct hci_cp_reject_conn_req cp; 18571da177e4SLinus Torvalds 18581da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 18599f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_REJ_BAD_ADDR; 1860a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 18611da177e4SLinus Torvalds } 18621da177e4SLinus Torvalds } 18631da177e4SLinus Torvalds 18641da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 18651da177e4SLinus Torvalds { 1866a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 186704837f64SMarcel Holtmann struct hci_conn *conn; 18681da177e4SLinus Torvalds 18691da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 18701da177e4SLinus Torvalds 18711da177e4SLinus Torvalds hci_dev_lock(hdev); 18721da177e4SLinus Torvalds 187304837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1874f7520543SJohan Hedberg if (!conn) 1875f7520543SJohan Hedberg goto unlock; 1876f7520543SJohan Hedberg 187737d9ef76SJohan Hedberg if (ev->status == 0) 18781da177e4SLinus Torvalds conn->state = BT_CLOSED; 18797d0db0a3SMarcel Holtmann 1880b644ba33SJohan Hedberg if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) && 1881b644ba33SJohan Hedberg (conn->type == ACL_LINK || conn->type == LE_LINK)) { 188237d9ef76SJohan Hedberg if (ev->status != 0) 188388c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 188488c3df13SJohan Hedberg conn->dst_type, ev->status); 188537d9ef76SJohan Hedberg else 1886afc747a6SJohan Hedberg mgmt_device_disconnected(hdev, &conn->dst, conn->type, 188748264f06SJohan Hedberg conn->dst_type); 188837d9ef76SJohan Hedberg } 1889f7520543SJohan Hedberg 189037d9ef76SJohan Hedberg if (ev->status == 0) { 18912950f21aSMarcel Holtmann hci_proto_disconn_cfm(conn, ev->reason); 18921da177e4SLinus Torvalds hci_conn_del(conn); 189337d9ef76SJohan Hedberg } 18941da177e4SLinus Torvalds 1895f7520543SJohan Hedberg unlock: 18961da177e4SLinus Torvalds hci_dev_unlock(hdev); 18971da177e4SLinus Torvalds } 18981da177e4SLinus Torvalds 1899a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1900a9de9248SMarcel Holtmann { 1901a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 1902a9de9248SMarcel Holtmann struct hci_conn *conn; 1903a9de9248SMarcel Holtmann 1904a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1905a9de9248SMarcel Holtmann 1906a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1907a9de9248SMarcel Holtmann 1908a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1909d7556e20SWaldemar Rymarkiewicz if (!conn) 1910d7556e20SWaldemar Rymarkiewicz goto unlock; 1911d7556e20SWaldemar Rymarkiewicz 1912765c2a96SJohan Hedberg if (!ev->status) { 1913aa64a8b5SJohan Hedberg if (!hci_conn_ssp_enabled(conn) && 191451a8efd7SJohan Hedberg test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) { 1915d7556e20SWaldemar Rymarkiewicz BT_INFO("re-auth of legacy device is not possible."); 191619f8def0SWaldemar Rymarkiewicz } else { 1917a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1918765c2a96SJohan Hedberg conn->sec_level = conn->pending_sec_level; 191919f8def0SWaldemar Rymarkiewicz } 19202a611692SJohan Hedberg } else { 1921bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 1922bab73cb6SJohan Hedberg ev->status); 19232a611692SJohan Hedberg } 1924a9de9248SMarcel Holtmann 192551a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 192651a8efd7SJohan Hedberg clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags); 1927a9de9248SMarcel Holtmann 1928f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1929aa64a8b5SJohan Hedberg if (!ev->status && hci_conn_ssp_enabled(conn)) { 1930f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1931f8558555SMarcel Holtmann cp.handle = ev->handle; 1932f8558555SMarcel Holtmann cp.encrypt = 0x01; 1933d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1934d7556e20SWaldemar Rymarkiewicz &cp); 1935f8558555SMarcel Holtmann } else { 1936f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1937f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1938f8558555SMarcel Holtmann hci_conn_put(conn); 1939f8558555SMarcel Holtmann } 1940052b30b0SMarcel Holtmann } else { 1941a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 1942a9de9248SMarcel Holtmann 1943052b30b0SMarcel Holtmann hci_conn_hold(conn); 1944052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1945052b30b0SMarcel Holtmann hci_conn_put(conn); 1946052b30b0SMarcel Holtmann } 1947052b30b0SMarcel Holtmann 194851a8efd7SJohan Hedberg if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) { 1949a9de9248SMarcel Holtmann if (!ev->status) { 1950a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1951f8558555SMarcel Holtmann cp.handle = ev->handle; 1952f8558555SMarcel Holtmann cp.encrypt = 0x01; 1953d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1954d7556e20SWaldemar Rymarkiewicz &cp); 1955a9de9248SMarcel Holtmann } else { 195651a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 1957a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 1958a9de9248SMarcel Holtmann } 1959a9de9248SMarcel Holtmann } 1960a9de9248SMarcel Holtmann 1961d7556e20SWaldemar Rymarkiewicz unlock: 1962a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1963a9de9248SMarcel Holtmann } 1964a9de9248SMarcel Holtmann 1965a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 1966a9de9248SMarcel Holtmann { 1967127178d2SJohan Hedberg struct hci_ev_remote_name *ev = (void *) skb->data; 1968127178d2SJohan Hedberg struct hci_conn *conn; 1969127178d2SJohan Hedberg 1970a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1971a9de9248SMarcel Holtmann 1972a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 1973127178d2SJohan Hedberg 1974127178d2SJohan Hedberg hci_dev_lock(hdev); 1975127178d2SJohan Hedberg 1976127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 1977b644ba33SJohan Hedberg 1978b644ba33SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 1979b644ba33SJohan Hedberg goto check_auth; 1980b644ba33SJohan Hedberg 1981b644ba33SJohan Hedberg if (ev->status == 0) 1982b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name, 1983b644ba33SJohan Hedberg strnlen(ev->name, HCI_MAX_NAME_LENGTH)); 1984b644ba33SJohan Hedberg else 1985b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0); 1986b644ba33SJohan Hedberg 1987b644ba33SJohan Hedberg check_auth: 198879c6c70cSJohan Hedberg if (!conn) 198979c6c70cSJohan Hedberg goto unlock; 199079c6c70cSJohan Hedberg 199179c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 199279c6c70cSJohan Hedberg goto unlock; 199379c6c70cSJohan Hedberg 199451a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 1995127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1996127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1997127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1998127178d2SJohan Hedberg } 1999127178d2SJohan Hedberg 200079c6c70cSJohan Hedberg unlock: 2001127178d2SJohan Hedberg hci_dev_unlock(hdev); 2002a9de9248SMarcel Holtmann } 2003a9de9248SMarcel Holtmann 2004a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2005a9de9248SMarcel Holtmann { 2006a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 2007a9de9248SMarcel Holtmann struct hci_conn *conn; 2008a9de9248SMarcel Holtmann 2009a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2010a9de9248SMarcel Holtmann 2011a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2012a9de9248SMarcel Holtmann 2013a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2014a9de9248SMarcel Holtmann if (conn) { 2015a9de9248SMarcel Holtmann if (!ev->status) { 2016ae293196SMarcel Holtmann if (ev->encrypt) { 2017ae293196SMarcel Holtmann /* Encryption implies authentication */ 2018ae293196SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 2019a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 2020da85e5e5SVinicius Costa Gomes conn->sec_level = conn->pending_sec_level; 2021ae293196SMarcel Holtmann } else 2022a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_ENCRYPT; 2023a9de9248SMarcel Holtmann } 2024a9de9248SMarcel Holtmann 202551a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 2026a9de9248SMarcel Holtmann 2027f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 2028f8558555SMarcel Holtmann if (!ev->status) 2029f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 2030f8558555SMarcel Holtmann 2031f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2032f8558555SMarcel Holtmann hci_conn_put(conn); 2033f8558555SMarcel Holtmann } else 2034a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 2035a9de9248SMarcel Holtmann } 2036a9de9248SMarcel Holtmann 2037a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2038a9de9248SMarcel Holtmann } 2039a9de9248SMarcel Holtmann 2040a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2041a9de9248SMarcel Holtmann { 2042a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 2043a9de9248SMarcel Holtmann struct hci_conn *conn; 2044a9de9248SMarcel Holtmann 2045a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2046a9de9248SMarcel Holtmann 2047a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2048a9de9248SMarcel Holtmann 2049a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2050a9de9248SMarcel Holtmann if (conn) { 2051a9de9248SMarcel Holtmann if (!ev->status) 2052a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_SECURE; 2053a9de9248SMarcel Holtmann 205451a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 2055a9de9248SMarcel Holtmann 2056a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 2057a9de9248SMarcel Holtmann } 2058a9de9248SMarcel Holtmann 2059a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2060a9de9248SMarcel Holtmann } 2061a9de9248SMarcel Holtmann 2062a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 2063a9de9248SMarcel Holtmann { 2064a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 2065a9de9248SMarcel Holtmann struct hci_conn *conn; 2066a9de9248SMarcel Holtmann 2067a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2068a9de9248SMarcel Holtmann 2069a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2070a9de9248SMarcel Holtmann 2071a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2072ccd556feSJohan Hedberg if (!conn) 2073ccd556feSJohan Hedberg goto unlock; 2074ccd556feSJohan Hedberg 2075769be974SMarcel Holtmann if (!ev->status) 2076a9de9248SMarcel Holtmann memcpy(conn->features, ev->features, 8); 2077a9de9248SMarcel Holtmann 2078ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2079ccd556feSJohan Hedberg goto unlock; 2080ccd556feSJohan Hedberg 2081ccd556feSJohan Hedberg if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { 2082769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 2083769be974SMarcel Holtmann cp.handle = ev->handle; 2084769be974SMarcel Holtmann cp.page = 0x01; 2085ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 2086769be974SMarcel Holtmann sizeof(cp), &cp); 2087392599b9SJohan Hedberg goto unlock; 2088392599b9SJohan Hedberg } 2089392599b9SJohan Hedberg 2090127178d2SJohan Hedberg if (!ev->status) { 2091127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2092127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2093127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2094127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2095127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2096b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 2097b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 2098b644ba33SJohan Hedberg conn->dst_type, NULL, 0, 2099b644ba33SJohan Hedberg conn->dev_class); 2100392599b9SJohan Hedberg 2101127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2102769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2103769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2104769be974SMarcel Holtmann hci_conn_put(conn); 2105769be974SMarcel Holtmann } 2106769be974SMarcel Holtmann 2107ccd556feSJohan Hedberg unlock: 2108a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2109a9de9248SMarcel Holtmann } 2110a9de9248SMarcel Holtmann 2111a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) 2112a9de9248SMarcel Holtmann { 2113a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2114a9de9248SMarcel Holtmann } 2115a9de9248SMarcel Holtmann 2116a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2117a9de9248SMarcel Holtmann { 2118a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2119a9de9248SMarcel Holtmann } 2120a9de9248SMarcel Holtmann 2121a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2122a9de9248SMarcel Holtmann { 2123a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 2124a9de9248SMarcel Holtmann __u16 opcode; 2125a9de9248SMarcel Holtmann 2126a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2127a9de9248SMarcel Holtmann 2128a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2129a9de9248SMarcel Holtmann 2130a9de9248SMarcel Holtmann switch (opcode) { 2131a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 2132a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 2133a9de9248SMarcel Holtmann break; 2134a9de9248SMarcel Holtmann 2135a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 2136a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 2137a9de9248SMarcel Holtmann break; 2138a9de9248SMarcel Holtmann 2139a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 2140a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 2141a9de9248SMarcel Holtmann break; 2142a9de9248SMarcel Holtmann 2143a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 2144a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 2145a9de9248SMarcel Holtmann break; 2146a9de9248SMarcel Holtmann 2147e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 2148e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 2149e4e8e37cSMarcel Holtmann break; 2150e4e8e37cSMarcel Holtmann 2151a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 2152a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 2153a9de9248SMarcel Holtmann break; 2154a9de9248SMarcel Holtmann 2155e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 2156e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 2157e4e8e37cSMarcel Holtmann break; 2158e4e8e37cSMarcel Holtmann 2159e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 2160e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 2161e4e8e37cSMarcel Holtmann break; 2162e4e8e37cSMarcel Holtmann 2163a9de9248SMarcel Holtmann case HCI_OP_RESET: 2164a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 2165a9de9248SMarcel Holtmann break; 2166a9de9248SMarcel Holtmann 2167a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 2168a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 2169a9de9248SMarcel Holtmann break; 2170a9de9248SMarcel Holtmann 2171a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 2172a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 2173a9de9248SMarcel Holtmann break; 2174a9de9248SMarcel Holtmann 2175a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 2176a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 2177a9de9248SMarcel Holtmann break; 2178a9de9248SMarcel Holtmann 2179a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 2180a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 2181a9de9248SMarcel Holtmann break; 2182a9de9248SMarcel Holtmann 2183a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 2184a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 2185a9de9248SMarcel Holtmann break; 2186a9de9248SMarcel Holtmann 2187a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 2188a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 2189a9de9248SMarcel Holtmann break; 2190a9de9248SMarcel Holtmann 2191a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 2192a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 2193a9de9248SMarcel Holtmann break; 2194a9de9248SMarcel Holtmann 2195a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 2196a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 2197a9de9248SMarcel Holtmann break; 2198a9de9248SMarcel Holtmann 2199a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 2200a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 2201a9de9248SMarcel Holtmann break; 2202a9de9248SMarcel Holtmann 2203a9de9248SMarcel Holtmann case HCI_OP_HOST_BUFFER_SIZE: 2204a9de9248SMarcel Holtmann hci_cc_host_buffer_size(hdev, skb); 2205a9de9248SMarcel Holtmann break; 2206a9de9248SMarcel Holtmann 2207333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 2208333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 2209333140b5SMarcel Holtmann break; 2210333140b5SMarcel Holtmann 2211a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 2212a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 2213a9de9248SMarcel Holtmann break; 2214a9de9248SMarcel Holtmann 2215a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 2216a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 2217a9de9248SMarcel Holtmann break; 2218a9de9248SMarcel Holtmann 2219a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 2220a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 2221a9de9248SMarcel Holtmann break; 2222a9de9248SMarcel Holtmann 2223971e3a4bSAndre Guedes case HCI_OP_READ_LOCAL_EXT_FEATURES: 2224971e3a4bSAndre Guedes hci_cc_read_local_ext_features(hdev, skb); 2225971e3a4bSAndre Guedes break; 2226971e3a4bSAndre Guedes 2227a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 2228a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 2229a9de9248SMarcel Holtmann break; 2230a9de9248SMarcel Holtmann 2231a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 2232a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 2233a9de9248SMarcel Holtmann break; 2234a9de9248SMarcel Holtmann 2235350ee4cfSAndrei Emeltchenko case HCI_OP_READ_DATA_BLOCK_SIZE: 2236350ee4cfSAndrei Emeltchenko hci_cc_read_data_block_size(hdev, skb); 2237350ee4cfSAndrei Emeltchenko break; 2238350ee4cfSAndrei Emeltchenko 223923bb5763SJohan Hedberg case HCI_OP_WRITE_CA_TIMEOUT: 224023bb5763SJohan Hedberg hci_cc_write_ca_timeout(hdev, skb); 224123bb5763SJohan Hedberg break; 224223bb5763SJohan Hedberg 22431e89cffbSAndrei Emeltchenko case HCI_OP_READ_FLOW_CONTROL_MODE: 22441e89cffbSAndrei Emeltchenko hci_cc_read_flow_control_mode(hdev, skb); 22451e89cffbSAndrei Emeltchenko break; 22461e89cffbSAndrei Emeltchenko 2247928abaa7SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_INFO: 2248928abaa7SAndrei Emeltchenko hci_cc_read_local_amp_info(hdev, skb); 2249928abaa7SAndrei Emeltchenko break; 2250928abaa7SAndrei Emeltchenko 2251b0916ea0SJohan Hedberg case HCI_OP_DELETE_STORED_LINK_KEY: 2252b0916ea0SJohan Hedberg hci_cc_delete_stored_link_key(hdev, skb); 2253b0916ea0SJohan Hedberg break; 2254b0916ea0SJohan Hedberg 2255d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_MASK: 2256d5859e22SJohan Hedberg hci_cc_set_event_mask(hdev, skb); 2257d5859e22SJohan Hedberg break; 2258d5859e22SJohan Hedberg 2259d5859e22SJohan Hedberg case HCI_OP_WRITE_INQUIRY_MODE: 2260d5859e22SJohan Hedberg hci_cc_write_inquiry_mode(hdev, skb); 2261d5859e22SJohan Hedberg break; 2262d5859e22SJohan Hedberg 2263d5859e22SJohan Hedberg case HCI_OP_READ_INQ_RSP_TX_POWER: 2264d5859e22SJohan Hedberg hci_cc_read_inq_rsp_tx_power(hdev, skb); 2265d5859e22SJohan Hedberg break; 2266d5859e22SJohan Hedberg 2267d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_FLT: 2268d5859e22SJohan Hedberg hci_cc_set_event_flt(hdev, skb); 2269d5859e22SJohan Hedberg break; 2270d5859e22SJohan Hedberg 2271980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_REPLY: 2272980e1a53SJohan Hedberg hci_cc_pin_code_reply(hdev, skb); 2273980e1a53SJohan Hedberg break; 2274980e1a53SJohan Hedberg 2275980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_NEG_REPLY: 2276980e1a53SJohan Hedberg hci_cc_pin_code_neg_reply(hdev, skb); 2277980e1a53SJohan Hedberg break; 2278980e1a53SJohan Hedberg 2279c35938b2SSzymon Janc case HCI_OP_READ_LOCAL_OOB_DATA: 2280c35938b2SSzymon Janc hci_cc_read_local_oob_data_reply(hdev, skb); 2281c35938b2SSzymon Janc break; 2282c35938b2SSzymon Janc 22836ed58ec5SVille Tervo case HCI_OP_LE_READ_BUFFER_SIZE: 22846ed58ec5SVille Tervo hci_cc_le_read_buffer_size(hdev, skb); 22856ed58ec5SVille Tervo break; 22866ed58ec5SVille Tervo 2287a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_REPLY: 2288a5c29683SJohan Hedberg hci_cc_user_confirm_reply(hdev, skb); 2289a5c29683SJohan Hedberg break; 2290a5c29683SJohan Hedberg 2291a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_NEG_REPLY: 2292a5c29683SJohan Hedberg hci_cc_user_confirm_neg_reply(hdev, skb); 2293a5c29683SJohan Hedberg break; 2294a5c29683SJohan Hedberg 22951143d458SBrian Gix case HCI_OP_USER_PASSKEY_REPLY: 22961143d458SBrian Gix hci_cc_user_passkey_reply(hdev, skb); 22971143d458SBrian Gix break; 22981143d458SBrian Gix 22991143d458SBrian Gix case HCI_OP_USER_PASSKEY_NEG_REPLY: 23001143d458SBrian Gix hci_cc_user_passkey_neg_reply(hdev, skb); 230107f7fa5dSAndre Guedes 230207f7fa5dSAndre Guedes case HCI_OP_LE_SET_SCAN_PARAM: 230307f7fa5dSAndre Guedes hci_cc_le_set_scan_param(hdev, skb); 23041143d458SBrian Gix break; 23051143d458SBrian Gix 2306eb9d91f5SAndre Guedes case HCI_OP_LE_SET_SCAN_ENABLE: 2307eb9d91f5SAndre Guedes hci_cc_le_set_scan_enable(hdev, skb); 2308eb9d91f5SAndre Guedes break; 2309eb9d91f5SAndre Guedes 2310a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_REPLY: 2311a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_reply(hdev, skb); 2312a7a595f6SVinicius Costa Gomes break; 2313a7a595f6SVinicius Costa Gomes 2314a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_NEG_REPLY: 2315a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_neg_reply(hdev, skb); 2316a7a595f6SVinicius Costa Gomes break; 2317a7a595f6SVinicius Costa Gomes 2318f9b49306SAndre Guedes case HCI_OP_WRITE_LE_HOST_SUPPORTED: 2319f9b49306SAndre Guedes hci_cc_write_le_host_supported(hdev, skb); 2320f9b49306SAndre Guedes break; 2321f9b49306SAndre Guedes 2322a9de9248SMarcel Holtmann default: 2323a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 2324a9de9248SMarcel Holtmann break; 2325a9de9248SMarcel Holtmann } 2326a9de9248SMarcel Holtmann 23276bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 23286bd32326SVille Tervo del_timer(&hdev->cmd_timer); 23296bd32326SVille Tervo 2330a9de9248SMarcel Holtmann if (ev->ncmd) { 2331a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2332a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2333c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2334a9de9248SMarcel Holtmann } 2335a9de9248SMarcel Holtmann } 2336a9de9248SMarcel Holtmann 2337a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 2338a9de9248SMarcel Holtmann { 2339a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 2340a9de9248SMarcel Holtmann __u16 opcode; 2341a9de9248SMarcel Holtmann 2342a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2343a9de9248SMarcel Holtmann 2344a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2345a9de9248SMarcel Holtmann 2346a9de9248SMarcel Holtmann switch (opcode) { 2347a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 2348a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 2349a9de9248SMarcel Holtmann break; 2350a9de9248SMarcel Holtmann 2351a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 2352a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 2353a9de9248SMarcel Holtmann break; 2354a9de9248SMarcel Holtmann 2355a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 2356a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 2357a9de9248SMarcel Holtmann break; 2358a9de9248SMarcel Holtmann 2359f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 2360f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 2361f8558555SMarcel Holtmann break; 2362f8558555SMarcel Holtmann 2363f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 2364f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 2365f8558555SMarcel Holtmann break; 2366f8558555SMarcel Holtmann 2367a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 2368a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 2369a9de9248SMarcel Holtmann break; 2370a9de9248SMarcel Holtmann 2371769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 2372769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 2373769be974SMarcel Holtmann break; 2374769be974SMarcel Holtmann 2375769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 2376769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 2377769be974SMarcel Holtmann break; 2378769be974SMarcel Holtmann 2379a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 2380a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 2381a9de9248SMarcel Holtmann break; 2382a9de9248SMarcel Holtmann 2383a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 2384a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 2385a9de9248SMarcel Holtmann break; 2386a9de9248SMarcel Holtmann 2387a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 2388a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 2389a9de9248SMarcel Holtmann break; 2390a9de9248SMarcel Holtmann 23918962ee74SJohan Hedberg case HCI_OP_DISCONNECT: 239288c3df13SJohan Hedberg hci_cs_disconnect(hdev, ev->status); 23938962ee74SJohan Hedberg break; 23948962ee74SJohan Hedberg 2395fcd89c09SVille Tervo case HCI_OP_LE_CREATE_CONN: 2396fcd89c09SVille Tervo hci_cs_le_create_conn(hdev, ev->status); 2397fcd89c09SVille Tervo break; 2398fcd89c09SVille Tervo 2399a7a595f6SVinicius Costa Gomes case HCI_OP_LE_START_ENC: 2400a7a595f6SVinicius Costa Gomes hci_cs_le_start_enc(hdev, ev->status); 2401a7a595f6SVinicius Costa Gomes break; 2402a7a595f6SVinicius Costa Gomes 2403a9de9248SMarcel Holtmann default: 2404a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 2405a9de9248SMarcel Holtmann break; 2406a9de9248SMarcel Holtmann } 2407a9de9248SMarcel Holtmann 24086bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 24096bd32326SVille Tervo del_timer(&hdev->cmd_timer); 24106bd32326SVille Tervo 241110572132SGustavo F. Padovan if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2412a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2413a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2414c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2415a9de9248SMarcel Holtmann } 2416a9de9248SMarcel Holtmann } 2417a9de9248SMarcel Holtmann 2418a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2419a9de9248SMarcel Holtmann { 2420a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 2421a9de9248SMarcel Holtmann struct hci_conn *conn; 2422a9de9248SMarcel Holtmann 2423a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2424a9de9248SMarcel Holtmann 2425a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2426a9de9248SMarcel Holtmann 2427a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2428a9de9248SMarcel Holtmann if (conn) { 2429a9de9248SMarcel Holtmann if (!ev->status) { 2430a9de9248SMarcel Holtmann if (ev->role) 2431a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_MASTER; 2432a9de9248SMarcel Holtmann else 2433a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_MASTER; 2434a9de9248SMarcel Holtmann } 2435a9de9248SMarcel Holtmann 243651a8efd7SJohan Hedberg clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); 2437a9de9248SMarcel Holtmann 2438a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 2439a9de9248SMarcel Holtmann } 2440a9de9248SMarcel Holtmann 2441a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2442a9de9248SMarcel Holtmann } 2443a9de9248SMarcel Holtmann 24441da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 24451da177e4SLinus Torvalds { 2446a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 24471da177e4SLinus Torvalds int i; 24481da177e4SLinus Torvalds 244932ac5b9bSAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) { 245032ac5b9bSAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 245132ac5b9bSAndrei Emeltchenko return; 245232ac5b9bSAndrei Emeltchenko } 245332ac5b9bSAndrei Emeltchenko 2454c5993de8SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 2455c5993de8SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_pkts_info)) { 24561da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 24571da177e4SLinus Torvalds return; 24581da177e4SLinus Torvalds } 24591da177e4SLinus Torvalds 2460c5993de8SAndrei Emeltchenko BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 2461c5993de8SAndrei Emeltchenko 2462613a1c0cSAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 2463613a1c0cSAndrei Emeltchenko struct hci_comp_pkts_info *info = &ev->handles[i]; 24641da177e4SLinus Torvalds struct hci_conn *conn; 24651da177e4SLinus Torvalds __u16 handle, count; 24661da177e4SLinus Torvalds 2467613a1c0cSAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 2468613a1c0cSAndrei Emeltchenko count = __le16_to_cpu(info->count); 24691da177e4SLinus Torvalds 24701da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 2471f4280918SAndrei Emeltchenko if (!conn) 2472f4280918SAndrei Emeltchenko continue; 2473f4280918SAndrei Emeltchenko 24741da177e4SLinus Torvalds conn->sent -= count; 24751da177e4SLinus Torvalds 2476f4280918SAndrei Emeltchenko switch (conn->type) { 2477f4280918SAndrei Emeltchenko case ACL_LINK: 247870f23020SAndrei Emeltchenko hdev->acl_cnt += count; 247970f23020SAndrei Emeltchenko if (hdev->acl_cnt > hdev->acl_pkts) 24801da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 2481f4280918SAndrei Emeltchenko break; 2482f4280918SAndrei Emeltchenko 2483f4280918SAndrei Emeltchenko case LE_LINK: 24846ed58ec5SVille Tervo if (hdev->le_pkts) { 24856ed58ec5SVille Tervo hdev->le_cnt += count; 24866ed58ec5SVille Tervo if (hdev->le_cnt > hdev->le_pkts) 24876ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 24886ed58ec5SVille Tervo } else { 24896ed58ec5SVille Tervo hdev->acl_cnt += count; 24906ed58ec5SVille Tervo if (hdev->acl_cnt > hdev->acl_pkts) 24916ed58ec5SVille Tervo hdev->acl_cnt = hdev->acl_pkts; 24926ed58ec5SVille Tervo } 2493f4280918SAndrei Emeltchenko break; 2494f4280918SAndrei Emeltchenko 2495f4280918SAndrei Emeltchenko case SCO_LINK: 249670f23020SAndrei Emeltchenko hdev->sco_cnt += count; 249770f23020SAndrei Emeltchenko if (hdev->sco_cnt > hdev->sco_pkts) 24985b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 2499f4280918SAndrei Emeltchenko break; 2500f4280918SAndrei Emeltchenko 2501f4280918SAndrei Emeltchenko default: 2502f4280918SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 2503f4280918SAndrei Emeltchenko break; 25041da177e4SLinus Torvalds } 25051da177e4SLinus Torvalds } 2506a9de9248SMarcel Holtmann 25073eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 25081da177e4SLinus Torvalds } 25091da177e4SLinus Torvalds 251025e89e99SAndrei Emeltchenko static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev, 251125e89e99SAndrei Emeltchenko struct sk_buff *skb) 251225e89e99SAndrei Emeltchenko { 251325e89e99SAndrei Emeltchenko struct hci_ev_num_comp_blocks *ev = (void *) skb->data; 251425e89e99SAndrei Emeltchenko int i; 251525e89e99SAndrei Emeltchenko 251625e89e99SAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) { 251725e89e99SAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 251825e89e99SAndrei Emeltchenko return; 251925e89e99SAndrei Emeltchenko } 252025e89e99SAndrei Emeltchenko 252125e89e99SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 252225e89e99SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_blocks_info)) { 252325e89e99SAndrei Emeltchenko BT_DBG("%s bad parameters", hdev->name); 252425e89e99SAndrei Emeltchenko return; 252525e89e99SAndrei Emeltchenko } 252625e89e99SAndrei Emeltchenko 252725e89e99SAndrei Emeltchenko BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks, 252825e89e99SAndrei Emeltchenko ev->num_hndl); 252925e89e99SAndrei Emeltchenko 253025e89e99SAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 253125e89e99SAndrei Emeltchenko struct hci_comp_blocks_info *info = &ev->handles[i]; 253225e89e99SAndrei Emeltchenko struct hci_conn *conn; 253325e89e99SAndrei Emeltchenko __u16 handle, block_count; 253425e89e99SAndrei Emeltchenko 253525e89e99SAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 253625e89e99SAndrei Emeltchenko block_count = __le16_to_cpu(info->blocks); 253725e89e99SAndrei Emeltchenko 253825e89e99SAndrei Emeltchenko conn = hci_conn_hash_lookup_handle(hdev, handle); 253925e89e99SAndrei Emeltchenko if (!conn) 254025e89e99SAndrei Emeltchenko continue; 254125e89e99SAndrei Emeltchenko 254225e89e99SAndrei Emeltchenko conn->sent -= block_count; 254325e89e99SAndrei Emeltchenko 254425e89e99SAndrei Emeltchenko switch (conn->type) { 254525e89e99SAndrei Emeltchenko case ACL_LINK: 254625e89e99SAndrei Emeltchenko hdev->block_cnt += block_count; 254725e89e99SAndrei Emeltchenko if (hdev->block_cnt > hdev->num_blocks) 254825e89e99SAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 254925e89e99SAndrei Emeltchenko break; 255025e89e99SAndrei Emeltchenko 255125e89e99SAndrei Emeltchenko default: 255225e89e99SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 255325e89e99SAndrei Emeltchenko break; 255425e89e99SAndrei Emeltchenko } 255525e89e99SAndrei Emeltchenko } 255625e89e99SAndrei Emeltchenko 255725e89e99SAndrei Emeltchenko queue_work(hdev->workqueue, &hdev->tx_work); 255825e89e99SAndrei Emeltchenko } 255925e89e99SAndrei Emeltchenko 256004837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 25611da177e4SLinus Torvalds { 2562a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 256304837f64SMarcel Holtmann struct hci_conn *conn; 25641da177e4SLinus Torvalds 25651da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 25661da177e4SLinus Torvalds 25671da177e4SLinus Torvalds hci_dev_lock(hdev); 25681da177e4SLinus Torvalds 256904837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 257004837f64SMarcel Holtmann if (conn) { 257104837f64SMarcel Holtmann conn->mode = ev->mode; 257204837f64SMarcel Holtmann conn->interval = __le16_to_cpu(ev->interval); 257304837f64SMarcel Holtmann 257451a8efd7SJohan Hedberg if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) { 257504837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 257658a681efSJohan Hedberg set_bit(HCI_CONN_POWER_SAVE, &conn->flags); 257704837f64SMarcel Holtmann else 257858a681efSJohan Hedberg clear_bit(HCI_CONN_POWER_SAVE, &conn->flags); 257904837f64SMarcel Holtmann } 2580e73439d8SMarcel Holtmann 258151a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 2582e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 258304837f64SMarcel Holtmann } 258404837f64SMarcel Holtmann 258504837f64SMarcel Holtmann hci_dev_unlock(hdev); 258604837f64SMarcel Holtmann } 258704837f64SMarcel Holtmann 25881da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 25891da177e4SLinus Torvalds { 2590052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 2591052b30b0SMarcel Holtmann struct hci_conn *conn; 2592052b30b0SMarcel Holtmann 2593a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2594052b30b0SMarcel Holtmann 2595052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2596052b30b0SMarcel Holtmann 2597052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2598b6f98044SWaldemar Rymarkiewicz if (!conn) 2599b6f98044SWaldemar Rymarkiewicz goto unlock; 2600b6f98044SWaldemar Rymarkiewicz 2601b6f98044SWaldemar Rymarkiewicz if (conn->state == BT_CONNECTED) { 2602052b30b0SMarcel Holtmann hci_conn_hold(conn); 2603052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 2604052b30b0SMarcel Holtmann hci_conn_put(conn); 2605052b30b0SMarcel Holtmann } 2606052b30b0SMarcel Holtmann 2607a8b2d5c2SJohan Hedberg if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags)) 260803b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 260903b555e1SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 2610a8b2d5c2SJohan Hedberg else if (test_bit(HCI_MGMT, &hdev->dev_flags)) { 2611a770bb5aSWaldemar Rymarkiewicz u8 secure; 2612a770bb5aSWaldemar Rymarkiewicz 2613a770bb5aSWaldemar Rymarkiewicz if (conn->pending_sec_level == BT_SECURITY_HIGH) 2614a770bb5aSWaldemar Rymarkiewicz secure = 1; 2615a770bb5aSWaldemar Rymarkiewicz else 2616a770bb5aSWaldemar Rymarkiewicz secure = 0; 2617a770bb5aSWaldemar Rymarkiewicz 2618744cf19eSJohan Hedberg mgmt_pin_code_request(hdev, &ev->bdaddr, secure); 2619a770bb5aSWaldemar Rymarkiewicz } 2620980e1a53SJohan Hedberg 2621b6f98044SWaldemar Rymarkiewicz unlock: 2622052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 26231da177e4SLinus Torvalds } 26241da177e4SLinus Torvalds 26251da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 26261da177e4SLinus Torvalds { 262755ed8ca1SJohan Hedberg struct hci_ev_link_key_req *ev = (void *) skb->data; 262855ed8ca1SJohan Hedberg struct hci_cp_link_key_reply cp; 262955ed8ca1SJohan Hedberg struct hci_conn *conn; 263055ed8ca1SJohan Hedberg struct link_key *key; 263155ed8ca1SJohan Hedberg 2632a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 263355ed8ca1SJohan Hedberg 2634a8b2d5c2SJohan Hedberg if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) 263555ed8ca1SJohan Hedberg return; 263655ed8ca1SJohan Hedberg 263755ed8ca1SJohan Hedberg hci_dev_lock(hdev); 263855ed8ca1SJohan Hedberg 263955ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, &ev->bdaddr); 264055ed8ca1SJohan Hedberg if (!key) { 264155ed8ca1SJohan Hedberg BT_DBG("%s link key not found for %s", hdev->name, 264255ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 264355ed8ca1SJohan Hedberg goto not_found; 264455ed8ca1SJohan Hedberg } 264555ed8ca1SJohan Hedberg 264655ed8ca1SJohan Hedberg BT_DBG("%s found key type %u for %s", hdev->name, key->type, 264755ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 264855ed8ca1SJohan Hedberg 2649a8b2d5c2SJohan Hedberg if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) && 2650b6020ba0SWaldemar Rymarkiewicz key->type == HCI_LK_DEBUG_COMBINATION) { 265155ed8ca1SJohan Hedberg BT_DBG("%s ignoring debug key", hdev->name); 265255ed8ca1SJohan Hedberg goto not_found; 265355ed8ca1SJohan Hedberg } 265455ed8ca1SJohan Hedberg 265555ed8ca1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 265660b83f57SWaldemar Rymarkiewicz if (conn) { 265760b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_UNAUTH_COMBINATION && 265860b83f57SWaldemar Rymarkiewicz conn->auth_type != 0xff && 265960b83f57SWaldemar Rymarkiewicz (conn->auth_type & 0x01)) { 266055ed8ca1SJohan Hedberg BT_DBG("%s ignoring unauthenticated key", hdev->name); 266155ed8ca1SJohan Hedberg goto not_found; 266255ed8ca1SJohan Hedberg } 266355ed8ca1SJohan Hedberg 266460b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && 266560b83f57SWaldemar Rymarkiewicz conn->pending_sec_level == BT_SECURITY_HIGH) { 266660b83f57SWaldemar Rymarkiewicz BT_DBG("%s ignoring key unauthenticated for high \ 266760b83f57SWaldemar Rymarkiewicz security", hdev->name); 266860b83f57SWaldemar Rymarkiewicz goto not_found; 266960b83f57SWaldemar Rymarkiewicz } 267060b83f57SWaldemar Rymarkiewicz 267160b83f57SWaldemar Rymarkiewicz conn->key_type = key->type; 267260b83f57SWaldemar Rymarkiewicz conn->pin_length = key->pin_len; 267360b83f57SWaldemar Rymarkiewicz } 267460b83f57SWaldemar Rymarkiewicz 267555ed8ca1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 267655ed8ca1SJohan Hedberg memcpy(cp.link_key, key->val, 16); 267755ed8ca1SJohan Hedberg 267855ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 267955ed8ca1SJohan Hedberg 268055ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 268155ed8ca1SJohan Hedberg 268255ed8ca1SJohan Hedberg return; 268355ed8ca1SJohan Hedberg 268455ed8ca1SJohan Hedberg not_found: 268555ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 268655ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 26871da177e4SLinus Torvalds } 26881da177e4SLinus Torvalds 26891da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 26901da177e4SLinus Torvalds { 2691052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 2692052b30b0SMarcel Holtmann struct hci_conn *conn; 269355ed8ca1SJohan Hedberg u8 pin_len = 0; 2694052b30b0SMarcel Holtmann 2695a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2696052b30b0SMarcel Holtmann 2697052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2698052b30b0SMarcel Holtmann 2699052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2700052b30b0SMarcel Holtmann if (conn) { 2701052b30b0SMarcel Holtmann hci_conn_hold(conn); 2702052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2703980e1a53SJohan Hedberg pin_len = conn->pin_length; 270413d39315SWaldemar Rymarkiewicz 270513d39315SWaldemar Rymarkiewicz if (ev->key_type != HCI_LK_CHANGED_COMBINATION) 270613d39315SWaldemar Rymarkiewicz conn->key_type = ev->key_type; 270713d39315SWaldemar Rymarkiewicz 2708052b30b0SMarcel Holtmann hci_conn_put(conn); 2709052b30b0SMarcel Holtmann } 2710052b30b0SMarcel Holtmann 2711a8b2d5c2SJohan Hedberg if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) 2712d25e28abSJohan Hedberg hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, 271355ed8ca1SJohan Hedberg ev->key_type, pin_len); 271455ed8ca1SJohan Hedberg 2715052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 27161da177e4SLinus Torvalds } 27171da177e4SLinus Torvalds 271804837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 271904837f64SMarcel Holtmann { 2720a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 272104837f64SMarcel Holtmann struct hci_conn *conn; 272204837f64SMarcel Holtmann 272304837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 272404837f64SMarcel Holtmann 272504837f64SMarcel Holtmann hci_dev_lock(hdev); 272604837f64SMarcel Holtmann 272704837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 27281da177e4SLinus Torvalds if (conn && !ev->status) { 27291da177e4SLinus Torvalds struct inquiry_entry *ie; 27301da177e4SLinus Torvalds 2731cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2732cc11b9c1SAndrei Emeltchenko if (ie) { 27331da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 27341da177e4SLinus Torvalds ie->timestamp = jiffies; 27351da177e4SLinus Torvalds } 27361da177e4SLinus Torvalds } 27371da177e4SLinus Torvalds 27381da177e4SLinus Torvalds hci_dev_unlock(hdev); 27391da177e4SLinus Torvalds } 27401da177e4SLinus Torvalds 2741a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2742a8746417SMarcel Holtmann { 2743a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 2744a8746417SMarcel Holtmann struct hci_conn *conn; 2745a8746417SMarcel Holtmann 2746a8746417SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2747a8746417SMarcel Holtmann 2748a8746417SMarcel Holtmann hci_dev_lock(hdev); 2749a8746417SMarcel Holtmann 2750a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2751a8746417SMarcel Holtmann if (conn && !ev->status) 2752a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 2753a8746417SMarcel Holtmann 2754a8746417SMarcel Holtmann hci_dev_unlock(hdev); 2755a8746417SMarcel Holtmann } 2756a8746417SMarcel Holtmann 275785a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 275885a1e930SMarcel Holtmann { 2759a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 276085a1e930SMarcel Holtmann struct inquiry_entry *ie; 276185a1e930SMarcel Holtmann 276285a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 276385a1e930SMarcel Holtmann 276485a1e930SMarcel Holtmann hci_dev_lock(hdev); 276585a1e930SMarcel Holtmann 2766cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2767cc11b9c1SAndrei Emeltchenko if (ie) { 276885a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 276985a1e930SMarcel Holtmann ie->timestamp = jiffies; 277085a1e930SMarcel Holtmann } 277185a1e930SMarcel Holtmann 277285a1e930SMarcel Holtmann hci_dev_unlock(hdev); 277385a1e930SMarcel Holtmann } 277485a1e930SMarcel Holtmann 2775a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb) 2776a9de9248SMarcel Holtmann { 2777a9de9248SMarcel Holtmann struct inquiry_data data; 2778a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 27793175405bSJohan Hedberg bool name_known; 2780a9de9248SMarcel Holtmann 2781a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2782a9de9248SMarcel Holtmann 2783a9de9248SMarcel Holtmann if (!num_rsp) 2784a9de9248SMarcel Holtmann return; 2785a9de9248SMarcel Holtmann 2786a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2787a9de9248SMarcel Holtmann 2788a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 2789138d22efSSzymon Janc struct inquiry_info_with_rssi_and_pscan_mode *info; 2790138d22efSSzymon Janc info = (void *) (skb->data + 1); 2791a9de9248SMarcel Holtmann 2792e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2793a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2794a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2795a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2796a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 2797a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2798a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2799a9de9248SMarcel Holtmann data.rssi = info->rssi; 280041a96212SMarcel Holtmann data.ssp_mode = 0x00; 28013175405bSJohan Hedberg 28023175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 28033175405bSJohan Hedberg false); 280448264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2805e17acd40SJohan Hedberg info->dev_class, info->rssi, 28067d262f86SAndre Guedes !name_known, NULL, 0); 2807a9de9248SMarcel Holtmann } 2808a9de9248SMarcel Holtmann } else { 2809a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 2810a9de9248SMarcel Holtmann 2811e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2812a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2813a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2814a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2815a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2816a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2817a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2818a9de9248SMarcel Holtmann data.rssi = info->rssi; 281941a96212SMarcel Holtmann data.ssp_mode = 0x00; 28203175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 28213175405bSJohan Hedberg false); 282248264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2823e17acd40SJohan Hedberg info->dev_class, info->rssi, 28247d262f86SAndre Guedes !name_known, NULL, 0); 2825a9de9248SMarcel Holtmann } 2826a9de9248SMarcel Holtmann } 2827a9de9248SMarcel Holtmann 2828a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2829a9de9248SMarcel Holtmann } 2830a9de9248SMarcel Holtmann 2831a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 2832a9de9248SMarcel Holtmann { 283341a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 283441a96212SMarcel Holtmann struct hci_conn *conn; 283541a96212SMarcel Holtmann 2836a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 283741a96212SMarcel Holtmann 283841a96212SMarcel Holtmann hci_dev_lock(hdev); 283941a96212SMarcel Holtmann 284041a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2841ccd556feSJohan Hedberg if (!conn) 2842ccd556feSJohan Hedberg goto unlock; 2843ccd556feSJohan Hedberg 2844769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 284541a96212SMarcel Holtmann struct inquiry_entry *ie; 284641a96212SMarcel Holtmann 2847cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2848cc11b9c1SAndrei Emeltchenko if (ie) 284941a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 285041a96212SMarcel Holtmann 285158a681efSJohan Hedberg if (ev->features[0] & 0x01) 285258a681efSJohan Hedberg set_bit(HCI_CONN_SSP_ENABLED, &conn->flags); 285341a96212SMarcel Holtmann } 285441a96212SMarcel Holtmann 2855ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2856ccd556feSJohan Hedberg goto unlock; 2857ccd556feSJohan Hedberg 2858127178d2SJohan Hedberg if (!ev->status) { 2859127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2860127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2861127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2862127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2863127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2864b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 2865b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 2866b644ba33SJohan Hedberg conn->dst_type, NULL, 0, 2867b644ba33SJohan Hedberg conn->dev_class); 2868392599b9SJohan Hedberg 2869127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2870769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2871769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2872769be974SMarcel Holtmann hci_conn_put(conn); 2873769be974SMarcel Holtmann } 2874769be974SMarcel Holtmann 2875ccd556feSJohan Hedberg unlock: 287641a96212SMarcel Holtmann hci_dev_unlock(hdev); 2877a9de9248SMarcel Holtmann } 2878a9de9248SMarcel Holtmann 2879a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2880a9de9248SMarcel Holtmann { 2881b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 2882b6a0dc82SMarcel Holtmann struct hci_conn *conn; 2883b6a0dc82SMarcel Holtmann 2884b6a0dc82SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2885b6a0dc82SMarcel Holtmann 2886b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 2887b6a0dc82SMarcel Holtmann 2888b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 28899dc0a3afSMarcel Holtmann if (!conn) { 28909dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 28919dc0a3afSMarcel Holtmann goto unlock; 28929dc0a3afSMarcel Holtmann 28939dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 2894b6a0dc82SMarcel Holtmann if (!conn) 2895b6a0dc82SMarcel Holtmann goto unlock; 2896b6a0dc82SMarcel Holtmann 28979dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 28989dc0a3afSMarcel Holtmann } 28999dc0a3afSMarcel Holtmann 2900732547f9SMarcel Holtmann switch (ev->status) { 2901732547f9SMarcel Holtmann case 0x00: 2902732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 2903732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 2904732547f9SMarcel Holtmann 29059eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 2906732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 2907732547f9SMarcel Holtmann break; 2908732547f9SMarcel Holtmann 2909705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 2910732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 29111038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 2912732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 2913732547f9SMarcel Holtmann if (conn->out && conn->attempt < 2) { 2914efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 2915efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 2916efc7688bSMarcel Holtmann hci_setup_sync(conn, conn->link->handle); 2917efc7688bSMarcel Holtmann goto unlock; 2918efc7688bSMarcel Holtmann } 2919732547f9SMarcel Holtmann /* fall through */ 2920efc7688bSMarcel Holtmann 2921732547f9SMarcel Holtmann default: 2922b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 2923732547f9SMarcel Holtmann break; 2924732547f9SMarcel Holtmann } 2925b6a0dc82SMarcel Holtmann 2926b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2927b6a0dc82SMarcel Holtmann if (ev->status) 2928b6a0dc82SMarcel Holtmann hci_conn_del(conn); 2929b6a0dc82SMarcel Holtmann 2930b6a0dc82SMarcel Holtmann unlock: 2931b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 2932a9de9248SMarcel Holtmann } 2933a9de9248SMarcel Holtmann 2934a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) 2935a9de9248SMarcel Holtmann { 2936a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2937a9de9248SMarcel Holtmann } 2938a9de9248SMarcel Holtmann 293904837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) 294004837f64SMarcel Holtmann { 2941a9de9248SMarcel Holtmann struct hci_ev_sniff_subrate *ev = (void *) skb->data; 294204837f64SMarcel Holtmann 294304837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 294404837f64SMarcel Holtmann } 294504837f64SMarcel Holtmann 2946a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 2947a9de9248SMarcel Holtmann { 2948a9de9248SMarcel Holtmann struct inquiry_data data; 2949a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 2950a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2951a9de9248SMarcel Holtmann 2952a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2953a9de9248SMarcel Holtmann 2954a9de9248SMarcel Holtmann if (!num_rsp) 2955a9de9248SMarcel Holtmann return; 2956a9de9248SMarcel Holtmann 2957a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2958a9de9248SMarcel Holtmann 2959e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2960561aafbcSJohan Hedberg bool name_known; 2961561aafbcSJohan Hedberg 2962a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2963a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2964a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2965a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2966a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2967a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2968a9de9248SMarcel Holtmann data.rssi = info->rssi; 296941a96212SMarcel Holtmann data.ssp_mode = 0x01; 2970561aafbcSJohan Hedberg 2971a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 29724ddb1930SJohan Hedberg name_known = eir_has_data_type(info->data, 29734ddb1930SJohan Hedberg sizeof(info->data), 29744ddb1930SJohan Hedberg EIR_NAME_COMPLETE); 2975561aafbcSJohan Hedberg else 2976561aafbcSJohan Hedberg name_known = true; 2977561aafbcSJohan Hedberg 29783175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, name_known); 297948264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2980561aafbcSJohan Hedberg info->dev_class, info->rssi, 29817d262f86SAndre Guedes !name_known, info->data, 29827d262f86SAndre Guedes sizeof(info->data)); 2983a9de9248SMarcel Holtmann } 2984a9de9248SMarcel Holtmann 2985a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2986a9de9248SMarcel Holtmann } 2987a9de9248SMarcel Holtmann 298817fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn) 298917fa4b9dSJohan Hedberg { 299017fa4b9dSJohan Hedberg /* If remote requests dedicated bonding follow that lead */ 299117fa4b9dSJohan Hedberg if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) { 299217fa4b9dSJohan Hedberg /* If both remote and local IO capabilities allow MITM 299317fa4b9dSJohan Hedberg * protection then require it, otherwise don't */ 299417fa4b9dSJohan Hedberg if (conn->remote_cap == 0x03 || conn->io_capability == 0x03) 299517fa4b9dSJohan Hedberg return 0x02; 299617fa4b9dSJohan Hedberg else 299717fa4b9dSJohan Hedberg return 0x03; 299817fa4b9dSJohan Hedberg } 299917fa4b9dSJohan Hedberg 300017fa4b9dSJohan Hedberg /* If remote requests no-bonding follow that lead */ 300117fa4b9dSJohan Hedberg if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01) 300258797bf7SWaldemar Rymarkiewicz return conn->remote_auth | (conn->auth_type & 0x01); 300317fa4b9dSJohan Hedberg 300417fa4b9dSJohan Hedberg return conn->auth_type; 300517fa4b9dSJohan Hedberg } 300617fa4b9dSJohan Hedberg 30070493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 30080493684eSMarcel Holtmann { 30090493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 30100493684eSMarcel Holtmann struct hci_conn *conn; 30110493684eSMarcel Holtmann 30120493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 30130493684eSMarcel Holtmann 30140493684eSMarcel Holtmann hci_dev_lock(hdev); 30150493684eSMarcel Holtmann 30160493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 301703b555e1SJohan Hedberg if (!conn) 301803b555e1SJohan Hedberg goto unlock; 301903b555e1SJohan Hedberg 30200493684eSMarcel Holtmann hci_conn_hold(conn); 30210493684eSMarcel Holtmann 3022a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 302303b555e1SJohan Hedberg goto unlock; 302403b555e1SJohan Hedberg 3025a8b2d5c2SJohan Hedberg if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) || 302603b555e1SJohan Hedberg (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 302717fa4b9dSJohan Hedberg struct hci_cp_io_capability_reply cp; 302817fa4b9dSJohan Hedberg 302917fa4b9dSJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 30307a7f1e7cSHemant Gupta /* Change the IO capability from KeyboardDisplay 30317a7f1e7cSHemant Gupta * to DisplayYesNo as it is not supported by BT spec. */ 30327a7f1e7cSHemant Gupta cp.capability = (conn->io_capability == 0x04) ? 30337a7f1e7cSHemant Gupta 0x01 : conn->io_capability; 30347cbc9bd9SJohan Hedberg conn->auth_type = hci_get_auth_req(conn); 30357cbc9bd9SJohan Hedberg cp.authentication = conn->auth_type; 303617fa4b9dSJohan Hedberg 303758a681efSJohan Hedberg if ((conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)) && 3038ce85ee13SSzymon Janc hci_find_remote_oob_data(hdev, &conn->dst)) 3039ce85ee13SSzymon Janc cp.oob_data = 0x01; 3040ce85ee13SSzymon Janc else 3041ce85ee13SSzymon Janc cp.oob_data = 0x00; 3042ce85ee13SSzymon Janc 304317fa4b9dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, 304417fa4b9dSJohan Hedberg sizeof(cp), &cp); 304503b555e1SJohan Hedberg } else { 304603b555e1SJohan Hedberg struct hci_cp_io_capability_neg_reply cp; 304703b555e1SJohan Hedberg 304803b555e1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 30499f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED; 305003b555e1SJohan Hedberg 305103b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 305203b555e1SJohan Hedberg sizeof(cp), &cp); 305303b555e1SJohan Hedberg } 305403b555e1SJohan Hedberg 305503b555e1SJohan Hedberg unlock: 305603b555e1SJohan Hedberg hci_dev_unlock(hdev); 305703b555e1SJohan Hedberg } 305803b555e1SJohan Hedberg 305903b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 306003b555e1SJohan Hedberg { 306103b555e1SJohan Hedberg struct hci_ev_io_capa_reply *ev = (void *) skb->data; 306203b555e1SJohan Hedberg struct hci_conn *conn; 306303b555e1SJohan Hedberg 306403b555e1SJohan Hedberg BT_DBG("%s", hdev->name); 306503b555e1SJohan Hedberg 306603b555e1SJohan Hedberg hci_dev_lock(hdev); 306703b555e1SJohan Hedberg 306803b555e1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 306903b555e1SJohan Hedberg if (!conn) 307003b555e1SJohan Hedberg goto unlock; 307103b555e1SJohan Hedberg 307203b555e1SJohan Hedberg conn->remote_cap = ev->capability; 307303b555e1SJohan Hedberg conn->remote_auth = ev->authentication; 307458a681efSJohan Hedberg if (ev->oob_data) 307558a681efSJohan Hedberg set_bit(HCI_CONN_REMOTE_OOB, &conn->flags); 307603b555e1SJohan Hedberg 307703b555e1SJohan Hedberg unlock: 30780493684eSMarcel Holtmann hci_dev_unlock(hdev); 30790493684eSMarcel Holtmann } 30800493684eSMarcel Holtmann 3081a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev, 3082a5c29683SJohan Hedberg struct sk_buff *skb) 3083a5c29683SJohan Hedberg { 3084a5c29683SJohan Hedberg struct hci_ev_user_confirm_req *ev = (void *) skb->data; 308555bc1a37SJohan Hedberg int loc_mitm, rem_mitm, confirm_hint = 0; 30867a828908SJohan Hedberg struct hci_conn *conn; 3087a5c29683SJohan Hedberg 3088a5c29683SJohan Hedberg BT_DBG("%s", hdev->name); 3089a5c29683SJohan Hedberg 3090a5c29683SJohan Hedberg hci_dev_lock(hdev); 3091a5c29683SJohan Hedberg 3092a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 30937a828908SJohan Hedberg goto unlock; 30947a828908SJohan Hedberg 30957a828908SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 30967a828908SJohan Hedberg if (!conn) 30977a828908SJohan Hedberg goto unlock; 30987a828908SJohan Hedberg 30997a828908SJohan Hedberg loc_mitm = (conn->auth_type & 0x01); 31007a828908SJohan Hedberg rem_mitm = (conn->remote_auth & 0x01); 31017a828908SJohan Hedberg 31027a828908SJohan Hedberg /* If we require MITM but the remote device can't provide that 31037a828908SJohan Hedberg * (it has NoInputNoOutput) then reject the confirmation 31047a828908SJohan Hedberg * request. The only exception is when we're dedicated bonding 31057a828908SJohan Hedberg * initiators (connect_cfm_cb set) since then we always have the MITM 31067a828908SJohan Hedberg * bit set. */ 31077a828908SJohan Hedberg if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) { 31087a828908SJohan Hedberg BT_DBG("Rejecting request: remote device can't provide MITM"); 31097a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, 31107a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 31117a828908SJohan Hedberg goto unlock; 31127a828908SJohan Hedberg } 31137a828908SJohan Hedberg 31147a828908SJohan Hedberg /* If no side requires MITM protection; auto-accept */ 31157a828908SJohan Hedberg if ((!loc_mitm || conn->remote_cap == 0x03) && 31167a828908SJohan Hedberg (!rem_mitm || conn->io_capability == 0x03)) { 311755bc1a37SJohan Hedberg 311855bc1a37SJohan Hedberg /* If we're not the initiators request authorization to 311955bc1a37SJohan Hedberg * proceed from user space (mgmt_user_confirm with 312055bc1a37SJohan Hedberg * confirm_hint set to 1). */ 312151a8efd7SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 312255bc1a37SJohan Hedberg BT_DBG("Confirming auto-accept as acceptor"); 312355bc1a37SJohan Hedberg confirm_hint = 1; 312455bc1a37SJohan Hedberg goto confirm; 312555bc1a37SJohan Hedberg } 312655bc1a37SJohan Hedberg 31279f61656aSJohan Hedberg BT_DBG("Auto-accept of user confirmation with %ums delay", 31289f61656aSJohan Hedberg hdev->auto_accept_delay); 31299f61656aSJohan Hedberg 31309f61656aSJohan Hedberg if (hdev->auto_accept_delay > 0) { 31319f61656aSJohan Hedberg int delay = msecs_to_jiffies(hdev->auto_accept_delay); 31329f61656aSJohan Hedberg mod_timer(&conn->auto_accept_timer, jiffies + delay); 31339f61656aSJohan Hedberg goto unlock; 31349f61656aSJohan Hedberg } 31359f61656aSJohan Hedberg 31367a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, 31377a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 31387a828908SJohan Hedberg goto unlock; 31397a828908SJohan Hedberg } 31407a828908SJohan Hedberg 314155bc1a37SJohan Hedberg confirm: 3142272d90dfSJohan Hedberg mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey, 314355bc1a37SJohan Hedberg confirm_hint); 3144a5c29683SJohan Hedberg 31457a828908SJohan Hedberg unlock: 3146a5c29683SJohan Hedberg hci_dev_unlock(hdev); 3147a5c29683SJohan Hedberg } 3148a5c29683SJohan Hedberg 31491143d458SBrian Gix static inline void hci_user_passkey_request_evt(struct hci_dev *hdev, 31501143d458SBrian Gix struct sk_buff *skb) 31511143d458SBrian Gix { 31521143d458SBrian Gix struct hci_ev_user_passkey_req *ev = (void *) skb->data; 31531143d458SBrian Gix 31541143d458SBrian Gix BT_DBG("%s", hdev->name); 31551143d458SBrian Gix 31561143d458SBrian Gix hci_dev_lock(hdev); 31571143d458SBrian Gix 3158a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 3159272d90dfSJohan Hedberg mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); 31601143d458SBrian Gix 31611143d458SBrian Gix hci_dev_unlock(hdev); 31621143d458SBrian Gix } 31631143d458SBrian Gix 31640493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 31650493684eSMarcel Holtmann { 31660493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 31670493684eSMarcel Holtmann struct hci_conn *conn; 31680493684eSMarcel Holtmann 31690493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 31700493684eSMarcel Holtmann 31710493684eSMarcel Holtmann hci_dev_lock(hdev); 31720493684eSMarcel Holtmann 31730493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 31742a611692SJohan Hedberg if (!conn) 31752a611692SJohan Hedberg goto unlock; 31762a611692SJohan Hedberg 31772a611692SJohan Hedberg /* To avoid duplicate auth_failed events to user space we check 31782a611692SJohan Hedberg * the HCI_CONN_AUTH_PEND flag which will be set if we 31792a611692SJohan Hedberg * initiated the authentication. A traditional auth_complete 31802a611692SJohan Hedberg * event gets always produced as initiator and is also mapped to 31812a611692SJohan Hedberg * the mgmt_auth_failed event */ 318251a8efd7SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status != 0) 3183bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 3184bab73cb6SJohan Hedberg ev->status); 31852a611692SJohan Hedberg 31860493684eSMarcel Holtmann hci_conn_put(conn); 31870493684eSMarcel Holtmann 31882a611692SJohan Hedberg unlock: 31890493684eSMarcel Holtmann hci_dev_unlock(hdev); 31900493684eSMarcel Holtmann } 31910493684eSMarcel Holtmann 319241a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 319341a96212SMarcel Holtmann { 319441a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 319541a96212SMarcel Holtmann struct inquiry_entry *ie; 319641a96212SMarcel Holtmann 319741a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 319841a96212SMarcel Holtmann 319941a96212SMarcel Holtmann hci_dev_lock(hdev); 320041a96212SMarcel Holtmann 3201cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 3202cc11b9c1SAndrei Emeltchenko if (ie) 320341a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 320441a96212SMarcel Holtmann 320541a96212SMarcel Holtmann hci_dev_unlock(hdev); 320641a96212SMarcel Holtmann } 320741a96212SMarcel Holtmann 32082763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev, 32092763eda6SSzymon Janc struct sk_buff *skb) 32102763eda6SSzymon Janc { 32112763eda6SSzymon Janc struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; 32122763eda6SSzymon Janc struct oob_data *data; 32132763eda6SSzymon Janc 32142763eda6SSzymon Janc BT_DBG("%s", hdev->name); 32152763eda6SSzymon Janc 32162763eda6SSzymon Janc hci_dev_lock(hdev); 32172763eda6SSzymon Janc 3218a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 3219e1ba1f15SSzymon Janc goto unlock; 3220e1ba1f15SSzymon Janc 32212763eda6SSzymon Janc data = hci_find_remote_oob_data(hdev, &ev->bdaddr); 32222763eda6SSzymon Janc if (data) { 32232763eda6SSzymon Janc struct hci_cp_remote_oob_data_reply cp; 32242763eda6SSzymon Janc 32252763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 32262763eda6SSzymon Janc memcpy(cp.hash, data->hash, sizeof(cp.hash)); 32272763eda6SSzymon Janc memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); 32282763eda6SSzymon Janc 32292763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), 32302763eda6SSzymon Janc &cp); 32312763eda6SSzymon Janc } else { 32322763eda6SSzymon Janc struct hci_cp_remote_oob_data_neg_reply cp; 32332763eda6SSzymon Janc 32342763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 32352763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), 32362763eda6SSzymon Janc &cp); 32372763eda6SSzymon Janc } 32382763eda6SSzymon Janc 3239e1ba1f15SSzymon Janc unlock: 32402763eda6SSzymon Janc hci_dev_unlock(hdev); 32412763eda6SSzymon Janc } 32422763eda6SSzymon Janc 3243fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 3244fcd89c09SVille Tervo { 3245fcd89c09SVille Tervo struct hci_ev_le_conn_complete *ev = (void *) skb->data; 3246fcd89c09SVille Tervo struct hci_conn *conn; 3247fcd89c09SVille Tervo 3248fcd89c09SVille Tervo BT_DBG("%s status %d", hdev->name, ev->status); 3249fcd89c09SVille Tervo 3250fcd89c09SVille Tervo hci_dev_lock(hdev); 3251fcd89c09SVille Tervo 3252fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr); 3253b62f328bSVille Tervo if (!conn) { 3254b62f328bSVille Tervo conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); 3255b62f328bSVille Tervo if (!conn) { 3256b62f328bSVille Tervo BT_ERR("No memory for new connection"); 3257b62f328bSVille Tervo hci_dev_unlock(hdev); 3258b62f328bSVille Tervo return; 3259b62f328bSVille Tervo } 326029b7988aSAndre Guedes 326129b7988aSAndre Guedes conn->dst_type = ev->bdaddr_type; 3262b62f328bSVille Tervo } 3263fcd89c09SVille Tervo 3264fcd89c09SVille Tervo if (ev->status) { 326548264f06SJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 326648264f06SJohan Hedberg conn->dst_type, ev->status); 3267fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 3268fcd89c09SVille Tervo conn->state = BT_CLOSED; 3269fcd89c09SVille Tervo hci_conn_del(conn); 3270fcd89c09SVille Tervo goto unlock; 3271fcd89c09SVille Tervo } 3272fcd89c09SVille Tervo 3273b644ba33SJohan Hedberg if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 3274b644ba33SJohan Hedberg mgmt_device_connected(hdev, &ev->bdaddr, conn->type, 3275b644ba33SJohan Hedberg conn->dst_type, NULL, 0, 0); 327683bc71b4SVinicius Costa Gomes 32777b5c0d52SVinicius Costa Gomes conn->sec_level = BT_SECURITY_LOW; 3278fcd89c09SVille Tervo conn->handle = __le16_to_cpu(ev->handle); 3279fcd89c09SVille Tervo conn->state = BT_CONNECTED; 3280fcd89c09SVille Tervo 3281fcd89c09SVille Tervo hci_conn_hold_device(conn); 3282fcd89c09SVille Tervo hci_conn_add_sysfs(conn); 3283fcd89c09SVille Tervo 3284fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 3285fcd89c09SVille Tervo 3286fcd89c09SVille Tervo unlock: 3287fcd89c09SVille Tervo hci_dev_unlock(hdev); 3288fcd89c09SVille Tervo } 3289fcd89c09SVille Tervo 32909aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev, 32919aa04c91SAndre Guedes struct sk_buff *skb) 32929aa04c91SAndre Guedes { 3293e95beb41SAndre Guedes u8 num_reports = skb->data[0]; 3294e95beb41SAndre Guedes void *ptr = &skb->data[1]; 32953c9e9195SAndre Guedes s8 rssi; 32969aa04c91SAndre Guedes 32979aa04c91SAndre Guedes hci_dev_lock(hdev); 32989aa04c91SAndre Guedes 3299e95beb41SAndre Guedes while (num_reports--) { 3300e95beb41SAndre Guedes struct hci_ev_le_advertising_info *ev = ptr; 3301e95beb41SAndre Guedes 33029aa04c91SAndre Guedes hci_add_adv_entry(hdev, ev); 33039aa04c91SAndre Guedes 33043c9e9195SAndre Guedes rssi = ev->data[ev->length]; 33053c9e9195SAndre Guedes mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type, 33063c9e9195SAndre Guedes NULL, rssi, 0, ev->data, ev->length); 33073c9e9195SAndre Guedes 3308e95beb41SAndre Guedes ptr += sizeof(*ev) + ev->length + 1; 33099aa04c91SAndre Guedes } 33109aa04c91SAndre Guedes 33119aa04c91SAndre Guedes hci_dev_unlock(hdev); 33129aa04c91SAndre Guedes } 33139aa04c91SAndre Guedes 3314a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev, 3315a7a595f6SVinicius Costa Gomes struct sk_buff *skb) 3316a7a595f6SVinicius Costa Gomes { 3317a7a595f6SVinicius Costa Gomes struct hci_ev_le_ltk_req *ev = (void *) skb->data; 3318a7a595f6SVinicius Costa Gomes struct hci_cp_le_ltk_reply cp; 3319bea710feSVinicius Costa Gomes struct hci_cp_le_ltk_neg_reply neg; 3320a7a595f6SVinicius Costa Gomes struct hci_conn *conn; 3321c9839a11SVinicius Costa Gomes struct smp_ltk *ltk; 3322a7a595f6SVinicius Costa Gomes 3323a7a595f6SVinicius Costa Gomes BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle)); 3324a7a595f6SVinicius Costa Gomes 3325a7a595f6SVinicius Costa Gomes hci_dev_lock(hdev); 3326a7a595f6SVinicius Costa Gomes 3327a7a595f6SVinicius Costa Gomes conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3328bea710feSVinicius Costa Gomes if (conn == NULL) 3329bea710feSVinicius Costa Gomes goto not_found; 3330a7a595f6SVinicius Costa Gomes 3331bea710feSVinicius Costa Gomes ltk = hci_find_ltk(hdev, ev->ediv, ev->random); 3332bea710feSVinicius Costa Gomes if (ltk == NULL) 3333bea710feSVinicius Costa Gomes goto not_found; 3334bea710feSVinicius Costa Gomes 3335bea710feSVinicius Costa Gomes memcpy(cp.ltk, ltk->val, sizeof(ltk->val)); 3336a7a595f6SVinicius Costa Gomes cp.handle = cpu_to_le16(conn->handle); 3337c9839a11SVinicius Costa Gomes 3338c9839a11SVinicius Costa Gomes if (ltk->authenticated) 3339c9839a11SVinicius Costa Gomes conn->sec_level = BT_SECURITY_HIGH; 3340a7a595f6SVinicius Costa Gomes 3341a7a595f6SVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); 3342a7a595f6SVinicius Costa Gomes 3343c9839a11SVinicius Costa Gomes if (ltk->type & HCI_SMP_STK) { 3344c9839a11SVinicius Costa Gomes list_del(<k->list); 3345c9839a11SVinicius Costa Gomes kfree(ltk); 3346c9839a11SVinicius Costa Gomes } 3347c9839a11SVinicius Costa Gomes 3348a7a595f6SVinicius Costa Gomes hci_dev_unlock(hdev); 3349bea710feSVinicius Costa Gomes 3350bea710feSVinicius Costa Gomes return; 3351bea710feSVinicius Costa Gomes 3352bea710feSVinicius Costa Gomes not_found: 3353bea710feSVinicius Costa Gomes neg.handle = ev->handle; 3354bea710feSVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg); 3355bea710feSVinicius Costa Gomes hci_dev_unlock(hdev); 3356a7a595f6SVinicius Costa Gomes } 3357a7a595f6SVinicius Costa Gomes 3358fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 3359fcd89c09SVille Tervo { 3360fcd89c09SVille Tervo struct hci_ev_le_meta *le_ev = (void *) skb->data; 3361fcd89c09SVille Tervo 3362fcd89c09SVille Tervo skb_pull(skb, sizeof(*le_ev)); 3363fcd89c09SVille Tervo 3364fcd89c09SVille Tervo switch (le_ev->subevent) { 3365fcd89c09SVille Tervo case HCI_EV_LE_CONN_COMPLETE: 3366fcd89c09SVille Tervo hci_le_conn_complete_evt(hdev, skb); 3367fcd89c09SVille Tervo break; 3368fcd89c09SVille Tervo 33699aa04c91SAndre Guedes case HCI_EV_LE_ADVERTISING_REPORT: 33709aa04c91SAndre Guedes hci_le_adv_report_evt(hdev, skb); 33719aa04c91SAndre Guedes break; 33729aa04c91SAndre Guedes 3373a7a595f6SVinicius Costa Gomes case HCI_EV_LE_LTK_REQ: 3374a7a595f6SVinicius Costa Gomes hci_le_ltk_request_evt(hdev, skb); 3375a7a595f6SVinicius Costa Gomes break; 3376a7a595f6SVinicius Costa Gomes 3377fcd89c09SVille Tervo default: 3378fcd89c09SVille Tervo break; 3379fcd89c09SVille Tervo } 3380fcd89c09SVille Tervo } 3381fcd89c09SVille Tervo 33821da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 33831da177e4SLinus Torvalds { 3384a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 3385a9de9248SMarcel Holtmann __u8 event = hdr->evt; 33861da177e4SLinus Torvalds 33871da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 33881da177e4SLinus Torvalds 3389a9de9248SMarcel Holtmann switch (event) { 33901da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 33911da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 33921da177e4SLinus Torvalds break; 33931da177e4SLinus Torvalds 33941da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 33951da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 33961da177e4SLinus Torvalds break; 33971da177e4SLinus Torvalds 3398a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 3399a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 340021d9e30eSMarcel Holtmann break; 340121d9e30eSMarcel Holtmann 34021da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 34031da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 34041da177e4SLinus Torvalds break; 34051da177e4SLinus Torvalds 34061da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 34071da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 34081da177e4SLinus Torvalds break; 34091da177e4SLinus Torvalds 34101da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 34111da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 34121da177e4SLinus Torvalds break; 34131da177e4SLinus Torvalds 3414a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 3415a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 3416a9de9248SMarcel Holtmann break; 3417a9de9248SMarcel Holtmann 34181da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 34191da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 34201da177e4SLinus Torvalds break; 34211da177e4SLinus Torvalds 3422a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 3423a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 3424a9de9248SMarcel Holtmann break; 3425a9de9248SMarcel Holtmann 3426a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 3427a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 3428a9de9248SMarcel Holtmann break; 3429a9de9248SMarcel Holtmann 3430a9de9248SMarcel Holtmann case HCI_EV_REMOTE_VERSION: 3431a9de9248SMarcel Holtmann hci_remote_version_evt(hdev, skb); 3432a9de9248SMarcel Holtmann break; 3433a9de9248SMarcel Holtmann 3434a9de9248SMarcel Holtmann case HCI_EV_QOS_SETUP_COMPLETE: 3435a9de9248SMarcel Holtmann hci_qos_setup_complete_evt(hdev, skb); 3436a9de9248SMarcel Holtmann break; 3437a9de9248SMarcel Holtmann 3438a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 3439a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 3440a9de9248SMarcel Holtmann break; 3441a9de9248SMarcel Holtmann 3442a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 3443a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 3444a9de9248SMarcel Holtmann break; 3445a9de9248SMarcel Holtmann 3446a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 3447a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 3448a9de9248SMarcel Holtmann break; 3449a9de9248SMarcel Holtmann 3450a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 3451a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 3452a9de9248SMarcel Holtmann break; 3453a9de9248SMarcel Holtmann 3454a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 3455a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 34561da177e4SLinus Torvalds break; 34571da177e4SLinus Torvalds 34581da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 34591da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 34601da177e4SLinus Torvalds break; 34611da177e4SLinus Torvalds 34621da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 34631da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 34641da177e4SLinus Torvalds break; 34651da177e4SLinus Torvalds 34661da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 34671da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 34681da177e4SLinus Torvalds break; 34691da177e4SLinus Torvalds 34701da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 34711da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 34721da177e4SLinus Torvalds break; 34731da177e4SLinus Torvalds 3474a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 3475a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 3476a8746417SMarcel Holtmann break; 3477a8746417SMarcel Holtmann 347885a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 347985a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 348085a1e930SMarcel Holtmann break; 348185a1e930SMarcel Holtmann 3482a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 3483a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 3484a9de9248SMarcel Holtmann break; 3485a9de9248SMarcel Holtmann 3486a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 3487a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 3488a9de9248SMarcel Holtmann break; 3489a9de9248SMarcel Holtmann 3490a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 3491a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 3492a9de9248SMarcel Holtmann break; 3493a9de9248SMarcel Holtmann 3494a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_CHANGED: 3495a9de9248SMarcel Holtmann hci_sync_conn_changed_evt(hdev, skb); 3496a9de9248SMarcel Holtmann break; 3497a9de9248SMarcel Holtmann 349804837f64SMarcel Holtmann case HCI_EV_SNIFF_SUBRATE: 349904837f64SMarcel Holtmann hci_sniff_subrate_evt(hdev, skb); 350004837f64SMarcel Holtmann break; 350104837f64SMarcel Holtmann 3502a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 3503a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 35041da177e4SLinus Torvalds break; 35051da177e4SLinus Torvalds 35060493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 35070493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 35080493684eSMarcel Holtmann break; 35090493684eSMarcel Holtmann 351003b555e1SJohan Hedberg case HCI_EV_IO_CAPA_REPLY: 351103b555e1SJohan Hedberg hci_io_capa_reply_evt(hdev, skb); 351203b555e1SJohan Hedberg break; 351303b555e1SJohan Hedberg 3514a5c29683SJohan Hedberg case HCI_EV_USER_CONFIRM_REQUEST: 3515a5c29683SJohan Hedberg hci_user_confirm_request_evt(hdev, skb); 3516a5c29683SJohan Hedberg break; 3517a5c29683SJohan Hedberg 35181143d458SBrian Gix case HCI_EV_USER_PASSKEY_REQUEST: 35191143d458SBrian Gix hci_user_passkey_request_evt(hdev, skb); 35201143d458SBrian Gix break; 35211143d458SBrian Gix 35220493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 35230493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 35240493684eSMarcel Holtmann break; 35250493684eSMarcel Holtmann 352641a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 352741a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 352841a96212SMarcel Holtmann break; 352941a96212SMarcel Holtmann 3530fcd89c09SVille Tervo case HCI_EV_LE_META: 3531fcd89c09SVille Tervo hci_le_meta_evt(hdev, skb); 3532fcd89c09SVille Tervo break; 3533fcd89c09SVille Tervo 35342763eda6SSzymon Janc case HCI_EV_REMOTE_OOB_DATA_REQUEST: 35352763eda6SSzymon Janc hci_remote_oob_data_request_evt(hdev, skb); 35362763eda6SSzymon Janc break; 35372763eda6SSzymon Janc 353825e89e99SAndrei Emeltchenko case HCI_EV_NUM_COMP_BLOCKS: 353925e89e99SAndrei Emeltchenko hci_num_comp_blocks_evt(hdev, skb); 354025e89e99SAndrei Emeltchenko break; 354125e89e99SAndrei Emeltchenko 35421da177e4SLinus Torvalds default: 3543a9de9248SMarcel Holtmann BT_DBG("%s event 0x%x", hdev->name, event); 35441da177e4SLinus Torvalds break; 35451da177e4SLinus Torvalds } 35461da177e4SLinus Torvalds 35471da177e4SLinus Torvalds kfree_skb(skb); 35481da177e4SLinus Torvalds hdev->stat.evt_rx++; 35491da177e4SLinus Torvalds } 3550