11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds BlueZ - Bluetooth protocol stack for Linux 32d0a0346SRon Shaffer Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved. 41da177e4SLinus Torvalds 51da177e4SLinus Torvalds Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> 61da177e4SLinus Torvalds 71da177e4SLinus Torvalds This program is free software; you can redistribute it and/or modify 81da177e4SLinus Torvalds it under the terms of the GNU General Public License version 2 as 91da177e4SLinus Torvalds published by the Free Software Foundation; 101da177e4SLinus Torvalds 111da177e4SLinus Torvalds THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 121da177e4SLinus Torvalds OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 131da177e4SLinus Torvalds FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 141da177e4SLinus Torvalds IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 151da177e4SLinus Torvalds CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 161da177e4SLinus Torvalds WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 171da177e4SLinus Torvalds ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 181da177e4SLinus Torvalds OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 211da177e4SLinus Torvalds COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 221da177e4SLinus Torvalds SOFTWARE IS DISCLAIMED. 231da177e4SLinus Torvalds */ 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds /* Bluetooth HCI event handling. */ 261da177e4SLinus Torvalds 271da177e4SLinus Torvalds #include <linux/module.h> 281da177e4SLinus Torvalds 291da177e4SLinus Torvalds #include <linux/types.h> 301da177e4SLinus Torvalds #include <linux/errno.h> 311da177e4SLinus Torvalds #include <linux/kernel.h> 321da177e4SLinus Torvalds #include <linux/slab.h> 331da177e4SLinus Torvalds #include <linux/poll.h> 341da177e4SLinus Torvalds #include <linux/fcntl.h> 351da177e4SLinus Torvalds #include <linux/init.h> 361da177e4SLinus Torvalds #include <linux/skbuff.h> 371da177e4SLinus Torvalds #include <linux/interrupt.h> 381da177e4SLinus Torvalds #include <linux/notifier.h> 391da177e4SLinus Torvalds #include <net/sock.h> 401da177e4SLinus Torvalds 411da177e4SLinus Torvalds #include <asm/system.h> 4270f23020SAndrei Emeltchenko #include <linux/uaccess.h> 431da177e4SLinus Torvalds #include <asm/unaligned.h> 441da177e4SLinus Torvalds 451da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h> 461da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h> 471da177e4SLinus Torvalds 48e6100a25SAndre Guedes static int enable_le; 49e6100a25SAndre Guedes 501da177e4SLinus Torvalds /* Handle HCI Event packets */ 511da177e4SLinus Torvalds 52a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb) 531da177e4SLinus Torvalds { 54a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 551da177e4SLinus Torvalds 56a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 571da177e4SLinus Torvalds 58a9de9248SMarcel Holtmann if (status) 59a9de9248SMarcel Holtmann return; 601da177e4SLinus Torvalds 612d20a26aSOliver Neukum if (test_and_clear_bit(HCI_INQUIRY, &hdev->flags) && 622d20a26aSOliver Neukum test_bit(HCI_MGMT, &hdev->flags)) 63314b2381SJohan Hedberg mgmt_discovering(hdev->id, 0); 64a9de9248SMarcel Holtmann 6523bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status); 66a9de9248SMarcel Holtmann 67a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 681da177e4SLinus Torvalds } 696bd57416SMarcel Holtmann 70a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 711da177e4SLinus Torvalds { 72a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 73a9de9248SMarcel Holtmann 74a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 75a9de9248SMarcel Holtmann 76a9de9248SMarcel Holtmann if (status) 77a9de9248SMarcel Holtmann return; 78a9de9248SMarcel Holtmann 792d20a26aSOliver Neukum if (test_and_clear_bit(HCI_INQUIRY, &hdev->flags) && 802d20a26aSOliver Neukum test_bit(HCI_MGMT, &hdev->flags)) 81314b2381SJohan Hedberg mgmt_discovering(hdev->id, 0); 82a9de9248SMarcel Holtmann 83a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 84a9de9248SMarcel Holtmann } 85a9de9248SMarcel Holtmann 86a9de9248SMarcel Holtmann static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb) 87a9de9248SMarcel Holtmann { 88a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 89a9de9248SMarcel Holtmann } 90a9de9248SMarcel Holtmann 91a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb) 92a9de9248SMarcel Holtmann { 93a9de9248SMarcel Holtmann struct hci_rp_role_discovery *rp = (void *) skb->data; 941da177e4SLinus Torvalds struct hci_conn *conn; 951da177e4SLinus Torvalds 96a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 971da177e4SLinus Torvalds 98a9de9248SMarcel Holtmann if (rp->status) 99a9de9248SMarcel Holtmann return; 1001da177e4SLinus Torvalds 1011da177e4SLinus Torvalds hci_dev_lock(hdev); 1021da177e4SLinus Torvalds 103a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 1041da177e4SLinus Torvalds if (conn) { 105a9de9248SMarcel Holtmann if (rp->role) 1061da177e4SLinus Torvalds conn->link_mode &= ~HCI_LM_MASTER; 1071da177e4SLinus Torvalds else 1081da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 1091da177e4SLinus Torvalds } 1101da177e4SLinus Torvalds 1111da177e4SLinus Torvalds hci_dev_unlock(hdev); 112a9de9248SMarcel Holtmann } 1131da177e4SLinus Torvalds 114e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 115e4e8e37cSMarcel Holtmann { 116e4e8e37cSMarcel Holtmann struct hci_rp_read_link_policy *rp = (void *) skb->data; 117e4e8e37cSMarcel Holtmann struct hci_conn *conn; 118e4e8e37cSMarcel Holtmann 119e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 120e4e8e37cSMarcel Holtmann 121e4e8e37cSMarcel Holtmann if (rp->status) 122e4e8e37cSMarcel Holtmann return; 123e4e8e37cSMarcel Holtmann 124e4e8e37cSMarcel Holtmann hci_dev_lock(hdev); 125e4e8e37cSMarcel Holtmann 126e4e8e37cSMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 127e4e8e37cSMarcel Holtmann if (conn) 128e4e8e37cSMarcel Holtmann conn->link_policy = __le16_to_cpu(rp->policy); 129e4e8e37cSMarcel Holtmann 130e4e8e37cSMarcel Holtmann hci_dev_unlock(hdev); 131e4e8e37cSMarcel Holtmann } 132e4e8e37cSMarcel Holtmann 133a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 134a9de9248SMarcel Holtmann { 135a9de9248SMarcel Holtmann struct hci_rp_write_link_policy *rp = (void *) skb->data; 136a9de9248SMarcel Holtmann struct hci_conn *conn; 137a9de9248SMarcel Holtmann void *sent; 138a9de9248SMarcel Holtmann 139a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 140a9de9248SMarcel Holtmann 141a9de9248SMarcel Holtmann if (rp->status) 142a9de9248SMarcel Holtmann return; 143a9de9248SMarcel Holtmann 144a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY); 14504837f64SMarcel Holtmann if (!sent) 146a9de9248SMarcel Holtmann return; 14704837f64SMarcel Holtmann 14804837f64SMarcel Holtmann hci_dev_lock(hdev); 14904837f64SMarcel Holtmann 150a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 151e4e8e37cSMarcel Holtmann if (conn) 15283985319SHarvey Harrison conn->link_policy = get_unaligned_le16(sent + 2); 15304837f64SMarcel Holtmann 15404837f64SMarcel Holtmann hci_dev_unlock(hdev); 1551da177e4SLinus Torvalds } 1561da177e4SLinus Torvalds 157e4e8e37cSMarcel Holtmann static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 158e4e8e37cSMarcel Holtmann { 159e4e8e37cSMarcel Holtmann struct hci_rp_read_def_link_policy *rp = (void *) skb->data; 160e4e8e37cSMarcel Holtmann 161e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 162e4e8e37cSMarcel Holtmann 163e4e8e37cSMarcel Holtmann if (rp->status) 164e4e8e37cSMarcel Holtmann return; 165e4e8e37cSMarcel Holtmann 166e4e8e37cSMarcel Holtmann hdev->link_policy = __le16_to_cpu(rp->policy); 167e4e8e37cSMarcel Holtmann } 168e4e8e37cSMarcel Holtmann 169e4e8e37cSMarcel Holtmann static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 170e4e8e37cSMarcel Holtmann { 171e4e8e37cSMarcel Holtmann __u8 status = *((__u8 *) skb->data); 172e4e8e37cSMarcel Holtmann void *sent; 173e4e8e37cSMarcel Holtmann 174e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 175e4e8e37cSMarcel Holtmann 176e4e8e37cSMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY); 177e4e8e37cSMarcel Holtmann if (!sent) 178e4e8e37cSMarcel Holtmann return; 179e4e8e37cSMarcel Holtmann 180e4e8e37cSMarcel Holtmann if (!status) 181e4e8e37cSMarcel Holtmann hdev->link_policy = get_unaligned_le16(sent); 182e4e8e37cSMarcel Holtmann 18323bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status); 184e4e8e37cSMarcel Holtmann } 185e4e8e37cSMarcel Holtmann 186a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) 1871da177e4SLinus Torvalds { 188a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 189a9de9248SMarcel Holtmann 190a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 191a9de9248SMarcel Holtmann 19210572132SGustavo F. Padovan clear_bit(HCI_RESET, &hdev->flags); 19310572132SGustavo F. Padovan 19423bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_RESET, status); 195a9de9248SMarcel Holtmann } 196a9de9248SMarcel Holtmann 197a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) 198a9de9248SMarcel Holtmann { 199a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 2001da177e4SLinus Torvalds void *sent; 2011da177e4SLinus Torvalds 202a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 2031da177e4SLinus Torvalds 204a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); 2051da177e4SLinus Torvalds if (!sent) 206a9de9248SMarcel Holtmann return; 2071da177e4SLinus Torvalds 208b312b161SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 209b312b161SJohan Hedberg mgmt_set_local_name_complete(hdev->id, sent, status); 210b312b161SJohan Hedberg 211b312b161SJohan Hedberg if (status) 212b312b161SJohan Hedberg return; 213b312b161SJohan Hedberg 2141f6c6378SJohan Hedberg memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); 215a9de9248SMarcel Holtmann } 216a9de9248SMarcel Holtmann 217a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) 218a9de9248SMarcel Holtmann { 219a9de9248SMarcel Holtmann struct hci_rp_read_local_name *rp = (void *) skb->data; 220a9de9248SMarcel Holtmann 221a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 222a9de9248SMarcel Holtmann 223a9de9248SMarcel Holtmann if (rp->status) 224a9de9248SMarcel Holtmann return; 225a9de9248SMarcel Holtmann 2261f6c6378SJohan Hedberg memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); 227a9de9248SMarcel Holtmann } 228a9de9248SMarcel Holtmann 229a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) 230a9de9248SMarcel Holtmann { 231a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 232a9de9248SMarcel Holtmann void *sent; 233a9de9248SMarcel Holtmann 234a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 235a9de9248SMarcel Holtmann 236a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); 237a9de9248SMarcel Holtmann if (!sent) 238a9de9248SMarcel Holtmann return; 2391da177e4SLinus Torvalds 2401da177e4SLinus Torvalds if (!status) { 241a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 242a9de9248SMarcel Holtmann 2431da177e4SLinus Torvalds if (param == AUTH_ENABLED) 2441da177e4SLinus Torvalds set_bit(HCI_AUTH, &hdev->flags); 2451da177e4SLinus Torvalds else 2461da177e4SLinus Torvalds clear_bit(HCI_AUTH, &hdev->flags); 2471da177e4SLinus Torvalds } 248a9de9248SMarcel Holtmann 24923bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status); 250a9de9248SMarcel Holtmann } 2511da177e4SLinus Torvalds 252a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) 253a9de9248SMarcel Holtmann { 254a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 255a9de9248SMarcel Holtmann void *sent; 256a9de9248SMarcel Holtmann 257a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 258a9de9248SMarcel Holtmann 259a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); 2601da177e4SLinus Torvalds if (!sent) 261a9de9248SMarcel Holtmann return; 2621da177e4SLinus Torvalds 2631da177e4SLinus Torvalds if (!status) { 264a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 265a9de9248SMarcel Holtmann 2661da177e4SLinus Torvalds if (param) 2671da177e4SLinus Torvalds set_bit(HCI_ENCRYPT, &hdev->flags); 2681da177e4SLinus Torvalds else 2691da177e4SLinus Torvalds clear_bit(HCI_ENCRYPT, &hdev->flags); 2701da177e4SLinus Torvalds } 271a9de9248SMarcel Holtmann 27223bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status); 2731da177e4SLinus Torvalds } 2741da177e4SLinus Torvalds 275a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) 276a9de9248SMarcel Holtmann { 277a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 278a9de9248SMarcel Holtmann void *sent; 2791da177e4SLinus Torvalds 280a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 281a9de9248SMarcel Holtmann 282a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); 2831da177e4SLinus Torvalds if (!sent) 284a9de9248SMarcel Holtmann return; 2851da177e4SLinus Torvalds 2861da177e4SLinus Torvalds if (!status) { 287a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 2889fbcbb45SJohan Hedberg int old_pscan, old_iscan; 289a9de9248SMarcel Holtmann 2909fbcbb45SJohan Hedberg old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags); 2919fbcbb45SJohan Hedberg old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags); 292a9de9248SMarcel Holtmann 29373f22f62SJohan Hedberg if (param & SCAN_INQUIRY) { 2941da177e4SLinus Torvalds set_bit(HCI_ISCAN, &hdev->flags); 2959fbcbb45SJohan Hedberg if (!old_iscan) 29673f22f62SJohan Hedberg mgmt_discoverable(hdev->id, 1); 2979fbcbb45SJohan Hedberg } else if (old_iscan) 29873f22f62SJohan Hedberg mgmt_discoverable(hdev->id, 0); 2991da177e4SLinus Torvalds 3009fbcbb45SJohan Hedberg if (param & SCAN_PAGE) { 3011da177e4SLinus Torvalds set_bit(HCI_PSCAN, &hdev->flags); 3029fbcbb45SJohan Hedberg if (!old_pscan) 3039fbcbb45SJohan Hedberg mgmt_connectable(hdev->id, 1); 3049fbcbb45SJohan Hedberg } else if (old_pscan) 3059fbcbb45SJohan Hedberg mgmt_connectable(hdev->id, 0); 3061da177e4SLinus Torvalds } 307a9de9248SMarcel Holtmann 30823bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status); 3091da177e4SLinus Torvalds } 3101da177e4SLinus Torvalds 311a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 312a9de9248SMarcel Holtmann { 313a9de9248SMarcel Holtmann struct hci_rp_read_class_of_dev *rp = (void *) skb->data; 314a9de9248SMarcel Holtmann 315a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 316a9de9248SMarcel Holtmann 317a9de9248SMarcel Holtmann if (rp->status) 318a9de9248SMarcel Holtmann return; 319a9de9248SMarcel Holtmann 320a9de9248SMarcel Holtmann memcpy(hdev->dev_class, rp->dev_class, 3); 321a9de9248SMarcel Holtmann 322a9de9248SMarcel Holtmann BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, 323a9de9248SMarcel Holtmann hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); 324a9de9248SMarcel Holtmann } 325a9de9248SMarcel Holtmann 326a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 327a9de9248SMarcel Holtmann { 328a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 329a9de9248SMarcel Holtmann void *sent; 330a9de9248SMarcel Holtmann 331a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 332a9de9248SMarcel Holtmann 333f383f275SMarcel Holtmann if (status) 334f383f275SMarcel Holtmann return; 335f383f275SMarcel Holtmann 336a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); 337a9de9248SMarcel Holtmann if (!sent) 338a9de9248SMarcel Holtmann return; 339a9de9248SMarcel Holtmann 340a9de9248SMarcel Holtmann memcpy(hdev->dev_class, sent, 3); 341a9de9248SMarcel Holtmann } 342a9de9248SMarcel Holtmann 343a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 344a9de9248SMarcel Holtmann { 345a9de9248SMarcel Holtmann struct hci_rp_read_voice_setting *rp = (void *) skb->data; 346a9de9248SMarcel Holtmann __u16 setting; 347a9de9248SMarcel Holtmann 348a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 349a9de9248SMarcel Holtmann 350a9de9248SMarcel Holtmann if (rp->status) 351a9de9248SMarcel Holtmann return; 352a9de9248SMarcel Holtmann 353a9de9248SMarcel Holtmann setting = __le16_to_cpu(rp->voice_setting); 354a9de9248SMarcel Holtmann 355a9de9248SMarcel Holtmann if (hdev->voice_setting == setting) 356a9de9248SMarcel Holtmann return; 357a9de9248SMarcel Holtmann 358a9de9248SMarcel Holtmann hdev->voice_setting = setting; 359a9de9248SMarcel Holtmann 360a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 361a9de9248SMarcel Holtmann 362a9de9248SMarcel Holtmann if (hdev->notify) { 363a9de9248SMarcel Holtmann tasklet_disable(&hdev->tx_task); 364a9de9248SMarcel Holtmann hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 365a9de9248SMarcel Holtmann tasklet_enable(&hdev->tx_task); 366a9de9248SMarcel Holtmann } 367a9de9248SMarcel Holtmann } 368a9de9248SMarcel Holtmann 369a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 370a9de9248SMarcel Holtmann { 371a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 372f383f275SMarcel Holtmann __u16 setting; 373a9de9248SMarcel Holtmann void *sent; 374a9de9248SMarcel Holtmann 375a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 376a9de9248SMarcel Holtmann 377f383f275SMarcel Holtmann if (status) 378f383f275SMarcel Holtmann return; 379f383f275SMarcel Holtmann 380a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); 381a9de9248SMarcel Holtmann if (!sent) 382a9de9248SMarcel Holtmann return; 383a9de9248SMarcel Holtmann 384f383f275SMarcel Holtmann setting = get_unaligned_le16(sent); 3851da177e4SLinus Torvalds 386f383f275SMarcel Holtmann if (hdev->voice_setting == setting) 387f383f275SMarcel Holtmann return; 388f383f275SMarcel Holtmann 3891da177e4SLinus Torvalds hdev->voice_setting = setting; 3901da177e4SLinus Torvalds 391a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 3921da177e4SLinus Torvalds 3931da177e4SLinus Torvalds if (hdev->notify) { 3941da177e4SLinus Torvalds tasklet_disable(&hdev->tx_task); 3951da177e4SLinus Torvalds hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 3961da177e4SLinus Torvalds tasklet_enable(&hdev->tx_task); 3971da177e4SLinus Torvalds } 3981da177e4SLinus Torvalds } 3991da177e4SLinus Torvalds 400a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 4011da177e4SLinus Torvalds { 402a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 4031da177e4SLinus Torvalds 404a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 4051da177e4SLinus Torvalds 40623bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status); 4071143e5a6SMarcel Holtmann } 4081143e5a6SMarcel Holtmann 409333140b5SMarcel Holtmann static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 410333140b5SMarcel Holtmann { 411333140b5SMarcel Holtmann struct hci_rp_read_ssp_mode *rp = (void *) skb->data; 412333140b5SMarcel Holtmann 413333140b5SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 414333140b5SMarcel Holtmann 415333140b5SMarcel Holtmann if (rp->status) 416333140b5SMarcel Holtmann return; 417333140b5SMarcel Holtmann 418333140b5SMarcel Holtmann hdev->ssp_mode = rp->mode; 419333140b5SMarcel Holtmann } 420333140b5SMarcel Holtmann 421333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 422333140b5SMarcel Holtmann { 423333140b5SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 424333140b5SMarcel Holtmann void *sent; 425333140b5SMarcel Holtmann 426333140b5SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 427333140b5SMarcel Holtmann 428333140b5SMarcel Holtmann if (status) 429333140b5SMarcel Holtmann return; 430333140b5SMarcel Holtmann 431333140b5SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); 432333140b5SMarcel Holtmann if (!sent) 433333140b5SMarcel Holtmann return; 434333140b5SMarcel Holtmann 435333140b5SMarcel Holtmann hdev->ssp_mode = *((__u8 *) sent); 436333140b5SMarcel Holtmann } 437333140b5SMarcel Holtmann 438d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev) 439d5859e22SJohan Hedberg { 440d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 441d5859e22SJohan Hedberg return 2; 442d5859e22SJohan Hedberg 443d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 444d5859e22SJohan Hedberg return 1; 445d5859e22SJohan Hedberg 446d5859e22SJohan Hedberg if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 && 447d5859e22SJohan Hedberg hdev->lmp_subver == 0x0757) 448d5859e22SJohan Hedberg return 1; 449d5859e22SJohan Hedberg 450d5859e22SJohan Hedberg if (hdev->manufacturer == 15) { 451d5859e22SJohan Hedberg if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963) 452d5859e22SJohan Hedberg return 1; 453d5859e22SJohan Hedberg if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963) 454d5859e22SJohan Hedberg return 1; 455d5859e22SJohan Hedberg if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965) 456d5859e22SJohan Hedberg return 1; 457d5859e22SJohan Hedberg } 458d5859e22SJohan Hedberg 459d5859e22SJohan Hedberg if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 && 460d5859e22SJohan Hedberg hdev->lmp_subver == 0x1805) 461d5859e22SJohan Hedberg return 1; 462d5859e22SJohan Hedberg 463d5859e22SJohan Hedberg return 0; 464d5859e22SJohan Hedberg } 465d5859e22SJohan Hedberg 466d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev) 467d5859e22SJohan Hedberg { 468d5859e22SJohan Hedberg u8 mode; 469d5859e22SJohan Hedberg 470d5859e22SJohan Hedberg mode = hci_get_inquiry_mode(hdev); 471d5859e22SJohan Hedberg 472d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode); 473d5859e22SJohan Hedberg } 474d5859e22SJohan Hedberg 475d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev) 476d5859e22SJohan Hedberg { 477d5859e22SJohan Hedberg /* The second byte is 0xff instead of 0x9f (two reserved bits 478d5859e22SJohan Hedberg * disabled) since a Broadcom 1.2 dongle doesn't respond to the 479d5859e22SJohan Hedberg * command otherwise */ 480d5859e22SJohan Hedberg u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 }; 481d5859e22SJohan Hedberg 4826de6c18dSVille Tervo /* CSR 1.1 dongles does not accept any bitfield so don't try to set 4836de6c18dSVille Tervo * any event mask for pre 1.2 devices */ 4846de6c18dSVille Tervo if (hdev->lmp_ver <= 1) 4856de6c18dSVille Tervo return; 4866de6c18dSVille Tervo 487d5859e22SJohan Hedberg events[4] |= 0x01; /* Flow Specification Complete */ 488d5859e22SJohan Hedberg events[4] |= 0x02; /* Inquiry Result with RSSI */ 489d5859e22SJohan Hedberg events[4] |= 0x04; /* Read Remote Extended Features Complete */ 490d5859e22SJohan Hedberg events[5] |= 0x08; /* Synchronous Connection Complete */ 491d5859e22SJohan Hedberg events[5] |= 0x10; /* Synchronous Connection Changed */ 492d5859e22SJohan Hedberg 493d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 494d5859e22SJohan Hedberg events[4] |= 0x04; /* Inquiry Result with RSSI */ 495d5859e22SJohan Hedberg 496d5859e22SJohan Hedberg if (hdev->features[5] & LMP_SNIFF_SUBR) 497d5859e22SJohan Hedberg events[5] |= 0x20; /* Sniff Subrating */ 498d5859e22SJohan Hedberg 499d5859e22SJohan Hedberg if (hdev->features[5] & LMP_PAUSE_ENC) 500d5859e22SJohan Hedberg events[5] |= 0x80; /* Encryption Key Refresh Complete */ 501d5859e22SJohan Hedberg 502d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 503d5859e22SJohan Hedberg events[5] |= 0x40; /* Extended Inquiry Result */ 504d5859e22SJohan Hedberg 505d5859e22SJohan Hedberg if (hdev->features[6] & LMP_NO_FLUSH) 506d5859e22SJohan Hedberg events[7] |= 0x01; /* Enhanced Flush Complete */ 507d5859e22SJohan Hedberg 508d5859e22SJohan Hedberg if (hdev->features[7] & LMP_LSTO) 509d5859e22SJohan Hedberg events[6] |= 0x80; /* Link Supervision Timeout Changed */ 510d5859e22SJohan Hedberg 511d5859e22SJohan Hedberg if (hdev->features[6] & LMP_SIMPLE_PAIR) { 512d5859e22SJohan Hedberg events[6] |= 0x01; /* IO Capability Request */ 513d5859e22SJohan Hedberg events[6] |= 0x02; /* IO Capability Response */ 514d5859e22SJohan Hedberg events[6] |= 0x04; /* User Confirmation Request */ 515d5859e22SJohan Hedberg events[6] |= 0x08; /* User Passkey Request */ 516d5859e22SJohan Hedberg events[6] |= 0x10; /* Remote OOB Data Request */ 517d5859e22SJohan Hedberg events[6] |= 0x20; /* Simple Pairing Complete */ 518d5859e22SJohan Hedberg events[7] |= 0x04; /* User Passkey Notification */ 519d5859e22SJohan Hedberg events[7] |= 0x08; /* Keypress Notification */ 520d5859e22SJohan Hedberg events[7] |= 0x10; /* Remote Host Supported 521d5859e22SJohan Hedberg * Features Notification */ 522d5859e22SJohan Hedberg } 523d5859e22SJohan Hedberg 524d5859e22SJohan Hedberg if (hdev->features[4] & LMP_LE) 525d5859e22SJohan Hedberg events[7] |= 0x20; /* LE Meta-Event */ 526d5859e22SJohan Hedberg 527d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); 528d5859e22SJohan Hedberg } 529d5859e22SJohan Hedberg 530e6100a25SAndre Guedes static void hci_set_le_support(struct hci_dev *hdev) 531e6100a25SAndre Guedes { 532e6100a25SAndre Guedes struct hci_cp_write_le_host_supported cp; 533e6100a25SAndre Guedes 534e6100a25SAndre Guedes memset(&cp, 0, sizeof(cp)); 535e6100a25SAndre Guedes 536e6100a25SAndre Guedes if (enable_le) { 537e6100a25SAndre Guedes cp.le = 1; 538e6100a25SAndre Guedes cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR); 539e6100a25SAndre Guedes } 540e6100a25SAndre Guedes 541e6100a25SAndre Guedes hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), &cp); 542e6100a25SAndre Guedes } 543e6100a25SAndre Guedes 544d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev) 545d5859e22SJohan Hedberg { 546d5859e22SJohan Hedberg hci_setup_event_mask(hdev); 547d5859e22SJohan Hedberg 548d5859e22SJohan Hedberg if (hdev->lmp_ver > 1) 549d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); 550d5859e22SJohan Hedberg 551d5859e22SJohan Hedberg if (hdev->features[6] & LMP_SIMPLE_PAIR) { 552d5859e22SJohan Hedberg u8 mode = 0x01; 553d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode); 554d5859e22SJohan Hedberg } 555d5859e22SJohan Hedberg 556d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 557d5859e22SJohan Hedberg hci_setup_inquiry_mode(hdev); 558d5859e22SJohan Hedberg 559d5859e22SJohan Hedberg if (hdev->features[7] & LMP_INQ_TX_PWR) 560d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL); 561971e3a4bSAndre Guedes 562971e3a4bSAndre Guedes if (hdev->features[7] & LMP_EXTFEATURES) { 563971e3a4bSAndre Guedes struct hci_cp_read_local_ext_features cp; 564971e3a4bSAndre Guedes 565971e3a4bSAndre Guedes cp.page = 0x01; 566971e3a4bSAndre Guedes hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, 567971e3a4bSAndre Guedes sizeof(cp), &cp); 568971e3a4bSAndre Guedes } 569e6100a25SAndre Guedes 570e6100a25SAndre Guedes if (hdev->features[4] & LMP_LE) 571e6100a25SAndre Guedes hci_set_le_support(hdev); 572d5859e22SJohan Hedberg } 573d5859e22SJohan Hedberg 574a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) 575a9de9248SMarcel Holtmann { 576a9de9248SMarcel Holtmann struct hci_rp_read_local_version *rp = (void *) skb->data; 5771143e5a6SMarcel Holtmann 578a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 5791143e5a6SMarcel Holtmann 580a9de9248SMarcel Holtmann if (rp->status) 581a9de9248SMarcel Holtmann return; 5821143e5a6SMarcel Holtmann 583a9de9248SMarcel Holtmann hdev->hci_ver = rp->hci_ver; 584e4e8e37cSMarcel Holtmann hdev->hci_rev = __le16_to_cpu(rp->hci_rev); 585d5859e22SJohan Hedberg hdev->lmp_ver = rp->lmp_ver; 586e4e8e37cSMarcel Holtmann hdev->manufacturer = __le16_to_cpu(rp->manufacturer); 587d5859e22SJohan Hedberg hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); 5881da177e4SLinus Torvalds 589a9de9248SMarcel Holtmann BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name, 590a9de9248SMarcel Holtmann hdev->manufacturer, 591a9de9248SMarcel Holtmann hdev->hci_ver, hdev->hci_rev); 592d5859e22SJohan Hedberg 593d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags)) 594d5859e22SJohan Hedberg hci_setup(hdev); 595d5859e22SJohan Hedberg } 596d5859e22SJohan Hedberg 597d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev) 598d5859e22SJohan Hedberg { 599d5859e22SJohan Hedberg u16 link_policy = 0; 600d5859e22SJohan Hedberg 601d5859e22SJohan Hedberg if (hdev->features[0] & LMP_RSWITCH) 602d5859e22SJohan Hedberg link_policy |= HCI_LP_RSWITCH; 603d5859e22SJohan Hedberg if (hdev->features[0] & LMP_HOLD) 604d5859e22SJohan Hedberg link_policy |= HCI_LP_HOLD; 605d5859e22SJohan Hedberg if (hdev->features[0] & LMP_SNIFF) 606d5859e22SJohan Hedberg link_policy |= HCI_LP_SNIFF; 607d5859e22SJohan Hedberg if (hdev->features[1] & LMP_PARK) 608d5859e22SJohan Hedberg link_policy |= HCI_LP_PARK; 609d5859e22SJohan Hedberg 610d5859e22SJohan Hedberg link_policy = cpu_to_le16(link_policy); 611d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, 612d5859e22SJohan Hedberg sizeof(link_policy), &link_policy); 6131da177e4SLinus Torvalds } 6141da177e4SLinus Torvalds 615a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb) 616a9de9248SMarcel Holtmann { 617a9de9248SMarcel Holtmann struct hci_rp_read_local_commands *rp = (void *) skb->data; 618a9de9248SMarcel Holtmann 619a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 620a9de9248SMarcel Holtmann 621a9de9248SMarcel Holtmann if (rp->status) 622d5859e22SJohan Hedberg goto done; 623a9de9248SMarcel Holtmann 624a9de9248SMarcel Holtmann memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); 625d5859e22SJohan Hedberg 626d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10)) 627d5859e22SJohan Hedberg hci_setup_link_policy(hdev); 628d5859e22SJohan Hedberg 629d5859e22SJohan Hedberg done: 630d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status); 631a9de9248SMarcel Holtmann } 632a9de9248SMarcel Holtmann 633a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb) 634a9de9248SMarcel Holtmann { 635a9de9248SMarcel Holtmann struct hci_rp_read_local_features *rp = (void *) skb->data; 636a9de9248SMarcel Holtmann 637a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 638a9de9248SMarcel Holtmann 639a9de9248SMarcel Holtmann if (rp->status) 640a9de9248SMarcel Holtmann return; 641a9de9248SMarcel Holtmann 642a9de9248SMarcel Holtmann memcpy(hdev->features, rp->features, 8); 6431da177e4SLinus Torvalds 6441da177e4SLinus Torvalds /* Adjust default settings according to features 6451da177e4SLinus Torvalds * supported by device. */ 646a9de9248SMarcel Holtmann 6471da177e4SLinus Torvalds if (hdev->features[0] & LMP_3SLOT) 6481da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM3 | HCI_DH3); 6491da177e4SLinus Torvalds 6501da177e4SLinus Torvalds if (hdev->features[0] & LMP_5SLOT) 6511da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM5 | HCI_DH5); 6521da177e4SLinus Torvalds 6535b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV2) { 6541da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV2); 6555b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV2); 6565b7f9909SMarcel Holtmann } 6571da177e4SLinus Torvalds 6585b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV3) { 6591da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV3); 6605b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV3); 6615b7f9909SMarcel Holtmann } 6625b7f9909SMarcel Holtmann 6635b7f9909SMarcel Holtmann if (hdev->features[3] & LMP_ESCO) 6645b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV3); 6655b7f9909SMarcel Holtmann 6665b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV4) 6675b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV4); 6685b7f9909SMarcel Holtmann 6695b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV5) 6705b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV5); 6711da177e4SLinus Torvalds 672efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_2M) 673efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV3); 674efc7688bSMarcel Holtmann 675efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_3M) 676efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_3EV3); 677efc7688bSMarcel Holtmann 678efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_3S_ESCO) 679efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); 680efc7688bSMarcel Holtmann 681a9de9248SMarcel Holtmann BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, 682a9de9248SMarcel Holtmann hdev->features[0], hdev->features[1], 683a9de9248SMarcel Holtmann hdev->features[2], hdev->features[3], 684a9de9248SMarcel Holtmann hdev->features[4], hdev->features[5], 685a9de9248SMarcel Holtmann hdev->features[6], hdev->features[7]); 6861da177e4SLinus Torvalds } 6871da177e4SLinus Torvalds 688971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev, 689971e3a4bSAndre Guedes struct sk_buff *skb) 690971e3a4bSAndre Guedes { 691971e3a4bSAndre Guedes struct hci_rp_read_local_ext_features *rp = (void *) skb->data; 692971e3a4bSAndre Guedes 693971e3a4bSAndre Guedes BT_DBG("%s status 0x%x", hdev->name, rp->status); 694971e3a4bSAndre Guedes 695971e3a4bSAndre Guedes if (rp->status) 696971e3a4bSAndre Guedes return; 697971e3a4bSAndre Guedes 698971e3a4bSAndre Guedes memcpy(hdev->extfeatures, rp->features, 8); 699971e3a4bSAndre Guedes 700971e3a4bSAndre Guedes hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status); 701971e3a4bSAndre Guedes } 702971e3a4bSAndre Guedes 703a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 704a9de9248SMarcel Holtmann { 705a9de9248SMarcel Holtmann struct hci_rp_read_buffer_size *rp = (void *) skb->data; 706a9de9248SMarcel Holtmann 707a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 708a9de9248SMarcel Holtmann 709a9de9248SMarcel Holtmann if (rp->status) 710a9de9248SMarcel Holtmann return; 711a9de9248SMarcel Holtmann 712a9de9248SMarcel Holtmann hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); 713a9de9248SMarcel Holtmann hdev->sco_mtu = rp->sco_mtu; 714a9de9248SMarcel Holtmann hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); 715a9de9248SMarcel Holtmann hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); 716da1f5198SMarcel Holtmann 717da1f5198SMarcel Holtmann if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { 718da1f5198SMarcel Holtmann hdev->sco_mtu = 64; 719da1f5198SMarcel Holtmann hdev->sco_pkts = 8; 720da1f5198SMarcel Holtmann } 721da1f5198SMarcel Holtmann 722da1f5198SMarcel Holtmann hdev->acl_cnt = hdev->acl_pkts; 723da1f5198SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 7241da177e4SLinus Torvalds 725a9de9248SMarcel Holtmann BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, 726a9de9248SMarcel Holtmann hdev->acl_mtu, hdev->acl_pkts, 727a9de9248SMarcel Holtmann hdev->sco_mtu, hdev->sco_pkts); 7281da177e4SLinus Torvalds } 7291da177e4SLinus Torvalds 730a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) 731a9de9248SMarcel Holtmann { 732a9de9248SMarcel Holtmann struct hci_rp_read_bd_addr *rp = (void *) skb->data; 7331da177e4SLinus Torvalds 734a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 735a9de9248SMarcel Holtmann 736a9de9248SMarcel Holtmann if (!rp->status) 737a9de9248SMarcel Holtmann bacpy(&hdev->bdaddr, &rp->bdaddr); 738a9de9248SMarcel Holtmann 73923bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status); 74023bb5763SJohan Hedberg } 74123bb5763SJohan Hedberg 74223bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb) 74323bb5763SJohan Hedberg { 74423bb5763SJohan Hedberg __u8 status = *((__u8 *) skb->data); 74523bb5763SJohan Hedberg 74623bb5763SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 74723bb5763SJohan Hedberg 74823bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status); 7491da177e4SLinus Torvalds } 7501da177e4SLinus Torvalds 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 90135815085SAndre Guedes if (cp->enable == 0x01) { 90235815085SAndre Guedes del_timer(&hdev->adv_timer); 903a8f13c8cSAndre Guedes 904a8f13c8cSAndre Guedes hci_dev_lock(hdev); 905eb9d91f5SAndre Guedes hci_adv_entries_clear(hdev); 906a8f13c8cSAndre Guedes hci_dev_unlock(hdev); 90735815085SAndre Guedes } else if (cp->enable == 0x00) { 90835815085SAndre Guedes mod_timer(&hdev->adv_timer, jiffies + ADV_CLEAR_TIMEOUT); 90935815085SAndre Guedes } 910eb9d91f5SAndre Guedes } 911eb9d91f5SAndre Guedes 912a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb) 913a7a595f6SVinicius Costa Gomes { 914a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_reply *rp = (void *) skb->data; 915a7a595f6SVinicius Costa Gomes 916a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, rp->status); 917a7a595f6SVinicius Costa Gomes 918a7a595f6SVinicius Costa Gomes if (rp->status) 919a7a595f6SVinicius Costa Gomes return; 920a7a595f6SVinicius Costa Gomes 921a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status); 922a7a595f6SVinicius Costa Gomes } 923a7a595f6SVinicius Costa Gomes 924a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 925a7a595f6SVinicius Costa Gomes { 926a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data; 927a7a595f6SVinicius Costa Gomes 928a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, rp->status); 929a7a595f6SVinicius Costa Gomes 930a7a595f6SVinicius Costa Gomes if (rp->status) 931a7a595f6SVinicius Costa Gomes return; 932a7a595f6SVinicius Costa Gomes 933a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status); 934a7a595f6SVinicius Costa Gomes } 935a7a595f6SVinicius Costa Gomes 936f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev, 937f9b49306SAndre Guedes struct sk_buff *skb) 938f9b49306SAndre Guedes { 939f9b49306SAndre Guedes struct hci_cp_read_local_ext_features cp; 940f9b49306SAndre Guedes __u8 status = *((__u8 *) skb->data); 941f9b49306SAndre Guedes 942f9b49306SAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 943f9b49306SAndre Guedes 944f9b49306SAndre Guedes if (status) 945f9b49306SAndre Guedes return; 946f9b49306SAndre Guedes 947f9b49306SAndre Guedes cp.page = 0x01; 948f9b49306SAndre Guedes hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), &cp); 949f9b49306SAndre Guedes } 950f9b49306SAndre Guedes 951a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 952a9de9248SMarcel Holtmann { 953a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 954a9de9248SMarcel Holtmann 955a9de9248SMarcel Holtmann if (status) { 95623bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 957a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 958314b2381SJohan Hedberg return; 959314b2381SJohan Hedberg } 960314b2381SJohan Hedberg 9612d20a26aSOliver Neukum if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags) && 9622d20a26aSOliver Neukum test_bit(HCI_MGMT, &hdev->flags)) 963314b2381SJohan Hedberg mgmt_discovering(hdev->id, 1); 964a9de9248SMarcel Holtmann } 965a9de9248SMarcel Holtmann 9661da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 9671da177e4SLinus Torvalds { 968a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 9691da177e4SLinus Torvalds struct hci_conn *conn; 9701da177e4SLinus Torvalds 971a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 972a9de9248SMarcel Holtmann 973a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 9741da177e4SLinus Torvalds if (!cp) 9751da177e4SLinus Torvalds return; 9761da177e4SLinus Torvalds 9771da177e4SLinus Torvalds hci_dev_lock(hdev); 9781da177e4SLinus Torvalds 9791da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 9801da177e4SLinus Torvalds 981a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn); 9821da177e4SLinus Torvalds 9831da177e4SLinus Torvalds if (status) { 9841da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 9854c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 9861da177e4SLinus Torvalds conn->state = BT_CLOSED; 9871da177e4SLinus Torvalds hci_proto_connect_cfm(conn, status); 9881da177e4SLinus Torvalds hci_conn_del(conn); 9894c67bc74SMarcel Holtmann } else 9904c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 9911da177e4SLinus Torvalds } 9921da177e4SLinus Torvalds } else { 9931da177e4SLinus Torvalds if (!conn) { 9941da177e4SLinus Torvalds conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); 9951da177e4SLinus Torvalds if (conn) { 9961da177e4SLinus Torvalds conn->out = 1; 9971da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 9981da177e4SLinus Torvalds } else 999893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 10001da177e4SLinus Torvalds } 10011da177e4SLinus Torvalds } 10021da177e4SLinus Torvalds 10031da177e4SLinus Torvalds hci_dev_unlock(hdev); 10041da177e4SLinus Torvalds } 10051da177e4SLinus Torvalds 1006a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 10071da177e4SLinus Torvalds { 1008a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 10091da177e4SLinus Torvalds struct hci_conn *acl, *sco; 10101da177e4SLinus Torvalds __u16 handle; 10111da177e4SLinus Torvalds 1012b6a0dc82SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1013b6a0dc82SMarcel Holtmann 1014a9de9248SMarcel Holtmann if (!status) 1015a9de9248SMarcel Holtmann return; 1016a9de9248SMarcel Holtmann 1017a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 10181da177e4SLinus Torvalds if (!cp) 1019a9de9248SMarcel Holtmann return; 10201da177e4SLinus Torvalds 10211da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 10221da177e4SLinus Torvalds 1023a9de9248SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 10241da177e4SLinus Torvalds 10251da177e4SLinus Torvalds hci_dev_lock(hdev); 10261da177e4SLinus Torvalds 10271da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 10285a08ecceSAndrei Emeltchenko if (acl) { 10295a08ecceSAndrei Emeltchenko sco = acl->link; 10305a08ecceSAndrei Emeltchenko if (sco) { 10311da177e4SLinus Torvalds sco->state = BT_CLOSED; 10321da177e4SLinus Torvalds 10331da177e4SLinus Torvalds hci_proto_connect_cfm(sco, status); 10341da177e4SLinus Torvalds hci_conn_del(sco); 10351da177e4SLinus Torvalds } 10365a08ecceSAndrei Emeltchenko } 10371da177e4SLinus Torvalds 10381da177e4SLinus Torvalds hci_dev_unlock(hdev); 10391da177e4SLinus Torvalds } 10401da177e4SLinus Torvalds 1041f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 1042f8558555SMarcel Holtmann { 1043f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 1044f8558555SMarcel Holtmann struct hci_conn *conn; 1045f8558555SMarcel Holtmann 1046f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1047f8558555SMarcel Holtmann 1048f8558555SMarcel Holtmann if (!status) 1049f8558555SMarcel Holtmann return; 1050f8558555SMarcel Holtmann 1051f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 1052f8558555SMarcel Holtmann if (!cp) 1053f8558555SMarcel Holtmann return; 1054f8558555SMarcel Holtmann 1055f8558555SMarcel Holtmann hci_dev_lock(hdev); 1056f8558555SMarcel Holtmann 1057f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1058f8558555SMarcel Holtmann if (conn) { 1059f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1060f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1061f8558555SMarcel Holtmann hci_conn_put(conn); 1062f8558555SMarcel Holtmann } 1063f8558555SMarcel Holtmann } 1064f8558555SMarcel Holtmann 1065f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1066f8558555SMarcel Holtmann } 1067f8558555SMarcel Holtmann 1068f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 1069f8558555SMarcel Holtmann { 1070f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 1071f8558555SMarcel Holtmann struct hci_conn *conn; 1072f8558555SMarcel Holtmann 1073f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1074f8558555SMarcel Holtmann 1075f8558555SMarcel Holtmann if (!status) 1076f8558555SMarcel Holtmann return; 1077f8558555SMarcel Holtmann 1078f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 1079f8558555SMarcel Holtmann if (!cp) 1080f8558555SMarcel Holtmann return; 1081f8558555SMarcel Holtmann 1082f8558555SMarcel Holtmann hci_dev_lock(hdev); 1083f8558555SMarcel Holtmann 1084f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1085f8558555SMarcel Holtmann if (conn) { 1086f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1087f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1088f8558555SMarcel Holtmann hci_conn_put(conn); 1089f8558555SMarcel Holtmann } 1090f8558555SMarcel Holtmann } 1091f8558555SMarcel Holtmann 1092f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1093f8558555SMarcel Holtmann } 1094f8558555SMarcel Holtmann 1095127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev, 1096392599b9SJohan Hedberg struct hci_conn *conn) 1097392599b9SJohan Hedberg { 1098392599b9SJohan Hedberg if (conn->state != BT_CONFIG || !conn->out) 1099392599b9SJohan Hedberg return 0; 1100392599b9SJohan Hedberg 1101765c2a96SJohan Hedberg if (conn->pending_sec_level == BT_SECURITY_SDP) 1102392599b9SJohan Hedberg return 0; 1103392599b9SJohan Hedberg 1104392599b9SJohan Hedberg /* Only request authentication for SSP connections or non-SSP 1105e9bf2bf0SVinicius Costa Gomes * devices with sec_level HIGH or if MITM protection is requested */ 1106392599b9SJohan Hedberg if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) && 1107e9bf2bf0SVinicius Costa Gomes conn->pending_sec_level != BT_SECURITY_HIGH && 1108e9bf2bf0SVinicius Costa Gomes !(conn->auth_type & 0x01)) 1109392599b9SJohan Hedberg return 0; 1110392599b9SJohan Hedberg 1111392599b9SJohan Hedberg return 1; 1112392599b9SJohan Hedberg } 1113392599b9SJohan Hedberg 1114a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 11151da177e4SLinus Torvalds { 1116127178d2SJohan Hedberg struct hci_cp_remote_name_req *cp; 1117127178d2SJohan Hedberg struct hci_conn *conn; 1118127178d2SJohan Hedberg 1119a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1120127178d2SJohan Hedberg 1121127178d2SJohan Hedberg /* If successful wait for the name req complete event before 1122127178d2SJohan Hedberg * checking for the need to do authentication */ 1123127178d2SJohan Hedberg if (!status) 1124127178d2SJohan Hedberg return; 1125127178d2SJohan Hedberg 1126127178d2SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); 1127127178d2SJohan Hedberg if (!cp) 1128127178d2SJohan Hedberg return; 1129127178d2SJohan Hedberg 1130127178d2SJohan Hedberg hci_dev_lock(hdev); 1131127178d2SJohan Hedberg 1132127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 113379c6c70cSJohan Hedberg if (!conn) 113479c6c70cSJohan Hedberg goto unlock; 113579c6c70cSJohan Hedberg 113679c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 113779c6c70cSJohan Hedberg goto unlock; 113879c6c70cSJohan Hedberg 113979c6c70cSJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { 1140127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1141127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1142127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1143127178d2SJohan Hedberg } 1144127178d2SJohan Hedberg 114579c6c70cSJohan Hedberg unlock: 1146127178d2SJohan Hedberg hci_dev_unlock(hdev); 1147a9de9248SMarcel Holtmann } 11481da177e4SLinus Torvalds 1149769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 1150769be974SMarcel Holtmann { 1151769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 1152769be974SMarcel Holtmann struct hci_conn *conn; 1153769be974SMarcel Holtmann 1154769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1155769be974SMarcel Holtmann 1156769be974SMarcel Holtmann if (!status) 1157769be974SMarcel Holtmann return; 1158769be974SMarcel Holtmann 1159769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 1160769be974SMarcel Holtmann if (!cp) 1161769be974SMarcel Holtmann return; 1162769be974SMarcel Holtmann 1163769be974SMarcel Holtmann hci_dev_lock(hdev); 1164769be974SMarcel Holtmann 1165769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1166769be974SMarcel Holtmann if (conn) { 1167769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1168769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1169769be974SMarcel Holtmann hci_conn_put(conn); 1170769be974SMarcel Holtmann } 1171769be974SMarcel Holtmann } 1172769be974SMarcel Holtmann 1173769be974SMarcel Holtmann hci_dev_unlock(hdev); 1174769be974SMarcel Holtmann } 1175769be974SMarcel Holtmann 1176769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 1177769be974SMarcel Holtmann { 1178769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features *cp; 1179769be974SMarcel Holtmann struct hci_conn *conn; 1180769be974SMarcel Holtmann 1181769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1182769be974SMarcel Holtmann 1183769be974SMarcel Holtmann if (!status) 1184769be974SMarcel Holtmann return; 1185769be974SMarcel Holtmann 1186769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 1187769be974SMarcel Holtmann if (!cp) 1188769be974SMarcel Holtmann return; 1189769be974SMarcel Holtmann 1190769be974SMarcel Holtmann hci_dev_lock(hdev); 1191769be974SMarcel Holtmann 1192769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1193769be974SMarcel Holtmann if (conn) { 1194769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1195769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1196769be974SMarcel Holtmann hci_conn_put(conn); 1197769be974SMarcel Holtmann } 1198769be974SMarcel Holtmann } 1199769be974SMarcel Holtmann 1200769be974SMarcel Holtmann hci_dev_unlock(hdev); 1201769be974SMarcel Holtmann } 1202769be974SMarcel Holtmann 1203a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 1204a9de9248SMarcel Holtmann { 1205b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 1206b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 1207b6a0dc82SMarcel Holtmann __u16 handle; 1208b6a0dc82SMarcel Holtmann 1209a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1210b6a0dc82SMarcel Holtmann 1211b6a0dc82SMarcel Holtmann if (!status) 1212b6a0dc82SMarcel Holtmann return; 1213b6a0dc82SMarcel Holtmann 1214b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 1215b6a0dc82SMarcel Holtmann if (!cp) 1216b6a0dc82SMarcel Holtmann return; 1217b6a0dc82SMarcel Holtmann 1218b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 1219b6a0dc82SMarcel Holtmann 1220b6a0dc82SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 1221b6a0dc82SMarcel Holtmann 1222b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 1223b6a0dc82SMarcel Holtmann 1224b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 12255a08ecceSAndrei Emeltchenko if (acl) { 12265a08ecceSAndrei Emeltchenko sco = acl->link; 12275a08ecceSAndrei Emeltchenko if (sco) { 1228b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 1229b6a0dc82SMarcel Holtmann 1230b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(sco, status); 1231b6a0dc82SMarcel Holtmann hci_conn_del(sco); 1232b6a0dc82SMarcel Holtmann } 12335a08ecceSAndrei Emeltchenko } 1234b6a0dc82SMarcel Holtmann 1235b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 1236a9de9248SMarcel Holtmann } 1237a9de9248SMarcel Holtmann 1238a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 1239a9de9248SMarcel Holtmann { 1240a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 124104837f64SMarcel Holtmann struct hci_conn *conn; 124204837f64SMarcel Holtmann 1243a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1244a9de9248SMarcel Holtmann 1245a9de9248SMarcel Holtmann if (!status) 1246a9de9248SMarcel Holtmann return; 1247a9de9248SMarcel Holtmann 1248a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 124904837f64SMarcel Holtmann if (!cp) 1250a9de9248SMarcel Holtmann return; 125104837f64SMarcel Holtmann 125204837f64SMarcel Holtmann hci_dev_lock(hdev); 125304837f64SMarcel Holtmann 125404837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1255e73439d8SMarcel Holtmann if (conn) { 125604837f64SMarcel Holtmann clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); 125704837f64SMarcel Holtmann 1258e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 1259e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1260e73439d8SMarcel Holtmann } 1261e73439d8SMarcel Holtmann 126204837f64SMarcel Holtmann hci_dev_unlock(hdev); 126304837f64SMarcel Holtmann } 126404837f64SMarcel Holtmann 1265a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 1266a9de9248SMarcel Holtmann { 1267a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 126804837f64SMarcel Holtmann struct hci_conn *conn; 126904837f64SMarcel Holtmann 1270a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1271a9de9248SMarcel Holtmann 1272a9de9248SMarcel Holtmann if (!status) 1273a9de9248SMarcel Holtmann return; 1274a9de9248SMarcel Holtmann 1275a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 127604837f64SMarcel Holtmann if (!cp) 1277a9de9248SMarcel Holtmann return; 127804837f64SMarcel Holtmann 127904837f64SMarcel Holtmann hci_dev_lock(hdev); 128004837f64SMarcel Holtmann 128104837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1282e73439d8SMarcel Holtmann if (conn) { 128304837f64SMarcel Holtmann clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); 128404837f64SMarcel Holtmann 1285e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 1286e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1287e73439d8SMarcel Holtmann } 1288e73439d8SMarcel Holtmann 128904837f64SMarcel Holtmann hci_dev_unlock(hdev); 129004837f64SMarcel Holtmann } 129104837f64SMarcel Holtmann 1292fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) 1293fcd89c09SVille Tervo { 1294fcd89c09SVille Tervo struct hci_cp_le_create_conn *cp; 1295fcd89c09SVille Tervo struct hci_conn *conn; 1296fcd89c09SVille Tervo 1297fcd89c09SVille Tervo BT_DBG("%s status 0x%x", hdev->name, status); 1298fcd89c09SVille Tervo 1299fcd89c09SVille Tervo cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN); 1300fcd89c09SVille Tervo if (!cp) 1301fcd89c09SVille Tervo return; 1302fcd89c09SVille Tervo 1303fcd89c09SVille Tervo hci_dev_lock(hdev); 1304fcd89c09SVille Tervo 1305fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr); 1306fcd89c09SVille Tervo 1307fcd89c09SVille Tervo BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr), 1308fcd89c09SVille Tervo conn); 1309fcd89c09SVille Tervo 1310fcd89c09SVille Tervo if (status) { 1311fcd89c09SVille Tervo if (conn && conn->state == BT_CONNECT) { 1312fcd89c09SVille Tervo conn->state = BT_CLOSED; 1313fcd89c09SVille Tervo hci_proto_connect_cfm(conn, status); 1314fcd89c09SVille Tervo hci_conn_del(conn); 1315fcd89c09SVille Tervo } 1316fcd89c09SVille Tervo } else { 1317fcd89c09SVille Tervo if (!conn) { 1318fcd89c09SVille Tervo conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr); 131929b7988aSAndre Guedes if (conn) { 132029b7988aSAndre Guedes conn->dst_type = cp->peer_addr_type; 1321fcd89c09SVille Tervo conn->out = 1; 132229b7988aSAndre Guedes } else { 1323fcd89c09SVille Tervo BT_ERR("No memory for new connection"); 1324fcd89c09SVille Tervo } 1325fcd89c09SVille Tervo } 132629b7988aSAndre Guedes } 1327fcd89c09SVille Tervo 1328fcd89c09SVille Tervo hci_dev_unlock(hdev); 1329fcd89c09SVille Tervo } 1330fcd89c09SVille Tervo 1331a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) 1332a7a595f6SVinicius Costa Gomes { 1333a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, status); 1334a7a595f6SVinicius Costa Gomes } 1335a7a595f6SVinicius Costa Gomes 13361da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 13371da177e4SLinus Torvalds { 13381da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 13391da177e4SLinus Torvalds 13401da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, status); 13411da177e4SLinus Torvalds 13422d20a26aSOliver Neukum if (test_and_clear_bit(HCI_INQUIRY, &hdev->flags) && 13432d20a26aSOliver Neukum test_bit(HCI_MGMT, &hdev->flags)) 1344314b2381SJohan Hedberg mgmt_discovering(hdev->id, 0); 1345a9de9248SMarcel Holtmann 134623bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 13476bd57416SMarcel Holtmann 1348a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 13491da177e4SLinus Torvalds } 13501da177e4SLinus Torvalds 13511da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 13521da177e4SLinus Torvalds { 135345bb4bf0SMarcel Holtmann struct inquiry_data data; 1354a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 13551da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 13561da177e4SLinus Torvalds 13571da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 13581da177e4SLinus Torvalds 135945bb4bf0SMarcel Holtmann if (!num_rsp) 136045bb4bf0SMarcel Holtmann return; 136145bb4bf0SMarcel Holtmann 13621da177e4SLinus Torvalds hci_dev_lock(hdev); 136345bb4bf0SMarcel Holtmann 1364314b2381SJohan Hedberg if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) { 1365314b2381SJohan Hedberg 1366314b2381SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 1367314b2381SJohan Hedberg mgmt_discovering(hdev->id, 1); 1368314b2381SJohan Hedberg } 1369314b2381SJohan Hedberg 1370e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 13711da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 13721da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 13731da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 13741da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 13751da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 13761da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 13771da177e4SLinus Torvalds data.rssi = 0x00; 137841a96212SMarcel Holtmann data.ssp_mode = 0x00; 13791da177e4SLinus Torvalds hci_inquiry_cache_update(hdev, &data); 1380e17acd40SJohan Hedberg mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class, 0, 1381e17acd40SJohan Hedberg NULL); 13821da177e4SLinus Torvalds } 138345bb4bf0SMarcel Holtmann 13841da177e4SLinus Torvalds hci_dev_unlock(hdev); 13851da177e4SLinus Torvalds } 13861da177e4SLinus Torvalds 1387a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 13881da177e4SLinus Torvalds { 1389a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 1390a9de9248SMarcel Holtmann struct hci_conn *conn; 13911da177e4SLinus Torvalds 1392a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 139345bb4bf0SMarcel Holtmann 13941da177e4SLinus Torvalds hci_dev_lock(hdev); 139545bb4bf0SMarcel Holtmann 1396a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 13979499237aSMarcel Holtmann if (!conn) { 13989499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 13999499237aSMarcel Holtmann goto unlock; 14009499237aSMarcel Holtmann 14019499237aSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 1402a9de9248SMarcel Holtmann if (!conn) 1403a9de9248SMarcel Holtmann goto unlock; 140445bb4bf0SMarcel Holtmann 14059499237aSMarcel Holtmann conn->type = SCO_LINK; 14069499237aSMarcel Holtmann } 14079499237aSMarcel Holtmann 1408a9de9248SMarcel Holtmann if (!ev->status) { 1409a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 1410769be974SMarcel Holtmann 1411769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 1412769be974SMarcel Holtmann conn->state = BT_CONFIG; 1413769be974SMarcel Holtmann hci_conn_hold(conn); 1414052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1415cfafccf7SVinicius Costa Gomes mgmt_connected(hdev->id, &ev->bdaddr, conn->type); 1416769be974SMarcel Holtmann } else 1417a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 1418a9de9248SMarcel Holtmann 14199eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 14207d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 14217d0db0a3SMarcel Holtmann 1422a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 1423a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1424a9de9248SMarcel Holtmann 1425a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 1426a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1427a9de9248SMarcel Holtmann 1428a9de9248SMarcel Holtmann /* Get remote features */ 1429a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 1430a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 1431a9de9248SMarcel Holtmann cp.handle = ev->handle; 1432769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 1433769be974SMarcel Holtmann sizeof(cp), &cp); 143445bb4bf0SMarcel Holtmann } 1435a9de9248SMarcel Holtmann 1436a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 1437a8746417SMarcel Holtmann if (!conn->out && hdev->hci_ver < 3) { 1438a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 1439a9de9248SMarcel Holtmann cp.handle = ev->handle; 1440a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1441a8746417SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, 1442a8746417SMarcel Holtmann sizeof(cp), &cp); 1443a9de9248SMarcel Holtmann } 144417d5c04cSJohan Hedberg } else { 1445a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 144617d5c04cSJohan Hedberg if (conn->type == ACL_LINK) 144717d5c04cSJohan Hedberg mgmt_connect_failed(hdev->id, &ev->bdaddr, ev->status); 144817d5c04cSJohan Hedberg } 144945bb4bf0SMarcel Holtmann 1450e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 1451e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 145245bb4bf0SMarcel Holtmann 1453769be974SMarcel Holtmann if (ev->status) { 1454a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1455a9de9248SMarcel Holtmann hci_conn_del(conn); 1456c89b6e6bSMarcel Holtmann } else if (ev->link_type != ACL_LINK) 1457c89b6e6bSMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1458a9de9248SMarcel Holtmann 1459a9de9248SMarcel Holtmann unlock: 14601da177e4SLinus Torvalds hci_dev_unlock(hdev); 1461a9de9248SMarcel Holtmann 1462a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 14631da177e4SLinus Torvalds } 14641da177e4SLinus Torvalds 14651da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 14661da177e4SLinus Torvalds { 1467a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 14681da177e4SLinus Torvalds int mask = hdev->link_mode; 14691da177e4SLinus Torvalds 1470a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s type 0x%x", hdev->name, 14711da177e4SLinus Torvalds batostr(&ev->bdaddr), ev->link_type); 14721da177e4SLinus Torvalds 14731da177e4SLinus Torvalds mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); 14741da177e4SLinus Torvalds 1475138d22efSSzymon Janc if ((mask & HCI_LM_ACCEPT) && 1476138d22efSSzymon Janc !hci_blacklist_lookup(hdev, &ev->bdaddr)) { 14771da177e4SLinus Torvalds /* Connection accepted */ 1478c7bdd502SMarcel Holtmann struct inquiry_entry *ie; 14791da177e4SLinus Torvalds struct hci_conn *conn; 14801da177e4SLinus Torvalds 14811da177e4SLinus Torvalds hci_dev_lock(hdev); 1482b6a0dc82SMarcel Holtmann 1483cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 1484cc11b9c1SAndrei Emeltchenko if (ie) 1485c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 1486c7bdd502SMarcel Holtmann 14871da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 14881da177e4SLinus Torvalds if (!conn) { 1489cc11b9c1SAndrei Emeltchenko conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); 1490cc11b9c1SAndrei Emeltchenko if (!conn) { 1491893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 14921da177e4SLinus Torvalds hci_dev_unlock(hdev); 14931da177e4SLinus Torvalds return; 14941da177e4SLinus Torvalds } 14951da177e4SLinus Torvalds } 1496b6a0dc82SMarcel Holtmann 14971da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 14981da177e4SLinus Torvalds conn->state = BT_CONNECT; 1499b6a0dc82SMarcel Holtmann 15001da177e4SLinus Torvalds hci_dev_unlock(hdev); 15011da177e4SLinus Torvalds 1502b6a0dc82SMarcel Holtmann if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) { 1503b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 1504b6a0dc82SMarcel Holtmann 15051da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 15061da177e4SLinus Torvalds 15071da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 15081da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 15091da177e4SLinus Torvalds else 15101da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 15111da177e4SLinus Torvalds 1512b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, 1513b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1514b6a0dc82SMarcel Holtmann } else { 1515b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 1516b6a0dc82SMarcel Holtmann 1517b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 1518a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1519b6a0dc82SMarcel Holtmann 1520b6a0dc82SMarcel Holtmann cp.tx_bandwidth = cpu_to_le32(0x00001f40); 1521b6a0dc82SMarcel Holtmann cp.rx_bandwidth = cpu_to_le32(0x00001f40); 1522b6a0dc82SMarcel Holtmann cp.max_latency = cpu_to_le16(0xffff); 1523b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 1524b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 1525b6a0dc82SMarcel Holtmann 1526b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 1527b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1528b6a0dc82SMarcel Holtmann } 15291da177e4SLinus Torvalds } else { 15301da177e4SLinus Torvalds /* Connection rejected */ 15311da177e4SLinus Torvalds struct hci_cp_reject_conn_req cp; 15321da177e4SLinus Torvalds 15331da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 15341da177e4SLinus Torvalds cp.reason = 0x0f; 1535a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 15361da177e4SLinus Torvalds } 15371da177e4SLinus Torvalds } 15381da177e4SLinus Torvalds 15391da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 15401da177e4SLinus Torvalds { 1541a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 154204837f64SMarcel Holtmann struct hci_conn *conn; 15431da177e4SLinus Torvalds 15441da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 15451da177e4SLinus Torvalds 15468962ee74SJohan Hedberg if (ev->status) { 15478962ee74SJohan Hedberg mgmt_disconnect_failed(hdev->id); 15481da177e4SLinus Torvalds return; 15498962ee74SJohan Hedberg } 15501da177e4SLinus Torvalds 15511da177e4SLinus Torvalds hci_dev_lock(hdev); 15521da177e4SLinus Torvalds 155304837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1554f7520543SJohan Hedberg if (!conn) 1555f7520543SJohan Hedberg goto unlock; 1556f7520543SJohan Hedberg 15571da177e4SLinus Torvalds conn->state = BT_CLOSED; 15587d0db0a3SMarcel Holtmann 155983bc71b4SVinicius Costa Gomes if (conn->type == ACL_LINK || conn->type == LE_LINK) 1560f7520543SJohan Hedberg mgmt_disconnected(hdev->id, &conn->dst); 1561f7520543SJohan Hedberg 15622950f21aSMarcel Holtmann hci_proto_disconn_cfm(conn, ev->reason); 15631da177e4SLinus Torvalds hci_conn_del(conn); 15641da177e4SLinus Torvalds 1565f7520543SJohan Hedberg unlock: 15661da177e4SLinus Torvalds hci_dev_unlock(hdev); 15671da177e4SLinus Torvalds } 15681da177e4SLinus Torvalds 1569a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1570a9de9248SMarcel Holtmann { 1571a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 1572a9de9248SMarcel Holtmann struct hci_conn *conn; 1573a9de9248SMarcel Holtmann 1574a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1575a9de9248SMarcel Holtmann 1576a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1577a9de9248SMarcel Holtmann 1578a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1579d7556e20SWaldemar Rymarkiewicz if (!conn) 1580d7556e20SWaldemar Rymarkiewicz goto unlock; 1581d7556e20SWaldemar Rymarkiewicz 1582765c2a96SJohan Hedberg if (!ev->status) { 158319f8def0SWaldemar Rymarkiewicz if (!(conn->ssp_mode > 0 && hdev->ssp_mode > 0) && 1584d7556e20SWaldemar Rymarkiewicz test_bit(HCI_CONN_REAUTH_PEND, &conn->pend)) { 1585d7556e20SWaldemar Rymarkiewicz BT_INFO("re-auth of legacy device is not possible."); 158619f8def0SWaldemar Rymarkiewicz } else { 1587a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1588765c2a96SJohan Hedberg conn->sec_level = conn->pending_sec_level; 158919f8def0SWaldemar Rymarkiewicz } 15902a611692SJohan Hedberg } else { 15912a611692SJohan Hedberg mgmt_auth_failed(hdev->id, &conn->dst, ev->status); 15922a611692SJohan Hedberg } 1593a9de9248SMarcel Holtmann 1594a9de9248SMarcel Holtmann clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); 159519f8def0SWaldemar Rymarkiewicz clear_bit(HCI_CONN_REAUTH_PEND, &conn->pend); 1596a9de9248SMarcel Holtmann 1597f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1598d7556e20SWaldemar Rymarkiewicz if (!ev->status && hdev->ssp_mode > 0 && conn->ssp_mode > 0) { 1599f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1600f8558555SMarcel Holtmann cp.handle = ev->handle; 1601f8558555SMarcel Holtmann cp.encrypt = 0x01; 1602d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1603d7556e20SWaldemar Rymarkiewicz &cp); 1604f8558555SMarcel Holtmann } else { 1605f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1606f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1607f8558555SMarcel Holtmann hci_conn_put(conn); 1608f8558555SMarcel Holtmann } 1609052b30b0SMarcel Holtmann } else { 1610a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 1611a9de9248SMarcel Holtmann 1612052b30b0SMarcel Holtmann hci_conn_hold(conn); 1613052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1614052b30b0SMarcel Holtmann hci_conn_put(conn); 1615052b30b0SMarcel Holtmann } 1616052b30b0SMarcel Holtmann 1617a9de9248SMarcel Holtmann if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) { 1618a9de9248SMarcel Holtmann if (!ev->status) { 1619a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1620f8558555SMarcel Holtmann cp.handle = ev->handle; 1621f8558555SMarcel Holtmann cp.encrypt = 0x01; 1622d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1623d7556e20SWaldemar Rymarkiewicz &cp); 1624a9de9248SMarcel Holtmann } else { 1625a9de9248SMarcel Holtmann clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); 1626a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 1627a9de9248SMarcel Holtmann } 1628a9de9248SMarcel Holtmann } 1629a9de9248SMarcel Holtmann 1630d7556e20SWaldemar Rymarkiewicz unlock: 1631a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1632a9de9248SMarcel Holtmann } 1633a9de9248SMarcel Holtmann 1634a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 1635a9de9248SMarcel Holtmann { 1636127178d2SJohan Hedberg struct hci_ev_remote_name *ev = (void *) skb->data; 1637127178d2SJohan Hedberg struct hci_conn *conn; 1638127178d2SJohan Hedberg 1639a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1640a9de9248SMarcel Holtmann 1641a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 1642127178d2SJohan Hedberg 1643127178d2SJohan Hedberg hci_dev_lock(hdev); 1644127178d2SJohan Hedberg 1645a88a9652SJohan Hedberg if (ev->status == 0 && test_bit(HCI_MGMT, &hdev->flags)) 1646a88a9652SJohan Hedberg mgmt_remote_name(hdev->id, &ev->bdaddr, ev->name); 1647a88a9652SJohan Hedberg 1648127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 164979c6c70cSJohan Hedberg if (!conn) 165079c6c70cSJohan Hedberg goto unlock; 165179c6c70cSJohan Hedberg 165279c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 165379c6c70cSJohan Hedberg goto unlock; 165479c6c70cSJohan Hedberg 165579c6c70cSJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { 1656127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1657127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1658127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1659127178d2SJohan Hedberg } 1660127178d2SJohan Hedberg 166179c6c70cSJohan Hedberg unlock: 1662127178d2SJohan Hedberg hci_dev_unlock(hdev); 1663a9de9248SMarcel Holtmann } 1664a9de9248SMarcel Holtmann 1665a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 1666a9de9248SMarcel Holtmann { 1667a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 1668a9de9248SMarcel Holtmann struct hci_conn *conn; 1669a9de9248SMarcel Holtmann 1670a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1671a9de9248SMarcel Holtmann 1672a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1673a9de9248SMarcel Holtmann 1674a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1675a9de9248SMarcel Holtmann if (conn) { 1676a9de9248SMarcel Holtmann if (!ev->status) { 1677ae293196SMarcel Holtmann if (ev->encrypt) { 1678ae293196SMarcel Holtmann /* Encryption implies authentication */ 1679ae293196SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1680a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1681da85e5e5SVinicius Costa Gomes conn->sec_level = conn->pending_sec_level; 1682ae293196SMarcel Holtmann } else 1683a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_ENCRYPT; 1684a9de9248SMarcel Holtmann } 1685a9de9248SMarcel Holtmann 1686a9de9248SMarcel Holtmann clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); 1687a9de9248SMarcel Holtmann 1688f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1689f8558555SMarcel Holtmann if (!ev->status) 1690f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1691f8558555SMarcel Holtmann 1692f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1693f8558555SMarcel Holtmann hci_conn_put(conn); 1694f8558555SMarcel Holtmann } else 1695a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 1696a9de9248SMarcel Holtmann } 1697a9de9248SMarcel Holtmann 1698a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1699a9de9248SMarcel Holtmann } 1700a9de9248SMarcel Holtmann 1701a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1702a9de9248SMarcel Holtmann { 1703a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 1704a9de9248SMarcel Holtmann struct hci_conn *conn; 1705a9de9248SMarcel Holtmann 1706a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1707a9de9248SMarcel Holtmann 1708a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1709a9de9248SMarcel Holtmann 1710a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1711a9de9248SMarcel Holtmann if (conn) { 1712a9de9248SMarcel Holtmann if (!ev->status) 1713a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_SECURE; 1714a9de9248SMarcel Holtmann 1715a9de9248SMarcel Holtmann clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); 1716a9de9248SMarcel Holtmann 1717a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 1718a9de9248SMarcel Holtmann } 1719a9de9248SMarcel Holtmann 1720a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1721a9de9248SMarcel Holtmann } 1722a9de9248SMarcel Holtmann 1723a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 1724a9de9248SMarcel Holtmann { 1725a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 1726a9de9248SMarcel Holtmann struct hci_conn *conn; 1727a9de9248SMarcel Holtmann 1728a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1729a9de9248SMarcel Holtmann 1730a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1731a9de9248SMarcel Holtmann 1732a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1733ccd556feSJohan Hedberg if (!conn) 1734ccd556feSJohan Hedberg goto unlock; 1735ccd556feSJohan Hedberg 1736769be974SMarcel Holtmann if (!ev->status) 1737a9de9248SMarcel Holtmann memcpy(conn->features, ev->features, 8); 1738a9de9248SMarcel Holtmann 1739ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 1740ccd556feSJohan Hedberg goto unlock; 1741ccd556feSJohan Hedberg 1742ccd556feSJohan Hedberg if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { 1743769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 1744769be974SMarcel Holtmann cp.handle = ev->handle; 1745769be974SMarcel Holtmann cp.page = 0x01; 1746ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 1747769be974SMarcel Holtmann sizeof(cp), &cp); 1748392599b9SJohan Hedberg goto unlock; 1749392599b9SJohan Hedberg } 1750392599b9SJohan Hedberg 1751127178d2SJohan Hedberg if (!ev->status) { 1752127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 1753127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 1754127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 1755127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 1756127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 1757127178d2SJohan Hedberg } 1758392599b9SJohan Hedberg 1759127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 1760769be974SMarcel Holtmann conn->state = BT_CONNECTED; 1761769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1762769be974SMarcel Holtmann hci_conn_put(conn); 1763769be974SMarcel Holtmann } 1764769be974SMarcel Holtmann 1765ccd556feSJohan Hedberg unlock: 1766a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1767a9de9248SMarcel Holtmann } 1768a9de9248SMarcel Holtmann 1769a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) 1770a9de9248SMarcel Holtmann { 1771a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1772a9de9248SMarcel Holtmann } 1773a9de9248SMarcel Holtmann 1774a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1775a9de9248SMarcel Holtmann { 1776a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1777a9de9248SMarcel Holtmann } 1778a9de9248SMarcel Holtmann 1779a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1780a9de9248SMarcel Holtmann { 1781a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 1782a9de9248SMarcel Holtmann __u16 opcode; 1783a9de9248SMarcel Holtmann 1784a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 1785a9de9248SMarcel Holtmann 1786a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 1787a9de9248SMarcel Holtmann 1788a9de9248SMarcel Holtmann switch (opcode) { 1789a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 1790a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 1791a9de9248SMarcel Holtmann break; 1792a9de9248SMarcel Holtmann 1793a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 1794a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 1795a9de9248SMarcel Holtmann break; 1796a9de9248SMarcel Holtmann 1797a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 1798a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 1799a9de9248SMarcel Holtmann break; 1800a9de9248SMarcel Holtmann 1801a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 1802a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 1803a9de9248SMarcel Holtmann break; 1804a9de9248SMarcel Holtmann 1805e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 1806e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 1807e4e8e37cSMarcel Holtmann break; 1808e4e8e37cSMarcel Holtmann 1809a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 1810a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 1811a9de9248SMarcel Holtmann break; 1812a9de9248SMarcel Holtmann 1813e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 1814e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 1815e4e8e37cSMarcel Holtmann break; 1816e4e8e37cSMarcel Holtmann 1817e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 1818e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 1819e4e8e37cSMarcel Holtmann break; 1820e4e8e37cSMarcel Holtmann 1821a9de9248SMarcel Holtmann case HCI_OP_RESET: 1822a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 1823a9de9248SMarcel Holtmann break; 1824a9de9248SMarcel Holtmann 1825a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 1826a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 1827a9de9248SMarcel Holtmann break; 1828a9de9248SMarcel Holtmann 1829a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 1830a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 1831a9de9248SMarcel Holtmann break; 1832a9de9248SMarcel Holtmann 1833a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 1834a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 1835a9de9248SMarcel Holtmann break; 1836a9de9248SMarcel Holtmann 1837a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 1838a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 1839a9de9248SMarcel Holtmann break; 1840a9de9248SMarcel Holtmann 1841a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 1842a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 1843a9de9248SMarcel Holtmann break; 1844a9de9248SMarcel Holtmann 1845a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 1846a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 1847a9de9248SMarcel Holtmann break; 1848a9de9248SMarcel Holtmann 1849a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 1850a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 1851a9de9248SMarcel Holtmann break; 1852a9de9248SMarcel Holtmann 1853a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 1854a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 1855a9de9248SMarcel Holtmann break; 1856a9de9248SMarcel Holtmann 1857a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 1858a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 1859a9de9248SMarcel Holtmann break; 1860a9de9248SMarcel Holtmann 1861a9de9248SMarcel Holtmann case HCI_OP_HOST_BUFFER_SIZE: 1862a9de9248SMarcel Holtmann hci_cc_host_buffer_size(hdev, skb); 1863a9de9248SMarcel Holtmann break; 1864a9de9248SMarcel Holtmann 1865333140b5SMarcel Holtmann case HCI_OP_READ_SSP_MODE: 1866333140b5SMarcel Holtmann hci_cc_read_ssp_mode(hdev, skb); 1867333140b5SMarcel Holtmann break; 1868333140b5SMarcel Holtmann 1869333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 1870333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 1871333140b5SMarcel Holtmann break; 1872333140b5SMarcel Holtmann 1873a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 1874a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 1875a9de9248SMarcel Holtmann break; 1876a9de9248SMarcel Holtmann 1877a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 1878a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 1879a9de9248SMarcel Holtmann break; 1880a9de9248SMarcel Holtmann 1881a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 1882a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 1883a9de9248SMarcel Holtmann break; 1884a9de9248SMarcel Holtmann 1885971e3a4bSAndre Guedes case HCI_OP_READ_LOCAL_EXT_FEATURES: 1886971e3a4bSAndre Guedes hci_cc_read_local_ext_features(hdev, skb); 1887971e3a4bSAndre Guedes break; 1888971e3a4bSAndre Guedes 1889a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 1890a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 1891a9de9248SMarcel Holtmann break; 1892a9de9248SMarcel Holtmann 1893a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 1894a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 1895a9de9248SMarcel Holtmann break; 1896a9de9248SMarcel Holtmann 189723bb5763SJohan Hedberg case HCI_OP_WRITE_CA_TIMEOUT: 189823bb5763SJohan Hedberg hci_cc_write_ca_timeout(hdev, skb); 189923bb5763SJohan Hedberg break; 190023bb5763SJohan Hedberg 1901b0916ea0SJohan Hedberg case HCI_OP_DELETE_STORED_LINK_KEY: 1902b0916ea0SJohan Hedberg hci_cc_delete_stored_link_key(hdev, skb); 1903b0916ea0SJohan Hedberg break; 1904b0916ea0SJohan Hedberg 1905d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_MASK: 1906d5859e22SJohan Hedberg hci_cc_set_event_mask(hdev, skb); 1907d5859e22SJohan Hedberg break; 1908d5859e22SJohan Hedberg 1909d5859e22SJohan Hedberg case HCI_OP_WRITE_INQUIRY_MODE: 1910d5859e22SJohan Hedberg hci_cc_write_inquiry_mode(hdev, skb); 1911d5859e22SJohan Hedberg break; 1912d5859e22SJohan Hedberg 1913d5859e22SJohan Hedberg case HCI_OP_READ_INQ_RSP_TX_POWER: 1914d5859e22SJohan Hedberg hci_cc_read_inq_rsp_tx_power(hdev, skb); 1915d5859e22SJohan Hedberg break; 1916d5859e22SJohan Hedberg 1917d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_FLT: 1918d5859e22SJohan Hedberg hci_cc_set_event_flt(hdev, skb); 1919d5859e22SJohan Hedberg break; 1920d5859e22SJohan Hedberg 1921980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_REPLY: 1922980e1a53SJohan Hedberg hci_cc_pin_code_reply(hdev, skb); 1923980e1a53SJohan Hedberg break; 1924980e1a53SJohan Hedberg 1925980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_NEG_REPLY: 1926980e1a53SJohan Hedberg hci_cc_pin_code_neg_reply(hdev, skb); 1927980e1a53SJohan Hedberg break; 1928980e1a53SJohan Hedberg 1929c35938b2SSzymon Janc case HCI_OP_READ_LOCAL_OOB_DATA: 1930c35938b2SSzymon Janc hci_cc_read_local_oob_data_reply(hdev, skb); 1931c35938b2SSzymon Janc break; 1932c35938b2SSzymon Janc 19336ed58ec5SVille Tervo case HCI_OP_LE_READ_BUFFER_SIZE: 19346ed58ec5SVille Tervo hci_cc_le_read_buffer_size(hdev, skb); 19356ed58ec5SVille Tervo break; 19366ed58ec5SVille Tervo 1937a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_REPLY: 1938a5c29683SJohan Hedberg hci_cc_user_confirm_reply(hdev, skb); 1939a5c29683SJohan Hedberg break; 1940a5c29683SJohan Hedberg 1941a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_NEG_REPLY: 1942a5c29683SJohan Hedberg hci_cc_user_confirm_neg_reply(hdev, skb); 1943a5c29683SJohan Hedberg break; 1944a5c29683SJohan Hedberg 1945eb9d91f5SAndre Guedes case HCI_OP_LE_SET_SCAN_ENABLE: 1946eb9d91f5SAndre Guedes hci_cc_le_set_scan_enable(hdev, skb); 1947eb9d91f5SAndre Guedes break; 1948eb9d91f5SAndre Guedes 1949a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_REPLY: 1950a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_reply(hdev, skb); 1951a7a595f6SVinicius Costa Gomes break; 1952a7a595f6SVinicius Costa Gomes 1953a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_NEG_REPLY: 1954a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_neg_reply(hdev, skb); 1955a7a595f6SVinicius Costa Gomes break; 1956a7a595f6SVinicius Costa Gomes 1957f9b49306SAndre Guedes case HCI_OP_WRITE_LE_HOST_SUPPORTED: 1958f9b49306SAndre Guedes hci_cc_write_le_host_supported(hdev, skb); 1959f9b49306SAndre Guedes break; 1960f9b49306SAndre Guedes 1961a9de9248SMarcel Holtmann default: 1962a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 1963a9de9248SMarcel Holtmann break; 1964a9de9248SMarcel Holtmann } 1965a9de9248SMarcel Holtmann 19666bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 19676bd32326SVille Tervo del_timer(&hdev->cmd_timer); 19686bd32326SVille Tervo 1969a9de9248SMarcel Holtmann if (ev->ncmd) { 1970a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 1971a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 1972c78ae283SMarcel Holtmann tasklet_schedule(&hdev->cmd_task); 1973a9de9248SMarcel Holtmann } 1974a9de9248SMarcel Holtmann } 1975a9de9248SMarcel Holtmann 1976a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 1977a9de9248SMarcel Holtmann { 1978a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 1979a9de9248SMarcel Holtmann __u16 opcode; 1980a9de9248SMarcel Holtmann 1981a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 1982a9de9248SMarcel Holtmann 1983a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 1984a9de9248SMarcel Holtmann 1985a9de9248SMarcel Holtmann switch (opcode) { 1986a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 1987a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 1988a9de9248SMarcel Holtmann break; 1989a9de9248SMarcel Holtmann 1990a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 1991a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 1992a9de9248SMarcel Holtmann break; 1993a9de9248SMarcel Holtmann 1994a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 1995a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 1996a9de9248SMarcel Holtmann break; 1997a9de9248SMarcel Holtmann 1998f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 1999f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 2000f8558555SMarcel Holtmann break; 2001f8558555SMarcel Holtmann 2002f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 2003f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 2004f8558555SMarcel Holtmann break; 2005f8558555SMarcel Holtmann 2006a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 2007a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 2008a9de9248SMarcel Holtmann break; 2009a9de9248SMarcel Holtmann 2010769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 2011769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 2012769be974SMarcel Holtmann break; 2013769be974SMarcel Holtmann 2014769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 2015769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 2016769be974SMarcel Holtmann break; 2017769be974SMarcel Holtmann 2018a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 2019a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 2020a9de9248SMarcel Holtmann break; 2021a9de9248SMarcel Holtmann 2022a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 2023a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 2024a9de9248SMarcel Holtmann break; 2025a9de9248SMarcel Holtmann 2026a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 2027a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 2028a9de9248SMarcel Holtmann break; 2029a9de9248SMarcel Holtmann 20308962ee74SJohan Hedberg case HCI_OP_DISCONNECT: 20318962ee74SJohan Hedberg if (ev->status != 0) 20328962ee74SJohan Hedberg mgmt_disconnect_failed(hdev->id); 20338962ee74SJohan Hedberg break; 20348962ee74SJohan Hedberg 2035fcd89c09SVille Tervo case HCI_OP_LE_CREATE_CONN: 2036fcd89c09SVille Tervo hci_cs_le_create_conn(hdev, ev->status); 2037fcd89c09SVille Tervo break; 2038fcd89c09SVille Tervo 2039a7a595f6SVinicius Costa Gomes case HCI_OP_LE_START_ENC: 2040a7a595f6SVinicius Costa Gomes hci_cs_le_start_enc(hdev, ev->status); 2041a7a595f6SVinicius Costa Gomes break; 2042a7a595f6SVinicius Costa Gomes 2043a9de9248SMarcel Holtmann default: 2044a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 2045a9de9248SMarcel Holtmann break; 2046a9de9248SMarcel Holtmann } 2047a9de9248SMarcel Holtmann 20486bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 20496bd32326SVille Tervo del_timer(&hdev->cmd_timer); 20506bd32326SVille Tervo 205110572132SGustavo F. Padovan if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2052a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2053a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2054c78ae283SMarcel Holtmann tasklet_schedule(&hdev->cmd_task); 2055a9de9248SMarcel Holtmann } 2056a9de9248SMarcel Holtmann } 2057a9de9248SMarcel Holtmann 2058a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2059a9de9248SMarcel Holtmann { 2060a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 2061a9de9248SMarcel Holtmann struct hci_conn *conn; 2062a9de9248SMarcel Holtmann 2063a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2064a9de9248SMarcel Holtmann 2065a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2066a9de9248SMarcel Holtmann 2067a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2068a9de9248SMarcel Holtmann if (conn) { 2069a9de9248SMarcel Holtmann if (!ev->status) { 2070a9de9248SMarcel Holtmann if (ev->role) 2071a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_MASTER; 2072a9de9248SMarcel Holtmann else 2073a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_MASTER; 2074a9de9248SMarcel Holtmann } 2075a9de9248SMarcel Holtmann 2076a9de9248SMarcel Holtmann clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend); 2077a9de9248SMarcel Holtmann 2078a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 2079a9de9248SMarcel Holtmann } 2080a9de9248SMarcel Holtmann 2081a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2082a9de9248SMarcel Holtmann } 2083a9de9248SMarcel Holtmann 20841da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 20851da177e4SLinus Torvalds { 2086a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 20871ebb9252SMarcel Holtmann __le16 *ptr; 20881da177e4SLinus Torvalds int i; 20891da177e4SLinus Torvalds 20901da177e4SLinus Torvalds skb_pull(skb, sizeof(*ev)); 20911da177e4SLinus Torvalds 20921da177e4SLinus Torvalds BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 20931da177e4SLinus Torvalds 20941da177e4SLinus Torvalds if (skb->len < ev->num_hndl * 4) { 20951da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 20961da177e4SLinus Torvalds return; 20971da177e4SLinus Torvalds } 20981da177e4SLinus Torvalds 20991da177e4SLinus Torvalds tasklet_disable(&hdev->tx_task); 21001da177e4SLinus Torvalds 21011ebb9252SMarcel Holtmann for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) { 21021da177e4SLinus Torvalds struct hci_conn *conn; 21031da177e4SLinus Torvalds __u16 handle, count; 21041da177e4SLinus Torvalds 210583985319SHarvey Harrison handle = get_unaligned_le16(ptr++); 210683985319SHarvey Harrison count = get_unaligned_le16(ptr++); 21071da177e4SLinus Torvalds 21081da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 21091da177e4SLinus Torvalds if (conn) { 21101da177e4SLinus Torvalds conn->sent -= count; 21111da177e4SLinus Torvalds 21125b7f9909SMarcel Holtmann if (conn->type == ACL_LINK) { 211370f23020SAndrei Emeltchenko hdev->acl_cnt += count; 211470f23020SAndrei Emeltchenko if (hdev->acl_cnt > hdev->acl_pkts) 21151da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 21166ed58ec5SVille Tervo } else if (conn->type == LE_LINK) { 21176ed58ec5SVille Tervo if (hdev->le_pkts) { 21186ed58ec5SVille Tervo hdev->le_cnt += count; 21196ed58ec5SVille Tervo if (hdev->le_cnt > hdev->le_pkts) 21206ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 21216ed58ec5SVille Tervo } else { 21226ed58ec5SVille Tervo hdev->acl_cnt += count; 21236ed58ec5SVille Tervo if (hdev->acl_cnt > hdev->acl_pkts) 21246ed58ec5SVille Tervo hdev->acl_cnt = hdev->acl_pkts; 21256ed58ec5SVille Tervo } 21265b7f9909SMarcel Holtmann } else { 212770f23020SAndrei Emeltchenko hdev->sco_cnt += count; 212870f23020SAndrei Emeltchenko if (hdev->sco_cnt > hdev->sco_pkts) 21295b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 21301da177e4SLinus Torvalds } 21311da177e4SLinus Torvalds } 21321da177e4SLinus Torvalds } 2133a9de9248SMarcel Holtmann 2134c78ae283SMarcel Holtmann tasklet_schedule(&hdev->tx_task); 21351da177e4SLinus Torvalds 21361da177e4SLinus Torvalds tasklet_enable(&hdev->tx_task); 21371da177e4SLinus Torvalds } 21381da177e4SLinus Torvalds 213904837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 21401da177e4SLinus Torvalds { 2141a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 214204837f64SMarcel Holtmann struct hci_conn *conn; 21431da177e4SLinus Torvalds 21441da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 21451da177e4SLinus Torvalds 21461da177e4SLinus Torvalds hci_dev_lock(hdev); 21471da177e4SLinus Torvalds 214804837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 214904837f64SMarcel Holtmann if (conn) { 215004837f64SMarcel Holtmann conn->mode = ev->mode; 215104837f64SMarcel Holtmann conn->interval = __le16_to_cpu(ev->interval); 215204837f64SMarcel Holtmann 215304837f64SMarcel Holtmann if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) { 215404837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 215504837f64SMarcel Holtmann conn->power_save = 1; 215604837f64SMarcel Holtmann else 215704837f64SMarcel Holtmann conn->power_save = 0; 215804837f64SMarcel Holtmann } 2159e73439d8SMarcel Holtmann 2160e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 2161e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 216204837f64SMarcel Holtmann } 216304837f64SMarcel Holtmann 216404837f64SMarcel Holtmann hci_dev_unlock(hdev); 216504837f64SMarcel Holtmann } 216604837f64SMarcel Holtmann 21671da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 21681da177e4SLinus Torvalds { 2169052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 2170052b30b0SMarcel Holtmann struct hci_conn *conn; 2171052b30b0SMarcel Holtmann 2172a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2173052b30b0SMarcel Holtmann 2174052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2175052b30b0SMarcel Holtmann 2176052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 21773d7a9d1cSMarcel Holtmann if (conn && conn->state == BT_CONNECTED) { 2178052b30b0SMarcel Holtmann hci_conn_hold(conn); 2179052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 2180052b30b0SMarcel Holtmann hci_conn_put(conn); 2181052b30b0SMarcel Holtmann } 2182052b30b0SMarcel Holtmann 218303b555e1SJohan Hedberg if (!test_bit(HCI_PAIRABLE, &hdev->flags)) 218403b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 218503b555e1SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 2186582fbe9eSJohan Hedberg else if (test_bit(HCI_MGMT, &hdev->flags)) { 2187a770bb5aSWaldemar Rymarkiewicz u8 secure; 2188a770bb5aSWaldemar Rymarkiewicz 2189a770bb5aSWaldemar Rymarkiewicz if (conn->pending_sec_level == BT_SECURITY_HIGH) 2190a770bb5aSWaldemar Rymarkiewicz secure = 1; 2191a770bb5aSWaldemar Rymarkiewicz else 2192a770bb5aSWaldemar Rymarkiewicz secure = 0; 2193a770bb5aSWaldemar Rymarkiewicz 2194a770bb5aSWaldemar Rymarkiewicz mgmt_pin_code_request(hdev->id, &ev->bdaddr, secure); 2195a770bb5aSWaldemar Rymarkiewicz } 2196980e1a53SJohan Hedberg 2197052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 21981da177e4SLinus Torvalds } 21991da177e4SLinus Torvalds 22001da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 22011da177e4SLinus Torvalds { 220255ed8ca1SJohan Hedberg struct hci_ev_link_key_req *ev = (void *) skb->data; 220355ed8ca1SJohan Hedberg struct hci_cp_link_key_reply cp; 220455ed8ca1SJohan Hedberg struct hci_conn *conn; 220555ed8ca1SJohan Hedberg struct link_key *key; 220655ed8ca1SJohan Hedberg 2207a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 220855ed8ca1SJohan Hedberg 220955ed8ca1SJohan Hedberg if (!test_bit(HCI_LINK_KEYS, &hdev->flags)) 221055ed8ca1SJohan Hedberg return; 221155ed8ca1SJohan Hedberg 221255ed8ca1SJohan Hedberg hci_dev_lock(hdev); 221355ed8ca1SJohan Hedberg 221455ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, &ev->bdaddr); 221555ed8ca1SJohan Hedberg if (!key) { 221655ed8ca1SJohan Hedberg BT_DBG("%s link key not found for %s", hdev->name, 221755ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 221855ed8ca1SJohan Hedberg goto not_found; 221955ed8ca1SJohan Hedberg } 222055ed8ca1SJohan Hedberg 222155ed8ca1SJohan Hedberg BT_DBG("%s found key type %u for %s", hdev->name, key->type, 222255ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 222355ed8ca1SJohan Hedberg 2224b6020ba0SWaldemar Rymarkiewicz if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) && 2225b6020ba0SWaldemar Rymarkiewicz key->type == HCI_LK_DEBUG_COMBINATION) { 222655ed8ca1SJohan Hedberg BT_DBG("%s ignoring debug key", hdev->name); 222755ed8ca1SJohan Hedberg goto not_found; 222855ed8ca1SJohan Hedberg } 222955ed8ca1SJohan Hedberg 223055ed8ca1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 223160b83f57SWaldemar Rymarkiewicz if (conn) { 223260b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_UNAUTH_COMBINATION && 223360b83f57SWaldemar Rymarkiewicz conn->auth_type != 0xff && 223460b83f57SWaldemar Rymarkiewicz (conn->auth_type & 0x01)) { 223555ed8ca1SJohan Hedberg BT_DBG("%s ignoring unauthenticated key", hdev->name); 223655ed8ca1SJohan Hedberg goto not_found; 223755ed8ca1SJohan Hedberg } 223855ed8ca1SJohan Hedberg 223960b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && 224060b83f57SWaldemar Rymarkiewicz conn->pending_sec_level == BT_SECURITY_HIGH) { 224160b83f57SWaldemar Rymarkiewicz BT_DBG("%s ignoring key unauthenticated for high \ 224260b83f57SWaldemar Rymarkiewicz security", hdev->name); 224360b83f57SWaldemar Rymarkiewicz goto not_found; 224460b83f57SWaldemar Rymarkiewicz } 224560b83f57SWaldemar Rymarkiewicz 224660b83f57SWaldemar Rymarkiewicz conn->key_type = key->type; 224760b83f57SWaldemar Rymarkiewicz conn->pin_length = key->pin_len; 224860b83f57SWaldemar Rymarkiewicz } 224960b83f57SWaldemar Rymarkiewicz 225055ed8ca1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 225155ed8ca1SJohan Hedberg memcpy(cp.link_key, key->val, 16); 225255ed8ca1SJohan Hedberg 225355ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 225455ed8ca1SJohan Hedberg 225555ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 225655ed8ca1SJohan Hedberg 225755ed8ca1SJohan Hedberg return; 225855ed8ca1SJohan Hedberg 225955ed8ca1SJohan Hedberg not_found: 226055ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 226155ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 22621da177e4SLinus Torvalds } 22631da177e4SLinus Torvalds 22641da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 22651da177e4SLinus Torvalds { 2266052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 2267052b30b0SMarcel Holtmann struct hci_conn *conn; 226855ed8ca1SJohan Hedberg u8 pin_len = 0; 2269052b30b0SMarcel Holtmann 2270a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2271052b30b0SMarcel Holtmann 2272052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2273052b30b0SMarcel Holtmann 2274052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2275052b30b0SMarcel Holtmann if (conn) { 2276052b30b0SMarcel Holtmann hci_conn_hold(conn); 2277052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2278980e1a53SJohan Hedberg pin_len = conn->pin_length; 227913d39315SWaldemar Rymarkiewicz 228013d39315SWaldemar Rymarkiewicz if (ev->key_type != HCI_LK_CHANGED_COMBINATION) 228113d39315SWaldemar Rymarkiewicz conn->key_type = ev->key_type; 228213d39315SWaldemar Rymarkiewicz 2283052b30b0SMarcel Holtmann hci_conn_put(conn); 2284052b30b0SMarcel Holtmann } 2285052b30b0SMarcel Holtmann 228655ed8ca1SJohan Hedberg if (test_bit(HCI_LINK_KEYS, &hdev->flags)) 2287d25e28abSJohan Hedberg hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, 228855ed8ca1SJohan Hedberg ev->key_type, pin_len); 228955ed8ca1SJohan Hedberg 2290052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 22911da177e4SLinus Torvalds } 22921da177e4SLinus Torvalds 229304837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 229404837f64SMarcel Holtmann { 2295a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 229604837f64SMarcel Holtmann struct hci_conn *conn; 229704837f64SMarcel Holtmann 229804837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 229904837f64SMarcel Holtmann 230004837f64SMarcel Holtmann hci_dev_lock(hdev); 230104837f64SMarcel Holtmann 230204837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 23031da177e4SLinus Torvalds if (conn && !ev->status) { 23041da177e4SLinus Torvalds struct inquiry_entry *ie; 23051da177e4SLinus Torvalds 2306cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2307cc11b9c1SAndrei Emeltchenko if (ie) { 23081da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 23091da177e4SLinus Torvalds ie->timestamp = jiffies; 23101da177e4SLinus Torvalds } 23111da177e4SLinus Torvalds } 23121da177e4SLinus Torvalds 23131da177e4SLinus Torvalds hci_dev_unlock(hdev); 23141da177e4SLinus Torvalds } 23151da177e4SLinus Torvalds 2316a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2317a8746417SMarcel Holtmann { 2318a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 2319a8746417SMarcel Holtmann struct hci_conn *conn; 2320a8746417SMarcel Holtmann 2321a8746417SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2322a8746417SMarcel Holtmann 2323a8746417SMarcel Holtmann hci_dev_lock(hdev); 2324a8746417SMarcel Holtmann 2325a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2326a8746417SMarcel Holtmann if (conn && !ev->status) 2327a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 2328a8746417SMarcel Holtmann 2329a8746417SMarcel Holtmann hci_dev_unlock(hdev); 2330a8746417SMarcel Holtmann } 2331a8746417SMarcel Holtmann 233285a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 233385a1e930SMarcel Holtmann { 2334a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 233585a1e930SMarcel Holtmann struct inquiry_entry *ie; 233685a1e930SMarcel Holtmann 233785a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 233885a1e930SMarcel Holtmann 233985a1e930SMarcel Holtmann hci_dev_lock(hdev); 234085a1e930SMarcel Holtmann 2341cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2342cc11b9c1SAndrei Emeltchenko if (ie) { 234385a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 234485a1e930SMarcel Holtmann ie->timestamp = jiffies; 234585a1e930SMarcel Holtmann } 234685a1e930SMarcel Holtmann 234785a1e930SMarcel Holtmann hci_dev_unlock(hdev); 234885a1e930SMarcel Holtmann } 234985a1e930SMarcel Holtmann 2350a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb) 2351a9de9248SMarcel Holtmann { 2352a9de9248SMarcel Holtmann struct inquiry_data data; 2353a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2354a9de9248SMarcel Holtmann 2355a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2356a9de9248SMarcel Holtmann 2357a9de9248SMarcel Holtmann if (!num_rsp) 2358a9de9248SMarcel Holtmann return; 2359a9de9248SMarcel Holtmann 2360a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2361a9de9248SMarcel Holtmann 2362314b2381SJohan Hedberg if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) { 2363314b2381SJohan Hedberg 2364314b2381SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 2365314b2381SJohan Hedberg mgmt_discovering(hdev->id, 1); 2366314b2381SJohan Hedberg } 2367314b2381SJohan Hedberg 2368a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 2369138d22efSSzymon Janc struct inquiry_info_with_rssi_and_pscan_mode *info; 2370138d22efSSzymon Janc info = (void *) (skb->data + 1); 2371a9de9248SMarcel Holtmann 2372e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2373a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2374a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2375a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2376a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 2377a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2378a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2379a9de9248SMarcel Holtmann data.rssi = info->rssi; 238041a96212SMarcel Holtmann data.ssp_mode = 0x00; 2381a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 2382e17acd40SJohan Hedberg mgmt_device_found(hdev->id, &info->bdaddr, 2383e17acd40SJohan Hedberg info->dev_class, info->rssi, 2384e17acd40SJohan Hedberg NULL); 2385a9de9248SMarcel Holtmann } 2386a9de9248SMarcel Holtmann } else { 2387a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 2388a9de9248SMarcel Holtmann 2389e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2390a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2391a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2392a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2393a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2394a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2395a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2396a9de9248SMarcel Holtmann data.rssi = info->rssi; 239741a96212SMarcel Holtmann data.ssp_mode = 0x00; 2398a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 2399e17acd40SJohan Hedberg mgmt_device_found(hdev->id, &info->bdaddr, 2400e17acd40SJohan Hedberg info->dev_class, info->rssi, 2401e17acd40SJohan Hedberg NULL); 2402a9de9248SMarcel Holtmann } 2403a9de9248SMarcel Holtmann } 2404a9de9248SMarcel Holtmann 2405a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2406a9de9248SMarcel Holtmann } 2407a9de9248SMarcel Holtmann 2408a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 2409a9de9248SMarcel Holtmann { 241041a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 241141a96212SMarcel Holtmann struct hci_conn *conn; 241241a96212SMarcel Holtmann 2413a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 241441a96212SMarcel Holtmann 241541a96212SMarcel Holtmann hci_dev_lock(hdev); 241641a96212SMarcel Holtmann 241741a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2418ccd556feSJohan Hedberg if (!conn) 2419ccd556feSJohan Hedberg goto unlock; 2420ccd556feSJohan Hedberg 2421769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 242241a96212SMarcel Holtmann struct inquiry_entry *ie; 242341a96212SMarcel Holtmann 2424cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2425cc11b9c1SAndrei Emeltchenko if (ie) 242641a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 242741a96212SMarcel Holtmann 242841a96212SMarcel Holtmann conn->ssp_mode = (ev->features[0] & 0x01); 242941a96212SMarcel Holtmann } 243041a96212SMarcel Holtmann 2431ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2432ccd556feSJohan Hedberg goto unlock; 2433ccd556feSJohan Hedberg 2434127178d2SJohan Hedberg if (!ev->status) { 2435127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2436127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2437127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2438127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2439127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2440127178d2SJohan Hedberg } 2441392599b9SJohan Hedberg 2442127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2443769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2444769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2445769be974SMarcel Holtmann hci_conn_put(conn); 2446769be974SMarcel Holtmann } 2447769be974SMarcel Holtmann 2448ccd556feSJohan Hedberg unlock: 244941a96212SMarcel Holtmann hci_dev_unlock(hdev); 2450a9de9248SMarcel Holtmann } 2451a9de9248SMarcel Holtmann 2452a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2453a9de9248SMarcel Holtmann { 2454b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 2455b6a0dc82SMarcel Holtmann struct hci_conn *conn; 2456b6a0dc82SMarcel Holtmann 2457b6a0dc82SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2458b6a0dc82SMarcel Holtmann 2459b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 2460b6a0dc82SMarcel Holtmann 2461b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 24629dc0a3afSMarcel Holtmann if (!conn) { 24639dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 24649dc0a3afSMarcel Holtmann goto unlock; 24659dc0a3afSMarcel Holtmann 24669dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 2467b6a0dc82SMarcel Holtmann if (!conn) 2468b6a0dc82SMarcel Holtmann goto unlock; 2469b6a0dc82SMarcel Holtmann 24709dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 24719dc0a3afSMarcel Holtmann } 24729dc0a3afSMarcel Holtmann 2473732547f9SMarcel Holtmann switch (ev->status) { 2474732547f9SMarcel Holtmann case 0x00: 2475732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 2476732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 2477732547f9SMarcel Holtmann 24789eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 2479732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 2480732547f9SMarcel Holtmann break; 2481732547f9SMarcel Holtmann 2482705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 2483732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 24841038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 2485732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 2486732547f9SMarcel Holtmann if (conn->out && conn->attempt < 2) { 2487efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 2488efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 2489efc7688bSMarcel Holtmann hci_setup_sync(conn, conn->link->handle); 2490efc7688bSMarcel Holtmann goto unlock; 2491efc7688bSMarcel Holtmann } 2492732547f9SMarcel Holtmann /* fall through */ 2493efc7688bSMarcel Holtmann 2494732547f9SMarcel Holtmann default: 2495b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 2496732547f9SMarcel Holtmann break; 2497732547f9SMarcel Holtmann } 2498b6a0dc82SMarcel Holtmann 2499b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2500b6a0dc82SMarcel Holtmann if (ev->status) 2501b6a0dc82SMarcel Holtmann hci_conn_del(conn); 2502b6a0dc82SMarcel Holtmann 2503b6a0dc82SMarcel Holtmann unlock: 2504b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 2505a9de9248SMarcel Holtmann } 2506a9de9248SMarcel Holtmann 2507a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) 2508a9de9248SMarcel Holtmann { 2509a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2510a9de9248SMarcel Holtmann } 2511a9de9248SMarcel Holtmann 251204837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) 251304837f64SMarcel Holtmann { 2514a9de9248SMarcel Holtmann struct hci_ev_sniff_subrate *ev = (void *) skb->data; 251504837f64SMarcel Holtmann 251604837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 251704837f64SMarcel Holtmann } 251804837f64SMarcel Holtmann 2519a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 2520a9de9248SMarcel Holtmann { 2521a9de9248SMarcel Holtmann struct inquiry_data data; 2522a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 2523a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2524a9de9248SMarcel Holtmann 2525a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2526a9de9248SMarcel Holtmann 2527a9de9248SMarcel Holtmann if (!num_rsp) 2528a9de9248SMarcel Holtmann return; 2529a9de9248SMarcel Holtmann 2530314b2381SJohan Hedberg if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) { 2531314b2381SJohan Hedberg 2532314b2381SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 2533314b2381SJohan Hedberg mgmt_discovering(hdev->id, 1); 2534314b2381SJohan Hedberg } 2535314b2381SJohan Hedberg 2536a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2537a9de9248SMarcel Holtmann 2538e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2539a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2540a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2541a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2542a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2543a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2544a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2545a9de9248SMarcel Holtmann data.rssi = info->rssi; 254641a96212SMarcel Holtmann data.ssp_mode = 0x01; 2547a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 2548e17acd40SJohan Hedberg mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class, 2549e17acd40SJohan Hedberg info->rssi, info->data); 2550a9de9248SMarcel Holtmann } 2551a9de9248SMarcel Holtmann 2552a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2553a9de9248SMarcel Holtmann } 2554a9de9248SMarcel Holtmann 255517fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn) 255617fa4b9dSJohan Hedberg { 255717fa4b9dSJohan Hedberg /* If remote requests dedicated bonding follow that lead */ 255817fa4b9dSJohan Hedberg if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) { 255917fa4b9dSJohan Hedberg /* If both remote and local IO capabilities allow MITM 256017fa4b9dSJohan Hedberg * protection then require it, otherwise don't */ 256117fa4b9dSJohan Hedberg if (conn->remote_cap == 0x03 || conn->io_capability == 0x03) 256217fa4b9dSJohan Hedberg return 0x02; 256317fa4b9dSJohan Hedberg else 256417fa4b9dSJohan Hedberg return 0x03; 256517fa4b9dSJohan Hedberg } 256617fa4b9dSJohan Hedberg 256717fa4b9dSJohan Hedberg /* If remote requests no-bonding follow that lead */ 256817fa4b9dSJohan Hedberg if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01) 256958797bf7SWaldemar Rymarkiewicz return conn->remote_auth | (conn->auth_type & 0x01); 257017fa4b9dSJohan Hedberg 257117fa4b9dSJohan Hedberg return conn->auth_type; 257217fa4b9dSJohan Hedberg } 257317fa4b9dSJohan Hedberg 25740493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 25750493684eSMarcel Holtmann { 25760493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 25770493684eSMarcel Holtmann struct hci_conn *conn; 25780493684eSMarcel Holtmann 25790493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 25800493684eSMarcel Holtmann 25810493684eSMarcel Holtmann hci_dev_lock(hdev); 25820493684eSMarcel Holtmann 25830493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 258403b555e1SJohan Hedberg if (!conn) 258503b555e1SJohan Hedberg goto unlock; 258603b555e1SJohan Hedberg 25870493684eSMarcel Holtmann hci_conn_hold(conn); 25880493684eSMarcel Holtmann 258903b555e1SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->flags)) 259003b555e1SJohan Hedberg goto unlock; 259103b555e1SJohan Hedberg 259203b555e1SJohan Hedberg if (test_bit(HCI_PAIRABLE, &hdev->flags) || 259303b555e1SJohan Hedberg (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 259417fa4b9dSJohan Hedberg struct hci_cp_io_capability_reply cp; 259517fa4b9dSJohan Hedberg 259617fa4b9dSJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 259717fa4b9dSJohan Hedberg cp.capability = conn->io_capability; 25987cbc9bd9SJohan Hedberg conn->auth_type = hci_get_auth_req(conn); 25997cbc9bd9SJohan Hedberg cp.authentication = conn->auth_type; 260017fa4b9dSJohan Hedberg 2601ce85ee13SSzymon Janc if ((conn->out == 0x01 || conn->remote_oob == 0x01) && 2602ce85ee13SSzymon Janc hci_find_remote_oob_data(hdev, &conn->dst)) 2603ce85ee13SSzymon Janc cp.oob_data = 0x01; 2604ce85ee13SSzymon Janc else 2605ce85ee13SSzymon Janc cp.oob_data = 0x00; 2606ce85ee13SSzymon Janc 260717fa4b9dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, 260817fa4b9dSJohan Hedberg sizeof(cp), &cp); 260903b555e1SJohan Hedberg } else { 261003b555e1SJohan Hedberg struct hci_cp_io_capability_neg_reply cp; 261103b555e1SJohan Hedberg 261203b555e1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 2613be77159cSJohan Hedberg cp.reason = 0x18; /* Pairing not allowed */ 261403b555e1SJohan Hedberg 261503b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 261603b555e1SJohan Hedberg sizeof(cp), &cp); 261703b555e1SJohan Hedberg } 261803b555e1SJohan Hedberg 261903b555e1SJohan Hedberg unlock: 262003b555e1SJohan Hedberg hci_dev_unlock(hdev); 262103b555e1SJohan Hedberg } 262203b555e1SJohan Hedberg 262303b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 262403b555e1SJohan Hedberg { 262503b555e1SJohan Hedberg struct hci_ev_io_capa_reply *ev = (void *) skb->data; 262603b555e1SJohan Hedberg struct hci_conn *conn; 262703b555e1SJohan Hedberg 262803b555e1SJohan Hedberg BT_DBG("%s", hdev->name); 262903b555e1SJohan Hedberg 263003b555e1SJohan Hedberg hci_dev_lock(hdev); 263103b555e1SJohan Hedberg 263203b555e1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 263303b555e1SJohan Hedberg if (!conn) 263403b555e1SJohan Hedberg goto unlock; 263503b555e1SJohan Hedberg 263603b555e1SJohan Hedberg conn->remote_cap = ev->capability; 263703b555e1SJohan Hedberg conn->remote_oob = ev->oob_data; 263803b555e1SJohan Hedberg conn->remote_auth = ev->authentication; 263903b555e1SJohan Hedberg 264003b555e1SJohan Hedberg unlock: 26410493684eSMarcel Holtmann hci_dev_unlock(hdev); 26420493684eSMarcel Holtmann } 26430493684eSMarcel Holtmann 2644a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev, 2645a5c29683SJohan Hedberg struct sk_buff *skb) 2646a5c29683SJohan Hedberg { 2647a5c29683SJohan Hedberg struct hci_ev_user_confirm_req *ev = (void *) skb->data; 264855bc1a37SJohan Hedberg int loc_mitm, rem_mitm, confirm_hint = 0; 26497a828908SJohan Hedberg struct hci_conn *conn; 2650a5c29683SJohan Hedberg 2651a5c29683SJohan Hedberg BT_DBG("%s", hdev->name); 2652a5c29683SJohan Hedberg 2653a5c29683SJohan Hedberg hci_dev_lock(hdev); 2654a5c29683SJohan Hedberg 26557a828908SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->flags)) 26567a828908SJohan Hedberg goto unlock; 26577a828908SJohan Hedberg 26587a828908SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 26597a828908SJohan Hedberg if (!conn) 26607a828908SJohan Hedberg goto unlock; 26617a828908SJohan Hedberg 26627a828908SJohan Hedberg loc_mitm = (conn->auth_type & 0x01); 26637a828908SJohan Hedberg rem_mitm = (conn->remote_auth & 0x01); 26647a828908SJohan Hedberg 26657a828908SJohan Hedberg /* If we require MITM but the remote device can't provide that 26667a828908SJohan Hedberg * (it has NoInputNoOutput) then reject the confirmation 26677a828908SJohan Hedberg * request. The only exception is when we're dedicated bonding 26687a828908SJohan Hedberg * initiators (connect_cfm_cb set) since then we always have the MITM 26697a828908SJohan Hedberg * bit set. */ 26707a828908SJohan Hedberg if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) { 26717a828908SJohan Hedberg BT_DBG("Rejecting request: remote device can't provide MITM"); 26727a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, 26737a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 26747a828908SJohan Hedberg goto unlock; 26757a828908SJohan Hedberg } 26767a828908SJohan Hedberg 26777a828908SJohan Hedberg /* If no side requires MITM protection; auto-accept */ 26787a828908SJohan Hedberg if ((!loc_mitm || conn->remote_cap == 0x03) && 26797a828908SJohan Hedberg (!rem_mitm || conn->io_capability == 0x03)) { 268055bc1a37SJohan Hedberg 268155bc1a37SJohan Hedberg /* If we're not the initiators request authorization to 268255bc1a37SJohan Hedberg * proceed from user space (mgmt_user_confirm with 268355bc1a37SJohan Hedberg * confirm_hint set to 1). */ 268455bc1a37SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { 268555bc1a37SJohan Hedberg BT_DBG("Confirming auto-accept as acceptor"); 268655bc1a37SJohan Hedberg confirm_hint = 1; 268755bc1a37SJohan Hedberg goto confirm; 268855bc1a37SJohan Hedberg } 268955bc1a37SJohan Hedberg 26909f61656aSJohan Hedberg BT_DBG("Auto-accept of user confirmation with %ums delay", 26919f61656aSJohan Hedberg hdev->auto_accept_delay); 26929f61656aSJohan Hedberg 26939f61656aSJohan Hedberg if (hdev->auto_accept_delay > 0) { 26949f61656aSJohan Hedberg int delay = msecs_to_jiffies(hdev->auto_accept_delay); 26959f61656aSJohan Hedberg mod_timer(&conn->auto_accept_timer, jiffies + delay); 26969f61656aSJohan Hedberg goto unlock; 26979f61656aSJohan Hedberg } 26989f61656aSJohan Hedberg 26997a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, 27007a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 27017a828908SJohan Hedberg goto unlock; 27027a828908SJohan Hedberg } 27037a828908SJohan Hedberg 270455bc1a37SJohan Hedberg confirm: 270555bc1a37SJohan Hedberg mgmt_user_confirm_request(hdev->id, &ev->bdaddr, ev->passkey, 270655bc1a37SJohan Hedberg confirm_hint); 2707a5c29683SJohan Hedberg 27087a828908SJohan Hedberg unlock: 2709a5c29683SJohan Hedberg hci_dev_unlock(hdev); 2710a5c29683SJohan Hedberg } 2711a5c29683SJohan Hedberg 27120493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 27130493684eSMarcel Holtmann { 27140493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 27150493684eSMarcel Holtmann struct hci_conn *conn; 27160493684eSMarcel Holtmann 27170493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 27180493684eSMarcel Holtmann 27190493684eSMarcel Holtmann hci_dev_lock(hdev); 27200493684eSMarcel Holtmann 27210493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 27222a611692SJohan Hedberg if (!conn) 27232a611692SJohan Hedberg goto unlock; 27242a611692SJohan Hedberg 27252a611692SJohan Hedberg /* To avoid duplicate auth_failed events to user space we check 27262a611692SJohan Hedberg * the HCI_CONN_AUTH_PEND flag which will be set if we 27272a611692SJohan Hedberg * initiated the authentication. A traditional auth_complete 27282a611692SJohan Hedberg * event gets always produced as initiator and is also mapped to 27292a611692SJohan Hedberg * the mgmt_auth_failed event */ 27302a611692SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0) 27312a611692SJohan Hedberg mgmt_auth_failed(hdev->id, &conn->dst, ev->status); 27322a611692SJohan Hedberg 27330493684eSMarcel Holtmann hci_conn_put(conn); 27340493684eSMarcel Holtmann 27352a611692SJohan Hedberg unlock: 27360493684eSMarcel Holtmann hci_dev_unlock(hdev); 27370493684eSMarcel Holtmann } 27380493684eSMarcel Holtmann 273941a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 274041a96212SMarcel Holtmann { 274141a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 274241a96212SMarcel Holtmann struct inquiry_entry *ie; 274341a96212SMarcel Holtmann 274441a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 274541a96212SMarcel Holtmann 274641a96212SMarcel Holtmann hci_dev_lock(hdev); 274741a96212SMarcel Holtmann 2748cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2749cc11b9c1SAndrei Emeltchenko if (ie) 275041a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 275141a96212SMarcel Holtmann 275241a96212SMarcel Holtmann hci_dev_unlock(hdev); 275341a96212SMarcel Holtmann } 275441a96212SMarcel Holtmann 27552763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev, 27562763eda6SSzymon Janc struct sk_buff *skb) 27572763eda6SSzymon Janc { 27582763eda6SSzymon Janc struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; 27592763eda6SSzymon Janc struct oob_data *data; 27602763eda6SSzymon Janc 27612763eda6SSzymon Janc BT_DBG("%s", hdev->name); 27622763eda6SSzymon Janc 27632763eda6SSzymon Janc hci_dev_lock(hdev); 27642763eda6SSzymon Janc 2765e1ba1f15SSzymon Janc if (!test_bit(HCI_MGMT, &hdev->flags)) 2766e1ba1f15SSzymon Janc goto unlock; 2767e1ba1f15SSzymon Janc 27682763eda6SSzymon Janc data = hci_find_remote_oob_data(hdev, &ev->bdaddr); 27692763eda6SSzymon Janc if (data) { 27702763eda6SSzymon Janc struct hci_cp_remote_oob_data_reply cp; 27712763eda6SSzymon Janc 27722763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 27732763eda6SSzymon Janc memcpy(cp.hash, data->hash, sizeof(cp.hash)); 27742763eda6SSzymon Janc memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); 27752763eda6SSzymon Janc 27762763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), 27772763eda6SSzymon Janc &cp); 27782763eda6SSzymon Janc } else { 27792763eda6SSzymon Janc struct hci_cp_remote_oob_data_neg_reply cp; 27802763eda6SSzymon Janc 27812763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 27822763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), 27832763eda6SSzymon Janc &cp); 27842763eda6SSzymon Janc } 27852763eda6SSzymon Janc 2786e1ba1f15SSzymon Janc unlock: 27872763eda6SSzymon Janc hci_dev_unlock(hdev); 27882763eda6SSzymon Janc } 27892763eda6SSzymon Janc 2790fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2791fcd89c09SVille Tervo { 2792fcd89c09SVille Tervo struct hci_ev_le_conn_complete *ev = (void *) skb->data; 2793fcd89c09SVille Tervo struct hci_conn *conn; 2794fcd89c09SVille Tervo 2795fcd89c09SVille Tervo BT_DBG("%s status %d", hdev->name, ev->status); 2796fcd89c09SVille Tervo 2797fcd89c09SVille Tervo hci_dev_lock(hdev); 2798fcd89c09SVille Tervo 2799fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr); 2800b62f328bSVille Tervo if (!conn) { 2801b62f328bSVille Tervo conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); 2802b62f328bSVille Tervo if (!conn) { 2803b62f328bSVille Tervo BT_ERR("No memory for new connection"); 2804b62f328bSVille Tervo hci_dev_unlock(hdev); 2805b62f328bSVille Tervo return; 2806b62f328bSVille Tervo } 280729b7988aSAndre Guedes 280829b7988aSAndre Guedes conn->dst_type = ev->bdaddr_type; 2809b62f328bSVille Tervo } 2810fcd89c09SVille Tervo 2811fcd89c09SVille Tervo if (ev->status) { 281283bc71b4SVinicius Costa Gomes mgmt_connect_failed(hdev->id, &ev->bdaddr, ev->status); 2813fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 2814fcd89c09SVille Tervo conn->state = BT_CLOSED; 2815fcd89c09SVille Tervo hci_conn_del(conn); 2816fcd89c09SVille Tervo goto unlock; 2817fcd89c09SVille Tervo } 2818fcd89c09SVille Tervo 2819cfafccf7SVinicius Costa Gomes mgmt_connected(hdev->id, &ev->bdaddr, conn->type); 282083bc71b4SVinicius Costa Gomes 28217b5c0d52SVinicius Costa Gomes conn->sec_level = BT_SECURITY_LOW; 2822fcd89c09SVille Tervo conn->handle = __le16_to_cpu(ev->handle); 2823fcd89c09SVille Tervo conn->state = BT_CONNECTED; 2824fcd89c09SVille Tervo 2825fcd89c09SVille Tervo hci_conn_hold_device(conn); 2826fcd89c09SVille Tervo hci_conn_add_sysfs(conn); 2827fcd89c09SVille Tervo 2828fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 2829fcd89c09SVille Tervo 2830fcd89c09SVille Tervo unlock: 2831fcd89c09SVille Tervo hci_dev_unlock(hdev); 2832fcd89c09SVille Tervo } 2833fcd89c09SVille Tervo 28349aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev, 28359aa04c91SAndre Guedes struct sk_buff *skb) 28369aa04c91SAndre Guedes { 28379aa04c91SAndre Guedes struct hci_ev_le_advertising_info *ev; 28389aa04c91SAndre Guedes u8 num_reports; 28399aa04c91SAndre Guedes 28409aa04c91SAndre Guedes num_reports = skb->data[0]; 28419aa04c91SAndre Guedes ev = (void *) &skb->data[1]; 28429aa04c91SAndre Guedes 28439aa04c91SAndre Guedes hci_dev_lock(hdev); 28449aa04c91SAndre Guedes 28459aa04c91SAndre Guedes hci_add_adv_entry(hdev, ev); 28469aa04c91SAndre Guedes 28479aa04c91SAndre Guedes while (--num_reports) { 28489aa04c91SAndre Guedes ev = (void *) (ev->data + ev->length + 1); 28499aa04c91SAndre Guedes hci_add_adv_entry(hdev, ev); 28509aa04c91SAndre Guedes } 28519aa04c91SAndre Guedes 28529aa04c91SAndre Guedes hci_dev_unlock(hdev); 28539aa04c91SAndre Guedes } 28549aa04c91SAndre Guedes 2855a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev, 2856a7a595f6SVinicius Costa Gomes struct sk_buff *skb) 2857a7a595f6SVinicius Costa Gomes { 2858a7a595f6SVinicius Costa Gomes struct hci_ev_le_ltk_req *ev = (void *) skb->data; 2859a7a595f6SVinicius Costa Gomes struct hci_cp_le_ltk_reply cp; 2860bea710feSVinicius Costa Gomes struct hci_cp_le_ltk_neg_reply neg; 2861a7a595f6SVinicius Costa Gomes struct hci_conn *conn; 2862bea710feSVinicius Costa Gomes struct link_key *ltk; 2863a7a595f6SVinicius Costa Gomes 2864a7a595f6SVinicius Costa Gomes BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle)); 2865a7a595f6SVinicius Costa Gomes 2866a7a595f6SVinicius Costa Gomes hci_dev_lock(hdev); 2867a7a595f6SVinicius Costa Gomes 2868a7a595f6SVinicius Costa Gomes conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2869bea710feSVinicius Costa Gomes if (conn == NULL) 2870bea710feSVinicius Costa Gomes goto not_found; 2871a7a595f6SVinicius Costa Gomes 2872bea710feSVinicius Costa Gomes ltk = hci_find_ltk(hdev, ev->ediv, ev->random); 2873bea710feSVinicius Costa Gomes if (ltk == NULL) 2874bea710feSVinicius Costa Gomes goto not_found; 2875bea710feSVinicius Costa Gomes 2876bea710feSVinicius Costa Gomes memcpy(cp.ltk, ltk->val, sizeof(ltk->val)); 2877a7a595f6SVinicius Costa Gomes cp.handle = cpu_to_le16(conn->handle); 2878726b4ffcSVinicius Costa Gomes conn->pin_length = ltk->pin_len; 2879a7a595f6SVinicius Costa Gomes 2880a7a595f6SVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); 2881a7a595f6SVinicius Costa Gomes 2882a7a595f6SVinicius Costa Gomes hci_dev_unlock(hdev); 2883bea710feSVinicius Costa Gomes 2884bea710feSVinicius Costa Gomes return; 2885bea710feSVinicius Costa Gomes 2886bea710feSVinicius Costa Gomes not_found: 2887bea710feSVinicius Costa Gomes neg.handle = ev->handle; 2888bea710feSVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg); 2889bea710feSVinicius Costa Gomes hci_dev_unlock(hdev); 2890a7a595f6SVinicius Costa Gomes } 2891a7a595f6SVinicius Costa Gomes 2892fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 2893fcd89c09SVille Tervo { 2894fcd89c09SVille Tervo struct hci_ev_le_meta *le_ev = (void *) skb->data; 2895fcd89c09SVille Tervo 2896fcd89c09SVille Tervo skb_pull(skb, sizeof(*le_ev)); 2897fcd89c09SVille Tervo 2898fcd89c09SVille Tervo switch (le_ev->subevent) { 2899fcd89c09SVille Tervo case HCI_EV_LE_CONN_COMPLETE: 2900fcd89c09SVille Tervo hci_le_conn_complete_evt(hdev, skb); 2901fcd89c09SVille Tervo break; 2902fcd89c09SVille Tervo 29039aa04c91SAndre Guedes case HCI_EV_LE_ADVERTISING_REPORT: 29049aa04c91SAndre Guedes hci_le_adv_report_evt(hdev, skb); 29059aa04c91SAndre Guedes break; 29069aa04c91SAndre Guedes 2907a7a595f6SVinicius Costa Gomes case HCI_EV_LE_LTK_REQ: 2908a7a595f6SVinicius Costa Gomes hci_le_ltk_request_evt(hdev, skb); 2909a7a595f6SVinicius Costa Gomes break; 2910a7a595f6SVinicius Costa Gomes 2911fcd89c09SVille Tervo default: 2912fcd89c09SVille Tervo break; 2913fcd89c09SVille Tervo } 2914fcd89c09SVille Tervo } 2915fcd89c09SVille Tervo 29161da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 29171da177e4SLinus Torvalds { 2918a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 2919a9de9248SMarcel Holtmann __u8 event = hdr->evt; 29201da177e4SLinus Torvalds 29211da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 29221da177e4SLinus Torvalds 2923a9de9248SMarcel Holtmann switch (event) { 29241da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 29251da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 29261da177e4SLinus Torvalds break; 29271da177e4SLinus Torvalds 29281da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 29291da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 29301da177e4SLinus Torvalds break; 29311da177e4SLinus Torvalds 2932a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 2933a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 293421d9e30eSMarcel Holtmann break; 293521d9e30eSMarcel Holtmann 29361da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 29371da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 29381da177e4SLinus Torvalds break; 29391da177e4SLinus Torvalds 29401da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 29411da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 29421da177e4SLinus Torvalds break; 29431da177e4SLinus Torvalds 29441da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 29451da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 29461da177e4SLinus Torvalds break; 29471da177e4SLinus Torvalds 2948a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 2949a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 2950a9de9248SMarcel Holtmann break; 2951a9de9248SMarcel Holtmann 29521da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 29531da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 29541da177e4SLinus Torvalds break; 29551da177e4SLinus Torvalds 2956a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 2957a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 2958a9de9248SMarcel Holtmann break; 2959a9de9248SMarcel Holtmann 2960a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 2961a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 2962a9de9248SMarcel Holtmann break; 2963a9de9248SMarcel Holtmann 2964a9de9248SMarcel Holtmann case HCI_EV_REMOTE_VERSION: 2965a9de9248SMarcel Holtmann hci_remote_version_evt(hdev, skb); 2966a9de9248SMarcel Holtmann break; 2967a9de9248SMarcel Holtmann 2968a9de9248SMarcel Holtmann case HCI_EV_QOS_SETUP_COMPLETE: 2969a9de9248SMarcel Holtmann hci_qos_setup_complete_evt(hdev, skb); 2970a9de9248SMarcel Holtmann break; 2971a9de9248SMarcel Holtmann 2972a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 2973a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 2974a9de9248SMarcel Holtmann break; 2975a9de9248SMarcel Holtmann 2976a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 2977a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 2978a9de9248SMarcel Holtmann break; 2979a9de9248SMarcel Holtmann 2980a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 2981a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 2982a9de9248SMarcel Holtmann break; 2983a9de9248SMarcel Holtmann 2984a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 2985a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 2986a9de9248SMarcel Holtmann break; 2987a9de9248SMarcel Holtmann 2988a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 2989a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 29901da177e4SLinus Torvalds break; 29911da177e4SLinus Torvalds 29921da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 29931da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 29941da177e4SLinus Torvalds break; 29951da177e4SLinus Torvalds 29961da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 29971da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 29981da177e4SLinus Torvalds break; 29991da177e4SLinus Torvalds 30001da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 30011da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 30021da177e4SLinus Torvalds break; 30031da177e4SLinus Torvalds 30041da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 30051da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 30061da177e4SLinus Torvalds break; 30071da177e4SLinus Torvalds 3008a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 3009a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 3010a8746417SMarcel Holtmann break; 3011a8746417SMarcel Holtmann 301285a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 301385a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 301485a1e930SMarcel Holtmann break; 301585a1e930SMarcel Holtmann 3016a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 3017a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 3018a9de9248SMarcel Holtmann break; 3019a9de9248SMarcel Holtmann 3020a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 3021a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 3022a9de9248SMarcel Holtmann break; 3023a9de9248SMarcel Holtmann 3024a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 3025a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 3026a9de9248SMarcel Holtmann break; 3027a9de9248SMarcel Holtmann 3028a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_CHANGED: 3029a9de9248SMarcel Holtmann hci_sync_conn_changed_evt(hdev, skb); 3030a9de9248SMarcel Holtmann break; 3031a9de9248SMarcel Holtmann 303204837f64SMarcel Holtmann case HCI_EV_SNIFF_SUBRATE: 303304837f64SMarcel Holtmann hci_sniff_subrate_evt(hdev, skb); 303404837f64SMarcel Holtmann break; 303504837f64SMarcel Holtmann 3036a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 3037a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 30381da177e4SLinus Torvalds break; 30391da177e4SLinus Torvalds 30400493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 30410493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 30420493684eSMarcel Holtmann break; 30430493684eSMarcel Holtmann 304403b555e1SJohan Hedberg case HCI_EV_IO_CAPA_REPLY: 304503b555e1SJohan Hedberg hci_io_capa_reply_evt(hdev, skb); 304603b555e1SJohan Hedberg break; 304703b555e1SJohan Hedberg 3048a5c29683SJohan Hedberg case HCI_EV_USER_CONFIRM_REQUEST: 3049a5c29683SJohan Hedberg hci_user_confirm_request_evt(hdev, skb); 3050a5c29683SJohan Hedberg break; 3051a5c29683SJohan Hedberg 30520493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 30530493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 30540493684eSMarcel Holtmann break; 30550493684eSMarcel Holtmann 305641a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 305741a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 305841a96212SMarcel Holtmann break; 305941a96212SMarcel Holtmann 3060fcd89c09SVille Tervo case HCI_EV_LE_META: 3061fcd89c09SVille Tervo hci_le_meta_evt(hdev, skb); 3062fcd89c09SVille Tervo break; 3063fcd89c09SVille Tervo 30642763eda6SSzymon Janc case HCI_EV_REMOTE_OOB_DATA_REQUEST: 30652763eda6SSzymon Janc hci_remote_oob_data_request_evt(hdev, skb); 30662763eda6SSzymon Janc break; 30672763eda6SSzymon Janc 30681da177e4SLinus Torvalds default: 3069a9de9248SMarcel Holtmann BT_DBG("%s event 0x%x", hdev->name, event); 30701da177e4SLinus Torvalds break; 30711da177e4SLinus Torvalds } 30721da177e4SLinus Torvalds 30731da177e4SLinus Torvalds kfree_skb(skb); 30741da177e4SLinus Torvalds hdev->stat.evt_rx++; 30751da177e4SLinus Torvalds } 30761da177e4SLinus Torvalds 30771da177e4SLinus Torvalds /* Generate internal stack event */ 30781da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data) 30791da177e4SLinus Torvalds { 30801da177e4SLinus Torvalds struct hci_event_hdr *hdr; 30811da177e4SLinus Torvalds struct hci_ev_stack_internal *ev; 30821da177e4SLinus Torvalds struct sk_buff *skb; 30831da177e4SLinus Torvalds 30841da177e4SLinus Torvalds skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC); 30851da177e4SLinus Torvalds if (!skb) 30861da177e4SLinus Torvalds return; 30871da177e4SLinus Torvalds 30881da177e4SLinus Torvalds hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE); 30891da177e4SLinus Torvalds hdr->evt = HCI_EV_STACK_INTERNAL; 30901da177e4SLinus Torvalds hdr->plen = sizeof(*ev) + dlen; 30911da177e4SLinus Torvalds 30921da177e4SLinus Torvalds ev = (void *) skb_put(skb, sizeof(*ev) + dlen); 30931da177e4SLinus Torvalds ev->type = type; 30941da177e4SLinus Torvalds memcpy(ev->data, data, dlen); 30951da177e4SLinus Torvalds 3096576c7d85SMarcel Holtmann bt_cb(skb)->incoming = 1; 3097a61bbcf2SPatrick McHardy __net_timestamp(skb); 3098576c7d85SMarcel Holtmann 30990d48d939SMarcel Holtmann bt_cb(skb)->pkt_type = HCI_EVENT_PKT; 31001da177e4SLinus Torvalds skb->dev = (void *) hdev; 3101eec8d2bcSJohan Hedberg hci_send_to_sock(hdev, skb, NULL); 31021da177e4SLinus Torvalds kfree_skb(skb); 31031da177e4SLinus Torvalds } 3104e6100a25SAndre Guedes 3105e6100a25SAndre Guedes module_param(enable_le, bool, 0444); 3106e6100a25SAndre Guedes MODULE_PARM_DESC(enable_le, "Enable LE support"); 3107