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 724d93483bSAndre Guedes static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 734d93483bSAndre Guedes { 744d93483bSAndre Guedes __u8 status = *((__u8 *) skb->data); 754d93483bSAndre Guedes 764d93483bSAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 77ae854a70SAndre Guedes 78ae854a70SAndre Guedes if (status) 79ae854a70SAndre Guedes return; 80ae854a70SAndre Guedes 81ae854a70SAndre Guedes set_bit(HCI_PERIODIC_INQ, &hdev->dev_flags); 824d93483bSAndre Guedes } 834d93483bSAndre Guedes 84a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 851da177e4SLinus Torvalds { 86a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 87a9de9248SMarcel Holtmann 88a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 89a9de9248SMarcel Holtmann 90a9de9248SMarcel Holtmann if (status) 91a9de9248SMarcel Holtmann return; 92a9de9248SMarcel Holtmann 93ae854a70SAndre Guedes clear_bit(HCI_PERIODIC_INQ, &hdev->dev_flags); 94ae854a70SAndre Guedes 95a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 96a9de9248SMarcel Holtmann } 97a9de9248SMarcel Holtmann 98a9de9248SMarcel Holtmann static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb) 99a9de9248SMarcel Holtmann { 100a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 101a9de9248SMarcel Holtmann } 102a9de9248SMarcel Holtmann 103a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb) 104a9de9248SMarcel Holtmann { 105a9de9248SMarcel Holtmann struct hci_rp_role_discovery *rp = (void *) skb->data; 1061da177e4SLinus Torvalds struct hci_conn *conn; 1071da177e4SLinus Torvalds 108a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 1091da177e4SLinus Torvalds 110a9de9248SMarcel Holtmann if (rp->status) 111a9de9248SMarcel Holtmann return; 1121da177e4SLinus Torvalds 1131da177e4SLinus Torvalds hci_dev_lock(hdev); 1141da177e4SLinus Torvalds 115a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 1161da177e4SLinus Torvalds if (conn) { 117a9de9248SMarcel Holtmann if (rp->role) 1181da177e4SLinus Torvalds conn->link_mode &= ~HCI_LM_MASTER; 1191da177e4SLinus Torvalds else 1201da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 1211da177e4SLinus Torvalds } 1221da177e4SLinus Torvalds 1231da177e4SLinus Torvalds hci_dev_unlock(hdev); 124a9de9248SMarcel Holtmann } 1251da177e4SLinus Torvalds 126e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 127e4e8e37cSMarcel Holtmann { 128e4e8e37cSMarcel Holtmann struct hci_rp_read_link_policy *rp = (void *) skb->data; 129e4e8e37cSMarcel Holtmann struct hci_conn *conn; 130e4e8e37cSMarcel Holtmann 131e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 132e4e8e37cSMarcel Holtmann 133e4e8e37cSMarcel Holtmann if (rp->status) 134e4e8e37cSMarcel Holtmann return; 135e4e8e37cSMarcel Holtmann 136e4e8e37cSMarcel Holtmann hci_dev_lock(hdev); 137e4e8e37cSMarcel Holtmann 138e4e8e37cSMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 139e4e8e37cSMarcel Holtmann if (conn) 140e4e8e37cSMarcel Holtmann conn->link_policy = __le16_to_cpu(rp->policy); 141e4e8e37cSMarcel Holtmann 142e4e8e37cSMarcel Holtmann hci_dev_unlock(hdev); 143e4e8e37cSMarcel Holtmann } 144e4e8e37cSMarcel Holtmann 145a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 146a9de9248SMarcel Holtmann { 147a9de9248SMarcel Holtmann struct hci_rp_write_link_policy *rp = (void *) skb->data; 148a9de9248SMarcel Holtmann struct hci_conn *conn; 149a9de9248SMarcel Holtmann void *sent; 150a9de9248SMarcel Holtmann 151a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 152a9de9248SMarcel Holtmann 153a9de9248SMarcel Holtmann if (rp->status) 154a9de9248SMarcel Holtmann return; 155a9de9248SMarcel Holtmann 156a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY); 15704837f64SMarcel Holtmann if (!sent) 158a9de9248SMarcel Holtmann return; 15904837f64SMarcel Holtmann 16004837f64SMarcel Holtmann hci_dev_lock(hdev); 16104837f64SMarcel Holtmann 162a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 163e4e8e37cSMarcel Holtmann if (conn) 16483985319SHarvey Harrison conn->link_policy = get_unaligned_le16(sent + 2); 16504837f64SMarcel Holtmann 16604837f64SMarcel Holtmann hci_dev_unlock(hdev); 1671da177e4SLinus Torvalds } 1681da177e4SLinus Torvalds 169e4e8e37cSMarcel Holtmann static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 170e4e8e37cSMarcel Holtmann { 171e4e8e37cSMarcel Holtmann struct hci_rp_read_def_link_policy *rp = (void *) skb->data; 172e4e8e37cSMarcel Holtmann 173e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 174e4e8e37cSMarcel Holtmann 175e4e8e37cSMarcel Holtmann if (rp->status) 176e4e8e37cSMarcel Holtmann return; 177e4e8e37cSMarcel Holtmann 178e4e8e37cSMarcel Holtmann hdev->link_policy = __le16_to_cpu(rp->policy); 179e4e8e37cSMarcel Holtmann } 180e4e8e37cSMarcel Holtmann 181e4e8e37cSMarcel Holtmann static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 182e4e8e37cSMarcel Holtmann { 183e4e8e37cSMarcel Holtmann __u8 status = *((__u8 *) skb->data); 184e4e8e37cSMarcel Holtmann void *sent; 185e4e8e37cSMarcel Holtmann 186e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 187e4e8e37cSMarcel Holtmann 188e4e8e37cSMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY); 189e4e8e37cSMarcel Holtmann if (!sent) 190e4e8e37cSMarcel Holtmann return; 191e4e8e37cSMarcel Holtmann 192e4e8e37cSMarcel Holtmann if (!status) 193e4e8e37cSMarcel Holtmann hdev->link_policy = get_unaligned_le16(sent); 194e4e8e37cSMarcel Holtmann 19523bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status); 196e4e8e37cSMarcel Holtmann } 197e4e8e37cSMarcel Holtmann 198a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) 1991da177e4SLinus Torvalds { 200a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 201a9de9248SMarcel Holtmann 202a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 203a9de9248SMarcel Holtmann 20410572132SGustavo F. Padovan clear_bit(HCI_RESET, &hdev->flags); 20510572132SGustavo F. Padovan 20623bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_RESET, status); 207d23264a8SAndre Guedes 208a297e97cSJohan Hedberg /* Reset all non-persistent flags */ 209ae854a70SAndre Guedes hdev->dev_flags &= ~(BIT(HCI_LE_SCAN) | BIT(HCI_PENDING_CLASS) | 210ae854a70SAndre Guedes BIT(HCI_PERIODIC_INQ)); 21169775ff6SAndre Guedes 21269775ff6SAndre Guedes hdev->discovery.state = DISCOVERY_STOPPED; 213a9de9248SMarcel Holtmann } 214a9de9248SMarcel Holtmann 215a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) 216a9de9248SMarcel Holtmann { 217a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 2181da177e4SLinus Torvalds void *sent; 2191da177e4SLinus Torvalds 220a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 2211da177e4SLinus Torvalds 222a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); 2231da177e4SLinus Torvalds if (!sent) 224a9de9248SMarcel Holtmann return; 2251da177e4SLinus Torvalds 22656e5cb86SJohan Hedberg hci_dev_lock(hdev); 22756e5cb86SJohan Hedberg 228f51d5b24SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 229f51d5b24SJohan Hedberg mgmt_set_local_name_complete(hdev, sent, status); 23028cc7bdeSJohan Hedberg else if (!status) 23128cc7bdeSJohan Hedberg memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); 232f51d5b24SJohan Hedberg 23356e5cb86SJohan Hedberg hci_dev_unlock(hdev); 2343159d384SJohan Hedberg 2353159d384SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status); 236a9de9248SMarcel Holtmann } 237a9de9248SMarcel Holtmann 238a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) 239a9de9248SMarcel Holtmann { 240a9de9248SMarcel Holtmann struct hci_rp_read_local_name *rp = (void *) skb->data; 241a9de9248SMarcel Holtmann 242a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 243a9de9248SMarcel Holtmann 244a9de9248SMarcel Holtmann if (rp->status) 245a9de9248SMarcel Holtmann return; 246a9de9248SMarcel Holtmann 247db99b5fcSJohan Hedberg if (test_bit(HCI_SETUP, &hdev->dev_flags)) 2481f6c6378SJohan Hedberg memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); 249a9de9248SMarcel Holtmann } 250a9de9248SMarcel Holtmann 251a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) 252a9de9248SMarcel Holtmann { 253a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 254a9de9248SMarcel Holtmann void *sent; 255a9de9248SMarcel Holtmann 256a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 257a9de9248SMarcel Holtmann 258a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); 259a9de9248SMarcel Holtmann if (!sent) 260a9de9248SMarcel Holtmann return; 2611da177e4SLinus Torvalds 2621da177e4SLinus Torvalds if (!status) { 263a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 264a9de9248SMarcel Holtmann 2651da177e4SLinus Torvalds if (param == AUTH_ENABLED) 2661da177e4SLinus Torvalds set_bit(HCI_AUTH, &hdev->flags); 2671da177e4SLinus Torvalds else 2681da177e4SLinus Torvalds clear_bit(HCI_AUTH, &hdev->flags); 2691da177e4SLinus Torvalds } 270a9de9248SMarcel Holtmann 27133ef95edSJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 27233ef95edSJohan Hedberg mgmt_auth_enable_complete(hdev, status); 27333ef95edSJohan Hedberg 27423bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status); 275a9de9248SMarcel Holtmann } 2761da177e4SLinus Torvalds 277a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) 278a9de9248SMarcel Holtmann { 279a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 280a9de9248SMarcel Holtmann void *sent; 281a9de9248SMarcel Holtmann 282a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 283a9de9248SMarcel Holtmann 284a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); 2851da177e4SLinus Torvalds if (!sent) 286a9de9248SMarcel Holtmann return; 2871da177e4SLinus Torvalds 2881da177e4SLinus Torvalds if (!status) { 289a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 290a9de9248SMarcel Holtmann 2911da177e4SLinus Torvalds if (param) 2921da177e4SLinus Torvalds set_bit(HCI_ENCRYPT, &hdev->flags); 2931da177e4SLinus Torvalds else 2941da177e4SLinus Torvalds clear_bit(HCI_ENCRYPT, &hdev->flags); 2951da177e4SLinus Torvalds } 296a9de9248SMarcel Holtmann 29723bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status); 2981da177e4SLinus Torvalds } 2991da177e4SLinus Torvalds 300a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) 301a9de9248SMarcel Holtmann { 30236f7fc7eSJohan Hedberg __u8 param, status = *((__u8 *) skb->data); 30336f7fc7eSJohan Hedberg int old_pscan, old_iscan; 304a9de9248SMarcel Holtmann void *sent; 3051da177e4SLinus Torvalds 306a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 307a9de9248SMarcel Holtmann 308a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); 3091da177e4SLinus Torvalds if (!sent) 310a9de9248SMarcel Holtmann return; 3111da177e4SLinus Torvalds 31236f7fc7eSJohan Hedberg param = *((__u8 *) sent); 313a9de9248SMarcel Holtmann 31456e5cb86SJohan Hedberg hci_dev_lock(hdev); 31556e5cb86SJohan Hedberg 3162d7cee58SJohan Hedberg if (status != 0) { 317744cf19eSJohan Hedberg mgmt_write_scan_failed(hdev, param, status); 3182d7cee58SJohan Hedberg hdev->discov_timeout = 0; 3192d7cee58SJohan Hedberg goto done; 3202d7cee58SJohan Hedberg } 3212d7cee58SJohan Hedberg 3229fbcbb45SJohan Hedberg old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags); 3239fbcbb45SJohan Hedberg old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags); 324a9de9248SMarcel Holtmann 32573f22f62SJohan Hedberg if (param & SCAN_INQUIRY) { 3261da177e4SLinus Torvalds set_bit(HCI_ISCAN, &hdev->flags); 3279fbcbb45SJohan Hedberg if (!old_iscan) 328744cf19eSJohan Hedberg mgmt_discoverable(hdev, 1); 32916ab91abSJohan Hedberg if (hdev->discov_timeout > 0) { 33016ab91abSJohan Hedberg int to = msecs_to_jiffies(hdev->discov_timeout * 1000); 33116ab91abSJohan Hedberg queue_delayed_work(hdev->workqueue, &hdev->discov_off, 33216ab91abSJohan Hedberg to); 33316ab91abSJohan Hedberg } 3349fbcbb45SJohan Hedberg } else if (old_iscan) 335744cf19eSJohan Hedberg mgmt_discoverable(hdev, 0); 3361da177e4SLinus Torvalds 3379fbcbb45SJohan Hedberg if (param & SCAN_PAGE) { 3381da177e4SLinus Torvalds set_bit(HCI_PSCAN, &hdev->flags); 3399fbcbb45SJohan Hedberg if (!old_pscan) 340744cf19eSJohan Hedberg mgmt_connectable(hdev, 1); 3419fbcbb45SJohan Hedberg } else if (old_pscan) 342744cf19eSJohan Hedberg mgmt_connectable(hdev, 0); 343a9de9248SMarcel Holtmann 34436f7fc7eSJohan Hedberg done: 34556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 34623bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status); 3471da177e4SLinus Torvalds } 3481da177e4SLinus Torvalds 349a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 350a9de9248SMarcel Holtmann { 351a9de9248SMarcel Holtmann struct hci_rp_read_class_of_dev *rp = (void *) skb->data; 352a9de9248SMarcel Holtmann 353a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 354a9de9248SMarcel Holtmann 355a9de9248SMarcel Holtmann if (rp->status) 356a9de9248SMarcel Holtmann return; 357a9de9248SMarcel Holtmann 358a9de9248SMarcel Holtmann memcpy(hdev->dev_class, rp->dev_class, 3); 359a9de9248SMarcel Holtmann 360a9de9248SMarcel Holtmann BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, 361a9de9248SMarcel Holtmann hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); 362a9de9248SMarcel Holtmann } 363a9de9248SMarcel Holtmann 364a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 365a9de9248SMarcel Holtmann { 366a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 367a9de9248SMarcel Holtmann void *sent; 368a9de9248SMarcel Holtmann 369a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 370a9de9248SMarcel Holtmann 371a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); 372a9de9248SMarcel Holtmann if (!sent) 373a9de9248SMarcel Holtmann return; 374a9de9248SMarcel Holtmann 3757f9a903cSMarcel Holtmann hci_dev_lock(hdev); 3767f9a903cSMarcel Holtmann 3777f9a903cSMarcel Holtmann if (status == 0) 378a9de9248SMarcel Holtmann memcpy(hdev->dev_class, sent, 3); 3797f9a903cSMarcel Holtmann 3807f9a903cSMarcel Holtmann if (test_bit(HCI_MGMT, &hdev->dev_flags)) 3817f9a903cSMarcel Holtmann mgmt_set_class_of_dev_complete(hdev, sent, status); 3827f9a903cSMarcel Holtmann 3837f9a903cSMarcel Holtmann hci_dev_unlock(hdev); 384a9de9248SMarcel Holtmann } 385a9de9248SMarcel Holtmann 386a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 387a9de9248SMarcel Holtmann { 388a9de9248SMarcel Holtmann struct hci_rp_read_voice_setting *rp = (void *) skb->data; 389a9de9248SMarcel Holtmann __u16 setting; 390a9de9248SMarcel Holtmann 391a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 392a9de9248SMarcel Holtmann 393a9de9248SMarcel Holtmann if (rp->status) 394a9de9248SMarcel Holtmann return; 395a9de9248SMarcel Holtmann 396a9de9248SMarcel Holtmann setting = __le16_to_cpu(rp->voice_setting); 397a9de9248SMarcel Holtmann 398a9de9248SMarcel Holtmann if (hdev->voice_setting == setting) 399a9de9248SMarcel Holtmann return; 400a9de9248SMarcel Holtmann 401a9de9248SMarcel Holtmann hdev->voice_setting = setting; 402a9de9248SMarcel Holtmann 403a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 404a9de9248SMarcel Holtmann 4053c54711cSGustavo F. Padovan if (hdev->notify) 406a9de9248SMarcel Holtmann hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 407a9de9248SMarcel Holtmann } 408a9de9248SMarcel Holtmann 409a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 410a9de9248SMarcel Holtmann { 411a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 412f383f275SMarcel Holtmann __u16 setting; 413a9de9248SMarcel Holtmann void *sent; 414a9de9248SMarcel Holtmann 415a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 416a9de9248SMarcel Holtmann 417f383f275SMarcel Holtmann if (status) 418f383f275SMarcel Holtmann return; 419f383f275SMarcel Holtmann 420a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); 421a9de9248SMarcel Holtmann if (!sent) 422a9de9248SMarcel Holtmann return; 423a9de9248SMarcel Holtmann 424f383f275SMarcel Holtmann setting = get_unaligned_le16(sent); 4251da177e4SLinus Torvalds 426f383f275SMarcel Holtmann if (hdev->voice_setting == setting) 427f383f275SMarcel Holtmann return; 428f383f275SMarcel Holtmann 4291da177e4SLinus Torvalds hdev->voice_setting = setting; 4301da177e4SLinus Torvalds 431a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 4321da177e4SLinus Torvalds 4333c54711cSGustavo F. Padovan if (hdev->notify) 4341da177e4SLinus Torvalds hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 4351da177e4SLinus Torvalds } 4361da177e4SLinus Torvalds 437a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 4381da177e4SLinus Torvalds { 439a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 4401da177e4SLinus Torvalds 441a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 4421da177e4SLinus Torvalds 44323bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status); 4441143e5a6SMarcel Holtmann } 4451143e5a6SMarcel Holtmann 446333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 447333140b5SMarcel Holtmann { 448333140b5SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 449333140b5SMarcel Holtmann void *sent; 450333140b5SMarcel Holtmann 451333140b5SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 452333140b5SMarcel Holtmann 453333140b5SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); 454333140b5SMarcel Holtmann if (!sent) 455333140b5SMarcel Holtmann return; 456333140b5SMarcel Holtmann 457c0ecddc2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 458c0ecddc2SJohan Hedberg mgmt_ssp_enable_complete(hdev, *((u8 *) sent), status); 459c0ecddc2SJohan Hedberg else if (!status) { 46084bde9d6SJohan Hedberg if (*((u8 *) sent)) 46184bde9d6SJohan Hedberg set_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 46284bde9d6SJohan Hedberg else 46384bde9d6SJohan Hedberg clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 464c0ecddc2SJohan Hedberg } 465333140b5SMarcel Holtmann } 466333140b5SMarcel Holtmann 467d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev) 468d5859e22SJohan Hedberg { 469d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 470d5859e22SJohan Hedberg return 2; 471d5859e22SJohan Hedberg 472d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 473d5859e22SJohan Hedberg return 1; 474d5859e22SJohan Hedberg 475d5859e22SJohan Hedberg if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 && 476d5859e22SJohan Hedberg hdev->lmp_subver == 0x0757) 477d5859e22SJohan Hedberg return 1; 478d5859e22SJohan Hedberg 479d5859e22SJohan Hedberg if (hdev->manufacturer == 15) { 480d5859e22SJohan Hedberg if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963) 481d5859e22SJohan Hedberg return 1; 482d5859e22SJohan Hedberg if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963) 483d5859e22SJohan Hedberg return 1; 484d5859e22SJohan Hedberg if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965) 485d5859e22SJohan Hedberg return 1; 486d5859e22SJohan Hedberg } 487d5859e22SJohan Hedberg 488d5859e22SJohan Hedberg if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 && 489d5859e22SJohan Hedberg hdev->lmp_subver == 0x1805) 490d5859e22SJohan Hedberg return 1; 491d5859e22SJohan Hedberg 492d5859e22SJohan Hedberg return 0; 493d5859e22SJohan Hedberg } 494d5859e22SJohan Hedberg 495d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev) 496d5859e22SJohan Hedberg { 497d5859e22SJohan Hedberg u8 mode; 498d5859e22SJohan Hedberg 499d5859e22SJohan Hedberg mode = hci_get_inquiry_mode(hdev); 500d5859e22SJohan Hedberg 501d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode); 502d5859e22SJohan Hedberg } 503d5859e22SJohan Hedberg 504d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev) 505d5859e22SJohan Hedberg { 506d5859e22SJohan Hedberg /* The second byte is 0xff instead of 0x9f (two reserved bits 507d5859e22SJohan Hedberg * disabled) since a Broadcom 1.2 dongle doesn't respond to the 508d5859e22SJohan Hedberg * command otherwise */ 509d5859e22SJohan Hedberg u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 }; 510d5859e22SJohan Hedberg 5116de6c18dSVille Tervo /* CSR 1.1 dongles does not accept any bitfield so don't try to set 5126de6c18dSVille Tervo * any event mask for pre 1.2 devices */ 5135a13b095SAndrei Emeltchenko if (hdev->hci_ver < BLUETOOTH_VER_1_2) 5146de6c18dSVille Tervo return; 5156de6c18dSVille Tervo 516d5859e22SJohan Hedberg events[4] |= 0x01; /* Flow Specification Complete */ 517d5859e22SJohan Hedberg events[4] |= 0x02; /* Inquiry Result with RSSI */ 518d5859e22SJohan Hedberg events[4] |= 0x04; /* Read Remote Extended Features Complete */ 519d5859e22SJohan Hedberg events[5] |= 0x08; /* Synchronous Connection Complete */ 520d5859e22SJohan Hedberg events[5] |= 0x10; /* Synchronous Connection Changed */ 521d5859e22SJohan Hedberg 522d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 523d5859e22SJohan Hedberg events[4] |= 0x04; /* Inquiry Result with RSSI */ 524d5859e22SJohan Hedberg 525d5859e22SJohan Hedberg if (hdev->features[5] & LMP_SNIFF_SUBR) 526d5859e22SJohan Hedberg events[5] |= 0x20; /* Sniff Subrating */ 527d5859e22SJohan Hedberg 528d5859e22SJohan Hedberg if (hdev->features[5] & LMP_PAUSE_ENC) 529d5859e22SJohan Hedberg events[5] |= 0x80; /* Encryption Key Refresh Complete */ 530d5859e22SJohan Hedberg 531d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 532d5859e22SJohan Hedberg events[5] |= 0x40; /* Extended Inquiry Result */ 533d5859e22SJohan Hedberg 534d5859e22SJohan Hedberg if (hdev->features[6] & LMP_NO_FLUSH) 535d5859e22SJohan Hedberg events[7] |= 0x01; /* Enhanced Flush Complete */ 536d5859e22SJohan Hedberg 537d5859e22SJohan Hedberg if (hdev->features[7] & LMP_LSTO) 538d5859e22SJohan Hedberg events[6] |= 0x80; /* Link Supervision Timeout Changed */ 539d5859e22SJohan Hedberg 540d5859e22SJohan Hedberg if (hdev->features[6] & LMP_SIMPLE_PAIR) { 541d5859e22SJohan Hedberg events[6] |= 0x01; /* IO Capability Request */ 542d5859e22SJohan Hedberg events[6] |= 0x02; /* IO Capability Response */ 543d5859e22SJohan Hedberg events[6] |= 0x04; /* User Confirmation Request */ 544d5859e22SJohan Hedberg events[6] |= 0x08; /* User Passkey Request */ 545d5859e22SJohan Hedberg events[6] |= 0x10; /* Remote OOB Data Request */ 546d5859e22SJohan Hedberg events[6] |= 0x20; /* Simple Pairing Complete */ 547d5859e22SJohan Hedberg events[7] |= 0x04; /* User Passkey Notification */ 548d5859e22SJohan Hedberg events[7] |= 0x08; /* Keypress Notification */ 549d5859e22SJohan Hedberg events[7] |= 0x10; /* Remote Host Supported 550d5859e22SJohan Hedberg * Features Notification */ 551d5859e22SJohan Hedberg } 552d5859e22SJohan Hedberg 553d5859e22SJohan Hedberg if (hdev->features[4] & LMP_LE) 554d5859e22SJohan Hedberg events[7] |= 0x20; /* LE Meta-Event */ 555d5859e22SJohan Hedberg 556d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); 557d5859e22SJohan Hedberg } 558d5859e22SJohan Hedberg 559d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev) 560d5859e22SJohan Hedberg { 561e61ef499SAndrei Emeltchenko if (hdev->dev_type != HCI_BREDR) 562e61ef499SAndrei Emeltchenko return; 563e61ef499SAndrei Emeltchenko 564d5859e22SJohan Hedberg hci_setup_event_mask(hdev); 565d5859e22SJohan Hedberg 566d095c1ebSAndrei Emeltchenko if (hdev->hci_ver > BLUETOOTH_VER_1_1) 567d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); 568d5859e22SJohan Hedberg 56954d04dbbSJohan Hedberg if (hdev->features[6] & LMP_SIMPLE_PAIR) { 57054d04dbbSJohan Hedberg if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { 571d5859e22SJohan Hedberg u8 mode = 0x01; 57254d04dbbSJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 57354d04dbbSJohan Hedberg sizeof(mode), &mode); 57454d04dbbSJohan Hedberg } else { 57554d04dbbSJohan Hedberg struct hci_cp_write_eir cp; 57654d04dbbSJohan Hedberg 57754d04dbbSJohan Hedberg memset(hdev->eir, 0, sizeof(hdev->eir)); 57854d04dbbSJohan Hedberg memset(&cp, 0, sizeof(cp)); 57954d04dbbSJohan Hedberg 58054d04dbbSJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp); 58154d04dbbSJohan Hedberg } 582d5859e22SJohan Hedberg } 583d5859e22SJohan Hedberg 584d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 585d5859e22SJohan Hedberg hci_setup_inquiry_mode(hdev); 586d5859e22SJohan Hedberg 587d5859e22SJohan Hedberg if (hdev->features[7] & LMP_INQ_TX_PWR) 588d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL); 589971e3a4bSAndre Guedes 590971e3a4bSAndre Guedes if (hdev->features[7] & LMP_EXTFEATURES) { 591971e3a4bSAndre Guedes struct hci_cp_read_local_ext_features cp; 592971e3a4bSAndre Guedes 593971e3a4bSAndre Guedes cp.page = 0x01; 59404124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), 59504124681SGustavo F. Padovan &cp); 596971e3a4bSAndre Guedes } 597e6100a25SAndre Guedes 59847990ea0SJohan Hedberg if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) { 59947990ea0SJohan Hedberg u8 enable = 1; 60004124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable), 60104124681SGustavo F. Padovan &enable); 60247990ea0SJohan Hedberg } 603d5859e22SJohan Hedberg } 604d5859e22SJohan Hedberg 605a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) 606a9de9248SMarcel Holtmann { 607a9de9248SMarcel Holtmann struct hci_rp_read_local_version *rp = (void *) skb->data; 6081143e5a6SMarcel Holtmann 609a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 6101143e5a6SMarcel Holtmann 611a9de9248SMarcel Holtmann if (rp->status) 61228b8df77SAndrei Emeltchenko goto done; 6131143e5a6SMarcel Holtmann 614a9de9248SMarcel Holtmann hdev->hci_ver = rp->hci_ver; 615e4e8e37cSMarcel Holtmann hdev->hci_rev = __le16_to_cpu(rp->hci_rev); 616d5859e22SJohan Hedberg hdev->lmp_ver = rp->lmp_ver; 617e4e8e37cSMarcel Holtmann hdev->manufacturer = __le16_to_cpu(rp->manufacturer); 618d5859e22SJohan Hedberg hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); 6191da177e4SLinus Torvalds 620a9de9248SMarcel Holtmann BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name, 621a9de9248SMarcel Holtmann hdev->manufacturer, 622a9de9248SMarcel Holtmann hdev->hci_ver, hdev->hci_rev); 623d5859e22SJohan Hedberg 624d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags)) 625d5859e22SJohan Hedberg hci_setup(hdev); 62628b8df77SAndrei Emeltchenko 62728b8df77SAndrei Emeltchenko done: 62828b8df77SAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status); 629d5859e22SJohan Hedberg } 630d5859e22SJohan Hedberg 631d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev) 632d5859e22SJohan Hedberg { 633035100c8SAndrei Emeltchenko struct hci_cp_write_def_link_policy cp; 634d5859e22SJohan Hedberg u16 link_policy = 0; 635d5859e22SJohan Hedberg 636d5859e22SJohan Hedberg if (hdev->features[0] & LMP_RSWITCH) 637d5859e22SJohan Hedberg link_policy |= HCI_LP_RSWITCH; 638d5859e22SJohan Hedberg if (hdev->features[0] & LMP_HOLD) 639d5859e22SJohan Hedberg link_policy |= HCI_LP_HOLD; 640d5859e22SJohan Hedberg if (hdev->features[0] & LMP_SNIFF) 641d5859e22SJohan Hedberg link_policy |= HCI_LP_SNIFF; 642d5859e22SJohan Hedberg if (hdev->features[1] & LMP_PARK) 643d5859e22SJohan Hedberg link_policy |= HCI_LP_PARK; 644d5859e22SJohan Hedberg 645035100c8SAndrei Emeltchenko cp.policy = cpu_to_le16(link_policy); 646035100c8SAndrei Emeltchenko hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp); 6471da177e4SLinus Torvalds } 6481da177e4SLinus Torvalds 649a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb) 650a9de9248SMarcel Holtmann { 651a9de9248SMarcel Holtmann struct hci_rp_read_local_commands *rp = (void *) skb->data; 652a9de9248SMarcel Holtmann 653a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 654a9de9248SMarcel Holtmann 655a9de9248SMarcel Holtmann if (rp->status) 656d5859e22SJohan Hedberg goto done; 657a9de9248SMarcel Holtmann 658a9de9248SMarcel Holtmann memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); 659d5859e22SJohan Hedberg 660d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10)) 661d5859e22SJohan Hedberg hci_setup_link_policy(hdev); 662d5859e22SJohan Hedberg 663d5859e22SJohan Hedberg done: 664d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status); 665a9de9248SMarcel Holtmann } 666a9de9248SMarcel Holtmann 667a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb) 668a9de9248SMarcel Holtmann { 669a9de9248SMarcel Holtmann struct hci_rp_read_local_features *rp = (void *) skb->data; 670a9de9248SMarcel Holtmann 671a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 672a9de9248SMarcel Holtmann 673a9de9248SMarcel Holtmann if (rp->status) 674a9de9248SMarcel Holtmann return; 675a9de9248SMarcel Holtmann 676a9de9248SMarcel Holtmann memcpy(hdev->features, rp->features, 8); 6771da177e4SLinus Torvalds 6781da177e4SLinus Torvalds /* Adjust default settings according to features 6791da177e4SLinus Torvalds * supported by device. */ 680a9de9248SMarcel Holtmann 6811da177e4SLinus Torvalds if (hdev->features[0] & LMP_3SLOT) 6821da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM3 | HCI_DH3); 6831da177e4SLinus Torvalds 6841da177e4SLinus Torvalds if (hdev->features[0] & LMP_5SLOT) 6851da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM5 | HCI_DH5); 6861da177e4SLinus Torvalds 6875b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV2) { 6881da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV2); 6895b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV2); 6905b7f9909SMarcel Holtmann } 6911da177e4SLinus Torvalds 6925b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV3) { 6931da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV3); 6945b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV3); 6955b7f9909SMarcel Holtmann } 6965b7f9909SMarcel Holtmann 6975b7f9909SMarcel Holtmann if (hdev->features[3] & LMP_ESCO) 6985b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV3); 6995b7f9909SMarcel Holtmann 7005b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV4) 7015b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV4); 7025b7f9909SMarcel Holtmann 7035b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV5) 7045b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV5); 7051da177e4SLinus Torvalds 706efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_2M) 707efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV3); 708efc7688bSMarcel Holtmann 709efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_3M) 710efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_3EV3); 711efc7688bSMarcel Holtmann 712efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_3S_ESCO) 713efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); 714efc7688bSMarcel Holtmann 715a9de9248SMarcel Holtmann BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, 716a9de9248SMarcel Holtmann hdev->features[0], hdev->features[1], 717a9de9248SMarcel Holtmann hdev->features[2], hdev->features[3], 718a9de9248SMarcel Holtmann hdev->features[4], hdev->features[5], 719a9de9248SMarcel Holtmann hdev->features[6], hdev->features[7]); 7201da177e4SLinus Torvalds } 7211da177e4SLinus Torvalds 7228f984dfaSJohan Hedberg static void hci_set_le_support(struct hci_dev *hdev) 7238f984dfaSJohan Hedberg { 7248f984dfaSJohan Hedberg struct hci_cp_write_le_host_supported cp; 7258f984dfaSJohan Hedberg 7268f984dfaSJohan Hedberg memset(&cp, 0, sizeof(cp)); 7278f984dfaSJohan Hedberg 7288f984dfaSJohan Hedberg if (enable_le && test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { 7298f984dfaSJohan Hedberg cp.le = 1; 7308f984dfaSJohan Hedberg cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR); 7318f984dfaSJohan Hedberg } 7328f984dfaSJohan Hedberg 7338f984dfaSJohan Hedberg if (cp.le != !!(hdev->host_features[0] & LMP_HOST_LE)) 73404124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), 73504124681SGustavo F. Padovan &cp); 7368f984dfaSJohan Hedberg } 7378f984dfaSJohan Hedberg 738971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev, 739971e3a4bSAndre Guedes struct sk_buff *skb) 740971e3a4bSAndre Guedes { 741971e3a4bSAndre Guedes struct hci_rp_read_local_ext_features *rp = (void *) skb->data; 742971e3a4bSAndre Guedes 743971e3a4bSAndre Guedes BT_DBG("%s status 0x%x", hdev->name, rp->status); 744971e3a4bSAndre Guedes 745971e3a4bSAndre Guedes if (rp->status) 7468f984dfaSJohan Hedberg goto done; 747971e3a4bSAndre Guedes 748b5b32b65SAndre Guedes switch (rp->page) { 749b5b32b65SAndre Guedes case 0: 750b5b32b65SAndre Guedes memcpy(hdev->features, rp->features, 8); 751b5b32b65SAndre Guedes break; 752b5b32b65SAndre Guedes case 1: 75359e29406SAndre Guedes memcpy(hdev->host_features, rp->features, 8); 754b5b32b65SAndre Guedes break; 755b5b32b65SAndre Guedes } 756971e3a4bSAndre Guedes 7578f984dfaSJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags) && hdev->features[4] & LMP_LE) 7588f984dfaSJohan Hedberg hci_set_le_support(hdev); 7598f984dfaSJohan Hedberg 7608f984dfaSJohan Hedberg done: 761971e3a4bSAndre Guedes hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status); 762971e3a4bSAndre Guedes } 763971e3a4bSAndre Guedes 7641e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, 7651e89cffbSAndrei Emeltchenko struct sk_buff *skb) 7661e89cffbSAndrei Emeltchenko { 7671e89cffbSAndrei Emeltchenko struct hci_rp_read_flow_control_mode *rp = (void *) skb->data; 7681e89cffbSAndrei Emeltchenko 7691e89cffbSAndrei Emeltchenko BT_DBG("%s status 0x%x", hdev->name, rp->status); 7701e89cffbSAndrei Emeltchenko 7711e89cffbSAndrei Emeltchenko if (rp->status) 7721e89cffbSAndrei Emeltchenko return; 7731e89cffbSAndrei Emeltchenko 7741e89cffbSAndrei Emeltchenko hdev->flow_ctl_mode = rp->mode; 7751e89cffbSAndrei Emeltchenko 7761e89cffbSAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status); 7771e89cffbSAndrei Emeltchenko } 7781e89cffbSAndrei Emeltchenko 779a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 780a9de9248SMarcel Holtmann { 781a9de9248SMarcel Holtmann struct hci_rp_read_buffer_size *rp = (void *) skb->data; 782a9de9248SMarcel Holtmann 783a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 784a9de9248SMarcel Holtmann 785a9de9248SMarcel Holtmann if (rp->status) 786a9de9248SMarcel Holtmann return; 787a9de9248SMarcel Holtmann 788a9de9248SMarcel Holtmann hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); 789a9de9248SMarcel Holtmann hdev->sco_mtu = rp->sco_mtu; 790a9de9248SMarcel Holtmann hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); 791a9de9248SMarcel Holtmann hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); 792da1f5198SMarcel Holtmann 793da1f5198SMarcel Holtmann if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { 794da1f5198SMarcel Holtmann hdev->sco_mtu = 64; 795da1f5198SMarcel Holtmann hdev->sco_pkts = 8; 796da1f5198SMarcel Holtmann } 797da1f5198SMarcel Holtmann 798da1f5198SMarcel Holtmann hdev->acl_cnt = hdev->acl_pkts; 799da1f5198SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 8001da177e4SLinus Torvalds 801a9de9248SMarcel Holtmann BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, 802a9de9248SMarcel Holtmann hdev->acl_mtu, hdev->acl_pkts, 803a9de9248SMarcel Holtmann hdev->sco_mtu, hdev->sco_pkts); 8041da177e4SLinus Torvalds } 8051da177e4SLinus Torvalds 806a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) 807a9de9248SMarcel Holtmann { 808a9de9248SMarcel Holtmann struct hci_rp_read_bd_addr *rp = (void *) skb->data; 8091da177e4SLinus Torvalds 810a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 811a9de9248SMarcel Holtmann 812a9de9248SMarcel Holtmann if (!rp->status) 813a9de9248SMarcel Holtmann bacpy(&hdev->bdaddr, &rp->bdaddr); 814a9de9248SMarcel Holtmann 81523bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status); 81623bb5763SJohan Hedberg } 81723bb5763SJohan Hedberg 818350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev, 819350ee4cfSAndrei Emeltchenko struct sk_buff *skb) 820350ee4cfSAndrei Emeltchenko { 821350ee4cfSAndrei Emeltchenko struct hci_rp_read_data_block_size *rp = (void *) skb->data; 822350ee4cfSAndrei Emeltchenko 823350ee4cfSAndrei Emeltchenko BT_DBG("%s status 0x%x", hdev->name, rp->status); 824350ee4cfSAndrei Emeltchenko 825350ee4cfSAndrei Emeltchenko if (rp->status) 826350ee4cfSAndrei Emeltchenko return; 827350ee4cfSAndrei Emeltchenko 828350ee4cfSAndrei Emeltchenko hdev->block_mtu = __le16_to_cpu(rp->max_acl_len); 829350ee4cfSAndrei Emeltchenko hdev->block_len = __le16_to_cpu(rp->block_len); 830350ee4cfSAndrei Emeltchenko hdev->num_blocks = __le16_to_cpu(rp->num_blocks); 831350ee4cfSAndrei Emeltchenko 832350ee4cfSAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 833350ee4cfSAndrei Emeltchenko 834350ee4cfSAndrei Emeltchenko BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu, 835350ee4cfSAndrei Emeltchenko hdev->block_cnt, hdev->block_len); 836350ee4cfSAndrei Emeltchenko 837350ee4cfSAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status); 838350ee4cfSAndrei Emeltchenko } 839350ee4cfSAndrei Emeltchenko 84023bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb) 84123bb5763SJohan Hedberg { 84223bb5763SJohan Hedberg __u8 status = *((__u8 *) skb->data); 84323bb5763SJohan Hedberg 84423bb5763SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 84523bb5763SJohan Hedberg 84623bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status); 8471da177e4SLinus Torvalds } 8481da177e4SLinus Torvalds 849928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev, 850928abaa7SAndrei Emeltchenko struct sk_buff *skb) 851928abaa7SAndrei Emeltchenko { 852928abaa7SAndrei Emeltchenko struct hci_rp_read_local_amp_info *rp = (void *) skb->data; 853928abaa7SAndrei Emeltchenko 854928abaa7SAndrei Emeltchenko BT_DBG("%s status 0x%x", hdev->name, rp->status); 855928abaa7SAndrei Emeltchenko 856928abaa7SAndrei Emeltchenko if (rp->status) 857928abaa7SAndrei Emeltchenko return; 858928abaa7SAndrei Emeltchenko 859928abaa7SAndrei Emeltchenko hdev->amp_status = rp->amp_status; 860928abaa7SAndrei Emeltchenko hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); 861928abaa7SAndrei Emeltchenko hdev->amp_max_bw = __le32_to_cpu(rp->max_bw); 862928abaa7SAndrei Emeltchenko hdev->amp_min_latency = __le32_to_cpu(rp->min_latency); 863928abaa7SAndrei Emeltchenko hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu); 864928abaa7SAndrei Emeltchenko hdev->amp_type = rp->amp_type; 865928abaa7SAndrei Emeltchenko hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap); 866928abaa7SAndrei Emeltchenko hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size); 867928abaa7SAndrei Emeltchenko hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); 868928abaa7SAndrei Emeltchenko hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); 869928abaa7SAndrei Emeltchenko 870928abaa7SAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status); 871928abaa7SAndrei Emeltchenko } 872928abaa7SAndrei Emeltchenko 873b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, 874b0916ea0SJohan Hedberg struct sk_buff *skb) 875b0916ea0SJohan Hedberg { 876b0916ea0SJohan Hedberg __u8 status = *((__u8 *) skb->data); 877b0916ea0SJohan Hedberg 878b0916ea0SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 879b0916ea0SJohan Hedberg 880b0916ea0SJohan Hedberg hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status); 881b0916ea0SJohan Hedberg } 882b0916ea0SJohan Hedberg 883d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb) 884d5859e22SJohan Hedberg { 885d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 886d5859e22SJohan Hedberg 887d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 888d5859e22SJohan Hedberg 889d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status); 890d5859e22SJohan Hedberg } 891d5859e22SJohan Hedberg 892d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev, 893d5859e22SJohan Hedberg struct sk_buff *skb) 894d5859e22SJohan Hedberg { 895d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 896d5859e22SJohan Hedberg 897d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 898d5859e22SJohan Hedberg 899d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status); 900d5859e22SJohan Hedberg } 901d5859e22SJohan Hedberg 902d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, 903d5859e22SJohan Hedberg struct sk_buff *skb) 904d5859e22SJohan Hedberg { 90591c4e9b1SMarcel Holtmann struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data; 906d5859e22SJohan Hedberg 90791c4e9b1SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 908d5859e22SJohan Hedberg 90991c4e9b1SMarcel Holtmann if (!rp->status) 91091c4e9b1SMarcel Holtmann hdev->inq_tx_power = rp->tx_power; 91191c4e9b1SMarcel Holtmann 91291c4e9b1SMarcel Holtmann hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status); 913d5859e22SJohan Hedberg } 914d5859e22SJohan Hedberg 915d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb) 916d5859e22SJohan Hedberg { 917d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 918d5859e22SJohan Hedberg 919d5859e22SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, status); 920d5859e22SJohan Hedberg 921d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status); 922d5859e22SJohan Hedberg } 923d5859e22SJohan Hedberg 924980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) 925980e1a53SJohan Hedberg { 926980e1a53SJohan Hedberg struct hci_rp_pin_code_reply *rp = (void *) skb->data; 927980e1a53SJohan Hedberg struct hci_cp_pin_code_reply *cp; 928980e1a53SJohan Hedberg struct hci_conn *conn; 929980e1a53SJohan Hedberg 930980e1a53SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 931980e1a53SJohan Hedberg 93256e5cb86SJohan Hedberg hci_dev_lock(hdev); 93356e5cb86SJohan Hedberg 934a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 935744cf19eSJohan Hedberg mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); 936980e1a53SJohan Hedberg 937980e1a53SJohan Hedberg if (rp->status != 0) 93856e5cb86SJohan Hedberg goto unlock; 939980e1a53SJohan Hedberg 940980e1a53SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); 941980e1a53SJohan Hedberg if (!cp) 94256e5cb86SJohan Hedberg goto unlock; 943980e1a53SJohan Hedberg 944980e1a53SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 945980e1a53SJohan Hedberg if (conn) 946980e1a53SJohan Hedberg conn->pin_length = cp->pin_len; 94756e5cb86SJohan Hedberg 94856e5cb86SJohan Hedberg unlock: 94956e5cb86SJohan Hedberg hci_dev_unlock(hdev); 950980e1a53SJohan Hedberg } 951980e1a53SJohan Hedberg 952980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 953980e1a53SJohan Hedberg { 954980e1a53SJohan Hedberg struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data; 955980e1a53SJohan Hedberg 956980e1a53SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 957980e1a53SJohan Hedberg 95856e5cb86SJohan Hedberg hci_dev_lock(hdev); 95956e5cb86SJohan Hedberg 960a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 961744cf19eSJohan Hedberg mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr, 962980e1a53SJohan Hedberg rp->status); 96356e5cb86SJohan Hedberg 96456e5cb86SJohan Hedberg hci_dev_unlock(hdev); 965980e1a53SJohan Hedberg } 96656e5cb86SJohan Hedberg 9676ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, 9686ed58ec5SVille Tervo struct sk_buff *skb) 9696ed58ec5SVille Tervo { 9706ed58ec5SVille Tervo struct hci_rp_le_read_buffer_size *rp = (void *) skb->data; 9716ed58ec5SVille Tervo 9726ed58ec5SVille Tervo BT_DBG("%s status 0x%x", hdev->name, rp->status); 9736ed58ec5SVille Tervo 9746ed58ec5SVille Tervo if (rp->status) 9756ed58ec5SVille Tervo return; 9766ed58ec5SVille Tervo 9776ed58ec5SVille Tervo hdev->le_mtu = __le16_to_cpu(rp->le_mtu); 9786ed58ec5SVille Tervo hdev->le_pkts = rp->le_max_pkt; 9796ed58ec5SVille Tervo 9806ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 9816ed58ec5SVille Tervo 9826ed58ec5SVille Tervo BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); 9836ed58ec5SVille Tervo 9846ed58ec5SVille Tervo hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status); 9856ed58ec5SVille Tervo } 986980e1a53SJohan Hedberg 987a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) 988a5c29683SJohan Hedberg { 989a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 990a5c29683SJohan Hedberg 991a5c29683SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 992a5c29683SJohan Hedberg 99356e5cb86SJohan Hedberg hci_dev_lock(hdev); 99456e5cb86SJohan Hedberg 995a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 99604124681SGustavo F. Padovan mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0, 99704124681SGustavo F. Padovan rp->status); 99856e5cb86SJohan Hedberg 99956e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1000a5c29683SJohan Hedberg } 1001a5c29683SJohan Hedberg 1002a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, 1003a5c29683SJohan Hedberg struct sk_buff *skb) 1004a5c29683SJohan Hedberg { 1005a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 1006a5c29683SJohan Hedberg 1007a5c29683SJohan Hedberg BT_DBG("%s status 0x%x", hdev->name, rp->status); 1008a5c29683SJohan Hedberg 100956e5cb86SJohan Hedberg hci_dev_lock(hdev); 101056e5cb86SJohan Hedberg 1011a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1012744cf19eSJohan Hedberg mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr, 101304124681SGustavo F. Padovan ACL_LINK, 0, rp->status); 101456e5cb86SJohan Hedberg 101556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1016a5c29683SJohan Hedberg } 1017a5c29683SJohan Hedberg 10181143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb) 10191143d458SBrian Gix { 10201143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 10211143d458SBrian Gix 10221143d458SBrian Gix BT_DBG("%s status 0x%x", hdev->name, rp->status); 10231143d458SBrian Gix 10241143d458SBrian Gix hci_dev_lock(hdev); 10251143d458SBrian Gix 1026a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1027272d90dfSJohan Hedberg mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 1028272d90dfSJohan Hedberg 0, rp->status); 10291143d458SBrian Gix 10301143d458SBrian Gix hci_dev_unlock(hdev); 10311143d458SBrian Gix } 10321143d458SBrian Gix 10331143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, 10341143d458SBrian Gix struct sk_buff *skb) 10351143d458SBrian Gix { 10361143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 10371143d458SBrian Gix 10381143d458SBrian Gix BT_DBG("%s status 0x%x", hdev->name, rp->status); 10391143d458SBrian Gix 10401143d458SBrian Gix hci_dev_lock(hdev); 10411143d458SBrian Gix 1042a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 10431143d458SBrian Gix mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr, 104404124681SGustavo F. Padovan ACL_LINK, 0, rp->status); 10451143d458SBrian Gix 10461143d458SBrian Gix hci_dev_unlock(hdev); 10471143d458SBrian Gix } 10481143d458SBrian Gix 1049c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, 1050c35938b2SSzymon Janc struct sk_buff *skb) 1051c35938b2SSzymon Janc { 1052c35938b2SSzymon Janc struct hci_rp_read_local_oob_data *rp = (void *) skb->data; 1053c35938b2SSzymon Janc 1054c35938b2SSzymon Janc BT_DBG("%s status 0x%x", hdev->name, rp->status); 1055c35938b2SSzymon Janc 105656e5cb86SJohan Hedberg hci_dev_lock(hdev); 1057744cf19eSJohan Hedberg mgmt_read_local_oob_data_reply_complete(hdev, rp->hash, 1058c35938b2SSzymon Janc rp->randomizer, rp->status); 105956e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1060c35938b2SSzymon Janc } 1061c35938b2SSzymon Janc 106207f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) 106307f7fa5dSAndre Guedes { 106407f7fa5dSAndre Guedes __u8 status = *((__u8 *) skb->data); 106507f7fa5dSAndre Guedes 106607f7fa5dSAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 10677ba8b4beSAndre Guedes 10687ba8b4beSAndre Guedes hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status); 10693fd24153SAndre Guedes 10703fd24153SAndre Guedes if (status) { 10713fd24153SAndre Guedes hci_dev_lock(hdev); 10723fd24153SAndre Guedes mgmt_start_discovery_failed(hdev, status); 10733fd24153SAndre Guedes hci_dev_unlock(hdev); 10743fd24153SAndre Guedes return; 10753fd24153SAndre Guedes } 107607f7fa5dSAndre Guedes } 107707f7fa5dSAndre Guedes 1078eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, 1079eb9d91f5SAndre Guedes struct sk_buff *skb) 1080eb9d91f5SAndre Guedes { 1081eb9d91f5SAndre Guedes struct hci_cp_le_set_scan_enable *cp; 1082eb9d91f5SAndre Guedes __u8 status = *((__u8 *) skb->data); 1083eb9d91f5SAndre Guedes 1084eb9d91f5SAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 1085eb9d91f5SAndre Guedes 1086eb9d91f5SAndre Guedes cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE); 1087eb9d91f5SAndre Guedes if (!cp) 1088eb9d91f5SAndre Guedes return; 1089eb9d91f5SAndre Guedes 109068a8aea4SAndrei Emeltchenko switch (cp->enable) { 109168a8aea4SAndrei Emeltchenko case LE_SCANNING_ENABLED: 10927ba8b4beSAndre Guedes hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status); 10937ba8b4beSAndre Guedes 10943fd24153SAndre Guedes if (status) { 10953fd24153SAndre Guedes hci_dev_lock(hdev); 10963fd24153SAndre Guedes mgmt_start_discovery_failed(hdev, status); 10973fd24153SAndre Guedes hci_dev_unlock(hdev); 10987ba8b4beSAndre Guedes return; 10993fd24153SAndre Guedes } 11007ba8b4beSAndre Guedes 1101d23264a8SAndre Guedes set_bit(HCI_LE_SCAN, &hdev->dev_flags); 1102d23264a8SAndre Guedes 1103db323f2fSGustavo F. Padovan cancel_delayed_work_sync(&hdev->adv_work); 1104a8f13c8cSAndre Guedes 1105a8f13c8cSAndre Guedes hci_dev_lock(hdev); 1106eb9d91f5SAndre Guedes hci_adv_entries_clear(hdev); 1107343f935bSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_FINDING); 1108a8f13c8cSAndre Guedes hci_dev_unlock(hdev); 110968a8aea4SAndrei Emeltchenko break; 111068a8aea4SAndrei Emeltchenko 111168a8aea4SAndrei Emeltchenko case LE_SCANNING_DISABLED: 1112c9ecc48eSAndre Guedes if (status) { 1113c9ecc48eSAndre Guedes hci_dev_lock(hdev); 1114c9ecc48eSAndre Guedes mgmt_stop_discovery_failed(hdev, status); 1115c9ecc48eSAndre Guedes hci_dev_unlock(hdev); 11167ba8b4beSAndre Guedes return; 1117c9ecc48eSAndre Guedes } 11187ba8b4beSAndre Guedes 1119d23264a8SAndre Guedes clear_bit(HCI_LE_SCAN, &hdev->dev_flags); 1120d23264a8SAndre Guedes 11215e0452c0SAndre Guedes schedule_delayed_work(&hdev->adv_work, ADV_CLEAR_TIMEOUT); 11225e0452c0SAndre Guedes 1123bc3dd33cSAndre Guedes if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED && 1124bc3dd33cSAndre Guedes hdev->discovery.state == DISCOVERY_FINDING) { 11255e0452c0SAndre Guedes mgmt_interleaved_discovery(hdev); 11265e0452c0SAndre Guedes } else { 1127c599008fSAndre Guedes hci_dev_lock(hdev); 1128c599008fSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 1129c599008fSAndre Guedes hci_dev_unlock(hdev); 11305e0452c0SAndre Guedes } 1131c599008fSAndre Guedes 113268a8aea4SAndrei Emeltchenko break; 113368a8aea4SAndrei Emeltchenko 113468a8aea4SAndrei Emeltchenko default: 113568a8aea4SAndrei Emeltchenko BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable); 113668a8aea4SAndrei Emeltchenko break; 113735815085SAndre Guedes } 1138eb9d91f5SAndre Guedes } 1139eb9d91f5SAndre Guedes 1140a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb) 1141a7a595f6SVinicius Costa Gomes { 1142a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_reply *rp = (void *) skb->data; 1143a7a595f6SVinicius Costa Gomes 1144a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, rp->status); 1145a7a595f6SVinicius Costa Gomes 1146a7a595f6SVinicius Costa Gomes if (rp->status) 1147a7a595f6SVinicius Costa Gomes return; 1148a7a595f6SVinicius Costa Gomes 1149a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status); 1150a7a595f6SVinicius Costa Gomes } 1151a7a595f6SVinicius Costa Gomes 1152a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 1153a7a595f6SVinicius Costa Gomes { 1154a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data; 1155a7a595f6SVinicius Costa Gomes 1156a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, rp->status); 1157a7a595f6SVinicius Costa Gomes 1158a7a595f6SVinicius Costa Gomes if (rp->status) 1159a7a595f6SVinicius Costa Gomes return; 1160a7a595f6SVinicius Costa Gomes 1161a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status); 1162a7a595f6SVinicius Costa Gomes } 1163a7a595f6SVinicius Costa Gomes 1164f9b49306SAndre Guedes static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev, 1165f9b49306SAndre Guedes struct sk_buff *skb) 1166f9b49306SAndre Guedes { 116706199cf8SJohan Hedberg struct hci_cp_write_le_host_supported *sent; 1168f9b49306SAndre Guedes __u8 status = *((__u8 *) skb->data); 1169f9b49306SAndre Guedes 1170f9b49306SAndre Guedes BT_DBG("%s status 0x%x", hdev->name, status); 1171f9b49306SAndre Guedes 117206199cf8SJohan Hedberg sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED); 11738f984dfaSJohan Hedberg if (!sent) 1174f9b49306SAndre Guedes return; 1175f9b49306SAndre Guedes 11768f984dfaSJohan Hedberg if (!status) { 11778f984dfaSJohan Hedberg if (sent->le) 11788f984dfaSJohan Hedberg hdev->host_features[0] |= LMP_HOST_LE; 11798f984dfaSJohan Hedberg else 11808f984dfaSJohan Hedberg hdev->host_features[0] &= ~LMP_HOST_LE; 11818f984dfaSJohan Hedberg } 11828f984dfaSJohan Hedberg 11838f984dfaSJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags) && 11848f984dfaSJohan Hedberg !test_bit(HCI_INIT, &hdev->flags)) 11858f984dfaSJohan Hedberg mgmt_le_enable_complete(hdev, sent->le, status); 11868f984dfaSJohan Hedberg 11878f984dfaSJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status); 1188f9b49306SAndre Guedes } 1189f9b49306SAndre Guedes 1190a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 1191a9de9248SMarcel Holtmann { 1192a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1193a9de9248SMarcel Holtmann 1194a9de9248SMarcel Holtmann if (status) { 119523bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 1196a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 119756e5cb86SJohan Hedberg hci_dev_lock(hdev); 1198a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 11997a135109SAndre Guedes mgmt_start_discovery_failed(hdev, status); 120056e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1201314b2381SJohan Hedberg return; 1202314b2381SJohan Hedberg } 1203314b2381SJohan Hedberg 120489352e7dSAndre Guedes set_bit(HCI_INQUIRY, &hdev->flags); 120589352e7dSAndre Guedes 120656e5cb86SJohan Hedberg hci_dev_lock(hdev); 1207343f935bSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_FINDING); 120856e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1209a9de9248SMarcel Holtmann } 1210a9de9248SMarcel Holtmann 12111da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 12121da177e4SLinus Torvalds { 1213a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 12141da177e4SLinus Torvalds struct hci_conn *conn; 12151da177e4SLinus Torvalds 1216a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1217a9de9248SMarcel Holtmann 1218a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 12191da177e4SLinus Torvalds if (!cp) 12201da177e4SLinus Torvalds return; 12211da177e4SLinus Torvalds 12221da177e4SLinus Torvalds hci_dev_lock(hdev); 12231da177e4SLinus Torvalds 12241da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 12251da177e4SLinus Torvalds 1226a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn); 12271da177e4SLinus Torvalds 12281da177e4SLinus Torvalds if (status) { 12291da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 12304c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 12311da177e4SLinus Torvalds conn->state = BT_CLOSED; 12321da177e4SLinus Torvalds hci_proto_connect_cfm(conn, status); 12331da177e4SLinus Torvalds hci_conn_del(conn); 12344c67bc74SMarcel Holtmann } else 12354c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 12361da177e4SLinus Torvalds } 12371da177e4SLinus Torvalds } else { 12381da177e4SLinus Torvalds if (!conn) { 12391da177e4SLinus Torvalds conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); 12401da177e4SLinus Torvalds if (conn) { 1241a0c808b3SJohan Hedberg conn->out = true; 12421da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 12431da177e4SLinus Torvalds } else 1244893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 12451da177e4SLinus Torvalds } 12461da177e4SLinus Torvalds } 12471da177e4SLinus Torvalds 12481da177e4SLinus Torvalds hci_dev_unlock(hdev); 12491da177e4SLinus Torvalds } 12501da177e4SLinus Torvalds 1251a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 12521da177e4SLinus Torvalds { 1253a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 12541da177e4SLinus Torvalds struct hci_conn *acl, *sco; 12551da177e4SLinus Torvalds __u16 handle; 12561da177e4SLinus Torvalds 1257b6a0dc82SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1258b6a0dc82SMarcel Holtmann 1259a9de9248SMarcel Holtmann if (!status) 1260a9de9248SMarcel Holtmann return; 1261a9de9248SMarcel Holtmann 1262a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 12631da177e4SLinus Torvalds if (!cp) 1264a9de9248SMarcel Holtmann return; 12651da177e4SLinus Torvalds 12661da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 12671da177e4SLinus Torvalds 1268a9de9248SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 12691da177e4SLinus Torvalds 12701da177e4SLinus Torvalds hci_dev_lock(hdev); 12711da177e4SLinus Torvalds 12721da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 12735a08ecceSAndrei Emeltchenko if (acl) { 12745a08ecceSAndrei Emeltchenko sco = acl->link; 12755a08ecceSAndrei Emeltchenko if (sco) { 12761da177e4SLinus Torvalds sco->state = BT_CLOSED; 12771da177e4SLinus Torvalds 12781da177e4SLinus Torvalds hci_proto_connect_cfm(sco, status); 12791da177e4SLinus Torvalds hci_conn_del(sco); 12801da177e4SLinus Torvalds } 12815a08ecceSAndrei Emeltchenko } 12821da177e4SLinus Torvalds 12831da177e4SLinus Torvalds hci_dev_unlock(hdev); 12841da177e4SLinus Torvalds } 12851da177e4SLinus Torvalds 1286f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 1287f8558555SMarcel Holtmann { 1288f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 1289f8558555SMarcel Holtmann struct hci_conn *conn; 1290f8558555SMarcel Holtmann 1291f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1292f8558555SMarcel Holtmann 1293f8558555SMarcel Holtmann if (!status) 1294f8558555SMarcel Holtmann return; 1295f8558555SMarcel Holtmann 1296f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 1297f8558555SMarcel Holtmann if (!cp) 1298f8558555SMarcel Holtmann return; 1299f8558555SMarcel Holtmann 1300f8558555SMarcel Holtmann hci_dev_lock(hdev); 1301f8558555SMarcel Holtmann 1302f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1303f8558555SMarcel Holtmann if (conn) { 1304f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1305f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1306f8558555SMarcel Holtmann hci_conn_put(conn); 1307f8558555SMarcel Holtmann } 1308f8558555SMarcel Holtmann } 1309f8558555SMarcel Holtmann 1310f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1311f8558555SMarcel Holtmann } 1312f8558555SMarcel Holtmann 1313f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 1314f8558555SMarcel Holtmann { 1315f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 1316f8558555SMarcel Holtmann struct hci_conn *conn; 1317f8558555SMarcel Holtmann 1318f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1319f8558555SMarcel Holtmann 1320f8558555SMarcel Holtmann if (!status) 1321f8558555SMarcel Holtmann return; 1322f8558555SMarcel Holtmann 1323f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 1324f8558555SMarcel Holtmann if (!cp) 1325f8558555SMarcel Holtmann return; 1326f8558555SMarcel Holtmann 1327f8558555SMarcel Holtmann hci_dev_lock(hdev); 1328f8558555SMarcel Holtmann 1329f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1330f8558555SMarcel Holtmann if (conn) { 1331f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1332f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1333f8558555SMarcel Holtmann hci_conn_put(conn); 1334f8558555SMarcel Holtmann } 1335f8558555SMarcel Holtmann } 1336f8558555SMarcel Holtmann 1337f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1338f8558555SMarcel Holtmann } 1339f8558555SMarcel Holtmann 1340127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev, 1341392599b9SJohan Hedberg struct hci_conn *conn) 1342392599b9SJohan Hedberg { 1343392599b9SJohan Hedberg if (conn->state != BT_CONFIG || !conn->out) 1344392599b9SJohan Hedberg return 0; 1345392599b9SJohan Hedberg 1346765c2a96SJohan Hedberg if (conn->pending_sec_level == BT_SECURITY_SDP) 1347392599b9SJohan Hedberg return 0; 1348392599b9SJohan Hedberg 1349392599b9SJohan Hedberg /* Only request authentication for SSP connections or non-SSP 1350e9bf2bf0SVinicius Costa Gomes * devices with sec_level HIGH or if MITM protection is requested */ 1351aa64a8b5SJohan Hedberg if (!hci_conn_ssp_enabled(conn) && 1352e9bf2bf0SVinicius Costa Gomes conn->pending_sec_level != BT_SECURITY_HIGH && 1353e9bf2bf0SVinicius Costa Gomes !(conn->auth_type & 0x01)) 1354392599b9SJohan Hedberg return 0; 1355392599b9SJohan Hedberg 1356392599b9SJohan Hedberg return 1; 1357392599b9SJohan Hedberg } 1358392599b9SJohan Hedberg 135900abfe44SGustavo F. Padovan static inline int hci_resolve_name(struct hci_dev *hdev, 136000abfe44SGustavo F. Padovan struct inquiry_entry *e) 136130dc78e1SJohan Hedberg { 136230dc78e1SJohan Hedberg struct hci_cp_remote_name_req cp; 136330dc78e1SJohan Hedberg 136430dc78e1SJohan Hedberg memset(&cp, 0, sizeof(cp)); 136530dc78e1SJohan Hedberg 136630dc78e1SJohan Hedberg bacpy(&cp.bdaddr, &e->data.bdaddr); 136730dc78e1SJohan Hedberg cp.pscan_rep_mode = e->data.pscan_rep_mode; 136830dc78e1SJohan Hedberg cp.pscan_mode = e->data.pscan_mode; 136930dc78e1SJohan Hedberg cp.clock_offset = e->data.clock_offset; 137030dc78e1SJohan Hedberg 137130dc78e1SJohan Hedberg return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 137230dc78e1SJohan Hedberg } 137330dc78e1SJohan Hedberg 1374b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev) 137530dc78e1SJohan Hedberg { 137630dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 137730dc78e1SJohan Hedberg struct inquiry_entry *e; 137830dc78e1SJohan Hedberg 1379b644ba33SJohan Hedberg if (list_empty(&discov->resolve)) 1380b644ba33SJohan Hedberg return false; 1381b644ba33SJohan Hedberg 1382b644ba33SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 1383b644ba33SJohan Hedberg if (hci_resolve_name(hdev, e) == 0) { 1384b644ba33SJohan Hedberg e->name_state = NAME_PENDING; 1385b644ba33SJohan Hedberg return true; 1386b644ba33SJohan Hedberg } 1387b644ba33SJohan Hedberg 1388b644ba33SJohan Hedberg return false; 1389b644ba33SJohan Hedberg } 1390b644ba33SJohan Hedberg 1391b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn, 1392b644ba33SJohan Hedberg bdaddr_t *bdaddr, u8 *name, u8 name_len) 1393b644ba33SJohan Hedberg { 1394b644ba33SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 1395b644ba33SJohan Hedberg struct inquiry_entry *e; 1396b644ba33SJohan Hedberg 1397b644ba33SJohan Hedberg if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 139804124681SGustavo F. Padovan mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name, 139904124681SGustavo F. Padovan name_len, conn->dev_class); 1400b644ba33SJohan Hedberg 1401b644ba33SJohan Hedberg if (discov->state == DISCOVERY_STOPPED) 1402b644ba33SJohan Hedberg return; 1403b644ba33SJohan Hedberg 140430dc78e1SJohan Hedberg if (discov->state == DISCOVERY_STOPPING) 140530dc78e1SJohan Hedberg goto discov_complete; 140630dc78e1SJohan Hedberg 140730dc78e1SJohan Hedberg if (discov->state != DISCOVERY_RESOLVING) 140830dc78e1SJohan Hedberg return; 140930dc78e1SJohan Hedberg 141030dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING); 141130dc78e1SJohan Hedberg if (e) { 141230dc78e1SJohan Hedberg e->name_state = NAME_KNOWN; 141330dc78e1SJohan Hedberg list_del(&e->list); 1414b644ba33SJohan Hedberg if (name) 1415b644ba33SJohan Hedberg mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, 1416b644ba33SJohan Hedberg e->data.rssi, name, name_len); 141730dc78e1SJohan Hedberg } 141830dc78e1SJohan Hedberg 1419b644ba33SJohan Hedberg if (hci_resolve_next_name(hdev)) 142030dc78e1SJohan Hedberg return; 142130dc78e1SJohan Hedberg 142230dc78e1SJohan Hedberg discov_complete: 142330dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 142430dc78e1SJohan Hedberg } 142530dc78e1SJohan Hedberg 1426a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 14271da177e4SLinus Torvalds { 1428127178d2SJohan Hedberg struct hci_cp_remote_name_req *cp; 1429127178d2SJohan Hedberg struct hci_conn *conn; 1430127178d2SJohan Hedberg 1431a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1432127178d2SJohan Hedberg 1433127178d2SJohan Hedberg /* If successful wait for the name req complete event before 1434127178d2SJohan Hedberg * checking for the need to do authentication */ 1435127178d2SJohan Hedberg if (!status) 1436127178d2SJohan Hedberg return; 1437127178d2SJohan Hedberg 1438127178d2SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); 1439127178d2SJohan Hedberg if (!cp) 1440127178d2SJohan Hedberg return; 1441127178d2SJohan Hedberg 1442127178d2SJohan Hedberg hci_dev_lock(hdev); 1443127178d2SJohan Hedberg 1444127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 1445b644ba33SJohan Hedberg 1446b644ba33SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1447b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0); 1448b644ba33SJohan Hedberg 144979c6c70cSJohan Hedberg if (!conn) 145079c6c70cSJohan Hedberg goto unlock; 145179c6c70cSJohan Hedberg 145279c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 145379c6c70cSJohan Hedberg goto unlock; 145479c6c70cSJohan Hedberg 145551a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 1456127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1457127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1458127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1459127178d2SJohan Hedberg } 1460127178d2SJohan Hedberg 146179c6c70cSJohan Hedberg unlock: 1462127178d2SJohan Hedberg hci_dev_unlock(hdev); 1463a9de9248SMarcel Holtmann } 14641da177e4SLinus Torvalds 1465769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 1466769be974SMarcel Holtmann { 1467769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 1468769be974SMarcel Holtmann struct hci_conn *conn; 1469769be974SMarcel Holtmann 1470769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1471769be974SMarcel Holtmann 1472769be974SMarcel Holtmann if (!status) 1473769be974SMarcel Holtmann return; 1474769be974SMarcel Holtmann 1475769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 1476769be974SMarcel Holtmann if (!cp) 1477769be974SMarcel Holtmann return; 1478769be974SMarcel Holtmann 1479769be974SMarcel Holtmann hci_dev_lock(hdev); 1480769be974SMarcel Holtmann 1481769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1482769be974SMarcel Holtmann if (conn) { 1483769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1484769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1485769be974SMarcel Holtmann hci_conn_put(conn); 1486769be974SMarcel Holtmann } 1487769be974SMarcel Holtmann } 1488769be974SMarcel Holtmann 1489769be974SMarcel Holtmann hci_dev_unlock(hdev); 1490769be974SMarcel Holtmann } 1491769be974SMarcel Holtmann 1492769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 1493769be974SMarcel Holtmann { 1494769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features *cp; 1495769be974SMarcel Holtmann struct hci_conn *conn; 1496769be974SMarcel Holtmann 1497769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1498769be974SMarcel Holtmann 1499769be974SMarcel Holtmann if (!status) 1500769be974SMarcel Holtmann return; 1501769be974SMarcel Holtmann 1502769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 1503769be974SMarcel Holtmann if (!cp) 1504769be974SMarcel Holtmann return; 1505769be974SMarcel Holtmann 1506769be974SMarcel Holtmann hci_dev_lock(hdev); 1507769be974SMarcel Holtmann 1508769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1509769be974SMarcel Holtmann if (conn) { 1510769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1511769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1512769be974SMarcel Holtmann hci_conn_put(conn); 1513769be974SMarcel Holtmann } 1514769be974SMarcel Holtmann } 1515769be974SMarcel Holtmann 1516769be974SMarcel Holtmann hci_dev_unlock(hdev); 1517769be974SMarcel Holtmann } 1518769be974SMarcel Holtmann 1519a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 1520a9de9248SMarcel Holtmann { 1521b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 1522b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 1523b6a0dc82SMarcel Holtmann __u16 handle; 1524b6a0dc82SMarcel Holtmann 1525a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1526b6a0dc82SMarcel Holtmann 1527b6a0dc82SMarcel Holtmann if (!status) 1528b6a0dc82SMarcel Holtmann return; 1529b6a0dc82SMarcel Holtmann 1530b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 1531b6a0dc82SMarcel Holtmann if (!cp) 1532b6a0dc82SMarcel Holtmann return; 1533b6a0dc82SMarcel Holtmann 1534b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 1535b6a0dc82SMarcel Holtmann 1536b6a0dc82SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 1537b6a0dc82SMarcel Holtmann 1538b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 1539b6a0dc82SMarcel Holtmann 1540b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 15415a08ecceSAndrei Emeltchenko if (acl) { 15425a08ecceSAndrei Emeltchenko sco = acl->link; 15435a08ecceSAndrei Emeltchenko if (sco) { 1544b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 1545b6a0dc82SMarcel Holtmann 1546b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(sco, status); 1547b6a0dc82SMarcel Holtmann hci_conn_del(sco); 1548b6a0dc82SMarcel Holtmann } 15495a08ecceSAndrei Emeltchenko } 1550b6a0dc82SMarcel Holtmann 1551b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 1552a9de9248SMarcel Holtmann } 1553a9de9248SMarcel Holtmann 1554a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 1555a9de9248SMarcel Holtmann { 1556a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 155704837f64SMarcel Holtmann struct hci_conn *conn; 155804837f64SMarcel Holtmann 1559a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1560a9de9248SMarcel Holtmann 1561a9de9248SMarcel Holtmann if (!status) 1562a9de9248SMarcel Holtmann return; 1563a9de9248SMarcel Holtmann 1564a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 156504837f64SMarcel Holtmann if (!cp) 1566a9de9248SMarcel Holtmann return; 156704837f64SMarcel Holtmann 156804837f64SMarcel Holtmann hci_dev_lock(hdev); 156904837f64SMarcel Holtmann 157004837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1571e73439d8SMarcel Holtmann if (conn) { 157251a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 157304837f64SMarcel Holtmann 157451a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1575e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1576e73439d8SMarcel Holtmann } 1577e73439d8SMarcel Holtmann 157804837f64SMarcel Holtmann hci_dev_unlock(hdev); 157904837f64SMarcel Holtmann } 158004837f64SMarcel Holtmann 1581a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 1582a9de9248SMarcel Holtmann { 1583a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 158404837f64SMarcel Holtmann struct hci_conn *conn; 158504837f64SMarcel Holtmann 1586a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1587a9de9248SMarcel Holtmann 1588a9de9248SMarcel Holtmann if (!status) 1589a9de9248SMarcel Holtmann return; 1590a9de9248SMarcel Holtmann 1591a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 159204837f64SMarcel Holtmann if (!cp) 1593a9de9248SMarcel Holtmann return; 159404837f64SMarcel Holtmann 159504837f64SMarcel Holtmann hci_dev_lock(hdev); 159604837f64SMarcel Holtmann 159704837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1598e73439d8SMarcel Holtmann if (conn) { 159951a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 160004837f64SMarcel Holtmann 160151a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1602e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1603e73439d8SMarcel Holtmann } 1604e73439d8SMarcel Holtmann 160504837f64SMarcel Holtmann hci_dev_unlock(hdev); 160604837f64SMarcel Holtmann } 160704837f64SMarcel Holtmann 160888c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) 160988c3df13SJohan Hedberg { 161088c3df13SJohan Hedberg struct hci_cp_disconnect *cp; 161188c3df13SJohan Hedberg struct hci_conn *conn; 161288c3df13SJohan Hedberg 161388c3df13SJohan Hedberg if (!status) 161488c3df13SJohan Hedberg return; 161588c3df13SJohan Hedberg 161688c3df13SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT); 161788c3df13SJohan Hedberg if (!cp) 161888c3df13SJohan Hedberg return; 161988c3df13SJohan Hedberg 162088c3df13SJohan Hedberg hci_dev_lock(hdev); 162188c3df13SJohan Hedberg 162288c3df13SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 162388c3df13SJohan Hedberg if (conn) 162488c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 162588c3df13SJohan Hedberg conn->dst_type, status); 162688c3df13SJohan Hedberg 162788c3df13SJohan Hedberg hci_dev_unlock(hdev); 162888c3df13SJohan Hedberg } 162988c3df13SJohan Hedberg 1630fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) 1631fcd89c09SVille Tervo { 1632fcd89c09SVille Tervo struct hci_cp_le_create_conn *cp; 1633fcd89c09SVille Tervo struct hci_conn *conn; 1634fcd89c09SVille Tervo 1635fcd89c09SVille Tervo BT_DBG("%s status 0x%x", hdev->name, status); 1636fcd89c09SVille Tervo 1637fcd89c09SVille Tervo cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN); 1638fcd89c09SVille Tervo if (!cp) 1639fcd89c09SVille Tervo return; 1640fcd89c09SVille Tervo 1641fcd89c09SVille Tervo hci_dev_lock(hdev); 1642fcd89c09SVille Tervo 1643fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr); 1644fcd89c09SVille Tervo 1645fcd89c09SVille Tervo BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr), 1646fcd89c09SVille Tervo conn); 1647fcd89c09SVille Tervo 1648fcd89c09SVille Tervo if (status) { 1649fcd89c09SVille Tervo if (conn && conn->state == BT_CONNECT) { 1650fcd89c09SVille Tervo conn->state = BT_CLOSED; 1651328c9248SHemant Gupta mgmt_connect_failed(hdev, &cp->peer_addr, conn->type, 1652328c9248SHemant Gupta conn->dst_type, status); 1653fcd89c09SVille Tervo hci_proto_connect_cfm(conn, status); 1654fcd89c09SVille Tervo hci_conn_del(conn); 1655fcd89c09SVille Tervo } 1656fcd89c09SVille Tervo } else { 1657fcd89c09SVille Tervo if (!conn) { 1658fcd89c09SVille Tervo conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr); 165929b7988aSAndre Guedes if (conn) { 166029b7988aSAndre Guedes conn->dst_type = cp->peer_addr_type; 1661a0c808b3SJohan Hedberg conn->out = true; 166229b7988aSAndre Guedes } else { 1663fcd89c09SVille Tervo BT_ERR("No memory for new connection"); 1664fcd89c09SVille Tervo } 1665fcd89c09SVille Tervo } 166629b7988aSAndre Guedes } 1667fcd89c09SVille Tervo 1668fcd89c09SVille Tervo hci_dev_unlock(hdev); 1669fcd89c09SVille Tervo } 1670fcd89c09SVille Tervo 1671a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) 1672a7a595f6SVinicius Costa Gomes { 1673a7a595f6SVinicius Costa Gomes BT_DBG("%s status 0x%x", hdev->name, status); 1674a7a595f6SVinicius Costa Gomes } 1675a7a595f6SVinicius Costa Gomes 16761da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 16771da177e4SLinus Torvalds { 16781da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 167930dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 168030dc78e1SJohan Hedberg struct inquiry_entry *e; 16811da177e4SLinus Torvalds 16821da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, status); 16831da177e4SLinus Torvalds 168423bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 16856bd57416SMarcel Holtmann 1686a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 168789352e7dSAndre Guedes 168889352e7dSAndre Guedes if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) 168989352e7dSAndre Guedes return; 169089352e7dSAndre Guedes 1691a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 169230dc78e1SJohan Hedberg return; 169330dc78e1SJohan Hedberg 169456e5cb86SJohan Hedberg hci_dev_lock(hdev); 169530dc78e1SJohan Hedberg 1696343f935bSAndre Guedes if (discov->state != DISCOVERY_FINDING) 169730dc78e1SJohan Hedberg goto unlock; 169830dc78e1SJohan Hedberg 169930dc78e1SJohan Hedberg if (list_empty(&discov->resolve)) { 1700ff9ef578SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 170130dc78e1SJohan Hedberg goto unlock; 170230dc78e1SJohan Hedberg } 170330dc78e1SJohan Hedberg 170430dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 170530dc78e1SJohan Hedberg if (e && hci_resolve_name(hdev, e) == 0) { 170630dc78e1SJohan Hedberg e->name_state = NAME_PENDING; 170730dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_RESOLVING); 170830dc78e1SJohan Hedberg } else { 170930dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 171030dc78e1SJohan Hedberg } 171130dc78e1SJohan Hedberg 171230dc78e1SJohan Hedberg unlock: 171356e5cb86SJohan Hedberg hci_dev_unlock(hdev); 17141da177e4SLinus Torvalds } 17151da177e4SLinus Torvalds 17161da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 17171da177e4SLinus Torvalds { 171845bb4bf0SMarcel Holtmann struct inquiry_data data; 1719a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 17201da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 17211da177e4SLinus Torvalds 17221da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 17231da177e4SLinus Torvalds 172445bb4bf0SMarcel Holtmann if (!num_rsp) 172545bb4bf0SMarcel Holtmann return; 172645bb4bf0SMarcel Holtmann 17271519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 17281519cc17SAndre Guedes return; 17291519cc17SAndre Guedes 17301da177e4SLinus Torvalds hci_dev_lock(hdev); 173145bb4bf0SMarcel Holtmann 1732e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 1733388fc8faSJohan Hedberg bool name_known, ssp; 17343175405bSJohan Hedberg 17351da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 17361da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 17371da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 17381da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 17391da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 17401da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 17411da177e4SLinus Torvalds data.rssi = 0x00; 174241a96212SMarcel Holtmann data.ssp_mode = 0x00; 17433175405bSJohan Hedberg 1744388fc8faSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp); 174548264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 174604124681SGustavo F. Padovan info->dev_class, 0, !name_known, ssp, NULL, 174704124681SGustavo F. Padovan 0); 17481da177e4SLinus Torvalds } 174945bb4bf0SMarcel Holtmann 17501da177e4SLinus Torvalds hci_dev_unlock(hdev); 17511da177e4SLinus Torvalds } 17521da177e4SLinus Torvalds 1753a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 17541da177e4SLinus Torvalds { 1755a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 1756a9de9248SMarcel Holtmann struct hci_conn *conn; 17571da177e4SLinus Torvalds 1758a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 175945bb4bf0SMarcel Holtmann 17601da177e4SLinus Torvalds hci_dev_lock(hdev); 176145bb4bf0SMarcel Holtmann 1762a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 17639499237aSMarcel Holtmann if (!conn) { 17649499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 17659499237aSMarcel Holtmann goto unlock; 17669499237aSMarcel Holtmann 17679499237aSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 1768a9de9248SMarcel Holtmann if (!conn) 1769a9de9248SMarcel Holtmann goto unlock; 177045bb4bf0SMarcel Holtmann 17719499237aSMarcel Holtmann conn->type = SCO_LINK; 17729499237aSMarcel Holtmann } 17739499237aSMarcel Holtmann 1774a9de9248SMarcel Holtmann if (!ev->status) { 1775a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 1776769be974SMarcel Holtmann 1777769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 1778769be974SMarcel Holtmann conn->state = BT_CONFIG; 1779769be974SMarcel Holtmann hci_conn_hold(conn); 1780052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1781769be974SMarcel Holtmann } else 1782a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 1783a9de9248SMarcel Holtmann 17849eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 17857d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 17867d0db0a3SMarcel Holtmann 1787a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 1788a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1789a9de9248SMarcel Holtmann 1790a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 1791a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1792a9de9248SMarcel Holtmann 1793a9de9248SMarcel Holtmann /* Get remote features */ 1794a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 1795a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 1796a9de9248SMarcel Holtmann cp.handle = ev->handle; 1797769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 1798769be974SMarcel Holtmann sizeof(cp), &cp); 179945bb4bf0SMarcel Holtmann } 1800a9de9248SMarcel Holtmann 1801a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 1802d095c1ebSAndrei Emeltchenko if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) { 1803a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 1804a9de9248SMarcel Holtmann cp.handle = ev->handle; 1805a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 180604124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp), 180704124681SGustavo F. Padovan &cp); 1808a9de9248SMarcel Holtmann } 180917d5c04cSJohan Hedberg } else { 1810a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 181117d5c04cSJohan Hedberg if (conn->type == ACL_LINK) 1812744cf19eSJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 181348264f06SJohan Hedberg conn->dst_type, ev->status); 181417d5c04cSJohan Hedberg } 181545bb4bf0SMarcel Holtmann 1816e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 1817e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 181845bb4bf0SMarcel Holtmann 1819769be974SMarcel Holtmann if (ev->status) { 1820a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1821a9de9248SMarcel Holtmann hci_conn_del(conn); 1822c89b6e6bSMarcel Holtmann } else if (ev->link_type != ACL_LINK) 1823c89b6e6bSMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1824a9de9248SMarcel Holtmann 1825a9de9248SMarcel Holtmann unlock: 18261da177e4SLinus Torvalds hci_dev_unlock(hdev); 1827a9de9248SMarcel Holtmann 1828a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 18291da177e4SLinus Torvalds } 18301da177e4SLinus Torvalds 18311da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 18321da177e4SLinus Torvalds { 1833a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 18341da177e4SLinus Torvalds int mask = hdev->link_mode; 18351da177e4SLinus Torvalds 1836a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s type 0x%x", hdev->name, 18371da177e4SLinus Torvalds batostr(&ev->bdaddr), ev->link_type); 18381da177e4SLinus Torvalds 18391da177e4SLinus Torvalds mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); 18401da177e4SLinus Torvalds 1841138d22efSSzymon Janc if ((mask & HCI_LM_ACCEPT) && 1842138d22efSSzymon Janc !hci_blacklist_lookup(hdev, &ev->bdaddr)) { 18431da177e4SLinus Torvalds /* Connection accepted */ 1844c7bdd502SMarcel Holtmann struct inquiry_entry *ie; 18451da177e4SLinus Torvalds struct hci_conn *conn; 18461da177e4SLinus Torvalds 18471da177e4SLinus Torvalds hci_dev_lock(hdev); 1848b6a0dc82SMarcel Holtmann 1849cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 1850cc11b9c1SAndrei Emeltchenko if (ie) 1851c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 1852c7bdd502SMarcel Holtmann 18531da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 18541da177e4SLinus Torvalds if (!conn) { 1855cc11b9c1SAndrei Emeltchenko conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); 1856cc11b9c1SAndrei Emeltchenko if (!conn) { 1857893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 18581da177e4SLinus Torvalds hci_dev_unlock(hdev); 18591da177e4SLinus Torvalds return; 18601da177e4SLinus Torvalds } 18611da177e4SLinus Torvalds } 1862b6a0dc82SMarcel Holtmann 18631da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 18641da177e4SLinus Torvalds conn->state = BT_CONNECT; 1865b6a0dc82SMarcel Holtmann 18661da177e4SLinus Torvalds hci_dev_unlock(hdev); 18671da177e4SLinus Torvalds 1868b6a0dc82SMarcel Holtmann if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) { 1869b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 1870b6a0dc82SMarcel Holtmann 18711da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 18721da177e4SLinus Torvalds 18731da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 18741da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 18751da177e4SLinus Torvalds else 18761da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 18771da177e4SLinus Torvalds 187804124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), 187904124681SGustavo F. Padovan &cp); 1880b6a0dc82SMarcel Holtmann } else { 1881b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 1882b6a0dc82SMarcel Holtmann 1883b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 1884a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1885b6a0dc82SMarcel Holtmann 1886b6a0dc82SMarcel Holtmann cp.tx_bandwidth = cpu_to_le32(0x00001f40); 1887b6a0dc82SMarcel Holtmann cp.rx_bandwidth = cpu_to_le32(0x00001f40); 1888b6a0dc82SMarcel Holtmann cp.max_latency = cpu_to_le16(0xffff); 1889b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 1890b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 1891b6a0dc82SMarcel Holtmann 1892b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 1893b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1894b6a0dc82SMarcel Holtmann } 18951da177e4SLinus Torvalds } else { 18961da177e4SLinus Torvalds /* Connection rejected */ 18971da177e4SLinus Torvalds struct hci_cp_reject_conn_req cp; 18981da177e4SLinus Torvalds 18991da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 19009f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_REJ_BAD_ADDR; 1901a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 19021da177e4SLinus Torvalds } 19031da177e4SLinus Torvalds } 19041da177e4SLinus Torvalds 19051da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 19061da177e4SLinus Torvalds { 1907a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 190804837f64SMarcel Holtmann struct hci_conn *conn; 19091da177e4SLinus Torvalds 19101da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 19111da177e4SLinus Torvalds 19121da177e4SLinus Torvalds hci_dev_lock(hdev); 19131da177e4SLinus Torvalds 191404837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1915f7520543SJohan Hedberg if (!conn) 1916f7520543SJohan Hedberg goto unlock; 1917f7520543SJohan Hedberg 191837d9ef76SJohan Hedberg if (ev->status == 0) 19191da177e4SLinus Torvalds conn->state = BT_CLOSED; 19207d0db0a3SMarcel Holtmann 1921b644ba33SJohan Hedberg if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) && 1922b644ba33SJohan Hedberg (conn->type == ACL_LINK || conn->type == LE_LINK)) { 192337d9ef76SJohan Hedberg if (ev->status != 0) 192488c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 192588c3df13SJohan Hedberg conn->dst_type, ev->status); 192637d9ef76SJohan Hedberg else 1927afc747a6SJohan Hedberg mgmt_device_disconnected(hdev, &conn->dst, conn->type, 192848264f06SJohan Hedberg conn->dst_type); 192937d9ef76SJohan Hedberg } 1930f7520543SJohan Hedberg 193137d9ef76SJohan Hedberg if (ev->status == 0) { 19326ec5bcadSVishal Agarwal if (conn->type == ACL_LINK && conn->flush_key) 19336ec5bcadSVishal Agarwal hci_remove_link_key(hdev, &conn->dst); 19342950f21aSMarcel Holtmann hci_proto_disconn_cfm(conn, ev->reason); 19351da177e4SLinus Torvalds hci_conn_del(conn); 193637d9ef76SJohan Hedberg } 19371da177e4SLinus Torvalds 1938f7520543SJohan Hedberg unlock: 19391da177e4SLinus Torvalds hci_dev_unlock(hdev); 19401da177e4SLinus Torvalds } 19411da177e4SLinus Torvalds 1942a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1943a9de9248SMarcel Holtmann { 1944a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 1945a9de9248SMarcel Holtmann struct hci_conn *conn; 1946a9de9248SMarcel Holtmann 1947a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1948a9de9248SMarcel Holtmann 1949a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1950a9de9248SMarcel Holtmann 1951a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1952d7556e20SWaldemar Rymarkiewicz if (!conn) 1953d7556e20SWaldemar Rymarkiewicz goto unlock; 1954d7556e20SWaldemar Rymarkiewicz 1955765c2a96SJohan Hedberg if (!ev->status) { 1956aa64a8b5SJohan Hedberg if (!hci_conn_ssp_enabled(conn) && 195751a8efd7SJohan Hedberg test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) { 1958d7556e20SWaldemar Rymarkiewicz BT_INFO("re-auth of legacy device is not possible."); 195919f8def0SWaldemar Rymarkiewicz } else { 1960a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1961765c2a96SJohan Hedberg conn->sec_level = conn->pending_sec_level; 196219f8def0SWaldemar Rymarkiewicz } 19632a611692SJohan Hedberg } else { 1964bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 1965bab73cb6SJohan Hedberg ev->status); 19662a611692SJohan Hedberg } 1967a9de9248SMarcel Holtmann 196851a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 196951a8efd7SJohan Hedberg clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags); 1970a9de9248SMarcel Holtmann 1971f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1972aa64a8b5SJohan Hedberg if (!ev->status && hci_conn_ssp_enabled(conn)) { 1973f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1974f8558555SMarcel Holtmann cp.handle = ev->handle; 1975f8558555SMarcel Holtmann cp.encrypt = 0x01; 1976d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1977d7556e20SWaldemar Rymarkiewicz &cp); 1978f8558555SMarcel Holtmann } else { 1979f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1980f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1981f8558555SMarcel Holtmann hci_conn_put(conn); 1982f8558555SMarcel Holtmann } 1983052b30b0SMarcel Holtmann } else { 1984a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 1985a9de9248SMarcel Holtmann 1986052b30b0SMarcel Holtmann hci_conn_hold(conn); 1987052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1988052b30b0SMarcel Holtmann hci_conn_put(conn); 1989052b30b0SMarcel Holtmann } 1990052b30b0SMarcel Holtmann 199151a8efd7SJohan Hedberg if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) { 1992a9de9248SMarcel Holtmann if (!ev->status) { 1993a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1994f8558555SMarcel Holtmann cp.handle = ev->handle; 1995f8558555SMarcel Holtmann cp.encrypt = 0x01; 1996d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1997d7556e20SWaldemar Rymarkiewicz &cp); 1998a9de9248SMarcel Holtmann } else { 199951a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 2000a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 2001a9de9248SMarcel Holtmann } 2002a9de9248SMarcel Holtmann } 2003a9de9248SMarcel Holtmann 2004d7556e20SWaldemar Rymarkiewicz unlock: 2005a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2006a9de9248SMarcel Holtmann } 2007a9de9248SMarcel Holtmann 2008a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 2009a9de9248SMarcel Holtmann { 2010127178d2SJohan Hedberg struct hci_ev_remote_name *ev = (void *) skb->data; 2011127178d2SJohan Hedberg struct hci_conn *conn; 2012127178d2SJohan Hedberg 2013a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2014a9de9248SMarcel Holtmann 2015a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 2016127178d2SJohan Hedberg 2017127178d2SJohan Hedberg hci_dev_lock(hdev); 2018127178d2SJohan Hedberg 2019127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2020b644ba33SJohan Hedberg 2021b644ba33SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 2022b644ba33SJohan Hedberg goto check_auth; 2023b644ba33SJohan Hedberg 2024b644ba33SJohan Hedberg if (ev->status == 0) 2025b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name, 2026b644ba33SJohan Hedberg strnlen(ev->name, HCI_MAX_NAME_LENGTH)); 2027b644ba33SJohan Hedberg else 2028b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0); 2029b644ba33SJohan Hedberg 2030b644ba33SJohan Hedberg check_auth: 203179c6c70cSJohan Hedberg if (!conn) 203279c6c70cSJohan Hedberg goto unlock; 203379c6c70cSJohan Hedberg 203479c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 203579c6c70cSJohan Hedberg goto unlock; 203679c6c70cSJohan Hedberg 203751a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 2038127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 2039127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 2040127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 2041127178d2SJohan Hedberg } 2042127178d2SJohan Hedberg 204379c6c70cSJohan Hedberg unlock: 2044127178d2SJohan Hedberg hci_dev_unlock(hdev); 2045a9de9248SMarcel Holtmann } 2046a9de9248SMarcel Holtmann 2047a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2048a9de9248SMarcel Holtmann { 2049a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 2050a9de9248SMarcel Holtmann struct hci_conn *conn; 2051a9de9248SMarcel Holtmann 2052a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2053a9de9248SMarcel Holtmann 2054a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2055a9de9248SMarcel Holtmann 2056a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2057a9de9248SMarcel Holtmann if (conn) { 2058a9de9248SMarcel Holtmann if (!ev->status) { 2059ae293196SMarcel Holtmann if (ev->encrypt) { 2060ae293196SMarcel Holtmann /* Encryption implies authentication */ 2061ae293196SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 2062a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 2063da85e5e5SVinicius Costa Gomes conn->sec_level = conn->pending_sec_level; 2064ae293196SMarcel Holtmann } else 2065a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_ENCRYPT; 2066a9de9248SMarcel Holtmann } 2067a9de9248SMarcel Holtmann 206851a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 2069a9de9248SMarcel Holtmann 2070f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 2071f8558555SMarcel Holtmann if (!ev->status) 2072f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 2073f8558555SMarcel Holtmann 2074f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2075f8558555SMarcel Holtmann hci_conn_put(conn); 2076f8558555SMarcel Holtmann } else 2077a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 2078a9de9248SMarcel Holtmann } 2079a9de9248SMarcel Holtmann 2080a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2081a9de9248SMarcel Holtmann } 2082a9de9248SMarcel Holtmann 2083a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2084a9de9248SMarcel Holtmann { 2085a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 2086a9de9248SMarcel Holtmann struct hci_conn *conn; 2087a9de9248SMarcel Holtmann 2088a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2089a9de9248SMarcel Holtmann 2090a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2091a9de9248SMarcel Holtmann 2092a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2093a9de9248SMarcel Holtmann if (conn) { 2094a9de9248SMarcel Holtmann if (!ev->status) 2095a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_SECURE; 2096a9de9248SMarcel Holtmann 209751a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 2098a9de9248SMarcel Holtmann 2099a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 2100a9de9248SMarcel Holtmann } 2101a9de9248SMarcel Holtmann 2102a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2103a9de9248SMarcel Holtmann } 2104a9de9248SMarcel Holtmann 2105a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 2106a9de9248SMarcel Holtmann { 2107a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 2108a9de9248SMarcel Holtmann struct hci_conn *conn; 2109a9de9248SMarcel Holtmann 2110a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2111a9de9248SMarcel Holtmann 2112a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2113a9de9248SMarcel Holtmann 2114a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2115ccd556feSJohan Hedberg if (!conn) 2116ccd556feSJohan Hedberg goto unlock; 2117ccd556feSJohan Hedberg 2118769be974SMarcel Holtmann if (!ev->status) 2119a9de9248SMarcel Holtmann memcpy(conn->features, ev->features, 8); 2120a9de9248SMarcel Holtmann 2121ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2122ccd556feSJohan Hedberg goto unlock; 2123ccd556feSJohan Hedberg 2124ccd556feSJohan Hedberg if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { 2125769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 2126769be974SMarcel Holtmann cp.handle = ev->handle; 2127769be974SMarcel Holtmann cp.page = 0x01; 2128ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 2129769be974SMarcel Holtmann sizeof(cp), &cp); 2130392599b9SJohan Hedberg goto unlock; 2131392599b9SJohan Hedberg } 2132392599b9SJohan Hedberg 2133127178d2SJohan Hedberg if (!ev->status) { 2134127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2135127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2136127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2137127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2138127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2139b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 2140b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 214108c79b61SJohan Hedberg conn->dst_type, 0, NULL, 0, 2142b644ba33SJohan Hedberg conn->dev_class); 2143392599b9SJohan Hedberg 2144127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2145769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2146769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2147769be974SMarcel Holtmann hci_conn_put(conn); 2148769be974SMarcel Holtmann } 2149769be974SMarcel Holtmann 2150ccd556feSJohan Hedberg unlock: 2151a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2152a9de9248SMarcel Holtmann } 2153a9de9248SMarcel Holtmann 2154a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) 2155a9de9248SMarcel Holtmann { 2156a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2157a9de9248SMarcel Holtmann } 2158a9de9248SMarcel Holtmann 2159a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2160a9de9248SMarcel Holtmann { 2161a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2162a9de9248SMarcel Holtmann } 2163a9de9248SMarcel Holtmann 2164a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2165a9de9248SMarcel Holtmann { 2166a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 2167a9de9248SMarcel Holtmann __u16 opcode; 2168a9de9248SMarcel Holtmann 2169a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2170a9de9248SMarcel Holtmann 2171a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2172a9de9248SMarcel Holtmann 2173a9de9248SMarcel Holtmann switch (opcode) { 2174a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 2175a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 2176a9de9248SMarcel Holtmann break; 2177a9de9248SMarcel Holtmann 21784d93483bSAndre Guedes case HCI_OP_PERIODIC_INQ: 21794d93483bSAndre Guedes hci_cc_periodic_inq(hdev, skb); 21804d93483bSAndre Guedes break; 21814d93483bSAndre Guedes 2182a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 2183a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 2184a9de9248SMarcel Holtmann break; 2185a9de9248SMarcel Holtmann 2186a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 2187a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 2188a9de9248SMarcel Holtmann break; 2189a9de9248SMarcel Holtmann 2190a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 2191a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 2192a9de9248SMarcel Holtmann break; 2193a9de9248SMarcel Holtmann 2194e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 2195e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 2196e4e8e37cSMarcel Holtmann break; 2197e4e8e37cSMarcel Holtmann 2198a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 2199a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 2200a9de9248SMarcel Holtmann break; 2201a9de9248SMarcel Holtmann 2202e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 2203e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 2204e4e8e37cSMarcel Holtmann break; 2205e4e8e37cSMarcel Holtmann 2206e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 2207e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 2208e4e8e37cSMarcel Holtmann break; 2209e4e8e37cSMarcel Holtmann 2210a9de9248SMarcel Holtmann case HCI_OP_RESET: 2211a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 2212a9de9248SMarcel Holtmann break; 2213a9de9248SMarcel Holtmann 2214a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 2215a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 2216a9de9248SMarcel Holtmann break; 2217a9de9248SMarcel Holtmann 2218a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 2219a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 2220a9de9248SMarcel Holtmann break; 2221a9de9248SMarcel Holtmann 2222a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 2223a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 2224a9de9248SMarcel Holtmann break; 2225a9de9248SMarcel Holtmann 2226a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 2227a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 2228a9de9248SMarcel Holtmann break; 2229a9de9248SMarcel Holtmann 2230a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 2231a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 2232a9de9248SMarcel Holtmann break; 2233a9de9248SMarcel Holtmann 2234a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 2235a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 2236a9de9248SMarcel Holtmann break; 2237a9de9248SMarcel Holtmann 2238a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 2239a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 2240a9de9248SMarcel Holtmann break; 2241a9de9248SMarcel Holtmann 2242a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 2243a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 2244a9de9248SMarcel Holtmann break; 2245a9de9248SMarcel Holtmann 2246a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 2247a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 2248a9de9248SMarcel Holtmann break; 2249a9de9248SMarcel Holtmann 2250a9de9248SMarcel Holtmann case HCI_OP_HOST_BUFFER_SIZE: 2251a9de9248SMarcel Holtmann hci_cc_host_buffer_size(hdev, skb); 2252a9de9248SMarcel Holtmann break; 2253a9de9248SMarcel Holtmann 2254333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 2255333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 2256333140b5SMarcel Holtmann break; 2257333140b5SMarcel Holtmann 2258a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 2259a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 2260a9de9248SMarcel Holtmann break; 2261a9de9248SMarcel Holtmann 2262a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 2263a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 2264a9de9248SMarcel Holtmann break; 2265a9de9248SMarcel Holtmann 2266a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 2267a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 2268a9de9248SMarcel Holtmann break; 2269a9de9248SMarcel Holtmann 2270971e3a4bSAndre Guedes case HCI_OP_READ_LOCAL_EXT_FEATURES: 2271971e3a4bSAndre Guedes hci_cc_read_local_ext_features(hdev, skb); 2272971e3a4bSAndre Guedes break; 2273971e3a4bSAndre Guedes 2274a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 2275a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 2276a9de9248SMarcel Holtmann break; 2277a9de9248SMarcel Holtmann 2278a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 2279a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 2280a9de9248SMarcel Holtmann break; 2281a9de9248SMarcel Holtmann 2282350ee4cfSAndrei Emeltchenko case HCI_OP_READ_DATA_BLOCK_SIZE: 2283350ee4cfSAndrei Emeltchenko hci_cc_read_data_block_size(hdev, skb); 2284350ee4cfSAndrei Emeltchenko break; 2285350ee4cfSAndrei Emeltchenko 228623bb5763SJohan Hedberg case HCI_OP_WRITE_CA_TIMEOUT: 228723bb5763SJohan Hedberg hci_cc_write_ca_timeout(hdev, skb); 228823bb5763SJohan Hedberg break; 228923bb5763SJohan Hedberg 22901e89cffbSAndrei Emeltchenko case HCI_OP_READ_FLOW_CONTROL_MODE: 22911e89cffbSAndrei Emeltchenko hci_cc_read_flow_control_mode(hdev, skb); 22921e89cffbSAndrei Emeltchenko break; 22931e89cffbSAndrei Emeltchenko 2294928abaa7SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_INFO: 2295928abaa7SAndrei Emeltchenko hci_cc_read_local_amp_info(hdev, skb); 2296928abaa7SAndrei Emeltchenko break; 2297928abaa7SAndrei Emeltchenko 2298b0916ea0SJohan Hedberg case HCI_OP_DELETE_STORED_LINK_KEY: 2299b0916ea0SJohan Hedberg hci_cc_delete_stored_link_key(hdev, skb); 2300b0916ea0SJohan Hedberg break; 2301b0916ea0SJohan Hedberg 2302d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_MASK: 2303d5859e22SJohan Hedberg hci_cc_set_event_mask(hdev, skb); 2304d5859e22SJohan Hedberg break; 2305d5859e22SJohan Hedberg 2306d5859e22SJohan Hedberg case HCI_OP_WRITE_INQUIRY_MODE: 2307d5859e22SJohan Hedberg hci_cc_write_inquiry_mode(hdev, skb); 2308d5859e22SJohan Hedberg break; 2309d5859e22SJohan Hedberg 2310d5859e22SJohan Hedberg case HCI_OP_READ_INQ_RSP_TX_POWER: 2311d5859e22SJohan Hedberg hci_cc_read_inq_rsp_tx_power(hdev, skb); 2312d5859e22SJohan Hedberg break; 2313d5859e22SJohan Hedberg 2314d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_FLT: 2315d5859e22SJohan Hedberg hci_cc_set_event_flt(hdev, skb); 2316d5859e22SJohan Hedberg break; 2317d5859e22SJohan Hedberg 2318980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_REPLY: 2319980e1a53SJohan Hedberg hci_cc_pin_code_reply(hdev, skb); 2320980e1a53SJohan Hedberg break; 2321980e1a53SJohan Hedberg 2322980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_NEG_REPLY: 2323980e1a53SJohan Hedberg hci_cc_pin_code_neg_reply(hdev, skb); 2324980e1a53SJohan Hedberg break; 2325980e1a53SJohan Hedberg 2326c35938b2SSzymon Janc case HCI_OP_READ_LOCAL_OOB_DATA: 2327c35938b2SSzymon Janc hci_cc_read_local_oob_data_reply(hdev, skb); 2328c35938b2SSzymon Janc break; 2329c35938b2SSzymon Janc 23306ed58ec5SVille Tervo case HCI_OP_LE_READ_BUFFER_SIZE: 23316ed58ec5SVille Tervo hci_cc_le_read_buffer_size(hdev, skb); 23326ed58ec5SVille Tervo break; 23336ed58ec5SVille Tervo 2334a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_REPLY: 2335a5c29683SJohan Hedberg hci_cc_user_confirm_reply(hdev, skb); 2336a5c29683SJohan Hedberg break; 2337a5c29683SJohan Hedberg 2338a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_NEG_REPLY: 2339a5c29683SJohan Hedberg hci_cc_user_confirm_neg_reply(hdev, skb); 2340a5c29683SJohan Hedberg break; 2341a5c29683SJohan Hedberg 23421143d458SBrian Gix case HCI_OP_USER_PASSKEY_REPLY: 23431143d458SBrian Gix hci_cc_user_passkey_reply(hdev, skb); 23441143d458SBrian Gix break; 23451143d458SBrian Gix 23461143d458SBrian Gix case HCI_OP_USER_PASSKEY_NEG_REPLY: 23471143d458SBrian Gix hci_cc_user_passkey_neg_reply(hdev, skb); 234816cde993SSzymon Janc break; 234907f7fa5dSAndre Guedes 235007f7fa5dSAndre Guedes case HCI_OP_LE_SET_SCAN_PARAM: 235107f7fa5dSAndre Guedes hci_cc_le_set_scan_param(hdev, skb); 23521143d458SBrian Gix break; 23531143d458SBrian Gix 2354eb9d91f5SAndre Guedes case HCI_OP_LE_SET_SCAN_ENABLE: 2355eb9d91f5SAndre Guedes hci_cc_le_set_scan_enable(hdev, skb); 2356eb9d91f5SAndre Guedes break; 2357eb9d91f5SAndre Guedes 2358a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_REPLY: 2359a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_reply(hdev, skb); 2360a7a595f6SVinicius Costa Gomes break; 2361a7a595f6SVinicius Costa Gomes 2362a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_NEG_REPLY: 2363a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_neg_reply(hdev, skb); 2364a7a595f6SVinicius Costa Gomes break; 2365a7a595f6SVinicius Costa Gomes 2366f9b49306SAndre Guedes case HCI_OP_WRITE_LE_HOST_SUPPORTED: 2367f9b49306SAndre Guedes hci_cc_write_le_host_supported(hdev, skb); 2368f9b49306SAndre Guedes break; 2369f9b49306SAndre Guedes 2370a9de9248SMarcel Holtmann default: 2371a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 2372a9de9248SMarcel Holtmann break; 2373a9de9248SMarcel Holtmann } 2374a9de9248SMarcel Holtmann 23756bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 23766bd32326SVille Tervo del_timer(&hdev->cmd_timer); 23776bd32326SVille Tervo 2378a9de9248SMarcel Holtmann if (ev->ncmd) { 2379a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2380a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2381c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2382a9de9248SMarcel Holtmann } 2383a9de9248SMarcel Holtmann } 2384a9de9248SMarcel Holtmann 2385a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 2386a9de9248SMarcel Holtmann { 2387a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 2388a9de9248SMarcel Holtmann __u16 opcode; 2389a9de9248SMarcel Holtmann 2390a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2391a9de9248SMarcel Holtmann 2392a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2393a9de9248SMarcel Holtmann 2394a9de9248SMarcel Holtmann switch (opcode) { 2395a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 2396a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 2397a9de9248SMarcel Holtmann break; 2398a9de9248SMarcel Holtmann 2399a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 2400a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 2401a9de9248SMarcel Holtmann break; 2402a9de9248SMarcel Holtmann 2403a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 2404a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 2405a9de9248SMarcel Holtmann break; 2406a9de9248SMarcel Holtmann 2407f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 2408f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 2409f8558555SMarcel Holtmann break; 2410f8558555SMarcel Holtmann 2411f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 2412f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 2413f8558555SMarcel Holtmann break; 2414f8558555SMarcel Holtmann 2415a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 2416a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 2417a9de9248SMarcel Holtmann break; 2418a9de9248SMarcel Holtmann 2419769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 2420769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 2421769be974SMarcel Holtmann break; 2422769be974SMarcel Holtmann 2423769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 2424769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 2425769be974SMarcel Holtmann break; 2426769be974SMarcel Holtmann 2427a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 2428a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 2429a9de9248SMarcel Holtmann break; 2430a9de9248SMarcel Holtmann 2431a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 2432a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 2433a9de9248SMarcel Holtmann break; 2434a9de9248SMarcel Holtmann 2435a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 2436a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 2437a9de9248SMarcel Holtmann break; 2438a9de9248SMarcel Holtmann 24398962ee74SJohan Hedberg case HCI_OP_DISCONNECT: 244088c3df13SJohan Hedberg hci_cs_disconnect(hdev, ev->status); 24418962ee74SJohan Hedberg break; 24428962ee74SJohan Hedberg 2443fcd89c09SVille Tervo case HCI_OP_LE_CREATE_CONN: 2444fcd89c09SVille Tervo hci_cs_le_create_conn(hdev, ev->status); 2445fcd89c09SVille Tervo break; 2446fcd89c09SVille Tervo 2447a7a595f6SVinicius Costa Gomes case HCI_OP_LE_START_ENC: 2448a7a595f6SVinicius Costa Gomes hci_cs_le_start_enc(hdev, ev->status); 2449a7a595f6SVinicius Costa Gomes break; 2450a7a595f6SVinicius Costa Gomes 2451a9de9248SMarcel Holtmann default: 2452a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 2453a9de9248SMarcel Holtmann break; 2454a9de9248SMarcel Holtmann } 2455a9de9248SMarcel Holtmann 24566bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 24576bd32326SVille Tervo del_timer(&hdev->cmd_timer); 24586bd32326SVille Tervo 245910572132SGustavo F. Padovan if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2460a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2461a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2462c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2463a9de9248SMarcel Holtmann } 2464a9de9248SMarcel Holtmann } 2465a9de9248SMarcel Holtmann 2466a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2467a9de9248SMarcel Holtmann { 2468a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 2469a9de9248SMarcel Holtmann struct hci_conn *conn; 2470a9de9248SMarcel Holtmann 2471a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2472a9de9248SMarcel Holtmann 2473a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2474a9de9248SMarcel Holtmann 2475a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2476a9de9248SMarcel Holtmann if (conn) { 2477a9de9248SMarcel Holtmann if (!ev->status) { 2478a9de9248SMarcel Holtmann if (ev->role) 2479a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_MASTER; 2480a9de9248SMarcel Holtmann else 2481a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_MASTER; 2482a9de9248SMarcel Holtmann } 2483a9de9248SMarcel Holtmann 248451a8efd7SJohan Hedberg clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); 2485a9de9248SMarcel Holtmann 2486a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 2487a9de9248SMarcel Holtmann } 2488a9de9248SMarcel Holtmann 2489a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2490a9de9248SMarcel Holtmann } 2491a9de9248SMarcel Holtmann 24921da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 24931da177e4SLinus Torvalds { 2494a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 24951da177e4SLinus Torvalds int i; 24961da177e4SLinus Torvalds 249732ac5b9bSAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) { 249832ac5b9bSAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 249932ac5b9bSAndrei Emeltchenko return; 250032ac5b9bSAndrei Emeltchenko } 250132ac5b9bSAndrei Emeltchenko 2502c5993de8SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 2503c5993de8SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_pkts_info)) { 25041da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 25051da177e4SLinus Torvalds return; 25061da177e4SLinus Torvalds } 25071da177e4SLinus Torvalds 2508c5993de8SAndrei Emeltchenko BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 2509c5993de8SAndrei Emeltchenko 2510613a1c0cSAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 2511613a1c0cSAndrei Emeltchenko struct hci_comp_pkts_info *info = &ev->handles[i]; 25121da177e4SLinus Torvalds struct hci_conn *conn; 25131da177e4SLinus Torvalds __u16 handle, count; 25141da177e4SLinus Torvalds 2515613a1c0cSAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 2516613a1c0cSAndrei Emeltchenko count = __le16_to_cpu(info->count); 25171da177e4SLinus Torvalds 25181da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 2519f4280918SAndrei Emeltchenko if (!conn) 2520f4280918SAndrei Emeltchenko continue; 2521f4280918SAndrei Emeltchenko 25221da177e4SLinus Torvalds conn->sent -= count; 25231da177e4SLinus Torvalds 2524f4280918SAndrei Emeltchenko switch (conn->type) { 2525f4280918SAndrei Emeltchenko case ACL_LINK: 252670f23020SAndrei Emeltchenko hdev->acl_cnt += count; 252770f23020SAndrei Emeltchenko if (hdev->acl_cnt > hdev->acl_pkts) 25281da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 2529f4280918SAndrei Emeltchenko break; 2530f4280918SAndrei Emeltchenko 2531f4280918SAndrei Emeltchenko case LE_LINK: 25326ed58ec5SVille Tervo if (hdev->le_pkts) { 25336ed58ec5SVille Tervo hdev->le_cnt += count; 25346ed58ec5SVille Tervo if (hdev->le_cnt > hdev->le_pkts) 25356ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 25366ed58ec5SVille Tervo } else { 25376ed58ec5SVille Tervo hdev->acl_cnt += count; 25386ed58ec5SVille Tervo if (hdev->acl_cnt > hdev->acl_pkts) 25396ed58ec5SVille Tervo hdev->acl_cnt = hdev->acl_pkts; 25406ed58ec5SVille Tervo } 2541f4280918SAndrei Emeltchenko break; 2542f4280918SAndrei Emeltchenko 2543f4280918SAndrei Emeltchenko case SCO_LINK: 254470f23020SAndrei Emeltchenko hdev->sco_cnt += count; 254570f23020SAndrei Emeltchenko if (hdev->sco_cnt > hdev->sco_pkts) 25465b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 2547f4280918SAndrei Emeltchenko break; 2548f4280918SAndrei Emeltchenko 2549f4280918SAndrei Emeltchenko default: 2550f4280918SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 2551f4280918SAndrei Emeltchenko break; 25521da177e4SLinus Torvalds } 25531da177e4SLinus Torvalds } 2554a9de9248SMarcel Holtmann 25553eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 25561da177e4SLinus Torvalds } 25571da177e4SLinus Torvalds 255825e89e99SAndrei Emeltchenko static inline void hci_num_comp_blocks_evt(struct hci_dev *hdev, 255925e89e99SAndrei Emeltchenko struct sk_buff *skb) 256025e89e99SAndrei Emeltchenko { 256125e89e99SAndrei Emeltchenko struct hci_ev_num_comp_blocks *ev = (void *) skb->data; 256225e89e99SAndrei Emeltchenko int i; 256325e89e99SAndrei Emeltchenko 256425e89e99SAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) { 256525e89e99SAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 256625e89e99SAndrei Emeltchenko return; 256725e89e99SAndrei Emeltchenko } 256825e89e99SAndrei Emeltchenko 256925e89e99SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 257025e89e99SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_blocks_info)) { 257125e89e99SAndrei Emeltchenko BT_DBG("%s bad parameters", hdev->name); 257225e89e99SAndrei Emeltchenko return; 257325e89e99SAndrei Emeltchenko } 257425e89e99SAndrei Emeltchenko 257525e89e99SAndrei Emeltchenko BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks, 257625e89e99SAndrei Emeltchenko ev->num_hndl); 257725e89e99SAndrei Emeltchenko 257825e89e99SAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 257925e89e99SAndrei Emeltchenko struct hci_comp_blocks_info *info = &ev->handles[i]; 258025e89e99SAndrei Emeltchenko struct hci_conn *conn; 258125e89e99SAndrei Emeltchenko __u16 handle, block_count; 258225e89e99SAndrei Emeltchenko 258325e89e99SAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 258425e89e99SAndrei Emeltchenko block_count = __le16_to_cpu(info->blocks); 258525e89e99SAndrei Emeltchenko 258625e89e99SAndrei Emeltchenko conn = hci_conn_hash_lookup_handle(hdev, handle); 258725e89e99SAndrei Emeltchenko if (!conn) 258825e89e99SAndrei Emeltchenko continue; 258925e89e99SAndrei Emeltchenko 259025e89e99SAndrei Emeltchenko conn->sent -= block_count; 259125e89e99SAndrei Emeltchenko 259225e89e99SAndrei Emeltchenko switch (conn->type) { 259325e89e99SAndrei Emeltchenko case ACL_LINK: 259425e89e99SAndrei Emeltchenko hdev->block_cnt += block_count; 259525e89e99SAndrei Emeltchenko if (hdev->block_cnt > hdev->num_blocks) 259625e89e99SAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 259725e89e99SAndrei Emeltchenko break; 259825e89e99SAndrei Emeltchenko 259925e89e99SAndrei Emeltchenko default: 260025e89e99SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 260125e89e99SAndrei Emeltchenko break; 260225e89e99SAndrei Emeltchenko } 260325e89e99SAndrei Emeltchenko } 260425e89e99SAndrei Emeltchenko 260525e89e99SAndrei Emeltchenko queue_work(hdev->workqueue, &hdev->tx_work); 260625e89e99SAndrei Emeltchenko } 260725e89e99SAndrei Emeltchenko 260804837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 26091da177e4SLinus Torvalds { 2610a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 261104837f64SMarcel Holtmann struct hci_conn *conn; 26121da177e4SLinus Torvalds 26131da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 26141da177e4SLinus Torvalds 26151da177e4SLinus Torvalds hci_dev_lock(hdev); 26161da177e4SLinus Torvalds 261704837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 261804837f64SMarcel Holtmann if (conn) { 261904837f64SMarcel Holtmann conn->mode = ev->mode; 262004837f64SMarcel Holtmann conn->interval = __le16_to_cpu(ev->interval); 262104837f64SMarcel Holtmann 262251a8efd7SJohan Hedberg if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) { 262304837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 262458a681efSJohan Hedberg set_bit(HCI_CONN_POWER_SAVE, &conn->flags); 262504837f64SMarcel Holtmann else 262658a681efSJohan Hedberg clear_bit(HCI_CONN_POWER_SAVE, &conn->flags); 262704837f64SMarcel Holtmann } 2628e73439d8SMarcel Holtmann 262951a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 2630e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 263104837f64SMarcel Holtmann } 263204837f64SMarcel Holtmann 263304837f64SMarcel Holtmann hci_dev_unlock(hdev); 263404837f64SMarcel Holtmann } 263504837f64SMarcel Holtmann 26361da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 26371da177e4SLinus Torvalds { 2638052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 2639052b30b0SMarcel Holtmann struct hci_conn *conn; 2640052b30b0SMarcel Holtmann 2641a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2642052b30b0SMarcel Holtmann 2643052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2644052b30b0SMarcel Holtmann 2645052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2646b6f98044SWaldemar Rymarkiewicz if (!conn) 2647b6f98044SWaldemar Rymarkiewicz goto unlock; 2648b6f98044SWaldemar Rymarkiewicz 2649b6f98044SWaldemar Rymarkiewicz if (conn->state == BT_CONNECTED) { 2650052b30b0SMarcel Holtmann hci_conn_hold(conn); 2651052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 2652052b30b0SMarcel Holtmann hci_conn_put(conn); 2653052b30b0SMarcel Holtmann } 2654052b30b0SMarcel Holtmann 2655a8b2d5c2SJohan Hedberg if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags)) 265603b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 265703b555e1SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 2658a8b2d5c2SJohan Hedberg else if (test_bit(HCI_MGMT, &hdev->dev_flags)) { 2659a770bb5aSWaldemar Rymarkiewicz u8 secure; 2660a770bb5aSWaldemar Rymarkiewicz 2661a770bb5aSWaldemar Rymarkiewicz if (conn->pending_sec_level == BT_SECURITY_HIGH) 2662a770bb5aSWaldemar Rymarkiewicz secure = 1; 2663a770bb5aSWaldemar Rymarkiewicz else 2664a770bb5aSWaldemar Rymarkiewicz secure = 0; 2665a770bb5aSWaldemar Rymarkiewicz 2666744cf19eSJohan Hedberg mgmt_pin_code_request(hdev, &ev->bdaddr, secure); 2667a770bb5aSWaldemar Rymarkiewicz } 2668980e1a53SJohan Hedberg 2669b6f98044SWaldemar Rymarkiewicz unlock: 2670052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 26711da177e4SLinus Torvalds } 26721da177e4SLinus Torvalds 26731da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 26741da177e4SLinus Torvalds { 267555ed8ca1SJohan Hedberg struct hci_ev_link_key_req *ev = (void *) skb->data; 267655ed8ca1SJohan Hedberg struct hci_cp_link_key_reply cp; 267755ed8ca1SJohan Hedberg struct hci_conn *conn; 267855ed8ca1SJohan Hedberg struct link_key *key; 267955ed8ca1SJohan Hedberg 2680a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 268155ed8ca1SJohan Hedberg 2682a8b2d5c2SJohan Hedberg if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) 268355ed8ca1SJohan Hedberg return; 268455ed8ca1SJohan Hedberg 268555ed8ca1SJohan Hedberg hci_dev_lock(hdev); 268655ed8ca1SJohan Hedberg 268755ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, &ev->bdaddr); 268855ed8ca1SJohan Hedberg if (!key) { 268955ed8ca1SJohan Hedberg BT_DBG("%s link key not found for %s", hdev->name, 269055ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 269155ed8ca1SJohan Hedberg goto not_found; 269255ed8ca1SJohan Hedberg } 269355ed8ca1SJohan Hedberg 269455ed8ca1SJohan Hedberg BT_DBG("%s found key type %u for %s", hdev->name, key->type, 269555ed8ca1SJohan Hedberg batostr(&ev->bdaddr)); 269655ed8ca1SJohan Hedberg 2697a8b2d5c2SJohan Hedberg if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) && 2698b6020ba0SWaldemar Rymarkiewicz key->type == HCI_LK_DEBUG_COMBINATION) { 269955ed8ca1SJohan Hedberg BT_DBG("%s ignoring debug key", hdev->name); 270055ed8ca1SJohan Hedberg goto not_found; 270155ed8ca1SJohan Hedberg } 270255ed8ca1SJohan Hedberg 270355ed8ca1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 270460b83f57SWaldemar Rymarkiewicz if (conn) { 270560b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_UNAUTH_COMBINATION && 270660b83f57SWaldemar Rymarkiewicz conn->auth_type != 0xff && 270760b83f57SWaldemar Rymarkiewicz (conn->auth_type & 0x01)) { 270855ed8ca1SJohan Hedberg BT_DBG("%s ignoring unauthenticated key", hdev->name); 270955ed8ca1SJohan Hedberg goto not_found; 271055ed8ca1SJohan Hedberg } 271155ed8ca1SJohan Hedberg 271260b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && 271360b83f57SWaldemar Rymarkiewicz conn->pending_sec_level == BT_SECURITY_HIGH) { 271460b83f57SWaldemar Rymarkiewicz BT_DBG("%s ignoring key unauthenticated for high \ 271560b83f57SWaldemar Rymarkiewicz security", hdev->name); 271660b83f57SWaldemar Rymarkiewicz goto not_found; 271760b83f57SWaldemar Rymarkiewicz } 271860b83f57SWaldemar Rymarkiewicz 271960b83f57SWaldemar Rymarkiewicz conn->key_type = key->type; 272060b83f57SWaldemar Rymarkiewicz conn->pin_length = key->pin_len; 272160b83f57SWaldemar Rymarkiewicz } 272260b83f57SWaldemar Rymarkiewicz 272355ed8ca1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 272455ed8ca1SJohan Hedberg memcpy(cp.link_key, key->val, 16); 272555ed8ca1SJohan Hedberg 272655ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 272755ed8ca1SJohan Hedberg 272855ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 272955ed8ca1SJohan Hedberg 273055ed8ca1SJohan Hedberg return; 273155ed8ca1SJohan Hedberg 273255ed8ca1SJohan Hedberg not_found: 273355ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 273455ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 27351da177e4SLinus Torvalds } 27361da177e4SLinus Torvalds 27371da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 27381da177e4SLinus Torvalds { 2739052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 2740052b30b0SMarcel Holtmann struct hci_conn *conn; 274155ed8ca1SJohan Hedberg u8 pin_len = 0; 2742052b30b0SMarcel Holtmann 2743a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2744052b30b0SMarcel Holtmann 2745052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2746052b30b0SMarcel Holtmann 2747052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2748052b30b0SMarcel Holtmann if (conn) { 2749052b30b0SMarcel Holtmann hci_conn_hold(conn); 2750052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2751980e1a53SJohan Hedberg pin_len = conn->pin_length; 275213d39315SWaldemar Rymarkiewicz 275313d39315SWaldemar Rymarkiewicz if (ev->key_type != HCI_LK_CHANGED_COMBINATION) 275413d39315SWaldemar Rymarkiewicz conn->key_type = ev->key_type; 275513d39315SWaldemar Rymarkiewicz 2756052b30b0SMarcel Holtmann hci_conn_put(conn); 2757052b30b0SMarcel Holtmann } 2758052b30b0SMarcel Holtmann 2759a8b2d5c2SJohan Hedberg if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) 2760d25e28abSJohan Hedberg hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, 276155ed8ca1SJohan Hedberg ev->key_type, pin_len); 276255ed8ca1SJohan Hedberg 2763052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 27641da177e4SLinus Torvalds } 27651da177e4SLinus Torvalds 276604837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 276704837f64SMarcel Holtmann { 2768a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 276904837f64SMarcel Holtmann struct hci_conn *conn; 277004837f64SMarcel Holtmann 277104837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 277204837f64SMarcel Holtmann 277304837f64SMarcel Holtmann hci_dev_lock(hdev); 277404837f64SMarcel Holtmann 277504837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 27761da177e4SLinus Torvalds if (conn && !ev->status) { 27771da177e4SLinus Torvalds struct inquiry_entry *ie; 27781da177e4SLinus Torvalds 2779cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2780cc11b9c1SAndrei Emeltchenko if (ie) { 27811da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 27821da177e4SLinus Torvalds ie->timestamp = jiffies; 27831da177e4SLinus Torvalds } 27841da177e4SLinus Torvalds } 27851da177e4SLinus Torvalds 27861da177e4SLinus Torvalds hci_dev_unlock(hdev); 27871da177e4SLinus Torvalds } 27881da177e4SLinus Torvalds 2789a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2790a8746417SMarcel Holtmann { 2791a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 2792a8746417SMarcel Holtmann struct hci_conn *conn; 2793a8746417SMarcel Holtmann 2794a8746417SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2795a8746417SMarcel Holtmann 2796a8746417SMarcel Holtmann hci_dev_lock(hdev); 2797a8746417SMarcel Holtmann 2798a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2799a8746417SMarcel Holtmann if (conn && !ev->status) 2800a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 2801a8746417SMarcel Holtmann 2802a8746417SMarcel Holtmann hci_dev_unlock(hdev); 2803a8746417SMarcel Holtmann } 2804a8746417SMarcel Holtmann 280585a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 280685a1e930SMarcel Holtmann { 2807a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 280885a1e930SMarcel Holtmann struct inquiry_entry *ie; 280985a1e930SMarcel Holtmann 281085a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 281185a1e930SMarcel Holtmann 281285a1e930SMarcel Holtmann hci_dev_lock(hdev); 281385a1e930SMarcel Holtmann 2814cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2815cc11b9c1SAndrei Emeltchenko if (ie) { 281685a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 281785a1e930SMarcel Holtmann ie->timestamp = jiffies; 281885a1e930SMarcel Holtmann } 281985a1e930SMarcel Holtmann 282085a1e930SMarcel Holtmann hci_dev_unlock(hdev); 282185a1e930SMarcel Holtmann } 282285a1e930SMarcel Holtmann 2823a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb) 2824a9de9248SMarcel Holtmann { 2825a9de9248SMarcel Holtmann struct inquiry_data data; 2826a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2827388fc8faSJohan Hedberg bool name_known, ssp; 2828a9de9248SMarcel Holtmann 2829a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2830a9de9248SMarcel Holtmann 2831a9de9248SMarcel Holtmann if (!num_rsp) 2832a9de9248SMarcel Holtmann return; 2833a9de9248SMarcel Holtmann 28341519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 28351519cc17SAndre Guedes return; 28361519cc17SAndre Guedes 2837a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2838a9de9248SMarcel Holtmann 2839a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 2840138d22efSSzymon Janc struct inquiry_info_with_rssi_and_pscan_mode *info; 2841138d22efSSzymon Janc info = (void *) (skb->data + 1); 2842a9de9248SMarcel Holtmann 2843e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2844a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2845a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2846a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2847a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 2848a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2849a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2850a9de9248SMarcel Holtmann data.rssi = info->rssi; 285141a96212SMarcel Holtmann data.ssp_mode = 0x00; 28523175405bSJohan Hedberg 28533175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 2854388fc8faSJohan Hedberg false, &ssp); 285548264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2856e17acd40SJohan Hedberg info->dev_class, info->rssi, 2857388fc8faSJohan Hedberg !name_known, ssp, NULL, 0); 2858a9de9248SMarcel Holtmann } 2859a9de9248SMarcel Holtmann } else { 2860a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 2861a9de9248SMarcel Holtmann 2862e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2863a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2864a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2865a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2866a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2867a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2868a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2869a9de9248SMarcel Holtmann data.rssi = info->rssi; 287041a96212SMarcel Holtmann data.ssp_mode = 0x00; 28713175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 2872388fc8faSJohan Hedberg false, &ssp); 287348264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2874e17acd40SJohan Hedberg info->dev_class, info->rssi, 2875388fc8faSJohan Hedberg !name_known, ssp, NULL, 0); 2876a9de9248SMarcel Holtmann } 2877a9de9248SMarcel Holtmann } 2878a9de9248SMarcel Holtmann 2879a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2880a9de9248SMarcel Holtmann } 2881a9de9248SMarcel Holtmann 2882a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 2883a9de9248SMarcel Holtmann { 288441a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 288541a96212SMarcel Holtmann struct hci_conn *conn; 288641a96212SMarcel Holtmann 2887a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 288841a96212SMarcel Holtmann 288941a96212SMarcel Holtmann hci_dev_lock(hdev); 289041a96212SMarcel Holtmann 289141a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2892ccd556feSJohan Hedberg if (!conn) 2893ccd556feSJohan Hedberg goto unlock; 2894ccd556feSJohan Hedberg 2895769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 289641a96212SMarcel Holtmann struct inquiry_entry *ie; 289741a96212SMarcel Holtmann 2898cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2899cc11b9c1SAndrei Emeltchenko if (ie) 290002b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 290141a96212SMarcel Holtmann 290202b7cc62SJohan Hedberg if (ev->features[0] & LMP_HOST_SSP) 290358a681efSJohan Hedberg set_bit(HCI_CONN_SSP_ENABLED, &conn->flags); 290441a96212SMarcel Holtmann } 290541a96212SMarcel Holtmann 2906ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2907ccd556feSJohan Hedberg goto unlock; 2908ccd556feSJohan Hedberg 2909127178d2SJohan Hedberg if (!ev->status) { 2910127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2911127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2912127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2913127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2914127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2915b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 2916b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 291708c79b61SJohan Hedberg conn->dst_type, 0, NULL, 0, 2918b644ba33SJohan Hedberg conn->dev_class); 2919392599b9SJohan Hedberg 2920127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2921769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2922769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2923769be974SMarcel Holtmann hci_conn_put(conn); 2924769be974SMarcel Holtmann } 2925769be974SMarcel Holtmann 2926ccd556feSJohan Hedberg unlock: 292741a96212SMarcel Holtmann hci_dev_unlock(hdev); 2928a9de9248SMarcel Holtmann } 2929a9de9248SMarcel Holtmann 2930a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2931a9de9248SMarcel Holtmann { 2932b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 2933b6a0dc82SMarcel Holtmann struct hci_conn *conn; 2934b6a0dc82SMarcel Holtmann 2935b6a0dc82SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 2936b6a0dc82SMarcel Holtmann 2937b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 2938b6a0dc82SMarcel Holtmann 2939b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 29409dc0a3afSMarcel Holtmann if (!conn) { 29419dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 29429dc0a3afSMarcel Holtmann goto unlock; 29439dc0a3afSMarcel Holtmann 29449dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 2945b6a0dc82SMarcel Holtmann if (!conn) 2946b6a0dc82SMarcel Holtmann goto unlock; 2947b6a0dc82SMarcel Holtmann 29489dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 29499dc0a3afSMarcel Holtmann } 29509dc0a3afSMarcel Holtmann 2951732547f9SMarcel Holtmann switch (ev->status) { 2952732547f9SMarcel Holtmann case 0x00: 2953732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 2954732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 2955732547f9SMarcel Holtmann 29569eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 2957732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 2958732547f9SMarcel Holtmann break; 2959732547f9SMarcel Holtmann 2960705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 2961732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 29621038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 2963732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 2964732547f9SMarcel Holtmann if (conn->out && conn->attempt < 2) { 2965efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 2966efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 2967efc7688bSMarcel Holtmann hci_setup_sync(conn, conn->link->handle); 2968efc7688bSMarcel Holtmann goto unlock; 2969efc7688bSMarcel Holtmann } 2970732547f9SMarcel Holtmann /* fall through */ 2971efc7688bSMarcel Holtmann 2972732547f9SMarcel Holtmann default: 2973b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 2974732547f9SMarcel Holtmann break; 2975732547f9SMarcel Holtmann } 2976b6a0dc82SMarcel Holtmann 2977b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2978b6a0dc82SMarcel Holtmann if (ev->status) 2979b6a0dc82SMarcel Holtmann hci_conn_del(conn); 2980b6a0dc82SMarcel Holtmann 2981b6a0dc82SMarcel Holtmann unlock: 2982b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 2983a9de9248SMarcel Holtmann } 2984a9de9248SMarcel Holtmann 2985a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) 2986a9de9248SMarcel Holtmann { 2987a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2988a9de9248SMarcel Holtmann } 2989a9de9248SMarcel Holtmann 299004837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) 299104837f64SMarcel Holtmann { 2992a9de9248SMarcel Holtmann struct hci_ev_sniff_subrate *ev = (void *) skb->data; 299304837f64SMarcel Holtmann 299404837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 299504837f64SMarcel Holtmann } 299604837f64SMarcel Holtmann 2997a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 2998a9de9248SMarcel Holtmann { 2999a9de9248SMarcel Holtmann struct inquiry_data data; 3000a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 3001a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 3002a9de9248SMarcel Holtmann 3003a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 3004a9de9248SMarcel Holtmann 3005a9de9248SMarcel Holtmann if (!num_rsp) 3006a9de9248SMarcel Holtmann return; 3007a9de9248SMarcel Holtmann 30081519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 30091519cc17SAndre Guedes return; 30101519cc17SAndre Guedes 3011a9de9248SMarcel Holtmann hci_dev_lock(hdev); 3012a9de9248SMarcel Holtmann 3013e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 3014388fc8faSJohan Hedberg bool name_known, ssp; 3015561aafbcSJohan Hedberg 3016a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 3017a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 3018a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 3019a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 3020a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 3021a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 3022a9de9248SMarcel Holtmann data.rssi = info->rssi; 302341a96212SMarcel Holtmann data.ssp_mode = 0x01; 3024561aafbcSJohan Hedberg 3025a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 30264ddb1930SJohan Hedberg name_known = eir_has_data_type(info->data, 30274ddb1930SJohan Hedberg sizeof(info->data), 30284ddb1930SJohan Hedberg EIR_NAME_COMPLETE); 3029561aafbcSJohan Hedberg else 3030561aafbcSJohan Hedberg name_known = true; 3031561aafbcSJohan Hedberg 3032388fc8faSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, name_known, 3033388fc8faSJohan Hedberg &ssp); 303448264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 303504124681SGustavo F. Padovan info->dev_class, info->rssi, !name_known, 303604124681SGustavo F. Padovan ssp, info->data, sizeof(info->data)); 3037a9de9248SMarcel Holtmann } 3038a9de9248SMarcel Holtmann 3039a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 3040a9de9248SMarcel Holtmann } 3041a9de9248SMarcel Holtmann 304217fa4b9dSJohan Hedberg static inline u8 hci_get_auth_req(struct hci_conn *conn) 304317fa4b9dSJohan Hedberg { 304417fa4b9dSJohan Hedberg /* If remote requests dedicated bonding follow that lead */ 304517fa4b9dSJohan Hedberg if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) { 304617fa4b9dSJohan Hedberg /* If both remote and local IO capabilities allow MITM 304717fa4b9dSJohan Hedberg * protection then require it, otherwise don't */ 304817fa4b9dSJohan Hedberg if (conn->remote_cap == 0x03 || conn->io_capability == 0x03) 304917fa4b9dSJohan Hedberg return 0x02; 305017fa4b9dSJohan Hedberg else 305117fa4b9dSJohan Hedberg return 0x03; 305217fa4b9dSJohan Hedberg } 305317fa4b9dSJohan Hedberg 305417fa4b9dSJohan Hedberg /* If remote requests no-bonding follow that lead */ 305517fa4b9dSJohan Hedberg if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01) 305658797bf7SWaldemar Rymarkiewicz return conn->remote_auth | (conn->auth_type & 0x01); 305717fa4b9dSJohan Hedberg 305817fa4b9dSJohan Hedberg return conn->auth_type; 305917fa4b9dSJohan Hedberg } 306017fa4b9dSJohan Hedberg 30610493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 30620493684eSMarcel Holtmann { 30630493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 30640493684eSMarcel Holtmann struct hci_conn *conn; 30650493684eSMarcel Holtmann 30660493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 30670493684eSMarcel Holtmann 30680493684eSMarcel Holtmann hci_dev_lock(hdev); 30690493684eSMarcel Holtmann 30700493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 307103b555e1SJohan Hedberg if (!conn) 307203b555e1SJohan Hedberg goto unlock; 307303b555e1SJohan Hedberg 30740493684eSMarcel Holtmann hci_conn_hold(conn); 30750493684eSMarcel Holtmann 3076a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 307703b555e1SJohan Hedberg goto unlock; 307803b555e1SJohan Hedberg 3079a8b2d5c2SJohan Hedberg if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) || 308003b555e1SJohan Hedberg (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 308117fa4b9dSJohan Hedberg struct hci_cp_io_capability_reply cp; 308217fa4b9dSJohan Hedberg 308317fa4b9dSJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 30847a7f1e7cSHemant Gupta /* Change the IO capability from KeyboardDisplay 30857a7f1e7cSHemant Gupta * to DisplayYesNo as it is not supported by BT spec. */ 30867a7f1e7cSHemant Gupta cp.capability = (conn->io_capability == 0x04) ? 30877a7f1e7cSHemant Gupta 0x01 : conn->io_capability; 30887cbc9bd9SJohan Hedberg conn->auth_type = hci_get_auth_req(conn); 30897cbc9bd9SJohan Hedberg cp.authentication = conn->auth_type; 309017fa4b9dSJohan Hedberg 309158a681efSJohan Hedberg if ((conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)) && 3092ce85ee13SSzymon Janc hci_find_remote_oob_data(hdev, &conn->dst)) 3093ce85ee13SSzymon Janc cp.oob_data = 0x01; 3094ce85ee13SSzymon Janc else 3095ce85ee13SSzymon Janc cp.oob_data = 0x00; 3096ce85ee13SSzymon Janc 309717fa4b9dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, 309817fa4b9dSJohan Hedberg sizeof(cp), &cp); 309903b555e1SJohan Hedberg } else { 310003b555e1SJohan Hedberg struct hci_cp_io_capability_neg_reply cp; 310103b555e1SJohan Hedberg 310203b555e1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 31039f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED; 310403b555e1SJohan Hedberg 310503b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 310603b555e1SJohan Hedberg sizeof(cp), &cp); 310703b555e1SJohan Hedberg } 310803b555e1SJohan Hedberg 310903b555e1SJohan Hedberg unlock: 311003b555e1SJohan Hedberg hci_dev_unlock(hdev); 311103b555e1SJohan Hedberg } 311203b555e1SJohan Hedberg 311303b555e1SJohan Hedberg static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 311403b555e1SJohan Hedberg { 311503b555e1SJohan Hedberg struct hci_ev_io_capa_reply *ev = (void *) skb->data; 311603b555e1SJohan Hedberg struct hci_conn *conn; 311703b555e1SJohan Hedberg 311803b555e1SJohan Hedberg BT_DBG("%s", hdev->name); 311903b555e1SJohan Hedberg 312003b555e1SJohan Hedberg hci_dev_lock(hdev); 312103b555e1SJohan Hedberg 312203b555e1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 312303b555e1SJohan Hedberg if (!conn) 312403b555e1SJohan Hedberg goto unlock; 312503b555e1SJohan Hedberg 312603b555e1SJohan Hedberg conn->remote_cap = ev->capability; 312703b555e1SJohan Hedberg conn->remote_auth = ev->authentication; 312858a681efSJohan Hedberg if (ev->oob_data) 312958a681efSJohan Hedberg set_bit(HCI_CONN_REMOTE_OOB, &conn->flags); 313003b555e1SJohan Hedberg 313103b555e1SJohan Hedberg unlock: 31320493684eSMarcel Holtmann hci_dev_unlock(hdev); 31330493684eSMarcel Holtmann } 31340493684eSMarcel Holtmann 3135a5c29683SJohan Hedberg static inline void hci_user_confirm_request_evt(struct hci_dev *hdev, 3136a5c29683SJohan Hedberg struct sk_buff *skb) 3137a5c29683SJohan Hedberg { 3138a5c29683SJohan Hedberg struct hci_ev_user_confirm_req *ev = (void *) skb->data; 313955bc1a37SJohan Hedberg int loc_mitm, rem_mitm, confirm_hint = 0; 31407a828908SJohan Hedberg struct hci_conn *conn; 3141a5c29683SJohan Hedberg 3142a5c29683SJohan Hedberg BT_DBG("%s", hdev->name); 3143a5c29683SJohan Hedberg 3144a5c29683SJohan Hedberg hci_dev_lock(hdev); 3145a5c29683SJohan Hedberg 3146a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 31477a828908SJohan Hedberg goto unlock; 31487a828908SJohan Hedberg 31497a828908SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 31507a828908SJohan Hedberg if (!conn) 31517a828908SJohan Hedberg goto unlock; 31527a828908SJohan Hedberg 31537a828908SJohan Hedberg loc_mitm = (conn->auth_type & 0x01); 31547a828908SJohan Hedberg rem_mitm = (conn->remote_auth & 0x01); 31557a828908SJohan Hedberg 31567a828908SJohan Hedberg /* If we require MITM but the remote device can't provide that 31577a828908SJohan Hedberg * (it has NoInputNoOutput) then reject the confirmation 31587a828908SJohan Hedberg * request. The only exception is when we're dedicated bonding 31597a828908SJohan Hedberg * initiators (connect_cfm_cb set) since then we always have the MITM 31607a828908SJohan Hedberg * bit set. */ 31617a828908SJohan Hedberg if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) { 31627a828908SJohan Hedberg BT_DBG("Rejecting request: remote device can't provide MITM"); 31637a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, 31647a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 31657a828908SJohan Hedberg goto unlock; 31667a828908SJohan Hedberg } 31677a828908SJohan Hedberg 31687a828908SJohan Hedberg /* If no side requires MITM protection; auto-accept */ 31697a828908SJohan Hedberg if ((!loc_mitm || conn->remote_cap == 0x03) && 31707a828908SJohan Hedberg (!rem_mitm || conn->io_capability == 0x03)) { 317155bc1a37SJohan Hedberg 317255bc1a37SJohan Hedberg /* If we're not the initiators request authorization to 317355bc1a37SJohan Hedberg * proceed from user space (mgmt_user_confirm with 317455bc1a37SJohan Hedberg * confirm_hint set to 1). */ 317551a8efd7SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 317655bc1a37SJohan Hedberg BT_DBG("Confirming auto-accept as acceptor"); 317755bc1a37SJohan Hedberg confirm_hint = 1; 317855bc1a37SJohan Hedberg goto confirm; 317955bc1a37SJohan Hedberg } 318055bc1a37SJohan Hedberg 31819f61656aSJohan Hedberg BT_DBG("Auto-accept of user confirmation with %ums delay", 31829f61656aSJohan Hedberg hdev->auto_accept_delay); 31839f61656aSJohan Hedberg 31849f61656aSJohan Hedberg if (hdev->auto_accept_delay > 0) { 31859f61656aSJohan Hedberg int delay = msecs_to_jiffies(hdev->auto_accept_delay); 31869f61656aSJohan Hedberg mod_timer(&conn->auto_accept_timer, jiffies + delay); 31879f61656aSJohan Hedberg goto unlock; 31889f61656aSJohan Hedberg } 31899f61656aSJohan Hedberg 31907a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, 31917a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 31927a828908SJohan Hedberg goto unlock; 31937a828908SJohan Hedberg } 31947a828908SJohan Hedberg 319555bc1a37SJohan Hedberg confirm: 3196272d90dfSJohan Hedberg mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey, 319755bc1a37SJohan Hedberg confirm_hint); 3198a5c29683SJohan Hedberg 31997a828908SJohan Hedberg unlock: 3200a5c29683SJohan Hedberg hci_dev_unlock(hdev); 3201a5c29683SJohan Hedberg } 3202a5c29683SJohan Hedberg 32031143d458SBrian Gix static inline void hci_user_passkey_request_evt(struct hci_dev *hdev, 32041143d458SBrian Gix struct sk_buff *skb) 32051143d458SBrian Gix { 32061143d458SBrian Gix struct hci_ev_user_passkey_req *ev = (void *) skb->data; 32071143d458SBrian Gix 32081143d458SBrian Gix BT_DBG("%s", hdev->name); 32091143d458SBrian Gix 32101143d458SBrian Gix hci_dev_lock(hdev); 32111143d458SBrian Gix 3212a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 3213272d90dfSJohan Hedberg mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); 32141143d458SBrian Gix 32151143d458SBrian Gix hci_dev_unlock(hdev); 32161143d458SBrian Gix } 32171143d458SBrian Gix 32180493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 32190493684eSMarcel Holtmann { 32200493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 32210493684eSMarcel Holtmann struct hci_conn *conn; 32220493684eSMarcel Holtmann 32230493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 32240493684eSMarcel Holtmann 32250493684eSMarcel Holtmann hci_dev_lock(hdev); 32260493684eSMarcel Holtmann 32270493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 32282a611692SJohan Hedberg if (!conn) 32292a611692SJohan Hedberg goto unlock; 32302a611692SJohan Hedberg 32312a611692SJohan Hedberg /* To avoid duplicate auth_failed events to user space we check 32322a611692SJohan Hedberg * the HCI_CONN_AUTH_PEND flag which will be set if we 32332a611692SJohan Hedberg * initiated the authentication. A traditional auth_complete 32342a611692SJohan Hedberg * event gets always produced as initiator and is also mapped to 32352a611692SJohan Hedberg * the mgmt_auth_failed event */ 323651a8efd7SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status != 0) 3237bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 3238bab73cb6SJohan Hedberg ev->status); 32392a611692SJohan Hedberg 32400493684eSMarcel Holtmann hci_conn_put(conn); 32410493684eSMarcel Holtmann 32422a611692SJohan Hedberg unlock: 32430493684eSMarcel Holtmann hci_dev_unlock(hdev); 32440493684eSMarcel Holtmann } 32450493684eSMarcel Holtmann 324641a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 324741a96212SMarcel Holtmann { 324841a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 324941a96212SMarcel Holtmann struct inquiry_entry *ie; 325041a96212SMarcel Holtmann 325141a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 325241a96212SMarcel Holtmann 325341a96212SMarcel Holtmann hci_dev_lock(hdev); 325441a96212SMarcel Holtmann 3255cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 3256cc11b9c1SAndrei Emeltchenko if (ie) 325702b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 325841a96212SMarcel Holtmann 325941a96212SMarcel Holtmann hci_dev_unlock(hdev); 326041a96212SMarcel Holtmann } 326141a96212SMarcel Holtmann 32622763eda6SSzymon Janc static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev, 32632763eda6SSzymon Janc struct sk_buff *skb) 32642763eda6SSzymon Janc { 32652763eda6SSzymon Janc struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; 32662763eda6SSzymon Janc struct oob_data *data; 32672763eda6SSzymon Janc 32682763eda6SSzymon Janc BT_DBG("%s", hdev->name); 32692763eda6SSzymon Janc 32702763eda6SSzymon Janc hci_dev_lock(hdev); 32712763eda6SSzymon Janc 3272a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 3273e1ba1f15SSzymon Janc goto unlock; 3274e1ba1f15SSzymon Janc 32752763eda6SSzymon Janc data = hci_find_remote_oob_data(hdev, &ev->bdaddr); 32762763eda6SSzymon Janc if (data) { 32772763eda6SSzymon Janc struct hci_cp_remote_oob_data_reply cp; 32782763eda6SSzymon Janc 32792763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 32802763eda6SSzymon Janc memcpy(cp.hash, data->hash, sizeof(cp.hash)); 32812763eda6SSzymon Janc memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); 32822763eda6SSzymon Janc 32832763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), 32842763eda6SSzymon Janc &cp); 32852763eda6SSzymon Janc } else { 32862763eda6SSzymon Janc struct hci_cp_remote_oob_data_neg_reply cp; 32872763eda6SSzymon Janc 32882763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 32892763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), 32902763eda6SSzymon Janc &cp); 32912763eda6SSzymon Janc } 32922763eda6SSzymon Janc 3293e1ba1f15SSzymon Janc unlock: 32942763eda6SSzymon Janc hci_dev_unlock(hdev); 32952763eda6SSzymon Janc } 32962763eda6SSzymon Janc 3297fcd89c09SVille Tervo static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 3298fcd89c09SVille Tervo { 3299fcd89c09SVille Tervo struct hci_ev_le_conn_complete *ev = (void *) skb->data; 3300fcd89c09SVille Tervo struct hci_conn *conn; 3301fcd89c09SVille Tervo 3302fcd89c09SVille Tervo BT_DBG("%s status %d", hdev->name, ev->status); 3303fcd89c09SVille Tervo 3304fcd89c09SVille Tervo hci_dev_lock(hdev); 3305fcd89c09SVille Tervo 3306fcd89c09SVille Tervo conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr); 3307b62f328bSVille Tervo if (!conn) { 3308b62f328bSVille Tervo conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); 3309b62f328bSVille Tervo if (!conn) { 3310b62f328bSVille Tervo BT_ERR("No memory for new connection"); 3311b62f328bSVille Tervo hci_dev_unlock(hdev); 3312b62f328bSVille Tervo return; 3313b62f328bSVille Tervo } 331429b7988aSAndre Guedes 331529b7988aSAndre Guedes conn->dst_type = ev->bdaddr_type; 3316b62f328bSVille Tervo } 3317fcd89c09SVille Tervo 3318fcd89c09SVille Tervo if (ev->status) { 331948264f06SJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 332048264f06SJohan Hedberg conn->dst_type, ev->status); 3321fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 3322fcd89c09SVille Tervo conn->state = BT_CLOSED; 3323fcd89c09SVille Tervo hci_conn_del(conn); 3324fcd89c09SVille Tervo goto unlock; 3325fcd89c09SVille Tervo } 3326fcd89c09SVille Tervo 3327b644ba33SJohan Hedberg if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 3328b644ba33SJohan Hedberg mgmt_device_connected(hdev, &ev->bdaddr, conn->type, 332995b23582SSzymon Janc conn->dst_type, 0, NULL, 0, NULL); 333083bc71b4SVinicius Costa Gomes 33317b5c0d52SVinicius Costa Gomes conn->sec_level = BT_SECURITY_LOW; 3332fcd89c09SVille Tervo conn->handle = __le16_to_cpu(ev->handle); 3333fcd89c09SVille Tervo conn->state = BT_CONNECTED; 3334fcd89c09SVille Tervo 3335fcd89c09SVille Tervo hci_conn_hold_device(conn); 3336fcd89c09SVille Tervo hci_conn_add_sysfs(conn); 3337fcd89c09SVille Tervo 3338fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 3339fcd89c09SVille Tervo 3340fcd89c09SVille Tervo unlock: 3341fcd89c09SVille Tervo hci_dev_unlock(hdev); 3342fcd89c09SVille Tervo } 3343fcd89c09SVille Tervo 33449aa04c91SAndre Guedes static inline void hci_le_adv_report_evt(struct hci_dev *hdev, 33459aa04c91SAndre Guedes struct sk_buff *skb) 33469aa04c91SAndre Guedes { 3347e95beb41SAndre Guedes u8 num_reports = skb->data[0]; 3348e95beb41SAndre Guedes void *ptr = &skb->data[1]; 33493c9e9195SAndre Guedes s8 rssi; 33509aa04c91SAndre Guedes 33519aa04c91SAndre Guedes hci_dev_lock(hdev); 33529aa04c91SAndre Guedes 3353e95beb41SAndre Guedes while (num_reports--) { 3354e95beb41SAndre Guedes struct hci_ev_le_advertising_info *ev = ptr; 3355e95beb41SAndre Guedes 33569aa04c91SAndre Guedes hci_add_adv_entry(hdev, ev); 33579aa04c91SAndre Guedes 33583c9e9195SAndre Guedes rssi = ev->data[ev->length]; 33593c9e9195SAndre Guedes mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type, 336004124681SGustavo F. Padovan NULL, rssi, 0, 1, ev->data, ev->length); 33613c9e9195SAndre Guedes 3362e95beb41SAndre Guedes ptr += sizeof(*ev) + ev->length + 1; 33639aa04c91SAndre Guedes } 33649aa04c91SAndre Guedes 33659aa04c91SAndre Guedes hci_dev_unlock(hdev); 33669aa04c91SAndre Guedes } 33679aa04c91SAndre Guedes 3368a7a595f6SVinicius Costa Gomes static inline void hci_le_ltk_request_evt(struct hci_dev *hdev, 3369a7a595f6SVinicius Costa Gomes struct sk_buff *skb) 3370a7a595f6SVinicius Costa Gomes { 3371a7a595f6SVinicius Costa Gomes struct hci_ev_le_ltk_req *ev = (void *) skb->data; 3372a7a595f6SVinicius Costa Gomes struct hci_cp_le_ltk_reply cp; 3373bea710feSVinicius Costa Gomes struct hci_cp_le_ltk_neg_reply neg; 3374a7a595f6SVinicius Costa Gomes struct hci_conn *conn; 3375c9839a11SVinicius Costa Gomes struct smp_ltk *ltk; 3376a7a595f6SVinicius Costa Gomes 3377e4666881SAndrei Emeltchenko BT_DBG("%s handle %d", hdev->name, __le16_to_cpu(ev->handle)); 3378a7a595f6SVinicius Costa Gomes 3379a7a595f6SVinicius Costa Gomes hci_dev_lock(hdev); 3380a7a595f6SVinicius Costa Gomes 3381a7a595f6SVinicius Costa Gomes conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3382bea710feSVinicius Costa Gomes if (conn == NULL) 3383bea710feSVinicius Costa Gomes goto not_found; 3384a7a595f6SVinicius Costa Gomes 3385bea710feSVinicius Costa Gomes ltk = hci_find_ltk(hdev, ev->ediv, ev->random); 3386bea710feSVinicius Costa Gomes if (ltk == NULL) 3387bea710feSVinicius Costa Gomes goto not_found; 3388bea710feSVinicius Costa Gomes 3389bea710feSVinicius Costa Gomes memcpy(cp.ltk, ltk->val, sizeof(ltk->val)); 3390a7a595f6SVinicius Costa Gomes cp.handle = cpu_to_le16(conn->handle); 3391c9839a11SVinicius Costa Gomes 3392c9839a11SVinicius Costa Gomes if (ltk->authenticated) 3393c9839a11SVinicius Costa Gomes conn->sec_level = BT_SECURITY_HIGH; 3394a7a595f6SVinicius Costa Gomes 3395a7a595f6SVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); 3396a7a595f6SVinicius Costa Gomes 3397c9839a11SVinicius Costa Gomes if (ltk->type & HCI_SMP_STK) { 3398c9839a11SVinicius Costa Gomes list_del(<k->list); 3399c9839a11SVinicius Costa Gomes kfree(ltk); 3400c9839a11SVinicius Costa Gomes } 3401c9839a11SVinicius Costa Gomes 3402a7a595f6SVinicius Costa Gomes hci_dev_unlock(hdev); 3403bea710feSVinicius Costa Gomes 3404bea710feSVinicius Costa Gomes return; 3405bea710feSVinicius Costa Gomes 3406bea710feSVinicius Costa Gomes not_found: 3407bea710feSVinicius Costa Gomes neg.handle = ev->handle; 3408bea710feSVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg); 3409bea710feSVinicius Costa Gomes hci_dev_unlock(hdev); 3410a7a595f6SVinicius Costa Gomes } 3411a7a595f6SVinicius Costa Gomes 3412fcd89c09SVille Tervo static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 3413fcd89c09SVille Tervo { 3414fcd89c09SVille Tervo struct hci_ev_le_meta *le_ev = (void *) skb->data; 3415fcd89c09SVille Tervo 3416fcd89c09SVille Tervo skb_pull(skb, sizeof(*le_ev)); 3417fcd89c09SVille Tervo 3418fcd89c09SVille Tervo switch (le_ev->subevent) { 3419fcd89c09SVille Tervo case HCI_EV_LE_CONN_COMPLETE: 3420fcd89c09SVille Tervo hci_le_conn_complete_evt(hdev, skb); 3421fcd89c09SVille Tervo break; 3422fcd89c09SVille Tervo 34239aa04c91SAndre Guedes case HCI_EV_LE_ADVERTISING_REPORT: 34249aa04c91SAndre Guedes hci_le_adv_report_evt(hdev, skb); 34259aa04c91SAndre Guedes break; 34269aa04c91SAndre Guedes 3427a7a595f6SVinicius Costa Gomes case HCI_EV_LE_LTK_REQ: 3428a7a595f6SVinicius Costa Gomes hci_le_ltk_request_evt(hdev, skb); 3429a7a595f6SVinicius Costa Gomes break; 3430a7a595f6SVinicius Costa Gomes 3431fcd89c09SVille Tervo default: 3432fcd89c09SVille Tervo break; 3433fcd89c09SVille Tervo } 3434fcd89c09SVille Tervo } 3435fcd89c09SVille Tervo 34361da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 34371da177e4SLinus Torvalds { 3438a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 3439a9de9248SMarcel Holtmann __u8 event = hdr->evt; 34401da177e4SLinus Torvalds 34411da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 34421da177e4SLinus Torvalds 3443a9de9248SMarcel Holtmann switch (event) { 34441da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 34451da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 34461da177e4SLinus Torvalds break; 34471da177e4SLinus Torvalds 34481da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 34491da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 34501da177e4SLinus Torvalds break; 34511da177e4SLinus Torvalds 3452a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 3453a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 345421d9e30eSMarcel Holtmann break; 345521d9e30eSMarcel Holtmann 34561da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 34571da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 34581da177e4SLinus Torvalds break; 34591da177e4SLinus Torvalds 34601da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 34611da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 34621da177e4SLinus Torvalds break; 34631da177e4SLinus Torvalds 34641da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 34651da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 34661da177e4SLinus Torvalds break; 34671da177e4SLinus Torvalds 3468a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 3469a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 3470a9de9248SMarcel Holtmann break; 3471a9de9248SMarcel Holtmann 34721da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 34731da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 34741da177e4SLinus Torvalds break; 34751da177e4SLinus Torvalds 3476a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 3477a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 3478a9de9248SMarcel Holtmann break; 3479a9de9248SMarcel Holtmann 3480a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 3481a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 3482a9de9248SMarcel Holtmann break; 3483a9de9248SMarcel Holtmann 3484a9de9248SMarcel Holtmann case HCI_EV_REMOTE_VERSION: 3485a9de9248SMarcel Holtmann hci_remote_version_evt(hdev, skb); 3486a9de9248SMarcel Holtmann break; 3487a9de9248SMarcel Holtmann 3488a9de9248SMarcel Holtmann case HCI_EV_QOS_SETUP_COMPLETE: 3489a9de9248SMarcel Holtmann hci_qos_setup_complete_evt(hdev, skb); 3490a9de9248SMarcel Holtmann break; 3491a9de9248SMarcel Holtmann 3492a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 3493a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 3494a9de9248SMarcel Holtmann break; 3495a9de9248SMarcel Holtmann 3496a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 3497a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 3498a9de9248SMarcel Holtmann break; 3499a9de9248SMarcel Holtmann 3500a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 3501a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 3502a9de9248SMarcel Holtmann break; 3503a9de9248SMarcel Holtmann 3504a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 3505a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 3506a9de9248SMarcel Holtmann break; 3507a9de9248SMarcel Holtmann 3508a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 3509a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 35101da177e4SLinus Torvalds break; 35111da177e4SLinus Torvalds 35121da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 35131da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 35141da177e4SLinus Torvalds break; 35151da177e4SLinus Torvalds 35161da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 35171da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 35181da177e4SLinus Torvalds break; 35191da177e4SLinus Torvalds 35201da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 35211da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 35221da177e4SLinus Torvalds break; 35231da177e4SLinus Torvalds 35241da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 35251da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 35261da177e4SLinus Torvalds break; 35271da177e4SLinus Torvalds 3528a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 3529a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 3530a8746417SMarcel Holtmann break; 3531a8746417SMarcel Holtmann 353285a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 353385a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 353485a1e930SMarcel Holtmann break; 353585a1e930SMarcel Holtmann 3536a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 3537a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 3538a9de9248SMarcel Holtmann break; 3539a9de9248SMarcel Holtmann 3540a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 3541a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 3542a9de9248SMarcel Holtmann break; 3543a9de9248SMarcel Holtmann 3544a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 3545a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 3546a9de9248SMarcel Holtmann break; 3547a9de9248SMarcel Holtmann 3548a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_CHANGED: 3549a9de9248SMarcel Holtmann hci_sync_conn_changed_evt(hdev, skb); 3550a9de9248SMarcel Holtmann break; 3551a9de9248SMarcel Holtmann 355204837f64SMarcel Holtmann case HCI_EV_SNIFF_SUBRATE: 355304837f64SMarcel Holtmann hci_sniff_subrate_evt(hdev, skb); 355404837f64SMarcel Holtmann break; 355504837f64SMarcel Holtmann 3556a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 3557a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 35581da177e4SLinus Torvalds break; 35591da177e4SLinus Torvalds 35600493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 35610493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 35620493684eSMarcel Holtmann break; 35630493684eSMarcel Holtmann 356403b555e1SJohan Hedberg case HCI_EV_IO_CAPA_REPLY: 356503b555e1SJohan Hedberg hci_io_capa_reply_evt(hdev, skb); 356603b555e1SJohan Hedberg break; 356703b555e1SJohan Hedberg 3568a5c29683SJohan Hedberg case HCI_EV_USER_CONFIRM_REQUEST: 3569a5c29683SJohan Hedberg hci_user_confirm_request_evt(hdev, skb); 3570a5c29683SJohan Hedberg break; 3571a5c29683SJohan Hedberg 35721143d458SBrian Gix case HCI_EV_USER_PASSKEY_REQUEST: 35731143d458SBrian Gix hci_user_passkey_request_evt(hdev, skb); 35741143d458SBrian Gix break; 35751143d458SBrian Gix 35760493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 35770493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 35780493684eSMarcel Holtmann break; 35790493684eSMarcel Holtmann 358041a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 358141a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 358241a96212SMarcel Holtmann break; 358341a96212SMarcel Holtmann 3584fcd89c09SVille Tervo case HCI_EV_LE_META: 3585fcd89c09SVille Tervo hci_le_meta_evt(hdev, skb); 3586fcd89c09SVille Tervo break; 3587fcd89c09SVille Tervo 35882763eda6SSzymon Janc case HCI_EV_REMOTE_OOB_DATA_REQUEST: 35892763eda6SSzymon Janc hci_remote_oob_data_request_evt(hdev, skb); 35902763eda6SSzymon Janc break; 35912763eda6SSzymon Janc 359225e89e99SAndrei Emeltchenko case HCI_EV_NUM_COMP_BLOCKS: 359325e89e99SAndrei Emeltchenko hci_num_comp_blocks_evt(hdev, skb); 359425e89e99SAndrei Emeltchenko break; 359525e89e99SAndrei Emeltchenko 35961da177e4SLinus Torvalds default: 3597a9de9248SMarcel Holtmann BT_DBG("%s event 0x%x", hdev->name, event); 35981da177e4SLinus Torvalds break; 35991da177e4SLinus Torvalds } 36001da177e4SLinus Torvalds 36011da177e4SLinus Torvalds kfree_skb(skb); 36021da177e4SLinus Torvalds hdev->stat.evt_rx++; 36031da177e4SLinus Torvalds } 3604