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 481da177e4SLinus Torvalds /* Handle HCI Event packets */ 491da177e4SLinus Torvalds 50a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb) 511da177e4SLinus Torvalds { 52a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 531da177e4SLinus Torvalds 54a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 551da177e4SLinus Torvalds 56a9de9248SMarcel Holtmann if (status) 57a9de9248SMarcel Holtmann return; 581da177e4SLinus Torvalds 591da177e4SLinus Torvalds clear_bit(HCI_INQUIRY, &hdev->flags); 60a9de9248SMarcel Holtmann 6123bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status); 62a9de9248SMarcel Holtmann 63a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 641da177e4SLinus Torvalds } 656bd57416SMarcel Holtmann 66a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 671da177e4SLinus Torvalds { 68a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 69a9de9248SMarcel Holtmann 70a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 71a9de9248SMarcel Holtmann 72a9de9248SMarcel Holtmann if (status) 73a9de9248SMarcel Holtmann return; 74a9de9248SMarcel Holtmann 75a9de9248SMarcel Holtmann clear_bit(HCI_INQUIRY, &hdev->flags); 76a9de9248SMarcel Holtmann 77a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 78a9de9248SMarcel Holtmann } 79a9de9248SMarcel Holtmann 80a9de9248SMarcel Holtmann static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb) 81a9de9248SMarcel Holtmann { 82a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 83a9de9248SMarcel Holtmann } 84a9de9248SMarcel Holtmann 85a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb) 86a9de9248SMarcel Holtmann { 87a9de9248SMarcel Holtmann struct hci_rp_role_discovery *rp = (void *) skb->data; 881da177e4SLinus Torvalds struct hci_conn *conn; 891da177e4SLinus Torvalds 90a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 911da177e4SLinus Torvalds 92a9de9248SMarcel Holtmann if (rp->status) 93a9de9248SMarcel Holtmann return; 941da177e4SLinus Torvalds 951da177e4SLinus Torvalds hci_dev_lock(hdev); 961da177e4SLinus Torvalds 97a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 981da177e4SLinus Torvalds if (conn) { 99a9de9248SMarcel Holtmann if (rp->role) 1001da177e4SLinus Torvalds conn->link_mode &= ~HCI_LM_MASTER; 1011da177e4SLinus Torvalds else 1021da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 1031da177e4SLinus Torvalds } 1041da177e4SLinus Torvalds 1051da177e4SLinus Torvalds hci_dev_unlock(hdev); 106a9de9248SMarcel Holtmann } 1071da177e4SLinus Torvalds 108e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 109e4e8e37cSMarcel Holtmann { 110e4e8e37cSMarcel Holtmann struct hci_rp_read_link_policy *rp = (void *) skb->data; 111e4e8e37cSMarcel Holtmann struct hci_conn *conn; 112e4e8e37cSMarcel Holtmann 113e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 114e4e8e37cSMarcel Holtmann 115e4e8e37cSMarcel Holtmann if (rp->status) 116e4e8e37cSMarcel Holtmann return; 117e4e8e37cSMarcel Holtmann 118e4e8e37cSMarcel Holtmann hci_dev_lock(hdev); 119e4e8e37cSMarcel Holtmann 120e4e8e37cSMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 121e4e8e37cSMarcel Holtmann if (conn) 122e4e8e37cSMarcel Holtmann conn->link_policy = __le16_to_cpu(rp->policy); 123e4e8e37cSMarcel Holtmann 124e4e8e37cSMarcel Holtmann hci_dev_unlock(hdev); 125e4e8e37cSMarcel Holtmann } 126e4e8e37cSMarcel Holtmann 127a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 128a9de9248SMarcel Holtmann { 129a9de9248SMarcel Holtmann struct hci_rp_write_link_policy *rp = (void *) skb->data; 130a9de9248SMarcel Holtmann struct hci_conn *conn; 131a9de9248SMarcel Holtmann void *sent; 132a9de9248SMarcel Holtmann 133a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 134a9de9248SMarcel Holtmann 135a9de9248SMarcel Holtmann if (rp->status) 136a9de9248SMarcel Holtmann return; 137a9de9248SMarcel Holtmann 138a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY); 13904837f64SMarcel Holtmann if (!sent) 140a9de9248SMarcel Holtmann return; 14104837f64SMarcel Holtmann 14204837f64SMarcel Holtmann hci_dev_lock(hdev); 14304837f64SMarcel Holtmann 144a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 145e4e8e37cSMarcel Holtmann if (conn) 14683985319SHarvey Harrison conn->link_policy = get_unaligned_le16(sent + 2); 14704837f64SMarcel Holtmann 14804837f64SMarcel Holtmann hci_dev_unlock(hdev); 1491da177e4SLinus Torvalds } 1501da177e4SLinus Torvalds 151e4e8e37cSMarcel Holtmann static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 152e4e8e37cSMarcel Holtmann { 153e4e8e37cSMarcel Holtmann struct hci_rp_read_def_link_policy *rp = (void *) skb->data; 154e4e8e37cSMarcel Holtmann 155e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 156e4e8e37cSMarcel Holtmann 157e4e8e37cSMarcel Holtmann if (rp->status) 158e4e8e37cSMarcel Holtmann return; 159e4e8e37cSMarcel Holtmann 160e4e8e37cSMarcel Holtmann hdev->link_policy = __le16_to_cpu(rp->policy); 161e4e8e37cSMarcel Holtmann } 162e4e8e37cSMarcel Holtmann 163e4e8e37cSMarcel Holtmann static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 164e4e8e37cSMarcel Holtmann { 165e4e8e37cSMarcel Holtmann __u8 status = *((__u8 *) skb->data); 166e4e8e37cSMarcel Holtmann void *sent; 167e4e8e37cSMarcel Holtmann 168e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 169e4e8e37cSMarcel Holtmann 170e4e8e37cSMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY); 171e4e8e37cSMarcel Holtmann if (!sent) 172e4e8e37cSMarcel Holtmann return; 173e4e8e37cSMarcel Holtmann 174e4e8e37cSMarcel Holtmann if (!status) 175e4e8e37cSMarcel Holtmann hdev->link_policy = get_unaligned_le16(sent); 176e4e8e37cSMarcel Holtmann 17723bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status); 178e4e8e37cSMarcel Holtmann } 179e4e8e37cSMarcel Holtmann 180a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) 1811da177e4SLinus Torvalds { 182a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 183a9de9248SMarcel Holtmann 184a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 185a9de9248SMarcel Holtmann 18623bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_RESET, status); 187a9de9248SMarcel Holtmann } 188a9de9248SMarcel Holtmann 189a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) 190a9de9248SMarcel Holtmann { 191a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 1921da177e4SLinus Torvalds void *sent; 1931da177e4SLinus Torvalds 194a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1951da177e4SLinus Torvalds 196a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); 1971da177e4SLinus Torvalds if (!sent) 198a9de9248SMarcel Holtmann return; 1991da177e4SLinus Torvalds 200b312b161SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 201b312b161SJohan Hedberg mgmt_set_local_name_complete(hdev->id, sent, status); 202b312b161SJohan Hedberg 203b312b161SJohan Hedberg if (status) 204b312b161SJohan Hedberg return; 205b312b161SJohan Hedberg 2061f6c6378SJohan Hedberg memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); 207a9de9248SMarcel Holtmann } 208a9de9248SMarcel Holtmann 209a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) 210a9de9248SMarcel Holtmann { 211a9de9248SMarcel Holtmann struct hci_rp_read_local_name *rp = (void *) skb->data; 212a9de9248SMarcel Holtmann 213a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 214a9de9248SMarcel Holtmann 215a9de9248SMarcel Holtmann if (rp->status) 216a9de9248SMarcel Holtmann return; 217a9de9248SMarcel Holtmann 2181f6c6378SJohan Hedberg memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); 219a9de9248SMarcel Holtmann } 220a9de9248SMarcel Holtmann 221a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) 222a9de9248SMarcel Holtmann { 223a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 224a9de9248SMarcel Holtmann void *sent; 225a9de9248SMarcel Holtmann 226a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 227a9de9248SMarcel Holtmann 228a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); 229a9de9248SMarcel Holtmann if (!sent) 230a9de9248SMarcel Holtmann return; 2311da177e4SLinus Torvalds 2321da177e4SLinus Torvalds if (!status) { 233a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 234a9de9248SMarcel Holtmann 2351da177e4SLinus Torvalds if (param == AUTH_ENABLED) 2361da177e4SLinus Torvalds set_bit(HCI_AUTH, &hdev->flags); 2371da177e4SLinus Torvalds else 2381da177e4SLinus Torvalds clear_bit(HCI_AUTH, &hdev->flags); 2391da177e4SLinus Torvalds } 240a9de9248SMarcel Holtmann 24123bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status); 242a9de9248SMarcel Holtmann } 2431da177e4SLinus Torvalds 244a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) 245a9de9248SMarcel Holtmann { 246a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 247a9de9248SMarcel Holtmann void *sent; 248a9de9248SMarcel Holtmann 249a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 250a9de9248SMarcel Holtmann 251a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); 2521da177e4SLinus Torvalds if (!sent) 253a9de9248SMarcel Holtmann return; 2541da177e4SLinus Torvalds 2551da177e4SLinus Torvalds if (!status) { 256a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 257a9de9248SMarcel Holtmann 2581da177e4SLinus Torvalds if (param) 2591da177e4SLinus Torvalds set_bit(HCI_ENCRYPT, &hdev->flags); 2601da177e4SLinus Torvalds else 2611da177e4SLinus Torvalds clear_bit(HCI_ENCRYPT, &hdev->flags); 2621da177e4SLinus Torvalds } 263a9de9248SMarcel Holtmann 26423bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status); 2651da177e4SLinus Torvalds } 2661da177e4SLinus Torvalds 267a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) 268a9de9248SMarcel Holtmann { 269a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 270a9de9248SMarcel Holtmann void *sent; 2711da177e4SLinus Torvalds 272a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 273a9de9248SMarcel Holtmann 274a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); 2751da177e4SLinus Torvalds if (!sent) 276a9de9248SMarcel Holtmann return; 2771da177e4SLinus Torvalds 2781da177e4SLinus Torvalds if (!status) { 279a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 2809fbcbb45SJohan Hedberg int old_pscan, old_iscan; 281a9de9248SMarcel Holtmann 2829fbcbb45SJohan Hedberg old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags); 2839fbcbb45SJohan Hedberg old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags); 284a9de9248SMarcel Holtmann 28573f22f62SJohan Hedberg if (param & SCAN_INQUIRY) { 2861da177e4SLinus Torvalds set_bit(HCI_ISCAN, &hdev->flags); 2879fbcbb45SJohan Hedberg if (!old_iscan) 28873f22f62SJohan Hedberg mgmt_discoverable(hdev->id, 1); 2899fbcbb45SJohan Hedberg } else if (old_iscan) 29073f22f62SJohan Hedberg mgmt_discoverable(hdev->id, 0); 2911da177e4SLinus Torvalds 2929fbcbb45SJohan Hedberg if (param & SCAN_PAGE) { 2931da177e4SLinus Torvalds set_bit(HCI_PSCAN, &hdev->flags); 2949fbcbb45SJohan Hedberg if (!old_pscan) 2959fbcbb45SJohan Hedberg mgmt_connectable(hdev->id, 1); 2969fbcbb45SJohan Hedberg } else if (old_pscan) 2979fbcbb45SJohan Hedberg mgmt_connectable(hdev->id, 0); 2981da177e4SLinus Torvalds } 299a9de9248SMarcel Holtmann 30023bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status); 3011da177e4SLinus Torvalds } 3021da177e4SLinus Torvalds 303a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 304a9de9248SMarcel Holtmann { 305a9de9248SMarcel Holtmann struct hci_rp_read_class_of_dev *rp = (void *) skb->data; 306a9de9248SMarcel Holtmann 307a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 308a9de9248SMarcel Holtmann 309a9de9248SMarcel Holtmann if (rp->status) 310a9de9248SMarcel Holtmann return; 311a9de9248SMarcel Holtmann 312a9de9248SMarcel Holtmann memcpy(hdev->dev_class, rp->dev_class, 3); 313a9de9248SMarcel Holtmann 314a9de9248SMarcel Holtmann BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, 315a9de9248SMarcel Holtmann hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); 316a9de9248SMarcel Holtmann } 317a9de9248SMarcel Holtmann 318a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 319a9de9248SMarcel Holtmann { 320a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 321a9de9248SMarcel Holtmann void *sent; 322a9de9248SMarcel Holtmann 323a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 324a9de9248SMarcel Holtmann 325f383f275SMarcel Holtmann if (status) 326f383f275SMarcel Holtmann return; 327f383f275SMarcel Holtmann 328a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); 329a9de9248SMarcel Holtmann if (!sent) 330a9de9248SMarcel Holtmann return; 331a9de9248SMarcel Holtmann 332a9de9248SMarcel Holtmann memcpy(hdev->dev_class, sent, 3); 333a9de9248SMarcel Holtmann } 334a9de9248SMarcel Holtmann 335a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 336a9de9248SMarcel Holtmann { 337a9de9248SMarcel Holtmann struct hci_rp_read_voice_setting *rp = (void *) skb->data; 338a9de9248SMarcel Holtmann __u16 setting; 339a9de9248SMarcel Holtmann 340a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 341a9de9248SMarcel Holtmann 342a9de9248SMarcel Holtmann if (rp->status) 343a9de9248SMarcel Holtmann return; 344a9de9248SMarcel Holtmann 345a9de9248SMarcel Holtmann setting = __le16_to_cpu(rp->voice_setting); 346a9de9248SMarcel Holtmann 347a9de9248SMarcel Holtmann if (hdev->voice_setting == setting) 348a9de9248SMarcel Holtmann return; 349a9de9248SMarcel Holtmann 350a9de9248SMarcel Holtmann hdev->voice_setting = setting; 351a9de9248SMarcel Holtmann 352a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 353a9de9248SMarcel Holtmann 354a9de9248SMarcel Holtmann if (hdev->notify) { 355a9de9248SMarcel Holtmann tasklet_disable(&hdev->tx_task); 356a9de9248SMarcel Holtmann hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 357a9de9248SMarcel Holtmann tasklet_enable(&hdev->tx_task); 358a9de9248SMarcel Holtmann } 359a9de9248SMarcel Holtmann } 360a9de9248SMarcel Holtmann 361a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 362a9de9248SMarcel Holtmann { 363a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 364f383f275SMarcel Holtmann __u16 setting; 365a9de9248SMarcel Holtmann void *sent; 366a9de9248SMarcel Holtmann 367a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 368a9de9248SMarcel Holtmann 369f383f275SMarcel Holtmann if (status) 370f383f275SMarcel Holtmann return; 371f383f275SMarcel Holtmann 372a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); 373a9de9248SMarcel Holtmann if (!sent) 374a9de9248SMarcel Holtmann return; 375a9de9248SMarcel Holtmann 376f383f275SMarcel Holtmann setting = get_unaligned_le16(sent); 3771da177e4SLinus Torvalds 378f383f275SMarcel Holtmann if (hdev->voice_setting == setting) 379f383f275SMarcel Holtmann return; 380f383f275SMarcel Holtmann 3811da177e4SLinus Torvalds hdev->voice_setting = setting; 3821da177e4SLinus Torvalds 383a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 3841da177e4SLinus Torvalds 3851da177e4SLinus Torvalds if (hdev->notify) { 3861da177e4SLinus Torvalds tasklet_disable(&hdev->tx_task); 3871da177e4SLinus Torvalds hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 3881da177e4SLinus Torvalds tasklet_enable(&hdev->tx_task); 3891da177e4SLinus Torvalds } 3901da177e4SLinus Torvalds } 3911da177e4SLinus Torvalds 392a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 3931da177e4SLinus Torvalds { 394a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 3951da177e4SLinus Torvalds 396a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 3971da177e4SLinus Torvalds 39823bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status); 3991143e5a6SMarcel Holtmann } 4001143e5a6SMarcel Holtmann 401333140b5SMarcel Holtmann static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 402333140b5SMarcel Holtmann { 403333140b5SMarcel Holtmann struct hci_rp_read_ssp_mode *rp = (void *) skb->data; 404333140b5SMarcel Holtmann 405333140b5SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 406333140b5SMarcel Holtmann 407333140b5SMarcel Holtmann if (rp->status) 408333140b5SMarcel Holtmann return; 409333140b5SMarcel Holtmann 410333140b5SMarcel Holtmann hdev->ssp_mode = rp->mode; 411333140b5SMarcel Holtmann } 412333140b5SMarcel Holtmann 413333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 414333140b5SMarcel Holtmann { 415333140b5SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 416333140b5SMarcel Holtmann void *sent; 417333140b5SMarcel Holtmann 418333140b5SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 419333140b5SMarcel Holtmann 420333140b5SMarcel Holtmann if (status) 421333140b5SMarcel Holtmann return; 422333140b5SMarcel Holtmann 423333140b5SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); 424333140b5SMarcel Holtmann if (!sent) 425333140b5SMarcel Holtmann return; 426333140b5SMarcel Holtmann 427333140b5SMarcel Holtmann hdev->ssp_mode = *((__u8 *) sent); 428333140b5SMarcel Holtmann } 429333140b5SMarcel Holtmann 430d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev) 431d5859e22SJohan Hedberg { 432d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 433d5859e22SJohan Hedberg return 2; 434d5859e22SJohan Hedberg 435d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 436d5859e22SJohan Hedberg return 1; 437d5859e22SJohan Hedberg 438d5859e22SJohan Hedberg if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 && 439d5859e22SJohan Hedberg hdev->lmp_subver == 0x0757) 440d5859e22SJohan Hedberg return 1; 441d5859e22SJohan Hedberg 442d5859e22SJohan Hedberg if (hdev->manufacturer == 15) { 443d5859e22SJohan Hedberg if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963) 444d5859e22SJohan Hedberg return 1; 445d5859e22SJohan Hedberg if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963) 446d5859e22SJohan Hedberg return 1; 447d5859e22SJohan Hedberg if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965) 448d5859e22SJohan Hedberg return 1; 449d5859e22SJohan Hedberg } 450d5859e22SJohan Hedberg 451d5859e22SJohan Hedberg if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 && 452d5859e22SJohan Hedberg hdev->lmp_subver == 0x1805) 453d5859e22SJohan Hedberg return 1; 454d5859e22SJohan Hedberg 455d5859e22SJohan Hedberg return 0; 456d5859e22SJohan Hedberg } 457d5859e22SJohan Hedberg 458d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev) 459d5859e22SJohan Hedberg { 460d5859e22SJohan Hedberg u8 mode; 461d5859e22SJohan Hedberg 462d5859e22SJohan Hedberg mode = hci_get_inquiry_mode(hdev); 463d5859e22SJohan Hedberg 464d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode); 465d5859e22SJohan Hedberg } 466d5859e22SJohan Hedberg 467d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev) 468d5859e22SJohan Hedberg { 469d5859e22SJohan Hedberg /* The second byte is 0xff instead of 0x9f (two reserved bits 470d5859e22SJohan Hedberg * disabled) since a Broadcom 1.2 dongle doesn't respond to the 471d5859e22SJohan Hedberg * command otherwise */ 472d5859e22SJohan Hedberg u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 }; 473d5859e22SJohan Hedberg 474d5859e22SJohan Hedberg /* Events for 1.2 and newer controllers */ 475d5859e22SJohan Hedberg if (hdev->lmp_ver > 1) { 476d5859e22SJohan Hedberg events[4] |= 0x01; /* Flow Specification Complete */ 477d5859e22SJohan Hedberg events[4] |= 0x02; /* Inquiry Result with RSSI */ 478d5859e22SJohan Hedberg events[4] |= 0x04; /* Read Remote Extended Features Complete */ 479d5859e22SJohan Hedberg events[5] |= 0x08; /* Synchronous Connection Complete */ 480d5859e22SJohan Hedberg events[5] |= 0x10; /* Synchronous Connection Changed */ 481d5859e22SJohan Hedberg } 482d5859e22SJohan Hedberg 483d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 484d5859e22SJohan Hedberg events[4] |= 0x04; /* Inquiry Result with RSSI */ 485d5859e22SJohan Hedberg 486d5859e22SJohan Hedberg if (hdev->features[5] & LMP_SNIFF_SUBR) 487d5859e22SJohan Hedberg events[5] |= 0x20; /* Sniff Subrating */ 488d5859e22SJohan Hedberg 489d5859e22SJohan Hedberg if (hdev->features[5] & LMP_PAUSE_ENC) 490d5859e22SJohan Hedberg events[5] |= 0x80; /* Encryption Key Refresh Complete */ 491d5859e22SJohan Hedberg 492d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 493d5859e22SJohan Hedberg events[5] |= 0x40; /* Extended Inquiry Result */ 494d5859e22SJohan Hedberg 495d5859e22SJohan Hedberg if (hdev->features[6] & LMP_NO_FLUSH) 496d5859e22SJohan Hedberg events[7] |= 0x01; /* Enhanced Flush Complete */ 497d5859e22SJohan Hedberg 498d5859e22SJohan Hedberg if (hdev->features[7] & LMP_LSTO) 499d5859e22SJohan Hedberg events[6] |= 0x80; /* Link Supervision Timeout Changed */ 500d5859e22SJohan Hedberg 501d5859e22SJohan Hedberg if (hdev->features[6] & LMP_SIMPLE_PAIR) { 502d5859e22SJohan Hedberg events[6] |= 0x01; /* IO Capability Request */ 503d5859e22SJohan Hedberg events[6] |= 0x02; /* IO Capability Response */ 504d5859e22SJohan Hedberg events[6] |= 0x04; /* User Confirmation Request */ 505d5859e22SJohan Hedberg events[6] |= 0x08; /* User Passkey Request */ 506d5859e22SJohan Hedberg events[6] |= 0x10; /* Remote OOB Data Request */ 507d5859e22SJohan Hedberg events[6] |= 0x20; /* Simple Pairing Complete */ 508d5859e22SJohan Hedberg events[7] |= 0x04; /* User Passkey Notification */ 509d5859e22SJohan Hedberg events[7] |= 0x08; /* Keypress Notification */ 510d5859e22SJohan Hedberg events[7] |= 0x10; /* Remote Host Supported 511d5859e22SJohan Hedberg * Features Notification */ 512d5859e22SJohan Hedberg } 513d5859e22SJohan Hedberg 514d5859e22SJohan Hedberg if (hdev->features[4] & LMP_LE) 515d5859e22SJohan Hedberg events[7] |= 0x20; /* LE Meta-Event */ 516d5859e22SJohan Hedberg 517d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); 518d5859e22SJohan Hedberg } 519d5859e22SJohan Hedberg 520d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev) 521d5859e22SJohan Hedberg { 522d5859e22SJohan Hedberg hci_setup_event_mask(hdev); 523d5859e22SJohan Hedberg 524d5859e22SJohan Hedberg if (hdev->lmp_ver > 1) 525d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); 526d5859e22SJohan Hedberg 527d5859e22SJohan Hedberg if (hdev->features[6] & LMP_SIMPLE_PAIR) { 528d5859e22SJohan Hedberg u8 mode = 0x01; 529d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode); 530d5859e22SJohan Hedberg } 531d5859e22SJohan Hedberg 532d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 533d5859e22SJohan Hedberg hci_setup_inquiry_mode(hdev); 534d5859e22SJohan Hedberg 535d5859e22SJohan Hedberg if (hdev->features[7] & LMP_INQ_TX_PWR) 536d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL); 537d5859e22SJohan Hedberg } 538d5859e22SJohan Hedberg 539a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) 540a9de9248SMarcel Holtmann { 541a9de9248SMarcel Holtmann struct hci_rp_read_local_version *rp = (void *) skb->data; 5421143e5a6SMarcel Holtmann 543a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 5441143e5a6SMarcel Holtmann 545a9de9248SMarcel Holtmann if (rp->status) 546a9de9248SMarcel Holtmann return; 5471143e5a6SMarcel Holtmann 548a9de9248SMarcel Holtmann hdev->hci_ver = rp->hci_ver; 549e4e8e37cSMarcel Holtmann hdev->hci_rev = __le16_to_cpu(rp->hci_rev); 550d5859e22SJohan Hedberg hdev->lmp_ver = rp->lmp_ver; 551e4e8e37cSMarcel Holtmann hdev->manufacturer = __le16_to_cpu(rp->manufacturer); 552d5859e22SJohan Hedberg hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); 5531da177e4SLinus Torvalds 554a9de9248SMarcel Holtmann BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name, 555a9de9248SMarcel Holtmann hdev->manufacturer, 556a9de9248SMarcel Holtmann hdev->hci_ver, hdev->hci_rev); 557d5859e22SJohan Hedberg 558d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags)) 559d5859e22SJohan Hedberg hci_setup(hdev); 560d5859e22SJohan Hedberg } 561d5859e22SJohan Hedberg 562d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev) 563d5859e22SJohan Hedberg { 564d5859e22SJohan Hedberg u16 link_policy = 0; 565d5859e22SJohan Hedberg 566d5859e22SJohan Hedberg if (hdev->features[0] & LMP_RSWITCH) 567d5859e22SJohan Hedberg link_policy |= HCI_LP_RSWITCH; 568d5859e22SJohan Hedberg if (hdev->features[0] & LMP_HOLD) 569d5859e22SJohan Hedberg link_policy |= HCI_LP_HOLD; 570d5859e22SJohan Hedberg if (hdev->features[0] & LMP_SNIFF) 571d5859e22SJohan Hedberg link_policy |= HCI_LP_SNIFF; 572d5859e22SJohan Hedberg if (hdev->features[1] & LMP_PARK) 573d5859e22SJohan Hedberg link_policy |= HCI_LP_PARK; 574d5859e22SJohan Hedberg 575d5859e22SJohan Hedberg link_policy = cpu_to_le16(link_policy); 576d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, 577d5859e22SJohan Hedberg sizeof(link_policy), &link_policy); 5781da177e4SLinus Torvalds } 5791da177e4SLinus Torvalds 580a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb) 581a9de9248SMarcel Holtmann { 582a9de9248SMarcel Holtmann struct hci_rp_read_local_commands *rp = (void *) skb->data; 583a9de9248SMarcel Holtmann 584a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 585a9de9248SMarcel Holtmann 586a9de9248SMarcel Holtmann if (rp->status) 587d5859e22SJohan Hedberg goto done; 588a9de9248SMarcel Holtmann 589a9de9248SMarcel Holtmann memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); 590d5859e22SJohan Hedberg 591d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10)) 592d5859e22SJohan Hedberg hci_setup_link_policy(hdev); 593d5859e22SJohan Hedberg 594d5859e22SJohan Hedberg done: 595d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status); 596a9de9248SMarcel Holtmann } 597a9de9248SMarcel Holtmann 598a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb) 599a9de9248SMarcel Holtmann { 600a9de9248SMarcel Holtmann struct hci_rp_read_local_features *rp = (void *) skb->data; 601a9de9248SMarcel Holtmann 602a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 603a9de9248SMarcel Holtmann 604a9de9248SMarcel Holtmann if (rp->status) 605a9de9248SMarcel Holtmann return; 606a9de9248SMarcel Holtmann 607a9de9248SMarcel Holtmann memcpy(hdev->features, rp->features, 8); 6081da177e4SLinus Torvalds 6091da177e4SLinus Torvalds /* Adjust default settings according to features 6101da177e4SLinus Torvalds * supported by device. */ 611a9de9248SMarcel Holtmann 6121da177e4SLinus Torvalds if (hdev->features[0] & LMP_3SLOT) 6131da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM3 | HCI_DH3); 6141da177e4SLinus Torvalds 6151da177e4SLinus Torvalds if (hdev->features[0] & LMP_5SLOT) 6161da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM5 | HCI_DH5); 6171da177e4SLinus Torvalds 6185b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV2) { 6191da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV2); 6205b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV2); 6215b7f9909SMarcel Holtmann } 6221da177e4SLinus Torvalds 6235b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV3) { 6241da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV3); 6255b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV3); 6265b7f9909SMarcel Holtmann } 6275b7f9909SMarcel Holtmann 6285b7f9909SMarcel Holtmann if (hdev->features[3] & LMP_ESCO) 6295b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV3); 6305b7f9909SMarcel Holtmann 6315b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV4) 6325b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV4); 6335b7f9909SMarcel Holtmann 6345b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV5) 6355b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV5); 6361da177e4SLinus Torvalds 637efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_2M) 638efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV3); 639efc7688bSMarcel Holtmann 640efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_3M) 641efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_3EV3); 642efc7688bSMarcel Holtmann 643efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_3S_ESCO) 644efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); 645efc7688bSMarcel Holtmann 646a9de9248SMarcel Holtmann BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, 647a9de9248SMarcel Holtmann hdev->features[0], hdev->features[1], 648a9de9248SMarcel Holtmann hdev->features[2], hdev->features[3], 649a9de9248SMarcel Holtmann hdev->features[4], hdev->features[5], 650a9de9248SMarcel Holtmann hdev->features[6], hdev->features[7]); 6511da177e4SLinus Torvalds } 6521da177e4SLinus Torvalds 653a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 654a9de9248SMarcel Holtmann { 655a9de9248SMarcel Holtmann struct hci_rp_read_buffer_size *rp = (void *) skb->data; 656a9de9248SMarcel Holtmann 657a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 658a9de9248SMarcel Holtmann 659a9de9248SMarcel Holtmann if (rp->status) 660a9de9248SMarcel Holtmann return; 661a9de9248SMarcel Holtmann 662a9de9248SMarcel Holtmann hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); 663a9de9248SMarcel Holtmann hdev->sco_mtu = rp->sco_mtu; 664a9de9248SMarcel Holtmann hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); 665a9de9248SMarcel Holtmann hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); 666da1f5198SMarcel Holtmann 667da1f5198SMarcel Holtmann if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { 668da1f5198SMarcel Holtmann hdev->sco_mtu = 64; 669da1f5198SMarcel Holtmann hdev->sco_pkts = 8; 670da1f5198SMarcel Holtmann } 671da1f5198SMarcel Holtmann 672da1f5198SMarcel Holtmann hdev->acl_cnt = hdev->acl_pkts; 673da1f5198SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 6741da177e4SLinus Torvalds 675a9de9248SMarcel Holtmann BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, 676a9de9248SMarcel Holtmann hdev->acl_mtu, hdev->acl_pkts, 677a9de9248SMarcel Holtmann hdev->sco_mtu, hdev->sco_pkts); 6781da177e4SLinus Torvalds } 6791da177e4SLinus Torvalds 680a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) 681a9de9248SMarcel Holtmann { 682a9de9248SMarcel Holtmann struct hci_rp_read_bd_addr *rp = (void *) skb->data; 6831da177e4SLinus Torvalds 684a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 685a9de9248SMarcel Holtmann 686a9de9248SMarcel Holtmann if (!rp->status) 687a9de9248SMarcel Holtmann bacpy(&hdev->bdaddr, &rp->bdaddr); 688a9de9248SMarcel Holtmann 68923bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status); 69023bb5763SJohan Hedberg } 69123bb5763SJohan Hedberg 69223bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb) 69323bb5763SJohan Hedberg { 69423bb5763SJohan Hedberg __u8 status = *((__u8 *) skb->data); 69523bb5763SJohan Hedberg 69623bb5763SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 69723bb5763SJohan Hedberg 69823bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status); 6991da177e4SLinus Torvalds } 7001da177e4SLinus Torvalds 701b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, 702b0916ea0SJohan Hedberg struct sk_buff *skb) 703b0916ea0SJohan Hedberg { 704b0916ea0SJohan Hedberg __u8 status = *((__u8 *) skb->data); 705b0916ea0SJohan Hedberg 706b0916ea0SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 707b0916ea0SJohan Hedberg 708b0916ea0SJohan Hedberg hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status); 709b0916ea0SJohan Hedberg } 710b0916ea0SJohan Hedberg 711d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb) 712d5859e22SJohan Hedberg { 713d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 714d5859e22SJohan Hedberg 715d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 716d5859e22SJohan Hedberg 717d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status); 718d5859e22SJohan Hedberg } 719d5859e22SJohan Hedberg 720d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev, 721d5859e22SJohan Hedberg struct sk_buff *skb) 722d5859e22SJohan Hedberg { 723d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 724d5859e22SJohan Hedberg 725d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 726d5859e22SJohan Hedberg 727d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status); 728d5859e22SJohan Hedberg } 729d5859e22SJohan Hedberg 730d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, 731d5859e22SJohan Hedberg struct sk_buff *skb) 732d5859e22SJohan Hedberg { 733d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 734d5859e22SJohan Hedberg 735d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 736d5859e22SJohan Hedberg 737d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status); 738d5859e22SJohan Hedberg } 739d5859e22SJohan Hedberg 740d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb) 741d5859e22SJohan Hedberg { 742d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 743d5859e22SJohan Hedberg 744d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 745d5859e22SJohan Hedberg 746d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status); 747d5859e22SJohan Hedberg } 748d5859e22SJohan Hedberg 749980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) 750980e1a53SJohan Hedberg { 751980e1a53SJohan Hedberg struct hci_rp_pin_code_reply *rp = (void *) skb->data; 752980e1a53SJohan Hedberg struct hci_cp_pin_code_reply *cp; 753980e1a53SJohan Hedberg struct hci_conn *conn; 754980e1a53SJohan Hedberg 755980e1a53SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 756980e1a53SJohan Hedberg 757980e1a53SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 758980e1a53SJohan Hedberg mgmt_pin_code_reply_complete(hdev->id, &rp->bdaddr, rp->status); 759980e1a53SJohan Hedberg 760980e1a53SJohan Hedberg if (rp->status != 0) 761980e1a53SJohan Hedberg return; 762980e1a53SJohan Hedberg 763980e1a53SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); 764980e1a53SJohan Hedberg if (!cp) 765980e1a53SJohan Hedberg return; 766980e1a53SJohan Hedberg 767980e1a53SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 768980e1a53SJohan Hedberg if (conn) 769980e1a53SJohan Hedberg conn->pin_length = cp->pin_len; 770980e1a53SJohan Hedberg } 771980e1a53SJohan Hedberg 772980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 773980e1a53SJohan Hedberg { 774980e1a53SJohan Hedberg struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data; 775980e1a53SJohan Hedberg 776980e1a53SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 777980e1a53SJohan Hedberg 778980e1a53SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 779980e1a53SJohan Hedberg mgmt_pin_code_neg_reply_complete(hdev->id, &rp->bdaddr, 780980e1a53SJohan Hedberg rp->status); 781980e1a53SJohan Hedberg } 7826ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, 7836ed58ec5SVille Tervo struct sk_buff *skb) 7846ed58ec5SVille Tervo { 7856ed58ec5SVille Tervo struct hci_rp_le_read_buffer_size *rp = (void *) skb->data; 7866ed58ec5SVille Tervo 7876ed58ec5SVille Tervo BT_DBG("%s status 0x%x", hdev->name, rp->status); 7886ed58ec5SVille Tervo 7896ed58ec5SVille Tervo if (rp->status) 7906ed58ec5SVille Tervo return; 7916ed58ec5SVille Tervo 7926ed58ec5SVille Tervo hdev->le_mtu = __le16_to_cpu(rp->le_mtu); 7936ed58ec5SVille Tervo hdev->le_pkts = rp->le_max_pkt; 7946ed58ec5SVille Tervo 7956ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 7966ed58ec5SVille Tervo 7976ed58ec5SVille Tervo BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); 7986ed58ec5SVille Tervo 7996ed58ec5SVille Tervo hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status); 8006ed58ec5SVille Tervo } 801980e1a53SJohan Hedberg 802a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) 803a5c29683SJohan Hedberg { 804a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 805a5c29683SJohan Hedberg 806a5c29683SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 807a5c29683SJohan Hedberg 808a5c29683SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 809a5c29683SJohan Hedberg mgmt_user_confirm_reply_complete(hdev->id, &rp->bdaddr, 810a5c29683SJohan Hedberg rp->status); 811a5c29683SJohan Hedberg } 812a5c29683SJohan Hedberg 813a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, 814a5c29683SJohan Hedberg struct sk_buff *skb) 815a5c29683SJohan Hedberg { 816a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 817a5c29683SJohan Hedberg 818a5c29683SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 819a5c29683SJohan Hedberg 820a5c29683SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 821a5c29683SJohan Hedberg mgmt_user_confirm_neg_reply_complete(hdev->id, &rp->bdaddr, 822a5c29683SJohan Hedberg rp->status); 823a5c29683SJohan Hedberg } 824a5c29683SJohan Hedberg 825a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 826a9de9248SMarcel Holtmann { 827a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 828a9de9248SMarcel Holtmann 829a9de9248SMarcel Holtmann if (status) { 83023bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 831a9de9248SMarcel Holtmann 832a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 833a9de9248SMarcel Holtmann } else 834a9de9248SMarcel Holtmann set_bit(HCI_INQUIRY, &hdev->flags); 835a9de9248SMarcel Holtmann } 836a9de9248SMarcel Holtmann 8371da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 8381da177e4SLinus Torvalds { 839a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 8401da177e4SLinus Torvalds struct hci_conn *conn; 8411da177e4SLinus Torvalds 842a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 843a9de9248SMarcel Holtmann 844a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 8451da177e4SLinus Torvalds if (!cp) 8461da177e4SLinus Torvalds return; 8471da177e4SLinus Torvalds 8481da177e4SLinus Torvalds hci_dev_lock(hdev); 8491da177e4SLinus Torvalds 8501da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 8511da177e4SLinus Torvalds 852a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn); 8531da177e4SLinus Torvalds 8541da177e4SLinus Torvalds if (status) { 8551da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 8564c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 8571da177e4SLinus Torvalds conn->state = BT_CLOSED; 8581da177e4SLinus Torvalds hci_proto_connect_cfm(conn, status); 8591da177e4SLinus Torvalds hci_conn_del(conn); 8604c67bc74SMarcel Holtmann } else 8614c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 8621da177e4SLinus Torvalds } 8631da177e4SLinus Torvalds } else { 8641da177e4SLinus Torvalds if (!conn) { 8651da177e4SLinus Torvalds conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); 8661da177e4SLinus Torvalds if (conn) { 8671da177e4SLinus Torvalds conn->out = 1; 8681da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 8691da177e4SLinus Torvalds } else 870893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 8711da177e4SLinus Torvalds } 8721da177e4SLinus Torvalds } 8731da177e4SLinus Torvalds 8741da177e4SLinus Torvalds hci_dev_unlock(hdev); 8751da177e4SLinus Torvalds } 8761da177e4SLinus Torvalds 877a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 8781da177e4SLinus Torvalds { 879a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 8801da177e4SLinus Torvalds struct hci_conn *acl, *sco; 8811da177e4SLinus Torvalds __u16 handle; 8821da177e4SLinus Torvalds 883b6a0dc82SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 884b6a0dc82SMarcel Holtmann 885a9de9248SMarcel Holtmann if (!status) 886a9de9248SMarcel Holtmann return; 887a9de9248SMarcel Holtmann 888a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 8891da177e4SLinus Torvalds if (!cp) 890a9de9248SMarcel Holtmann return; 8911da177e4SLinus Torvalds 8921da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 8931da177e4SLinus Torvalds 894a9de9248SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 8951da177e4SLinus Torvalds 8961da177e4SLinus Torvalds hci_dev_lock(hdev); 8971da177e4SLinus Torvalds 8981da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 8995a08ecceSAndrei Emeltchenko if (acl) { 9005a08ecceSAndrei Emeltchenko sco = acl->link; 9015a08ecceSAndrei Emeltchenko if (sco) { 9021da177e4SLinus Torvalds sco->state = BT_CLOSED; 9031da177e4SLinus Torvalds 9041da177e4SLinus Torvalds hci_proto_connect_cfm(sco, status); 9051da177e4SLinus Torvalds hci_conn_del(sco); 9061da177e4SLinus Torvalds } 9075a08ecceSAndrei Emeltchenko } 9081da177e4SLinus Torvalds 9091da177e4SLinus Torvalds hci_dev_unlock(hdev); 9101da177e4SLinus Torvalds } 9111da177e4SLinus Torvalds 912f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 913f8558555SMarcel Holtmann { 914f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 915f8558555SMarcel Holtmann struct hci_conn *conn; 916f8558555SMarcel Holtmann 917f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 918f8558555SMarcel Holtmann 919f8558555SMarcel Holtmann if (!status) 920f8558555SMarcel Holtmann return; 921f8558555SMarcel Holtmann 922f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 923f8558555SMarcel Holtmann if (!cp) 924f8558555SMarcel Holtmann return; 925f8558555SMarcel Holtmann 926f8558555SMarcel Holtmann hci_dev_lock(hdev); 927f8558555SMarcel Holtmann 928f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 929f8558555SMarcel Holtmann if (conn) { 930f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 931f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 932f8558555SMarcel Holtmann hci_conn_put(conn); 933f8558555SMarcel Holtmann } 934f8558555SMarcel Holtmann } 935f8558555SMarcel Holtmann 936f8558555SMarcel Holtmann hci_dev_unlock(hdev); 937f8558555SMarcel Holtmann } 938f8558555SMarcel Holtmann 939f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 940f8558555SMarcel Holtmann { 941f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 942f8558555SMarcel Holtmann struct hci_conn *conn; 943f8558555SMarcel Holtmann 944f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 945f8558555SMarcel Holtmann 946f8558555SMarcel Holtmann if (!status) 947f8558555SMarcel Holtmann return; 948f8558555SMarcel Holtmann 949f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 950f8558555SMarcel Holtmann if (!cp) 951f8558555SMarcel Holtmann return; 952f8558555SMarcel Holtmann 953f8558555SMarcel Holtmann hci_dev_lock(hdev); 954f8558555SMarcel Holtmann 955f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 956f8558555SMarcel Holtmann if (conn) { 957f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 958f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 959f8558555SMarcel Holtmann hci_conn_put(conn); 960f8558555SMarcel Holtmann } 961f8558555SMarcel Holtmann } 962f8558555SMarcel Holtmann 963f8558555SMarcel Holtmann hci_dev_unlock(hdev); 964f8558555SMarcel Holtmann } 965f8558555SMarcel Holtmann 966127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev, 967392599b9SJohan Hedberg struct hci_conn *conn) 968392599b9SJohan Hedberg { 969392599b9SJohan Hedberg if (conn->state != BT_CONFIG || !conn->out) 970392599b9SJohan Hedberg return 0; 971392599b9SJohan Hedberg 972765c2a96SJohan Hedberg if (conn->pending_sec_level == BT_SECURITY_SDP) 973392599b9SJohan Hedberg return 0; 974392599b9SJohan Hedberg 975392599b9SJohan Hedberg /* Only request authentication for SSP connections or non-SSP 976392599b9SJohan Hedberg * devices with sec_level HIGH */ 977392599b9SJohan Hedberg if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) && 978765c2a96SJohan Hedberg conn->pending_sec_level != BT_SECURITY_HIGH) 979392599b9SJohan Hedberg return 0; 980392599b9SJohan Hedberg 981392599b9SJohan Hedberg return 1; 982392599b9SJohan Hedberg } 983392599b9SJohan Hedberg 984a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 9851da177e4SLinus Torvalds { 986127178d2SJohan Hedberg struct hci_cp_remote_name_req *cp; 987127178d2SJohan Hedberg struct hci_conn *conn; 988127178d2SJohan Hedberg 989a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 990127178d2SJohan Hedberg 991127178d2SJohan Hedberg /* If successful wait for the name req complete event before 992127178d2SJohan Hedberg * checking for the need to do authentication */ 993127178d2SJohan Hedberg if (!status) 994127178d2SJohan Hedberg return; 995127178d2SJohan Hedberg 996127178d2SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); 997127178d2SJohan Hedberg if (!cp) 998127178d2SJohan Hedberg return; 999127178d2SJohan Hedberg 1000127178d2SJohan Hedberg hci_dev_lock(hdev); 1001127178d2SJohan Hedberg 1002127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 1003127178d2SJohan Hedberg if (conn && hci_outgoing_auth_needed(hdev, conn)) { 1004127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1005127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1006127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1007127178d2SJohan Hedberg } 1008127178d2SJohan Hedberg 1009127178d2SJohan Hedberg hci_dev_unlock(hdev); 1010a9de9248SMarcel Holtmann } 10111da177e4SLinus Torvalds 1012769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 1013769be974SMarcel Holtmann { 1014769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 1015769be974SMarcel Holtmann struct hci_conn *conn; 1016769be974SMarcel Holtmann 1017769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1018769be974SMarcel Holtmann 1019769be974SMarcel Holtmann if (!status) 1020769be974SMarcel Holtmann return; 1021769be974SMarcel Holtmann 1022769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 1023769be974SMarcel Holtmann if (!cp) 1024769be974SMarcel Holtmann return; 1025769be974SMarcel Holtmann 1026769be974SMarcel Holtmann hci_dev_lock(hdev); 1027769be974SMarcel Holtmann 1028769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1029769be974SMarcel Holtmann if (conn) { 1030769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1031769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1032769be974SMarcel Holtmann hci_conn_put(conn); 1033769be974SMarcel Holtmann } 1034769be974SMarcel Holtmann } 1035769be974SMarcel Holtmann 1036769be974SMarcel Holtmann hci_dev_unlock(hdev); 1037769be974SMarcel Holtmann } 1038769be974SMarcel Holtmann 1039769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 1040769be974SMarcel Holtmann { 1041769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features *cp; 1042769be974SMarcel Holtmann struct hci_conn *conn; 1043769be974SMarcel Holtmann 1044769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1045769be974SMarcel Holtmann 1046769be974SMarcel Holtmann if (!status) 1047769be974SMarcel Holtmann return; 1048769be974SMarcel Holtmann 1049769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 1050769be974SMarcel Holtmann if (!cp) 1051769be974SMarcel Holtmann return; 1052769be974SMarcel Holtmann 1053769be974SMarcel Holtmann hci_dev_lock(hdev); 1054769be974SMarcel Holtmann 1055769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1056769be974SMarcel Holtmann if (conn) { 1057769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1058769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1059769be974SMarcel Holtmann hci_conn_put(conn); 1060769be974SMarcel Holtmann } 1061769be974SMarcel Holtmann } 1062769be974SMarcel Holtmann 1063769be974SMarcel Holtmann hci_dev_unlock(hdev); 1064769be974SMarcel Holtmann } 1065769be974SMarcel Holtmann 1066a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 1067a9de9248SMarcel Holtmann { 1068b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 1069b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 1070b6a0dc82SMarcel Holtmann __u16 handle; 1071b6a0dc82SMarcel Holtmann 1072a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1073b6a0dc82SMarcel Holtmann 1074b6a0dc82SMarcel Holtmann if (!status) 1075b6a0dc82SMarcel Holtmann return; 1076b6a0dc82SMarcel Holtmann 1077b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 1078b6a0dc82SMarcel Holtmann if (!cp) 1079b6a0dc82SMarcel Holtmann return; 1080b6a0dc82SMarcel Holtmann 1081b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 1082b6a0dc82SMarcel Holtmann 1083b6a0dc82SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 1084b6a0dc82SMarcel Holtmann 1085b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 1086b6a0dc82SMarcel Holtmann 1087b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 10885a08ecceSAndrei Emeltchenko if (acl) { 10895a08ecceSAndrei Emeltchenko sco = acl->link; 10905a08ecceSAndrei Emeltchenko if (sco) { 1091b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 1092b6a0dc82SMarcel Holtmann 1093b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(sco, status); 1094b6a0dc82SMarcel Holtmann hci_conn_del(sco); 1095b6a0dc82SMarcel Holtmann } 10965a08ecceSAndrei Emeltchenko } 1097b6a0dc82SMarcel Holtmann 1098b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 1099a9de9248SMarcel Holtmann } 1100a9de9248SMarcel Holtmann 1101a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 1102a9de9248SMarcel Holtmann { 1103a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 110404837f64SMarcel Holtmann struct hci_conn *conn; 110504837f64SMarcel Holtmann 1106a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1107a9de9248SMarcel Holtmann 1108a9de9248SMarcel Holtmann if (!status) 1109a9de9248SMarcel Holtmann return; 1110a9de9248SMarcel Holtmann 1111a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 111204837f64SMarcel Holtmann if (!cp) 1113a9de9248SMarcel Holtmann return; 111404837f64SMarcel Holtmann 111504837f64SMarcel Holtmann hci_dev_lock(hdev); 111604837f64SMarcel Holtmann 111704837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1118e73439d8SMarcel Holtmann if (conn) { 111904837f64SMarcel Holtmann clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); 112004837f64SMarcel Holtmann 1121e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 1122e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1123e73439d8SMarcel Holtmann } 1124e73439d8SMarcel Holtmann 112504837f64SMarcel Holtmann hci_dev_unlock(hdev); 112604837f64SMarcel Holtmann } 112704837f64SMarcel Holtmann 1128a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 1129a9de9248SMarcel Holtmann { 1130a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 113104837f64SMarcel Holtmann struct hci_conn *conn; 113204837f64SMarcel Holtmann 1133a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1134a9de9248SMarcel Holtmann 1135a9de9248SMarcel Holtmann if (!status) 1136a9de9248SMarcel Holtmann return; 1137a9de9248SMarcel Holtmann 1138a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 113904837f64SMarcel Holtmann if (!cp) 1140a9de9248SMarcel Holtmann return; 114104837f64SMarcel Holtmann 114204837f64SMarcel Holtmann hci_dev_lock(hdev); 114304837f64SMarcel Holtmann 114404837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1145e73439d8SMarcel Holtmann if (conn) { 114604837f64SMarcel Holtmann clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); 114704837f64SMarcel Holtmann 1148e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 1149e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1150e73439d8SMarcel Holtmann } 1151e73439d8SMarcel Holtmann 115204837f64SMarcel Holtmann hci_dev_unlock(hdev); 115304837f64SMarcel Holtmann } 115404837f64SMarcel Holtmann 1155fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) 1156fcd89c09SVille Tervo { 1157fcd89c09SVille Tervo struct hci_cp_le_create_conn *cp; 1158fcd89c09SVille Tervo struct hci_conn *conn; 1159fcd89c09SVille Tervo 1160fcd89c09SVille Tervo BT_DBG("%s status 0x%x", hdev->name, status); 1161fcd89c09SVille Tervo 1162fcd89c09SVille Tervo cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN); 1163fcd89c09SVille Tervo if (!cp) 1164fcd89c09SVille Tervo return; 1165fcd89c09SVille Tervo 1166fcd89c09SVille Tervo hci_dev_lock(hdev); 1167fcd89c09SVille Tervo 1168fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr); 1169fcd89c09SVille Tervo 1170fcd89c09SVille Tervo BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr), 1171fcd89c09SVille Tervo conn); 1172fcd89c09SVille Tervo 1173fcd89c09SVille Tervo if (status) { 1174fcd89c09SVille Tervo if (conn && conn->state == BT_CONNECT) { 1175fcd89c09SVille Tervo conn->state = BT_CLOSED; 1176fcd89c09SVille Tervo hci_proto_connect_cfm(conn, status); 1177fcd89c09SVille Tervo hci_conn_del(conn); 1178fcd89c09SVille Tervo } 1179fcd89c09SVille Tervo } else { 1180fcd89c09SVille Tervo if (!conn) { 1181fcd89c09SVille Tervo conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr); 1182fcd89c09SVille Tervo if (conn) 1183fcd89c09SVille Tervo conn->out = 1; 1184fcd89c09SVille Tervo else 1185fcd89c09SVille Tervo BT_ERR("No memory for new connection"); 1186fcd89c09SVille Tervo } 1187fcd89c09SVille Tervo } 1188fcd89c09SVille Tervo 1189fcd89c09SVille Tervo hci_dev_unlock(hdev); 1190fcd89c09SVille Tervo } 1191fcd89c09SVille Tervo 11921da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 11931da177e4SLinus Torvalds { 11941da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 11951da177e4SLinus Torvalds 11961da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, status); 11971da177e4SLinus Torvalds 11981da177e4SLinus Torvalds clear_bit(HCI_INQUIRY, &hdev->flags); 1199a9de9248SMarcel Holtmann 120023bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 12016bd57416SMarcel Holtmann 1202a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 12031da177e4SLinus Torvalds } 12041da177e4SLinus Torvalds 12051da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 12061da177e4SLinus Torvalds { 120745bb4bf0SMarcel Holtmann struct inquiry_data data; 1208a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 12091da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 12101da177e4SLinus Torvalds 12111da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 12121da177e4SLinus Torvalds 121345bb4bf0SMarcel Holtmann if (!num_rsp) 121445bb4bf0SMarcel Holtmann return; 121545bb4bf0SMarcel Holtmann 12161da177e4SLinus Torvalds hci_dev_lock(hdev); 121745bb4bf0SMarcel Holtmann 12181da177e4SLinus Torvalds for (; num_rsp; num_rsp--) { 12191da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 12201da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 12211da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 12221da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 12231da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 12241da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 12251da177e4SLinus Torvalds data.rssi = 0x00; 122641a96212SMarcel Holtmann data.ssp_mode = 0x00; 12271da177e4SLinus Torvalds info++; 12281da177e4SLinus Torvalds hci_inquiry_cache_update(hdev, &data); 12291da177e4SLinus Torvalds } 123045bb4bf0SMarcel Holtmann 12311da177e4SLinus Torvalds hci_dev_unlock(hdev); 12321da177e4SLinus Torvalds } 12331da177e4SLinus Torvalds 1234a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 12351da177e4SLinus Torvalds { 1236a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 1237a9de9248SMarcel Holtmann struct hci_conn *conn; 12381da177e4SLinus Torvalds 1239a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 124045bb4bf0SMarcel Holtmann 12411da177e4SLinus Torvalds hci_dev_lock(hdev); 124245bb4bf0SMarcel Holtmann 1243a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 12449499237aSMarcel Holtmann if (!conn) { 12459499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 12469499237aSMarcel Holtmann goto unlock; 12479499237aSMarcel Holtmann 12489499237aSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 1249a9de9248SMarcel Holtmann if (!conn) 1250a9de9248SMarcel Holtmann goto unlock; 125145bb4bf0SMarcel Holtmann 12529499237aSMarcel Holtmann conn->type = SCO_LINK; 12539499237aSMarcel Holtmann } 12549499237aSMarcel Holtmann 1255a9de9248SMarcel Holtmann if (!ev->status) { 1256a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 1257769be974SMarcel Holtmann 1258769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 1259769be974SMarcel Holtmann conn->state = BT_CONFIG; 1260769be974SMarcel Holtmann hci_conn_hold(conn); 1261052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1262f7520543SJohan Hedberg mgmt_connected(hdev->id, &ev->bdaddr); 1263769be974SMarcel Holtmann } else 1264a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 1265a9de9248SMarcel Holtmann 12669eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 12677d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 12687d0db0a3SMarcel Holtmann 1269a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 1270a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1271a9de9248SMarcel Holtmann 1272a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 1273a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1274a9de9248SMarcel Holtmann 1275a9de9248SMarcel Holtmann /* Get remote features */ 1276a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 1277a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 1278a9de9248SMarcel Holtmann cp.handle = ev->handle; 1279769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 1280769be974SMarcel Holtmann sizeof(cp), &cp); 128145bb4bf0SMarcel Holtmann } 1282a9de9248SMarcel Holtmann 1283a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 1284a8746417SMarcel Holtmann if (!conn->out && hdev->hci_ver < 3) { 1285a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 1286a9de9248SMarcel Holtmann cp.handle = ev->handle; 1287a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1288a8746417SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, 1289a8746417SMarcel Holtmann sizeof(cp), &cp); 1290a9de9248SMarcel Holtmann } 129117d5c04cSJohan Hedberg } else { 1292a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 129317d5c04cSJohan Hedberg if (conn->type == ACL_LINK) 129417d5c04cSJohan Hedberg mgmt_connect_failed(hdev->id, &ev->bdaddr, ev->status); 129517d5c04cSJohan Hedberg } 129645bb4bf0SMarcel Holtmann 1297e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 1298e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 129945bb4bf0SMarcel Holtmann 1300769be974SMarcel Holtmann if (ev->status) { 1301a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1302a9de9248SMarcel Holtmann hci_conn_del(conn); 1303c89b6e6bSMarcel Holtmann } else if (ev->link_type != ACL_LINK) 1304c89b6e6bSMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1305a9de9248SMarcel Holtmann 1306a9de9248SMarcel Holtmann unlock: 13071da177e4SLinus Torvalds hci_dev_unlock(hdev); 1308a9de9248SMarcel Holtmann 1309a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 13101da177e4SLinus Torvalds } 13111da177e4SLinus Torvalds 13121da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 13131da177e4SLinus Torvalds { 1314a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 13151da177e4SLinus Torvalds int mask = hdev->link_mode; 13161da177e4SLinus Torvalds 1317a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s type 0x%x", hdev->name, 13181da177e4SLinus Torvalds batostr(&ev->bdaddr), ev->link_type); 13191da177e4SLinus Torvalds 13201da177e4SLinus Torvalds mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); 13211da177e4SLinus Torvalds 1322138d22efSSzymon Janc if ((mask & HCI_LM_ACCEPT) && 1323138d22efSSzymon Janc !hci_blacklist_lookup(hdev, &ev->bdaddr)) { 13241da177e4SLinus Torvalds /* Connection accepted */ 1325c7bdd502SMarcel Holtmann struct inquiry_entry *ie; 13261da177e4SLinus Torvalds struct hci_conn *conn; 13271da177e4SLinus Torvalds 13281da177e4SLinus Torvalds hci_dev_lock(hdev); 1329b6a0dc82SMarcel Holtmann 1330cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 1331cc11b9c1SAndrei Emeltchenko if (ie) 1332c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 1333c7bdd502SMarcel Holtmann 13341da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 13351da177e4SLinus Torvalds if (!conn) { 1336cc11b9c1SAndrei Emeltchenko conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); 1337cc11b9c1SAndrei Emeltchenko if (!conn) { 1338893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 13391da177e4SLinus Torvalds hci_dev_unlock(hdev); 13401da177e4SLinus Torvalds return; 13411da177e4SLinus Torvalds } 13421da177e4SLinus Torvalds } 1343b6a0dc82SMarcel Holtmann 13441da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 13451da177e4SLinus Torvalds conn->state = BT_CONNECT; 1346b6a0dc82SMarcel Holtmann 13471da177e4SLinus Torvalds hci_dev_unlock(hdev); 13481da177e4SLinus Torvalds 1349b6a0dc82SMarcel Holtmann if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) { 1350b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 1351b6a0dc82SMarcel Holtmann 13521da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 13531da177e4SLinus Torvalds 13541da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 13551da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 13561da177e4SLinus Torvalds else 13571da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 13581da177e4SLinus Torvalds 1359b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, 1360b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1361b6a0dc82SMarcel Holtmann } else { 1362b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 1363b6a0dc82SMarcel Holtmann 1364b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 1365a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1366b6a0dc82SMarcel Holtmann 1367b6a0dc82SMarcel Holtmann cp.tx_bandwidth = cpu_to_le32(0x00001f40); 1368b6a0dc82SMarcel Holtmann cp.rx_bandwidth = cpu_to_le32(0x00001f40); 1369b6a0dc82SMarcel Holtmann cp.max_latency = cpu_to_le16(0xffff); 1370b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 1371b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 1372b6a0dc82SMarcel Holtmann 1373b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 1374b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1375b6a0dc82SMarcel Holtmann } 13761da177e4SLinus Torvalds } else { 13771da177e4SLinus Torvalds /* Connection rejected */ 13781da177e4SLinus Torvalds struct hci_cp_reject_conn_req cp; 13791da177e4SLinus Torvalds 13801da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 13811da177e4SLinus Torvalds cp.reason = 0x0f; 1382a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 13831da177e4SLinus Torvalds } 13841da177e4SLinus Torvalds } 13851da177e4SLinus Torvalds 13861da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 13871da177e4SLinus Torvalds { 1388a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 138904837f64SMarcel Holtmann struct hci_conn *conn; 13901da177e4SLinus Torvalds 13911da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 13921da177e4SLinus Torvalds 13938962ee74SJohan Hedberg if (ev->status) { 13948962ee74SJohan Hedberg mgmt_disconnect_failed(hdev->id); 13951da177e4SLinus Torvalds return; 13968962ee74SJohan Hedberg } 13971da177e4SLinus Torvalds 13981da177e4SLinus Torvalds hci_dev_lock(hdev); 13991da177e4SLinus Torvalds 140004837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1401f7520543SJohan Hedberg if (!conn) 1402f7520543SJohan Hedberg goto unlock; 1403f7520543SJohan Hedberg 14041da177e4SLinus Torvalds conn->state = BT_CLOSED; 14057d0db0a3SMarcel Holtmann 1406f7520543SJohan Hedberg if (conn->type == ACL_LINK) 1407f7520543SJohan Hedberg mgmt_disconnected(hdev->id, &conn->dst); 1408f7520543SJohan Hedberg 14092950f21aSMarcel Holtmann hci_proto_disconn_cfm(conn, ev->reason); 14101da177e4SLinus Torvalds hci_conn_del(conn); 14111da177e4SLinus Torvalds 1412f7520543SJohan Hedberg unlock: 14131da177e4SLinus Torvalds hci_dev_unlock(hdev); 14141da177e4SLinus Torvalds } 14151da177e4SLinus Torvalds 1416a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1417a9de9248SMarcel Holtmann { 1418a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 1419a9de9248SMarcel Holtmann struct hci_conn *conn; 1420a9de9248SMarcel Holtmann 1421a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1422a9de9248SMarcel Holtmann 1423a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1424a9de9248SMarcel Holtmann 1425a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1426a9de9248SMarcel Holtmann if (conn) { 1427765c2a96SJohan Hedberg if (!ev->status) { 1428a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1429765c2a96SJohan Hedberg conn->sec_level = conn->pending_sec_level; 14302a611692SJohan Hedberg } else { 14312a611692SJohan Hedberg mgmt_auth_failed(hdev->id, &conn->dst, ev->status); 1432da213f41SJohan Hedberg conn->sec_level = BT_SECURITY_LOW; 14332a611692SJohan Hedberg } 1434a9de9248SMarcel Holtmann 1435a9de9248SMarcel Holtmann clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); 1436a9de9248SMarcel Holtmann 1437f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1438f8558555SMarcel Holtmann if (!ev->status && hdev->ssp_mode > 0 && 1439f8558555SMarcel Holtmann conn->ssp_mode > 0) { 1440f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1441f8558555SMarcel Holtmann cp.handle = ev->handle; 1442f8558555SMarcel Holtmann cp.encrypt = 0x01; 1443f8558555SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, 1444f8558555SMarcel Holtmann sizeof(cp), &cp); 1445f8558555SMarcel Holtmann } else { 1446f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1447f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1448f8558555SMarcel Holtmann hci_conn_put(conn); 1449f8558555SMarcel Holtmann } 1450052b30b0SMarcel Holtmann } else { 1451a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 1452a9de9248SMarcel Holtmann 1453052b30b0SMarcel Holtmann hci_conn_hold(conn); 1454052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1455052b30b0SMarcel Holtmann hci_conn_put(conn); 1456052b30b0SMarcel Holtmann } 1457052b30b0SMarcel Holtmann 1458a9de9248SMarcel Holtmann if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) { 1459a9de9248SMarcel Holtmann if (!ev->status) { 1460a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1461f8558555SMarcel Holtmann cp.handle = ev->handle; 1462f8558555SMarcel Holtmann cp.encrypt = 0x01; 1463f8558555SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, 1464f8558555SMarcel Holtmann sizeof(cp), &cp); 1465a9de9248SMarcel Holtmann } else { 1466a9de9248SMarcel Holtmann clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); 1467a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 1468a9de9248SMarcel Holtmann } 1469a9de9248SMarcel Holtmann } 1470a9de9248SMarcel Holtmann } 1471a9de9248SMarcel Holtmann 1472a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1473a9de9248SMarcel Holtmann } 1474a9de9248SMarcel Holtmann 1475a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 1476a9de9248SMarcel Holtmann { 1477127178d2SJohan Hedberg struct hci_ev_remote_name *ev = (void *) skb->data; 1478127178d2SJohan Hedberg struct hci_conn *conn; 1479127178d2SJohan Hedberg 1480a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1481a9de9248SMarcel Holtmann 1482a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 1483127178d2SJohan Hedberg 1484127178d2SJohan Hedberg hci_dev_lock(hdev); 1485127178d2SJohan Hedberg 1486127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 1487127178d2SJohan Hedberg if (conn && hci_outgoing_auth_needed(hdev, conn)) { 1488127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1489127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1490127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1491127178d2SJohan Hedberg } 1492127178d2SJohan Hedberg 1493127178d2SJohan Hedberg hci_dev_unlock(hdev); 1494a9de9248SMarcel Holtmann } 1495a9de9248SMarcel Holtmann 1496a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 1497a9de9248SMarcel Holtmann { 1498a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 1499a9de9248SMarcel Holtmann struct hci_conn *conn; 1500a9de9248SMarcel Holtmann 1501a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1502a9de9248SMarcel Holtmann 1503a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1504a9de9248SMarcel Holtmann 1505a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1506a9de9248SMarcel Holtmann if (conn) { 1507a9de9248SMarcel Holtmann if (!ev->status) { 1508ae293196SMarcel Holtmann if (ev->encrypt) { 1509ae293196SMarcel Holtmann /* Encryption implies authentication */ 1510ae293196SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1511a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1512ae293196SMarcel Holtmann } else 1513a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_ENCRYPT; 1514a9de9248SMarcel Holtmann } 1515a9de9248SMarcel Holtmann 1516a9de9248SMarcel Holtmann clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); 1517a9de9248SMarcel Holtmann 1518f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1519f8558555SMarcel Holtmann if (!ev->status) 1520f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1521f8558555SMarcel Holtmann 1522f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1523f8558555SMarcel Holtmann hci_conn_put(conn); 1524f8558555SMarcel Holtmann } else 1525a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 1526a9de9248SMarcel Holtmann } 1527a9de9248SMarcel Holtmann 1528a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1529a9de9248SMarcel Holtmann } 1530a9de9248SMarcel Holtmann 1531a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1532a9de9248SMarcel Holtmann { 1533a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 1534a9de9248SMarcel Holtmann struct hci_conn *conn; 1535a9de9248SMarcel Holtmann 1536a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1537a9de9248SMarcel Holtmann 1538a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1539a9de9248SMarcel Holtmann 1540a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1541a9de9248SMarcel Holtmann if (conn) { 1542a9de9248SMarcel Holtmann if (!ev->status) 1543a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_SECURE; 1544a9de9248SMarcel Holtmann 1545a9de9248SMarcel Holtmann clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); 1546a9de9248SMarcel Holtmann 1547a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 1548a9de9248SMarcel Holtmann } 1549a9de9248SMarcel Holtmann 1550a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1551a9de9248SMarcel Holtmann } 1552a9de9248SMarcel Holtmann 1553a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 1554a9de9248SMarcel Holtmann { 1555a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 1556a9de9248SMarcel Holtmann struct hci_conn *conn; 1557a9de9248SMarcel Holtmann 1558a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1559a9de9248SMarcel Holtmann 1560a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1561a9de9248SMarcel Holtmann 1562a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1563ccd556feSJohan Hedberg if (!conn) 1564ccd556feSJohan Hedberg goto unlock; 1565ccd556feSJohan Hedberg 1566769be974SMarcel Holtmann if (!ev->status) 1567a9de9248SMarcel Holtmann memcpy(conn->features, ev->features, 8); 1568a9de9248SMarcel Holtmann 1569ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 1570ccd556feSJohan Hedberg goto unlock; 1571ccd556feSJohan Hedberg 1572ccd556feSJohan Hedberg if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { 1573769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 1574769be974SMarcel Holtmann cp.handle = ev->handle; 1575769be974SMarcel Holtmann cp.page = 0x01; 1576ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 1577769be974SMarcel Holtmann sizeof(cp), &cp); 1578392599b9SJohan Hedberg goto unlock; 1579392599b9SJohan Hedberg } 1580392599b9SJohan Hedberg 1581127178d2SJohan Hedberg if (!ev->status) { 1582127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 1583127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 1584127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 1585127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 1586127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 1587127178d2SJohan Hedberg } 1588392599b9SJohan Hedberg 1589127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 1590769be974SMarcel Holtmann conn->state = BT_CONNECTED; 1591769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1592769be974SMarcel Holtmann hci_conn_put(conn); 1593769be974SMarcel Holtmann } 1594769be974SMarcel Holtmann 1595ccd556feSJohan Hedberg unlock: 1596a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1597a9de9248SMarcel Holtmann } 1598a9de9248SMarcel Holtmann 1599a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) 1600a9de9248SMarcel Holtmann { 1601a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1602a9de9248SMarcel Holtmann } 1603a9de9248SMarcel Holtmann 1604a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1605a9de9248SMarcel Holtmann { 1606a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1607a9de9248SMarcel Holtmann } 1608a9de9248SMarcel Holtmann 1609a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1610a9de9248SMarcel Holtmann { 1611a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 1612a9de9248SMarcel Holtmann __u16 opcode; 1613a9de9248SMarcel Holtmann 1614a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 1615a9de9248SMarcel Holtmann 1616a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 1617a9de9248SMarcel Holtmann 1618a9de9248SMarcel Holtmann switch (opcode) { 1619a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 1620a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 1621a9de9248SMarcel Holtmann break; 1622a9de9248SMarcel Holtmann 1623a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 1624a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 1625a9de9248SMarcel Holtmann break; 1626a9de9248SMarcel Holtmann 1627a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 1628a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 1629a9de9248SMarcel Holtmann break; 1630a9de9248SMarcel Holtmann 1631a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 1632a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 1633a9de9248SMarcel Holtmann break; 1634a9de9248SMarcel Holtmann 1635e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 1636e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 1637e4e8e37cSMarcel Holtmann break; 1638e4e8e37cSMarcel Holtmann 1639a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 1640a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 1641a9de9248SMarcel Holtmann break; 1642a9de9248SMarcel Holtmann 1643e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 1644e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 1645e4e8e37cSMarcel Holtmann break; 1646e4e8e37cSMarcel Holtmann 1647e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 1648e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 1649e4e8e37cSMarcel Holtmann break; 1650e4e8e37cSMarcel Holtmann 1651a9de9248SMarcel Holtmann case HCI_OP_RESET: 1652a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 1653a9de9248SMarcel Holtmann break; 1654a9de9248SMarcel Holtmann 1655a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 1656a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 1657a9de9248SMarcel Holtmann break; 1658a9de9248SMarcel Holtmann 1659a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 1660a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 1661a9de9248SMarcel Holtmann break; 1662a9de9248SMarcel Holtmann 1663a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 1664a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 1665a9de9248SMarcel Holtmann break; 1666a9de9248SMarcel Holtmann 1667a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 1668a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 1669a9de9248SMarcel Holtmann break; 1670a9de9248SMarcel Holtmann 1671a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 1672a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 1673a9de9248SMarcel Holtmann break; 1674a9de9248SMarcel Holtmann 1675a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 1676a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 1677a9de9248SMarcel Holtmann break; 1678a9de9248SMarcel Holtmann 1679a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 1680a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 1681a9de9248SMarcel Holtmann break; 1682a9de9248SMarcel Holtmann 1683a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 1684a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 1685a9de9248SMarcel Holtmann break; 1686a9de9248SMarcel Holtmann 1687a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 1688a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 1689a9de9248SMarcel Holtmann break; 1690a9de9248SMarcel Holtmann 1691a9de9248SMarcel Holtmann case HCI_OP_HOST_BUFFER_SIZE: 1692a9de9248SMarcel Holtmann hci_cc_host_buffer_size(hdev, skb); 1693a9de9248SMarcel Holtmann break; 1694a9de9248SMarcel Holtmann 1695333140b5SMarcel Holtmann case HCI_OP_READ_SSP_MODE: 1696333140b5SMarcel Holtmann hci_cc_read_ssp_mode(hdev, skb); 1697333140b5SMarcel Holtmann break; 1698333140b5SMarcel Holtmann 1699333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 1700333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 1701333140b5SMarcel Holtmann break; 1702333140b5SMarcel Holtmann 1703a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 1704a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 1705a9de9248SMarcel Holtmann break; 1706a9de9248SMarcel Holtmann 1707a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 1708a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 1709a9de9248SMarcel Holtmann break; 1710a9de9248SMarcel Holtmann 1711a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 1712a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 1713a9de9248SMarcel Holtmann break; 1714a9de9248SMarcel Holtmann 1715a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 1716a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 1717a9de9248SMarcel Holtmann break; 1718a9de9248SMarcel Holtmann 1719a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 1720a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 1721a9de9248SMarcel Holtmann break; 1722a9de9248SMarcel Holtmann 172323bb5763SJohan Hedberg case HCI_OP_WRITE_CA_TIMEOUT: 172423bb5763SJohan Hedberg hci_cc_write_ca_timeout(hdev, skb); 172523bb5763SJohan Hedberg break; 172623bb5763SJohan Hedberg 1727b0916ea0SJohan Hedberg case HCI_OP_DELETE_STORED_LINK_KEY: 1728b0916ea0SJohan Hedberg hci_cc_delete_stored_link_key(hdev, skb); 1729b0916ea0SJohan Hedberg break; 1730b0916ea0SJohan Hedberg 1731d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_MASK: 1732d5859e22SJohan Hedberg hci_cc_set_event_mask(hdev, skb); 1733d5859e22SJohan Hedberg break; 1734d5859e22SJohan Hedberg 1735d5859e22SJohan Hedberg case HCI_OP_WRITE_INQUIRY_MODE: 1736d5859e22SJohan Hedberg hci_cc_write_inquiry_mode(hdev, skb); 1737d5859e22SJohan Hedberg break; 1738d5859e22SJohan Hedberg 1739d5859e22SJohan Hedberg case HCI_OP_READ_INQ_RSP_TX_POWER: 1740d5859e22SJohan Hedberg hci_cc_read_inq_rsp_tx_power(hdev, skb); 1741d5859e22SJohan Hedberg break; 1742d5859e22SJohan Hedberg 1743d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_FLT: 1744d5859e22SJohan Hedberg hci_cc_set_event_flt(hdev, skb); 1745d5859e22SJohan Hedberg break; 1746d5859e22SJohan Hedberg 1747980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_REPLY: 1748980e1a53SJohan Hedberg hci_cc_pin_code_reply(hdev, skb); 1749980e1a53SJohan Hedberg break; 1750980e1a53SJohan Hedberg 1751980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_NEG_REPLY: 1752980e1a53SJohan Hedberg hci_cc_pin_code_neg_reply(hdev, skb); 1753980e1a53SJohan Hedberg break; 1754980e1a53SJohan Hedberg 17556ed58ec5SVille Tervo case HCI_OP_LE_READ_BUFFER_SIZE: 17566ed58ec5SVille Tervo hci_cc_le_read_buffer_size(hdev, skb); 17576ed58ec5SVille Tervo break; 17586ed58ec5SVille Tervo 1759a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_REPLY: 1760a5c29683SJohan Hedberg hci_cc_user_confirm_reply(hdev, skb); 1761a5c29683SJohan Hedberg break; 1762a5c29683SJohan Hedberg 1763a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_NEG_REPLY: 1764a5c29683SJohan Hedberg hci_cc_user_confirm_neg_reply(hdev, skb); 1765a5c29683SJohan Hedberg break; 1766a5c29683SJohan Hedberg 1767a9de9248SMarcel Holtmann default: 1768a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 1769a9de9248SMarcel Holtmann break; 1770a9de9248SMarcel Holtmann } 1771a9de9248SMarcel Holtmann 17726bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 17736bd32326SVille Tervo del_timer(&hdev->cmd_timer); 17746bd32326SVille Tervo 1775a9de9248SMarcel Holtmann if (ev->ncmd) { 1776a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 1777a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 1778c78ae283SMarcel Holtmann tasklet_schedule(&hdev->cmd_task); 1779a9de9248SMarcel Holtmann } 1780a9de9248SMarcel Holtmann } 1781a9de9248SMarcel Holtmann 1782a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 1783a9de9248SMarcel Holtmann { 1784a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 1785a9de9248SMarcel Holtmann __u16 opcode; 1786a9de9248SMarcel Holtmann 1787a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 1788a9de9248SMarcel Holtmann 1789a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 1790a9de9248SMarcel Holtmann 1791a9de9248SMarcel Holtmann switch (opcode) { 1792a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 1793a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 1794a9de9248SMarcel Holtmann break; 1795a9de9248SMarcel Holtmann 1796a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 1797a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 1798a9de9248SMarcel Holtmann break; 1799a9de9248SMarcel Holtmann 1800a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 1801a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 1802a9de9248SMarcel Holtmann break; 1803a9de9248SMarcel Holtmann 1804f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 1805f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 1806f8558555SMarcel Holtmann break; 1807f8558555SMarcel Holtmann 1808f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 1809f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 1810f8558555SMarcel Holtmann break; 1811f8558555SMarcel Holtmann 1812a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 1813a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 1814a9de9248SMarcel Holtmann break; 1815a9de9248SMarcel Holtmann 1816769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 1817769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 1818769be974SMarcel Holtmann break; 1819769be974SMarcel Holtmann 1820769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 1821769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 1822769be974SMarcel Holtmann break; 1823769be974SMarcel Holtmann 1824a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 1825a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 1826a9de9248SMarcel Holtmann break; 1827a9de9248SMarcel Holtmann 1828a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 1829a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 1830a9de9248SMarcel Holtmann break; 1831a9de9248SMarcel Holtmann 1832a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 1833a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 1834a9de9248SMarcel Holtmann break; 1835a9de9248SMarcel Holtmann 18368962ee74SJohan Hedberg case HCI_OP_DISCONNECT: 18378962ee74SJohan Hedberg if (ev->status != 0) 18388962ee74SJohan Hedberg mgmt_disconnect_failed(hdev->id); 18398962ee74SJohan Hedberg break; 18408962ee74SJohan Hedberg 1841fcd89c09SVille Tervo case HCI_OP_LE_CREATE_CONN: 1842fcd89c09SVille Tervo hci_cs_le_create_conn(hdev, ev->status); 1843fcd89c09SVille Tervo break; 1844fcd89c09SVille Tervo 1845a9de9248SMarcel Holtmann default: 1846a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 1847a9de9248SMarcel Holtmann break; 1848a9de9248SMarcel Holtmann } 1849a9de9248SMarcel Holtmann 18506bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 18516bd32326SVille Tervo del_timer(&hdev->cmd_timer); 18526bd32326SVille Tervo 1853a9de9248SMarcel Holtmann if (ev->ncmd) { 1854a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 1855a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 1856c78ae283SMarcel Holtmann tasklet_schedule(&hdev->cmd_task); 1857a9de9248SMarcel Holtmann } 1858a9de9248SMarcel Holtmann } 1859a9de9248SMarcel Holtmann 1860a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 1861a9de9248SMarcel Holtmann { 1862a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 1863a9de9248SMarcel Holtmann struct hci_conn *conn; 1864a9de9248SMarcel Holtmann 1865a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1866a9de9248SMarcel Holtmann 1867a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1868a9de9248SMarcel Holtmann 1869a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 1870a9de9248SMarcel Holtmann if (conn) { 1871a9de9248SMarcel Holtmann if (!ev->status) { 1872a9de9248SMarcel Holtmann if (ev->role) 1873a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_MASTER; 1874a9de9248SMarcel Holtmann else 1875a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_MASTER; 1876a9de9248SMarcel Holtmann } 1877a9de9248SMarcel Holtmann 1878a9de9248SMarcel Holtmann clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend); 1879a9de9248SMarcel Holtmann 1880a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 1881a9de9248SMarcel Holtmann } 1882a9de9248SMarcel Holtmann 1883a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1884a9de9248SMarcel Holtmann } 1885a9de9248SMarcel Holtmann 18861da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 18871da177e4SLinus Torvalds { 1888a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 18891ebb9252SMarcel Holtmann __le16 *ptr; 18901da177e4SLinus Torvalds int i; 18911da177e4SLinus Torvalds 18921da177e4SLinus Torvalds skb_pull(skb, sizeof(*ev)); 18931da177e4SLinus Torvalds 18941da177e4SLinus Torvalds BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 18951da177e4SLinus Torvalds 18961da177e4SLinus Torvalds if (skb->len < ev->num_hndl * 4) { 18971da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 18981da177e4SLinus Torvalds return; 18991da177e4SLinus Torvalds } 19001da177e4SLinus Torvalds 19011da177e4SLinus Torvalds tasklet_disable(&hdev->tx_task); 19021da177e4SLinus Torvalds 19031ebb9252SMarcel Holtmann for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) { 19041da177e4SLinus Torvalds struct hci_conn *conn; 19051da177e4SLinus Torvalds __u16 handle, count; 19061da177e4SLinus Torvalds 190783985319SHarvey Harrison handle = get_unaligned_le16(ptr++); 190883985319SHarvey Harrison count = get_unaligned_le16(ptr++); 19091da177e4SLinus Torvalds 19101da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 19111da177e4SLinus Torvalds if (conn) { 19121da177e4SLinus Torvalds conn->sent -= count; 19131da177e4SLinus Torvalds 19145b7f9909SMarcel Holtmann if (conn->type == ACL_LINK) { 191570f23020SAndrei Emeltchenko hdev->acl_cnt += count; 191670f23020SAndrei Emeltchenko if (hdev->acl_cnt > hdev->acl_pkts) 19171da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 19186ed58ec5SVille Tervo } else if (conn->type == LE_LINK) { 19196ed58ec5SVille Tervo if (hdev->le_pkts) { 19206ed58ec5SVille Tervo hdev->le_cnt += count; 19216ed58ec5SVille Tervo if (hdev->le_cnt > hdev->le_pkts) 19226ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 19236ed58ec5SVille Tervo } else { 19246ed58ec5SVille Tervo hdev->acl_cnt += count; 19256ed58ec5SVille Tervo if (hdev->acl_cnt > hdev->acl_pkts) 19266ed58ec5SVille Tervo hdev->acl_cnt = hdev->acl_pkts; 19276ed58ec5SVille Tervo } 19285b7f9909SMarcel Holtmann } else { 192970f23020SAndrei Emeltchenko hdev->sco_cnt += count; 193070f23020SAndrei Emeltchenko if (hdev->sco_cnt > hdev->sco_pkts) 19315b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 19321da177e4SLinus Torvalds } 19331da177e4SLinus Torvalds } 19341da177e4SLinus Torvalds } 1935a9de9248SMarcel Holtmann 1936c78ae283SMarcel Holtmann tasklet_schedule(&hdev->tx_task); 19371da177e4SLinus Torvalds 19381da177e4SLinus Torvalds tasklet_enable(&hdev->tx_task); 19391da177e4SLinus Torvalds } 19401da177e4SLinus Torvalds 194104837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 19421da177e4SLinus Torvalds { 1943a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 194404837f64SMarcel Holtmann struct hci_conn *conn; 19451da177e4SLinus Torvalds 19461da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 19471da177e4SLinus Torvalds 19481da177e4SLinus Torvalds hci_dev_lock(hdev); 19491da177e4SLinus Torvalds 195004837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 195104837f64SMarcel Holtmann if (conn) { 195204837f64SMarcel Holtmann conn->mode = ev->mode; 195304837f64SMarcel Holtmann conn->interval = __le16_to_cpu(ev->interval); 195404837f64SMarcel Holtmann 195504837f64SMarcel Holtmann if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) { 195604837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 195704837f64SMarcel Holtmann conn->power_save = 1; 195804837f64SMarcel Holtmann else 195904837f64SMarcel Holtmann conn->power_save = 0; 196004837f64SMarcel Holtmann } 1961e73439d8SMarcel Holtmann 1962e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 1963e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 196404837f64SMarcel Holtmann } 196504837f64SMarcel Holtmann 196604837f64SMarcel Holtmann hci_dev_unlock(hdev); 196704837f64SMarcel Holtmann } 196804837f64SMarcel Holtmann 19691da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 19701da177e4SLinus Torvalds { 1971052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 1972052b30b0SMarcel Holtmann struct hci_conn *conn; 1973052b30b0SMarcel Holtmann 1974a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1975052b30b0SMarcel Holtmann 1976052b30b0SMarcel Holtmann hci_dev_lock(hdev); 1977052b30b0SMarcel Holtmann 1978052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 19793d7a9d1cSMarcel Holtmann if (conn && conn->state == BT_CONNECTED) { 1980052b30b0SMarcel Holtmann hci_conn_hold(conn); 1981052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 1982052b30b0SMarcel Holtmann hci_conn_put(conn); 1983052b30b0SMarcel Holtmann } 1984052b30b0SMarcel Holtmann 198503b555e1SJohan Hedberg if (!test_bit(HCI_PAIRABLE, &hdev->flags)) 198603b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 198703b555e1SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 198803b555e1SJohan Hedberg 1989980e1a53SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 1990980e1a53SJohan Hedberg mgmt_pin_code_request(hdev->id, &ev->bdaddr); 1991980e1a53SJohan Hedberg 1992052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 19931da177e4SLinus Torvalds } 19941da177e4SLinus Torvalds 19951da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 19961da177e4SLinus Torvalds { 199755ed8ca1SJohan Hedberg struct hci_ev_link_key_req *ev = (void *) skb->data; 199855ed8ca1SJohan Hedberg struct hci_cp_link_key_reply cp; 199955ed8ca1SJohan Hedberg struct hci_conn *conn; 200055ed8ca1SJohan Hedberg struct link_key *key; 200155ed8ca1SJohan Hedberg 2002a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 200355ed8ca1SJohan Hedberg 200455ed8ca1SJohan Hedberg if (!test_bit(HCI_LINK_KEYS, &hdev->flags)) 200555ed8ca1SJohan Hedberg return; 200655ed8ca1SJohan Hedberg 200755ed8ca1SJohan Hedberg hci_dev_lock(hdev); 200855ed8ca1SJohan Hedberg 200955ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, &ev->bdaddr); 201055ed8ca1SJohan Hedberg if (!key) { 201155ed8ca1SJohan Hedberg BT_DBG("%s link key not found for %s", hdev->name, 201255ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 201355ed8ca1SJohan Hedberg goto not_found; 201455ed8ca1SJohan Hedberg } 201555ed8ca1SJohan Hedberg 201655ed8ca1SJohan Hedberg BT_DBG("%s found key type %u for %s", hdev->name, key->type, 201755ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 201855ed8ca1SJohan Hedberg 201955ed8ca1SJohan Hedberg if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) && key->type == 0x03) { 202055ed8ca1SJohan Hedberg BT_DBG("%s ignoring debug key", hdev->name); 202155ed8ca1SJohan Hedberg goto not_found; 202255ed8ca1SJohan Hedberg } 202355ed8ca1SJohan Hedberg 202455ed8ca1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 202555ed8ca1SJohan Hedberg 202655ed8ca1SJohan Hedberg if (key->type == 0x04 && conn && conn->auth_type != 0xff && 202755ed8ca1SJohan Hedberg (conn->auth_type & 0x01)) { 202855ed8ca1SJohan Hedberg BT_DBG("%s ignoring unauthenticated key", hdev->name); 202955ed8ca1SJohan Hedberg goto not_found; 203055ed8ca1SJohan Hedberg } 203155ed8ca1SJohan Hedberg 203255ed8ca1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 203355ed8ca1SJohan Hedberg memcpy(cp.link_key, key->val, 16); 203455ed8ca1SJohan Hedberg 203555ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 203655ed8ca1SJohan Hedberg 203755ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 203855ed8ca1SJohan Hedberg 203955ed8ca1SJohan Hedberg return; 204055ed8ca1SJohan Hedberg 204155ed8ca1SJohan Hedberg not_found: 204255ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 204355ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 20441da177e4SLinus Torvalds } 20451da177e4SLinus Torvalds 20461da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 20471da177e4SLinus Torvalds { 2048052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 2049052b30b0SMarcel Holtmann struct hci_conn *conn; 205055ed8ca1SJohan Hedberg u8 pin_len = 0; 2051052b30b0SMarcel Holtmann 2052a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2053052b30b0SMarcel Holtmann 2054052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2055052b30b0SMarcel Holtmann 2056052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2057052b30b0SMarcel Holtmann if (conn) { 2058052b30b0SMarcel Holtmann hci_conn_hold(conn); 2059052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2060980e1a53SJohan Hedberg pin_len = conn->pin_length; 2061052b30b0SMarcel Holtmann hci_conn_put(conn); 2062052b30b0SMarcel Holtmann } 2063052b30b0SMarcel Holtmann 206455ed8ca1SJohan Hedberg if (test_bit(HCI_LINK_KEYS, &hdev->flags)) 206555ed8ca1SJohan Hedberg hci_add_link_key(hdev, 1, &ev->bdaddr, ev->link_key, 206655ed8ca1SJohan Hedberg ev->key_type, pin_len); 206755ed8ca1SJohan Hedberg 2068052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 20691da177e4SLinus Torvalds } 20701da177e4SLinus Torvalds 207104837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 207204837f64SMarcel Holtmann { 2073a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 207404837f64SMarcel Holtmann struct hci_conn *conn; 207504837f64SMarcel Holtmann 207604837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 207704837f64SMarcel Holtmann 207804837f64SMarcel Holtmann hci_dev_lock(hdev); 207904837f64SMarcel Holtmann 208004837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 20811da177e4SLinus Torvalds if (conn && !ev->status) { 20821da177e4SLinus Torvalds struct inquiry_entry *ie; 20831da177e4SLinus Torvalds 2084cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2085cc11b9c1SAndrei Emeltchenko if (ie) { 20861da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 20871da177e4SLinus Torvalds ie->timestamp = jiffies; 20881da177e4SLinus Torvalds } 20891da177e4SLinus Torvalds } 20901da177e4SLinus Torvalds 20911da177e4SLinus Torvalds hci_dev_unlock(hdev); 20921da177e4SLinus Torvalds } 20931da177e4SLinus Torvalds 2094a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2095a8746417SMarcel Holtmann { 2096a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 2097a8746417SMarcel Holtmann struct hci_conn *conn; 2098a8746417SMarcel Holtmann 2099a8746417SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2100a8746417SMarcel Holtmann 2101a8746417SMarcel Holtmann hci_dev_lock(hdev); 2102a8746417SMarcel Holtmann 2103a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2104a8746417SMarcel Holtmann if (conn && !ev->status) 2105a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 2106a8746417SMarcel Holtmann 2107a8746417SMarcel Holtmann hci_dev_unlock(hdev); 2108a8746417SMarcel Holtmann } 2109a8746417SMarcel Holtmann 211085a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 211185a1e930SMarcel Holtmann { 2112a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 211385a1e930SMarcel Holtmann struct inquiry_entry *ie; 211485a1e930SMarcel Holtmann 211585a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 211685a1e930SMarcel Holtmann 211785a1e930SMarcel Holtmann hci_dev_lock(hdev); 211885a1e930SMarcel Holtmann 2119cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2120cc11b9c1SAndrei Emeltchenko if (ie) { 212185a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 212285a1e930SMarcel Holtmann ie->timestamp = jiffies; 212385a1e930SMarcel Holtmann } 212485a1e930SMarcel Holtmann 212585a1e930SMarcel Holtmann hci_dev_unlock(hdev); 212685a1e930SMarcel Holtmann } 212785a1e930SMarcel Holtmann 2128a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb) 2129a9de9248SMarcel Holtmann { 2130a9de9248SMarcel Holtmann struct inquiry_data data; 2131a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2132a9de9248SMarcel Holtmann 2133a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2134a9de9248SMarcel Holtmann 2135a9de9248SMarcel Holtmann if (!num_rsp) 2136a9de9248SMarcel Holtmann return; 2137a9de9248SMarcel Holtmann 2138a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2139a9de9248SMarcel Holtmann 2140a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 2141138d22efSSzymon Janc struct inquiry_info_with_rssi_and_pscan_mode *info; 2142138d22efSSzymon Janc info = (void *) (skb->data + 1); 2143a9de9248SMarcel Holtmann 2144a9de9248SMarcel Holtmann for (; num_rsp; num_rsp--) { 2145a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2146a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2147a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2148a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 2149a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2150a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2151a9de9248SMarcel Holtmann data.rssi = info->rssi; 215241a96212SMarcel Holtmann data.ssp_mode = 0x00; 2153a9de9248SMarcel Holtmann info++; 2154a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 2155a9de9248SMarcel Holtmann } 2156a9de9248SMarcel Holtmann } else { 2157a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 2158a9de9248SMarcel Holtmann 2159a9de9248SMarcel Holtmann for (; num_rsp; num_rsp--) { 2160a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2161a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2162a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2163a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2164a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2165a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2166a9de9248SMarcel Holtmann data.rssi = info->rssi; 216741a96212SMarcel Holtmann data.ssp_mode = 0x00; 2168a9de9248SMarcel Holtmann info++; 2169a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 2170a9de9248SMarcel Holtmann } 2171a9de9248SMarcel Holtmann } 2172a9de9248SMarcel Holtmann 2173a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2174a9de9248SMarcel Holtmann } 2175a9de9248SMarcel Holtmann 2176a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 2177a9de9248SMarcel Holtmann { 217841a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 217941a96212SMarcel Holtmann struct hci_conn *conn; 218041a96212SMarcel Holtmann 2181a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 218241a96212SMarcel Holtmann 218341a96212SMarcel Holtmann hci_dev_lock(hdev); 218441a96212SMarcel Holtmann 218541a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2186ccd556feSJohan Hedberg if (!conn) 2187ccd556feSJohan Hedberg goto unlock; 2188ccd556feSJohan Hedberg 2189769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 219041a96212SMarcel Holtmann struct inquiry_entry *ie; 219141a96212SMarcel Holtmann 2192cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2193cc11b9c1SAndrei Emeltchenko if (ie) 219441a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 219541a96212SMarcel Holtmann 219641a96212SMarcel Holtmann conn->ssp_mode = (ev->features[0] & 0x01); 219741a96212SMarcel Holtmann } 219841a96212SMarcel Holtmann 2199ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2200ccd556feSJohan Hedberg goto unlock; 2201ccd556feSJohan Hedberg 2202127178d2SJohan Hedberg if (!ev->status) { 2203127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2204127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2205127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2206127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2207127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2208127178d2SJohan Hedberg } 2209392599b9SJohan Hedberg 2210127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2211769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2212769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2213769be974SMarcel Holtmann hci_conn_put(conn); 2214769be974SMarcel Holtmann } 2215769be974SMarcel Holtmann 2216ccd556feSJohan Hedberg unlock: 221741a96212SMarcel Holtmann hci_dev_unlock(hdev); 2218a9de9248SMarcel Holtmann } 2219a9de9248SMarcel Holtmann 2220a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2221a9de9248SMarcel Holtmann { 2222b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 2223b6a0dc82SMarcel Holtmann struct hci_conn *conn; 2224b6a0dc82SMarcel Holtmann 2225b6a0dc82SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2226b6a0dc82SMarcel Holtmann 2227b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 2228b6a0dc82SMarcel Holtmann 2229b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 22309dc0a3afSMarcel Holtmann if (!conn) { 22319dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 22329dc0a3afSMarcel Holtmann goto unlock; 22339dc0a3afSMarcel Holtmann 22349dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 2235b6a0dc82SMarcel Holtmann if (!conn) 2236b6a0dc82SMarcel Holtmann goto unlock; 2237b6a0dc82SMarcel Holtmann 22389dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 22399dc0a3afSMarcel Holtmann } 22409dc0a3afSMarcel Holtmann 2241732547f9SMarcel Holtmann switch (ev->status) { 2242732547f9SMarcel Holtmann case 0x00: 2243732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 2244732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 2245732547f9SMarcel Holtmann 22469eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 2247732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 2248732547f9SMarcel Holtmann break; 2249732547f9SMarcel Holtmann 2250705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 2251732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 22521038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 2253732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 2254732547f9SMarcel Holtmann if (conn->out && conn->attempt < 2) { 2255efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 2256efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 2257efc7688bSMarcel Holtmann hci_setup_sync(conn, conn->link->handle); 2258efc7688bSMarcel Holtmann goto unlock; 2259efc7688bSMarcel Holtmann } 2260732547f9SMarcel Holtmann /* fall through */ 2261efc7688bSMarcel Holtmann 2262732547f9SMarcel Holtmann default: 2263b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 2264732547f9SMarcel Holtmann break; 2265732547f9SMarcel Holtmann } 2266b6a0dc82SMarcel Holtmann 2267b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2268b6a0dc82SMarcel Holtmann if (ev->status) 2269b6a0dc82SMarcel Holtmann hci_conn_del(conn); 2270b6a0dc82SMarcel Holtmann 2271b6a0dc82SMarcel Holtmann unlock: 2272b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 2273a9de9248SMarcel Holtmann } 2274a9de9248SMarcel Holtmann 2275a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) 2276a9de9248SMarcel Holtmann { 2277a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2278a9de9248SMarcel Holtmann } 2279a9de9248SMarcel Holtmann 228004837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) 228104837f64SMarcel Holtmann { 2282a9de9248SMarcel Holtmann struct hci_ev_sniff_subrate *ev = (void *) skb->data; 228304837f64SMarcel Holtmann 228404837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 228504837f64SMarcel Holtmann } 228604837f64SMarcel Holtmann 2287a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 2288a9de9248SMarcel Holtmann { 2289a9de9248SMarcel Holtmann struct inquiry_data data; 2290a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 2291a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2292a9de9248SMarcel Holtmann 2293a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2294a9de9248SMarcel Holtmann 2295a9de9248SMarcel Holtmann if (!num_rsp) 2296a9de9248SMarcel Holtmann return; 2297a9de9248SMarcel Holtmann 2298a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2299a9de9248SMarcel Holtmann 2300a9de9248SMarcel Holtmann for (; num_rsp; num_rsp--) { 2301a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2302a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2303a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2304a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2305a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2306a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2307a9de9248SMarcel Holtmann data.rssi = info->rssi; 230841a96212SMarcel Holtmann data.ssp_mode = 0x01; 2309a9de9248SMarcel Holtmann info++; 2310a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 2311a9de9248SMarcel Holtmann } 2312a9de9248SMarcel Holtmann 2313a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2314a9de9248SMarcel Holtmann } 2315a9de9248SMarcel Holtmann 231617fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn) 231717fa4b9dSJohan Hedberg { 231817fa4b9dSJohan Hedberg /* If remote requests dedicated bonding follow that lead */ 231917fa4b9dSJohan Hedberg if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) { 232017fa4b9dSJohan Hedberg /* If both remote and local IO capabilities allow MITM 232117fa4b9dSJohan Hedberg * protection then require it, otherwise don't */ 232217fa4b9dSJohan Hedberg if (conn->remote_cap == 0x03 || conn->io_capability == 0x03) 232317fa4b9dSJohan Hedberg return 0x02; 232417fa4b9dSJohan Hedberg else 232517fa4b9dSJohan Hedberg return 0x03; 232617fa4b9dSJohan Hedberg } 232717fa4b9dSJohan Hedberg 232817fa4b9dSJohan Hedberg /* If remote requests no-bonding follow that lead */ 232917fa4b9dSJohan Hedberg if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01) 233017fa4b9dSJohan Hedberg return 0x00; 233117fa4b9dSJohan Hedberg 233217fa4b9dSJohan Hedberg return conn->auth_type; 233317fa4b9dSJohan Hedberg } 233417fa4b9dSJohan Hedberg 23350493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 23360493684eSMarcel Holtmann { 23370493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 23380493684eSMarcel Holtmann struct hci_conn *conn; 23390493684eSMarcel Holtmann 23400493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 23410493684eSMarcel Holtmann 23420493684eSMarcel Holtmann hci_dev_lock(hdev); 23430493684eSMarcel Holtmann 23440493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 234503b555e1SJohan Hedberg if (!conn) 234603b555e1SJohan Hedberg goto unlock; 234703b555e1SJohan Hedberg 23480493684eSMarcel Holtmann hci_conn_hold(conn); 23490493684eSMarcel Holtmann 235003b555e1SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->flags)) 235103b555e1SJohan Hedberg goto unlock; 235203b555e1SJohan Hedberg 235303b555e1SJohan Hedberg if (test_bit(HCI_PAIRABLE, &hdev->flags) || 235403b555e1SJohan Hedberg (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 235517fa4b9dSJohan Hedberg struct hci_cp_io_capability_reply cp; 235617fa4b9dSJohan Hedberg 235717fa4b9dSJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 235817fa4b9dSJohan Hedberg cp.capability = conn->io_capability; 235917fa4b9dSJohan Hedberg cp.oob_data = 0; 236017fa4b9dSJohan Hedberg cp.authentication = hci_get_auth_req(conn); 236117fa4b9dSJohan Hedberg 236217fa4b9dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, 236317fa4b9dSJohan Hedberg sizeof(cp), &cp); 236403b555e1SJohan Hedberg } else { 236503b555e1SJohan Hedberg struct hci_cp_io_capability_neg_reply cp; 236603b555e1SJohan Hedberg 236703b555e1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 236803b555e1SJohan Hedberg cp.reason = 0x16; /* Pairing not allowed */ 236903b555e1SJohan Hedberg 237003b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 237103b555e1SJohan Hedberg sizeof(cp), &cp); 237203b555e1SJohan Hedberg } 237303b555e1SJohan Hedberg 237403b555e1SJohan Hedberg unlock: 237503b555e1SJohan Hedberg hci_dev_unlock(hdev); 237603b555e1SJohan Hedberg } 237703b555e1SJohan Hedberg 237803b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 237903b555e1SJohan Hedberg { 238003b555e1SJohan Hedberg struct hci_ev_io_capa_reply *ev = (void *) skb->data; 238103b555e1SJohan Hedberg struct hci_conn *conn; 238203b555e1SJohan Hedberg 238303b555e1SJohan Hedberg BT_DBG("%s", hdev->name); 238403b555e1SJohan Hedberg 238503b555e1SJohan Hedberg hci_dev_lock(hdev); 238603b555e1SJohan Hedberg 238703b555e1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 238803b555e1SJohan Hedberg if (!conn) 238903b555e1SJohan Hedberg goto unlock; 239003b555e1SJohan Hedberg 239103b555e1SJohan Hedberg hci_conn_hold(conn); 239203b555e1SJohan Hedberg 239303b555e1SJohan Hedberg conn->remote_cap = ev->capability; 239403b555e1SJohan Hedberg conn->remote_oob = ev->oob_data; 239503b555e1SJohan Hedberg conn->remote_auth = ev->authentication; 239603b555e1SJohan Hedberg 239703b555e1SJohan Hedberg unlock: 23980493684eSMarcel Holtmann hci_dev_unlock(hdev); 23990493684eSMarcel Holtmann } 24000493684eSMarcel Holtmann 2401a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev, 2402a5c29683SJohan Hedberg struct sk_buff *skb) 2403a5c29683SJohan Hedberg { 2404a5c29683SJohan Hedberg struct hci_ev_user_confirm_req *ev = (void *) skb->data; 2405a5c29683SJohan Hedberg 2406a5c29683SJohan Hedberg BT_DBG("%s", hdev->name); 2407a5c29683SJohan Hedberg 2408a5c29683SJohan Hedberg hci_dev_lock(hdev); 2409a5c29683SJohan Hedberg 2410a5c29683SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 2411a5c29683SJohan Hedberg mgmt_user_confirm_request(hdev->id, &ev->bdaddr, ev->passkey); 2412a5c29683SJohan Hedberg 2413a5c29683SJohan Hedberg hci_dev_unlock(hdev); 2414a5c29683SJohan Hedberg } 2415a5c29683SJohan Hedberg 24160493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 24170493684eSMarcel Holtmann { 24180493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 24190493684eSMarcel Holtmann struct hci_conn *conn; 24200493684eSMarcel Holtmann 24210493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 24220493684eSMarcel Holtmann 24230493684eSMarcel Holtmann hci_dev_lock(hdev); 24240493684eSMarcel Holtmann 24250493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 24262a611692SJohan Hedberg if (!conn) 24272a611692SJohan Hedberg goto unlock; 24282a611692SJohan Hedberg 24292a611692SJohan Hedberg /* To avoid duplicate auth_failed events to user space we check 24302a611692SJohan Hedberg * the HCI_CONN_AUTH_PEND flag which will be set if we 24312a611692SJohan Hedberg * initiated the authentication. A traditional auth_complete 24322a611692SJohan Hedberg * event gets always produced as initiator and is also mapped to 24332a611692SJohan Hedberg * the mgmt_auth_failed event */ 24342a611692SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0) 24352a611692SJohan Hedberg mgmt_auth_failed(hdev->id, &conn->dst, ev->status); 24362a611692SJohan Hedberg 24370493684eSMarcel Holtmann hci_conn_put(conn); 24380493684eSMarcel Holtmann 24392a611692SJohan Hedberg unlock: 24400493684eSMarcel Holtmann hci_dev_unlock(hdev); 24410493684eSMarcel Holtmann } 24420493684eSMarcel Holtmann 244341a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 244441a96212SMarcel Holtmann { 244541a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 244641a96212SMarcel Holtmann struct inquiry_entry *ie; 244741a96212SMarcel Holtmann 244841a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 244941a96212SMarcel Holtmann 245041a96212SMarcel Holtmann hci_dev_lock(hdev); 245141a96212SMarcel Holtmann 2452cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2453cc11b9c1SAndrei Emeltchenko if (ie) 245441a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 245541a96212SMarcel Holtmann 245641a96212SMarcel Holtmann hci_dev_unlock(hdev); 245741a96212SMarcel Holtmann } 245841a96212SMarcel Holtmann 2459fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2460fcd89c09SVille Tervo { 2461fcd89c09SVille Tervo struct hci_ev_le_conn_complete *ev = (void *) skb->data; 2462fcd89c09SVille Tervo struct hci_conn *conn; 2463fcd89c09SVille Tervo 2464fcd89c09SVille Tervo BT_DBG("%s status %d", hdev->name, ev->status); 2465fcd89c09SVille Tervo 2466fcd89c09SVille Tervo hci_dev_lock(hdev); 2467fcd89c09SVille Tervo 2468fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr); 2469b62f328bSVille Tervo if (!conn) { 2470b62f328bSVille Tervo conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); 2471b62f328bSVille Tervo if (!conn) { 2472b62f328bSVille Tervo BT_ERR("No memory for new connection"); 2473b62f328bSVille Tervo hci_dev_unlock(hdev); 2474b62f328bSVille Tervo return; 2475b62f328bSVille Tervo } 2476b62f328bSVille Tervo } 2477fcd89c09SVille Tervo 2478fcd89c09SVille Tervo if (ev->status) { 2479fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 2480fcd89c09SVille Tervo conn->state = BT_CLOSED; 2481fcd89c09SVille Tervo hci_conn_del(conn); 2482fcd89c09SVille Tervo goto unlock; 2483fcd89c09SVille Tervo } 2484fcd89c09SVille Tervo 2485fcd89c09SVille Tervo conn->handle = __le16_to_cpu(ev->handle); 2486fcd89c09SVille Tervo conn->state = BT_CONNECTED; 2487fcd89c09SVille Tervo 2488fcd89c09SVille Tervo hci_conn_hold_device(conn); 2489fcd89c09SVille Tervo hci_conn_add_sysfs(conn); 2490fcd89c09SVille Tervo 2491fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 2492fcd89c09SVille Tervo 2493fcd89c09SVille Tervo unlock: 2494fcd89c09SVille Tervo hci_dev_unlock(hdev); 2495fcd89c09SVille Tervo } 2496fcd89c09SVille Tervo 2497fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 2498fcd89c09SVille Tervo { 2499fcd89c09SVille Tervo struct hci_ev_le_meta *le_ev = (void *) skb->data; 2500fcd89c09SVille Tervo 2501fcd89c09SVille Tervo skb_pull(skb, sizeof(*le_ev)); 2502fcd89c09SVille Tervo 2503fcd89c09SVille Tervo switch (le_ev->subevent) { 2504fcd89c09SVille Tervo case HCI_EV_LE_CONN_COMPLETE: 2505fcd89c09SVille Tervo hci_le_conn_complete_evt(hdev, skb); 2506fcd89c09SVille Tervo break; 2507fcd89c09SVille Tervo 2508fcd89c09SVille Tervo default: 2509fcd89c09SVille Tervo break; 2510fcd89c09SVille Tervo } 2511fcd89c09SVille Tervo } 2512fcd89c09SVille Tervo 25131da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 25141da177e4SLinus Torvalds { 2515a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 2516a9de9248SMarcel Holtmann __u8 event = hdr->evt; 25171da177e4SLinus Torvalds 25181da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 25191da177e4SLinus Torvalds 2520a9de9248SMarcel Holtmann switch (event) { 25211da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 25221da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 25231da177e4SLinus Torvalds break; 25241da177e4SLinus Torvalds 25251da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 25261da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 25271da177e4SLinus Torvalds break; 25281da177e4SLinus Torvalds 2529a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 2530a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 253121d9e30eSMarcel Holtmann break; 253221d9e30eSMarcel Holtmann 25331da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 25341da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 25351da177e4SLinus Torvalds break; 25361da177e4SLinus Torvalds 25371da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 25381da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 25391da177e4SLinus Torvalds break; 25401da177e4SLinus Torvalds 25411da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 25421da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 25431da177e4SLinus Torvalds break; 25441da177e4SLinus Torvalds 2545a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 2546a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 2547a9de9248SMarcel Holtmann break; 2548a9de9248SMarcel Holtmann 25491da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 25501da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 25511da177e4SLinus Torvalds break; 25521da177e4SLinus Torvalds 2553a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 2554a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 2555a9de9248SMarcel Holtmann break; 2556a9de9248SMarcel Holtmann 2557a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 2558a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 2559a9de9248SMarcel Holtmann break; 2560a9de9248SMarcel Holtmann 2561a9de9248SMarcel Holtmann case HCI_EV_REMOTE_VERSION: 2562a9de9248SMarcel Holtmann hci_remote_version_evt(hdev, skb); 2563a9de9248SMarcel Holtmann break; 2564a9de9248SMarcel Holtmann 2565a9de9248SMarcel Holtmann case HCI_EV_QOS_SETUP_COMPLETE: 2566a9de9248SMarcel Holtmann hci_qos_setup_complete_evt(hdev, skb); 2567a9de9248SMarcel Holtmann break; 2568a9de9248SMarcel Holtmann 2569a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 2570a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 2571a9de9248SMarcel Holtmann break; 2572a9de9248SMarcel Holtmann 2573a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 2574a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 2575a9de9248SMarcel Holtmann break; 2576a9de9248SMarcel Holtmann 2577a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 2578a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 2579a9de9248SMarcel Holtmann break; 2580a9de9248SMarcel Holtmann 2581a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 2582a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 2583a9de9248SMarcel Holtmann break; 2584a9de9248SMarcel Holtmann 2585a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 2586a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 25871da177e4SLinus Torvalds break; 25881da177e4SLinus Torvalds 25891da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 25901da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 25911da177e4SLinus Torvalds break; 25921da177e4SLinus Torvalds 25931da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 25941da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 25951da177e4SLinus Torvalds break; 25961da177e4SLinus Torvalds 25971da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 25981da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 25991da177e4SLinus Torvalds break; 26001da177e4SLinus Torvalds 26011da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 26021da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 26031da177e4SLinus Torvalds break; 26041da177e4SLinus Torvalds 2605a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 2606a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 2607a8746417SMarcel Holtmann break; 2608a8746417SMarcel Holtmann 260985a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 261085a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 261185a1e930SMarcel Holtmann break; 261285a1e930SMarcel Holtmann 2613a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 2614a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 2615a9de9248SMarcel Holtmann break; 2616a9de9248SMarcel Holtmann 2617a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 2618a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 2619a9de9248SMarcel Holtmann break; 2620a9de9248SMarcel Holtmann 2621a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 2622a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 2623a9de9248SMarcel Holtmann break; 2624a9de9248SMarcel Holtmann 2625a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_CHANGED: 2626a9de9248SMarcel Holtmann hci_sync_conn_changed_evt(hdev, skb); 2627a9de9248SMarcel Holtmann break; 2628a9de9248SMarcel Holtmann 262904837f64SMarcel Holtmann case HCI_EV_SNIFF_SUBRATE: 263004837f64SMarcel Holtmann hci_sniff_subrate_evt(hdev, skb); 263104837f64SMarcel Holtmann break; 263204837f64SMarcel Holtmann 2633a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 2634a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 26351da177e4SLinus Torvalds break; 26361da177e4SLinus Torvalds 26370493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 26380493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 26390493684eSMarcel Holtmann break; 26400493684eSMarcel Holtmann 264103b555e1SJohan Hedberg case HCI_EV_IO_CAPA_REPLY: 264203b555e1SJohan Hedberg hci_io_capa_reply_evt(hdev, skb); 264303b555e1SJohan Hedberg break; 264403b555e1SJohan Hedberg 2645a5c29683SJohan Hedberg case HCI_EV_USER_CONFIRM_REQUEST: 2646a5c29683SJohan Hedberg hci_user_confirm_request_evt(hdev, skb); 2647a5c29683SJohan Hedberg break; 2648a5c29683SJohan Hedberg 26490493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 26500493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 26510493684eSMarcel Holtmann break; 26520493684eSMarcel Holtmann 265341a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 265441a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 265541a96212SMarcel Holtmann break; 265641a96212SMarcel Holtmann 2657fcd89c09SVille Tervo case HCI_EV_LE_META: 2658fcd89c09SVille Tervo hci_le_meta_evt(hdev, skb); 2659fcd89c09SVille Tervo break; 2660fcd89c09SVille Tervo 26611da177e4SLinus Torvalds default: 2662a9de9248SMarcel Holtmann BT_DBG("%s event 0x%x", hdev->name, event); 26631da177e4SLinus Torvalds break; 26641da177e4SLinus Torvalds } 26651da177e4SLinus Torvalds 26661da177e4SLinus Torvalds kfree_skb(skb); 26671da177e4SLinus Torvalds hdev->stat.evt_rx++; 26681da177e4SLinus Torvalds } 26691da177e4SLinus Torvalds 26701da177e4SLinus Torvalds /* Generate internal stack event */ 26711da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data) 26721da177e4SLinus Torvalds { 26731da177e4SLinus Torvalds struct hci_event_hdr *hdr; 26741da177e4SLinus Torvalds struct hci_ev_stack_internal *ev; 26751da177e4SLinus Torvalds struct sk_buff *skb; 26761da177e4SLinus Torvalds 26771da177e4SLinus Torvalds skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC); 26781da177e4SLinus Torvalds if (!skb) 26791da177e4SLinus Torvalds return; 26801da177e4SLinus Torvalds 26811da177e4SLinus Torvalds hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE); 26821da177e4SLinus Torvalds hdr->evt = HCI_EV_STACK_INTERNAL; 26831da177e4SLinus Torvalds hdr->plen = sizeof(*ev) + dlen; 26841da177e4SLinus Torvalds 26851da177e4SLinus Torvalds ev = (void *) skb_put(skb, sizeof(*ev) + dlen); 26861da177e4SLinus Torvalds ev->type = type; 26871da177e4SLinus Torvalds memcpy(ev->data, data, dlen); 26881da177e4SLinus Torvalds 2689576c7d85SMarcel Holtmann bt_cb(skb)->incoming = 1; 2690a61bbcf2SPatrick McHardy __net_timestamp(skb); 2691576c7d85SMarcel Holtmann 26920d48d939SMarcel Holtmann bt_cb(skb)->pkt_type = HCI_EVENT_PKT; 26931da177e4SLinus Torvalds skb->dev = (void *) hdev; 2694eec8d2bcSJohan Hedberg hci_send_to_sock(hdev, skb, NULL); 26951da177e4SLinus Torvalds kfree_skb(skb); 26961da177e4SLinus Torvalds } 2697