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 61314b2381SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags) && 62314b2381SJohan Hedberg test_and_clear_bit(HCI_INQUIRY, &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 79314b2381SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags) && 80314b2381SJohan Hedberg test_and_clear_bit(HCI_INQUIRY, &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 751b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, 752b0916ea0SJohan Hedberg struct sk_buff *skb) 753b0916ea0SJohan Hedberg { 754b0916ea0SJohan Hedberg __u8 status = *((__u8 *) skb->data); 755b0916ea0SJohan Hedberg 756b0916ea0SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 757b0916ea0SJohan Hedberg 758b0916ea0SJohan Hedberg hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status); 759b0916ea0SJohan Hedberg } 760b0916ea0SJohan Hedberg 761d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb) 762d5859e22SJohan Hedberg { 763d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 764d5859e22SJohan Hedberg 765d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 766d5859e22SJohan Hedberg 767d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status); 768d5859e22SJohan Hedberg } 769d5859e22SJohan Hedberg 770d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev, 771d5859e22SJohan Hedberg struct sk_buff *skb) 772d5859e22SJohan Hedberg { 773d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 774d5859e22SJohan Hedberg 775d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 776d5859e22SJohan Hedberg 777d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status); 778d5859e22SJohan Hedberg } 779d5859e22SJohan Hedberg 780d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, 781d5859e22SJohan Hedberg struct sk_buff *skb) 782d5859e22SJohan Hedberg { 783d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 784d5859e22SJohan Hedberg 785d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 786d5859e22SJohan Hedberg 787d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status); 788d5859e22SJohan Hedberg } 789d5859e22SJohan Hedberg 790d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb) 791d5859e22SJohan Hedberg { 792d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 793d5859e22SJohan Hedberg 794d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 795d5859e22SJohan Hedberg 796d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status); 797d5859e22SJohan Hedberg } 798d5859e22SJohan Hedberg 799980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) 800980e1a53SJohan Hedberg { 801980e1a53SJohan Hedberg struct hci_rp_pin_code_reply *rp = (void *) skb->data; 802980e1a53SJohan Hedberg struct hci_cp_pin_code_reply *cp; 803980e1a53SJohan Hedberg struct hci_conn *conn; 804980e1a53SJohan Hedberg 805980e1a53SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 806980e1a53SJohan Hedberg 807980e1a53SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 808980e1a53SJohan Hedberg mgmt_pin_code_reply_complete(hdev->id, &rp->bdaddr, rp->status); 809980e1a53SJohan Hedberg 810980e1a53SJohan Hedberg if (rp->status != 0) 811980e1a53SJohan Hedberg return; 812980e1a53SJohan Hedberg 813980e1a53SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); 814980e1a53SJohan Hedberg if (!cp) 815980e1a53SJohan Hedberg return; 816980e1a53SJohan Hedberg 817980e1a53SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 818980e1a53SJohan Hedberg if (conn) 819980e1a53SJohan Hedberg conn->pin_length = cp->pin_len; 820980e1a53SJohan Hedberg } 821980e1a53SJohan Hedberg 822980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 823980e1a53SJohan Hedberg { 824980e1a53SJohan Hedberg struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data; 825980e1a53SJohan Hedberg 826980e1a53SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 827980e1a53SJohan Hedberg 828980e1a53SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 829980e1a53SJohan Hedberg mgmt_pin_code_neg_reply_complete(hdev->id, &rp->bdaddr, 830980e1a53SJohan Hedberg rp->status); 831980e1a53SJohan Hedberg } 8326ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, 8336ed58ec5SVille Tervo struct sk_buff *skb) 8346ed58ec5SVille Tervo { 8356ed58ec5SVille Tervo struct hci_rp_le_read_buffer_size *rp = (void *) skb->data; 8366ed58ec5SVille Tervo 8376ed58ec5SVille Tervo BT_DBG("%s status 0x%x", hdev->name, rp->status); 8386ed58ec5SVille Tervo 8396ed58ec5SVille Tervo if (rp->status) 8406ed58ec5SVille Tervo return; 8416ed58ec5SVille Tervo 8426ed58ec5SVille Tervo hdev->le_mtu = __le16_to_cpu(rp->le_mtu); 8436ed58ec5SVille Tervo hdev->le_pkts = rp->le_max_pkt; 8446ed58ec5SVille Tervo 8456ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 8466ed58ec5SVille Tervo 8476ed58ec5SVille Tervo BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); 8486ed58ec5SVille Tervo 8496ed58ec5SVille Tervo hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status); 8506ed58ec5SVille Tervo } 851980e1a53SJohan Hedberg 852a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) 853a5c29683SJohan Hedberg { 854a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 855a5c29683SJohan Hedberg 856a5c29683SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 857a5c29683SJohan Hedberg 858a5c29683SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 859a5c29683SJohan Hedberg mgmt_user_confirm_reply_complete(hdev->id, &rp->bdaddr, 860a5c29683SJohan Hedberg rp->status); 861a5c29683SJohan Hedberg } 862a5c29683SJohan Hedberg 863a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, 864a5c29683SJohan Hedberg struct sk_buff *skb) 865a5c29683SJohan Hedberg { 866a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 867a5c29683SJohan Hedberg 868a5c29683SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 869a5c29683SJohan Hedberg 870a5c29683SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 871a5c29683SJohan Hedberg mgmt_user_confirm_neg_reply_complete(hdev->id, &rp->bdaddr, 872a5c29683SJohan Hedberg rp->status); 873a5c29683SJohan Hedberg } 874a5c29683SJohan Hedberg 875c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, 876c35938b2SSzymon Janc struct sk_buff *skb) 877c35938b2SSzymon Janc { 878c35938b2SSzymon Janc struct hci_rp_read_local_oob_data *rp = (void *) skb->data; 879c35938b2SSzymon Janc 880c35938b2SSzymon Janc BT_DBG("%s status 0x%x", hdev->name, rp->status); 881c35938b2SSzymon Janc 882c35938b2SSzymon Janc mgmt_read_local_oob_data_reply_complete(hdev->id, rp->hash, 883c35938b2SSzymon Janc rp->randomizer, rp->status); 884c35938b2SSzymon Janc } 885c35938b2SSzymon Janc 886eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, 887eb9d91f5SAndre Guedes struct sk_buff *skb) 888eb9d91f5SAndre Guedes { 889eb9d91f5SAndre Guedes struct hci_cp_le_set_scan_enable *cp; 890eb9d91f5SAndre Guedes __u8 status = *((__u8 *) skb->data); 891eb9d91f5SAndre Guedes 892eb9d91f5SAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 893eb9d91f5SAndre Guedes 894eb9d91f5SAndre Guedes if (status) 895eb9d91f5SAndre Guedes return; 896eb9d91f5SAndre Guedes 897eb9d91f5SAndre Guedes cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE); 898eb9d91f5SAndre Guedes if (!cp) 899eb9d91f5SAndre Guedes return; 900eb9d91f5SAndre Guedes 901eb9d91f5SAndre Guedes hci_dev_lock(hdev); 902eb9d91f5SAndre Guedes 90335815085SAndre Guedes if (cp->enable == 0x01) { 90435815085SAndre Guedes del_timer(&hdev->adv_timer); 905eb9d91f5SAndre Guedes hci_adv_entries_clear(hdev); 90635815085SAndre Guedes } else if (cp->enable == 0x00) { 90735815085SAndre Guedes mod_timer(&hdev->adv_timer, jiffies + ADV_CLEAR_TIMEOUT); 90835815085SAndre Guedes } 909eb9d91f5SAndre Guedes 910eb9d91f5SAndre Guedes hci_dev_unlock(hdev); 911eb9d91f5SAndre Guedes } 912eb9d91f5SAndre Guedes 913a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb) 914a7a595f6SVinicius Costa Gomes { 915a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_reply *rp = (void *) skb->data; 916a7a595f6SVinicius Costa Gomes 917a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, rp->status); 918a7a595f6SVinicius Costa Gomes 919a7a595f6SVinicius Costa Gomes if (rp->status) 920a7a595f6SVinicius Costa Gomes return; 921a7a595f6SVinicius Costa Gomes 922a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status); 923a7a595f6SVinicius Costa Gomes } 924a7a595f6SVinicius Costa Gomes 925a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 926a7a595f6SVinicius Costa Gomes { 927a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data; 928a7a595f6SVinicius Costa Gomes 929a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, rp->status); 930a7a595f6SVinicius Costa Gomes 931a7a595f6SVinicius Costa Gomes if (rp->status) 932a7a595f6SVinicius Costa Gomes return; 933a7a595f6SVinicius Costa Gomes 934a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status); 935a7a595f6SVinicius Costa Gomes } 936a7a595f6SVinicius Costa Gomes 937f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev, 938f9b49306SAndre Guedes struct sk_buff *skb) 939f9b49306SAndre Guedes { 940f9b49306SAndre Guedes struct hci_cp_read_local_ext_features cp; 941f9b49306SAndre Guedes __u8 status = *((__u8 *) skb->data); 942f9b49306SAndre Guedes 943f9b49306SAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 944f9b49306SAndre Guedes 945f9b49306SAndre Guedes if (status) 946f9b49306SAndre Guedes return; 947f9b49306SAndre Guedes 948f9b49306SAndre Guedes cp.page = 0x01; 949f9b49306SAndre Guedes hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp); 950f9b49306SAndre Guedes } 951f9b49306SAndre Guedes 952a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 953a9de9248SMarcel Holtmann { 954a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 955a9de9248SMarcel Holtmann 956a9de9248SMarcel Holtmann if (status) { 95723bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 958a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 959314b2381SJohan Hedberg return; 960314b2381SJohan Hedberg } 961314b2381SJohan Hedberg 962314b2381SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags) && 963314b2381SJohan Hedberg !test_and_set_bit(HCI_INQUIRY, 964314b2381SJohan Hedberg &hdev->flags)) 965314b2381SJohan Hedberg mgmt_discovering(hdev->id, 1); 966a9de9248SMarcel Holtmann } 967a9de9248SMarcel Holtmann 9681da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 9691da177e4SLinus Torvalds { 970a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 9711da177e4SLinus Torvalds struct hci_conn *conn; 9721da177e4SLinus Torvalds 973a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 974a9de9248SMarcel Holtmann 975a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 9761da177e4SLinus Torvalds if (!cp) 9771da177e4SLinus Torvalds return; 9781da177e4SLinus Torvalds 9791da177e4SLinus Torvalds hci_dev_lock(hdev); 9801da177e4SLinus Torvalds 9811da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 9821da177e4SLinus Torvalds 983a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn); 9841da177e4SLinus Torvalds 9851da177e4SLinus Torvalds if (status) { 9861da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 9874c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 9881da177e4SLinus Torvalds conn->state = BT_CLOSED; 9891da177e4SLinus Torvalds hci_proto_connect_cfm(conn, status); 9901da177e4SLinus Torvalds hci_conn_del(conn); 9914c67bc74SMarcel Holtmann } else 9924c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 9931da177e4SLinus Torvalds } 9941da177e4SLinus Torvalds } else { 9951da177e4SLinus Torvalds if (!conn) { 9961da177e4SLinus Torvalds conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); 9971da177e4SLinus Torvalds if (conn) { 9981da177e4SLinus Torvalds conn->out = 1; 9991da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 10001da177e4SLinus Torvalds } else 1001893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 10021da177e4SLinus Torvalds } 10031da177e4SLinus Torvalds } 10041da177e4SLinus Torvalds 10051da177e4SLinus Torvalds hci_dev_unlock(hdev); 10061da177e4SLinus Torvalds } 10071da177e4SLinus Torvalds 1008a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 10091da177e4SLinus Torvalds { 1010a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 10111da177e4SLinus Torvalds struct hci_conn *acl, *sco; 10121da177e4SLinus Torvalds __u16 handle; 10131da177e4SLinus Torvalds 1014b6a0dc82SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1015b6a0dc82SMarcel Holtmann 1016a9de9248SMarcel Holtmann if (!status) 1017a9de9248SMarcel Holtmann return; 1018a9de9248SMarcel Holtmann 1019a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 10201da177e4SLinus Torvalds if (!cp) 1021a9de9248SMarcel Holtmann return; 10221da177e4SLinus Torvalds 10231da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 10241da177e4SLinus Torvalds 1025a9de9248SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 10261da177e4SLinus Torvalds 10271da177e4SLinus Torvalds hci_dev_lock(hdev); 10281da177e4SLinus Torvalds 10291da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 10305a08ecceSAndrei Emeltchenko if (acl) { 10315a08ecceSAndrei Emeltchenko sco = acl->link; 10325a08ecceSAndrei Emeltchenko if (sco) { 10331da177e4SLinus Torvalds sco->state = BT_CLOSED; 10341da177e4SLinus Torvalds 10351da177e4SLinus Torvalds hci_proto_connect_cfm(sco, status); 10361da177e4SLinus Torvalds hci_conn_del(sco); 10371da177e4SLinus Torvalds } 10385a08ecceSAndrei Emeltchenko } 10391da177e4SLinus Torvalds 10401da177e4SLinus Torvalds hci_dev_unlock(hdev); 10411da177e4SLinus Torvalds } 10421da177e4SLinus Torvalds 1043f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 1044f8558555SMarcel Holtmann { 1045f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 1046f8558555SMarcel Holtmann struct hci_conn *conn; 1047f8558555SMarcel Holtmann 1048f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1049f8558555SMarcel Holtmann 1050f8558555SMarcel Holtmann if (!status) 1051f8558555SMarcel Holtmann return; 1052f8558555SMarcel Holtmann 1053f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 1054f8558555SMarcel Holtmann if (!cp) 1055f8558555SMarcel Holtmann return; 1056f8558555SMarcel Holtmann 1057f8558555SMarcel Holtmann hci_dev_lock(hdev); 1058f8558555SMarcel Holtmann 1059f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1060f8558555SMarcel Holtmann if (conn) { 1061f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1062f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1063f8558555SMarcel Holtmann hci_conn_put(conn); 1064f8558555SMarcel Holtmann } 1065f8558555SMarcel Holtmann } 1066f8558555SMarcel Holtmann 1067f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1068f8558555SMarcel Holtmann } 1069f8558555SMarcel Holtmann 1070f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 1071f8558555SMarcel Holtmann { 1072f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 1073f8558555SMarcel Holtmann struct hci_conn *conn; 1074f8558555SMarcel Holtmann 1075f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1076f8558555SMarcel Holtmann 1077f8558555SMarcel Holtmann if (!status) 1078f8558555SMarcel Holtmann return; 1079f8558555SMarcel Holtmann 1080f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 1081f8558555SMarcel Holtmann if (!cp) 1082f8558555SMarcel Holtmann return; 1083f8558555SMarcel Holtmann 1084f8558555SMarcel Holtmann hci_dev_lock(hdev); 1085f8558555SMarcel Holtmann 1086f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1087f8558555SMarcel Holtmann if (conn) { 1088f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1089f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1090f8558555SMarcel Holtmann hci_conn_put(conn); 1091f8558555SMarcel Holtmann } 1092f8558555SMarcel Holtmann } 1093f8558555SMarcel Holtmann 1094f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1095f8558555SMarcel Holtmann } 1096f8558555SMarcel Holtmann 1097127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev, 1098392599b9SJohan Hedberg struct hci_conn *conn) 1099392599b9SJohan Hedberg { 1100392599b9SJohan Hedberg if (conn->state != BT_CONFIG || !conn->out) 1101392599b9SJohan Hedberg return 0; 1102392599b9SJohan Hedberg 1103765c2a96SJohan Hedberg if (conn->pending_sec_level == BT_SECURITY_SDP) 1104392599b9SJohan Hedberg return 0; 1105392599b9SJohan Hedberg 1106392599b9SJohan Hedberg /* Only request authentication for SSP connections or non-SSP 1107392599b9SJohan Hedberg * devices with sec_level HIGH */ 1108392599b9SJohan Hedberg if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) && 1109765c2a96SJohan Hedberg conn->pending_sec_level != BT_SECURITY_HIGH) 1110392599b9SJohan Hedberg return 0; 1111392599b9SJohan Hedberg 1112392599b9SJohan Hedberg return 1; 1113392599b9SJohan Hedberg } 1114392599b9SJohan Hedberg 1115a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 11161da177e4SLinus Torvalds { 1117127178d2SJohan Hedberg struct hci_cp_remote_name_req *cp; 1118127178d2SJohan Hedberg struct hci_conn *conn; 1119127178d2SJohan Hedberg 1120a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1121127178d2SJohan Hedberg 1122127178d2SJohan Hedberg /* If successful wait for the name req complete event before 1123127178d2SJohan Hedberg * checking for the need to do authentication */ 1124127178d2SJohan Hedberg if (!status) 1125127178d2SJohan Hedberg return; 1126127178d2SJohan Hedberg 1127127178d2SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); 1128127178d2SJohan Hedberg if (!cp) 1129127178d2SJohan Hedberg return; 1130127178d2SJohan Hedberg 1131127178d2SJohan Hedberg hci_dev_lock(hdev); 1132127178d2SJohan Hedberg 1133127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 113479c6c70cSJohan Hedberg if (!conn) 113579c6c70cSJohan Hedberg goto unlock; 113679c6c70cSJohan Hedberg 113779c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 113879c6c70cSJohan Hedberg goto unlock; 113979c6c70cSJohan Hedberg 114079c6c70cSJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { 1141127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1142127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1143127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1144127178d2SJohan Hedberg } 1145127178d2SJohan Hedberg 114679c6c70cSJohan Hedberg unlock: 1147127178d2SJohan Hedberg hci_dev_unlock(hdev); 1148a9de9248SMarcel Holtmann } 11491da177e4SLinus Torvalds 1150769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 1151769be974SMarcel Holtmann { 1152769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 1153769be974SMarcel Holtmann struct hci_conn *conn; 1154769be974SMarcel Holtmann 1155769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1156769be974SMarcel Holtmann 1157769be974SMarcel Holtmann if (!status) 1158769be974SMarcel Holtmann return; 1159769be974SMarcel Holtmann 1160769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 1161769be974SMarcel Holtmann if (!cp) 1162769be974SMarcel Holtmann return; 1163769be974SMarcel Holtmann 1164769be974SMarcel Holtmann hci_dev_lock(hdev); 1165769be974SMarcel Holtmann 1166769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1167769be974SMarcel Holtmann if (conn) { 1168769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1169769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1170769be974SMarcel Holtmann hci_conn_put(conn); 1171769be974SMarcel Holtmann } 1172769be974SMarcel Holtmann } 1173769be974SMarcel Holtmann 1174769be974SMarcel Holtmann hci_dev_unlock(hdev); 1175769be974SMarcel Holtmann } 1176769be974SMarcel Holtmann 1177769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 1178769be974SMarcel Holtmann { 1179769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features *cp; 1180769be974SMarcel Holtmann struct hci_conn *conn; 1181769be974SMarcel Holtmann 1182769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1183769be974SMarcel Holtmann 1184769be974SMarcel Holtmann if (!status) 1185769be974SMarcel Holtmann return; 1186769be974SMarcel Holtmann 1187769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 1188769be974SMarcel Holtmann if (!cp) 1189769be974SMarcel Holtmann return; 1190769be974SMarcel Holtmann 1191769be974SMarcel Holtmann hci_dev_lock(hdev); 1192769be974SMarcel Holtmann 1193769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1194769be974SMarcel Holtmann if (conn) { 1195769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1196769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1197769be974SMarcel Holtmann hci_conn_put(conn); 1198769be974SMarcel Holtmann } 1199769be974SMarcel Holtmann } 1200769be974SMarcel Holtmann 1201769be974SMarcel Holtmann hci_dev_unlock(hdev); 1202769be974SMarcel Holtmann } 1203769be974SMarcel Holtmann 1204a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 1205a9de9248SMarcel Holtmann { 1206b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 1207b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 1208b6a0dc82SMarcel Holtmann __u16 handle; 1209b6a0dc82SMarcel Holtmann 1210a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1211b6a0dc82SMarcel Holtmann 1212b6a0dc82SMarcel Holtmann if (!status) 1213b6a0dc82SMarcel Holtmann return; 1214b6a0dc82SMarcel Holtmann 1215b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 1216b6a0dc82SMarcel Holtmann if (!cp) 1217b6a0dc82SMarcel Holtmann return; 1218b6a0dc82SMarcel Holtmann 1219b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 1220b6a0dc82SMarcel Holtmann 1221b6a0dc82SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 1222b6a0dc82SMarcel Holtmann 1223b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 1224b6a0dc82SMarcel Holtmann 1225b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 12265a08ecceSAndrei Emeltchenko if (acl) { 12275a08ecceSAndrei Emeltchenko sco = acl->link; 12285a08ecceSAndrei Emeltchenko if (sco) { 1229b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 1230b6a0dc82SMarcel Holtmann 1231b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(sco, status); 1232b6a0dc82SMarcel Holtmann hci_conn_del(sco); 1233b6a0dc82SMarcel Holtmann } 12345a08ecceSAndrei Emeltchenko } 1235b6a0dc82SMarcel Holtmann 1236b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 1237a9de9248SMarcel Holtmann } 1238a9de9248SMarcel Holtmann 1239a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 1240a9de9248SMarcel Holtmann { 1241a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 124204837f64SMarcel Holtmann struct hci_conn *conn; 124304837f64SMarcel Holtmann 1244a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1245a9de9248SMarcel Holtmann 1246a9de9248SMarcel Holtmann if (!status) 1247a9de9248SMarcel Holtmann return; 1248a9de9248SMarcel Holtmann 1249a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 125004837f64SMarcel Holtmann if (!cp) 1251a9de9248SMarcel Holtmann return; 125204837f64SMarcel Holtmann 125304837f64SMarcel Holtmann hci_dev_lock(hdev); 125404837f64SMarcel Holtmann 125504837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1256e73439d8SMarcel Holtmann if (conn) { 125704837f64SMarcel Holtmann clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); 125804837f64SMarcel Holtmann 1259e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 1260e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1261e73439d8SMarcel Holtmann } 1262e73439d8SMarcel Holtmann 126304837f64SMarcel Holtmann hci_dev_unlock(hdev); 126404837f64SMarcel Holtmann } 126504837f64SMarcel Holtmann 1266a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 1267a9de9248SMarcel Holtmann { 1268a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 126904837f64SMarcel Holtmann struct hci_conn *conn; 127004837f64SMarcel Holtmann 1271a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1272a9de9248SMarcel Holtmann 1273a9de9248SMarcel Holtmann if (!status) 1274a9de9248SMarcel Holtmann return; 1275a9de9248SMarcel Holtmann 1276a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 127704837f64SMarcel Holtmann if (!cp) 1278a9de9248SMarcel Holtmann return; 127904837f64SMarcel Holtmann 128004837f64SMarcel Holtmann hci_dev_lock(hdev); 128104837f64SMarcel Holtmann 128204837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1283e73439d8SMarcel Holtmann if (conn) { 128404837f64SMarcel Holtmann clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); 128504837f64SMarcel Holtmann 1286e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 1287e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1288e73439d8SMarcel Holtmann } 1289e73439d8SMarcel Holtmann 129004837f64SMarcel Holtmann hci_dev_unlock(hdev); 129104837f64SMarcel Holtmann } 129204837f64SMarcel Holtmann 1293fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) 1294fcd89c09SVille Tervo { 1295fcd89c09SVille Tervo struct hci_cp_le_create_conn *cp; 1296fcd89c09SVille Tervo struct hci_conn *conn; 1297fcd89c09SVille Tervo 1298fcd89c09SVille Tervo BT_DBG("%s status 0x%x", hdev->name, status); 1299fcd89c09SVille Tervo 1300fcd89c09SVille Tervo cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN); 1301fcd89c09SVille Tervo if (!cp) 1302fcd89c09SVille Tervo return; 1303fcd89c09SVille Tervo 1304fcd89c09SVille Tervo hci_dev_lock(hdev); 1305fcd89c09SVille Tervo 1306fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr); 1307fcd89c09SVille Tervo 1308fcd89c09SVille Tervo BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr), 1309fcd89c09SVille Tervo conn); 1310fcd89c09SVille Tervo 1311fcd89c09SVille Tervo if (status) { 1312fcd89c09SVille Tervo if (conn && conn->state == BT_CONNECT) { 1313fcd89c09SVille Tervo conn->state = BT_CLOSED; 1314fcd89c09SVille Tervo hci_proto_connect_cfm(conn, status); 1315fcd89c09SVille Tervo hci_conn_del(conn); 1316fcd89c09SVille Tervo } 1317fcd89c09SVille Tervo } else { 1318fcd89c09SVille Tervo if (!conn) { 1319fcd89c09SVille Tervo conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr); 132029b7988aSAndre Guedes if (conn) { 132129b7988aSAndre Guedes conn->dst_type = cp->peer_addr_type; 1322fcd89c09SVille Tervo conn->out = 1; 132329b7988aSAndre Guedes } else { 1324fcd89c09SVille Tervo BT_ERR("No memory for new connection"); 1325fcd89c09SVille Tervo } 1326fcd89c09SVille Tervo } 132729b7988aSAndre Guedes } 1328fcd89c09SVille Tervo 1329fcd89c09SVille Tervo hci_dev_unlock(hdev); 1330fcd89c09SVille Tervo } 1331fcd89c09SVille Tervo 1332a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) 1333a7a595f6SVinicius Costa Gomes { 1334a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, status); 1335a7a595f6SVinicius Costa Gomes } 1336a7a595f6SVinicius Costa Gomes 13371da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 13381da177e4SLinus Torvalds { 13391da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 13401da177e4SLinus Torvalds 13411da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, status); 13421da177e4SLinus Torvalds 1343314b2381SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags) && 1344314b2381SJohan Hedberg test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) 1345314b2381SJohan Hedberg mgmt_discovering(hdev->id, 0); 1346a9de9248SMarcel Holtmann 134723bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 13486bd57416SMarcel Holtmann 1349a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 13501da177e4SLinus Torvalds } 13511da177e4SLinus Torvalds 13521da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 13531da177e4SLinus Torvalds { 135445bb4bf0SMarcel Holtmann struct inquiry_data data; 1355a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 13561da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 13571da177e4SLinus Torvalds 13581da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 13591da177e4SLinus Torvalds 136045bb4bf0SMarcel Holtmann if (!num_rsp) 136145bb4bf0SMarcel Holtmann return; 136245bb4bf0SMarcel Holtmann 13631da177e4SLinus Torvalds hci_dev_lock(hdev); 136445bb4bf0SMarcel Holtmann 1365314b2381SJohan Hedberg if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) { 1366314b2381SJohan Hedberg 1367314b2381SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 1368314b2381SJohan Hedberg mgmt_discovering(hdev->id, 1); 1369314b2381SJohan Hedberg } 1370314b2381SJohan Hedberg 1371e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 13721da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 13731da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 13741da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 13751da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 13761da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 13771da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 13781da177e4SLinus Torvalds data.rssi = 0x00; 137941a96212SMarcel Holtmann data.ssp_mode = 0x00; 13801da177e4SLinus Torvalds hci_inquiry_cache_update(hdev, &data); 1381e17acd40SJohan Hedberg mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class, 0, 1382e17acd40SJohan Hedberg NULL); 13831da177e4SLinus Torvalds } 138445bb4bf0SMarcel Holtmann 13851da177e4SLinus Torvalds hci_dev_unlock(hdev); 13861da177e4SLinus Torvalds } 13871da177e4SLinus Torvalds 1388a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 13891da177e4SLinus Torvalds { 1390a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 1391a9de9248SMarcel Holtmann struct hci_conn *conn; 13921da177e4SLinus Torvalds 1393a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 139445bb4bf0SMarcel Holtmann 13951da177e4SLinus Torvalds hci_dev_lock(hdev); 139645bb4bf0SMarcel Holtmann 1397a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 13989499237aSMarcel Holtmann if (!conn) { 13999499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 14009499237aSMarcel Holtmann goto unlock; 14019499237aSMarcel Holtmann 14029499237aSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 1403a9de9248SMarcel Holtmann if (!conn) 1404a9de9248SMarcel Holtmann goto unlock; 140545bb4bf0SMarcel Holtmann 14069499237aSMarcel Holtmann conn->type = SCO_LINK; 14079499237aSMarcel Holtmann } 14089499237aSMarcel Holtmann 1409a9de9248SMarcel Holtmann if (!ev->status) { 1410a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 1411769be974SMarcel Holtmann 1412769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 1413769be974SMarcel Holtmann conn->state = BT_CONFIG; 1414769be974SMarcel Holtmann hci_conn_hold(conn); 1415052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1416f7520543SJohan Hedberg mgmt_connected(hdev->id, &ev->bdaddr); 1417769be974SMarcel Holtmann } else 1418a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 1419a9de9248SMarcel Holtmann 14209eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 14217d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 14227d0db0a3SMarcel Holtmann 1423a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 1424a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1425a9de9248SMarcel Holtmann 1426a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 1427a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1428a9de9248SMarcel Holtmann 1429a9de9248SMarcel Holtmann /* Get remote features */ 1430a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 1431a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 1432a9de9248SMarcel Holtmann cp.handle = ev->handle; 1433769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 1434769be974SMarcel Holtmann sizeof(cp), &cp); 143545bb4bf0SMarcel Holtmann } 1436a9de9248SMarcel Holtmann 1437a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 1438a8746417SMarcel Holtmann if (!conn->out && hdev->hci_ver < 3) { 1439a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 1440a9de9248SMarcel Holtmann cp.handle = ev->handle; 1441a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1442a8746417SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, 1443a8746417SMarcel Holtmann sizeof(cp), &cp); 1444a9de9248SMarcel Holtmann } 144517d5c04cSJohan Hedberg } else { 1446a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 144717d5c04cSJohan Hedberg if (conn->type == ACL_LINK) 144817d5c04cSJohan Hedberg mgmt_connect_failed(hdev->id, &ev->bdaddr, ev->status); 144917d5c04cSJohan Hedberg } 145045bb4bf0SMarcel Holtmann 1451e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 1452e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 145345bb4bf0SMarcel Holtmann 1454769be974SMarcel Holtmann if (ev->status) { 1455a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1456a9de9248SMarcel Holtmann hci_conn_del(conn); 1457c89b6e6bSMarcel Holtmann } else if (ev->link_type != ACL_LINK) 1458c89b6e6bSMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1459a9de9248SMarcel Holtmann 1460a9de9248SMarcel Holtmann unlock: 14611da177e4SLinus Torvalds hci_dev_unlock(hdev); 1462a9de9248SMarcel Holtmann 1463a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 14641da177e4SLinus Torvalds } 14651da177e4SLinus Torvalds 14661da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 14671da177e4SLinus Torvalds { 1468a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 14691da177e4SLinus Torvalds int mask = hdev->link_mode; 14701da177e4SLinus Torvalds 1471a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s type 0x%x", hdev->name, 14721da177e4SLinus Torvalds batostr(&ev->bdaddr), ev->link_type); 14731da177e4SLinus Torvalds 14741da177e4SLinus Torvalds mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); 14751da177e4SLinus Torvalds 1476138d22efSSzymon Janc if ((mask & HCI_LM_ACCEPT) && 1477138d22efSSzymon Janc !hci_blacklist_lookup(hdev, &ev->bdaddr)) { 14781da177e4SLinus Torvalds /* Connection accepted */ 1479c7bdd502SMarcel Holtmann struct inquiry_entry *ie; 14801da177e4SLinus Torvalds struct hci_conn *conn; 14811da177e4SLinus Torvalds 14821da177e4SLinus Torvalds hci_dev_lock(hdev); 1483b6a0dc82SMarcel Holtmann 1484cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 1485cc11b9c1SAndrei Emeltchenko if (ie) 1486c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 1487c7bdd502SMarcel Holtmann 14881da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 14891da177e4SLinus Torvalds if (!conn) { 1490cc11b9c1SAndrei Emeltchenko conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); 1491cc11b9c1SAndrei Emeltchenko if (!conn) { 1492893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 14931da177e4SLinus Torvalds hci_dev_unlock(hdev); 14941da177e4SLinus Torvalds return; 14951da177e4SLinus Torvalds } 14961da177e4SLinus Torvalds } 1497b6a0dc82SMarcel Holtmann 14981da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 14991da177e4SLinus Torvalds conn->state = BT_CONNECT; 1500b6a0dc82SMarcel Holtmann 15011da177e4SLinus Torvalds hci_dev_unlock(hdev); 15021da177e4SLinus Torvalds 1503b6a0dc82SMarcel Holtmann if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) { 1504b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 1505b6a0dc82SMarcel Holtmann 15061da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 15071da177e4SLinus Torvalds 15081da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 15091da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 15101da177e4SLinus Torvalds else 15111da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 15121da177e4SLinus Torvalds 1513b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, 1514b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1515b6a0dc82SMarcel Holtmann } else { 1516b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 1517b6a0dc82SMarcel Holtmann 1518b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 1519a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1520b6a0dc82SMarcel Holtmann 1521b6a0dc82SMarcel Holtmann cp.tx_bandwidth = cpu_to_le32(0x00001f40); 1522b6a0dc82SMarcel Holtmann cp.rx_bandwidth = cpu_to_le32(0x00001f40); 1523b6a0dc82SMarcel Holtmann cp.max_latency = cpu_to_le16(0xffff); 1524b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 1525b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 1526b6a0dc82SMarcel Holtmann 1527b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 1528b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1529b6a0dc82SMarcel Holtmann } 15301da177e4SLinus Torvalds } else { 15311da177e4SLinus Torvalds /* Connection rejected */ 15321da177e4SLinus Torvalds struct hci_cp_reject_conn_req cp; 15331da177e4SLinus Torvalds 15341da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 15351da177e4SLinus Torvalds cp.reason = 0x0f; 1536a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 15371da177e4SLinus Torvalds } 15381da177e4SLinus Torvalds } 15391da177e4SLinus Torvalds 15401da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 15411da177e4SLinus Torvalds { 1542a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 154304837f64SMarcel Holtmann struct hci_conn *conn; 15441da177e4SLinus Torvalds 15451da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 15461da177e4SLinus Torvalds 15478962ee74SJohan Hedberg if (ev->status) { 15488962ee74SJohan Hedberg mgmt_disconnect_failed(hdev->id); 15491da177e4SLinus Torvalds return; 15508962ee74SJohan Hedberg } 15511da177e4SLinus Torvalds 15521da177e4SLinus Torvalds hci_dev_lock(hdev); 15531da177e4SLinus Torvalds 155404837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1555f7520543SJohan Hedberg if (!conn) 1556f7520543SJohan Hedberg goto unlock; 1557f7520543SJohan Hedberg 15581da177e4SLinus Torvalds conn->state = BT_CLOSED; 15597d0db0a3SMarcel Holtmann 156083bc71b4SVinicius Costa Gomes if (conn->type == ACL_LINK || conn->type == LE_LINK) 1561f7520543SJohan Hedberg mgmt_disconnected(hdev->id, &conn->dst); 1562f7520543SJohan Hedberg 15632950f21aSMarcel Holtmann hci_proto_disconn_cfm(conn, ev->reason); 15641da177e4SLinus Torvalds hci_conn_del(conn); 15651da177e4SLinus Torvalds 1566f7520543SJohan Hedberg unlock: 15671da177e4SLinus Torvalds hci_dev_unlock(hdev); 15681da177e4SLinus Torvalds } 15691da177e4SLinus Torvalds 1570a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1571a9de9248SMarcel Holtmann { 1572a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 1573a9de9248SMarcel Holtmann struct hci_conn *conn; 1574a9de9248SMarcel Holtmann 1575a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1576a9de9248SMarcel Holtmann 1577a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1578a9de9248SMarcel Holtmann 1579a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1580d7556e20SWaldemar Rymarkiewicz if (!conn) 1581d7556e20SWaldemar Rymarkiewicz goto unlock; 1582d7556e20SWaldemar Rymarkiewicz 1583765c2a96SJohan Hedberg if (!ev->status) { 158419f8def0SWaldemar Rymarkiewicz if (!(conn->ssp_mode > 0 && hdev->ssp_mode > 0) && 1585d7556e20SWaldemar Rymarkiewicz test_bit(HCI_CONN_REAUTH_PEND, &conn->pend)) { 1586d7556e20SWaldemar Rymarkiewicz BT_INFO("re-auth of legacy device is not possible."); 158719f8def0SWaldemar Rymarkiewicz } else { 1588a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1589765c2a96SJohan Hedberg conn->sec_level = conn->pending_sec_level; 159019f8def0SWaldemar Rymarkiewicz } 15912a611692SJohan Hedberg } else { 15922a611692SJohan Hedberg mgmt_auth_failed(hdev->id, &conn->dst, ev->status); 15932a611692SJohan Hedberg } 1594a9de9248SMarcel Holtmann 1595a9de9248SMarcel Holtmann clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); 159619f8def0SWaldemar Rymarkiewicz clear_bit(HCI_CONN_REAUTH_PEND, &conn->pend); 1597a9de9248SMarcel Holtmann 1598f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1599d7556e20SWaldemar Rymarkiewicz if (!ev->status && hdev->ssp_mode > 0 && conn->ssp_mode > 0) { 1600f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1601f8558555SMarcel Holtmann cp.handle = ev->handle; 1602f8558555SMarcel Holtmann cp.encrypt = 0x01; 1603d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1604d7556e20SWaldemar Rymarkiewicz &cp); 1605f8558555SMarcel Holtmann } else { 1606f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1607f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1608f8558555SMarcel Holtmann hci_conn_put(conn); 1609f8558555SMarcel Holtmann } 1610052b30b0SMarcel Holtmann } else { 1611a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 1612a9de9248SMarcel Holtmann 1613052b30b0SMarcel Holtmann hci_conn_hold(conn); 1614052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1615052b30b0SMarcel Holtmann hci_conn_put(conn); 1616052b30b0SMarcel Holtmann } 1617052b30b0SMarcel Holtmann 1618a9de9248SMarcel Holtmann if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) { 1619a9de9248SMarcel Holtmann if (!ev->status) { 1620a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1621f8558555SMarcel Holtmann cp.handle = ev->handle; 1622f8558555SMarcel Holtmann cp.encrypt = 0x01; 1623d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1624d7556e20SWaldemar Rymarkiewicz &cp); 1625a9de9248SMarcel Holtmann } else { 1626a9de9248SMarcel Holtmann clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); 1627a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 1628a9de9248SMarcel Holtmann } 1629a9de9248SMarcel Holtmann } 1630a9de9248SMarcel Holtmann 1631d7556e20SWaldemar Rymarkiewicz unlock: 1632a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1633a9de9248SMarcel Holtmann } 1634a9de9248SMarcel Holtmann 1635a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 1636a9de9248SMarcel Holtmann { 1637127178d2SJohan Hedberg struct hci_ev_remote_name *ev = (void *) skb->data; 1638127178d2SJohan Hedberg struct hci_conn *conn; 1639127178d2SJohan Hedberg 1640a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1641a9de9248SMarcel Holtmann 1642a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 1643127178d2SJohan Hedberg 1644127178d2SJohan Hedberg hci_dev_lock(hdev); 1645127178d2SJohan Hedberg 1646a88a9652SJohan Hedberg if (ev->status == 0 && test_bit(HCI_MGMT, &hdev->flags)) 1647a88a9652SJohan Hedberg mgmt_remote_name(hdev->id, &ev->bdaddr, ev->name); 1648a88a9652SJohan Hedberg 1649127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 165079c6c70cSJohan Hedberg if (!conn) 165179c6c70cSJohan Hedberg goto unlock; 165279c6c70cSJohan Hedberg 165379c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 165479c6c70cSJohan Hedberg goto unlock; 165579c6c70cSJohan Hedberg 165679c6c70cSJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { 1657127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1658127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1659127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1660127178d2SJohan Hedberg } 1661127178d2SJohan Hedberg 166279c6c70cSJohan Hedberg unlock: 1663127178d2SJohan Hedberg hci_dev_unlock(hdev); 1664a9de9248SMarcel Holtmann } 1665a9de9248SMarcel Holtmann 1666a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 1667a9de9248SMarcel Holtmann { 1668a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 1669a9de9248SMarcel Holtmann struct hci_conn *conn; 1670a9de9248SMarcel Holtmann 1671a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1672a9de9248SMarcel Holtmann 1673a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1674a9de9248SMarcel Holtmann 1675a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1676a9de9248SMarcel Holtmann if (conn) { 1677a9de9248SMarcel Holtmann if (!ev->status) { 1678ae293196SMarcel Holtmann if (ev->encrypt) { 1679ae293196SMarcel Holtmann /* Encryption implies authentication */ 1680ae293196SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1681a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1682da85e5e5SVinicius Costa Gomes conn->sec_level = conn->pending_sec_level; 1683ae293196SMarcel Holtmann } else 1684a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_ENCRYPT; 1685a9de9248SMarcel Holtmann } 1686a9de9248SMarcel Holtmann 1687a9de9248SMarcel Holtmann clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); 1688a9de9248SMarcel Holtmann 1689f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1690f8558555SMarcel Holtmann if (!ev->status) 1691f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1692f8558555SMarcel Holtmann 1693f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1694f8558555SMarcel Holtmann hci_conn_put(conn); 1695f8558555SMarcel Holtmann } else 1696a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 1697a9de9248SMarcel Holtmann } 1698a9de9248SMarcel Holtmann 1699a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1700a9de9248SMarcel Holtmann } 1701a9de9248SMarcel Holtmann 1702a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1703a9de9248SMarcel Holtmann { 1704a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 1705a9de9248SMarcel Holtmann struct hci_conn *conn; 1706a9de9248SMarcel Holtmann 1707a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1708a9de9248SMarcel Holtmann 1709a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1710a9de9248SMarcel Holtmann 1711a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1712a9de9248SMarcel Holtmann if (conn) { 1713a9de9248SMarcel Holtmann if (!ev->status) 1714a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_SECURE; 1715a9de9248SMarcel Holtmann 1716a9de9248SMarcel Holtmann clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); 1717a9de9248SMarcel Holtmann 1718a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 1719a9de9248SMarcel Holtmann } 1720a9de9248SMarcel Holtmann 1721a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1722a9de9248SMarcel Holtmann } 1723a9de9248SMarcel Holtmann 1724a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 1725a9de9248SMarcel Holtmann { 1726a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 1727a9de9248SMarcel Holtmann struct hci_conn *conn; 1728a9de9248SMarcel Holtmann 1729a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1730a9de9248SMarcel Holtmann 1731a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1732a9de9248SMarcel Holtmann 1733a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1734ccd556feSJohan Hedberg if (!conn) 1735ccd556feSJohan Hedberg goto unlock; 1736ccd556feSJohan Hedberg 1737769be974SMarcel Holtmann if (!ev->status) 1738a9de9248SMarcel Holtmann memcpy(conn->features, ev->features, 8); 1739a9de9248SMarcel Holtmann 1740ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 1741ccd556feSJohan Hedberg goto unlock; 1742ccd556feSJohan Hedberg 1743ccd556feSJohan Hedberg if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { 1744769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 1745769be974SMarcel Holtmann cp.handle = ev->handle; 1746769be974SMarcel Holtmann cp.page = 0x01; 1747ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 1748769be974SMarcel Holtmann sizeof(cp), &cp); 1749392599b9SJohan Hedberg goto unlock; 1750392599b9SJohan Hedberg } 1751392599b9SJohan Hedberg 1752127178d2SJohan Hedberg if (!ev->status) { 1753127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 1754127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 1755127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 1756127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 1757127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 1758127178d2SJohan Hedberg } 1759392599b9SJohan Hedberg 1760127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 1761769be974SMarcel Holtmann conn->state = BT_CONNECTED; 1762769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1763769be974SMarcel Holtmann hci_conn_put(conn); 1764769be974SMarcel Holtmann } 1765769be974SMarcel Holtmann 1766ccd556feSJohan Hedberg unlock: 1767a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1768a9de9248SMarcel Holtmann } 1769a9de9248SMarcel Holtmann 1770a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) 1771a9de9248SMarcel Holtmann { 1772a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1773a9de9248SMarcel Holtmann } 1774a9de9248SMarcel Holtmann 1775a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1776a9de9248SMarcel Holtmann { 1777a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1778a9de9248SMarcel Holtmann } 1779a9de9248SMarcel Holtmann 1780a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1781a9de9248SMarcel Holtmann { 1782a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 1783a9de9248SMarcel Holtmann __u16 opcode; 1784a9de9248SMarcel Holtmann 1785a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 1786a9de9248SMarcel Holtmann 1787a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 1788a9de9248SMarcel Holtmann 1789a9de9248SMarcel Holtmann switch (opcode) { 1790a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 1791a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 1792a9de9248SMarcel Holtmann break; 1793a9de9248SMarcel Holtmann 1794a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 1795a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 1796a9de9248SMarcel Holtmann break; 1797a9de9248SMarcel Holtmann 1798a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 1799a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 1800a9de9248SMarcel Holtmann break; 1801a9de9248SMarcel Holtmann 1802a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 1803a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 1804a9de9248SMarcel Holtmann break; 1805a9de9248SMarcel Holtmann 1806e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 1807e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 1808e4e8e37cSMarcel Holtmann break; 1809e4e8e37cSMarcel Holtmann 1810a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 1811a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 1812a9de9248SMarcel Holtmann break; 1813a9de9248SMarcel Holtmann 1814e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 1815e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 1816e4e8e37cSMarcel Holtmann break; 1817e4e8e37cSMarcel Holtmann 1818e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 1819e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 1820e4e8e37cSMarcel Holtmann break; 1821e4e8e37cSMarcel Holtmann 1822a9de9248SMarcel Holtmann case HCI_OP_RESET: 1823a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 1824a9de9248SMarcel Holtmann break; 1825a9de9248SMarcel Holtmann 1826a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 1827a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 1828a9de9248SMarcel Holtmann break; 1829a9de9248SMarcel Holtmann 1830a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 1831a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 1832a9de9248SMarcel Holtmann break; 1833a9de9248SMarcel Holtmann 1834a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 1835a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 1836a9de9248SMarcel Holtmann break; 1837a9de9248SMarcel Holtmann 1838a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 1839a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 1840a9de9248SMarcel Holtmann break; 1841a9de9248SMarcel Holtmann 1842a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 1843a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 1844a9de9248SMarcel Holtmann break; 1845a9de9248SMarcel Holtmann 1846a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 1847a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 1848a9de9248SMarcel Holtmann break; 1849a9de9248SMarcel Holtmann 1850a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 1851a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 1852a9de9248SMarcel Holtmann break; 1853a9de9248SMarcel Holtmann 1854a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 1855a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 1856a9de9248SMarcel Holtmann break; 1857a9de9248SMarcel Holtmann 1858a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 1859a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 1860a9de9248SMarcel Holtmann break; 1861a9de9248SMarcel Holtmann 1862a9de9248SMarcel Holtmann case HCI_OP_HOST_BUFFER_SIZE: 1863a9de9248SMarcel Holtmann hci_cc_host_buffer_size(hdev, skb); 1864a9de9248SMarcel Holtmann break; 1865a9de9248SMarcel Holtmann 1866333140b5SMarcel Holtmann case HCI_OP_READ_SSP_MODE: 1867333140b5SMarcel Holtmann hci_cc_read_ssp_mode(hdev, skb); 1868333140b5SMarcel Holtmann break; 1869333140b5SMarcel Holtmann 1870333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 1871333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 1872333140b5SMarcel Holtmann break; 1873333140b5SMarcel Holtmann 1874a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 1875a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 1876a9de9248SMarcel Holtmann break; 1877a9de9248SMarcel Holtmann 1878a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 1879a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 1880a9de9248SMarcel Holtmann break; 1881a9de9248SMarcel Holtmann 1882a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 1883a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 1884a9de9248SMarcel Holtmann break; 1885a9de9248SMarcel Holtmann 1886971e3a4bSAndre Guedes case HCI_OP_READ_LOCAL_EXT_FEATURES: 1887971e3a4bSAndre Guedes hci_cc_read_local_ext_features(hdev, skb); 1888971e3a4bSAndre Guedes break; 1889971e3a4bSAndre Guedes 1890a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 1891a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 1892a9de9248SMarcel Holtmann break; 1893a9de9248SMarcel Holtmann 1894a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 1895a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 1896a9de9248SMarcel Holtmann break; 1897a9de9248SMarcel Holtmann 189823bb5763SJohan Hedberg case HCI_OP_WRITE_CA_TIMEOUT: 189923bb5763SJohan Hedberg hci_cc_write_ca_timeout(hdev, skb); 190023bb5763SJohan Hedberg break; 190123bb5763SJohan Hedberg 1902b0916ea0SJohan Hedberg case HCI_OP_DELETE_STORED_LINK_KEY: 1903b0916ea0SJohan Hedberg hci_cc_delete_stored_link_key(hdev, skb); 1904b0916ea0SJohan Hedberg break; 1905b0916ea0SJohan Hedberg 1906d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_MASK: 1907d5859e22SJohan Hedberg hci_cc_set_event_mask(hdev, skb); 1908d5859e22SJohan Hedberg break; 1909d5859e22SJohan Hedberg 1910d5859e22SJohan Hedberg case HCI_OP_WRITE_INQUIRY_MODE: 1911d5859e22SJohan Hedberg hci_cc_write_inquiry_mode(hdev, skb); 1912d5859e22SJohan Hedberg break; 1913d5859e22SJohan Hedberg 1914d5859e22SJohan Hedberg case HCI_OP_READ_INQ_RSP_TX_POWER: 1915d5859e22SJohan Hedberg hci_cc_read_inq_rsp_tx_power(hdev, skb); 1916d5859e22SJohan Hedberg break; 1917d5859e22SJohan Hedberg 1918d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_FLT: 1919d5859e22SJohan Hedberg hci_cc_set_event_flt(hdev, skb); 1920d5859e22SJohan Hedberg break; 1921d5859e22SJohan Hedberg 1922980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_REPLY: 1923980e1a53SJohan Hedberg hci_cc_pin_code_reply(hdev, skb); 1924980e1a53SJohan Hedberg break; 1925980e1a53SJohan Hedberg 1926980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_NEG_REPLY: 1927980e1a53SJohan Hedberg hci_cc_pin_code_neg_reply(hdev, skb); 1928980e1a53SJohan Hedberg break; 1929980e1a53SJohan Hedberg 1930c35938b2SSzymon Janc case HCI_OP_READ_LOCAL_OOB_DATA: 1931c35938b2SSzymon Janc hci_cc_read_local_oob_data_reply(hdev, skb); 1932c35938b2SSzymon Janc break; 1933c35938b2SSzymon Janc 19346ed58ec5SVille Tervo case HCI_OP_LE_READ_BUFFER_SIZE: 19356ed58ec5SVille Tervo hci_cc_le_read_buffer_size(hdev, skb); 19366ed58ec5SVille Tervo break; 19376ed58ec5SVille Tervo 1938a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_REPLY: 1939a5c29683SJohan Hedberg hci_cc_user_confirm_reply(hdev, skb); 1940a5c29683SJohan Hedberg break; 1941a5c29683SJohan Hedberg 1942a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_NEG_REPLY: 1943a5c29683SJohan Hedberg hci_cc_user_confirm_neg_reply(hdev, skb); 1944a5c29683SJohan Hedberg break; 1945a5c29683SJohan Hedberg 1946eb9d91f5SAndre Guedes case HCI_OP_LE_SET_SCAN_ENABLE: 1947eb9d91f5SAndre Guedes hci_cc_le_set_scan_enable(hdev, skb); 1948eb9d91f5SAndre Guedes break; 1949eb9d91f5SAndre Guedes 1950a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_REPLY: 1951a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_reply(hdev, skb); 1952a7a595f6SVinicius Costa Gomes break; 1953a7a595f6SVinicius Costa Gomes 1954a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_NEG_REPLY: 1955a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_neg_reply(hdev, skb); 1956a7a595f6SVinicius Costa Gomes break; 1957a7a595f6SVinicius Costa Gomes 1958f9b49306SAndre Guedes case HCI_OP_WRITE_LE_HOST_SUPPORTED: 1959f9b49306SAndre Guedes hci_cc_write_le_host_supported(hdev, skb); 1960f9b49306SAndre Guedes break; 1961f9b49306SAndre Guedes 1962a9de9248SMarcel Holtmann default: 1963a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 1964a9de9248SMarcel Holtmann break; 1965a9de9248SMarcel Holtmann } 1966a9de9248SMarcel Holtmann 19676bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 19686bd32326SVille Tervo del_timer(&hdev->cmd_timer); 19696bd32326SVille Tervo 1970a9de9248SMarcel Holtmann if (ev->ncmd) { 1971a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 1972a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 1973c78ae283SMarcel Holtmann tasklet_schedule(&hdev->cmd_task); 1974a9de9248SMarcel Holtmann } 1975a9de9248SMarcel Holtmann } 1976a9de9248SMarcel Holtmann 1977a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 1978a9de9248SMarcel Holtmann { 1979a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 1980a9de9248SMarcel Holtmann __u16 opcode; 1981a9de9248SMarcel Holtmann 1982a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 1983a9de9248SMarcel Holtmann 1984a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 1985a9de9248SMarcel Holtmann 1986a9de9248SMarcel Holtmann switch (opcode) { 1987a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 1988a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 1989a9de9248SMarcel Holtmann break; 1990a9de9248SMarcel Holtmann 1991a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 1992a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 1993a9de9248SMarcel Holtmann break; 1994a9de9248SMarcel Holtmann 1995a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 1996a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 1997a9de9248SMarcel Holtmann break; 1998a9de9248SMarcel Holtmann 1999f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 2000f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 2001f8558555SMarcel Holtmann break; 2002f8558555SMarcel Holtmann 2003f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 2004f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 2005f8558555SMarcel Holtmann break; 2006f8558555SMarcel Holtmann 2007a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 2008a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 2009a9de9248SMarcel Holtmann break; 2010a9de9248SMarcel Holtmann 2011769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 2012769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 2013769be974SMarcel Holtmann break; 2014769be974SMarcel Holtmann 2015769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 2016769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 2017769be974SMarcel Holtmann break; 2018769be974SMarcel Holtmann 2019a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 2020a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 2021a9de9248SMarcel Holtmann break; 2022a9de9248SMarcel Holtmann 2023a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 2024a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 2025a9de9248SMarcel Holtmann break; 2026a9de9248SMarcel Holtmann 2027a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 2028a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 2029a9de9248SMarcel Holtmann break; 2030a9de9248SMarcel Holtmann 20318962ee74SJohan Hedberg case HCI_OP_DISCONNECT: 20328962ee74SJohan Hedberg if (ev->status != 0) 20338962ee74SJohan Hedberg mgmt_disconnect_failed(hdev->id); 20348962ee74SJohan Hedberg break; 20358962ee74SJohan Hedberg 2036fcd89c09SVille Tervo case HCI_OP_LE_CREATE_CONN: 2037fcd89c09SVille Tervo hci_cs_le_create_conn(hdev, ev->status); 2038fcd89c09SVille Tervo break; 2039fcd89c09SVille Tervo 2040a7a595f6SVinicius Costa Gomes case HCI_OP_LE_START_ENC: 2041a7a595f6SVinicius Costa Gomes hci_cs_le_start_enc(hdev, ev->status); 2042a7a595f6SVinicius Costa Gomes break; 2043a7a595f6SVinicius Costa Gomes 2044a9de9248SMarcel Holtmann default: 2045a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 2046a9de9248SMarcel Holtmann break; 2047a9de9248SMarcel Holtmann } 2048a9de9248SMarcel Holtmann 20496bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 20506bd32326SVille Tervo del_timer(&hdev->cmd_timer); 20516bd32326SVille Tervo 205210572132SGustavo F. Padovan if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2053a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2054a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2055c78ae283SMarcel Holtmann tasklet_schedule(&hdev->cmd_task); 2056a9de9248SMarcel Holtmann } 2057a9de9248SMarcel Holtmann } 2058a9de9248SMarcel Holtmann 2059a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2060a9de9248SMarcel Holtmann { 2061a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 2062a9de9248SMarcel Holtmann struct hci_conn *conn; 2063a9de9248SMarcel Holtmann 2064a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2065a9de9248SMarcel Holtmann 2066a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2067a9de9248SMarcel Holtmann 2068a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2069a9de9248SMarcel Holtmann if (conn) { 2070a9de9248SMarcel Holtmann if (!ev->status) { 2071a9de9248SMarcel Holtmann if (ev->role) 2072a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_MASTER; 2073a9de9248SMarcel Holtmann else 2074a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_MASTER; 2075a9de9248SMarcel Holtmann } 2076a9de9248SMarcel Holtmann 2077a9de9248SMarcel Holtmann clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend); 2078a9de9248SMarcel Holtmann 2079a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 2080a9de9248SMarcel Holtmann } 2081a9de9248SMarcel Holtmann 2082a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2083a9de9248SMarcel Holtmann } 2084a9de9248SMarcel Holtmann 20851da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 20861da177e4SLinus Torvalds { 2087a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 20881ebb9252SMarcel Holtmann __le16 *ptr; 20891da177e4SLinus Torvalds int i; 20901da177e4SLinus Torvalds 20911da177e4SLinus Torvalds skb_pull(skb, sizeof(*ev)); 20921da177e4SLinus Torvalds 20931da177e4SLinus Torvalds BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 20941da177e4SLinus Torvalds 20951da177e4SLinus Torvalds if (skb->len < ev->num_hndl * 4) { 20961da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 20971da177e4SLinus Torvalds return; 20981da177e4SLinus Torvalds } 20991da177e4SLinus Torvalds 21001da177e4SLinus Torvalds tasklet_disable(&hdev->tx_task); 21011da177e4SLinus Torvalds 21021ebb9252SMarcel Holtmann for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) { 21031da177e4SLinus Torvalds struct hci_conn *conn; 21041da177e4SLinus Torvalds __u16 handle, count; 21051da177e4SLinus Torvalds 210683985319SHarvey Harrison handle = get_unaligned_le16(ptr++); 210783985319SHarvey Harrison count = get_unaligned_le16(ptr++); 21081da177e4SLinus Torvalds 21091da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 21101da177e4SLinus Torvalds if (conn) { 21111da177e4SLinus Torvalds conn->sent -= count; 21121da177e4SLinus Torvalds 21135b7f9909SMarcel Holtmann if (conn->type == ACL_LINK) { 211470f23020SAndrei Emeltchenko hdev->acl_cnt += count; 211570f23020SAndrei Emeltchenko if (hdev->acl_cnt > hdev->acl_pkts) 21161da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 21176ed58ec5SVille Tervo } else if (conn->type == LE_LINK) { 21186ed58ec5SVille Tervo if (hdev->le_pkts) { 21196ed58ec5SVille Tervo hdev->le_cnt += count; 21206ed58ec5SVille Tervo if (hdev->le_cnt > hdev->le_pkts) 21216ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 21226ed58ec5SVille Tervo } else { 21236ed58ec5SVille Tervo hdev->acl_cnt += count; 21246ed58ec5SVille Tervo if (hdev->acl_cnt > hdev->acl_pkts) 21256ed58ec5SVille Tervo hdev->acl_cnt = hdev->acl_pkts; 21266ed58ec5SVille Tervo } 21275b7f9909SMarcel Holtmann } else { 212870f23020SAndrei Emeltchenko hdev->sco_cnt += count; 212970f23020SAndrei Emeltchenko if (hdev->sco_cnt > hdev->sco_pkts) 21305b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 21311da177e4SLinus Torvalds } 21321da177e4SLinus Torvalds } 21331da177e4SLinus Torvalds } 2134a9de9248SMarcel Holtmann 2135c78ae283SMarcel Holtmann tasklet_schedule(&hdev->tx_task); 21361da177e4SLinus Torvalds 21371da177e4SLinus Torvalds tasklet_enable(&hdev->tx_task); 21381da177e4SLinus Torvalds } 21391da177e4SLinus Torvalds 214004837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 21411da177e4SLinus Torvalds { 2142a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 214304837f64SMarcel Holtmann struct hci_conn *conn; 21441da177e4SLinus Torvalds 21451da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 21461da177e4SLinus Torvalds 21471da177e4SLinus Torvalds hci_dev_lock(hdev); 21481da177e4SLinus Torvalds 214904837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 215004837f64SMarcel Holtmann if (conn) { 215104837f64SMarcel Holtmann conn->mode = ev->mode; 215204837f64SMarcel Holtmann conn->interval = __le16_to_cpu(ev->interval); 215304837f64SMarcel Holtmann 215404837f64SMarcel Holtmann if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) { 215504837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 215604837f64SMarcel Holtmann conn->power_save = 1; 215704837f64SMarcel Holtmann else 215804837f64SMarcel Holtmann conn->power_save = 0; 215904837f64SMarcel Holtmann } 2160e73439d8SMarcel Holtmann 2161e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 2162e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 216304837f64SMarcel Holtmann } 216404837f64SMarcel Holtmann 216504837f64SMarcel Holtmann hci_dev_unlock(hdev); 216604837f64SMarcel Holtmann } 216704837f64SMarcel Holtmann 21681da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 21691da177e4SLinus Torvalds { 2170052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 2171052b30b0SMarcel Holtmann struct hci_conn *conn; 2172052b30b0SMarcel Holtmann 2173a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2174052b30b0SMarcel Holtmann 2175052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2176052b30b0SMarcel Holtmann 2177052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 21783d7a9d1cSMarcel Holtmann if (conn && conn->state == BT_CONNECTED) { 2179052b30b0SMarcel Holtmann hci_conn_hold(conn); 2180052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 2181052b30b0SMarcel Holtmann hci_conn_put(conn); 2182052b30b0SMarcel Holtmann } 2183052b30b0SMarcel Holtmann 218403b555e1SJohan Hedberg if (!test_bit(HCI_PAIRABLE, &hdev->flags)) 218503b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 218603b555e1SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 2187582fbe9eSJohan Hedberg else if (test_bit(HCI_MGMT, &hdev->flags)) { 2188a770bb5aSWaldemar Rymarkiewicz u8 secure; 2189a770bb5aSWaldemar Rymarkiewicz 2190a770bb5aSWaldemar Rymarkiewicz if (conn->pending_sec_level == BT_SECURITY_HIGH) 2191a770bb5aSWaldemar Rymarkiewicz secure = 1; 2192a770bb5aSWaldemar Rymarkiewicz else 2193a770bb5aSWaldemar Rymarkiewicz secure = 0; 2194a770bb5aSWaldemar Rymarkiewicz 2195a770bb5aSWaldemar Rymarkiewicz mgmt_pin_code_request(hdev->id, &ev->bdaddr, secure); 2196a770bb5aSWaldemar Rymarkiewicz } 2197980e1a53SJohan Hedberg 2198052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 21991da177e4SLinus Torvalds } 22001da177e4SLinus Torvalds 22011da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 22021da177e4SLinus Torvalds { 220355ed8ca1SJohan Hedberg struct hci_ev_link_key_req *ev = (void *) skb->data; 220455ed8ca1SJohan Hedberg struct hci_cp_link_key_reply cp; 220555ed8ca1SJohan Hedberg struct hci_conn *conn; 220655ed8ca1SJohan Hedberg struct link_key *key; 220755ed8ca1SJohan Hedberg 2208a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 220955ed8ca1SJohan Hedberg 221055ed8ca1SJohan Hedberg if (!test_bit(HCI_LINK_KEYS, &hdev->flags)) 221155ed8ca1SJohan Hedberg return; 221255ed8ca1SJohan Hedberg 221355ed8ca1SJohan Hedberg hci_dev_lock(hdev); 221455ed8ca1SJohan Hedberg 221555ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, &ev->bdaddr); 221655ed8ca1SJohan Hedberg if (!key) { 221755ed8ca1SJohan Hedberg BT_DBG("%s link key not found for %s", hdev->name, 221855ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 221955ed8ca1SJohan Hedberg goto not_found; 222055ed8ca1SJohan Hedberg } 222155ed8ca1SJohan Hedberg 222255ed8ca1SJohan Hedberg BT_DBG("%s found key type %u for %s", hdev->name, key->type, 222355ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 222455ed8ca1SJohan Hedberg 2225b6020ba0SWaldemar Rymarkiewicz if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) && 2226b6020ba0SWaldemar Rymarkiewicz key->type == HCI_LK_DEBUG_COMBINATION) { 222755ed8ca1SJohan Hedberg BT_DBG("%s ignoring debug key", hdev->name); 222855ed8ca1SJohan Hedberg goto not_found; 222955ed8ca1SJohan Hedberg } 223055ed8ca1SJohan Hedberg 223155ed8ca1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 223260b83f57SWaldemar Rymarkiewicz if (conn) { 223360b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_UNAUTH_COMBINATION && 223460b83f57SWaldemar Rymarkiewicz conn->auth_type != 0xff && 223560b83f57SWaldemar Rymarkiewicz (conn->auth_type & 0x01)) { 223655ed8ca1SJohan Hedberg BT_DBG("%s ignoring unauthenticated key", hdev->name); 223755ed8ca1SJohan Hedberg goto not_found; 223855ed8ca1SJohan Hedberg } 223955ed8ca1SJohan Hedberg 224060b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && 224160b83f57SWaldemar Rymarkiewicz conn->pending_sec_level == BT_SECURITY_HIGH) { 224260b83f57SWaldemar Rymarkiewicz BT_DBG("%s ignoring key unauthenticated for high \ 224360b83f57SWaldemar Rymarkiewicz security", hdev->name); 224460b83f57SWaldemar Rymarkiewicz goto not_found; 224560b83f57SWaldemar Rymarkiewicz } 224660b83f57SWaldemar Rymarkiewicz 224760b83f57SWaldemar Rymarkiewicz conn->key_type = key->type; 224860b83f57SWaldemar Rymarkiewicz conn->pin_length = key->pin_len; 224960b83f57SWaldemar Rymarkiewicz } 225060b83f57SWaldemar Rymarkiewicz 225155ed8ca1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 225255ed8ca1SJohan Hedberg memcpy(cp.link_key, key->val, 16); 225355ed8ca1SJohan Hedberg 225455ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 225555ed8ca1SJohan Hedberg 225655ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 225755ed8ca1SJohan Hedberg 225855ed8ca1SJohan Hedberg return; 225955ed8ca1SJohan Hedberg 226055ed8ca1SJohan Hedberg not_found: 226155ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 226255ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 22631da177e4SLinus Torvalds } 22641da177e4SLinus Torvalds 22651da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 22661da177e4SLinus Torvalds { 2267052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 2268052b30b0SMarcel Holtmann struct hci_conn *conn; 226955ed8ca1SJohan Hedberg u8 pin_len = 0; 2270052b30b0SMarcel Holtmann 2271a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2272052b30b0SMarcel Holtmann 2273052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2274052b30b0SMarcel Holtmann 2275052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2276052b30b0SMarcel Holtmann if (conn) { 2277052b30b0SMarcel Holtmann hci_conn_hold(conn); 2278052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2279980e1a53SJohan Hedberg pin_len = conn->pin_length; 228013d39315SWaldemar Rymarkiewicz 228113d39315SWaldemar Rymarkiewicz if (ev->key_type != HCI_LK_CHANGED_COMBINATION) 228213d39315SWaldemar Rymarkiewicz conn->key_type = ev->key_type; 228313d39315SWaldemar Rymarkiewicz 2284052b30b0SMarcel Holtmann hci_conn_put(conn); 2285052b30b0SMarcel Holtmann } 2286052b30b0SMarcel Holtmann 228755ed8ca1SJohan Hedberg if (test_bit(HCI_LINK_KEYS, &hdev->flags)) 2288d25e28abSJohan Hedberg hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, 228955ed8ca1SJohan Hedberg ev->key_type, pin_len); 229055ed8ca1SJohan Hedberg 2291052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 22921da177e4SLinus Torvalds } 22931da177e4SLinus Torvalds 229404837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 229504837f64SMarcel Holtmann { 2296a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 229704837f64SMarcel Holtmann struct hci_conn *conn; 229804837f64SMarcel Holtmann 229904837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 230004837f64SMarcel Holtmann 230104837f64SMarcel Holtmann hci_dev_lock(hdev); 230204837f64SMarcel Holtmann 230304837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 23041da177e4SLinus Torvalds if (conn && !ev->status) { 23051da177e4SLinus Torvalds struct inquiry_entry *ie; 23061da177e4SLinus Torvalds 2307cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2308cc11b9c1SAndrei Emeltchenko if (ie) { 23091da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 23101da177e4SLinus Torvalds ie->timestamp = jiffies; 23111da177e4SLinus Torvalds } 23121da177e4SLinus Torvalds } 23131da177e4SLinus Torvalds 23141da177e4SLinus Torvalds hci_dev_unlock(hdev); 23151da177e4SLinus Torvalds } 23161da177e4SLinus Torvalds 2317a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2318a8746417SMarcel Holtmann { 2319a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 2320a8746417SMarcel Holtmann struct hci_conn *conn; 2321a8746417SMarcel Holtmann 2322a8746417SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2323a8746417SMarcel Holtmann 2324a8746417SMarcel Holtmann hci_dev_lock(hdev); 2325a8746417SMarcel Holtmann 2326a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2327a8746417SMarcel Holtmann if (conn && !ev->status) 2328a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 2329a8746417SMarcel Holtmann 2330a8746417SMarcel Holtmann hci_dev_unlock(hdev); 2331a8746417SMarcel Holtmann } 2332a8746417SMarcel Holtmann 233385a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 233485a1e930SMarcel Holtmann { 2335a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 233685a1e930SMarcel Holtmann struct inquiry_entry *ie; 233785a1e930SMarcel Holtmann 233885a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 233985a1e930SMarcel Holtmann 234085a1e930SMarcel Holtmann hci_dev_lock(hdev); 234185a1e930SMarcel Holtmann 2342cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2343cc11b9c1SAndrei Emeltchenko if (ie) { 234485a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 234585a1e930SMarcel Holtmann ie->timestamp = jiffies; 234685a1e930SMarcel Holtmann } 234785a1e930SMarcel Holtmann 234885a1e930SMarcel Holtmann hci_dev_unlock(hdev); 234985a1e930SMarcel Holtmann } 235085a1e930SMarcel Holtmann 2351a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb) 2352a9de9248SMarcel Holtmann { 2353a9de9248SMarcel Holtmann struct inquiry_data data; 2354a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2355a9de9248SMarcel Holtmann 2356a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2357a9de9248SMarcel Holtmann 2358a9de9248SMarcel Holtmann if (!num_rsp) 2359a9de9248SMarcel Holtmann return; 2360a9de9248SMarcel Holtmann 2361a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2362a9de9248SMarcel Holtmann 2363314b2381SJohan Hedberg if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) { 2364314b2381SJohan Hedberg 2365314b2381SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 2366314b2381SJohan Hedberg mgmt_discovering(hdev->id, 1); 2367314b2381SJohan Hedberg } 2368314b2381SJohan Hedberg 2369a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 2370138d22efSSzymon Janc struct inquiry_info_with_rssi_and_pscan_mode *info; 2371138d22efSSzymon Janc info = (void *) (skb->data + 1); 2372a9de9248SMarcel Holtmann 2373e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2374a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2375a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2376a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2377a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 2378a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2379a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2380a9de9248SMarcel Holtmann data.rssi = info->rssi; 238141a96212SMarcel Holtmann data.ssp_mode = 0x00; 2382a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 2383e17acd40SJohan Hedberg mgmt_device_found(hdev->id, &info->bdaddr, 2384e17acd40SJohan Hedberg info->dev_class, info->rssi, 2385e17acd40SJohan Hedberg NULL); 2386a9de9248SMarcel Holtmann } 2387a9de9248SMarcel Holtmann } else { 2388a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 2389a9de9248SMarcel Holtmann 2390e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2391a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2392a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2393a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2394a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2395a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2396a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2397a9de9248SMarcel Holtmann data.rssi = info->rssi; 239841a96212SMarcel Holtmann data.ssp_mode = 0x00; 2399a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 2400e17acd40SJohan Hedberg mgmt_device_found(hdev->id, &info->bdaddr, 2401e17acd40SJohan Hedberg info->dev_class, info->rssi, 2402e17acd40SJohan Hedberg NULL); 2403a9de9248SMarcel Holtmann } 2404a9de9248SMarcel Holtmann } 2405a9de9248SMarcel Holtmann 2406a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2407a9de9248SMarcel Holtmann } 2408a9de9248SMarcel Holtmann 2409a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 2410a9de9248SMarcel Holtmann { 241141a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 241241a96212SMarcel Holtmann struct hci_conn *conn; 241341a96212SMarcel Holtmann 2414a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 241541a96212SMarcel Holtmann 241641a96212SMarcel Holtmann hci_dev_lock(hdev); 241741a96212SMarcel Holtmann 241841a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2419ccd556feSJohan Hedberg if (!conn) 2420ccd556feSJohan Hedberg goto unlock; 2421ccd556feSJohan Hedberg 2422769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 242341a96212SMarcel Holtmann struct inquiry_entry *ie; 242441a96212SMarcel Holtmann 2425cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2426cc11b9c1SAndrei Emeltchenko if (ie) 242741a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 242841a96212SMarcel Holtmann 242941a96212SMarcel Holtmann conn->ssp_mode = (ev->features[0] & 0x01); 243041a96212SMarcel Holtmann } 243141a96212SMarcel Holtmann 2432ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2433ccd556feSJohan Hedberg goto unlock; 2434ccd556feSJohan Hedberg 2435127178d2SJohan Hedberg if (!ev->status) { 2436127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2437127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2438127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2439127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2440127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2441127178d2SJohan Hedberg } 2442392599b9SJohan Hedberg 2443127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2444769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2445769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2446769be974SMarcel Holtmann hci_conn_put(conn); 2447769be974SMarcel Holtmann } 2448769be974SMarcel Holtmann 2449ccd556feSJohan Hedberg unlock: 245041a96212SMarcel Holtmann hci_dev_unlock(hdev); 2451a9de9248SMarcel Holtmann } 2452a9de9248SMarcel Holtmann 2453a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2454a9de9248SMarcel Holtmann { 2455b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 2456b6a0dc82SMarcel Holtmann struct hci_conn *conn; 2457b6a0dc82SMarcel Holtmann 2458b6a0dc82SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2459b6a0dc82SMarcel Holtmann 2460b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 2461b6a0dc82SMarcel Holtmann 2462b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 24639dc0a3afSMarcel Holtmann if (!conn) { 24649dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 24659dc0a3afSMarcel Holtmann goto unlock; 24669dc0a3afSMarcel Holtmann 24679dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 2468b6a0dc82SMarcel Holtmann if (!conn) 2469b6a0dc82SMarcel Holtmann goto unlock; 2470b6a0dc82SMarcel Holtmann 24719dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 24729dc0a3afSMarcel Holtmann } 24739dc0a3afSMarcel Holtmann 2474732547f9SMarcel Holtmann switch (ev->status) { 2475732547f9SMarcel Holtmann case 0x00: 2476732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 2477732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 2478732547f9SMarcel Holtmann 24799eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 2480732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 2481732547f9SMarcel Holtmann break; 2482732547f9SMarcel Holtmann 2483705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 2484732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 24851038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 2486732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 2487732547f9SMarcel Holtmann if (conn->out && conn->attempt < 2) { 2488efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 2489efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 2490efc7688bSMarcel Holtmann hci_setup_sync(conn, conn->link->handle); 2491efc7688bSMarcel Holtmann goto unlock; 2492efc7688bSMarcel Holtmann } 2493732547f9SMarcel Holtmann /* fall through */ 2494efc7688bSMarcel Holtmann 2495732547f9SMarcel Holtmann default: 2496b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 2497732547f9SMarcel Holtmann break; 2498732547f9SMarcel Holtmann } 2499b6a0dc82SMarcel Holtmann 2500b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2501b6a0dc82SMarcel Holtmann if (ev->status) 2502b6a0dc82SMarcel Holtmann hci_conn_del(conn); 2503b6a0dc82SMarcel Holtmann 2504b6a0dc82SMarcel Holtmann unlock: 2505b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 2506a9de9248SMarcel Holtmann } 2507a9de9248SMarcel Holtmann 2508a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) 2509a9de9248SMarcel Holtmann { 2510a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2511a9de9248SMarcel Holtmann } 2512a9de9248SMarcel Holtmann 251304837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) 251404837f64SMarcel Holtmann { 2515a9de9248SMarcel Holtmann struct hci_ev_sniff_subrate *ev = (void *) skb->data; 251604837f64SMarcel Holtmann 251704837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 251804837f64SMarcel Holtmann } 251904837f64SMarcel Holtmann 2520a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 2521a9de9248SMarcel Holtmann { 2522a9de9248SMarcel Holtmann struct inquiry_data data; 2523a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 2524a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2525a9de9248SMarcel Holtmann 2526a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2527a9de9248SMarcel Holtmann 2528a9de9248SMarcel Holtmann if (!num_rsp) 2529a9de9248SMarcel Holtmann return; 2530a9de9248SMarcel Holtmann 2531314b2381SJohan Hedberg if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) { 2532314b2381SJohan Hedberg 2533314b2381SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 2534314b2381SJohan Hedberg mgmt_discovering(hdev->id, 1); 2535314b2381SJohan Hedberg } 2536314b2381SJohan Hedberg 2537a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2538a9de9248SMarcel Holtmann 2539e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2540a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2541a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2542a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2543a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2544a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2545a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2546a9de9248SMarcel Holtmann data.rssi = info->rssi; 254741a96212SMarcel Holtmann data.ssp_mode = 0x01; 2548a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 2549e17acd40SJohan Hedberg mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class, 2550e17acd40SJohan Hedberg info->rssi, info->data); 2551a9de9248SMarcel Holtmann } 2552a9de9248SMarcel Holtmann 2553a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2554a9de9248SMarcel Holtmann } 2555a9de9248SMarcel Holtmann 255617fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn) 255717fa4b9dSJohan Hedberg { 255817fa4b9dSJohan Hedberg /* If remote requests dedicated bonding follow that lead */ 255917fa4b9dSJohan Hedberg if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) { 256017fa4b9dSJohan Hedberg /* If both remote and local IO capabilities allow MITM 256117fa4b9dSJohan Hedberg * protection then require it, otherwise don't */ 256217fa4b9dSJohan Hedberg if (conn->remote_cap == 0x03 || conn->io_capability == 0x03) 256317fa4b9dSJohan Hedberg return 0x02; 256417fa4b9dSJohan Hedberg else 256517fa4b9dSJohan Hedberg return 0x03; 256617fa4b9dSJohan Hedberg } 256717fa4b9dSJohan Hedberg 256817fa4b9dSJohan Hedberg /* If remote requests no-bonding follow that lead */ 256917fa4b9dSJohan Hedberg if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01) 257058797bf7SWaldemar Rymarkiewicz return conn->remote_auth | (conn->auth_type & 0x01); 257117fa4b9dSJohan Hedberg 257217fa4b9dSJohan Hedberg return conn->auth_type; 257317fa4b9dSJohan Hedberg } 257417fa4b9dSJohan Hedberg 25750493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 25760493684eSMarcel Holtmann { 25770493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 25780493684eSMarcel Holtmann struct hci_conn *conn; 25790493684eSMarcel Holtmann 25800493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 25810493684eSMarcel Holtmann 25820493684eSMarcel Holtmann hci_dev_lock(hdev); 25830493684eSMarcel Holtmann 25840493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 258503b555e1SJohan Hedberg if (!conn) 258603b555e1SJohan Hedberg goto unlock; 258703b555e1SJohan Hedberg 25880493684eSMarcel Holtmann hci_conn_hold(conn); 25890493684eSMarcel Holtmann 259003b555e1SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->flags)) 259103b555e1SJohan Hedberg goto unlock; 259203b555e1SJohan Hedberg 259303b555e1SJohan Hedberg if (test_bit(HCI_PAIRABLE, &hdev->flags) || 259403b555e1SJohan Hedberg (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 259517fa4b9dSJohan Hedberg struct hci_cp_io_capability_reply cp; 259617fa4b9dSJohan Hedberg 259717fa4b9dSJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 259817fa4b9dSJohan Hedberg cp.capability = conn->io_capability; 25997cbc9bd9SJohan Hedberg conn->auth_type = hci_get_auth_req(conn); 26007cbc9bd9SJohan Hedberg cp.authentication = conn->auth_type; 260117fa4b9dSJohan Hedberg 2602ce85ee13SSzymon Janc if ((conn->out == 0x01 || conn->remote_oob == 0x01) && 2603ce85ee13SSzymon Janc hci_find_remote_oob_data(hdev, &conn->dst)) 2604ce85ee13SSzymon Janc cp.oob_data = 0x01; 2605ce85ee13SSzymon Janc else 2606ce85ee13SSzymon Janc cp.oob_data = 0x00; 2607ce85ee13SSzymon Janc 260817fa4b9dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, 260917fa4b9dSJohan Hedberg sizeof(cp), &cp); 261003b555e1SJohan Hedberg } else { 261103b555e1SJohan Hedberg struct hci_cp_io_capability_neg_reply cp; 261203b555e1SJohan Hedberg 261303b555e1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 2614be77159cSJohan Hedberg cp.reason = 0x18; /* Pairing not allowed */ 261503b555e1SJohan Hedberg 261603b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 261703b555e1SJohan Hedberg sizeof(cp), &cp); 261803b555e1SJohan Hedberg } 261903b555e1SJohan Hedberg 262003b555e1SJohan Hedberg unlock: 262103b555e1SJohan Hedberg hci_dev_unlock(hdev); 262203b555e1SJohan Hedberg } 262303b555e1SJohan Hedberg 262403b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 262503b555e1SJohan Hedberg { 262603b555e1SJohan Hedberg struct hci_ev_io_capa_reply *ev = (void *) skb->data; 262703b555e1SJohan Hedberg struct hci_conn *conn; 262803b555e1SJohan Hedberg 262903b555e1SJohan Hedberg BT_DBG("%s", hdev->name); 263003b555e1SJohan Hedberg 263103b555e1SJohan Hedberg hci_dev_lock(hdev); 263203b555e1SJohan Hedberg 263303b555e1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 263403b555e1SJohan Hedberg if (!conn) 263503b555e1SJohan Hedberg goto unlock; 263603b555e1SJohan Hedberg 263703b555e1SJohan Hedberg conn->remote_cap = ev->capability; 263803b555e1SJohan Hedberg conn->remote_oob = ev->oob_data; 263903b555e1SJohan Hedberg conn->remote_auth = ev->authentication; 264003b555e1SJohan Hedberg 264103b555e1SJohan Hedberg unlock: 26420493684eSMarcel Holtmann hci_dev_unlock(hdev); 26430493684eSMarcel Holtmann } 26440493684eSMarcel Holtmann 2645a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev, 2646a5c29683SJohan Hedberg struct sk_buff *skb) 2647a5c29683SJohan Hedberg { 2648a5c29683SJohan Hedberg struct hci_ev_user_confirm_req *ev = (void *) skb->data; 264955bc1a37SJohan Hedberg int loc_mitm, rem_mitm, confirm_hint = 0; 26507a828908SJohan Hedberg struct hci_conn *conn; 2651a5c29683SJohan Hedberg 2652a5c29683SJohan Hedberg BT_DBG("%s", hdev->name); 2653a5c29683SJohan Hedberg 2654a5c29683SJohan Hedberg hci_dev_lock(hdev); 2655a5c29683SJohan Hedberg 26567a828908SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->flags)) 26577a828908SJohan Hedberg goto unlock; 26587a828908SJohan Hedberg 26597a828908SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 26607a828908SJohan Hedberg if (!conn) 26617a828908SJohan Hedberg goto unlock; 26627a828908SJohan Hedberg 26637a828908SJohan Hedberg loc_mitm = (conn->auth_type & 0x01); 26647a828908SJohan Hedberg rem_mitm = (conn->remote_auth & 0x01); 26657a828908SJohan Hedberg 26667a828908SJohan Hedberg /* If we require MITM but the remote device can't provide that 26677a828908SJohan Hedberg * (it has NoInputNoOutput) then reject the confirmation 26687a828908SJohan Hedberg * request. The only exception is when we're dedicated bonding 26697a828908SJohan Hedberg * initiators (connect_cfm_cb set) since then we always have the MITM 26707a828908SJohan Hedberg * bit set. */ 26717a828908SJohan Hedberg if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) { 26727a828908SJohan Hedberg BT_DBG("Rejecting request: remote device can't provide MITM"); 26737a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, 26747a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 26757a828908SJohan Hedberg goto unlock; 26767a828908SJohan Hedberg } 26777a828908SJohan Hedberg 26787a828908SJohan Hedberg /* If no side requires MITM protection; auto-accept */ 26797a828908SJohan Hedberg if ((!loc_mitm || conn->remote_cap == 0x03) && 26807a828908SJohan Hedberg (!rem_mitm || conn->io_capability == 0x03)) { 268155bc1a37SJohan Hedberg 268255bc1a37SJohan Hedberg /* If we're not the initiators request authorization to 268355bc1a37SJohan Hedberg * proceed from user space (mgmt_user_confirm with 268455bc1a37SJohan Hedberg * confirm_hint set to 1). */ 268555bc1a37SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { 268655bc1a37SJohan Hedberg BT_DBG("Confirming auto-accept as acceptor"); 268755bc1a37SJohan Hedberg confirm_hint = 1; 268855bc1a37SJohan Hedberg goto confirm; 268955bc1a37SJohan Hedberg } 269055bc1a37SJohan Hedberg 26919f61656aSJohan Hedberg BT_DBG("Auto-accept of user confirmation with %ums delay", 26929f61656aSJohan Hedberg hdev->auto_accept_delay); 26939f61656aSJohan Hedberg 26949f61656aSJohan Hedberg if (hdev->auto_accept_delay > 0) { 26959f61656aSJohan Hedberg int delay = msecs_to_jiffies(hdev->auto_accept_delay); 26969f61656aSJohan Hedberg mod_timer(&conn->auto_accept_timer, jiffies + delay); 26979f61656aSJohan Hedberg goto unlock; 26989f61656aSJohan Hedberg } 26999f61656aSJohan Hedberg 27007a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, 27017a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 27027a828908SJohan Hedberg goto unlock; 27037a828908SJohan Hedberg } 27047a828908SJohan Hedberg 270555bc1a37SJohan Hedberg confirm: 270655bc1a37SJohan Hedberg mgmt_user_confirm_request(hdev->id, &ev->bdaddr, ev->passkey, 270755bc1a37SJohan Hedberg confirm_hint); 2708a5c29683SJohan Hedberg 27097a828908SJohan Hedberg unlock: 2710a5c29683SJohan Hedberg hci_dev_unlock(hdev); 2711a5c29683SJohan Hedberg } 2712a5c29683SJohan Hedberg 27130493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 27140493684eSMarcel Holtmann { 27150493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 27160493684eSMarcel Holtmann struct hci_conn *conn; 27170493684eSMarcel Holtmann 27180493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 27190493684eSMarcel Holtmann 27200493684eSMarcel Holtmann hci_dev_lock(hdev); 27210493684eSMarcel Holtmann 27220493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 27232a611692SJohan Hedberg if (!conn) 27242a611692SJohan Hedberg goto unlock; 27252a611692SJohan Hedberg 27262a611692SJohan Hedberg /* To avoid duplicate auth_failed events to user space we check 27272a611692SJohan Hedberg * the HCI_CONN_AUTH_PEND flag which will be set if we 27282a611692SJohan Hedberg * initiated the authentication. A traditional auth_complete 27292a611692SJohan Hedberg * event gets always produced as initiator and is also mapped to 27302a611692SJohan Hedberg * the mgmt_auth_failed event */ 27312a611692SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0) 27322a611692SJohan Hedberg mgmt_auth_failed(hdev->id, &conn->dst, ev->status); 27332a611692SJohan Hedberg 27340493684eSMarcel Holtmann hci_conn_put(conn); 27350493684eSMarcel Holtmann 27362a611692SJohan Hedberg unlock: 27370493684eSMarcel Holtmann hci_dev_unlock(hdev); 27380493684eSMarcel Holtmann } 27390493684eSMarcel Holtmann 274041a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 274141a96212SMarcel Holtmann { 274241a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 274341a96212SMarcel Holtmann struct inquiry_entry *ie; 274441a96212SMarcel Holtmann 274541a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 274641a96212SMarcel Holtmann 274741a96212SMarcel Holtmann hci_dev_lock(hdev); 274841a96212SMarcel Holtmann 2749cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2750cc11b9c1SAndrei Emeltchenko if (ie) 275141a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 275241a96212SMarcel Holtmann 275341a96212SMarcel Holtmann hci_dev_unlock(hdev); 275441a96212SMarcel Holtmann } 275541a96212SMarcel Holtmann 27562763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev, 27572763eda6SSzymon Janc struct sk_buff *skb) 27582763eda6SSzymon Janc { 27592763eda6SSzymon Janc struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; 27602763eda6SSzymon Janc struct oob_data *data; 27612763eda6SSzymon Janc 27622763eda6SSzymon Janc BT_DBG("%s", hdev->name); 27632763eda6SSzymon Janc 27642763eda6SSzymon Janc hci_dev_lock(hdev); 27652763eda6SSzymon Janc 2766e1ba1f15SSzymon Janc if (!test_bit(HCI_MGMT, &hdev->flags)) 2767e1ba1f15SSzymon Janc goto unlock; 2768e1ba1f15SSzymon Janc 27692763eda6SSzymon Janc data = hci_find_remote_oob_data(hdev, &ev->bdaddr); 27702763eda6SSzymon Janc if (data) { 27712763eda6SSzymon Janc struct hci_cp_remote_oob_data_reply cp; 27722763eda6SSzymon Janc 27732763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 27742763eda6SSzymon Janc memcpy(cp.hash, data->hash, sizeof(cp.hash)); 27752763eda6SSzymon Janc memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); 27762763eda6SSzymon Janc 27772763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), 27782763eda6SSzymon Janc &cp); 27792763eda6SSzymon Janc } else { 27802763eda6SSzymon Janc struct hci_cp_remote_oob_data_neg_reply cp; 27812763eda6SSzymon Janc 27822763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 27832763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), 27842763eda6SSzymon Janc &cp); 27852763eda6SSzymon Janc } 27862763eda6SSzymon Janc 2787e1ba1f15SSzymon Janc unlock: 27882763eda6SSzymon Janc hci_dev_unlock(hdev); 27892763eda6SSzymon Janc } 27902763eda6SSzymon Janc 2791fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2792fcd89c09SVille Tervo { 2793fcd89c09SVille Tervo struct hci_ev_le_conn_complete *ev = (void *) skb->data; 2794fcd89c09SVille Tervo struct hci_conn *conn; 2795fcd89c09SVille Tervo 2796fcd89c09SVille Tervo BT_DBG("%s status %d", hdev->name, ev->status); 2797fcd89c09SVille Tervo 2798fcd89c09SVille Tervo hci_dev_lock(hdev); 2799fcd89c09SVille Tervo 2800fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr); 2801b62f328bSVille Tervo if (!conn) { 2802b62f328bSVille Tervo conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); 2803b62f328bSVille Tervo if (!conn) { 2804b62f328bSVille Tervo BT_ERR("No memory for new connection"); 2805b62f328bSVille Tervo hci_dev_unlock(hdev); 2806b62f328bSVille Tervo return; 2807b62f328bSVille Tervo } 280829b7988aSAndre Guedes 280929b7988aSAndre Guedes conn->dst_type = ev->bdaddr_type; 2810b62f328bSVille Tervo } 2811fcd89c09SVille Tervo 2812fcd89c09SVille Tervo if (ev->status) { 281383bc71b4SVinicius Costa Gomes mgmt_connect_failed(hdev->id, &ev->bdaddr, ev->status); 2814fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 2815fcd89c09SVille Tervo conn->state = BT_CLOSED; 2816fcd89c09SVille Tervo hci_conn_del(conn); 2817fcd89c09SVille Tervo goto unlock; 2818fcd89c09SVille Tervo } 2819fcd89c09SVille Tervo 282083bc71b4SVinicius Costa Gomes mgmt_connected(hdev->id, &ev->bdaddr); 282183bc71b4SVinicius Costa Gomes 28227b5c0d52SVinicius Costa Gomes conn->sec_level = BT_SECURITY_LOW; 2823fcd89c09SVille Tervo conn->handle = __le16_to_cpu(ev->handle); 2824fcd89c09SVille Tervo conn->state = BT_CONNECTED; 2825fcd89c09SVille Tervo 2826fcd89c09SVille Tervo hci_conn_hold_device(conn); 2827fcd89c09SVille Tervo hci_conn_add_sysfs(conn); 2828fcd89c09SVille Tervo 2829fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 2830fcd89c09SVille Tervo 2831fcd89c09SVille Tervo unlock: 2832fcd89c09SVille Tervo hci_dev_unlock(hdev); 2833fcd89c09SVille Tervo } 2834fcd89c09SVille Tervo 28359aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev, 28369aa04c91SAndre Guedes struct sk_buff *skb) 28379aa04c91SAndre Guedes { 28389aa04c91SAndre Guedes struct hci_ev_le_advertising_info *ev; 28399aa04c91SAndre Guedes u8 num_reports; 28409aa04c91SAndre Guedes 28419aa04c91SAndre Guedes num_reports = skb->data[0]; 28429aa04c91SAndre Guedes ev = (void *) &skb->data[1]; 28439aa04c91SAndre Guedes 28449aa04c91SAndre Guedes hci_dev_lock(hdev); 28459aa04c91SAndre Guedes 28469aa04c91SAndre Guedes hci_add_adv_entry(hdev, ev); 28479aa04c91SAndre Guedes 28489aa04c91SAndre Guedes while (--num_reports) { 28499aa04c91SAndre Guedes ev = (void *) (ev->data + ev->length + 1); 28509aa04c91SAndre Guedes hci_add_adv_entry(hdev, ev); 28519aa04c91SAndre Guedes } 28529aa04c91SAndre Guedes 28539aa04c91SAndre Guedes hci_dev_unlock(hdev); 28549aa04c91SAndre Guedes } 28559aa04c91SAndre Guedes 2856a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev, 2857a7a595f6SVinicius Costa Gomes struct sk_buff *skb) 2858a7a595f6SVinicius Costa Gomes { 2859a7a595f6SVinicius Costa Gomes struct hci_ev_le_ltk_req *ev = (void *) skb->data; 2860a7a595f6SVinicius Costa Gomes struct hci_cp_le_ltk_reply cp; 2861a7a595f6SVinicius Costa Gomes struct hci_conn *conn; 2862a7a595f6SVinicius Costa Gomes 2863a7a595f6SVinicius Costa Gomes BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle)); 2864a7a595f6SVinicius Costa Gomes 2865a7a595f6SVinicius Costa Gomes hci_dev_lock(hdev); 2866a7a595f6SVinicius Costa Gomes 2867a7a595f6SVinicius Costa Gomes conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2868a7a595f6SVinicius Costa Gomes 2869a7a595f6SVinicius Costa Gomes memset(&cp, 0, sizeof(cp)); 2870a7a595f6SVinicius Costa Gomes cp.handle = cpu_to_le16(conn->handle); 2871a7a595f6SVinicius Costa Gomes memcpy(cp.ltk, conn->ltk, sizeof(conn->ltk)); 2872a7a595f6SVinicius Costa Gomes 2873a7a595f6SVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); 2874a7a595f6SVinicius Costa Gomes 2875a7a595f6SVinicius Costa Gomes hci_dev_unlock(hdev); 2876a7a595f6SVinicius Costa Gomes } 2877a7a595f6SVinicius Costa Gomes 2878fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 2879fcd89c09SVille Tervo { 2880fcd89c09SVille Tervo struct hci_ev_le_meta *le_ev = (void *) skb->data; 2881fcd89c09SVille Tervo 2882fcd89c09SVille Tervo skb_pull(skb, sizeof(*le_ev)); 2883fcd89c09SVille Tervo 2884fcd89c09SVille Tervo switch (le_ev->subevent) { 2885fcd89c09SVille Tervo case HCI_EV_LE_CONN_COMPLETE: 2886fcd89c09SVille Tervo hci_le_conn_complete_evt(hdev, skb); 2887fcd89c09SVille Tervo break; 2888fcd89c09SVille Tervo 28899aa04c91SAndre Guedes case HCI_EV_LE_ADVERTISING_REPORT: 28909aa04c91SAndre Guedes hci_le_adv_report_evt(hdev, skb); 28919aa04c91SAndre Guedes break; 28929aa04c91SAndre Guedes 2893a7a595f6SVinicius Costa Gomes case HCI_EV_LE_LTK_REQ: 2894a7a595f6SVinicius Costa Gomes hci_le_ltk_request_evt(hdev, skb); 2895a7a595f6SVinicius Costa Gomes break; 2896a7a595f6SVinicius Costa Gomes 2897fcd89c09SVille Tervo default: 2898fcd89c09SVille Tervo break; 2899fcd89c09SVille Tervo } 2900fcd89c09SVille Tervo } 2901fcd89c09SVille Tervo 29021da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 29031da177e4SLinus Torvalds { 2904a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 2905a9de9248SMarcel Holtmann __u8 event = hdr->evt; 29061da177e4SLinus Torvalds 29071da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 29081da177e4SLinus Torvalds 2909a9de9248SMarcel Holtmann switch (event) { 29101da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 29111da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 29121da177e4SLinus Torvalds break; 29131da177e4SLinus Torvalds 29141da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 29151da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 29161da177e4SLinus Torvalds break; 29171da177e4SLinus Torvalds 2918a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 2919a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 292021d9e30eSMarcel Holtmann break; 292121d9e30eSMarcel Holtmann 29221da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 29231da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 29241da177e4SLinus Torvalds break; 29251da177e4SLinus Torvalds 29261da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 29271da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 29281da177e4SLinus Torvalds break; 29291da177e4SLinus Torvalds 29301da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 29311da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 29321da177e4SLinus Torvalds break; 29331da177e4SLinus Torvalds 2934a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 2935a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 2936a9de9248SMarcel Holtmann break; 2937a9de9248SMarcel Holtmann 29381da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 29391da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 29401da177e4SLinus Torvalds break; 29411da177e4SLinus Torvalds 2942a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 2943a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 2944a9de9248SMarcel Holtmann break; 2945a9de9248SMarcel Holtmann 2946a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 2947a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 2948a9de9248SMarcel Holtmann break; 2949a9de9248SMarcel Holtmann 2950a9de9248SMarcel Holtmann case HCI_EV_REMOTE_VERSION: 2951a9de9248SMarcel Holtmann hci_remote_version_evt(hdev, skb); 2952a9de9248SMarcel Holtmann break; 2953a9de9248SMarcel Holtmann 2954a9de9248SMarcel Holtmann case HCI_EV_QOS_SETUP_COMPLETE: 2955a9de9248SMarcel Holtmann hci_qos_setup_complete_evt(hdev, skb); 2956a9de9248SMarcel Holtmann break; 2957a9de9248SMarcel Holtmann 2958a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 2959a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 2960a9de9248SMarcel Holtmann break; 2961a9de9248SMarcel Holtmann 2962a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 2963a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 2964a9de9248SMarcel Holtmann break; 2965a9de9248SMarcel Holtmann 2966a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 2967a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 2968a9de9248SMarcel Holtmann break; 2969a9de9248SMarcel Holtmann 2970a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 2971a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 2972a9de9248SMarcel Holtmann break; 2973a9de9248SMarcel Holtmann 2974a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 2975a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 29761da177e4SLinus Torvalds break; 29771da177e4SLinus Torvalds 29781da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 29791da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 29801da177e4SLinus Torvalds break; 29811da177e4SLinus Torvalds 29821da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 29831da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 29841da177e4SLinus Torvalds break; 29851da177e4SLinus Torvalds 29861da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 29871da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 29881da177e4SLinus Torvalds break; 29891da177e4SLinus Torvalds 29901da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 29911da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 29921da177e4SLinus Torvalds break; 29931da177e4SLinus Torvalds 2994a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 2995a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 2996a8746417SMarcel Holtmann break; 2997a8746417SMarcel Holtmann 299885a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 299985a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 300085a1e930SMarcel Holtmann break; 300185a1e930SMarcel Holtmann 3002a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 3003a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 3004a9de9248SMarcel Holtmann break; 3005a9de9248SMarcel Holtmann 3006a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 3007a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 3008a9de9248SMarcel Holtmann break; 3009a9de9248SMarcel Holtmann 3010a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 3011a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 3012a9de9248SMarcel Holtmann break; 3013a9de9248SMarcel Holtmann 3014a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_CHANGED: 3015a9de9248SMarcel Holtmann hci_sync_conn_changed_evt(hdev, skb); 3016a9de9248SMarcel Holtmann break; 3017a9de9248SMarcel Holtmann 301804837f64SMarcel Holtmann case HCI_EV_SNIFF_SUBRATE: 301904837f64SMarcel Holtmann hci_sniff_subrate_evt(hdev, skb); 302004837f64SMarcel Holtmann break; 302104837f64SMarcel Holtmann 3022a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 3023a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 30241da177e4SLinus Torvalds break; 30251da177e4SLinus Torvalds 30260493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 30270493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 30280493684eSMarcel Holtmann break; 30290493684eSMarcel Holtmann 303003b555e1SJohan Hedberg case HCI_EV_IO_CAPA_REPLY: 303103b555e1SJohan Hedberg hci_io_capa_reply_evt(hdev, skb); 303203b555e1SJohan Hedberg break; 303303b555e1SJohan Hedberg 3034a5c29683SJohan Hedberg case HCI_EV_USER_CONFIRM_REQUEST: 3035a5c29683SJohan Hedberg hci_user_confirm_request_evt(hdev, skb); 3036a5c29683SJohan Hedberg break; 3037a5c29683SJohan Hedberg 30380493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 30390493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 30400493684eSMarcel Holtmann break; 30410493684eSMarcel Holtmann 304241a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 304341a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 304441a96212SMarcel Holtmann break; 304541a96212SMarcel Holtmann 3046fcd89c09SVille Tervo case HCI_EV_LE_META: 3047fcd89c09SVille Tervo hci_le_meta_evt(hdev, skb); 3048fcd89c09SVille Tervo break; 3049fcd89c09SVille Tervo 30502763eda6SSzymon Janc case HCI_EV_REMOTE_OOB_DATA_REQUEST: 30512763eda6SSzymon Janc hci_remote_oob_data_request_evt(hdev, skb); 30522763eda6SSzymon Janc break; 30532763eda6SSzymon Janc 30541da177e4SLinus Torvalds default: 3055a9de9248SMarcel Holtmann BT_DBG("%s event 0x%x", hdev->name, event); 30561da177e4SLinus Torvalds break; 30571da177e4SLinus Torvalds } 30581da177e4SLinus Torvalds 30591da177e4SLinus Torvalds kfree_skb(skb); 30601da177e4SLinus Torvalds hdev->stat.evt_rx++; 30611da177e4SLinus Torvalds } 30621da177e4SLinus Torvalds 30631da177e4SLinus Torvalds /* Generate internal stack event */ 30641da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data) 30651da177e4SLinus Torvalds { 30661da177e4SLinus Torvalds struct hci_event_hdr *hdr; 30671da177e4SLinus Torvalds struct hci_ev_stack_internal *ev; 30681da177e4SLinus Torvalds struct sk_buff *skb; 30691da177e4SLinus Torvalds 30701da177e4SLinus Torvalds skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC); 30711da177e4SLinus Torvalds if (!skb) 30721da177e4SLinus Torvalds return; 30731da177e4SLinus Torvalds 30741da177e4SLinus Torvalds hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE); 30751da177e4SLinus Torvalds hdr->evt = HCI_EV_STACK_INTERNAL; 30761da177e4SLinus Torvalds hdr->plen = sizeof(*ev) + dlen; 30771da177e4SLinus Torvalds 30781da177e4SLinus Torvalds ev = (void *) skb_put(skb, sizeof(*ev) + dlen); 30791da177e4SLinus Torvalds ev->type = type; 30801da177e4SLinus Torvalds memcpy(ev->data, data, dlen); 30811da177e4SLinus Torvalds 3082576c7d85SMarcel Holtmann bt_cb(skb)->incoming = 1; 3083a61bbcf2SPatrick McHardy __net_timestamp(skb); 3084576c7d85SMarcel Holtmann 30850d48d939SMarcel Holtmann bt_cb(skb)->pkt_type = HCI_EVENT_PKT; 30861da177e4SLinus Torvalds skb->dev = (void *) hdev; 3087eec8d2bcSJohan Hedberg hci_send_to_sock(hdev, skb, NULL); 30881da177e4SLinus Torvalds kfree_skb(skb); 30891da177e4SLinus Torvalds } 3090e6100a25SAndre Guedes 3091e6100a25SAndre Guedes module_param(enable_le, bool, 0444); 3092e6100a25SAndre Guedes MODULE_PARM_DESC(enable_le, "Enable LE support"); 3093