11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds BlueZ - Bluetooth protocol stack for Linux 32d0a0346SRon Shaffer Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved. 41da177e4SLinus Torvalds 51da177e4SLinus Torvalds Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> 61da177e4SLinus Torvalds 71da177e4SLinus Torvalds This program is free software; you can redistribute it and/or modify 81da177e4SLinus Torvalds it under the terms of the GNU General Public License version 2 as 91da177e4SLinus Torvalds published by the Free Software Foundation; 101da177e4SLinus Torvalds 111da177e4SLinus Torvalds THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 121da177e4SLinus Torvalds OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 131da177e4SLinus Torvalds FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 141da177e4SLinus Torvalds IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 151da177e4SLinus Torvalds CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 161da177e4SLinus Torvalds WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 171da177e4SLinus Torvalds ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 181da177e4SLinus Torvalds OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 211da177e4SLinus Torvalds COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 221da177e4SLinus Torvalds SOFTWARE IS DISCLAIMED. 231da177e4SLinus Torvalds */ 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds /* Bluetooth HCI event handling. */ 261da177e4SLinus Torvalds 271da177e4SLinus Torvalds #include <linux/module.h> 281da177e4SLinus Torvalds 291da177e4SLinus Torvalds #include <linux/types.h> 301da177e4SLinus Torvalds #include <linux/errno.h> 311da177e4SLinus Torvalds #include <linux/kernel.h> 321da177e4SLinus Torvalds #include <linux/slab.h> 331da177e4SLinus Torvalds #include <linux/poll.h> 341da177e4SLinus Torvalds #include <linux/fcntl.h> 351da177e4SLinus Torvalds #include <linux/init.h> 361da177e4SLinus Torvalds #include <linux/skbuff.h> 371da177e4SLinus Torvalds #include <linux/interrupt.h> 381da177e4SLinus Torvalds #include <linux/notifier.h> 391da177e4SLinus Torvalds #include <net/sock.h> 401da177e4SLinus Torvalds 411da177e4SLinus Torvalds #include <asm/system.h> 4270f23020SAndrei Emeltchenko #include <linux/uaccess.h> 431da177e4SLinus Torvalds #include <asm/unaligned.h> 441da177e4SLinus Torvalds 451da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h> 461da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h> 471da177e4SLinus Torvalds 48e6100a25SAndre Guedes static int enable_le; 49e6100a25SAndre Guedes 501da177e4SLinus Torvalds /* Handle HCI Event packets */ 511da177e4SLinus Torvalds 52a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb) 531da177e4SLinus Torvalds { 54a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 551da177e4SLinus Torvalds 56a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 571da177e4SLinus Torvalds 58a9de9248SMarcel Holtmann if (status) 59a9de9248SMarcel Holtmann return; 601da177e4SLinus Torvalds 612d20a26aSOliver Neukum if (test_and_clear_bit(HCI_INQUIRY, &hdev->flags) && 622d20a26aSOliver Neukum test_bit(HCI_MGMT, &hdev->flags)) 63314b2381SJohan Hedberg mgmt_discovering(hdev->id, 0); 64a9de9248SMarcel Holtmann 6523bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status); 66a9de9248SMarcel Holtmann 67a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 681da177e4SLinus Torvalds } 696bd57416SMarcel Holtmann 70a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 711da177e4SLinus Torvalds { 72a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 73a9de9248SMarcel Holtmann 74a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 75a9de9248SMarcel Holtmann 76a9de9248SMarcel Holtmann if (status) 77a9de9248SMarcel Holtmann return; 78a9de9248SMarcel Holtmann 792d20a26aSOliver Neukum if (test_and_clear_bit(HCI_INQUIRY, &hdev->flags) && 802d20a26aSOliver Neukum test_bit(HCI_MGMT, &hdev->flags)) 81314b2381SJohan Hedberg mgmt_discovering(hdev->id, 0); 82a9de9248SMarcel Holtmann 83a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 84a9de9248SMarcel Holtmann } 85a9de9248SMarcel Holtmann 86a9de9248SMarcel Holtmann static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb) 87a9de9248SMarcel Holtmann { 88a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 89a9de9248SMarcel Holtmann } 90a9de9248SMarcel Holtmann 91a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb) 92a9de9248SMarcel Holtmann { 93a9de9248SMarcel Holtmann struct hci_rp_role_discovery *rp = (void *) skb->data; 941da177e4SLinus Torvalds struct hci_conn *conn; 951da177e4SLinus Torvalds 96a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 971da177e4SLinus Torvalds 98a9de9248SMarcel Holtmann if (rp->status) 99a9de9248SMarcel Holtmann return; 1001da177e4SLinus Torvalds 1011da177e4SLinus Torvalds hci_dev_lock(hdev); 1021da177e4SLinus Torvalds 103a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 1041da177e4SLinus Torvalds if (conn) { 105a9de9248SMarcel Holtmann if (rp->role) 1061da177e4SLinus Torvalds conn->link_mode &= ~HCI_LM_MASTER; 1071da177e4SLinus Torvalds else 1081da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 1091da177e4SLinus Torvalds } 1101da177e4SLinus Torvalds 1111da177e4SLinus Torvalds hci_dev_unlock(hdev); 112a9de9248SMarcel Holtmann } 1131da177e4SLinus Torvalds 114e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 115e4e8e37cSMarcel Holtmann { 116e4e8e37cSMarcel Holtmann struct hci_rp_read_link_policy *rp = (void *) skb->data; 117e4e8e37cSMarcel Holtmann struct hci_conn *conn; 118e4e8e37cSMarcel Holtmann 119e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 120e4e8e37cSMarcel Holtmann 121e4e8e37cSMarcel Holtmann if (rp->status) 122e4e8e37cSMarcel Holtmann return; 123e4e8e37cSMarcel Holtmann 124e4e8e37cSMarcel Holtmann hci_dev_lock(hdev); 125e4e8e37cSMarcel Holtmann 126e4e8e37cSMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 127e4e8e37cSMarcel Holtmann if (conn) 128e4e8e37cSMarcel Holtmann conn->link_policy = __le16_to_cpu(rp->policy); 129e4e8e37cSMarcel Holtmann 130e4e8e37cSMarcel Holtmann hci_dev_unlock(hdev); 131e4e8e37cSMarcel Holtmann } 132e4e8e37cSMarcel Holtmann 133a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 134a9de9248SMarcel Holtmann { 135a9de9248SMarcel Holtmann struct hci_rp_write_link_policy *rp = (void *) skb->data; 136a9de9248SMarcel Holtmann struct hci_conn *conn; 137a9de9248SMarcel Holtmann void *sent; 138a9de9248SMarcel Holtmann 139a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 140a9de9248SMarcel Holtmann 141a9de9248SMarcel Holtmann if (rp->status) 142a9de9248SMarcel Holtmann return; 143a9de9248SMarcel Holtmann 144a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY); 14504837f64SMarcel Holtmann if (!sent) 146a9de9248SMarcel Holtmann return; 14704837f64SMarcel Holtmann 14804837f64SMarcel Holtmann hci_dev_lock(hdev); 14904837f64SMarcel Holtmann 150a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 151e4e8e37cSMarcel Holtmann if (conn) 15283985319SHarvey Harrison conn->link_policy = get_unaligned_le16(sent + 2); 15304837f64SMarcel Holtmann 15404837f64SMarcel Holtmann hci_dev_unlock(hdev); 1551da177e4SLinus Torvalds } 1561da177e4SLinus Torvalds 157e4e8e37cSMarcel Holtmann static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 158e4e8e37cSMarcel Holtmann { 159e4e8e37cSMarcel Holtmann struct hci_rp_read_def_link_policy *rp = (void *) skb->data; 160e4e8e37cSMarcel Holtmann 161e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 162e4e8e37cSMarcel Holtmann 163e4e8e37cSMarcel Holtmann if (rp->status) 164e4e8e37cSMarcel Holtmann return; 165e4e8e37cSMarcel Holtmann 166e4e8e37cSMarcel Holtmann hdev->link_policy = __le16_to_cpu(rp->policy); 167e4e8e37cSMarcel Holtmann } 168e4e8e37cSMarcel Holtmann 169e4e8e37cSMarcel Holtmann static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 170e4e8e37cSMarcel Holtmann { 171e4e8e37cSMarcel Holtmann __u8 status = *((__u8 *) skb->data); 172e4e8e37cSMarcel Holtmann void *sent; 173e4e8e37cSMarcel Holtmann 174e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 175e4e8e37cSMarcel Holtmann 176e4e8e37cSMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY); 177e4e8e37cSMarcel Holtmann if (!sent) 178e4e8e37cSMarcel Holtmann return; 179e4e8e37cSMarcel Holtmann 180e4e8e37cSMarcel Holtmann if (!status) 181e4e8e37cSMarcel Holtmann hdev->link_policy = get_unaligned_le16(sent); 182e4e8e37cSMarcel Holtmann 18323bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status); 184e4e8e37cSMarcel Holtmann } 185e4e8e37cSMarcel Holtmann 186a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) 1871da177e4SLinus Torvalds { 188a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 189a9de9248SMarcel Holtmann 190a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 191a9de9248SMarcel Holtmann 19210572132SGustavo F. Padovan clear_bit(HCI_RESET, &hdev->flags); 19310572132SGustavo F. Padovan 19423bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_RESET, status); 195a9de9248SMarcel Holtmann } 196a9de9248SMarcel Holtmann 197a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) 198a9de9248SMarcel Holtmann { 199a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 2001da177e4SLinus Torvalds void *sent; 2011da177e4SLinus Torvalds 202a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 2031da177e4SLinus Torvalds 204a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); 2051da177e4SLinus Torvalds if (!sent) 206a9de9248SMarcel Holtmann return; 2071da177e4SLinus Torvalds 208b312b161SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 209b312b161SJohan Hedberg mgmt_set_local_name_complete(hdev->id, sent, status); 210b312b161SJohan Hedberg 211b312b161SJohan Hedberg if (status) 212b312b161SJohan Hedberg return; 213b312b161SJohan Hedberg 2141f6c6378SJohan Hedberg memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); 215a9de9248SMarcel Holtmann } 216a9de9248SMarcel Holtmann 217a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) 218a9de9248SMarcel Holtmann { 219a9de9248SMarcel Holtmann struct hci_rp_read_local_name *rp = (void *) skb->data; 220a9de9248SMarcel Holtmann 221a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 222a9de9248SMarcel Holtmann 223a9de9248SMarcel Holtmann if (rp->status) 224a9de9248SMarcel Holtmann return; 225a9de9248SMarcel Holtmann 2261f6c6378SJohan Hedberg memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); 227a9de9248SMarcel Holtmann } 228a9de9248SMarcel Holtmann 229a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) 230a9de9248SMarcel Holtmann { 231a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 232a9de9248SMarcel Holtmann void *sent; 233a9de9248SMarcel Holtmann 234a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 235a9de9248SMarcel Holtmann 236a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); 237a9de9248SMarcel Holtmann if (!sent) 238a9de9248SMarcel Holtmann return; 2391da177e4SLinus Torvalds 2401da177e4SLinus Torvalds if (!status) { 241a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 242a9de9248SMarcel Holtmann 2431da177e4SLinus Torvalds if (param == AUTH_ENABLED) 2441da177e4SLinus Torvalds set_bit(HCI_AUTH, &hdev->flags); 2451da177e4SLinus Torvalds else 2461da177e4SLinus Torvalds clear_bit(HCI_AUTH, &hdev->flags); 2471da177e4SLinus Torvalds } 248a9de9248SMarcel Holtmann 24923bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status); 250a9de9248SMarcel Holtmann } 2511da177e4SLinus Torvalds 252a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) 253a9de9248SMarcel Holtmann { 254a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 255a9de9248SMarcel Holtmann void *sent; 256a9de9248SMarcel Holtmann 257a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 258a9de9248SMarcel Holtmann 259a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); 2601da177e4SLinus Torvalds if (!sent) 261a9de9248SMarcel Holtmann return; 2621da177e4SLinus Torvalds 2631da177e4SLinus Torvalds if (!status) { 264a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 265a9de9248SMarcel Holtmann 2661da177e4SLinus Torvalds if (param) 2671da177e4SLinus Torvalds set_bit(HCI_ENCRYPT, &hdev->flags); 2681da177e4SLinus Torvalds else 2691da177e4SLinus Torvalds clear_bit(HCI_ENCRYPT, &hdev->flags); 2701da177e4SLinus Torvalds } 271a9de9248SMarcel Holtmann 27223bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status); 2731da177e4SLinus Torvalds } 2741da177e4SLinus Torvalds 275a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) 276a9de9248SMarcel Holtmann { 277a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 278a9de9248SMarcel Holtmann void *sent; 2791da177e4SLinus Torvalds 280a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 281a9de9248SMarcel Holtmann 282a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); 2831da177e4SLinus Torvalds if (!sent) 284a9de9248SMarcel Holtmann return; 2851da177e4SLinus Torvalds 2861da177e4SLinus Torvalds if (!status) { 287a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 2889fbcbb45SJohan Hedberg int old_pscan, old_iscan; 289a9de9248SMarcel Holtmann 2909fbcbb45SJohan Hedberg old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags); 2919fbcbb45SJohan Hedberg old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags); 292a9de9248SMarcel Holtmann 29373f22f62SJohan Hedberg if (param & SCAN_INQUIRY) { 2941da177e4SLinus Torvalds set_bit(HCI_ISCAN, &hdev->flags); 2959fbcbb45SJohan Hedberg if (!old_iscan) 29673f22f62SJohan Hedberg mgmt_discoverable(hdev->id, 1); 2979fbcbb45SJohan Hedberg } else if (old_iscan) 29873f22f62SJohan Hedberg mgmt_discoverable(hdev->id, 0); 2991da177e4SLinus Torvalds 3009fbcbb45SJohan Hedberg if (param & SCAN_PAGE) { 3011da177e4SLinus Torvalds set_bit(HCI_PSCAN, &hdev->flags); 3029fbcbb45SJohan Hedberg if (!old_pscan) 3039fbcbb45SJohan Hedberg mgmt_connectable(hdev->id, 1); 3049fbcbb45SJohan Hedberg } else if (old_pscan) 3059fbcbb45SJohan Hedberg mgmt_connectable(hdev->id, 0); 3061da177e4SLinus Torvalds } 307a9de9248SMarcel Holtmann 30823bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status); 3091da177e4SLinus Torvalds } 3101da177e4SLinus Torvalds 311a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 312a9de9248SMarcel Holtmann { 313a9de9248SMarcel Holtmann struct hci_rp_read_class_of_dev *rp = (void *) skb->data; 314a9de9248SMarcel Holtmann 315a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 316a9de9248SMarcel Holtmann 317a9de9248SMarcel Holtmann if (rp->status) 318a9de9248SMarcel Holtmann return; 319a9de9248SMarcel Holtmann 320a9de9248SMarcel Holtmann memcpy(hdev->dev_class, rp->dev_class, 3); 321a9de9248SMarcel Holtmann 322a9de9248SMarcel Holtmann BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, 323a9de9248SMarcel Holtmann hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); 324a9de9248SMarcel Holtmann } 325a9de9248SMarcel Holtmann 326a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 327a9de9248SMarcel Holtmann { 328a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 329a9de9248SMarcel Holtmann void *sent; 330a9de9248SMarcel Holtmann 331a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 332a9de9248SMarcel Holtmann 333f383f275SMarcel Holtmann if (status) 334f383f275SMarcel Holtmann return; 335f383f275SMarcel Holtmann 336a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); 337a9de9248SMarcel Holtmann if (!sent) 338a9de9248SMarcel Holtmann return; 339a9de9248SMarcel Holtmann 340a9de9248SMarcel Holtmann memcpy(hdev->dev_class, sent, 3); 341a9de9248SMarcel Holtmann } 342a9de9248SMarcel Holtmann 343a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 344a9de9248SMarcel Holtmann { 345a9de9248SMarcel Holtmann struct hci_rp_read_voice_setting *rp = (void *) skb->data; 346a9de9248SMarcel Holtmann __u16 setting; 347a9de9248SMarcel Holtmann 348a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 349a9de9248SMarcel Holtmann 350a9de9248SMarcel Holtmann if (rp->status) 351a9de9248SMarcel Holtmann return; 352a9de9248SMarcel Holtmann 353a9de9248SMarcel Holtmann setting = __le16_to_cpu(rp->voice_setting); 354a9de9248SMarcel Holtmann 355a9de9248SMarcel Holtmann if (hdev->voice_setting == setting) 356a9de9248SMarcel Holtmann return; 357a9de9248SMarcel Holtmann 358a9de9248SMarcel Holtmann hdev->voice_setting = setting; 359a9de9248SMarcel Holtmann 360a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 361a9de9248SMarcel Holtmann 362a9de9248SMarcel Holtmann if (hdev->notify) { 363a9de9248SMarcel Holtmann tasklet_disable(&hdev->tx_task); 364a9de9248SMarcel Holtmann hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 365a9de9248SMarcel Holtmann tasklet_enable(&hdev->tx_task); 366a9de9248SMarcel Holtmann } 367a9de9248SMarcel Holtmann } 368a9de9248SMarcel Holtmann 369a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 370a9de9248SMarcel Holtmann { 371a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 372f383f275SMarcel Holtmann __u16 setting; 373a9de9248SMarcel Holtmann void *sent; 374a9de9248SMarcel Holtmann 375a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 376a9de9248SMarcel Holtmann 377f383f275SMarcel Holtmann if (status) 378f383f275SMarcel Holtmann return; 379f383f275SMarcel Holtmann 380a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); 381a9de9248SMarcel Holtmann if (!sent) 382a9de9248SMarcel Holtmann return; 383a9de9248SMarcel Holtmann 384f383f275SMarcel Holtmann setting = get_unaligned_le16(sent); 3851da177e4SLinus Torvalds 386f383f275SMarcel Holtmann if (hdev->voice_setting == setting) 387f383f275SMarcel Holtmann return; 388f383f275SMarcel Holtmann 3891da177e4SLinus Torvalds hdev->voice_setting = setting; 3901da177e4SLinus Torvalds 391a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 3921da177e4SLinus Torvalds 3931da177e4SLinus Torvalds if (hdev->notify) { 3941da177e4SLinus Torvalds tasklet_disable(&hdev->tx_task); 3951da177e4SLinus Torvalds hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 3961da177e4SLinus Torvalds tasklet_enable(&hdev->tx_task); 3971da177e4SLinus Torvalds } 3981da177e4SLinus Torvalds } 3991da177e4SLinus Torvalds 400a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 4011da177e4SLinus Torvalds { 402a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 4031da177e4SLinus Torvalds 404a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 4051da177e4SLinus Torvalds 40623bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status); 4071143e5a6SMarcel Holtmann } 4081143e5a6SMarcel Holtmann 409333140b5SMarcel Holtmann static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 410333140b5SMarcel Holtmann { 411333140b5SMarcel Holtmann struct hci_rp_read_ssp_mode *rp = (void *) skb->data; 412333140b5SMarcel Holtmann 413333140b5SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 414333140b5SMarcel Holtmann 415333140b5SMarcel Holtmann if (rp->status) 416333140b5SMarcel Holtmann return; 417333140b5SMarcel Holtmann 418333140b5SMarcel Holtmann hdev->ssp_mode = rp->mode; 419333140b5SMarcel Holtmann } 420333140b5SMarcel Holtmann 421333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 422333140b5SMarcel Holtmann { 423333140b5SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 424333140b5SMarcel Holtmann void *sent; 425333140b5SMarcel Holtmann 426333140b5SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 427333140b5SMarcel Holtmann 428333140b5SMarcel Holtmann if (status) 429333140b5SMarcel Holtmann return; 430333140b5SMarcel Holtmann 431333140b5SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); 432333140b5SMarcel Holtmann if (!sent) 433333140b5SMarcel Holtmann return; 434333140b5SMarcel Holtmann 435333140b5SMarcel Holtmann hdev->ssp_mode = *((__u8 *) sent); 436333140b5SMarcel Holtmann } 437333140b5SMarcel Holtmann 438d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev) 439d5859e22SJohan Hedberg { 440d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 441d5859e22SJohan Hedberg return 2; 442d5859e22SJohan Hedberg 443d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 444d5859e22SJohan Hedberg return 1; 445d5859e22SJohan Hedberg 446d5859e22SJohan Hedberg if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 && 447d5859e22SJohan Hedberg hdev->lmp_subver == 0x0757) 448d5859e22SJohan Hedberg return 1; 449d5859e22SJohan Hedberg 450d5859e22SJohan Hedberg if (hdev->manufacturer == 15) { 451d5859e22SJohan Hedberg if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963) 452d5859e22SJohan Hedberg return 1; 453d5859e22SJohan Hedberg if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963) 454d5859e22SJohan Hedberg return 1; 455d5859e22SJohan Hedberg if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965) 456d5859e22SJohan Hedberg return 1; 457d5859e22SJohan Hedberg } 458d5859e22SJohan Hedberg 459d5859e22SJohan Hedberg if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 && 460d5859e22SJohan Hedberg hdev->lmp_subver == 0x1805) 461d5859e22SJohan Hedberg return 1; 462d5859e22SJohan Hedberg 463d5859e22SJohan Hedberg return 0; 464d5859e22SJohan Hedberg } 465d5859e22SJohan Hedberg 466d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev) 467d5859e22SJohan Hedberg { 468d5859e22SJohan Hedberg u8 mode; 469d5859e22SJohan Hedberg 470d5859e22SJohan Hedberg mode = hci_get_inquiry_mode(hdev); 471d5859e22SJohan Hedberg 472d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode); 473d5859e22SJohan Hedberg } 474d5859e22SJohan Hedberg 475d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev) 476d5859e22SJohan Hedberg { 477d5859e22SJohan Hedberg /* The second byte is 0xff instead of 0x9f (two reserved bits 478d5859e22SJohan Hedberg * disabled) since a Broadcom 1.2 dongle doesn't respond to the 479d5859e22SJohan Hedberg * command otherwise */ 480d5859e22SJohan Hedberg u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 }; 481d5859e22SJohan Hedberg 4826de6c18dSVille Tervo /* CSR 1.1 dongles does not accept any bitfield so don't try to set 4836de6c18dSVille Tervo * any event mask for pre 1.2 devices */ 4846de6c18dSVille Tervo if (hdev->lmp_ver <= 1) 4856de6c18dSVille Tervo return; 4866de6c18dSVille Tervo 487d5859e22SJohan Hedberg events[4] |= 0x01; /* Flow Specification Complete */ 488d5859e22SJohan Hedberg events[4] |= 0x02; /* Inquiry Result with RSSI */ 489d5859e22SJohan Hedberg events[4] |= 0x04; /* Read Remote Extended Features Complete */ 490d5859e22SJohan Hedberg events[5] |= 0x08; /* Synchronous Connection Complete */ 491d5859e22SJohan Hedberg events[5] |= 0x10; /* Synchronous Connection Changed */ 492d5859e22SJohan Hedberg 493d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 494d5859e22SJohan Hedberg events[4] |= 0x04; /* Inquiry Result with RSSI */ 495d5859e22SJohan Hedberg 496d5859e22SJohan Hedberg if (hdev->features[5] & LMP_SNIFF_SUBR) 497d5859e22SJohan Hedberg events[5] |= 0x20; /* Sniff Subrating */ 498d5859e22SJohan Hedberg 499d5859e22SJohan Hedberg if (hdev->features[5] & LMP_PAUSE_ENC) 500d5859e22SJohan Hedberg events[5] |= 0x80; /* Encryption Key Refresh Complete */ 501d5859e22SJohan Hedberg 502d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 503d5859e22SJohan Hedberg events[5] |= 0x40; /* Extended Inquiry Result */ 504d5859e22SJohan Hedberg 505d5859e22SJohan Hedberg if (hdev->features[6] & LMP_NO_FLUSH) 506d5859e22SJohan Hedberg events[7] |= 0x01; /* Enhanced Flush Complete */ 507d5859e22SJohan Hedberg 508d5859e22SJohan Hedberg if (hdev->features[7] & LMP_LSTO) 509d5859e22SJohan Hedberg events[6] |= 0x80; /* Link Supervision Timeout Changed */ 510d5859e22SJohan Hedberg 511d5859e22SJohan Hedberg if (hdev->features[6] & LMP_SIMPLE_PAIR) { 512d5859e22SJohan Hedberg events[6] |= 0x01; /* IO Capability Request */ 513d5859e22SJohan Hedberg events[6] |= 0x02; /* IO Capability Response */ 514d5859e22SJohan Hedberg events[6] |= 0x04; /* User Confirmation Request */ 515d5859e22SJohan Hedberg events[6] |= 0x08; /* User Passkey Request */ 516d5859e22SJohan Hedberg events[6] |= 0x10; /* Remote OOB Data Request */ 517d5859e22SJohan Hedberg events[6] |= 0x20; /* Simple Pairing Complete */ 518d5859e22SJohan Hedberg events[7] |= 0x04; /* User Passkey Notification */ 519d5859e22SJohan Hedberg events[7] |= 0x08; /* Keypress Notification */ 520d5859e22SJohan Hedberg events[7] |= 0x10; /* Remote Host Supported 521d5859e22SJohan Hedberg * Features Notification */ 522d5859e22SJohan Hedberg } 523d5859e22SJohan Hedberg 524d5859e22SJohan Hedberg if (hdev->features[4] & LMP_LE) 525d5859e22SJohan Hedberg events[7] |= 0x20; /* LE Meta-Event */ 526d5859e22SJohan Hedberg 527d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); 528d5859e22SJohan Hedberg } 529d5859e22SJohan Hedberg 530e6100a25SAndre Guedes static void hci_set_le_support(struct hci_dev *hdev) 531e6100a25SAndre Guedes { 532e6100a25SAndre Guedes struct hci_cp_write_le_host_supported cp; 533e6100a25SAndre Guedes 534e6100a25SAndre Guedes memset(&cp, 0, sizeof(cp)); 535e6100a25SAndre Guedes 536e6100a25SAndre Guedes if (enable_le) { 537e6100a25SAndre Guedes cp.le = 1; 538e6100a25SAndre Guedes cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR); 539e6100a25SAndre Guedes } 540e6100a25SAndre Guedes 541e6100a25SAndre Guedes hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), &cp); 542e6100a25SAndre Guedes } 543e6100a25SAndre Guedes 544d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev) 545d5859e22SJohan Hedberg { 546d5859e22SJohan Hedberg hci_setup_event_mask(hdev); 547d5859e22SJohan Hedberg 548d5859e22SJohan Hedberg if (hdev->lmp_ver > 1) 549d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); 550d5859e22SJohan Hedberg 551d5859e22SJohan Hedberg if (hdev->features[6] & LMP_SIMPLE_PAIR) { 552d5859e22SJohan Hedberg u8 mode = 0x01; 553d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode); 554d5859e22SJohan Hedberg } 555d5859e22SJohan Hedberg 556d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 557d5859e22SJohan Hedberg hci_setup_inquiry_mode(hdev); 558d5859e22SJohan Hedberg 559d5859e22SJohan Hedberg if (hdev->features[7] & LMP_INQ_TX_PWR) 560d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL); 561971e3a4bSAndre Guedes 562971e3a4bSAndre Guedes if (hdev->features[7] & LMP_EXTFEATURES) { 563971e3a4bSAndre Guedes struct hci_cp_read_local_ext_features cp; 564971e3a4bSAndre Guedes 565971e3a4bSAndre Guedes cp.page = 0x01; 566971e3a4bSAndre Guedes hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, 567971e3a4bSAndre Guedes sizeof(cp), &cp); 568971e3a4bSAndre Guedes } 569e6100a25SAndre Guedes 570e6100a25SAndre Guedes if (hdev->features[4] & LMP_LE) 571e6100a25SAndre Guedes hci_set_le_support(hdev); 572d5859e22SJohan Hedberg } 573d5859e22SJohan Hedberg 574a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) 575a9de9248SMarcel Holtmann { 576a9de9248SMarcel Holtmann struct hci_rp_read_local_version *rp = (void *) skb->data; 5771143e5a6SMarcel Holtmann 578a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 5791143e5a6SMarcel Holtmann 580a9de9248SMarcel Holtmann if (rp->status) 581a9de9248SMarcel Holtmann return; 5821143e5a6SMarcel Holtmann 583a9de9248SMarcel Holtmann hdev->hci_ver = rp->hci_ver; 584e4e8e37cSMarcel Holtmann hdev->hci_rev = __le16_to_cpu(rp->hci_rev); 585d5859e22SJohan Hedberg hdev->lmp_ver = rp->lmp_ver; 586e4e8e37cSMarcel Holtmann hdev->manufacturer = __le16_to_cpu(rp->manufacturer); 587d5859e22SJohan Hedberg hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); 5881da177e4SLinus Torvalds 589a9de9248SMarcel Holtmann BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name, 590a9de9248SMarcel Holtmann hdev->manufacturer, 591a9de9248SMarcel Holtmann hdev->hci_ver, hdev->hci_rev); 592d5859e22SJohan Hedberg 593d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags)) 594d5859e22SJohan Hedberg hci_setup(hdev); 595d5859e22SJohan Hedberg } 596d5859e22SJohan Hedberg 597d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev) 598d5859e22SJohan Hedberg { 599d5859e22SJohan Hedberg u16 link_policy = 0; 600d5859e22SJohan Hedberg 601d5859e22SJohan Hedberg if (hdev->features[0] & LMP_RSWITCH) 602d5859e22SJohan Hedberg link_policy |= HCI_LP_RSWITCH; 603d5859e22SJohan Hedberg if (hdev->features[0] & LMP_HOLD) 604d5859e22SJohan Hedberg link_policy |= HCI_LP_HOLD; 605d5859e22SJohan Hedberg if (hdev->features[0] & LMP_SNIFF) 606d5859e22SJohan Hedberg link_policy |= HCI_LP_SNIFF; 607d5859e22SJohan Hedberg if (hdev->features[1] & LMP_PARK) 608d5859e22SJohan Hedberg link_policy |= HCI_LP_PARK; 609d5859e22SJohan Hedberg 610d5859e22SJohan Hedberg link_policy = cpu_to_le16(link_policy); 611d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, 612d5859e22SJohan Hedberg sizeof(link_policy), &link_policy); 6131da177e4SLinus Torvalds } 6141da177e4SLinus Torvalds 615a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb) 616a9de9248SMarcel Holtmann { 617a9de9248SMarcel Holtmann struct hci_rp_read_local_commands *rp = (void *) skb->data; 618a9de9248SMarcel Holtmann 619a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 620a9de9248SMarcel Holtmann 621a9de9248SMarcel Holtmann if (rp->status) 622d5859e22SJohan Hedberg goto done; 623a9de9248SMarcel Holtmann 624a9de9248SMarcel Holtmann memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); 625d5859e22SJohan Hedberg 626d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10)) 627d5859e22SJohan Hedberg hci_setup_link_policy(hdev); 628d5859e22SJohan Hedberg 629d5859e22SJohan Hedberg done: 630d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status); 631a9de9248SMarcel Holtmann } 632a9de9248SMarcel Holtmann 633a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb) 634a9de9248SMarcel Holtmann { 635a9de9248SMarcel Holtmann struct hci_rp_read_local_features *rp = (void *) skb->data; 636a9de9248SMarcel Holtmann 637a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 638a9de9248SMarcel Holtmann 639a9de9248SMarcel Holtmann if (rp->status) 640a9de9248SMarcel Holtmann return; 641a9de9248SMarcel Holtmann 642a9de9248SMarcel Holtmann memcpy(hdev->features, rp->features, 8); 6431da177e4SLinus Torvalds 6441da177e4SLinus Torvalds /* Adjust default settings according to features 6451da177e4SLinus Torvalds * supported by device. */ 646a9de9248SMarcel Holtmann 6471da177e4SLinus Torvalds if (hdev->features[0] & LMP_3SLOT) 6481da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM3 | HCI_DH3); 6491da177e4SLinus Torvalds 6501da177e4SLinus Torvalds if (hdev->features[0] & LMP_5SLOT) 6511da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM5 | HCI_DH5); 6521da177e4SLinus Torvalds 6535b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV2) { 6541da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV2); 6555b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV2); 6565b7f9909SMarcel Holtmann } 6571da177e4SLinus Torvalds 6585b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV3) { 6591da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV3); 6605b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV3); 6615b7f9909SMarcel Holtmann } 6625b7f9909SMarcel Holtmann 6635b7f9909SMarcel Holtmann if (hdev->features[3] & LMP_ESCO) 6645b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV3); 6655b7f9909SMarcel Holtmann 6665b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV4) 6675b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV4); 6685b7f9909SMarcel Holtmann 6695b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV5) 6705b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV5); 6711da177e4SLinus Torvalds 672efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_2M) 673efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV3); 674efc7688bSMarcel Holtmann 675efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_3M) 676efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_3EV3); 677efc7688bSMarcel Holtmann 678efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_3S_ESCO) 679efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); 680efc7688bSMarcel Holtmann 681a9de9248SMarcel Holtmann BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, 682a9de9248SMarcel Holtmann hdev->features[0], hdev->features[1], 683a9de9248SMarcel Holtmann hdev->features[2], hdev->features[3], 684a9de9248SMarcel Holtmann hdev->features[4], hdev->features[5], 685a9de9248SMarcel Holtmann hdev->features[6], hdev->features[7]); 6861da177e4SLinus Torvalds } 6871da177e4SLinus Torvalds 688971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev, 689971e3a4bSAndre Guedes struct sk_buff *skb) 690971e3a4bSAndre Guedes { 691971e3a4bSAndre Guedes struct hci_rp_read_local_ext_features *rp = (void *) skb->data; 692971e3a4bSAndre Guedes 693971e3a4bSAndre Guedes BT_DBG("%s status 0x%x", hdev->name, rp->status); 694971e3a4bSAndre Guedes 695971e3a4bSAndre Guedes if (rp->status) 696971e3a4bSAndre Guedes return; 697971e3a4bSAndre Guedes 698971e3a4bSAndre Guedes memcpy(hdev->extfeatures, rp->features, 8); 699971e3a4bSAndre Guedes 700971e3a4bSAndre Guedes hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status); 701971e3a4bSAndre Guedes } 702971e3a4bSAndre Guedes 703a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 704a9de9248SMarcel Holtmann { 705a9de9248SMarcel Holtmann struct hci_rp_read_buffer_size *rp = (void *) skb->data; 706a9de9248SMarcel Holtmann 707a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 708a9de9248SMarcel Holtmann 709a9de9248SMarcel Holtmann if (rp->status) 710a9de9248SMarcel Holtmann return; 711a9de9248SMarcel Holtmann 712a9de9248SMarcel Holtmann hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); 713a9de9248SMarcel Holtmann hdev->sco_mtu = rp->sco_mtu; 714a9de9248SMarcel Holtmann hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); 715a9de9248SMarcel Holtmann hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); 716da1f5198SMarcel Holtmann 717da1f5198SMarcel Holtmann if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { 718da1f5198SMarcel Holtmann hdev->sco_mtu = 64; 719da1f5198SMarcel Holtmann hdev->sco_pkts = 8; 720da1f5198SMarcel Holtmann } 721da1f5198SMarcel Holtmann 722da1f5198SMarcel Holtmann hdev->acl_cnt = hdev->acl_pkts; 723da1f5198SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 7241da177e4SLinus Torvalds 725a9de9248SMarcel Holtmann BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, 726a9de9248SMarcel Holtmann hdev->acl_mtu, hdev->acl_pkts, 727a9de9248SMarcel Holtmann hdev->sco_mtu, hdev->sco_pkts); 7281da177e4SLinus Torvalds } 7291da177e4SLinus Torvalds 730a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) 731a9de9248SMarcel Holtmann { 732a9de9248SMarcel Holtmann struct hci_rp_read_bd_addr *rp = (void *) skb->data; 7331da177e4SLinus Torvalds 734a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 735a9de9248SMarcel Holtmann 736a9de9248SMarcel Holtmann if (!rp->status) 737a9de9248SMarcel Holtmann bacpy(&hdev->bdaddr, &rp->bdaddr); 738a9de9248SMarcel Holtmann 73923bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status); 74023bb5763SJohan Hedberg } 74123bb5763SJohan Hedberg 74223bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb) 74323bb5763SJohan Hedberg { 74423bb5763SJohan Hedberg __u8 status = *((__u8 *) skb->data); 74523bb5763SJohan Hedberg 74623bb5763SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 74723bb5763SJohan Hedberg 74823bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status); 7491da177e4SLinus Torvalds } 7501da177e4SLinus Torvalds 751928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev, 752928abaa7SAndrei Emeltchenko struct sk_buff *skb) 753928abaa7SAndrei Emeltchenko { 754928abaa7SAndrei Emeltchenko struct hci_rp_read_local_amp_info *rp = (void *) skb->data; 755928abaa7SAndrei Emeltchenko 756928abaa7SAndrei Emeltchenko BT_DBG("%s status 0x%x", hdev->name, rp->status); 757928abaa7SAndrei Emeltchenko 758928abaa7SAndrei Emeltchenko if (rp->status) 759928abaa7SAndrei Emeltchenko return; 760928abaa7SAndrei Emeltchenko 761928abaa7SAndrei Emeltchenko hdev->amp_status = rp->amp_status; 762928abaa7SAndrei Emeltchenko hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); 763928abaa7SAndrei Emeltchenko hdev->amp_max_bw = __le32_to_cpu(rp->max_bw); 764928abaa7SAndrei Emeltchenko hdev->amp_min_latency = __le32_to_cpu(rp->min_latency); 765928abaa7SAndrei Emeltchenko hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu); 766928abaa7SAndrei Emeltchenko hdev->amp_type = rp->amp_type; 767928abaa7SAndrei Emeltchenko hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap); 768928abaa7SAndrei Emeltchenko hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size); 769928abaa7SAndrei Emeltchenko hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); 770928abaa7SAndrei Emeltchenko hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); 771928abaa7SAndrei Emeltchenko 772928abaa7SAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status); 773928abaa7SAndrei Emeltchenko } 774928abaa7SAndrei Emeltchenko 775b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, 776b0916ea0SJohan Hedberg struct sk_buff *skb) 777b0916ea0SJohan Hedberg { 778b0916ea0SJohan Hedberg __u8 status = *((__u8 *) skb->data); 779b0916ea0SJohan Hedberg 780b0916ea0SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 781b0916ea0SJohan Hedberg 782b0916ea0SJohan Hedberg hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status); 783b0916ea0SJohan Hedberg } 784b0916ea0SJohan Hedberg 785d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb) 786d5859e22SJohan Hedberg { 787d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 788d5859e22SJohan Hedberg 789d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 790d5859e22SJohan Hedberg 791d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status); 792d5859e22SJohan Hedberg } 793d5859e22SJohan Hedberg 794d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev, 795d5859e22SJohan Hedberg struct sk_buff *skb) 796d5859e22SJohan Hedberg { 797d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 798d5859e22SJohan Hedberg 799d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 800d5859e22SJohan Hedberg 801d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status); 802d5859e22SJohan Hedberg } 803d5859e22SJohan Hedberg 804d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, 805d5859e22SJohan Hedberg struct sk_buff *skb) 806d5859e22SJohan Hedberg { 807d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 808d5859e22SJohan Hedberg 809d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 810d5859e22SJohan Hedberg 811d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status); 812d5859e22SJohan Hedberg } 813d5859e22SJohan Hedberg 814d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb) 815d5859e22SJohan Hedberg { 816d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 817d5859e22SJohan Hedberg 818d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 819d5859e22SJohan Hedberg 820d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status); 821d5859e22SJohan Hedberg } 822d5859e22SJohan Hedberg 823980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) 824980e1a53SJohan Hedberg { 825980e1a53SJohan Hedberg struct hci_rp_pin_code_reply *rp = (void *) skb->data; 826980e1a53SJohan Hedberg struct hci_cp_pin_code_reply *cp; 827980e1a53SJohan Hedberg struct hci_conn *conn; 828980e1a53SJohan Hedberg 829980e1a53SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 830980e1a53SJohan Hedberg 831980e1a53SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 832980e1a53SJohan Hedberg mgmt_pin_code_reply_complete(hdev->id, &rp->bdaddr, rp->status); 833980e1a53SJohan Hedberg 834980e1a53SJohan Hedberg if (rp->status != 0) 835980e1a53SJohan Hedberg return; 836980e1a53SJohan Hedberg 837980e1a53SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); 838980e1a53SJohan Hedberg if (!cp) 839980e1a53SJohan Hedberg return; 840980e1a53SJohan Hedberg 841980e1a53SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 842980e1a53SJohan Hedberg if (conn) 843980e1a53SJohan Hedberg conn->pin_length = cp->pin_len; 844980e1a53SJohan Hedberg } 845980e1a53SJohan Hedberg 846980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 847980e1a53SJohan Hedberg { 848980e1a53SJohan Hedberg struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data; 849980e1a53SJohan Hedberg 850980e1a53SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 851980e1a53SJohan Hedberg 852980e1a53SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 853980e1a53SJohan Hedberg mgmt_pin_code_neg_reply_complete(hdev->id, &rp->bdaddr, 854980e1a53SJohan Hedberg rp->status); 855980e1a53SJohan Hedberg } 8566ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, 8576ed58ec5SVille Tervo struct sk_buff *skb) 8586ed58ec5SVille Tervo { 8596ed58ec5SVille Tervo struct hci_rp_le_read_buffer_size *rp = (void *) skb->data; 8606ed58ec5SVille Tervo 8616ed58ec5SVille Tervo BT_DBG("%s status 0x%x", hdev->name, rp->status); 8626ed58ec5SVille Tervo 8636ed58ec5SVille Tervo if (rp->status) 8646ed58ec5SVille Tervo return; 8656ed58ec5SVille Tervo 8666ed58ec5SVille Tervo hdev->le_mtu = __le16_to_cpu(rp->le_mtu); 8676ed58ec5SVille Tervo hdev->le_pkts = rp->le_max_pkt; 8686ed58ec5SVille Tervo 8696ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 8706ed58ec5SVille Tervo 8716ed58ec5SVille Tervo BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); 8726ed58ec5SVille Tervo 8736ed58ec5SVille Tervo hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status); 8746ed58ec5SVille Tervo } 875980e1a53SJohan Hedberg 876a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) 877a5c29683SJohan Hedberg { 878a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 879a5c29683SJohan Hedberg 880a5c29683SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 881a5c29683SJohan Hedberg 882a5c29683SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 883a5c29683SJohan Hedberg mgmt_user_confirm_reply_complete(hdev->id, &rp->bdaddr, 884a5c29683SJohan Hedberg rp->status); 885a5c29683SJohan Hedberg } 886a5c29683SJohan Hedberg 887a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, 888a5c29683SJohan Hedberg struct sk_buff *skb) 889a5c29683SJohan Hedberg { 890a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 891a5c29683SJohan Hedberg 892a5c29683SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 893a5c29683SJohan Hedberg 894a5c29683SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 895a5c29683SJohan Hedberg mgmt_user_confirm_neg_reply_complete(hdev->id, &rp->bdaddr, 896a5c29683SJohan Hedberg rp->status); 897a5c29683SJohan Hedberg } 898a5c29683SJohan Hedberg 899c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, 900c35938b2SSzymon Janc struct sk_buff *skb) 901c35938b2SSzymon Janc { 902c35938b2SSzymon Janc struct hci_rp_read_local_oob_data *rp = (void *) skb->data; 903c35938b2SSzymon Janc 904c35938b2SSzymon Janc BT_DBG("%s status 0x%x", hdev->name, rp->status); 905c35938b2SSzymon Janc 906c35938b2SSzymon Janc mgmt_read_local_oob_data_reply_complete(hdev->id, rp->hash, 907c35938b2SSzymon Janc rp->randomizer, rp->status); 908c35938b2SSzymon Janc } 909c35938b2SSzymon Janc 910eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, 911eb9d91f5SAndre Guedes struct sk_buff *skb) 912eb9d91f5SAndre Guedes { 913eb9d91f5SAndre Guedes struct hci_cp_le_set_scan_enable *cp; 914eb9d91f5SAndre Guedes __u8 status = *((__u8 *) skb->data); 915eb9d91f5SAndre Guedes 916eb9d91f5SAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 917eb9d91f5SAndre Guedes 918eb9d91f5SAndre Guedes if (status) 919eb9d91f5SAndre Guedes return; 920eb9d91f5SAndre Guedes 921eb9d91f5SAndre Guedes cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE); 922eb9d91f5SAndre Guedes if (!cp) 923eb9d91f5SAndre Guedes return; 924eb9d91f5SAndre Guedes 92535815085SAndre Guedes if (cp->enable == 0x01) { 92635815085SAndre Guedes del_timer(&hdev->adv_timer); 927a8f13c8cSAndre Guedes 928a8f13c8cSAndre Guedes hci_dev_lock(hdev); 929eb9d91f5SAndre Guedes hci_adv_entries_clear(hdev); 930a8f13c8cSAndre Guedes hci_dev_unlock(hdev); 93135815085SAndre Guedes } else if (cp->enable == 0x00) { 93235815085SAndre Guedes mod_timer(&hdev->adv_timer, jiffies + ADV_CLEAR_TIMEOUT); 93335815085SAndre Guedes } 934eb9d91f5SAndre Guedes } 935eb9d91f5SAndre Guedes 936a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb) 937a7a595f6SVinicius Costa Gomes { 938a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_reply *rp = (void *) skb->data; 939a7a595f6SVinicius Costa Gomes 940a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, rp->status); 941a7a595f6SVinicius Costa Gomes 942a7a595f6SVinicius Costa Gomes if (rp->status) 943a7a595f6SVinicius Costa Gomes return; 944a7a595f6SVinicius Costa Gomes 945a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status); 946a7a595f6SVinicius Costa Gomes } 947a7a595f6SVinicius Costa Gomes 948a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 949a7a595f6SVinicius Costa Gomes { 950a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data; 951a7a595f6SVinicius Costa Gomes 952a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, rp->status); 953a7a595f6SVinicius Costa Gomes 954a7a595f6SVinicius Costa Gomes if (rp->status) 955a7a595f6SVinicius Costa Gomes return; 956a7a595f6SVinicius Costa Gomes 957a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status); 958a7a595f6SVinicius Costa Gomes } 959a7a595f6SVinicius Costa Gomes 960f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev, 961f9b49306SAndre Guedes struct sk_buff *skb) 962f9b49306SAndre Guedes { 963f9b49306SAndre Guedes struct hci_cp_read_local_ext_features cp; 964f9b49306SAndre Guedes __u8 status = *((__u8 *) skb->data); 965f9b49306SAndre Guedes 966f9b49306SAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 967f9b49306SAndre Guedes 968f9b49306SAndre Guedes if (status) 969f9b49306SAndre Guedes return; 970f9b49306SAndre Guedes 971f9b49306SAndre Guedes cp.page = 0x01; 972f9b49306SAndre Guedes hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp); 973f9b49306SAndre Guedes } 974f9b49306SAndre Guedes 975a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 976a9de9248SMarcel Holtmann { 977a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 978a9de9248SMarcel Holtmann 979a9de9248SMarcel Holtmann if (status) { 98023bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 981a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 982164a6e78SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 983164a6e78SJohan Hedberg mgmt_inquiry_failed(hdev->id, status); 984314b2381SJohan Hedberg return; 985314b2381SJohan Hedberg } 986314b2381SJohan Hedberg 9872d20a26aSOliver Neukum if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags) && 9882d20a26aSOliver Neukum test_bit(HCI_MGMT, &hdev->flags)) 989314b2381SJohan Hedberg mgmt_discovering(hdev->id, 1); 990a9de9248SMarcel Holtmann } 991a9de9248SMarcel Holtmann 9921da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 9931da177e4SLinus Torvalds { 994a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 9951da177e4SLinus Torvalds struct hci_conn *conn; 9961da177e4SLinus Torvalds 997a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 998a9de9248SMarcel Holtmann 999a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 10001da177e4SLinus Torvalds if (!cp) 10011da177e4SLinus Torvalds return; 10021da177e4SLinus Torvalds 10031da177e4SLinus Torvalds hci_dev_lock(hdev); 10041da177e4SLinus Torvalds 10051da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 10061da177e4SLinus Torvalds 1007a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn); 10081da177e4SLinus Torvalds 10091da177e4SLinus Torvalds if (status) { 10101da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 10114c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 10121da177e4SLinus Torvalds conn->state = BT_CLOSED; 10131da177e4SLinus Torvalds hci_proto_connect_cfm(conn, status); 10141da177e4SLinus Torvalds hci_conn_del(conn); 10154c67bc74SMarcel Holtmann } else 10164c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 10171da177e4SLinus Torvalds } 10181da177e4SLinus Torvalds } else { 10191da177e4SLinus Torvalds if (!conn) { 10201da177e4SLinus Torvalds conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); 10211da177e4SLinus Torvalds if (conn) { 10221da177e4SLinus Torvalds conn->out = 1; 10231da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 10241da177e4SLinus Torvalds } else 1025893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 10261da177e4SLinus Torvalds } 10271da177e4SLinus Torvalds } 10281da177e4SLinus Torvalds 10291da177e4SLinus Torvalds hci_dev_unlock(hdev); 10301da177e4SLinus Torvalds } 10311da177e4SLinus Torvalds 1032a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 10331da177e4SLinus Torvalds { 1034a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 10351da177e4SLinus Torvalds struct hci_conn *acl, *sco; 10361da177e4SLinus Torvalds __u16 handle; 10371da177e4SLinus Torvalds 1038b6a0dc82SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1039b6a0dc82SMarcel Holtmann 1040a9de9248SMarcel Holtmann if (!status) 1041a9de9248SMarcel Holtmann return; 1042a9de9248SMarcel Holtmann 1043a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 10441da177e4SLinus Torvalds if (!cp) 1045a9de9248SMarcel Holtmann return; 10461da177e4SLinus Torvalds 10471da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 10481da177e4SLinus Torvalds 1049a9de9248SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 10501da177e4SLinus Torvalds 10511da177e4SLinus Torvalds hci_dev_lock(hdev); 10521da177e4SLinus Torvalds 10531da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 10545a08ecceSAndrei Emeltchenko if (acl) { 10555a08ecceSAndrei Emeltchenko sco = acl->link; 10565a08ecceSAndrei Emeltchenko if (sco) { 10571da177e4SLinus Torvalds sco->state = BT_CLOSED; 10581da177e4SLinus Torvalds 10591da177e4SLinus Torvalds hci_proto_connect_cfm(sco, status); 10601da177e4SLinus Torvalds hci_conn_del(sco); 10611da177e4SLinus Torvalds } 10625a08ecceSAndrei Emeltchenko } 10631da177e4SLinus Torvalds 10641da177e4SLinus Torvalds hci_dev_unlock(hdev); 10651da177e4SLinus Torvalds } 10661da177e4SLinus Torvalds 1067f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 1068f8558555SMarcel Holtmann { 1069f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 1070f8558555SMarcel Holtmann struct hci_conn *conn; 1071f8558555SMarcel Holtmann 1072f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1073f8558555SMarcel Holtmann 1074f8558555SMarcel Holtmann if (!status) 1075f8558555SMarcel Holtmann return; 1076f8558555SMarcel Holtmann 1077f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 1078f8558555SMarcel Holtmann if (!cp) 1079f8558555SMarcel Holtmann return; 1080f8558555SMarcel Holtmann 1081f8558555SMarcel Holtmann hci_dev_lock(hdev); 1082f8558555SMarcel Holtmann 1083f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1084f8558555SMarcel Holtmann if (conn) { 1085f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1086f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1087f8558555SMarcel Holtmann hci_conn_put(conn); 1088f8558555SMarcel Holtmann } 1089f8558555SMarcel Holtmann } 1090f8558555SMarcel Holtmann 1091f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1092f8558555SMarcel Holtmann } 1093f8558555SMarcel Holtmann 1094f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 1095f8558555SMarcel Holtmann { 1096f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 1097f8558555SMarcel Holtmann struct hci_conn *conn; 1098f8558555SMarcel Holtmann 1099f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1100f8558555SMarcel Holtmann 1101f8558555SMarcel Holtmann if (!status) 1102f8558555SMarcel Holtmann return; 1103f8558555SMarcel Holtmann 1104f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 1105f8558555SMarcel Holtmann if (!cp) 1106f8558555SMarcel Holtmann return; 1107f8558555SMarcel Holtmann 1108f8558555SMarcel Holtmann hci_dev_lock(hdev); 1109f8558555SMarcel Holtmann 1110f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1111f8558555SMarcel Holtmann if (conn) { 1112f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1113f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1114f8558555SMarcel Holtmann hci_conn_put(conn); 1115f8558555SMarcel Holtmann } 1116f8558555SMarcel Holtmann } 1117f8558555SMarcel Holtmann 1118f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1119f8558555SMarcel Holtmann } 1120f8558555SMarcel Holtmann 1121127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev, 1122392599b9SJohan Hedberg struct hci_conn *conn) 1123392599b9SJohan Hedberg { 1124392599b9SJohan Hedberg if (conn->state != BT_CONFIG || !conn->out) 1125392599b9SJohan Hedberg return 0; 1126392599b9SJohan Hedberg 1127765c2a96SJohan Hedberg if (conn->pending_sec_level == BT_SECURITY_SDP) 1128392599b9SJohan Hedberg return 0; 1129392599b9SJohan Hedberg 1130392599b9SJohan Hedberg /* Only request authentication for SSP connections or non-SSP 1131e9bf2bf0SVinicius Costa Gomes * devices with sec_level HIGH or if MITM protection is requested */ 1132392599b9SJohan Hedberg if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) && 1133e9bf2bf0SVinicius Costa Gomes conn->pending_sec_level != BT_SECURITY_HIGH && 1134e9bf2bf0SVinicius Costa Gomes !(conn->auth_type & 0x01)) 1135392599b9SJohan Hedberg return 0; 1136392599b9SJohan Hedberg 1137392599b9SJohan Hedberg return 1; 1138392599b9SJohan Hedberg } 1139392599b9SJohan Hedberg 1140a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 11411da177e4SLinus Torvalds { 1142127178d2SJohan Hedberg struct hci_cp_remote_name_req *cp; 1143127178d2SJohan Hedberg struct hci_conn *conn; 1144127178d2SJohan Hedberg 1145a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1146127178d2SJohan Hedberg 1147127178d2SJohan Hedberg /* If successful wait for the name req complete event before 1148127178d2SJohan Hedberg * checking for the need to do authentication */ 1149127178d2SJohan Hedberg if (!status) 1150127178d2SJohan Hedberg return; 1151127178d2SJohan Hedberg 1152127178d2SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); 1153127178d2SJohan Hedberg if (!cp) 1154127178d2SJohan Hedberg return; 1155127178d2SJohan Hedberg 1156127178d2SJohan Hedberg hci_dev_lock(hdev); 1157127178d2SJohan Hedberg 1158127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 115979c6c70cSJohan Hedberg if (!conn) 116079c6c70cSJohan Hedberg goto unlock; 116179c6c70cSJohan Hedberg 116279c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 116379c6c70cSJohan Hedberg goto unlock; 116479c6c70cSJohan Hedberg 116579c6c70cSJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { 1166127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1167127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1168127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1169127178d2SJohan Hedberg } 1170127178d2SJohan Hedberg 117179c6c70cSJohan Hedberg unlock: 1172127178d2SJohan Hedberg hci_dev_unlock(hdev); 1173a9de9248SMarcel Holtmann } 11741da177e4SLinus Torvalds 1175769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 1176769be974SMarcel Holtmann { 1177769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 1178769be974SMarcel Holtmann struct hci_conn *conn; 1179769be974SMarcel Holtmann 1180769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1181769be974SMarcel Holtmann 1182769be974SMarcel Holtmann if (!status) 1183769be974SMarcel Holtmann return; 1184769be974SMarcel Holtmann 1185769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 1186769be974SMarcel Holtmann if (!cp) 1187769be974SMarcel Holtmann return; 1188769be974SMarcel Holtmann 1189769be974SMarcel Holtmann hci_dev_lock(hdev); 1190769be974SMarcel Holtmann 1191769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1192769be974SMarcel Holtmann if (conn) { 1193769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1194769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1195769be974SMarcel Holtmann hci_conn_put(conn); 1196769be974SMarcel Holtmann } 1197769be974SMarcel Holtmann } 1198769be974SMarcel Holtmann 1199769be974SMarcel Holtmann hci_dev_unlock(hdev); 1200769be974SMarcel Holtmann } 1201769be974SMarcel Holtmann 1202769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 1203769be974SMarcel Holtmann { 1204769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features *cp; 1205769be974SMarcel Holtmann struct hci_conn *conn; 1206769be974SMarcel Holtmann 1207769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1208769be974SMarcel Holtmann 1209769be974SMarcel Holtmann if (!status) 1210769be974SMarcel Holtmann return; 1211769be974SMarcel Holtmann 1212769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 1213769be974SMarcel Holtmann if (!cp) 1214769be974SMarcel Holtmann return; 1215769be974SMarcel Holtmann 1216769be974SMarcel Holtmann hci_dev_lock(hdev); 1217769be974SMarcel Holtmann 1218769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1219769be974SMarcel Holtmann if (conn) { 1220769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1221769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1222769be974SMarcel Holtmann hci_conn_put(conn); 1223769be974SMarcel Holtmann } 1224769be974SMarcel Holtmann } 1225769be974SMarcel Holtmann 1226769be974SMarcel Holtmann hci_dev_unlock(hdev); 1227769be974SMarcel Holtmann } 1228769be974SMarcel Holtmann 1229a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 1230a9de9248SMarcel Holtmann { 1231b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 1232b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 1233b6a0dc82SMarcel Holtmann __u16 handle; 1234b6a0dc82SMarcel Holtmann 1235a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1236b6a0dc82SMarcel Holtmann 1237b6a0dc82SMarcel Holtmann if (!status) 1238b6a0dc82SMarcel Holtmann return; 1239b6a0dc82SMarcel Holtmann 1240b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 1241b6a0dc82SMarcel Holtmann if (!cp) 1242b6a0dc82SMarcel Holtmann return; 1243b6a0dc82SMarcel Holtmann 1244b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 1245b6a0dc82SMarcel Holtmann 1246b6a0dc82SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 1247b6a0dc82SMarcel Holtmann 1248b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 1249b6a0dc82SMarcel Holtmann 1250b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 12515a08ecceSAndrei Emeltchenko if (acl) { 12525a08ecceSAndrei Emeltchenko sco = acl->link; 12535a08ecceSAndrei Emeltchenko if (sco) { 1254b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 1255b6a0dc82SMarcel Holtmann 1256b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(sco, status); 1257b6a0dc82SMarcel Holtmann hci_conn_del(sco); 1258b6a0dc82SMarcel Holtmann } 12595a08ecceSAndrei Emeltchenko } 1260b6a0dc82SMarcel Holtmann 1261b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 1262a9de9248SMarcel Holtmann } 1263a9de9248SMarcel Holtmann 1264a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 1265a9de9248SMarcel Holtmann { 1266a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 126704837f64SMarcel Holtmann struct hci_conn *conn; 126804837f64SMarcel Holtmann 1269a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1270a9de9248SMarcel Holtmann 1271a9de9248SMarcel Holtmann if (!status) 1272a9de9248SMarcel Holtmann return; 1273a9de9248SMarcel Holtmann 1274a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 127504837f64SMarcel Holtmann if (!cp) 1276a9de9248SMarcel Holtmann return; 127704837f64SMarcel Holtmann 127804837f64SMarcel Holtmann hci_dev_lock(hdev); 127904837f64SMarcel Holtmann 128004837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1281e73439d8SMarcel Holtmann if (conn) { 128204837f64SMarcel Holtmann clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); 128304837f64SMarcel Holtmann 1284e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 1285e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1286e73439d8SMarcel Holtmann } 1287e73439d8SMarcel Holtmann 128804837f64SMarcel Holtmann hci_dev_unlock(hdev); 128904837f64SMarcel Holtmann } 129004837f64SMarcel Holtmann 1291a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 1292a9de9248SMarcel Holtmann { 1293a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 129404837f64SMarcel Holtmann struct hci_conn *conn; 129504837f64SMarcel Holtmann 1296a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1297a9de9248SMarcel Holtmann 1298a9de9248SMarcel Holtmann if (!status) 1299a9de9248SMarcel Holtmann return; 1300a9de9248SMarcel Holtmann 1301a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 130204837f64SMarcel Holtmann if (!cp) 1303a9de9248SMarcel Holtmann return; 130404837f64SMarcel Holtmann 130504837f64SMarcel Holtmann hci_dev_lock(hdev); 130604837f64SMarcel Holtmann 130704837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1308e73439d8SMarcel Holtmann if (conn) { 130904837f64SMarcel Holtmann clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); 131004837f64SMarcel Holtmann 1311e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 1312e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1313e73439d8SMarcel Holtmann } 1314e73439d8SMarcel Holtmann 131504837f64SMarcel Holtmann hci_dev_unlock(hdev); 131604837f64SMarcel Holtmann } 131704837f64SMarcel Holtmann 1318fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) 1319fcd89c09SVille Tervo { 1320fcd89c09SVille Tervo struct hci_cp_le_create_conn *cp; 1321fcd89c09SVille Tervo struct hci_conn *conn; 1322fcd89c09SVille Tervo 1323fcd89c09SVille Tervo BT_DBG("%s status 0x%x", hdev->name, status); 1324fcd89c09SVille Tervo 1325fcd89c09SVille Tervo cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN); 1326fcd89c09SVille Tervo if (!cp) 1327fcd89c09SVille Tervo return; 1328fcd89c09SVille Tervo 1329fcd89c09SVille Tervo hci_dev_lock(hdev); 1330fcd89c09SVille Tervo 1331fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr); 1332fcd89c09SVille Tervo 1333fcd89c09SVille Tervo BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr), 1334fcd89c09SVille Tervo conn); 1335fcd89c09SVille Tervo 1336fcd89c09SVille Tervo if (status) { 1337fcd89c09SVille Tervo if (conn && conn->state == BT_CONNECT) { 1338fcd89c09SVille Tervo conn->state = BT_CLOSED; 1339fcd89c09SVille Tervo hci_proto_connect_cfm(conn, status); 1340fcd89c09SVille Tervo hci_conn_del(conn); 1341fcd89c09SVille Tervo } 1342fcd89c09SVille Tervo } else { 1343fcd89c09SVille Tervo if (!conn) { 1344fcd89c09SVille Tervo conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr); 134529b7988aSAndre Guedes if (conn) { 134629b7988aSAndre Guedes conn->dst_type = cp->peer_addr_type; 1347fcd89c09SVille Tervo conn->out = 1; 134829b7988aSAndre Guedes } else { 1349fcd89c09SVille Tervo BT_ERR("No memory for new connection"); 1350fcd89c09SVille Tervo } 1351fcd89c09SVille Tervo } 135229b7988aSAndre Guedes } 1353fcd89c09SVille Tervo 1354fcd89c09SVille Tervo hci_dev_unlock(hdev); 1355fcd89c09SVille Tervo } 1356fcd89c09SVille Tervo 1357a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) 1358a7a595f6SVinicius Costa Gomes { 1359a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, status); 1360a7a595f6SVinicius Costa Gomes } 1361a7a595f6SVinicius Costa Gomes 13621da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 13631da177e4SLinus Torvalds { 13641da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 13651da177e4SLinus Torvalds 13661da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, status); 13671da177e4SLinus Torvalds 13682d20a26aSOliver Neukum if (test_and_clear_bit(HCI_INQUIRY, &hdev->flags) && 13692d20a26aSOliver Neukum test_bit(HCI_MGMT, &hdev->flags)) 1370314b2381SJohan Hedberg mgmt_discovering(hdev->id, 0); 1371a9de9248SMarcel Holtmann 137223bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 13736bd57416SMarcel Holtmann 1374a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 13751da177e4SLinus Torvalds } 13761da177e4SLinus Torvalds 13771da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 13781da177e4SLinus Torvalds { 137945bb4bf0SMarcel Holtmann struct inquiry_data data; 1380a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 13811da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 13821da177e4SLinus Torvalds 13831da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 13841da177e4SLinus Torvalds 138545bb4bf0SMarcel Holtmann if (!num_rsp) 138645bb4bf0SMarcel Holtmann return; 138745bb4bf0SMarcel Holtmann 13881da177e4SLinus Torvalds hci_dev_lock(hdev); 138945bb4bf0SMarcel Holtmann 1390314b2381SJohan Hedberg if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) { 1391314b2381SJohan Hedberg 1392314b2381SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 1393314b2381SJohan Hedberg mgmt_discovering(hdev->id, 1); 1394314b2381SJohan Hedberg } 1395314b2381SJohan Hedberg 1396e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 13971da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 13981da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 13991da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 14001da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 14011da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 14021da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 14031da177e4SLinus Torvalds data.rssi = 0x00; 140441a96212SMarcel Holtmann data.ssp_mode = 0x00; 14051da177e4SLinus Torvalds hci_inquiry_cache_update(hdev, &data); 1406e17acd40SJohan Hedberg mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class, 0, 1407e17acd40SJohan Hedberg NULL); 14081da177e4SLinus Torvalds } 140945bb4bf0SMarcel Holtmann 14101da177e4SLinus Torvalds hci_dev_unlock(hdev); 14111da177e4SLinus Torvalds } 14121da177e4SLinus Torvalds 1413a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 14141da177e4SLinus Torvalds { 1415a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 1416a9de9248SMarcel Holtmann struct hci_conn *conn; 14171da177e4SLinus Torvalds 1418a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 141945bb4bf0SMarcel Holtmann 14201da177e4SLinus Torvalds hci_dev_lock(hdev); 142145bb4bf0SMarcel Holtmann 1422a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 14239499237aSMarcel Holtmann if (!conn) { 14249499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 14259499237aSMarcel Holtmann goto unlock; 14269499237aSMarcel Holtmann 14279499237aSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 1428a9de9248SMarcel Holtmann if (!conn) 1429a9de9248SMarcel Holtmann goto unlock; 143045bb4bf0SMarcel Holtmann 14319499237aSMarcel Holtmann conn->type = SCO_LINK; 14329499237aSMarcel Holtmann } 14339499237aSMarcel Holtmann 1434a9de9248SMarcel Holtmann if (!ev->status) { 1435a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 1436769be974SMarcel Holtmann 1437769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 1438769be974SMarcel Holtmann conn->state = BT_CONFIG; 1439769be974SMarcel Holtmann hci_conn_hold(conn); 1440052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1441cfafccf7SVinicius Costa Gomes mgmt_connected(hdev->id, &ev->bdaddr, conn->type); 1442769be974SMarcel Holtmann } else 1443a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 1444a9de9248SMarcel Holtmann 14459eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 14467d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 14477d0db0a3SMarcel Holtmann 1448a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 1449a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1450a9de9248SMarcel Holtmann 1451a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 1452a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1453a9de9248SMarcel Holtmann 1454a9de9248SMarcel Holtmann /* Get remote features */ 1455a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 1456a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 1457a9de9248SMarcel Holtmann cp.handle = ev->handle; 1458769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 1459769be974SMarcel Holtmann sizeof(cp), &cp); 146045bb4bf0SMarcel Holtmann } 1461a9de9248SMarcel Holtmann 1462a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 1463a8746417SMarcel Holtmann if (!conn->out && hdev->hci_ver < 3) { 1464a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 1465a9de9248SMarcel Holtmann cp.handle = ev->handle; 1466a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1467a8746417SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, 1468a8746417SMarcel Holtmann sizeof(cp), &cp); 1469a9de9248SMarcel Holtmann } 147017d5c04cSJohan Hedberg } else { 1471a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 147217d5c04cSJohan Hedberg if (conn->type == ACL_LINK) 147317d5c04cSJohan Hedberg mgmt_connect_failed(hdev->id, &ev->bdaddr, ev->status); 147417d5c04cSJohan Hedberg } 147545bb4bf0SMarcel Holtmann 1476e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 1477e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 147845bb4bf0SMarcel Holtmann 1479769be974SMarcel Holtmann if (ev->status) { 1480a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1481a9de9248SMarcel Holtmann hci_conn_del(conn); 1482c89b6e6bSMarcel Holtmann } else if (ev->link_type != ACL_LINK) 1483c89b6e6bSMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1484a9de9248SMarcel Holtmann 1485a9de9248SMarcel Holtmann unlock: 14861da177e4SLinus Torvalds hci_dev_unlock(hdev); 1487a9de9248SMarcel Holtmann 1488a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 14891da177e4SLinus Torvalds } 14901da177e4SLinus Torvalds 14911da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 14921da177e4SLinus Torvalds { 1493a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 14941da177e4SLinus Torvalds int mask = hdev->link_mode; 14951da177e4SLinus Torvalds 1496a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s type 0x%x", hdev->name, 14971da177e4SLinus Torvalds batostr(&ev->bdaddr), ev->link_type); 14981da177e4SLinus Torvalds 14991da177e4SLinus Torvalds mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); 15001da177e4SLinus Torvalds 1501138d22efSSzymon Janc if ((mask & HCI_LM_ACCEPT) && 1502138d22efSSzymon Janc !hci_blacklist_lookup(hdev, &ev->bdaddr)) { 15031da177e4SLinus Torvalds /* Connection accepted */ 1504c7bdd502SMarcel Holtmann struct inquiry_entry *ie; 15051da177e4SLinus Torvalds struct hci_conn *conn; 15061da177e4SLinus Torvalds 15071da177e4SLinus Torvalds hci_dev_lock(hdev); 1508b6a0dc82SMarcel Holtmann 1509cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 1510cc11b9c1SAndrei Emeltchenko if (ie) 1511c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 1512c7bdd502SMarcel Holtmann 15131da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 15141da177e4SLinus Torvalds if (!conn) { 1515cc11b9c1SAndrei Emeltchenko conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); 1516cc11b9c1SAndrei Emeltchenko if (!conn) { 1517893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 15181da177e4SLinus Torvalds hci_dev_unlock(hdev); 15191da177e4SLinus Torvalds return; 15201da177e4SLinus Torvalds } 15211da177e4SLinus Torvalds } 1522b6a0dc82SMarcel Holtmann 15231da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 15241da177e4SLinus Torvalds conn->state = BT_CONNECT; 1525b6a0dc82SMarcel Holtmann 15261da177e4SLinus Torvalds hci_dev_unlock(hdev); 15271da177e4SLinus Torvalds 1528b6a0dc82SMarcel Holtmann if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) { 1529b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 1530b6a0dc82SMarcel Holtmann 15311da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 15321da177e4SLinus Torvalds 15331da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 15341da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 15351da177e4SLinus Torvalds else 15361da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 15371da177e4SLinus Torvalds 1538b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, 1539b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1540b6a0dc82SMarcel Holtmann } else { 1541b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 1542b6a0dc82SMarcel Holtmann 1543b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 1544a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1545b6a0dc82SMarcel Holtmann 1546b6a0dc82SMarcel Holtmann cp.tx_bandwidth = cpu_to_le32(0x00001f40); 1547b6a0dc82SMarcel Holtmann cp.rx_bandwidth = cpu_to_le32(0x00001f40); 1548b6a0dc82SMarcel Holtmann cp.max_latency = cpu_to_le16(0xffff); 1549b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 1550b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 1551b6a0dc82SMarcel Holtmann 1552b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 1553b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1554b6a0dc82SMarcel Holtmann } 15551da177e4SLinus Torvalds } else { 15561da177e4SLinus Torvalds /* Connection rejected */ 15571da177e4SLinus Torvalds struct hci_cp_reject_conn_req cp; 15581da177e4SLinus Torvalds 15591da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 15601da177e4SLinus Torvalds cp.reason = 0x0f; 1561a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 15621da177e4SLinus Torvalds } 15631da177e4SLinus Torvalds } 15641da177e4SLinus Torvalds 15651da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 15661da177e4SLinus Torvalds { 1567a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 156804837f64SMarcel Holtmann struct hci_conn *conn; 15691da177e4SLinus Torvalds 15701da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 15711da177e4SLinus Torvalds 15728962ee74SJohan Hedberg if (ev->status) { 15738962ee74SJohan Hedberg mgmt_disconnect_failed(hdev->id); 15741da177e4SLinus Torvalds return; 15758962ee74SJohan Hedberg } 15761da177e4SLinus Torvalds 15771da177e4SLinus Torvalds hci_dev_lock(hdev); 15781da177e4SLinus Torvalds 157904837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1580f7520543SJohan Hedberg if (!conn) 1581f7520543SJohan Hedberg goto unlock; 1582f7520543SJohan Hedberg 15831da177e4SLinus Torvalds conn->state = BT_CLOSED; 15847d0db0a3SMarcel Holtmann 158583bc71b4SVinicius Costa Gomes if (conn->type == ACL_LINK || conn->type == LE_LINK) 1586f7520543SJohan Hedberg mgmt_disconnected(hdev->id, &conn->dst); 1587f7520543SJohan Hedberg 15882950f21aSMarcel Holtmann hci_proto_disconn_cfm(conn, ev->reason); 15891da177e4SLinus Torvalds hci_conn_del(conn); 15901da177e4SLinus Torvalds 1591f7520543SJohan Hedberg unlock: 15921da177e4SLinus Torvalds hci_dev_unlock(hdev); 15931da177e4SLinus Torvalds } 15941da177e4SLinus Torvalds 1595a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1596a9de9248SMarcel Holtmann { 1597a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 1598a9de9248SMarcel Holtmann struct hci_conn *conn; 1599a9de9248SMarcel Holtmann 1600a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1601a9de9248SMarcel Holtmann 1602a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1603a9de9248SMarcel Holtmann 1604a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1605d7556e20SWaldemar Rymarkiewicz if (!conn) 1606d7556e20SWaldemar Rymarkiewicz goto unlock; 1607d7556e20SWaldemar Rymarkiewicz 1608765c2a96SJohan Hedberg if (!ev->status) { 160919f8def0SWaldemar Rymarkiewicz if (!(conn->ssp_mode > 0 && hdev->ssp_mode > 0) && 1610d7556e20SWaldemar Rymarkiewicz test_bit(HCI_CONN_REAUTH_PEND, &conn->pend)) { 1611d7556e20SWaldemar Rymarkiewicz BT_INFO("re-auth of legacy device is not possible."); 161219f8def0SWaldemar Rymarkiewicz } else { 1613a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1614765c2a96SJohan Hedberg conn->sec_level = conn->pending_sec_level; 161519f8def0SWaldemar Rymarkiewicz } 16162a611692SJohan Hedberg } else { 16172a611692SJohan Hedberg mgmt_auth_failed(hdev->id, &conn->dst, ev->status); 16182a611692SJohan Hedberg } 1619a9de9248SMarcel Holtmann 1620a9de9248SMarcel Holtmann clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); 162119f8def0SWaldemar Rymarkiewicz clear_bit(HCI_CONN_REAUTH_PEND, &conn->pend); 1622a9de9248SMarcel Holtmann 1623f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1624d7556e20SWaldemar Rymarkiewicz if (!ev->status && hdev->ssp_mode > 0 && conn->ssp_mode > 0) { 1625f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1626f8558555SMarcel Holtmann cp.handle = ev->handle; 1627f8558555SMarcel Holtmann cp.encrypt = 0x01; 1628d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1629d7556e20SWaldemar Rymarkiewicz &cp); 1630f8558555SMarcel Holtmann } else { 1631f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1632f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1633f8558555SMarcel Holtmann hci_conn_put(conn); 1634f8558555SMarcel Holtmann } 1635052b30b0SMarcel Holtmann } else { 1636a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 1637a9de9248SMarcel Holtmann 1638052b30b0SMarcel Holtmann hci_conn_hold(conn); 1639052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1640052b30b0SMarcel Holtmann hci_conn_put(conn); 1641052b30b0SMarcel Holtmann } 1642052b30b0SMarcel Holtmann 1643a9de9248SMarcel Holtmann if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) { 1644a9de9248SMarcel Holtmann if (!ev->status) { 1645a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1646f8558555SMarcel Holtmann cp.handle = ev->handle; 1647f8558555SMarcel Holtmann cp.encrypt = 0x01; 1648d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1649d7556e20SWaldemar Rymarkiewicz &cp); 1650a9de9248SMarcel Holtmann } else { 1651a9de9248SMarcel Holtmann clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); 1652a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 1653a9de9248SMarcel Holtmann } 1654a9de9248SMarcel Holtmann } 1655a9de9248SMarcel Holtmann 1656d7556e20SWaldemar Rymarkiewicz unlock: 1657a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1658a9de9248SMarcel Holtmann } 1659a9de9248SMarcel Holtmann 1660a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 1661a9de9248SMarcel Holtmann { 1662127178d2SJohan Hedberg struct hci_ev_remote_name *ev = (void *) skb->data; 1663127178d2SJohan Hedberg struct hci_conn *conn; 1664127178d2SJohan Hedberg 1665a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1666a9de9248SMarcel Holtmann 1667a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 1668127178d2SJohan Hedberg 1669127178d2SJohan Hedberg hci_dev_lock(hdev); 1670127178d2SJohan Hedberg 1671a88a9652SJohan Hedberg if (ev->status == 0 && test_bit(HCI_MGMT, &hdev->flags)) 1672a88a9652SJohan Hedberg mgmt_remote_name(hdev->id, &ev->bdaddr, ev->name); 1673a88a9652SJohan Hedberg 1674127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 167579c6c70cSJohan Hedberg if (!conn) 167679c6c70cSJohan Hedberg goto unlock; 167779c6c70cSJohan Hedberg 167879c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 167979c6c70cSJohan Hedberg goto unlock; 168079c6c70cSJohan Hedberg 168179c6c70cSJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { 1682127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1683127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1684127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1685127178d2SJohan Hedberg } 1686127178d2SJohan Hedberg 168779c6c70cSJohan Hedberg unlock: 1688127178d2SJohan Hedberg hci_dev_unlock(hdev); 1689a9de9248SMarcel Holtmann } 1690a9de9248SMarcel Holtmann 1691a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 1692a9de9248SMarcel Holtmann { 1693a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 1694a9de9248SMarcel Holtmann struct hci_conn *conn; 1695a9de9248SMarcel Holtmann 1696a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1697a9de9248SMarcel Holtmann 1698a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1699a9de9248SMarcel Holtmann 1700a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1701a9de9248SMarcel Holtmann if (conn) { 1702a9de9248SMarcel Holtmann if (!ev->status) { 1703ae293196SMarcel Holtmann if (ev->encrypt) { 1704ae293196SMarcel Holtmann /* Encryption implies authentication */ 1705ae293196SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1706a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1707da85e5e5SVinicius Costa Gomes conn->sec_level = conn->pending_sec_level; 1708ae293196SMarcel Holtmann } else 1709a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_ENCRYPT; 1710a9de9248SMarcel Holtmann } 1711a9de9248SMarcel Holtmann 1712a9de9248SMarcel Holtmann clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); 1713a9de9248SMarcel Holtmann 1714f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1715f8558555SMarcel Holtmann if (!ev->status) 1716f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1717f8558555SMarcel Holtmann 1718f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1719f8558555SMarcel Holtmann hci_conn_put(conn); 1720f8558555SMarcel Holtmann } else 1721a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 1722a9de9248SMarcel Holtmann } 1723a9de9248SMarcel Holtmann 1724a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1725a9de9248SMarcel Holtmann } 1726a9de9248SMarcel Holtmann 1727a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1728a9de9248SMarcel Holtmann { 1729a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 1730a9de9248SMarcel Holtmann struct hci_conn *conn; 1731a9de9248SMarcel Holtmann 1732a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1733a9de9248SMarcel Holtmann 1734a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1735a9de9248SMarcel Holtmann 1736a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1737a9de9248SMarcel Holtmann if (conn) { 1738a9de9248SMarcel Holtmann if (!ev->status) 1739a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_SECURE; 1740a9de9248SMarcel Holtmann 1741a9de9248SMarcel Holtmann clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); 1742a9de9248SMarcel Holtmann 1743a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 1744a9de9248SMarcel Holtmann } 1745a9de9248SMarcel Holtmann 1746a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1747a9de9248SMarcel Holtmann } 1748a9de9248SMarcel Holtmann 1749a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 1750a9de9248SMarcel Holtmann { 1751a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 1752a9de9248SMarcel Holtmann struct hci_conn *conn; 1753a9de9248SMarcel Holtmann 1754a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1755a9de9248SMarcel Holtmann 1756a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1757a9de9248SMarcel Holtmann 1758a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1759ccd556feSJohan Hedberg if (!conn) 1760ccd556feSJohan Hedberg goto unlock; 1761ccd556feSJohan Hedberg 1762769be974SMarcel Holtmann if (!ev->status) 1763a9de9248SMarcel Holtmann memcpy(conn->features, ev->features, 8); 1764a9de9248SMarcel Holtmann 1765ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 1766ccd556feSJohan Hedberg goto unlock; 1767ccd556feSJohan Hedberg 1768ccd556feSJohan Hedberg if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { 1769769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 1770769be974SMarcel Holtmann cp.handle = ev->handle; 1771769be974SMarcel Holtmann cp.page = 0x01; 1772ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 1773769be974SMarcel Holtmann sizeof(cp), &cp); 1774392599b9SJohan Hedberg goto unlock; 1775392599b9SJohan Hedberg } 1776392599b9SJohan Hedberg 1777127178d2SJohan Hedberg if (!ev->status) { 1778127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 1779127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 1780127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 1781127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 1782127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 1783127178d2SJohan Hedberg } 1784392599b9SJohan Hedberg 1785127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 1786769be974SMarcel Holtmann conn->state = BT_CONNECTED; 1787769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1788769be974SMarcel Holtmann hci_conn_put(conn); 1789769be974SMarcel Holtmann } 1790769be974SMarcel Holtmann 1791ccd556feSJohan Hedberg unlock: 1792a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1793a9de9248SMarcel Holtmann } 1794a9de9248SMarcel Holtmann 1795a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) 1796a9de9248SMarcel Holtmann { 1797a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1798a9de9248SMarcel Holtmann } 1799a9de9248SMarcel Holtmann 1800a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1801a9de9248SMarcel Holtmann { 1802a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1803a9de9248SMarcel Holtmann } 1804a9de9248SMarcel Holtmann 1805a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1806a9de9248SMarcel Holtmann { 1807a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 1808a9de9248SMarcel Holtmann __u16 opcode; 1809a9de9248SMarcel Holtmann 1810a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 1811a9de9248SMarcel Holtmann 1812a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 1813a9de9248SMarcel Holtmann 1814a9de9248SMarcel Holtmann switch (opcode) { 1815a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 1816a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 1817a9de9248SMarcel Holtmann break; 1818a9de9248SMarcel Holtmann 1819a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 1820a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 1821a9de9248SMarcel Holtmann break; 1822a9de9248SMarcel Holtmann 1823a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 1824a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 1825a9de9248SMarcel Holtmann break; 1826a9de9248SMarcel Holtmann 1827a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 1828a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 1829a9de9248SMarcel Holtmann break; 1830a9de9248SMarcel Holtmann 1831e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 1832e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 1833e4e8e37cSMarcel Holtmann break; 1834e4e8e37cSMarcel Holtmann 1835a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 1836a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 1837a9de9248SMarcel Holtmann break; 1838a9de9248SMarcel Holtmann 1839e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 1840e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 1841e4e8e37cSMarcel Holtmann break; 1842e4e8e37cSMarcel Holtmann 1843e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 1844e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 1845e4e8e37cSMarcel Holtmann break; 1846e4e8e37cSMarcel Holtmann 1847a9de9248SMarcel Holtmann case HCI_OP_RESET: 1848a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 1849a9de9248SMarcel Holtmann break; 1850a9de9248SMarcel Holtmann 1851a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 1852a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 1853a9de9248SMarcel Holtmann break; 1854a9de9248SMarcel Holtmann 1855a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 1856a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 1857a9de9248SMarcel Holtmann break; 1858a9de9248SMarcel Holtmann 1859a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 1860a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 1861a9de9248SMarcel Holtmann break; 1862a9de9248SMarcel Holtmann 1863a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 1864a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 1865a9de9248SMarcel Holtmann break; 1866a9de9248SMarcel Holtmann 1867a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 1868a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 1869a9de9248SMarcel Holtmann break; 1870a9de9248SMarcel Holtmann 1871a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 1872a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 1873a9de9248SMarcel Holtmann break; 1874a9de9248SMarcel Holtmann 1875a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 1876a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 1877a9de9248SMarcel Holtmann break; 1878a9de9248SMarcel Holtmann 1879a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 1880a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 1881a9de9248SMarcel Holtmann break; 1882a9de9248SMarcel Holtmann 1883a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 1884a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 1885a9de9248SMarcel Holtmann break; 1886a9de9248SMarcel Holtmann 1887a9de9248SMarcel Holtmann case HCI_OP_HOST_BUFFER_SIZE: 1888a9de9248SMarcel Holtmann hci_cc_host_buffer_size(hdev, skb); 1889a9de9248SMarcel Holtmann break; 1890a9de9248SMarcel Holtmann 1891333140b5SMarcel Holtmann case HCI_OP_READ_SSP_MODE: 1892333140b5SMarcel Holtmann hci_cc_read_ssp_mode(hdev, skb); 1893333140b5SMarcel Holtmann break; 1894333140b5SMarcel Holtmann 1895333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 1896333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 1897333140b5SMarcel Holtmann break; 1898333140b5SMarcel Holtmann 1899a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 1900a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 1901a9de9248SMarcel Holtmann break; 1902a9de9248SMarcel Holtmann 1903a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 1904a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 1905a9de9248SMarcel Holtmann break; 1906a9de9248SMarcel Holtmann 1907a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 1908a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 1909a9de9248SMarcel Holtmann break; 1910a9de9248SMarcel Holtmann 1911971e3a4bSAndre Guedes case HCI_OP_READ_LOCAL_EXT_FEATURES: 1912971e3a4bSAndre Guedes hci_cc_read_local_ext_features(hdev, skb); 1913971e3a4bSAndre Guedes break; 1914971e3a4bSAndre Guedes 1915a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 1916a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 1917a9de9248SMarcel Holtmann break; 1918a9de9248SMarcel Holtmann 1919a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 1920a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 1921a9de9248SMarcel Holtmann break; 1922a9de9248SMarcel Holtmann 192323bb5763SJohan Hedberg case HCI_OP_WRITE_CA_TIMEOUT: 192423bb5763SJohan Hedberg hci_cc_write_ca_timeout(hdev, skb); 192523bb5763SJohan Hedberg break; 192623bb5763SJohan Hedberg 1927928abaa7SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_INFO: 1928928abaa7SAndrei Emeltchenko hci_cc_read_local_amp_info(hdev, skb); 1929928abaa7SAndrei Emeltchenko break; 1930928abaa7SAndrei Emeltchenko 1931b0916ea0SJohan Hedberg case HCI_OP_DELETE_STORED_LINK_KEY: 1932b0916ea0SJohan Hedberg hci_cc_delete_stored_link_key(hdev, skb); 1933b0916ea0SJohan Hedberg break; 1934b0916ea0SJohan Hedberg 1935d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_MASK: 1936d5859e22SJohan Hedberg hci_cc_set_event_mask(hdev, skb); 1937d5859e22SJohan Hedberg break; 1938d5859e22SJohan Hedberg 1939d5859e22SJohan Hedberg case HCI_OP_WRITE_INQUIRY_MODE: 1940d5859e22SJohan Hedberg hci_cc_write_inquiry_mode(hdev, skb); 1941d5859e22SJohan Hedberg break; 1942d5859e22SJohan Hedberg 1943d5859e22SJohan Hedberg case HCI_OP_READ_INQ_RSP_TX_POWER: 1944d5859e22SJohan Hedberg hci_cc_read_inq_rsp_tx_power(hdev, skb); 1945d5859e22SJohan Hedberg break; 1946d5859e22SJohan Hedberg 1947d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_FLT: 1948d5859e22SJohan Hedberg hci_cc_set_event_flt(hdev, skb); 1949d5859e22SJohan Hedberg break; 1950d5859e22SJohan Hedberg 1951980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_REPLY: 1952980e1a53SJohan Hedberg hci_cc_pin_code_reply(hdev, skb); 1953980e1a53SJohan Hedberg break; 1954980e1a53SJohan Hedberg 1955980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_NEG_REPLY: 1956980e1a53SJohan Hedberg hci_cc_pin_code_neg_reply(hdev, skb); 1957980e1a53SJohan Hedberg break; 1958980e1a53SJohan Hedberg 1959c35938b2SSzymon Janc case HCI_OP_READ_LOCAL_OOB_DATA: 1960c35938b2SSzymon Janc hci_cc_read_local_oob_data_reply(hdev, skb); 1961c35938b2SSzymon Janc break; 1962c35938b2SSzymon Janc 19636ed58ec5SVille Tervo case HCI_OP_LE_READ_BUFFER_SIZE: 19646ed58ec5SVille Tervo hci_cc_le_read_buffer_size(hdev, skb); 19656ed58ec5SVille Tervo break; 19666ed58ec5SVille Tervo 1967a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_REPLY: 1968a5c29683SJohan Hedberg hci_cc_user_confirm_reply(hdev, skb); 1969a5c29683SJohan Hedberg break; 1970a5c29683SJohan Hedberg 1971a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_NEG_REPLY: 1972a5c29683SJohan Hedberg hci_cc_user_confirm_neg_reply(hdev, skb); 1973a5c29683SJohan Hedberg break; 1974a5c29683SJohan Hedberg 1975eb9d91f5SAndre Guedes case HCI_OP_LE_SET_SCAN_ENABLE: 1976eb9d91f5SAndre Guedes hci_cc_le_set_scan_enable(hdev, skb); 1977eb9d91f5SAndre Guedes break; 1978eb9d91f5SAndre Guedes 1979a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_REPLY: 1980a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_reply(hdev, skb); 1981a7a595f6SVinicius Costa Gomes break; 1982a7a595f6SVinicius Costa Gomes 1983a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_NEG_REPLY: 1984a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_neg_reply(hdev, skb); 1985a7a595f6SVinicius Costa Gomes break; 1986a7a595f6SVinicius Costa Gomes 1987f9b49306SAndre Guedes case HCI_OP_WRITE_LE_HOST_SUPPORTED: 1988f9b49306SAndre Guedes hci_cc_write_le_host_supported(hdev, skb); 1989f9b49306SAndre Guedes break; 1990f9b49306SAndre Guedes 1991a9de9248SMarcel Holtmann default: 1992a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 1993a9de9248SMarcel Holtmann break; 1994a9de9248SMarcel Holtmann } 1995a9de9248SMarcel Holtmann 19966bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 19976bd32326SVille Tervo del_timer(&hdev->cmd_timer); 19986bd32326SVille Tervo 1999a9de9248SMarcel Holtmann if (ev->ncmd) { 2000a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2001a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2002c78ae283SMarcel Holtmann tasklet_schedule(&hdev->cmd_task); 2003a9de9248SMarcel Holtmann } 2004a9de9248SMarcel Holtmann } 2005a9de9248SMarcel Holtmann 2006a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 2007a9de9248SMarcel Holtmann { 2008a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 2009a9de9248SMarcel Holtmann __u16 opcode; 2010a9de9248SMarcel Holtmann 2011a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2012a9de9248SMarcel Holtmann 2013a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2014a9de9248SMarcel Holtmann 2015a9de9248SMarcel Holtmann switch (opcode) { 2016a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 2017a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 2018a9de9248SMarcel Holtmann break; 2019a9de9248SMarcel Holtmann 2020a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 2021a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 2022a9de9248SMarcel Holtmann break; 2023a9de9248SMarcel Holtmann 2024a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 2025a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 2026a9de9248SMarcel Holtmann break; 2027a9de9248SMarcel Holtmann 2028f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 2029f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 2030f8558555SMarcel Holtmann break; 2031f8558555SMarcel Holtmann 2032f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 2033f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 2034f8558555SMarcel Holtmann break; 2035f8558555SMarcel Holtmann 2036a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 2037a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 2038a9de9248SMarcel Holtmann break; 2039a9de9248SMarcel Holtmann 2040769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 2041769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 2042769be974SMarcel Holtmann break; 2043769be974SMarcel Holtmann 2044769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 2045769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 2046769be974SMarcel Holtmann break; 2047769be974SMarcel Holtmann 2048a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 2049a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 2050a9de9248SMarcel Holtmann break; 2051a9de9248SMarcel Holtmann 2052a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 2053a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 2054a9de9248SMarcel Holtmann break; 2055a9de9248SMarcel Holtmann 2056a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 2057a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 2058a9de9248SMarcel Holtmann break; 2059a9de9248SMarcel Holtmann 20608962ee74SJohan Hedberg case HCI_OP_DISCONNECT: 20618962ee74SJohan Hedberg if (ev->status != 0) 20628962ee74SJohan Hedberg mgmt_disconnect_failed(hdev->id); 20638962ee74SJohan Hedberg break; 20648962ee74SJohan Hedberg 2065fcd89c09SVille Tervo case HCI_OP_LE_CREATE_CONN: 2066fcd89c09SVille Tervo hci_cs_le_create_conn(hdev, ev->status); 2067fcd89c09SVille Tervo break; 2068fcd89c09SVille Tervo 2069a7a595f6SVinicius Costa Gomes case HCI_OP_LE_START_ENC: 2070a7a595f6SVinicius Costa Gomes hci_cs_le_start_enc(hdev, ev->status); 2071a7a595f6SVinicius Costa Gomes break; 2072a7a595f6SVinicius Costa Gomes 2073a9de9248SMarcel Holtmann default: 2074a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 2075a9de9248SMarcel Holtmann break; 2076a9de9248SMarcel Holtmann } 2077a9de9248SMarcel Holtmann 20786bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 20796bd32326SVille Tervo del_timer(&hdev->cmd_timer); 20806bd32326SVille Tervo 208110572132SGustavo F. Padovan if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2082a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2083a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2084c78ae283SMarcel Holtmann tasklet_schedule(&hdev->cmd_task); 2085a9de9248SMarcel Holtmann } 2086a9de9248SMarcel Holtmann } 2087a9de9248SMarcel Holtmann 2088a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2089a9de9248SMarcel Holtmann { 2090a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 2091a9de9248SMarcel Holtmann struct hci_conn *conn; 2092a9de9248SMarcel Holtmann 2093a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2094a9de9248SMarcel Holtmann 2095a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2096a9de9248SMarcel Holtmann 2097a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2098a9de9248SMarcel Holtmann if (conn) { 2099a9de9248SMarcel Holtmann if (!ev->status) { 2100a9de9248SMarcel Holtmann if (ev->role) 2101a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_MASTER; 2102a9de9248SMarcel Holtmann else 2103a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_MASTER; 2104a9de9248SMarcel Holtmann } 2105a9de9248SMarcel Holtmann 2106a9de9248SMarcel Holtmann clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend); 2107a9de9248SMarcel Holtmann 2108a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 2109a9de9248SMarcel Holtmann } 2110a9de9248SMarcel Holtmann 2111a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2112a9de9248SMarcel Holtmann } 2113a9de9248SMarcel Holtmann 21141da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 21151da177e4SLinus Torvalds { 2116a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 21171ebb9252SMarcel Holtmann __le16 *ptr; 21181da177e4SLinus Torvalds int i; 21191da177e4SLinus Torvalds 21201da177e4SLinus Torvalds skb_pull(skb, sizeof(*ev)); 21211da177e4SLinus Torvalds 21221da177e4SLinus Torvalds BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 21231da177e4SLinus Torvalds 21241da177e4SLinus Torvalds if (skb->len < ev->num_hndl * 4) { 21251da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 21261da177e4SLinus Torvalds return; 21271da177e4SLinus Torvalds } 21281da177e4SLinus Torvalds 21291da177e4SLinus Torvalds tasklet_disable(&hdev->tx_task); 21301da177e4SLinus Torvalds 21311ebb9252SMarcel Holtmann for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) { 21321da177e4SLinus Torvalds struct hci_conn *conn; 21331da177e4SLinus Torvalds __u16 handle, count; 21341da177e4SLinus Torvalds 213583985319SHarvey Harrison handle = get_unaligned_le16(ptr++); 213683985319SHarvey Harrison count = get_unaligned_le16(ptr++); 21371da177e4SLinus Torvalds 21381da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 21391da177e4SLinus Torvalds if (conn) { 21401da177e4SLinus Torvalds conn->sent -= count; 21411da177e4SLinus Torvalds 21425b7f9909SMarcel Holtmann if (conn->type == ACL_LINK) { 214370f23020SAndrei Emeltchenko hdev->acl_cnt += count; 214470f23020SAndrei Emeltchenko if (hdev->acl_cnt > hdev->acl_pkts) 21451da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 21466ed58ec5SVille Tervo } else if (conn->type == LE_LINK) { 21476ed58ec5SVille Tervo if (hdev->le_pkts) { 21486ed58ec5SVille Tervo hdev->le_cnt += count; 21496ed58ec5SVille Tervo if (hdev->le_cnt > hdev->le_pkts) 21506ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 21516ed58ec5SVille Tervo } else { 21526ed58ec5SVille Tervo hdev->acl_cnt += count; 21536ed58ec5SVille Tervo if (hdev->acl_cnt > hdev->acl_pkts) 21546ed58ec5SVille Tervo hdev->acl_cnt = hdev->acl_pkts; 21556ed58ec5SVille Tervo } 21565b7f9909SMarcel Holtmann } else { 215770f23020SAndrei Emeltchenko hdev->sco_cnt += count; 215870f23020SAndrei Emeltchenko if (hdev->sco_cnt > hdev->sco_pkts) 21595b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 21601da177e4SLinus Torvalds } 21611da177e4SLinus Torvalds } 21621da177e4SLinus Torvalds } 2163a9de9248SMarcel Holtmann 2164c78ae283SMarcel Holtmann tasklet_schedule(&hdev->tx_task); 21651da177e4SLinus Torvalds 21661da177e4SLinus Torvalds tasklet_enable(&hdev->tx_task); 21671da177e4SLinus Torvalds } 21681da177e4SLinus Torvalds 216904837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 21701da177e4SLinus Torvalds { 2171a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 217204837f64SMarcel Holtmann struct hci_conn *conn; 21731da177e4SLinus Torvalds 21741da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 21751da177e4SLinus Torvalds 21761da177e4SLinus Torvalds hci_dev_lock(hdev); 21771da177e4SLinus Torvalds 217804837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 217904837f64SMarcel Holtmann if (conn) { 218004837f64SMarcel Holtmann conn->mode = ev->mode; 218104837f64SMarcel Holtmann conn->interval = __le16_to_cpu(ev->interval); 218204837f64SMarcel Holtmann 218304837f64SMarcel Holtmann if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) { 218404837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 218504837f64SMarcel Holtmann conn->power_save = 1; 218604837f64SMarcel Holtmann else 218704837f64SMarcel Holtmann conn->power_save = 0; 218804837f64SMarcel Holtmann } 2189e73439d8SMarcel Holtmann 2190e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 2191e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 219204837f64SMarcel Holtmann } 219304837f64SMarcel Holtmann 219404837f64SMarcel Holtmann hci_dev_unlock(hdev); 219504837f64SMarcel Holtmann } 219604837f64SMarcel Holtmann 21971da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 21981da177e4SLinus Torvalds { 2199052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 2200052b30b0SMarcel Holtmann struct hci_conn *conn; 2201052b30b0SMarcel Holtmann 2202a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2203052b30b0SMarcel Holtmann 2204052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2205052b30b0SMarcel Holtmann 2206052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2207b6f98044SWaldemar Rymarkiewicz if (!conn) 2208b6f98044SWaldemar Rymarkiewicz goto unlock; 2209b6f98044SWaldemar Rymarkiewicz 2210b6f98044SWaldemar Rymarkiewicz if (conn->state == BT_CONNECTED) { 2211052b30b0SMarcel Holtmann hci_conn_hold(conn); 2212052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 2213052b30b0SMarcel Holtmann hci_conn_put(conn); 2214052b30b0SMarcel Holtmann } 2215052b30b0SMarcel Holtmann 221603b555e1SJohan Hedberg if (!test_bit(HCI_PAIRABLE, &hdev->flags)) 221703b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 221803b555e1SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 2219582fbe9eSJohan Hedberg else if (test_bit(HCI_MGMT, &hdev->flags)) { 2220a770bb5aSWaldemar Rymarkiewicz u8 secure; 2221a770bb5aSWaldemar Rymarkiewicz 2222a770bb5aSWaldemar Rymarkiewicz if (conn->pending_sec_level == BT_SECURITY_HIGH) 2223a770bb5aSWaldemar Rymarkiewicz secure = 1; 2224a770bb5aSWaldemar Rymarkiewicz else 2225a770bb5aSWaldemar Rymarkiewicz secure = 0; 2226a770bb5aSWaldemar Rymarkiewicz 2227a770bb5aSWaldemar Rymarkiewicz mgmt_pin_code_request(hdev->id, &ev->bdaddr, secure); 2228a770bb5aSWaldemar Rymarkiewicz } 2229980e1a53SJohan Hedberg 2230b6f98044SWaldemar Rymarkiewicz unlock: 2231052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 22321da177e4SLinus Torvalds } 22331da177e4SLinus Torvalds 22341da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 22351da177e4SLinus Torvalds { 223655ed8ca1SJohan Hedberg struct hci_ev_link_key_req *ev = (void *) skb->data; 223755ed8ca1SJohan Hedberg struct hci_cp_link_key_reply cp; 223855ed8ca1SJohan Hedberg struct hci_conn *conn; 223955ed8ca1SJohan Hedberg struct link_key *key; 224055ed8ca1SJohan Hedberg 2241a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 224255ed8ca1SJohan Hedberg 224355ed8ca1SJohan Hedberg if (!test_bit(HCI_LINK_KEYS, &hdev->flags)) 224455ed8ca1SJohan Hedberg return; 224555ed8ca1SJohan Hedberg 224655ed8ca1SJohan Hedberg hci_dev_lock(hdev); 224755ed8ca1SJohan Hedberg 224855ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, &ev->bdaddr); 224955ed8ca1SJohan Hedberg if (!key) { 225055ed8ca1SJohan Hedberg BT_DBG("%s link key not found for %s", hdev->name, 225155ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 225255ed8ca1SJohan Hedberg goto not_found; 225355ed8ca1SJohan Hedberg } 225455ed8ca1SJohan Hedberg 225555ed8ca1SJohan Hedberg BT_DBG("%s found key type %u for %s", hdev->name, key->type, 225655ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 225755ed8ca1SJohan Hedberg 2258b6020ba0SWaldemar Rymarkiewicz if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) && 2259b6020ba0SWaldemar Rymarkiewicz key->type == HCI_LK_DEBUG_COMBINATION) { 226055ed8ca1SJohan Hedberg BT_DBG("%s ignoring debug key", hdev->name); 226155ed8ca1SJohan Hedberg goto not_found; 226255ed8ca1SJohan Hedberg } 226355ed8ca1SJohan Hedberg 226455ed8ca1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 226560b83f57SWaldemar Rymarkiewicz if (conn) { 226660b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_UNAUTH_COMBINATION && 226760b83f57SWaldemar Rymarkiewicz conn->auth_type != 0xff && 226860b83f57SWaldemar Rymarkiewicz (conn->auth_type & 0x01)) { 226955ed8ca1SJohan Hedberg BT_DBG("%s ignoring unauthenticated key", hdev->name); 227055ed8ca1SJohan Hedberg goto not_found; 227155ed8ca1SJohan Hedberg } 227255ed8ca1SJohan Hedberg 227360b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && 227460b83f57SWaldemar Rymarkiewicz conn->pending_sec_level == BT_SECURITY_HIGH) { 227560b83f57SWaldemar Rymarkiewicz BT_DBG("%s ignoring key unauthenticated for high \ 227660b83f57SWaldemar Rymarkiewicz security", hdev->name); 227760b83f57SWaldemar Rymarkiewicz goto not_found; 227860b83f57SWaldemar Rymarkiewicz } 227960b83f57SWaldemar Rymarkiewicz 228060b83f57SWaldemar Rymarkiewicz conn->key_type = key->type; 228160b83f57SWaldemar Rymarkiewicz conn->pin_length = key->pin_len; 228260b83f57SWaldemar Rymarkiewicz } 228360b83f57SWaldemar Rymarkiewicz 228455ed8ca1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 228555ed8ca1SJohan Hedberg memcpy(cp.link_key, key->val, 16); 228655ed8ca1SJohan Hedberg 228755ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 228855ed8ca1SJohan Hedberg 228955ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 229055ed8ca1SJohan Hedberg 229155ed8ca1SJohan Hedberg return; 229255ed8ca1SJohan Hedberg 229355ed8ca1SJohan Hedberg not_found: 229455ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 229555ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 22961da177e4SLinus Torvalds } 22971da177e4SLinus Torvalds 22981da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 22991da177e4SLinus Torvalds { 2300052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 2301052b30b0SMarcel Holtmann struct hci_conn *conn; 230255ed8ca1SJohan Hedberg u8 pin_len = 0; 2303052b30b0SMarcel Holtmann 2304a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2305052b30b0SMarcel Holtmann 2306052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2307052b30b0SMarcel Holtmann 2308052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2309052b30b0SMarcel Holtmann if (conn) { 2310052b30b0SMarcel Holtmann hci_conn_hold(conn); 2311052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2312980e1a53SJohan Hedberg pin_len = conn->pin_length; 231313d39315SWaldemar Rymarkiewicz 231413d39315SWaldemar Rymarkiewicz if (ev->key_type != HCI_LK_CHANGED_COMBINATION) 231513d39315SWaldemar Rymarkiewicz conn->key_type = ev->key_type; 231613d39315SWaldemar Rymarkiewicz 2317052b30b0SMarcel Holtmann hci_conn_put(conn); 2318052b30b0SMarcel Holtmann } 2319052b30b0SMarcel Holtmann 232055ed8ca1SJohan Hedberg if (test_bit(HCI_LINK_KEYS, &hdev->flags)) 2321d25e28abSJohan Hedberg hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, 232255ed8ca1SJohan Hedberg ev->key_type, pin_len); 232355ed8ca1SJohan Hedberg 2324052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 23251da177e4SLinus Torvalds } 23261da177e4SLinus Torvalds 232704837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 232804837f64SMarcel Holtmann { 2329a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 233004837f64SMarcel Holtmann struct hci_conn *conn; 233104837f64SMarcel Holtmann 233204837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 233304837f64SMarcel Holtmann 233404837f64SMarcel Holtmann hci_dev_lock(hdev); 233504837f64SMarcel Holtmann 233604837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 23371da177e4SLinus Torvalds if (conn && !ev->status) { 23381da177e4SLinus Torvalds struct inquiry_entry *ie; 23391da177e4SLinus Torvalds 2340cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2341cc11b9c1SAndrei Emeltchenko if (ie) { 23421da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 23431da177e4SLinus Torvalds ie->timestamp = jiffies; 23441da177e4SLinus Torvalds } 23451da177e4SLinus Torvalds } 23461da177e4SLinus Torvalds 23471da177e4SLinus Torvalds hci_dev_unlock(hdev); 23481da177e4SLinus Torvalds } 23491da177e4SLinus Torvalds 2350a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2351a8746417SMarcel Holtmann { 2352a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 2353a8746417SMarcel Holtmann struct hci_conn *conn; 2354a8746417SMarcel Holtmann 2355a8746417SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2356a8746417SMarcel Holtmann 2357a8746417SMarcel Holtmann hci_dev_lock(hdev); 2358a8746417SMarcel Holtmann 2359a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2360a8746417SMarcel Holtmann if (conn && !ev->status) 2361a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 2362a8746417SMarcel Holtmann 2363a8746417SMarcel Holtmann hci_dev_unlock(hdev); 2364a8746417SMarcel Holtmann } 2365a8746417SMarcel Holtmann 236685a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 236785a1e930SMarcel Holtmann { 2368a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 236985a1e930SMarcel Holtmann struct inquiry_entry *ie; 237085a1e930SMarcel Holtmann 237185a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 237285a1e930SMarcel Holtmann 237385a1e930SMarcel Holtmann hci_dev_lock(hdev); 237485a1e930SMarcel Holtmann 2375cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2376cc11b9c1SAndrei Emeltchenko if (ie) { 237785a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 237885a1e930SMarcel Holtmann ie->timestamp = jiffies; 237985a1e930SMarcel Holtmann } 238085a1e930SMarcel Holtmann 238185a1e930SMarcel Holtmann hci_dev_unlock(hdev); 238285a1e930SMarcel Holtmann } 238385a1e930SMarcel Holtmann 2384a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb) 2385a9de9248SMarcel Holtmann { 2386a9de9248SMarcel Holtmann struct inquiry_data data; 2387a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2388a9de9248SMarcel Holtmann 2389a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2390a9de9248SMarcel Holtmann 2391a9de9248SMarcel Holtmann if (!num_rsp) 2392a9de9248SMarcel Holtmann return; 2393a9de9248SMarcel Holtmann 2394a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2395a9de9248SMarcel Holtmann 2396314b2381SJohan Hedberg if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) { 2397314b2381SJohan Hedberg 2398314b2381SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 2399314b2381SJohan Hedberg mgmt_discovering(hdev->id, 1); 2400314b2381SJohan Hedberg } 2401314b2381SJohan Hedberg 2402a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 2403138d22efSSzymon Janc struct inquiry_info_with_rssi_and_pscan_mode *info; 2404138d22efSSzymon Janc info = (void *) (skb->data + 1); 2405a9de9248SMarcel Holtmann 2406e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2407a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2408a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2409a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2410a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 2411a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2412a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2413a9de9248SMarcel Holtmann data.rssi = info->rssi; 241441a96212SMarcel Holtmann data.ssp_mode = 0x00; 2415a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 2416e17acd40SJohan Hedberg mgmt_device_found(hdev->id, &info->bdaddr, 2417e17acd40SJohan Hedberg info->dev_class, info->rssi, 2418e17acd40SJohan Hedberg NULL); 2419a9de9248SMarcel Holtmann } 2420a9de9248SMarcel Holtmann } else { 2421a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 2422a9de9248SMarcel Holtmann 2423e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2424a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2425a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2426a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2427a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2428a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2429a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2430a9de9248SMarcel Holtmann data.rssi = info->rssi; 243141a96212SMarcel Holtmann data.ssp_mode = 0x00; 2432a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 2433e17acd40SJohan Hedberg mgmt_device_found(hdev->id, &info->bdaddr, 2434e17acd40SJohan Hedberg info->dev_class, info->rssi, 2435e17acd40SJohan Hedberg NULL); 2436a9de9248SMarcel Holtmann } 2437a9de9248SMarcel Holtmann } 2438a9de9248SMarcel Holtmann 2439a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2440a9de9248SMarcel Holtmann } 2441a9de9248SMarcel Holtmann 2442a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 2443a9de9248SMarcel Holtmann { 244441a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 244541a96212SMarcel Holtmann struct hci_conn *conn; 244641a96212SMarcel Holtmann 2447a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 244841a96212SMarcel Holtmann 244941a96212SMarcel Holtmann hci_dev_lock(hdev); 245041a96212SMarcel Holtmann 245141a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2452ccd556feSJohan Hedberg if (!conn) 2453ccd556feSJohan Hedberg goto unlock; 2454ccd556feSJohan Hedberg 2455769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 245641a96212SMarcel Holtmann struct inquiry_entry *ie; 245741a96212SMarcel Holtmann 2458cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2459cc11b9c1SAndrei Emeltchenko if (ie) 246041a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 246141a96212SMarcel Holtmann 246241a96212SMarcel Holtmann conn->ssp_mode = (ev->features[0] & 0x01); 246341a96212SMarcel Holtmann } 246441a96212SMarcel Holtmann 2465ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2466ccd556feSJohan Hedberg goto unlock; 2467ccd556feSJohan Hedberg 2468127178d2SJohan Hedberg if (!ev->status) { 2469127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2470127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2471127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2472127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2473127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2474127178d2SJohan Hedberg } 2475392599b9SJohan Hedberg 2476127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2477769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2478769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2479769be974SMarcel Holtmann hci_conn_put(conn); 2480769be974SMarcel Holtmann } 2481769be974SMarcel Holtmann 2482ccd556feSJohan Hedberg unlock: 248341a96212SMarcel Holtmann hci_dev_unlock(hdev); 2484a9de9248SMarcel Holtmann } 2485a9de9248SMarcel Holtmann 2486a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2487a9de9248SMarcel Holtmann { 2488b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 2489b6a0dc82SMarcel Holtmann struct hci_conn *conn; 2490b6a0dc82SMarcel Holtmann 2491b6a0dc82SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2492b6a0dc82SMarcel Holtmann 2493b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 2494b6a0dc82SMarcel Holtmann 2495b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 24969dc0a3afSMarcel Holtmann if (!conn) { 24979dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 24989dc0a3afSMarcel Holtmann goto unlock; 24999dc0a3afSMarcel Holtmann 25009dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 2501b6a0dc82SMarcel Holtmann if (!conn) 2502b6a0dc82SMarcel Holtmann goto unlock; 2503b6a0dc82SMarcel Holtmann 25049dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 25059dc0a3afSMarcel Holtmann } 25069dc0a3afSMarcel Holtmann 2507732547f9SMarcel Holtmann switch (ev->status) { 2508732547f9SMarcel Holtmann case 0x00: 2509732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 2510732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 2511732547f9SMarcel Holtmann 25129eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 2513732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 2514732547f9SMarcel Holtmann break; 2515732547f9SMarcel Holtmann 2516705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 2517732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 25181038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 2519732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 2520732547f9SMarcel Holtmann if (conn->out && conn->attempt < 2) { 2521efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 2522efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 2523efc7688bSMarcel Holtmann hci_setup_sync(conn, conn->link->handle); 2524efc7688bSMarcel Holtmann goto unlock; 2525efc7688bSMarcel Holtmann } 2526732547f9SMarcel Holtmann /* fall through */ 2527efc7688bSMarcel Holtmann 2528732547f9SMarcel Holtmann default: 2529b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 2530732547f9SMarcel Holtmann break; 2531732547f9SMarcel Holtmann } 2532b6a0dc82SMarcel Holtmann 2533b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2534b6a0dc82SMarcel Holtmann if (ev->status) 2535b6a0dc82SMarcel Holtmann hci_conn_del(conn); 2536b6a0dc82SMarcel Holtmann 2537b6a0dc82SMarcel Holtmann unlock: 2538b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 2539a9de9248SMarcel Holtmann } 2540a9de9248SMarcel Holtmann 2541a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) 2542a9de9248SMarcel Holtmann { 2543a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2544a9de9248SMarcel Holtmann } 2545a9de9248SMarcel Holtmann 254604837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) 254704837f64SMarcel Holtmann { 2548a9de9248SMarcel Holtmann struct hci_ev_sniff_subrate *ev = (void *) skb->data; 254904837f64SMarcel Holtmann 255004837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 255104837f64SMarcel Holtmann } 255204837f64SMarcel Holtmann 2553a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 2554a9de9248SMarcel Holtmann { 2555a9de9248SMarcel Holtmann struct inquiry_data data; 2556a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 2557a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2558a9de9248SMarcel Holtmann 2559a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2560a9de9248SMarcel Holtmann 2561a9de9248SMarcel Holtmann if (!num_rsp) 2562a9de9248SMarcel Holtmann return; 2563a9de9248SMarcel Holtmann 2564314b2381SJohan Hedberg if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) { 2565314b2381SJohan Hedberg 2566314b2381SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 2567314b2381SJohan Hedberg mgmt_discovering(hdev->id, 1); 2568314b2381SJohan Hedberg } 2569314b2381SJohan Hedberg 2570a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2571a9de9248SMarcel Holtmann 2572e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2573a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2574a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2575a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2576a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2577a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2578a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2579a9de9248SMarcel Holtmann data.rssi = info->rssi; 258041a96212SMarcel Holtmann data.ssp_mode = 0x01; 2581a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 2582e17acd40SJohan Hedberg mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class, 2583e17acd40SJohan Hedberg info->rssi, info->data); 2584a9de9248SMarcel Holtmann } 2585a9de9248SMarcel Holtmann 2586a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2587a9de9248SMarcel Holtmann } 2588a9de9248SMarcel Holtmann 258917fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn) 259017fa4b9dSJohan Hedberg { 259117fa4b9dSJohan Hedberg /* If remote requests dedicated bonding follow that lead */ 259217fa4b9dSJohan Hedberg if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) { 259317fa4b9dSJohan Hedberg /* If both remote and local IO capabilities allow MITM 259417fa4b9dSJohan Hedberg * protection then require it, otherwise don't */ 259517fa4b9dSJohan Hedberg if (conn->remote_cap == 0x03 || conn->io_capability == 0x03) 259617fa4b9dSJohan Hedberg return 0x02; 259717fa4b9dSJohan Hedberg else 259817fa4b9dSJohan Hedberg return 0x03; 259917fa4b9dSJohan Hedberg } 260017fa4b9dSJohan Hedberg 260117fa4b9dSJohan Hedberg /* If remote requests no-bonding follow that lead */ 260217fa4b9dSJohan Hedberg if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01) 260358797bf7SWaldemar Rymarkiewicz return conn->remote_auth | (conn->auth_type & 0x01); 260417fa4b9dSJohan Hedberg 260517fa4b9dSJohan Hedberg return conn->auth_type; 260617fa4b9dSJohan Hedberg } 260717fa4b9dSJohan Hedberg 26080493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 26090493684eSMarcel Holtmann { 26100493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 26110493684eSMarcel Holtmann struct hci_conn *conn; 26120493684eSMarcel Holtmann 26130493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 26140493684eSMarcel Holtmann 26150493684eSMarcel Holtmann hci_dev_lock(hdev); 26160493684eSMarcel Holtmann 26170493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 261803b555e1SJohan Hedberg if (!conn) 261903b555e1SJohan Hedberg goto unlock; 262003b555e1SJohan Hedberg 26210493684eSMarcel Holtmann hci_conn_hold(conn); 26220493684eSMarcel Holtmann 262303b555e1SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->flags)) 262403b555e1SJohan Hedberg goto unlock; 262503b555e1SJohan Hedberg 262603b555e1SJohan Hedberg if (test_bit(HCI_PAIRABLE, &hdev->flags) || 262703b555e1SJohan Hedberg (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 262817fa4b9dSJohan Hedberg struct hci_cp_io_capability_reply cp; 262917fa4b9dSJohan Hedberg 263017fa4b9dSJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 263117fa4b9dSJohan Hedberg cp.capability = conn->io_capability; 26327cbc9bd9SJohan Hedberg conn->auth_type = hci_get_auth_req(conn); 26337cbc9bd9SJohan Hedberg cp.authentication = conn->auth_type; 263417fa4b9dSJohan Hedberg 2635ce85ee13SSzymon Janc if ((conn->out == 0x01 || conn->remote_oob == 0x01) && 2636ce85ee13SSzymon Janc hci_find_remote_oob_data(hdev, &conn->dst)) 2637ce85ee13SSzymon Janc cp.oob_data = 0x01; 2638ce85ee13SSzymon Janc else 2639ce85ee13SSzymon Janc cp.oob_data = 0x00; 2640ce85ee13SSzymon Janc 264117fa4b9dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, 264217fa4b9dSJohan Hedberg sizeof(cp), &cp); 264303b555e1SJohan Hedberg } else { 264403b555e1SJohan Hedberg struct hci_cp_io_capability_neg_reply cp; 264503b555e1SJohan Hedberg 264603b555e1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 2647be77159cSJohan Hedberg cp.reason = 0x18; /* Pairing not allowed */ 264803b555e1SJohan Hedberg 264903b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 265003b555e1SJohan Hedberg sizeof(cp), &cp); 265103b555e1SJohan Hedberg } 265203b555e1SJohan Hedberg 265303b555e1SJohan Hedberg unlock: 265403b555e1SJohan Hedberg hci_dev_unlock(hdev); 265503b555e1SJohan Hedberg } 265603b555e1SJohan Hedberg 265703b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 265803b555e1SJohan Hedberg { 265903b555e1SJohan Hedberg struct hci_ev_io_capa_reply *ev = (void *) skb->data; 266003b555e1SJohan Hedberg struct hci_conn *conn; 266103b555e1SJohan Hedberg 266203b555e1SJohan Hedberg BT_DBG("%s", hdev->name); 266303b555e1SJohan Hedberg 266403b555e1SJohan Hedberg hci_dev_lock(hdev); 266503b555e1SJohan Hedberg 266603b555e1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 266703b555e1SJohan Hedberg if (!conn) 266803b555e1SJohan Hedberg goto unlock; 266903b555e1SJohan Hedberg 267003b555e1SJohan Hedberg conn->remote_cap = ev->capability; 267103b555e1SJohan Hedberg conn->remote_oob = ev->oob_data; 267203b555e1SJohan Hedberg conn->remote_auth = ev->authentication; 267303b555e1SJohan Hedberg 267403b555e1SJohan Hedberg unlock: 26750493684eSMarcel Holtmann hci_dev_unlock(hdev); 26760493684eSMarcel Holtmann } 26770493684eSMarcel Holtmann 2678a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev, 2679a5c29683SJohan Hedberg struct sk_buff *skb) 2680a5c29683SJohan Hedberg { 2681a5c29683SJohan Hedberg struct hci_ev_user_confirm_req *ev = (void *) skb->data; 268255bc1a37SJohan Hedberg int loc_mitm, rem_mitm, confirm_hint = 0; 26837a828908SJohan Hedberg struct hci_conn *conn; 2684a5c29683SJohan Hedberg 2685a5c29683SJohan Hedberg BT_DBG("%s", hdev->name); 2686a5c29683SJohan Hedberg 2687a5c29683SJohan Hedberg hci_dev_lock(hdev); 2688a5c29683SJohan Hedberg 26897a828908SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->flags)) 26907a828908SJohan Hedberg goto unlock; 26917a828908SJohan Hedberg 26927a828908SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 26937a828908SJohan Hedberg if (!conn) 26947a828908SJohan Hedberg goto unlock; 26957a828908SJohan Hedberg 26967a828908SJohan Hedberg loc_mitm = (conn->auth_type & 0x01); 26977a828908SJohan Hedberg rem_mitm = (conn->remote_auth & 0x01); 26987a828908SJohan Hedberg 26997a828908SJohan Hedberg /* If we require MITM but the remote device can't provide that 27007a828908SJohan Hedberg * (it has NoInputNoOutput) then reject the confirmation 27017a828908SJohan Hedberg * request. The only exception is when we're dedicated bonding 27027a828908SJohan Hedberg * initiators (connect_cfm_cb set) since then we always have the MITM 27037a828908SJohan Hedberg * bit set. */ 27047a828908SJohan Hedberg if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) { 27057a828908SJohan Hedberg BT_DBG("Rejecting request: remote device can't provide MITM"); 27067a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, 27077a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 27087a828908SJohan Hedberg goto unlock; 27097a828908SJohan Hedberg } 27107a828908SJohan Hedberg 27117a828908SJohan Hedberg /* If no side requires MITM protection; auto-accept */ 27127a828908SJohan Hedberg if ((!loc_mitm || conn->remote_cap == 0x03) && 27137a828908SJohan Hedberg (!rem_mitm || conn->io_capability == 0x03)) { 271455bc1a37SJohan Hedberg 271555bc1a37SJohan Hedberg /* If we're not the initiators request authorization to 271655bc1a37SJohan Hedberg * proceed from user space (mgmt_user_confirm with 271755bc1a37SJohan Hedberg * confirm_hint set to 1). */ 271855bc1a37SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { 271955bc1a37SJohan Hedberg BT_DBG("Confirming auto-accept as acceptor"); 272055bc1a37SJohan Hedberg confirm_hint = 1; 272155bc1a37SJohan Hedberg goto confirm; 272255bc1a37SJohan Hedberg } 272355bc1a37SJohan Hedberg 27249f61656aSJohan Hedberg BT_DBG("Auto-accept of user confirmation with %ums delay", 27259f61656aSJohan Hedberg hdev->auto_accept_delay); 27269f61656aSJohan Hedberg 27279f61656aSJohan Hedberg if (hdev->auto_accept_delay > 0) { 27289f61656aSJohan Hedberg int delay = msecs_to_jiffies(hdev->auto_accept_delay); 27299f61656aSJohan Hedberg mod_timer(&conn->auto_accept_timer, jiffies + delay); 27309f61656aSJohan Hedberg goto unlock; 27319f61656aSJohan Hedberg } 27329f61656aSJohan Hedberg 27337a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, 27347a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 27357a828908SJohan Hedberg goto unlock; 27367a828908SJohan Hedberg } 27377a828908SJohan Hedberg 273855bc1a37SJohan Hedberg confirm: 273955bc1a37SJohan Hedberg mgmt_user_confirm_request(hdev->id, &ev->bdaddr, ev->passkey, 274055bc1a37SJohan Hedberg confirm_hint); 2741a5c29683SJohan Hedberg 27427a828908SJohan Hedberg unlock: 2743a5c29683SJohan Hedberg hci_dev_unlock(hdev); 2744a5c29683SJohan Hedberg } 2745a5c29683SJohan Hedberg 27460493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 27470493684eSMarcel Holtmann { 27480493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 27490493684eSMarcel Holtmann struct hci_conn *conn; 27500493684eSMarcel Holtmann 27510493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 27520493684eSMarcel Holtmann 27530493684eSMarcel Holtmann hci_dev_lock(hdev); 27540493684eSMarcel Holtmann 27550493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 27562a611692SJohan Hedberg if (!conn) 27572a611692SJohan Hedberg goto unlock; 27582a611692SJohan Hedberg 27592a611692SJohan Hedberg /* To avoid duplicate auth_failed events to user space we check 27602a611692SJohan Hedberg * the HCI_CONN_AUTH_PEND flag which will be set if we 27612a611692SJohan Hedberg * initiated the authentication. A traditional auth_complete 27622a611692SJohan Hedberg * event gets always produced as initiator and is also mapped to 27632a611692SJohan Hedberg * the mgmt_auth_failed event */ 27642a611692SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0) 27652a611692SJohan Hedberg mgmt_auth_failed(hdev->id, &conn->dst, ev->status); 27662a611692SJohan Hedberg 27670493684eSMarcel Holtmann hci_conn_put(conn); 27680493684eSMarcel Holtmann 27692a611692SJohan Hedberg unlock: 27700493684eSMarcel Holtmann hci_dev_unlock(hdev); 27710493684eSMarcel Holtmann } 27720493684eSMarcel Holtmann 277341a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 277441a96212SMarcel Holtmann { 277541a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 277641a96212SMarcel Holtmann struct inquiry_entry *ie; 277741a96212SMarcel Holtmann 277841a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 277941a96212SMarcel Holtmann 278041a96212SMarcel Holtmann hci_dev_lock(hdev); 278141a96212SMarcel Holtmann 2782cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2783cc11b9c1SAndrei Emeltchenko if (ie) 278441a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 278541a96212SMarcel Holtmann 278641a96212SMarcel Holtmann hci_dev_unlock(hdev); 278741a96212SMarcel Holtmann } 278841a96212SMarcel Holtmann 27892763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev, 27902763eda6SSzymon Janc struct sk_buff *skb) 27912763eda6SSzymon Janc { 27922763eda6SSzymon Janc struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; 27932763eda6SSzymon Janc struct oob_data *data; 27942763eda6SSzymon Janc 27952763eda6SSzymon Janc BT_DBG("%s", hdev->name); 27962763eda6SSzymon Janc 27972763eda6SSzymon Janc hci_dev_lock(hdev); 27982763eda6SSzymon Janc 2799e1ba1f15SSzymon Janc if (!test_bit(HCI_MGMT, &hdev->flags)) 2800e1ba1f15SSzymon Janc goto unlock; 2801e1ba1f15SSzymon Janc 28022763eda6SSzymon Janc data = hci_find_remote_oob_data(hdev, &ev->bdaddr); 28032763eda6SSzymon Janc if (data) { 28042763eda6SSzymon Janc struct hci_cp_remote_oob_data_reply cp; 28052763eda6SSzymon Janc 28062763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 28072763eda6SSzymon Janc memcpy(cp.hash, data->hash, sizeof(cp.hash)); 28082763eda6SSzymon Janc memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); 28092763eda6SSzymon Janc 28102763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), 28112763eda6SSzymon Janc &cp); 28122763eda6SSzymon Janc } else { 28132763eda6SSzymon Janc struct hci_cp_remote_oob_data_neg_reply cp; 28142763eda6SSzymon Janc 28152763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 28162763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), 28172763eda6SSzymon Janc &cp); 28182763eda6SSzymon Janc } 28192763eda6SSzymon Janc 2820e1ba1f15SSzymon Janc unlock: 28212763eda6SSzymon Janc hci_dev_unlock(hdev); 28222763eda6SSzymon Janc } 28232763eda6SSzymon Janc 2824fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2825fcd89c09SVille Tervo { 2826fcd89c09SVille Tervo struct hci_ev_le_conn_complete *ev = (void *) skb->data; 2827fcd89c09SVille Tervo struct hci_conn *conn; 2828fcd89c09SVille Tervo 2829fcd89c09SVille Tervo BT_DBG("%s status %d", hdev->name, ev->status); 2830fcd89c09SVille Tervo 2831fcd89c09SVille Tervo hci_dev_lock(hdev); 2832fcd89c09SVille Tervo 2833fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr); 2834b62f328bSVille Tervo if (!conn) { 2835b62f328bSVille Tervo conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); 2836b62f328bSVille Tervo if (!conn) { 2837b62f328bSVille Tervo BT_ERR("No memory for new connection"); 2838b62f328bSVille Tervo hci_dev_unlock(hdev); 2839b62f328bSVille Tervo return; 2840b62f328bSVille Tervo } 284129b7988aSAndre Guedes 284229b7988aSAndre Guedes conn->dst_type = ev->bdaddr_type; 2843b62f328bSVille Tervo } 2844fcd89c09SVille Tervo 2845fcd89c09SVille Tervo if (ev->status) { 284683bc71b4SVinicius Costa Gomes mgmt_connect_failed(hdev->id, &ev->bdaddr, ev->status); 2847fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 2848fcd89c09SVille Tervo conn->state = BT_CLOSED; 2849fcd89c09SVille Tervo hci_conn_del(conn); 2850fcd89c09SVille Tervo goto unlock; 2851fcd89c09SVille Tervo } 2852fcd89c09SVille Tervo 2853cfafccf7SVinicius Costa Gomes mgmt_connected(hdev->id, &ev->bdaddr, conn->type); 285483bc71b4SVinicius Costa Gomes 28557b5c0d52SVinicius Costa Gomes conn->sec_level = BT_SECURITY_LOW; 2856fcd89c09SVille Tervo conn->handle = __le16_to_cpu(ev->handle); 2857fcd89c09SVille Tervo conn->state = BT_CONNECTED; 2858fcd89c09SVille Tervo 2859fcd89c09SVille Tervo hci_conn_hold_device(conn); 2860fcd89c09SVille Tervo hci_conn_add_sysfs(conn); 2861fcd89c09SVille Tervo 2862fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 2863fcd89c09SVille Tervo 2864fcd89c09SVille Tervo unlock: 2865fcd89c09SVille Tervo hci_dev_unlock(hdev); 2866fcd89c09SVille Tervo } 2867fcd89c09SVille Tervo 28689aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev, 28699aa04c91SAndre Guedes struct sk_buff *skb) 28709aa04c91SAndre Guedes { 2871e95beb41SAndre Guedes u8 num_reports = skb->data[0]; 2872e95beb41SAndre Guedes void *ptr = &skb->data[1]; 28739aa04c91SAndre Guedes 28749aa04c91SAndre Guedes hci_dev_lock(hdev); 28759aa04c91SAndre Guedes 2876e95beb41SAndre Guedes while (num_reports--) { 2877e95beb41SAndre Guedes struct hci_ev_le_advertising_info *ev = ptr; 2878e95beb41SAndre Guedes 28799aa04c91SAndre Guedes hci_add_adv_entry(hdev, ev); 28809aa04c91SAndre Guedes 2881e95beb41SAndre Guedes ptr += sizeof(*ev) + ev->length + 1; 28829aa04c91SAndre Guedes } 28839aa04c91SAndre Guedes 28849aa04c91SAndre Guedes hci_dev_unlock(hdev); 28859aa04c91SAndre Guedes } 28869aa04c91SAndre Guedes 2887a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev, 2888a7a595f6SVinicius Costa Gomes struct sk_buff *skb) 2889a7a595f6SVinicius Costa Gomes { 2890a7a595f6SVinicius Costa Gomes struct hci_ev_le_ltk_req *ev = (void *) skb->data; 2891a7a595f6SVinicius Costa Gomes struct hci_cp_le_ltk_reply cp; 2892bea710feSVinicius Costa Gomes struct hci_cp_le_ltk_neg_reply neg; 2893a7a595f6SVinicius Costa Gomes struct hci_conn *conn; 2894bea710feSVinicius Costa Gomes struct link_key *ltk; 2895a7a595f6SVinicius Costa Gomes 2896a7a595f6SVinicius Costa Gomes BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle)); 2897a7a595f6SVinicius Costa Gomes 2898a7a595f6SVinicius Costa Gomes hci_dev_lock(hdev); 2899a7a595f6SVinicius Costa Gomes 2900a7a595f6SVinicius Costa Gomes conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2901bea710feSVinicius Costa Gomes if (conn == NULL) 2902bea710feSVinicius Costa Gomes goto not_found; 2903a7a595f6SVinicius Costa Gomes 2904bea710feSVinicius Costa Gomes ltk = hci_find_ltk(hdev, ev->ediv, ev->random); 2905bea710feSVinicius Costa Gomes if (ltk == NULL) 2906bea710feSVinicius Costa Gomes goto not_found; 2907bea710feSVinicius Costa Gomes 2908bea710feSVinicius Costa Gomes memcpy(cp.ltk, ltk->val, sizeof(ltk->val)); 2909a7a595f6SVinicius Costa Gomes cp.handle = cpu_to_le16(conn->handle); 2910726b4ffcSVinicius Costa Gomes conn->pin_length = ltk->pin_len; 2911a7a595f6SVinicius Costa Gomes 2912a7a595f6SVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); 2913a7a595f6SVinicius Costa Gomes 2914a7a595f6SVinicius Costa Gomes hci_dev_unlock(hdev); 2915bea710feSVinicius Costa Gomes 2916bea710feSVinicius Costa Gomes return; 2917bea710feSVinicius Costa Gomes 2918bea710feSVinicius Costa Gomes not_found: 2919bea710feSVinicius Costa Gomes neg.handle = ev->handle; 2920bea710feSVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg); 2921bea710feSVinicius Costa Gomes hci_dev_unlock(hdev); 2922a7a595f6SVinicius Costa Gomes } 2923a7a595f6SVinicius Costa Gomes 2924fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 2925fcd89c09SVille Tervo { 2926fcd89c09SVille Tervo struct hci_ev_le_meta *le_ev = (void *) skb->data; 2927fcd89c09SVille Tervo 2928fcd89c09SVille Tervo skb_pull(skb, sizeof(*le_ev)); 2929fcd89c09SVille Tervo 2930fcd89c09SVille Tervo switch (le_ev->subevent) { 2931fcd89c09SVille Tervo case HCI_EV_LE_CONN_COMPLETE: 2932fcd89c09SVille Tervo hci_le_conn_complete_evt(hdev, skb); 2933fcd89c09SVille Tervo break; 2934fcd89c09SVille Tervo 29359aa04c91SAndre Guedes case HCI_EV_LE_ADVERTISING_REPORT: 29369aa04c91SAndre Guedes hci_le_adv_report_evt(hdev, skb); 29379aa04c91SAndre Guedes break; 29389aa04c91SAndre Guedes 2939a7a595f6SVinicius Costa Gomes case HCI_EV_LE_LTK_REQ: 2940a7a595f6SVinicius Costa Gomes hci_le_ltk_request_evt(hdev, skb); 2941a7a595f6SVinicius Costa Gomes break; 2942a7a595f6SVinicius Costa Gomes 2943fcd89c09SVille Tervo default: 2944fcd89c09SVille Tervo break; 2945fcd89c09SVille Tervo } 2946fcd89c09SVille Tervo } 2947fcd89c09SVille Tervo 29481da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 29491da177e4SLinus Torvalds { 2950a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 2951a9de9248SMarcel Holtmann __u8 event = hdr->evt; 29521da177e4SLinus Torvalds 29531da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 29541da177e4SLinus Torvalds 2955a9de9248SMarcel Holtmann switch (event) { 29561da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 29571da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 29581da177e4SLinus Torvalds break; 29591da177e4SLinus Torvalds 29601da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 29611da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 29621da177e4SLinus Torvalds break; 29631da177e4SLinus Torvalds 2964a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 2965a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 296621d9e30eSMarcel Holtmann break; 296721d9e30eSMarcel Holtmann 29681da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 29691da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 29701da177e4SLinus Torvalds break; 29711da177e4SLinus Torvalds 29721da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 29731da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 29741da177e4SLinus Torvalds break; 29751da177e4SLinus Torvalds 29761da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 29771da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 29781da177e4SLinus Torvalds break; 29791da177e4SLinus Torvalds 2980a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 2981a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 2982a9de9248SMarcel Holtmann break; 2983a9de9248SMarcel Holtmann 29841da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 29851da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 29861da177e4SLinus Torvalds break; 29871da177e4SLinus Torvalds 2988a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 2989a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 2990a9de9248SMarcel Holtmann break; 2991a9de9248SMarcel Holtmann 2992a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 2993a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 2994a9de9248SMarcel Holtmann break; 2995a9de9248SMarcel Holtmann 2996a9de9248SMarcel Holtmann case HCI_EV_REMOTE_VERSION: 2997a9de9248SMarcel Holtmann hci_remote_version_evt(hdev, skb); 2998a9de9248SMarcel Holtmann break; 2999a9de9248SMarcel Holtmann 3000a9de9248SMarcel Holtmann case HCI_EV_QOS_SETUP_COMPLETE: 3001a9de9248SMarcel Holtmann hci_qos_setup_complete_evt(hdev, skb); 3002a9de9248SMarcel Holtmann break; 3003a9de9248SMarcel Holtmann 3004a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 3005a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 3006a9de9248SMarcel Holtmann break; 3007a9de9248SMarcel Holtmann 3008a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 3009a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 3010a9de9248SMarcel Holtmann break; 3011a9de9248SMarcel Holtmann 3012a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 3013a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 3014a9de9248SMarcel Holtmann break; 3015a9de9248SMarcel Holtmann 3016a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 3017a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 3018a9de9248SMarcel Holtmann break; 3019a9de9248SMarcel Holtmann 3020a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 3021a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 30221da177e4SLinus Torvalds break; 30231da177e4SLinus Torvalds 30241da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 30251da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 30261da177e4SLinus Torvalds break; 30271da177e4SLinus Torvalds 30281da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 30291da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 30301da177e4SLinus Torvalds break; 30311da177e4SLinus Torvalds 30321da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 30331da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 30341da177e4SLinus Torvalds break; 30351da177e4SLinus Torvalds 30361da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 30371da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 30381da177e4SLinus Torvalds break; 30391da177e4SLinus Torvalds 3040a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 3041a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 3042a8746417SMarcel Holtmann break; 3043a8746417SMarcel Holtmann 304485a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 304585a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 304685a1e930SMarcel Holtmann break; 304785a1e930SMarcel Holtmann 3048a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 3049a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 3050a9de9248SMarcel Holtmann break; 3051a9de9248SMarcel Holtmann 3052a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 3053a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 3054a9de9248SMarcel Holtmann break; 3055a9de9248SMarcel Holtmann 3056a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 3057a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 3058a9de9248SMarcel Holtmann break; 3059a9de9248SMarcel Holtmann 3060a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_CHANGED: 3061a9de9248SMarcel Holtmann hci_sync_conn_changed_evt(hdev, skb); 3062a9de9248SMarcel Holtmann break; 3063a9de9248SMarcel Holtmann 306404837f64SMarcel Holtmann case HCI_EV_SNIFF_SUBRATE: 306504837f64SMarcel Holtmann hci_sniff_subrate_evt(hdev, skb); 306604837f64SMarcel Holtmann break; 306704837f64SMarcel Holtmann 3068a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 3069a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 30701da177e4SLinus Torvalds break; 30711da177e4SLinus Torvalds 30720493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 30730493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 30740493684eSMarcel Holtmann break; 30750493684eSMarcel Holtmann 307603b555e1SJohan Hedberg case HCI_EV_IO_CAPA_REPLY: 307703b555e1SJohan Hedberg hci_io_capa_reply_evt(hdev, skb); 307803b555e1SJohan Hedberg break; 307903b555e1SJohan Hedberg 3080a5c29683SJohan Hedberg case HCI_EV_USER_CONFIRM_REQUEST: 3081a5c29683SJohan Hedberg hci_user_confirm_request_evt(hdev, skb); 3082a5c29683SJohan Hedberg break; 3083a5c29683SJohan Hedberg 30840493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 30850493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 30860493684eSMarcel Holtmann break; 30870493684eSMarcel Holtmann 308841a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 308941a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 309041a96212SMarcel Holtmann break; 309141a96212SMarcel Holtmann 3092fcd89c09SVille Tervo case HCI_EV_LE_META: 3093fcd89c09SVille Tervo hci_le_meta_evt(hdev, skb); 3094fcd89c09SVille Tervo break; 3095fcd89c09SVille Tervo 30962763eda6SSzymon Janc case HCI_EV_REMOTE_OOB_DATA_REQUEST: 30972763eda6SSzymon Janc hci_remote_oob_data_request_evt(hdev, skb); 30982763eda6SSzymon Janc break; 30992763eda6SSzymon Janc 31001da177e4SLinus Torvalds default: 3101a9de9248SMarcel Holtmann BT_DBG("%s event 0x%x", hdev->name, event); 31021da177e4SLinus Torvalds break; 31031da177e4SLinus Torvalds } 31041da177e4SLinus Torvalds 31051da177e4SLinus Torvalds kfree_skb(skb); 31061da177e4SLinus Torvalds hdev->stat.evt_rx++; 31071da177e4SLinus Torvalds } 31081da177e4SLinus Torvalds 31091da177e4SLinus Torvalds /* Generate internal stack event */ 31101da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data) 31111da177e4SLinus Torvalds { 31121da177e4SLinus Torvalds struct hci_event_hdr *hdr; 31131da177e4SLinus Torvalds struct hci_ev_stack_internal *ev; 31141da177e4SLinus Torvalds struct sk_buff *skb; 31151da177e4SLinus Torvalds 31161da177e4SLinus Torvalds skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC); 31171da177e4SLinus Torvalds if (!skb) 31181da177e4SLinus Torvalds return; 31191da177e4SLinus Torvalds 31201da177e4SLinus Torvalds hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE); 31211da177e4SLinus Torvalds hdr->evt = HCI_EV_STACK_INTERNAL; 31221da177e4SLinus Torvalds hdr->plen = sizeof(*ev) + dlen; 31231da177e4SLinus Torvalds 31241da177e4SLinus Torvalds ev = (void *) skb_put(skb, sizeof(*ev) + dlen); 31251da177e4SLinus Torvalds ev->type = type; 31261da177e4SLinus Torvalds memcpy(ev->data, data, dlen); 31271da177e4SLinus Torvalds 3128576c7d85SMarcel Holtmann bt_cb(skb)->incoming = 1; 3129a61bbcf2SPatrick McHardy __net_timestamp(skb); 3130576c7d85SMarcel Holtmann 31310d48d939SMarcel Holtmann bt_cb(skb)->pkt_type = HCI_EVENT_PKT; 31321da177e4SLinus Torvalds skb->dev = (void *) hdev; 3133eec8d2bcSJohan Hedberg hci_send_to_sock(hdev, skb, NULL); 31341da177e4SLinus Torvalds kfree_skb(skb); 31351da177e4SLinus Torvalds } 3136e6100a25SAndre Guedes 3137669bb396SGustavo F. Padovan module_param(enable_le, bool, 0644); 3138e6100a25SAndre Guedes MODULE_PARM_DESC(enable_le, "Enable LE support"); 3139