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 212f51d5b24SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 213f51d5b24SJohan Hedberg mgmt_set_local_name_complete(hdev, sent, status); 21428cc7bdeSJohan Hedberg else if (!status) 21528cc7bdeSJohan Hedberg memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); 216f51d5b24SJohan Hedberg 21756e5cb86SJohan Hedberg hci_dev_unlock(hdev); 218a9de9248SMarcel Holtmann } 219a9de9248SMarcel Holtmann 220a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) 221a9de9248SMarcel Holtmann { 222a9de9248SMarcel Holtmann struct hci_rp_read_local_name *rp = (void *) skb->data; 223a9de9248SMarcel Holtmann 224a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 225a9de9248SMarcel Holtmann 226a9de9248SMarcel Holtmann if (rp->status) 227a9de9248SMarcel Holtmann return; 228a9de9248SMarcel Holtmann 229db99b5fcSJohan Hedberg if (test_bit(HCI_SETUP, &hdev->dev_flags)) 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 353a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); 354a9de9248SMarcel Holtmann if (!sent) 355a9de9248SMarcel Holtmann return; 356a9de9248SMarcel Holtmann 3577f9a903cSMarcel Holtmann hci_dev_lock(hdev); 3587f9a903cSMarcel Holtmann 3597f9a903cSMarcel Holtmann if (status == 0) 360a9de9248SMarcel Holtmann memcpy(hdev->dev_class, sent, 3); 3617f9a903cSMarcel Holtmann 3627f9a903cSMarcel Holtmann if (test_bit(HCI_MGMT, &hdev->dev_flags)) 3637f9a903cSMarcel Holtmann mgmt_set_class_of_dev_complete(hdev, sent, status); 3647f9a903cSMarcel Holtmann 3657f9a903cSMarcel Holtmann hci_dev_unlock(hdev); 366a9de9248SMarcel Holtmann } 367a9de9248SMarcel Holtmann 368a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 369a9de9248SMarcel Holtmann { 370a9de9248SMarcel Holtmann struct hci_rp_read_voice_setting *rp = (void *) skb->data; 371a9de9248SMarcel Holtmann __u16 setting; 372a9de9248SMarcel Holtmann 373a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 374a9de9248SMarcel Holtmann 375a9de9248SMarcel Holtmann if (rp->status) 376a9de9248SMarcel Holtmann return; 377a9de9248SMarcel Holtmann 378a9de9248SMarcel Holtmann setting = __le16_to_cpu(rp->voice_setting); 379a9de9248SMarcel Holtmann 380a9de9248SMarcel Holtmann if (hdev->voice_setting == setting) 381a9de9248SMarcel Holtmann return; 382a9de9248SMarcel Holtmann 383a9de9248SMarcel Holtmann hdev->voice_setting = setting; 384a9de9248SMarcel Holtmann 385a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 386a9de9248SMarcel Holtmann 3873c54711cSGustavo F. Padovan if (hdev->notify) 388a9de9248SMarcel Holtmann hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 389a9de9248SMarcel Holtmann } 390a9de9248SMarcel Holtmann 391a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 392a9de9248SMarcel Holtmann { 393a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 394f383f275SMarcel Holtmann __u16 setting; 395a9de9248SMarcel Holtmann void *sent; 396a9de9248SMarcel Holtmann 397a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 398a9de9248SMarcel Holtmann 399f383f275SMarcel Holtmann if (status) 400f383f275SMarcel Holtmann return; 401f383f275SMarcel Holtmann 402a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); 403a9de9248SMarcel Holtmann if (!sent) 404a9de9248SMarcel Holtmann return; 405a9de9248SMarcel Holtmann 406f383f275SMarcel Holtmann setting = get_unaligned_le16(sent); 4071da177e4SLinus Torvalds 408f383f275SMarcel Holtmann if (hdev->voice_setting == setting) 409f383f275SMarcel Holtmann return; 410f383f275SMarcel Holtmann 4111da177e4SLinus Torvalds hdev->voice_setting = setting; 4121da177e4SLinus Torvalds 413a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 4141da177e4SLinus Torvalds 4153c54711cSGustavo F. Padovan if (hdev->notify) 4161da177e4SLinus Torvalds hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 4171da177e4SLinus Torvalds } 4181da177e4SLinus Torvalds 419a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 4201da177e4SLinus Torvalds { 421a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 4221da177e4SLinus Torvalds 423a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 4241da177e4SLinus Torvalds 42523bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status); 4261143e5a6SMarcel Holtmann } 4271143e5a6SMarcel Holtmann 428333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 429333140b5SMarcel Holtmann { 430333140b5SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 431333140b5SMarcel Holtmann void *sent; 432333140b5SMarcel Holtmann 433333140b5SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 434333140b5SMarcel Holtmann 435333140b5SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); 436333140b5SMarcel Holtmann if (!sent) 437333140b5SMarcel Holtmann return; 438333140b5SMarcel Holtmann 439c0ecddc2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 440c0ecddc2SJohan Hedberg mgmt_ssp_enable_complete(hdev, *((u8 *) sent), status); 441c0ecddc2SJohan Hedberg else if (!status) { 44284bde9d6SJohan Hedberg if (*((u8 *) sent)) 44384bde9d6SJohan Hedberg set_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 44484bde9d6SJohan Hedberg else 44584bde9d6SJohan Hedberg clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 446c0ecddc2SJohan Hedberg } 447333140b5SMarcel Holtmann } 448333140b5SMarcel Holtmann 449d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev) 450d5859e22SJohan Hedberg { 451d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 452d5859e22SJohan Hedberg return 2; 453d5859e22SJohan Hedberg 454d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 455d5859e22SJohan Hedberg return 1; 456d5859e22SJohan Hedberg 457d5859e22SJohan Hedberg if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 && 458d5859e22SJohan Hedberg hdev->lmp_subver == 0x0757) 459d5859e22SJohan Hedberg return 1; 460d5859e22SJohan Hedberg 461d5859e22SJohan Hedberg if (hdev->manufacturer == 15) { 462d5859e22SJohan Hedberg if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963) 463d5859e22SJohan Hedberg return 1; 464d5859e22SJohan Hedberg if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963) 465d5859e22SJohan Hedberg return 1; 466d5859e22SJohan Hedberg if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965) 467d5859e22SJohan Hedberg return 1; 468d5859e22SJohan Hedberg } 469d5859e22SJohan Hedberg 470d5859e22SJohan Hedberg if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 && 471d5859e22SJohan Hedberg hdev->lmp_subver == 0x1805) 472d5859e22SJohan Hedberg return 1; 473d5859e22SJohan Hedberg 474d5859e22SJohan Hedberg return 0; 475d5859e22SJohan Hedberg } 476d5859e22SJohan Hedberg 477d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev) 478d5859e22SJohan Hedberg { 479d5859e22SJohan Hedberg u8 mode; 480d5859e22SJohan Hedberg 481d5859e22SJohan Hedberg mode = hci_get_inquiry_mode(hdev); 482d5859e22SJohan Hedberg 483d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode); 484d5859e22SJohan Hedberg } 485d5859e22SJohan Hedberg 486d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev) 487d5859e22SJohan Hedberg { 488d5859e22SJohan Hedberg /* The second byte is 0xff instead of 0x9f (two reserved bits 489d5859e22SJohan Hedberg * disabled) since a Broadcom 1.2 dongle doesn't respond to the 490d5859e22SJohan Hedberg * command otherwise */ 491d5859e22SJohan Hedberg u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 }; 492d5859e22SJohan Hedberg 4936de6c18dSVille Tervo /* CSR 1.1 dongles does not accept any bitfield so don't try to set 4946de6c18dSVille Tervo * any event mask for pre 1.2 devices */ 4955a13b095SAndrei Emeltchenko if (hdev->hci_ver < BLUETOOTH_VER_1_2) 4966de6c18dSVille Tervo return; 4976de6c18dSVille Tervo 498d5859e22SJohan Hedberg events[4] |= 0x01; /* Flow Specification Complete */ 499d5859e22SJohan Hedberg events[4] |= 0x02; /* Inquiry Result with RSSI */ 500d5859e22SJohan Hedberg events[4] |= 0x04; /* Read Remote Extended Features Complete */ 501d5859e22SJohan Hedberg events[5] |= 0x08; /* Synchronous Connection Complete */ 502d5859e22SJohan Hedberg events[5] |= 0x10; /* Synchronous Connection Changed */ 503d5859e22SJohan Hedberg 504d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 505d5859e22SJohan Hedberg events[4] |= 0x04; /* Inquiry Result with RSSI */ 506d5859e22SJohan Hedberg 507d5859e22SJohan Hedberg if (hdev->features[5] & LMP_SNIFF_SUBR) 508d5859e22SJohan Hedberg events[5] |= 0x20; /* Sniff Subrating */ 509d5859e22SJohan Hedberg 510d5859e22SJohan Hedberg if (hdev->features[5] & LMP_PAUSE_ENC) 511d5859e22SJohan Hedberg events[5] |= 0x80; /* Encryption Key Refresh Complete */ 512d5859e22SJohan Hedberg 513d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 514d5859e22SJohan Hedberg events[5] |= 0x40; /* Extended Inquiry Result */ 515d5859e22SJohan Hedberg 516d5859e22SJohan Hedberg if (hdev->features[6] & LMP_NO_FLUSH) 517d5859e22SJohan Hedberg events[7] |= 0x01; /* Enhanced Flush Complete */ 518d5859e22SJohan Hedberg 519d5859e22SJohan Hedberg if (hdev->features[7] & LMP_LSTO) 520d5859e22SJohan Hedberg events[6] |= 0x80; /* Link Supervision Timeout Changed */ 521d5859e22SJohan Hedberg 522d5859e22SJohan Hedberg if (hdev->features[6] & LMP_SIMPLE_PAIR) { 523d5859e22SJohan Hedberg events[6] |= 0x01; /* IO Capability Request */ 524d5859e22SJohan Hedberg events[6] |= 0x02; /* IO Capability Response */ 525d5859e22SJohan Hedberg events[6] |= 0x04; /* User Confirmation Request */ 526d5859e22SJohan Hedberg events[6] |= 0x08; /* User Passkey Request */ 527d5859e22SJohan Hedberg events[6] |= 0x10; /* Remote OOB Data Request */ 528d5859e22SJohan Hedberg events[6] |= 0x20; /* Simple Pairing Complete */ 529d5859e22SJohan Hedberg events[7] |= 0x04; /* User Passkey Notification */ 530d5859e22SJohan Hedberg events[7] |= 0x08; /* Keypress Notification */ 531d5859e22SJohan Hedberg events[7] |= 0x10; /* Remote Host Supported 532d5859e22SJohan Hedberg * Features Notification */ 533d5859e22SJohan Hedberg } 534d5859e22SJohan Hedberg 535d5859e22SJohan Hedberg if (hdev->features[4] & LMP_LE) 536d5859e22SJohan Hedberg events[7] |= 0x20; /* LE Meta-Event */ 537d5859e22SJohan Hedberg 538d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); 539d5859e22SJohan Hedberg } 540d5859e22SJohan Hedberg 541e6100a25SAndre Guedes static void hci_set_le_support(struct hci_dev *hdev) 542e6100a25SAndre Guedes { 543e6100a25SAndre Guedes struct hci_cp_write_le_host_supported cp; 544e6100a25SAndre Guedes 545e6100a25SAndre Guedes memset(&cp, 0, sizeof(cp)); 546e6100a25SAndre Guedes 54706199cf8SJohan Hedberg if (enable_le && test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { 548e6100a25SAndre Guedes cp.le = 1; 549e6100a25SAndre Guedes cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR); 550e6100a25SAndre Guedes } 551e6100a25SAndre Guedes 552e6100a25SAndre Guedes hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), &cp); 553e6100a25SAndre Guedes } 554e6100a25SAndre Guedes 555d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev) 556d5859e22SJohan Hedberg { 557e61ef499SAndrei Emeltchenko if (hdev->dev_type != HCI_BREDR) 558e61ef499SAndrei Emeltchenko return; 559e61ef499SAndrei Emeltchenko 560d5859e22SJohan Hedberg hci_setup_event_mask(hdev); 561d5859e22SJohan Hedberg 562d095c1ebSAndrei Emeltchenko if (hdev->hci_ver > BLUETOOTH_VER_1_1) 563d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); 564d5859e22SJohan Hedberg 56528cc7bdeSJohan Hedberg if (!test_bit(HCI_SETUP, &hdev->dev_flags) && 56628cc7bdeSJohan Hedberg test_bit(HCI_MGMT, &hdev->dev_flags)) { 56728cc7bdeSJohan Hedberg struct hci_cp_write_local_name cp; 56828cc7bdeSJohan Hedberg 56928cc7bdeSJohan Hedberg memcpy(cp.name, hdev->dev_name, sizeof(cp.name)); 57028cc7bdeSJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp); 57128cc7bdeSJohan Hedberg } 57228cc7bdeSJohan Hedberg 57354d04dbbSJohan Hedberg if (hdev->features[6] & LMP_SIMPLE_PAIR) { 57454d04dbbSJohan Hedberg if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { 575d5859e22SJohan Hedberg u8 mode = 0x01; 57654d04dbbSJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 57754d04dbbSJohan Hedberg sizeof(mode), &mode); 57854d04dbbSJohan Hedberg } else { 57954d04dbbSJohan Hedberg struct hci_cp_write_eir cp; 58054d04dbbSJohan Hedberg 58154d04dbbSJohan Hedberg memset(hdev->eir, 0, sizeof(hdev->eir)); 58254d04dbbSJohan Hedberg memset(&cp, 0, sizeof(cp)); 58354d04dbbSJohan Hedberg 58454d04dbbSJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp); 58554d04dbbSJohan Hedberg } 586d5859e22SJohan Hedberg } 587d5859e22SJohan Hedberg 588d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 589d5859e22SJohan Hedberg hci_setup_inquiry_mode(hdev); 590d5859e22SJohan Hedberg 591d5859e22SJohan Hedberg if (hdev->features[7] & LMP_INQ_TX_PWR) 592d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL); 593971e3a4bSAndre Guedes 594971e3a4bSAndre Guedes if (hdev->features[7] & LMP_EXTFEATURES) { 595971e3a4bSAndre Guedes struct hci_cp_read_local_ext_features cp; 596971e3a4bSAndre Guedes 597971e3a4bSAndre Guedes cp.page = 0x01; 598971e3a4bSAndre Guedes hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, 599971e3a4bSAndre Guedes sizeof(cp), &cp); 600971e3a4bSAndre Guedes } 601e6100a25SAndre Guedes 60247990ea0SJohan Hedberg if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) { 60347990ea0SJohan Hedberg u8 enable = 1; 60447990ea0SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, 60547990ea0SJohan Hedberg sizeof(enable), &enable); 60647990ea0SJohan Hedberg } 60747990ea0SJohan Hedberg 608e6100a25SAndre Guedes if (hdev->features[4] & LMP_LE) 609e6100a25SAndre Guedes hci_set_le_support(hdev); 610d5859e22SJohan Hedberg } 611d5859e22SJohan Hedberg 612a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) 613a9de9248SMarcel Holtmann { 614a9de9248SMarcel Holtmann struct hci_rp_read_local_version *rp = (void *) skb->data; 6151143e5a6SMarcel Holtmann 616a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 6171143e5a6SMarcel Holtmann 618a9de9248SMarcel Holtmann if (rp->status) 619a9de9248SMarcel Holtmann return; 6201143e5a6SMarcel Holtmann 621a9de9248SMarcel Holtmann hdev->hci_ver = rp->hci_ver; 622e4e8e37cSMarcel Holtmann hdev->hci_rev = __le16_to_cpu(rp->hci_rev); 623d5859e22SJohan Hedberg hdev->lmp_ver = rp->lmp_ver; 624e4e8e37cSMarcel Holtmann hdev->manufacturer = __le16_to_cpu(rp->manufacturer); 625d5859e22SJohan Hedberg hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); 6261da177e4SLinus Torvalds 627a9de9248SMarcel Holtmann BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name, 628a9de9248SMarcel Holtmann hdev->manufacturer, 629a9de9248SMarcel Holtmann hdev->hci_ver, hdev->hci_rev); 630d5859e22SJohan Hedberg 631d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags)) 632d5859e22SJohan Hedberg hci_setup(hdev); 633d5859e22SJohan Hedberg } 634d5859e22SJohan Hedberg 635d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev) 636d5859e22SJohan Hedberg { 637d5859e22SJohan Hedberg u16 link_policy = 0; 638d5859e22SJohan Hedberg 639d5859e22SJohan Hedberg if (hdev->features[0] & LMP_RSWITCH) 640d5859e22SJohan Hedberg link_policy |= HCI_LP_RSWITCH; 641d5859e22SJohan Hedberg if (hdev->features[0] & LMP_HOLD) 642d5859e22SJohan Hedberg link_policy |= HCI_LP_HOLD; 643d5859e22SJohan Hedberg if (hdev->features[0] & LMP_SNIFF) 644d5859e22SJohan Hedberg link_policy |= HCI_LP_SNIFF; 645d5859e22SJohan Hedberg if (hdev->features[1] & LMP_PARK) 646d5859e22SJohan Hedberg link_policy |= HCI_LP_PARK; 647d5859e22SJohan Hedberg 648d5859e22SJohan Hedberg link_policy = cpu_to_le16(link_policy); 649d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, 650d5859e22SJohan Hedberg sizeof(link_policy), &link_policy); 6511da177e4SLinus Torvalds } 6521da177e4SLinus Torvalds 653a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb) 654a9de9248SMarcel Holtmann { 655a9de9248SMarcel Holtmann struct hci_rp_read_local_commands *rp = (void *) skb->data; 656a9de9248SMarcel Holtmann 657a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 658a9de9248SMarcel Holtmann 659a9de9248SMarcel Holtmann if (rp->status) 660d5859e22SJohan Hedberg goto done; 661a9de9248SMarcel Holtmann 662a9de9248SMarcel Holtmann memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); 663d5859e22SJohan Hedberg 664d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10)) 665d5859e22SJohan Hedberg hci_setup_link_policy(hdev); 666d5859e22SJohan Hedberg 667d5859e22SJohan Hedberg done: 668d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status); 669a9de9248SMarcel Holtmann } 670a9de9248SMarcel Holtmann 671a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb) 672a9de9248SMarcel Holtmann { 673a9de9248SMarcel Holtmann struct hci_rp_read_local_features *rp = (void *) skb->data; 674a9de9248SMarcel Holtmann 675a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 676a9de9248SMarcel Holtmann 677a9de9248SMarcel Holtmann if (rp->status) 678a9de9248SMarcel Holtmann return; 679a9de9248SMarcel Holtmann 680a9de9248SMarcel Holtmann memcpy(hdev->features, rp->features, 8); 6811da177e4SLinus Torvalds 6821da177e4SLinus Torvalds /* Adjust default settings according to features 6831da177e4SLinus Torvalds * supported by device. */ 684a9de9248SMarcel Holtmann 6851da177e4SLinus Torvalds if (hdev->features[0] & LMP_3SLOT) 6861da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM3 | HCI_DH3); 6871da177e4SLinus Torvalds 6881da177e4SLinus Torvalds if (hdev->features[0] & LMP_5SLOT) 6891da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM5 | HCI_DH5); 6901da177e4SLinus Torvalds 6915b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV2) { 6921da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV2); 6935b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV2); 6945b7f9909SMarcel Holtmann } 6951da177e4SLinus Torvalds 6965b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV3) { 6971da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV3); 6985b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV3); 6995b7f9909SMarcel Holtmann } 7005b7f9909SMarcel Holtmann 7015b7f9909SMarcel Holtmann if (hdev->features[3] & LMP_ESCO) 7025b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV3); 7035b7f9909SMarcel Holtmann 7045b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV4) 7055b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV4); 7065b7f9909SMarcel Holtmann 7075b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV5) 7085b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV5); 7091da177e4SLinus Torvalds 710efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_2M) 711efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV3); 712efc7688bSMarcel Holtmann 713efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_3M) 714efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_3EV3); 715efc7688bSMarcel Holtmann 716efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_3S_ESCO) 717efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); 718efc7688bSMarcel Holtmann 719a9de9248SMarcel Holtmann BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, 720a9de9248SMarcel Holtmann hdev->features[0], hdev->features[1], 721a9de9248SMarcel Holtmann hdev->features[2], hdev->features[3], 722a9de9248SMarcel Holtmann hdev->features[4], hdev->features[5], 723a9de9248SMarcel Holtmann hdev->features[6], hdev->features[7]); 7241da177e4SLinus Torvalds } 7251da177e4SLinus Torvalds 726971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev, 727971e3a4bSAndre Guedes struct sk_buff *skb) 728971e3a4bSAndre Guedes { 729971e3a4bSAndre Guedes struct hci_rp_read_local_ext_features *rp = (void *) skb->data; 730971e3a4bSAndre Guedes 731971e3a4bSAndre Guedes BT_DBG("%s status 0x%x", hdev->name, rp->status); 732971e3a4bSAndre Guedes 733971e3a4bSAndre Guedes if (rp->status) 734971e3a4bSAndre Guedes return; 735971e3a4bSAndre Guedes 736b5b32b65SAndre Guedes switch (rp->page) { 737b5b32b65SAndre Guedes case 0: 738b5b32b65SAndre Guedes memcpy(hdev->features, rp->features, 8); 739b5b32b65SAndre Guedes break; 740b5b32b65SAndre Guedes case 1: 74159e29406SAndre Guedes memcpy(hdev->host_features, rp->features, 8); 742b5b32b65SAndre Guedes break; 743b5b32b65SAndre Guedes } 744971e3a4bSAndre Guedes 745971e3a4bSAndre Guedes hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status); 746971e3a4bSAndre Guedes } 747971e3a4bSAndre Guedes 7481e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, 7491e89cffbSAndrei Emeltchenko struct sk_buff *skb) 7501e89cffbSAndrei Emeltchenko { 7511e89cffbSAndrei Emeltchenko struct hci_rp_read_flow_control_mode *rp = (void *) skb->data; 7521e89cffbSAndrei Emeltchenko 7531e89cffbSAndrei Emeltchenko BT_DBG("%s status 0x%x", hdev->name, rp->status); 7541e89cffbSAndrei Emeltchenko 7551e89cffbSAndrei Emeltchenko if (rp->status) 7561e89cffbSAndrei Emeltchenko return; 7571e89cffbSAndrei Emeltchenko 7581e89cffbSAndrei Emeltchenko hdev->flow_ctl_mode = rp->mode; 7591e89cffbSAndrei Emeltchenko 7601e89cffbSAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status); 7611e89cffbSAndrei Emeltchenko } 7621e89cffbSAndrei Emeltchenko 763a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 764a9de9248SMarcel Holtmann { 765a9de9248SMarcel Holtmann struct hci_rp_read_buffer_size *rp = (void *) skb->data; 766a9de9248SMarcel Holtmann 767a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 768a9de9248SMarcel Holtmann 769a9de9248SMarcel Holtmann if (rp->status) 770a9de9248SMarcel Holtmann return; 771a9de9248SMarcel Holtmann 772a9de9248SMarcel Holtmann hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); 773a9de9248SMarcel Holtmann hdev->sco_mtu = rp->sco_mtu; 774a9de9248SMarcel Holtmann hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); 775a9de9248SMarcel Holtmann hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); 776da1f5198SMarcel Holtmann 777da1f5198SMarcel Holtmann if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { 778da1f5198SMarcel Holtmann hdev->sco_mtu = 64; 779da1f5198SMarcel Holtmann hdev->sco_pkts = 8; 780da1f5198SMarcel Holtmann } 781da1f5198SMarcel Holtmann 782da1f5198SMarcel Holtmann hdev->acl_cnt = hdev->acl_pkts; 783da1f5198SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 7841da177e4SLinus Torvalds 785a9de9248SMarcel Holtmann BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, 786a9de9248SMarcel Holtmann hdev->acl_mtu, hdev->acl_pkts, 787a9de9248SMarcel Holtmann hdev->sco_mtu, hdev->sco_pkts); 7881da177e4SLinus Torvalds } 7891da177e4SLinus Torvalds 790a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) 791a9de9248SMarcel Holtmann { 792a9de9248SMarcel Holtmann struct hci_rp_read_bd_addr *rp = (void *) skb->data; 7931da177e4SLinus Torvalds 794a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 795a9de9248SMarcel Holtmann 796a9de9248SMarcel Holtmann if (!rp->status) 797a9de9248SMarcel Holtmann bacpy(&hdev->bdaddr, &rp->bdaddr); 798a9de9248SMarcel Holtmann 79923bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status); 80023bb5763SJohan Hedberg } 80123bb5763SJohan Hedberg 802350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev, 803350ee4cfSAndrei Emeltchenko struct sk_buff *skb) 804350ee4cfSAndrei Emeltchenko { 805350ee4cfSAndrei Emeltchenko struct hci_rp_read_data_block_size *rp = (void *) skb->data; 806350ee4cfSAndrei Emeltchenko 807350ee4cfSAndrei Emeltchenko BT_DBG("%s status 0x%x", hdev->name, rp->status); 808350ee4cfSAndrei Emeltchenko 809350ee4cfSAndrei Emeltchenko if (rp->status) 810350ee4cfSAndrei Emeltchenko return; 811350ee4cfSAndrei Emeltchenko 812350ee4cfSAndrei Emeltchenko hdev->block_mtu = __le16_to_cpu(rp->max_acl_len); 813350ee4cfSAndrei Emeltchenko hdev->block_len = __le16_to_cpu(rp->block_len); 814350ee4cfSAndrei Emeltchenko hdev->num_blocks = __le16_to_cpu(rp->num_blocks); 815350ee4cfSAndrei Emeltchenko 816350ee4cfSAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 817350ee4cfSAndrei Emeltchenko 818350ee4cfSAndrei Emeltchenko BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu, 819350ee4cfSAndrei Emeltchenko hdev->block_cnt, hdev->block_len); 820350ee4cfSAndrei Emeltchenko 821350ee4cfSAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status); 822350ee4cfSAndrei Emeltchenko } 823350ee4cfSAndrei Emeltchenko 82423bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb) 82523bb5763SJohan Hedberg { 82623bb5763SJohan Hedberg __u8 status = *((__u8 *) skb->data); 82723bb5763SJohan Hedberg 82823bb5763SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 82923bb5763SJohan Hedberg 83023bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status); 8311da177e4SLinus Torvalds } 8321da177e4SLinus Torvalds 833928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev, 834928abaa7SAndrei Emeltchenko struct sk_buff *skb) 835928abaa7SAndrei Emeltchenko { 836928abaa7SAndrei Emeltchenko struct hci_rp_read_local_amp_info *rp = (void *) skb->data; 837928abaa7SAndrei Emeltchenko 838928abaa7SAndrei Emeltchenko BT_DBG("%s status 0x%x", hdev->name, rp->status); 839928abaa7SAndrei Emeltchenko 840928abaa7SAndrei Emeltchenko if (rp->status) 841928abaa7SAndrei Emeltchenko return; 842928abaa7SAndrei Emeltchenko 843928abaa7SAndrei Emeltchenko hdev->amp_status = rp->amp_status; 844928abaa7SAndrei Emeltchenko hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); 845928abaa7SAndrei Emeltchenko hdev->amp_max_bw = __le32_to_cpu(rp->max_bw); 846928abaa7SAndrei Emeltchenko hdev->amp_min_latency = __le32_to_cpu(rp->min_latency); 847928abaa7SAndrei Emeltchenko hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu); 848928abaa7SAndrei Emeltchenko hdev->amp_type = rp->amp_type; 849928abaa7SAndrei Emeltchenko hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap); 850928abaa7SAndrei Emeltchenko hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size); 851928abaa7SAndrei Emeltchenko hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); 852928abaa7SAndrei Emeltchenko hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); 853928abaa7SAndrei Emeltchenko 854928abaa7SAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status); 855928abaa7SAndrei Emeltchenko } 856928abaa7SAndrei Emeltchenko 857b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, 858b0916ea0SJohan Hedberg struct sk_buff *skb) 859b0916ea0SJohan Hedberg { 860b0916ea0SJohan Hedberg __u8 status = *((__u8 *) skb->data); 861b0916ea0SJohan Hedberg 862b0916ea0SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 863b0916ea0SJohan Hedberg 864b0916ea0SJohan Hedberg hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status); 865b0916ea0SJohan Hedberg } 866b0916ea0SJohan Hedberg 867d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb) 868d5859e22SJohan Hedberg { 869d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 870d5859e22SJohan Hedberg 871d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 872d5859e22SJohan Hedberg 873d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status); 874d5859e22SJohan Hedberg } 875d5859e22SJohan Hedberg 876d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev, 877d5859e22SJohan Hedberg struct sk_buff *skb) 878d5859e22SJohan Hedberg { 879d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 880d5859e22SJohan Hedberg 881d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 882d5859e22SJohan Hedberg 883d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status); 884d5859e22SJohan Hedberg } 885d5859e22SJohan Hedberg 886d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, 887d5859e22SJohan Hedberg struct sk_buff *skb) 888d5859e22SJohan Hedberg { 889d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 890d5859e22SJohan Hedberg 891d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 892d5859e22SJohan Hedberg 893d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status); 894d5859e22SJohan Hedberg } 895d5859e22SJohan Hedberg 896d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb) 897d5859e22SJohan Hedberg { 898d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 899d5859e22SJohan Hedberg 900d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 901d5859e22SJohan Hedberg 902d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status); 903d5859e22SJohan Hedberg } 904d5859e22SJohan Hedberg 905980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) 906980e1a53SJohan Hedberg { 907980e1a53SJohan Hedberg struct hci_rp_pin_code_reply *rp = (void *) skb->data; 908980e1a53SJohan Hedberg struct hci_cp_pin_code_reply *cp; 909980e1a53SJohan Hedberg struct hci_conn *conn; 910980e1a53SJohan Hedberg 911980e1a53SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 912980e1a53SJohan Hedberg 91356e5cb86SJohan Hedberg hci_dev_lock(hdev); 91456e5cb86SJohan Hedberg 915a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 916744cf19eSJohan Hedberg mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); 917980e1a53SJohan Hedberg 918980e1a53SJohan Hedberg if (rp->status != 0) 91956e5cb86SJohan Hedberg goto unlock; 920980e1a53SJohan Hedberg 921980e1a53SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); 922980e1a53SJohan Hedberg if (!cp) 92356e5cb86SJohan Hedberg goto unlock; 924980e1a53SJohan Hedberg 925980e1a53SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 926980e1a53SJohan Hedberg if (conn) 927980e1a53SJohan Hedberg conn->pin_length = cp->pin_len; 92856e5cb86SJohan Hedberg 92956e5cb86SJohan Hedberg unlock: 93056e5cb86SJohan Hedberg hci_dev_unlock(hdev); 931980e1a53SJohan Hedberg } 932980e1a53SJohan Hedberg 933980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 934980e1a53SJohan Hedberg { 935980e1a53SJohan Hedberg struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data; 936980e1a53SJohan Hedberg 937980e1a53SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 938980e1a53SJohan Hedberg 93956e5cb86SJohan Hedberg hci_dev_lock(hdev); 94056e5cb86SJohan Hedberg 941a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 942744cf19eSJohan Hedberg mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr, 943980e1a53SJohan Hedberg rp->status); 94456e5cb86SJohan Hedberg 94556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 946980e1a53SJohan Hedberg } 94756e5cb86SJohan Hedberg 9486ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, 9496ed58ec5SVille Tervo struct sk_buff *skb) 9506ed58ec5SVille Tervo { 9516ed58ec5SVille Tervo struct hci_rp_le_read_buffer_size *rp = (void *) skb->data; 9526ed58ec5SVille Tervo 9536ed58ec5SVille Tervo BT_DBG("%s status 0x%x", hdev->name, rp->status); 9546ed58ec5SVille Tervo 9556ed58ec5SVille Tervo if (rp->status) 9566ed58ec5SVille Tervo return; 9576ed58ec5SVille Tervo 9586ed58ec5SVille Tervo hdev->le_mtu = __le16_to_cpu(rp->le_mtu); 9596ed58ec5SVille Tervo hdev->le_pkts = rp->le_max_pkt; 9606ed58ec5SVille Tervo 9616ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 9626ed58ec5SVille Tervo 9636ed58ec5SVille Tervo BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); 9646ed58ec5SVille Tervo 9656ed58ec5SVille Tervo hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status); 9666ed58ec5SVille Tervo } 967980e1a53SJohan Hedberg 968a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) 969a5c29683SJohan Hedberg { 970a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 971a5c29683SJohan Hedberg 972a5c29683SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 973a5c29683SJohan Hedberg 97456e5cb86SJohan Hedberg hci_dev_lock(hdev); 97556e5cb86SJohan Hedberg 976a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 977272d90dfSJohan Hedberg mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 978272d90dfSJohan Hedberg 0, rp->status); 97956e5cb86SJohan Hedberg 98056e5cb86SJohan Hedberg hci_dev_unlock(hdev); 981a5c29683SJohan Hedberg } 982a5c29683SJohan Hedberg 983a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, 984a5c29683SJohan Hedberg struct sk_buff *skb) 985a5c29683SJohan Hedberg { 986a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 987a5c29683SJohan Hedberg 988a5c29683SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 989a5c29683SJohan Hedberg 99056e5cb86SJohan Hedberg hci_dev_lock(hdev); 99156e5cb86SJohan Hedberg 992a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 993744cf19eSJohan Hedberg mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr, 994272d90dfSJohan Hedberg ACL_LINK, 0, 995a5c29683SJohan Hedberg rp->status); 99656e5cb86SJohan Hedberg 99756e5cb86SJohan Hedberg hci_dev_unlock(hdev); 998a5c29683SJohan Hedberg } 999a5c29683SJohan Hedberg 10001143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb) 10011143d458SBrian Gix { 10021143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 10031143d458SBrian Gix 10041143d458SBrian Gix BT_DBG("%s status 0x%x", hdev->name, rp->status); 10051143d458SBrian Gix 10061143d458SBrian Gix hci_dev_lock(hdev); 10071143d458SBrian Gix 1008a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1009272d90dfSJohan Hedberg mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 1010272d90dfSJohan Hedberg 0, rp->status); 10111143d458SBrian Gix 10121143d458SBrian Gix hci_dev_unlock(hdev); 10131143d458SBrian Gix } 10141143d458SBrian Gix 10151143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, 10161143d458SBrian Gix struct sk_buff *skb) 10171143d458SBrian Gix { 10181143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 10191143d458SBrian Gix 10201143d458SBrian Gix BT_DBG("%s status 0x%x", hdev->name, rp->status); 10211143d458SBrian Gix 10221143d458SBrian Gix hci_dev_lock(hdev); 10231143d458SBrian Gix 1024a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 10251143d458SBrian Gix mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr, 1026272d90dfSJohan Hedberg ACL_LINK, 0, 10271143d458SBrian Gix rp->status); 10281143d458SBrian Gix 10291143d458SBrian Gix hci_dev_unlock(hdev); 10301143d458SBrian Gix } 10311143d458SBrian Gix 1032c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, 1033c35938b2SSzymon Janc struct sk_buff *skb) 1034c35938b2SSzymon Janc { 1035c35938b2SSzymon Janc struct hci_rp_read_local_oob_data *rp = (void *) skb->data; 1036c35938b2SSzymon Janc 1037c35938b2SSzymon Janc BT_DBG("%s status 0x%x", hdev->name, rp->status); 1038c35938b2SSzymon Janc 103956e5cb86SJohan Hedberg hci_dev_lock(hdev); 1040744cf19eSJohan Hedberg mgmt_read_local_oob_data_reply_complete(hdev, rp->hash, 1041c35938b2SSzymon Janc rp->randomizer, rp->status); 104256e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1043c35938b2SSzymon Janc } 1044c35938b2SSzymon Janc 104507f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) 104607f7fa5dSAndre Guedes { 104707f7fa5dSAndre Guedes __u8 status = *((__u8 *) skb->data); 104807f7fa5dSAndre Guedes 104907f7fa5dSAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 10507ba8b4beSAndre Guedes 10517ba8b4beSAndre Guedes hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status); 10523fd24153SAndre Guedes 10533fd24153SAndre Guedes if (status) { 10543fd24153SAndre Guedes hci_dev_lock(hdev); 10553fd24153SAndre Guedes mgmt_start_discovery_failed(hdev, status); 10563fd24153SAndre Guedes hci_dev_unlock(hdev); 10573fd24153SAndre Guedes return; 10583fd24153SAndre Guedes } 105907f7fa5dSAndre Guedes } 106007f7fa5dSAndre Guedes 1061eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, 1062eb9d91f5SAndre Guedes struct sk_buff *skb) 1063eb9d91f5SAndre Guedes { 1064eb9d91f5SAndre Guedes struct hci_cp_le_set_scan_enable *cp; 1065eb9d91f5SAndre Guedes __u8 status = *((__u8 *) skb->data); 1066eb9d91f5SAndre Guedes 1067eb9d91f5SAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 1068eb9d91f5SAndre Guedes 1069eb9d91f5SAndre Guedes cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE); 1070eb9d91f5SAndre Guedes if (!cp) 1071eb9d91f5SAndre Guedes return; 1072eb9d91f5SAndre Guedes 107368a8aea4SAndrei Emeltchenko switch (cp->enable) { 107468a8aea4SAndrei Emeltchenko case LE_SCANNING_ENABLED: 10757ba8b4beSAndre Guedes hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status); 10767ba8b4beSAndre Guedes 10773fd24153SAndre Guedes if (status) { 10783fd24153SAndre Guedes hci_dev_lock(hdev); 10793fd24153SAndre Guedes mgmt_start_discovery_failed(hdev, status); 10803fd24153SAndre Guedes hci_dev_unlock(hdev); 10817ba8b4beSAndre Guedes return; 10823fd24153SAndre Guedes } 10837ba8b4beSAndre Guedes 1084d23264a8SAndre Guedes set_bit(HCI_LE_SCAN, &hdev->dev_flags); 1085d23264a8SAndre Guedes 1086db323f2fSGustavo F. Padovan cancel_delayed_work_sync(&hdev->adv_work); 1087a8f13c8cSAndre Guedes 1088a8f13c8cSAndre Guedes hci_dev_lock(hdev); 1089eb9d91f5SAndre Guedes hci_adv_entries_clear(hdev); 1090343f935bSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_FINDING); 1091a8f13c8cSAndre Guedes hci_dev_unlock(hdev); 109268a8aea4SAndrei Emeltchenko break; 109368a8aea4SAndrei Emeltchenko 109468a8aea4SAndrei Emeltchenko case LE_SCANNING_DISABLED: 10957ba8b4beSAndre Guedes if (status) 10967ba8b4beSAndre Guedes return; 10977ba8b4beSAndre Guedes 1098d23264a8SAndre Guedes clear_bit(HCI_LE_SCAN, &hdev->dev_flags); 1099d23264a8SAndre Guedes 11005e0452c0SAndre Guedes schedule_delayed_work(&hdev->adv_work, ADV_CLEAR_TIMEOUT); 11015e0452c0SAndre Guedes 11025e0452c0SAndre Guedes if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED) { 11035e0452c0SAndre Guedes mgmt_interleaved_discovery(hdev); 11045e0452c0SAndre Guedes } else { 1105c599008fSAndre Guedes hci_dev_lock(hdev); 1106c599008fSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 1107c599008fSAndre Guedes hci_dev_unlock(hdev); 11085e0452c0SAndre Guedes } 1109c599008fSAndre Guedes 111068a8aea4SAndrei Emeltchenko break; 111168a8aea4SAndrei Emeltchenko 111268a8aea4SAndrei Emeltchenko default: 111368a8aea4SAndrei Emeltchenko BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable); 111468a8aea4SAndrei Emeltchenko break; 111535815085SAndre Guedes } 1116eb9d91f5SAndre Guedes } 1117eb9d91f5SAndre Guedes 1118a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb) 1119a7a595f6SVinicius Costa Gomes { 1120a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_reply *rp = (void *) skb->data; 1121a7a595f6SVinicius Costa Gomes 1122a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, rp->status); 1123a7a595f6SVinicius Costa Gomes 1124a7a595f6SVinicius Costa Gomes if (rp->status) 1125a7a595f6SVinicius Costa Gomes return; 1126a7a595f6SVinicius Costa Gomes 1127a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status); 1128a7a595f6SVinicius Costa Gomes } 1129a7a595f6SVinicius Costa Gomes 1130a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 1131a7a595f6SVinicius Costa Gomes { 1132a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data; 1133a7a595f6SVinicius Costa Gomes 1134a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, rp->status); 1135a7a595f6SVinicius Costa Gomes 1136a7a595f6SVinicius Costa Gomes if (rp->status) 1137a7a595f6SVinicius Costa Gomes return; 1138a7a595f6SVinicius Costa Gomes 1139a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status); 1140a7a595f6SVinicius Costa Gomes } 1141a7a595f6SVinicius Costa Gomes 1142f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev, 1143f9b49306SAndre Guedes struct sk_buff *skb) 1144f9b49306SAndre Guedes { 1145f9b49306SAndre Guedes struct hci_cp_read_local_ext_features cp; 114606199cf8SJohan Hedberg struct hci_cp_write_le_host_supported *sent; 1147f9b49306SAndre Guedes __u8 status = *((__u8 *) skb->data); 1148f9b49306SAndre Guedes 1149f9b49306SAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 1150f9b49306SAndre Guedes 115106199cf8SJohan Hedberg sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED); 115206199cf8SJohan Hedberg if (sent && test_bit(HCI_MGMT, &hdev->dev_flags)) 115306199cf8SJohan Hedberg mgmt_le_enable_complete(hdev, sent->le, status); 115406199cf8SJohan Hedberg 1155f9b49306SAndre Guedes if (status) 1156f9b49306SAndre Guedes return; 1157f9b49306SAndre Guedes 1158f9b49306SAndre Guedes cp.page = 0x01; 1159f9b49306SAndre Guedes hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp); 1160f9b49306SAndre Guedes } 1161f9b49306SAndre Guedes 1162a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 1163a9de9248SMarcel Holtmann { 1164a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1165a9de9248SMarcel Holtmann 1166a9de9248SMarcel Holtmann if (status) { 116723bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 1168a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 116956e5cb86SJohan Hedberg hci_dev_lock(hdev); 1170a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 11717a135109SAndre Guedes mgmt_start_discovery_failed(hdev, status); 117256e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1173314b2381SJohan Hedberg return; 1174314b2381SJohan Hedberg } 1175314b2381SJohan Hedberg 117689352e7dSAndre Guedes set_bit(HCI_INQUIRY, &hdev->flags); 117789352e7dSAndre Guedes 117856e5cb86SJohan Hedberg hci_dev_lock(hdev); 1179343f935bSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_FINDING); 118056e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1181a9de9248SMarcel Holtmann } 1182a9de9248SMarcel Holtmann 11831da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 11841da177e4SLinus Torvalds { 1185a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 11861da177e4SLinus Torvalds struct hci_conn *conn; 11871da177e4SLinus Torvalds 1188a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1189a9de9248SMarcel Holtmann 1190a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 11911da177e4SLinus Torvalds if (!cp) 11921da177e4SLinus Torvalds return; 11931da177e4SLinus Torvalds 11941da177e4SLinus Torvalds hci_dev_lock(hdev); 11951da177e4SLinus Torvalds 11961da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 11971da177e4SLinus Torvalds 1198a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn); 11991da177e4SLinus Torvalds 12001da177e4SLinus Torvalds if (status) { 12011da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 12024c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 12031da177e4SLinus Torvalds conn->state = BT_CLOSED; 12041da177e4SLinus Torvalds hci_proto_connect_cfm(conn, status); 12051da177e4SLinus Torvalds hci_conn_del(conn); 12064c67bc74SMarcel Holtmann } else 12074c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 12081da177e4SLinus Torvalds } 12091da177e4SLinus Torvalds } else { 12101da177e4SLinus Torvalds if (!conn) { 12111da177e4SLinus Torvalds conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); 12121da177e4SLinus Torvalds if (conn) { 1213a0c808b3SJohan Hedberg conn->out = true; 12141da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 12151da177e4SLinus Torvalds } else 1216893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 12171da177e4SLinus Torvalds } 12181da177e4SLinus Torvalds } 12191da177e4SLinus Torvalds 12201da177e4SLinus Torvalds hci_dev_unlock(hdev); 12211da177e4SLinus Torvalds } 12221da177e4SLinus Torvalds 1223a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 12241da177e4SLinus Torvalds { 1225a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 12261da177e4SLinus Torvalds struct hci_conn *acl, *sco; 12271da177e4SLinus Torvalds __u16 handle; 12281da177e4SLinus Torvalds 1229b6a0dc82SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1230b6a0dc82SMarcel Holtmann 1231a9de9248SMarcel Holtmann if (!status) 1232a9de9248SMarcel Holtmann return; 1233a9de9248SMarcel Holtmann 1234a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 12351da177e4SLinus Torvalds if (!cp) 1236a9de9248SMarcel Holtmann return; 12371da177e4SLinus Torvalds 12381da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 12391da177e4SLinus Torvalds 1240a9de9248SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 12411da177e4SLinus Torvalds 12421da177e4SLinus Torvalds hci_dev_lock(hdev); 12431da177e4SLinus Torvalds 12441da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 12455a08ecceSAndrei Emeltchenko if (acl) { 12465a08ecceSAndrei Emeltchenko sco = acl->link; 12475a08ecceSAndrei Emeltchenko if (sco) { 12481da177e4SLinus Torvalds sco->state = BT_CLOSED; 12491da177e4SLinus Torvalds 12501da177e4SLinus Torvalds hci_proto_connect_cfm(sco, status); 12511da177e4SLinus Torvalds hci_conn_del(sco); 12521da177e4SLinus Torvalds } 12535a08ecceSAndrei Emeltchenko } 12541da177e4SLinus Torvalds 12551da177e4SLinus Torvalds hci_dev_unlock(hdev); 12561da177e4SLinus Torvalds } 12571da177e4SLinus Torvalds 1258f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 1259f8558555SMarcel Holtmann { 1260f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 1261f8558555SMarcel Holtmann struct hci_conn *conn; 1262f8558555SMarcel Holtmann 1263f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1264f8558555SMarcel Holtmann 1265f8558555SMarcel Holtmann if (!status) 1266f8558555SMarcel Holtmann return; 1267f8558555SMarcel Holtmann 1268f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 1269f8558555SMarcel Holtmann if (!cp) 1270f8558555SMarcel Holtmann return; 1271f8558555SMarcel Holtmann 1272f8558555SMarcel Holtmann hci_dev_lock(hdev); 1273f8558555SMarcel Holtmann 1274f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1275f8558555SMarcel Holtmann if (conn) { 1276f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1277f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1278f8558555SMarcel Holtmann hci_conn_put(conn); 1279f8558555SMarcel Holtmann } 1280f8558555SMarcel Holtmann } 1281f8558555SMarcel Holtmann 1282f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1283f8558555SMarcel Holtmann } 1284f8558555SMarcel Holtmann 1285f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 1286f8558555SMarcel Holtmann { 1287f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 1288f8558555SMarcel Holtmann struct hci_conn *conn; 1289f8558555SMarcel Holtmann 1290f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1291f8558555SMarcel Holtmann 1292f8558555SMarcel Holtmann if (!status) 1293f8558555SMarcel Holtmann return; 1294f8558555SMarcel Holtmann 1295f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 1296f8558555SMarcel Holtmann if (!cp) 1297f8558555SMarcel Holtmann return; 1298f8558555SMarcel Holtmann 1299f8558555SMarcel Holtmann hci_dev_lock(hdev); 1300f8558555SMarcel Holtmann 1301f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1302f8558555SMarcel Holtmann if (conn) { 1303f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1304f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1305f8558555SMarcel Holtmann hci_conn_put(conn); 1306f8558555SMarcel Holtmann } 1307f8558555SMarcel Holtmann } 1308f8558555SMarcel Holtmann 1309f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1310f8558555SMarcel Holtmann } 1311f8558555SMarcel Holtmann 1312127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev, 1313392599b9SJohan Hedberg struct hci_conn *conn) 1314392599b9SJohan Hedberg { 1315392599b9SJohan Hedberg if (conn->state != BT_CONFIG || !conn->out) 1316392599b9SJohan Hedberg return 0; 1317392599b9SJohan Hedberg 1318765c2a96SJohan Hedberg if (conn->pending_sec_level == BT_SECURITY_SDP) 1319392599b9SJohan Hedberg return 0; 1320392599b9SJohan Hedberg 1321392599b9SJohan Hedberg /* Only request authentication for SSP connections or non-SSP 1322e9bf2bf0SVinicius Costa Gomes * devices with sec_level HIGH or if MITM protection is requested */ 1323aa64a8b5SJohan Hedberg if (!hci_conn_ssp_enabled(conn) && 1324e9bf2bf0SVinicius Costa Gomes conn->pending_sec_level != BT_SECURITY_HIGH && 1325e9bf2bf0SVinicius Costa Gomes !(conn->auth_type & 0x01)) 1326392599b9SJohan Hedberg return 0; 1327392599b9SJohan Hedberg 1328392599b9SJohan Hedberg return 1; 1329392599b9SJohan Hedberg } 1330392599b9SJohan Hedberg 133130dc78e1SJohan Hedberg static inline int hci_resolve_name(struct hci_dev *hdev, struct inquiry_entry *e) 133230dc78e1SJohan Hedberg { 133330dc78e1SJohan Hedberg struct hci_cp_remote_name_req cp; 133430dc78e1SJohan Hedberg 133530dc78e1SJohan Hedberg memset(&cp, 0, sizeof(cp)); 133630dc78e1SJohan Hedberg 133730dc78e1SJohan Hedberg bacpy(&cp.bdaddr, &e->data.bdaddr); 133830dc78e1SJohan Hedberg cp.pscan_rep_mode = e->data.pscan_rep_mode; 133930dc78e1SJohan Hedberg cp.pscan_mode = e->data.pscan_mode; 134030dc78e1SJohan Hedberg cp.clock_offset = e->data.clock_offset; 134130dc78e1SJohan Hedberg 134230dc78e1SJohan Hedberg return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 134330dc78e1SJohan Hedberg } 134430dc78e1SJohan Hedberg 1345b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev) 134630dc78e1SJohan Hedberg { 134730dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 134830dc78e1SJohan Hedberg struct inquiry_entry *e; 134930dc78e1SJohan Hedberg 1350b644ba33SJohan Hedberg if (list_empty(&discov->resolve)) 1351b644ba33SJohan Hedberg return false; 1352b644ba33SJohan Hedberg 1353b644ba33SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 1354b644ba33SJohan Hedberg if (hci_resolve_name(hdev, e) == 0) { 1355b644ba33SJohan Hedberg e->name_state = NAME_PENDING; 1356b644ba33SJohan Hedberg return true; 1357b644ba33SJohan Hedberg } 1358b644ba33SJohan Hedberg 1359b644ba33SJohan Hedberg return false; 1360b644ba33SJohan Hedberg } 1361b644ba33SJohan Hedberg 1362b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn, 1363b644ba33SJohan Hedberg bdaddr_t *bdaddr, u8 *name, u8 name_len) 1364b644ba33SJohan Hedberg { 1365b644ba33SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 1366b644ba33SJohan Hedberg struct inquiry_entry *e; 1367b644ba33SJohan Hedberg 1368b644ba33SJohan Hedberg if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 1369b644ba33SJohan Hedberg mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 1370b644ba33SJohan Hedberg name, name_len, conn->dev_class); 1371b644ba33SJohan Hedberg 1372b644ba33SJohan Hedberg if (discov->state == DISCOVERY_STOPPED) 1373b644ba33SJohan Hedberg return; 1374b644ba33SJohan Hedberg 137530dc78e1SJohan Hedberg if (discov->state == DISCOVERY_STOPPING) 137630dc78e1SJohan Hedberg goto discov_complete; 137730dc78e1SJohan Hedberg 137830dc78e1SJohan Hedberg if (discov->state != DISCOVERY_RESOLVING) 137930dc78e1SJohan Hedberg return; 138030dc78e1SJohan Hedberg 138130dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING); 138230dc78e1SJohan Hedberg if (e) { 138330dc78e1SJohan Hedberg e->name_state = NAME_KNOWN; 138430dc78e1SJohan Hedberg list_del(&e->list); 1385b644ba33SJohan Hedberg if (name) 1386b644ba33SJohan Hedberg mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, 1387b644ba33SJohan Hedberg e->data.rssi, name, name_len); 138830dc78e1SJohan Hedberg } 138930dc78e1SJohan Hedberg 1390b644ba33SJohan Hedberg if (hci_resolve_next_name(hdev)) 139130dc78e1SJohan Hedberg return; 139230dc78e1SJohan Hedberg 139330dc78e1SJohan Hedberg discov_complete: 139430dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 139530dc78e1SJohan Hedberg } 139630dc78e1SJohan Hedberg 1397a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 13981da177e4SLinus Torvalds { 1399127178d2SJohan Hedberg struct hci_cp_remote_name_req *cp; 1400127178d2SJohan Hedberg struct hci_conn *conn; 1401127178d2SJohan Hedberg 1402a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1403127178d2SJohan Hedberg 1404127178d2SJohan Hedberg /* If successful wait for the name req complete event before 1405127178d2SJohan Hedberg * checking for the need to do authentication */ 1406127178d2SJohan Hedberg if (!status) 1407127178d2SJohan Hedberg return; 1408127178d2SJohan Hedberg 1409127178d2SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); 1410127178d2SJohan Hedberg if (!cp) 1411127178d2SJohan Hedberg return; 1412127178d2SJohan Hedberg 1413127178d2SJohan Hedberg hci_dev_lock(hdev); 1414127178d2SJohan Hedberg 1415127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 1416b644ba33SJohan Hedberg 1417b644ba33SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1418b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0); 1419b644ba33SJohan Hedberg 142079c6c70cSJohan Hedberg if (!conn) 142179c6c70cSJohan Hedberg goto unlock; 142279c6c70cSJohan Hedberg 142379c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 142479c6c70cSJohan Hedberg goto unlock; 142579c6c70cSJohan Hedberg 142651a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 1427127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1428127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1429127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1430127178d2SJohan Hedberg } 1431127178d2SJohan Hedberg 143279c6c70cSJohan Hedberg unlock: 1433127178d2SJohan Hedberg hci_dev_unlock(hdev); 1434a9de9248SMarcel Holtmann } 14351da177e4SLinus Torvalds 1436769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 1437769be974SMarcel Holtmann { 1438769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 1439769be974SMarcel Holtmann struct hci_conn *conn; 1440769be974SMarcel Holtmann 1441769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1442769be974SMarcel Holtmann 1443769be974SMarcel Holtmann if (!status) 1444769be974SMarcel Holtmann return; 1445769be974SMarcel Holtmann 1446769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 1447769be974SMarcel Holtmann if (!cp) 1448769be974SMarcel Holtmann return; 1449769be974SMarcel Holtmann 1450769be974SMarcel Holtmann hci_dev_lock(hdev); 1451769be974SMarcel Holtmann 1452769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1453769be974SMarcel Holtmann if (conn) { 1454769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1455769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1456769be974SMarcel Holtmann hci_conn_put(conn); 1457769be974SMarcel Holtmann } 1458769be974SMarcel Holtmann } 1459769be974SMarcel Holtmann 1460769be974SMarcel Holtmann hci_dev_unlock(hdev); 1461769be974SMarcel Holtmann } 1462769be974SMarcel Holtmann 1463769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 1464769be974SMarcel Holtmann { 1465769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features *cp; 1466769be974SMarcel Holtmann struct hci_conn *conn; 1467769be974SMarcel Holtmann 1468769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1469769be974SMarcel Holtmann 1470769be974SMarcel Holtmann if (!status) 1471769be974SMarcel Holtmann return; 1472769be974SMarcel Holtmann 1473769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 1474769be974SMarcel Holtmann if (!cp) 1475769be974SMarcel Holtmann return; 1476769be974SMarcel Holtmann 1477769be974SMarcel Holtmann hci_dev_lock(hdev); 1478769be974SMarcel Holtmann 1479769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1480769be974SMarcel Holtmann if (conn) { 1481769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1482769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1483769be974SMarcel Holtmann hci_conn_put(conn); 1484769be974SMarcel Holtmann } 1485769be974SMarcel Holtmann } 1486769be974SMarcel Holtmann 1487769be974SMarcel Holtmann hci_dev_unlock(hdev); 1488769be974SMarcel Holtmann } 1489769be974SMarcel Holtmann 1490a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 1491a9de9248SMarcel Holtmann { 1492b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 1493b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 1494b6a0dc82SMarcel Holtmann __u16 handle; 1495b6a0dc82SMarcel Holtmann 1496a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1497b6a0dc82SMarcel Holtmann 1498b6a0dc82SMarcel Holtmann if (!status) 1499b6a0dc82SMarcel Holtmann return; 1500b6a0dc82SMarcel Holtmann 1501b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 1502b6a0dc82SMarcel Holtmann if (!cp) 1503b6a0dc82SMarcel Holtmann return; 1504b6a0dc82SMarcel Holtmann 1505b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 1506b6a0dc82SMarcel Holtmann 1507b6a0dc82SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 1508b6a0dc82SMarcel Holtmann 1509b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 1510b6a0dc82SMarcel Holtmann 1511b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 15125a08ecceSAndrei Emeltchenko if (acl) { 15135a08ecceSAndrei Emeltchenko sco = acl->link; 15145a08ecceSAndrei Emeltchenko if (sco) { 1515b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 1516b6a0dc82SMarcel Holtmann 1517b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(sco, status); 1518b6a0dc82SMarcel Holtmann hci_conn_del(sco); 1519b6a0dc82SMarcel Holtmann } 15205a08ecceSAndrei Emeltchenko } 1521b6a0dc82SMarcel Holtmann 1522b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 1523a9de9248SMarcel Holtmann } 1524a9de9248SMarcel Holtmann 1525a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 1526a9de9248SMarcel Holtmann { 1527a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 152804837f64SMarcel Holtmann struct hci_conn *conn; 152904837f64SMarcel Holtmann 1530a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1531a9de9248SMarcel Holtmann 1532a9de9248SMarcel Holtmann if (!status) 1533a9de9248SMarcel Holtmann return; 1534a9de9248SMarcel Holtmann 1535a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 153604837f64SMarcel Holtmann if (!cp) 1537a9de9248SMarcel Holtmann return; 153804837f64SMarcel Holtmann 153904837f64SMarcel Holtmann hci_dev_lock(hdev); 154004837f64SMarcel Holtmann 154104837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1542e73439d8SMarcel Holtmann if (conn) { 154351a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 154404837f64SMarcel Holtmann 154551a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1546e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1547e73439d8SMarcel Holtmann } 1548e73439d8SMarcel Holtmann 154904837f64SMarcel Holtmann hci_dev_unlock(hdev); 155004837f64SMarcel Holtmann } 155104837f64SMarcel Holtmann 1552a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 1553a9de9248SMarcel Holtmann { 1554a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 155504837f64SMarcel Holtmann struct hci_conn *conn; 155604837f64SMarcel Holtmann 1557a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1558a9de9248SMarcel Holtmann 1559a9de9248SMarcel Holtmann if (!status) 1560a9de9248SMarcel Holtmann return; 1561a9de9248SMarcel Holtmann 1562a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 156304837f64SMarcel Holtmann if (!cp) 1564a9de9248SMarcel Holtmann return; 156504837f64SMarcel Holtmann 156604837f64SMarcel Holtmann hci_dev_lock(hdev); 156704837f64SMarcel Holtmann 156804837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1569e73439d8SMarcel Holtmann if (conn) { 157051a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 157104837f64SMarcel Holtmann 157251a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1573e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1574e73439d8SMarcel Holtmann } 1575e73439d8SMarcel Holtmann 157604837f64SMarcel Holtmann hci_dev_unlock(hdev); 157704837f64SMarcel Holtmann } 157804837f64SMarcel Holtmann 157988c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) 158088c3df13SJohan Hedberg { 158188c3df13SJohan Hedberg struct hci_cp_disconnect *cp; 158288c3df13SJohan Hedberg struct hci_conn *conn; 158388c3df13SJohan Hedberg 158488c3df13SJohan Hedberg if (!status) 158588c3df13SJohan Hedberg return; 158688c3df13SJohan Hedberg 158788c3df13SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT); 158888c3df13SJohan Hedberg if (!cp) 158988c3df13SJohan Hedberg return; 159088c3df13SJohan Hedberg 159188c3df13SJohan Hedberg hci_dev_lock(hdev); 159288c3df13SJohan Hedberg 159388c3df13SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 159488c3df13SJohan Hedberg if (conn) 159588c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 159688c3df13SJohan Hedberg conn->dst_type, status); 159788c3df13SJohan Hedberg 159888c3df13SJohan Hedberg hci_dev_unlock(hdev); 159988c3df13SJohan Hedberg } 160088c3df13SJohan Hedberg 1601fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) 1602fcd89c09SVille Tervo { 1603fcd89c09SVille Tervo struct hci_cp_le_create_conn *cp; 1604fcd89c09SVille Tervo struct hci_conn *conn; 1605fcd89c09SVille Tervo 1606fcd89c09SVille Tervo BT_DBG("%s status 0x%x", hdev->name, status); 1607fcd89c09SVille Tervo 1608fcd89c09SVille Tervo cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN); 1609fcd89c09SVille Tervo if (!cp) 1610fcd89c09SVille Tervo return; 1611fcd89c09SVille Tervo 1612fcd89c09SVille Tervo hci_dev_lock(hdev); 1613fcd89c09SVille Tervo 1614fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr); 1615fcd89c09SVille Tervo 1616fcd89c09SVille Tervo BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr), 1617fcd89c09SVille Tervo conn); 1618fcd89c09SVille Tervo 1619fcd89c09SVille Tervo if (status) { 1620fcd89c09SVille Tervo if (conn && conn->state == BT_CONNECT) { 1621fcd89c09SVille Tervo conn->state = BT_CLOSED; 1622fcd89c09SVille Tervo hci_proto_connect_cfm(conn, status); 1623fcd89c09SVille Tervo hci_conn_del(conn); 1624fcd89c09SVille Tervo } 1625fcd89c09SVille Tervo } else { 1626fcd89c09SVille Tervo if (!conn) { 1627fcd89c09SVille Tervo conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr); 162829b7988aSAndre Guedes if (conn) { 162929b7988aSAndre Guedes conn->dst_type = cp->peer_addr_type; 1630a0c808b3SJohan Hedberg conn->out = true; 163129b7988aSAndre Guedes } else { 1632fcd89c09SVille Tervo BT_ERR("No memory for new connection"); 1633fcd89c09SVille Tervo } 1634fcd89c09SVille Tervo } 163529b7988aSAndre Guedes } 1636fcd89c09SVille Tervo 1637fcd89c09SVille Tervo hci_dev_unlock(hdev); 1638fcd89c09SVille Tervo } 1639fcd89c09SVille Tervo 1640a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) 1641a7a595f6SVinicius Costa Gomes { 1642a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, status); 1643a7a595f6SVinicius Costa Gomes } 1644a7a595f6SVinicius Costa Gomes 16451da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 16461da177e4SLinus Torvalds { 16471da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 164830dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 164930dc78e1SJohan Hedberg struct inquiry_entry *e; 16501da177e4SLinus Torvalds 16511da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, status); 16521da177e4SLinus Torvalds 165323bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 16546bd57416SMarcel Holtmann 1655a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 165689352e7dSAndre Guedes 165789352e7dSAndre Guedes if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) 165889352e7dSAndre Guedes return; 165989352e7dSAndre Guedes 1660a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 166130dc78e1SJohan Hedberg return; 166230dc78e1SJohan Hedberg 166356e5cb86SJohan Hedberg hci_dev_lock(hdev); 166430dc78e1SJohan Hedberg 1665343f935bSAndre Guedes if (discov->state != DISCOVERY_FINDING) 166630dc78e1SJohan Hedberg goto unlock; 166730dc78e1SJohan Hedberg 166830dc78e1SJohan Hedberg if (list_empty(&discov->resolve)) { 1669ff9ef578SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 167030dc78e1SJohan Hedberg goto unlock; 167130dc78e1SJohan Hedberg } 167230dc78e1SJohan Hedberg 167330dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 167430dc78e1SJohan Hedberg if (e && hci_resolve_name(hdev, e) == 0) { 167530dc78e1SJohan Hedberg e->name_state = NAME_PENDING; 167630dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_RESOLVING); 167730dc78e1SJohan Hedberg } else { 167830dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 167930dc78e1SJohan Hedberg } 168030dc78e1SJohan Hedberg 168130dc78e1SJohan Hedberg unlock: 168256e5cb86SJohan Hedberg hci_dev_unlock(hdev); 16831da177e4SLinus Torvalds } 16841da177e4SLinus Torvalds 16851da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 16861da177e4SLinus Torvalds { 168745bb4bf0SMarcel Holtmann struct inquiry_data data; 1688a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 16891da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 16901da177e4SLinus Torvalds 16911da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 16921da177e4SLinus Torvalds 169345bb4bf0SMarcel Holtmann if (!num_rsp) 169445bb4bf0SMarcel Holtmann return; 169545bb4bf0SMarcel Holtmann 16961da177e4SLinus Torvalds hci_dev_lock(hdev); 169745bb4bf0SMarcel Holtmann 1698e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 1699388fc8faSJohan Hedberg bool name_known, ssp; 17003175405bSJohan Hedberg 17011da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 17021da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 17031da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 17041da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 17051da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 17061da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 17071da177e4SLinus Torvalds data.rssi = 0x00; 170841a96212SMarcel Holtmann data.ssp_mode = 0x00; 17093175405bSJohan Hedberg 1710388fc8faSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp); 171148264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 1712388fc8faSJohan Hedberg info->dev_class, 0, !name_known, ssp, 17137d262f86SAndre Guedes NULL, 0); 17141da177e4SLinus Torvalds } 171545bb4bf0SMarcel Holtmann 17161da177e4SLinus Torvalds hci_dev_unlock(hdev); 17171da177e4SLinus Torvalds } 17181da177e4SLinus Torvalds 1719a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 17201da177e4SLinus Torvalds { 1721a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 1722a9de9248SMarcel Holtmann struct hci_conn *conn; 17231da177e4SLinus Torvalds 1724a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 172545bb4bf0SMarcel Holtmann 17261da177e4SLinus Torvalds hci_dev_lock(hdev); 172745bb4bf0SMarcel Holtmann 1728a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 17299499237aSMarcel Holtmann if (!conn) { 17309499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 17319499237aSMarcel Holtmann goto unlock; 17329499237aSMarcel Holtmann 17339499237aSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 1734a9de9248SMarcel Holtmann if (!conn) 1735a9de9248SMarcel Holtmann goto unlock; 173645bb4bf0SMarcel Holtmann 17379499237aSMarcel Holtmann conn->type = SCO_LINK; 17389499237aSMarcel Holtmann } 17399499237aSMarcel Holtmann 1740a9de9248SMarcel Holtmann if (!ev->status) { 1741a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 1742769be974SMarcel Holtmann 1743769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 1744769be974SMarcel Holtmann conn->state = BT_CONFIG; 1745769be974SMarcel Holtmann hci_conn_hold(conn); 1746052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1747769be974SMarcel Holtmann } else 1748a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 1749a9de9248SMarcel Holtmann 17509eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 17517d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 17527d0db0a3SMarcel Holtmann 1753a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 1754a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1755a9de9248SMarcel Holtmann 1756a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 1757a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1758a9de9248SMarcel Holtmann 1759a9de9248SMarcel Holtmann /* Get remote features */ 1760a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 1761a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 1762a9de9248SMarcel Holtmann cp.handle = ev->handle; 1763769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 1764769be974SMarcel Holtmann sizeof(cp), &cp); 176545bb4bf0SMarcel Holtmann } 1766a9de9248SMarcel Holtmann 1767a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 1768d095c1ebSAndrei Emeltchenko if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) { 1769a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 1770a9de9248SMarcel Holtmann cp.handle = ev->handle; 1771a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1772a8746417SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, 1773a8746417SMarcel Holtmann sizeof(cp), &cp); 1774a9de9248SMarcel Holtmann } 177517d5c04cSJohan Hedberg } else { 1776a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 177717d5c04cSJohan Hedberg if (conn->type == ACL_LINK) 1778744cf19eSJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 177948264f06SJohan Hedberg conn->dst_type, ev->status); 178017d5c04cSJohan Hedberg } 178145bb4bf0SMarcel Holtmann 1782e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 1783e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 178445bb4bf0SMarcel Holtmann 1785769be974SMarcel Holtmann if (ev->status) { 1786a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1787a9de9248SMarcel Holtmann hci_conn_del(conn); 1788c89b6e6bSMarcel Holtmann } else if (ev->link_type != ACL_LINK) 1789c89b6e6bSMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1790a9de9248SMarcel Holtmann 1791a9de9248SMarcel Holtmann unlock: 17921da177e4SLinus Torvalds hci_dev_unlock(hdev); 1793a9de9248SMarcel Holtmann 1794a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 17951da177e4SLinus Torvalds } 17961da177e4SLinus Torvalds 17971da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 17981da177e4SLinus Torvalds { 1799a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 18001da177e4SLinus Torvalds int mask = hdev->link_mode; 18011da177e4SLinus Torvalds 1802a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s type 0x%x", hdev->name, 18031da177e4SLinus Torvalds batostr(&ev->bdaddr), ev->link_type); 18041da177e4SLinus Torvalds 18051da177e4SLinus Torvalds mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); 18061da177e4SLinus Torvalds 1807138d22efSSzymon Janc if ((mask & HCI_LM_ACCEPT) && 1808138d22efSSzymon Janc !hci_blacklist_lookup(hdev, &ev->bdaddr)) { 18091da177e4SLinus Torvalds /* Connection accepted */ 1810c7bdd502SMarcel Holtmann struct inquiry_entry *ie; 18111da177e4SLinus Torvalds struct hci_conn *conn; 18121da177e4SLinus Torvalds 18131da177e4SLinus Torvalds hci_dev_lock(hdev); 1814b6a0dc82SMarcel Holtmann 1815cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 1816cc11b9c1SAndrei Emeltchenko if (ie) 1817c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 1818c7bdd502SMarcel Holtmann 18191da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 18201da177e4SLinus Torvalds if (!conn) { 1821cc11b9c1SAndrei Emeltchenko conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); 1822cc11b9c1SAndrei Emeltchenko if (!conn) { 1823893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 18241da177e4SLinus Torvalds hci_dev_unlock(hdev); 18251da177e4SLinus Torvalds return; 18261da177e4SLinus Torvalds } 18271da177e4SLinus Torvalds } 1828b6a0dc82SMarcel Holtmann 18291da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 18301da177e4SLinus Torvalds conn->state = BT_CONNECT; 1831b6a0dc82SMarcel Holtmann 18321da177e4SLinus Torvalds hci_dev_unlock(hdev); 18331da177e4SLinus Torvalds 1834b6a0dc82SMarcel Holtmann if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) { 1835b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 1836b6a0dc82SMarcel Holtmann 18371da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 18381da177e4SLinus Torvalds 18391da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 18401da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 18411da177e4SLinus Torvalds else 18421da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 18431da177e4SLinus Torvalds 1844b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, 1845b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1846b6a0dc82SMarcel Holtmann } else { 1847b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 1848b6a0dc82SMarcel Holtmann 1849b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 1850a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1851b6a0dc82SMarcel Holtmann 1852b6a0dc82SMarcel Holtmann cp.tx_bandwidth = cpu_to_le32(0x00001f40); 1853b6a0dc82SMarcel Holtmann cp.rx_bandwidth = cpu_to_le32(0x00001f40); 1854b6a0dc82SMarcel Holtmann cp.max_latency = cpu_to_le16(0xffff); 1855b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 1856b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 1857b6a0dc82SMarcel Holtmann 1858b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 1859b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1860b6a0dc82SMarcel Holtmann } 18611da177e4SLinus Torvalds } else { 18621da177e4SLinus Torvalds /* Connection rejected */ 18631da177e4SLinus Torvalds struct hci_cp_reject_conn_req cp; 18641da177e4SLinus Torvalds 18651da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 18669f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_REJ_BAD_ADDR; 1867a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 18681da177e4SLinus Torvalds } 18691da177e4SLinus Torvalds } 18701da177e4SLinus Torvalds 18711da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 18721da177e4SLinus Torvalds { 1873a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 187404837f64SMarcel Holtmann struct hci_conn *conn; 18751da177e4SLinus Torvalds 18761da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 18771da177e4SLinus Torvalds 18781da177e4SLinus Torvalds hci_dev_lock(hdev); 18791da177e4SLinus Torvalds 188004837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1881f7520543SJohan Hedberg if (!conn) 1882f7520543SJohan Hedberg goto unlock; 1883f7520543SJohan Hedberg 188437d9ef76SJohan Hedberg if (ev->status == 0) 18851da177e4SLinus Torvalds conn->state = BT_CLOSED; 18867d0db0a3SMarcel Holtmann 1887b644ba33SJohan Hedberg if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) && 1888b644ba33SJohan Hedberg (conn->type == ACL_LINK || conn->type == LE_LINK)) { 188937d9ef76SJohan Hedberg if (ev->status != 0) 189088c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 189188c3df13SJohan Hedberg conn->dst_type, ev->status); 189237d9ef76SJohan Hedberg else 1893afc747a6SJohan Hedberg mgmt_device_disconnected(hdev, &conn->dst, conn->type, 189448264f06SJohan Hedberg conn->dst_type); 189537d9ef76SJohan Hedberg } 1896f7520543SJohan Hedberg 189737d9ef76SJohan Hedberg if (ev->status == 0) { 18982950f21aSMarcel Holtmann hci_proto_disconn_cfm(conn, ev->reason); 18991da177e4SLinus Torvalds hci_conn_del(conn); 190037d9ef76SJohan Hedberg } 19011da177e4SLinus Torvalds 1902f7520543SJohan Hedberg unlock: 19031da177e4SLinus Torvalds hci_dev_unlock(hdev); 19041da177e4SLinus Torvalds } 19051da177e4SLinus Torvalds 1906a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1907a9de9248SMarcel Holtmann { 1908a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 1909a9de9248SMarcel Holtmann struct hci_conn *conn; 1910a9de9248SMarcel Holtmann 1911a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1912a9de9248SMarcel Holtmann 1913a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1914a9de9248SMarcel Holtmann 1915a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1916d7556e20SWaldemar Rymarkiewicz if (!conn) 1917d7556e20SWaldemar Rymarkiewicz goto unlock; 1918d7556e20SWaldemar Rymarkiewicz 1919765c2a96SJohan Hedberg if (!ev->status) { 1920aa64a8b5SJohan Hedberg if (!hci_conn_ssp_enabled(conn) && 192151a8efd7SJohan Hedberg test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) { 1922d7556e20SWaldemar Rymarkiewicz BT_INFO("re-auth of legacy device is not possible."); 192319f8def0SWaldemar Rymarkiewicz } else { 1924a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1925765c2a96SJohan Hedberg conn->sec_level = conn->pending_sec_level; 192619f8def0SWaldemar Rymarkiewicz } 19272a611692SJohan Hedberg } else { 1928bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 1929bab73cb6SJohan Hedberg ev->status); 19302a611692SJohan Hedberg } 1931a9de9248SMarcel Holtmann 193251a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 193351a8efd7SJohan Hedberg clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags); 1934a9de9248SMarcel Holtmann 1935f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1936aa64a8b5SJohan Hedberg if (!ev->status && hci_conn_ssp_enabled(conn)) { 1937f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1938f8558555SMarcel Holtmann cp.handle = ev->handle; 1939f8558555SMarcel Holtmann cp.encrypt = 0x01; 1940d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1941d7556e20SWaldemar Rymarkiewicz &cp); 1942f8558555SMarcel Holtmann } else { 1943f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1944f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1945f8558555SMarcel Holtmann hci_conn_put(conn); 1946f8558555SMarcel Holtmann } 1947052b30b0SMarcel Holtmann } else { 1948a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 1949a9de9248SMarcel Holtmann 1950052b30b0SMarcel Holtmann hci_conn_hold(conn); 1951052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1952052b30b0SMarcel Holtmann hci_conn_put(conn); 1953052b30b0SMarcel Holtmann } 1954052b30b0SMarcel Holtmann 195551a8efd7SJohan Hedberg if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) { 1956a9de9248SMarcel Holtmann if (!ev->status) { 1957a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1958f8558555SMarcel Holtmann cp.handle = ev->handle; 1959f8558555SMarcel Holtmann cp.encrypt = 0x01; 1960d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1961d7556e20SWaldemar Rymarkiewicz &cp); 1962a9de9248SMarcel Holtmann } else { 196351a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 1964a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 1965a9de9248SMarcel Holtmann } 1966a9de9248SMarcel Holtmann } 1967a9de9248SMarcel Holtmann 1968d7556e20SWaldemar Rymarkiewicz unlock: 1969a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1970a9de9248SMarcel Holtmann } 1971a9de9248SMarcel Holtmann 1972a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 1973a9de9248SMarcel Holtmann { 1974127178d2SJohan Hedberg struct hci_ev_remote_name *ev = (void *) skb->data; 1975127178d2SJohan Hedberg struct hci_conn *conn; 1976127178d2SJohan Hedberg 1977a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1978a9de9248SMarcel Holtmann 1979a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 1980127178d2SJohan Hedberg 1981127178d2SJohan Hedberg hci_dev_lock(hdev); 1982127178d2SJohan Hedberg 1983127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 1984b644ba33SJohan Hedberg 1985b644ba33SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 1986b644ba33SJohan Hedberg goto check_auth; 1987b644ba33SJohan Hedberg 1988b644ba33SJohan Hedberg if (ev->status == 0) 1989b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name, 1990b644ba33SJohan Hedberg strnlen(ev->name, HCI_MAX_NAME_LENGTH)); 1991b644ba33SJohan Hedberg else 1992b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0); 1993b644ba33SJohan Hedberg 1994b644ba33SJohan Hedberg check_auth: 199579c6c70cSJohan Hedberg if (!conn) 199679c6c70cSJohan Hedberg goto unlock; 199779c6c70cSJohan Hedberg 199879c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 199979c6c70cSJohan Hedberg goto unlock; 200079c6c70cSJohan Hedberg 200151a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 2002127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 2003127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 2004127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 2005127178d2SJohan Hedberg } 2006127178d2SJohan Hedberg 200779c6c70cSJohan Hedberg unlock: 2008127178d2SJohan Hedberg hci_dev_unlock(hdev); 2009a9de9248SMarcel Holtmann } 2010a9de9248SMarcel Holtmann 2011a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2012a9de9248SMarcel Holtmann { 2013a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 2014a9de9248SMarcel Holtmann struct hci_conn *conn; 2015a9de9248SMarcel Holtmann 2016a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2017a9de9248SMarcel Holtmann 2018a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2019a9de9248SMarcel Holtmann 2020a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2021a9de9248SMarcel Holtmann if (conn) { 2022a9de9248SMarcel Holtmann if (!ev->status) { 2023ae293196SMarcel Holtmann if (ev->encrypt) { 2024ae293196SMarcel Holtmann /* Encryption implies authentication */ 2025ae293196SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 2026a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 2027da85e5e5SVinicius Costa Gomes conn->sec_level = conn->pending_sec_level; 2028ae293196SMarcel Holtmann } else 2029a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_ENCRYPT; 2030a9de9248SMarcel Holtmann } 2031a9de9248SMarcel Holtmann 203251a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 2033a9de9248SMarcel Holtmann 2034f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 2035f8558555SMarcel Holtmann if (!ev->status) 2036f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 2037f8558555SMarcel Holtmann 2038f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2039f8558555SMarcel Holtmann hci_conn_put(conn); 2040f8558555SMarcel Holtmann } else 2041a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 2042a9de9248SMarcel Holtmann } 2043a9de9248SMarcel Holtmann 2044a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2045a9de9248SMarcel Holtmann } 2046a9de9248SMarcel Holtmann 2047a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2048a9de9248SMarcel Holtmann { 2049a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 2050a9de9248SMarcel Holtmann struct hci_conn *conn; 2051a9de9248SMarcel Holtmann 2052a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2053a9de9248SMarcel Holtmann 2054a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2055a9de9248SMarcel Holtmann 2056a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2057a9de9248SMarcel Holtmann if (conn) { 2058a9de9248SMarcel Holtmann if (!ev->status) 2059a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_SECURE; 2060a9de9248SMarcel Holtmann 206151a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 2062a9de9248SMarcel Holtmann 2063a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 2064a9de9248SMarcel Holtmann } 2065a9de9248SMarcel Holtmann 2066a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2067a9de9248SMarcel Holtmann } 2068a9de9248SMarcel Holtmann 2069a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 2070a9de9248SMarcel Holtmann { 2071a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 2072a9de9248SMarcel Holtmann struct hci_conn *conn; 2073a9de9248SMarcel Holtmann 2074a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2075a9de9248SMarcel Holtmann 2076a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2077a9de9248SMarcel Holtmann 2078a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2079ccd556feSJohan Hedberg if (!conn) 2080ccd556feSJohan Hedberg goto unlock; 2081ccd556feSJohan Hedberg 2082769be974SMarcel Holtmann if (!ev->status) 2083a9de9248SMarcel Holtmann memcpy(conn->features, ev->features, 8); 2084a9de9248SMarcel Holtmann 2085ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2086ccd556feSJohan Hedberg goto unlock; 2087ccd556feSJohan Hedberg 2088ccd556feSJohan Hedberg if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { 2089769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 2090769be974SMarcel Holtmann cp.handle = ev->handle; 2091769be974SMarcel Holtmann cp.page = 0x01; 2092ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 2093769be974SMarcel Holtmann sizeof(cp), &cp); 2094392599b9SJohan Hedberg goto unlock; 2095392599b9SJohan Hedberg } 2096392599b9SJohan Hedberg 2097127178d2SJohan Hedberg if (!ev->status) { 2098127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2099127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2100127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2101127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2102127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2103b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 2104b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 2105b644ba33SJohan Hedberg conn->dst_type, NULL, 0, 2106b644ba33SJohan Hedberg conn->dev_class); 2107392599b9SJohan Hedberg 2108127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2109769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2110769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2111769be974SMarcel Holtmann hci_conn_put(conn); 2112769be974SMarcel Holtmann } 2113769be974SMarcel Holtmann 2114ccd556feSJohan Hedberg unlock: 2115a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2116a9de9248SMarcel Holtmann } 2117a9de9248SMarcel Holtmann 2118a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) 2119a9de9248SMarcel Holtmann { 2120a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2121a9de9248SMarcel Holtmann } 2122a9de9248SMarcel Holtmann 2123a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2124a9de9248SMarcel Holtmann { 2125a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2126a9de9248SMarcel Holtmann } 2127a9de9248SMarcel Holtmann 2128a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2129a9de9248SMarcel Holtmann { 2130a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 2131a9de9248SMarcel Holtmann __u16 opcode; 2132a9de9248SMarcel Holtmann 2133a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2134a9de9248SMarcel Holtmann 2135a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2136a9de9248SMarcel Holtmann 2137a9de9248SMarcel Holtmann switch (opcode) { 2138a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 2139a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 2140a9de9248SMarcel Holtmann break; 2141a9de9248SMarcel Holtmann 2142a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 2143a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 2144a9de9248SMarcel Holtmann break; 2145a9de9248SMarcel Holtmann 2146a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 2147a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 2148a9de9248SMarcel Holtmann break; 2149a9de9248SMarcel Holtmann 2150a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 2151a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 2152a9de9248SMarcel Holtmann break; 2153a9de9248SMarcel Holtmann 2154e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 2155e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 2156e4e8e37cSMarcel Holtmann break; 2157e4e8e37cSMarcel Holtmann 2158a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 2159a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 2160a9de9248SMarcel Holtmann break; 2161a9de9248SMarcel Holtmann 2162e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 2163e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 2164e4e8e37cSMarcel Holtmann break; 2165e4e8e37cSMarcel Holtmann 2166e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 2167e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 2168e4e8e37cSMarcel Holtmann break; 2169e4e8e37cSMarcel Holtmann 2170a9de9248SMarcel Holtmann case HCI_OP_RESET: 2171a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 2172a9de9248SMarcel Holtmann break; 2173a9de9248SMarcel Holtmann 2174a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 2175a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 2176a9de9248SMarcel Holtmann break; 2177a9de9248SMarcel Holtmann 2178a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 2179a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 2180a9de9248SMarcel Holtmann break; 2181a9de9248SMarcel Holtmann 2182a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 2183a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 2184a9de9248SMarcel Holtmann break; 2185a9de9248SMarcel Holtmann 2186a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 2187a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 2188a9de9248SMarcel Holtmann break; 2189a9de9248SMarcel Holtmann 2190a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 2191a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 2192a9de9248SMarcel Holtmann break; 2193a9de9248SMarcel Holtmann 2194a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 2195a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 2196a9de9248SMarcel Holtmann break; 2197a9de9248SMarcel Holtmann 2198a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 2199a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 2200a9de9248SMarcel Holtmann break; 2201a9de9248SMarcel Holtmann 2202a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 2203a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 2204a9de9248SMarcel Holtmann break; 2205a9de9248SMarcel Holtmann 2206a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 2207a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 2208a9de9248SMarcel Holtmann break; 2209a9de9248SMarcel Holtmann 2210a9de9248SMarcel Holtmann case HCI_OP_HOST_BUFFER_SIZE: 2211a9de9248SMarcel Holtmann hci_cc_host_buffer_size(hdev, skb); 2212a9de9248SMarcel Holtmann break; 2213a9de9248SMarcel Holtmann 2214333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 2215333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 2216333140b5SMarcel Holtmann break; 2217333140b5SMarcel Holtmann 2218a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 2219a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 2220a9de9248SMarcel Holtmann break; 2221a9de9248SMarcel Holtmann 2222a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 2223a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 2224a9de9248SMarcel Holtmann break; 2225a9de9248SMarcel Holtmann 2226a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 2227a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 2228a9de9248SMarcel Holtmann break; 2229a9de9248SMarcel Holtmann 2230971e3a4bSAndre Guedes case HCI_OP_READ_LOCAL_EXT_FEATURES: 2231971e3a4bSAndre Guedes hci_cc_read_local_ext_features(hdev, skb); 2232971e3a4bSAndre Guedes break; 2233971e3a4bSAndre Guedes 2234a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 2235a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 2236a9de9248SMarcel Holtmann break; 2237a9de9248SMarcel Holtmann 2238a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 2239a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 2240a9de9248SMarcel Holtmann break; 2241a9de9248SMarcel Holtmann 2242350ee4cfSAndrei Emeltchenko case HCI_OP_READ_DATA_BLOCK_SIZE: 2243350ee4cfSAndrei Emeltchenko hci_cc_read_data_block_size(hdev, skb); 2244350ee4cfSAndrei Emeltchenko break; 2245350ee4cfSAndrei Emeltchenko 224623bb5763SJohan Hedberg case HCI_OP_WRITE_CA_TIMEOUT: 224723bb5763SJohan Hedberg hci_cc_write_ca_timeout(hdev, skb); 224823bb5763SJohan Hedberg break; 224923bb5763SJohan Hedberg 22501e89cffbSAndrei Emeltchenko case HCI_OP_READ_FLOW_CONTROL_MODE: 22511e89cffbSAndrei Emeltchenko hci_cc_read_flow_control_mode(hdev, skb); 22521e89cffbSAndrei Emeltchenko break; 22531e89cffbSAndrei Emeltchenko 2254928abaa7SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_INFO: 2255928abaa7SAndrei Emeltchenko hci_cc_read_local_amp_info(hdev, skb); 2256928abaa7SAndrei Emeltchenko break; 2257928abaa7SAndrei Emeltchenko 2258b0916ea0SJohan Hedberg case HCI_OP_DELETE_STORED_LINK_KEY: 2259b0916ea0SJohan Hedberg hci_cc_delete_stored_link_key(hdev, skb); 2260b0916ea0SJohan Hedberg break; 2261b0916ea0SJohan Hedberg 2262d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_MASK: 2263d5859e22SJohan Hedberg hci_cc_set_event_mask(hdev, skb); 2264d5859e22SJohan Hedberg break; 2265d5859e22SJohan Hedberg 2266d5859e22SJohan Hedberg case HCI_OP_WRITE_INQUIRY_MODE: 2267d5859e22SJohan Hedberg hci_cc_write_inquiry_mode(hdev, skb); 2268d5859e22SJohan Hedberg break; 2269d5859e22SJohan Hedberg 2270d5859e22SJohan Hedberg case HCI_OP_READ_INQ_RSP_TX_POWER: 2271d5859e22SJohan Hedberg hci_cc_read_inq_rsp_tx_power(hdev, skb); 2272d5859e22SJohan Hedberg break; 2273d5859e22SJohan Hedberg 2274d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_FLT: 2275d5859e22SJohan Hedberg hci_cc_set_event_flt(hdev, skb); 2276d5859e22SJohan Hedberg break; 2277d5859e22SJohan Hedberg 2278980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_REPLY: 2279980e1a53SJohan Hedberg hci_cc_pin_code_reply(hdev, skb); 2280980e1a53SJohan Hedberg break; 2281980e1a53SJohan Hedberg 2282980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_NEG_REPLY: 2283980e1a53SJohan Hedberg hci_cc_pin_code_neg_reply(hdev, skb); 2284980e1a53SJohan Hedberg break; 2285980e1a53SJohan Hedberg 2286c35938b2SSzymon Janc case HCI_OP_READ_LOCAL_OOB_DATA: 2287c35938b2SSzymon Janc hci_cc_read_local_oob_data_reply(hdev, skb); 2288c35938b2SSzymon Janc break; 2289c35938b2SSzymon Janc 22906ed58ec5SVille Tervo case HCI_OP_LE_READ_BUFFER_SIZE: 22916ed58ec5SVille Tervo hci_cc_le_read_buffer_size(hdev, skb); 22926ed58ec5SVille Tervo break; 22936ed58ec5SVille Tervo 2294a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_REPLY: 2295a5c29683SJohan Hedberg hci_cc_user_confirm_reply(hdev, skb); 2296a5c29683SJohan Hedberg break; 2297a5c29683SJohan Hedberg 2298a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_NEG_REPLY: 2299a5c29683SJohan Hedberg hci_cc_user_confirm_neg_reply(hdev, skb); 2300a5c29683SJohan Hedberg break; 2301a5c29683SJohan Hedberg 23021143d458SBrian Gix case HCI_OP_USER_PASSKEY_REPLY: 23031143d458SBrian Gix hci_cc_user_passkey_reply(hdev, skb); 23041143d458SBrian Gix break; 23051143d458SBrian Gix 23061143d458SBrian Gix case HCI_OP_USER_PASSKEY_NEG_REPLY: 23071143d458SBrian Gix hci_cc_user_passkey_neg_reply(hdev, skb); 230807f7fa5dSAndre Guedes 230907f7fa5dSAndre Guedes case HCI_OP_LE_SET_SCAN_PARAM: 231007f7fa5dSAndre Guedes hci_cc_le_set_scan_param(hdev, skb); 23111143d458SBrian Gix break; 23121143d458SBrian Gix 2313eb9d91f5SAndre Guedes case HCI_OP_LE_SET_SCAN_ENABLE: 2314eb9d91f5SAndre Guedes hci_cc_le_set_scan_enable(hdev, skb); 2315eb9d91f5SAndre Guedes break; 2316eb9d91f5SAndre Guedes 2317a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_REPLY: 2318a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_reply(hdev, skb); 2319a7a595f6SVinicius Costa Gomes break; 2320a7a595f6SVinicius Costa Gomes 2321a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_NEG_REPLY: 2322a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_neg_reply(hdev, skb); 2323a7a595f6SVinicius Costa Gomes break; 2324a7a595f6SVinicius Costa Gomes 2325f9b49306SAndre Guedes case HCI_OP_WRITE_LE_HOST_SUPPORTED: 2326f9b49306SAndre Guedes hci_cc_write_le_host_supported(hdev, skb); 2327f9b49306SAndre Guedes break; 2328f9b49306SAndre Guedes 2329a9de9248SMarcel Holtmann default: 2330a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 2331a9de9248SMarcel Holtmann break; 2332a9de9248SMarcel Holtmann } 2333a9de9248SMarcel Holtmann 23346bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 23356bd32326SVille Tervo del_timer(&hdev->cmd_timer); 23366bd32326SVille Tervo 2337a9de9248SMarcel Holtmann if (ev->ncmd) { 2338a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2339a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2340c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2341a9de9248SMarcel Holtmann } 2342a9de9248SMarcel Holtmann } 2343a9de9248SMarcel Holtmann 2344a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 2345a9de9248SMarcel Holtmann { 2346a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 2347a9de9248SMarcel Holtmann __u16 opcode; 2348a9de9248SMarcel Holtmann 2349a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2350a9de9248SMarcel Holtmann 2351a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2352a9de9248SMarcel Holtmann 2353a9de9248SMarcel Holtmann switch (opcode) { 2354a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 2355a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 2356a9de9248SMarcel Holtmann break; 2357a9de9248SMarcel Holtmann 2358a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 2359a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 2360a9de9248SMarcel Holtmann break; 2361a9de9248SMarcel Holtmann 2362a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 2363a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 2364a9de9248SMarcel Holtmann break; 2365a9de9248SMarcel Holtmann 2366f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 2367f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 2368f8558555SMarcel Holtmann break; 2369f8558555SMarcel Holtmann 2370f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 2371f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 2372f8558555SMarcel Holtmann break; 2373f8558555SMarcel Holtmann 2374a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 2375a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 2376a9de9248SMarcel Holtmann break; 2377a9de9248SMarcel Holtmann 2378769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 2379769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 2380769be974SMarcel Holtmann break; 2381769be974SMarcel Holtmann 2382769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 2383769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 2384769be974SMarcel Holtmann break; 2385769be974SMarcel Holtmann 2386a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 2387a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 2388a9de9248SMarcel Holtmann break; 2389a9de9248SMarcel Holtmann 2390a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 2391a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 2392a9de9248SMarcel Holtmann break; 2393a9de9248SMarcel Holtmann 2394a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 2395a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 2396a9de9248SMarcel Holtmann break; 2397a9de9248SMarcel Holtmann 23988962ee74SJohan Hedberg case HCI_OP_DISCONNECT: 239988c3df13SJohan Hedberg hci_cs_disconnect(hdev, ev->status); 24008962ee74SJohan Hedberg break; 24018962ee74SJohan Hedberg 2402fcd89c09SVille Tervo case HCI_OP_LE_CREATE_CONN: 2403fcd89c09SVille Tervo hci_cs_le_create_conn(hdev, ev->status); 2404fcd89c09SVille Tervo break; 2405fcd89c09SVille Tervo 2406a7a595f6SVinicius Costa Gomes case HCI_OP_LE_START_ENC: 2407a7a595f6SVinicius Costa Gomes hci_cs_le_start_enc(hdev, ev->status); 2408a7a595f6SVinicius Costa Gomes break; 2409a7a595f6SVinicius Costa Gomes 2410a9de9248SMarcel Holtmann default: 2411a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 2412a9de9248SMarcel Holtmann break; 2413a9de9248SMarcel Holtmann } 2414a9de9248SMarcel Holtmann 24156bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 24166bd32326SVille Tervo del_timer(&hdev->cmd_timer); 24176bd32326SVille Tervo 241810572132SGustavo F. Padovan if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2419a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2420a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2421c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2422a9de9248SMarcel Holtmann } 2423a9de9248SMarcel Holtmann } 2424a9de9248SMarcel Holtmann 2425a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2426a9de9248SMarcel Holtmann { 2427a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 2428a9de9248SMarcel Holtmann struct hci_conn *conn; 2429a9de9248SMarcel Holtmann 2430a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2431a9de9248SMarcel Holtmann 2432a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2433a9de9248SMarcel Holtmann 2434a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2435a9de9248SMarcel Holtmann if (conn) { 2436a9de9248SMarcel Holtmann if (!ev->status) { 2437a9de9248SMarcel Holtmann if (ev->role) 2438a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_MASTER; 2439a9de9248SMarcel Holtmann else 2440a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_MASTER; 2441a9de9248SMarcel Holtmann } 2442a9de9248SMarcel Holtmann 244351a8efd7SJohan Hedberg clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); 2444a9de9248SMarcel Holtmann 2445a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 2446a9de9248SMarcel Holtmann } 2447a9de9248SMarcel Holtmann 2448a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2449a9de9248SMarcel Holtmann } 2450a9de9248SMarcel Holtmann 24511da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 24521da177e4SLinus Torvalds { 2453a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 24541da177e4SLinus Torvalds int i; 24551da177e4SLinus Torvalds 245632ac5b9bSAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) { 245732ac5b9bSAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 245832ac5b9bSAndrei Emeltchenko return; 245932ac5b9bSAndrei Emeltchenko } 246032ac5b9bSAndrei Emeltchenko 2461c5993de8SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 2462c5993de8SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_pkts_info)) { 24631da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 24641da177e4SLinus Torvalds return; 24651da177e4SLinus Torvalds } 24661da177e4SLinus Torvalds 2467c5993de8SAndrei Emeltchenko BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 2468c5993de8SAndrei Emeltchenko 2469613a1c0cSAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 2470613a1c0cSAndrei Emeltchenko struct hci_comp_pkts_info *info = &ev->handles[i]; 24711da177e4SLinus Torvalds struct hci_conn *conn; 24721da177e4SLinus Torvalds __u16 handle, count; 24731da177e4SLinus Torvalds 2474613a1c0cSAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 2475613a1c0cSAndrei Emeltchenko count = __le16_to_cpu(info->count); 24761da177e4SLinus Torvalds 24771da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 2478f4280918SAndrei Emeltchenko if (!conn) 2479f4280918SAndrei Emeltchenko continue; 2480f4280918SAndrei Emeltchenko 24811da177e4SLinus Torvalds conn->sent -= count; 24821da177e4SLinus Torvalds 2483f4280918SAndrei Emeltchenko switch (conn->type) { 2484f4280918SAndrei Emeltchenko case ACL_LINK: 248570f23020SAndrei Emeltchenko hdev->acl_cnt += count; 248670f23020SAndrei Emeltchenko if (hdev->acl_cnt > hdev->acl_pkts) 24871da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 2488f4280918SAndrei Emeltchenko break; 2489f4280918SAndrei Emeltchenko 2490f4280918SAndrei Emeltchenko case LE_LINK: 24916ed58ec5SVille Tervo if (hdev->le_pkts) { 24926ed58ec5SVille Tervo hdev->le_cnt += count; 24936ed58ec5SVille Tervo if (hdev->le_cnt > hdev->le_pkts) 24946ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 24956ed58ec5SVille Tervo } else { 24966ed58ec5SVille Tervo hdev->acl_cnt += count; 24976ed58ec5SVille Tervo if (hdev->acl_cnt > hdev->acl_pkts) 24986ed58ec5SVille Tervo hdev->acl_cnt = hdev->acl_pkts; 24996ed58ec5SVille Tervo } 2500f4280918SAndrei Emeltchenko break; 2501f4280918SAndrei Emeltchenko 2502f4280918SAndrei Emeltchenko case SCO_LINK: 250370f23020SAndrei Emeltchenko hdev->sco_cnt += count; 250470f23020SAndrei Emeltchenko if (hdev->sco_cnt > hdev->sco_pkts) 25055b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 2506f4280918SAndrei Emeltchenko break; 2507f4280918SAndrei Emeltchenko 2508f4280918SAndrei Emeltchenko default: 2509f4280918SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 2510f4280918SAndrei Emeltchenko break; 25111da177e4SLinus Torvalds } 25121da177e4SLinus Torvalds } 2513a9de9248SMarcel Holtmann 25143eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 25151da177e4SLinus Torvalds } 25161da177e4SLinus Torvalds 251725e89e99SAndrei Emeltchenko static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev, 251825e89e99SAndrei Emeltchenko struct sk_buff *skb) 251925e89e99SAndrei Emeltchenko { 252025e89e99SAndrei Emeltchenko struct hci_ev_num_comp_blocks *ev = (void *) skb->data; 252125e89e99SAndrei Emeltchenko int i; 252225e89e99SAndrei Emeltchenko 252325e89e99SAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) { 252425e89e99SAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 252525e89e99SAndrei Emeltchenko return; 252625e89e99SAndrei Emeltchenko } 252725e89e99SAndrei Emeltchenko 252825e89e99SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 252925e89e99SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_blocks_info)) { 253025e89e99SAndrei Emeltchenko BT_DBG("%s bad parameters", hdev->name); 253125e89e99SAndrei Emeltchenko return; 253225e89e99SAndrei Emeltchenko } 253325e89e99SAndrei Emeltchenko 253425e89e99SAndrei Emeltchenko BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks, 253525e89e99SAndrei Emeltchenko ev->num_hndl); 253625e89e99SAndrei Emeltchenko 253725e89e99SAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 253825e89e99SAndrei Emeltchenko struct hci_comp_blocks_info *info = &ev->handles[i]; 253925e89e99SAndrei Emeltchenko struct hci_conn *conn; 254025e89e99SAndrei Emeltchenko __u16 handle, block_count; 254125e89e99SAndrei Emeltchenko 254225e89e99SAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 254325e89e99SAndrei Emeltchenko block_count = __le16_to_cpu(info->blocks); 254425e89e99SAndrei Emeltchenko 254525e89e99SAndrei Emeltchenko conn = hci_conn_hash_lookup_handle(hdev, handle); 254625e89e99SAndrei Emeltchenko if (!conn) 254725e89e99SAndrei Emeltchenko continue; 254825e89e99SAndrei Emeltchenko 254925e89e99SAndrei Emeltchenko conn->sent -= block_count; 255025e89e99SAndrei Emeltchenko 255125e89e99SAndrei Emeltchenko switch (conn->type) { 255225e89e99SAndrei Emeltchenko case ACL_LINK: 255325e89e99SAndrei Emeltchenko hdev->block_cnt += block_count; 255425e89e99SAndrei Emeltchenko if (hdev->block_cnt > hdev->num_blocks) 255525e89e99SAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 255625e89e99SAndrei Emeltchenko break; 255725e89e99SAndrei Emeltchenko 255825e89e99SAndrei Emeltchenko default: 255925e89e99SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 256025e89e99SAndrei Emeltchenko break; 256125e89e99SAndrei Emeltchenko } 256225e89e99SAndrei Emeltchenko } 256325e89e99SAndrei Emeltchenko 256425e89e99SAndrei Emeltchenko queue_work(hdev->workqueue, &hdev->tx_work); 256525e89e99SAndrei Emeltchenko } 256625e89e99SAndrei Emeltchenko 256704837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 25681da177e4SLinus Torvalds { 2569a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 257004837f64SMarcel Holtmann struct hci_conn *conn; 25711da177e4SLinus Torvalds 25721da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 25731da177e4SLinus Torvalds 25741da177e4SLinus Torvalds hci_dev_lock(hdev); 25751da177e4SLinus Torvalds 257604837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 257704837f64SMarcel Holtmann if (conn) { 257804837f64SMarcel Holtmann conn->mode = ev->mode; 257904837f64SMarcel Holtmann conn->interval = __le16_to_cpu(ev->interval); 258004837f64SMarcel Holtmann 258151a8efd7SJohan Hedberg if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) { 258204837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 258358a681efSJohan Hedberg set_bit(HCI_CONN_POWER_SAVE, &conn->flags); 258404837f64SMarcel Holtmann else 258558a681efSJohan Hedberg clear_bit(HCI_CONN_POWER_SAVE, &conn->flags); 258604837f64SMarcel Holtmann } 2587e73439d8SMarcel Holtmann 258851a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 2589e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 259004837f64SMarcel Holtmann } 259104837f64SMarcel Holtmann 259204837f64SMarcel Holtmann hci_dev_unlock(hdev); 259304837f64SMarcel Holtmann } 259404837f64SMarcel Holtmann 25951da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 25961da177e4SLinus Torvalds { 2597052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 2598052b30b0SMarcel Holtmann struct hci_conn *conn; 2599052b30b0SMarcel Holtmann 2600a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2601052b30b0SMarcel Holtmann 2602052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2603052b30b0SMarcel Holtmann 2604052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2605b6f98044SWaldemar Rymarkiewicz if (!conn) 2606b6f98044SWaldemar Rymarkiewicz goto unlock; 2607b6f98044SWaldemar Rymarkiewicz 2608b6f98044SWaldemar Rymarkiewicz if (conn->state == BT_CONNECTED) { 2609052b30b0SMarcel Holtmann hci_conn_hold(conn); 2610052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 2611052b30b0SMarcel Holtmann hci_conn_put(conn); 2612052b30b0SMarcel Holtmann } 2613052b30b0SMarcel Holtmann 2614a8b2d5c2SJohan Hedberg if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags)) 261503b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 261603b555e1SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 2617a8b2d5c2SJohan Hedberg else if (test_bit(HCI_MGMT, &hdev->dev_flags)) { 2618a770bb5aSWaldemar Rymarkiewicz u8 secure; 2619a770bb5aSWaldemar Rymarkiewicz 2620a770bb5aSWaldemar Rymarkiewicz if (conn->pending_sec_level == BT_SECURITY_HIGH) 2621a770bb5aSWaldemar Rymarkiewicz secure = 1; 2622a770bb5aSWaldemar Rymarkiewicz else 2623a770bb5aSWaldemar Rymarkiewicz secure = 0; 2624a770bb5aSWaldemar Rymarkiewicz 2625744cf19eSJohan Hedberg mgmt_pin_code_request(hdev, &ev->bdaddr, secure); 2626a770bb5aSWaldemar Rymarkiewicz } 2627980e1a53SJohan Hedberg 2628b6f98044SWaldemar Rymarkiewicz unlock: 2629052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 26301da177e4SLinus Torvalds } 26311da177e4SLinus Torvalds 26321da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 26331da177e4SLinus Torvalds { 263455ed8ca1SJohan Hedberg struct hci_ev_link_key_req *ev = (void *) skb->data; 263555ed8ca1SJohan Hedberg struct hci_cp_link_key_reply cp; 263655ed8ca1SJohan Hedberg struct hci_conn *conn; 263755ed8ca1SJohan Hedberg struct link_key *key; 263855ed8ca1SJohan Hedberg 2639a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 264055ed8ca1SJohan Hedberg 2641a8b2d5c2SJohan Hedberg if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) 264255ed8ca1SJohan Hedberg return; 264355ed8ca1SJohan Hedberg 264455ed8ca1SJohan Hedberg hci_dev_lock(hdev); 264555ed8ca1SJohan Hedberg 264655ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, &ev->bdaddr); 264755ed8ca1SJohan Hedberg if (!key) { 264855ed8ca1SJohan Hedberg BT_DBG("%s link key not found for %s", hdev->name, 264955ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 265055ed8ca1SJohan Hedberg goto not_found; 265155ed8ca1SJohan Hedberg } 265255ed8ca1SJohan Hedberg 265355ed8ca1SJohan Hedberg BT_DBG("%s found key type %u for %s", hdev->name, key->type, 265455ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 265555ed8ca1SJohan Hedberg 2656a8b2d5c2SJohan Hedberg if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) && 2657b6020ba0SWaldemar Rymarkiewicz key->type == HCI_LK_DEBUG_COMBINATION) { 265855ed8ca1SJohan Hedberg BT_DBG("%s ignoring debug key", hdev->name); 265955ed8ca1SJohan Hedberg goto not_found; 266055ed8ca1SJohan Hedberg } 266155ed8ca1SJohan Hedberg 266255ed8ca1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 266360b83f57SWaldemar Rymarkiewicz if (conn) { 266460b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_UNAUTH_COMBINATION && 266560b83f57SWaldemar Rymarkiewicz conn->auth_type != 0xff && 266660b83f57SWaldemar Rymarkiewicz (conn->auth_type & 0x01)) { 266755ed8ca1SJohan Hedberg BT_DBG("%s ignoring unauthenticated key", hdev->name); 266855ed8ca1SJohan Hedberg goto not_found; 266955ed8ca1SJohan Hedberg } 267055ed8ca1SJohan Hedberg 267160b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && 267260b83f57SWaldemar Rymarkiewicz conn->pending_sec_level == BT_SECURITY_HIGH) { 267360b83f57SWaldemar Rymarkiewicz BT_DBG("%s ignoring key unauthenticated for high \ 267460b83f57SWaldemar Rymarkiewicz security", hdev->name); 267560b83f57SWaldemar Rymarkiewicz goto not_found; 267660b83f57SWaldemar Rymarkiewicz } 267760b83f57SWaldemar Rymarkiewicz 267860b83f57SWaldemar Rymarkiewicz conn->key_type = key->type; 267960b83f57SWaldemar Rymarkiewicz conn->pin_length = key->pin_len; 268060b83f57SWaldemar Rymarkiewicz } 268160b83f57SWaldemar Rymarkiewicz 268255ed8ca1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 268355ed8ca1SJohan Hedberg memcpy(cp.link_key, key->val, 16); 268455ed8ca1SJohan Hedberg 268555ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 268655ed8ca1SJohan Hedberg 268755ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 268855ed8ca1SJohan Hedberg 268955ed8ca1SJohan Hedberg return; 269055ed8ca1SJohan Hedberg 269155ed8ca1SJohan Hedberg not_found: 269255ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 269355ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 26941da177e4SLinus Torvalds } 26951da177e4SLinus Torvalds 26961da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 26971da177e4SLinus Torvalds { 2698052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 2699052b30b0SMarcel Holtmann struct hci_conn *conn; 270055ed8ca1SJohan Hedberg u8 pin_len = 0; 2701052b30b0SMarcel Holtmann 2702a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2703052b30b0SMarcel Holtmann 2704052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2705052b30b0SMarcel Holtmann 2706052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2707052b30b0SMarcel Holtmann if (conn) { 2708052b30b0SMarcel Holtmann hci_conn_hold(conn); 2709052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2710980e1a53SJohan Hedberg pin_len = conn->pin_length; 271113d39315SWaldemar Rymarkiewicz 271213d39315SWaldemar Rymarkiewicz if (ev->key_type != HCI_LK_CHANGED_COMBINATION) 271313d39315SWaldemar Rymarkiewicz conn->key_type = ev->key_type; 271413d39315SWaldemar Rymarkiewicz 2715052b30b0SMarcel Holtmann hci_conn_put(conn); 2716052b30b0SMarcel Holtmann } 2717052b30b0SMarcel Holtmann 2718a8b2d5c2SJohan Hedberg if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) 2719d25e28abSJohan Hedberg hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, 272055ed8ca1SJohan Hedberg ev->key_type, pin_len); 272155ed8ca1SJohan Hedberg 2722052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 27231da177e4SLinus Torvalds } 27241da177e4SLinus Torvalds 272504837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 272604837f64SMarcel Holtmann { 2727a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 272804837f64SMarcel Holtmann struct hci_conn *conn; 272904837f64SMarcel Holtmann 273004837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 273104837f64SMarcel Holtmann 273204837f64SMarcel Holtmann hci_dev_lock(hdev); 273304837f64SMarcel Holtmann 273404837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 27351da177e4SLinus Torvalds if (conn && !ev->status) { 27361da177e4SLinus Torvalds struct inquiry_entry *ie; 27371da177e4SLinus Torvalds 2738cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2739cc11b9c1SAndrei Emeltchenko if (ie) { 27401da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 27411da177e4SLinus Torvalds ie->timestamp = jiffies; 27421da177e4SLinus Torvalds } 27431da177e4SLinus Torvalds } 27441da177e4SLinus Torvalds 27451da177e4SLinus Torvalds hci_dev_unlock(hdev); 27461da177e4SLinus Torvalds } 27471da177e4SLinus Torvalds 2748a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2749a8746417SMarcel Holtmann { 2750a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 2751a8746417SMarcel Holtmann struct hci_conn *conn; 2752a8746417SMarcel Holtmann 2753a8746417SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2754a8746417SMarcel Holtmann 2755a8746417SMarcel Holtmann hci_dev_lock(hdev); 2756a8746417SMarcel Holtmann 2757a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2758a8746417SMarcel Holtmann if (conn && !ev->status) 2759a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 2760a8746417SMarcel Holtmann 2761a8746417SMarcel Holtmann hci_dev_unlock(hdev); 2762a8746417SMarcel Holtmann } 2763a8746417SMarcel Holtmann 276485a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 276585a1e930SMarcel Holtmann { 2766a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 276785a1e930SMarcel Holtmann struct inquiry_entry *ie; 276885a1e930SMarcel Holtmann 276985a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 277085a1e930SMarcel Holtmann 277185a1e930SMarcel Holtmann hci_dev_lock(hdev); 277285a1e930SMarcel Holtmann 2773cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2774cc11b9c1SAndrei Emeltchenko if (ie) { 277585a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 277685a1e930SMarcel Holtmann ie->timestamp = jiffies; 277785a1e930SMarcel Holtmann } 277885a1e930SMarcel Holtmann 277985a1e930SMarcel Holtmann hci_dev_unlock(hdev); 278085a1e930SMarcel Holtmann } 278185a1e930SMarcel Holtmann 2782a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb) 2783a9de9248SMarcel Holtmann { 2784a9de9248SMarcel Holtmann struct inquiry_data data; 2785a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2786388fc8faSJohan Hedberg bool name_known, ssp; 2787a9de9248SMarcel Holtmann 2788a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2789a9de9248SMarcel Holtmann 2790a9de9248SMarcel Holtmann if (!num_rsp) 2791a9de9248SMarcel Holtmann return; 2792a9de9248SMarcel Holtmann 2793a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2794a9de9248SMarcel Holtmann 2795a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 2796138d22efSSzymon Janc struct inquiry_info_with_rssi_and_pscan_mode *info; 2797138d22efSSzymon Janc info = (void *) (skb->data + 1); 2798a9de9248SMarcel Holtmann 2799e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2800a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2801a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2802a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2803a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 2804a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2805a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2806a9de9248SMarcel Holtmann data.rssi = info->rssi; 280741a96212SMarcel Holtmann data.ssp_mode = 0x00; 28083175405bSJohan Hedberg 28093175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 2810388fc8faSJohan Hedberg false, &ssp); 281148264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2812e17acd40SJohan Hedberg info->dev_class, info->rssi, 2813388fc8faSJohan Hedberg !name_known, ssp, NULL, 0); 2814a9de9248SMarcel Holtmann } 2815a9de9248SMarcel Holtmann } else { 2816a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 2817a9de9248SMarcel Holtmann 2818e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2819a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2820a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2821a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2822a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2823a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2824a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2825a9de9248SMarcel Holtmann data.rssi = info->rssi; 282641a96212SMarcel Holtmann data.ssp_mode = 0x00; 28273175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 2828388fc8faSJohan Hedberg false, &ssp); 282948264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2830e17acd40SJohan Hedberg info->dev_class, info->rssi, 2831388fc8faSJohan Hedberg !name_known, ssp, NULL, 0); 2832a9de9248SMarcel Holtmann } 2833a9de9248SMarcel Holtmann } 2834a9de9248SMarcel Holtmann 2835a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2836a9de9248SMarcel Holtmann } 2837a9de9248SMarcel Holtmann 2838a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 2839a9de9248SMarcel Holtmann { 284041a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 284141a96212SMarcel Holtmann struct hci_conn *conn; 284241a96212SMarcel Holtmann 2843a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 284441a96212SMarcel Holtmann 284541a96212SMarcel Holtmann hci_dev_lock(hdev); 284641a96212SMarcel Holtmann 284741a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2848ccd556feSJohan Hedberg if (!conn) 2849ccd556feSJohan Hedberg goto unlock; 2850ccd556feSJohan Hedberg 2851769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 285241a96212SMarcel Holtmann struct inquiry_entry *ie; 285341a96212SMarcel Holtmann 2854cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2855cc11b9c1SAndrei Emeltchenko if (ie) 285641a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 285741a96212SMarcel Holtmann 285858a681efSJohan Hedberg if (ev->features[0] & 0x01) 285958a681efSJohan Hedberg set_bit(HCI_CONN_SSP_ENABLED, &conn->flags); 286041a96212SMarcel Holtmann } 286141a96212SMarcel Holtmann 2862ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2863ccd556feSJohan Hedberg goto unlock; 2864ccd556feSJohan Hedberg 2865127178d2SJohan Hedberg if (!ev->status) { 2866127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2867127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2868127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2869127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2870127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2871b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 2872b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 2873b644ba33SJohan Hedberg conn->dst_type, NULL, 0, 2874b644ba33SJohan Hedberg conn->dev_class); 2875392599b9SJohan Hedberg 2876127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2877769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2878769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2879769be974SMarcel Holtmann hci_conn_put(conn); 2880769be974SMarcel Holtmann } 2881769be974SMarcel Holtmann 2882ccd556feSJohan Hedberg unlock: 288341a96212SMarcel Holtmann hci_dev_unlock(hdev); 2884a9de9248SMarcel Holtmann } 2885a9de9248SMarcel Holtmann 2886a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2887a9de9248SMarcel Holtmann { 2888b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 2889b6a0dc82SMarcel Holtmann struct hci_conn *conn; 2890b6a0dc82SMarcel Holtmann 2891b6a0dc82SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2892b6a0dc82SMarcel Holtmann 2893b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 2894b6a0dc82SMarcel Holtmann 2895b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 28969dc0a3afSMarcel Holtmann if (!conn) { 28979dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 28989dc0a3afSMarcel Holtmann goto unlock; 28999dc0a3afSMarcel Holtmann 29009dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 2901b6a0dc82SMarcel Holtmann if (!conn) 2902b6a0dc82SMarcel Holtmann goto unlock; 2903b6a0dc82SMarcel Holtmann 29049dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 29059dc0a3afSMarcel Holtmann } 29069dc0a3afSMarcel Holtmann 2907732547f9SMarcel Holtmann switch (ev->status) { 2908732547f9SMarcel Holtmann case 0x00: 2909732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 2910732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 2911732547f9SMarcel Holtmann 29129eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 2913732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 2914732547f9SMarcel Holtmann break; 2915732547f9SMarcel Holtmann 2916705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 2917732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 29181038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 2919732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 2920732547f9SMarcel Holtmann if (conn->out && conn->attempt < 2) { 2921efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 2922efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 2923efc7688bSMarcel Holtmann hci_setup_sync(conn, conn->link->handle); 2924efc7688bSMarcel Holtmann goto unlock; 2925efc7688bSMarcel Holtmann } 2926732547f9SMarcel Holtmann /* fall through */ 2927efc7688bSMarcel Holtmann 2928732547f9SMarcel Holtmann default: 2929b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 2930732547f9SMarcel Holtmann break; 2931732547f9SMarcel Holtmann } 2932b6a0dc82SMarcel Holtmann 2933b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2934b6a0dc82SMarcel Holtmann if (ev->status) 2935b6a0dc82SMarcel Holtmann hci_conn_del(conn); 2936b6a0dc82SMarcel Holtmann 2937b6a0dc82SMarcel Holtmann unlock: 2938b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 2939a9de9248SMarcel Holtmann } 2940a9de9248SMarcel Holtmann 2941a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) 2942a9de9248SMarcel Holtmann { 2943a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2944a9de9248SMarcel Holtmann } 2945a9de9248SMarcel Holtmann 294604837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) 294704837f64SMarcel Holtmann { 2948a9de9248SMarcel Holtmann struct hci_ev_sniff_subrate *ev = (void *) skb->data; 294904837f64SMarcel Holtmann 295004837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 295104837f64SMarcel Holtmann } 295204837f64SMarcel Holtmann 2953a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 2954a9de9248SMarcel Holtmann { 2955a9de9248SMarcel Holtmann struct inquiry_data data; 2956a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 2957a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2958a9de9248SMarcel Holtmann 2959a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2960a9de9248SMarcel Holtmann 2961a9de9248SMarcel Holtmann if (!num_rsp) 2962a9de9248SMarcel Holtmann return; 2963a9de9248SMarcel Holtmann 2964a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2965a9de9248SMarcel Holtmann 2966e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2967388fc8faSJohan Hedberg bool name_known, ssp; 2968561aafbcSJohan Hedberg 2969a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2970a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2971a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2972a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2973a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2974a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2975a9de9248SMarcel Holtmann data.rssi = info->rssi; 297641a96212SMarcel Holtmann data.ssp_mode = 0x01; 2977561aafbcSJohan Hedberg 2978a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 29794ddb1930SJohan Hedberg name_known = eir_has_data_type(info->data, 29804ddb1930SJohan Hedberg sizeof(info->data), 29814ddb1930SJohan Hedberg EIR_NAME_COMPLETE); 2982561aafbcSJohan Hedberg else 2983561aafbcSJohan Hedberg name_known = true; 2984561aafbcSJohan Hedberg 2985388fc8faSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, name_known, 2986388fc8faSJohan Hedberg &ssp); 298748264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2988561aafbcSJohan Hedberg info->dev_class, info->rssi, 2989388fc8faSJohan Hedberg !name_known, ssp, info->data, 29907d262f86SAndre Guedes sizeof(info->data)); 2991a9de9248SMarcel Holtmann } 2992a9de9248SMarcel Holtmann 2993a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2994a9de9248SMarcel Holtmann } 2995a9de9248SMarcel Holtmann 299617fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn) 299717fa4b9dSJohan Hedberg { 299817fa4b9dSJohan Hedberg /* If remote requests dedicated bonding follow that lead */ 299917fa4b9dSJohan Hedberg if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) { 300017fa4b9dSJohan Hedberg /* If both remote and local IO capabilities allow MITM 300117fa4b9dSJohan Hedberg * protection then require it, otherwise don't */ 300217fa4b9dSJohan Hedberg if (conn->remote_cap == 0x03 || conn->io_capability == 0x03) 300317fa4b9dSJohan Hedberg return 0x02; 300417fa4b9dSJohan Hedberg else 300517fa4b9dSJohan Hedberg return 0x03; 300617fa4b9dSJohan Hedberg } 300717fa4b9dSJohan Hedberg 300817fa4b9dSJohan Hedberg /* If remote requests no-bonding follow that lead */ 300917fa4b9dSJohan Hedberg if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01) 301058797bf7SWaldemar Rymarkiewicz return conn->remote_auth | (conn->auth_type & 0x01); 301117fa4b9dSJohan Hedberg 301217fa4b9dSJohan Hedberg return conn->auth_type; 301317fa4b9dSJohan Hedberg } 301417fa4b9dSJohan Hedberg 30150493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 30160493684eSMarcel Holtmann { 30170493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 30180493684eSMarcel Holtmann struct hci_conn *conn; 30190493684eSMarcel Holtmann 30200493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 30210493684eSMarcel Holtmann 30220493684eSMarcel Holtmann hci_dev_lock(hdev); 30230493684eSMarcel Holtmann 30240493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 302503b555e1SJohan Hedberg if (!conn) 302603b555e1SJohan Hedberg goto unlock; 302703b555e1SJohan Hedberg 30280493684eSMarcel Holtmann hci_conn_hold(conn); 30290493684eSMarcel Holtmann 3030a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 303103b555e1SJohan Hedberg goto unlock; 303203b555e1SJohan Hedberg 3033a8b2d5c2SJohan Hedberg if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) || 303403b555e1SJohan Hedberg (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 303517fa4b9dSJohan Hedberg struct hci_cp_io_capability_reply cp; 303617fa4b9dSJohan Hedberg 303717fa4b9dSJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 30387a7f1e7cSHemant Gupta /* Change the IO capability from KeyboardDisplay 30397a7f1e7cSHemant Gupta * to DisplayYesNo as it is not supported by BT spec. */ 30407a7f1e7cSHemant Gupta cp.capability = (conn->io_capability == 0x04) ? 30417a7f1e7cSHemant Gupta 0x01 : conn->io_capability; 30427cbc9bd9SJohan Hedberg conn->auth_type = hci_get_auth_req(conn); 30437cbc9bd9SJohan Hedberg cp.authentication = conn->auth_type; 304417fa4b9dSJohan Hedberg 304558a681efSJohan Hedberg if ((conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)) && 3046ce85ee13SSzymon Janc hci_find_remote_oob_data(hdev, &conn->dst)) 3047ce85ee13SSzymon Janc cp.oob_data = 0x01; 3048ce85ee13SSzymon Janc else 3049ce85ee13SSzymon Janc cp.oob_data = 0x00; 3050ce85ee13SSzymon Janc 305117fa4b9dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, 305217fa4b9dSJohan Hedberg sizeof(cp), &cp); 305303b555e1SJohan Hedberg } else { 305403b555e1SJohan Hedberg struct hci_cp_io_capability_neg_reply cp; 305503b555e1SJohan Hedberg 305603b555e1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 30579f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED; 305803b555e1SJohan Hedberg 305903b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 306003b555e1SJohan Hedberg sizeof(cp), &cp); 306103b555e1SJohan Hedberg } 306203b555e1SJohan Hedberg 306303b555e1SJohan Hedberg unlock: 306403b555e1SJohan Hedberg hci_dev_unlock(hdev); 306503b555e1SJohan Hedberg } 306603b555e1SJohan Hedberg 306703b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 306803b555e1SJohan Hedberg { 306903b555e1SJohan Hedberg struct hci_ev_io_capa_reply *ev = (void *) skb->data; 307003b555e1SJohan Hedberg struct hci_conn *conn; 307103b555e1SJohan Hedberg 307203b555e1SJohan Hedberg BT_DBG("%s", hdev->name); 307303b555e1SJohan Hedberg 307403b555e1SJohan Hedberg hci_dev_lock(hdev); 307503b555e1SJohan Hedberg 307603b555e1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 307703b555e1SJohan Hedberg if (!conn) 307803b555e1SJohan Hedberg goto unlock; 307903b555e1SJohan Hedberg 308003b555e1SJohan Hedberg conn->remote_cap = ev->capability; 308103b555e1SJohan Hedberg conn->remote_auth = ev->authentication; 308258a681efSJohan Hedberg if (ev->oob_data) 308358a681efSJohan Hedberg set_bit(HCI_CONN_REMOTE_OOB, &conn->flags); 308403b555e1SJohan Hedberg 308503b555e1SJohan Hedberg unlock: 30860493684eSMarcel Holtmann hci_dev_unlock(hdev); 30870493684eSMarcel Holtmann } 30880493684eSMarcel Holtmann 3089a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev, 3090a5c29683SJohan Hedberg struct sk_buff *skb) 3091a5c29683SJohan Hedberg { 3092a5c29683SJohan Hedberg struct hci_ev_user_confirm_req *ev = (void *) skb->data; 309355bc1a37SJohan Hedberg int loc_mitm, rem_mitm, confirm_hint = 0; 30947a828908SJohan Hedberg struct hci_conn *conn; 3095a5c29683SJohan Hedberg 3096a5c29683SJohan Hedberg BT_DBG("%s", hdev->name); 3097a5c29683SJohan Hedberg 3098a5c29683SJohan Hedberg hci_dev_lock(hdev); 3099a5c29683SJohan Hedberg 3100a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 31017a828908SJohan Hedberg goto unlock; 31027a828908SJohan Hedberg 31037a828908SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 31047a828908SJohan Hedberg if (!conn) 31057a828908SJohan Hedberg goto unlock; 31067a828908SJohan Hedberg 31077a828908SJohan Hedberg loc_mitm = (conn->auth_type & 0x01); 31087a828908SJohan Hedberg rem_mitm = (conn->remote_auth & 0x01); 31097a828908SJohan Hedberg 31107a828908SJohan Hedberg /* If we require MITM but the remote device can't provide that 31117a828908SJohan Hedberg * (it has NoInputNoOutput) then reject the confirmation 31127a828908SJohan Hedberg * request. The only exception is when we're dedicated bonding 31137a828908SJohan Hedberg * initiators (connect_cfm_cb set) since then we always have the MITM 31147a828908SJohan Hedberg * bit set. */ 31157a828908SJohan Hedberg if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) { 31167a828908SJohan Hedberg BT_DBG("Rejecting request: remote device can't provide MITM"); 31177a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, 31187a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 31197a828908SJohan Hedberg goto unlock; 31207a828908SJohan Hedberg } 31217a828908SJohan Hedberg 31227a828908SJohan Hedberg /* If no side requires MITM protection; auto-accept */ 31237a828908SJohan Hedberg if ((!loc_mitm || conn->remote_cap == 0x03) && 31247a828908SJohan Hedberg (!rem_mitm || conn->io_capability == 0x03)) { 312555bc1a37SJohan Hedberg 312655bc1a37SJohan Hedberg /* If we're not the initiators request authorization to 312755bc1a37SJohan Hedberg * proceed from user space (mgmt_user_confirm with 312855bc1a37SJohan Hedberg * confirm_hint set to 1). */ 312951a8efd7SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 313055bc1a37SJohan Hedberg BT_DBG("Confirming auto-accept as acceptor"); 313155bc1a37SJohan Hedberg confirm_hint = 1; 313255bc1a37SJohan Hedberg goto confirm; 313355bc1a37SJohan Hedberg } 313455bc1a37SJohan Hedberg 31359f61656aSJohan Hedberg BT_DBG("Auto-accept of user confirmation with %ums delay", 31369f61656aSJohan Hedberg hdev->auto_accept_delay); 31379f61656aSJohan Hedberg 31389f61656aSJohan Hedberg if (hdev->auto_accept_delay > 0) { 31399f61656aSJohan Hedberg int delay = msecs_to_jiffies(hdev->auto_accept_delay); 31409f61656aSJohan Hedberg mod_timer(&conn->auto_accept_timer, jiffies + delay); 31419f61656aSJohan Hedberg goto unlock; 31429f61656aSJohan Hedberg } 31439f61656aSJohan Hedberg 31447a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, 31457a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 31467a828908SJohan Hedberg goto unlock; 31477a828908SJohan Hedberg } 31487a828908SJohan Hedberg 314955bc1a37SJohan Hedberg confirm: 3150272d90dfSJohan Hedberg mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey, 315155bc1a37SJohan Hedberg confirm_hint); 3152a5c29683SJohan Hedberg 31537a828908SJohan Hedberg unlock: 3154a5c29683SJohan Hedberg hci_dev_unlock(hdev); 3155a5c29683SJohan Hedberg } 3156a5c29683SJohan Hedberg 31571143d458SBrian Gix static inline void hci_user_passkey_request_evt(struct hci_dev *hdev, 31581143d458SBrian Gix struct sk_buff *skb) 31591143d458SBrian Gix { 31601143d458SBrian Gix struct hci_ev_user_passkey_req *ev = (void *) skb->data; 31611143d458SBrian Gix 31621143d458SBrian Gix BT_DBG("%s", hdev->name); 31631143d458SBrian Gix 31641143d458SBrian Gix hci_dev_lock(hdev); 31651143d458SBrian Gix 3166a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 3167272d90dfSJohan Hedberg mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); 31681143d458SBrian Gix 31691143d458SBrian Gix hci_dev_unlock(hdev); 31701143d458SBrian Gix } 31711143d458SBrian Gix 31720493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 31730493684eSMarcel Holtmann { 31740493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 31750493684eSMarcel Holtmann struct hci_conn *conn; 31760493684eSMarcel Holtmann 31770493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 31780493684eSMarcel Holtmann 31790493684eSMarcel Holtmann hci_dev_lock(hdev); 31800493684eSMarcel Holtmann 31810493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 31822a611692SJohan Hedberg if (!conn) 31832a611692SJohan Hedberg goto unlock; 31842a611692SJohan Hedberg 31852a611692SJohan Hedberg /* To avoid duplicate auth_failed events to user space we check 31862a611692SJohan Hedberg * the HCI_CONN_AUTH_PEND flag which will be set if we 31872a611692SJohan Hedberg * initiated the authentication. A traditional auth_complete 31882a611692SJohan Hedberg * event gets always produced as initiator and is also mapped to 31892a611692SJohan Hedberg * the mgmt_auth_failed event */ 319051a8efd7SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status != 0) 3191bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 3192bab73cb6SJohan Hedberg ev->status); 31932a611692SJohan Hedberg 31940493684eSMarcel Holtmann hci_conn_put(conn); 31950493684eSMarcel Holtmann 31962a611692SJohan Hedberg unlock: 31970493684eSMarcel Holtmann hci_dev_unlock(hdev); 31980493684eSMarcel Holtmann } 31990493684eSMarcel Holtmann 320041a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 320141a96212SMarcel Holtmann { 320241a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 320341a96212SMarcel Holtmann struct inquiry_entry *ie; 320441a96212SMarcel Holtmann 320541a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 320641a96212SMarcel Holtmann 320741a96212SMarcel Holtmann hci_dev_lock(hdev); 320841a96212SMarcel Holtmann 3209cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 3210cc11b9c1SAndrei Emeltchenko if (ie) 321141a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 321241a96212SMarcel Holtmann 321341a96212SMarcel Holtmann hci_dev_unlock(hdev); 321441a96212SMarcel Holtmann } 321541a96212SMarcel Holtmann 32162763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev, 32172763eda6SSzymon Janc struct sk_buff *skb) 32182763eda6SSzymon Janc { 32192763eda6SSzymon Janc struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; 32202763eda6SSzymon Janc struct oob_data *data; 32212763eda6SSzymon Janc 32222763eda6SSzymon Janc BT_DBG("%s", hdev->name); 32232763eda6SSzymon Janc 32242763eda6SSzymon Janc hci_dev_lock(hdev); 32252763eda6SSzymon Janc 3226a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 3227e1ba1f15SSzymon Janc goto unlock; 3228e1ba1f15SSzymon Janc 32292763eda6SSzymon Janc data = hci_find_remote_oob_data(hdev, &ev->bdaddr); 32302763eda6SSzymon Janc if (data) { 32312763eda6SSzymon Janc struct hci_cp_remote_oob_data_reply cp; 32322763eda6SSzymon Janc 32332763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 32342763eda6SSzymon Janc memcpy(cp.hash, data->hash, sizeof(cp.hash)); 32352763eda6SSzymon Janc memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); 32362763eda6SSzymon Janc 32372763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), 32382763eda6SSzymon Janc &cp); 32392763eda6SSzymon Janc } else { 32402763eda6SSzymon Janc struct hci_cp_remote_oob_data_neg_reply cp; 32412763eda6SSzymon Janc 32422763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 32432763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), 32442763eda6SSzymon Janc &cp); 32452763eda6SSzymon Janc } 32462763eda6SSzymon Janc 3247e1ba1f15SSzymon Janc unlock: 32482763eda6SSzymon Janc hci_dev_unlock(hdev); 32492763eda6SSzymon Janc } 32502763eda6SSzymon Janc 3251fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 3252fcd89c09SVille Tervo { 3253fcd89c09SVille Tervo struct hci_ev_le_conn_complete *ev = (void *) skb->data; 3254fcd89c09SVille Tervo struct hci_conn *conn; 3255fcd89c09SVille Tervo 3256fcd89c09SVille Tervo BT_DBG("%s status %d", hdev->name, ev->status); 3257fcd89c09SVille Tervo 3258fcd89c09SVille Tervo hci_dev_lock(hdev); 3259fcd89c09SVille Tervo 3260fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr); 3261b62f328bSVille Tervo if (!conn) { 3262b62f328bSVille Tervo conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); 3263b62f328bSVille Tervo if (!conn) { 3264b62f328bSVille Tervo BT_ERR("No memory for new connection"); 3265b62f328bSVille Tervo hci_dev_unlock(hdev); 3266b62f328bSVille Tervo return; 3267b62f328bSVille Tervo } 326829b7988aSAndre Guedes 326929b7988aSAndre Guedes conn->dst_type = ev->bdaddr_type; 3270b62f328bSVille Tervo } 3271fcd89c09SVille Tervo 3272fcd89c09SVille Tervo if (ev->status) { 327348264f06SJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 327448264f06SJohan Hedberg conn->dst_type, ev->status); 3275fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 3276fcd89c09SVille Tervo conn->state = BT_CLOSED; 3277fcd89c09SVille Tervo hci_conn_del(conn); 3278fcd89c09SVille Tervo goto unlock; 3279fcd89c09SVille Tervo } 3280fcd89c09SVille Tervo 3281b644ba33SJohan Hedberg if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 3282b644ba33SJohan Hedberg mgmt_device_connected(hdev, &ev->bdaddr, conn->type, 3283b644ba33SJohan Hedberg conn->dst_type, NULL, 0, 0); 328483bc71b4SVinicius Costa Gomes 32857b5c0d52SVinicius Costa Gomes conn->sec_level = BT_SECURITY_LOW; 3286fcd89c09SVille Tervo conn->handle = __le16_to_cpu(ev->handle); 3287fcd89c09SVille Tervo conn->state = BT_CONNECTED; 3288fcd89c09SVille Tervo 3289fcd89c09SVille Tervo hci_conn_hold_device(conn); 3290fcd89c09SVille Tervo hci_conn_add_sysfs(conn); 3291fcd89c09SVille Tervo 3292fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 3293fcd89c09SVille Tervo 3294fcd89c09SVille Tervo unlock: 3295fcd89c09SVille Tervo hci_dev_unlock(hdev); 3296fcd89c09SVille Tervo } 3297fcd89c09SVille Tervo 32989aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev, 32999aa04c91SAndre Guedes struct sk_buff *skb) 33009aa04c91SAndre Guedes { 3301e95beb41SAndre Guedes u8 num_reports = skb->data[0]; 3302e95beb41SAndre Guedes void *ptr = &skb->data[1]; 33033c9e9195SAndre Guedes s8 rssi; 33049aa04c91SAndre Guedes 33059aa04c91SAndre Guedes hci_dev_lock(hdev); 33069aa04c91SAndre Guedes 3307e95beb41SAndre Guedes while (num_reports--) { 3308e95beb41SAndre Guedes struct hci_ev_le_advertising_info *ev = ptr; 3309e95beb41SAndre Guedes 33109aa04c91SAndre Guedes hci_add_adv_entry(hdev, ev); 33119aa04c91SAndre Guedes 33123c9e9195SAndre Guedes rssi = ev->data[ev->length]; 33133c9e9195SAndre Guedes mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type, 3314388fc8faSJohan Hedberg NULL, rssi, 0, 1, ev->data, 3315388fc8faSJohan Hedberg ev->length); 33163c9e9195SAndre Guedes 3317e95beb41SAndre Guedes ptr += sizeof(*ev) + ev->length + 1; 33189aa04c91SAndre Guedes } 33199aa04c91SAndre Guedes 33209aa04c91SAndre Guedes hci_dev_unlock(hdev); 33219aa04c91SAndre Guedes } 33229aa04c91SAndre Guedes 3323a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev, 3324a7a595f6SVinicius Costa Gomes struct sk_buff *skb) 3325a7a595f6SVinicius Costa Gomes { 3326a7a595f6SVinicius Costa Gomes struct hci_ev_le_ltk_req *ev = (void *) skb->data; 3327a7a595f6SVinicius Costa Gomes struct hci_cp_le_ltk_reply cp; 3328bea710feSVinicius Costa Gomes struct hci_cp_le_ltk_neg_reply neg; 3329a7a595f6SVinicius Costa Gomes struct hci_conn *conn; 3330c9839a11SVinicius Costa Gomes struct smp_ltk *ltk; 3331a7a595f6SVinicius Costa Gomes 3332a7a595f6SVinicius Costa Gomes BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle)); 3333a7a595f6SVinicius Costa Gomes 3334a7a595f6SVinicius Costa Gomes hci_dev_lock(hdev); 3335a7a595f6SVinicius Costa Gomes 3336a7a595f6SVinicius Costa Gomes conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3337bea710feSVinicius Costa Gomes if (conn == NULL) 3338bea710feSVinicius Costa Gomes goto not_found; 3339a7a595f6SVinicius Costa Gomes 3340bea710feSVinicius Costa Gomes ltk = hci_find_ltk(hdev, ev->ediv, ev->random); 3341bea710feSVinicius Costa Gomes if (ltk == NULL) 3342bea710feSVinicius Costa Gomes goto not_found; 3343bea710feSVinicius Costa Gomes 3344bea710feSVinicius Costa Gomes memcpy(cp.ltk, ltk->val, sizeof(ltk->val)); 3345a7a595f6SVinicius Costa Gomes cp.handle = cpu_to_le16(conn->handle); 3346c9839a11SVinicius Costa Gomes 3347c9839a11SVinicius Costa Gomes if (ltk->authenticated) 3348c9839a11SVinicius Costa Gomes conn->sec_level = BT_SECURITY_HIGH; 3349a7a595f6SVinicius Costa Gomes 3350a7a595f6SVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); 3351a7a595f6SVinicius Costa Gomes 3352c9839a11SVinicius Costa Gomes if (ltk->type & HCI_SMP_STK) { 3353c9839a11SVinicius Costa Gomes list_del(<k->list); 3354c9839a11SVinicius Costa Gomes kfree(ltk); 3355c9839a11SVinicius Costa Gomes } 3356c9839a11SVinicius Costa Gomes 3357a7a595f6SVinicius Costa Gomes hci_dev_unlock(hdev); 3358bea710feSVinicius Costa Gomes 3359bea710feSVinicius Costa Gomes return; 3360bea710feSVinicius Costa Gomes 3361bea710feSVinicius Costa Gomes not_found: 3362bea710feSVinicius Costa Gomes neg.handle = ev->handle; 3363bea710feSVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg); 3364bea710feSVinicius Costa Gomes hci_dev_unlock(hdev); 3365a7a595f6SVinicius Costa Gomes } 3366a7a595f6SVinicius Costa Gomes 3367fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 3368fcd89c09SVille Tervo { 3369fcd89c09SVille Tervo struct hci_ev_le_meta *le_ev = (void *) skb->data; 3370fcd89c09SVille Tervo 3371fcd89c09SVille Tervo skb_pull(skb, sizeof(*le_ev)); 3372fcd89c09SVille Tervo 3373fcd89c09SVille Tervo switch (le_ev->subevent) { 3374fcd89c09SVille Tervo case HCI_EV_LE_CONN_COMPLETE: 3375fcd89c09SVille Tervo hci_le_conn_complete_evt(hdev, skb); 3376fcd89c09SVille Tervo break; 3377fcd89c09SVille Tervo 33789aa04c91SAndre Guedes case HCI_EV_LE_ADVERTISING_REPORT: 33799aa04c91SAndre Guedes hci_le_adv_report_evt(hdev, skb); 33809aa04c91SAndre Guedes break; 33819aa04c91SAndre Guedes 3382a7a595f6SVinicius Costa Gomes case HCI_EV_LE_LTK_REQ: 3383a7a595f6SVinicius Costa Gomes hci_le_ltk_request_evt(hdev, skb); 3384a7a595f6SVinicius Costa Gomes break; 3385a7a595f6SVinicius Costa Gomes 3386fcd89c09SVille Tervo default: 3387fcd89c09SVille Tervo break; 3388fcd89c09SVille Tervo } 3389fcd89c09SVille Tervo } 3390fcd89c09SVille Tervo 33911da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 33921da177e4SLinus Torvalds { 3393a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 3394a9de9248SMarcel Holtmann __u8 event = hdr->evt; 33951da177e4SLinus Torvalds 33961da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 33971da177e4SLinus Torvalds 3398a9de9248SMarcel Holtmann switch (event) { 33991da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 34001da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 34011da177e4SLinus Torvalds break; 34021da177e4SLinus Torvalds 34031da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 34041da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 34051da177e4SLinus Torvalds break; 34061da177e4SLinus Torvalds 3407a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 3408a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 340921d9e30eSMarcel Holtmann break; 341021d9e30eSMarcel Holtmann 34111da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 34121da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 34131da177e4SLinus Torvalds break; 34141da177e4SLinus Torvalds 34151da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 34161da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 34171da177e4SLinus Torvalds break; 34181da177e4SLinus Torvalds 34191da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 34201da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 34211da177e4SLinus Torvalds break; 34221da177e4SLinus Torvalds 3423a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 3424a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 3425a9de9248SMarcel Holtmann break; 3426a9de9248SMarcel Holtmann 34271da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 34281da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 34291da177e4SLinus Torvalds break; 34301da177e4SLinus Torvalds 3431a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 3432a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 3433a9de9248SMarcel Holtmann break; 3434a9de9248SMarcel Holtmann 3435a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 3436a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 3437a9de9248SMarcel Holtmann break; 3438a9de9248SMarcel Holtmann 3439a9de9248SMarcel Holtmann case HCI_EV_REMOTE_VERSION: 3440a9de9248SMarcel Holtmann hci_remote_version_evt(hdev, skb); 3441a9de9248SMarcel Holtmann break; 3442a9de9248SMarcel Holtmann 3443a9de9248SMarcel Holtmann case HCI_EV_QOS_SETUP_COMPLETE: 3444a9de9248SMarcel Holtmann hci_qos_setup_complete_evt(hdev, skb); 3445a9de9248SMarcel Holtmann break; 3446a9de9248SMarcel Holtmann 3447a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 3448a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 3449a9de9248SMarcel Holtmann break; 3450a9de9248SMarcel Holtmann 3451a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 3452a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 3453a9de9248SMarcel Holtmann break; 3454a9de9248SMarcel Holtmann 3455a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 3456a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 3457a9de9248SMarcel Holtmann break; 3458a9de9248SMarcel Holtmann 3459a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 3460a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 3461a9de9248SMarcel Holtmann break; 3462a9de9248SMarcel Holtmann 3463a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 3464a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 34651da177e4SLinus Torvalds break; 34661da177e4SLinus Torvalds 34671da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 34681da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 34691da177e4SLinus Torvalds break; 34701da177e4SLinus Torvalds 34711da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 34721da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 34731da177e4SLinus Torvalds break; 34741da177e4SLinus Torvalds 34751da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 34761da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 34771da177e4SLinus Torvalds break; 34781da177e4SLinus Torvalds 34791da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 34801da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 34811da177e4SLinus Torvalds break; 34821da177e4SLinus Torvalds 3483a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 3484a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 3485a8746417SMarcel Holtmann break; 3486a8746417SMarcel Holtmann 348785a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 348885a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 348985a1e930SMarcel Holtmann break; 349085a1e930SMarcel Holtmann 3491a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 3492a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 3493a9de9248SMarcel Holtmann break; 3494a9de9248SMarcel Holtmann 3495a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 3496a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 3497a9de9248SMarcel Holtmann break; 3498a9de9248SMarcel Holtmann 3499a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 3500a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 3501a9de9248SMarcel Holtmann break; 3502a9de9248SMarcel Holtmann 3503a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_CHANGED: 3504a9de9248SMarcel Holtmann hci_sync_conn_changed_evt(hdev, skb); 3505a9de9248SMarcel Holtmann break; 3506a9de9248SMarcel Holtmann 350704837f64SMarcel Holtmann case HCI_EV_SNIFF_SUBRATE: 350804837f64SMarcel Holtmann hci_sniff_subrate_evt(hdev, skb); 350904837f64SMarcel Holtmann break; 351004837f64SMarcel Holtmann 3511a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 3512a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 35131da177e4SLinus Torvalds break; 35141da177e4SLinus Torvalds 35150493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 35160493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 35170493684eSMarcel Holtmann break; 35180493684eSMarcel Holtmann 351903b555e1SJohan Hedberg case HCI_EV_IO_CAPA_REPLY: 352003b555e1SJohan Hedberg hci_io_capa_reply_evt(hdev, skb); 352103b555e1SJohan Hedberg break; 352203b555e1SJohan Hedberg 3523a5c29683SJohan Hedberg case HCI_EV_USER_CONFIRM_REQUEST: 3524a5c29683SJohan Hedberg hci_user_confirm_request_evt(hdev, skb); 3525a5c29683SJohan Hedberg break; 3526a5c29683SJohan Hedberg 35271143d458SBrian Gix case HCI_EV_USER_PASSKEY_REQUEST: 35281143d458SBrian Gix hci_user_passkey_request_evt(hdev, skb); 35291143d458SBrian Gix break; 35301143d458SBrian Gix 35310493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 35320493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 35330493684eSMarcel Holtmann break; 35340493684eSMarcel Holtmann 353541a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 353641a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 353741a96212SMarcel Holtmann break; 353841a96212SMarcel Holtmann 3539fcd89c09SVille Tervo case HCI_EV_LE_META: 3540fcd89c09SVille Tervo hci_le_meta_evt(hdev, skb); 3541fcd89c09SVille Tervo break; 3542fcd89c09SVille Tervo 35432763eda6SSzymon Janc case HCI_EV_REMOTE_OOB_DATA_REQUEST: 35442763eda6SSzymon Janc hci_remote_oob_data_request_evt(hdev, skb); 35452763eda6SSzymon Janc break; 35462763eda6SSzymon Janc 354725e89e99SAndrei Emeltchenko case HCI_EV_NUM_COMP_BLOCKS: 354825e89e99SAndrei Emeltchenko hci_num_comp_blocks_evt(hdev, skb); 354925e89e99SAndrei Emeltchenko break; 355025e89e99SAndrei Emeltchenko 35511da177e4SLinus Torvalds default: 3552a9de9248SMarcel Holtmann BT_DBG("%s event 0x%x", hdev->name, event); 35531da177e4SLinus Torvalds break; 35541da177e4SLinus Torvalds } 35551da177e4SLinus Torvalds 35561da177e4SLinus Torvalds kfree_skb(skb); 35571da177e4SLinus Torvalds hdev->stat.evt_rx++; 35581da177e4SLinus Torvalds } 3559