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 59314b2381SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags) && 60314b2381SJohan Hedberg test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) 61314b2381SJohan Hedberg mgmt_discovering(hdev->id, 0); 62a9de9248SMarcel Holtmann 6323bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status); 64a9de9248SMarcel Holtmann 65a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 661da177e4SLinus Torvalds } 676bd57416SMarcel Holtmann 68a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 691da177e4SLinus Torvalds { 70a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 71a9de9248SMarcel Holtmann 72a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 73a9de9248SMarcel Holtmann 74a9de9248SMarcel Holtmann if (status) 75a9de9248SMarcel Holtmann return; 76a9de9248SMarcel Holtmann 77314b2381SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags) && 78314b2381SJohan Hedberg test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) 79314b2381SJohan Hedberg mgmt_discovering(hdev->id, 0); 80a9de9248SMarcel Holtmann 81a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 82a9de9248SMarcel Holtmann } 83a9de9248SMarcel Holtmann 84a9de9248SMarcel Holtmann static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb) 85a9de9248SMarcel Holtmann { 86a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 87a9de9248SMarcel Holtmann } 88a9de9248SMarcel Holtmann 89a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb) 90a9de9248SMarcel Holtmann { 91a9de9248SMarcel Holtmann struct hci_rp_role_discovery *rp = (void *) skb->data; 921da177e4SLinus Torvalds struct hci_conn *conn; 931da177e4SLinus Torvalds 94a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 951da177e4SLinus Torvalds 96a9de9248SMarcel Holtmann if (rp->status) 97a9de9248SMarcel Holtmann return; 981da177e4SLinus Torvalds 991da177e4SLinus Torvalds hci_dev_lock(hdev); 1001da177e4SLinus Torvalds 101a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 1021da177e4SLinus Torvalds if (conn) { 103a9de9248SMarcel Holtmann if (rp->role) 1041da177e4SLinus Torvalds conn->link_mode &= ~HCI_LM_MASTER; 1051da177e4SLinus Torvalds else 1061da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 1071da177e4SLinus Torvalds } 1081da177e4SLinus Torvalds 1091da177e4SLinus Torvalds hci_dev_unlock(hdev); 110a9de9248SMarcel Holtmann } 1111da177e4SLinus Torvalds 112e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 113e4e8e37cSMarcel Holtmann { 114e4e8e37cSMarcel Holtmann struct hci_rp_read_link_policy *rp = (void *) skb->data; 115e4e8e37cSMarcel Holtmann struct hci_conn *conn; 116e4e8e37cSMarcel Holtmann 117e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 118e4e8e37cSMarcel Holtmann 119e4e8e37cSMarcel Holtmann if (rp->status) 120e4e8e37cSMarcel Holtmann return; 121e4e8e37cSMarcel Holtmann 122e4e8e37cSMarcel Holtmann hci_dev_lock(hdev); 123e4e8e37cSMarcel Holtmann 124e4e8e37cSMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 125e4e8e37cSMarcel Holtmann if (conn) 126e4e8e37cSMarcel Holtmann conn->link_policy = __le16_to_cpu(rp->policy); 127e4e8e37cSMarcel Holtmann 128e4e8e37cSMarcel Holtmann hci_dev_unlock(hdev); 129e4e8e37cSMarcel Holtmann } 130e4e8e37cSMarcel Holtmann 131a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 132a9de9248SMarcel Holtmann { 133a9de9248SMarcel Holtmann struct hci_rp_write_link_policy *rp = (void *) skb->data; 134a9de9248SMarcel Holtmann struct hci_conn *conn; 135a9de9248SMarcel Holtmann void *sent; 136a9de9248SMarcel Holtmann 137a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 138a9de9248SMarcel Holtmann 139a9de9248SMarcel Holtmann if (rp->status) 140a9de9248SMarcel Holtmann return; 141a9de9248SMarcel Holtmann 142a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY); 14304837f64SMarcel Holtmann if (!sent) 144a9de9248SMarcel Holtmann return; 14504837f64SMarcel Holtmann 14604837f64SMarcel Holtmann hci_dev_lock(hdev); 14704837f64SMarcel Holtmann 148a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 149e4e8e37cSMarcel Holtmann if (conn) 15083985319SHarvey Harrison conn->link_policy = get_unaligned_le16(sent + 2); 15104837f64SMarcel Holtmann 15204837f64SMarcel Holtmann hci_dev_unlock(hdev); 1531da177e4SLinus Torvalds } 1541da177e4SLinus Torvalds 155e4e8e37cSMarcel Holtmann static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 156e4e8e37cSMarcel Holtmann { 157e4e8e37cSMarcel Holtmann struct hci_rp_read_def_link_policy *rp = (void *) skb->data; 158e4e8e37cSMarcel Holtmann 159e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 160e4e8e37cSMarcel Holtmann 161e4e8e37cSMarcel Holtmann if (rp->status) 162e4e8e37cSMarcel Holtmann return; 163e4e8e37cSMarcel Holtmann 164e4e8e37cSMarcel Holtmann hdev->link_policy = __le16_to_cpu(rp->policy); 165e4e8e37cSMarcel Holtmann } 166e4e8e37cSMarcel Holtmann 167e4e8e37cSMarcel Holtmann static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 168e4e8e37cSMarcel Holtmann { 169e4e8e37cSMarcel Holtmann __u8 status = *((__u8 *) skb->data); 170e4e8e37cSMarcel Holtmann void *sent; 171e4e8e37cSMarcel Holtmann 172e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 173e4e8e37cSMarcel Holtmann 174e4e8e37cSMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY); 175e4e8e37cSMarcel Holtmann if (!sent) 176e4e8e37cSMarcel Holtmann return; 177e4e8e37cSMarcel Holtmann 178e4e8e37cSMarcel Holtmann if (!status) 179e4e8e37cSMarcel Holtmann hdev->link_policy = get_unaligned_le16(sent); 180e4e8e37cSMarcel Holtmann 18123bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status); 182e4e8e37cSMarcel Holtmann } 183e4e8e37cSMarcel Holtmann 184a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) 1851da177e4SLinus Torvalds { 186a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 187a9de9248SMarcel Holtmann 188a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 189a9de9248SMarcel Holtmann 19010572132SGustavo F. Padovan clear_bit(HCI_RESET, &hdev->flags); 19110572132SGustavo F. Padovan 19223bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_RESET, status); 193a9de9248SMarcel Holtmann } 194a9de9248SMarcel Holtmann 195a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) 196a9de9248SMarcel Holtmann { 197a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 1981da177e4SLinus Torvalds void *sent; 1991da177e4SLinus Torvalds 200a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 2011da177e4SLinus Torvalds 202a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); 2031da177e4SLinus Torvalds if (!sent) 204a9de9248SMarcel Holtmann return; 2051da177e4SLinus Torvalds 206b312b161SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 207b312b161SJohan Hedberg mgmt_set_local_name_complete(hdev->id, sent, status); 208b312b161SJohan Hedberg 209b312b161SJohan Hedberg if (status) 210b312b161SJohan Hedberg return; 211b312b161SJohan Hedberg 2121f6c6378SJohan Hedberg memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); 213a9de9248SMarcel Holtmann } 214a9de9248SMarcel Holtmann 215a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) 216a9de9248SMarcel Holtmann { 217a9de9248SMarcel Holtmann struct hci_rp_read_local_name *rp = (void *) skb->data; 218a9de9248SMarcel Holtmann 219a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 220a9de9248SMarcel Holtmann 221a9de9248SMarcel Holtmann if (rp->status) 222a9de9248SMarcel Holtmann return; 223a9de9248SMarcel Holtmann 2241f6c6378SJohan Hedberg memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); 225a9de9248SMarcel Holtmann } 226a9de9248SMarcel Holtmann 227a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) 228a9de9248SMarcel Holtmann { 229a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 230a9de9248SMarcel Holtmann void *sent; 231a9de9248SMarcel Holtmann 232a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 233a9de9248SMarcel Holtmann 234a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); 235a9de9248SMarcel Holtmann if (!sent) 236a9de9248SMarcel Holtmann return; 2371da177e4SLinus Torvalds 2381da177e4SLinus Torvalds if (!status) { 239a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 240a9de9248SMarcel Holtmann 2411da177e4SLinus Torvalds if (param == AUTH_ENABLED) 2421da177e4SLinus Torvalds set_bit(HCI_AUTH, &hdev->flags); 2431da177e4SLinus Torvalds else 2441da177e4SLinus Torvalds clear_bit(HCI_AUTH, &hdev->flags); 2451da177e4SLinus Torvalds } 246a9de9248SMarcel Holtmann 24723bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status); 248a9de9248SMarcel Holtmann } 2491da177e4SLinus Torvalds 250a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) 251a9de9248SMarcel Holtmann { 252a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 253a9de9248SMarcel Holtmann void *sent; 254a9de9248SMarcel Holtmann 255a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 256a9de9248SMarcel Holtmann 257a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); 2581da177e4SLinus Torvalds if (!sent) 259a9de9248SMarcel Holtmann return; 2601da177e4SLinus Torvalds 2611da177e4SLinus Torvalds if (!status) { 262a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 263a9de9248SMarcel Holtmann 2641da177e4SLinus Torvalds if (param) 2651da177e4SLinus Torvalds set_bit(HCI_ENCRYPT, &hdev->flags); 2661da177e4SLinus Torvalds else 2671da177e4SLinus Torvalds clear_bit(HCI_ENCRYPT, &hdev->flags); 2681da177e4SLinus Torvalds } 269a9de9248SMarcel Holtmann 27023bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status); 2711da177e4SLinus Torvalds } 2721da177e4SLinus Torvalds 273a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) 274a9de9248SMarcel Holtmann { 275a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 276a9de9248SMarcel Holtmann void *sent; 2771da177e4SLinus Torvalds 278a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 279a9de9248SMarcel Holtmann 280a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); 2811da177e4SLinus Torvalds if (!sent) 282a9de9248SMarcel Holtmann return; 2831da177e4SLinus Torvalds 2841da177e4SLinus Torvalds if (!status) { 285a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 2869fbcbb45SJohan Hedberg int old_pscan, old_iscan; 287a9de9248SMarcel Holtmann 2889fbcbb45SJohan Hedberg old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags); 2899fbcbb45SJohan Hedberg old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags); 290a9de9248SMarcel Holtmann 29173f22f62SJohan Hedberg if (param & SCAN_INQUIRY) { 2921da177e4SLinus Torvalds set_bit(HCI_ISCAN, &hdev->flags); 2939fbcbb45SJohan Hedberg if (!old_iscan) 29473f22f62SJohan Hedberg mgmt_discoverable(hdev->id, 1); 2959fbcbb45SJohan Hedberg } else if (old_iscan) 29673f22f62SJohan Hedberg mgmt_discoverable(hdev->id, 0); 2971da177e4SLinus Torvalds 2989fbcbb45SJohan Hedberg if (param & SCAN_PAGE) { 2991da177e4SLinus Torvalds set_bit(HCI_PSCAN, &hdev->flags); 3009fbcbb45SJohan Hedberg if (!old_pscan) 3019fbcbb45SJohan Hedberg mgmt_connectable(hdev->id, 1); 3029fbcbb45SJohan Hedberg } else if (old_pscan) 3039fbcbb45SJohan Hedberg mgmt_connectable(hdev->id, 0); 3041da177e4SLinus Torvalds } 305a9de9248SMarcel Holtmann 30623bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status); 3071da177e4SLinus Torvalds } 3081da177e4SLinus Torvalds 309a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 310a9de9248SMarcel Holtmann { 311a9de9248SMarcel Holtmann struct hci_rp_read_class_of_dev *rp = (void *) skb->data; 312a9de9248SMarcel Holtmann 313a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 314a9de9248SMarcel Holtmann 315a9de9248SMarcel Holtmann if (rp->status) 316a9de9248SMarcel Holtmann return; 317a9de9248SMarcel Holtmann 318a9de9248SMarcel Holtmann memcpy(hdev->dev_class, rp->dev_class, 3); 319a9de9248SMarcel Holtmann 320a9de9248SMarcel Holtmann BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, 321a9de9248SMarcel Holtmann hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); 322a9de9248SMarcel Holtmann } 323a9de9248SMarcel Holtmann 324a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 325a9de9248SMarcel Holtmann { 326a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 327a9de9248SMarcel Holtmann void *sent; 328a9de9248SMarcel Holtmann 329a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 330a9de9248SMarcel Holtmann 331f383f275SMarcel Holtmann if (status) 332f383f275SMarcel Holtmann return; 333f383f275SMarcel Holtmann 334a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); 335a9de9248SMarcel Holtmann if (!sent) 336a9de9248SMarcel Holtmann return; 337a9de9248SMarcel Holtmann 338a9de9248SMarcel Holtmann memcpy(hdev->dev_class, sent, 3); 339a9de9248SMarcel Holtmann } 340a9de9248SMarcel Holtmann 341a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 342a9de9248SMarcel Holtmann { 343a9de9248SMarcel Holtmann struct hci_rp_read_voice_setting *rp = (void *) skb->data; 344a9de9248SMarcel Holtmann __u16 setting; 345a9de9248SMarcel Holtmann 346a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 347a9de9248SMarcel Holtmann 348a9de9248SMarcel Holtmann if (rp->status) 349a9de9248SMarcel Holtmann return; 350a9de9248SMarcel Holtmann 351a9de9248SMarcel Holtmann setting = __le16_to_cpu(rp->voice_setting); 352a9de9248SMarcel Holtmann 353a9de9248SMarcel Holtmann if (hdev->voice_setting == setting) 354a9de9248SMarcel Holtmann return; 355a9de9248SMarcel Holtmann 356a9de9248SMarcel Holtmann hdev->voice_setting = setting; 357a9de9248SMarcel Holtmann 358a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 359a9de9248SMarcel Holtmann 360a9de9248SMarcel Holtmann if (hdev->notify) { 361a9de9248SMarcel Holtmann tasklet_disable(&hdev->tx_task); 362a9de9248SMarcel Holtmann hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 363a9de9248SMarcel Holtmann tasklet_enable(&hdev->tx_task); 364a9de9248SMarcel Holtmann } 365a9de9248SMarcel Holtmann } 366a9de9248SMarcel Holtmann 367a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 368a9de9248SMarcel Holtmann { 369a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 370f383f275SMarcel Holtmann __u16 setting; 371a9de9248SMarcel Holtmann void *sent; 372a9de9248SMarcel Holtmann 373a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 374a9de9248SMarcel Holtmann 375f383f275SMarcel Holtmann if (status) 376f383f275SMarcel Holtmann return; 377f383f275SMarcel Holtmann 378a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); 379a9de9248SMarcel Holtmann if (!sent) 380a9de9248SMarcel Holtmann return; 381a9de9248SMarcel Holtmann 382f383f275SMarcel Holtmann setting = get_unaligned_le16(sent); 3831da177e4SLinus Torvalds 384f383f275SMarcel Holtmann if (hdev->voice_setting == setting) 385f383f275SMarcel Holtmann return; 386f383f275SMarcel Holtmann 3871da177e4SLinus Torvalds hdev->voice_setting = setting; 3881da177e4SLinus Torvalds 389a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 3901da177e4SLinus Torvalds 3911da177e4SLinus Torvalds if (hdev->notify) { 3921da177e4SLinus Torvalds tasklet_disable(&hdev->tx_task); 3931da177e4SLinus Torvalds hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 3941da177e4SLinus Torvalds tasklet_enable(&hdev->tx_task); 3951da177e4SLinus Torvalds } 3961da177e4SLinus Torvalds } 3971da177e4SLinus Torvalds 398a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 3991da177e4SLinus Torvalds { 400a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 4011da177e4SLinus Torvalds 402a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 4031da177e4SLinus Torvalds 40423bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status); 4051143e5a6SMarcel Holtmann } 4061143e5a6SMarcel Holtmann 407333140b5SMarcel Holtmann static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 408333140b5SMarcel Holtmann { 409333140b5SMarcel Holtmann struct hci_rp_read_ssp_mode *rp = (void *) skb->data; 410333140b5SMarcel Holtmann 411333140b5SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 412333140b5SMarcel Holtmann 413333140b5SMarcel Holtmann if (rp->status) 414333140b5SMarcel Holtmann return; 415333140b5SMarcel Holtmann 416333140b5SMarcel Holtmann hdev->ssp_mode = rp->mode; 417333140b5SMarcel Holtmann } 418333140b5SMarcel Holtmann 419333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 420333140b5SMarcel Holtmann { 421333140b5SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 422333140b5SMarcel Holtmann void *sent; 423333140b5SMarcel Holtmann 424333140b5SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 425333140b5SMarcel Holtmann 426333140b5SMarcel Holtmann if (status) 427333140b5SMarcel Holtmann return; 428333140b5SMarcel Holtmann 429333140b5SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); 430333140b5SMarcel Holtmann if (!sent) 431333140b5SMarcel Holtmann return; 432333140b5SMarcel Holtmann 433333140b5SMarcel Holtmann hdev->ssp_mode = *((__u8 *) sent); 434333140b5SMarcel Holtmann } 435333140b5SMarcel Holtmann 436d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev) 437d5859e22SJohan Hedberg { 438d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 439d5859e22SJohan Hedberg return 2; 440d5859e22SJohan Hedberg 441d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 442d5859e22SJohan Hedberg return 1; 443d5859e22SJohan Hedberg 444d5859e22SJohan Hedberg if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 && 445d5859e22SJohan Hedberg hdev->lmp_subver == 0x0757) 446d5859e22SJohan Hedberg return 1; 447d5859e22SJohan Hedberg 448d5859e22SJohan Hedberg if (hdev->manufacturer == 15) { 449d5859e22SJohan Hedberg if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963) 450d5859e22SJohan Hedberg return 1; 451d5859e22SJohan Hedberg if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963) 452d5859e22SJohan Hedberg return 1; 453d5859e22SJohan Hedberg if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965) 454d5859e22SJohan Hedberg return 1; 455d5859e22SJohan Hedberg } 456d5859e22SJohan Hedberg 457d5859e22SJohan Hedberg if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 && 458d5859e22SJohan Hedberg hdev->lmp_subver == 0x1805) 459d5859e22SJohan Hedberg return 1; 460d5859e22SJohan Hedberg 461d5859e22SJohan Hedberg return 0; 462d5859e22SJohan Hedberg } 463d5859e22SJohan Hedberg 464d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev) 465d5859e22SJohan Hedberg { 466d5859e22SJohan Hedberg u8 mode; 467d5859e22SJohan Hedberg 468d5859e22SJohan Hedberg mode = hci_get_inquiry_mode(hdev); 469d5859e22SJohan Hedberg 470d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode); 471d5859e22SJohan Hedberg } 472d5859e22SJohan Hedberg 473d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev) 474d5859e22SJohan Hedberg { 475d5859e22SJohan Hedberg /* The second byte is 0xff instead of 0x9f (two reserved bits 476d5859e22SJohan Hedberg * disabled) since a Broadcom 1.2 dongle doesn't respond to the 477d5859e22SJohan Hedberg * command otherwise */ 478d5859e22SJohan Hedberg u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 }; 479d5859e22SJohan Hedberg 480d5859e22SJohan Hedberg /* Events for 1.2 and newer controllers */ 481d5859e22SJohan Hedberg if (hdev->lmp_ver > 1) { 482d5859e22SJohan Hedberg events[4] |= 0x01; /* Flow Specification Complete */ 483d5859e22SJohan Hedberg events[4] |= 0x02; /* Inquiry Result with RSSI */ 484d5859e22SJohan Hedberg events[4] |= 0x04; /* Read Remote Extended Features Complete */ 485d5859e22SJohan Hedberg events[5] |= 0x08; /* Synchronous Connection Complete */ 486d5859e22SJohan Hedberg events[5] |= 0x10; /* Synchronous Connection Changed */ 487d5859e22SJohan Hedberg } 488d5859e22SJohan Hedberg 489d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 490d5859e22SJohan Hedberg events[4] |= 0x04; /* Inquiry Result with RSSI */ 491d5859e22SJohan Hedberg 492d5859e22SJohan Hedberg if (hdev->features[5] & LMP_SNIFF_SUBR) 493d5859e22SJohan Hedberg events[5] |= 0x20; /* Sniff Subrating */ 494d5859e22SJohan Hedberg 495d5859e22SJohan Hedberg if (hdev->features[5] & LMP_PAUSE_ENC) 496d5859e22SJohan Hedberg events[5] |= 0x80; /* Encryption Key Refresh Complete */ 497d5859e22SJohan Hedberg 498d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 499d5859e22SJohan Hedberg events[5] |= 0x40; /* Extended Inquiry Result */ 500d5859e22SJohan Hedberg 501d5859e22SJohan Hedberg if (hdev->features[6] & LMP_NO_FLUSH) 502d5859e22SJohan Hedberg events[7] |= 0x01; /* Enhanced Flush Complete */ 503d5859e22SJohan Hedberg 504d5859e22SJohan Hedberg if (hdev->features[7] & LMP_LSTO) 505d5859e22SJohan Hedberg events[6] |= 0x80; /* Link Supervision Timeout Changed */ 506d5859e22SJohan Hedberg 507d5859e22SJohan Hedberg if (hdev->features[6] & LMP_SIMPLE_PAIR) { 508d5859e22SJohan Hedberg events[6] |= 0x01; /* IO Capability Request */ 509d5859e22SJohan Hedberg events[6] |= 0x02; /* IO Capability Response */ 510d5859e22SJohan Hedberg events[6] |= 0x04; /* User Confirmation Request */ 511d5859e22SJohan Hedberg events[6] |= 0x08; /* User Passkey Request */ 512d5859e22SJohan Hedberg events[6] |= 0x10; /* Remote OOB Data Request */ 513d5859e22SJohan Hedberg events[6] |= 0x20; /* Simple Pairing Complete */ 514d5859e22SJohan Hedberg events[7] |= 0x04; /* User Passkey Notification */ 515d5859e22SJohan Hedberg events[7] |= 0x08; /* Keypress Notification */ 516d5859e22SJohan Hedberg events[7] |= 0x10; /* Remote Host Supported 517d5859e22SJohan Hedberg * Features Notification */ 518d5859e22SJohan Hedberg } 519d5859e22SJohan Hedberg 520d5859e22SJohan Hedberg if (hdev->features[4] & LMP_LE) 521d5859e22SJohan Hedberg events[7] |= 0x20; /* LE Meta-Event */ 522d5859e22SJohan Hedberg 523d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); 524d5859e22SJohan Hedberg } 525d5859e22SJohan Hedberg 526d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev) 527d5859e22SJohan Hedberg { 528d5859e22SJohan Hedberg hci_setup_event_mask(hdev); 529d5859e22SJohan Hedberg 530d5859e22SJohan Hedberg if (hdev->lmp_ver > 1) 531d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); 532d5859e22SJohan Hedberg 533d5859e22SJohan Hedberg if (hdev->features[6] & LMP_SIMPLE_PAIR) { 534d5859e22SJohan Hedberg u8 mode = 0x01; 535d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode); 536d5859e22SJohan Hedberg } 537d5859e22SJohan Hedberg 538d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 539d5859e22SJohan Hedberg hci_setup_inquiry_mode(hdev); 540d5859e22SJohan Hedberg 541d5859e22SJohan Hedberg if (hdev->features[7] & LMP_INQ_TX_PWR) 542d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL); 543d5859e22SJohan Hedberg } 544d5859e22SJohan Hedberg 545a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) 546a9de9248SMarcel Holtmann { 547a9de9248SMarcel Holtmann struct hci_rp_read_local_version *rp = (void *) skb->data; 5481143e5a6SMarcel Holtmann 549a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 5501143e5a6SMarcel Holtmann 551a9de9248SMarcel Holtmann if (rp->status) 552a9de9248SMarcel Holtmann return; 5531143e5a6SMarcel Holtmann 554a9de9248SMarcel Holtmann hdev->hci_ver = rp->hci_ver; 555e4e8e37cSMarcel Holtmann hdev->hci_rev = __le16_to_cpu(rp->hci_rev); 556d5859e22SJohan Hedberg hdev->lmp_ver = rp->lmp_ver; 557e4e8e37cSMarcel Holtmann hdev->manufacturer = __le16_to_cpu(rp->manufacturer); 558d5859e22SJohan Hedberg hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); 5591da177e4SLinus Torvalds 560a9de9248SMarcel Holtmann BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name, 561a9de9248SMarcel Holtmann hdev->manufacturer, 562a9de9248SMarcel Holtmann hdev->hci_ver, hdev->hci_rev); 563d5859e22SJohan Hedberg 564d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags)) 565d5859e22SJohan Hedberg hci_setup(hdev); 566d5859e22SJohan Hedberg } 567d5859e22SJohan Hedberg 568d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev) 569d5859e22SJohan Hedberg { 570d5859e22SJohan Hedberg u16 link_policy = 0; 571d5859e22SJohan Hedberg 572d5859e22SJohan Hedberg if (hdev->features[0] & LMP_RSWITCH) 573d5859e22SJohan Hedberg link_policy |= HCI_LP_RSWITCH; 574d5859e22SJohan Hedberg if (hdev->features[0] & LMP_HOLD) 575d5859e22SJohan Hedberg link_policy |= HCI_LP_HOLD; 576d5859e22SJohan Hedberg if (hdev->features[0] & LMP_SNIFF) 577d5859e22SJohan Hedberg link_policy |= HCI_LP_SNIFF; 578d5859e22SJohan Hedberg if (hdev->features[1] & LMP_PARK) 579d5859e22SJohan Hedberg link_policy |= HCI_LP_PARK; 580d5859e22SJohan Hedberg 581d5859e22SJohan Hedberg link_policy = cpu_to_le16(link_policy); 582d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, 583d5859e22SJohan Hedberg sizeof(link_policy), &link_policy); 5841da177e4SLinus Torvalds } 5851da177e4SLinus Torvalds 586a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb) 587a9de9248SMarcel Holtmann { 588a9de9248SMarcel Holtmann struct hci_rp_read_local_commands *rp = (void *) skb->data; 589a9de9248SMarcel Holtmann 590a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 591a9de9248SMarcel Holtmann 592a9de9248SMarcel Holtmann if (rp->status) 593d5859e22SJohan Hedberg goto done; 594a9de9248SMarcel Holtmann 595a9de9248SMarcel Holtmann memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); 596d5859e22SJohan Hedberg 597d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10)) 598d5859e22SJohan Hedberg hci_setup_link_policy(hdev); 599d5859e22SJohan Hedberg 600d5859e22SJohan Hedberg done: 601d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status); 602a9de9248SMarcel Holtmann } 603a9de9248SMarcel Holtmann 604a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb) 605a9de9248SMarcel Holtmann { 606a9de9248SMarcel Holtmann struct hci_rp_read_local_features *rp = (void *) skb->data; 607a9de9248SMarcel Holtmann 608a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 609a9de9248SMarcel Holtmann 610a9de9248SMarcel Holtmann if (rp->status) 611a9de9248SMarcel Holtmann return; 612a9de9248SMarcel Holtmann 613a9de9248SMarcel Holtmann memcpy(hdev->features, rp->features, 8); 6141da177e4SLinus Torvalds 6151da177e4SLinus Torvalds /* Adjust default settings according to features 6161da177e4SLinus Torvalds * supported by device. */ 617a9de9248SMarcel Holtmann 6181da177e4SLinus Torvalds if (hdev->features[0] & LMP_3SLOT) 6191da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM3 | HCI_DH3); 6201da177e4SLinus Torvalds 6211da177e4SLinus Torvalds if (hdev->features[0] & LMP_5SLOT) 6221da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM5 | HCI_DH5); 6231da177e4SLinus Torvalds 6245b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV2) { 6251da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV2); 6265b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV2); 6275b7f9909SMarcel Holtmann } 6281da177e4SLinus Torvalds 6295b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV3) { 6301da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV3); 6315b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV3); 6325b7f9909SMarcel Holtmann } 6335b7f9909SMarcel Holtmann 6345b7f9909SMarcel Holtmann if (hdev->features[3] & LMP_ESCO) 6355b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV3); 6365b7f9909SMarcel Holtmann 6375b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV4) 6385b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV4); 6395b7f9909SMarcel Holtmann 6405b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV5) 6415b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV5); 6421da177e4SLinus Torvalds 643efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_2M) 644efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV3); 645efc7688bSMarcel Holtmann 646efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_3M) 647efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_3EV3); 648efc7688bSMarcel Holtmann 649efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_3S_ESCO) 650efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); 651efc7688bSMarcel Holtmann 652a9de9248SMarcel Holtmann BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, 653a9de9248SMarcel Holtmann hdev->features[0], hdev->features[1], 654a9de9248SMarcel Holtmann hdev->features[2], hdev->features[3], 655a9de9248SMarcel Holtmann hdev->features[4], hdev->features[5], 656a9de9248SMarcel Holtmann hdev->features[6], hdev->features[7]); 6571da177e4SLinus Torvalds } 6581da177e4SLinus Torvalds 659a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 660a9de9248SMarcel Holtmann { 661a9de9248SMarcel Holtmann struct hci_rp_read_buffer_size *rp = (void *) skb->data; 662a9de9248SMarcel Holtmann 663a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 664a9de9248SMarcel Holtmann 665a9de9248SMarcel Holtmann if (rp->status) 666a9de9248SMarcel Holtmann return; 667a9de9248SMarcel Holtmann 668a9de9248SMarcel Holtmann hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); 669a9de9248SMarcel Holtmann hdev->sco_mtu = rp->sco_mtu; 670a9de9248SMarcel Holtmann hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); 671a9de9248SMarcel Holtmann hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); 672da1f5198SMarcel Holtmann 673da1f5198SMarcel Holtmann if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { 674da1f5198SMarcel Holtmann hdev->sco_mtu = 64; 675da1f5198SMarcel Holtmann hdev->sco_pkts = 8; 676da1f5198SMarcel Holtmann } 677da1f5198SMarcel Holtmann 678da1f5198SMarcel Holtmann hdev->acl_cnt = hdev->acl_pkts; 679da1f5198SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 6801da177e4SLinus Torvalds 681a9de9248SMarcel Holtmann BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, 682a9de9248SMarcel Holtmann hdev->acl_mtu, hdev->acl_pkts, 683a9de9248SMarcel Holtmann hdev->sco_mtu, hdev->sco_pkts); 6841da177e4SLinus Torvalds } 6851da177e4SLinus Torvalds 686a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) 687a9de9248SMarcel Holtmann { 688a9de9248SMarcel Holtmann struct hci_rp_read_bd_addr *rp = (void *) skb->data; 6891da177e4SLinus Torvalds 690a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 691a9de9248SMarcel Holtmann 692a9de9248SMarcel Holtmann if (!rp->status) 693a9de9248SMarcel Holtmann bacpy(&hdev->bdaddr, &rp->bdaddr); 694a9de9248SMarcel Holtmann 69523bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status); 69623bb5763SJohan Hedberg } 69723bb5763SJohan Hedberg 69823bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb) 69923bb5763SJohan Hedberg { 70023bb5763SJohan Hedberg __u8 status = *((__u8 *) skb->data); 70123bb5763SJohan Hedberg 70223bb5763SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 70323bb5763SJohan Hedberg 70423bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status); 7051da177e4SLinus Torvalds } 7061da177e4SLinus Torvalds 707b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, 708b0916ea0SJohan Hedberg struct sk_buff *skb) 709b0916ea0SJohan Hedberg { 710b0916ea0SJohan Hedberg __u8 status = *((__u8 *) skb->data); 711b0916ea0SJohan Hedberg 712b0916ea0SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 713b0916ea0SJohan Hedberg 714b0916ea0SJohan Hedberg hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status); 715b0916ea0SJohan Hedberg } 716b0916ea0SJohan Hedberg 717d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb) 718d5859e22SJohan Hedberg { 719d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 720d5859e22SJohan Hedberg 721d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 722d5859e22SJohan Hedberg 723d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status); 724d5859e22SJohan Hedberg } 725d5859e22SJohan Hedberg 726d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev, 727d5859e22SJohan Hedberg struct sk_buff *skb) 728d5859e22SJohan Hedberg { 729d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 730d5859e22SJohan Hedberg 731d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 732d5859e22SJohan Hedberg 733d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status); 734d5859e22SJohan Hedberg } 735d5859e22SJohan Hedberg 736d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, 737d5859e22SJohan Hedberg 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_READ_INQ_RSP_TX_POWER, status); 744d5859e22SJohan Hedberg } 745d5859e22SJohan Hedberg 746d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb) 747d5859e22SJohan Hedberg { 748d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 749d5859e22SJohan Hedberg 750d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 751d5859e22SJohan Hedberg 752d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status); 753d5859e22SJohan Hedberg } 754d5859e22SJohan Hedberg 755980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) 756980e1a53SJohan Hedberg { 757980e1a53SJohan Hedberg struct hci_rp_pin_code_reply *rp = (void *) skb->data; 758980e1a53SJohan Hedberg struct hci_cp_pin_code_reply *cp; 759980e1a53SJohan Hedberg struct hci_conn *conn; 760980e1a53SJohan Hedberg 761980e1a53SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 762980e1a53SJohan Hedberg 763980e1a53SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 764980e1a53SJohan Hedberg mgmt_pin_code_reply_complete(hdev->id, &rp->bdaddr, rp->status); 765980e1a53SJohan Hedberg 766980e1a53SJohan Hedberg if (rp->status != 0) 767980e1a53SJohan Hedberg return; 768980e1a53SJohan Hedberg 769980e1a53SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); 770980e1a53SJohan Hedberg if (!cp) 771980e1a53SJohan Hedberg return; 772980e1a53SJohan Hedberg 773980e1a53SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 774980e1a53SJohan Hedberg if (conn) 775980e1a53SJohan Hedberg conn->pin_length = cp->pin_len; 776980e1a53SJohan Hedberg } 777980e1a53SJohan Hedberg 778980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 779980e1a53SJohan Hedberg { 780980e1a53SJohan Hedberg struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data; 781980e1a53SJohan Hedberg 782980e1a53SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 783980e1a53SJohan Hedberg 784980e1a53SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 785980e1a53SJohan Hedberg mgmt_pin_code_neg_reply_complete(hdev->id, &rp->bdaddr, 786980e1a53SJohan Hedberg rp->status); 787980e1a53SJohan Hedberg } 7886ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, 7896ed58ec5SVille Tervo struct sk_buff *skb) 7906ed58ec5SVille Tervo { 7916ed58ec5SVille Tervo struct hci_rp_le_read_buffer_size *rp = (void *) skb->data; 7926ed58ec5SVille Tervo 7936ed58ec5SVille Tervo BT_DBG("%s status 0x%x", hdev->name, rp->status); 7946ed58ec5SVille Tervo 7956ed58ec5SVille Tervo if (rp->status) 7966ed58ec5SVille Tervo return; 7976ed58ec5SVille Tervo 7986ed58ec5SVille Tervo hdev->le_mtu = __le16_to_cpu(rp->le_mtu); 7996ed58ec5SVille Tervo hdev->le_pkts = rp->le_max_pkt; 8006ed58ec5SVille Tervo 8016ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 8026ed58ec5SVille Tervo 8036ed58ec5SVille Tervo BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); 8046ed58ec5SVille Tervo 8056ed58ec5SVille Tervo hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status); 8066ed58ec5SVille Tervo } 807980e1a53SJohan Hedberg 808a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) 809a5c29683SJohan Hedberg { 810a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 811a5c29683SJohan Hedberg 812a5c29683SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 813a5c29683SJohan Hedberg 814a5c29683SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 815a5c29683SJohan Hedberg mgmt_user_confirm_reply_complete(hdev->id, &rp->bdaddr, 816a5c29683SJohan Hedberg rp->status); 817a5c29683SJohan Hedberg } 818a5c29683SJohan Hedberg 819a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, 820a5c29683SJohan Hedberg struct sk_buff *skb) 821a5c29683SJohan Hedberg { 822a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 823a5c29683SJohan Hedberg 824a5c29683SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 825a5c29683SJohan Hedberg 826a5c29683SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 827a5c29683SJohan Hedberg mgmt_user_confirm_neg_reply_complete(hdev->id, &rp->bdaddr, 828a5c29683SJohan Hedberg rp->status); 829a5c29683SJohan Hedberg } 830a5c29683SJohan Hedberg 831c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, 832c35938b2SSzymon Janc struct sk_buff *skb) 833c35938b2SSzymon Janc { 834c35938b2SSzymon Janc struct hci_rp_read_local_oob_data *rp = (void *) skb->data; 835c35938b2SSzymon Janc 836c35938b2SSzymon Janc BT_DBG("%s status 0x%x", hdev->name, rp->status); 837c35938b2SSzymon Janc 838c35938b2SSzymon Janc mgmt_read_local_oob_data_reply_complete(hdev->id, rp->hash, 839c35938b2SSzymon Janc rp->randomizer, rp->status); 840c35938b2SSzymon Janc } 841c35938b2SSzymon Janc 842a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 843a9de9248SMarcel Holtmann { 844a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 845a9de9248SMarcel Holtmann 846a9de9248SMarcel Holtmann if (status) { 84723bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 848a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 849314b2381SJohan Hedberg return; 850314b2381SJohan Hedberg } 851314b2381SJohan Hedberg 852314b2381SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags) && 853314b2381SJohan Hedberg !test_and_set_bit(HCI_INQUIRY, 854314b2381SJohan Hedberg &hdev->flags)) 855314b2381SJohan Hedberg mgmt_discovering(hdev->id, 1); 856a9de9248SMarcel Holtmann } 857a9de9248SMarcel Holtmann 8581da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 8591da177e4SLinus Torvalds { 860a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 8611da177e4SLinus Torvalds struct hci_conn *conn; 8621da177e4SLinus Torvalds 863a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 864a9de9248SMarcel Holtmann 865a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 8661da177e4SLinus Torvalds if (!cp) 8671da177e4SLinus Torvalds return; 8681da177e4SLinus Torvalds 8691da177e4SLinus Torvalds hci_dev_lock(hdev); 8701da177e4SLinus Torvalds 8711da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 8721da177e4SLinus Torvalds 873a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn); 8741da177e4SLinus Torvalds 8751da177e4SLinus Torvalds if (status) { 8761da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 8774c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 8781da177e4SLinus Torvalds conn->state = BT_CLOSED; 8791da177e4SLinus Torvalds hci_proto_connect_cfm(conn, status); 8801da177e4SLinus Torvalds hci_conn_del(conn); 8814c67bc74SMarcel Holtmann } else 8824c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 8831da177e4SLinus Torvalds } 8841da177e4SLinus Torvalds } else { 8851da177e4SLinus Torvalds if (!conn) { 8861da177e4SLinus Torvalds conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); 8871da177e4SLinus Torvalds if (conn) { 8881da177e4SLinus Torvalds conn->out = 1; 8891da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 8901da177e4SLinus Torvalds } else 891893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 8921da177e4SLinus Torvalds } 8931da177e4SLinus Torvalds } 8941da177e4SLinus Torvalds 8951da177e4SLinus Torvalds hci_dev_unlock(hdev); 8961da177e4SLinus Torvalds } 8971da177e4SLinus Torvalds 898a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 8991da177e4SLinus Torvalds { 900a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 9011da177e4SLinus Torvalds struct hci_conn *acl, *sco; 9021da177e4SLinus Torvalds __u16 handle; 9031da177e4SLinus Torvalds 904b6a0dc82SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 905b6a0dc82SMarcel Holtmann 906a9de9248SMarcel Holtmann if (!status) 907a9de9248SMarcel Holtmann return; 908a9de9248SMarcel Holtmann 909a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 9101da177e4SLinus Torvalds if (!cp) 911a9de9248SMarcel Holtmann return; 9121da177e4SLinus Torvalds 9131da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 9141da177e4SLinus Torvalds 915a9de9248SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 9161da177e4SLinus Torvalds 9171da177e4SLinus Torvalds hci_dev_lock(hdev); 9181da177e4SLinus Torvalds 9191da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 9205a08ecceSAndrei Emeltchenko if (acl) { 9215a08ecceSAndrei Emeltchenko sco = acl->link; 9225a08ecceSAndrei Emeltchenko if (sco) { 9231da177e4SLinus Torvalds sco->state = BT_CLOSED; 9241da177e4SLinus Torvalds 9251da177e4SLinus Torvalds hci_proto_connect_cfm(sco, status); 9261da177e4SLinus Torvalds hci_conn_del(sco); 9271da177e4SLinus Torvalds } 9285a08ecceSAndrei Emeltchenko } 9291da177e4SLinus Torvalds 9301da177e4SLinus Torvalds hci_dev_unlock(hdev); 9311da177e4SLinus Torvalds } 9321da177e4SLinus Torvalds 933f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 934f8558555SMarcel Holtmann { 935f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 936f8558555SMarcel Holtmann struct hci_conn *conn; 937f8558555SMarcel Holtmann 938f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 939f8558555SMarcel Holtmann 940f8558555SMarcel Holtmann if (!status) 941f8558555SMarcel Holtmann return; 942f8558555SMarcel Holtmann 943f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 944f8558555SMarcel Holtmann if (!cp) 945f8558555SMarcel Holtmann return; 946f8558555SMarcel Holtmann 947f8558555SMarcel Holtmann hci_dev_lock(hdev); 948f8558555SMarcel Holtmann 949f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 950f8558555SMarcel Holtmann if (conn) { 951f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 952f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 953f8558555SMarcel Holtmann hci_conn_put(conn); 954f8558555SMarcel Holtmann } 955f8558555SMarcel Holtmann } 956f8558555SMarcel Holtmann 957f8558555SMarcel Holtmann hci_dev_unlock(hdev); 958f8558555SMarcel Holtmann } 959f8558555SMarcel Holtmann 960f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 961f8558555SMarcel Holtmann { 962f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 963f8558555SMarcel Holtmann struct hci_conn *conn; 964f8558555SMarcel Holtmann 965f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 966f8558555SMarcel Holtmann 967f8558555SMarcel Holtmann if (!status) 968f8558555SMarcel Holtmann return; 969f8558555SMarcel Holtmann 970f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 971f8558555SMarcel Holtmann if (!cp) 972f8558555SMarcel Holtmann return; 973f8558555SMarcel Holtmann 974f8558555SMarcel Holtmann hci_dev_lock(hdev); 975f8558555SMarcel Holtmann 976f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 977f8558555SMarcel Holtmann if (conn) { 978f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 979f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 980f8558555SMarcel Holtmann hci_conn_put(conn); 981f8558555SMarcel Holtmann } 982f8558555SMarcel Holtmann } 983f8558555SMarcel Holtmann 984f8558555SMarcel Holtmann hci_dev_unlock(hdev); 985f8558555SMarcel Holtmann } 986f8558555SMarcel Holtmann 987127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev, 988392599b9SJohan Hedberg struct hci_conn *conn) 989392599b9SJohan Hedberg { 990392599b9SJohan Hedberg if (conn->state != BT_CONFIG || !conn->out) 991392599b9SJohan Hedberg return 0; 992392599b9SJohan Hedberg 993765c2a96SJohan Hedberg if (conn->pending_sec_level == BT_SECURITY_SDP) 994392599b9SJohan Hedberg return 0; 995392599b9SJohan Hedberg 996392599b9SJohan Hedberg /* Only request authentication for SSP connections or non-SSP 997392599b9SJohan Hedberg * devices with sec_level HIGH */ 998392599b9SJohan Hedberg if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) && 999765c2a96SJohan Hedberg conn->pending_sec_level != BT_SECURITY_HIGH) 1000392599b9SJohan Hedberg return 0; 1001392599b9SJohan Hedberg 1002392599b9SJohan Hedberg return 1; 1003392599b9SJohan Hedberg } 1004392599b9SJohan Hedberg 1005a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 10061da177e4SLinus Torvalds { 1007127178d2SJohan Hedberg struct hci_cp_remote_name_req *cp; 1008127178d2SJohan Hedberg struct hci_conn *conn; 1009127178d2SJohan Hedberg 1010a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1011127178d2SJohan Hedberg 1012127178d2SJohan Hedberg /* If successful wait for the name req complete event before 1013127178d2SJohan Hedberg * checking for the need to do authentication */ 1014127178d2SJohan Hedberg if (!status) 1015127178d2SJohan Hedberg return; 1016127178d2SJohan Hedberg 1017127178d2SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); 1018127178d2SJohan Hedberg if (!cp) 1019127178d2SJohan Hedberg return; 1020127178d2SJohan Hedberg 1021127178d2SJohan Hedberg hci_dev_lock(hdev); 1022127178d2SJohan Hedberg 1023127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 102479c6c70cSJohan Hedberg if (!conn) 102579c6c70cSJohan Hedberg goto unlock; 102679c6c70cSJohan Hedberg 102779c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 102879c6c70cSJohan Hedberg goto unlock; 102979c6c70cSJohan Hedberg 103079c6c70cSJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { 1031127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1032127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1033127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1034127178d2SJohan Hedberg } 1035127178d2SJohan Hedberg 103679c6c70cSJohan Hedberg unlock: 1037127178d2SJohan Hedberg hci_dev_unlock(hdev); 1038a9de9248SMarcel Holtmann } 10391da177e4SLinus Torvalds 1040769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 1041769be974SMarcel Holtmann { 1042769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 1043769be974SMarcel Holtmann struct hci_conn *conn; 1044769be974SMarcel Holtmann 1045769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1046769be974SMarcel Holtmann 1047769be974SMarcel Holtmann if (!status) 1048769be974SMarcel Holtmann return; 1049769be974SMarcel Holtmann 1050769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 1051769be974SMarcel Holtmann if (!cp) 1052769be974SMarcel Holtmann return; 1053769be974SMarcel Holtmann 1054769be974SMarcel Holtmann hci_dev_lock(hdev); 1055769be974SMarcel Holtmann 1056769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1057769be974SMarcel Holtmann if (conn) { 1058769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1059769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1060769be974SMarcel Holtmann hci_conn_put(conn); 1061769be974SMarcel Holtmann } 1062769be974SMarcel Holtmann } 1063769be974SMarcel Holtmann 1064769be974SMarcel Holtmann hci_dev_unlock(hdev); 1065769be974SMarcel Holtmann } 1066769be974SMarcel Holtmann 1067769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 1068769be974SMarcel Holtmann { 1069769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features *cp; 1070769be974SMarcel Holtmann struct hci_conn *conn; 1071769be974SMarcel Holtmann 1072769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1073769be974SMarcel Holtmann 1074769be974SMarcel Holtmann if (!status) 1075769be974SMarcel Holtmann return; 1076769be974SMarcel Holtmann 1077769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 1078769be974SMarcel Holtmann if (!cp) 1079769be974SMarcel Holtmann return; 1080769be974SMarcel Holtmann 1081769be974SMarcel Holtmann hci_dev_lock(hdev); 1082769be974SMarcel Holtmann 1083769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1084769be974SMarcel Holtmann if (conn) { 1085769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1086769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1087769be974SMarcel Holtmann hci_conn_put(conn); 1088769be974SMarcel Holtmann } 1089769be974SMarcel Holtmann } 1090769be974SMarcel Holtmann 1091769be974SMarcel Holtmann hci_dev_unlock(hdev); 1092769be974SMarcel Holtmann } 1093769be974SMarcel Holtmann 1094a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 1095a9de9248SMarcel Holtmann { 1096b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 1097b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 1098b6a0dc82SMarcel Holtmann __u16 handle; 1099b6a0dc82SMarcel Holtmann 1100a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1101b6a0dc82SMarcel Holtmann 1102b6a0dc82SMarcel Holtmann if (!status) 1103b6a0dc82SMarcel Holtmann return; 1104b6a0dc82SMarcel Holtmann 1105b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 1106b6a0dc82SMarcel Holtmann if (!cp) 1107b6a0dc82SMarcel Holtmann return; 1108b6a0dc82SMarcel Holtmann 1109b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 1110b6a0dc82SMarcel Holtmann 1111b6a0dc82SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 1112b6a0dc82SMarcel Holtmann 1113b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 1114b6a0dc82SMarcel Holtmann 1115b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 11165a08ecceSAndrei Emeltchenko if (acl) { 11175a08ecceSAndrei Emeltchenko sco = acl->link; 11185a08ecceSAndrei Emeltchenko if (sco) { 1119b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 1120b6a0dc82SMarcel Holtmann 1121b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(sco, status); 1122b6a0dc82SMarcel Holtmann hci_conn_del(sco); 1123b6a0dc82SMarcel Holtmann } 11245a08ecceSAndrei Emeltchenko } 1125b6a0dc82SMarcel Holtmann 1126b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 1127a9de9248SMarcel Holtmann } 1128a9de9248SMarcel Holtmann 1129a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 1130a9de9248SMarcel Holtmann { 1131a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 113204837f64SMarcel Holtmann struct hci_conn *conn; 113304837f64SMarcel Holtmann 1134a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1135a9de9248SMarcel Holtmann 1136a9de9248SMarcel Holtmann if (!status) 1137a9de9248SMarcel Holtmann return; 1138a9de9248SMarcel Holtmann 1139a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 114004837f64SMarcel Holtmann if (!cp) 1141a9de9248SMarcel Holtmann return; 114204837f64SMarcel Holtmann 114304837f64SMarcel Holtmann hci_dev_lock(hdev); 114404837f64SMarcel Holtmann 114504837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1146e73439d8SMarcel Holtmann if (conn) { 114704837f64SMarcel Holtmann clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); 114804837f64SMarcel Holtmann 1149e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 1150e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1151e73439d8SMarcel Holtmann } 1152e73439d8SMarcel Holtmann 115304837f64SMarcel Holtmann hci_dev_unlock(hdev); 115404837f64SMarcel Holtmann } 115504837f64SMarcel Holtmann 1156a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 1157a9de9248SMarcel Holtmann { 1158a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 115904837f64SMarcel Holtmann struct hci_conn *conn; 116004837f64SMarcel Holtmann 1161a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1162a9de9248SMarcel Holtmann 1163a9de9248SMarcel Holtmann if (!status) 1164a9de9248SMarcel Holtmann return; 1165a9de9248SMarcel Holtmann 1166a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 116704837f64SMarcel Holtmann if (!cp) 1168a9de9248SMarcel Holtmann return; 116904837f64SMarcel Holtmann 117004837f64SMarcel Holtmann hci_dev_lock(hdev); 117104837f64SMarcel Holtmann 117204837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1173e73439d8SMarcel Holtmann if (conn) { 117404837f64SMarcel Holtmann clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); 117504837f64SMarcel Holtmann 1176e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 1177e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1178e73439d8SMarcel Holtmann } 1179e73439d8SMarcel Holtmann 118004837f64SMarcel Holtmann hci_dev_unlock(hdev); 118104837f64SMarcel Holtmann } 118204837f64SMarcel Holtmann 1183fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) 1184fcd89c09SVille Tervo { 1185fcd89c09SVille Tervo struct hci_cp_le_create_conn *cp; 1186fcd89c09SVille Tervo struct hci_conn *conn; 1187fcd89c09SVille Tervo 1188fcd89c09SVille Tervo BT_DBG("%s status 0x%x", hdev->name, status); 1189fcd89c09SVille Tervo 1190fcd89c09SVille Tervo cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN); 1191fcd89c09SVille Tervo if (!cp) 1192fcd89c09SVille Tervo return; 1193fcd89c09SVille Tervo 1194fcd89c09SVille Tervo hci_dev_lock(hdev); 1195fcd89c09SVille Tervo 1196fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr); 1197fcd89c09SVille Tervo 1198fcd89c09SVille Tervo BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr), 1199fcd89c09SVille Tervo conn); 1200fcd89c09SVille Tervo 1201fcd89c09SVille Tervo if (status) { 1202fcd89c09SVille Tervo if (conn && conn->state == BT_CONNECT) { 1203fcd89c09SVille Tervo conn->state = BT_CLOSED; 1204fcd89c09SVille Tervo hci_proto_connect_cfm(conn, status); 1205fcd89c09SVille Tervo hci_conn_del(conn); 1206fcd89c09SVille Tervo } 1207fcd89c09SVille Tervo } else { 1208fcd89c09SVille Tervo if (!conn) { 1209fcd89c09SVille Tervo conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr); 1210fcd89c09SVille Tervo if (conn) 1211fcd89c09SVille Tervo conn->out = 1; 1212fcd89c09SVille Tervo else 1213fcd89c09SVille Tervo BT_ERR("No memory for new connection"); 1214fcd89c09SVille Tervo } 1215fcd89c09SVille Tervo } 1216fcd89c09SVille Tervo 1217fcd89c09SVille Tervo hci_dev_unlock(hdev); 1218fcd89c09SVille Tervo } 1219fcd89c09SVille Tervo 12201da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 12211da177e4SLinus Torvalds { 12221da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 12231da177e4SLinus Torvalds 12241da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, status); 12251da177e4SLinus Torvalds 1226314b2381SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags) && 1227314b2381SJohan Hedberg test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) 1228314b2381SJohan Hedberg mgmt_discovering(hdev->id, 0); 1229a9de9248SMarcel Holtmann 123023bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 12316bd57416SMarcel Holtmann 1232a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 12331da177e4SLinus Torvalds } 12341da177e4SLinus Torvalds 12351da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 12361da177e4SLinus Torvalds { 123745bb4bf0SMarcel Holtmann struct inquiry_data data; 1238a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 12391da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 12401da177e4SLinus Torvalds 12411da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 12421da177e4SLinus Torvalds 124345bb4bf0SMarcel Holtmann if (!num_rsp) 124445bb4bf0SMarcel Holtmann return; 124545bb4bf0SMarcel Holtmann 12461da177e4SLinus Torvalds hci_dev_lock(hdev); 124745bb4bf0SMarcel Holtmann 1248314b2381SJohan Hedberg if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) { 1249314b2381SJohan Hedberg 1250314b2381SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 1251314b2381SJohan Hedberg mgmt_discovering(hdev->id, 1); 1252314b2381SJohan Hedberg } 1253314b2381SJohan Hedberg 1254e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 12551da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 12561da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 12571da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 12581da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 12591da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 12601da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 12611da177e4SLinus Torvalds data.rssi = 0x00; 126241a96212SMarcel Holtmann data.ssp_mode = 0x00; 12631da177e4SLinus Torvalds hci_inquiry_cache_update(hdev, &data); 1264e17acd40SJohan Hedberg mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class, 0, 1265e17acd40SJohan Hedberg NULL); 12661da177e4SLinus Torvalds } 126745bb4bf0SMarcel Holtmann 12681da177e4SLinus Torvalds hci_dev_unlock(hdev); 12691da177e4SLinus Torvalds } 12701da177e4SLinus Torvalds 1271a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 12721da177e4SLinus Torvalds { 1273a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 1274a9de9248SMarcel Holtmann struct hci_conn *conn; 12751da177e4SLinus Torvalds 1276a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 127745bb4bf0SMarcel Holtmann 12781da177e4SLinus Torvalds hci_dev_lock(hdev); 127945bb4bf0SMarcel Holtmann 1280a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 12819499237aSMarcel Holtmann if (!conn) { 12829499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 12839499237aSMarcel Holtmann goto unlock; 12849499237aSMarcel Holtmann 12859499237aSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 1286a9de9248SMarcel Holtmann if (!conn) 1287a9de9248SMarcel Holtmann goto unlock; 128845bb4bf0SMarcel Holtmann 12899499237aSMarcel Holtmann conn->type = SCO_LINK; 12909499237aSMarcel Holtmann } 12919499237aSMarcel Holtmann 1292a9de9248SMarcel Holtmann if (!ev->status) { 1293a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 1294769be974SMarcel Holtmann 1295769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 1296769be974SMarcel Holtmann conn->state = BT_CONFIG; 1297769be974SMarcel Holtmann hci_conn_hold(conn); 1298052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1299f7520543SJohan Hedberg mgmt_connected(hdev->id, &ev->bdaddr); 1300769be974SMarcel Holtmann } else 1301a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 1302a9de9248SMarcel Holtmann 13039eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 13047d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 13057d0db0a3SMarcel Holtmann 1306a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 1307a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1308a9de9248SMarcel Holtmann 1309a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 1310a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1311a9de9248SMarcel Holtmann 1312a9de9248SMarcel Holtmann /* Get remote features */ 1313a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 1314a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 1315a9de9248SMarcel Holtmann cp.handle = ev->handle; 1316769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 1317769be974SMarcel Holtmann sizeof(cp), &cp); 131845bb4bf0SMarcel Holtmann } 1319a9de9248SMarcel Holtmann 1320a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 1321a8746417SMarcel Holtmann if (!conn->out && hdev->hci_ver < 3) { 1322a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 1323a9de9248SMarcel Holtmann cp.handle = ev->handle; 1324a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1325a8746417SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, 1326a8746417SMarcel Holtmann sizeof(cp), &cp); 1327a9de9248SMarcel Holtmann } 132817d5c04cSJohan Hedberg } else { 1329a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 133017d5c04cSJohan Hedberg if (conn->type == ACL_LINK) 133117d5c04cSJohan Hedberg mgmt_connect_failed(hdev->id, &ev->bdaddr, ev->status); 133217d5c04cSJohan Hedberg } 133345bb4bf0SMarcel Holtmann 1334e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 1335e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 133645bb4bf0SMarcel Holtmann 1337769be974SMarcel Holtmann if (ev->status) { 1338a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1339a9de9248SMarcel Holtmann hci_conn_del(conn); 1340c89b6e6bSMarcel Holtmann } else if (ev->link_type != ACL_LINK) 1341c89b6e6bSMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1342a9de9248SMarcel Holtmann 1343a9de9248SMarcel Holtmann unlock: 13441da177e4SLinus Torvalds hci_dev_unlock(hdev); 1345a9de9248SMarcel Holtmann 1346a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 13471da177e4SLinus Torvalds } 13481da177e4SLinus Torvalds 13491da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 13501da177e4SLinus Torvalds { 1351a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 13521da177e4SLinus Torvalds int mask = hdev->link_mode; 13531da177e4SLinus Torvalds 1354a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s type 0x%x", hdev->name, 13551da177e4SLinus Torvalds batostr(&ev->bdaddr), ev->link_type); 13561da177e4SLinus Torvalds 13571da177e4SLinus Torvalds mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); 13581da177e4SLinus Torvalds 1359138d22efSSzymon Janc if ((mask & HCI_LM_ACCEPT) && 1360138d22efSSzymon Janc !hci_blacklist_lookup(hdev, &ev->bdaddr)) { 13611da177e4SLinus Torvalds /* Connection accepted */ 1362c7bdd502SMarcel Holtmann struct inquiry_entry *ie; 13631da177e4SLinus Torvalds struct hci_conn *conn; 13641da177e4SLinus Torvalds 13651da177e4SLinus Torvalds hci_dev_lock(hdev); 1366b6a0dc82SMarcel Holtmann 1367cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 1368cc11b9c1SAndrei Emeltchenko if (ie) 1369c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 1370c7bdd502SMarcel Holtmann 13711da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 13721da177e4SLinus Torvalds if (!conn) { 1373cc11b9c1SAndrei Emeltchenko conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); 1374cc11b9c1SAndrei Emeltchenko if (!conn) { 1375893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 13761da177e4SLinus Torvalds hci_dev_unlock(hdev); 13771da177e4SLinus Torvalds return; 13781da177e4SLinus Torvalds } 13791da177e4SLinus Torvalds } 1380b6a0dc82SMarcel Holtmann 13811da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 13821da177e4SLinus Torvalds conn->state = BT_CONNECT; 1383b6a0dc82SMarcel Holtmann 13841da177e4SLinus Torvalds hci_dev_unlock(hdev); 13851da177e4SLinus Torvalds 1386b6a0dc82SMarcel Holtmann if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) { 1387b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 1388b6a0dc82SMarcel Holtmann 13891da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 13901da177e4SLinus Torvalds 13911da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 13921da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 13931da177e4SLinus Torvalds else 13941da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 13951da177e4SLinus Torvalds 1396b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, 1397b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1398b6a0dc82SMarcel Holtmann } else { 1399b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 1400b6a0dc82SMarcel Holtmann 1401b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 1402a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1403b6a0dc82SMarcel Holtmann 1404b6a0dc82SMarcel Holtmann cp.tx_bandwidth = cpu_to_le32(0x00001f40); 1405b6a0dc82SMarcel Holtmann cp.rx_bandwidth = cpu_to_le32(0x00001f40); 1406b6a0dc82SMarcel Holtmann cp.max_latency = cpu_to_le16(0xffff); 1407b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 1408b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 1409b6a0dc82SMarcel Holtmann 1410b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 1411b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1412b6a0dc82SMarcel Holtmann } 14131da177e4SLinus Torvalds } else { 14141da177e4SLinus Torvalds /* Connection rejected */ 14151da177e4SLinus Torvalds struct hci_cp_reject_conn_req cp; 14161da177e4SLinus Torvalds 14171da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 14181da177e4SLinus Torvalds cp.reason = 0x0f; 1419a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 14201da177e4SLinus Torvalds } 14211da177e4SLinus Torvalds } 14221da177e4SLinus Torvalds 14231da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 14241da177e4SLinus Torvalds { 1425a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 142604837f64SMarcel Holtmann struct hci_conn *conn; 14271da177e4SLinus Torvalds 14281da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 14291da177e4SLinus Torvalds 14308962ee74SJohan Hedberg if (ev->status) { 14318962ee74SJohan Hedberg mgmt_disconnect_failed(hdev->id); 14321da177e4SLinus Torvalds return; 14338962ee74SJohan Hedberg } 14341da177e4SLinus Torvalds 14351da177e4SLinus Torvalds hci_dev_lock(hdev); 14361da177e4SLinus Torvalds 143704837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1438f7520543SJohan Hedberg if (!conn) 1439f7520543SJohan Hedberg goto unlock; 1440f7520543SJohan Hedberg 14411da177e4SLinus Torvalds conn->state = BT_CLOSED; 14427d0db0a3SMarcel Holtmann 1443f7520543SJohan Hedberg if (conn->type == ACL_LINK) 1444f7520543SJohan Hedberg mgmt_disconnected(hdev->id, &conn->dst); 1445f7520543SJohan Hedberg 14462950f21aSMarcel Holtmann hci_proto_disconn_cfm(conn, ev->reason); 14471da177e4SLinus Torvalds hci_conn_del(conn); 14481da177e4SLinus Torvalds 1449f7520543SJohan Hedberg unlock: 14501da177e4SLinus Torvalds hci_dev_unlock(hdev); 14511da177e4SLinus Torvalds } 14521da177e4SLinus Torvalds 1453a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1454a9de9248SMarcel Holtmann { 1455a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 1456a9de9248SMarcel Holtmann struct hci_conn *conn; 1457a9de9248SMarcel Holtmann 1458a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1459a9de9248SMarcel Holtmann 1460a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1461a9de9248SMarcel Holtmann 1462a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1463a9de9248SMarcel Holtmann if (conn) { 1464765c2a96SJohan Hedberg if (!ev->status) { 1465a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1466765c2a96SJohan Hedberg conn->sec_level = conn->pending_sec_level; 14672a611692SJohan Hedberg } else { 14682a611692SJohan Hedberg mgmt_auth_failed(hdev->id, &conn->dst, ev->status); 14692a611692SJohan Hedberg } 1470a9de9248SMarcel Holtmann 1471a9de9248SMarcel Holtmann clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); 1472a9de9248SMarcel Holtmann 1473f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1474f8558555SMarcel Holtmann if (!ev->status && hdev->ssp_mode > 0 && 1475f8558555SMarcel Holtmann conn->ssp_mode > 0) { 1476f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1477f8558555SMarcel Holtmann cp.handle = ev->handle; 1478f8558555SMarcel Holtmann cp.encrypt = 0x01; 1479f8558555SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, 1480f8558555SMarcel Holtmann sizeof(cp), &cp); 1481f8558555SMarcel Holtmann } else { 1482f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1483f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1484f8558555SMarcel Holtmann hci_conn_put(conn); 1485f8558555SMarcel Holtmann } 1486052b30b0SMarcel Holtmann } else { 1487a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 1488a9de9248SMarcel Holtmann 1489052b30b0SMarcel Holtmann hci_conn_hold(conn); 1490052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1491052b30b0SMarcel Holtmann hci_conn_put(conn); 1492052b30b0SMarcel Holtmann } 1493052b30b0SMarcel Holtmann 1494a9de9248SMarcel Holtmann if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) { 1495a9de9248SMarcel Holtmann if (!ev->status) { 1496a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1497f8558555SMarcel Holtmann cp.handle = ev->handle; 1498f8558555SMarcel Holtmann cp.encrypt = 0x01; 1499f8558555SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, 1500f8558555SMarcel Holtmann sizeof(cp), &cp); 1501a9de9248SMarcel Holtmann } else { 1502a9de9248SMarcel Holtmann clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); 1503a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 1504a9de9248SMarcel Holtmann } 1505a9de9248SMarcel Holtmann } 1506a9de9248SMarcel Holtmann } 1507a9de9248SMarcel Holtmann 1508a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1509a9de9248SMarcel Holtmann } 1510a9de9248SMarcel Holtmann 1511a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 1512a9de9248SMarcel Holtmann { 1513127178d2SJohan Hedberg struct hci_ev_remote_name *ev = (void *) skb->data; 1514127178d2SJohan Hedberg struct hci_conn *conn; 1515127178d2SJohan Hedberg 1516a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1517a9de9248SMarcel Holtmann 1518a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 1519127178d2SJohan Hedberg 1520127178d2SJohan Hedberg hci_dev_lock(hdev); 1521127178d2SJohan Hedberg 1522a88a9652SJohan Hedberg if (ev->status == 0 && test_bit(HCI_MGMT, &hdev->flags)) 1523a88a9652SJohan Hedberg mgmt_remote_name(hdev->id, &ev->bdaddr, ev->name); 1524a88a9652SJohan Hedberg 1525127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 152679c6c70cSJohan Hedberg if (!conn) 152779c6c70cSJohan Hedberg goto unlock; 152879c6c70cSJohan Hedberg 152979c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 153079c6c70cSJohan Hedberg goto unlock; 153179c6c70cSJohan Hedberg 153279c6c70cSJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { 1533127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1534127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1535127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1536127178d2SJohan Hedberg } 1537127178d2SJohan Hedberg 153879c6c70cSJohan Hedberg unlock: 1539127178d2SJohan Hedberg hci_dev_unlock(hdev); 1540a9de9248SMarcel Holtmann } 1541a9de9248SMarcel Holtmann 1542a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 1543a9de9248SMarcel Holtmann { 1544a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 1545a9de9248SMarcel Holtmann struct hci_conn *conn; 1546a9de9248SMarcel Holtmann 1547a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1548a9de9248SMarcel Holtmann 1549a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1550a9de9248SMarcel Holtmann 1551a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1552a9de9248SMarcel Holtmann if (conn) { 1553a9de9248SMarcel Holtmann if (!ev->status) { 1554ae293196SMarcel Holtmann if (ev->encrypt) { 1555ae293196SMarcel Holtmann /* Encryption implies authentication */ 1556ae293196SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1557a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1558ae293196SMarcel Holtmann } else 1559a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_ENCRYPT; 1560a9de9248SMarcel Holtmann } 1561a9de9248SMarcel Holtmann 1562a9de9248SMarcel Holtmann clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); 1563a9de9248SMarcel Holtmann 1564f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1565f8558555SMarcel Holtmann if (!ev->status) 1566f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1567f8558555SMarcel Holtmann 1568f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1569f8558555SMarcel Holtmann hci_conn_put(conn); 1570f8558555SMarcel Holtmann } else 1571a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 1572a9de9248SMarcel Holtmann } 1573a9de9248SMarcel Holtmann 1574a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1575a9de9248SMarcel Holtmann } 1576a9de9248SMarcel Holtmann 1577a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1578a9de9248SMarcel Holtmann { 1579a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 1580a9de9248SMarcel Holtmann struct hci_conn *conn; 1581a9de9248SMarcel Holtmann 1582a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1583a9de9248SMarcel Holtmann 1584a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1585a9de9248SMarcel Holtmann 1586a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1587a9de9248SMarcel Holtmann if (conn) { 1588a9de9248SMarcel Holtmann if (!ev->status) 1589a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_SECURE; 1590a9de9248SMarcel Holtmann 1591a9de9248SMarcel Holtmann clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); 1592a9de9248SMarcel Holtmann 1593a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 1594a9de9248SMarcel Holtmann } 1595a9de9248SMarcel Holtmann 1596a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1597a9de9248SMarcel Holtmann } 1598a9de9248SMarcel Holtmann 1599a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 1600a9de9248SMarcel Holtmann { 1601a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 1602a9de9248SMarcel Holtmann struct hci_conn *conn; 1603a9de9248SMarcel Holtmann 1604a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1605a9de9248SMarcel Holtmann 1606a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1607a9de9248SMarcel Holtmann 1608a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1609ccd556feSJohan Hedberg if (!conn) 1610ccd556feSJohan Hedberg goto unlock; 1611ccd556feSJohan Hedberg 1612769be974SMarcel Holtmann if (!ev->status) 1613a9de9248SMarcel Holtmann memcpy(conn->features, ev->features, 8); 1614a9de9248SMarcel Holtmann 1615ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 1616ccd556feSJohan Hedberg goto unlock; 1617ccd556feSJohan Hedberg 1618ccd556feSJohan Hedberg if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { 1619769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 1620769be974SMarcel Holtmann cp.handle = ev->handle; 1621769be974SMarcel Holtmann cp.page = 0x01; 1622ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 1623769be974SMarcel Holtmann sizeof(cp), &cp); 1624392599b9SJohan Hedberg goto unlock; 1625392599b9SJohan Hedberg } 1626392599b9SJohan Hedberg 1627127178d2SJohan Hedberg if (!ev->status) { 1628127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 1629127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 1630127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 1631127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 1632127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 1633127178d2SJohan Hedberg } 1634392599b9SJohan Hedberg 1635127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 1636769be974SMarcel Holtmann conn->state = BT_CONNECTED; 1637769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1638769be974SMarcel Holtmann hci_conn_put(conn); 1639769be974SMarcel Holtmann } 1640769be974SMarcel Holtmann 1641ccd556feSJohan Hedberg unlock: 1642a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1643a9de9248SMarcel Holtmann } 1644a9de9248SMarcel Holtmann 1645a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) 1646a9de9248SMarcel Holtmann { 1647a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1648a9de9248SMarcel Holtmann } 1649a9de9248SMarcel Holtmann 1650a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1651a9de9248SMarcel Holtmann { 1652a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1653a9de9248SMarcel Holtmann } 1654a9de9248SMarcel Holtmann 1655a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1656a9de9248SMarcel Holtmann { 1657a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 1658a9de9248SMarcel Holtmann __u16 opcode; 1659a9de9248SMarcel Holtmann 1660a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 1661a9de9248SMarcel Holtmann 1662a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 1663a9de9248SMarcel Holtmann 1664a9de9248SMarcel Holtmann switch (opcode) { 1665a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 1666a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 1667a9de9248SMarcel Holtmann break; 1668a9de9248SMarcel Holtmann 1669a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 1670a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 1671a9de9248SMarcel Holtmann break; 1672a9de9248SMarcel Holtmann 1673a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 1674a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 1675a9de9248SMarcel Holtmann break; 1676a9de9248SMarcel Holtmann 1677a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 1678a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 1679a9de9248SMarcel Holtmann break; 1680a9de9248SMarcel Holtmann 1681e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 1682e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 1683e4e8e37cSMarcel Holtmann break; 1684e4e8e37cSMarcel Holtmann 1685a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 1686a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 1687a9de9248SMarcel Holtmann break; 1688a9de9248SMarcel Holtmann 1689e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 1690e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 1691e4e8e37cSMarcel Holtmann break; 1692e4e8e37cSMarcel Holtmann 1693e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 1694e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 1695e4e8e37cSMarcel Holtmann break; 1696e4e8e37cSMarcel Holtmann 1697a9de9248SMarcel Holtmann case HCI_OP_RESET: 1698a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 1699a9de9248SMarcel Holtmann break; 1700a9de9248SMarcel Holtmann 1701a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 1702a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 1703a9de9248SMarcel Holtmann break; 1704a9de9248SMarcel Holtmann 1705a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 1706a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 1707a9de9248SMarcel Holtmann break; 1708a9de9248SMarcel Holtmann 1709a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 1710a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 1711a9de9248SMarcel Holtmann break; 1712a9de9248SMarcel Holtmann 1713a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 1714a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 1715a9de9248SMarcel Holtmann break; 1716a9de9248SMarcel Holtmann 1717a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 1718a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 1719a9de9248SMarcel Holtmann break; 1720a9de9248SMarcel Holtmann 1721a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 1722a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 1723a9de9248SMarcel Holtmann break; 1724a9de9248SMarcel Holtmann 1725a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 1726a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 1727a9de9248SMarcel Holtmann break; 1728a9de9248SMarcel Holtmann 1729a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 1730a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 1731a9de9248SMarcel Holtmann break; 1732a9de9248SMarcel Holtmann 1733a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 1734a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 1735a9de9248SMarcel Holtmann break; 1736a9de9248SMarcel Holtmann 1737a9de9248SMarcel Holtmann case HCI_OP_HOST_BUFFER_SIZE: 1738a9de9248SMarcel Holtmann hci_cc_host_buffer_size(hdev, skb); 1739a9de9248SMarcel Holtmann break; 1740a9de9248SMarcel Holtmann 1741333140b5SMarcel Holtmann case HCI_OP_READ_SSP_MODE: 1742333140b5SMarcel Holtmann hci_cc_read_ssp_mode(hdev, skb); 1743333140b5SMarcel Holtmann break; 1744333140b5SMarcel Holtmann 1745333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 1746333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 1747333140b5SMarcel Holtmann break; 1748333140b5SMarcel Holtmann 1749a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 1750a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 1751a9de9248SMarcel Holtmann break; 1752a9de9248SMarcel Holtmann 1753a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 1754a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 1755a9de9248SMarcel Holtmann break; 1756a9de9248SMarcel Holtmann 1757a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 1758a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 1759a9de9248SMarcel Holtmann break; 1760a9de9248SMarcel Holtmann 1761a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 1762a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 1763a9de9248SMarcel Holtmann break; 1764a9de9248SMarcel Holtmann 1765a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 1766a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 1767a9de9248SMarcel Holtmann break; 1768a9de9248SMarcel Holtmann 176923bb5763SJohan Hedberg case HCI_OP_WRITE_CA_TIMEOUT: 177023bb5763SJohan Hedberg hci_cc_write_ca_timeout(hdev, skb); 177123bb5763SJohan Hedberg break; 177223bb5763SJohan Hedberg 1773b0916ea0SJohan Hedberg case HCI_OP_DELETE_STORED_LINK_KEY: 1774b0916ea0SJohan Hedberg hci_cc_delete_stored_link_key(hdev, skb); 1775b0916ea0SJohan Hedberg break; 1776b0916ea0SJohan Hedberg 1777d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_MASK: 1778d5859e22SJohan Hedberg hci_cc_set_event_mask(hdev, skb); 1779d5859e22SJohan Hedberg break; 1780d5859e22SJohan Hedberg 1781d5859e22SJohan Hedberg case HCI_OP_WRITE_INQUIRY_MODE: 1782d5859e22SJohan Hedberg hci_cc_write_inquiry_mode(hdev, skb); 1783d5859e22SJohan Hedberg break; 1784d5859e22SJohan Hedberg 1785d5859e22SJohan Hedberg case HCI_OP_READ_INQ_RSP_TX_POWER: 1786d5859e22SJohan Hedberg hci_cc_read_inq_rsp_tx_power(hdev, skb); 1787d5859e22SJohan Hedberg break; 1788d5859e22SJohan Hedberg 1789d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_FLT: 1790d5859e22SJohan Hedberg hci_cc_set_event_flt(hdev, skb); 1791d5859e22SJohan Hedberg break; 1792d5859e22SJohan Hedberg 1793980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_REPLY: 1794980e1a53SJohan Hedberg hci_cc_pin_code_reply(hdev, skb); 1795980e1a53SJohan Hedberg break; 1796980e1a53SJohan Hedberg 1797980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_NEG_REPLY: 1798980e1a53SJohan Hedberg hci_cc_pin_code_neg_reply(hdev, skb); 1799980e1a53SJohan Hedberg break; 1800980e1a53SJohan Hedberg 1801c35938b2SSzymon Janc case HCI_OP_READ_LOCAL_OOB_DATA: 1802c35938b2SSzymon Janc hci_cc_read_local_oob_data_reply(hdev, skb); 1803c35938b2SSzymon Janc break; 1804c35938b2SSzymon Janc 18056ed58ec5SVille Tervo case HCI_OP_LE_READ_BUFFER_SIZE: 18066ed58ec5SVille Tervo hci_cc_le_read_buffer_size(hdev, skb); 18076ed58ec5SVille Tervo break; 18086ed58ec5SVille Tervo 1809a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_REPLY: 1810a5c29683SJohan Hedberg hci_cc_user_confirm_reply(hdev, skb); 1811a5c29683SJohan Hedberg break; 1812a5c29683SJohan Hedberg 1813a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_NEG_REPLY: 1814a5c29683SJohan Hedberg hci_cc_user_confirm_neg_reply(hdev, skb); 1815a5c29683SJohan Hedberg break; 1816a5c29683SJohan Hedberg 1817a9de9248SMarcel Holtmann default: 1818a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 1819a9de9248SMarcel Holtmann break; 1820a9de9248SMarcel Holtmann } 1821a9de9248SMarcel Holtmann 18226bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 18236bd32326SVille Tervo del_timer(&hdev->cmd_timer); 18246bd32326SVille Tervo 1825a9de9248SMarcel Holtmann if (ev->ncmd) { 1826a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 1827a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 1828c78ae283SMarcel Holtmann tasklet_schedule(&hdev->cmd_task); 1829a9de9248SMarcel Holtmann } 1830a9de9248SMarcel Holtmann } 1831a9de9248SMarcel Holtmann 1832a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 1833a9de9248SMarcel Holtmann { 1834a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 1835a9de9248SMarcel Holtmann __u16 opcode; 1836a9de9248SMarcel Holtmann 1837a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 1838a9de9248SMarcel Holtmann 1839a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 1840a9de9248SMarcel Holtmann 1841a9de9248SMarcel Holtmann switch (opcode) { 1842a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 1843a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 1844a9de9248SMarcel Holtmann break; 1845a9de9248SMarcel Holtmann 1846a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 1847a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 1848a9de9248SMarcel Holtmann break; 1849a9de9248SMarcel Holtmann 1850a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 1851a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 1852a9de9248SMarcel Holtmann break; 1853a9de9248SMarcel Holtmann 1854f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 1855f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 1856f8558555SMarcel Holtmann break; 1857f8558555SMarcel Holtmann 1858f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 1859f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 1860f8558555SMarcel Holtmann break; 1861f8558555SMarcel Holtmann 1862a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 1863a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 1864a9de9248SMarcel Holtmann break; 1865a9de9248SMarcel Holtmann 1866769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 1867769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 1868769be974SMarcel Holtmann break; 1869769be974SMarcel Holtmann 1870769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 1871769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 1872769be974SMarcel Holtmann break; 1873769be974SMarcel Holtmann 1874a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 1875a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 1876a9de9248SMarcel Holtmann break; 1877a9de9248SMarcel Holtmann 1878a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 1879a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 1880a9de9248SMarcel Holtmann break; 1881a9de9248SMarcel Holtmann 1882a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 1883a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 1884a9de9248SMarcel Holtmann break; 1885a9de9248SMarcel Holtmann 18868962ee74SJohan Hedberg case HCI_OP_DISCONNECT: 18878962ee74SJohan Hedberg if (ev->status != 0) 18888962ee74SJohan Hedberg mgmt_disconnect_failed(hdev->id); 18898962ee74SJohan Hedberg break; 18908962ee74SJohan Hedberg 1891fcd89c09SVille Tervo case HCI_OP_LE_CREATE_CONN: 1892fcd89c09SVille Tervo hci_cs_le_create_conn(hdev, ev->status); 1893fcd89c09SVille Tervo break; 1894fcd89c09SVille Tervo 1895a9de9248SMarcel Holtmann default: 1896a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 1897a9de9248SMarcel Holtmann break; 1898a9de9248SMarcel Holtmann } 1899a9de9248SMarcel Holtmann 19006bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 19016bd32326SVille Tervo del_timer(&hdev->cmd_timer); 19026bd32326SVille Tervo 190310572132SGustavo F. Padovan if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 1904a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 1905a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 1906c78ae283SMarcel Holtmann tasklet_schedule(&hdev->cmd_task); 1907a9de9248SMarcel Holtmann } 1908a9de9248SMarcel Holtmann } 1909a9de9248SMarcel Holtmann 1910a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 1911a9de9248SMarcel Holtmann { 1912a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 1913a9de9248SMarcel Holtmann struct hci_conn *conn; 1914a9de9248SMarcel Holtmann 1915a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1916a9de9248SMarcel Holtmann 1917a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1918a9de9248SMarcel Holtmann 1919a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 1920a9de9248SMarcel Holtmann if (conn) { 1921a9de9248SMarcel Holtmann if (!ev->status) { 1922a9de9248SMarcel Holtmann if (ev->role) 1923a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_MASTER; 1924a9de9248SMarcel Holtmann else 1925a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_MASTER; 1926a9de9248SMarcel Holtmann } 1927a9de9248SMarcel Holtmann 1928a9de9248SMarcel Holtmann clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend); 1929a9de9248SMarcel Holtmann 1930a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 1931a9de9248SMarcel Holtmann } 1932a9de9248SMarcel Holtmann 1933a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1934a9de9248SMarcel Holtmann } 1935a9de9248SMarcel Holtmann 19361da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 19371da177e4SLinus Torvalds { 1938a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 19391ebb9252SMarcel Holtmann __le16 *ptr; 19401da177e4SLinus Torvalds int i; 19411da177e4SLinus Torvalds 19421da177e4SLinus Torvalds skb_pull(skb, sizeof(*ev)); 19431da177e4SLinus Torvalds 19441da177e4SLinus Torvalds BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 19451da177e4SLinus Torvalds 19461da177e4SLinus Torvalds if (skb->len < ev->num_hndl * 4) { 19471da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 19481da177e4SLinus Torvalds return; 19491da177e4SLinus Torvalds } 19501da177e4SLinus Torvalds 19511da177e4SLinus Torvalds tasklet_disable(&hdev->tx_task); 19521da177e4SLinus Torvalds 19531ebb9252SMarcel Holtmann for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) { 19541da177e4SLinus Torvalds struct hci_conn *conn; 19551da177e4SLinus Torvalds __u16 handle, count; 19561da177e4SLinus Torvalds 195783985319SHarvey Harrison handle = get_unaligned_le16(ptr++); 195883985319SHarvey Harrison count = get_unaligned_le16(ptr++); 19591da177e4SLinus Torvalds 19601da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 19611da177e4SLinus Torvalds if (conn) { 19621da177e4SLinus Torvalds conn->sent -= count; 19631da177e4SLinus Torvalds 19645b7f9909SMarcel Holtmann if (conn->type == ACL_LINK) { 196570f23020SAndrei Emeltchenko hdev->acl_cnt += count; 196670f23020SAndrei Emeltchenko if (hdev->acl_cnt > hdev->acl_pkts) 19671da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 19686ed58ec5SVille Tervo } else if (conn->type == LE_LINK) { 19696ed58ec5SVille Tervo if (hdev->le_pkts) { 19706ed58ec5SVille Tervo hdev->le_cnt += count; 19716ed58ec5SVille Tervo if (hdev->le_cnt > hdev->le_pkts) 19726ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 19736ed58ec5SVille Tervo } else { 19746ed58ec5SVille Tervo hdev->acl_cnt += count; 19756ed58ec5SVille Tervo if (hdev->acl_cnt > hdev->acl_pkts) 19766ed58ec5SVille Tervo hdev->acl_cnt = hdev->acl_pkts; 19776ed58ec5SVille Tervo } 19785b7f9909SMarcel Holtmann } else { 197970f23020SAndrei Emeltchenko hdev->sco_cnt += count; 198070f23020SAndrei Emeltchenko if (hdev->sco_cnt > hdev->sco_pkts) 19815b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 19821da177e4SLinus Torvalds } 19831da177e4SLinus Torvalds } 19841da177e4SLinus Torvalds } 1985a9de9248SMarcel Holtmann 1986c78ae283SMarcel Holtmann tasklet_schedule(&hdev->tx_task); 19871da177e4SLinus Torvalds 19881da177e4SLinus Torvalds tasklet_enable(&hdev->tx_task); 19891da177e4SLinus Torvalds } 19901da177e4SLinus Torvalds 199104837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 19921da177e4SLinus Torvalds { 1993a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 199404837f64SMarcel Holtmann struct hci_conn *conn; 19951da177e4SLinus Torvalds 19961da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 19971da177e4SLinus Torvalds 19981da177e4SLinus Torvalds hci_dev_lock(hdev); 19991da177e4SLinus Torvalds 200004837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 200104837f64SMarcel Holtmann if (conn) { 200204837f64SMarcel Holtmann conn->mode = ev->mode; 200304837f64SMarcel Holtmann conn->interval = __le16_to_cpu(ev->interval); 200404837f64SMarcel Holtmann 200504837f64SMarcel Holtmann if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) { 200604837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 200704837f64SMarcel Holtmann conn->power_save = 1; 200804837f64SMarcel Holtmann else 200904837f64SMarcel Holtmann conn->power_save = 0; 201004837f64SMarcel Holtmann } 2011e73439d8SMarcel Holtmann 2012e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 2013e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 201404837f64SMarcel Holtmann } 201504837f64SMarcel Holtmann 201604837f64SMarcel Holtmann hci_dev_unlock(hdev); 201704837f64SMarcel Holtmann } 201804837f64SMarcel Holtmann 20191da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 20201da177e4SLinus Torvalds { 2021052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 2022052b30b0SMarcel Holtmann struct hci_conn *conn; 2023052b30b0SMarcel Holtmann 2024a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2025052b30b0SMarcel Holtmann 2026052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2027052b30b0SMarcel Holtmann 2028052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 20293d7a9d1cSMarcel Holtmann if (conn && conn->state == BT_CONNECTED) { 2030052b30b0SMarcel Holtmann hci_conn_hold(conn); 2031052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 2032052b30b0SMarcel Holtmann hci_conn_put(conn); 2033052b30b0SMarcel Holtmann } 2034052b30b0SMarcel Holtmann 203503b555e1SJohan Hedberg if (!test_bit(HCI_PAIRABLE, &hdev->flags)) 203603b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 203703b555e1SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 2038582fbe9eSJohan Hedberg else if (test_bit(HCI_MGMT, &hdev->flags)) { 2039a770bb5aSWaldemar Rymarkiewicz u8 secure; 2040a770bb5aSWaldemar Rymarkiewicz 2041a770bb5aSWaldemar Rymarkiewicz if (conn->pending_sec_level == BT_SECURITY_HIGH) 2042a770bb5aSWaldemar Rymarkiewicz secure = 1; 2043a770bb5aSWaldemar Rymarkiewicz else 2044a770bb5aSWaldemar Rymarkiewicz secure = 0; 2045a770bb5aSWaldemar Rymarkiewicz 2046a770bb5aSWaldemar Rymarkiewicz mgmt_pin_code_request(hdev->id, &ev->bdaddr, secure); 2047a770bb5aSWaldemar Rymarkiewicz } 2048980e1a53SJohan Hedberg 2049052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 20501da177e4SLinus Torvalds } 20511da177e4SLinus Torvalds 20521da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 20531da177e4SLinus Torvalds { 205455ed8ca1SJohan Hedberg struct hci_ev_link_key_req *ev = (void *) skb->data; 205555ed8ca1SJohan Hedberg struct hci_cp_link_key_reply cp; 205655ed8ca1SJohan Hedberg struct hci_conn *conn; 205755ed8ca1SJohan Hedberg struct link_key *key; 205855ed8ca1SJohan Hedberg 2059a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 206055ed8ca1SJohan Hedberg 206155ed8ca1SJohan Hedberg if (!test_bit(HCI_LINK_KEYS, &hdev->flags)) 206255ed8ca1SJohan Hedberg return; 206355ed8ca1SJohan Hedberg 206455ed8ca1SJohan Hedberg hci_dev_lock(hdev); 206555ed8ca1SJohan Hedberg 206655ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, &ev->bdaddr); 206755ed8ca1SJohan Hedberg if (!key) { 206855ed8ca1SJohan Hedberg BT_DBG("%s link key not found for %s", hdev->name, 206955ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 207055ed8ca1SJohan Hedberg goto not_found; 207155ed8ca1SJohan Hedberg } 207255ed8ca1SJohan Hedberg 207355ed8ca1SJohan Hedberg BT_DBG("%s found key type %u for %s", hdev->name, key->type, 207455ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 207555ed8ca1SJohan Hedberg 2076b6020ba0SWaldemar Rymarkiewicz if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) && 2077b6020ba0SWaldemar Rymarkiewicz key->type == HCI_LK_DEBUG_COMBINATION) { 207855ed8ca1SJohan Hedberg BT_DBG("%s ignoring debug key", hdev->name); 207955ed8ca1SJohan Hedberg goto not_found; 208055ed8ca1SJohan Hedberg } 208155ed8ca1SJohan Hedberg 208255ed8ca1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 208360b83f57SWaldemar Rymarkiewicz if (conn) { 208460b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_UNAUTH_COMBINATION && 208560b83f57SWaldemar Rymarkiewicz conn->auth_type != 0xff && 208660b83f57SWaldemar Rymarkiewicz (conn->auth_type & 0x01)) { 208755ed8ca1SJohan Hedberg BT_DBG("%s ignoring unauthenticated key", hdev->name); 208855ed8ca1SJohan Hedberg goto not_found; 208955ed8ca1SJohan Hedberg } 209055ed8ca1SJohan Hedberg 209160b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && 209260b83f57SWaldemar Rymarkiewicz conn->pending_sec_level == BT_SECURITY_HIGH) { 209360b83f57SWaldemar Rymarkiewicz BT_DBG("%s ignoring key unauthenticated for high \ 209460b83f57SWaldemar Rymarkiewicz security", hdev->name); 209560b83f57SWaldemar Rymarkiewicz goto not_found; 209660b83f57SWaldemar Rymarkiewicz } 209760b83f57SWaldemar Rymarkiewicz 209860b83f57SWaldemar Rymarkiewicz conn->key_type = key->type; 209960b83f57SWaldemar Rymarkiewicz conn->pin_length = key->pin_len; 210060b83f57SWaldemar Rymarkiewicz } 210160b83f57SWaldemar Rymarkiewicz 210255ed8ca1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 210355ed8ca1SJohan Hedberg memcpy(cp.link_key, key->val, 16); 210455ed8ca1SJohan Hedberg 210555ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 210655ed8ca1SJohan Hedberg 210755ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 210855ed8ca1SJohan Hedberg 210955ed8ca1SJohan Hedberg return; 211055ed8ca1SJohan Hedberg 211155ed8ca1SJohan Hedberg not_found: 211255ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 211355ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 21141da177e4SLinus Torvalds } 21151da177e4SLinus Torvalds 21161da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 21171da177e4SLinus Torvalds { 2118052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 2119052b30b0SMarcel Holtmann struct hci_conn *conn; 212055ed8ca1SJohan Hedberg u8 pin_len = 0; 2121052b30b0SMarcel Holtmann 2122a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2123052b30b0SMarcel Holtmann 2124052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2125052b30b0SMarcel Holtmann 2126052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2127052b30b0SMarcel Holtmann if (conn) { 2128052b30b0SMarcel Holtmann hci_conn_hold(conn); 2129052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2130980e1a53SJohan Hedberg pin_len = conn->pin_length; 213113d39315SWaldemar Rymarkiewicz 213213d39315SWaldemar Rymarkiewicz if (ev->key_type != HCI_LK_CHANGED_COMBINATION) 213313d39315SWaldemar Rymarkiewicz conn->key_type = ev->key_type; 213413d39315SWaldemar Rymarkiewicz 2135052b30b0SMarcel Holtmann hci_conn_put(conn); 2136052b30b0SMarcel Holtmann } 2137052b30b0SMarcel Holtmann 213855ed8ca1SJohan Hedberg if (test_bit(HCI_LINK_KEYS, &hdev->flags)) 213955ed8ca1SJohan Hedberg hci_add_link_key(hdev, 1, &ev->bdaddr, ev->link_key, 214055ed8ca1SJohan Hedberg ev->key_type, pin_len); 214155ed8ca1SJohan Hedberg 2142052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 21431da177e4SLinus Torvalds } 21441da177e4SLinus Torvalds 214504837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 214604837f64SMarcel Holtmann { 2147a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 214804837f64SMarcel Holtmann struct hci_conn *conn; 214904837f64SMarcel Holtmann 215004837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 215104837f64SMarcel Holtmann 215204837f64SMarcel Holtmann hci_dev_lock(hdev); 215304837f64SMarcel Holtmann 215404837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 21551da177e4SLinus Torvalds if (conn && !ev->status) { 21561da177e4SLinus Torvalds struct inquiry_entry *ie; 21571da177e4SLinus Torvalds 2158cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2159cc11b9c1SAndrei Emeltchenko if (ie) { 21601da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 21611da177e4SLinus Torvalds ie->timestamp = jiffies; 21621da177e4SLinus Torvalds } 21631da177e4SLinus Torvalds } 21641da177e4SLinus Torvalds 21651da177e4SLinus Torvalds hci_dev_unlock(hdev); 21661da177e4SLinus Torvalds } 21671da177e4SLinus Torvalds 2168a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2169a8746417SMarcel Holtmann { 2170a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 2171a8746417SMarcel Holtmann struct hci_conn *conn; 2172a8746417SMarcel Holtmann 2173a8746417SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2174a8746417SMarcel Holtmann 2175a8746417SMarcel Holtmann hci_dev_lock(hdev); 2176a8746417SMarcel Holtmann 2177a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2178a8746417SMarcel Holtmann if (conn && !ev->status) 2179a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 2180a8746417SMarcel Holtmann 2181a8746417SMarcel Holtmann hci_dev_unlock(hdev); 2182a8746417SMarcel Holtmann } 2183a8746417SMarcel Holtmann 218485a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 218585a1e930SMarcel Holtmann { 2186a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 218785a1e930SMarcel Holtmann struct inquiry_entry *ie; 218885a1e930SMarcel Holtmann 218985a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 219085a1e930SMarcel Holtmann 219185a1e930SMarcel Holtmann hci_dev_lock(hdev); 219285a1e930SMarcel Holtmann 2193cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2194cc11b9c1SAndrei Emeltchenko if (ie) { 219585a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 219685a1e930SMarcel Holtmann ie->timestamp = jiffies; 219785a1e930SMarcel Holtmann } 219885a1e930SMarcel Holtmann 219985a1e930SMarcel Holtmann hci_dev_unlock(hdev); 220085a1e930SMarcel Holtmann } 220185a1e930SMarcel Holtmann 2202a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb) 2203a9de9248SMarcel Holtmann { 2204a9de9248SMarcel Holtmann struct inquiry_data data; 2205a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2206a9de9248SMarcel Holtmann 2207a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2208a9de9248SMarcel Holtmann 2209a9de9248SMarcel Holtmann if (!num_rsp) 2210a9de9248SMarcel Holtmann return; 2211a9de9248SMarcel Holtmann 2212a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2213a9de9248SMarcel Holtmann 2214314b2381SJohan Hedberg if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) { 2215314b2381SJohan Hedberg 2216314b2381SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 2217314b2381SJohan Hedberg mgmt_discovering(hdev->id, 1); 2218314b2381SJohan Hedberg } 2219314b2381SJohan Hedberg 2220a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 2221138d22efSSzymon Janc struct inquiry_info_with_rssi_and_pscan_mode *info; 2222138d22efSSzymon Janc info = (void *) (skb->data + 1); 2223a9de9248SMarcel Holtmann 2224e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2225a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2226a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2227a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2228a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 2229a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2230a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2231a9de9248SMarcel Holtmann data.rssi = info->rssi; 223241a96212SMarcel Holtmann data.ssp_mode = 0x00; 2233a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 2234e17acd40SJohan Hedberg mgmt_device_found(hdev->id, &info->bdaddr, 2235e17acd40SJohan Hedberg info->dev_class, info->rssi, 2236e17acd40SJohan Hedberg NULL); 2237a9de9248SMarcel Holtmann } 2238a9de9248SMarcel Holtmann } else { 2239a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 2240a9de9248SMarcel Holtmann 2241e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2242a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2243a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2244a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2245a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2246a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2247a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2248a9de9248SMarcel Holtmann data.rssi = info->rssi; 224941a96212SMarcel Holtmann data.ssp_mode = 0x00; 2250a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 2251e17acd40SJohan Hedberg mgmt_device_found(hdev->id, &info->bdaddr, 2252e17acd40SJohan Hedberg info->dev_class, info->rssi, 2253e17acd40SJohan Hedberg NULL); 2254a9de9248SMarcel Holtmann } 2255a9de9248SMarcel Holtmann } 2256a9de9248SMarcel Holtmann 2257a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2258a9de9248SMarcel Holtmann } 2259a9de9248SMarcel Holtmann 2260a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 2261a9de9248SMarcel Holtmann { 226241a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 226341a96212SMarcel Holtmann struct hci_conn *conn; 226441a96212SMarcel Holtmann 2265a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 226641a96212SMarcel Holtmann 226741a96212SMarcel Holtmann hci_dev_lock(hdev); 226841a96212SMarcel Holtmann 226941a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2270ccd556feSJohan Hedberg if (!conn) 2271ccd556feSJohan Hedberg goto unlock; 2272ccd556feSJohan Hedberg 2273769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 227441a96212SMarcel Holtmann struct inquiry_entry *ie; 227541a96212SMarcel Holtmann 2276cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2277cc11b9c1SAndrei Emeltchenko if (ie) 227841a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 227941a96212SMarcel Holtmann 228041a96212SMarcel Holtmann conn->ssp_mode = (ev->features[0] & 0x01); 228141a96212SMarcel Holtmann } 228241a96212SMarcel Holtmann 2283ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2284ccd556feSJohan Hedberg goto unlock; 2285ccd556feSJohan Hedberg 2286127178d2SJohan Hedberg if (!ev->status) { 2287127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2288127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2289127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2290127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2291127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2292127178d2SJohan Hedberg } 2293392599b9SJohan Hedberg 2294127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2295769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2296769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2297769be974SMarcel Holtmann hci_conn_put(conn); 2298769be974SMarcel Holtmann } 2299769be974SMarcel Holtmann 2300ccd556feSJohan Hedberg unlock: 230141a96212SMarcel Holtmann hci_dev_unlock(hdev); 2302a9de9248SMarcel Holtmann } 2303a9de9248SMarcel Holtmann 2304a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2305a9de9248SMarcel Holtmann { 2306b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 2307b6a0dc82SMarcel Holtmann struct hci_conn *conn; 2308b6a0dc82SMarcel Holtmann 2309b6a0dc82SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2310b6a0dc82SMarcel Holtmann 2311b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 2312b6a0dc82SMarcel Holtmann 2313b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 23149dc0a3afSMarcel Holtmann if (!conn) { 23159dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 23169dc0a3afSMarcel Holtmann goto unlock; 23179dc0a3afSMarcel Holtmann 23189dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 2319b6a0dc82SMarcel Holtmann if (!conn) 2320b6a0dc82SMarcel Holtmann goto unlock; 2321b6a0dc82SMarcel Holtmann 23229dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 23239dc0a3afSMarcel Holtmann } 23249dc0a3afSMarcel Holtmann 2325732547f9SMarcel Holtmann switch (ev->status) { 2326732547f9SMarcel Holtmann case 0x00: 2327732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 2328732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 2329732547f9SMarcel Holtmann 23309eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 2331732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 2332732547f9SMarcel Holtmann break; 2333732547f9SMarcel Holtmann 2334705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 2335732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 23361038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 2337732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 2338732547f9SMarcel Holtmann if (conn->out && conn->attempt < 2) { 2339efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 2340efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 2341efc7688bSMarcel Holtmann hci_setup_sync(conn, conn->link->handle); 2342efc7688bSMarcel Holtmann goto unlock; 2343efc7688bSMarcel Holtmann } 2344732547f9SMarcel Holtmann /* fall through */ 2345efc7688bSMarcel Holtmann 2346732547f9SMarcel Holtmann default: 2347b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 2348732547f9SMarcel Holtmann break; 2349732547f9SMarcel Holtmann } 2350b6a0dc82SMarcel Holtmann 2351b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2352b6a0dc82SMarcel Holtmann if (ev->status) 2353b6a0dc82SMarcel Holtmann hci_conn_del(conn); 2354b6a0dc82SMarcel Holtmann 2355b6a0dc82SMarcel Holtmann unlock: 2356b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 2357a9de9248SMarcel Holtmann } 2358a9de9248SMarcel Holtmann 2359a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) 2360a9de9248SMarcel Holtmann { 2361a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2362a9de9248SMarcel Holtmann } 2363a9de9248SMarcel Holtmann 236404837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) 236504837f64SMarcel Holtmann { 2366a9de9248SMarcel Holtmann struct hci_ev_sniff_subrate *ev = (void *) skb->data; 236704837f64SMarcel Holtmann 236804837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 236904837f64SMarcel Holtmann } 237004837f64SMarcel Holtmann 2371a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 2372a9de9248SMarcel Holtmann { 2373a9de9248SMarcel Holtmann struct inquiry_data data; 2374a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 2375a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2376a9de9248SMarcel Holtmann 2377a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2378a9de9248SMarcel Holtmann 2379a9de9248SMarcel Holtmann if (!num_rsp) 2380a9de9248SMarcel Holtmann return; 2381a9de9248SMarcel Holtmann 2382314b2381SJohan Hedberg if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags)) { 2383314b2381SJohan Hedberg 2384314b2381SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->flags)) 2385314b2381SJohan Hedberg mgmt_discovering(hdev->id, 1); 2386314b2381SJohan Hedberg } 2387314b2381SJohan Hedberg 2388a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2389a9de9248SMarcel Holtmann 2390e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2391a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2392a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2393a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2394a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2395a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2396a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2397a9de9248SMarcel Holtmann data.rssi = info->rssi; 239841a96212SMarcel Holtmann data.ssp_mode = 0x01; 2399a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 2400e17acd40SJohan Hedberg mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class, 2401e17acd40SJohan Hedberg info->rssi, info->data); 2402a9de9248SMarcel Holtmann } 2403a9de9248SMarcel Holtmann 2404a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2405a9de9248SMarcel Holtmann } 2406a9de9248SMarcel Holtmann 240717fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn) 240817fa4b9dSJohan Hedberg { 240917fa4b9dSJohan Hedberg /* If remote requests dedicated bonding follow that lead */ 241017fa4b9dSJohan Hedberg if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) { 241117fa4b9dSJohan Hedberg /* If both remote and local IO capabilities allow MITM 241217fa4b9dSJohan Hedberg * protection then require it, otherwise don't */ 241317fa4b9dSJohan Hedberg if (conn->remote_cap == 0x03 || conn->io_capability == 0x03) 241417fa4b9dSJohan Hedberg return 0x02; 241517fa4b9dSJohan Hedberg else 241617fa4b9dSJohan Hedberg return 0x03; 241717fa4b9dSJohan Hedberg } 241817fa4b9dSJohan Hedberg 241917fa4b9dSJohan Hedberg /* If remote requests no-bonding follow that lead */ 242017fa4b9dSJohan Hedberg if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01) 242158797bf7SWaldemar Rymarkiewicz return conn->remote_auth | (conn->auth_type & 0x01); 242217fa4b9dSJohan Hedberg 242317fa4b9dSJohan Hedberg return conn->auth_type; 242417fa4b9dSJohan Hedberg } 242517fa4b9dSJohan Hedberg 24260493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 24270493684eSMarcel Holtmann { 24280493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 24290493684eSMarcel Holtmann struct hci_conn *conn; 24300493684eSMarcel Holtmann 24310493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 24320493684eSMarcel Holtmann 24330493684eSMarcel Holtmann hci_dev_lock(hdev); 24340493684eSMarcel Holtmann 24350493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 243603b555e1SJohan Hedberg if (!conn) 243703b555e1SJohan Hedberg goto unlock; 243803b555e1SJohan Hedberg 24390493684eSMarcel Holtmann hci_conn_hold(conn); 24400493684eSMarcel Holtmann 244103b555e1SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->flags)) 244203b555e1SJohan Hedberg goto unlock; 244303b555e1SJohan Hedberg 244403b555e1SJohan Hedberg if (test_bit(HCI_PAIRABLE, &hdev->flags) || 244503b555e1SJohan Hedberg (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 244617fa4b9dSJohan Hedberg struct hci_cp_io_capability_reply cp; 244717fa4b9dSJohan Hedberg 244817fa4b9dSJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 244917fa4b9dSJohan Hedberg cp.capability = conn->io_capability; 245017fa4b9dSJohan Hedberg cp.authentication = hci_get_auth_req(conn); 245117fa4b9dSJohan Hedberg 2452ce85ee13SSzymon Janc if ((conn->out == 0x01 || conn->remote_oob == 0x01) && 2453ce85ee13SSzymon Janc hci_find_remote_oob_data(hdev, &conn->dst)) 2454ce85ee13SSzymon Janc cp.oob_data = 0x01; 2455ce85ee13SSzymon Janc else 2456ce85ee13SSzymon Janc cp.oob_data = 0x00; 2457ce85ee13SSzymon Janc 245817fa4b9dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, 245917fa4b9dSJohan Hedberg sizeof(cp), &cp); 246003b555e1SJohan Hedberg } else { 246103b555e1SJohan Hedberg struct hci_cp_io_capability_neg_reply cp; 246203b555e1SJohan Hedberg 246303b555e1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 2464be77159cSJohan Hedberg cp.reason = 0x18; /* Pairing not allowed */ 246503b555e1SJohan Hedberg 246603b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 246703b555e1SJohan Hedberg sizeof(cp), &cp); 246803b555e1SJohan Hedberg } 246903b555e1SJohan Hedberg 247003b555e1SJohan Hedberg unlock: 247103b555e1SJohan Hedberg hci_dev_unlock(hdev); 247203b555e1SJohan Hedberg } 247303b555e1SJohan Hedberg 247403b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 247503b555e1SJohan Hedberg { 247603b555e1SJohan Hedberg struct hci_ev_io_capa_reply *ev = (void *) skb->data; 247703b555e1SJohan Hedberg struct hci_conn *conn; 247803b555e1SJohan Hedberg 247903b555e1SJohan Hedberg BT_DBG("%s", hdev->name); 248003b555e1SJohan Hedberg 248103b555e1SJohan Hedberg hci_dev_lock(hdev); 248203b555e1SJohan Hedberg 248303b555e1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 248403b555e1SJohan Hedberg if (!conn) 248503b555e1SJohan Hedberg goto unlock; 248603b555e1SJohan Hedberg 248703b555e1SJohan Hedberg conn->remote_cap = ev->capability; 248803b555e1SJohan Hedberg conn->remote_oob = ev->oob_data; 248903b555e1SJohan Hedberg conn->remote_auth = ev->authentication; 249003b555e1SJohan Hedberg 249103b555e1SJohan Hedberg unlock: 24920493684eSMarcel Holtmann hci_dev_unlock(hdev); 24930493684eSMarcel Holtmann } 24940493684eSMarcel Holtmann 2495a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev, 2496a5c29683SJohan Hedberg struct sk_buff *skb) 2497a5c29683SJohan Hedberg { 2498a5c29683SJohan Hedberg struct hci_ev_user_confirm_req *ev = (void *) skb->data; 249955bc1a37SJohan Hedberg int loc_mitm, rem_mitm, confirm_hint = 0; 25007a828908SJohan Hedberg struct hci_conn *conn; 2501a5c29683SJohan Hedberg 2502a5c29683SJohan Hedberg BT_DBG("%s", hdev->name); 2503a5c29683SJohan Hedberg 2504a5c29683SJohan Hedberg hci_dev_lock(hdev); 2505a5c29683SJohan Hedberg 25067a828908SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->flags)) 25077a828908SJohan Hedberg goto unlock; 25087a828908SJohan Hedberg 25097a828908SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 25107a828908SJohan Hedberg if (!conn) 25117a828908SJohan Hedberg goto unlock; 25127a828908SJohan Hedberg 25137a828908SJohan Hedberg loc_mitm = (conn->auth_type & 0x01); 25147a828908SJohan Hedberg rem_mitm = (conn->remote_auth & 0x01); 25157a828908SJohan Hedberg 25167a828908SJohan Hedberg /* If we require MITM but the remote device can't provide that 25177a828908SJohan Hedberg * (it has NoInputNoOutput) then reject the confirmation 25187a828908SJohan Hedberg * request. The only exception is when we're dedicated bonding 25197a828908SJohan Hedberg * initiators (connect_cfm_cb set) since then we always have the MITM 25207a828908SJohan Hedberg * bit set. */ 25217a828908SJohan Hedberg if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) { 25227a828908SJohan Hedberg BT_DBG("Rejecting request: remote device can't provide MITM"); 25237a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, 25247a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 25257a828908SJohan Hedberg goto unlock; 25267a828908SJohan Hedberg } 25277a828908SJohan Hedberg 25287a828908SJohan Hedberg /* If no side requires MITM protection; auto-accept */ 25297a828908SJohan Hedberg if ((!loc_mitm || conn->remote_cap == 0x03) && 25307a828908SJohan Hedberg (!rem_mitm || conn->io_capability == 0x03)) { 253155bc1a37SJohan Hedberg 253255bc1a37SJohan Hedberg /* If we're not the initiators request authorization to 253355bc1a37SJohan Hedberg * proceed from user space (mgmt_user_confirm with 253455bc1a37SJohan Hedberg * confirm_hint set to 1). */ 253555bc1a37SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { 253655bc1a37SJohan Hedberg BT_DBG("Confirming auto-accept as acceptor"); 253755bc1a37SJohan Hedberg confirm_hint = 1; 253855bc1a37SJohan Hedberg goto confirm; 253955bc1a37SJohan Hedberg } 254055bc1a37SJohan Hedberg 25419f61656aSJohan Hedberg BT_DBG("Auto-accept of user confirmation with %ums delay", 25429f61656aSJohan Hedberg hdev->auto_accept_delay); 25439f61656aSJohan Hedberg 25449f61656aSJohan Hedberg if (hdev->auto_accept_delay > 0) { 25459f61656aSJohan Hedberg int delay = msecs_to_jiffies(hdev->auto_accept_delay); 25469f61656aSJohan Hedberg mod_timer(&conn->auto_accept_timer, jiffies + delay); 25479f61656aSJohan Hedberg goto unlock; 25489f61656aSJohan Hedberg } 25499f61656aSJohan Hedberg 25507a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, 25517a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 25527a828908SJohan Hedberg goto unlock; 25537a828908SJohan Hedberg } 25547a828908SJohan Hedberg 255555bc1a37SJohan Hedberg confirm: 255655bc1a37SJohan Hedberg mgmt_user_confirm_request(hdev->id, &ev->bdaddr, ev->passkey, 255755bc1a37SJohan Hedberg confirm_hint); 2558a5c29683SJohan Hedberg 25597a828908SJohan Hedberg unlock: 2560a5c29683SJohan Hedberg hci_dev_unlock(hdev); 2561a5c29683SJohan Hedberg } 2562a5c29683SJohan Hedberg 25630493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 25640493684eSMarcel Holtmann { 25650493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 25660493684eSMarcel Holtmann struct hci_conn *conn; 25670493684eSMarcel Holtmann 25680493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 25690493684eSMarcel Holtmann 25700493684eSMarcel Holtmann hci_dev_lock(hdev); 25710493684eSMarcel Holtmann 25720493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 25732a611692SJohan Hedberg if (!conn) 25742a611692SJohan Hedberg goto unlock; 25752a611692SJohan Hedberg 25762a611692SJohan Hedberg /* To avoid duplicate auth_failed events to user space we check 25772a611692SJohan Hedberg * the HCI_CONN_AUTH_PEND flag which will be set if we 25782a611692SJohan Hedberg * initiated the authentication. A traditional auth_complete 25792a611692SJohan Hedberg * event gets always produced as initiator and is also mapped to 25802a611692SJohan Hedberg * the mgmt_auth_failed event */ 25812a611692SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0) 25822a611692SJohan Hedberg mgmt_auth_failed(hdev->id, &conn->dst, ev->status); 25832a611692SJohan Hedberg 25840493684eSMarcel Holtmann hci_conn_put(conn); 25850493684eSMarcel Holtmann 25862a611692SJohan Hedberg unlock: 25870493684eSMarcel Holtmann hci_dev_unlock(hdev); 25880493684eSMarcel Holtmann } 25890493684eSMarcel Holtmann 259041a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 259141a96212SMarcel Holtmann { 259241a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 259341a96212SMarcel Holtmann struct inquiry_entry *ie; 259441a96212SMarcel Holtmann 259541a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 259641a96212SMarcel Holtmann 259741a96212SMarcel Holtmann hci_dev_lock(hdev); 259841a96212SMarcel Holtmann 2599cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2600cc11b9c1SAndrei Emeltchenko if (ie) 260141a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 260241a96212SMarcel Holtmann 260341a96212SMarcel Holtmann hci_dev_unlock(hdev); 260441a96212SMarcel Holtmann } 260541a96212SMarcel Holtmann 26062763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev, 26072763eda6SSzymon Janc struct sk_buff *skb) 26082763eda6SSzymon Janc { 26092763eda6SSzymon Janc struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; 26102763eda6SSzymon Janc struct oob_data *data; 26112763eda6SSzymon Janc 26122763eda6SSzymon Janc BT_DBG("%s", hdev->name); 26132763eda6SSzymon Janc 26142763eda6SSzymon Janc hci_dev_lock(hdev); 26152763eda6SSzymon Janc 2616e1ba1f15SSzymon Janc if (!test_bit(HCI_MGMT, &hdev->flags)) 2617e1ba1f15SSzymon Janc goto unlock; 2618e1ba1f15SSzymon Janc 26192763eda6SSzymon Janc data = hci_find_remote_oob_data(hdev, &ev->bdaddr); 26202763eda6SSzymon Janc if (data) { 26212763eda6SSzymon Janc struct hci_cp_remote_oob_data_reply cp; 26222763eda6SSzymon Janc 26232763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 26242763eda6SSzymon Janc memcpy(cp.hash, data->hash, sizeof(cp.hash)); 26252763eda6SSzymon Janc memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); 26262763eda6SSzymon Janc 26272763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), 26282763eda6SSzymon Janc &cp); 26292763eda6SSzymon Janc } else { 26302763eda6SSzymon Janc struct hci_cp_remote_oob_data_neg_reply cp; 26312763eda6SSzymon Janc 26322763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 26332763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), 26342763eda6SSzymon Janc &cp); 26352763eda6SSzymon Janc } 26362763eda6SSzymon Janc 2637e1ba1f15SSzymon Janc unlock: 26382763eda6SSzymon Janc hci_dev_unlock(hdev); 26392763eda6SSzymon Janc } 26402763eda6SSzymon Janc 2641fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2642fcd89c09SVille Tervo { 2643fcd89c09SVille Tervo struct hci_ev_le_conn_complete *ev = (void *) skb->data; 2644fcd89c09SVille Tervo struct hci_conn *conn; 2645fcd89c09SVille Tervo 2646fcd89c09SVille Tervo BT_DBG("%s status %d", hdev->name, ev->status); 2647fcd89c09SVille Tervo 2648fcd89c09SVille Tervo hci_dev_lock(hdev); 2649fcd89c09SVille Tervo 2650fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr); 2651b62f328bSVille Tervo if (!conn) { 2652b62f328bSVille Tervo conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); 2653b62f328bSVille Tervo if (!conn) { 2654b62f328bSVille Tervo BT_ERR("No memory for new connection"); 2655b62f328bSVille Tervo hci_dev_unlock(hdev); 2656b62f328bSVille Tervo return; 2657b62f328bSVille Tervo } 2658b62f328bSVille Tervo } 2659fcd89c09SVille Tervo 2660fcd89c09SVille Tervo if (ev->status) { 2661fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 2662fcd89c09SVille Tervo conn->state = BT_CLOSED; 2663fcd89c09SVille Tervo hci_conn_del(conn); 2664fcd89c09SVille Tervo goto unlock; 2665fcd89c09SVille Tervo } 2666fcd89c09SVille Tervo 2667fcd89c09SVille Tervo conn->handle = __le16_to_cpu(ev->handle); 2668fcd89c09SVille Tervo conn->state = BT_CONNECTED; 2669fcd89c09SVille Tervo 2670fcd89c09SVille Tervo hci_conn_hold_device(conn); 2671fcd89c09SVille Tervo hci_conn_add_sysfs(conn); 2672fcd89c09SVille Tervo 2673fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 2674fcd89c09SVille Tervo 2675fcd89c09SVille Tervo unlock: 2676fcd89c09SVille Tervo hci_dev_unlock(hdev); 2677fcd89c09SVille Tervo } 2678fcd89c09SVille Tervo 2679fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 2680fcd89c09SVille Tervo { 2681fcd89c09SVille Tervo struct hci_ev_le_meta *le_ev = (void *) skb->data; 2682fcd89c09SVille Tervo 2683fcd89c09SVille Tervo skb_pull(skb, sizeof(*le_ev)); 2684fcd89c09SVille Tervo 2685fcd89c09SVille Tervo switch (le_ev->subevent) { 2686fcd89c09SVille Tervo case HCI_EV_LE_CONN_COMPLETE: 2687fcd89c09SVille Tervo hci_le_conn_complete_evt(hdev, skb); 2688fcd89c09SVille Tervo break; 2689fcd89c09SVille Tervo 2690fcd89c09SVille Tervo default: 2691fcd89c09SVille Tervo break; 2692fcd89c09SVille Tervo } 2693fcd89c09SVille Tervo } 2694fcd89c09SVille Tervo 26951da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 26961da177e4SLinus Torvalds { 2697a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 2698a9de9248SMarcel Holtmann __u8 event = hdr->evt; 26991da177e4SLinus Torvalds 27001da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 27011da177e4SLinus Torvalds 2702a9de9248SMarcel Holtmann switch (event) { 27031da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 27041da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 27051da177e4SLinus Torvalds break; 27061da177e4SLinus Torvalds 27071da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 27081da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 27091da177e4SLinus Torvalds break; 27101da177e4SLinus Torvalds 2711a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 2712a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 271321d9e30eSMarcel Holtmann break; 271421d9e30eSMarcel Holtmann 27151da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 27161da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 27171da177e4SLinus Torvalds break; 27181da177e4SLinus Torvalds 27191da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 27201da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 27211da177e4SLinus Torvalds break; 27221da177e4SLinus Torvalds 27231da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 27241da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 27251da177e4SLinus Torvalds break; 27261da177e4SLinus Torvalds 2727a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 2728a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 2729a9de9248SMarcel Holtmann break; 2730a9de9248SMarcel Holtmann 27311da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 27321da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 27331da177e4SLinus Torvalds break; 27341da177e4SLinus Torvalds 2735a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 2736a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 2737a9de9248SMarcel Holtmann break; 2738a9de9248SMarcel Holtmann 2739a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 2740a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 2741a9de9248SMarcel Holtmann break; 2742a9de9248SMarcel Holtmann 2743a9de9248SMarcel Holtmann case HCI_EV_REMOTE_VERSION: 2744a9de9248SMarcel Holtmann hci_remote_version_evt(hdev, skb); 2745a9de9248SMarcel Holtmann break; 2746a9de9248SMarcel Holtmann 2747a9de9248SMarcel Holtmann case HCI_EV_QOS_SETUP_COMPLETE: 2748a9de9248SMarcel Holtmann hci_qos_setup_complete_evt(hdev, skb); 2749a9de9248SMarcel Holtmann break; 2750a9de9248SMarcel Holtmann 2751a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 2752a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 2753a9de9248SMarcel Holtmann break; 2754a9de9248SMarcel Holtmann 2755a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 2756a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 2757a9de9248SMarcel Holtmann break; 2758a9de9248SMarcel Holtmann 2759a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 2760a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 2761a9de9248SMarcel Holtmann break; 2762a9de9248SMarcel Holtmann 2763a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 2764a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 2765a9de9248SMarcel Holtmann break; 2766a9de9248SMarcel Holtmann 2767a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 2768a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 27691da177e4SLinus Torvalds break; 27701da177e4SLinus Torvalds 27711da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 27721da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 27731da177e4SLinus Torvalds break; 27741da177e4SLinus Torvalds 27751da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 27761da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 27771da177e4SLinus Torvalds break; 27781da177e4SLinus Torvalds 27791da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 27801da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 27811da177e4SLinus Torvalds break; 27821da177e4SLinus Torvalds 27831da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 27841da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 27851da177e4SLinus Torvalds break; 27861da177e4SLinus Torvalds 2787a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 2788a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 2789a8746417SMarcel Holtmann break; 2790a8746417SMarcel Holtmann 279185a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 279285a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 279385a1e930SMarcel Holtmann break; 279485a1e930SMarcel Holtmann 2795a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 2796a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 2797a9de9248SMarcel Holtmann break; 2798a9de9248SMarcel Holtmann 2799a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 2800a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 2801a9de9248SMarcel Holtmann break; 2802a9de9248SMarcel Holtmann 2803a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 2804a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 2805a9de9248SMarcel Holtmann break; 2806a9de9248SMarcel Holtmann 2807a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_CHANGED: 2808a9de9248SMarcel Holtmann hci_sync_conn_changed_evt(hdev, skb); 2809a9de9248SMarcel Holtmann break; 2810a9de9248SMarcel Holtmann 281104837f64SMarcel Holtmann case HCI_EV_SNIFF_SUBRATE: 281204837f64SMarcel Holtmann hci_sniff_subrate_evt(hdev, skb); 281304837f64SMarcel Holtmann break; 281404837f64SMarcel Holtmann 2815a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 2816a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 28171da177e4SLinus Torvalds break; 28181da177e4SLinus Torvalds 28190493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 28200493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 28210493684eSMarcel Holtmann break; 28220493684eSMarcel Holtmann 282303b555e1SJohan Hedberg case HCI_EV_IO_CAPA_REPLY: 282403b555e1SJohan Hedberg hci_io_capa_reply_evt(hdev, skb); 282503b555e1SJohan Hedberg break; 282603b555e1SJohan Hedberg 2827a5c29683SJohan Hedberg case HCI_EV_USER_CONFIRM_REQUEST: 2828a5c29683SJohan Hedberg hci_user_confirm_request_evt(hdev, skb); 2829a5c29683SJohan Hedberg break; 2830a5c29683SJohan Hedberg 28310493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 28320493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 28330493684eSMarcel Holtmann break; 28340493684eSMarcel Holtmann 283541a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 283641a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 283741a96212SMarcel Holtmann break; 283841a96212SMarcel Holtmann 2839fcd89c09SVille Tervo case HCI_EV_LE_META: 2840fcd89c09SVille Tervo hci_le_meta_evt(hdev, skb); 2841fcd89c09SVille Tervo break; 2842fcd89c09SVille Tervo 28432763eda6SSzymon Janc case HCI_EV_REMOTE_OOB_DATA_REQUEST: 28442763eda6SSzymon Janc hci_remote_oob_data_request_evt(hdev, skb); 28452763eda6SSzymon Janc break; 28462763eda6SSzymon Janc 28471da177e4SLinus Torvalds default: 2848a9de9248SMarcel Holtmann BT_DBG("%s event 0x%x", hdev->name, event); 28491da177e4SLinus Torvalds break; 28501da177e4SLinus Torvalds } 28511da177e4SLinus Torvalds 28521da177e4SLinus Torvalds kfree_skb(skb); 28531da177e4SLinus Torvalds hdev->stat.evt_rx++; 28541da177e4SLinus Torvalds } 28551da177e4SLinus Torvalds 28561da177e4SLinus Torvalds /* Generate internal stack event */ 28571da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data) 28581da177e4SLinus Torvalds { 28591da177e4SLinus Torvalds struct hci_event_hdr *hdr; 28601da177e4SLinus Torvalds struct hci_ev_stack_internal *ev; 28611da177e4SLinus Torvalds struct sk_buff *skb; 28621da177e4SLinus Torvalds 28631da177e4SLinus Torvalds skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC); 28641da177e4SLinus Torvalds if (!skb) 28651da177e4SLinus Torvalds return; 28661da177e4SLinus Torvalds 28671da177e4SLinus Torvalds hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE); 28681da177e4SLinus Torvalds hdr->evt = HCI_EV_STACK_INTERNAL; 28691da177e4SLinus Torvalds hdr->plen = sizeof(*ev) + dlen; 28701da177e4SLinus Torvalds 28711da177e4SLinus Torvalds ev = (void *) skb_put(skb, sizeof(*ev) + dlen); 28721da177e4SLinus Torvalds ev->type = type; 28731da177e4SLinus Torvalds memcpy(ev->data, data, dlen); 28741da177e4SLinus Torvalds 2875576c7d85SMarcel Holtmann bt_cb(skb)->incoming = 1; 2876a61bbcf2SPatrick McHardy __net_timestamp(skb); 2877576c7d85SMarcel Holtmann 28780d48d939SMarcel Holtmann bt_cb(skb)->pkt_type = HCI_EVENT_PKT; 28791da177e4SLinus Torvalds skb->dev = (void *) hdev; 2880eec8d2bcSJohan Hedberg hci_send_to_sock(hdev, skb, NULL); 28811da177e4SLinus Torvalds kfree_skb(skb); 28821da177e4SLinus Torvalds } 2883