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 196f383f275SMarcel Holtmann if (status) 197f383f275SMarcel Holtmann return; 198f383f275SMarcel Holtmann 199a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); 2001da177e4SLinus Torvalds if (!sent) 201a9de9248SMarcel Holtmann return; 2021da177e4SLinus Torvalds 203a9de9248SMarcel Holtmann memcpy(hdev->dev_name, sent, 248); 204a9de9248SMarcel Holtmann } 205a9de9248SMarcel Holtmann 206a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) 207a9de9248SMarcel Holtmann { 208a9de9248SMarcel Holtmann struct hci_rp_read_local_name *rp = (void *) skb->data; 209a9de9248SMarcel Holtmann 210a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 211a9de9248SMarcel Holtmann 212a9de9248SMarcel Holtmann if (rp->status) 213a9de9248SMarcel Holtmann return; 214a9de9248SMarcel Holtmann 215a9de9248SMarcel Holtmann memcpy(hdev->dev_name, rp->name, 248); 216a9de9248SMarcel Holtmann } 217a9de9248SMarcel Holtmann 218a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) 219a9de9248SMarcel Holtmann { 220a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 221a9de9248SMarcel Holtmann void *sent; 222a9de9248SMarcel Holtmann 223a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 224a9de9248SMarcel Holtmann 225a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); 226a9de9248SMarcel Holtmann if (!sent) 227a9de9248SMarcel Holtmann return; 2281da177e4SLinus Torvalds 2291da177e4SLinus Torvalds if (!status) { 230a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 231a9de9248SMarcel Holtmann 2321da177e4SLinus Torvalds if (param == AUTH_ENABLED) 2331da177e4SLinus Torvalds set_bit(HCI_AUTH, &hdev->flags); 2341da177e4SLinus Torvalds else 2351da177e4SLinus Torvalds clear_bit(HCI_AUTH, &hdev->flags); 2361da177e4SLinus Torvalds } 237a9de9248SMarcel Holtmann 23823bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status); 239a9de9248SMarcel Holtmann } 2401da177e4SLinus Torvalds 241a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) 242a9de9248SMarcel Holtmann { 243a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 244a9de9248SMarcel Holtmann void *sent; 245a9de9248SMarcel Holtmann 246a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 247a9de9248SMarcel Holtmann 248a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); 2491da177e4SLinus Torvalds if (!sent) 250a9de9248SMarcel Holtmann return; 2511da177e4SLinus Torvalds 2521da177e4SLinus Torvalds if (!status) { 253a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 254a9de9248SMarcel Holtmann 2551da177e4SLinus Torvalds if (param) 2561da177e4SLinus Torvalds set_bit(HCI_ENCRYPT, &hdev->flags); 2571da177e4SLinus Torvalds else 2581da177e4SLinus Torvalds clear_bit(HCI_ENCRYPT, &hdev->flags); 2591da177e4SLinus Torvalds } 260a9de9248SMarcel Holtmann 26123bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status); 2621da177e4SLinus Torvalds } 2631da177e4SLinus Torvalds 264a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) 265a9de9248SMarcel Holtmann { 266a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 267a9de9248SMarcel Holtmann void *sent; 2681da177e4SLinus Torvalds 269a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 270a9de9248SMarcel Holtmann 271a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); 2721da177e4SLinus Torvalds if (!sent) 273a9de9248SMarcel Holtmann return; 2741da177e4SLinus Torvalds 2751da177e4SLinus Torvalds if (!status) { 276a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 2779fbcbb45SJohan Hedberg int old_pscan, old_iscan; 278a9de9248SMarcel Holtmann 2799fbcbb45SJohan Hedberg old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags); 2809fbcbb45SJohan Hedberg old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags); 281a9de9248SMarcel Holtmann 28273f22f62SJohan Hedberg if (param & SCAN_INQUIRY) { 2831da177e4SLinus Torvalds set_bit(HCI_ISCAN, &hdev->flags); 2849fbcbb45SJohan Hedberg if (!old_iscan) 28573f22f62SJohan Hedberg mgmt_discoverable(hdev->id, 1); 2869fbcbb45SJohan Hedberg } else if (old_iscan) 28773f22f62SJohan Hedberg mgmt_discoverable(hdev->id, 0); 2881da177e4SLinus Torvalds 2899fbcbb45SJohan Hedberg if (param & SCAN_PAGE) { 2901da177e4SLinus Torvalds set_bit(HCI_PSCAN, &hdev->flags); 2919fbcbb45SJohan Hedberg if (!old_pscan) 2929fbcbb45SJohan Hedberg mgmt_connectable(hdev->id, 1); 2939fbcbb45SJohan Hedberg } else if (old_pscan) 2949fbcbb45SJohan Hedberg mgmt_connectable(hdev->id, 0); 2951da177e4SLinus Torvalds } 296a9de9248SMarcel Holtmann 29723bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status); 2981da177e4SLinus Torvalds } 2991da177e4SLinus Torvalds 300a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 301a9de9248SMarcel Holtmann { 302a9de9248SMarcel Holtmann struct hci_rp_read_class_of_dev *rp = (void *) skb->data; 303a9de9248SMarcel Holtmann 304a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 305a9de9248SMarcel Holtmann 306a9de9248SMarcel Holtmann if (rp->status) 307a9de9248SMarcel Holtmann return; 308a9de9248SMarcel Holtmann 309a9de9248SMarcel Holtmann memcpy(hdev->dev_class, rp->dev_class, 3); 310a9de9248SMarcel Holtmann 311a9de9248SMarcel Holtmann BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, 312a9de9248SMarcel Holtmann hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); 313a9de9248SMarcel Holtmann } 314a9de9248SMarcel Holtmann 315a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 316a9de9248SMarcel Holtmann { 317a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 318a9de9248SMarcel Holtmann void *sent; 319a9de9248SMarcel Holtmann 320a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 321a9de9248SMarcel Holtmann 322f383f275SMarcel Holtmann if (status) 323f383f275SMarcel Holtmann return; 324f383f275SMarcel Holtmann 325a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); 326a9de9248SMarcel Holtmann if (!sent) 327a9de9248SMarcel Holtmann return; 328a9de9248SMarcel Holtmann 329a9de9248SMarcel Holtmann memcpy(hdev->dev_class, sent, 3); 330a9de9248SMarcel Holtmann } 331a9de9248SMarcel Holtmann 332a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 333a9de9248SMarcel Holtmann { 334a9de9248SMarcel Holtmann struct hci_rp_read_voice_setting *rp = (void *) skb->data; 335a9de9248SMarcel Holtmann __u16 setting; 336a9de9248SMarcel Holtmann 337a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 338a9de9248SMarcel Holtmann 339a9de9248SMarcel Holtmann if (rp->status) 340a9de9248SMarcel Holtmann return; 341a9de9248SMarcel Holtmann 342a9de9248SMarcel Holtmann setting = __le16_to_cpu(rp->voice_setting); 343a9de9248SMarcel Holtmann 344a9de9248SMarcel Holtmann if (hdev->voice_setting == setting) 345a9de9248SMarcel Holtmann return; 346a9de9248SMarcel Holtmann 347a9de9248SMarcel Holtmann hdev->voice_setting = setting; 348a9de9248SMarcel Holtmann 349a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 350a9de9248SMarcel Holtmann 351a9de9248SMarcel Holtmann if (hdev->notify) { 352a9de9248SMarcel Holtmann tasklet_disable(&hdev->tx_task); 353a9de9248SMarcel Holtmann hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 354a9de9248SMarcel Holtmann tasklet_enable(&hdev->tx_task); 355a9de9248SMarcel Holtmann } 356a9de9248SMarcel Holtmann } 357a9de9248SMarcel Holtmann 358a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 359a9de9248SMarcel Holtmann { 360a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 361f383f275SMarcel Holtmann __u16 setting; 362a9de9248SMarcel Holtmann void *sent; 363a9de9248SMarcel Holtmann 364a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 365a9de9248SMarcel Holtmann 366f383f275SMarcel Holtmann if (status) 367f383f275SMarcel Holtmann return; 368f383f275SMarcel Holtmann 369a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); 370a9de9248SMarcel Holtmann if (!sent) 371a9de9248SMarcel Holtmann return; 372a9de9248SMarcel Holtmann 373f383f275SMarcel Holtmann setting = get_unaligned_le16(sent); 3741da177e4SLinus Torvalds 375f383f275SMarcel Holtmann if (hdev->voice_setting == setting) 376f383f275SMarcel Holtmann return; 377f383f275SMarcel Holtmann 3781da177e4SLinus Torvalds hdev->voice_setting = setting; 3791da177e4SLinus Torvalds 380a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 3811da177e4SLinus Torvalds 3821da177e4SLinus Torvalds if (hdev->notify) { 3831da177e4SLinus Torvalds tasklet_disable(&hdev->tx_task); 3841da177e4SLinus Torvalds hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 3851da177e4SLinus Torvalds tasklet_enable(&hdev->tx_task); 3861da177e4SLinus Torvalds } 3871da177e4SLinus Torvalds } 3881da177e4SLinus Torvalds 389a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 3901da177e4SLinus Torvalds { 391a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 3921da177e4SLinus Torvalds 393a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 3941da177e4SLinus Torvalds 39523bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status); 3961143e5a6SMarcel Holtmann } 3971143e5a6SMarcel Holtmann 398333140b5SMarcel Holtmann static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 399333140b5SMarcel Holtmann { 400333140b5SMarcel Holtmann struct hci_rp_read_ssp_mode *rp = (void *) skb->data; 401333140b5SMarcel Holtmann 402333140b5SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 403333140b5SMarcel Holtmann 404333140b5SMarcel Holtmann if (rp->status) 405333140b5SMarcel Holtmann return; 406333140b5SMarcel Holtmann 407333140b5SMarcel Holtmann hdev->ssp_mode = rp->mode; 408333140b5SMarcel Holtmann } 409333140b5SMarcel Holtmann 410333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 411333140b5SMarcel Holtmann { 412333140b5SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 413333140b5SMarcel Holtmann void *sent; 414333140b5SMarcel Holtmann 415333140b5SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 416333140b5SMarcel Holtmann 417333140b5SMarcel Holtmann if (status) 418333140b5SMarcel Holtmann return; 419333140b5SMarcel Holtmann 420333140b5SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); 421333140b5SMarcel Holtmann if (!sent) 422333140b5SMarcel Holtmann return; 423333140b5SMarcel Holtmann 424333140b5SMarcel Holtmann hdev->ssp_mode = *((__u8 *) sent); 425333140b5SMarcel Holtmann } 426333140b5SMarcel Holtmann 427d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev) 428d5859e22SJohan Hedberg { 429d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 430d5859e22SJohan Hedberg return 2; 431d5859e22SJohan Hedberg 432d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 433d5859e22SJohan Hedberg return 1; 434d5859e22SJohan Hedberg 435d5859e22SJohan Hedberg if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 && 436d5859e22SJohan Hedberg hdev->lmp_subver == 0x0757) 437d5859e22SJohan Hedberg return 1; 438d5859e22SJohan Hedberg 439d5859e22SJohan Hedberg if (hdev->manufacturer == 15) { 440d5859e22SJohan Hedberg if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963) 441d5859e22SJohan Hedberg return 1; 442d5859e22SJohan Hedberg if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963) 443d5859e22SJohan Hedberg return 1; 444d5859e22SJohan Hedberg if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965) 445d5859e22SJohan Hedberg return 1; 446d5859e22SJohan Hedberg } 447d5859e22SJohan Hedberg 448d5859e22SJohan Hedberg if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 && 449d5859e22SJohan Hedberg hdev->lmp_subver == 0x1805) 450d5859e22SJohan Hedberg return 1; 451d5859e22SJohan Hedberg 452d5859e22SJohan Hedberg return 0; 453d5859e22SJohan Hedberg } 454d5859e22SJohan Hedberg 455d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev) 456d5859e22SJohan Hedberg { 457d5859e22SJohan Hedberg u8 mode; 458d5859e22SJohan Hedberg 459d5859e22SJohan Hedberg mode = hci_get_inquiry_mode(hdev); 460d5859e22SJohan Hedberg 461d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode); 462d5859e22SJohan Hedberg } 463d5859e22SJohan Hedberg 464d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev) 465d5859e22SJohan Hedberg { 466d5859e22SJohan Hedberg /* The second byte is 0xff instead of 0x9f (two reserved bits 467d5859e22SJohan Hedberg * disabled) since a Broadcom 1.2 dongle doesn't respond to the 468d5859e22SJohan Hedberg * command otherwise */ 469d5859e22SJohan Hedberg u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 }; 470d5859e22SJohan Hedberg 471d5859e22SJohan Hedberg /* Events for 1.2 and newer controllers */ 472d5859e22SJohan Hedberg if (hdev->lmp_ver > 1) { 473d5859e22SJohan Hedberg events[4] |= 0x01; /* Flow Specification Complete */ 474d5859e22SJohan Hedberg events[4] |= 0x02; /* Inquiry Result with RSSI */ 475d5859e22SJohan Hedberg events[4] |= 0x04; /* Read Remote Extended Features Complete */ 476d5859e22SJohan Hedberg events[5] |= 0x08; /* Synchronous Connection Complete */ 477d5859e22SJohan Hedberg events[5] |= 0x10; /* Synchronous Connection Changed */ 478d5859e22SJohan Hedberg } 479d5859e22SJohan Hedberg 480d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 481d5859e22SJohan Hedberg events[4] |= 0x04; /* Inquiry Result with RSSI */ 482d5859e22SJohan Hedberg 483d5859e22SJohan Hedberg if (hdev->features[5] & LMP_SNIFF_SUBR) 484d5859e22SJohan Hedberg events[5] |= 0x20; /* Sniff Subrating */ 485d5859e22SJohan Hedberg 486d5859e22SJohan Hedberg if (hdev->features[5] & LMP_PAUSE_ENC) 487d5859e22SJohan Hedberg events[5] |= 0x80; /* Encryption Key Refresh Complete */ 488d5859e22SJohan Hedberg 489d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 490d5859e22SJohan Hedberg events[5] |= 0x40; /* Extended Inquiry Result */ 491d5859e22SJohan Hedberg 492d5859e22SJohan Hedberg if (hdev->features[6] & LMP_NO_FLUSH) 493d5859e22SJohan Hedberg events[7] |= 0x01; /* Enhanced Flush Complete */ 494d5859e22SJohan Hedberg 495d5859e22SJohan Hedberg if (hdev->features[7] & LMP_LSTO) 496d5859e22SJohan Hedberg events[6] |= 0x80; /* Link Supervision Timeout Changed */ 497d5859e22SJohan Hedberg 498d5859e22SJohan Hedberg if (hdev->features[6] & LMP_SIMPLE_PAIR) { 499d5859e22SJohan Hedberg events[6] |= 0x01; /* IO Capability Request */ 500d5859e22SJohan Hedberg events[6] |= 0x02; /* IO Capability Response */ 501d5859e22SJohan Hedberg events[6] |= 0x04; /* User Confirmation Request */ 502d5859e22SJohan Hedberg events[6] |= 0x08; /* User Passkey Request */ 503d5859e22SJohan Hedberg events[6] |= 0x10; /* Remote OOB Data Request */ 504d5859e22SJohan Hedberg events[6] |= 0x20; /* Simple Pairing Complete */ 505d5859e22SJohan Hedberg events[7] |= 0x04; /* User Passkey Notification */ 506d5859e22SJohan Hedberg events[7] |= 0x08; /* Keypress Notification */ 507d5859e22SJohan Hedberg events[7] |= 0x10; /* Remote Host Supported 508d5859e22SJohan Hedberg * Features Notification */ 509d5859e22SJohan Hedberg } 510d5859e22SJohan Hedberg 511d5859e22SJohan Hedberg if (hdev->features[4] & LMP_LE) 512d5859e22SJohan Hedberg events[7] |= 0x20; /* LE Meta-Event */ 513d5859e22SJohan Hedberg 514d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); 515d5859e22SJohan Hedberg } 516d5859e22SJohan Hedberg 517d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev) 518d5859e22SJohan Hedberg { 519d5859e22SJohan Hedberg hci_setup_event_mask(hdev); 520d5859e22SJohan Hedberg 521d5859e22SJohan Hedberg if (hdev->lmp_ver > 1) 522d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); 523d5859e22SJohan Hedberg 524d5859e22SJohan Hedberg if (hdev->features[6] & LMP_SIMPLE_PAIR) { 525d5859e22SJohan Hedberg u8 mode = 0x01; 526d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode); 527d5859e22SJohan Hedberg } 528d5859e22SJohan Hedberg 529d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 530d5859e22SJohan Hedberg hci_setup_inquiry_mode(hdev); 531d5859e22SJohan Hedberg 532d5859e22SJohan Hedberg if (hdev->features[7] & LMP_INQ_TX_PWR) 533d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL); 534d5859e22SJohan Hedberg } 535d5859e22SJohan Hedberg 536a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) 537a9de9248SMarcel Holtmann { 538a9de9248SMarcel Holtmann struct hci_rp_read_local_version *rp = (void *) skb->data; 5391143e5a6SMarcel Holtmann 540a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 5411143e5a6SMarcel Holtmann 542a9de9248SMarcel Holtmann if (rp->status) 543a9de9248SMarcel Holtmann return; 5441143e5a6SMarcel Holtmann 545a9de9248SMarcel Holtmann hdev->hci_ver = rp->hci_ver; 546e4e8e37cSMarcel Holtmann hdev->hci_rev = __le16_to_cpu(rp->hci_rev); 547d5859e22SJohan Hedberg hdev->lmp_ver = rp->lmp_ver; 548e4e8e37cSMarcel Holtmann hdev->manufacturer = __le16_to_cpu(rp->manufacturer); 549d5859e22SJohan Hedberg hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); 5501da177e4SLinus Torvalds 551a9de9248SMarcel Holtmann BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name, 552a9de9248SMarcel Holtmann hdev->manufacturer, 553a9de9248SMarcel Holtmann hdev->hci_ver, hdev->hci_rev); 554d5859e22SJohan Hedberg 555d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags)) 556d5859e22SJohan Hedberg hci_setup(hdev); 557d5859e22SJohan Hedberg } 558d5859e22SJohan Hedberg 559d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev) 560d5859e22SJohan Hedberg { 561d5859e22SJohan Hedberg u16 link_policy = 0; 562d5859e22SJohan Hedberg 563d5859e22SJohan Hedberg if (hdev->features[0] & LMP_RSWITCH) 564d5859e22SJohan Hedberg link_policy |= HCI_LP_RSWITCH; 565d5859e22SJohan Hedberg if (hdev->features[0] & LMP_HOLD) 566d5859e22SJohan Hedberg link_policy |= HCI_LP_HOLD; 567d5859e22SJohan Hedberg if (hdev->features[0] & LMP_SNIFF) 568d5859e22SJohan Hedberg link_policy |= HCI_LP_SNIFF; 569d5859e22SJohan Hedberg if (hdev->features[1] & LMP_PARK) 570d5859e22SJohan Hedberg link_policy |= HCI_LP_PARK; 571d5859e22SJohan Hedberg 572d5859e22SJohan Hedberg link_policy = cpu_to_le16(link_policy); 573d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, 574d5859e22SJohan Hedberg sizeof(link_policy), &link_policy); 5751da177e4SLinus Torvalds } 5761da177e4SLinus Torvalds 577a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb) 578a9de9248SMarcel Holtmann { 579a9de9248SMarcel Holtmann struct hci_rp_read_local_commands *rp = (void *) skb->data; 580a9de9248SMarcel Holtmann 581a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 582a9de9248SMarcel Holtmann 583a9de9248SMarcel Holtmann if (rp->status) 584d5859e22SJohan Hedberg goto done; 585a9de9248SMarcel Holtmann 586a9de9248SMarcel Holtmann memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); 587d5859e22SJohan Hedberg 588d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10)) 589d5859e22SJohan Hedberg hci_setup_link_policy(hdev); 590d5859e22SJohan Hedberg 591d5859e22SJohan Hedberg done: 592d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status); 593a9de9248SMarcel Holtmann } 594a9de9248SMarcel Holtmann 595a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb) 596a9de9248SMarcel Holtmann { 597a9de9248SMarcel Holtmann struct hci_rp_read_local_features *rp = (void *) skb->data; 598a9de9248SMarcel Holtmann 599a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 600a9de9248SMarcel Holtmann 601a9de9248SMarcel Holtmann if (rp->status) 602a9de9248SMarcel Holtmann return; 603a9de9248SMarcel Holtmann 604a9de9248SMarcel Holtmann memcpy(hdev->features, rp->features, 8); 6051da177e4SLinus Torvalds 6061da177e4SLinus Torvalds /* Adjust default settings according to features 6071da177e4SLinus Torvalds * supported by device. */ 608a9de9248SMarcel Holtmann 6091da177e4SLinus Torvalds if (hdev->features[0] & LMP_3SLOT) 6101da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM3 | HCI_DH3); 6111da177e4SLinus Torvalds 6121da177e4SLinus Torvalds if (hdev->features[0] & LMP_5SLOT) 6131da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM5 | HCI_DH5); 6141da177e4SLinus Torvalds 6155b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV2) { 6161da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV2); 6175b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV2); 6185b7f9909SMarcel Holtmann } 6191da177e4SLinus Torvalds 6205b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV3) { 6211da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV3); 6225b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV3); 6235b7f9909SMarcel Holtmann } 6245b7f9909SMarcel Holtmann 6255b7f9909SMarcel Holtmann if (hdev->features[3] & LMP_ESCO) 6265b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV3); 6275b7f9909SMarcel Holtmann 6285b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV4) 6295b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV4); 6305b7f9909SMarcel Holtmann 6315b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV5) 6325b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV5); 6331da177e4SLinus Torvalds 634efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_2M) 635efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV3); 636efc7688bSMarcel Holtmann 637efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_3M) 638efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_3EV3); 639efc7688bSMarcel Holtmann 640efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_3S_ESCO) 641efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); 642efc7688bSMarcel Holtmann 643a9de9248SMarcel Holtmann BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, 644a9de9248SMarcel Holtmann hdev->features[0], hdev->features[1], 645a9de9248SMarcel Holtmann hdev->features[2], hdev->features[3], 646a9de9248SMarcel Holtmann hdev->features[4], hdev->features[5], 647a9de9248SMarcel Holtmann hdev->features[6], hdev->features[7]); 6481da177e4SLinus Torvalds } 6491da177e4SLinus Torvalds 650a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 651a9de9248SMarcel Holtmann { 652a9de9248SMarcel Holtmann struct hci_rp_read_buffer_size *rp = (void *) skb->data; 653a9de9248SMarcel Holtmann 654a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 655a9de9248SMarcel Holtmann 656a9de9248SMarcel Holtmann if (rp->status) 657a9de9248SMarcel Holtmann return; 658a9de9248SMarcel Holtmann 659a9de9248SMarcel Holtmann hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); 660a9de9248SMarcel Holtmann hdev->sco_mtu = rp->sco_mtu; 661a9de9248SMarcel Holtmann hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); 662a9de9248SMarcel Holtmann hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); 663da1f5198SMarcel Holtmann 664da1f5198SMarcel Holtmann if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { 665da1f5198SMarcel Holtmann hdev->sco_mtu = 64; 666da1f5198SMarcel Holtmann hdev->sco_pkts = 8; 667da1f5198SMarcel Holtmann } 668da1f5198SMarcel Holtmann 669da1f5198SMarcel Holtmann hdev->acl_cnt = hdev->acl_pkts; 670da1f5198SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 6711da177e4SLinus Torvalds 672a9de9248SMarcel Holtmann BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, 673a9de9248SMarcel Holtmann hdev->acl_mtu, hdev->acl_pkts, 674a9de9248SMarcel Holtmann hdev->sco_mtu, hdev->sco_pkts); 6751da177e4SLinus Torvalds } 6761da177e4SLinus Torvalds 677a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) 678a9de9248SMarcel Holtmann { 679a9de9248SMarcel Holtmann struct hci_rp_read_bd_addr *rp = (void *) skb->data; 6801da177e4SLinus Torvalds 681a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 682a9de9248SMarcel Holtmann 683a9de9248SMarcel Holtmann if (!rp->status) 684a9de9248SMarcel Holtmann bacpy(&hdev->bdaddr, &rp->bdaddr); 685a9de9248SMarcel Holtmann 68623bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status); 68723bb5763SJohan Hedberg } 68823bb5763SJohan Hedberg 68923bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb) 69023bb5763SJohan Hedberg { 69123bb5763SJohan Hedberg __u8 status = *((__u8 *) skb->data); 69223bb5763SJohan Hedberg 69323bb5763SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 69423bb5763SJohan Hedberg 69523bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status); 6961da177e4SLinus Torvalds } 6971da177e4SLinus Torvalds 698b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, 699b0916ea0SJohan Hedberg struct sk_buff *skb) 700b0916ea0SJohan Hedberg { 701b0916ea0SJohan Hedberg __u8 status = *((__u8 *) skb->data); 702b0916ea0SJohan Hedberg 703b0916ea0SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 704b0916ea0SJohan Hedberg 705b0916ea0SJohan Hedberg hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status); 706b0916ea0SJohan Hedberg } 707b0916ea0SJohan Hedberg 708d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb) 709d5859e22SJohan Hedberg { 710d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 711d5859e22SJohan Hedberg 712d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 713d5859e22SJohan Hedberg 714d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status); 715d5859e22SJohan Hedberg } 716d5859e22SJohan Hedberg 717d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev, 718d5859e22SJohan Hedberg struct sk_buff *skb) 719d5859e22SJohan Hedberg { 720d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 721d5859e22SJohan Hedberg 722d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 723d5859e22SJohan Hedberg 724d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status); 725d5859e22SJohan Hedberg } 726d5859e22SJohan Hedberg 727d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, 728d5859e22SJohan Hedberg struct sk_buff *skb) 729d5859e22SJohan Hedberg { 730d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 731d5859e22SJohan Hedberg 732d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 733d5859e22SJohan Hedberg 734d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status); 735d5859e22SJohan Hedberg } 736d5859e22SJohan Hedberg 737d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb) 738d5859e22SJohan Hedberg { 739d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 740d5859e22SJohan Hedberg 741d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 742d5859e22SJohan Hedberg 743d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status); 744d5859e22SJohan Hedberg } 745d5859e22SJohan Hedberg 746a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 747a9de9248SMarcel Holtmann { 748a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 749a9de9248SMarcel Holtmann 750a9de9248SMarcel Holtmann if (status) { 75123bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 752a9de9248SMarcel Holtmann 753a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 754a9de9248SMarcel Holtmann } else 755a9de9248SMarcel Holtmann set_bit(HCI_INQUIRY, &hdev->flags); 756a9de9248SMarcel Holtmann } 757a9de9248SMarcel Holtmann 7581da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 7591da177e4SLinus Torvalds { 760a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 7611da177e4SLinus Torvalds struct hci_conn *conn; 7621da177e4SLinus Torvalds 763a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 764a9de9248SMarcel Holtmann 765a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 7661da177e4SLinus Torvalds if (!cp) 7671da177e4SLinus Torvalds return; 7681da177e4SLinus Torvalds 7691da177e4SLinus Torvalds hci_dev_lock(hdev); 7701da177e4SLinus Torvalds 7711da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 7721da177e4SLinus Torvalds 773a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn); 7741da177e4SLinus Torvalds 7751da177e4SLinus Torvalds if (status) { 7761da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 7774c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 7781da177e4SLinus Torvalds conn->state = BT_CLOSED; 7791da177e4SLinus Torvalds hci_proto_connect_cfm(conn, status); 7801da177e4SLinus Torvalds hci_conn_del(conn); 7814c67bc74SMarcel Holtmann } else 7824c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 7831da177e4SLinus Torvalds } 7841da177e4SLinus Torvalds } else { 7851da177e4SLinus Torvalds if (!conn) { 7861da177e4SLinus Torvalds conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); 7871da177e4SLinus Torvalds if (conn) { 7881da177e4SLinus Torvalds conn->out = 1; 7891da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 7901da177e4SLinus Torvalds } else 791893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 7921da177e4SLinus Torvalds } 7931da177e4SLinus Torvalds } 7941da177e4SLinus Torvalds 7951da177e4SLinus Torvalds hci_dev_unlock(hdev); 7961da177e4SLinus Torvalds } 7971da177e4SLinus Torvalds 798a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 7991da177e4SLinus Torvalds { 800a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 8011da177e4SLinus Torvalds struct hci_conn *acl, *sco; 8021da177e4SLinus Torvalds __u16 handle; 8031da177e4SLinus Torvalds 804b6a0dc82SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 805b6a0dc82SMarcel Holtmann 806a9de9248SMarcel Holtmann if (!status) 807a9de9248SMarcel Holtmann return; 808a9de9248SMarcel Holtmann 809a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 8101da177e4SLinus Torvalds if (!cp) 811a9de9248SMarcel Holtmann return; 8121da177e4SLinus Torvalds 8131da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 8141da177e4SLinus Torvalds 815a9de9248SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 8161da177e4SLinus Torvalds 8171da177e4SLinus Torvalds hci_dev_lock(hdev); 8181da177e4SLinus Torvalds 8191da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 8201da177e4SLinus Torvalds if (acl && (sco = acl->link)) { 8211da177e4SLinus Torvalds sco->state = BT_CLOSED; 8221da177e4SLinus Torvalds 8231da177e4SLinus Torvalds hci_proto_connect_cfm(sco, status); 8241da177e4SLinus Torvalds hci_conn_del(sco); 8251da177e4SLinus Torvalds } 8261da177e4SLinus Torvalds 8271da177e4SLinus Torvalds hci_dev_unlock(hdev); 8281da177e4SLinus Torvalds } 8291da177e4SLinus Torvalds 830f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 831f8558555SMarcel Holtmann { 832f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 833f8558555SMarcel Holtmann struct hci_conn *conn; 834f8558555SMarcel Holtmann 835f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 836f8558555SMarcel Holtmann 837f8558555SMarcel Holtmann if (!status) 838f8558555SMarcel Holtmann return; 839f8558555SMarcel Holtmann 840f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 841f8558555SMarcel Holtmann if (!cp) 842f8558555SMarcel Holtmann return; 843f8558555SMarcel Holtmann 844f8558555SMarcel Holtmann hci_dev_lock(hdev); 845f8558555SMarcel Holtmann 846f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 847f8558555SMarcel Holtmann if (conn) { 848f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 849f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 850f8558555SMarcel Holtmann hci_conn_put(conn); 851f8558555SMarcel Holtmann } 852f8558555SMarcel Holtmann } 853f8558555SMarcel Holtmann 854f8558555SMarcel Holtmann hci_dev_unlock(hdev); 855f8558555SMarcel Holtmann } 856f8558555SMarcel Holtmann 857f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 858f8558555SMarcel Holtmann { 859f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 860f8558555SMarcel Holtmann struct hci_conn *conn; 861f8558555SMarcel Holtmann 862f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 863f8558555SMarcel Holtmann 864f8558555SMarcel Holtmann if (!status) 865f8558555SMarcel Holtmann return; 866f8558555SMarcel Holtmann 867f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 868f8558555SMarcel Holtmann if (!cp) 869f8558555SMarcel Holtmann return; 870f8558555SMarcel Holtmann 871f8558555SMarcel Holtmann hci_dev_lock(hdev); 872f8558555SMarcel Holtmann 873f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 874f8558555SMarcel Holtmann if (conn) { 875f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 876f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 877f8558555SMarcel Holtmann hci_conn_put(conn); 878f8558555SMarcel Holtmann } 879f8558555SMarcel Holtmann } 880f8558555SMarcel Holtmann 881f8558555SMarcel Holtmann hci_dev_unlock(hdev); 882f8558555SMarcel Holtmann } 883f8558555SMarcel Holtmann 884127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev, 885392599b9SJohan Hedberg struct hci_conn *conn) 886392599b9SJohan Hedberg { 887392599b9SJohan Hedberg if (conn->state != BT_CONFIG || !conn->out) 888392599b9SJohan Hedberg return 0; 889392599b9SJohan Hedberg 890765c2a96SJohan Hedberg if (conn->pending_sec_level == BT_SECURITY_SDP) 891392599b9SJohan Hedberg return 0; 892392599b9SJohan Hedberg 893392599b9SJohan Hedberg /* Only request authentication for SSP connections or non-SSP 894392599b9SJohan Hedberg * devices with sec_level HIGH */ 895392599b9SJohan Hedberg if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) && 896765c2a96SJohan Hedberg conn->pending_sec_level != BT_SECURITY_HIGH) 897392599b9SJohan Hedberg return 0; 898392599b9SJohan Hedberg 899392599b9SJohan Hedberg return 1; 900392599b9SJohan Hedberg } 901392599b9SJohan Hedberg 902a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 9031da177e4SLinus Torvalds { 904127178d2SJohan Hedberg struct hci_cp_remote_name_req *cp; 905127178d2SJohan Hedberg struct hci_conn *conn; 906127178d2SJohan Hedberg 907a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 908127178d2SJohan Hedberg 909127178d2SJohan Hedberg /* If successful wait for the name req complete event before 910127178d2SJohan Hedberg * checking for the need to do authentication */ 911127178d2SJohan Hedberg if (!status) 912127178d2SJohan Hedberg return; 913127178d2SJohan Hedberg 914127178d2SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); 915127178d2SJohan Hedberg if (!cp) 916127178d2SJohan Hedberg return; 917127178d2SJohan Hedberg 918127178d2SJohan Hedberg hci_dev_lock(hdev); 919127178d2SJohan Hedberg 920127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 921127178d2SJohan Hedberg if (conn && hci_outgoing_auth_needed(hdev, conn)) { 922127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 923127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 924127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 925127178d2SJohan Hedberg } 926127178d2SJohan Hedberg 927127178d2SJohan Hedberg hci_dev_unlock(hdev); 928a9de9248SMarcel Holtmann } 9291da177e4SLinus Torvalds 930769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 931769be974SMarcel Holtmann { 932769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 933769be974SMarcel Holtmann struct hci_conn *conn; 934769be974SMarcel Holtmann 935769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 936769be974SMarcel Holtmann 937769be974SMarcel Holtmann if (!status) 938769be974SMarcel Holtmann return; 939769be974SMarcel Holtmann 940769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 941769be974SMarcel Holtmann if (!cp) 942769be974SMarcel Holtmann return; 943769be974SMarcel Holtmann 944769be974SMarcel Holtmann hci_dev_lock(hdev); 945769be974SMarcel Holtmann 946769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 947769be974SMarcel Holtmann if (conn) { 948769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 949769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 950769be974SMarcel Holtmann hci_conn_put(conn); 951769be974SMarcel Holtmann } 952769be974SMarcel Holtmann } 953769be974SMarcel Holtmann 954769be974SMarcel Holtmann hci_dev_unlock(hdev); 955769be974SMarcel Holtmann } 956769be974SMarcel Holtmann 957769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 958769be974SMarcel Holtmann { 959769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features *cp; 960769be974SMarcel Holtmann struct hci_conn *conn; 961769be974SMarcel Holtmann 962769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 963769be974SMarcel Holtmann 964769be974SMarcel Holtmann if (!status) 965769be974SMarcel Holtmann return; 966769be974SMarcel Holtmann 967769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 968769be974SMarcel Holtmann if (!cp) 969769be974SMarcel Holtmann return; 970769be974SMarcel Holtmann 971769be974SMarcel Holtmann hci_dev_lock(hdev); 972769be974SMarcel Holtmann 973769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 974769be974SMarcel Holtmann if (conn) { 975769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 976769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 977769be974SMarcel Holtmann hci_conn_put(conn); 978769be974SMarcel Holtmann } 979769be974SMarcel Holtmann } 980769be974SMarcel Holtmann 981769be974SMarcel Holtmann hci_dev_unlock(hdev); 982769be974SMarcel Holtmann } 983769be974SMarcel Holtmann 984a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 985a9de9248SMarcel Holtmann { 986b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 987b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 988b6a0dc82SMarcel Holtmann __u16 handle; 989b6a0dc82SMarcel Holtmann 990a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 991b6a0dc82SMarcel Holtmann 992b6a0dc82SMarcel Holtmann if (!status) 993b6a0dc82SMarcel Holtmann return; 994b6a0dc82SMarcel Holtmann 995b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 996b6a0dc82SMarcel Holtmann if (!cp) 997b6a0dc82SMarcel Holtmann return; 998b6a0dc82SMarcel Holtmann 999b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 1000b6a0dc82SMarcel Holtmann 1001b6a0dc82SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 1002b6a0dc82SMarcel Holtmann 1003b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 1004b6a0dc82SMarcel Holtmann 1005b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 1006b6a0dc82SMarcel Holtmann if (acl && (sco = acl->link)) { 1007b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 1008b6a0dc82SMarcel Holtmann 1009b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(sco, status); 1010b6a0dc82SMarcel Holtmann hci_conn_del(sco); 1011b6a0dc82SMarcel Holtmann } 1012b6a0dc82SMarcel Holtmann 1013b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 1014a9de9248SMarcel Holtmann } 1015a9de9248SMarcel Holtmann 1016a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 1017a9de9248SMarcel Holtmann { 1018a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 101904837f64SMarcel Holtmann struct hci_conn *conn; 102004837f64SMarcel Holtmann 1021a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1022a9de9248SMarcel Holtmann 1023a9de9248SMarcel Holtmann if (!status) 1024a9de9248SMarcel Holtmann return; 1025a9de9248SMarcel Holtmann 1026a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 102704837f64SMarcel Holtmann if (!cp) 1028a9de9248SMarcel Holtmann return; 102904837f64SMarcel Holtmann 103004837f64SMarcel Holtmann hci_dev_lock(hdev); 103104837f64SMarcel Holtmann 103204837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1033e73439d8SMarcel Holtmann if (conn) { 103404837f64SMarcel Holtmann clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); 103504837f64SMarcel Holtmann 1036e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 1037e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1038e73439d8SMarcel Holtmann } 1039e73439d8SMarcel Holtmann 104004837f64SMarcel Holtmann hci_dev_unlock(hdev); 104104837f64SMarcel Holtmann } 104204837f64SMarcel Holtmann 1043a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 1044a9de9248SMarcel Holtmann { 1045a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 104604837f64SMarcel Holtmann struct hci_conn *conn; 104704837f64SMarcel Holtmann 1048a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1049a9de9248SMarcel Holtmann 1050a9de9248SMarcel Holtmann if (!status) 1051a9de9248SMarcel Holtmann return; 1052a9de9248SMarcel Holtmann 1053a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 105404837f64SMarcel Holtmann if (!cp) 1055a9de9248SMarcel Holtmann return; 105604837f64SMarcel Holtmann 105704837f64SMarcel Holtmann hci_dev_lock(hdev); 105804837f64SMarcel Holtmann 105904837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1060e73439d8SMarcel Holtmann if (conn) { 106104837f64SMarcel Holtmann clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); 106204837f64SMarcel Holtmann 1063e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 1064e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1065e73439d8SMarcel Holtmann } 1066e73439d8SMarcel Holtmann 106704837f64SMarcel Holtmann hci_dev_unlock(hdev); 106804837f64SMarcel Holtmann } 106904837f64SMarcel Holtmann 10701da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 10711da177e4SLinus Torvalds { 10721da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 10731da177e4SLinus Torvalds 10741da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, status); 10751da177e4SLinus Torvalds 10761da177e4SLinus Torvalds clear_bit(HCI_INQUIRY, &hdev->flags); 1077a9de9248SMarcel Holtmann 107823bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 10796bd57416SMarcel Holtmann 1080a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 10811da177e4SLinus Torvalds } 10821da177e4SLinus Torvalds 10831da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 10841da177e4SLinus Torvalds { 108545bb4bf0SMarcel Holtmann struct inquiry_data data; 1086a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 10871da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 10881da177e4SLinus Torvalds 10891da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 10901da177e4SLinus Torvalds 109145bb4bf0SMarcel Holtmann if (!num_rsp) 109245bb4bf0SMarcel Holtmann return; 109345bb4bf0SMarcel Holtmann 10941da177e4SLinus Torvalds hci_dev_lock(hdev); 109545bb4bf0SMarcel Holtmann 10961da177e4SLinus Torvalds for (; num_rsp; num_rsp--) { 10971da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 10981da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 10991da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 11001da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 11011da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 11021da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 11031da177e4SLinus Torvalds data.rssi = 0x00; 110441a96212SMarcel Holtmann data.ssp_mode = 0x00; 11051da177e4SLinus Torvalds info++; 11061da177e4SLinus Torvalds hci_inquiry_cache_update(hdev, &data); 11071da177e4SLinus Torvalds } 110845bb4bf0SMarcel Holtmann 11091da177e4SLinus Torvalds hci_dev_unlock(hdev); 11101da177e4SLinus Torvalds } 11111da177e4SLinus Torvalds 1112a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 11131da177e4SLinus Torvalds { 1114a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 1115a9de9248SMarcel Holtmann struct hci_conn *conn; 11161da177e4SLinus Torvalds 1117a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 111845bb4bf0SMarcel Holtmann 11191da177e4SLinus Torvalds hci_dev_lock(hdev); 112045bb4bf0SMarcel Holtmann 1121a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 11229499237aSMarcel Holtmann if (!conn) { 11239499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 11249499237aSMarcel Holtmann goto unlock; 11259499237aSMarcel Holtmann 11269499237aSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 1127a9de9248SMarcel Holtmann if (!conn) 1128a9de9248SMarcel Holtmann goto unlock; 112945bb4bf0SMarcel Holtmann 11309499237aSMarcel Holtmann conn->type = SCO_LINK; 11319499237aSMarcel Holtmann } 11329499237aSMarcel Holtmann 1133a9de9248SMarcel Holtmann if (!ev->status) { 1134a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 1135769be974SMarcel Holtmann 1136769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 1137769be974SMarcel Holtmann conn->state = BT_CONFIG; 1138769be974SMarcel Holtmann hci_conn_hold(conn); 1139052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1140f7520543SJohan Hedberg mgmt_connected(hdev->id, &ev->bdaddr); 1141769be974SMarcel Holtmann } else 1142a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 1143a9de9248SMarcel Holtmann 11449eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 11457d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 11467d0db0a3SMarcel Holtmann 1147a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 1148a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1149a9de9248SMarcel Holtmann 1150a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 1151a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1152a9de9248SMarcel Holtmann 1153a9de9248SMarcel Holtmann /* Get remote features */ 1154a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 1155a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 1156a9de9248SMarcel Holtmann cp.handle = ev->handle; 1157769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 1158769be974SMarcel Holtmann sizeof(cp), &cp); 115945bb4bf0SMarcel Holtmann } 1160a9de9248SMarcel Holtmann 1161a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 1162a8746417SMarcel Holtmann if (!conn->out && hdev->hci_ver < 3) { 1163a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 1164a9de9248SMarcel Holtmann cp.handle = ev->handle; 1165a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1166a8746417SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, 1167a8746417SMarcel Holtmann sizeof(cp), &cp); 1168a9de9248SMarcel Holtmann } 1169a9de9248SMarcel Holtmann } else 1170a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 117145bb4bf0SMarcel Holtmann 1172e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 1173e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 117445bb4bf0SMarcel Holtmann 1175769be974SMarcel Holtmann if (ev->status) { 1176a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1177a9de9248SMarcel Holtmann hci_conn_del(conn); 1178c89b6e6bSMarcel Holtmann } else if (ev->link_type != ACL_LINK) 1179c89b6e6bSMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1180a9de9248SMarcel Holtmann 1181a9de9248SMarcel Holtmann unlock: 11821da177e4SLinus Torvalds hci_dev_unlock(hdev); 1183a9de9248SMarcel Holtmann 1184a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 11851da177e4SLinus Torvalds } 11861da177e4SLinus Torvalds 11871da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 11881da177e4SLinus Torvalds { 1189a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 11901da177e4SLinus Torvalds int mask = hdev->link_mode; 11911da177e4SLinus Torvalds 1192a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s type 0x%x", hdev->name, 11931da177e4SLinus Torvalds batostr(&ev->bdaddr), ev->link_type); 11941da177e4SLinus Torvalds 11951da177e4SLinus Torvalds mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); 11961da177e4SLinus Torvalds 1197f0358568SJohan Hedberg if ((mask & HCI_LM_ACCEPT) && !hci_blacklist_lookup(hdev, &ev->bdaddr)) { 11981da177e4SLinus Torvalds /* Connection accepted */ 1199c7bdd502SMarcel Holtmann struct inquiry_entry *ie; 12001da177e4SLinus Torvalds struct hci_conn *conn; 12011da177e4SLinus Torvalds 12021da177e4SLinus Torvalds hci_dev_lock(hdev); 1203b6a0dc82SMarcel Holtmann 1204cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 1205cc11b9c1SAndrei Emeltchenko if (ie) 1206c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 1207c7bdd502SMarcel Holtmann 12081da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 12091da177e4SLinus Torvalds if (!conn) { 1210cc11b9c1SAndrei Emeltchenko conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); 1211cc11b9c1SAndrei Emeltchenko if (!conn) { 1212893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 12131da177e4SLinus Torvalds hci_dev_unlock(hdev); 12141da177e4SLinus Torvalds return; 12151da177e4SLinus Torvalds } 12161da177e4SLinus Torvalds } 1217b6a0dc82SMarcel Holtmann 12181da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 12191da177e4SLinus Torvalds conn->state = BT_CONNECT; 1220b6a0dc82SMarcel Holtmann 12211da177e4SLinus Torvalds hci_dev_unlock(hdev); 12221da177e4SLinus Torvalds 1223b6a0dc82SMarcel Holtmann if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) { 1224b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 1225b6a0dc82SMarcel Holtmann 12261da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 12271da177e4SLinus Torvalds 12281da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 12291da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 12301da177e4SLinus Torvalds else 12311da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 12321da177e4SLinus Torvalds 1233b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, 1234b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1235b6a0dc82SMarcel Holtmann } else { 1236b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 1237b6a0dc82SMarcel Holtmann 1238b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 1239a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1240b6a0dc82SMarcel Holtmann 1241b6a0dc82SMarcel Holtmann cp.tx_bandwidth = cpu_to_le32(0x00001f40); 1242b6a0dc82SMarcel Holtmann cp.rx_bandwidth = cpu_to_le32(0x00001f40); 1243b6a0dc82SMarcel Holtmann cp.max_latency = cpu_to_le16(0xffff); 1244b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 1245b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 1246b6a0dc82SMarcel Holtmann 1247b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 1248b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1249b6a0dc82SMarcel Holtmann } 12501da177e4SLinus Torvalds } else { 12511da177e4SLinus Torvalds /* Connection rejected */ 12521da177e4SLinus Torvalds struct hci_cp_reject_conn_req cp; 12531da177e4SLinus Torvalds 12541da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 12551da177e4SLinus Torvalds cp.reason = 0x0f; 1256a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 12571da177e4SLinus Torvalds } 12581da177e4SLinus Torvalds } 12591da177e4SLinus Torvalds 12601da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 12611da177e4SLinus Torvalds { 1262a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 126304837f64SMarcel Holtmann struct hci_conn *conn; 12641da177e4SLinus Torvalds 12651da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 12661da177e4SLinus Torvalds 12678962ee74SJohan Hedberg if (ev->status) { 12688962ee74SJohan Hedberg mgmt_disconnect_failed(hdev->id); 12691da177e4SLinus Torvalds return; 12708962ee74SJohan Hedberg } 12711da177e4SLinus Torvalds 12721da177e4SLinus Torvalds hci_dev_lock(hdev); 12731da177e4SLinus Torvalds 127404837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1275f7520543SJohan Hedberg if (!conn) 1276f7520543SJohan Hedberg goto unlock; 1277f7520543SJohan Hedberg 12781da177e4SLinus Torvalds conn->state = BT_CLOSED; 12797d0db0a3SMarcel Holtmann 1280f7520543SJohan Hedberg if (conn->type == ACL_LINK) 1281f7520543SJohan Hedberg mgmt_disconnected(hdev->id, &conn->dst); 1282f7520543SJohan Hedberg 12832950f21aSMarcel Holtmann hci_proto_disconn_cfm(conn, ev->reason); 12841da177e4SLinus Torvalds hci_conn_del(conn); 12851da177e4SLinus Torvalds 1286f7520543SJohan Hedberg unlock: 12871da177e4SLinus Torvalds hci_dev_unlock(hdev); 12881da177e4SLinus Torvalds } 12891da177e4SLinus Torvalds 1290a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1291a9de9248SMarcel Holtmann { 1292a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 1293a9de9248SMarcel Holtmann struct hci_conn *conn; 1294a9de9248SMarcel Holtmann 1295a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1296a9de9248SMarcel Holtmann 1297a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1298a9de9248SMarcel Holtmann 1299a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1300a9de9248SMarcel Holtmann if (conn) { 1301765c2a96SJohan Hedberg if (!ev->status) { 1302a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1303765c2a96SJohan Hedberg conn->sec_level = conn->pending_sec_level; 1304765c2a96SJohan Hedberg } else 1305da213f41SJohan Hedberg conn->sec_level = BT_SECURITY_LOW; 1306a9de9248SMarcel Holtmann 1307a9de9248SMarcel Holtmann clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); 1308a9de9248SMarcel Holtmann 1309f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1310f8558555SMarcel Holtmann if (!ev->status && hdev->ssp_mode > 0 && 1311f8558555SMarcel Holtmann conn->ssp_mode > 0) { 1312f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1313f8558555SMarcel Holtmann cp.handle = ev->handle; 1314f8558555SMarcel Holtmann cp.encrypt = 0x01; 1315f8558555SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, 1316f8558555SMarcel Holtmann sizeof(cp), &cp); 1317f8558555SMarcel Holtmann } else { 1318f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1319f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1320f8558555SMarcel Holtmann hci_conn_put(conn); 1321f8558555SMarcel Holtmann } 1322052b30b0SMarcel Holtmann } else { 1323a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 1324a9de9248SMarcel Holtmann 1325052b30b0SMarcel Holtmann hci_conn_hold(conn); 1326052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1327052b30b0SMarcel Holtmann hci_conn_put(conn); 1328052b30b0SMarcel Holtmann } 1329052b30b0SMarcel Holtmann 1330a9de9248SMarcel Holtmann if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) { 1331a9de9248SMarcel Holtmann if (!ev->status) { 1332a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1333f8558555SMarcel Holtmann cp.handle = ev->handle; 1334f8558555SMarcel Holtmann cp.encrypt = 0x01; 1335f8558555SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, 1336f8558555SMarcel Holtmann sizeof(cp), &cp); 1337a9de9248SMarcel Holtmann } else { 1338a9de9248SMarcel Holtmann clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); 1339a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 1340a9de9248SMarcel Holtmann } 1341a9de9248SMarcel Holtmann } 1342a9de9248SMarcel Holtmann } 1343a9de9248SMarcel Holtmann 1344a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1345a9de9248SMarcel Holtmann } 1346a9de9248SMarcel Holtmann 1347a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 1348a9de9248SMarcel Holtmann { 1349127178d2SJohan Hedberg struct hci_ev_remote_name *ev = (void *) skb->data; 1350127178d2SJohan Hedberg struct hci_conn *conn; 1351127178d2SJohan Hedberg 1352a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1353a9de9248SMarcel Holtmann 1354a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 1355127178d2SJohan Hedberg 1356127178d2SJohan Hedberg hci_dev_lock(hdev); 1357127178d2SJohan Hedberg 1358127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 1359127178d2SJohan Hedberg if (conn && hci_outgoing_auth_needed(hdev, conn)) { 1360127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1361127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1362127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1363127178d2SJohan Hedberg } 1364127178d2SJohan Hedberg 1365127178d2SJohan Hedberg hci_dev_unlock(hdev); 1366a9de9248SMarcel Holtmann } 1367a9de9248SMarcel Holtmann 1368a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 1369a9de9248SMarcel Holtmann { 1370a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 1371a9de9248SMarcel Holtmann struct hci_conn *conn; 1372a9de9248SMarcel Holtmann 1373a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1374a9de9248SMarcel Holtmann 1375a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1376a9de9248SMarcel Holtmann 1377a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1378a9de9248SMarcel Holtmann if (conn) { 1379a9de9248SMarcel Holtmann if (!ev->status) { 1380ae293196SMarcel Holtmann if (ev->encrypt) { 1381ae293196SMarcel Holtmann /* Encryption implies authentication */ 1382ae293196SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1383a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1384ae293196SMarcel Holtmann } else 1385a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_ENCRYPT; 1386a9de9248SMarcel Holtmann } 1387a9de9248SMarcel Holtmann 1388a9de9248SMarcel Holtmann clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); 1389a9de9248SMarcel Holtmann 1390f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1391f8558555SMarcel Holtmann if (!ev->status) 1392f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1393f8558555SMarcel Holtmann 1394f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1395f8558555SMarcel Holtmann hci_conn_put(conn); 1396f8558555SMarcel Holtmann } else 1397a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 1398a9de9248SMarcel Holtmann } 1399a9de9248SMarcel Holtmann 1400a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1401a9de9248SMarcel Holtmann } 1402a9de9248SMarcel Holtmann 1403a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1404a9de9248SMarcel Holtmann { 1405a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 1406a9de9248SMarcel Holtmann struct hci_conn *conn; 1407a9de9248SMarcel Holtmann 1408a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1409a9de9248SMarcel Holtmann 1410a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1411a9de9248SMarcel Holtmann 1412a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1413a9de9248SMarcel Holtmann if (conn) { 1414a9de9248SMarcel Holtmann if (!ev->status) 1415a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_SECURE; 1416a9de9248SMarcel Holtmann 1417a9de9248SMarcel Holtmann clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); 1418a9de9248SMarcel Holtmann 1419a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 1420a9de9248SMarcel Holtmann } 1421a9de9248SMarcel Holtmann 1422a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1423a9de9248SMarcel Holtmann } 1424a9de9248SMarcel Holtmann 1425a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 1426a9de9248SMarcel Holtmann { 1427a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 1428a9de9248SMarcel Holtmann struct hci_conn *conn; 1429a9de9248SMarcel Holtmann 1430a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1431a9de9248SMarcel Holtmann 1432a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1433a9de9248SMarcel Holtmann 1434a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1435ccd556feSJohan Hedberg if (!conn) 1436ccd556feSJohan Hedberg goto unlock; 1437ccd556feSJohan Hedberg 1438769be974SMarcel Holtmann if (!ev->status) 1439a9de9248SMarcel Holtmann memcpy(conn->features, ev->features, 8); 1440a9de9248SMarcel Holtmann 1441ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 1442ccd556feSJohan Hedberg goto unlock; 1443ccd556feSJohan Hedberg 1444ccd556feSJohan Hedberg if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { 1445769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 1446769be974SMarcel Holtmann cp.handle = ev->handle; 1447769be974SMarcel Holtmann cp.page = 0x01; 1448ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 1449769be974SMarcel Holtmann sizeof(cp), &cp); 1450392599b9SJohan Hedberg goto unlock; 1451392599b9SJohan Hedberg } 1452392599b9SJohan Hedberg 1453127178d2SJohan Hedberg if (!ev->status) { 1454127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 1455127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 1456127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 1457127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 1458127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 1459127178d2SJohan Hedberg } 1460392599b9SJohan Hedberg 1461127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 1462769be974SMarcel Holtmann conn->state = BT_CONNECTED; 1463769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1464769be974SMarcel Holtmann hci_conn_put(conn); 1465769be974SMarcel Holtmann } 1466769be974SMarcel Holtmann 1467ccd556feSJohan Hedberg unlock: 1468a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1469a9de9248SMarcel Holtmann } 1470a9de9248SMarcel Holtmann 1471a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) 1472a9de9248SMarcel Holtmann { 1473a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1474a9de9248SMarcel Holtmann } 1475a9de9248SMarcel Holtmann 1476a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1477a9de9248SMarcel Holtmann { 1478a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1479a9de9248SMarcel Holtmann } 1480a9de9248SMarcel Holtmann 1481a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1482a9de9248SMarcel Holtmann { 1483a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 1484a9de9248SMarcel Holtmann __u16 opcode; 1485a9de9248SMarcel Holtmann 1486a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 1487a9de9248SMarcel Holtmann 1488a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 1489a9de9248SMarcel Holtmann 1490a9de9248SMarcel Holtmann switch (opcode) { 1491a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 1492a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 1493a9de9248SMarcel Holtmann break; 1494a9de9248SMarcel Holtmann 1495a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 1496a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 1497a9de9248SMarcel Holtmann break; 1498a9de9248SMarcel Holtmann 1499a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 1500a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 1501a9de9248SMarcel Holtmann break; 1502a9de9248SMarcel Holtmann 1503a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 1504a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 1505a9de9248SMarcel Holtmann break; 1506a9de9248SMarcel Holtmann 1507e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 1508e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 1509e4e8e37cSMarcel Holtmann break; 1510e4e8e37cSMarcel Holtmann 1511a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 1512a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 1513a9de9248SMarcel Holtmann break; 1514a9de9248SMarcel Holtmann 1515e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 1516e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 1517e4e8e37cSMarcel Holtmann break; 1518e4e8e37cSMarcel Holtmann 1519e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 1520e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 1521e4e8e37cSMarcel Holtmann break; 1522e4e8e37cSMarcel Holtmann 1523a9de9248SMarcel Holtmann case HCI_OP_RESET: 1524a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 1525a9de9248SMarcel Holtmann break; 1526a9de9248SMarcel Holtmann 1527a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 1528a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 1529a9de9248SMarcel Holtmann break; 1530a9de9248SMarcel Holtmann 1531a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 1532a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 1533a9de9248SMarcel Holtmann break; 1534a9de9248SMarcel Holtmann 1535a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 1536a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 1537a9de9248SMarcel Holtmann break; 1538a9de9248SMarcel Holtmann 1539a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 1540a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 1541a9de9248SMarcel Holtmann break; 1542a9de9248SMarcel Holtmann 1543a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 1544a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 1545a9de9248SMarcel Holtmann break; 1546a9de9248SMarcel Holtmann 1547a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 1548a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 1549a9de9248SMarcel Holtmann break; 1550a9de9248SMarcel Holtmann 1551a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 1552a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 1553a9de9248SMarcel Holtmann break; 1554a9de9248SMarcel Holtmann 1555a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 1556a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 1557a9de9248SMarcel Holtmann break; 1558a9de9248SMarcel Holtmann 1559a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 1560a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 1561a9de9248SMarcel Holtmann break; 1562a9de9248SMarcel Holtmann 1563a9de9248SMarcel Holtmann case HCI_OP_HOST_BUFFER_SIZE: 1564a9de9248SMarcel Holtmann hci_cc_host_buffer_size(hdev, skb); 1565a9de9248SMarcel Holtmann break; 1566a9de9248SMarcel Holtmann 1567333140b5SMarcel Holtmann case HCI_OP_READ_SSP_MODE: 1568333140b5SMarcel Holtmann hci_cc_read_ssp_mode(hdev, skb); 1569333140b5SMarcel Holtmann break; 1570333140b5SMarcel Holtmann 1571333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 1572333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 1573333140b5SMarcel Holtmann break; 1574333140b5SMarcel Holtmann 1575a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 1576a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 1577a9de9248SMarcel Holtmann break; 1578a9de9248SMarcel Holtmann 1579a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 1580a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 1581a9de9248SMarcel Holtmann break; 1582a9de9248SMarcel Holtmann 1583a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 1584a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 1585a9de9248SMarcel Holtmann break; 1586a9de9248SMarcel Holtmann 1587a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 1588a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 1589a9de9248SMarcel Holtmann break; 1590a9de9248SMarcel Holtmann 1591a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 1592a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 1593a9de9248SMarcel Holtmann break; 1594a9de9248SMarcel Holtmann 159523bb5763SJohan Hedberg case HCI_OP_WRITE_CA_TIMEOUT: 159623bb5763SJohan Hedberg hci_cc_write_ca_timeout(hdev, skb); 159723bb5763SJohan Hedberg break; 159823bb5763SJohan Hedberg 1599b0916ea0SJohan Hedberg case HCI_OP_DELETE_STORED_LINK_KEY: 1600b0916ea0SJohan Hedberg hci_cc_delete_stored_link_key(hdev, skb); 1601b0916ea0SJohan Hedberg break; 1602b0916ea0SJohan Hedberg 1603d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_MASK: 1604d5859e22SJohan Hedberg hci_cc_set_event_mask(hdev, skb); 1605d5859e22SJohan Hedberg break; 1606d5859e22SJohan Hedberg 1607d5859e22SJohan Hedberg case HCI_OP_WRITE_INQUIRY_MODE: 1608d5859e22SJohan Hedberg hci_cc_write_inquiry_mode(hdev, skb); 1609d5859e22SJohan Hedberg break; 1610d5859e22SJohan Hedberg 1611d5859e22SJohan Hedberg case HCI_OP_READ_INQ_RSP_TX_POWER: 1612d5859e22SJohan Hedberg hci_cc_read_inq_rsp_tx_power(hdev, skb); 1613d5859e22SJohan Hedberg break; 1614d5859e22SJohan Hedberg 1615d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_FLT: 1616d5859e22SJohan Hedberg hci_cc_set_event_flt(hdev, skb); 1617d5859e22SJohan Hedberg break; 1618d5859e22SJohan Hedberg 1619a9de9248SMarcel Holtmann default: 1620a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 1621a9de9248SMarcel Holtmann break; 1622a9de9248SMarcel Holtmann } 1623a9de9248SMarcel Holtmann 1624a9de9248SMarcel Holtmann if (ev->ncmd) { 1625a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 1626a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 1627c78ae283SMarcel Holtmann tasklet_schedule(&hdev->cmd_task); 1628a9de9248SMarcel Holtmann } 1629a9de9248SMarcel Holtmann } 1630a9de9248SMarcel Holtmann 1631a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 1632a9de9248SMarcel Holtmann { 1633a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 1634a9de9248SMarcel Holtmann __u16 opcode; 1635a9de9248SMarcel Holtmann 1636a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 1637a9de9248SMarcel Holtmann 1638a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 1639a9de9248SMarcel Holtmann 1640a9de9248SMarcel Holtmann switch (opcode) { 1641a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 1642a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 1643a9de9248SMarcel Holtmann break; 1644a9de9248SMarcel Holtmann 1645a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 1646a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 1647a9de9248SMarcel Holtmann break; 1648a9de9248SMarcel Holtmann 1649a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 1650a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 1651a9de9248SMarcel Holtmann break; 1652a9de9248SMarcel Holtmann 1653f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 1654f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 1655f8558555SMarcel Holtmann break; 1656f8558555SMarcel Holtmann 1657f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 1658f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 1659f8558555SMarcel Holtmann break; 1660f8558555SMarcel Holtmann 1661a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 1662a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 1663a9de9248SMarcel Holtmann break; 1664a9de9248SMarcel Holtmann 1665769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 1666769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 1667769be974SMarcel Holtmann break; 1668769be974SMarcel Holtmann 1669769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 1670769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 1671769be974SMarcel Holtmann break; 1672769be974SMarcel Holtmann 1673a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 1674a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 1675a9de9248SMarcel Holtmann break; 1676a9de9248SMarcel Holtmann 1677a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 1678a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 1679a9de9248SMarcel Holtmann break; 1680a9de9248SMarcel Holtmann 1681a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 1682a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 1683a9de9248SMarcel Holtmann break; 1684a9de9248SMarcel Holtmann 16858962ee74SJohan Hedberg case HCI_OP_DISCONNECT: 16868962ee74SJohan Hedberg if (ev->status != 0) 16878962ee74SJohan Hedberg mgmt_disconnect_failed(hdev->id); 16888962ee74SJohan Hedberg break; 16898962ee74SJohan Hedberg 1690a9de9248SMarcel Holtmann default: 1691a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 1692a9de9248SMarcel Holtmann break; 1693a9de9248SMarcel Holtmann } 1694a9de9248SMarcel Holtmann 1695a9de9248SMarcel Holtmann if (ev->ncmd) { 1696a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 1697a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 1698c78ae283SMarcel Holtmann tasklet_schedule(&hdev->cmd_task); 1699a9de9248SMarcel Holtmann } 1700a9de9248SMarcel Holtmann } 1701a9de9248SMarcel Holtmann 1702a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 1703a9de9248SMarcel Holtmann { 1704a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 1705a9de9248SMarcel Holtmann struct hci_conn *conn; 1706a9de9248SMarcel Holtmann 1707a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1708a9de9248SMarcel Holtmann 1709a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1710a9de9248SMarcel Holtmann 1711a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 1712a9de9248SMarcel Holtmann if (conn) { 1713a9de9248SMarcel Holtmann if (!ev->status) { 1714a9de9248SMarcel Holtmann if (ev->role) 1715a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_MASTER; 1716a9de9248SMarcel Holtmann else 1717a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_MASTER; 1718a9de9248SMarcel Holtmann } 1719a9de9248SMarcel Holtmann 1720a9de9248SMarcel Holtmann clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend); 1721a9de9248SMarcel Holtmann 1722a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 1723a9de9248SMarcel Holtmann } 1724a9de9248SMarcel Holtmann 1725a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1726a9de9248SMarcel Holtmann } 1727a9de9248SMarcel Holtmann 17281da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 17291da177e4SLinus Torvalds { 1730a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 17311ebb9252SMarcel Holtmann __le16 *ptr; 17321da177e4SLinus Torvalds int i; 17331da177e4SLinus Torvalds 17341da177e4SLinus Torvalds skb_pull(skb, sizeof(*ev)); 17351da177e4SLinus Torvalds 17361da177e4SLinus Torvalds BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 17371da177e4SLinus Torvalds 17381da177e4SLinus Torvalds if (skb->len < ev->num_hndl * 4) { 17391da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 17401da177e4SLinus Torvalds return; 17411da177e4SLinus Torvalds } 17421da177e4SLinus Torvalds 17431da177e4SLinus Torvalds tasklet_disable(&hdev->tx_task); 17441da177e4SLinus Torvalds 17451ebb9252SMarcel Holtmann for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) { 17461da177e4SLinus Torvalds struct hci_conn *conn; 17471da177e4SLinus Torvalds __u16 handle, count; 17481da177e4SLinus Torvalds 174983985319SHarvey Harrison handle = get_unaligned_le16(ptr++); 175083985319SHarvey Harrison count = get_unaligned_le16(ptr++); 17511da177e4SLinus Torvalds 17521da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 17531da177e4SLinus Torvalds if (conn) { 17541da177e4SLinus Torvalds conn->sent -= count; 17551da177e4SLinus Torvalds 17565b7f9909SMarcel Holtmann if (conn->type == ACL_LINK) { 175770f23020SAndrei Emeltchenko hdev->acl_cnt += count; 175870f23020SAndrei Emeltchenko if (hdev->acl_cnt > hdev->acl_pkts) 17591da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 17605b7f9909SMarcel Holtmann } else { 176170f23020SAndrei Emeltchenko hdev->sco_cnt += count; 176270f23020SAndrei Emeltchenko if (hdev->sco_cnt > hdev->sco_pkts) 17635b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 17641da177e4SLinus Torvalds } 17651da177e4SLinus Torvalds } 17661da177e4SLinus Torvalds } 1767a9de9248SMarcel Holtmann 1768c78ae283SMarcel Holtmann tasklet_schedule(&hdev->tx_task); 17691da177e4SLinus Torvalds 17701da177e4SLinus Torvalds tasklet_enable(&hdev->tx_task); 17711da177e4SLinus Torvalds } 17721da177e4SLinus Torvalds 177304837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 17741da177e4SLinus Torvalds { 1775a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 177604837f64SMarcel Holtmann struct hci_conn *conn; 17771da177e4SLinus Torvalds 17781da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 17791da177e4SLinus Torvalds 17801da177e4SLinus Torvalds hci_dev_lock(hdev); 17811da177e4SLinus Torvalds 178204837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 178304837f64SMarcel Holtmann if (conn) { 178404837f64SMarcel Holtmann conn->mode = ev->mode; 178504837f64SMarcel Holtmann conn->interval = __le16_to_cpu(ev->interval); 178604837f64SMarcel Holtmann 178704837f64SMarcel Holtmann if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) { 178804837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 178904837f64SMarcel Holtmann conn->power_save = 1; 179004837f64SMarcel Holtmann else 179104837f64SMarcel Holtmann conn->power_save = 0; 179204837f64SMarcel Holtmann } 1793e73439d8SMarcel Holtmann 1794e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 1795e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 179604837f64SMarcel Holtmann } 179704837f64SMarcel Holtmann 179804837f64SMarcel Holtmann hci_dev_unlock(hdev); 179904837f64SMarcel Holtmann } 180004837f64SMarcel Holtmann 18011da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 18021da177e4SLinus Torvalds { 1803052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 1804052b30b0SMarcel Holtmann struct hci_conn *conn; 1805052b30b0SMarcel Holtmann 1806a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1807052b30b0SMarcel Holtmann 1808052b30b0SMarcel Holtmann hci_dev_lock(hdev); 1809052b30b0SMarcel Holtmann 1810052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 18113d7a9d1cSMarcel Holtmann if (conn && conn->state == BT_CONNECTED) { 1812052b30b0SMarcel Holtmann hci_conn_hold(conn); 1813052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 1814052b30b0SMarcel Holtmann hci_conn_put(conn); 1815052b30b0SMarcel Holtmann } 1816052b30b0SMarcel Holtmann 181703b555e1SJohan Hedberg if (!test_bit(HCI_PAIRABLE, &hdev->flags)) 181803b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 181903b555e1SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 182003b555e1SJohan Hedberg 1821052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 18221da177e4SLinus Torvalds } 18231da177e4SLinus Torvalds 18241da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 18251da177e4SLinus Torvalds { 182655ed8ca1SJohan Hedberg struct hci_ev_link_key_req *ev = (void *) skb->data; 182755ed8ca1SJohan Hedberg struct hci_cp_link_key_reply cp; 182855ed8ca1SJohan Hedberg struct hci_conn *conn; 182955ed8ca1SJohan Hedberg struct link_key *key; 183055ed8ca1SJohan Hedberg 1831a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 183255ed8ca1SJohan Hedberg 183355ed8ca1SJohan Hedberg if (!test_bit(HCI_LINK_KEYS, &hdev->flags)) 183455ed8ca1SJohan Hedberg return; 183555ed8ca1SJohan Hedberg 183655ed8ca1SJohan Hedberg hci_dev_lock(hdev); 183755ed8ca1SJohan Hedberg 183855ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, &ev->bdaddr); 183955ed8ca1SJohan Hedberg if (!key) { 184055ed8ca1SJohan Hedberg BT_DBG("%s link key not found for %s", hdev->name, 184155ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 184255ed8ca1SJohan Hedberg goto not_found; 184355ed8ca1SJohan Hedberg } 184455ed8ca1SJohan Hedberg 184555ed8ca1SJohan Hedberg BT_DBG("%s found key type %u for %s", hdev->name, key->type, 184655ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 184755ed8ca1SJohan Hedberg 184855ed8ca1SJohan Hedberg if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) && key->type == 0x03) { 184955ed8ca1SJohan Hedberg BT_DBG("%s ignoring debug key", hdev->name); 185055ed8ca1SJohan Hedberg goto not_found; 185155ed8ca1SJohan Hedberg } 185255ed8ca1SJohan Hedberg 185355ed8ca1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 185455ed8ca1SJohan Hedberg 185555ed8ca1SJohan Hedberg if (key->type == 0x04 && conn && conn->auth_type != 0xff && 185655ed8ca1SJohan Hedberg (conn->auth_type & 0x01)) { 185755ed8ca1SJohan Hedberg BT_DBG("%s ignoring unauthenticated key", hdev->name); 185855ed8ca1SJohan Hedberg goto not_found; 185955ed8ca1SJohan Hedberg } 186055ed8ca1SJohan Hedberg 186155ed8ca1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 186255ed8ca1SJohan Hedberg memcpy(cp.link_key, key->val, 16); 186355ed8ca1SJohan Hedberg 186455ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 186555ed8ca1SJohan Hedberg 186655ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 186755ed8ca1SJohan Hedberg 186855ed8ca1SJohan Hedberg return; 186955ed8ca1SJohan Hedberg 187055ed8ca1SJohan Hedberg not_found: 187155ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 187255ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 18731da177e4SLinus Torvalds } 18741da177e4SLinus Torvalds 18751da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 18761da177e4SLinus Torvalds { 1877052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 1878052b30b0SMarcel Holtmann struct hci_conn *conn; 187955ed8ca1SJohan Hedberg u8 pin_len = 0; 1880052b30b0SMarcel Holtmann 1881a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1882052b30b0SMarcel Holtmann 1883052b30b0SMarcel Holtmann hci_dev_lock(hdev); 1884052b30b0SMarcel Holtmann 1885052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 1886052b30b0SMarcel Holtmann if (conn) { 1887052b30b0SMarcel Holtmann hci_conn_hold(conn); 1888052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1889052b30b0SMarcel Holtmann hci_conn_put(conn); 1890052b30b0SMarcel Holtmann } 1891052b30b0SMarcel Holtmann 189255ed8ca1SJohan Hedberg if (test_bit(HCI_LINK_KEYS, &hdev->flags)) 189355ed8ca1SJohan Hedberg hci_add_link_key(hdev, 1, &ev->bdaddr, ev->link_key, 189455ed8ca1SJohan Hedberg ev->key_type, pin_len); 189555ed8ca1SJohan Hedberg 1896052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 18971da177e4SLinus Torvalds } 18981da177e4SLinus Torvalds 189904837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 190004837f64SMarcel Holtmann { 1901a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 190204837f64SMarcel Holtmann struct hci_conn *conn; 190304837f64SMarcel Holtmann 190404837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 190504837f64SMarcel Holtmann 190604837f64SMarcel Holtmann hci_dev_lock(hdev); 190704837f64SMarcel Holtmann 190804837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 19091da177e4SLinus Torvalds if (conn && !ev->status) { 19101da177e4SLinus Torvalds struct inquiry_entry *ie; 19111da177e4SLinus Torvalds 1912cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 1913cc11b9c1SAndrei Emeltchenko if (ie) { 19141da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 19151da177e4SLinus Torvalds ie->timestamp = jiffies; 19161da177e4SLinus Torvalds } 19171da177e4SLinus Torvalds } 19181da177e4SLinus Torvalds 19191da177e4SLinus Torvalds hci_dev_unlock(hdev); 19201da177e4SLinus Torvalds } 19211da177e4SLinus Torvalds 1922a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 1923a8746417SMarcel Holtmann { 1924a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 1925a8746417SMarcel Holtmann struct hci_conn *conn; 1926a8746417SMarcel Holtmann 1927a8746417SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1928a8746417SMarcel Holtmann 1929a8746417SMarcel Holtmann hci_dev_lock(hdev); 1930a8746417SMarcel Holtmann 1931a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1932a8746417SMarcel Holtmann if (conn && !ev->status) 1933a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 1934a8746417SMarcel Holtmann 1935a8746417SMarcel Holtmann hci_dev_unlock(hdev); 1936a8746417SMarcel Holtmann } 1937a8746417SMarcel Holtmann 193885a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 193985a1e930SMarcel Holtmann { 1940a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 194185a1e930SMarcel Holtmann struct inquiry_entry *ie; 194285a1e930SMarcel Holtmann 194385a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 194485a1e930SMarcel Holtmann 194585a1e930SMarcel Holtmann hci_dev_lock(hdev); 194685a1e930SMarcel Holtmann 1947cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 1948cc11b9c1SAndrei Emeltchenko if (ie) { 194985a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 195085a1e930SMarcel Holtmann ie->timestamp = jiffies; 195185a1e930SMarcel Holtmann } 195285a1e930SMarcel Holtmann 195385a1e930SMarcel Holtmann hci_dev_unlock(hdev); 195485a1e930SMarcel Holtmann } 195585a1e930SMarcel Holtmann 1956a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb) 1957a9de9248SMarcel Holtmann { 1958a9de9248SMarcel Holtmann struct inquiry_data data; 1959a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 1960a9de9248SMarcel Holtmann 1961a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 1962a9de9248SMarcel Holtmann 1963a9de9248SMarcel Holtmann if (!num_rsp) 1964a9de9248SMarcel Holtmann return; 1965a9de9248SMarcel Holtmann 1966a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1967a9de9248SMarcel Holtmann 1968a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 1969a9de9248SMarcel Holtmann struct inquiry_info_with_rssi_and_pscan_mode *info = (void *) (skb->data + 1); 1970a9de9248SMarcel Holtmann 1971a9de9248SMarcel Holtmann for (; num_rsp; num_rsp--) { 1972a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 1973a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 1974a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 1975a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 1976a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 1977a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 1978a9de9248SMarcel Holtmann data.rssi = info->rssi; 197941a96212SMarcel Holtmann data.ssp_mode = 0x00; 1980a9de9248SMarcel Holtmann info++; 1981a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 1982a9de9248SMarcel Holtmann } 1983a9de9248SMarcel Holtmann } else { 1984a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 1985a9de9248SMarcel Holtmann 1986a9de9248SMarcel Holtmann for (; num_rsp; num_rsp--) { 1987a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 1988a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 1989a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 1990a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 1991a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 1992a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 1993a9de9248SMarcel Holtmann data.rssi = info->rssi; 199441a96212SMarcel Holtmann data.ssp_mode = 0x00; 1995a9de9248SMarcel Holtmann info++; 1996a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 1997a9de9248SMarcel Holtmann } 1998a9de9248SMarcel Holtmann } 1999a9de9248SMarcel Holtmann 2000a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2001a9de9248SMarcel Holtmann } 2002a9de9248SMarcel Holtmann 2003a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 2004a9de9248SMarcel Holtmann { 200541a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 200641a96212SMarcel Holtmann struct hci_conn *conn; 200741a96212SMarcel Holtmann 2008a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 200941a96212SMarcel Holtmann 201041a96212SMarcel Holtmann hci_dev_lock(hdev); 201141a96212SMarcel Holtmann 201241a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2013ccd556feSJohan Hedberg if (!conn) 2014ccd556feSJohan Hedberg goto unlock; 2015ccd556feSJohan Hedberg 2016769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 201741a96212SMarcel Holtmann struct inquiry_entry *ie; 201841a96212SMarcel Holtmann 2019cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2020cc11b9c1SAndrei Emeltchenko if (ie) 202141a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 202241a96212SMarcel Holtmann 202341a96212SMarcel Holtmann conn->ssp_mode = (ev->features[0] & 0x01); 202441a96212SMarcel Holtmann } 202541a96212SMarcel Holtmann 2026ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2027ccd556feSJohan Hedberg goto unlock; 2028ccd556feSJohan Hedberg 2029127178d2SJohan Hedberg if (!ev->status) { 2030127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2031127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2032127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2033127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2034127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2035127178d2SJohan Hedberg } 2036392599b9SJohan Hedberg 2037127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2038769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2039769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2040769be974SMarcel Holtmann hci_conn_put(conn); 2041769be974SMarcel Holtmann } 2042769be974SMarcel Holtmann 2043ccd556feSJohan Hedberg unlock: 204441a96212SMarcel Holtmann hci_dev_unlock(hdev); 2045a9de9248SMarcel Holtmann } 2046a9de9248SMarcel Holtmann 2047a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2048a9de9248SMarcel Holtmann { 2049b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 2050b6a0dc82SMarcel Holtmann struct hci_conn *conn; 2051b6a0dc82SMarcel Holtmann 2052b6a0dc82SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2053b6a0dc82SMarcel Holtmann 2054b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 2055b6a0dc82SMarcel Holtmann 2056b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 20579dc0a3afSMarcel Holtmann if (!conn) { 20589dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 20599dc0a3afSMarcel Holtmann goto unlock; 20609dc0a3afSMarcel Holtmann 20619dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 2062b6a0dc82SMarcel Holtmann if (!conn) 2063b6a0dc82SMarcel Holtmann goto unlock; 2064b6a0dc82SMarcel Holtmann 20659dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 20669dc0a3afSMarcel Holtmann } 20679dc0a3afSMarcel Holtmann 2068732547f9SMarcel Holtmann switch (ev->status) { 2069732547f9SMarcel Holtmann case 0x00: 2070732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 2071732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 2072732547f9SMarcel Holtmann 20739eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 2074732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 2075732547f9SMarcel Holtmann break; 2076732547f9SMarcel Holtmann 2077705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 2078732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 20791038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 2080732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 2081732547f9SMarcel Holtmann if (conn->out && conn->attempt < 2) { 2082efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 2083efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 2084efc7688bSMarcel Holtmann hci_setup_sync(conn, conn->link->handle); 2085efc7688bSMarcel Holtmann goto unlock; 2086efc7688bSMarcel Holtmann } 2087732547f9SMarcel Holtmann /* fall through */ 2088efc7688bSMarcel Holtmann 2089732547f9SMarcel Holtmann default: 2090b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 2091732547f9SMarcel Holtmann break; 2092732547f9SMarcel Holtmann } 2093b6a0dc82SMarcel Holtmann 2094b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2095b6a0dc82SMarcel Holtmann if (ev->status) 2096b6a0dc82SMarcel Holtmann hci_conn_del(conn); 2097b6a0dc82SMarcel Holtmann 2098b6a0dc82SMarcel Holtmann unlock: 2099b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 2100a9de9248SMarcel Holtmann } 2101a9de9248SMarcel Holtmann 2102a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) 2103a9de9248SMarcel Holtmann { 2104a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2105a9de9248SMarcel Holtmann } 2106a9de9248SMarcel Holtmann 210704837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) 210804837f64SMarcel Holtmann { 2109a9de9248SMarcel Holtmann struct hci_ev_sniff_subrate *ev = (void *) skb->data; 211004837f64SMarcel Holtmann struct hci_conn *conn; 211104837f64SMarcel Holtmann 211204837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 211304837f64SMarcel Holtmann 211404837f64SMarcel Holtmann hci_dev_lock(hdev); 211504837f64SMarcel Holtmann 211604837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 211704837f64SMarcel Holtmann if (conn) { 211804837f64SMarcel Holtmann } 211904837f64SMarcel Holtmann 212004837f64SMarcel Holtmann hci_dev_unlock(hdev); 212104837f64SMarcel Holtmann } 212204837f64SMarcel Holtmann 2123a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 2124a9de9248SMarcel Holtmann { 2125a9de9248SMarcel Holtmann struct inquiry_data data; 2126a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 2127a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2128a9de9248SMarcel Holtmann 2129a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2130a9de9248SMarcel Holtmann 2131a9de9248SMarcel Holtmann if (!num_rsp) 2132a9de9248SMarcel Holtmann return; 2133a9de9248SMarcel Holtmann 2134a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2135a9de9248SMarcel Holtmann 2136a9de9248SMarcel Holtmann for (; num_rsp; num_rsp--) { 2137a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2138a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2139a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2140a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2141a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2142a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2143a9de9248SMarcel Holtmann data.rssi = info->rssi; 214441a96212SMarcel Holtmann data.ssp_mode = 0x01; 2145a9de9248SMarcel Holtmann info++; 2146a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 2147a9de9248SMarcel Holtmann } 2148a9de9248SMarcel Holtmann 2149a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2150a9de9248SMarcel Holtmann } 2151a9de9248SMarcel Holtmann 21520493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 21530493684eSMarcel Holtmann { 21540493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 21550493684eSMarcel Holtmann struct hci_conn *conn; 21560493684eSMarcel Holtmann 21570493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 21580493684eSMarcel Holtmann 21590493684eSMarcel Holtmann hci_dev_lock(hdev); 21600493684eSMarcel Holtmann 21610493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 216203b555e1SJohan Hedberg if (!conn) 216303b555e1SJohan Hedberg goto unlock; 216403b555e1SJohan Hedberg 21650493684eSMarcel Holtmann hci_conn_hold(conn); 21660493684eSMarcel Holtmann 216703b555e1SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->flags)) 216803b555e1SJohan Hedberg goto unlock; 216903b555e1SJohan Hedberg 217003b555e1SJohan Hedberg if (test_bit(HCI_PAIRABLE, &hdev->flags) || 217103b555e1SJohan Hedberg (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 217203b555e1SJohan Hedberg /* FIXME: Do IO capa response based on information 217303b555e1SJohan Hedberg * provided through the management interface */ 217403b555e1SJohan Hedberg } else { 217503b555e1SJohan Hedberg struct hci_cp_io_capability_neg_reply cp; 217603b555e1SJohan Hedberg 217703b555e1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 217803b555e1SJohan Hedberg cp.reason = 0x16; /* Pairing not allowed */ 217903b555e1SJohan Hedberg 218003b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 218103b555e1SJohan Hedberg sizeof(cp), &cp); 218203b555e1SJohan Hedberg } 218303b555e1SJohan Hedberg 218403b555e1SJohan Hedberg unlock: 218503b555e1SJohan Hedberg hci_dev_unlock(hdev); 218603b555e1SJohan Hedberg } 218703b555e1SJohan Hedberg 218803b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 218903b555e1SJohan Hedberg { 219003b555e1SJohan Hedberg struct hci_ev_io_capa_reply *ev = (void *) skb->data; 219103b555e1SJohan Hedberg struct hci_conn *conn; 219203b555e1SJohan Hedberg 219303b555e1SJohan Hedberg BT_DBG("%s", hdev->name); 219403b555e1SJohan Hedberg 219503b555e1SJohan Hedberg hci_dev_lock(hdev); 219603b555e1SJohan Hedberg 219703b555e1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 219803b555e1SJohan Hedberg if (!conn) 219903b555e1SJohan Hedberg goto unlock; 220003b555e1SJohan Hedberg 220103b555e1SJohan Hedberg hci_conn_hold(conn); 220203b555e1SJohan Hedberg 220303b555e1SJohan Hedberg conn->remote_cap = ev->capability; 220403b555e1SJohan Hedberg conn->remote_oob = ev->oob_data; 220503b555e1SJohan Hedberg conn->remote_auth = ev->authentication; 220603b555e1SJohan Hedberg 220703b555e1SJohan Hedberg unlock: 22080493684eSMarcel Holtmann hci_dev_unlock(hdev); 22090493684eSMarcel Holtmann } 22100493684eSMarcel Holtmann 22110493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 22120493684eSMarcel Holtmann { 22130493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 22140493684eSMarcel Holtmann struct hci_conn *conn; 22150493684eSMarcel Holtmann 22160493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 22170493684eSMarcel Holtmann 22180493684eSMarcel Holtmann hci_dev_lock(hdev); 22190493684eSMarcel Holtmann 22200493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 22210493684eSMarcel Holtmann if (conn) 22220493684eSMarcel Holtmann hci_conn_put(conn); 22230493684eSMarcel Holtmann 22240493684eSMarcel Holtmann hci_dev_unlock(hdev); 22250493684eSMarcel Holtmann } 22260493684eSMarcel Holtmann 222741a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 222841a96212SMarcel Holtmann { 222941a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 223041a96212SMarcel Holtmann struct inquiry_entry *ie; 223141a96212SMarcel Holtmann 223241a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 223341a96212SMarcel Holtmann 223441a96212SMarcel Holtmann hci_dev_lock(hdev); 223541a96212SMarcel Holtmann 2236cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2237cc11b9c1SAndrei Emeltchenko if (ie) 223841a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 223941a96212SMarcel Holtmann 224041a96212SMarcel Holtmann hci_dev_unlock(hdev); 224141a96212SMarcel Holtmann } 224241a96212SMarcel Holtmann 22431da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 22441da177e4SLinus Torvalds { 2245a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 2246a9de9248SMarcel Holtmann __u8 event = hdr->evt; 22471da177e4SLinus Torvalds 22481da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 22491da177e4SLinus Torvalds 2250a9de9248SMarcel Holtmann switch (event) { 22511da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 22521da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 22531da177e4SLinus Torvalds break; 22541da177e4SLinus Torvalds 22551da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 22561da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 22571da177e4SLinus Torvalds break; 22581da177e4SLinus Torvalds 2259a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 2260a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 226121d9e30eSMarcel Holtmann break; 226221d9e30eSMarcel Holtmann 22631da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 22641da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 22651da177e4SLinus Torvalds break; 22661da177e4SLinus Torvalds 22671da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 22681da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 22691da177e4SLinus Torvalds break; 22701da177e4SLinus Torvalds 22711da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 22721da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 22731da177e4SLinus Torvalds break; 22741da177e4SLinus Torvalds 2275a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 2276a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 2277a9de9248SMarcel Holtmann break; 2278a9de9248SMarcel Holtmann 22791da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 22801da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 22811da177e4SLinus Torvalds break; 22821da177e4SLinus Torvalds 2283a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 2284a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 2285a9de9248SMarcel Holtmann break; 2286a9de9248SMarcel Holtmann 2287a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 2288a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 2289a9de9248SMarcel Holtmann break; 2290a9de9248SMarcel Holtmann 2291a9de9248SMarcel Holtmann case HCI_EV_REMOTE_VERSION: 2292a9de9248SMarcel Holtmann hci_remote_version_evt(hdev, skb); 2293a9de9248SMarcel Holtmann break; 2294a9de9248SMarcel Holtmann 2295a9de9248SMarcel Holtmann case HCI_EV_QOS_SETUP_COMPLETE: 2296a9de9248SMarcel Holtmann hci_qos_setup_complete_evt(hdev, skb); 2297a9de9248SMarcel Holtmann break; 2298a9de9248SMarcel Holtmann 2299a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 2300a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 2301a9de9248SMarcel Holtmann break; 2302a9de9248SMarcel Holtmann 2303a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 2304a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 2305a9de9248SMarcel Holtmann break; 2306a9de9248SMarcel Holtmann 2307a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 2308a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 2309a9de9248SMarcel Holtmann break; 2310a9de9248SMarcel Holtmann 2311a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 2312a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 2313a9de9248SMarcel Holtmann break; 2314a9de9248SMarcel Holtmann 2315a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 2316a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 23171da177e4SLinus Torvalds break; 23181da177e4SLinus Torvalds 23191da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 23201da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 23211da177e4SLinus Torvalds break; 23221da177e4SLinus Torvalds 23231da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 23241da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 23251da177e4SLinus Torvalds break; 23261da177e4SLinus Torvalds 23271da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 23281da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 23291da177e4SLinus Torvalds break; 23301da177e4SLinus Torvalds 23311da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 23321da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 23331da177e4SLinus Torvalds break; 23341da177e4SLinus Torvalds 2335a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 2336a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 2337a8746417SMarcel Holtmann break; 2338a8746417SMarcel Holtmann 233985a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 234085a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 234185a1e930SMarcel Holtmann break; 234285a1e930SMarcel Holtmann 2343a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 2344a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 2345a9de9248SMarcel Holtmann break; 2346a9de9248SMarcel Holtmann 2347a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 2348a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 2349a9de9248SMarcel Holtmann break; 2350a9de9248SMarcel Holtmann 2351a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 2352a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 2353a9de9248SMarcel Holtmann break; 2354a9de9248SMarcel Holtmann 2355a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_CHANGED: 2356a9de9248SMarcel Holtmann hci_sync_conn_changed_evt(hdev, skb); 2357a9de9248SMarcel Holtmann break; 2358a9de9248SMarcel Holtmann 235904837f64SMarcel Holtmann case HCI_EV_SNIFF_SUBRATE: 236004837f64SMarcel Holtmann hci_sniff_subrate_evt(hdev, skb); 236104837f64SMarcel Holtmann break; 236204837f64SMarcel Holtmann 2363a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 2364a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 23651da177e4SLinus Torvalds break; 23661da177e4SLinus Torvalds 23670493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 23680493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 23690493684eSMarcel Holtmann break; 23700493684eSMarcel Holtmann 237103b555e1SJohan Hedberg case HCI_EV_IO_CAPA_REPLY: 237203b555e1SJohan Hedberg hci_io_capa_reply_evt(hdev, skb); 237303b555e1SJohan Hedberg break; 237403b555e1SJohan Hedberg 23750493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 23760493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 23770493684eSMarcel Holtmann break; 23780493684eSMarcel Holtmann 237941a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 238041a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 238141a96212SMarcel Holtmann break; 238241a96212SMarcel Holtmann 23831da177e4SLinus Torvalds default: 2384a9de9248SMarcel Holtmann BT_DBG("%s event 0x%x", hdev->name, event); 23851da177e4SLinus Torvalds break; 23861da177e4SLinus Torvalds } 23871da177e4SLinus Torvalds 23881da177e4SLinus Torvalds kfree_skb(skb); 23891da177e4SLinus Torvalds hdev->stat.evt_rx++; 23901da177e4SLinus Torvalds } 23911da177e4SLinus Torvalds 23921da177e4SLinus Torvalds /* Generate internal stack event */ 23931da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data) 23941da177e4SLinus Torvalds { 23951da177e4SLinus Torvalds struct hci_event_hdr *hdr; 23961da177e4SLinus Torvalds struct hci_ev_stack_internal *ev; 23971da177e4SLinus Torvalds struct sk_buff *skb; 23981da177e4SLinus Torvalds 23991da177e4SLinus Torvalds skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC); 24001da177e4SLinus Torvalds if (!skb) 24011da177e4SLinus Torvalds return; 24021da177e4SLinus Torvalds 24031da177e4SLinus Torvalds hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE); 24041da177e4SLinus Torvalds hdr->evt = HCI_EV_STACK_INTERNAL; 24051da177e4SLinus Torvalds hdr->plen = sizeof(*ev) + dlen; 24061da177e4SLinus Torvalds 24071da177e4SLinus Torvalds ev = (void *) skb_put(skb, sizeof(*ev) + dlen); 24081da177e4SLinus Torvalds ev->type = type; 24091da177e4SLinus Torvalds memcpy(ev->data, data, dlen); 24101da177e4SLinus Torvalds 2411576c7d85SMarcel Holtmann bt_cb(skb)->incoming = 1; 2412a61bbcf2SPatrick McHardy __net_timestamp(skb); 2413576c7d85SMarcel Holtmann 24140d48d939SMarcel Holtmann bt_cb(skb)->pkt_type = HCI_EVENT_PKT; 24151da177e4SLinus Torvalds skb->dev = (void *) hdev; 2416eec8d2bcSJohan Hedberg hci_send_to_sock(hdev, skb, NULL); 24171da177e4SLinus Torvalds kfree_skb(skb); 24181da177e4SLinus Torvalds } 2419