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 <net/sock.h> 391da177e4SLinus Torvalds 4070f23020SAndrei Emeltchenko #include <linux/uaccess.h> 411da177e4SLinus Torvalds #include <asm/unaligned.h> 421da177e4SLinus Torvalds 431da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h> 441da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h> 451da177e4SLinus Torvalds 461da177e4SLinus Torvalds /* Handle HCI Event packets */ 471da177e4SLinus Torvalds 48a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb) 491da177e4SLinus Torvalds { 50a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 511da177e4SLinus Torvalds 52a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 531da177e4SLinus Torvalds 54e6d465cbSAndre Guedes if (status) { 55e6d465cbSAndre Guedes hci_dev_lock(hdev); 56e6d465cbSAndre Guedes mgmt_stop_discovery_failed(hdev, status); 57e6d465cbSAndre Guedes hci_dev_unlock(hdev); 58a9de9248SMarcel Holtmann return; 59e6d465cbSAndre Guedes } 601da177e4SLinus Torvalds 6189352e7dSAndre Guedes clear_bit(HCI_INQUIRY, &hdev->flags); 6289352e7dSAndre Guedes 6356e5cb86SJohan Hedberg hci_dev_lock(hdev); 64ff9ef578SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 6556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 66a9de9248SMarcel Holtmann 6723bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status); 68a9de9248SMarcel Holtmann 69a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 701da177e4SLinus Torvalds } 716bd57416SMarcel Holtmann 72a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 731da177e4SLinus Torvalds { 74a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 75a9de9248SMarcel Holtmann 76a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 77a9de9248SMarcel Holtmann 78a9de9248SMarcel Holtmann if (status) 79a9de9248SMarcel Holtmann return; 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); 193d23264a8SAndre Guedes 194a297e97cSJohan Hedberg /* Reset all non-persistent flags */ 1959f8ce967SJohan Hedberg hdev->dev_flags &= ~(BIT(HCI_LE_SCAN) | BIT(HCI_PENDING_CLASS)); 19669775ff6SAndre Guedes 19769775ff6SAndre Guedes hdev->discovery.state = DISCOVERY_STOPPED; 198a9de9248SMarcel Holtmann } 199a9de9248SMarcel Holtmann 200a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) 201a9de9248SMarcel Holtmann { 202a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 2031da177e4SLinus Torvalds void *sent; 2041da177e4SLinus Torvalds 205a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 2061da177e4SLinus Torvalds 207a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); 2081da177e4SLinus Torvalds if (!sent) 209a9de9248SMarcel Holtmann return; 2101da177e4SLinus Torvalds 21156e5cb86SJohan Hedberg hci_dev_lock(hdev); 21256e5cb86SJohan Hedberg 213f51d5b24SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 214f51d5b24SJohan Hedberg mgmt_set_local_name_complete(hdev, sent, status); 21528cc7bdeSJohan Hedberg else if (!status) 21628cc7bdeSJohan Hedberg memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); 217f51d5b24SJohan Hedberg 21856e5cb86SJohan Hedberg hci_dev_unlock(hdev); 2193159d384SJohan Hedberg 2203159d384SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status); 221a9de9248SMarcel Holtmann } 222a9de9248SMarcel Holtmann 223a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) 224a9de9248SMarcel Holtmann { 225a9de9248SMarcel Holtmann struct hci_rp_read_local_name *rp = (void *) skb->data; 226a9de9248SMarcel Holtmann 227a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 228a9de9248SMarcel Holtmann 229a9de9248SMarcel Holtmann if (rp->status) 230a9de9248SMarcel Holtmann return; 231a9de9248SMarcel Holtmann 232db99b5fcSJohan Hedberg if (test_bit(HCI_SETUP, &hdev->dev_flags)) 2331f6c6378SJohan Hedberg memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); 234a9de9248SMarcel Holtmann } 235a9de9248SMarcel Holtmann 236a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) 237a9de9248SMarcel Holtmann { 238a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 239a9de9248SMarcel Holtmann void *sent; 240a9de9248SMarcel Holtmann 241a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 242a9de9248SMarcel Holtmann 243a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); 244a9de9248SMarcel Holtmann if (!sent) 245a9de9248SMarcel Holtmann return; 2461da177e4SLinus Torvalds 2471da177e4SLinus Torvalds if (!status) { 248a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 249a9de9248SMarcel Holtmann 2501da177e4SLinus Torvalds if (param == AUTH_ENABLED) 2511da177e4SLinus Torvalds set_bit(HCI_AUTH, &hdev->flags); 2521da177e4SLinus Torvalds else 2531da177e4SLinus Torvalds clear_bit(HCI_AUTH, &hdev->flags); 2541da177e4SLinus Torvalds } 255a9de9248SMarcel Holtmann 25633ef95edSJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 25733ef95edSJohan Hedberg mgmt_auth_enable_complete(hdev, status); 25833ef95edSJohan Hedberg 25923bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status); 260a9de9248SMarcel Holtmann } 2611da177e4SLinus Torvalds 262a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) 263a9de9248SMarcel Holtmann { 264a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 265a9de9248SMarcel Holtmann void *sent; 266a9de9248SMarcel Holtmann 267a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 268a9de9248SMarcel Holtmann 269a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); 2701da177e4SLinus Torvalds if (!sent) 271a9de9248SMarcel Holtmann return; 2721da177e4SLinus Torvalds 2731da177e4SLinus Torvalds if (!status) { 274a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 275a9de9248SMarcel Holtmann 2761da177e4SLinus Torvalds if (param) 2771da177e4SLinus Torvalds set_bit(HCI_ENCRYPT, &hdev->flags); 2781da177e4SLinus Torvalds else 2791da177e4SLinus Torvalds clear_bit(HCI_ENCRYPT, &hdev->flags); 2801da177e4SLinus Torvalds } 281a9de9248SMarcel Holtmann 28223bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status); 2831da177e4SLinus Torvalds } 2841da177e4SLinus Torvalds 285a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) 286a9de9248SMarcel Holtmann { 28736f7fc7eSJohan Hedberg __u8 param, status = *((__u8 *) skb->data); 28836f7fc7eSJohan Hedberg int old_pscan, old_iscan; 289a9de9248SMarcel Holtmann void *sent; 2901da177e4SLinus Torvalds 291a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 292a9de9248SMarcel Holtmann 293a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); 2941da177e4SLinus Torvalds if (!sent) 295a9de9248SMarcel Holtmann return; 2961da177e4SLinus Torvalds 29736f7fc7eSJohan Hedberg param = *((__u8 *) sent); 298a9de9248SMarcel Holtmann 29956e5cb86SJohan Hedberg hci_dev_lock(hdev); 30056e5cb86SJohan Hedberg 3012d7cee58SJohan Hedberg if (status != 0) { 302744cf19eSJohan Hedberg mgmt_write_scan_failed(hdev, param, status); 3032d7cee58SJohan Hedberg hdev->discov_timeout = 0; 3042d7cee58SJohan Hedberg goto done; 3052d7cee58SJohan Hedberg } 3062d7cee58SJohan Hedberg 3079fbcbb45SJohan Hedberg old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags); 3089fbcbb45SJohan Hedberg old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags); 309a9de9248SMarcel Holtmann 31073f22f62SJohan Hedberg if (param & SCAN_INQUIRY) { 3111da177e4SLinus Torvalds set_bit(HCI_ISCAN, &hdev->flags); 3129fbcbb45SJohan Hedberg if (!old_iscan) 313744cf19eSJohan Hedberg mgmt_discoverable(hdev, 1); 31416ab91abSJohan Hedberg if (hdev->discov_timeout > 0) { 31516ab91abSJohan Hedberg int to = msecs_to_jiffies(hdev->discov_timeout * 1000); 31616ab91abSJohan Hedberg queue_delayed_work(hdev->workqueue, &hdev->discov_off, 31716ab91abSJohan Hedberg to); 31816ab91abSJohan Hedberg } 3199fbcbb45SJohan Hedberg } else if (old_iscan) 320744cf19eSJohan Hedberg mgmt_discoverable(hdev, 0); 3211da177e4SLinus Torvalds 3229fbcbb45SJohan Hedberg if (param & SCAN_PAGE) { 3231da177e4SLinus Torvalds set_bit(HCI_PSCAN, &hdev->flags); 3249fbcbb45SJohan Hedberg if (!old_pscan) 325744cf19eSJohan Hedberg mgmt_connectable(hdev, 1); 3269fbcbb45SJohan Hedberg } else if (old_pscan) 327744cf19eSJohan Hedberg mgmt_connectable(hdev, 0); 328a9de9248SMarcel Holtmann 32936f7fc7eSJohan Hedberg done: 33056e5cb86SJohan Hedberg hci_dev_unlock(hdev); 33123bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status); 3321da177e4SLinus Torvalds } 3331da177e4SLinus Torvalds 334a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 335a9de9248SMarcel Holtmann { 336a9de9248SMarcel Holtmann struct hci_rp_read_class_of_dev *rp = (void *) skb->data; 337a9de9248SMarcel Holtmann 338a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 339a9de9248SMarcel Holtmann 340a9de9248SMarcel Holtmann if (rp->status) 341a9de9248SMarcel Holtmann return; 342a9de9248SMarcel Holtmann 343a9de9248SMarcel Holtmann memcpy(hdev->dev_class, rp->dev_class, 3); 344a9de9248SMarcel Holtmann 345a9de9248SMarcel Holtmann BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, 346a9de9248SMarcel Holtmann hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); 347a9de9248SMarcel Holtmann } 348a9de9248SMarcel Holtmann 349a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 350a9de9248SMarcel Holtmann { 351a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 352a9de9248SMarcel Holtmann void *sent; 353a9de9248SMarcel Holtmann 354a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 355a9de9248SMarcel Holtmann 356a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); 357a9de9248SMarcel Holtmann if (!sent) 358a9de9248SMarcel Holtmann return; 359a9de9248SMarcel Holtmann 3607f9a903cSMarcel Holtmann hci_dev_lock(hdev); 3617f9a903cSMarcel Holtmann 3627f9a903cSMarcel Holtmann if (status == 0) 363a9de9248SMarcel Holtmann memcpy(hdev->dev_class, sent, 3); 3647f9a903cSMarcel Holtmann 3657f9a903cSMarcel Holtmann if (test_bit(HCI_MGMT, &hdev->dev_flags)) 3667f9a903cSMarcel Holtmann mgmt_set_class_of_dev_complete(hdev, sent, status); 3677f9a903cSMarcel Holtmann 3687f9a903cSMarcel Holtmann hci_dev_unlock(hdev); 369a9de9248SMarcel Holtmann } 370a9de9248SMarcel Holtmann 371a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 372a9de9248SMarcel Holtmann { 373a9de9248SMarcel Holtmann struct hci_rp_read_voice_setting *rp = (void *) skb->data; 374a9de9248SMarcel Holtmann __u16 setting; 375a9de9248SMarcel Holtmann 376a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 377a9de9248SMarcel Holtmann 378a9de9248SMarcel Holtmann if (rp->status) 379a9de9248SMarcel Holtmann return; 380a9de9248SMarcel Holtmann 381a9de9248SMarcel Holtmann setting = __le16_to_cpu(rp->voice_setting); 382a9de9248SMarcel Holtmann 383a9de9248SMarcel Holtmann if (hdev->voice_setting == setting) 384a9de9248SMarcel Holtmann return; 385a9de9248SMarcel Holtmann 386a9de9248SMarcel Holtmann hdev->voice_setting = setting; 387a9de9248SMarcel Holtmann 388a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 389a9de9248SMarcel Holtmann 3903c54711cSGustavo F. Padovan if (hdev->notify) 391a9de9248SMarcel Holtmann hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 392a9de9248SMarcel Holtmann } 393a9de9248SMarcel Holtmann 394a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 395a9de9248SMarcel Holtmann { 396a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 397f383f275SMarcel Holtmann __u16 setting; 398a9de9248SMarcel Holtmann void *sent; 399a9de9248SMarcel Holtmann 400a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 401a9de9248SMarcel Holtmann 402f383f275SMarcel Holtmann if (status) 403f383f275SMarcel Holtmann return; 404f383f275SMarcel Holtmann 405a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); 406a9de9248SMarcel Holtmann if (!sent) 407a9de9248SMarcel Holtmann return; 408a9de9248SMarcel Holtmann 409f383f275SMarcel Holtmann setting = get_unaligned_le16(sent); 4101da177e4SLinus Torvalds 411f383f275SMarcel Holtmann if (hdev->voice_setting == setting) 412f383f275SMarcel Holtmann return; 413f383f275SMarcel Holtmann 4141da177e4SLinus Torvalds hdev->voice_setting = setting; 4151da177e4SLinus Torvalds 416a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 4171da177e4SLinus Torvalds 4183c54711cSGustavo F. Padovan if (hdev->notify) 4191da177e4SLinus Torvalds hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 4201da177e4SLinus Torvalds } 4211da177e4SLinus Torvalds 422a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 4231da177e4SLinus Torvalds { 424a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 4251da177e4SLinus Torvalds 426a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 4271da177e4SLinus Torvalds 42823bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status); 4291143e5a6SMarcel Holtmann } 4301143e5a6SMarcel Holtmann 431333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 432333140b5SMarcel Holtmann { 433333140b5SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 434333140b5SMarcel Holtmann void *sent; 435333140b5SMarcel Holtmann 436333140b5SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 437333140b5SMarcel Holtmann 438333140b5SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); 439333140b5SMarcel Holtmann if (!sent) 440333140b5SMarcel Holtmann return; 441333140b5SMarcel Holtmann 442c0ecddc2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 443c0ecddc2SJohan Hedberg mgmt_ssp_enable_complete(hdev, *((u8 *) sent), status); 444c0ecddc2SJohan Hedberg else if (!status) { 44584bde9d6SJohan Hedberg if (*((u8 *) sent)) 44684bde9d6SJohan Hedberg set_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 44784bde9d6SJohan Hedberg else 44884bde9d6SJohan Hedberg clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 449c0ecddc2SJohan Hedberg } 450333140b5SMarcel Holtmann } 451333140b5SMarcel Holtmann 452d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev) 453d5859e22SJohan Hedberg { 454d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 455d5859e22SJohan Hedberg return 2; 456d5859e22SJohan Hedberg 457d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 458d5859e22SJohan Hedberg return 1; 459d5859e22SJohan Hedberg 460d5859e22SJohan Hedberg if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 && 461d5859e22SJohan Hedberg hdev->lmp_subver == 0x0757) 462d5859e22SJohan Hedberg return 1; 463d5859e22SJohan Hedberg 464d5859e22SJohan Hedberg if (hdev->manufacturer == 15) { 465d5859e22SJohan Hedberg if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963) 466d5859e22SJohan Hedberg return 1; 467d5859e22SJohan Hedberg if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963) 468d5859e22SJohan Hedberg return 1; 469d5859e22SJohan Hedberg if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965) 470d5859e22SJohan Hedberg return 1; 471d5859e22SJohan Hedberg } 472d5859e22SJohan Hedberg 473d5859e22SJohan Hedberg if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 && 474d5859e22SJohan Hedberg hdev->lmp_subver == 0x1805) 475d5859e22SJohan Hedberg return 1; 476d5859e22SJohan Hedberg 477d5859e22SJohan Hedberg return 0; 478d5859e22SJohan Hedberg } 479d5859e22SJohan Hedberg 480d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev) 481d5859e22SJohan Hedberg { 482d5859e22SJohan Hedberg u8 mode; 483d5859e22SJohan Hedberg 484d5859e22SJohan Hedberg mode = hci_get_inquiry_mode(hdev); 485d5859e22SJohan Hedberg 486d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode); 487d5859e22SJohan Hedberg } 488d5859e22SJohan Hedberg 489d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev) 490d5859e22SJohan Hedberg { 491d5859e22SJohan Hedberg /* The second byte is 0xff instead of 0x9f (two reserved bits 492d5859e22SJohan Hedberg * disabled) since a Broadcom 1.2 dongle doesn't respond to the 493d5859e22SJohan Hedberg * command otherwise */ 494d5859e22SJohan Hedberg u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 }; 495d5859e22SJohan Hedberg 4966de6c18dSVille Tervo /* CSR 1.1 dongles does not accept any bitfield so don't try to set 4976de6c18dSVille Tervo * any event mask for pre 1.2 devices */ 4985a13b095SAndrei Emeltchenko if (hdev->hci_ver < BLUETOOTH_VER_1_2) 4996de6c18dSVille Tervo return; 5006de6c18dSVille Tervo 501d5859e22SJohan Hedberg events[4] |= 0x01; /* Flow Specification Complete */ 502d5859e22SJohan Hedberg events[4] |= 0x02; /* Inquiry Result with RSSI */ 503d5859e22SJohan Hedberg events[4] |= 0x04; /* Read Remote Extended Features Complete */ 504d5859e22SJohan Hedberg events[5] |= 0x08; /* Synchronous Connection Complete */ 505d5859e22SJohan Hedberg events[5] |= 0x10; /* Synchronous Connection Changed */ 506d5859e22SJohan Hedberg 507d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 508d5859e22SJohan Hedberg events[4] |= 0x04; /* Inquiry Result with RSSI */ 509d5859e22SJohan Hedberg 510d5859e22SJohan Hedberg if (hdev->features[5] & LMP_SNIFF_SUBR) 511d5859e22SJohan Hedberg events[5] |= 0x20; /* Sniff Subrating */ 512d5859e22SJohan Hedberg 513d5859e22SJohan Hedberg if (hdev->features[5] & LMP_PAUSE_ENC) 514d5859e22SJohan Hedberg events[5] |= 0x80; /* Encryption Key Refresh Complete */ 515d5859e22SJohan Hedberg 516d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 517d5859e22SJohan Hedberg events[5] |= 0x40; /* Extended Inquiry Result */ 518d5859e22SJohan Hedberg 519d5859e22SJohan Hedberg if (hdev->features[6] & LMP_NO_FLUSH) 520d5859e22SJohan Hedberg events[7] |= 0x01; /* Enhanced Flush Complete */ 521d5859e22SJohan Hedberg 522d5859e22SJohan Hedberg if (hdev->features[7] & LMP_LSTO) 523d5859e22SJohan Hedberg events[6] |= 0x80; /* Link Supervision Timeout Changed */ 524d5859e22SJohan Hedberg 525d5859e22SJohan Hedberg if (hdev->features[6] & LMP_SIMPLE_PAIR) { 526d5859e22SJohan Hedberg events[6] |= 0x01; /* IO Capability Request */ 527d5859e22SJohan Hedberg events[6] |= 0x02; /* IO Capability Response */ 528d5859e22SJohan Hedberg events[6] |= 0x04; /* User Confirmation Request */ 529d5859e22SJohan Hedberg events[6] |= 0x08; /* User Passkey Request */ 530d5859e22SJohan Hedberg events[6] |= 0x10; /* Remote OOB Data Request */ 531d5859e22SJohan Hedberg events[6] |= 0x20; /* Simple Pairing Complete */ 532d5859e22SJohan Hedberg events[7] |= 0x04; /* User Passkey Notification */ 533d5859e22SJohan Hedberg events[7] |= 0x08; /* Keypress Notification */ 534d5859e22SJohan Hedberg events[7] |= 0x10; /* Remote Host Supported 535d5859e22SJohan Hedberg * Features Notification */ 536d5859e22SJohan Hedberg } 537d5859e22SJohan Hedberg 538d5859e22SJohan Hedberg if (hdev->features[4] & LMP_LE) 539d5859e22SJohan Hedberg events[7] |= 0x20; /* LE Meta-Event */ 540d5859e22SJohan Hedberg 541d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); 542d5859e22SJohan Hedberg } 543d5859e22SJohan Hedberg 544d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev) 545d5859e22SJohan Hedberg { 546e61ef499SAndrei Emeltchenko if (hdev->dev_type != HCI_BREDR) 547e61ef499SAndrei Emeltchenko return; 548e61ef499SAndrei Emeltchenko 549d5859e22SJohan Hedberg hci_setup_event_mask(hdev); 550d5859e22SJohan Hedberg 551d095c1ebSAndrei Emeltchenko if (hdev->hci_ver > BLUETOOTH_VER_1_1) 552d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); 553d5859e22SJohan Hedberg 55454d04dbbSJohan Hedberg if (hdev->features[6] & LMP_SIMPLE_PAIR) { 55554d04dbbSJohan Hedberg if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { 556d5859e22SJohan Hedberg u8 mode = 0x01; 55754d04dbbSJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 55854d04dbbSJohan Hedberg sizeof(mode), &mode); 55954d04dbbSJohan Hedberg } else { 56054d04dbbSJohan Hedberg struct hci_cp_write_eir cp; 56154d04dbbSJohan Hedberg 56254d04dbbSJohan Hedberg memset(hdev->eir, 0, sizeof(hdev->eir)); 56354d04dbbSJohan Hedberg memset(&cp, 0, sizeof(cp)); 56454d04dbbSJohan Hedberg 56554d04dbbSJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp); 56654d04dbbSJohan Hedberg } 567d5859e22SJohan Hedberg } 568d5859e22SJohan Hedberg 569d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 570d5859e22SJohan Hedberg hci_setup_inquiry_mode(hdev); 571d5859e22SJohan Hedberg 572d5859e22SJohan Hedberg if (hdev->features[7] & LMP_INQ_TX_PWR) 573d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL); 574971e3a4bSAndre Guedes 575971e3a4bSAndre Guedes if (hdev->features[7] & LMP_EXTFEATURES) { 576971e3a4bSAndre Guedes struct hci_cp_read_local_ext_features cp; 577971e3a4bSAndre Guedes 578971e3a4bSAndre Guedes cp.page = 0x01; 57904124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), 58004124681SGustavo F. Padovan &cp); 581971e3a4bSAndre Guedes } 582e6100a25SAndre Guedes 58347990ea0SJohan Hedberg if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) { 58447990ea0SJohan Hedberg u8 enable = 1; 58504124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable), 58604124681SGustavo F. Padovan &enable); 58747990ea0SJohan Hedberg } 588d5859e22SJohan Hedberg } 589d5859e22SJohan Hedberg 590a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) 591a9de9248SMarcel Holtmann { 592a9de9248SMarcel Holtmann struct hci_rp_read_local_version *rp = (void *) skb->data; 5931143e5a6SMarcel Holtmann 594a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 5951143e5a6SMarcel Holtmann 596a9de9248SMarcel Holtmann if (rp->status) 59728b8df77SAndrei Emeltchenko goto done; 5981143e5a6SMarcel Holtmann 599a9de9248SMarcel Holtmann hdev->hci_ver = rp->hci_ver; 600e4e8e37cSMarcel Holtmann hdev->hci_rev = __le16_to_cpu(rp->hci_rev); 601d5859e22SJohan Hedberg hdev->lmp_ver = rp->lmp_ver; 602e4e8e37cSMarcel Holtmann hdev->manufacturer = __le16_to_cpu(rp->manufacturer); 603d5859e22SJohan Hedberg hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); 6041da177e4SLinus Torvalds 605a9de9248SMarcel Holtmann BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name, 606a9de9248SMarcel Holtmann hdev->manufacturer, 607a9de9248SMarcel Holtmann hdev->hci_ver, hdev->hci_rev); 608d5859e22SJohan Hedberg 609d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags)) 610d5859e22SJohan Hedberg hci_setup(hdev); 61128b8df77SAndrei Emeltchenko 61228b8df77SAndrei Emeltchenko done: 61328b8df77SAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status); 614d5859e22SJohan Hedberg } 615d5859e22SJohan Hedberg 616d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev) 617d5859e22SJohan Hedberg { 618d5859e22SJohan Hedberg u16 link_policy = 0; 619d5859e22SJohan Hedberg 620d5859e22SJohan Hedberg if (hdev->features[0] & LMP_RSWITCH) 621d5859e22SJohan Hedberg link_policy |= HCI_LP_RSWITCH; 622d5859e22SJohan Hedberg if (hdev->features[0] & LMP_HOLD) 623d5859e22SJohan Hedberg link_policy |= HCI_LP_HOLD; 624d5859e22SJohan Hedberg if (hdev->features[0] & LMP_SNIFF) 625d5859e22SJohan Hedberg link_policy |= HCI_LP_SNIFF; 626d5859e22SJohan Hedberg if (hdev->features[1] & LMP_PARK) 627d5859e22SJohan Hedberg link_policy |= HCI_LP_PARK; 628d5859e22SJohan Hedberg 629d5859e22SJohan Hedberg link_policy = cpu_to_le16(link_policy); 63004124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(link_policy), 63104124681SGustavo F. Padovan &link_policy); 6321da177e4SLinus Torvalds } 6331da177e4SLinus Torvalds 634a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb) 635a9de9248SMarcel Holtmann { 636a9de9248SMarcel Holtmann struct hci_rp_read_local_commands *rp = (void *) skb->data; 637a9de9248SMarcel Holtmann 638a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 639a9de9248SMarcel Holtmann 640a9de9248SMarcel Holtmann if (rp->status) 641d5859e22SJohan Hedberg goto done; 642a9de9248SMarcel Holtmann 643a9de9248SMarcel Holtmann memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); 644d5859e22SJohan Hedberg 645d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10)) 646d5859e22SJohan Hedberg hci_setup_link_policy(hdev); 647d5859e22SJohan Hedberg 648d5859e22SJohan Hedberg done: 649d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status); 650a9de9248SMarcel Holtmann } 651a9de9248SMarcel Holtmann 652a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb) 653a9de9248SMarcel Holtmann { 654a9de9248SMarcel Holtmann struct hci_rp_read_local_features *rp = (void *) skb->data; 655a9de9248SMarcel Holtmann 656a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 657a9de9248SMarcel Holtmann 658a9de9248SMarcel Holtmann if (rp->status) 659a9de9248SMarcel Holtmann return; 660a9de9248SMarcel Holtmann 661a9de9248SMarcel Holtmann memcpy(hdev->features, rp->features, 8); 6621da177e4SLinus Torvalds 6631da177e4SLinus Torvalds /* Adjust default settings according to features 6641da177e4SLinus Torvalds * supported by device. */ 665a9de9248SMarcel Holtmann 6661da177e4SLinus Torvalds if (hdev->features[0] & LMP_3SLOT) 6671da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM3 | HCI_DH3); 6681da177e4SLinus Torvalds 6691da177e4SLinus Torvalds if (hdev->features[0] & LMP_5SLOT) 6701da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM5 | HCI_DH5); 6711da177e4SLinus Torvalds 6725b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV2) { 6731da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV2); 6745b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV2); 6755b7f9909SMarcel Holtmann } 6761da177e4SLinus Torvalds 6775b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV3) { 6781da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV3); 6795b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV3); 6805b7f9909SMarcel Holtmann } 6815b7f9909SMarcel Holtmann 6825b7f9909SMarcel Holtmann if (hdev->features[3] & LMP_ESCO) 6835b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV3); 6845b7f9909SMarcel Holtmann 6855b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV4) 6865b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV4); 6875b7f9909SMarcel Holtmann 6885b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV5) 6895b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV5); 6901da177e4SLinus Torvalds 691efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_2M) 692efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV3); 693efc7688bSMarcel Holtmann 694efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_3M) 695efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_3EV3); 696efc7688bSMarcel Holtmann 697efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_3S_ESCO) 698efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); 699efc7688bSMarcel Holtmann 700a9de9248SMarcel Holtmann BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, 701a9de9248SMarcel Holtmann hdev->features[0], hdev->features[1], 702a9de9248SMarcel Holtmann hdev->features[2], hdev->features[3], 703a9de9248SMarcel Holtmann hdev->features[4], hdev->features[5], 704a9de9248SMarcel Holtmann hdev->features[6], hdev->features[7]); 7051da177e4SLinus Torvalds } 7061da177e4SLinus Torvalds 7078f984dfaSJohan Hedberg static void hci_set_le_support(struct hci_dev *hdev) 7088f984dfaSJohan Hedberg { 7098f984dfaSJohan Hedberg struct hci_cp_write_le_host_supported cp; 7108f984dfaSJohan Hedberg 7118f984dfaSJohan Hedberg memset(&cp, 0, sizeof(cp)); 7128f984dfaSJohan Hedberg 7138f984dfaSJohan Hedberg if (enable_le && test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { 7148f984dfaSJohan Hedberg cp.le = 1; 7158f984dfaSJohan Hedberg cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR); 7168f984dfaSJohan Hedberg } 7178f984dfaSJohan Hedberg 7188f984dfaSJohan Hedberg if (cp.le != !!(hdev->host_features[0] & LMP_HOST_LE)) 71904124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), 72004124681SGustavo F. Padovan &cp); 7218f984dfaSJohan Hedberg } 7228f984dfaSJohan Hedberg 723971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev, 724971e3a4bSAndre Guedes struct sk_buff *skb) 725971e3a4bSAndre Guedes { 726971e3a4bSAndre Guedes struct hci_rp_read_local_ext_features *rp = (void *) skb->data; 727971e3a4bSAndre Guedes 728971e3a4bSAndre Guedes BT_DBG("%s status 0x%x", hdev->name, rp->status); 729971e3a4bSAndre Guedes 730971e3a4bSAndre Guedes if (rp->status) 7318f984dfaSJohan Hedberg goto done; 732971e3a4bSAndre Guedes 733b5b32b65SAndre Guedes switch (rp->page) { 734b5b32b65SAndre Guedes case 0: 735b5b32b65SAndre Guedes memcpy(hdev->features, rp->features, 8); 736b5b32b65SAndre Guedes break; 737b5b32b65SAndre Guedes case 1: 73859e29406SAndre Guedes memcpy(hdev->host_features, rp->features, 8); 739b5b32b65SAndre Guedes break; 740b5b32b65SAndre Guedes } 741971e3a4bSAndre Guedes 7428f984dfaSJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags) && hdev->features[4] & LMP_LE) 7438f984dfaSJohan Hedberg hci_set_le_support(hdev); 7448f984dfaSJohan Hedberg 7458f984dfaSJohan Hedberg done: 746971e3a4bSAndre Guedes hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status); 747971e3a4bSAndre Guedes } 748971e3a4bSAndre Guedes 7491e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, 7501e89cffbSAndrei Emeltchenko struct sk_buff *skb) 7511e89cffbSAndrei Emeltchenko { 7521e89cffbSAndrei Emeltchenko struct hci_rp_read_flow_control_mode *rp = (void *) skb->data; 7531e89cffbSAndrei Emeltchenko 7541e89cffbSAndrei Emeltchenko BT_DBG("%s status 0x%x", hdev->name, rp->status); 7551e89cffbSAndrei Emeltchenko 7561e89cffbSAndrei Emeltchenko if (rp->status) 7571e89cffbSAndrei Emeltchenko return; 7581e89cffbSAndrei Emeltchenko 7591e89cffbSAndrei Emeltchenko hdev->flow_ctl_mode = rp->mode; 7601e89cffbSAndrei Emeltchenko 7611e89cffbSAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status); 7621e89cffbSAndrei Emeltchenko } 7631e89cffbSAndrei Emeltchenko 764a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 765a9de9248SMarcel Holtmann { 766a9de9248SMarcel Holtmann struct hci_rp_read_buffer_size *rp = (void *) skb->data; 767a9de9248SMarcel Holtmann 768a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 769a9de9248SMarcel Holtmann 770a9de9248SMarcel Holtmann if (rp->status) 771a9de9248SMarcel Holtmann return; 772a9de9248SMarcel Holtmann 773a9de9248SMarcel Holtmann hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); 774a9de9248SMarcel Holtmann hdev->sco_mtu = rp->sco_mtu; 775a9de9248SMarcel Holtmann hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); 776a9de9248SMarcel Holtmann hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); 777da1f5198SMarcel Holtmann 778da1f5198SMarcel Holtmann if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { 779da1f5198SMarcel Holtmann hdev->sco_mtu = 64; 780da1f5198SMarcel Holtmann hdev->sco_pkts = 8; 781da1f5198SMarcel Holtmann } 782da1f5198SMarcel Holtmann 783da1f5198SMarcel Holtmann hdev->acl_cnt = hdev->acl_pkts; 784da1f5198SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 7851da177e4SLinus Torvalds 786a9de9248SMarcel Holtmann BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, 787a9de9248SMarcel Holtmann hdev->acl_mtu, hdev->acl_pkts, 788a9de9248SMarcel Holtmann hdev->sco_mtu, hdev->sco_pkts); 7891da177e4SLinus Torvalds } 7901da177e4SLinus Torvalds 791a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) 792a9de9248SMarcel Holtmann { 793a9de9248SMarcel Holtmann struct hci_rp_read_bd_addr *rp = (void *) skb->data; 7941da177e4SLinus Torvalds 795a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 796a9de9248SMarcel Holtmann 797a9de9248SMarcel Holtmann if (!rp->status) 798a9de9248SMarcel Holtmann bacpy(&hdev->bdaddr, &rp->bdaddr); 799a9de9248SMarcel Holtmann 80023bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status); 80123bb5763SJohan Hedberg } 80223bb5763SJohan Hedberg 803350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev, 804350ee4cfSAndrei Emeltchenko struct sk_buff *skb) 805350ee4cfSAndrei Emeltchenko { 806350ee4cfSAndrei Emeltchenko struct hci_rp_read_data_block_size *rp = (void *) skb->data; 807350ee4cfSAndrei Emeltchenko 808350ee4cfSAndrei Emeltchenko BT_DBG("%s status 0x%x", hdev->name, rp->status); 809350ee4cfSAndrei Emeltchenko 810350ee4cfSAndrei Emeltchenko if (rp->status) 811350ee4cfSAndrei Emeltchenko return; 812350ee4cfSAndrei Emeltchenko 813350ee4cfSAndrei Emeltchenko hdev->block_mtu = __le16_to_cpu(rp->max_acl_len); 814350ee4cfSAndrei Emeltchenko hdev->block_len = __le16_to_cpu(rp->block_len); 815350ee4cfSAndrei Emeltchenko hdev->num_blocks = __le16_to_cpu(rp->num_blocks); 816350ee4cfSAndrei Emeltchenko 817350ee4cfSAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 818350ee4cfSAndrei Emeltchenko 819350ee4cfSAndrei Emeltchenko BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu, 820350ee4cfSAndrei Emeltchenko hdev->block_cnt, hdev->block_len); 821350ee4cfSAndrei Emeltchenko 822350ee4cfSAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status); 823350ee4cfSAndrei Emeltchenko } 824350ee4cfSAndrei Emeltchenko 82523bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb) 82623bb5763SJohan Hedberg { 82723bb5763SJohan Hedberg __u8 status = *((__u8 *) skb->data); 82823bb5763SJohan Hedberg 82923bb5763SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 83023bb5763SJohan Hedberg 83123bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status); 8321da177e4SLinus Torvalds } 8331da177e4SLinus Torvalds 834928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev, 835928abaa7SAndrei Emeltchenko struct sk_buff *skb) 836928abaa7SAndrei Emeltchenko { 837928abaa7SAndrei Emeltchenko struct hci_rp_read_local_amp_info *rp = (void *) skb->data; 838928abaa7SAndrei Emeltchenko 839928abaa7SAndrei Emeltchenko BT_DBG("%s status 0x%x", hdev->name, rp->status); 840928abaa7SAndrei Emeltchenko 841928abaa7SAndrei Emeltchenko if (rp->status) 842928abaa7SAndrei Emeltchenko return; 843928abaa7SAndrei Emeltchenko 844928abaa7SAndrei Emeltchenko hdev->amp_status = rp->amp_status; 845928abaa7SAndrei Emeltchenko hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); 846928abaa7SAndrei Emeltchenko hdev->amp_max_bw = __le32_to_cpu(rp->max_bw); 847928abaa7SAndrei Emeltchenko hdev->amp_min_latency = __le32_to_cpu(rp->min_latency); 848928abaa7SAndrei Emeltchenko hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu); 849928abaa7SAndrei Emeltchenko hdev->amp_type = rp->amp_type; 850928abaa7SAndrei Emeltchenko hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap); 851928abaa7SAndrei Emeltchenko hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size); 852928abaa7SAndrei Emeltchenko hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); 853928abaa7SAndrei Emeltchenko hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); 854928abaa7SAndrei Emeltchenko 855928abaa7SAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status); 856928abaa7SAndrei Emeltchenko } 857928abaa7SAndrei Emeltchenko 858b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, 859b0916ea0SJohan Hedberg struct sk_buff *skb) 860b0916ea0SJohan Hedberg { 861b0916ea0SJohan Hedberg __u8 status = *((__u8 *) skb->data); 862b0916ea0SJohan Hedberg 863b0916ea0SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 864b0916ea0SJohan Hedberg 865b0916ea0SJohan Hedberg hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status); 866b0916ea0SJohan Hedberg } 867b0916ea0SJohan Hedberg 868d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb) 869d5859e22SJohan Hedberg { 870d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 871d5859e22SJohan Hedberg 872d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 873d5859e22SJohan Hedberg 874d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status); 875d5859e22SJohan Hedberg } 876d5859e22SJohan Hedberg 877d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev, 878d5859e22SJohan Hedberg struct sk_buff *skb) 879d5859e22SJohan Hedberg { 880d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 881d5859e22SJohan Hedberg 882d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 883d5859e22SJohan Hedberg 884d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status); 885d5859e22SJohan Hedberg } 886d5859e22SJohan Hedberg 887d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, 888d5859e22SJohan Hedberg struct sk_buff *skb) 889d5859e22SJohan Hedberg { 890d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 891d5859e22SJohan Hedberg 892d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 893d5859e22SJohan Hedberg 894d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, status); 895d5859e22SJohan Hedberg } 896d5859e22SJohan Hedberg 897d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb) 898d5859e22SJohan Hedberg { 899d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 900d5859e22SJohan Hedberg 901d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 902d5859e22SJohan Hedberg 903d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status); 904d5859e22SJohan Hedberg } 905d5859e22SJohan Hedberg 906980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) 907980e1a53SJohan Hedberg { 908980e1a53SJohan Hedberg struct hci_rp_pin_code_reply *rp = (void *) skb->data; 909980e1a53SJohan Hedberg struct hci_cp_pin_code_reply *cp; 910980e1a53SJohan Hedberg struct hci_conn *conn; 911980e1a53SJohan Hedberg 912980e1a53SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 913980e1a53SJohan Hedberg 91456e5cb86SJohan Hedberg hci_dev_lock(hdev); 91556e5cb86SJohan Hedberg 916a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 917744cf19eSJohan Hedberg mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); 918980e1a53SJohan Hedberg 919980e1a53SJohan Hedberg if (rp->status != 0) 92056e5cb86SJohan Hedberg goto unlock; 921980e1a53SJohan Hedberg 922980e1a53SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); 923980e1a53SJohan Hedberg if (!cp) 92456e5cb86SJohan Hedberg goto unlock; 925980e1a53SJohan Hedberg 926980e1a53SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 927980e1a53SJohan Hedberg if (conn) 928980e1a53SJohan Hedberg conn->pin_length = cp->pin_len; 92956e5cb86SJohan Hedberg 93056e5cb86SJohan Hedberg unlock: 93156e5cb86SJohan Hedberg hci_dev_unlock(hdev); 932980e1a53SJohan Hedberg } 933980e1a53SJohan Hedberg 934980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 935980e1a53SJohan Hedberg { 936980e1a53SJohan Hedberg struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data; 937980e1a53SJohan Hedberg 938980e1a53SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 939980e1a53SJohan Hedberg 94056e5cb86SJohan Hedberg hci_dev_lock(hdev); 94156e5cb86SJohan Hedberg 942a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 943744cf19eSJohan Hedberg mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr, 944980e1a53SJohan Hedberg rp->status); 94556e5cb86SJohan Hedberg 94656e5cb86SJohan Hedberg hci_dev_unlock(hdev); 947980e1a53SJohan Hedberg } 94856e5cb86SJohan Hedberg 9496ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, 9506ed58ec5SVille Tervo struct sk_buff *skb) 9516ed58ec5SVille Tervo { 9526ed58ec5SVille Tervo struct hci_rp_le_read_buffer_size *rp = (void *) skb->data; 9536ed58ec5SVille Tervo 9546ed58ec5SVille Tervo BT_DBG("%s status 0x%x", hdev->name, rp->status); 9556ed58ec5SVille Tervo 9566ed58ec5SVille Tervo if (rp->status) 9576ed58ec5SVille Tervo return; 9586ed58ec5SVille Tervo 9596ed58ec5SVille Tervo hdev->le_mtu = __le16_to_cpu(rp->le_mtu); 9606ed58ec5SVille Tervo hdev->le_pkts = rp->le_max_pkt; 9616ed58ec5SVille Tervo 9626ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 9636ed58ec5SVille Tervo 9646ed58ec5SVille Tervo BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); 9656ed58ec5SVille Tervo 9666ed58ec5SVille Tervo hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status); 9676ed58ec5SVille Tervo } 968980e1a53SJohan Hedberg 969a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) 970a5c29683SJohan Hedberg { 971a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 972a5c29683SJohan Hedberg 973a5c29683SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 974a5c29683SJohan Hedberg 97556e5cb86SJohan Hedberg hci_dev_lock(hdev); 97656e5cb86SJohan Hedberg 977a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 97804124681SGustavo F. Padovan mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0, 97904124681SGustavo F. Padovan rp->status); 98056e5cb86SJohan Hedberg 98156e5cb86SJohan Hedberg hci_dev_unlock(hdev); 982a5c29683SJohan Hedberg } 983a5c29683SJohan Hedberg 984a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, 985a5c29683SJohan Hedberg struct sk_buff *skb) 986a5c29683SJohan Hedberg { 987a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 988a5c29683SJohan Hedberg 989a5c29683SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 990a5c29683SJohan Hedberg 99156e5cb86SJohan Hedberg hci_dev_lock(hdev); 99256e5cb86SJohan Hedberg 993a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 994744cf19eSJohan Hedberg mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr, 99504124681SGustavo F. Padovan ACL_LINK, 0, rp->status); 99656e5cb86SJohan Hedberg 99756e5cb86SJohan Hedberg hci_dev_unlock(hdev); 998a5c29683SJohan Hedberg } 999a5c29683SJohan Hedberg 10001143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb) 10011143d458SBrian Gix { 10021143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 10031143d458SBrian Gix 10041143d458SBrian Gix BT_DBG("%s status 0x%x", hdev->name, rp->status); 10051143d458SBrian Gix 10061143d458SBrian Gix hci_dev_lock(hdev); 10071143d458SBrian Gix 1008a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1009272d90dfSJohan Hedberg mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 1010272d90dfSJohan Hedberg 0, rp->status); 10111143d458SBrian Gix 10121143d458SBrian Gix hci_dev_unlock(hdev); 10131143d458SBrian Gix } 10141143d458SBrian Gix 10151143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, 10161143d458SBrian Gix struct sk_buff *skb) 10171143d458SBrian Gix { 10181143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 10191143d458SBrian Gix 10201143d458SBrian Gix BT_DBG("%s status 0x%x", hdev->name, rp->status); 10211143d458SBrian Gix 10221143d458SBrian Gix hci_dev_lock(hdev); 10231143d458SBrian Gix 1024a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 10251143d458SBrian Gix mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr, 102604124681SGustavo F. Padovan ACL_LINK, 0, rp->status); 10271143d458SBrian Gix 10281143d458SBrian Gix hci_dev_unlock(hdev); 10291143d458SBrian Gix } 10301143d458SBrian Gix 1031c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, 1032c35938b2SSzymon Janc struct sk_buff *skb) 1033c35938b2SSzymon Janc { 1034c35938b2SSzymon Janc struct hci_rp_read_local_oob_data *rp = (void *) skb->data; 1035c35938b2SSzymon Janc 1036c35938b2SSzymon Janc BT_DBG("%s status 0x%x", hdev->name, rp->status); 1037c35938b2SSzymon Janc 103856e5cb86SJohan Hedberg hci_dev_lock(hdev); 1039744cf19eSJohan Hedberg mgmt_read_local_oob_data_reply_complete(hdev, rp->hash, 1040c35938b2SSzymon Janc rp->randomizer, rp->status); 104156e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1042c35938b2SSzymon Janc } 1043c35938b2SSzymon Janc 104407f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) 104507f7fa5dSAndre Guedes { 104607f7fa5dSAndre Guedes __u8 status = *((__u8 *) skb->data); 104707f7fa5dSAndre Guedes 104807f7fa5dSAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 10497ba8b4beSAndre Guedes 10507ba8b4beSAndre Guedes hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status); 10513fd24153SAndre Guedes 10523fd24153SAndre Guedes if (status) { 10533fd24153SAndre Guedes hci_dev_lock(hdev); 10543fd24153SAndre Guedes mgmt_start_discovery_failed(hdev, status); 10553fd24153SAndre Guedes hci_dev_unlock(hdev); 10563fd24153SAndre Guedes return; 10573fd24153SAndre Guedes } 105807f7fa5dSAndre Guedes } 105907f7fa5dSAndre Guedes 1060eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, 1061eb9d91f5SAndre Guedes struct sk_buff *skb) 1062eb9d91f5SAndre Guedes { 1063eb9d91f5SAndre Guedes struct hci_cp_le_set_scan_enable *cp; 1064eb9d91f5SAndre Guedes __u8 status = *((__u8 *) skb->data); 1065eb9d91f5SAndre Guedes 1066eb9d91f5SAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 1067eb9d91f5SAndre Guedes 1068eb9d91f5SAndre Guedes cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE); 1069eb9d91f5SAndre Guedes if (!cp) 1070eb9d91f5SAndre Guedes return; 1071eb9d91f5SAndre Guedes 107268a8aea4SAndrei Emeltchenko switch (cp->enable) { 107368a8aea4SAndrei Emeltchenko case LE_SCANNING_ENABLED: 10747ba8b4beSAndre Guedes hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status); 10757ba8b4beSAndre Guedes 10763fd24153SAndre Guedes if (status) { 10773fd24153SAndre Guedes hci_dev_lock(hdev); 10783fd24153SAndre Guedes mgmt_start_discovery_failed(hdev, status); 10793fd24153SAndre Guedes hci_dev_unlock(hdev); 10807ba8b4beSAndre Guedes return; 10813fd24153SAndre Guedes } 10827ba8b4beSAndre Guedes 1083d23264a8SAndre Guedes set_bit(HCI_LE_SCAN, &hdev->dev_flags); 1084d23264a8SAndre Guedes 1085db323f2fSGustavo F. Padovan cancel_delayed_work_sync(&hdev->adv_work); 1086a8f13c8cSAndre Guedes 1087a8f13c8cSAndre Guedes hci_dev_lock(hdev); 1088eb9d91f5SAndre Guedes hci_adv_entries_clear(hdev); 1089343f935bSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_FINDING); 1090a8f13c8cSAndre Guedes hci_dev_unlock(hdev); 109168a8aea4SAndrei Emeltchenko break; 109268a8aea4SAndrei Emeltchenko 109368a8aea4SAndrei Emeltchenko case LE_SCANNING_DISABLED: 10947ba8b4beSAndre Guedes if (status) 10957ba8b4beSAndre Guedes return; 10967ba8b4beSAndre Guedes 1097d23264a8SAndre Guedes clear_bit(HCI_LE_SCAN, &hdev->dev_flags); 1098d23264a8SAndre Guedes 10995e0452c0SAndre Guedes schedule_delayed_work(&hdev->adv_work, ADV_CLEAR_TIMEOUT); 11005e0452c0SAndre Guedes 11015e0452c0SAndre Guedes if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED) { 11025e0452c0SAndre Guedes mgmt_interleaved_discovery(hdev); 11035e0452c0SAndre Guedes } else { 1104c599008fSAndre Guedes hci_dev_lock(hdev); 1105c599008fSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 1106c599008fSAndre Guedes hci_dev_unlock(hdev); 11075e0452c0SAndre Guedes } 1108c599008fSAndre Guedes 110968a8aea4SAndrei Emeltchenko break; 111068a8aea4SAndrei Emeltchenko 111168a8aea4SAndrei Emeltchenko default: 111268a8aea4SAndrei Emeltchenko BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable); 111368a8aea4SAndrei Emeltchenko break; 111435815085SAndre Guedes } 1115eb9d91f5SAndre Guedes } 1116eb9d91f5SAndre Guedes 1117a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb) 1118a7a595f6SVinicius Costa Gomes { 1119a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_reply *rp = (void *) skb->data; 1120a7a595f6SVinicius Costa Gomes 1121a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, rp->status); 1122a7a595f6SVinicius Costa Gomes 1123a7a595f6SVinicius Costa Gomes if (rp->status) 1124a7a595f6SVinicius Costa Gomes return; 1125a7a595f6SVinicius Costa Gomes 1126a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status); 1127a7a595f6SVinicius Costa Gomes } 1128a7a595f6SVinicius Costa Gomes 1129a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 1130a7a595f6SVinicius Costa Gomes { 1131a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data; 1132a7a595f6SVinicius Costa Gomes 1133a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, rp->status); 1134a7a595f6SVinicius Costa Gomes 1135a7a595f6SVinicius Costa Gomes if (rp->status) 1136a7a595f6SVinicius Costa Gomes return; 1137a7a595f6SVinicius Costa Gomes 1138a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status); 1139a7a595f6SVinicius Costa Gomes } 1140a7a595f6SVinicius Costa Gomes 1141f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev, 1142f9b49306SAndre Guedes struct sk_buff *skb) 1143f9b49306SAndre Guedes { 114406199cf8SJohan Hedberg struct hci_cp_write_le_host_supported *sent; 1145f9b49306SAndre Guedes __u8 status = *((__u8 *) skb->data); 1146f9b49306SAndre Guedes 1147f9b49306SAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 1148f9b49306SAndre Guedes 114906199cf8SJohan Hedberg sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED); 11508f984dfaSJohan Hedberg if (!sent) 1151f9b49306SAndre Guedes return; 1152f9b49306SAndre Guedes 11538f984dfaSJohan Hedberg if (!status) { 11548f984dfaSJohan Hedberg if (sent->le) 11558f984dfaSJohan Hedberg hdev->host_features[0] |= LMP_HOST_LE; 11568f984dfaSJohan Hedberg else 11578f984dfaSJohan Hedberg hdev->host_features[0] &= ~LMP_HOST_LE; 11588f984dfaSJohan Hedberg } 11598f984dfaSJohan Hedberg 11608f984dfaSJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags) && 11618f984dfaSJohan Hedberg !test_bit(HCI_INIT, &hdev->flags)) 11628f984dfaSJohan Hedberg mgmt_le_enable_complete(hdev, sent->le, status); 11638f984dfaSJohan Hedberg 11648f984dfaSJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status); 1165f9b49306SAndre Guedes } 1166f9b49306SAndre Guedes 1167a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 1168a9de9248SMarcel Holtmann { 1169a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1170a9de9248SMarcel Holtmann 1171a9de9248SMarcel Holtmann if (status) { 117223bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 1173a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 117456e5cb86SJohan Hedberg hci_dev_lock(hdev); 1175a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 11767a135109SAndre Guedes mgmt_start_discovery_failed(hdev, status); 117756e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1178314b2381SJohan Hedberg return; 1179314b2381SJohan Hedberg } 1180314b2381SJohan Hedberg 118189352e7dSAndre Guedes set_bit(HCI_INQUIRY, &hdev->flags); 118289352e7dSAndre Guedes 118356e5cb86SJohan Hedberg hci_dev_lock(hdev); 1184343f935bSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_FINDING); 118556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1186a9de9248SMarcel Holtmann } 1187a9de9248SMarcel Holtmann 11881da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 11891da177e4SLinus Torvalds { 1190a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 11911da177e4SLinus Torvalds struct hci_conn *conn; 11921da177e4SLinus Torvalds 1193a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1194a9de9248SMarcel Holtmann 1195a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 11961da177e4SLinus Torvalds if (!cp) 11971da177e4SLinus Torvalds return; 11981da177e4SLinus Torvalds 11991da177e4SLinus Torvalds hci_dev_lock(hdev); 12001da177e4SLinus Torvalds 12011da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 12021da177e4SLinus Torvalds 1203a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn); 12041da177e4SLinus Torvalds 12051da177e4SLinus Torvalds if (status) { 12061da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 12074c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 12081da177e4SLinus Torvalds conn->state = BT_CLOSED; 12091da177e4SLinus Torvalds hci_proto_connect_cfm(conn, status); 12101da177e4SLinus Torvalds hci_conn_del(conn); 12114c67bc74SMarcel Holtmann } else 12124c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 12131da177e4SLinus Torvalds } 12141da177e4SLinus Torvalds } else { 12151da177e4SLinus Torvalds if (!conn) { 12161da177e4SLinus Torvalds conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); 12171da177e4SLinus Torvalds if (conn) { 1218a0c808b3SJohan Hedberg conn->out = true; 12191da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 12201da177e4SLinus Torvalds } else 1221893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 12221da177e4SLinus Torvalds } 12231da177e4SLinus Torvalds } 12241da177e4SLinus Torvalds 12251da177e4SLinus Torvalds hci_dev_unlock(hdev); 12261da177e4SLinus Torvalds } 12271da177e4SLinus Torvalds 1228a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 12291da177e4SLinus Torvalds { 1230a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 12311da177e4SLinus Torvalds struct hci_conn *acl, *sco; 12321da177e4SLinus Torvalds __u16 handle; 12331da177e4SLinus Torvalds 1234b6a0dc82SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1235b6a0dc82SMarcel Holtmann 1236a9de9248SMarcel Holtmann if (!status) 1237a9de9248SMarcel Holtmann return; 1238a9de9248SMarcel Holtmann 1239a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 12401da177e4SLinus Torvalds if (!cp) 1241a9de9248SMarcel Holtmann return; 12421da177e4SLinus Torvalds 12431da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 12441da177e4SLinus Torvalds 1245a9de9248SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 12461da177e4SLinus Torvalds 12471da177e4SLinus Torvalds hci_dev_lock(hdev); 12481da177e4SLinus Torvalds 12491da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 12505a08ecceSAndrei Emeltchenko if (acl) { 12515a08ecceSAndrei Emeltchenko sco = acl->link; 12525a08ecceSAndrei Emeltchenko if (sco) { 12531da177e4SLinus Torvalds sco->state = BT_CLOSED; 12541da177e4SLinus Torvalds 12551da177e4SLinus Torvalds hci_proto_connect_cfm(sco, status); 12561da177e4SLinus Torvalds hci_conn_del(sco); 12571da177e4SLinus Torvalds } 12585a08ecceSAndrei Emeltchenko } 12591da177e4SLinus Torvalds 12601da177e4SLinus Torvalds hci_dev_unlock(hdev); 12611da177e4SLinus Torvalds } 12621da177e4SLinus Torvalds 1263f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 1264f8558555SMarcel Holtmann { 1265f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 1266f8558555SMarcel Holtmann struct hci_conn *conn; 1267f8558555SMarcel Holtmann 1268f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1269f8558555SMarcel Holtmann 1270f8558555SMarcel Holtmann if (!status) 1271f8558555SMarcel Holtmann return; 1272f8558555SMarcel Holtmann 1273f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 1274f8558555SMarcel Holtmann if (!cp) 1275f8558555SMarcel Holtmann return; 1276f8558555SMarcel Holtmann 1277f8558555SMarcel Holtmann hci_dev_lock(hdev); 1278f8558555SMarcel Holtmann 1279f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1280f8558555SMarcel Holtmann if (conn) { 1281f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1282f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1283f8558555SMarcel Holtmann hci_conn_put(conn); 1284f8558555SMarcel Holtmann } 1285f8558555SMarcel Holtmann } 1286f8558555SMarcel Holtmann 1287f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1288f8558555SMarcel Holtmann } 1289f8558555SMarcel Holtmann 1290f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 1291f8558555SMarcel Holtmann { 1292f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 1293f8558555SMarcel Holtmann struct hci_conn *conn; 1294f8558555SMarcel Holtmann 1295f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1296f8558555SMarcel Holtmann 1297f8558555SMarcel Holtmann if (!status) 1298f8558555SMarcel Holtmann return; 1299f8558555SMarcel Holtmann 1300f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 1301f8558555SMarcel Holtmann if (!cp) 1302f8558555SMarcel Holtmann return; 1303f8558555SMarcel Holtmann 1304f8558555SMarcel Holtmann hci_dev_lock(hdev); 1305f8558555SMarcel Holtmann 1306f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1307f8558555SMarcel Holtmann if (conn) { 1308f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1309f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1310f8558555SMarcel Holtmann hci_conn_put(conn); 1311f8558555SMarcel Holtmann } 1312f8558555SMarcel Holtmann } 1313f8558555SMarcel Holtmann 1314f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1315f8558555SMarcel Holtmann } 1316f8558555SMarcel Holtmann 1317127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev, 1318392599b9SJohan Hedberg struct hci_conn *conn) 1319392599b9SJohan Hedberg { 1320392599b9SJohan Hedberg if (conn->state != BT_CONFIG || !conn->out) 1321392599b9SJohan Hedberg return 0; 1322392599b9SJohan Hedberg 1323765c2a96SJohan Hedberg if (conn->pending_sec_level == BT_SECURITY_SDP) 1324392599b9SJohan Hedberg return 0; 1325392599b9SJohan Hedberg 1326392599b9SJohan Hedberg /* Only request authentication for SSP connections or non-SSP 1327e9bf2bf0SVinicius Costa Gomes * devices with sec_level HIGH or if MITM protection is requested */ 1328aa64a8b5SJohan Hedberg if (!hci_conn_ssp_enabled(conn) && 1329e9bf2bf0SVinicius Costa Gomes conn->pending_sec_level != BT_SECURITY_HIGH && 1330e9bf2bf0SVinicius Costa Gomes !(conn->auth_type & 0x01)) 1331392599b9SJohan Hedberg return 0; 1332392599b9SJohan Hedberg 1333392599b9SJohan Hedberg return 1; 1334392599b9SJohan Hedberg } 1335392599b9SJohan Hedberg 133600abfe44SGustavo F. Padovan static inline int hci_resolve_name(struct hci_dev *hdev, 133700abfe44SGustavo F. Padovan struct inquiry_entry *e) 133830dc78e1SJohan Hedberg { 133930dc78e1SJohan Hedberg struct hci_cp_remote_name_req cp; 134030dc78e1SJohan Hedberg 134130dc78e1SJohan Hedberg memset(&cp, 0, sizeof(cp)); 134230dc78e1SJohan Hedberg 134330dc78e1SJohan Hedberg bacpy(&cp.bdaddr, &e->data.bdaddr); 134430dc78e1SJohan Hedberg cp.pscan_rep_mode = e->data.pscan_rep_mode; 134530dc78e1SJohan Hedberg cp.pscan_mode = e->data.pscan_mode; 134630dc78e1SJohan Hedberg cp.clock_offset = e->data.clock_offset; 134730dc78e1SJohan Hedberg 134830dc78e1SJohan Hedberg return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 134930dc78e1SJohan Hedberg } 135030dc78e1SJohan Hedberg 1351b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev) 135230dc78e1SJohan Hedberg { 135330dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 135430dc78e1SJohan Hedberg struct inquiry_entry *e; 135530dc78e1SJohan Hedberg 1356b644ba33SJohan Hedberg if (list_empty(&discov->resolve)) 1357b644ba33SJohan Hedberg return false; 1358b644ba33SJohan Hedberg 1359b644ba33SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 1360b644ba33SJohan Hedberg if (hci_resolve_name(hdev, e) == 0) { 1361b644ba33SJohan Hedberg e->name_state = NAME_PENDING; 1362b644ba33SJohan Hedberg return true; 1363b644ba33SJohan Hedberg } 1364b644ba33SJohan Hedberg 1365b644ba33SJohan Hedberg return false; 1366b644ba33SJohan Hedberg } 1367b644ba33SJohan Hedberg 1368b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn, 1369b644ba33SJohan Hedberg bdaddr_t *bdaddr, u8 *name, u8 name_len) 1370b644ba33SJohan Hedberg { 1371b644ba33SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 1372b644ba33SJohan Hedberg struct inquiry_entry *e; 1373b644ba33SJohan Hedberg 1374b644ba33SJohan Hedberg if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 137504124681SGustavo F. Padovan mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name, 137604124681SGustavo F. Padovan name_len, conn->dev_class); 1377b644ba33SJohan Hedberg 1378b644ba33SJohan Hedberg if (discov->state == DISCOVERY_STOPPED) 1379b644ba33SJohan Hedberg return; 1380b644ba33SJohan Hedberg 138130dc78e1SJohan Hedberg if (discov->state == DISCOVERY_STOPPING) 138230dc78e1SJohan Hedberg goto discov_complete; 138330dc78e1SJohan Hedberg 138430dc78e1SJohan Hedberg if (discov->state != DISCOVERY_RESOLVING) 138530dc78e1SJohan Hedberg return; 138630dc78e1SJohan Hedberg 138730dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING); 138830dc78e1SJohan Hedberg if (e) { 138930dc78e1SJohan Hedberg e->name_state = NAME_KNOWN; 139030dc78e1SJohan Hedberg list_del(&e->list); 1391b644ba33SJohan Hedberg if (name) 1392b644ba33SJohan Hedberg mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, 1393b644ba33SJohan Hedberg e->data.rssi, name, name_len); 139430dc78e1SJohan Hedberg } 139530dc78e1SJohan Hedberg 1396b644ba33SJohan Hedberg if (hci_resolve_next_name(hdev)) 139730dc78e1SJohan Hedberg return; 139830dc78e1SJohan Hedberg 139930dc78e1SJohan Hedberg discov_complete: 140030dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 140130dc78e1SJohan Hedberg } 140230dc78e1SJohan Hedberg 1403a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 14041da177e4SLinus Torvalds { 1405127178d2SJohan Hedberg struct hci_cp_remote_name_req *cp; 1406127178d2SJohan Hedberg struct hci_conn *conn; 1407127178d2SJohan Hedberg 1408a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1409127178d2SJohan Hedberg 1410127178d2SJohan Hedberg /* If successful wait for the name req complete event before 1411127178d2SJohan Hedberg * checking for the need to do authentication */ 1412127178d2SJohan Hedberg if (!status) 1413127178d2SJohan Hedberg return; 1414127178d2SJohan Hedberg 1415127178d2SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); 1416127178d2SJohan Hedberg if (!cp) 1417127178d2SJohan Hedberg return; 1418127178d2SJohan Hedberg 1419127178d2SJohan Hedberg hci_dev_lock(hdev); 1420127178d2SJohan Hedberg 1421127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 1422b644ba33SJohan Hedberg 1423b644ba33SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1424b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0); 1425b644ba33SJohan Hedberg 142679c6c70cSJohan Hedberg if (!conn) 142779c6c70cSJohan Hedberg goto unlock; 142879c6c70cSJohan Hedberg 142979c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 143079c6c70cSJohan Hedberg goto unlock; 143179c6c70cSJohan Hedberg 143251a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 1433127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1434127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1435127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1436127178d2SJohan Hedberg } 1437127178d2SJohan Hedberg 143879c6c70cSJohan Hedberg unlock: 1439127178d2SJohan Hedberg hci_dev_unlock(hdev); 1440a9de9248SMarcel Holtmann } 14411da177e4SLinus Torvalds 1442769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 1443769be974SMarcel Holtmann { 1444769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 1445769be974SMarcel Holtmann struct hci_conn *conn; 1446769be974SMarcel Holtmann 1447769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1448769be974SMarcel Holtmann 1449769be974SMarcel Holtmann if (!status) 1450769be974SMarcel Holtmann return; 1451769be974SMarcel Holtmann 1452769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 1453769be974SMarcel Holtmann if (!cp) 1454769be974SMarcel Holtmann return; 1455769be974SMarcel Holtmann 1456769be974SMarcel Holtmann hci_dev_lock(hdev); 1457769be974SMarcel Holtmann 1458769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1459769be974SMarcel Holtmann if (conn) { 1460769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1461769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1462769be974SMarcel Holtmann hci_conn_put(conn); 1463769be974SMarcel Holtmann } 1464769be974SMarcel Holtmann } 1465769be974SMarcel Holtmann 1466769be974SMarcel Holtmann hci_dev_unlock(hdev); 1467769be974SMarcel Holtmann } 1468769be974SMarcel Holtmann 1469769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 1470769be974SMarcel Holtmann { 1471769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features *cp; 1472769be974SMarcel Holtmann struct hci_conn *conn; 1473769be974SMarcel Holtmann 1474769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1475769be974SMarcel Holtmann 1476769be974SMarcel Holtmann if (!status) 1477769be974SMarcel Holtmann return; 1478769be974SMarcel Holtmann 1479769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 1480769be974SMarcel Holtmann if (!cp) 1481769be974SMarcel Holtmann return; 1482769be974SMarcel Holtmann 1483769be974SMarcel Holtmann hci_dev_lock(hdev); 1484769be974SMarcel Holtmann 1485769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1486769be974SMarcel Holtmann if (conn) { 1487769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1488769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1489769be974SMarcel Holtmann hci_conn_put(conn); 1490769be974SMarcel Holtmann } 1491769be974SMarcel Holtmann } 1492769be974SMarcel Holtmann 1493769be974SMarcel Holtmann hci_dev_unlock(hdev); 1494769be974SMarcel Holtmann } 1495769be974SMarcel Holtmann 1496a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 1497a9de9248SMarcel Holtmann { 1498b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 1499b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 1500b6a0dc82SMarcel Holtmann __u16 handle; 1501b6a0dc82SMarcel Holtmann 1502a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1503b6a0dc82SMarcel Holtmann 1504b6a0dc82SMarcel Holtmann if (!status) 1505b6a0dc82SMarcel Holtmann return; 1506b6a0dc82SMarcel Holtmann 1507b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 1508b6a0dc82SMarcel Holtmann if (!cp) 1509b6a0dc82SMarcel Holtmann return; 1510b6a0dc82SMarcel Holtmann 1511b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 1512b6a0dc82SMarcel Holtmann 1513b6a0dc82SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 1514b6a0dc82SMarcel Holtmann 1515b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 1516b6a0dc82SMarcel Holtmann 1517b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 15185a08ecceSAndrei Emeltchenko if (acl) { 15195a08ecceSAndrei Emeltchenko sco = acl->link; 15205a08ecceSAndrei Emeltchenko if (sco) { 1521b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 1522b6a0dc82SMarcel Holtmann 1523b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(sco, status); 1524b6a0dc82SMarcel Holtmann hci_conn_del(sco); 1525b6a0dc82SMarcel Holtmann } 15265a08ecceSAndrei Emeltchenko } 1527b6a0dc82SMarcel Holtmann 1528b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 1529a9de9248SMarcel Holtmann } 1530a9de9248SMarcel Holtmann 1531a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 1532a9de9248SMarcel Holtmann { 1533a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 153404837f64SMarcel Holtmann struct hci_conn *conn; 153504837f64SMarcel Holtmann 1536a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1537a9de9248SMarcel Holtmann 1538a9de9248SMarcel Holtmann if (!status) 1539a9de9248SMarcel Holtmann return; 1540a9de9248SMarcel Holtmann 1541a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 154204837f64SMarcel Holtmann if (!cp) 1543a9de9248SMarcel Holtmann return; 154404837f64SMarcel Holtmann 154504837f64SMarcel Holtmann hci_dev_lock(hdev); 154604837f64SMarcel Holtmann 154704837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1548e73439d8SMarcel Holtmann if (conn) { 154951a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 155004837f64SMarcel Holtmann 155151a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1552e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1553e73439d8SMarcel Holtmann } 1554e73439d8SMarcel Holtmann 155504837f64SMarcel Holtmann hci_dev_unlock(hdev); 155604837f64SMarcel Holtmann } 155704837f64SMarcel Holtmann 1558a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 1559a9de9248SMarcel Holtmann { 1560a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 156104837f64SMarcel Holtmann struct hci_conn *conn; 156204837f64SMarcel Holtmann 1563a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1564a9de9248SMarcel Holtmann 1565a9de9248SMarcel Holtmann if (!status) 1566a9de9248SMarcel Holtmann return; 1567a9de9248SMarcel Holtmann 1568a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 156904837f64SMarcel Holtmann if (!cp) 1570a9de9248SMarcel Holtmann return; 157104837f64SMarcel Holtmann 157204837f64SMarcel Holtmann hci_dev_lock(hdev); 157304837f64SMarcel Holtmann 157404837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1575e73439d8SMarcel Holtmann if (conn) { 157651a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 157704837f64SMarcel Holtmann 157851a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1579e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1580e73439d8SMarcel Holtmann } 1581e73439d8SMarcel Holtmann 158204837f64SMarcel Holtmann hci_dev_unlock(hdev); 158304837f64SMarcel Holtmann } 158404837f64SMarcel Holtmann 158588c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) 158688c3df13SJohan Hedberg { 158788c3df13SJohan Hedberg struct hci_cp_disconnect *cp; 158888c3df13SJohan Hedberg struct hci_conn *conn; 158988c3df13SJohan Hedberg 159088c3df13SJohan Hedberg if (!status) 159188c3df13SJohan Hedberg return; 159288c3df13SJohan Hedberg 159388c3df13SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT); 159488c3df13SJohan Hedberg if (!cp) 159588c3df13SJohan Hedberg return; 159688c3df13SJohan Hedberg 159788c3df13SJohan Hedberg hci_dev_lock(hdev); 159888c3df13SJohan Hedberg 159988c3df13SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 160088c3df13SJohan Hedberg if (conn) 160188c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 160288c3df13SJohan Hedberg conn->dst_type, status); 160388c3df13SJohan Hedberg 160488c3df13SJohan Hedberg hci_dev_unlock(hdev); 160588c3df13SJohan Hedberg } 160688c3df13SJohan Hedberg 1607fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) 1608fcd89c09SVille Tervo { 1609fcd89c09SVille Tervo struct hci_cp_le_create_conn *cp; 1610fcd89c09SVille Tervo struct hci_conn *conn; 1611fcd89c09SVille Tervo 1612fcd89c09SVille Tervo BT_DBG("%s status 0x%x", hdev->name, status); 1613fcd89c09SVille Tervo 1614fcd89c09SVille Tervo cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN); 1615fcd89c09SVille Tervo if (!cp) 1616fcd89c09SVille Tervo return; 1617fcd89c09SVille Tervo 1618fcd89c09SVille Tervo hci_dev_lock(hdev); 1619fcd89c09SVille Tervo 1620fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr); 1621fcd89c09SVille Tervo 1622fcd89c09SVille Tervo BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr), 1623fcd89c09SVille Tervo conn); 1624fcd89c09SVille Tervo 1625fcd89c09SVille Tervo if (status) { 1626fcd89c09SVille Tervo if (conn && conn->state == BT_CONNECT) { 1627fcd89c09SVille Tervo conn->state = BT_CLOSED; 1628fcd89c09SVille Tervo hci_proto_connect_cfm(conn, status); 1629fcd89c09SVille Tervo hci_conn_del(conn); 1630fcd89c09SVille Tervo } 1631fcd89c09SVille Tervo } else { 1632fcd89c09SVille Tervo if (!conn) { 1633fcd89c09SVille Tervo conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr); 163429b7988aSAndre Guedes if (conn) { 163529b7988aSAndre Guedes conn->dst_type = cp->peer_addr_type; 1636a0c808b3SJohan Hedberg conn->out = true; 163729b7988aSAndre Guedes } else { 1638fcd89c09SVille Tervo BT_ERR("No memory for new connection"); 1639fcd89c09SVille Tervo } 1640fcd89c09SVille Tervo } 164129b7988aSAndre Guedes } 1642fcd89c09SVille Tervo 1643fcd89c09SVille Tervo hci_dev_unlock(hdev); 1644fcd89c09SVille Tervo } 1645fcd89c09SVille Tervo 1646a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) 1647a7a595f6SVinicius Costa Gomes { 1648a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, status); 1649a7a595f6SVinicius Costa Gomes } 1650a7a595f6SVinicius Costa Gomes 16511da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 16521da177e4SLinus Torvalds { 16531da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 165430dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 165530dc78e1SJohan Hedberg struct inquiry_entry *e; 16561da177e4SLinus Torvalds 16571da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, status); 16581da177e4SLinus Torvalds 165923bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 16606bd57416SMarcel Holtmann 1661a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 166289352e7dSAndre Guedes 166389352e7dSAndre Guedes if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) 166489352e7dSAndre Guedes return; 166589352e7dSAndre Guedes 1666a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 166730dc78e1SJohan Hedberg return; 166830dc78e1SJohan Hedberg 166956e5cb86SJohan Hedberg hci_dev_lock(hdev); 167030dc78e1SJohan Hedberg 1671343f935bSAndre Guedes if (discov->state != DISCOVERY_FINDING) 167230dc78e1SJohan Hedberg goto unlock; 167330dc78e1SJohan Hedberg 167430dc78e1SJohan Hedberg if (list_empty(&discov->resolve)) { 1675ff9ef578SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 167630dc78e1SJohan Hedberg goto unlock; 167730dc78e1SJohan Hedberg } 167830dc78e1SJohan Hedberg 167930dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 168030dc78e1SJohan Hedberg if (e && hci_resolve_name(hdev, e) == 0) { 168130dc78e1SJohan Hedberg e->name_state = NAME_PENDING; 168230dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_RESOLVING); 168330dc78e1SJohan Hedberg } else { 168430dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 168530dc78e1SJohan Hedberg } 168630dc78e1SJohan Hedberg 168730dc78e1SJohan Hedberg unlock: 168856e5cb86SJohan Hedberg hci_dev_unlock(hdev); 16891da177e4SLinus Torvalds } 16901da177e4SLinus Torvalds 16911da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 16921da177e4SLinus Torvalds { 169345bb4bf0SMarcel Holtmann struct inquiry_data data; 1694a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 16951da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 16961da177e4SLinus Torvalds 16971da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 16981da177e4SLinus Torvalds 169945bb4bf0SMarcel Holtmann if (!num_rsp) 170045bb4bf0SMarcel Holtmann return; 170145bb4bf0SMarcel Holtmann 17021da177e4SLinus Torvalds hci_dev_lock(hdev); 170345bb4bf0SMarcel Holtmann 1704e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 1705388fc8faSJohan Hedberg bool name_known, ssp; 17063175405bSJohan Hedberg 17071da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 17081da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 17091da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 17101da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 17111da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 17121da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 17131da177e4SLinus Torvalds data.rssi = 0x00; 171441a96212SMarcel Holtmann data.ssp_mode = 0x00; 17153175405bSJohan Hedberg 1716388fc8faSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp); 171748264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 171804124681SGustavo F. Padovan info->dev_class, 0, !name_known, ssp, NULL, 171904124681SGustavo F. Padovan 0); 17201da177e4SLinus Torvalds } 172145bb4bf0SMarcel Holtmann 17221da177e4SLinus Torvalds hci_dev_unlock(hdev); 17231da177e4SLinus Torvalds } 17241da177e4SLinus Torvalds 1725a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 17261da177e4SLinus Torvalds { 1727a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 1728a9de9248SMarcel Holtmann struct hci_conn *conn; 17291da177e4SLinus Torvalds 1730a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 173145bb4bf0SMarcel Holtmann 17321da177e4SLinus Torvalds hci_dev_lock(hdev); 173345bb4bf0SMarcel Holtmann 1734a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 17359499237aSMarcel Holtmann if (!conn) { 17369499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 17379499237aSMarcel Holtmann goto unlock; 17389499237aSMarcel Holtmann 17399499237aSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 1740a9de9248SMarcel Holtmann if (!conn) 1741a9de9248SMarcel Holtmann goto unlock; 174245bb4bf0SMarcel Holtmann 17439499237aSMarcel Holtmann conn->type = SCO_LINK; 17449499237aSMarcel Holtmann } 17459499237aSMarcel Holtmann 1746a9de9248SMarcel Holtmann if (!ev->status) { 1747a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 1748769be974SMarcel Holtmann 1749769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 1750769be974SMarcel Holtmann conn->state = BT_CONFIG; 1751769be974SMarcel Holtmann hci_conn_hold(conn); 1752052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1753769be974SMarcel Holtmann } else 1754a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 1755a9de9248SMarcel Holtmann 17569eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 17577d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 17587d0db0a3SMarcel Holtmann 1759a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 1760a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1761a9de9248SMarcel Holtmann 1762a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 1763a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1764a9de9248SMarcel Holtmann 1765a9de9248SMarcel Holtmann /* Get remote features */ 1766a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 1767a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 1768a9de9248SMarcel Holtmann cp.handle = ev->handle; 1769769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 1770769be974SMarcel Holtmann sizeof(cp), &cp); 177145bb4bf0SMarcel Holtmann } 1772a9de9248SMarcel Holtmann 1773a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 1774d095c1ebSAndrei Emeltchenko if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) { 1775a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 1776a9de9248SMarcel Holtmann cp.handle = ev->handle; 1777a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 177804124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp), 177904124681SGustavo F. Padovan &cp); 1780a9de9248SMarcel Holtmann } 178117d5c04cSJohan Hedberg } else { 1782a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 178317d5c04cSJohan Hedberg if (conn->type == ACL_LINK) 1784744cf19eSJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 178548264f06SJohan Hedberg conn->dst_type, ev->status); 178617d5c04cSJohan Hedberg } 178745bb4bf0SMarcel Holtmann 1788e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 1789e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 179045bb4bf0SMarcel Holtmann 1791769be974SMarcel Holtmann if (ev->status) { 1792a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1793a9de9248SMarcel Holtmann hci_conn_del(conn); 1794c89b6e6bSMarcel Holtmann } else if (ev->link_type != ACL_LINK) 1795c89b6e6bSMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1796a9de9248SMarcel Holtmann 1797a9de9248SMarcel Holtmann unlock: 17981da177e4SLinus Torvalds hci_dev_unlock(hdev); 1799a9de9248SMarcel Holtmann 1800a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 18011da177e4SLinus Torvalds } 18021da177e4SLinus Torvalds 18031da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 18041da177e4SLinus Torvalds { 1805a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 18061da177e4SLinus Torvalds int mask = hdev->link_mode; 18071da177e4SLinus Torvalds 1808a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s type 0x%x", hdev->name, 18091da177e4SLinus Torvalds batostr(&ev->bdaddr), ev->link_type); 18101da177e4SLinus Torvalds 18111da177e4SLinus Torvalds mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); 18121da177e4SLinus Torvalds 1813138d22efSSzymon Janc if ((mask & HCI_LM_ACCEPT) && 1814138d22efSSzymon Janc !hci_blacklist_lookup(hdev, &ev->bdaddr)) { 18151da177e4SLinus Torvalds /* Connection accepted */ 1816c7bdd502SMarcel Holtmann struct inquiry_entry *ie; 18171da177e4SLinus Torvalds struct hci_conn *conn; 18181da177e4SLinus Torvalds 18191da177e4SLinus Torvalds hci_dev_lock(hdev); 1820b6a0dc82SMarcel Holtmann 1821cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 1822cc11b9c1SAndrei Emeltchenko if (ie) 1823c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 1824c7bdd502SMarcel Holtmann 18251da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 18261da177e4SLinus Torvalds if (!conn) { 1827cc11b9c1SAndrei Emeltchenko conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); 1828cc11b9c1SAndrei Emeltchenko if (!conn) { 1829893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 18301da177e4SLinus Torvalds hci_dev_unlock(hdev); 18311da177e4SLinus Torvalds return; 18321da177e4SLinus Torvalds } 18331da177e4SLinus Torvalds } 1834b6a0dc82SMarcel Holtmann 18351da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 18361da177e4SLinus Torvalds conn->state = BT_CONNECT; 1837b6a0dc82SMarcel Holtmann 18381da177e4SLinus Torvalds hci_dev_unlock(hdev); 18391da177e4SLinus Torvalds 1840b6a0dc82SMarcel Holtmann if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) { 1841b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 1842b6a0dc82SMarcel Holtmann 18431da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 18441da177e4SLinus Torvalds 18451da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 18461da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 18471da177e4SLinus Torvalds else 18481da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 18491da177e4SLinus Torvalds 185004124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), 185104124681SGustavo F. Padovan &cp); 1852b6a0dc82SMarcel Holtmann } else { 1853b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 1854b6a0dc82SMarcel Holtmann 1855b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 1856a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1857b6a0dc82SMarcel Holtmann 1858b6a0dc82SMarcel Holtmann cp.tx_bandwidth = cpu_to_le32(0x00001f40); 1859b6a0dc82SMarcel Holtmann cp.rx_bandwidth = cpu_to_le32(0x00001f40); 1860b6a0dc82SMarcel Holtmann cp.max_latency = cpu_to_le16(0xffff); 1861b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 1862b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 1863b6a0dc82SMarcel Holtmann 1864b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 1865b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1866b6a0dc82SMarcel Holtmann } 18671da177e4SLinus Torvalds } else { 18681da177e4SLinus Torvalds /* Connection rejected */ 18691da177e4SLinus Torvalds struct hci_cp_reject_conn_req cp; 18701da177e4SLinus Torvalds 18711da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 18729f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_REJ_BAD_ADDR; 1873a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 18741da177e4SLinus Torvalds } 18751da177e4SLinus Torvalds } 18761da177e4SLinus Torvalds 18771da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 18781da177e4SLinus Torvalds { 1879a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 188004837f64SMarcel Holtmann struct hci_conn *conn; 18811da177e4SLinus Torvalds 18821da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 18831da177e4SLinus Torvalds 18841da177e4SLinus Torvalds hci_dev_lock(hdev); 18851da177e4SLinus Torvalds 188604837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1887f7520543SJohan Hedberg if (!conn) 1888f7520543SJohan Hedberg goto unlock; 1889f7520543SJohan Hedberg 189037d9ef76SJohan Hedberg if (ev->status == 0) 18911da177e4SLinus Torvalds conn->state = BT_CLOSED; 18927d0db0a3SMarcel Holtmann 1893b644ba33SJohan Hedberg if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) && 1894b644ba33SJohan Hedberg (conn->type == ACL_LINK || conn->type == LE_LINK)) { 189537d9ef76SJohan Hedberg if (ev->status != 0) 189688c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 189788c3df13SJohan Hedberg conn->dst_type, ev->status); 189837d9ef76SJohan Hedberg else 1899afc747a6SJohan Hedberg mgmt_device_disconnected(hdev, &conn->dst, conn->type, 190048264f06SJohan Hedberg conn->dst_type); 190137d9ef76SJohan Hedberg } 1902f7520543SJohan Hedberg 190337d9ef76SJohan Hedberg if (ev->status == 0) { 19046ec5bcadSVishal Agarwal if (conn->type == ACL_LINK && conn->flush_key) 19056ec5bcadSVishal Agarwal hci_remove_link_key(hdev, &conn->dst); 19062950f21aSMarcel Holtmann hci_proto_disconn_cfm(conn, ev->reason); 19071da177e4SLinus Torvalds hci_conn_del(conn); 190837d9ef76SJohan Hedberg } 19091da177e4SLinus Torvalds 1910f7520543SJohan Hedberg unlock: 19111da177e4SLinus Torvalds hci_dev_unlock(hdev); 19121da177e4SLinus Torvalds } 19131da177e4SLinus Torvalds 1914a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1915a9de9248SMarcel Holtmann { 1916a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 1917a9de9248SMarcel Holtmann struct hci_conn *conn; 1918a9de9248SMarcel Holtmann 1919a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1920a9de9248SMarcel Holtmann 1921a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1922a9de9248SMarcel Holtmann 1923a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1924d7556e20SWaldemar Rymarkiewicz if (!conn) 1925d7556e20SWaldemar Rymarkiewicz goto unlock; 1926d7556e20SWaldemar Rymarkiewicz 1927765c2a96SJohan Hedberg if (!ev->status) { 1928aa64a8b5SJohan Hedberg if (!hci_conn_ssp_enabled(conn) && 192951a8efd7SJohan Hedberg test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) { 1930d7556e20SWaldemar Rymarkiewicz BT_INFO("re-auth of legacy device is not possible."); 193119f8def0SWaldemar Rymarkiewicz } else { 1932a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1933765c2a96SJohan Hedberg conn->sec_level = conn->pending_sec_level; 193419f8def0SWaldemar Rymarkiewicz } 19352a611692SJohan Hedberg } else { 1936bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 1937bab73cb6SJohan Hedberg ev->status); 19382a611692SJohan Hedberg } 1939a9de9248SMarcel Holtmann 194051a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 194151a8efd7SJohan Hedberg clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags); 1942a9de9248SMarcel Holtmann 1943f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1944aa64a8b5SJohan Hedberg if (!ev->status && hci_conn_ssp_enabled(conn)) { 1945f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1946f8558555SMarcel Holtmann cp.handle = ev->handle; 1947f8558555SMarcel Holtmann cp.encrypt = 0x01; 1948d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1949d7556e20SWaldemar Rymarkiewicz &cp); 1950f8558555SMarcel Holtmann } else { 1951f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1952f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1953f8558555SMarcel Holtmann hci_conn_put(conn); 1954f8558555SMarcel Holtmann } 1955052b30b0SMarcel Holtmann } else { 1956a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 1957a9de9248SMarcel Holtmann 1958052b30b0SMarcel Holtmann hci_conn_hold(conn); 1959052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1960052b30b0SMarcel Holtmann hci_conn_put(conn); 1961052b30b0SMarcel Holtmann } 1962052b30b0SMarcel Holtmann 196351a8efd7SJohan Hedberg if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) { 1964a9de9248SMarcel Holtmann if (!ev->status) { 1965a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1966f8558555SMarcel Holtmann cp.handle = ev->handle; 1967f8558555SMarcel Holtmann cp.encrypt = 0x01; 1968d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1969d7556e20SWaldemar Rymarkiewicz &cp); 1970a9de9248SMarcel Holtmann } else { 197151a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 1972a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 1973a9de9248SMarcel Holtmann } 1974a9de9248SMarcel Holtmann } 1975a9de9248SMarcel Holtmann 1976d7556e20SWaldemar Rymarkiewicz unlock: 1977a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1978a9de9248SMarcel Holtmann } 1979a9de9248SMarcel Holtmann 1980a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 1981a9de9248SMarcel Holtmann { 1982127178d2SJohan Hedberg struct hci_ev_remote_name *ev = (void *) skb->data; 1983127178d2SJohan Hedberg struct hci_conn *conn; 1984127178d2SJohan Hedberg 1985a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1986a9de9248SMarcel Holtmann 1987a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 1988127178d2SJohan Hedberg 1989127178d2SJohan Hedberg hci_dev_lock(hdev); 1990127178d2SJohan Hedberg 1991127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 1992b644ba33SJohan Hedberg 1993b644ba33SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 1994b644ba33SJohan Hedberg goto check_auth; 1995b644ba33SJohan Hedberg 1996b644ba33SJohan Hedberg if (ev->status == 0) 1997b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name, 1998b644ba33SJohan Hedberg strnlen(ev->name, HCI_MAX_NAME_LENGTH)); 1999b644ba33SJohan Hedberg else 2000b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0); 2001b644ba33SJohan Hedberg 2002b644ba33SJohan Hedberg check_auth: 200379c6c70cSJohan Hedberg if (!conn) 200479c6c70cSJohan Hedberg goto unlock; 200579c6c70cSJohan Hedberg 200679c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 200779c6c70cSJohan Hedberg goto unlock; 200879c6c70cSJohan Hedberg 200951a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 2010127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 2011127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 2012127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 2013127178d2SJohan Hedberg } 2014127178d2SJohan Hedberg 201579c6c70cSJohan Hedberg unlock: 2016127178d2SJohan Hedberg hci_dev_unlock(hdev); 2017a9de9248SMarcel Holtmann } 2018a9de9248SMarcel Holtmann 2019a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2020a9de9248SMarcel Holtmann { 2021a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 2022a9de9248SMarcel Holtmann struct hci_conn *conn; 2023a9de9248SMarcel Holtmann 2024a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2025a9de9248SMarcel Holtmann 2026a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2027a9de9248SMarcel Holtmann 2028a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2029a9de9248SMarcel Holtmann if (conn) { 2030a9de9248SMarcel Holtmann if (!ev->status) { 2031ae293196SMarcel Holtmann if (ev->encrypt) { 2032ae293196SMarcel Holtmann /* Encryption implies authentication */ 2033ae293196SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 2034a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 2035da85e5e5SVinicius Costa Gomes conn->sec_level = conn->pending_sec_level; 2036ae293196SMarcel Holtmann } else 2037a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_ENCRYPT; 2038a9de9248SMarcel Holtmann } 2039a9de9248SMarcel Holtmann 204051a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 2041a9de9248SMarcel Holtmann 2042f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 2043f8558555SMarcel Holtmann if (!ev->status) 2044f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 2045f8558555SMarcel Holtmann 2046f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2047f8558555SMarcel Holtmann hci_conn_put(conn); 2048f8558555SMarcel Holtmann } else 2049a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 2050a9de9248SMarcel Holtmann } 2051a9de9248SMarcel Holtmann 2052a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2053a9de9248SMarcel Holtmann } 2054a9de9248SMarcel Holtmann 2055a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2056a9de9248SMarcel Holtmann { 2057a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 2058a9de9248SMarcel Holtmann struct hci_conn *conn; 2059a9de9248SMarcel Holtmann 2060a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2061a9de9248SMarcel Holtmann 2062a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2063a9de9248SMarcel Holtmann 2064a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2065a9de9248SMarcel Holtmann if (conn) { 2066a9de9248SMarcel Holtmann if (!ev->status) 2067a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_SECURE; 2068a9de9248SMarcel Holtmann 206951a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 2070a9de9248SMarcel Holtmann 2071a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 2072a9de9248SMarcel Holtmann } 2073a9de9248SMarcel Holtmann 2074a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2075a9de9248SMarcel Holtmann } 2076a9de9248SMarcel Holtmann 2077a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 2078a9de9248SMarcel Holtmann { 2079a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 2080a9de9248SMarcel Holtmann struct hci_conn *conn; 2081a9de9248SMarcel Holtmann 2082a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2083a9de9248SMarcel Holtmann 2084a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2085a9de9248SMarcel Holtmann 2086a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2087ccd556feSJohan Hedberg if (!conn) 2088ccd556feSJohan Hedberg goto unlock; 2089ccd556feSJohan Hedberg 2090769be974SMarcel Holtmann if (!ev->status) 2091a9de9248SMarcel Holtmann memcpy(conn->features, ev->features, 8); 2092a9de9248SMarcel Holtmann 2093ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2094ccd556feSJohan Hedberg goto unlock; 2095ccd556feSJohan Hedberg 2096ccd556feSJohan Hedberg if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { 2097769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 2098769be974SMarcel Holtmann cp.handle = ev->handle; 2099769be974SMarcel Holtmann cp.page = 0x01; 2100ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 2101769be974SMarcel Holtmann sizeof(cp), &cp); 2102392599b9SJohan Hedberg goto unlock; 2103392599b9SJohan Hedberg } 2104392599b9SJohan Hedberg 2105127178d2SJohan Hedberg if (!ev->status) { 2106127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2107127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2108127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2109127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2110127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2111b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 2112b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 211308c79b61SJohan Hedberg conn->dst_type, 0, NULL, 0, 2114b644ba33SJohan Hedberg conn->dev_class); 2115392599b9SJohan Hedberg 2116127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2117769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2118769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2119769be974SMarcel Holtmann hci_conn_put(conn); 2120769be974SMarcel Holtmann } 2121769be974SMarcel Holtmann 2122ccd556feSJohan Hedberg unlock: 2123a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2124a9de9248SMarcel Holtmann } 2125a9de9248SMarcel Holtmann 2126a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) 2127a9de9248SMarcel Holtmann { 2128a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2129a9de9248SMarcel Holtmann } 2130a9de9248SMarcel Holtmann 2131a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2132a9de9248SMarcel Holtmann { 2133a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2134a9de9248SMarcel Holtmann } 2135a9de9248SMarcel Holtmann 2136a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2137a9de9248SMarcel Holtmann { 2138a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 2139a9de9248SMarcel Holtmann __u16 opcode; 2140a9de9248SMarcel Holtmann 2141a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2142a9de9248SMarcel Holtmann 2143a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2144a9de9248SMarcel Holtmann 2145a9de9248SMarcel Holtmann switch (opcode) { 2146a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 2147a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 2148a9de9248SMarcel Holtmann break; 2149a9de9248SMarcel Holtmann 2150a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 2151a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 2152a9de9248SMarcel Holtmann break; 2153a9de9248SMarcel Holtmann 2154a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 2155a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 2156a9de9248SMarcel Holtmann break; 2157a9de9248SMarcel Holtmann 2158a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 2159a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 2160a9de9248SMarcel Holtmann break; 2161a9de9248SMarcel Holtmann 2162e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 2163e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 2164e4e8e37cSMarcel Holtmann break; 2165e4e8e37cSMarcel Holtmann 2166a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 2167a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 2168a9de9248SMarcel Holtmann break; 2169a9de9248SMarcel Holtmann 2170e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 2171e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 2172e4e8e37cSMarcel Holtmann break; 2173e4e8e37cSMarcel Holtmann 2174e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 2175e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 2176e4e8e37cSMarcel Holtmann break; 2177e4e8e37cSMarcel Holtmann 2178a9de9248SMarcel Holtmann case HCI_OP_RESET: 2179a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 2180a9de9248SMarcel Holtmann break; 2181a9de9248SMarcel Holtmann 2182a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 2183a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 2184a9de9248SMarcel Holtmann break; 2185a9de9248SMarcel Holtmann 2186a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 2187a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 2188a9de9248SMarcel Holtmann break; 2189a9de9248SMarcel Holtmann 2190a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 2191a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 2192a9de9248SMarcel Holtmann break; 2193a9de9248SMarcel Holtmann 2194a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 2195a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 2196a9de9248SMarcel Holtmann break; 2197a9de9248SMarcel Holtmann 2198a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 2199a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 2200a9de9248SMarcel Holtmann break; 2201a9de9248SMarcel Holtmann 2202a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 2203a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 2204a9de9248SMarcel Holtmann break; 2205a9de9248SMarcel Holtmann 2206a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 2207a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 2208a9de9248SMarcel Holtmann break; 2209a9de9248SMarcel Holtmann 2210a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 2211a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 2212a9de9248SMarcel Holtmann break; 2213a9de9248SMarcel Holtmann 2214a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 2215a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 2216a9de9248SMarcel Holtmann break; 2217a9de9248SMarcel Holtmann 2218a9de9248SMarcel Holtmann case HCI_OP_HOST_BUFFER_SIZE: 2219a9de9248SMarcel Holtmann hci_cc_host_buffer_size(hdev, skb); 2220a9de9248SMarcel Holtmann break; 2221a9de9248SMarcel Holtmann 2222333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 2223333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 2224333140b5SMarcel Holtmann break; 2225333140b5SMarcel Holtmann 2226a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 2227a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 2228a9de9248SMarcel Holtmann break; 2229a9de9248SMarcel Holtmann 2230a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 2231a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 2232a9de9248SMarcel Holtmann break; 2233a9de9248SMarcel Holtmann 2234a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 2235a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 2236a9de9248SMarcel Holtmann break; 2237a9de9248SMarcel Holtmann 2238971e3a4bSAndre Guedes case HCI_OP_READ_LOCAL_EXT_FEATURES: 2239971e3a4bSAndre Guedes hci_cc_read_local_ext_features(hdev, skb); 2240971e3a4bSAndre Guedes break; 2241971e3a4bSAndre Guedes 2242a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 2243a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 2244a9de9248SMarcel Holtmann break; 2245a9de9248SMarcel Holtmann 2246a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 2247a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 2248a9de9248SMarcel Holtmann break; 2249a9de9248SMarcel Holtmann 2250350ee4cfSAndrei Emeltchenko case HCI_OP_READ_DATA_BLOCK_SIZE: 2251350ee4cfSAndrei Emeltchenko hci_cc_read_data_block_size(hdev, skb); 2252350ee4cfSAndrei Emeltchenko break; 2253350ee4cfSAndrei Emeltchenko 225423bb5763SJohan Hedberg case HCI_OP_WRITE_CA_TIMEOUT: 225523bb5763SJohan Hedberg hci_cc_write_ca_timeout(hdev, skb); 225623bb5763SJohan Hedberg break; 225723bb5763SJohan Hedberg 22581e89cffbSAndrei Emeltchenko case HCI_OP_READ_FLOW_CONTROL_MODE: 22591e89cffbSAndrei Emeltchenko hci_cc_read_flow_control_mode(hdev, skb); 22601e89cffbSAndrei Emeltchenko break; 22611e89cffbSAndrei Emeltchenko 2262928abaa7SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_INFO: 2263928abaa7SAndrei Emeltchenko hci_cc_read_local_amp_info(hdev, skb); 2264928abaa7SAndrei Emeltchenko break; 2265928abaa7SAndrei Emeltchenko 2266b0916ea0SJohan Hedberg case HCI_OP_DELETE_STORED_LINK_KEY: 2267b0916ea0SJohan Hedberg hci_cc_delete_stored_link_key(hdev, skb); 2268b0916ea0SJohan Hedberg break; 2269b0916ea0SJohan Hedberg 2270d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_MASK: 2271d5859e22SJohan Hedberg hci_cc_set_event_mask(hdev, skb); 2272d5859e22SJohan Hedberg break; 2273d5859e22SJohan Hedberg 2274d5859e22SJohan Hedberg case HCI_OP_WRITE_INQUIRY_MODE: 2275d5859e22SJohan Hedberg hci_cc_write_inquiry_mode(hdev, skb); 2276d5859e22SJohan Hedberg break; 2277d5859e22SJohan Hedberg 2278d5859e22SJohan Hedberg case HCI_OP_READ_INQ_RSP_TX_POWER: 2279d5859e22SJohan Hedberg hci_cc_read_inq_rsp_tx_power(hdev, skb); 2280d5859e22SJohan Hedberg break; 2281d5859e22SJohan Hedberg 2282d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_FLT: 2283d5859e22SJohan Hedberg hci_cc_set_event_flt(hdev, skb); 2284d5859e22SJohan Hedberg break; 2285d5859e22SJohan Hedberg 2286980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_REPLY: 2287980e1a53SJohan Hedberg hci_cc_pin_code_reply(hdev, skb); 2288980e1a53SJohan Hedberg break; 2289980e1a53SJohan Hedberg 2290980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_NEG_REPLY: 2291980e1a53SJohan Hedberg hci_cc_pin_code_neg_reply(hdev, skb); 2292980e1a53SJohan Hedberg break; 2293980e1a53SJohan Hedberg 2294c35938b2SSzymon Janc case HCI_OP_READ_LOCAL_OOB_DATA: 2295c35938b2SSzymon Janc hci_cc_read_local_oob_data_reply(hdev, skb); 2296c35938b2SSzymon Janc break; 2297c35938b2SSzymon Janc 22986ed58ec5SVille Tervo case HCI_OP_LE_READ_BUFFER_SIZE: 22996ed58ec5SVille Tervo hci_cc_le_read_buffer_size(hdev, skb); 23006ed58ec5SVille Tervo break; 23016ed58ec5SVille Tervo 2302a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_REPLY: 2303a5c29683SJohan Hedberg hci_cc_user_confirm_reply(hdev, skb); 2304a5c29683SJohan Hedberg break; 2305a5c29683SJohan Hedberg 2306a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_NEG_REPLY: 2307a5c29683SJohan Hedberg hci_cc_user_confirm_neg_reply(hdev, skb); 2308a5c29683SJohan Hedberg break; 2309a5c29683SJohan Hedberg 23101143d458SBrian Gix case HCI_OP_USER_PASSKEY_REPLY: 23111143d458SBrian Gix hci_cc_user_passkey_reply(hdev, skb); 23121143d458SBrian Gix break; 23131143d458SBrian Gix 23141143d458SBrian Gix case HCI_OP_USER_PASSKEY_NEG_REPLY: 23151143d458SBrian Gix hci_cc_user_passkey_neg_reply(hdev, skb); 231616cde993SSzymon Janc break; 231707f7fa5dSAndre Guedes 231807f7fa5dSAndre Guedes case HCI_OP_LE_SET_SCAN_PARAM: 231907f7fa5dSAndre Guedes hci_cc_le_set_scan_param(hdev, skb); 23201143d458SBrian Gix break; 23211143d458SBrian Gix 2322eb9d91f5SAndre Guedes case HCI_OP_LE_SET_SCAN_ENABLE: 2323eb9d91f5SAndre Guedes hci_cc_le_set_scan_enable(hdev, skb); 2324eb9d91f5SAndre Guedes break; 2325eb9d91f5SAndre Guedes 2326a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_REPLY: 2327a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_reply(hdev, skb); 2328a7a595f6SVinicius Costa Gomes break; 2329a7a595f6SVinicius Costa Gomes 2330a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_NEG_REPLY: 2331a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_neg_reply(hdev, skb); 2332a7a595f6SVinicius Costa Gomes break; 2333a7a595f6SVinicius Costa Gomes 2334f9b49306SAndre Guedes case HCI_OP_WRITE_LE_HOST_SUPPORTED: 2335f9b49306SAndre Guedes hci_cc_write_le_host_supported(hdev, skb); 2336f9b49306SAndre Guedes break; 2337f9b49306SAndre Guedes 2338a9de9248SMarcel Holtmann default: 2339a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 2340a9de9248SMarcel Holtmann break; 2341a9de9248SMarcel Holtmann } 2342a9de9248SMarcel Holtmann 23436bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 23446bd32326SVille Tervo del_timer(&hdev->cmd_timer); 23456bd32326SVille Tervo 2346a9de9248SMarcel Holtmann if (ev->ncmd) { 2347a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2348a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2349c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2350a9de9248SMarcel Holtmann } 2351a9de9248SMarcel Holtmann } 2352a9de9248SMarcel Holtmann 2353a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 2354a9de9248SMarcel Holtmann { 2355a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 2356a9de9248SMarcel Holtmann __u16 opcode; 2357a9de9248SMarcel Holtmann 2358a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2359a9de9248SMarcel Holtmann 2360a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2361a9de9248SMarcel Holtmann 2362a9de9248SMarcel Holtmann switch (opcode) { 2363a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 2364a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 2365a9de9248SMarcel Holtmann break; 2366a9de9248SMarcel Holtmann 2367a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 2368a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 2369a9de9248SMarcel Holtmann break; 2370a9de9248SMarcel Holtmann 2371a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 2372a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 2373a9de9248SMarcel Holtmann break; 2374a9de9248SMarcel Holtmann 2375f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 2376f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 2377f8558555SMarcel Holtmann break; 2378f8558555SMarcel Holtmann 2379f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 2380f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 2381f8558555SMarcel Holtmann break; 2382f8558555SMarcel Holtmann 2383a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 2384a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 2385a9de9248SMarcel Holtmann break; 2386a9de9248SMarcel Holtmann 2387769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 2388769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 2389769be974SMarcel Holtmann break; 2390769be974SMarcel Holtmann 2391769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 2392769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 2393769be974SMarcel Holtmann break; 2394769be974SMarcel Holtmann 2395a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 2396a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 2397a9de9248SMarcel Holtmann break; 2398a9de9248SMarcel Holtmann 2399a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 2400a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 2401a9de9248SMarcel Holtmann break; 2402a9de9248SMarcel Holtmann 2403a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 2404a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 2405a9de9248SMarcel Holtmann break; 2406a9de9248SMarcel Holtmann 24078962ee74SJohan Hedberg case HCI_OP_DISCONNECT: 240888c3df13SJohan Hedberg hci_cs_disconnect(hdev, ev->status); 24098962ee74SJohan Hedberg break; 24108962ee74SJohan Hedberg 2411fcd89c09SVille Tervo case HCI_OP_LE_CREATE_CONN: 2412fcd89c09SVille Tervo hci_cs_le_create_conn(hdev, ev->status); 2413fcd89c09SVille Tervo break; 2414fcd89c09SVille Tervo 2415a7a595f6SVinicius Costa Gomes case HCI_OP_LE_START_ENC: 2416a7a595f6SVinicius Costa Gomes hci_cs_le_start_enc(hdev, ev->status); 2417a7a595f6SVinicius Costa Gomes break; 2418a7a595f6SVinicius Costa Gomes 2419a9de9248SMarcel Holtmann default: 2420a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 2421a9de9248SMarcel Holtmann break; 2422a9de9248SMarcel Holtmann } 2423a9de9248SMarcel Holtmann 24246bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 24256bd32326SVille Tervo del_timer(&hdev->cmd_timer); 24266bd32326SVille Tervo 242710572132SGustavo F. Padovan if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2428a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2429a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2430c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2431a9de9248SMarcel Holtmann } 2432a9de9248SMarcel Holtmann } 2433a9de9248SMarcel Holtmann 2434a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2435a9de9248SMarcel Holtmann { 2436a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 2437a9de9248SMarcel Holtmann struct hci_conn *conn; 2438a9de9248SMarcel Holtmann 2439a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2440a9de9248SMarcel Holtmann 2441a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2442a9de9248SMarcel Holtmann 2443a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2444a9de9248SMarcel Holtmann if (conn) { 2445a9de9248SMarcel Holtmann if (!ev->status) { 2446a9de9248SMarcel Holtmann if (ev->role) 2447a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_MASTER; 2448a9de9248SMarcel Holtmann else 2449a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_MASTER; 2450a9de9248SMarcel Holtmann } 2451a9de9248SMarcel Holtmann 245251a8efd7SJohan Hedberg clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); 2453a9de9248SMarcel Holtmann 2454a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 2455a9de9248SMarcel Holtmann } 2456a9de9248SMarcel Holtmann 2457a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2458a9de9248SMarcel Holtmann } 2459a9de9248SMarcel Holtmann 24601da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 24611da177e4SLinus Torvalds { 2462a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 24631da177e4SLinus Torvalds int i; 24641da177e4SLinus Torvalds 246532ac5b9bSAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) { 246632ac5b9bSAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 246732ac5b9bSAndrei Emeltchenko return; 246832ac5b9bSAndrei Emeltchenko } 246932ac5b9bSAndrei Emeltchenko 2470c5993de8SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 2471c5993de8SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_pkts_info)) { 24721da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 24731da177e4SLinus Torvalds return; 24741da177e4SLinus Torvalds } 24751da177e4SLinus Torvalds 2476c5993de8SAndrei Emeltchenko BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 2477c5993de8SAndrei Emeltchenko 2478613a1c0cSAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 2479613a1c0cSAndrei Emeltchenko struct hci_comp_pkts_info *info = &ev->handles[i]; 24801da177e4SLinus Torvalds struct hci_conn *conn; 24811da177e4SLinus Torvalds __u16 handle, count; 24821da177e4SLinus Torvalds 2483613a1c0cSAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 2484613a1c0cSAndrei Emeltchenko count = __le16_to_cpu(info->count); 24851da177e4SLinus Torvalds 24861da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 2487f4280918SAndrei Emeltchenko if (!conn) 2488f4280918SAndrei Emeltchenko continue; 2489f4280918SAndrei Emeltchenko 24901da177e4SLinus Torvalds conn->sent -= count; 24911da177e4SLinus Torvalds 2492f4280918SAndrei Emeltchenko switch (conn->type) { 2493f4280918SAndrei Emeltchenko case ACL_LINK: 249470f23020SAndrei Emeltchenko hdev->acl_cnt += count; 249570f23020SAndrei Emeltchenko if (hdev->acl_cnt > hdev->acl_pkts) 24961da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 2497f4280918SAndrei Emeltchenko break; 2498f4280918SAndrei Emeltchenko 2499f4280918SAndrei Emeltchenko case LE_LINK: 25006ed58ec5SVille Tervo if (hdev->le_pkts) { 25016ed58ec5SVille Tervo hdev->le_cnt += count; 25026ed58ec5SVille Tervo if (hdev->le_cnt > hdev->le_pkts) 25036ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 25046ed58ec5SVille Tervo } else { 25056ed58ec5SVille Tervo hdev->acl_cnt += count; 25066ed58ec5SVille Tervo if (hdev->acl_cnt > hdev->acl_pkts) 25076ed58ec5SVille Tervo hdev->acl_cnt = hdev->acl_pkts; 25086ed58ec5SVille Tervo } 2509f4280918SAndrei Emeltchenko break; 2510f4280918SAndrei Emeltchenko 2511f4280918SAndrei Emeltchenko case SCO_LINK: 251270f23020SAndrei Emeltchenko hdev->sco_cnt += count; 251370f23020SAndrei Emeltchenko if (hdev->sco_cnt > hdev->sco_pkts) 25145b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 2515f4280918SAndrei Emeltchenko break; 2516f4280918SAndrei Emeltchenko 2517f4280918SAndrei Emeltchenko default: 2518f4280918SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 2519f4280918SAndrei Emeltchenko break; 25201da177e4SLinus Torvalds } 25211da177e4SLinus Torvalds } 2522a9de9248SMarcel Holtmann 25233eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 25241da177e4SLinus Torvalds } 25251da177e4SLinus Torvalds 252625e89e99SAndrei Emeltchenko static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev, 252725e89e99SAndrei Emeltchenko struct sk_buff *skb) 252825e89e99SAndrei Emeltchenko { 252925e89e99SAndrei Emeltchenko struct hci_ev_num_comp_blocks *ev = (void *) skb->data; 253025e89e99SAndrei Emeltchenko int i; 253125e89e99SAndrei Emeltchenko 253225e89e99SAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) { 253325e89e99SAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 253425e89e99SAndrei Emeltchenko return; 253525e89e99SAndrei Emeltchenko } 253625e89e99SAndrei Emeltchenko 253725e89e99SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 253825e89e99SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_blocks_info)) { 253925e89e99SAndrei Emeltchenko BT_DBG("%s bad parameters", hdev->name); 254025e89e99SAndrei Emeltchenko return; 254125e89e99SAndrei Emeltchenko } 254225e89e99SAndrei Emeltchenko 254325e89e99SAndrei Emeltchenko BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks, 254425e89e99SAndrei Emeltchenko ev->num_hndl); 254525e89e99SAndrei Emeltchenko 254625e89e99SAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 254725e89e99SAndrei Emeltchenko struct hci_comp_blocks_info *info = &ev->handles[i]; 254825e89e99SAndrei Emeltchenko struct hci_conn *conn; 254925e89e99SAndrei Emeltchenko __u16 handle, block_count; 255025e89e99SAndrei Emeltchenko 255125e89e99SAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 255225e89e99SAndrei Emeltchenko block_count = __le16_to_cpu(info->blocks); 255325e89e99SAndrei Emeltchenko 255425e89e99SAndrei Emeltchenko conn = hci_conn_hash_lookup_handle(hdev, handle); 255525e89e99SAndrei Emeltchenko if (!conn) 255625e89e99SAndrei Emeltchenko continue; 255725e89e99SAndrei Emeltchenko 255825e89e99SAndrei Emeltchenko conn->sent -= block_count; 255925e89e99SAndrei Emeltchenko 256025e89e99SAndrei Emeltchenko switch (conn->type) { 256125e89e99SAndrei Emeltchenko case ACL_LINK: 256225e89e99SAndrei Emeltchenko hdev->block_cnt += block_count; 256325e89e99SAndrei Emeltchenko if (hdev->block_cnt > hdev->num_blocks) 256425e89e99SAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 256525e89e99SAndrei Emeltchenko break; 256625e89e99SAndrei Emeltchenko 256725e89e99SAndrei Emeltchenko default: 256825e89e99SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 256925e89e99SAndrei Emeltchenko break; 257025e89e99SAndrei Emeltchenko } 257125e89e99SAndrei Emeltchenko } 257225e89e99SAndrei Emeltchenko 257325e89e99SAndrei Emeltchenko queue_work(hdev->workqueue, &hdev->tx_work); 257425e89e99SAndrei Emeltchenko } 257525e89e99SAndrei Emeltchenko 257604837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 25771da177e4SLinus Torvalds { 2578a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 257904837f64SMarcel Holtmann struct hci_conn *conn; 25801da177e4SLinus Torvalds 25811da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 25821da177e4SLinus Torvalds 25831da177e4SLinus Torvalds hci_dev_lock(hdev); 25841da177e4SLinus Torvalds 258504837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 258604837f64SMarcel Holtmann if (conn) { 258704837f64SMarcel Holtmann conn->mode = ev->mode; 258804837f64SMarcel Holtmann conn->interval = __le16_to_cpu(ev->interval); 258904837f64SMarcel Holtmann 259051a8efd7SJohan Hedberg if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) { 259104837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 259258a681efSJohan Hedberg set_bit(HCI_CONN_POWER_SAVE, &conn->flags); 259304837f64SMarcel Holtmann else 259458a681efSJohan Hedberg clear_bit(HCI_CONN_POWER_SAVE, &conn->flags); 259504837f64SMarcel Holtmann } 2596e73439d8SMarcel Holtmann 259751a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 2598e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 259904837f64SMarcel Holtmann } 260004837f64SMarcel Holtmann 260104837f64SMarcel Holtmann hci_dev_unlock(hdev); 260204837f64SMarcel Holtmann } 260304837f64SMarcel Holtmann 26041da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 26051da177e4SLinus Torvalds { 2606052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 2607052b30b0SMarcel Holtmann struct hci_conn *conn; 2608052b30b0SMarcel Holtmann 2609a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2610052b30b0SMarcel Holtmann 2611052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2612052b30b0SMarcel Holtmann 2613052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2614b6f98044SWaldemar Rymarkiewicz if (!conn) 2615b6f98044SWaldemar Rymarkiewicz goto unlock; 2616b6f98044SWaldemar Rymarkiewicz 2617b6f98044SWaldemar Rymarkiewicz if (conn->state == BT_CONNECTED) { 2618052b30b0SMarcel Holtmann hci_conn_hold(conn); 2619052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 2620052b30b0SMarcel Holtmann hci_conn_put(conn); 2621052b30b0SMarcel Holtmann } 2622052b30b0SMarcel Holtmann 2623a8b2d5c2SJohan Hedberg if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags)) 262403b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 262503b555e1SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 2626a8b2d5c2SJohan Hedberg else if (test_bit(HCI_MGMT, &hdev->dev_flags)) { 2627a770bb5aSWaldemar Rymarkiewicz u8 secure; 2628a770bb5aSWaldemar Rymarkiewicz 2629a770bb5aSWaldemar Rymarkiewicz if (conn->pending_sec_level == BT_SECURITY_HIGH) 2630a770bb5aSWaldemar Rymarkiewicz secure = 1; 2631a770bb5aSWaldemar Rymarkiewicz else 2632a770bb5aSWaldemar Rymarkiewicz secure = 0; 2633a770bb5aSWaldemar Rymarkiewicz 2634744cf19eSJohan Hedberg mgmt_pin_code_request(hdev, &ev->bdaddr, secure); 2635a770bb5aSWaldemar Rymarkiewicz } 2636980e1a53SJohan Hedberg 2637b6f98044SWaldemar Rymarkiewicz unlock: 2638052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 26391da177e4SLinus Torvalds } 26401da177e4SLinus Torvalds 26411da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 26421da177e4SLinus Torvalds { 264355ed8ca1SJohan Hedberg struct hci_ev_link_key_req *ev = (void *) skb->data; 264455ed8ca1SJohan Hedberg struct hci_cp_link_key_reply cp; 264555ed8ca1SJohan Hedberg struct hci_conn *conn; 264655ed8ca1SJohan Hedberg struct link_key *key; 264755ed8ca1SJohan Hedberg 2648a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 264955ed8ca1SJohan Hedberg 2650a8b2d5c2SJohan Hedberg if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) 265155ed8ca1SJohan Hedberg return; 265255ed8ca1SJohan Hedberg 265355ed8ca1SJohan Hedberg hci_dev_lock(hdev); 265455ed8ca1SJohan Hedberg 265555ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, &ev->bdaddr); 265655ed8ca1SJohan Hedberg if (!key) { 265755ed8ca1SJohan Hedberg BT_DBG("%s link key not found for %s", hdev->name, 265855ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 265955ed8ca1SJohan Hedberg goto not_found; 266055ed8ca1SJohan Hedberg } 266155ed8ca1SJohan Hedberg 266255ed8ca1SJohan Hedberg BT_DBG("%s found key type %u for %s", hdev->name, key->type, 266355ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 266455ed8ca1SJohan Hedberg 2665a8b2d5c2SJohan Hedberg if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) && 2666b6020ba0SWaldemar Rymarkiewicz key->type == HCI_LK_DEBUG_COMBINATION) { 266755ed8ca1SJohan Hedberg BT_DBG("%s ignoring debug key", hdev->name); 266855ed8ca1SJohan Hedberg goto not_found; 266955ed8ca1SJohan Hedberg } 267055ed8ca1SJohan Hedberg 267155ed8ca1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 267260b83f57SWaldemar Rymarkiewicz if (conn) { 267360b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_UNAUTH_COMBINATION && 267460b83f57SWaldemar Rymarkiewicz conn->auth_type != 0xff && 267560b83f57SWaldemar Rymarkiewicz (conn->auth_type & 0x01)) { 267655ed8ca1SJohan Hedberg BT_DBG("%s ignoring unauthenticated key", hdev->name); 267755ed8ca1SJohan Hedberg goto not_found; 267855ed8ca1SJohan Hedberg } 267955ed8ca1SJohan Hedberg 268060b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && 268160b83f57SWaldemar Rymarkiewicz conn->pending_sec_level == BT_SECURITY_HIGH) { 268260b83f57SWaldemar Rymarkiewicz BT_DBG("%s ignoring key unauthenticated for high \ 268360b83f57SWaldemar Rymarkiewicz security", hdev->name); 268460b83f57SWaldemar Rymarkiewicz goto not_found; 268560b83f57SWaldemar Rymarkiewicz } 268660b83f57SWaldemar Rymarkiewicz 268760b83f57SWaldemar Rymarkiewicz conn->key_type = key->type; 268860b83f57SWaldemar Rymarkiewicz conn->pin_length = key->pin_len; 268960b83f57SWaldemar Rymarkiewicz } 269060b83f57SWaldemar Rymarkiewicz 269155ed8ca1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 269255ed8ca1SJohan Hedberg memcpy(cp.link_key, key->val, 16); 269355ed8ca1SJohan Hedberg 269455ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 269555ed8ca1SJohan Hedberg 269655ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 269755ed8ca1SJohan Hedberg 269855ed8ca1SJohan Hedberg return; 269955ed8ca1SJohan Hedberg 270055ed8ca1SJohan Hedberg not_found: 270155ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 270255ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 27031da177e4SLinus Torvalds } 27041da177e4SLinus Torvalds 27051da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 27061da177e4SLinus Torvalds { 2707052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 2708052b30b0SMarcel Holtmann struct hci_conn *conn; 270955ed8ca1SJohan Hedberg u8 pin_len = 0; 2710052b30b0SMarcel Holtmann 2711a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2712052b30b0SMarcel Holtmann 2713052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2714052b30b0SMarcel Holtmann 2715052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2716052b30b0SMarcel Holtmann if (conn) { 2717052b30b0SMarcel Holtmann hci_conn_hold(conn); 2718052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2719980e1a53SJohan Hedberg pin_len = conn->pin_length; 272013d39315SWaldemar Rymarkiewicz 272113d39315SWaldemar Rymarkiewicz if (ev->key_type != HCI_LK_CHANGED_COMBINATION) 272213d39315SWaldemar Rymarkiewicz conn->key_type = ev->key_type; 272313d39315SWaldemar Rymarkiewicz 2724052b30b0SMarcel Holtmann hci_conn_put(conn); 2725052b30b0SMarcel Holtmann } 2726052b30b0SMarcel Holtmann 2727a8b2d5c2SJohan Hedberg if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) 2728d25e28abSJohan Hedberg hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, 272955ed8ca1SJohan Hedberg ev->key_type, pin_len); 273055ed8ca1SJohan Hedberg 2731052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 27321da177e4SLinus Torvalds } 27331da177e4SLinus Torvalds 273404837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 273504837f64SMarcel Holtmann { 2736a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 273704837f64SMarcel Holtmann struct hci_conn *conn; 273804837f64SMarcel Holtmann 273904837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 274004837f64SMarcel Holtmann 274104837f64SMarcel Holtmann hci_dev_lock(hdev); 274204837f64SMarcel Holtmann 274304837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 27441da177e4SLinus Torvalds if (conn && !ev->status) { 27451da177e4SLinus Torvalds struct inquiry_entry *ie; 27461da177e4SLinus Torvalds 2747cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2748cc11b9c1SAndrei Emeltchenko if (ie) { 27491da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 27501da177e4SLinus Torvalds ie->timestamp = jiffies; 27511da177e4SLinus Torvalds } 27521da177e4SLinus Torvalds } 27531da177e4SLinus Torvalds 27541da177e4SLinus Torvalds hci_dev_unlock(hdev); 27551da177e4SLinus Torvalds } 27561da177e4SLinus Torvalds 2757a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2758a8746417SMarcel Holtmann { 2759a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 2760a8746417SMarcel Holtmann struct hci_conn *conn; 2761a8746417SMarcel Holtmann 2762a8746417SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2763a8746417SMarcel Holtmann 2764a8746417SMarcel Holtmann hci_dev_lock(hdev); 2765a8746417SMarcel Holtmann 2766a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2767a8746417SMarcel Holtmann if (conn && !ev->status) 2768a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 2769a8746417SMarcel Holtmann 2770a8746417SMarcel Holtmann hci_dev_unlock(hdev); 2771a8746417SMarcel Holtmann } 2772a8746417SMarcel Holtmann 277385a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 277485a1e930SMarcel Holtmann { 2775a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 277685a1e930SMarcel Holtmann struct inquiry_entry *ie; 277785a1e930SMarcel Holtmann 277885a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 277985a1e930SMarcel Holtmann 278085a1e930SMarcel Holtmann hci_dev_lock(hdev); 278185a1e930SMarcel Holtmann 2782cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2783cc11b9c1SAndrei Emeltchenko if (ie) { 278485a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 278585a1e930SMarcel Holtmann ie->timestamp = jiffies; 278685a1e930SMarcel Holtmann } 278785a1e930SMarcel Holtmann 278885a1e930SMarcel Holtmann hci_dev_unlock(hdev); 278985a1e930SMarcel Holtmann } 279085a1e930SMarcel Holtmann 2791a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb) 2792a9de9248SMarcel Holtmann { 2793a9de9248SMarcel Holtmann struct inquiry_data data; 2794a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2795388fc8faSJohan Hedberg bool name_known, ssp; 2796a9de9248SMarcel Holtmann 2797a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2798a9de9248SMarcel Holtmann 2799a9de9248SMarcel Holtmann if (!num_rsp) 2800a9de9248SMarcel Holtmann return; 2801a9de9248SMarcel Holtmann 2802a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2803a9de9248SMarcel Holtmann 2804a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 2805138d22efSSzymon Janc struct inquiry_info_with_rssi_and_pscan_mode *info; 2806138d22efSSzymon Janc info = (void *) (skb->data + 1); 2807a9de9248SMarcel Holtmann 2808e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2809a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2810a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2811a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2812a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 2813a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2814a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2815a9de9248SMarcel Holtmann data.rssi = info->rssi; 281641a96212SMarcel Holtmann data.ssp_mode = 0x00; 28173175405bSJohan Hedberg 28183175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 2819388fc8faSJohan Hedberg false, &ssp); 282048264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2821e17acd40SJohan Hedberg info->dev_class, info->rssi, 2822388fc8faSJohan Hedberg !name_known, ssp, NULL, 0); 2823a9de9248SMarcel Holtmann } 2824a9de9248SMarcel Holtmann } else { 2825a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 2826a9de9248SMarcel Holtmann 2827e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2828a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2829a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2830a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2831a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2832a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2833a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2834a9de9248SMarcel Holtmann data.rssi = info->rssi; 283541a96212SMarcel Holtmann data.ssp_mode = 0x00; 28363175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 2837388fc8faSJohan Hedberg false, &ssp); 283848264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2839e17acd40SJohan Hedberg info->dev_class, info->rssi, 2840388fc8faSJohan Hedberg !name_known, ssp, NULL, 0); 2841a9de9248SMarcel Holtmann } 2842a9de9248SMarcel Holtmann } 2843a9de9248SMarcel Holtmann 2844a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2845a9de9248SMarcel Holtmann } 2846a9de9248SMarcel Holtmann 2847a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 2848a9de9248SMarcel Holtmann { 284941a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 285041a96212SMarcel Holtmann struct hci_conn *conn; 285141a96212SMarcel Holtmann 2852a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 285341a96212SMarcel Holtmann 285441a96212SMarcel Holtmann hci_dev_lock(hdev); 285541a96212SMarcel Holtmann 285641a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2857ccd556feSJohan Hedberg if (!conn) 2858ccd556feSJohan Hedberg goto unlock; 2859ccd556feSJohan Hedberg 2860769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 286141a96212SMarcel Holtmann struct inquiry_entry *ie; 286241a96212SMarcel Holtmann 2863cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2864cc11b9c1SAndrei Emeltchenko if (ie) 286502b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 286641a96212SMarcel Holtmann 286702b7cc62SJohan Hedberg if (ev->features[0] & LMP_HOST_SSP) 286858a681efSJohan Hedberg set_bit(HCI_CONN_SSP_ENABLED, &conn->flags); 286941a96212SMarcel Holtmann } 287041a96212SMarcel Holtmann 2871ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2872ccd556feSJohan Hedberg goto unlock; 2873ccd556feSJohan Hedberg 2874127178d2SJohan Hedberg if (!ev->status) { 2875127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2876127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2877127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2878127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2879127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2880b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 2881b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 288208c79b61SJohan Hedberg conn->dst_type, 0, NULL, 0, 2883b644ba33SJohan Hedberg conn->dev_class); 2884392599b9SJohan Hedberg 2885127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2886769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2887769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2888769be974SMarcel Holtmann hci_conn_put(conn); 2889769be974SMarcel Holtmann } 2890769be974SMarcel Holtmann 2891ccd556feSJohan Hedberg unlock: 289241a96212SMarcel Holtmann hci_dev_unlock(hdev); 2893a9de9248SMarcel Holtmann } 2894a9de9248SMarcel Holtmann 2895a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2896a9de9248SMarcel Holtmann { 2897b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 2898b6a0dc82SMarcel Holtmann struct hci_conn *conn; 2899b6a0dc82SMarcel Holtmann 2900b6a0dc82SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2901b6a0dc82SMarcel Holtmann 2902b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 2903b6a0dc82SMarcel Holtmann 2904b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 29059dc0a3afSMarcel Holtmann if (!conn) { 29069dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 29079dc0a3afSMarcel Holtmann goto unlock; 29089dc0a3afSMarcel Holtmann 29099dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 2910b6a0dc82SMarcel Holtmann if (!conn) 2911b6a0dc82SMarcel Holtmann goto unlock; 2912b6a0dc82SMarcel Holtmann 29139dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 29149dc0a3afSMarcel Holtmann } 29159dc0a3afSMarcel Holtmann 2916732547f9SMarcel Holtmann switch (ev->status) { 2917732547f9SMarcel Holtmann case 0x00: 2918732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 2919732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 2920732547f9SMarcel Holtmann 29219eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 2922732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 2923732547f9SMarcel Holtmann break; 2924732547f9SMarcel Holtmann 2925705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 2926732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 29271038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 2928732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 2929732547f9SMarcel Holtmann if (conn->out && conn->attempt < 2) { 2930efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 2931efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 2932efc7688bSMarcel Holtmann hci_setup_sync(conn, conn->link->handle); 2933efc7688bSMarcel Holtmann goto unlock; 2934efc7688bSMarcel Holtmann } 2935732547f9SMarcel Holtmann /* fall through */ 2936efc7688bSMarcel Holtmann 2937732547f9SMarcel Holtmann default: 2938b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 2939732547f9SMarcel Holtmann break; 2940732547f9SMarcel Holtmann } 2941b6a0dc82SMarcel Holtmann 2942b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2943b6a0dc82SMarcel Holtmann if (ev->status) 2944b6a0dc82SMarcel Holtmann hci_conn_del(conn); 2945b6a0dc82SMarcel Holtmann 2946b6a0dc82SMarcel Holtmann unlock: 2947b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 2948a9de9248SMarcel Holtmann } 2949a9de9248SMarcel Holtmann 2950a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) 2951a9de9248SMarcel Holtmann { 2952a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2953a9de9248SMarcel Holtmann } 2954a9de9248SMarcel Holtmann 295504837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) 295604837f64SMarcel Holtmann { 2957a9de9248SMarcel Holtmann struct hci_ev_sniff_subrate *ev = (void *) skb->data; 295804837f64SMarcel Holtmann 295904837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 296004837f64SMarcel Holtmann } 296104837f64SMarcel Holtmann 2962a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 2963a9de9248SMarcel Holtmann { 2964a9de9248SMarcel Holtmann struct inquiry_data data; 2965a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 2966a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2967a9de9248SMarcel Holtmann 2968a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2969a9de9248SMarcel Holtmann 2970a9de9248SMarcel Holtmann if (!num_rsp) 2971a9de9248SMarcel Holtmann return; 2972a9de9248SMarcel Holtmann 2973a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2974a9de9248SMarcel Holtmann 2975e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2976388fc8faSJohan Hedberg bool name_known, ssp; 2977561aafbcSJohan Hedberg 2978a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2979a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2980a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2981a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2982a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2983a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2984a9de9248SMarcel Holtmann data.rssi = info->rssi; 298541a96212SMarcel Holtmann data.ssp_mode = 0x01; 2986561aafbcSJohan Hedberg 2987a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 29884ddb1930SJohan Hedberg name_known = eir_has_data_type(info->data, 29894ddb1930SJohan Hedberg sizeof(info->data), 29904ddb1930SJohan Hedberg EIR_NAME_COMPLETE); 2991561aafbcSJohan Hedberg else 2992561aafbcSJohan Hedberg name_known = true; 2993561aafbcSJohan Hedberg 2994388fc8faSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, name_known, 2995388fc8faSJohan Hedberg &ssp); 299648264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 299704124681SGustavo F. Padovan info->dev_class, info->rssi, !name_known, 299804124681SGustavo F. Padovan ssp, info->data, sizeof(info->data)); 2999a9de9248SMarcel Holtmann } 3000a9de9248SMarcel Holtmann 3001a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 3002a9de9248SMarcel Holtmann } 3003a9de9248SMarcel Holtmann 300417fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn) 300517fa4b9dSJohan Hedberg { 300617fa4b9dSJohan Hedberg /* If remote requests dedicated bonding follow that lead */ 300717fa4b9dSJohan Hedberg if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) { 300817fa4b9dSJohan Hedberg /* If both remote and local IO capabilities allow MITM 300917fa4b9dSJohan Hedberg * protection then require it, otherwise don't */ 301017fa4b9dSJohan Hedberg if (conn->remote_cap == 0x03 || conn->io_capability == 0x03) 301117fa4b9dSJohan Hedberg return 0x02; 301217fa4b9dSJohan Hedberg else 301317fa4b9dSJohan Hedberg return 0x03; 301417fa4b9dSJohan Hedberg } 301517fa4b9dSJohan Hedberg 301617fa4b9dSJohan Hedberg /* If remote requests no-bonding follow that lead */ 301717fa4b9dSJohan Hedberg if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01) 301858797bf7SWaldemar Rymarkiewicz return conn->remote_auth | (conn->auth_type & 0x01); 301917fa4b9dSJohan Hedberg 302017fa4b9dSJohan Hedberg return conn->auth_type; 302117fa4b9dSJohan Hedberg } 302217fa4b9dSJohan Hedberg 30230493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 30240493684eSMarcel Holtmann { 30250493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 30260493684eSMarcel Holtmann struct hci_conn *conn; 30270493684eSMarcel Holtmann 30280493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 30290493684eSMarcel Holtmann 30300493684eSMarcel Holtmann hci_dev_lock(hdev); 30310493684eSMarcel Holtmann 30320493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 303303b555e1SJohan Hedberg if (!conn) 303403b555e1SJohan Hedberg goto unlock; 303503b555e1SJohan Hedberg 30360493684eSMarcel Holtmann hci_conn_hold(conn); 30370493684eSMarcel Holtmann 3038a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 303903b555e1SJohan Hedberg goto unlock; 304003b555e1SJohan Hedberg 3041a8b2d5c2SJohan Hedberg if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) || 304203b555e1SJohan Hedberg (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 304317fa4b9dSJohan Hedberg struct hci_cp_io_capability_reply cp; 304417fa4b9dSJohan Hedberg 304517fa4b9dSJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 30467a7f1e7cSHemant Gupta /* Change the IO capability from KeyboardDisplay 30477a7f1e7cSHemant Gupta * to DisplayYesNo as it is not supported by BT spec. */ 30487a7f1e7cSHemant Gupta cp.capability = (conn->io_capability == 0x04) ? 30497a7f1e7cSHemant Gupta 0x01 : conn->io_capability; 30507cbc9bd9SJohan Hedberg conn->auth_type = hci_get_auth_req(conn); 30517cbc9bd9SJohan Hedberg cp.authentication = conn->auth_type; 305217fa4b9dSJohan Hedberg 305358a681efSJohan Hedberg if ((conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)) && 3054ce85ee13SSzymon Janc hci_find_remote_oob_data(hdev, &conn->dst)) 3055ce85ee13SSzymon Janc cp.oob_data = 0x01; 3056ce85ee13SSzymon Janc else 3057ce85ee13SSzymon Janc cp.oob_data = 0x00; 3058ce85ee13SSzymon Janc 305917fa4b9dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, 306017fa4b9dSJohan Hedberg sizeof(cp), &cp); 306103b555e1SJohan Hedberg } else { 306203b555e1SJohan Hedberg struct hci_cp_io_capability_neg_reply cp; 306303b555e1SJohan Hedberg 306403b555e1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 30659f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED; 306603b555e1SJohan Hedberg 306703b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 306803b555e1SJohan Hedberg sizeof(cp), &cp); 306903b555e1SJohan Hedberg } 307003b555e1SJohan Hedberg 307103b555e1SJohan Hedberg unlock: 307203b555e1SJohan Hedberg hci_dev_unlock(hdev); 307303b555e1SJohan Hedberg } 307403b555e1SJohan Hedberg 307503b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 307603b555e1SJohan Hedberg { 307703b555e1SJohan Hedberg struct hci_ev_io_capa_reply *ev = (void *) skb->data; 307803b555e1SJohan Hedberg struct hci_conn *conn; 307903b555e1SJohan Hedberg 308003b555e1SJohan Hedberg BT_DBG("%s", hdev->name); 308103b555e1SJohan Hedberg 308203b555e1SJohan Hedberg hci_dev_lock(hdev); 308303b555e1SJohan Hedberg 308403b555e1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 308503b555e1SJohan Hedberg if (!conn) 308603b555e1SJohan Hedberg goto unlock; 308703b555e1SJohan Hedberg 308803b555e1SJohan Hedberg conn->remote_cap = ev->capability; 308903b555e1SJohan Hedberg conn->remote_auth = ev->authentication; 309058a681efSJohan Hedberg if (ev->oob_data) 309158a681efSJohan Hedberg set_bit(HCI_CONN_REMOTE_OOB, &conn->flags); 309203b555e1SJohan Hedberg 309303b555e1SJohan Hedberg unlock: 30940493684eSMarcel Holtmann hci_dev_unlock(hdev); 30950493684eSMarcel Holtmann } 30960493684eSMarcel Holtmann 3097a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev, 3098a5c29683SJohan Hedberg struct sk_buff *skb) 3099a5c29683SJohan Hedberg { 3100a5c29683SJohan Hedberg struct hci_ev_user_confirm_req *ev = (void *) skb->data; 310155bc1a37SJohan Hedberg int loc_mitm, rem_mitm, confirm_hint = 0; 31027a828908SJohan Hedberg struct hci_conn *conn; 3103a5c29683SJohan Hedberg 3104a5c29683SJohan Hedberg BT_DBG("%s", hdev->name); 3105a5c29683SJohan Hedberg 3106a5c29683SJohan Hedberg hci_dev_lock(hdev); 3107a5c29683SJohan Hedberg 3108a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 31097a828908SJohan Hedberg goto unlock; 31107a828908SJohan Hedberg 31117a828908SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 31127a828908SJohan Hedberg if (!conn) 31137a828908SJohan Hedberg goto unlock; 31147a828908SJohan Hedberg 31157a828908SJohan Hedberg loc_mitm = (conn->auth_type & 0x01); 31167a828908SJohan Hedberg rem_mitm = (conn->remote_auth & 0x01); 31177a828908SJohan Hedberg 31187a828908SJohan Hedberg /* If we require MITM but the remote device can't provide that 31197a828908SJohan Hedberg * (it has NoInputNoOutput) then reject the confirmation 31207a828908SJohan Hedberg * request. The only exception is when we're dedicated bonding 31217a828908SJohan Hedberg * initiators (connect_cfm_cb set) since then we always have the MITM 31227a828908SJohan Hedberg * bit set. */ 31237a828908SJohan Hedberg if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) { 31247a828908SJohan Hedberg BT_DBG("Rejecting request: remote device can't provide MITM"); 31257a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, 31267a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 31277a828908SJohan Hedberg goto unlock; 31287a828908SJohan Hedberg } 31297a828908SJohan Hedberg 31307a828908SJohan Hedberg /* If no side requires MITM protection; auto-accept */ 31317a828908SJohan Hedberg if ((!loc_mitm || conn->remote_cap == 0x03) && 31327a828908SJohan Hedberg (!rem_mitm || conn->io_capability == 0x03)) { 313355bc1a37SJohan Hedberg 313455bc1a37SJohan Hedberg /* If we're not the initiators request authorization to 313555bc1a37SJohan Hedberg * proceed from user space (mgmt_user_confirm with 313655bc1a37SJohan Hedberg * confirm_hint set to 1). */ 313751a8efd7SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 313855bc1a37SJohan Hedberg BT_DBG("Confirming auto-accept as acceptor"); 313955bc1a37SJohan Hedberg confirm_hint = 1; 314055bc1a37SJohan Hedberg goto confirm; 314155bc1a37SJohan Hedberg } 314255bc1a37SJohan Hedberg 31439f61656aSJohan Hedberg BT_DBG("Auto-accept of user confirmation with %ums delay", 31449f61656aSJohan Hedberg hdev->auto_accept_delay); 31459f61656aSJohan Hedberg 31469f61656aSJohan Hedberg if (hdev->auto_accept_delay > 0) { 31479f61656aSJohan Hedberg int delay = msecs_to_jiffies(hdev->auto_accept_delay); 31489f61656aSJohan Hedberg mod_timer(&conn->auto_accept_timer, jiffies + delay); 31499f61656aSJohan Hedberg goto unlock; 31509f61656aSJohan Hedberg } 31519f61656aSJohan Hedberg 31527a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, 31537a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 31547a828908SJohan Hedberg goto unlock; 31557a828908SJohan Hedberg } 31567a828908SJohan Hedberg 315755bc1a37SJohan Hedberg confirm: 3158272d90dfSJohan Hedberg mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey, 315955bc1a37SJohan Hedberg confirm_hint); 3160a5c29683SJohan Hedberg 31617a828908SJohan Hedberg unlock: 3162a5c29683SJohan Hedberg hci_dev_unlock(hdev); 3163a5c29683SJohan Hedberg } 3164a5c29683SJohan Hedberg 31651143d458SBrian Gix static inline void hci_user_passkey_request_evt(struct hci_dev *hdev, 31661143d458SBrian Gix struct sk_buff *skb) 31671143d458SBrian Gix { 31681143d458SBrian Gix struct hci_ev_user_passkey_req *ev = (void *) skb->data; 31691143d458SBrian Gix 31701143d458SBrian Gix BT_DBG("%s", hdev->name); 31711143d458SBrian Gix 31721143d458SBrian Gix hci_dev_lock(hdev); 31731143d458SBrian Gix 3174a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 3175272d90dfSJohan Hedberg mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); 31761143d458SBrian Gix 31771143d458SBrian Gix hci_dev_unlock(hdev); 31781143d458SBrian Gix } 31791143d458SBrian Gix 31800493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 31810493684eSMarcel Holtmann { 31820493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 31830493684eSMarcel Holtmann struct hci_conn *conn; 31840493684eSMarcel Holtmann 31850493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 31860493684eSMarcel Holtmann 31870493684eSMarcel Holtmann hci_dev_lock(hdev); 31880493684eSMarcel Holtmann 31890493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 31902a611692SJohan Hedberg if (!conn) 31912a611692SJohan Hedberg goto unlock; 31922a611692SJohan Hedberg 31932a611692SJohan Hedberg /* To avoid duplicate auth_failed events to user space we check 31942a611692SJohan Hedberg * the HCI_CONN_AUTH_PEND flag which will be set if we 31952a611692SJohan Hedberg * initiated the authentication. A traditional auth_complete 31962a611692SJohan Hedberg * event gets always produced as initiator and is also mapped to 31972a611692SJohan Hedberg * the mgmt_auth_failed event */ 319851a8efd7SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status != 0) 3199bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 3200bab73cb6SJohan Hedberg ev->status); 32012a611692SJohan Hedberg 32020493684eSMarcel Holtmann hci_conn_put(conn); 32030493684eSMarcel Holtmann 32042a611692SJohan Hedberg unlock: 32050493684eSMarcel Holtmann hci_dev_unlock(hdev); 32060493684eSMarcel Holtmann } 32070493684eSMarcel Holtmann 320841a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 320941a96212SMarcel Holtmann { 321041a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 321141a96212SMarcel Holtmann struct inquiry_entry *ie; 321241a96212SMarcel Holtmann 321341a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 321441a96212SMarcel Holtmann 321541a96212SMarcel Holtmann hci_dev_lock(hdev); 321641a96212SMarcel Holtmann 3217cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 3218cc11b9c1SAndrei Emeltchenko if (ie) 321902b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 322041a96212SMarcel Holtmann 322141a96212SMarcel Holtmann hci_dev_unlock(hdev); 322241a96212SMarcel Holtmann } 322341a96212SMarcel Holtmann 32242763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev, 32252763eda6SSzymon Janc struct sk_buff *skb) 32262763eda6SSzymon Janc { 32272763eda6SSzymon Janc struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; 32282763eda6SSzymon Janc struct oob_data *data; 32292763eda6SSzymon Janc 32302763eda6SSzymon Janc BT_DBG("%s", hdev->name); 32312763eda6SSzymon Janc 32322763eda6SSzymon Janc hci_dev_lock(hdev); 32332763eda6SSzymon Janc 3234a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 3235e1ba1f15SSzymon Janc goto unlock; 3236e1ba1f15SSzymon Janc 32372763eda6SSzymon Janc data = hci_find_remote_oob_data(hdev, &ev->bdaddr); 32382763eda6SSzymon Janc if (data) { 32392763eda6SSzymon Janc struct hci_cp_remote_oob_data_reply cp; 32402763eda6SSzymon Janc 32412763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 32422763eda6SSzymon Janc memcpy(cp.hash, data->hash, sizeof(cp.hash)); 32432763eda6SSzymon Janc memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); 32442763eda6SSzymon Janc 32452763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), 32462763eda6SSzymon Janc &cp); 32472763eda6SSzymon Janc } else { 32482763eda6SSzymon Janc struct hci_cp_remote_oob_data_neg_reply cp; 32492763eda6SSzymon Janc 32502763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 32512763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), 32522763eda6SSzymon Janc &cp); 32532763eda6SSzymon Janc } 32542763eda6SSzymon Janc 3255e1ba1f15SSzymon Janc unlock: 32562763eda6SSzymon Janc hci_dev_unlock(hdev); 32572763eda6SSzymon Janc } 32582763eda6SSzymon Janc 3259fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 3260fcd89c09SVille Tervo { 3261fcd89c09SVille Tervo struct hci_ev_le_conn_complete *ev = (void *) skb->data; 3262fcd89c09SVille Tervo struct hci_conn *conn; 3263fcd89c09SVille Tervo 3264fcd89c09SVille Tervo BT_DBG("%s status %d", hdev->name, ev->status); 3265fcd89c09SVille Tervo 3266fcd89c09SVille Tervo hci_dev_lock(hdev); 3267fcd89c09SVille Tervo 3268fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr); 3269b62f328bSVille Tervo if (!conn) { 3270b62f328bSVille Tervo conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); 3271b62f328bSVille Tervo if (!conn) { 3272b62f328bSVille Tervo BT_ERR("No memory for new connection"); 3273b62f328bSVille Tervo hci_dev_unlock(hdev); 3274b62f328bSVille Tervo return; 3275b62f328bSVille Tervo } 327629b7988aSAndre Guedes 327729b7988aSAndre Guedes conn->dst_type = ev->bdaddr_type; 3278b62f328bSVille Tervo } 3279fcd89c09SVille Tervo 3280fcd89c09SVille Tervo if (ev->status) { 328148264f06SJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 328248264f06SJohan Hedberg conn->dst_type, ev->status); 3283fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 3284fcd89c09SVille Tervo conn->state = BT_CLOSED; 3285fcd89c09SVille Tervo hci_conn_del(conn); 3286fcd89c09SVille Tervo goto unlock; 3287fcd89c09SVille Tervo } 3288fcd89c09SVille Tervo 3289b644ba33SJohan Hedberg if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 3290b644ba33SJohan Hedberg mgmt_device_connected(hdev, &ev->bdaddr, conn->type, 329195b23582SSzymon Janc conn->dst_type, 0, NULL, 0, NULL); 329283bc71b4SVinicius Costa Gomes 32937b5c0d52SVinicius Costa Gomes conn->sec_level = BT_SECURITY_LOW; 3294fcd89c09SVille Tervo conn->handle = __le16_to_cpu(ev->handle); 3295fcd89c09SVille Tervo conn->state = BT_CONNECTED; 3296fcd89c09SVille Tervo 3297fcd89c09SVille Tervo hci_conn_hold_device(conn); 3298fcd89c09SVille Tervo hci_conn_add_sysfs(conn); 3299fcd89c09SVille Tervo 3300fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 3301fcd89c09SVille Tervo 3302fcd89c09SVille Tervo unlock: 3303fcd89c09SVille Tervo hci_dev_unlock(hdev); 3304fcd89c09SVille Tervo } 3305fcd89c09SVille Tervo 33069aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev, 33079aa04c91SAndre Guedes struct sk_buff *skb) 33089aa04c91SAndre Guedes { 3309e95beb41SAndre Guedes u8 num_reports = skb->data[0]; 3310e95beb41SAndre Guedes void *ptr = &skb->data[1]; 33113c9e9195SAndre Guedes s8 rssi; 33129aa04c91SAndre Guedes 33139aa04c91SAndre Guedes hci_dev_lock(hdev); 33149aa04c91SAndre Guedes 3315e95beb41SAndre Guedes while (num_reports--) { 3316e95beb41SAndre Guedes struct hci_ev_le_advertising_info *ev = ptr; 3317e95beb41SAndre Guedes 33189aa04c91SAndre Guedes hci_add_adv_entry(hdev, ev); 33199aa04c91SAndre Guedes 33203c9e9195SAndre Guedes rssi = ev->data[ev->length]; 33213c9e9195SAndre Guedes mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type, 332204124681SGustavo F. Padovan NULL, rssi, 0, 1, ev->data, ev->length); 33233c9e9195SAndre Guedes 3324e95beb41SAndre Guedes ptr += sizeof(*ev) + ev->length + 1; 33259aa04c91SAndre Guedes } 33269aa04c91SAndre Guedes 33279aa04c91SAndre Guedes hci_dev_unlock(hdev); 33289aa04c91SAndre Guedes } 33299aa04c91SAndre Guedes 3330a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev, 3331a7a595f6SVinicius Costa Gomes struct sk_buff *skb) 3332a7a595f6SVinicius Costa Gomes { 3333a7a595f6SVinicius Costa Gomes struct hci_ev_le_ltk_req *ev = (void *) skb->data; 3334a7a595f6SVinicius Costa Gomes struct hci_cp_le_ltk_reply cp; 3335bea710feSVinicius Costa Gomes struct hci_cp_le_ltk_neg_reply neg; 3336a7a595f6SVinicius Costa Gomes struct hci_conn *conn; 3337c9839a11SVinicius Costa Gomes struct smp_ltk *ltk; 3338a7a595f6SVinicius Costa Gomes 3339*e4666881SAndrei Emeltchenko BT_DBG("%s handle %d", hdev->name, __le16_to_cpu(ev->handle)); 3340a7a595f6SVinicius Costa Gomes 3341a7a595f6SVinicius Costa Gomes hci_dev_lock(hdev); 3342a7a595f6SVinicius Costa Gomes 3343a7a595f6SVinicius Costa Gomes conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3344bea710feSVinicius Costa Gomes if (conn == NULL) 3345bea710feSVinicius Costa Gomes goto not_found; 3346a7a595f6SVinicius Costa Gomes 3347bea710feSVinicius Costa Gomes ltk = hci_find_ltk(hdev, ev->ediv, ev->random); 3348bea710feSVinicius Costa Gomes if (ltk == NULL) 3349bea710feSVinicius Costa Gomes goto not_found; 3350bea710feSVinicius Costa Gomes 3351bea710feSVinicius Costa Gomes memcpy(cp.ltk, ltk->val, sizeof(ltk->val)); 3352a7a595f6SVinicius Costa Gomes cp.handle = cpu_to_le16(conn->handle); 3353c9839a11SVinicius Costa Gomes 3354c9839a11SVinicius Costa Gomes if (ltk->authenticated) 3355c9839a11SVinicius Costa Gomes conn->sec_level = BT_SECURITY_HIGH; 3356a7a595f6SVinicius Costa Gomes 3357a7a595f6SVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); 3358a7a595f6SVinicius Costa Gomes 3359c9839a11SVinicius Costa Gomes if (ltk->type & HCI_SMP_STK) { 3360c9839a11SVinicius Costa Gomes list_del(<k->list); 3361c9839a11SVinicius Costa Gomes kfree(ltk); 3362c9839a11SVinicius Costa Gomes } 3363c9839a11SVinicius Costa Gomes 3364a7a595f6SVinicius Costa Gomes hci_dev_unlock(hdev); 3365bea710feSVinicius Costa Gomes 3366bea710feSVinicius Costa Gomes return; 3367bea710feSVinicius Costa Gomes 3368bea710feSVinicius Costa Gomes not_found: 3369bea710feSVinicius Costa Gomes neg.handle = ev->handle; 3370bea710feSVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg); 3371bea710feSVinicius Costa Gomes hci_dev_unlock(hdev); 3372a7a595f6SVinicius Costa Gomes } 3373a7a595f6SVinicius Costa Gomes 3374fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 3375fcd89c09SVille Tervo { 3376fcd89c09SVille Tervo struct hci_ev_le_meta *le_ev = (void *) skb->data; 3377fcd89c09SVille Tervo 3378fcd89c09SVille Tervo skb_pull(skb, sizeof(*le_ev)); 3379fcd89c09SVille Tervo 3380fcd89c09SVille Tervo switch (le_ev->subevent) { 3381fcd89c09SVille Tervo case HCI_EV_LE_CONN_COMPLETE: 3382fcd89c09SVille Tervo hci_le_conn_complete_evt(hdev, skb); 3383fcd89c09SVille Tervo break; 3384fcd89c09SVille Tervo 33859aa04c91SAndre Guedes case HCI_EV_LE_ADVERTISING_REPORT: 33869aa04c91SAndre Guedes hci_le_adv_report_evt(hdev, skb); 33879aa04c91SAndre Guedes break; 33889aa04c91SAndre Guedes 3389a7a595f6SVinicius Costa Gomes case HCI_EV_LE_LTK_REQ: 3390a7a595f6SVinicius Costa Gomes hci_le_ltk_request_evt(hdev, skb); 3391a7a595f6SVinicius Costa Gomes break; 3392a7a595f6SVinicius Costa Gomes 3393fcd89c09SVille Tervo default: 3394fcd89c09SVille Tervo break; 3395fcd89c09SVille Tervo } 3396fcd89c09SVille Tervo } 3397fcd89c09SVille Tervo 33981da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 33991da177e4SLinus Torvalds { 3400a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 3401a9de9248SMarcel Holtmann __u8 event = hdr->evt; 34021da177e4SLinus Torvalds 34031da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 34041da177e4SLinus Torvalds 3405a9de9248SMarcel Holtmann switch (event) { 34061da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 34071da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 34081da177e4SLinus Torvalds break; 34091da177e4SLinus Torvalds 34101da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 34111da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 34121da177e4SLinus Torvalds break; 34131da177e4SLinus Torvalds 3414a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 3415a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 341621d9e30eSMarcel Holtmann break; 341721d9e30eSMarcel Holtmann 34181da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 34191da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 34201da177e4SLinus Torvalds break; 34211da177e4SLinus Torvalds 34221da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 34231da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 34241da177e4SLinus Torvalds break; 34251da177e4SLinus Torvalds 34261da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 34271da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 34281da177e4SLinus Torvalds break; 34291da177e4SLinus Torvalds 3430a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 3431a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 3432a9de9248SMarcel Holtmann break; 3433a9de9248SMarcel Holtmann 34341da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 34351da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 34361da177e4SLinus Torvalds break; 34371da177e4SLinus Torvalds 3438a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 3439a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 3440a9de9248SMarcel Holtmann break; 3441a9de9248SMarcel Holtmann 3442a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 3443a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 3444a9de9248SMarcel Holtmann break; 3445a9de9248SMarcel Holtmann 3446a9de9248SMarcel Holtmann case HCI_EV_REMOTE_VERSION: 3447a9de9248SMarcel Holtmann hci_remote_version_evt(hdev, skb); 3448a9de9248SMarcel Holtmann break; 3449a9de9248SMarcel Holtmann 3450a9de9248SMarcel Holtmann case HCI_EV_QOS_SETUP_COMPLETE: 3451a9de9248SMarcel Holtmann hci_qos_setup_complete_evt(hdev, skb); 3452a9de9248SMarcel Holtmann break; 3453a9de9248SMarcel Holtmann 3454a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 3455a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 3456a9de9248SMarcel Holtmann break; 3457a9de9248SMarcel Holtmann 3458a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 3459a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 3460a9de9248SMarcel Holtmann break; 3461a9de9248SMarcel Holtmann 3462a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 3463a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 3464a9de9248SMarcel Holtmann break; 3465a9de9248SMarcel Holtmann 3466a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 3467a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 3468a9de9248SMarcel Holtmann break; 3469a9de9248SMarcel Holtmann 3470a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 3471a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 34721da177e4SLinus Torvalds break; 34731da177e4SLinus Torvalds 34741da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 34751da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 34761da177e4SLinus Torvalds break; 34771da177e4SLinus Torvalds 34781da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 34791da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 34801da177e4SLinus Torvalds break; 34811da177e4SLinus Torvalds 34821da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 34831da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 34841da177e4SLinus Torvalds break; 34851da177e4SLinus Torvalds 34861da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 34871da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 34881da177e4SLinus Torvalds break; 34891da177e4SLinus Torvalds 3490a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 3491a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 3492a8746417SMarcel Holtmann break; 3493a8746417SMarcel Holtmann 349485a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 349585a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 349685a1e930SMarcel Holtmann break; 349785a1e930SMarcel Holtmann 3498a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 3499a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 3500a9de9248SMarcel Holtmann break; 3501a9de9248SMarcel Holtmann 3502a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 3503a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 3504a9de9248SMarcel Holtmann break; 3505a9de9248SMarcel Holtmann 3506a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 3507a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 3508a9de9248SMarcel Holtmann break; 3509a9de9248SMarcel Holtmann 3510a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_CHANGED: 3511a9de9248SMarcel Holtmann hci_sync_conn_changed_evt(hdev, skb); 3512a9de9248SMarcel Holtmann break; 3513a9de9248SMarcel Holtmann 351404837f64SMarcel Holtmann case HCI_EV_SNIFF_SUBRATE: 351504837f64SMarcel Holtmann hci_sniff_subrate_evt(hdev, skb); 351604837f64SMarcel Holtmann break; 351704837f64SMarcel Holtmann 3518a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 3519a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 35201da177e4SLinus Torvalds break; 35211da177e4SLinus Torvalds 35220493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 35230493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 35240493684eSMarcel Holtmann break; 35250493684eSMarcel Holtmann 352603b555e1SJohan Hedberg case HCI_EV_IO_CAPA_REPLY: 352703b555e1SJohan Hedberg hci_io_capa_reply_evt(hdev, skb); 352803b555e1SJohan Hedberg break; 352903b555e1SJohan Hedberg 3530a5c29683SJohan Hedberg case HCI_EV_USER_CONFIRM_REQUEST: 3531a5c29683SJohan Hedberg hci_user_confirm_request_evt(hdev, skb); 3532a5c29683SJohan Hedberg break; 3533a5c29683SJohan Hedberg 35341143d458SBrian Gix case HCI_EV_USER_PASSKEY_REQUEST: 35351143d458SBrian Gix hci_user_passkey_request_evt(hdev, skb); 35361143d458SBrian Gix break; 35371143d458SBrian Gix 35380493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 35390493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 35400493684eSMarcel Holtmann break; 35410493684eSMarcel Holtmann 354241a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 354341a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 354441a96212SMarcel Holtmann break; 354541a96212SMarcel Holtmann 3546fcd89c09SVille Tervo case HCI_EV_LE_META: 3547fcd89c09SVille Tervo hci_le_meta_evt(hdev, skb); 3548fcd89c09SVille Tervo break; 3549fcd89c09SVille Tervo 35502763eda6SSzymon Janc case HCI_EV_REMOTE_OOB_DATA_REQUEST: 35512763eda6SSzymon Janc hci_remote_oob_data_request_evt(hdev, skb); 35522763eda6SSzymon Janc break; 35532763eda6SSzymon Janc 355425e89e99SAndrei Emeltchenko case HCI_EV_NUM_COMP_BLOCKS: 355525e89e99SAndrei Emeltchenko hci_num_comp_blocks_evt(hdev, skb); 355625e89e99SAndrei Emeltchenko break; 355725e89e99SAndrei Emeltchenko 35581da177e4SLinus Torvalds default: 3559a9de9248SMarcel Holtmann BT_DBG("%s event 0x%x", hdev->name, event); 35601da177e4SLinus Torvalds break; 35611da177e4SLinus Torvalds } 35621da177e4SLinus Torvalds 35631da177e4SLinus Torvalds kfree_skb(skb); 35641da177e4SLinus Torvalds hdev->stat.evt_rx++; 35651da177e4SLinus Torvalds } 3566