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 212a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 213744cf19eSJohan Hedberg mgmt_set_local_name_complete(hdev, sent, status); 214b312b161SJohan Hedberg 21556e5cb86SJohan Hedberg if (status == 0) 2161f6c6378SJohan Hedberg memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); 21756e5cb86SJohan Hedberg 21856e5cb86SJohan Hedberg hci_dev_unlock(hdev); 219a9de9248SMarcel Holtmann } 220a9de9248SMarcel Holtmann 221a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) 222a9de9248SMarcel Holtmann { 223a9de9248SMarcel Holtmann struct hci_rp_read_local_name *rp = (void *) skb->data; 224a9de9248SMarcel Holtmann 225a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 226a9de9248SMarcel Holtmann 227a9de9248SMarcel Holtmann if (rp->status) 228a9de9248SMarcel Holtmann return; 229a9de9248SMarcel Holtmann 2301f6c6378SJohan Hedberg memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); 231a9de9248SMarcel Holtmann } 232a9de9248SMarcel Holtmann 233a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) 234a9de9248SMarcel Holtmann { 235a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 236a9de9248SMarcel Holtmann void *sent; 237a9de9248SMarcel Holtmann 238a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 239a9de9248SMarcel Holtmann 240a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); 241a9de9248SMarcel Holtmann if (!sent) 242a9de9248SMarcel Holtmann return; 2431da177e4SLinus Torvalds 2441da177e4SLinus Torvalds if (!status) { 245a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 246a9de9248SMarcel Holtmann 2471da177e4SLinus Torvalds if (param == AUTH_ENABLED) 2481da177e4SLinus Torvalds set_bit(HCI_AUTH, &hdev->flags); 2491da177e4SLinus Torvalds else 2501da177e4SLinus Torvalds clear_bit(HCI_AUTH, &hdev->flags); 2511da177e4SLinus Torvalds } 252a9de9248SMarcel Holtmann 25333ef95edSJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 25433ef95edSJohan Hedberg mgmt_auth_enable_complete(hdev, status); 25533ef95edSJohan Hedberg 25623bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status); 257a9de9248SMarcel Holtmann } 2581da177e4SLinus Torvalds 259a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) 260a9de9248SMarcel Holtmann { 261a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 262a9de9248SMarcel Holtmann void *sent; 263a9de9248SMarcel Holtmann 264a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 265a9de9248SMarcel Holtmann 266a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); 2671da177e4SLinus Torvalds if (!sent) 268a9de9248SMarcel Holtmann return; 2691da177e4SLinus Torvalds 2701da177e4SLinus Torvalds if (!status) { 271a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 272a9de9248SMarcel Holtmann 2731da177e4SLinus Torvalds if (param) 2741da177e4SLinus Torvalds set_bit(HCI_ENCRYPT, &hdev->flags); 2751da177e4SLinus Torvalds else 2761da177e4SLinus Torvalds clear_bit(HCI_ENCRYPT, &hdev->flags); 2771da177e4SLinus Torvalds } 278a9de9248SMarcel Holtmann 27923bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status); 2801da177e4SLinus Torvalds } 2811da177e4SLinus Torvalds 282a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) 283a9de9248SMarcel Holtmann { 28436f7fc7eSJohan Hedberg __u8 param, status = *((__u8 *) skb->data); 28536f7fc7eSJohan Hedberg int old_pscan, old_iscan; 286a9de9248SMarcel Holtmann void *sent; 2871da177e4SLinus Torvalds 288a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 289a9de9248SMarcel Holtmann 290a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); 2911da177e4SLinus Torvalds if (!sent) 292a9de9248SMarcel Holtmann return; 2931da177e4SLinus Torvalds 29436f7fc7eSJohan Hedberg param = *((__u8 *) sent); 295a9de9248SMarcel Holtmann 29656e5cb86SJohan Hedberg hci_dev_lock(hdev); 29756e5cb86SJohan Hedberg 2982d7cee58SJohan Hedberg if (status != 0) { 299744cf19eSJohan Hedberg mgmt_write_scan_failed(hdev, param, status); 3002d7cee58SJohan Hedberg hdev->discov_timeout = 0; 3012d7cee58SJohan Hedberg goto done; 3022d7cee58SJohan Hedberg } 3032d7cee58SJohan Hedberg 3049fbcbb45SJohan Hedberg old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags); 3059fbcbb45SJohan Hedberg old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags); 306a9de9248SMarcel Holtmann 30773f22f62SJohan Hedberg if (param & SCAN_INQUIRY) { 3081da177e4SLinus Torvalds set_bit(HCI_ISCAN, &hdev->flags); 3099fbcbb45SJohan Hedberg if (!old_iscan) 310744cf19eSJohan Hedberg mgmt_discoverable(hdev, 1); 31116ab91abSJohan Hedberg if (hdev->discov_timeout > 0) { 31216ab91abSJohan Hedberg int to = msecs_to_jiffies(hdev->discov_timeout * 1000); 31316ab91abSJohan Hedberg queue_delayed_work(hdev->workqueue, &hdev->discov_off, 31416ab91abSJohan Hedberg to); 31516ab91abSJohan Hedberg } 3169fbcbb45SJohan Hedberg } else if (old_iscan) 317744cf19eSJohan Hedberg mgmt_discoverable(hdev, 0); 3181da177e4SLinus Torvalds 3199fbcbb45SJohan Hedberg if (param & SCAN_PAGE) { 3201da177e4SLinus Torvalds set_bit(HCI_PSCAN, &hdev->flags); 3219fbcbb45SJohan Hedberg if (!old_pscan) 322744cf19eSJohan Hedberg mgmt_connectable(hdev, 1); 3239fbcbb45SJohan Hedberg } else if (old_pscan) 324744cf19eSJohan Hedberg mgmt_connectable(hdev, 0); 325a9de9248SMarcel Holtmann 32636f7fc7eSJohan Hedberg done: 32756e5cb86SJohan Hedberg hci_dev_unlock(hdev); 32823bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status); 3291da177e4SLinus Torvalds } 3301da177e4SLinus Torvalds 331a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 332a9de9248SMarcel Holtmann { 333a9de9248SMarcel Holtmann struct hci_rp_read_class_of_dev *rp = (void *) skb->data; 334a9de9248SMarcel Holtmann 335a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 336a9de9248SMarcel Holtmann 337a9de9248SMarcel Holtmann if (rp->status) 338a9de9248SMarcel Holtmann return; 339a9de9248SMarcel Holtmann 340a9de9248SMarcel Holtmann memcpy(hdev->dev_class, rp->dev_class, 3); 341a9de9248SMarcel Holtmann 342a9de9248SMarcel Holtmann BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, 343a9de9248SMarcel Holtmann hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); 344a9de9248SMarcel Holtmann } 345a9de9248SMarcel Holtmann 346a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 347a9de9248SMarcel Holtmann { 348a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 349a9de9248SMarcel Holtmann void *sent; 350a9de9248SMarcel Holtmann 351a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 352a9de9248SMarcel Holtmann 353f383f275SMarcel Holtmann if (status) 354f383f275SMarcel Holtmann return; 355f383f275SMarcel Holtmann 356a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); 357a9de9248SMarcel Holtmann if (!sent) 358a9de9248SMarcel Holtmann return; 359a9de9248SMarcel Holtmann 360a9de9248SMarcel Holtmann memcpy(hdev->dev_class, sent, 3); 361a9de9248SMarcel Holtmann } 362a9de9248SMarcel Holtmann 363a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 364a9de9248SMarcel Holtmann { 365a9de9248SMarcel Holtmann struct hci_rp_read_voice_setting *rp = (void *) skb->data; 366a9de9248SMarcel Holtmann __u16 setting; 367a9de9248SMarcel Holtmann 368a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 369a9de9248SMarcel Holtmann 370a9de9248SMarcel Holtmann if (rp->status) 371a9de9248SMarcel Holtmann return; 372a9de9248SMarcel Holtmann 373a9de9248SMarcel Holtmann setting = __le16_to_cpu(rp->voice_setting); 374a9de9248SMarcel Holtmann 375a9de9248SMarcel Holtmann if (hdev->voice_setting == setting) 376a9de9248SMarcel Holtmann return; 377a9de9248SMarcel Holtmann 378a9de9248SMarcel Holtmann hdev->voice_setting = setting; 379a9de9248SMarcel Holtmann 380a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 381a9de9248SMarcel Holtmann 3823c54711cSGustavo F. Padovan if (hdev->notify) 383a9de9248SMarcel Holtmann hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 384a9de9248SMarcel Holtmann } 385a9de9248SMarcel Holtmann 386a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 387a9de9248SMarcel Holtmann { 388a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 389f383f275SMarcel Holtmann __u16 setting; 390a9de9248SMarcel Holtmann void *sent; 391a9de9248SMarcel Holtmann 392a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 393a9de9248SMarcel Holtmann 394f383f275SMarcel Holtmann if (status) 395f383f275SMarcel Holtmann return; 396f383f275SMarcel Holtmann 397a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); 398a9de9248SMarcel Holtmann if (!sent) 399a9de9248SMarcel Holtmann return; 400a9de9248SMarcel Holtmann 401f383f275SMarcel Holtmann setting = get_unaligned_le16(sent); 4021da177e4SLinus Torvalds 403f383f275SMarcel Holtmann if (hdev->voice_setting == setting) 404f383f275SMarcel Holtmann return; 405f383f275SMarcel Holtmann 4061da177e4SLinus Torvalds hdev->voice_setting = setting; 4071da177e4SLinus Torvalds 408a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 4091da177e4SLinus Torvalds 4103c54711cSGustavo F. Padovan if (hdev->notify) 4111da177e4SLinus Torvalds hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 4121da177e4SLinus Torvalds } 4131da177e4SLinus Torvalds 414a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 4151da177e4SLinus Torvalds { 416a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 4171da177e4SLinus Torvalds 418a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 4191da177e4SLinus Torvalds 42023bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status); 4211143e5a6SMarcel Holtmann } 4221143e5a6SMarcel Holtmann 423333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 424333140b5SMarcel Holtmann { 425333140b5SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 426333140b5SMarcel Holtmann void *sent; 427333140b5SMarcel Holtmann 428333140b5SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 429333140b5SMarcel Holtmann 430333140b5SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); 431333140b5SMarcel Holtmann if (!sent) 432333140b5SMarcel Holtmann return; 433333140b5SMarcel Holtmann 434c0ecddc2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 435c0ecddc2SJohan Hedberg mgmt_ssp_enable_complete(hdev, *((u8 *) sent), status); 436c0ecddc2SJohan Hedberg else if (!status) { 43784bde9d6SJohan Hedberg if (*((u8 *) sent)) 43884bde9d6SJohan Hedberg set_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 43984bde9d6SJohan Hedberg else 44084bde9d6SJohan Hedberg clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 441c0ecddc2SJohan Hedberg } 442333140b5SMarcel Holtmann } 443333140b5SMarcel Holtmann 444d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev) 445d5859e22SJohan Hedberg { 446d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 447d5859e22SJohan Hedberg return 2; 448d5859e22SJohan Hedberg 449d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 450d5859e22SJohan Hedberg return 1; 451d5859e22SJohan Hedberg 452d5859e22SJohan Hedberg if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 && 453d5859e22SJohan Hedberg hdev->lmp_subver == 0x0757) 454d5859e22SJohan Hedberg return 1; 455d5859e22SJohan Hedberg 456d5859e22SJohan Hedberg if (hdev->manufacturer == 15) { 457d5859e22SJohan Hedberg if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963) 458d5859e22SJohan Hedberg return 1; 459d5859e22SJohan Hedberg if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963) 460d5859e22SJohan Hedberg return 1; 461d5859e22SJohan Hedberg if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965) 462d5859e22SJohan Hedberg return 1; 463d5859e22SJohan Hedberg } 464d5859e22SJohan Hedberg 465d5859e22SJohan Hedberg if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 && 466d5859e22SJohan Hedberg hdev->lmp_subver == 0x1805) 467d5859e22SJohan Hedberg return 1; 468d5859e22SJohan Hedberg 469d5859e22SJohan Hedberg return 0; 470d5859e22SJohan Hedberg } 471d5859e22SJohan Hedberg 472d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev) 473d5859e22SJohan Hedberg { 474d5859e22SJohan Hedberg u8 mode; 475d5859e22SJohan Hedberg 476d5859e22SJohan Hedberg mode = hci_get_inquiry_mode(hdev); 477d5859e22SJohan Hedberg 478d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode); 479d5859e22SJohan Hedberg } 480d5859e22SJohan Hedberg 481d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev) 482d5859e22SJohan Hedberg { 483d5859e22SJohan Hedberg /* The second byte is 0xff instead of 0x9f (two reserved bits 484d5859e22SJohan Hedberg * disabled) since a Broadcom 1.2 dongle doesn't respond to the 485d5859e22SJohan Hedberg * command otherwise */ 486d5859e22SJohan Hedberg u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 }; 487d5859e22SJohan Hedberg 4886de6c18dSVille Tervo /* CSR 1.1 dongles does not accept any bitfield so don't try to set 4896de6c18dSVille Tervo * any event mask for pre 1.2 devices */ 4905a13b095SAndrei Emeltchenko if (hdev->hci_ver < BLUETOOTH_VER_1_2) 4916de6c18dSVille Tervo return; 4926de6c18dSVille Tervo 493d5859e22SJohan Hedberg events[4] |= 0x01; /* Flow Specification Complete */ 494d5859e22SJohan Hedberg events[4] |= 0x02; /* Inquiry Result with RSSI */ 495d5859e22SJohan Hedberg events[4] |= 0x04; /* Read Remote Extended Features Complete */ 496d5859e22SJohan Hedberg events[5] |= 0x08; /* Synchronous Connection Complete */ 497d5859e22SJohan Hedberg events[5] |= 0x10; /* Synchronous Connection Changed */ 498d5859e22SJohan Hedberg 499d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 500d5859e22SJohan Hedberg events[4] |= 0x04; /* Inquiry Result with RSSI */ 501d5859e22SJohan Hedberg 502d5859e22SJohan Hedberg if (hdev->features[5] & LMP_SNIFF_SUBR) 503d5859e22SJohan Hedberg events[5] |= 0x20; /* Sniff Subrating */ 504d5859e22SJohan Hedberg 505d5859e22SJohan Hedberg if (hdev->features[5] & LMP_PAUSE_ENC) 506d5859e22SJohan Hedberg events[5] |= 0x80; /* Encryption Key Refresh Complete */ 507d5859e22SJohan Hedberg 508d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 509d5859e22SJohan Hedberg events[5] |= 0x40; /* Extended Inquiry Result */ 510d5859e22SJohan Hedberg 511d5859e22SJohan Hedberg if (hdev->features[6] & LMP_NO_FLUSH) 512d5859e22SJohan Hedberg events[7] |= 0x01; /* Enhanced Flush Complete */ 513d5859e22SJohan Hedberg 514d5859e22SJohan Hedberg if (hdev->features[7] & LMP_LSTO) 515d5859e22SJohan Hedberg events[6] |= 0x80; /* Link Supervision Timeout Changed */ 516d5859e22SJohan Hedberg 517d5859e22SJohan Hedberg if (hdev->features[6] & LMP_SIMPLE_PAIR) { 518d5859e22SJohan Hedberg events[6] |= 0x01; /* IO Capability Request */ 519d5859e22SJohan Hedberg events[6] |= 0x02; /* IO Capability Response */ 520d5859e22SJohan Hedberg events[6] |= 0x04; /* User Confirmation Request */ 521d5859e22SJohan Hedberg events[6] |= 0x08; /* User Passkey Request */ 522d5859e22SJohan Hedberg events[6] |= 0x10; /* Remote OOB Data Request */ 523d5859e22SJohan Hedberg events[6] |= 0x20; /* Simple Pairing Complete */ 524d5859e22SJohan Hedberg events[7] |= 0x04; /* User Passkey Notification */ 525d5859e22SJohan Hedberg events[7] |= 0x08; /* Keypress Notification */ 526d5859e22SJohan Hedberg events[7] |= 0x10; /* Remote Host Supported 527d5859e22SJohan Hedberg * Features Notification */ 528d5859e22SJohan Hedberg } 529d5859e22SJohan Hedberg 530d5859e22SJohan Hedberg if (hdev->features[4] & LMP_LE) 531d5859e22SJohan Hedberg events[7] |= 0x20; /* LE Meta-Event */ 532d5859e22SJohan Hedberg 533d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); 534d5859e22SJohan Hedberg } 535d5859e22SJohan Hedberg 536e6100a25SAndre Guedes static void hci_set_le_support(struct hci_dev *hdev) 537e6100a25SAndre Guedes { 538e6100a25SAndre Guedes struct hci_cp_write_le_host_supported cp; 539e6100a25SAndre Guedes 540e6100a25SAndre Guedes memset(&cp, 0, sizeof(cp)); 541e6100a25SAndre Guedes 542e6100a25SAndre Guedes if (enable_le) { 543e6100a25SAndre Guedes cp.le = 1; 544e6100a25SAndre Guedes cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR); 545e6100a25SAndre Guedes } 546e6100a25SAndre Guedes 547e6100a25SAndre Guedes hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), &cp); 548e6100a25SAndre Guedes } 549e6100a25SAndre Guedes 550d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev) 551d5859e22SJohan Hedberg { 552e61ef499SAndrei Emeltchenko if (hdev->dev_type != HCI_BREDR) 553e61ef499SAndrei Emeltchenko return; 554e61ef499SAndrei Emeltchenko 555d5859e22SJohan Hedberg hci_setup_event_mask(hdev); 556d5859e22SJohan Hedberg 557d095c1ebSAndrei Emeltchenko if (hdev->hci_ver > BLUETOOTH_VER_1_1) 558d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); 559d5859e22SJohan Hedberg 560*54d04dbbSJohan Hedberg if (hdev->features[6] & LMP_SIMPLE_PAIR) { 561*54d04dbbSJohan Hedberg if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { 562d5859e22SJohan Hedberg u8 mode = 0x01; 563*54d04dbbSJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 564*54d04dbbSJohan Hedberg sizeof(mode), &mode); 565*54d04dbbSJohan Hedberg } else { 566*54d04dbbSJohan Hedberg struct hci_cp_write_eir cp; 567*54d04dbbSJohan Hedberg 568*54d04dbbSJohan Hedberg memset(hdev->eir, 0, sizeof(hdev->eir)); 569*54d04dbbSJohan Hedberg memset(&cp, 0, sizeof(cp)); 570*54d04dbbSJohan Hedberg 571*54d04dbbSJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp); 572*54d04dbbSJohan Hedberg } 573d5859e22SJohan Hedberg } 574d5859e22SJohan Hedberg 575d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 576d5859e22SJohan Hedberg hci_setup_inquiry_mode(hdev); 577d5859e22SJohan Hedberg 578d5859e22SJohan Hedberg if (hdev->features[7] & LMP_INQ_TX_PWR) 579d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL); 580971e3a4bSAndre Guedes 581971e3a4bSAndre Guedes if (hdev->features[7] & LMP_EXTFEATURES) { 582971e3a4bSAndre Guedes struct hci_cp_read_local_ext_features cp; 583971e3a4bSAndre Guedes 584971e3a4bSAndre Guedes cp.page = 0x01; 585971e3a4bSAndre Guedes hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, 586971e3a4bSAndre Guedes sizeof(cp), &cp); 587971e3a4bSAndre Guedes } 588e6100a25SAndre Guedes 58947990ea0SJohan Hedberg if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) { 59047990ea0SJohan Hedberg u8 enable = 1; 59147990ea0SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, 59247990ea0SJohan Hedberg sizeof(enable), &enable); 59347990ea0SJohan Hedberg } 59447990ea0SJohan Hedberg 595e6100a25SAndre Guedes if (hdev->features[4] & LMP_LE) 596e6100a25SAndre Guedes hci_set_le_support(hdev); 597d5859e22SJohan Hedberg } 598d5859e22SJohan Hedberg 599a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) 600a9de9248SMarcel Holtmann { 601a9de9248SMarcel Holtmann struct hci_rp_read_local_version *rp = (void *) skb->data; 6021143e5a6SMarcel Holtmann 603a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 6041143e5a6SMarcel Holtmann 605a9de9248SMarcel Holtmann if (rp->status) 606a9de9248SMarcel Holtmann return; 6071143e5a6SMarcel Holtmann 608a9de9248SMarcel Holtmann hdev->hci_ver = rp->hci_ver; 609e4e8e37cSMarcel Holtmann hdev->hci_rev = __le16_to_cpu(rp->hci_rev); 610d5859e22SJohan Hedberg hdev->lmp_ver = rp->lmp_ver; 611e4e8e37cSMarcel Holtmann hdev->manufacturer = __le16_to_cpu(rp->manufacturer); 612d5859e22SJohan Hedberg hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); 6131da177e4SLinus Torvalds 614a9de9248SMarcel Holtmann BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name, 615a9de9248SMarcel Holtmann hdev->manufacturer, 616a9de9248SMarcel Holtmann hdev->hci_ver, hdev->hci_rev); 617d5859e22SJohan Hedberg 618d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags)) 619d5859e22SJohan Hedberg hci_setup(hdev); 620d5859e22SJohan Hedberg } 621d5859e22SJohan Hedberg 622d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev) 623d5859e22SJohan Hedberg { 624d5859e22SJohan Hedberg u16 link_policy = 0; 625d5859e22SJohan Hedberg 626d5859e22SJohan Hedberg if (hdev->features[0] & LMP_RSWITCH) 627d5859e22SJohan Hedberg link_policy |= HCI_LP_RSWITCH; 628d5859e22SJohan Hedberg if (hdev->features[0] & LMP_HOLD) 629d5859e22SJohan Hedberg link_policy |= HCI_LP_HOLD; 630d5859e22SJohan Hedberg if (hdev->features[0] & LMP_SNIFF) 631d5859e22SJohan Hedberg link_policy |= HCI_LP_SNIFF; 632d5859e22SJohan Hedberg if (hdev->features[1] & LMP_PARK) 633d5859e22SJohan Hedberg link_policy |= HCI_LP_PARK; 634d5859e22SJohan Hedberg 635d5859e22SJohan Hedberg link_policy = cpu_to_le16(link_policy); 636d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, 637d5859e22SJohan Hedberg sizeof(link_policy), &link_policy); 6381da177e4SLinus Torvalds } 6391da177e4SLinus Torvalds 640a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb) 641a9de9248SMarcel Holtmann { 642a9de9248SMarcel Holtmann struct hci_rp_read_local_commands *rp = (void *) skb->data; 643a9de9248SMarcel Holtmann 644a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 645a9de9248SMarcel Holtmann 646a9de9248SMarcel Holtmann if (rp->status) 647d5859e22SJohan Hedberg goto done; 648a9de9248SMarcel Holtmann 649a9de9248SMarcel Holtmann memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); 650d5859e22SJohan Hedberg 651d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10)) 652d5859e22SJohan Hedberg hci_setup_link_policy(hdev); 653d5859e22SJohan Hedberg 654d5859e22SJohan Hedberg done: 655d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status); 656a9de9248SMarcel Holtmann } 657a9de9248SMarcel Holtmann 658a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb) 659a9de9248SMarcel Holtmann { 660a9de9248SMarcel Holtmann struct hci_rp_read_local_features *rp = (void *) skb->data; 661a9de9248SMarcel Holtmann 662a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 663a9de9248SMarcel Holtmann 664a9de9248SMarcel Holtmann if (rp->status) 665a9de9248SMarcel Holtmann return; 666a9de9248SMarcel Holtmann 667a9de9248SMarcel Holtmann memcpy(hdev->features, rp->features, 8); 6681da177e4SLinus Torvalds 6691da177e4SLinus Torvalds /* Adjust default settings according to features 6701da177e4SLinus Torvalds * supported by device. */ 671a9de9248SMarcel Holtmann 6721da177e4SLinus Torvalds if (hdev->features[0] & LMP_3SLOT) 6731da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM3 | HCI_DH3); 6741da177e4SLinus Torvalds 6751da177e4SLinus Torvalds if (hdev->features[0] & LMP_5SLOT) 6761da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM5 | HCI_DH5); 6771da177e4SLinus Torvalds 6785b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV2) { 6791da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV2); 6805b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV2); 6815b7f9909SMarcel Holtmann } 6821da177e4SLinus Torvalds 6835b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV3) { 6841da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV3); 6855b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV3); 6865b7f9909SMarcel Holtmann } 6875b7f9909SMarcel Holtmann 6885b7f9909SMarcel Holtmann if (hdev->features[3] & LMP_ESCO) 6895b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV3); 6905b7f9909SMarcel Holtmann 6915b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV4) 6925b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV4); 6935b7f9909SMarcel Holtmann 6945b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV5) 6955b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV5); 6961da177e4SLinus Torvalds 697efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_2M) 698efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV3); 699efc7688bSMarcel Holtmann 700efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_3M) 701efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_3EV3); 702efc7688bSMarcel Holtmann 703efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_3S_ESCO) 704efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); 705efc7688bSMarcel Holtmann 706a9de9248SMarcel Holtmann BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, 707a9de9248SMarcel Holtmann hdev->features[0], hdev->features[1], 708a9de9248SMarcel Holtmann hdev->features[2], hdev->features[3], 709a9de9248SMarcel Holtmann hdev->features[4], hdev->features[5], 710a9de9248SMarcel Holtmann hdev->features[6], hdev->features[7]); 7111da177e4SLinus Torvalds } 7121da177e4SLinus Torvalds 713971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev, 714971e3a4bSAndre Guedes struct sk_buff *skb) 715971e3a4bSAndre Guedes { 716971e3a4bSAndre Guedes struct hci_rp_read_local_ext_features *rp = (void *) skb->data; 717971e3a4bSAndre Guedes 718971e3a4bSAndre Guedes BT_DBG("%s status 0x%x", hdev->name, rp->status); 719971e3a4bSAndre Guedes 720971e3a4bSAndre Guedes if (rp->status) 721971e3a4bSAndre Guedes return; 722971e3a4bSAndre Guedes 723b5b32b65SAndre Guedes switch (rp->page) { 724b5b32b65SAndre Guedes case 0: 725b5b32b65SAndre Guedes memcpy(hdev->features, rp->features, 8); 726b5b32b65SAndre Guedes break; 727b5b32b65SAndre Guedes case 1: 72859e29406SAndre Guedes memcpy(hdev->host_features, rp->features, 8); 729b5b32b65SAndre Guedes break; 730b5b32b65SAndre Guedes } 731971e3a4bSAndre Guedes 732971e3a4bSAndre Guedes hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status); 733971e3a4bSAndre Guedes } 734971e3a4bSAndre Guedes 7351e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, 7361e89cffbSAndrei Emeltchenko struct sk_buff *skb) 7371e89cffbSAndrei Emeltchenko { 7381e89cffbSAndrei Emeltchenko struct hci_rp_read_flow_control_mode *rp = (void *) skb->data; 7391e89cffbSAndrei Emeltchenko 7401e89cffbSAndrei Emeltchenko BT_DBG("%s status 0x%x", hdev->name, rp->status); 7411e89cffbSAndrei Emeltchenko 7421e89cffbSAndrei Emeltchenko if (rp->status) 7431e89cffbSAndrei Emeltchenko return; 7441e89cffbSAndrei Emeltchenko 7451e89cffbSAndrei Emeltchenko hdev->flow_ctl_mode = rp->mode; 7461e89cffbSAndrei Emeltchenko 7471e89cffbSAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status); 7481e89cffbSAndrei Emeltchenko } 7491e89cffbSAndrei Emeltchenko 750a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 751a9de9248SMarcel Holtmann { 752a9de9248SMarcel Holtmann struct hci_rp_read_buffer_size *rp = (void *) skb->data; 753a9de9248SMarcel Holtmann 754a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 755a9de9248SMarcel Holtmann 756a9de9248SMarcel Holtmann if (rp->status) 757a9de9248SMarcel Holtmann return; 758a9de9248SMarcel Holtmann 759a9de9248SMarcel Holtmann hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); 760a9de9248SMarcel Holtmann hdev->sco_mtu = rp->sco_mtu; 761a9de9248SMarcel Holtmann hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); 762a9de9248SMarcel Holtmann hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); 763da1f5198SMarcel Holtmann 764da1f5198SMarcel Holtmann if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { 765da1f5198SMarcel Holtmann hdev->sco_mtu = 64; 766da1f5198SMarcel Holtmann hdev->sco_pkts = 8; 767da1f5198SMarcel Holtmann } 768da1f5198SMarcel Holtmann 769da1f5198SMarcel Holtmann hdev->acl_cnt = hdev->acl_pkts; 770da1f5198SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 7711da177e4SLinus Torvalds 772a9de9248SMarcel Holtmann BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, 773a9de9248SMarcel Holtmann hdev->acl_mtu, hdev->acl_pkts, 774a9de9248SMarcel Holtmann hdev->sco_mtu, hdev->sco_pkts); 7751da177e4SLinus Torvalds } 7761da177e4SLinus Torvalds 777a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) 778a9de9248SMarcel Holtmann { 779a9de9248SMarcel Holtmann struct hci_rp_read_bd_addr *rp = (void *) skb->data; 7801da177e4SLinus Torvalds 781a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 782a9de9248SMarcel Holtmann 783a9de9248SMarcel Holtmann if (!rp->status) 784a9de9248SMarcel Holtmann bacpy(&hdev->bdaddr, &rp->bdaddr); 785a9de9248SMarcel Holtmann 78623bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status); 78723bb5763SJohan Hedberg } 78823bb5763SJohan Hedberg 789350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev, 790350ee4cfSAndrei Emeltchenko struct sk_buff *skb) 791350ee4cfSAndrei Emeltchenko { 792350ee4cfSAndrei Emeltchenko struct hci_rp_read_data_block_size *rp = (void *) skb->data; 793350ee4cfSAndrei Emeltchenko 794350ee4cfSAndrei Emeltchenko BT_DBG("%s status 0x%x", hdev->name, rp->status); 795350ee4cfSAndrei Emeltchenko 796350ee4cfSAndrei Emeltchenko if (rp->status) 797350ee4cfSAndrei Emeltchenko return; 798350ee4cfSAndrei Emeltchenko 799350ee4cfSAndrei Emeltchenko hdev->block_mtu = __le16_to_cpu(rp->max_acl_len); 800350ee4cfSAndrei Emeltchenko hdev->block_len = __le16_to_cpu(rp->block_len); 801350ee4cfSAndrei Emeltchenko hdev->num_blocks = __le16_to_cpu(rp->num_blocks); 802350ee4cfSAndrei Emeltchenko 803350ee4cfSAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 804350ee4cfSAndrei Emeltchenko 805350ee4cfSAndrei Emeltchenko BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu, 806350ee4cfSAndrei Emeltchenko hdev->block_cnt, hdev->block_len); 807350ee4cfSAndrei Emeltchenko 808350ee4cfSAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status); 809350ee4cfSAndrei Emeltchenko } 810350ee4cfSAndrei Emeltchenko 81123bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb) 81223bb5763SJohan Hedberg { 81323bb5763SJohan Hedberg __u8 status = *((__u8 *) skb->data); 81423bb5763SJohan Hedberg 81523bb5763SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 81623bb5763SJohan Hedberg 81723bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status); 8181da177e4SLinus Torvalds } 8191da177e4SLinus Torvalds 820928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev, 821928abaa7SAndrei Emeltchenko struct sk_buff *skb) 822928abaa7SAndrei Emeltchenko { 823928abaa7SAndrei Emeltchenko struct hci_rp_read_local_amp_info *rp = (void *) skb->data; 824928abaa7SAndrei Emeltchenko 825928abaa7SAndrei Emeltchenko BT_DBG("%s status 0x%x", hdev->name, rp->status); 826928abaa7SAndrei Emeltchenko 827928abaa7SAndrei Emeltchenko if (rp->status) 828928abaa7SAndrei Emeltchenko return; 829928abaa7SAndrei Emeltchenko 830928abaa7SAndrei Emeltchenko hdev->amp_status = rp->amp_status; 831928abaa7SAndrei Emeltchenko hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); 832928abaa7SAndrei Emeltchenko hdev->amp_max_bw = __le32_to_cpu(rp->max_bw); 833928abaa7SAndrei Emeltchenko hdev->amp_min_latency = __le32_to_cpu(rp->min_latency); 834928abaa7SAndrei Emeltchenko hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu); 835928abaa7SAndrei Emeltchenko hdev->amp_type = rp->amp_type; 836928abaa7SAndrei Emeltchenko hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap); 837928abaa7SAndrei Emeltchenko hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size); 838928abaa7SAndrei Emeltchenko hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); 839928abaa7SAndrei Emeltchenko hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); 840928abaa7SAndrei Emeltchenko 841928abaa7SAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status); 842928abaa7SAndrei Emeltchenko } 843928abaa7SAndrei Emeltchenko 844b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, 845b0916ea0SJohan Hedberg struct sk_buff *skb) 846b0916ea0SJohan Hedberg { 847b0916ea0SJohan Hedberg __u8 status = *((__u8 *) skb->data); 848b0916ea0SJohan Hedberg 849b0916ea0SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 850b0916ea0SJohan Hedberg 851b0916ea0SJohan Hedberg hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status); 852b0916ea0SJohan Hedberg } 853b0916ea0SJohan Hedberg 854d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb) 855d5859e22SJohan Hedberg { 856d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 857d5859e22SJohan Hedberg 858d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 859d5859e22SJohan Hedberg 860d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status); 861d5859e22SJohan Hedberg } 862d5859e22SJohan Hedberg 863d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev, 864d5859e22SJohan Hedberg struct sk_buff *skb) 865d5859e22SJohan Hedberg { 866d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 867d5859e22SJohan Hedberg 868d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 869d5859e22SJohan Hedberg 870d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status); 871d5859e22SJohan Hedberg } 872d5859e22SJohan Hedberg 873d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, 874d5859e22SJohan Hedberg struct sk_buff *skb) 875d5859e22SJohan Hedberg { 876d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 877d5859e22SJohan Hedberg 878d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 879d5859e22SJohan Hedberg 880d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status); 881d5859e22SJohan Hedberg } 882d5859e22SJohan Hedberg 883d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb) 884d5859e22SJohan Hedberg { 885d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 886d5859e22SJohan Hedberg 887d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 888d5859e22SJohan Hedberg 889d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status); 890d5859e22SJohan Hedberg } 891d5859e22SJohan Hedberg 892980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) 893980e1a53SJohan Hedberg { 894980e1a53SJohan Hedberg struct hci_rp_pin_code_reply *rp = (void *) skb->data; 895980e1a53SJohan Hedberg struct hci_cp_pin_code_reply *cp; 896980e1a53SJohan Hedberg struct hci_conn *conn; 897980e1a53SJohan Hedberg 898980e1a53SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 899980e1a53SJohan Hedberg 90056e5cb86SJohan Hedberg hci_dev_lock(hdev); 90156e5cb86SJohan Hedberg 902a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 903744cf19eSJohan Hedberg mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); 904980e1a53SJohan Hedberg 905980e1a53SJohan Hedberg if (rp->status != 0) 90656e5cb86SJohan Hedberg goto unlock; 907980e1a53SJohan Hedberg 908980e1a53SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); 909980e1a53SJohan Hedberg if (!cp) 91056e5cb86SJohan Hedberg goto unlock; 911980e1a53SJohan Hedberg 912980e1a53SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 913980e1a53SJohan Hedberg if (conn) 914980e1a53SJohan Hedberg conn->pin_length = cp->pin_len; 91556e5cb86SJohan Hedberg 91656e5cb86SJohan Hedberg unlock: 91756e5cb86SJohan Hedberg hci_dev_unlock(hdev); 918980e1a53SJohan Hedberg } 919980e1a53SJohan Hedberg 920980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 921980e1a53SJohan Hedberg { 922980e1a53SJohan Hedberg struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data; 923980e1a53SJohan Hedberg 924980e1a53SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 925980e1a53SJohan Hedberg 92656e5cb86SJohan Hedberg hci_dev_lock(hdev); 92756e5cb86SJohan Hedberg 928a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 929744cf19eSJohan Hedberg mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr, 930980e1a53SJohan Hedberg rp->status); 93156e5cb86SJohan Hedberg 93256e5cb86SJohan Hedberg hci_dev_unlock(hdev); 933980e1a53SJohan Hedberg } 93456e5cb86SJohan Hedberg 9356ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, 9366ed58ec5SVille Tervo struct sk_buff *skb) 9376ed58ec5SVille Tervo { 9386ed58ec5SVille Tervo struct hci_rp_le_read_buffer_size *rp = (void *) skb->data; 9396ed58ec5SVille Tervo 9406ed58ec5SVille Tervo BT_DBG("%s status 0x%x", hdev->name, rp->status); 9416ed58ec5SVille Tervo 9426ed58ec5SVille Tervo if (rp->status) 9436ed58ec5SVille Tervo return; 9446ed58ec5SVille Tervo 9456ed58ec5SVille Tervo hdev->le_mtu = __le16_to_cpu(rp->le_mtu); 9466ed58ec5SVille Tervo hdev->le_pkts = rp->le_max_pkt; 9476ed58ec5SVille Tervo 9486ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 9496ed58ec5SVille Tervo 9506ed58ec5SVille Tervo BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); 9516ed58ec5SVille Tervo 9526ed58ec5SVille Tervo hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status); 9536ed58ec5SVille Tervo } 954980e1a53SJohan Hedberg 955a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) 956a5c29683SJohan Hedberg { 957a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 958a5c29683SJohan Hedberg 959a5c29683SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 960a5c29683SJohan Hedberg 96156e5cb86SJohan Hedberg hci_dev_lock(hdev); 96256e5cb86SJohan Hedberg 963a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 964272d90dfSJohan Hedberg mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 965272d90dfSJohan Hedberg 0, rp->status); 96656e5cb86SJohan Hedberg 96756e5cb86SJohan Hedberg hci_dev_unlock(hdev); 968a5c29683SJohan Hedberg } 969a5c29683SJohan Hedberg 970a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, 971a5c29683SJohan Hedberg struct sk_buff *skb) 972a5c29683SJohan Hedberg { 973a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 974a5c29683SJohan Hedberg 975a5c29683SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 976a5c29683SJohan Hedberg 97756e5cb86SJohan Hedberg hci_dev_lock(hdev); 97856e5cb86SJohan Hedberg 979a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 980744cf19eSJohan Hedberg mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr, 981272d90dfSJohan Hedberg ACL_LINK, 0, 982a5c29683SJohan Hedberg rp->status); 98356e5cb86SJohan Hedberg 98456e5cb86SJohan Hedberg hci_dev_unlock(hdev); 985a5c29683SJohan Hedberg } 986a5c29683SJohan Hedberg 9871143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb) 9881143d458SBrian Gix { 9891143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 9901143d458SBrian Gix 9911143d458SBrian Gix BT_DBG("%s status 0x%x", hdev->name, rp->status); 9921143d458SBrian Gix 9931143d458SBrian Gix hci_dev_lock(hdev); 9941143d458SBrian Gix 995a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 996272d90dfSJohan Hedberg mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 997272d90dfSJohan Hedberg 0, rp->status); 9981143d458SBrian Gix 9991143d458SBrian Gix hci_dev_unlock(hdev); 10001143d458SBrian Gix } 10011143d458SBrian Gix 10021143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, 10031143d458SBrian Gix struct sk_buff *skb) 10041143d458SBrian Gix { 10051143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 10061143d458SBrian Gix 10071143d458SBrian Gix BT_DBG("%s status 0x%x", hdev->name, rp->status); 10081143d458SBrian Gix 10091143d458SBrian Gix hci_dev_lock(hdev); 10101143d458SBrian Gix 1011a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 10121143d458SBrian Gix mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr, 1013272d90dfSJohan Hedberg ACL_LINK, 0, 10141143d458SBrian Gix rp->status); 10151143d458SBrian Gix 10161143d458SBrian Gix hci_dev_unlock(hdev); 10171143d458SBrian Gix } 10181143d458SBrian Gix 1019c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, 1020c35938b2SSzymon Janc struct sk_buff *skb) 1021c35938b2SSzymon Janc { 1022c35938b2SSzymon Janc struct hci_rp_read_local_oob_data *rp = (void *) skb->data; 1023c35938b2SSzymon Janc 1024c35938b2SSzymon Janc BT_DBG("%s status 0x%x", hdev->name, rp->status); 1025c35938b2SSzymon Janc 102656e5cb86SJohan Hedberg hci_dev_lock(hdev); 1027744cf19eSJohan Hedberg mgmt_read_local_oob_data_reply_complete(hdev, rp->hash, 1028c35938b2SSzymon Janc rp->randomizer, rp->status); 102956e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1030c35938b2SSzymon Janc } 1031c35938b2SSzymon Janc 103207f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) 103307f7fa5dSAndre Guedes { 103407f7fa5dSAndre Guedes __u8 status = *((__u8 *) skb->data); 103507f7fa5dSAndre Guedes 103607f7fa5dSAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 10377ba8b4beSAndre Guedes 10387ba8b4beSAndre Guedes hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status); 10393fd24153SAndre Guedes 10403fd24153SAndre Guedes if (status) { 10413fd24153SAndre Guedes hci_dev_lock(hdev); 10423fd24153SAndre Guedes mgmt_start_discovery_failed(hdev, status); 10433fd24153SAndre Guedes hci_dev_unlock(hdev); 10443fd24153SAndre Guedes return; 10453fd24153SAndre Guedes } 104607f7fa5dSAndre Guedes } 104707f7fa5dSAndre Guedes 1048eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, 1049eb9d91f5SAndre Guedes struct sk_buff *skb) 1050eb9d91f5SAndre Guedes { 1051eb9d91f5SAndre Guedes struct hci_cp_le_set_scan_enable *cp; 1052eb9d91f5SAndre Guedes __u8 status = *((__u8 *) skb->data); 1053eb9d91f5SAndre Guedes 1054eb9d91f5SAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 1055eb9d91f5SAndre Guedes 1056eb9d91f5SAndre Guedes cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE); 1057eb9d91f5SAndre Guedes if (!cp) 1058eb9d91f5SAndre Guedes return; 1059eb9d91f5SAndre Guedes 106068a8aea4SAndrei Emeltchenko switch (cp->enable) { 106168a8aea4SAndrei Emeltchenko case LE_SCANNING_ENABLED: 10627ba8b4beSAndre Guedes hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status); 10637ba8b4beSAndre Guedes 10643fd24153SAndre Guedes if (status) { 10653fd24153SAndre Guedes hci_dev_lock(hdev); 10663fd24153SAndre Guedes mgmt_start_discovery_failed(hdev, status); 10673fd24153SAndre Guedes hci_dev_unlock(hdev); 10687ba8b4beSAndre Guedes return; 10693fd24153SAndre Guedes } 10707ba8b4beSAndre Guedes 1071d23264a8SAndre Guedes set_bit(HCI_LE_SCAN, &hdev->dev_flags); 1072d23264a8SAndre Guedes 1073db323f2fSGustavo F. Padovan cancel_delayed_work_sync(&hdev->adv_work); 1074a8f13c8cSAndre Guedes 1075a8f13c8cSAndre Guedes hci_dev_lock(hdev); 1076eb9d91f5SAndre Guedes hci_adv_entries_clear(hdev); 1077343f935bSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_FINDING); 1078a8f13c8cSAndre Guedes hci_dev_unlock(hdev); 107968a8aea4SAndrei Emeltchenko break; 108068a8aea4SAndrei Emeltchenko 108168a8aea4SAndrei Emeltchenko case LE_SCANNING_DISABLED: 10827ba8b4beSAndre Guedes if (status) 10837ba8b4beSAndre Guedes return; 10847ba8b4beSAndre Guedes 1085d23264a8SAndre Guedes clear_bit(HCI_LE_SCAN, &hdev->dev_flags); 1086d23264a8SAndre Guedes 10875e0452c0SAndre Guedes schedule_delayed_work(&hdev->adv_work, ADV_CLEAR_TIMEOUT); 10885e0452c0SAndre Guedes 10895e0452c0SAndre Guedes if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED) { 10905e0452c0SAndre Guedes mgmt_interleaved_discovery(hdev); 10915e0452c0SAndre Guedes } else { 1092c599008fSAndre Guedes hci_dev_lock(hdev); 1093c599008fSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 1094c599008fSAndre Guedes hci_dev_unlock(hdev); 10955e0452c0SAndre Guedes } 1096c599008fSAndre Guedes 109768a8aea4SAndrei Emeltchenko break; 109868a8aea4SAndrei Emeltchenko 109968a8aea4SAndrei Emeltchenko default: 110068a8aea4SAndrei Emeltchenko BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable); 110168a8aea4SAndrei Emeltchenko break; 110235815085SAndre Guedes } 1103eb9d91f5SAndre Guedes } 1104eb9d91f5SAndre Guedes 1105a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb) 1106a7a595f6SVinicius Costa Gomes { 1107a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_reply *rp = (void *) skb->data; 1108a7a595f6SVinicius Costa Gomes 1109a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, rp->status); 1110a7a595f6SVinicius Costa Gomes 1111a7a595f6SVinicius Costa Gomes if (rp->status) 1112a7a595f6SVinicius Costa Gomes return; 1113a7a595f6SVinicius Costa Gomes 1114a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status); 1115a7a595f6SVinicius Costa Gomes } 1116a7a595f6SVinicius Costa Gomes 1117a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 1118a7a595f6SVinicius Costa Gomes { 1119a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data; 1120a7a595f6SVinicius Costa Gomes 1121a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, rp->status); 1122a7a595f6SVinicius Costa Gomes 1123a7a595f6SVinicius Costa Gomes if (rp->status) 1124a7a595f6SVinicius Costa Gomes return; 1125a7a595f6SVinicius Costa Gomes 1126a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status); 1127a7a595f6SVinicius Costa Gomes } 1128a7a595f6SVinicius Costa Gomes 1129f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev, 1130f9b49306SAndre Guedes struct sk_buff *skb) 1131f9b49306SAndre Guedes { 1132f9b49306SAndre Guedes struct hci_cp_read_local_ext_features cp; 1133f9b49306SAndre Guedes __u8 status = *((__u8 *) skb->data); 1134f9b49306SAndre Guedes 1135f9b49306SAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 1136f9b49306SAndre Guedes 1137f9b49306SAndre Guedes if (status) 1138f9b49306SAndre Guedes return; 1139f9b49306SAndre Guedes 1140f9b49306SAndre Guedes cp.page = 0x01; 1141f9b49306SAndre Guedes hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp); 1142f9b49306SAndre Guedes } 1143f9b49306SAndre Guedes 1144a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 1145a9de9248SMarcel Holtmann { 1146a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1147a9de9248SMarcel Holtmann 1148a9de9248SMarcel Holtmann if (status) { 114923bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 1150a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 115156e5cb86SJohan Hedberg hci_dev_lock(hdev); 1152a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 11537a135109SAndre Guedes mgmt_start_discovery_failed(hdev, status); 115456e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1155314b2381SJohan Hedberg return; 1156314b2381SJohan Hedberg } 1157314b2381SJohan Hedberg 115889352e7dSAndre Guedes set_bit(HCI_INQUIRY, &hdev->flags); 115989352e7dSAndre Guedes 116056e5cb86SJohan Hedberg hci_dev_lock(hdev); 1161343f935bSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_FINDING); 116256e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1163a9de9248SMarcel Holtmann } 1164a9de9248SMarcel Holtmann 11651da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 11661da177e4SLinus Torvalds { 1167a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 11681da177e4SLinus Torvalds struct hci_conn *conn; 11691da177e4SLinus Torvalds 1170a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1171a9de9248SMarcel Holtmann 1172a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 11731da177e4SLinus Torvalds if (!cp) 11741da177e4SLinus Torvalds return; 11751da177e4SLinus Torvalds 11761da177e4SLinus Torvalds hci_dev_lock(hdev); 11771da177e4SLinus Torvalds 11781da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 11791da177e4SLinus Torvalds 1180a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn); 11811da177e4SLinus Torvalds 11821da177e4SLinus Torvalds if (status) { 11831da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 11844c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 11851da177e4SLinus Torvalds conn->state = BT_CLOSED; 11861da177e4SLinus Torvalds hci_proto_connect_cfm(conn, status); 11871da177e4SLinus Torvalds hci_conn_del(conn); 11884c67bc74SMarcel Holtmann } else 11894c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 11901da177e4SLinus Torvalds } 11911da177e4SLinus Torvalds } else { 11921da177e4SLinus Torvalds if (!conn) { 11931da177e4SLinus Torvalds conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); 11941da177e4SLinus Torvalds if (conn) { 1195a0c808b3SJohan Hedberg conn->out = true; 11961da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 11971da177e4SLinus Torvalds } else 1198893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 11991da177e4SLinus Torvalds } 12001da177e4SLinus Torvalds } 12011da177e4SLinus Torvalds 12021da177e4SLinus Torvalds hci_dev_unlock(hdev); 12031da177e4SLinus Torvalds } 12041da177e4SLinus Torvalds 1205a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 12061da177e4SLinus Torvalds { 1207a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 12081da177e4SLinus Torvalds struct hci_conn *acl, *sco; 12091da177e4SLinus Torvalds __u16 handle; 12101da177e4SLinus Torvalds 1211b6a0dc82SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1212b6a0dc82SMarcel Holtmann 1213a9de9248SMarcel Holtmann if (!status) 1214a9de9248SMarcel Holtmann return; 1215a9de9248SMarcel Holtmann 1216a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 12171da177e4SLinus Torvalds if (!cp) 1218a9de9248SMarcel Holtmann return; 12191da177e4SLinus Torvalds 12201da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 12211da177e4SLinus Torvalds 1222a9de9248SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 12231da177e4SLinus Torvalds 12241da177e4SLinus Torvalds hci_dev_lock(hdev); 12251da177e4SLinus Torvalds 12261da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 12275a08ecceSAndrei Emeltchenko if (acl) { 12285a08ecceSAndrei Emeltchenko sco = acl->link; 12295a08ecceSAndrei Emeltchenko if (sco) { 12301da177e4SLinus Torvalds sco->state = BT_CLOSED; 12311da177e4SLinus Torvalds 12321da177e4SLinus Torvalds hci_proto_connect_cfm(sco, status); 12331da177e4SLinus Torvalds hci_conn_del(sco); 12341da177e4SLinus Torvalds } 12355a08ecceSAndrei Emeltchenko } 12361da177e4SLinus Torvalds 12371da177e4SLinus Torvalds hci_dev_unlock(hdev); 12381da177e4SLinus Torvalds } 12391da177e4SLinus Torvalds 1240f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 1241f8558555SMarcel Holtmann { 1242f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 1243f8558555SMarcel Holtmann struct hci_conn *conn; 1244f8558555SMarcel Holtmann 1245f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1246f8558555SMarcel Holtmann 1247f8558555SMarcel Holtmann if (!status) 1248f8558555SMarcel Holtmann return; 1249f8558555SMarcel Holtmann 1250f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 1251f8558555SMarcel Holtmann if (!cp) 1252f8558555SMarcel Holtmann return; 1253f8558555SMarcel Holtmann 1254f8558555SMarcel Holtmann hci_dev_lock(hdev); 1255f8558555SMarcel Holtmann 1256f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1257f8558555SMarcel Holtmann if (conn) { 1258f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1259f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1260f8558555SMarcel Holtmann hci_conn_put(conn); 1261f8558555SMarcel Holtmann } 1262f8558555SMarcel Holtmann } 1263f8558555SMarcel Holtmann 1264f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1265f8558555SMarcel Holtmann } 1266f8558555SMarcel Holtmann 1267f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 1268f8558555SMarcel Holtmann { 1269f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 1270f8558555SMarcel Holtmann struct hci_conn *conn; 1271f8558555SMarcel Holtmann 1272f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1273f8558555SMarcel Holtmann 1274f8558555SMarcel Holtmann if (!status) 1275f8558555SMarcel Holtmann return; 1276f8558555SMarcel Holtmann 1277f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 1278f8558555SMarcel Holtmann if (!cp) 1279f8558555SMarcel Holtmann return; 1280f8558555SMarcel Holtmann 1281f8558555SMarcel Holtmann hci_dev_lock(hdev); 1282f8558555SMarcel Holtmann 1283f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1284f8558555SMarcel Holtmann if (conn) { 1285f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1286f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1287f8558555SMarcel Holtmann hci_conn_put(conn); 1288f8558555SMarcel Holtmann } 1289f8558555SMarcel Holtmann } 1290f8558555SMarcel Holtmann 1291f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1292f8558555SMarcel Holtmann } 1293f8558555SMarcel Holtmann 1294127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev, 1295392599b9SJohan Hedberg struct hci_conn *conn) 1296392599b9SJohan Hedberg { 1297392599b9SJohan Hedberg if (conn->state != BT_CONFIG || !conn->out) 1298392599b9SJohan Hedberg return 0; 1299392599b9SJohan Hedberg 1300765c2a96SJohan Hedberg if (conn->pending_sec_level == BT_SECURITY_SDP) 1301392599b9SJohan Hedberg return 0; 1302392599b9SJohan Hedberg 1303392599b9SJohan Hedberg /* Only request authentication for SSP connections or non-SSP 1304e9bf2bf0SVinicius Costa Gomes * devices with sec_level HIGH or if MITM protection is requested */ 1305aa64a8b5SJohan Hedberg if (!hci_conn_ssp_enabled(conn) && 1306e9bf2bf0SVinicius Costa Gomes conn->pending_sec_level != BT_SECURITY_HIGH && 1307e9bf2bf0SVinicius Costa Gomes !(conn->auth_type & 0x01)) 1308392599b9SJohan Hedberg return 0; 1309392599b9SJohan Hedberg 1310392599b9SJohan Hedberg return 1; 1311392599b9SJohan Hedberg } 1312392599b9SJohan Hedberg 131330dc78e1SJohan Hedberg static inline int hci_resolve_name(struct hci_dev *hdev, struct inquiry_entry *e) 131430dc78e1SJohan Hedberg { 131530dc78e1SJohan Hedberg struct hci_cp_remote_name_req cp; 131630dc78e1SJohan Hedberg 131730dc78e1SJohan Hedberg memset(&cp, 0, sizeof(cp)); 131830dc78e1SJohan Hedberg 131930dc78e1SJohan Hedberg bacpy(&cp.bdaddr, &e->data.bdaddr); 132030dc78e1SJohan Hedberg cp.pscan_rep_mode = e->data.pscan_rep_mode; 132130dc78e1SJohan Hedberg cp.pscan_mode = e->data.pscan_mode; 132230dc78e1SJohan Hedberg cp.clock_offset = e->data.clock_offset; 132330dc78e1SJohan Hedberg 132430dc78e1SJohan Hedberg return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 132530dc78e1SJohan Hedberg } 132630dc78e1SJohan Hedberg 1327b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev) 132830dc78e1SJohan Hedberg { 132930dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 133030dc78e1SJohan Hedberg struct inquiry_entry *e; 133130dc78e1SJohan Hedberg 1332b644ba33SJohan Hedberg if (list_empty(&discov->resolve)) 1333b644ba33SJohan Hedberg return false; 1334b644ba33SJohan Hedberg 1335b644ba33SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 1336b644ba33SJohan Hedberg if (hci_resolve_name(hdev, e) == 0) { 1337b644ba33SJohan Hedberg e->name_state = NAME_PENDING; 1338b644ba33SJohan Hedberg return true; 1339b644ba33SJohan Hedberg } 1340b644ba33SJohan Hedberg 1341b644ba33SJohan Hedberg return false; 1342b644ba33SJohan Hedberg } 1343b644ba33SJohan Hedberg 1344b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn, 1345b644ba33SJohan Hedberg bdaddr_t *bdaddr, u8 *name, u8 name_len) 1346b644ba33SJohan Hedberg { 1347b644ba33SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 1348b644ba33SJohan Hedberg struct inquiry_entry *e; 1349b644ba33SJohan Hedberg 1350b644ba33SJohan Hedberg if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 1351b644ba33SJohan Hedberg mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 1352b644ba33SJohan Hedberg name, name_len, conn->dev_class); 1353b644ba33SJohan Hedberg 1354b644ba33SJohan Hedberg if (discov->state == DISCOVERY_STOPPED) 1355b644ba33SJohan Hedberg return; 1356b644ba33SJohan Hedberg 135730dc78e1SJohan Hedberg if (discov->state == DISCOVERY_STOPPING) 135830dc78e1SJohan Hedberg goto discov_complete; 135930dc78e1SJohan Hedberg 136030dc78e1SJohan Hedberg if (discov->state != DISCOVERY_RESOLVING) 136130dc78e1SJohan Hedberg return; 136230dc78e1SJohan Hedberg 136330dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING); 136430dc78e1SJohan Hedberg if (e) { 136530dc78e1SJohan Hedberg e->name_state = NAME_KNOWN; 136630dc78e1SJohan Hedberg list_del(&e->list); 1367b644ba33SJohan Hedberg if (name) 1368b644ba33SJohan Hedberg mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, 1369b644ba33SJohan Hedberg e->data.rssi, name, name_len); 137030dc78e1SJohan Hedberg } 137130dc78e1SJohan Hedberg 1372b644ba33SJohan Hedberg if (hci_resolve_next_name(hdev)) 137330dc78e1SJohan Hedberg return; 137430dc78e1SJohan Hedberg 137530dc78e1SJohan Hedberg discov_complete: 137630dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 137730dc78e1SJohan Hedberg } 137830dc78e1SJohan Hedberg 1379a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 13801da177e4SLinus Torvalds { 1381127178d2SJohan Hedberg struct hci_cp_remote_name_req *cp; 1382127178d2SJohan Hedberg struct hci_conn *conn; 1383127178d2SJohan Hedberg 1384a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1385127178d2SJohan Hedberg 1386127178d2SJohan Hedberg /* If successful wait for the name req complete event before 1387127178d2SJohan Hedberg * checking for the need to do authentication */ 1388127178d2SJohan Hedberg if (!status) 1389127178d2SJohan Hedberg return; 1390127178d2SJohan Hedberg 1391127178d2SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); 1392127178d2SJohan Hedberg if (!cp) 1393127178d2SJohan Hedberg return; 1394127178d2SJohan Hedberg 1395127178d2SJohan Hedberg hci_dev_lock(hdev); 1396127178d2SJohan Hedberg 1397127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 1398b644ba33SJohan Hedberg 1399b644ba33SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1400b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0); 1401b644ba33SJohan Hedberg 140279c6c70cSJohan Hedberg if (!conn) 140379c6c70cSJohan Hedberg goto unlock; 140479c6c70cSJohan Hedberg 140579c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 140679c6c70cSJohan Hedberg goto unlock; 140779c6c70cSJohan Hedberg 140851a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 1409127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1410127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1411127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1412127178d2SJohan Hedberg } 1413127178d2SJohan Hedberg 141479c6c70cSJohan Hedberg unlock: 1415127178d2SJohan Hedberg hci_dev_unlock(hdev); 1416a9de9248SMarcel Holtmann } 14171da177e4SLinus Torvalds 1418769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 1419769be974SMarcel Holtmann { 1420769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 1421769be974SMarcel Holtmann struct hci_conn *conn; 1422769be974SMarcel Holtmann 1423769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1424769be974SMarcel Holtmann 1425769be974SMarcel Holtmann if (!status) 1426769be974SMarcel Holtmann return; 1427769be974SMarcel Holtmann 1428769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 1429769be974SMarcel Holtmann if (!cp) 1430769be974SMarcel Holtmann return; 1431769be974SMarcel Holtmann 1432769be974SMarcel Holtmann hci_dev_lock(hdev); 1433769be974SMarcel Holtmann 1434769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1435769be974SMarcel Holtmann if (conn) { 1436769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1437769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1438769be974SMarcel Holtmann hci_conn_put(conn); 1439769be974SMarcel Holtmann } 1440769be974SMarcel Holtmann } 1441769be974SMarcel Holtmann 1442769be974SMarcel Holtmann hci_dev_unlock(hdev); 1443769be974SMarcel Holtmann } 1444769be974SMarcel Holtmann 1445769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 1446769be974SMarcel Holtmann { 1447769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features *cp; 1448769be974SMarcel Holtmann struct hci_conn *conn; 1449769be974SMarcel Holtmann 1450769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1451769be974SMarcel Holtmann 1452769be974SMarcel Holtmann if (!status) 1453769be974SMarcel Holtmann return; 1454769be974SMarcel Holtmann 1455769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 1456769be974SMarcel Holtmann if (!cp) 1457769be974SMarcel Holtmann return; 1458769be974SMarcel Holtmann 1459769be974SMarcel Holtmann hci_dev_lock(hdev); 1460769be974SMarcel Holtmann 1461769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1462769be974SMarcel Holtmann if (conn) { 1463769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1464769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1465769be974SMarcel Holtmann hci_conn_put(conn); 1466769be974SMarcel Holtmann } 1467769be974SMarcel Holtmann } 1468769be974SMarcel Holtmann 1469769be974SMarcel Holtmann hci_dev_unlock(hdev); 1470769be974SMarcel Holtmann } 1471769be974SMarcel Holtmann 1472a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 1473a9de9248SMarcel Holtmann { 1474b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 1475b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 1476b6a0dc82SMarcel Holtmann __u16 handle; 1477b6a0dc82SMarcel Holtmann 1478a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1479b6a0dc82SMarcel Holtmann 1480b6a0dc82SMarcel Holtmann if (!status) 1481b6a0dc82SMarcel Holtmann return; 1482b6a0dc82SMarcel Holtmann 1483b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 1484b6a0dc82SMarcel Holtmann if (!cp) 1485b6a0dc82SMarcel Holtmann return; 1486b6a0dc82SMarcel Holtmann 1487b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 1488b6a0dc82SMarcel Holtmann 1489b6a0dc82SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 1490b6a0dc82SMarcel Holtmann 1491b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 1492b6a0dc82SMarcel Holtmann 1493b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 14945a08ecceSAndrei Emeltchenko if (acl) { 14955a08ecceSAndrei Emeltchenko sco = acl->link; 14965a08ecceSAndrei Emeltchenko if (sco) { 1497b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 1498b6a0dc82SMarcel Holtmann 1499b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(sco, status); 1500b6a0dc82SMarcel Holtmann hci_conn_del(sco); 1501b6a0dc82SMarcel Holtmann } 15025a08ecceSAndrei Emeltchenko } 1503b6a0dc82SMarcel Holtmann 1504b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 1505a9de9248SMarcel Holtmann } 1506a9de9248SMarcel Holtmann 1507a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 1508a9de9248SMarcel Holtmann { 1509a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 151004837f64SMarcel Holtmann struct hci_conn *conn; 151104837f64SMarcel Holtmann 1512a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1513a9de9248SMarcel Holtmann 1514a9de9248SMarcel Holtmann if (!status) 1515a9de9248SMarcel Holtmann return; 1516a9de9248SMarcel Holtmann 1517a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 151804837f64SMarcel Holtmann if (!cp) 1519a9de9248SMarcel Holtmann return; 152004837f64SMarcel Holtmann 152104837f64SMarcel Holtmann hci_dev_lock(hdev); 152204837f64SMarcel Holtmann 152304837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1524e73439d8SMarcel Holtmann if (conn) { 152551a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 152604837f64SMarcel Holtmann 152751a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1528e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1529e73439d8SMarcel Holtmann } 1530e73439d8SMarcel Holtmann 153104837f64SMarcel Holtmann hci_dev_unlock(hdev); 153204837f64SMarcel Holtmann } 153304837f64SMarcel Holtmann 1534a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 1535a9de9248SMarcel Holtmann { 1536a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 153704837f64SMarcel Holtmann struct hci_conn *conn; 153804837f64SMarcel Holtmann 1539a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1540a9de9248SMarcel Holtmann 1541a9de9248SMarcel Holtmann if (!status) 1542a9de9248SMarcel Holtmann return; 1543a9de9248SMarcel Holtmann 1544a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 154504837f64SMarcel Holtmann if (!cp) 1546a9de9248SMarcel Holtmann return; 154704837f64SMarcel Holtmann 154804837f64SMarcel Holtmann hci_dev_lock(hdev); 154904837f64SMarcel Holtmann 155004837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1551e73439d8SMarcel Holtmann if (conn) { 155251a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 155304837f64SMarcel Holtmann 155451a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1555e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1556e73439d8SMarcel Holtmann } 1557e73439d8SMarcel Holtmann 155804837f64SMarcel Holtmann hci_dev_unlock(hdev); 155904837f64SMarcel Holtmann } 156004837f64SMarcel Holtmann 156188c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) 156288c3df13SJohan Hedberg { 156388c3df13SJohan Hedberg struct hci_cp_disconnect *cp; 156488c3df13SJohan Hedberg struct hci_conn *conn; 156588c3df13SJohan Hedberg 156688c3df13SJohan Hedberg if (!status) 156788c3df13SJohan Hedberg return; 156888c3df13SJohan Hedberg 156988c3df13SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT); 157088c3df13SJohan Hedberg if (!cp) 157188c3df13SJohan Hedberg return; 157288c3df13SJohan Hedberg 157388c3df13SJohan Hedberg hci_dev_lock(hdev); 157488c3df13SJohan Hedberg 157588c3df13SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 157688c3df13SJohan Hedberg if (conn) 157788c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 157888c3df13SJohan Hedberg conn->dst_type, status); 157988c3df13SJohan Hedberg 158088c3df13SJohan Hedberg hci_dev_unlock(hdev); 158188c3df13SJohan Hedberg } 158288c3df13SJohan Hedberg 1583fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) 1584fcd89c09SVille Tervo { 1585fcd89c09SVille Tervo struct hci_cp_le_create_conn *cp; 1586fcd89c09SVille Tervo struct hci_conn *conn; 1587fcd89c09SVille Tervo 1588fcd89c09SVille Tervo BT_DBG("%s status 0x%x", hdev->name, status); 1589fcd89c09SVille Tervo 1590fcd89c09SVille Tervo cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN); 1591fcd89c09SVille Tervo if (!cp) 1592fcd89c09SVille Tervo return; 1593fcd89c09SVille Tervo 1594fcd89c09SVille Tervo hci_dev_lock(hdev); 1595fcd89c09SVille Tervo 1596fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr); 1597fcd89c09SVille Tervo 1598fcd89c09SVille Tervo BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr), 1599fcd89c09SVille Tervo conn); 1600fcd89c09SVille Tervo 1601fcd89c09SVille Tervo if (status) { 1602fcd89c09SVille Tervo if (conn && conn->state == BT_CONNECT) { 1603fcd89c09SVille Tervo conn->state = BT_CLOSED; 1604fcd89c09SVille Tervo hci_proto_connect_cfm(conn, status); 1605fcd89c09SVille Tervo hci_conn_del(conn); 1606fcd89c09SVille Tervo } 1607fcd89c09SVille Tervo } else { 1608fcd89c09SVille Tervo if (!conn) { 1609fcd89c09SVille Tervo conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr); 161029b7988aSAndre Guedes if (conn) { 161129b7988aSAndre Guedes conn->dst_type = cp->peer_addr_type; 1612a0c808b3SJohan Hedberg conn->out = true; 161329b7988aSAndre Guedes } else { 1614fcd89c09SVille Tervo BT_ERR("No memory for new connection"); 1615fcd89c09SVille Tervo } 1616fcd89c09SVille Tervo } 161729b7988aSAndre Guedes } 1618fcd89c09SVille Tervo 1619fcd89c09SVille Tervo hci_dev_unlock(hdev); 1620fcd89c09SVille Tervo } 1621fcd89c09SVille Tervo 1622a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) 1623a7a595f6SVinicius Costa Gomes { 1624a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, status); 1625a7a595f6SVinicius Costa Gomes } 1626a7a595f6SVinicius Costa Gomes 16271da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 16281da177e4SLinus Torvalds { 16291da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 163030dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 163130dc78e1SJohan Hedberg struct inquiry_entry *e; 16321da177e4SLinus Torvalds 16331da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, status); 16341da177e4SLinus Torvalds 163523bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 16366bd57416SMarcel Holtmann 1637a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 163889352e7dSAndre Guedes 163989352e7dSAndre Guedes if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) 164089352e7dSAndre Guedes return; 164189352e7dSAndre Guedes 1642a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 164330dc78e1SJohan Hedberg return; 164430dc78e1SJohan Hedberg 164556e5cb86SJohan Hedberg hci_dev_lock(hdev); 164630dc78e1SJohan Hedberg 1647343f935bSAndre Guedes if (discov->state != DISCOVERY_FINDING) 164830dc78e1SJohan Hedberg goto unlock; 164930dc78e1SJohan Hedberg 165030dc78e1SJohan Hedberg if (list_empty(&discov->resolve)) { 1651ff9ef578SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 165230dc78e1SJohan Hedberg goto unlock; 165330dc78e1SJohan Hedberg } 165430dc78e1SJohan Hedberg 165530dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 165630dc78e1SJohan Hedberg if (e && hci_resolve_name(hdev, e) == 0) { 165730dc78e1SJohan Hedberg e->name_state = NAME_PENDING; 165830dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_RESOLVING); 165930dc78e1SJohan Hedberg } else { 166030dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 166130dc78e1SJohan Hedberg } 166230dc78e1SJohan Hedberg 166330dc78e1SJohan Hedberg unlock: 166456e5cb86SJohan Hedberg hci_dev_unlock(hdev); 16651da177e4SLinus Torvalds } 16661da177e4SLinus Torvalds 16671da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 16681da177e4SLinus Torvalds { 166945bb4bf0SMarcel Holtmann struct inquiry_data data; 1670a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 16711da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 16721da177e4SLinus Torvalds 16731da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 16741da177e4SLinus Torvalds 167545bb4bf0SMarcel Holtmann if (!num_rsp) 167645bb4bf0SMarcel Holtmann return; 167745bb4bf0SMarcel Holtmann 16781da177e4SLinus Torvalds hci_dev_lock(hdev); 167945bb4bf0SMarcel Holtmann 1680e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 16813175405bSJohan Hedberg bool name_known; 16823175405bSJohan Hedberg 16831da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 16841da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 16851da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 16861da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 16871da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 16881da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 16891da177e4SLinus Torvalds data.rssi = 0x00; 169041a96212SMarcel Holtmann data.ssp_mode = 0x00; 16913175405bSJohan Hedberg 16923175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, false); 169348264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 16947d262f86SAndre Guedes info->dev_class, 0, !name_known, 16957d262f86SAndre Guedes NULL, 0); 16961da177e4SLinus Torvalds } 169745bb4bf0SMarcel Holtmann 16981da177e4SLinus Torvalds hci_dev_unlock(hdev); 16991da177e4SLinus Torvalds } 17001da177e4SLinus Torvalds 1701a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 17021da177e4SLinus Torvalds { 1703a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 1704a9de9248SMarcel Holtmann struct hci_conn *conn; 17051da177e4SLinus Torvalds 1706a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 170745bb4bf0SMarcel Holtmann 17081da177e4SLinus Torvalds hci_dev_lock(hdev); 170945bb4bf0SMarcel Holtmann 1710a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 17119499237aSMarcel Holtmann if (!conn) { 17129499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 17139499237aSMarcel Holtmann goto unlock; 17149499237aSMarcel Holtmann 17159499237aSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 1716a9de9248SMarcel Holtmann if (!conn) 1717a9de9248SMarcel Holtmann goto unlock; 171845bb4bf0SMarcel Holtmann 17199499237aSMarcel Holtmann conn->type = SCO_LINK; 17209499237aSMarcel Holtmann } 17219499237aSMarcel Holtmann 1722a9de9248SMarcel Holtmann if (!ev->status) { 1723a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 1724769be974SMarcel Holtmann 1725769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 1726769be974SMarcel Holtmann conn->state = BT_CONFIG; 1727769be974SMarcel Holtmann hci_conn_hold(conn); 1728052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1729769be974SMarcel Holtmann } else 1730a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 1731a9de9248SMarcel Holtmann 17329eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 17337d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 17347d0db0a3SMarcel Holtmann 1735a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 1736a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1737a9de9248SMarcel Holtmann 1738a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 1739a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1740a9de9248SMarcel Holtmann 1741a9de9248SMarcel Holtmann /* Get remote features */ 1742a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 1743a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 1744a9de9248SMarcel Holtmann cp.handle = ev->handle; 1745769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 1746769be974SMarcel Holtmann sizeof(cp), &cp); 174745bb4bf0SMarcel Holtmann } 1748a9de9248SMarcel Holtmann 1749a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 1750d095c1ebSAndrei Emeltchenko if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) { 1751a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 1752a9de9248SMarcel Holtmann cp.handle = ev->handle; 1753a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1754a8746417SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, 1755a8746417SMarcel Holtmann sizeof(cp), &cp); 1756a9de9248SMarcel Holtmann } 175717d5c04cSJohan Hedberg } else { 1758a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 175917d5c04cSJohan Hedberg if (conn->type == ACL_LINK) 1760744cf19eSJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 176148264f06SJohan Hedberg conn->dst_type, ev->status); 176217d5c04cSJohan Hedberg } 176345bb4bf0SMarcel Holtmann 1764e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 1765e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 176645bb4bf0SMarcel Holtmann 1767769be974SMarcel Holtmann if (ev->status) { 1768a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1769a9de9248SMarcel Holtmann hci_conn_del(conn); 1770c89b6e6bSMarcel Holtmann } else if (ev->link_type != ACL_LINK) 1771c89b6e6bSMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1772a9de9248SMarcel Holtmann 1773a9de9248SMarcel Holtmann unlock: 17741da177e4SLinus Torvalds hci_dev_unlock(hdev); 1775a9de9248SMarcel Holtmann 1776a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 17771da177e4SLinus Torvalds } 17781da177e4SLinus Torvalds 17791da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 17801da177e4SLinus Torvalds { 1781a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 17821da177e4SLinus Torvalds int mask = hdev->link_mode; 17831da177e4SLinus Torvalds 1784a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s type 0x%x", hdev->name, 17851da177e4SLinus Torvalds batostr(&ev->bdaddr), ev->link_type); 17861da177e4SLinus Torvalds 17871da177e4SLinus Torvalds mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); 17881da177e4SLinus Torvalds 1789138d22efSSzymon Janc if ((mask & HCI_LM_ACCEPT) && 1790138d22efSSzymon Janc !hci_blacklist_lookup(hdev, &ev->bdaddr)) { 17911da177e4SLinus Torvalds /* Connection accepted */ 1792c7bdd502SMarcel Holtmann struct inquiry_entry *ie; 17931da177e4SLinus Torvalds struct hci_conn *conn; 17941da177e4SLinus Torvalds 17951da177e4SLinus Torvalds hci_dev_lock(hdev); 1796b6a0dc82SMarcel Holtmann 1797cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 1798cc11b9c1SAndrei Emeltchenko if (ie) 1799c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 1800c7bdd502SMarcel Holtmann 18011da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 18021da177e4SLinus Torvalds if (!conn) { 1803cc11b9c1SAndrei Emeltchenko conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); 1804cc11b9c1SAndrei Emeltchenko if (!conn) { 1805893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 18061da177e4SLinus Torvalds hci_dev_unlock(hdev); 18071da177e4SLinus Torvalds return; 18081da177e4SLinus Torvalds } 18091da177e4SLinus Torvalds } 1810b6a0dc82SMarcel Holtmann 18111da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 18121da177e4SLinus Torvalds conn->state = BT_CONNECT; 1813b6a0dc82SMarcel Holtmann 18141da177e4SLinus Torvalds hci_dev_unlock(hdev); 18151da177e4SLinus Torvalds 1816b6a0dc82SMarcel Holtmann if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) { 1817b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 1818b6a0dc82SMarcel Holtmann 18191da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 18201da177e4SLinus Torvalds 18211da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 18221da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 18231da177e4SLinus Torvalds else 18241da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 18251da177e4SLinus Torvalds 1826b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, 1827b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1828b6a0dc82SMarcel Holtmann } else { 1829b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 1830b6a0dc82SMarcel Holtmann 1831b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 1832a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1833b6a0dc82SMarcel Holtmann 1834b6a0dc82SMarcel Holtmann cp.tx_bandwidth = cpu_to_le32(0x00001f40); 1835b6a0dc82SMarcel Holtmann cp.rx_bandwidth = cpu_to_le32(0x00001f40); 1836b6a0dc82SMarcel Holtmann cp.max_latency = cpu_to_le16(0xffff); 1837b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 1838b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 1839b6a0dc82SMarcel Holtmann 1840b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 1841b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1842b6a0dc82SMarcel Holtmann } 18431da177e4SLinus Torvalds } else { 18441da177e4SLinus Torvalds /* Connection rejected */ 18451da177e4SLinus Torvalds struct hci_cp_reject_conn_req cp; 18461da177e4SLinus Torvalds 18471da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 18489f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_REJ_BAD_ADDR; 1849a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 18501da177e4SLinus Torvalds } 18511da177e4SLinus Torvalds } 18521da177e4SLinus Torvalds 18531da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 18541da177e4SLinus Torvalds { 1855a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 185604837f64SMarcel Holtmann struct hci_conn *conn; 18571da177e4SLinus Torvalds 18581da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 18591da177e4SLinus Torvalds 18601da177e4SLinus Torvalds hci_dev_lock(hdev); 18611da177e4SLinus Torvalds 186204837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1863f7520543SJohan Hedberg if (!conn) 1864f7520543SJohan Hedberg goto unlock; 1865f7520543SJohan Hedberg 186637d9ef76SJohan Hedberg if (ev->status == 0) 18671da177e4SLinus Torvalds conn->state = BT_CLOSED; 18687d0db0a3SMarcel Holtmann 1869b644ba33SJohan Hedberg if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) && 1870b644ba33SJohan Hedberg (conn->type == ACL_LINK || conn->type == LE_LINK)) { 187137d9ef76SJohan Hedberg if (ev->status != 0) 187288c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 187388c3df13SJohan Hedberg conn->dst_type, ev->status); 187437d9ef76SJohan Hedberg else 1875afc747a6SJohan Hedberg mgmt_device_disconnected(hdev, &conn->dst, conn->type, 187648264f06SJohan Hedberg conn->dst_type); 187737d9ef76SJohan Hedberg } 1878f7520543SJohan Hedberg 187937d9ef76SJohan Hedberg if (ev->status == 0) { 18802950f21aSMarcel Holtmann hci_proto_disconn_cfm(conn, ev->reason); 18811da177e4SLinus Torvalds hci_conn_del(conn); 188237d9ef76SJohan Hedberg } 18831da177e4SLinus Torvalds 1884f7520543SJohan Hedberg unlock: 18851da177e4SLinus Torvalds hci_dev_unlock(hdev); 18861da177e4SLinus Torvalds } 18871da177e4SLinus Torvalds 1888a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1889a9de9248SMarcel Holtmann { 1890a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 1891a9de9248SMarcel Holtmann struct hci_conn *conn; 1892a9de9248SMarcel Holtmann 1893a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1894a9de9248SMarcel Holtmann 1895a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1896a9de9248SMarcel Holtmann 1897a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1898d7556e20SWaldemar Rymarkiewicz if (!conn) 1899d7556e20SWaldemar Rymarkiewicz goto unlock; 1900d7556e20SWaldemar Rymarkiewicz 1901765c2a96SJohan Hedberg if (!ev->status) { 1902aa64a8b5SJohan Hedberg if (!hci_conn_ssp_enabled(conn) && 190351a8efd7SJohan Hedberg test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) { 1904d7556e20SWaldemar Rymarkiewicz BT_INFO("re-auth of legacy device is not possible."); 190519f8def0SWaldemar Rymarkiewicz } else { 1906a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1907765c2a96SJohan Hedberg conn->sec_level = conn->pending_sec_level; 190819f8def0SWaldemar Rymarkiewicz } 19092a611692SJohan Hedberg } else { 1910bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 1911bab73cb6SJohan Hedberg ev->status); 19122a611692SJohan Hedberg } 1913a9de9248SMarcel Holtmann 191451a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 191551a8efd7SJohan Hedberg clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags); 1916a9de9248SMarcel Holtmann 1917f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1918aa64a8b5SJohan Hedberg if (!ev->status && hci_conn_ssp_enabled(conn)) { 1919f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1920f8558555SMarcel Holtmann cp.handle = ev->handle; 1921f8558555SMarcel Holtmann cp.encrypt = 0x01; 1922d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1923d7556e20SWaldemar Rymarkiewicz &cp); 1924f8558555SMarcel Holtmann } else { 1925f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1926f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1927f8558555SMarcel Holtmann hci_conn_put(conn); 1928f8558555SMarcel Holtmann } 1929052b30b0SMarcel Holtmann } else { 1930a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 1931a9de9248SMarcel Holtmann 1932052b30b0SMarcel Holtmann hci_conn_hold(conn); 1933052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1934052b30b0SMarcel Holtmann hci_conn_put(conn); 1935052b30b0SMarcel Holtmann } 1936052b30b0SMarcel Holtmann 193751a8efd7SJohan Hedberg if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) { 1938a9de9248SMarcel Holtmann if (!ev->status) { 1939a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1940f8558555SMarcel Holtmann cp.handle = ev->handle; 1941f8558555SMarcel Holtmann cp.encrypt = 0x01; 1942d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1943d7556e20SWaldemar Rymarkiewicz &cp); 1944a9de9248SMarcel Holtmann } else { 194551a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 1946a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 1947a9de9248SMarcel Holtmann } 1948a9de9248SMarcel Holtmann } 1949a9de9248SMarcel Holtmann 1950d7556e20SWaldemar Rymarkiewicz unlock: 1951a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1952a9de9248SMarcel Holtmann } 1953a9de9248SMarcel Holtmann 1954a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 1955a9de9248SMarcel Holtmann { 1956127178d2SJohan Hedberg struct hci_ev_remote_name *ev = (void *) skb->data; 1957127178d2SJohan Hedberg struct hci_conn *conn; 1958127178d2SJohan Hedberg 1959a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1960a9de9248SMarcel Holtmann 1961a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 1962127178d2SJohan Hedberg 1963127178d2SJohan Hedberg hci_dev_lock(hdev); 1964127178d2SJohan Hedberg 1965127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 1966b644ba33SJohan Hedberg 1967b644ba33SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 1968b644ba33SJohan Hedberg goto check_auth; 1969b644ba33SJohan Hedberg 1970b644ba33SJohan Hedberg if (ev->status == 0) 1971b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name, 1972b644ba33SJohan Hedberg strnlen(ev->name, HCI_MAX_NAME_LENGTH)); 1973b644ba33SJohan Hedberg else 1974b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0); 1975b644ba33SJohan Hedberg 1976b644ba33SJohan Hedberg check_auth: 197779c6c70cSJohan Hedberg if (!conn) 197879c6c70cSJohan Hedberg goto unlock; 197979c6c70cSJohan Hedberg 198079c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 198179c6c70cSJohan Hedberg goto unlock; 198279c6c70cSJohan Hedberg 198351a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 1984127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1985127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1986127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1987127178d2SJohan Hedberg } 1988127178d2SJohan Hedberg 198979c6c70cSJohan Hedberg unlock: 1990127178d2SJohan Hedberg hci_dev_unlock(hdev); 1991a9de9248SMarcel Holtmann } 1992a9de9248SMarcel Holtmann 1993a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 1994a9de9248SMarcel Holtmann { 1995a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 1996a9de9248SMarcel Holtmann struct hci_conn *conn; 1997a9de9248SMarcel Holtmann 1998a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1999a9de9248SMarcel Holtmann 2000a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2001a9de9248SMarcel Holtmann 2002a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2003a9de9248SMarcel Holtmann if (conn) { 2004a9de9248SMarcel Holtmann if (!ev->status) { 2005ae293196SMarcel Holtmann if (ev->encrypt) { 2006ae293196SMarcel Holtmann /* Encryption implies authentication */ 2007ae293196SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 2008a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 2009da85e5e5SVinicius Costa Gomes conn->sec_level = conn->pending_sec_level; 2010ae293196SMarcel Holtmann } else 2011a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_ENCRYPT; 2012a9de9248SMarcel Holtmann } 2013a9de9248SMarcel Holtmann 201451a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 2015a9de9248SMarcel Holtmann 2016f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 2017f8558555SMarcel Holtmann if (!ev->status) 2018f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 2019f8558555SMarcel Holtmann 2020f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2021f8558555SMarcel Holtmann hci_conn_put(conn); 2022f8558555SMarcel Holtmann } else 2023a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 2024a9de9248SMarcel Holtmann } 2025a9de9248SMarcel Holtmann 2026a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2027a9de9248SMarcel Holtmann } 2028a9de9248SMarcel Holtmann 2029a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2030a9de9248SMarcel Holtmann { 2031a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 2032a9de9248SMarcel Holtmann struct hci_conn *conn; 2033a9de9248SMarcel Holtmann 2034a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2035a9de9248SMarcel Holtmann 2036a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2037a9de9248SMarcel Holtmann 2038a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2039a9de9248SMarcel Holtmann if (conn) { 2040a9de9248SMarcel Holtmann if (!ev->status) 2041a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_SECURE; 2042a9de9248SMarcel Holtmann 204351a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 2044a9de9248SMarcel Holtmann 2045a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 2046a9de9248SMarcel Holtmann } 2047a9de9248SMarcel Holtmann 2048a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2049a9de9248SMarcel Holtmann } 2050a9de9248SMarcel Holtmann 2051a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 2052a9de9248SMarcel Holtmann { 2053a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 2054a9de9248SMarcel Holtmann struct hci_conn *conn; 2055a9de9248SMarcel Holtmann 2056a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2057a9de9248SMarcel Holtmann 2058a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2059a9de9248SMarcel Holtmann 2060a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2061ccd556feSJohan Hedberg if (!conn) 2062ccd556feSJohan Hedberg goto unlock; 2063ccd556feSJohan Hedberg 2064769be974SMarcel Holtmann if (!ev->status) 2065a9de9248SMarcel Holtmann memcpy(conn->features, ev->features, 8); 2066a9de9248SMarcel Holtmann 2067ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2068ccd556feSJohan Hedberg goto unlock; 2069ccd556feSJohan Hedberg 2070ccd556feSJohan Hedberg if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { 2071769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 2072769be974SMarcel Holtmann cp.handle = ev->handle; 2073769be974SMarcel Holtmann cp.page = 0x01; 2074ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 2075769be974SMarcel Holtmann sizeof(cp), &cp); 2076392599b9SJohan Hedberg goto unlock; 2077392599b9SJohan Hedberg } 2078392599b9SJohan Hedberg 2079127178d2SJohan Hedberg if (!ev->status) { 2080127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2081127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2082127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2083127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2084127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2085b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 2086b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 2087b644ba33SJohan Hedberg conn->dst_type, NULL, 0, 2088b644ba33SJohan Hedberg conn->dev_class); 2089392599b9SJohan Hedberg 2090127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2091769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2092769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2093769be974SMarcel Holtmann hci_conn_put(conn); 2094769be974SMarcel Holtmann } 2095769be974SMarcel Holtmann 2096ccd556feSJohan Hedberg unlock: 2097a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2098a9de9248SMarcel Holtmann } 2099a9de9248SMarcel Holtmann 2100a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) 2101a9de9248SMarcel Holtmann { 2102a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2103a9de9248SMarcel Holtmann } 2104a9de9248SMarcel Holtmann 2105a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2106a9de9248SMarcel Holtmann { 2107a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2108a9de9248SMarcel Holtmann } 2109a9de9248SMarcel Holtmann 2110a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2111a9de9248SMarcel Holtmann { 2112a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 2113a9de9248SMarcel Holtmann __u16 opcode; 2114a9de9248SMarcel Holtmann 2115a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2116a9de9248SMarcel Holtmann 2117a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2118a9de9248SMarcel Holtmann 2119a9de9248SMarcel Holtmann switch (opcode) { 2120a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 2121a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 2122a9de9248SMarcel Holtmann break; 2123a9de9248SMarcel Holtmann 2124a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 2125a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 2126a9de9248SMarcel Holtmann break; 2127a9de9248SMarcel Holtmann 2128a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 2129a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 2130a9de9248SMarcel Holtmann break; 2131a9de9248SMarcel Holtmann 2132a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 2133a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 2134a9de9248SMarcel Holtmann break; 2135a9de9248SMarcel Holtmann 2136e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 2137e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 2138e4e8e37cSMarcel Holtmann break; 2139e4e8e37cSMarcel Holtmann 2140a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 2141a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 2142a9de9248SMarcel Holtmann break; 2143a9de9248SMarcel Holtmann 2144e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 2145e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 2146e4e8e37cSMarcel Holtmann break; 2147e4e8e37cSMarcel Holtmann 2148e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 2149e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 2150e4e8e37cSMarcel Holtmann break; 2151e4e8e37cSMarcel Holtmann 2152a9de9248SMarcel Holtmann case HCI_OP_RESET: 2153a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 2154a9de9248SMarcel Holtmann break; 2155a9de9248SMarcel Holtmann 2156a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 2157a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 2158a9de9248SMarcel Holtmann break; 2159a9de9248SMarcel Holtmann 2160a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 2161a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 2162a9de9248SMarcel Holtmann break; 2163a9de9248SMarcel Holtmann 2164a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 2165a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 2166a9de9248SMarcel Holtmann break; 2167a9de9248SMarcel Holtmann 2168a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 2169a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 2170a9de9248SMarcel Holtmann break; 2171a9de9248SMarcel Holtmann 2172a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 2173a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 2174a9de9248SMarcel Holtmann break; 2175a9de9248SMarcel Holtmann 2176a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 2177a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 2178a9de9248SMarcel Holtmann break; 2179a9de9248SMarcel Holtmann 2180a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 2181a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 2182a9de9248SMarcel Holtmann break; 2183a9de9248SMarcel Holtmann 2184a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 2185a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 2186a9de9248SMarcel Holtmann break; 2187a9de9248SMarcel Holtmann 2188a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 2189a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 2190a9de9248SMarcel Holtmann break; 2191a9de9248SMarcel Holtmann 2192a9de9248SMarcel Holtmann case HCI_OP_HOST_BUFFER_SIZE: 2193a9de9248SMarcel Holtmann hci_cc_host_buffer_size(hdev, skb); 2194a9de9248SMarcel Holtmann break; 2195a9de9248SMarcel Holtmann 2196333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 2197333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 2198333140b5SMarcel Holtmann break; 2199333140b5SMarcel Holtmann 2200a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 2201a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 2202a9de9248SMarcel Holtmann break; 2203a9de9248SMarcel Holtmann 2204a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 2205a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 2206a9de9248SMarcel Holtmann break; 2207a9de9248SMarcel Holtmann 2208a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 2209a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 2210a9de9248SMarcel Holtmann break; 2211a9de9248SMarcel Holtmann 2212971e3a4bSAndre Guedes case HCI_OP_READ_LOCAL_EXT_FEATURES: 2213971e3a4bSAndre Guedes hci_cc_read_local_ext_features(hdev, skb); 2214971e3a4bSAndre Guedes break; 2215971e3a4bSAndre Guedes 2216a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 2217a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 2218a9de9248SMarcel Holtmann break; 2219a9de9248SMarcel Holtmann 2220a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 2221a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 2222a9de9248SMarcel Holtmann break; 2223a9de9248SMarcel Holtmann 2224350ee4cfSAndrei Emeltchenko case HCI_OP_READ_DATA_BLOCK_SIZE: 2225350ee4cfSAndrei Emeltchenko hci_cc_read_data_block_size(hdev, skb); 2226350ee4cfSAndrei Emeltchenko break; 2227350ee4cfSAndrei Emeltchenko 222823bb5763SJohan Hedberg case HCI_OP_WRITE_CA_TIMEOUT: 222923bb5763SJohan Hedberg hci_cc_write_ca_timeout(hdev, skb); 223023bb5763SJohan Hedberg break; 223123bb5763SJohan Hedberg 22321e89cffbSAndrei Emeltchenko case HCI_OP_READ_FLOW_CONTROL_MODE: 22331e89cffbSAndrei Emeltchenko hci_cc_read_flow_control_mode(hdev, skb); 22341e89cffbSAndrei Emeltchenko break; 22351e89cffbSAndrei Emeltchenko 2236928abaa7SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_INFO: 2237928abaa7SAndrei Emeltchenko hci_cc_read_local_amp_info(hdev, skb); 2238928abaa7SAndrei Emeltchenko break; 2239928abaa7SAndrei Emeltchenko 2240b0916ea0SJohan Hedberg case HCI_OP_DELETE_STORED_LINK_KEY: 2241b0916ea0SJohan Hedberg hci_cc_delete_stored_link_key(hdev, skb); 2242b0916ea0SJohan Hedberg break; 2243b0916ea0SJohan Hedberg 2244d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_MASK: 2245d5859e22SJohan Hedberg hci_cc_set_event_mask(hdev, skb); 2246d5859e22SJohan Hedberg break; 2247d5859e22SJohan Hedberg 2248d5859e22SJohan Hedberg case HCI_OP_WRITE_INQUIRY_MODE: 2249d5859e22SJohan Hedberg hci_cc_write_inquiry_mode(hdev, skb); 2250d5859e22SJohan Hedberg break; 2251d5859e22SJohan Hedberg 2252d5859e22SJohan Hedberg case HCI_OP_READ_INQ_RSP_TX_POWER: 2253d5859e22SJohan Hedberg hci_cc_read_inq_rsp_tx_power(hdev, skb); 2254d5859e22SJohan Hedberg break; 2255d5859e22SJohan Hedberg 2256d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_FLT: 2257d5859e22SJohan Hedberg hci_cc_set_event_flt(hdev, skb); 2258d5859e22SJohan Hedberg break; 2259d5859e22SJohan Hedberg 2260980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_REPLY: 2261980e1a53SJohan Hedberg hci_cc_pin_code_reply(hdev, skb); 2262980e1a53SJohan Hedberg break; 2263980e1a53SJohan Hedberg 2264980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_NEG_REPLY: 2265980e1a53SJohan Hedberg hci_cc_pin_code_neg_reply(hdev, skb); 2266980e1a53SJohan Hedberg break; 2267980e1a53SJohan Hedberg 2268c35938b2SSzymon Janc case HCI_OP_READ_LOCAL_OOB_DATA: 2269c35938b2SSzymon Janc hci_cc_read_local_oob_data_reply(hdev, skb); 2270c35938b2SSzymon Janc break; 2271c35938b2SSzymon Janc 22726ed58ec5SVille Tervo case HCI_OP_LE_READ_BUFFER_SIZE: 22736ed58ec5SVille Tervo hci_cc_le_read_buffer_size(hdev, skb); 22746ed58ec5SVille Tervo break; 22756ed58ec5SVille Tervo 2276a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_REPLY: 2277a5c29683SJohan Hedberg hci_cc_user_confirm_reply(hdev, skb); 2278a5c29683SJohan Hedberg break; 2279a5c29683SJohan Hedberg 2280a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_NEG_REPLY: 2281a5c29683SJohan Hedberg hci_cc_user_confirm_neg_reply(hdev, skb); 2282a5c29683SJohan Hedberg break; 2283a5c29683SJohan Hedberg 22841143d458SBrian Gix case HCI_OP_USER_PASSKEY_REPLY: 22851143d458SBrian Gix hci_cc_user_passkey_reply(hdev, skb); 22861143d458SBrian Gix break; 22871143d458SBrian Gix 22881143d458SBrian Gix case HCI_OP_USER_PASSKEY_NEG_REPLY: 22891143d458SBrian Gix hci_cc_user_passkey_neg_reply(hdev, skb); 229007f7fa5dSAndre Guedes 229107f7fa5dSAndre Guedes case HCI_OP_LE_SET_SCAN_PARAM: 229207f7fa5dSAndre Guedes hci_cc_le_set_scan_param(hdev, skb); 22931143d458SBrian Gix break; 22941143d458SBrian Gix 2295eb9d91f5SAndre Guedes case HCI_OP_LE_SET_SCAN_ENABLE: 2296eb9d91f5SAndre Guedes hci_cc_le_set_scan_enable(hdev, skb); 2297eb9d91f5SAndre Guedes break; 2298eb9d91f5SAndre Guedes 2299a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_REPLY: 2300a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_reply(hdev, skb); 2301a7a595f6SVinicius Costa Gomes break; 2302a7a595f6SVinicius Costa Gomes 2303a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_NEG_REPLY: 2304a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_neg_reply(hdev, skb); 2305a7a595f6SVinicius Costa Gomes break; 2306a7a595f6SVinicius Costa Gomes 2307f9b49306SAndre Guedes case HCI_OP_WRITE_LE_HOST_SUPPORTED: 2308f9b49306SAndre Guedes hci_cc_write_le_host_supported(hdev, skb); 2309f9b49306SAndre Guedes break; 2310f9b49306SAndre Guedes 2311a9de9248SMarcel Holtmann default: 2312a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 2313a9de9248SMarcel Holtmann break; 2314a9de9248SMarcel Holtmann } 2315a9de9248SMarcel Holtmann 23166bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 23176bd32326SVille Tervo del_timer(&hdev->cmd_timer); 23186bd32326SVille Tervo 2319a9de9248SMarcel Holtmann if (ev->ncmd) { 2320a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2321a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2322c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2323a9de9248SMarcel Holtmann } 2324a9de9248SMarcel Holtmann } 2325a9de9248SMarcel Holtmann 2326a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 2327a9de9248SMarcel Holtmann { 2328a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 2329a9de9248SMarcel Holtmann __u16 opcode; 2330a9de9248SMarcel Holtmann 2331a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2332a9de9248SMarcel Holtmann 2333a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2334a9de9248SMarcel Holtmann 2335a9de9248SMarcel Holtmann switch (opcode) { 2336a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 2337a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 2338a9de9248SMarcel Holtmann break; 2339a9de9248SMarcel Holtmann 2340a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 2341a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 2342a9de9248SMarcel Holtmann break; 2343a9de9248SMarcel Holtmann 2344a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 2345a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 2346a9de9248SMarcel Holtmann break; 2347a9de9248SMarcel Holtmann 2348f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 2349f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 2350f8558555SMarcel Holtmann break; 2351f8558555SMarcel Holtmann 2352f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 2353f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 2354f8558555SMarcel Holtmann break; 2355f8558555SMarcel Holtmann 2356a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 2357a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 2358a9de9248SMarcel Holtmann break; 2359a9de9248SMarcel Holtmann 2360769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 2361769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 2362769be974SMarcel Holtmann break; 2363769be974SMarcel Holtmann 2364769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 2365769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 2366769be974SMarcel Holtmann break; 2367769be974SMarcel Holtmann 2368a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 2369a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 2370a9de9248SMarcel Holtmann break; 2371a9de9248SMarcel Holtmann 2372a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 2373a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 2374a9de9248SMarcel Holtmann break; 2375a9de9248SMarcel Holtmann 2376a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 2377a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 2378a9de9248SMarcel Holtmann break; 2379a9de9248SMarcel Holtmann 23808962ee74SJohan Hedberg case HCI_OP_DISCONNECT: 238188c3df13SJohan Hedberg hci_cs_disconnect(hdev, ev->status); 23828962ee74SJohan Hedberg break; 23838962ee74SJohan Hedberg 2384fcd89c09SVille Tervo case HCI_OP_LE_CREATE_CONN: 2385fcd89c09SVille Tervo hci_cs_le_create_conn(hdev, ev->status); 2386fcd89c09SVille Tervo break; 2387fcd89c09SVille Tervo 2388a7a595f6SVinicius Costa Gomes case HCI_OP_LE_START_ENC: 2389a7a595f6SVinicius Costa Gomes hci_cs_le_start_enc(hdev, ev->status); 2390a7a595f6SVinicius Costa Gomes break; 2391a7a595f6SVinicius Costa Gomes 2392a9de9248SMarcel Holtmann default: 2393a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 2394a9de9248SMarcel Holtmann break; 2395a9de9248SMarcel Holtmann } 2396a9de9248SMarcel Holtmann 23976bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 23986bd32326SVille Tervo del_timer(&hdev->cmd_timer); 23996bd32326SVille Tervo 240010572132SGustavo F. Padovan if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2401a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2402a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2403c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2404a9de9248SMarcel Holtmann } 2405a9de9248SMarcel Holtmann } 2406a9de9248SMarcel Holtmann 2407a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2408a9de9248SMarcel Holtmann { 2409a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 2410a9de9248SMarcel Holtmann struct hci_conn *conn; 2411a9de9248SMarcel Holtmann 2412a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2413a9de9248SMarcel Holtmann 2414a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2415a9de9248SMarcel Holtmann 2416a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2417a9de9248SMarcel Holtmann if (conn) { 2418a9de9248SMarcel Holtmann if (!ev->status) { 2419a9de9248SMarcel Holtmann if (ev->role) 2420a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_MASTER; 2421a9de9248SMarcel Holtmann else 2422a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_MASTER; 2423a9de9248SMarcel Holtmann } 2424a9de9248SMarcel Holtmann 242551a8efd7SJohan Hedberg clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); 2426a9de9248SMarcel Holtmann 2427a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 2428a9de9248SMarcel Holtmann } 2429a9de9248SMarcel Holtmann 2430a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2431a9de9248SMarcel Holtmann } 2432a9de9248SMarcel Holtmann 24331da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 24341da177e4SLinus Torvalds { 2435a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 24361da177e4SLinus Torvalds int i; 24371da177e4SLinus Torvalds 243832ac5b9bSAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) { 243932ac5b9bSAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 244032ac5b9bSAndrei Emeltchenko return; 244132ac5b9bSAndrei Emeltchenko } 244232ac5b9bSAndrei Emeltchenko 2443c5993de8SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 2444c5993de8SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_pkts_info)) { 24451da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 24461da177e4SLinus Torvalds return; 24471da177e4SLinus Torvalds } 24481da177e4SLinus Torvalds 2449c5993de8SAndrei Emeltchenko BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 2450c5993de8SAndrei Emeltchenko 2451613a1c0cSAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 2452613a1c0cSAndrei Emeltchenko struct hci_comp_pkts_info *info = &ev->handles[i]; 24531da177e4SLinus Torvalds struct hci_conn *conn; 24541da177e4SLinus Torvalds __u16 handle, count; 24551da177e4SLinus Torvalds 2456613a1c0cSAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 2457613a1c0cSAndrei Emeltchenko count = __le16_to_cpu(info->count); 24581da177e4SLinus Torvalds 24591da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 2460f4280918SAndrei Emeltchenko if (!conn) 2461f4280918SAndrei Emeltchenko continue; 2462f4280918SAndrei Emeltchenko 24631da177e4SLinus Torvalds conn->sent -= count; 24641da177e4SLinus Torvalds 2465f4280918SAndrei Emeltchenko switch (conn->type) { 2466f4280918SAndrei Emeltchenko case ACL_LINK: 246770f23020SAndrei Emeltchenko hdev->acl_cnt += count; 246870f23020SAndrei Emeltchenko if (hdev->acl_cnt > hdev->acl_pkts) 24691da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 2470f4280918SAndrei Emeltchenko break; 2471f4280918SAndrei Emeltchenko 2472f4280918SAndrei Emeltchenko case LE_LINK: 24736ed58ec5SVille Tervo if (hdev->le_pkts) { 24746ed58ec5SVille Tervo hdev->le_cnt += count; 24756ed58ec5SVille Tervo if (hdev->le_cnt > hdev->le_pkts) 24766ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 24776ed58ec5SVille Tervo } else { 24786ed58ec5SVille Tervo hdev->acl_cnt += count; 24796ed58ec5SVille Tervo if (hdev->acl_cnt > hdev->acl_pkts) 24806ed58ec5SVille Tervo hdev->acl_cnt = hdev->acl_pkts; 24816ed58ec5SVille Tervo } 2482f4280918SAndrei Emeltchenko break; 2483f4280918SAndrei Emeltchenko 2484f4280918SAndrei Emeltchenko case SCO_LINK: 248570f23020SAndrei Emeltchenko hdev->sco_cnt += count; 248670f23020SAndrei Emeltchenko if (hdev->sco_cnt > hdev->sco_pkts) 24875b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 2488f4280918SAndrei Emeltchenko break; 2489f4280918SAndrei Emeltchenko 2490f4280918SAndrei Emeltchenko default: 2491f4280918SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 2492f4280918SAndrei Emeltchenko break; 24931da177e4SLinus Torvalds } 24941da177e4SLinus Torvalds } 2495a9de9248SMarcel Holtmann 24963eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 24971da177e4SLinus Torvalds } 24981da177e4SLinus Torvalds 249925e89e99SAndrei Emeltchenko static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev, 250025e89e99SAndrei Emeltchenko struct sk_buff *skb) 250125e89e99SAndrei Emeltchenko { 250225e89e99SAndrei Emeltchenko struct hci_ev_num_comp_blocks *ev = (void *) skb->data; 250325e89e99SAndrei Emeltchenko int i; 250425e89e99SAndrei Emeltchenko 250525e89e99SAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) { 250625e89e99SAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 250725e89e99SAndrei Emeltchenko return; 250825e89e99SAndrei Emeltchenko } 250925e89e99SAndrei Emeltchenko 251025e89e99SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 251125e89e99SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_blocks_info)) { 251225e89e99SAndrei Emeltchenko BT_DBG("%s bad parameters", hdev->name); 251325e89e99SAndrei Emeltchenko return; 251425e89e99SAndrei Emeltchenko } 251525e89e99SAndrei Emeltchenko 251625e89e99SAndrei Emeltchenko BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks, 251725e89e99SAndrei Emeltchenko ev->num_hndl); 251825e89e99SAndrei Emeltchenko 251925e89e99SAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 252025e89e99SAndrei Emeltchenko struct hci_comp_blocks_info *info = &ev->handles[i]; 252125e89e99SAndrei Emeltchenko struct hci_conn *conn; 252225e89e99SAndrei Emeltchenko __u16 handle, block_count; 252325e89e99SAndrei Emeltchenko 252425e89e99SAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 252525e89e99SAndrei Emeltchenko block_count = __le16_to_cpu(info->blocks); 252625e89e99SAndrei Emeltchenko 252725e89e99SAndrei Emeltchenko conn = hci_conn_hash_lookup_handle(hdev, handle); 252825e89e99SAndrei Emeltchenko if (!conn) 252925e89e99SAndrei Emeltchenko continue; 253025e89e99SAndrei Emeltchenko 253125e89e99SAndrei Emeltchenko conn->sent -= block_count; 253225e89e99SAndrei Emeltchenko 253325e89e99SAndrei Emeltchenko switch (conn->type) { 253425e89e99SAndrei Emeltchenko case ACL_LINK: 253525e89e99SAndrei Emeltchenko hdev->block_cnt += block_count; 253625e89e99SAndrei Emeltchenko if (hdev->block_cnt > hdev->num_blocks) 253725e89e99SAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 253825e89e99SAndrei Emeltchenko break; 253925e89e99SAndrei Emeltchenko 254025e89e99SAndrei Emeltchenko default: 254125e89e99SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 254225e89e99SAndrei Emeltchenko break; 254325e89e99SAndrei Emeltchenko } 254425e89e99SAndrei Emeltchenko } 254525e89e99SAndrei Emeltchenko 254625e89e99SAndrei Emeltchenko queue_work(hdev->workqueue, &hdev->tx_work); 254725e89e99SAndrei Emeltchenko } 254825e89e99SAndrei Emeltchenko 254904837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 25501da177e4SLinus Torvalds { 2551a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 255204837f64SMarcel Holtmann struct hci_conn *conn; 25531da177e4SLinus Torvalds 25541da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 25551da177e4SLinus Torvalds 25561da177e4SLinus Torvalds hci_dev_lock(hdev); 25571da177e4SLinus Torvalds 255804837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 255904837f64SMarcel Holtmann if (conn) { 256004837f64SMarcel Holtmann conn->mode = ev->mode; 256104837f64SMarcel Holtmann conn->interval = __le16_to_cpu(ev->interval); 256204837f64SMarcel Holtmann 256351a8efd7SJohan Hedberg if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) { 256404837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 256558a681efSJohan Hedberg set_bit(HCI_CONN_POWER_SAVE, &conn->flags); 256604837f64SMarcel Holtmann else 256758a681efSJohan Hedberg clear_bit(HCI_CONN_POWER_SAVE, &conn->flags); 256804837f64SMarcel Holtmann } 2569e73439d8SMarcel Holtmann 257051a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 2571e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 257204837f64SMarcel Holtmann } 257304837f64SMarcel Holtmann 257404837f64SMarcel Holtmann hci_dev_unlock(hdev); 257504837f64SMarcel Holtmann } 257604837f64SMarcel Holtmann 25771da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 25781da177e4SLinus Torvalds { 2579052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 2580052b30b0SMarcel Holtmann struct hci_conn *conn; 2581052b30b0SMarcel Holtmann 2582a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2583052b30b0SMarcel Holtmann 2584052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2585052b30b0SMarcel Holtmann 2586052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2587b6f98044SWaldemar Rymarkiewicz if (!conn) 2588b6f98044SWaldemar Rymarkiewicz goto unlock; 2589b6f98044SWaldemar Rymarkiewicz 2590b6f98044SWaldemar Rymarkiewicz if (conn->state == BT_CONNECTED) { 2591052b30b0SMarcel Holtmann hci_conn_hold(conn); 2592052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 2593052b30b0SMarcel Holtmann hci_conn_put(conn); 2594052b30b0SMarcel Holtmann } 2595052b30b0SMarcel Holtmann 2596a8b2d5c2SJohan Hedberg if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags)) 259703b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 259803b555e1SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 2599a8b2d5c2SJohan Hedberg else if (test_bit(HCI_MGMT, &hdev->dev_flags)) { 2600a770bb5aSWaldemar Rymarkiewicz u8 secure; 2601a770bb5aSWaldemar Rymarkiewicz 2602a770bb5aSWaldemar Rymarkiewicz if (conn->pending_sec_level == BT_SECURITY_HIGH) 2603a770bb5aSWaldemar Rymarkiewicz secure = 1; 2604a770bb5aSWaldemar Rymarkiewicz else 2605a770bb5aSWaldemar Rymarkiewicz secure = 0; 2606a770bb5aSWaldemar Rymarkiewicz 2607744cf19eSJohan Hedberg mgmt_pin_code_request(hdev, &ev->bdaddr, secure); 2608a770bb5aSWaldemar Rymarkiewicz } 2609980e1a53SJohan Hedberg 2610b6f98044SWaldemar Rymarkiewicz unlock: 2611052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 26121da177e4SLinus Torvalds } 26131da177e4SLinus Torvalds 26141da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 26151da177e4SLinus Torvalds { 261655ed8ca1SJohan Hedberg struct hci_ev_link_key_req *ev = (void *) skb->data; 261755ed8ca1SJohan Hedberg struct hci_cp_link_key_reply cp; 261855ed8ca1SJohan Hedberg struct hci_conn *conn; 261955ed8ca1SJohan Hedberg struct link_key *key; 262055ed8ca1SJohan Hedberg 2621a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 262255ed8ca1SJohan Hedberg 2623a8b2d5c2SJohan Hedberg if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) 262455ed8ca1SJohan Hedberg return; 262555ed8ca1SJohan Hedberg 262655ed8ca1SJohan Hedberg hci_dev_lock(hdev); 262755ed8ca1SJohan Hedberg 262855ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, &ev->bdaddr); 262955ed8ca1SJohan Hedberg if (!key) { 263055ed8ca1SJohan Hedberg BT_DBG("%s link key not found for %s", hdev->name, 263155ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 263255ed8ca1SJohan Hedberg goto not_found; 263355ed8ca1SJohan Hedberg } 263455ed8ca1SJohan Hedberg 263555ed8ca1SJohan Hedberg BT_DBG("%s found key type %u for %s", hdev->name, key->type, 263655ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 263755ed8ca1SJohan Hedberg 2638a8b2d5c2SJohan Hedberg if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) && 2639b6020ba0SWaldemar Rymarkiewicz key->type == HCI_LK_DEBUG_COMBINATION) { 264055ed8ca1SJohan Hedberg BT_DBG("%s ignoring debug key", hdev->name); 264155ed8ca1SJohan Hedberg goto not_found; 264255ed8ca1SJohan Hedberg } 264355ed8ca1SJohan Hedberg 264455ed8ca1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 264560b83f57SWaldemar Rymarkiewicz if (conn) { 264660b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_UNAUTH_COMBINATION && 264760b83f57SWaldemar Rymarkiewicz conn->auth_type != 0xff && 264860b83f57SWaldemar Rymarkiewicz (conn->auth_type & 0x01)) { 264955ed8ca1SJohan Hedberg BT_DBG("%s ignoring unauthenticated key", hdev->name); 265055ed8ca1SJohan Hedberg goto not_found; 265155ed8ca1SJohan Hedberg } 265255ed8ca1SJohan Hedberg 265360b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && 265460b83f57SWaldemar Rymarkiewicz conn->pending_sec_level == BT_SECURITY_HIGH) { 265560b83f57SWaldemar Rymarkiewicz BT_DBG("%s ignoring key unauthenticated for high \ 265660b83f57SWaldemar Rymarkiewicz security", hdev->name); 265760b83f57SWaldemar Rymarkiewicz goto not_found; 265860b83f57SWaldemar Rymarkiewicz } 265960b83f57SWaldemar Rymarkiewicz 266060b83f57SWaldemar Rymarkiewicz conn->key_type = key->type; 266160b83f57SWaldemar Rymarkiewicz conn->pin_length = key->pin_len; 266260b83f57SWaldemar Rymarkiewicz } 266360b83f57SWaldemar Rymarkiewicz 266455ed8ca1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 266555ed8ca1SJohan Hedberg memcpy(cp.link_key, key->val, 16); 266655ed8ca1SJohan Hedberg 266755ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 266855ed8ca1SJohan Hedberg 266955ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 267055ed8ca1SJohan Hedberg 267155ed8ca1SJohan Hedberg return; 267255ed8ca1SJohan Hedberg 267355ed8ca1SJohan Hedberg not_found: 267455ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 267555ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 26761da177e4SLinus Torvalds } 26771da177e4SLinus Torvalds 26781da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 26791da177e4SLinus Torvalds { 2680052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 2681052b30b0SMarcel Holtmann struct hci_conn *conn; 268255ed8ca1SJohan Hedberg u8 pin_len = 0; 2683052b30b0SMarcel Holtmann 2684a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2685052b30b0SMarcel Holtmann 2686052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2687052b30b0SMarcel Holtmann 2688052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2689052b30b0SMarcel Holtmann if (conn) { 2690052b30b0SMarcel Holtmann hci_conn_hold(conn); 2691052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2692980e1a53SJohan Hedberg pin_len = conn->pin_length; 269313d39315SWaldemar Rymarkiewicz 269413d39315SWaldemar Rymarkiewicz if (ev->key_type != HCI_LK_CHANGED_COMBINATION) 269513d39315SWaldemar Rymarkiewicz conn->key_type = ev->key_type; 269613d39315SWaldemar Rymarkiewicz 2697052b30b0SMarcel Holtmann hci_conn_put(conn); 2698052b30b0SMarcel Holtmann } 2699052b30b0SMarcel Holtmann 2700a8b2d5c2SJohan Hedberg if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) 2701d25e28abSJohan Hedberg hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, 270255ed8ca1SJohan Hedberg ev->key_type, pin_len); 270355ed8ca1SJohan Hedberg 2704052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 27051da177e4SLinus Torvalds } 27061da177e4SLinus Torvalds 270704837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 270804837f64SMarcel Holtmann { 2709a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 271004837f64SMarcel Holtmann struct hci_conn *conn; 271104837f64SMarcel Holtmann 271204837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 271304837f64SMarcel Holtmann 271404837f64SMarcel Holtmann hci_dev_lock(hdev); 271504837f64SMarcel Holtmann 271604837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 27171da177e4SLinus Torvalds if (conn && !ev->status) { 27181da177e4SLinus Torvalds struct inquiry_entry *ie; 27191da177e4SLinus Torvalds 2720cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2721cc11b9c1SAndrei Emeltchenko if (ie) { 27221da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 27231da177e4SLinus Torvalds ie->timestamp = jiffies; 27241da177e4SLinus Torvalds } 27251da177e4SLinus Torvalds } 27261da177e4SLinus Torvalds 27271da177e4SLinus Torvalds hci_dev_unlock(hdev); 27281da177e4SLinus Torvalds } 27291da177e4SLinus Torvalds 2730a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2731a8746417SMarcel Holtmann { 2732a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 2733a8746417SMarcel Holtmann struct hci_conn *conn; 2734a8746417SMarcel Holtmann 2735a8746417SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2736a8746417SMarcel Holtmann 2737a8746417SMarcel Holtmann hci_dev_lock(hdev); 2738a8746417SMarcel Holtmann 2739a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2740a8746417SMarcel Holtmann if (conn && !ev->status) 2741a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 2742a8746417SMarcel Holtmann 2743a8746417SMarcel Holtmann hci_dev_unlock(hdev); 2744a8746417SMarcel Holtmann } 2745a8746417SMarcel Holtmann 274685a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 274785a1e930SMarcel Holtmann { 2748a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 274985a1e930SMarcel Holtmann struct inquiry_entry *ie; 275085a1e930SMarcel Holtmann 275185a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 275285a1e930SMarcel Holtmann 275385a1e930SMarcel Holtmann hci_dev_lock(hdev); 275485a1e930SMarcel Holtmann 2755cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2756cc11b9c1SAndrei Emeltchenko if (ie) { 275785a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 275885a1e930SMarcel Holtmann ie->timestamp = jiffies; 275985a1e930SMarcel Holtmann } 276085a1e930SMarcel Holtmann 276185a1e930SMarcel Holtmann hci_dev_unlock(hdev); 276285a1e930SMarcel Holtmann } 276385a1e930SMarcel Holtmann 2764a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb) 2765a9de9248SMarcel Holtmann { 2766a9de9248SMarcel Holtmann struct inquiry_data data; 2767a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 27683175405bSJohan Hedberg bool name_known; 2769a9de9248SMarcel Holtmann 2770a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2771a9de9248SMarcel Holtmann 2772a9de9248SMarcel Holtmann if (!num_rsp) 2773a9de9248SMarcel Holtmann return; 2774a9de9248SMarcel Holtmann 2775a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2776a9de9248SMarcel Holtmann 2777a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 2778138d22efSSzymon Janc struct inquiry_info_with_rssi_and_pscan_mode *info; 2779138d22efSSzymon Janc info = (void *) (skb->data + 1); 2780a9de9248SMarcel Holtmann 2781e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2782a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2783a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2784a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2785a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 2786a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2787a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2788a9de9248SMarcel Holtmann data.rssi = info->rssi; 278941a96212SMarcel Holtmann data.ssp_mode = 0x00; 27903175405bSJohan Hedberg 27913175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 27923175405bSJohan Hedberg false); 279348264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2794e17acd40SJohan Hedberg info->dev_class, info->rssi, 27957d262f86SAndre Guedes !name_known, NULL, 0); 2796a9de9248SMarcel Holtmann } 2797a9de9248SMarcel Holtmann } else { 2798a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 2799a9de9248SMarcel Holtmann 2800e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2801a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2802a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2803a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2804a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2805a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2806a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2807a9de9248SMarcel Holtmann data.rssi = info->rssi; 280841a96212SMarcel Holtmann data.ssp_mode = 0x00; 28093175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 28103175405bSJohan Hedberg false); 281148264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2812e17acd40SJohan Hedberg info->dev_class, info->rssi, 28137d262f86SAndre Guedes !name_known, NULL, 0); 2814a9de9248SMarcel Holtmann } 2815a9de9248SMarcel Holtmann } 2816a9de9248SMarcel Holtmann 2817a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2818a9de9248SMarcel Holtmann } 2819a9de9248SMarcel Holtmann 2820a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 2821a9de9248SMarcel Holtmann { 282241a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 282341a96212SMarcel Holtmann struct hci_conn *conn; 282441a96212SMarcel Holtmann 2825a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 282641a96212SMarcel Holtmann 282741a96212SMarcel Holtmann hci_dev_lock(hdev); 282841a96212SMarcel Holtmann 282941a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2830ccd556feSJohan Hedberg if (!conn) 2831ccd556feSJohan Hedberg goto unlock; 2832ccd556feSJohan Hedberg 2833769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 283441a96212SMarcel Holtmann struct inquiry_entry *ie; 283541a96212SMarcel Holtmann 2836cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2837cc11b9c1SAndrei Emeltchenko if (ie) 283841a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 283941a96212SMarcel Holtmann 284058a681efSJohan Hedberg if (ev->features[0] & 0x01) 284158a681efSJohan Hedberg set_bit(HCI_CONN_SSP_ENABLED, &conn->flags); 284241a96212SMarcel Holtmann } 284341a96212SMarcel Holtmann 2844ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2845ccd556feSJohan Hedberg goto unlock; 2846ccd556feSJohan Hedberg 2847127178d2SJohan Hedberg if (!ev->status) { 2848127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2849127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2850127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2851127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2852127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2853b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 2854b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 2855b644ba33SJohan Hedberg conn->dst_type, NULL, 0, 2856b644ba33SJohan Hedberg conn->dev_class); 2857392599b9SJohan Hedberg 2858127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2859769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2860769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2861769be974SMarcel Holtmann hci_conn_put(conn); 2862769be974SMarcel Holtmann } 2863769be974SMarcel Holtmann 2864ccd556feSJohan Hedberg unlock: 286541a96212SMarcel Holtmann hci_dev_unlock(hdev); 2866a9de9248SMarcel Holtmann } 2867a9de9248SMarcel Holtmann 2868a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2869a9de9248SMarcel Holtmann { 2870b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 2871b6a0dc82SMarcel Holtmann struct hci_conn *conn; 2872b6a0dc82SMarcel Holtmann 2873b6a0dc82SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2874b6a0dc82SMarcel Holtmann 2875b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 2876b6a0dc82SMarcel Holtmann 2877b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 28789dc0a3afSMarcel Holtmann if (!conn) { 28799dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 28809dc0a3afSMarcel Holtmann goto unlock; 28819dc0a3afSMarcel Holtmann 28829dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 2883b6a0dc82SMarcel Holtmann if (!conn) 2884b6a0dc82SMarcel Holtmann goto unlock; 2885b6a0dc82SMarcel Holtmann 28869dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 28879dc0a3afSMarcel Holtmann } 28889dc0a3afSMarcel Holtmann 2889732547f9SMarcel Holtmann switch (ev->status) { 2890732547f9SMarcel Holtmann case 0x00: 2891732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 2892732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 2893732547f9SMarcel Holtmann 28949eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 2895732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 2896732547f9SMarcel Holtmann break; 2897732547f9SMarcel Holtmann 2898705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 2899732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 29001038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 2901732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 2902732547f9SMarcel Holtmann if (conn->out && conn->attempt < 2) { 2903efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 2904efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 2905efc7688bSMarcel Holtmann hci_setup_sync(conn, conn->link->handle); 2906efc7688bSMarcel Holtmann goto unlock; 2907efc7688bSMarcel Holtmann } 2908732547f9SMarcel Holtmann /* fall through */ 2909efc7688bSMarcel Holtmann 2910732547f9SMarcel Holtmann default: 2911b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 2912732547f9SMarcel Holtmann break; 2913732547f9SMarcel Holtmann } 2914b6a0dc82SMarcel Holtmann 2915b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2916b6a0dc82SMarcel Holtmann if (ev->status) 2917b6a0dc82SMarcel Holtmann hci_conn_del(conn); 2918b6a0dc82SMarcel Holtmann 2919b6a0dc82SMarcel Holtmann unlock: 2920b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 2921a9de9248SMarcel Holtmann } 2922a9de9248SMarcel Holtmann 2923a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) 2924a9de9248SMarcel Holtmann { 2925a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2926a9de9248SMarcel Holtmann } 2927a9de9248SMarcel Holtmann 292804837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) 292904837f64SMarcel Holtmann { 2930a9de9248SMarcel Holtmann struct hci_ev_sniff_subrate *ev = (void *) skb->data; 293104837f64SMarcel Holtmann 293204837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 293304837f64SMarcel Holtmann } 293404837f64SMarcel Holtmann 2935a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 2936a9de9248SMarcel Holtmann { 2937a9de9248SMarcel Holtmann struct inquiry_data data; 2938a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 2939a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2940a9de9248SMarcel Holtmann 2941a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2942a9de9248SMarcel Holtmann 2943a9de9248SMarcel Holtmann if (!num_rsp) 2944a9de9248SMarcel Holtmann return; 2945a9de9248SMarcel Holtmann 2946a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2947a9de9248SMarcel Holtmann 2948e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2949561aafbcSJohan Hedberg bool name_known; 2950561aafbcSJohan Hedberg 2951a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2952a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2953a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2954a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2955a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2956a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2957a9de9248SMarcel Holtmann data.rssi = info->rssi; 295841a96212SMarcel Holtmann data.ssp_mode = 0x01; 2959561aafbcSJohan Hedberg 2960a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 29614ddb1930SJohan Hedberg name_known = eir_has_data_type(info->data, 29624ddb1930SJohan Hedberg sizeof(info->data), 29634ddb1930SJohan Hedberg EIR_NAME_COMPLETE); 2964561aafbcSJohan Hedberg else 2965561aafbcSJohan Hedberg name_known = true; 2966561aafbcSJohan Hedberg 29673175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, name_known); 296848264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2969561aafbcSJohan Hedberg info->dev_class, info->rssi, 29707d262f86SAndre Guedes !name_known, info->data, 29717d262f86SAndre Guedes sizeof(info->data)); 2972a9de9248SMarcel Holtmann } 2973a9de9248SMarcel Holtmann 2974a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2975a9de9248SMarcel Holtmann } 2976a9de9248SMarcel Holtmann 297717fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn) 297817fa4b9dSJohan Hedberg { 297917fa4b9dSJohan Hedberg /* If remote requests dedicated bonding follow that lead */ 298017fa4b9dSJohan Hedberg if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) { 298117fa4b9dSJohan Hedberg /* If both remote and local IO capabilities allow MITM 298217fa4b9dSJohan Hedberg * protection then require it, otherwise don't */ 298317fa4b9dSJohan Hedberg if (conn->remote_cap == 0x03 || conn->io_capability == 0x03) 298417fa4b9dSJohan Hedberg return 0x02; 298517fa4b9dSJohan Hedberg else 298617fa4b9dSJohan Hedberg return 0x03; 298717fa4b9dSJohan Hedberg } 298817fa4b9dSJohan Hedberg 298917fa4b9dSJohan Hedberg /* If remote requests no-bonding follow that lead */ 299017fa4b9dSJohan Hedberg if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01) 299158797bf7SWaldemar Rymarkiewicz return conn->remote_auth | (conn->auth_type & 0x01); 299217fa4b9dSJohan Hedberg 299317fa4b9dSJohan Hedberg return conn->auth_type; 299417fa4b9dSJohan Hedberg } 299517fa4b9dSJohan Hedberg 29960493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 29970493684eSMarcel Holtmann { 29980493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 29990493684eSMarcel Holtmann struct hci_conn *conn; 30000493684eSMarcel Holtmann 30010493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 30020493684eSMarcel Holtmann 30030493684eSMarcel Holtmann hci_dev_lock(hdev); 30040493684eSMarcel Holtmann 30050493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 300603b555e1SJohan Hedberg if (!conn) 300703b555e1SJohan Hedberg goto unlock; 300803b555e1SJohan Hedberg 30090493684eSMarcel Holtmann hci_conn_hold(conn); 30100493684eSMarcel Holtmann 3011a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 301203b555e1SJohan Hedberg goto unlock; 301303b555e1SJohan Hedberg 3014a8b2d5c2SJohan Hedberg if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) || 301503b555e1SJohan Hedberg (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 301617fa4b9dSJohan Hedberg struct hci_cp_io_capability_reply cp; 301717fa4b9dSJohan Hedberg 301817fa4b9dSJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 30197a7f1e7cSHemant Gupta /* Change the IO capability from KeyboardDisplay 30207a7f1e7cSHemant Gupta * to DisplayYesNo as it is not supported by BT spec. */ 30217a7f1e7cSHemant Gupta cp.capability = (conn->io_capability == 0x04) ? 30227a7f1e7cSHemant Gupta 0x01 : conn->io_capability; 30237cbc9bd9SJohan Hedberg conn->auth_type = hci_get_auth_req(conn); 30247cbc9bd9SJohan Hedberg cp.authentication = conn->auth_type; 302517fa4b9dSJohan Hedberg 302658a681efSJohan Hedberg if ((conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)) && 3027ce85ee13SSzymon Janc hci_find_remote_oob_data(hdev, &conn->dst)) 3028ce85ee13SSzymon Janc cp.oob_data = 0x01; 3029ce85ee13SSzymon Janc else 3030ce85ee13SSzymon Janc cp.oob_data = 0x00; 3031ce85ee13SSzymon Janc 303217fa4b9dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, 303317fa4b9dSJohan Hedberg sizeof(cp), &cp); 303403b555e1SJohan Hedberg } else { 303503b555e1SJohan Hedberg struct hci_cp_io_capability_neg_reply cp; 303603b555e1SJohan Hedberg 303703b555e1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 30389f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED; 303903b555e1SJohan Hedberg 304003b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 304103b555e1SJohan Hedberg sizeof(cp), &cp); 304203b555e1SJohan Hedberg } 304303b555e1SJohan Hedberg 304403b555e1SJohan Hedberg unlock: 304503b555e1SJohan Hedberg hci_dev_unlock(hdev); 304603b555e1SJohan Hedberg } 304703b555e1SJohan Hedberg 304803b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 304903b555e1SJohan Hedberg { 305003b555e1SJohan Hedberg struct hci_ev_io_capa_reply *ev = (void *) skb->data; 305103b555e1SJohan Hedberg struct hci_conn *conn; 305203b555e1SJohan Hedberg 305303b555e1SJohan Hedberg BT_DBG("%s", hdev->name); 305403b555e1SJohan Hedberg 305503b555e1SJohan Hedberg hci_dev_lock(hdev); 305603b555e1SJohan Hedberg 305703b555e1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 305803b555e1SJohan Hedberg if (!conn) 305903b555e1SJohan Hedberg goto unlock; 306003b555e1SJohan Hedberg 306103b555e1SJohan Hedberg conn->remote_cap = ev->capability; 306203b555e1SJohan Hedberg conn->remote_auth = ev->authentication; 306358a681efSJohan Hedberg if (ev->oob_data) 306458a681efSJohan Hedberg set_bit(HCI_CONN_REMOTE_OOB, &conn->flags); 306503b555e1SJohan Hedberg 306603b555e1SJohan Hedberg unlock: 30670493684eSMarcel Holtmann hci_dev_unlock(hdev); 30680493684eSMarcel Holtmann } 30690493684eSMarcel Holtmann 3070a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev, 3071a5c29683SJohan Hedberg struct sk_buff *skb) 3072a5c29683SJohan Hedberg { 3073a5c29683SJohan Hedberg struct hci_ev_user_confirm_req *ev = (void *) skb->data; 307455bc1a37SJohan Hedberg int loc_mitm, rem_mitm, confirm_hint = 0; 30757a828908SJohan Hedberg struct hci_conn *conn; 3076a5c29683SJohan Hedberg 3077a5c29683SJohan Hedberg BT_DBG("%s", hdev->name); 3078a5c29683SJohan Hedberg 3079a5c29683SJohan Hedberg hci_dev_lock(hdev); 3080a5c29683SJohan Hedberg 3081a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 30827a828908SJohan Hedberg goto unlock; 30837a828908SJohan Hedberg 30847a828908SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 30857a828908SJohan Hedberg if (!conn) 30867a828908SJohan Hedberg goto unlock; 30877a828908SJohan Hedberg 30887a828908SJohan Hedberg loc_mitm = (conn->auth_type & 0x01); 30897a828908SJohan Hedberg rem_mitm = (conn->remote_auth & 0x01); 30907a828908SJohan Hedberg 30917a828908SJohan Hedberg /* If we require MITM but the remote device can't provide that 30927a828908SJohan Hedberg * (it has NoInputNoOutput) then reject the confirmation 30937a828908SJohan Hedberg * request. The only exception is when we're dedicated bonding 30947a828908SJohan Hedberg * initiators (connect_cfm_cb set) since then we always have the MITM 30957a828908SJohan Hedberg * bit set. */ 30967a828908SJohan Hedberg if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) { 30977a828908SJohan Hedberg BT_DBG("Rejecting request: remote device can't provide MITM"); 30987a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, 30997a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 31007a828908SJohan Hedberg goto unlock; 31017a828908SJohan Hedberg } 31027a828908SJohan Hedberg 31037a828908SJohan Hedberg /* If no side requires MITM protection; auto-accept */ 31047a828908SJohan Hedberg if ((!loc_mitm || conn->remote_cap == 0x03) && 31057a828908SJohan Hedberg (!rem_mitm || conn->io_capability == 0x03)) { 310655bc1a37SJohan Hedberg 310755bc1a37SJohan Hedberg /* If we're not the initiators request authorization to 310855bc1a37SJohan Hedberg * proceed from user space (mgmt_user_confirm with 310955bc1a37SJohan Hedberg * confirm_hint set to 1). */ 311051a8efd7SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 311155bc1a37SJohan Hedberg BT_DBG("Confirming auto-accept as acceptor"); 311255bc1a37SJohan Hedberg confirm_hint = 1; 311355bc1a37SJohan Hedberg goto confirm; 311455bc1a37SJohan Hedberg } 311555bc1a37SJohan Hedberg 31169f61656aSJohan Hedberg BT_DBG("Auto-accept of user confirmation with %ums delay", 31179f61656aSJohan Hedberg hdev->auto_accept_delay); 31189f61656aSJohan Hedberg 31199f61656aSJohan Hedberg if (hdev->auto_accept_delay > 0) { 31209f61656aSJohan Hedberg int delay = msecs_to_jiffies(hdev->auto_accept_delay); 31219f61656aSJohan Hedberg mod_timer(&conn->auto_accept_timer, jiffies + delay); 31229f61656aSJohan Hedberg goto unlock; 31239f61656aSJohan Hedberg } 31249f61656aSJohan Hedberg 31257a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, 31267a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 31277a828908SJohan Hedberg goto unlock; 31287a828908SJohan Hedberg } 31297a828908SJohan Hedberg 313055bc1a37SJohan Hedberg confirm: 3131272d90dfSJohan Hedberg mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey, 313255bc1a37SJohan Hedberg confirm_hint); 3133a5c29683SJohan Hedberg 31347a828908SJohan Hedberg unlock: 3135a5c29683SJohan Hedberg hci_dev_unlock(hdev); 3136a5c29683SJohan Hedberg } 3137a5c29683SJohan Hedberg 31381143d458SBrian Gix static inline void hci_user_passkey_request_evt(struct hci_dev *hdev, 31391143d458SBrian Gix struct sk_buff *skb) 31401143d458SBrian Gix { 31411143d458SBrian Gix struct hci_ev_user_passkey_req *ev = (void *) skb->data; 31421143d458SBrian Gix 31431143d458SBrian Gix BT_DBG("%s", hdev->name); 31441143d458SBrian Gix 31451143d458SBrian Gix hci_dev_lock(hdev); 31461143d458SBrian Gix 3147a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 3148272d90dfSJohan Hedberg mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); 31491143d458SBrian Gix 31501143d458SBrian Gix hci_dev_unlock(hdev); 31511143d458SBrian Gix } 31521143d458SBrian Gix 31530493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 31540493684eSMarcel Holtmann { 31550493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 31560493684eSMarcel Holtmann struct hci_conn *conn; 31570493684eSMarcel Holtmann 31580493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 31590493684eSMarcel Holtmann 31600493684eSMarcel Holtmann hci_dev_lock(hdev); 31610493684eSMarcel Holtmann 31620493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 31632a611692SJohan Hedberg if (!conn) 31642a611692SJohan Hedberg goto unlock; 31652a611692SJohan Hedberg 31662a611692SJohan Hedberg /* To avoid duplicate auth_failed events to user space we check 31672a611692SJohan Hedberg * the HCI_CONN_AUTH_PEND flag which will be set if we 31682a611692SJohan Hedberg * initiated the authentication. A traditional auth_complete 31692a611692SJohan Hedberg * event gets always produced as initiator and is also mapped to 31702a611692SJohan Hedberg * the mgmt_auth_failed event */ 317151a8efd7SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status != 0) 3172bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 3173bab73cb6SJohan Hedberg ev->status); 31742a611692SJohan Hedberg 31750493684eSMarcel Holtmann hci_conn_put(conn); 31760493684eSMarcel Holtmann 31772a611692SJohan Hedberg unlock: 31780493684eSMarcel Holtmann hci_dev_unlock(hdev); 31790493684eSMarcel Holtmann } 31800493684eSMarcel Holtmann 318141a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 318241a96212SMarcel Holtmann { 318341a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 318441a96212SMarcel Holtmann struct inquiry_entry *ie; 318541a96212SMarcel Holtmann 318641a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 318741a96212SMarcel Holtmann 318841a96212SMarcel Holtmann hci_dev_lock(hdev); 318941a96212SMarcel Holtmann 3190cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 3191cc11b9c1SAndrei Emeltchenko if (ie) 319241a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 319341a96212SMarcel Holtmann 319441a96212SMarcel Holtmann hci_dev_unlock(hdev); 319541a96212SMarcel Holtmann } 319641a96212SMarcel Holtmann 31972763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev, 31982763eda6SSzymon Janc struct sk_buff *skb) 31992763eda6SSzymon Janc { 32002763eda6SSzymon Janc struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; 32012763eda6SSzymon Janc struct oob_data *data; 32022763eda6SSzymon Janc 32032763eda6SSzymon Janc BT_DBG("%s", hdev->name); 32042763eda6SSzymon Janc 32052763eda6SSzymon Janc hci_dev_lock(hdev); 32062763eda6SSzymon Janc 3207a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 3208e1ba1f15SSzymon Janc goto unlock; 3209e1ba1f15SSzymon Janc 32102763eda6SSzymon Janc data = hci_find_remote_oob_data(hdev, &ev->bdaddr); 32112763eda6SSzymon Janc if (data) { 32122763eda6SSzymon Janc struct hci_cp_remote_oob_data_reply cp; 32132763eda6SSzymon Janc 32142763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 32152763eda6SSzymon Janc memcpy(cp.hash, data->hash, sizeof(cp.hash)); 32162763eda6SSzymon Janc memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); 32172763eda6SSzymon Janc 32182763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), 32192763eda6SSzymon Janc &cp); 32202763eda6SSzymon Janc } else { 32212763eda6SSzymon Janc struct hci_cp_remote_oob_data_neg_reply cp; 32222763eda6SSzymon Janc 32232763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 32242763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), 32252763eda6SSzymon Janc &cp); 32262763eda6SSzymon Janc } 32272763eda6SSzymon Janc 3228e1ba1f15SSzymon Janc unlock: 32292763eda6SSzymon Janc hci_dev_unlock(hdev); 32302763eda6SSzymon Janc } 32312763eda6SSzymon Janc 3232fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 3233fcd89c09SVille Tervo { 3234fcd89c09SVille Tervo struct hci_ev_le_conn_complete *ev = (void *) skb->data; 3235fcd89c09SVille Tervo struct hci_conn *conn; 3236fcd89c09SVille Tervo 3237fcd89c09SVille Tervo BT_DBG("%s status %d", hdev->name, ev->status); 3238fcd89c09SVille Tervo 3239fcd89c09SVille Tervo hci_dev_lock(hdev); 3240fcd89c09SVille Tervo 3241fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr); 3242b62f328bSVille Tervo if (!conn) { 3243b62f328bSVille Tervo conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); 3244b62f328bSVille Tervo if (!conn) { 3245b62f328bSVille Tervo BT_ERR("No memory for new connection"); 3246b62f328bSVille Tervo hci_dev_unlock(hdev); 3247b62f328bSVille Tervo return; 3248b62f328bSVille Tervo } 324929b7988aSAndre Guedes 325029b7988aSAndre Guedes conn->dst_type = ev->bdaddr_type; 3251b62f328bSVille Tervo } 3252fcd89c09SVille Tervo 3253fcd89c09SVille Tervo if (ev->status) { 325448264f06SJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 325548264f06SJohan Hedberg conn->dst_type, ev->status); 3256fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 3257fcd89c09SVille Tervo conn->state = BT_CLOSED; 3258fcd89c09SVille Tervo hci_conn_del(conn); 3259fcd89c09SVille Tervo goto unlock; 3260fcd89c09SVille Tervo } 3261fcd89c09SVille Tervo 3262b644ba33SJohan Hedberg if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 3263b644ba33SJohan Hedberg mgmt_device_connected(hdev, &ev->bdaddr, conn->type, 3264b644ba33SJohan Hedberg conn->dst_type, NULL, 0, 0); 326583bc71b4SVinicius Costa Gomes 32667b5c0d52SVinicius Costa Gomes conn->sec_level = BT_SECURITY_LOW; 3267fcd89c09SVille Tervo conn->handle = __le16_to_cpu(ev->handle); 3268fcd89c09SVille Tervo conn->state = BT_CONNECTED; 3269fcd89c09SVille Tervo 3270fcd89c09SVille Tervo hci_conn_hold_device(conn); 3271fcd89c09SVille Tervo hci_conn_add_sysfs(conn); 3272fcd89c09SVille Tervo 3273fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 3274fcd89c09SVille Tervo 3275fcd89c09SVille Tervo unlock: 3276fcd89c09SVille Tervo hci_dev_unlock(hdev); 3277fcd89c09SVille Tervo } 3278fcd89c09SVille Tervo 32799aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev, 32809aa04c91SAndre Guedes struct sk_buff *skb) 32819aa04c91SAndre Guedes { 3282e95beb41SAndre Guedes u8 num_reports = skb->data[0]; 3283e95beb41SAndre Guedes void *ptr = &skb->data[1]; 32843c9e9195SAndre Guedes s8 rssi; 32859aa04c91SAndre Guedes 32869aa04c91SAndre Guedes hci_dev_lock(hdev); 32879aa04c91SAndre Guedes 3288e95beb41SAndre Guedes while (num_reports--) { 3289e95beb41SAndre Guedes struct hci_ev_le_advertising_info *ev = ptr; 3290e95beb41SAndre Guedes 32919aa04c91SAndre Guedes hci_add_adv_entry(hdev, ev); 32929aa04c91SAndre Guedes 32933c9e9195SAndre Guedes rssi = ev->data[ev->length]; 32943c9e9195SAndre Guedes mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type, 32953c9e9195SAndre Guedes NULL, rssi, 0, ev->data, ev->length); 32963c9e9195SAndre Guedes 3297e95beb41SAndre Guedes ptr += sizeof(*ev) + ev->length + 1; 32989aa04c91SAndre Guedes } 32999aa04c91SAndre Guedes 33009aa04c91SAndre Guedes hci_dev_unlock(hdev); 33019aa04c91SAndre Guedes } 33029aa04c91SAndre Guedes 3303a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev, 3304a7a595f6SVinicius Costa Gomes struct sk_buff *skb) 3305a7a595f6SVinicius Costa Gomes { 3306a7a595f6SVinicius Costa Gomes struct hci_ev_le_ltk_req *ev = (void *) skb->data; 3307a7a595f6SVinicius Costa Gomes struct hci_cp_le_ltk_reply cp; 3308bea710feSVinicius Costa Gomes struct hci_cp_le_ltk_neg_reply neg; 3309a7a595f6SVinicius Costa Gomes struct hci_conn *conn; 3310c9839a11SVinicius Costa Gomes struct smp_ltk *ltk; 3311a7a595f6SVinicius Costa Gomes 3312a7a595f6SVinicius Costa Gomes BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle)); 3313a7a595f6SVinicius Costa Gomes 3314a7a595f6SVinicius Costa Gomes hci_dev_lock(hdev); 3315a7a595f6SVinicius Costa Gomes 3316a7a595f6SVinicius Costa Gomes conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3317bea710feSVinicius Costa Gomes if (conn == NULL) 3318bea710feSVinicius Costa Gomes goto not_found; 3319a7a595f6SVinicius Costa Gomes 3320bea710feSVinicius Costa Gomes ltk = hci_find_ltk(hdev, ev->ediv, ev->random); 3321bea710feSVinicius Costa Gomes if (ltk == NULL) 3322bea710feSVinicius Costa Gomes goto not_found; 3323bea710feSVinicius Costa Gomes 3324bea710feSVinicius Costa Gomes memcpy(cp.ltk, ltk->val, sizeof(ltk->val)); 3325a7a595f6SVinicius Costa Gomes cp.handle = cpu_to_le16(conn->handle); 3326c9839a11SVinicius Costa Gomes 3327c9839a11SVinicius Costa Gomes if (ltk->authenticated) 3328c9839a11SVinicius Costa Gomes conn->sec_level = BT_SECURITY_HIGH; 3329a7a595f6SVinicius Costa Gomes 3330a7a595f6SVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); 3331a7a595f6SVinicius Costa Gomes 3332c9839a11SVinicius Costa Gomes if (ltk->type & HCI_SMP_STK) { 3333c9839a11SVinicius Costa Gomes list_del(<k->list); 3334c9839a11SVinicius Costa Gomes kfree(ltk); 3335c9839a11SVinicius Costa Gomes } 3336c9839a11SVinicius Costa Gomes 3337a7a595f6SVinicius Costa Gomes hci_dev_unlock(hdev); 3338bea710feSVinicius Costa Gomes 3339bea710feSVinicius Costa Gomes return; 3340bea710feSVinicius Costa Gomes 3341bea710feSVinicius Costa Gomes not_found: 3342bea710feSVinicius Costa Gomes neg.handle = ev->handle; 3343bea710feSVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg); 3344bea710feSVinicius Costa Gomes hci_dev_unlock(hdev); 3345a7a595f6SVinicius Costa Gomes } 3346a7a595f6SVinicius Costa Gomes 3347fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 3348fcd89c09SVille Tervo { 3349fcd89c09SVille Tervo struct hci_ev_le_meta *le_ev = (void *) skb->data; 3350fcd89c09SVille Tervo 3351fcd89c09SVille Tervo skb_pull(skb, sizeof(*le_ev)); 3352fcd89c09SVille Tervo 3353fcd89c09SVille Tervo switch (le_ev->subevent) { 3354fcd89c09SVille Tervo case HCI_EV_LE_CONN_COMPLETE: 3355fcd89c09SVille Tervo hci_le_conn_complete_evt(hdev, skb); 3356fcd89c09SVille Tervo break; 3357fcd89c09SVille Tervo 33589aa04c91SAndre Guedes case HCI_EV_LE_ADVERTISING_REPORT: 33599aa04c91SAndre Guedes hci_le_adv_report_evt(hdev, skb); 33609aa04c91SAndre Guedes break; 33619aa04c91SAndre Guedes 3362a7a595f6SVinicius Costa Gomes case HCI_EV_LE_LTK_REQ: 3363a7a595f6SVinicius Costa Gomes hci_le_ltk_request_evt(hdev, skb); 3364a7a595f6SVinicius Costa Gomes break; 3365a7a595f6SVinicius Costa Gomes 3366fcd89c09SVille Tervo default: 3367fcd89c09SVille Tervo break; 3368fcd89c09SVille Tervo } 3369fcd89c09SVille Tervo } 3370fcd89c09SVille Tervo 33711da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 33721da177e4SLinus Torvalds { 3373a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 3374a9de9248SMarcel Holtmann __u8 event = hdr->evt; 33751da177e4SLinus Torvalds 33761da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 33771da177e4SLinus Torvalds 3378a9de9248SMarcel Holtmann switch (event) { 33791da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 33801da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 33811da177e4SLinus Torvalds break; 33821da177e4SLinus Torvalds 33831da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 33841da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 33851da177e4SLinus Torvalds break; 33861da177e4SLinus Torvalds 3387a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 3388a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 338921d9e30eSMarcel Holtmann break; 339021d9e30eSMarcel Holtmann 33911da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 33921da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 33931da177e4SLinus Torvalds break; 33941da177e4SLinus Torvalds 33951da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 33961da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 33971da177e4SLinus Torvalds break; 33981da177e4SLinus Torvalds 33991da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 34001da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 34011da177e4SLinus Torvalds break; 34021da177e4SLinus Torvalds 3403a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 3404a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 3405a9de9248SMarcel Holtmann break; 3406a9de9248SMarcel Holtmann 34071da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 34081da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 34091da177e4SLinus Torvalds break; 34101da177e4SLinus Torvalds 3411a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 3412a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 3413a9de9248SMarcel Holtmann break; 3414a9de9248SMarcel Holtmann 3415a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 3416a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 3417a9de9248SMarcel Holtmann break; 3418a9de9248SMarcel Holtmann 3419a9de9248SMarcel Holtmann case HCI_EV_REMOTE_VERSION: 3420a9de9248SMarcel Holtmann hci_remote_version_evt(hdev, skb); 3421a9de9248SMarcel Holtmann break; 3422a9de9248SMarcel Holtmann 3423a9de9248SMarcel Holtmann case HCI_EV_QOS_SETUP_COMPLETE: 3424a9de9248SMarcel Holtmann hci_qos_setup_complete_evt(hdev, skb); 3425a9de9248SMarcel Holtmann break; 3426a9de9248SMarcel Holtmann 3427a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 3428a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 3429a9de9248SMarcel Holtmann break; 3430a9de9248SMarcel Holtmann 3431a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 3432a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 3433a9de9248SMarcel Holtmann break; 3434a9de9248SMarcel Holtmann 3435a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 3436a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 3437a9de9248SMarcel Holtmann break; 3438a9de9248SMarcel Holtmann 3439a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 3440a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 3441a9de9248SMarcel Holtmann break; 3442a9de9248SMarcel Holtmann 3443a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 3444a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 34451da177e4SLinus Torvalds break; 34461da177e4SLinus Torvalds 34471da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 34481da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 34491da177e4SLinus Torvalds break; 34501da177e4SLinus Torvalds 34511da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 34521da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 34531da177e4SLinus Torvalds break; 34541da177e4SLinus Torvalds 34551da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 34561da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 34571da177e4SLinus Torvalds break; 34581da177e4SLinus Torvalds 34591da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 34601da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 34611da177e4SLinus Torvalds break; 34621da177e4SLinus Torvalds 3463a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 3464a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 3465a8746417SMarcel Holtmann break; 3466a8746417SMarcel Holtmann 346785a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 346885a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 346985a1e930SMarcel Holtmann break; 347085a1e930SMarcel Holtmann 3471a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 3472a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 3473a9de9248SMarcel Holtmann break; 3474a9de9248SMarcel Holtmann 3475a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 3476a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 3477a9de9248SMarcel Holtmann break; 3478a9de9248SMarcel Holtmann 3479a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 3480a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 3481a9de9248SMarcel Holtmann break; 3482a9de9248SMarcel Holtmann 3483a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_CHANGED: 3484a9de9248SMarcel Holtmann hci_sync_conn_changed_evt(hdev, skb); 3485a9de9248SMarcel Holtmann break; 3486a9de9248SMarcel Holtmann 348704837f64SMarcel Holtmann case HCI_EV_SNIFF_SUBRATE: 348804837f64SMarcel Holtmann hci_sniff_subrate_evt(hdev, skb); 348904837f64SMarcel Holtmann break; 349004837f64SMarcel Holtmann 3491a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 3492a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 34931da177e4SLinus Torvalds break; 34941da177e4SLinus Torvalds 34950493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 34960493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 34970493684eSMarcel Holtmann break; 34980493684eSMarcel Holtmann 349903b555e1SJohan Hedberg case HCI_EV_IO_CAPA_REPLY: 350003b555e1SJohan Hedberg hci_io_capa_reply_evt(hdev, skb); 350103b555e1SJohan Hedberg break; 350203b555e1SJohan Hedberg 3503a5c29683SJohan Hedberg case HCI_EV_USER_CONFIRM_REQUEST: 3504a5c29683SJohan Hedberg hci_user_confirm_request_evt(hdev, skb); 3505a5c29683SJohan Hedberg break; 3506a5c29683SJohan Hedberg 35071143d458SBrian Gix case HCI_EV_USER_PASSKEY_REQUEST: 35081143d458SBrian Gix hci_user_passkey_request_evt(hdev, skb); 35091143d458SBrian Gix break; 35101143d458SBrian Gix 35110493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 35120493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 35130493684eSMarcel Holtmann break; 35140493684eSMarcel Holtmann 351541a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 351641a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 351741a96212SMarcel Holtmann break; 351841a96212SMarcel Holtmann 3519fcd89c09SVille Tervo case HCI_EV_LE_META: 3520fcd89c09SVille Tervo hci_le_meta_evt(hdev, skb); 3521fcd89c09SVille Tervo break; 3522fcd89c09SVille Tervo 35232763eda6SSzymon Janc case HCI_EV_REMOTE_OOB_DATA_REQUEST: 35242763eda6SSzymon Janc hci_remote_oob_data_request_evt(hdev, skb); 35252763eda6SSzymon Janc break; 35262763eda6SSzymon Janc 352725e89e99SAndrei Emeltchenko case HCI_EV_NUM_COMP_BLOCKS: 352825e89e99SAndrei Emeltchenko hci_num_comp_blocks_evt(hdev, skb); 352925e89e99SAndrei Emeltchenko break; 353025e89e99SAndrei Emeltchenko 35311da177e4SLinus Torvalds default: 3532a9de9248SMarcel Holtmann BT_DBG("%s event 0x%x", hdev->name, event); 35331da177e4SLinus Torvalds break; 35341da177e4SLinus Torvalds } 35351da177e4SLinus Torvalds 35361da177e4SLinus Torvalds kfree_skb(skb); 35371da177e4SLinus Torvalds hdev->stat.evt_rx++; 35381da177e4SLinus Torvalds } 3539