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 <asm/unaligned.h> 281da177e4SLinus Torvalds 291da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h> 301da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h> 31f0d6a0eaSMikel Astiz #include <net/bluetooth/mgmt.h> 328e2a0d92SAndrei Emeltchenko #include <net/bluetooth/a2mp.h> 33903e4541SAndrei Emeltchenko #include <net/bluetooth/amp.h> 341da177e4SLinus Torvalds 351da177e4SLinus Torvalds /* Handle HCI Event packets */ 361da177e4SLinus Torvalds 37a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb) 381da177e4SLinus Torvalds { 39a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 401da177e4SLinus Torvalds 419f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 421da177e4SLinus Torvalds 43e6d465cbSAndre Guedes if (status) { 44e6d465cbSAndre Guedes hci_dev_lock(hdev); 45e6d465cbSAndre Guedes mgmt_stop_discovery_failed(hdev, status); 46e6d465cbSAndre Guedes hci_dev_unlock(hdev); 47a9de9248SMarcel Holtmann return; 48e6d465cbSAndre Guedes } 491da177e4SLinus Torvalds 5089352e7dSAndre Guedes clear_bit(HCI_INQUIRY, &hdev->flags); 5189352e7dSAndre Guedes 5256e5cb86SJohan Hedberg hci_dev_lock(hdev); 53ff9ef578SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 5456e5cb86SJohan Hedberg hci_dev_unlock(hdev); 55a9de9248SMarcel Holtmann 5623bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status); 57a9de9248SMarcel Holtmann 58a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 591da177e4SLinus Torvalds } 606bd57416SMarcel Holtmann 614d93483bSAndre Guedes static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 624d93483bSAndre Guedes { 634d93483bSAndre Guedes __u8 status = *((__u8 *) skb->data); 644d93483bSAndre Guedes 659f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 66ae854a70SAndre Guedes 67ae854a70SAndre Guedes if (status) 68ae854a70SAndre Guedes return; 69ae854a70SAndre Guedes 70ae854a70SAndre Guedes set_bit(HCI_PERIODIC_INQ, &hdev->dev_flags); 714d93483bSAndre Guedes } 724d93483bSAndre Guedes 73a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 741da177e4SLinus Torvalds { 75a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 76a9de9248SMarcel Holtmann 779f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 78a9de9248SMarcel Holtmann 79a9de9248SMarcel Holtmann if (status) 80a9de9248SMarcel Holtmann return; 81a9de9248SMarcel Holtmann 82ae854a70SAndre Guedes clear_bit(HCI_PERIODIC_INQ, &hdev->dev_flags); 83ae854a70SAndre Guedes 84a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 85a9de9248SMarcel Holtmann } 86a9de9248SMarcel Holtmann 87807deac2SGustavo Padovan static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, 88807deac2SGustavo Padovan struct sk_buff *skb) 89a9de9248SMarcel Holtmann { 90a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 91a9de9248SMarcel Holtmann } 92a9de9248SMarcel Holtmann 93a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb) 94a9de9248SMarcel Holtmann { 95a9de9248SMarcel Holtmann struct hci_rp_role_discovery *rp = (void *) skb->data; 961da177e4SLinus Torvalds struct hci_conn *conn; 971da177e4SLinus Torvalds 989f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 991da177e4SLinus Torvalds 100a9de9248SMarcel Holtmann if (rp->status) 101a9de9248SMarcel Holtmann return; 1021da177e4SLinus Torvalds 1031da177e4SLinus Torvalds hci_dev_lock(hdev); 1041da177e4SLinus Torvalds 105a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 1061da177e4SLinus Torvalds if (conn) { 107a9de9248SMarcel Holtmann if (rp->role) 1081da177e4SLinus Torvalds conn->link_mode &= ~HCI_LM_MASTER; 1091da177e4SLinus Torvalds else 1101da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 1111da177e4SLinus Torvalds } 1121da177e4SLinus Torvalds 1131da177e4SLinus Torvalds hci_dev_unlock(hdev); 114a9de9248SMarcel Holtmann } 1151da177e4SLinus Torvalds 116e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 117e4e8e37cSMarcel Holtmann { 118e4e8e37cSMarcel Holtmann struct hci_rp_read_link_policy *rp = (void *) skb->data; 119e4e8e37cSMarcel Holtmann struct hci_conn *conn; 120e4e8e37cSMarcel Holtmann 1219f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 122e4e8e37cSMarcel Holtmann 123e4e8e37cSMarcel Holtmann if (rp->status) 124e4e8e37cSMarcel Holtmann return; 125e4e8e37cSMarcel Holtmann 126e4e8e37cSMarcel Holtmann hci_dev_lock(hdev); 127e4e8e37cSMarcel Holtmann 128e4e8e37cSMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 129e4e8e37cSMarcel Holtmann if (conn) 130e4e8e37cSMarcel Holtmann conn->link_policy = __le16_to_cpu(rp->policy); 131e4e8e37cSMarcel Holtmann 132e4e8e37cSMarcel Holtmann hci_dev_unlock(hdev); 133e4e8e37cSMarcel Holtmann } 134e4e8e37cSMarcel Holtmann 135a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 136a9de9248SMarcel Holtmann { 137a9de9248SMarcel Holtmann struct hci_rp_write_link_policy *rp = (void *) skb->data; 138a9de9248SMarcel Holtmann struct hci_conn *conn; 139a9de9248SMarcel Holtmann void *sent; 140a9de9248SMarcel Holtmann 1419f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 142a9de9248SMarcel Holtmann 143a9de9248SMarcel Holtmann if (rp->status) 144a9de9248SMarcel Holtmann return; 145a9de9248SMarcel Holtmann 146a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY); 14704837f64SMarcel Holtmann if (!sent) 148a9de9248SMarcel Holtmann return; 14904837f64SMarcel Holtmann 15004837f64SMarcel Holtmann hci_dev_lock(hdev); 15104837f64SMarcel Holtmann 152a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 153e4e8e37cSMarcel Holtmann if (conn) 15483985319SHarvey Harrison conn->link_policy = get_unaligned_le16(sent + 2); 15504837f64SMarcel Holtmann 15604837f64SMarcel Holtmann hci_dev_unlock(hdev); 1571da177e4SLinus Torvalds } 1581da177e4SLinus Torvalds 159807deac2SGustavo Padovan static void hci_cc_read_def_link_policy(struct hci_dev *hdev, 160807deac2SGustavo Padovan struct sk_buff *skb) 161e4e8e37cSMarcel Holtmann { 162e4e8e37cSMarcel Holtmann struct hci_rp_read_def_link_policy *rp = (void *) skb->data; 163e4e8e37cSMarcel Holtmann 1649f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 165e4e8e37cSMarcel Holtmann 166e4e8e37cSMarcel Holtmann if (rp->status) 167e4e8e37cSMarcel Holtmann return; 168e4e8e37cSMarcel Holtmann 169e4e8e37cSMarcel Holtmann hdev->link_policy = __le16_to_cpu(rp->policy); 170e4e8e37cSMarcel Holtmann } 171e4e8e37cSMarcel Holtmann 172807deac2SGustavo Padovan static void hci_cc_write_def_link_policy(struct hci_dev *hdev, 173807deac2SGustavo Padovan struct sk_buff *skb) 174e4e8e37cSMarcel Holtmann { 175e4e8e37cSMarcel Holtmann __u8 status = *((__u8 *) skb->data); 176e4e8e37cSMarcel Holtmann void *sent; 177e4e8e37cSMarcel Holtmann 1789f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 179e4e8e37cSMarcel Holtmann 180e4e8e37cSMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY); 181e4e8e37cSMarcel Holtmann if (!sent) 182e4e8e37cSMarcel Holtmann return; 183e4e8e37cSMarcel Holtmann 184e4e8e37cSMarcel Holtmann if (!status) 185e4e8e37cSMarcel Holtmann hdev->link_policy = get_unaligned_le16(sent); 186e4e8e37cSMarcel Holtmann 18723bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status); 188e4e8e37cSMarcel Holtmann } 189e4e8e37cSMarcel Holtmann 190a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) 1911da177e4SLinus Torvalds { 192a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 193a9de9248SMarcel Holtmann 1949f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 195a9de9248SMarcel Holtmann 19610572132SGustavo F. Padovan clear_bit(HCI_RESET, &hdev->flags); 19710572132SGustavo F. Padovan 19823bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_RESET, status); 199d23264a8SAndre Guedes 200a297e97cSJohan Hedberg /* Reset all non-persistent flags */ 201ae854a70SAndre Guedes hdev->dev_flags &= ~(BIT(HCI_LE_SCAN) | BIT(HCI_PENDING_CLASS) | 202ae854a70SAndre Guedes BIT(HCI_PERIODIC_INQ)); 20369775ff6SAndre Guedes 20469775ff6SAndre Guedes hdev->discovery.state = DISCOVERY_STOPPED; 205a9de9248SMarcel Holtmann } 206a9de9248SMarcel Holtmann 207a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) 208a9de9248SMarcel Holtmann { 209a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 2101da177e4SLinus Torvalds void *sent; 2111da177e4SLinus Torvalds 2129f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 2131da177e4SLinus Torvalds 214a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); 2151da177e4SLinus Torvalds if (!sent) 216a9de9248SMarcel Holtmann return; 2171da177e4SLinus Torvalds 21856e5cb86SJohan Hedberg hci_dev_lock(hdev); 21956e5cb86SJohan Hedberg 220f51d5b24SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 221f51d5b24SJohan Hedberg mgmt_set_local_name_complete(hdev, sent, status); 22228cc7bdeSJohan Hedberg else if (!status) 22328cc7bdeSJohan Hedberg memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); 224f51d5b24SJohan Hedberg 22556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 2263159d384SJohan Hedberg 2273159d384SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status); 228a9de9248SMarcel Holtmann } 229a9de9248SMarcel Holtmann 230a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) 231a9de9248SMarcel Holtmann { 232a9de9248SMarcel Holtmann struct hci_rp_read_local_name *rp = (void *) skb->data; 233a9de9248SMarcel Holtmann 2349f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 235a9de9248SMarcel Holtmann 236a9de9248SMarcel Holtmann if (rp->status) 237a9de9248SMarcel Holtmann return; 238a9de9248SMarcel Holtmann 239db99b5fcSJohan Hedberg if (test_bit(HCI_SETUP, &hdev->dev_flags)) 2401f6c6378SJohan Hedberg memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); 241a9de9248SMarcel Holtmann } 242a9de9248SMarcel Holtmann 243a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) 244a9de9248SMarcel Holtmann { 245a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 246a9de9248SMarcel Holtmann void *sent; 247a9de9248SMarcel Holtmann 2489f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 249a9de9248SMarcel Holtmann 250a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); 251a9de9248SMarcel Holtmann if (!sent) 252a9de9248SMarcel Holtmann return; 2531da177e4SLinus Torvalds 2541da177e4SLinus Torvalds if (!status) { 255a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 256a9de9248SMarcel Holtmann 2571da177e4SLinus Torvalds if (param == AUTH_ENABLED) 2581da177e4SLinus Torvalds set_bit(HCI_AUTH, &hdev->flags); 2591da177e4SLinus Torvalds else 2601da177e4SLinus Torvalds clear_bit(HCI_AUTH, &hdev->flags); 2611da177e4SLinus Torvalds } 262a9de9248SMarcel Holtmann 26333ef95edSJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 26433ef95edSJohan Hedberg mgmt_auth_enable_complete(hdev, status); 26533ef95edSJohan Hedberg 26623bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status); 267a9de9248SMarcel Holtmann } 2681da177e4SLinus Torvalds 269a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) 270a9de9248SMarcel Holtmann { 271a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 272a9de9248SMarcel Holtmann void *sent; 273a9de9248SMarcel Holtmann 2749f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 275a9de9248SMarcel Holtmann 276a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); 2771da177e4SLinus Torvalds if (!sent) 278a9de9248SMarcel Holtmann return; 2791da177e4SLinus Torvalds 2801da177e4SLinus Torvalds if (!status) { 281a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 282a9de9248SMarcel Holtmann 2831da177e4SLinus Torvalds if (param) 2841da177e4SLinus Torvalds set_bit(HCI_ENCRYPT, &hdev->flags); 2851da177e4SLinus Torvalds else 2861da177e4SLinus Torvalds clear_bit(HCI_ENCRYPT, &hdev->flags); 2871da177e4SLinus Torvalds } 288a9de9248SMarcel Holtmann 28923bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status); 2901da177e4SLinus Torvalds } 2911da177e4SLinus Torvalds 292a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) 293a9de9248SMarcel Holtmann { 29436f7fc7eSJohan Hedberg __u8 param, status = *((__u8 *) skb->data); 29536f7fc7eSJohan Hedberg int old_pscan, old_iscan; 296a9de9248SMarcel Holtmann void *sent; 2971da177e4SLinus Torvalds 2989f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 299a9de9248SMarcel Holtmann 300a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); 3011da177e4SLinus Torvalds if (!sent) 302a9de9248SMarcel Holtmann return; 3031da177e4SLinus Torvalds 30436f7fc7eSJohan Hedberg param = *((__u8 *) sent); 305a9de9248SMarcel Holtmann 30656e5cb86SJohan Hedberg hci_dev_lock(hdev); 30756e5cb86SJohan Hedberg 308fa1bd918SMikel Astiz if (status) { 309744cf19eSJohan Hedberg mgmt_write_scan_failed(hdev, param, status); 3102d7cee58SJohan Hedberg hdev->discov_timeout = 0; 3112d7cee58SJohan Hedberg goto done; 3122d7cee58SJohan Hedberg } 3132d7cee58SJohan Hedberg 3149fbcbb45SJohan Hedberg old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags); 3159fbcbb45SJohan Hedberg old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags); 316a9de9248SMarcel Holtmann 31773f22f62SJohan Hedberg if (param & SCAN_INQUIRY) { 3181da177e4SLinus Torvalds set_bit(HCI_ISCAN, &hdev->flags); 3199fbcbb45SJohan Hedberg if (!old_iscan) 320744cf19eSJohan Hedberg mgmt_discoverable(hdev, 1); 32116ab91abSJohan Hedberg if (hdev->discov_timeout > 0) { 32216ab91abSJohan Hedberg int to = msecs_to_jiffies(hdev->discov_timeout * 1000); 32316ab91abSJohan Hedberg queue_delayed_work(hdev->workqueue, &hdev->discov_off, 32416ab91abSJohan Hedberg to); 32516ab91abSJohan Hedberg } 3269fbcbb45SJohan Hedberg } else if (old_iscan) 327744cf19eSJohan Hedberg mgmt_discoverable(hdev, 0); 3281da177e4SLinus Torvalds 3299fbcbb45SJohan Hedberg if (param & SCAN_PAGE) { 3301da177e4SLinus Torvalds set_bit(HCI_PSCAN, &hdev->flags); 3319fbcbb45SJohan Hedberg if (!old_pscan) 332744cf19eSJohan Hedberg mgmt_connectable(hdev, 1); 3339fbcbb45SJohan Hedberg } else if (old_pscan) 334744cf19eSJohan Hedberg mgmt_connectable(hdev, 0); 335a9de9248SMarcel Holtmann 33636f7fc7eSJohan Hedberg done: 33756e5cb86SJohan Hedberg hci_dev_unlock(hdev); 33823bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status); 3391da177e4SLinus Torvalds } 3401da177e4SLinus Torvalds 341a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 342a9de9248SMarcel Holtmann { 343a9de9248SMarcel Holtmann struct hci_rp_read_class_of_dev *rp = (void *) skb->data; 344a9de9248SMarcel Holtmann 3459f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 346a9de9248SMarcel Holtmann 347a9de9248SMarcel Holtmann if (rp->status) 348a9de9248SMarcel Holtmann return; 349a9de9248SMarcel Holtmann 350a9de9248SMarcel Holtmann memcpy(hdev->dev_class, rp->dev_class, 3); 351a9de9248SMarcel Holtmann 352a9de9248SMarcel Holtmann BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, 353a9de9248SMarcel Holtmann hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); 354a9de9248SMarcel Holtmann } 355a9de9248SMarcel Holtmann 356a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 357a9de9248SMarcel Holtmann { 358a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 359a9de9248SMarcel Holtmann void *sent; 360a9de9248SMarcel Holtmann 3619f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 362a9de9248SMarcel Holtmann 363a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); 364a9de9248SMarcel Holtmann if (!sent) 365a9de9248SMarcel Holtmann return; 366a9de9248SMarcel Holtmann 3677f9a903cSMarcel Holtmann hci_dev_lock(hdev); 3687f9a903cSMarcel Holtmann 3697f9a903cSMarcel Holtmann if (status == 0) 370a9de9248SMarcel Holtmann memcpy(hdev->dev_class, sent, 3); 3717f9a903cSMarcel Holtmann 3727f9a903cSMarcel Holtmann if (test_bit(HCI_MGMT, &hdev->dev_flags)) 3737f9a903cSMarcel Holtmann mgmt_set_class_of_dev_complete(hdev, sent, status); 3747f9a903cSMarcel Holtmann 3757f9a903cSMarcel Holtmann hci_dev_unlock(hdev); 376a9de9248SMarcel Holtmann } 377a9de9248SMarcel Holtmann 378a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 379a9de9248SMarcel Holtmann { 380a9de9248SMarcel Holtmann struct hci_rp_read_voice_setting *rp = (void *) skb->data; 381a9de9248SMarcel Holtmann __u16 setting; 382a9de9248SMarcel Holtmann 3839f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 384a9de9248SMarcel Holtmann 385a9de9248SMarcel Holtmann if (rp->status) 386a9de9248SMarcel Holtmann return; 387a9de9248SMarcel Holtmann 388a9de9248SMarcel Holtmann setting = __le16_to_cpu(rp->voice_setting); 389a9de9248SMarcel Holtmann 390a9de9248SMarcel Holtmann if (hdev->voice_setting == setting) 391a9de9248SMarcel Holtmann return; 392a9de9248SMarcel Holtmann 393a9de9248SMarcel Holtmann hdev->voice_setting = setting; 394a9de9248SMarcel Holtmann 3959f1db00cSAndrei Emeltchenko BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting); 396a9de9248SMarcel Holtmann 3973c54711cSGustavo F. Padovan if (hdev->notify) 398a9de9248SMarcel Holtmann hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 399a9de9248SMarcel Holtmann } 400a9de9248SMarcel Holtmann 4018fc9ced3SGustavo Padovan static void hci_cc_write_voice_setting(struct hci_dev *hdev, 4028fc9ced3SGustavo Padovan struct sk_buff *skb) 403a9de9248SMarcel Holtmann { 404a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 405f383f275SMarcel Holtmann __u16 setting; 406a9de9248SMarcel Holtmann void *sent; 407a9de9248SMarcel Holtmann 4089f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 409a9de9248SMarcel Holtmann 410f383f275SMarcel Holtmann if (status) 411f383f275SMarcel Holtmann return; 412f383f275SMarcel Holtmann 413a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); 414a9de9248SMarcel Holtmann if (!sent) 415a9de9248SMarcel Holtmann return; 416a9de9248SMarcel Holtmann 417f383f275SMarcel Holtmann setting = get_unaligned_le16(sent); 4181da177e4SLinus Torvalds 419f383f275SMarcel Holtmann if (hdev->voice_setting == setting) 420f383f275SMarcel Holtmann return; 421f383f275SMarcel Holtmann 4221da177e4SLinus Torvalds hdev->voice_setting = setting; 4231da177e4SLinus Torvalds 4249f1db00cSAndrei Emeltchenko BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting); 4251da177e4SLinus Torvalds 4263c54711cSGustavo F. Padovan if (hdev->notify) 4271da177e4SLinus Torvalds hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 4281da177e4SLinus Torvalds } 4291da177e4SLinus Torvalds 430a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 4311da177e4SLinus Torvalds { 432a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 4331da177e4SLinus Torvalds 4349f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 4351da177e4SLinus Torvalds 43623bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status); 4371143e5a6SMarcel Holtmann } 4381143e5a6SMarcel Holtmann 439333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 440333140b5SMarcel Holtmann { 441333140b5SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 4425ed8eb2fSJohan Hedberg struct hci_cp_write_ssp_mode *sent; 443333140b5SMarcel Holtmann 4449f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 445333140b5SMarcel Holtmann 446333140b5SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); 447333140b5SMarcel Holtmann if (!sent) 448333140b5SMarcel Holtmann return; 449333140b5SMarcel Holtmann 4505ed8eb2fSJohan Hedberg if (!status) { 4515ed8eb2fSJohan Hedberg if (sent->mode) 4525ed8eb2fSJohan Hedberg hdev->host_features[0] |= LMP_HOST_SSP; 4535ed8eb2fSJohan Hedberg else 4545ed8eb2fSJohan Hedberg hdev->host_features[0] &= ~LMP_HOST_SSP; 4555ed8eb2fSJohan Hedberg } 4565ed8eb2fSJohan Hedberg 457c0ecddc2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 4585ed8eb2fSJohan Hedberg mgmt_ssp_enable_complete(hdev, sent->mode, status); 459c0ecddc2SJohan Hedberg else if (!status) { 4605ed8eb2fSJohan Hedberg if (sent->mode) 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 { 469976eb20eSJohan Hedberg if (lmp_ext_inq_capable(hdev)) 470d5859e22SJohan Hedberg return 2; 471d5859e22SJohan Hedberg 472976eb20eSJohan Hedberg if (lmp_inq_rssi_capable(hdev)) 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 516e1171e8dSJohan Hedberg if (lmp_bredr_capable(hdev)) { 517d5859e22SJohan Hedberg events[4] |= 0x01; /* Flow Specification Complete */ 518d5859e22SJohan Hedberg events[4] |= 0x02; /* Inquiry Result with RSSI */ 519d5859e22SJohan Hedberg events[4] |= 0x04; /* Read Remote Extended Features Complete */ 520d5859e22SJohan Hedberg events[5] |= 0x08; /* Synchronous Connection Complete */ 521d5859e22SJohan Hedberg events[5] |= 0x10; /* Synchronous Connection Changed */ 522e1171e8dSJohan Hedberg } 523d5859e22SJohan Hedberg 524976eb20eSJohan Hedberg if (lmp_inq_rssi_capable(hdev)) 525a24299e6SJohan Hedberg events[4] |= 0x02; /* Inquiry Result with RSSI */ 526d5859e22SJohan Hedberg 527999dcd10SAndre Guedes if (lmp_sniffsubr_capable(hdev)) 528d5859e22SJohan Hedberg events[5] |= 0x20; /* Sniff Subrating */ 529d5859e22SJohan Hedberg 530976eb20eSJohan Hedberg if (lmp_pause_enc_capable(hdev)) 531d5859e22SJohan Hedberg events[5] |= 0x80; /* Encryption Key Refresh Complete */ 532d5859e22SJohan Hedberg 533976eb20eSJohan Hedberg if (lmp_ext_inq_capable(hdev)) 534d5859e22SJohan Hedberg events[5] |= 0x40; /* Extended Inquiry Result */ 535d5859e22SJohan Hedberg 536c58e810eSAndre Guedes if (lmp_no_flush_capable(hdev)) 537d5859e22SJohan Hedberg events[7] |= 0x01; /* Enhanced Flush Complete */ 538d5859e22SJohan Hedberg 539976eb20eSJohan Hedberg if (lmp_lsto_capable(hdev)) 540d5859e22SJohan Hedberg events[6] |= 0x80; /* Link Supervision Timeout Changed */ 541d5859e22SJohan Hedberg 5429a1a1996SAndre Guedes if (lmp_ssp_capable(hdev)) { 543d5859e22SJohan Hedberg events[6] |= 0x01; /* IO Capability Request */ 544d5859e22SJohan Hedberg events[6] |= 0x02; /* IO Capability Response */ 545d5859e22SJohan Hedberg events[6] |= 0x04; /* User Confirmation Request */ 546d5859e22SJohan Hedberg events[6] |= 0x08; /* User Passkey Request */ 547d5859e22SJohan Hedberg events[6] |= 0x10; /* Remote OOB Data Request */ 548d5859e22SJohan Hedberg events[6] |= 0x20; /* Simple Pairing Complete */ 549d5859e22SJohan Hedberg events[7] |= 0x04; /* User Passkey Notification */ 550d5859e22SJohan Hedberg events[7] |= 0x08; /* Keypress Notification */ 551d5859e22SJohan Hedberg events[7] |= 0x10; /* Remote Host Supported 552d5859e22SJohan Hedberg * Features Notification */ 553d5859e22SJohan Hedberg } 554d5859e22SJohan Hedberg 555c383ddc4SAndre Guedes if (lmp_le_capable(hdev)) 556d5859e22SJohan Hedberg events[7] |= 0x20; /* LE Meta-Event */ 557d5859e22SJohan Hedberg 558d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); 559e36b04c8SJohan Hedberg 560e36b04c8SJohan Hedberg if (lmp_le_capable(hdev)) { 561e36b04c8SJohan Hedberg memset(events, 0, sizeof(events)); 562e36b04c8SJohan Hedberg events[0] = 0x1f; 563e36b04c8SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LE_SET_EVENT_MASK, 564e36b04c8SJohan Hedberg sizeof(events), events); 565e36b04c8SJohan Hedberg } 566d5859e22SJohan Hedberg } 567d5859e22SJohan Hedberg 5684611dfa8SGustavo Padovan static void bredr_setup(struct hci_dev *hdev) 569e1171e8dSJohan Hedberg { 570e1171e8dSJohan Hedberg struct hci_cp_delete_stored_link_key cp; 571e1171e8dSJohan Hedberg __le16 param; 572e1171e8dSJohan Hedberg __u8 flt_type; 573e1171e8dSJohan Hedberg 574e1171e8dSJohan Hedberg /* Read Buffer Size (ACL mtu, max pkt, etc.) */ 575e1171e8dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL); 576e1171e8dSJohan Hedberg 577e1171e8dSJohan Hedberg /* Read Class of Device */ 578e1171e8dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL); 579e1171e8dSJohan Hedberg 580e1171e8dSJohan Hedberg /* Read Local Name */ 581e1171e8dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL); 582e1171e8dSJohan Hedberg 583e1171e8dSJohan Hedberg /* Read Voice Setting */ 584e1171e8dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL); 585e1171e8dSJohan Hedberg 586e1171e8dSJohan Hedberg /* Clear Event Filters */ 587e1171e8dSJohan Hedberg flt_type = HCI_FLT_CLEAR_ALL; 588e1171e8dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type); 589e1171e8dSJohan Hedberg 590e1171e8dSJohan Hedberg /* Connection accept timeout ~20 secs */ 591e1171e8dSJohan Hedberg param = __constant_cpu_to_le16(0x7d00); 592e1171e8dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m); 593e1171e8dSJohan Hedberg 594e1171e8dSJohan Hedberg bacpy(&cp.bdaddr, BDADDR_ANY); 595e1171e8dSJohan Hedberg cp.delete_all = 1; 596e1171e8dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp); 597e1171e8dSJohan Hedberg } 598e1171e8dSJohan Hedberg 5994611dfa8SGustavo Padovan static void le_setup(struct hci_dev *hdev) 600e1171e8dSJohan Hedberg { 601e1171e8dSJohan Hedberg /* Read LE Buffer Size */ 602e1171e8dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL); 6038fa19098SJohan Hedberg 6048fa19098SJohan Hedberg /* Read LE Advertising Channel TX Power */ 6058fa19098SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL); 606e1171e8dSJohan Hedberg } 607e1171e8dSJohan Hedberg 608d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev) 609d5859e22SJohan Hedberg { 610e61ef499SAndrei Emeltchenko if (hdev->dev_type != HCI_BREDR) 611e61ef499SAndrei Emeltchenko return; 612e61ef499SAndrei Emeltchenko 613e1171e8dSJohan Hedberg /* Read BD Address */ 614e1171e8dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL); 615e1171e8dSJohan Hedberg 616e1171e8dSJohan Hedberg if (lmp_bredr_capable(hdev)) 6174611dfa8SGustavo Padovan bredr_setup(hdev); 618e1171e8dSJohan Hedberg 619e1171e8dSJohan Hedberg if (lmp_le_capable(hdev)) 6204611dfa8SGustavo Padovan le_setup(hdev); 621e1171e8dSJohan Hedberg 622d5859e22SJohan Hedberg hci_setup_event_mask(hdev); 623d5859e22SJohan Hedberg 624d095c1ebSAndrei Emeltchenko if (hdev->hci_ver > BLUETOOTH_VER_1_1) 625d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); 626d5859e22SJohan Hedberg 6276d3c730fSGustavo Padovan if (lmp_ssp_capable(hdev)) { 62854d04dbbSJohan Hedberg if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { 629d5859e22SJohan Hedberg u8 mode = 0x01; 63054d04dbbSJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 63154d04dbbSJohan Hedberg sizeof(mode), &mode); 63254d04dbbSJohan Hedberg } else { 63354d04dbbSJohan Hedberg struct hci_cp_write_eir cp; 63454d04dbbSJohan Hedberg 63554d04dbbSJohan Hedberg memset(hdev->eir, 0, sizeof(hdev->eir)); 63654d04dbbSJohan Hedberg memset(&cp, 0, sizeof(cp)); 63754d04dbbSJohan Hedberg 63854d04dbbSJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp); 63954d04dbbSJohan Hedberg } 640d5859e22SJohan Hedberg } 641d5859e22SJohan Hedberg 642976eb20eSJohan Hedberg if (lmp_inq_rssi_capable(hdev)) 643d5859e22SJohan Hedberg hci_setup_inquiry_mode(hdev); 644d5859e22SJohan Hedberg 645976eb20eSJohan Hedberg if (lmp_inq_tx_pwr_capable(hdev)) 646d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL); 647971e3a4bSAndre Guedes 648976eb20eSJohan Hedberg if (lmp_ext_feat_capable(hdev)) { 649971e3a4bSAndre Guedes struct hci_cp_read_local_ext_features cp; 650971e3a4bSAndre Guedes 651971e3a4bSAndre Guedes cp.page = 0x01; 65204124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), 65304124681SGustavo F. Padovan &cp); 654971e3a4bSAndre Guedes } 655e6100a25SAndre Guedes 65647990ea0SJohan Hedberg if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) { 65747990ea0SJohan Hedberg u8 enable = 1; 65804124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable), 65904124681SGustavo F. Padovan &enable); 66047990ea0SJohan Hedberg } 661d5859e22SJohan Hedberg } 662d5859e22SJohan Hedberg 663a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) 664a9de9248SMarcel Holtmann { 665a9de9248SMarcel Holtmann struct hci_rp_read_local_version *rp = (void *) skb->data; 6661143e5a6SMarcel Holtmann 6679f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 6681143e5a6SMarcel Holtmann 669a9de9248SMarcel Holtmann if (rp->status) 67028b8df77SAndrei Emeltchenko goto done; 6711143e5a6SMarcel Holtmann 672a9de9248SMarcel Holtmann hdev->hci_ver = rp->hci_ver; 673e4e8e37cSMarcel Holtmann hdev->hci_rev = __le16_to_cpu(rp->hci_rev); 674d5859e22SJohan Hedberg hdev->lmp_ver = rp->lmp_ver; 675e4e8e37cSMarcel Holtmann hdev->manufacturer = __le16_to_cpu(rp->manufacturer); 676d5859e22SJohan Hedberg hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); 6771da177e4SLinus Torvalds 6789f1db00cSAndrei Emeltchenko BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name, 679807deac2SGustavo Padovan hdev->manufacturer, hdev->hci_ver, hdev->hci_rev); 680d5859e22SJohan Hedberg 681d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags)) 682d5859e22SJohan Hedberg hci_setup(hdev); 68328b8df77SAndrei Emeltchenko 68428b8df77SAndrei Emeltchenko done: 68528b8df77SAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status); 686d5859e22SJohan Hedberg } 687d5859e22SJohan Hedberg 688d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev) 689d5859e22SJohan Hedberg { 690035100c8SAndrei Emeltchenko struct hci_cp_write_def_link_policy cp; 691d5859e22SJohan Hedberg u16 link_policy = 0; 692d5859e22SJohan Hedberg 6939f92ebf6SAndre Guedes if (lmp_rswitch_capable(hdev)) 694d5859e22SJohan Hedberg link_policy |= HCI_LP_RSWITCH; 695976eb20eSJohan Hedberg if (lmp_hold_capable(hdev)) 696d5859e22SJohan Hedberg link_policy |= HCI_LP_HOLD; 6976eded100SAndre Guedes if (lmp_sniff_capable(hdev)) 698d5859e22SJohan Hedberg link_policy |= HCI_LP_SNIFF; 699976eb20eSJohan Hedberg if (lmp_park_capable(hdev)) 700d5859e22SJohan Hedberg link_policy |= HCI_LP_PARK; 701d5859e22SJohan Hedberg 702035100c8SAndrei Emeltchenko cp.policy = cpu_to_le16(link_policy); 703035100c8SAndrei Emeltchenko hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp); 7041da177e4SLinus Torvalds } 7051da177e4SLinus Torvalds 7068fc9ced3SGustavo Padovan static void hci_cc_read_local_commands(struct hci_dev *hdev, 7078fc9ced3SGustavo Padovan struct sk_buff *skb) 708a9de9248SMarcel Holtmann { 709a9de9248SMarcel Holtmann struct hci_rp_read_local_commands *rp = (void *) skb->data; 710a9de9248SMarcel Holtmann 7119f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 712a9de9248SMarcel Holtmann 713a9de9248SMarcel Holtmann if (rp->status) 714d5859e22SJohan Hedberg goto done; 715a9de9248SMarcel Holtmann 716a9de9248SMarcel Holtmann memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); 717d5859e22SJohan Hedberg 718d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10)) 719d5859e22SJohan Hedberg hci_setup_link_policy(hdev); 720d5859e22SJohan Hedberg 721d5859e22SJohan Hedberg done: 722d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status); 723a9de9248SMarcel Holtmann } 724a9de9248SMarcel Holtmann 7258fc9ced3SGustavo Padovan static void hci_cc_read_local_features(struct hci_dev *hdev, 7268fc9ced3SGustavo Padovan struct sk_buff *skb) 727a9de9248SMarcel Holtmann { 728a9de9248SMarcel Holtmann struct hci_rp_read_local_features *rp = (void *) skb->data; 729a9de9248SMarcel Holtmann 7309f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 731a9de9248SMarcel Holtmann 732a9de9248SMarcel Holtmann if (rp->status) 733a9de9248SMarcel Holtmann return; 734a9de9248SMarcel Holtmann 735a9de9248SMarcel Holtmann memcpy(hdev->features, rp->features, 8); 7361da177e4SLinus Torvalds 7371da177e4SLinus Torvalds /* Adjust default settings according to features 7381da177e4SLinus Torvalds * supported by device. */ 739a9de9248SMarcel Holtmann 7401da177e4SLinus Torvalds if (hdev->features[0] & LMP_3SLOT) 7411da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM3 | HCI_DH3); 7421da177e4SLinus Torvalds 7431da177e4SLinus Torvalds if (hdev->features[0] & LMP_5SLOT) 7441da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM5 | HCI_DH5); 7451da177e4SLinus Torvalds 7465b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV2) { 7471da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV2); 7485b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV2); 7495b7f9909SMarcel Holtmann } 7501da177e4SLinus Torvalds 7515b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV3) { 7521da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV3); 7535b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV3); 7545b7f9909SMarcel Holtmann } 7555b7f9909SMarcel Holtmann 75645db810fSAndre Guedes if (lmp_esco_capable(hdev)) 7575b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV3); 7585b7f9909SMarcel Holtmann 7595b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV4) 7605b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV4); 7615b7f9909SMarcel Holtmann 7625b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV5) 7635b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV5); 7641da177e4SLinus Torvalds 765efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_2M) 766efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV3); 767efc7688bSMarcel Holtmann 768efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_3M) 769efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_3EV3); 770efc7688bSMarcel Holtmann 771efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_3S_ESCO) 772efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); 773efc7688bSMarcel Holtmann 774a9de9248SMarcel Holtmann BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, 775a9de9248SMarcel Holtmann hdev->features[0], hdev->features[1], 776a9de9248SMarcel Holtmann hdev->features[2], hdev->features[3], 777a9de9248SMarcel Holtmann hdev->features[4], hdev->features[5], 778a9de9248SMarcel Holtmann hdev->features[6], hdev->features[7]); 7791da177e4SLinus Torvalds } 7801da177e4SLinus Torvalds 7818f984dfaSJohan Hedberg static void hci_set_le_support(struct hci_dev *hdev) 7828f984dfaSJohan Hedberg { 7838f984dfaSJohan Hedberg struct hci_cp_write_le_host_supported cp; 7848f984dfaSJohan Hedberg 7858f984dfaSJohan Hedberg memset(&cp, 0, sizeof(cp)); 7868f984dfaSJohan Hedberg 7879d42820fSMarcel Holtmann if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { 7888f984dfaSJohan Hedberg cp.le = 1; 789976eb20eSJohan Hedberg cp.simul = !!lmp_le_br_capable(hdev); 7908f984dfaSJohan Hedberg } 7918f984dfaSJohan Hedberg 792976eb20eSJohan Hedberg if (cp.le != !!lmp_host_le_capable(hdev)) 79304124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), 79404124681SGustavo F. Padovan &cp); 7958f984dfaSJohan Hedberg } 7968f984dfaSJohan Hedberg 797971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev, 798971e3a4bSAndre Guedes struct sk_buff *skb) 799971e3a4bSAndre Guedes { 800971e3a4bSAndre Guedes struct hci_rp_read_local_ext_features *rp = (void *) skb->data; 801971e3a4bSAndre Guedes 8029f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 803971e3a4bSAndre Guedes 804971e3a4bSAndre Guedes if (rp->status) 8058f984dfaSJohan Hedberg goto done; 806971e3a4bSAndre Guedes 807b5b32b65SAndre Guedes switch (rp->page) { 808b5b32b65SAndre Guedes case 0: 809b5b32b65SAndre Guedes memcpy(hdev->features, rp->features, 8); 810b5b32b65SAndre Guedes break; 811b5b32b65SAndre Guedes case 1: 81259e29406SAndre Guedes memcpy(hdev->host_features, rp->features, 8); 813b5b32b65SAndre Guedes break; 814b5b32b65SAndre Guedes } 815971e3a4bSAndre Guedes 816c383ddc4SAndre Guedes if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev)) 8178f984dfaSJohan Hedberg hci_set_le_support(hdev); 8188f984dfaSJohan Hedberg 8198f984dfaSJohan Hedberg done: 820971e3a4bSAndre Guedes hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status); 821971e3a4bSAndre Guedes } 822971e3a4bSAndre Guedes 8231e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, 8241e89cffbSAndrei Emeltchenko struct sk_buff *skb) 8251e89cffbSAndrei Emeltchenko { 8261e89cffbSAndrei Emeltchenko struct hci_rp_read_flow_control_mode *rp = (void *) skb->data; 8271e89cffbSAndrei Emeltchenko 8289f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 8291e89cffbSAndrei Emeltchenko 8301e89cffbSAndrei Emeltchenko if (rp->status) 8311e89cffbSAndrei Emeltchenko return; 8321e89cffbSAndrei Emeltchenko 8331e89cffbSAndrei Emeltchenko hdev->flow_ctl_mode = rp->mode; 8341e89cffbSAndrei Emeltchenko 8351e89cffbSAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status); 8361e89cffbSAndrei Emeltchenko } 8371e89cffbSAndrei Emeltchenko 838a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 839a9de9248SMarcel Holtmann { 840a9de9248SMarcel Holtmann struct hci_rp_read_buffer_size *rp = (void *) skb->data; 841a9de9248SMarcel Holtmann 8429f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 843a9de9248SMarcel Holtmann 844a9de9248SMarcel Holtmann if (rp->status) 845a9de9248SMarcel Holtmann return; 846a9de9248SMarcel Holtmann 847a9de9248SMarcel Holtmann hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); 848a9de9248SMarcel Holtmann hdev->sco_mtu = rp->sco_mtu; 849a9de9248SMarcel Holtmann hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); 850a9de9248SMarcel Holtmann hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); 851da1f5198SMarcel Holtmann 852da1f5198SMarcel Holtmann if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { 853da1f5198SMarcel Holtmann hdev->sco_mtu = 64; 854da1f5198SMarcel Holtmann hdev->sco_pkts = 8; 855da1f5198SMarcel Holtmann } 856da1f5198SMarcel Holtmann 857da1f5198SMarcel Holtmann hdev->acl_cnt = hdev->acl_pkts; 858da1f5198SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 8591da177e4SLinus Torvalds 860807deac2SGustavo Padovan BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu, 861807deac2SGustavo Padovan hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts); 8621da177e4SLinus Torvalds } 8631da177e4SLinus Torvalds 864a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) 865a9de9248SMarcel Holtmann { 866a9de9248SMarcel Holtmann struct hci_rp_read_bd_addr *rp = (void *) skb->data; 8671da177e4SLinus Torvalds 8689f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 869a9de9248SMarcel Holtmann 870a9de9248SMarcel Holtmann if (!rp->status) 871a9de9248SMarcel Holtmann bacpy(&hdev->bdaddr, &rp->bdaddr); 872a9de9248SMarcel Holtmann 87323bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status); 87423bb5763SJohan Hedberg } 87523bb5763SJohan Hedberg 876350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev, 877350ee4cfSAndrei Emeltchenko struct sk_buff *skb) 878350ee4cfSAndrei Emeltchenko { 879350ee4cfSAndrei Emeltchenko struct hci_rp_read_data_block_size *rp = (void *) skb->data; 880350ee4cfSAndrei Emeltchenko 8819f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 882350ee4cfSAndrei Emeltchenko 883350ee4cfSAndrei Emeltchenko if (rp->status) 884350ee4cfSAndrei Emeltchenko return; 885350ee4cfSAndrei Emeltchenko 886350ee4cfSAndrei Emeltchenko hdev->block_mtu = __le16_to_cpu(rp->max_acl_len); 887350ee4cfSAndrei Emeltchenko hdev->block_len = __le16_to_cpu(rp->block_len); 888350ee4cfSAndrei Emeltchenko hdev->num_blocks = __le16_to_cpu(rp->num_blocks); 889350ee4cfSAndrei Emeltchenko 890350ee4cfSAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 891350ee4cfSAndrei Emeltchenko 892350ee4cfSAndrei Emeltchenko BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu, 893350ee4cfSAndrei Emeltchenko hdev->block_cnt, hdev->block_len); 894350ee4cfSAndrei Emeltchenko 895350ee4cfSAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status); 896350ee4cfSAndrei Emeltchenko } 897350ee4cfSAndrei Emeltchenko 89823bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb) 89923bb5763SJohan Hedberg { 90023bb5763SJohan Hedberg __u8 status = *((__u8 *) skb->data); 90123bb5763SJohan Hedberg 9029f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 90323bb5763SJohan Hedberg 90423bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status); 9051da177e4SLinus Torvalds } 9061da177e4SLinus Torvalds 907928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev, 908928abaa7SAndrei Emeltchenko struct sk_buff *skb) 909928abaa7SAndrei Emeltchenko { 910928abaa7SAndrei Emeltchenko struct hci_rp_read_local_amp_info *rp = (void *) skb->data; 911928abaa7SAndrei Emeltchenko 9129f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 913928abaa7SAndrei Emeltchenko 914928abaa7SAndrei Emeltchenko if (rp->status) 9158e2a0d92SAndrei Emeltchenko goto a2mp_rsp; 916928abaa7SAndrei Emeltchenko 917928abaa7SAndrei Emeltchenko hdev->amp_status = rp->amp_status; 918928abaa7SAndrei Emeltchenko hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); 919928abaa7SAndrei Emeltchenko hdev->amp_max_bw = __le32_to_cpu(rp->max_bw); 920928abaa7SAndrei Emeltchenko hdev->amp_min_latency = __le32_to_cpu(rp->min_latency); 921928abaa7SAndrei Emeltchenko hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu); 922928abaa7SAndrei Emeltchenko hdev->amp_type = rp->amp_type; 923928abaa7SAndrei Emeltchenko hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap); 924928abaa7SAndrei Emeltchenko hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size); 925928abaa7SAndrei Emeltchenko hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); 926928abaa7SAndrei Emeltchenko hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); 927928abaa7SAndrei Emeltchenko 928928abaa7SAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status); 9298e2a0d92SAndrei Emeltchenko 9308e2a0d92SAndrei Emeltchenko a2mp_rsp: 9318e2a0d92SAndrei Emeltchenko a2mp_send_getinfo_rsp(hdev); 932928abaa7SAndrei Emeltchenko } 933928abaa7SAndrei Emeltchenko 934903e4541SAndrei Emeltchenko static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev, 935903e4541SAndrei Emeltchenko struct sk_buff *skb) 936903e4541SAndrei Emeltchenko { 937903e4541SAndrei Emeltchenko struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data; 938903e4541SAndrei Emeltchenko struct amp_assoc *assoc = &hdev->loc_assoc; 939903e4541SAndrei Emeltchenko size_t rem_len, frag_len; 940903e4541SAndrei Emeltchenko 941903e4541SAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 942903e4541SAndrei Emeltchenko 943903e4541SAndrei Emeltchenko if (rp->status) 944903e4541SAndrei Emeltchenko goto a2mp_rsp; 945903e4541SAndrei Emeltchenko 946903e4541SAndrei Emeltchenko frag_len = skb->len - sizeof(*rp); 947903e4541SAndrei Emeltchenko rem_len = __le16_to_cpu(rp->rem_len); 948903e4541SAndrei Emeltchenko 949903e4541SAndrei Emeltchenko if (rem_len > frag_len) { 9502e430be3SAndrei Emeltchenko BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len); 951903e4541SAndrei Emeltchenko 952903e4541SAndrei Emeltchenko memcpy(assoc->data + assoc->offset, rp->frag, frag_len); 953903e4541SAndrei Emeltchenko assoc->offset += frag_len; 954903e4541SAndrei Emeltchenko 955903e4541SAndrei Emeltchenko /* Read other fragments */ 956903e4541SAndrei Emeltchenko amp_read_loc_assoc_frag(hdev, rp->phy_handle); 957903e4541SAndrei Emeltchenko 958903e4541SAndrei Emeltchenko return; 959903e4541SAndrei Emeltchenko } 960903e4541SAndrei Emeltchenko 961903e4541SAndrei Emeltchenko memcpy(assoc->data + assoc->offset, rp->frag, rem_len); 962903e4541SAndrei Emeltchenko assoc->len = assoc->offset + rem_len; 963903e4541SAndrei Emeltchenko assoc->offset = 0; 964903e4541SAndrei Emeltchenko 965903e4541SAndrei Emeltchenko a2mp_rsp: 966903e4541SAndrei Emeltchenko /* Send A2MP Rsp when all fragments are received */ 967903e4541SAndrei Emeltchenko a2mp_send_getampassoc_rsp(hdev, rp->status); 9689495b2eeSAndrei Emeltchenko a2mp_send_create_phy_link_req(hdev, rp->status); 969903e4541SAndrei Emeltchenko } 970903e4541SAndrei Emeltchenko 971b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, 972b0916ea0SJohan Hedberg struct sk_buff *skb) 973b0916ea0SJohan Hedberg { 974b0916ea0SJohan Hedberg __u8 status = *((__u8 *) skb->data); 975b0916ea0SJohan Hedberg 9769f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 977b0916ea0SJohan Hedberg 978b0916ea0SJohan Hedberg hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status); 979b0916ea0SJohan Hedberg } 980b0916ea0SJohan Hedberg 981d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb) 982d5859e22SJohan Hedberg { 983d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 984d5859e22SJohan Hedberg 9859f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 986d5859e22SJohan Hedberg 987d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status); 988d5859e22SJohan Hedberg } 989d5859e22SJohan Hedberg 990d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev, 991d5859e22SJohan Hedberg struct sk_buff *skb) 992d5859e22SJohan Hedberg { 993d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 994d5859e22SJohan Hedberg 9959f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 996d5859e22SJohan Hedberg 997d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status); 998d5859e22SJohan Hedberg } 999d5859e22SJohan Hedberg 1000d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, 1001d5859e22SJohan Hedberg struct sk_buff *skb) 1002d5859e22SJohan Hedberg { 100391c4e9b1SMarcel Holtmann struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data; 1004d5859e22SJohan Hedberg 10059f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1006d5859e22SJohan Hedberg 100791c4e9b1SMarcel Holtmann if (!rp->status) 100891c4e9b1SMarcel Holtmann hdev->inq_tx_power = rp->tx_power; 100991c4e9b1SMarcel Holtmann 101091c4e9b1SMarcel Holtmann hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status); 1011d5859e22SJohan Hedberg } 1012d5859e22SJohan Hedberg 1013d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb) 1014d5859e22SJohan Hedberg { 1015d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 1016d5859e22SJohan Hedberg 10179f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1018d5859e22SJohan Hedberg 1019d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status); 1020d5859e22SJohan Hedberg } 1021d5859e22SJohan Hedberg 1022980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) 1023980e1a53SJohan Hedberg { 1024980e1a53SJohan Hedberg struct hci_rp_pin_code_reply *rp = (void *) skb->data; 1025980e1a53SJohan Hedberg struct hci_cp_pin_code_reply *cp; 1026980e1a53SJohan Hedberg struct hci_conn *conn; 1027980e1a53SJohan Hedberg 10289f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1029980e1a53SJohan Hedberg 103056e5cb86SJohan Hedberg hci_dev_lock(hdev); 103156e5cb86SJohan Hedberg 1032a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1033744cf19eSJohan Hedberg mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); 1034980e1a53SJohan Hedberg 1035fa1bd918SMikel Astiz if (rp->status) 103656e5cb86SJohan Hedberg goto unlock; 1037980e1a53SJohan Hedberg 1038980e1a53SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); 1039980e1a53SJohan Hedberg if (!cp) 104056e5cb86SJohan Hedberg goto unlock; 1041980e1a53SJohan Hedberg 1042980e1a53SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 1043980e1a53SJohan Hedberg if (conn) 1044980e1a53SJohan Hedberg conn->pin_length = cp->pin_len; 104556e5cb86SJohan Hedberg 104656e5cb86SJohan Hedberg unlock: 104756e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1048980e1a53SJohan Hedberg } 1049980e1a53SJohan Hedberg 1050980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 1051980e1a53SJohan Hedberg { 1052980e1a53SJohan Hedberg struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data; 1053980e1a53SJohan Hedberg 10549f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1055980e1a53SJohan Hedberg 105656e5cb86SJohan Hedberg hci_dev_lock(hdev); 105756e5cb86SJohan Hedberg 1058a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1059744cf19eSJohan Hedberg mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr, 1060980e1a53SJohan Hedberg rp->status); 106156e5cb86SJohan Hedberg 106256e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1063980e1a53SJohan Hedberg } 106456e5cb86SJohan Hedberg 10656ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, 10666ed58ec5SVille Tervo struct sk_buff *skb) 10676ed58ec5SVille Tervo { 10686ed58ec5SVille Tervo struct hci_rp_le_read_buffer_size *rp = (void *) skb->data; 10696ed58ec5SVille Tervo 10709f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 10716ed58ec5SVille Tervo 10726ed58ec5SVille Tervo if (rp->status) 10736ed58ec5SVille Tervo return; 10746ed58ec5SVille Tervo 10756ed58ec5SVille Tervo hdev->le_mtu = __le16_to_cpu(rp->le_mtu); 10766ed58ec5SVille Tervo hdev->le_pkts = rp->le_max_pkt; 10776ed58ec5SVille Tervo 10786ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 10796ed58ec5SVille Tervo 10806ed58ec5SVille Tervo BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); 10816ed58ec5SVille Tervo 10826ed58ec5SVille Tervo hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status); 10836ed58ec5SVille Tervo } 1084980e1a53SJohan Hedberg 10858fa19098SJohan Hedberg static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, 10868fa19098SJohan Hedberg struct sk_buff *skb) 10878fa19098SJohan Hedberg { 10888fa19098SJohan Hedberg struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data; 10898fa19098SJohan Hedberg 10908fa19098SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 10918fa19098SJohan Hedberg 10928fa19098SJohan Hedberg if (!rp->status) 10938fa19098SJohan Hedberg hdev->adv_tx_power = rp->tx_power; 10948fa19098SJohan Hedberg 10958fa19098SJohan Hedberg hci_req_complete(hdev, HCI_OP_LE_READ_ADV_TX_POWER, rp->status); 10968fa19098SJohan Hedberg } 10978fa19098SJohan Hedberg 1098e36b04c8SJohan Hedberg static void hci_cc_le_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb) 1099e36b04c8SJohan Hedberg { 1100e36b04c8SJohan Hedberg __u8 status = *((__u8 *) skb->data); 1101e36b04c8SJohan Hedberg 1102e36b04c8SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 1103e36b04c8SJohan Hedberg 1104e36b04c8SJohan Hedberg hci_req_complete(hdev, HCI_OP_LE_SET_EVENT_MASK, status); 1105e36b04c8SJohan Hedberg } 1106e36b04c8SJohan Hedberg 1107a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) 1108a5c29683SJohan Hedberg { 1109a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 1110a5c29683SJohan Hedberg 11119f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1112a5c29683SJohan Hedberg 111356e5cb86SJohan Hedberg hci_dev_lock(hdev); 111456e5cb86SJohan Hedberg 1115a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 111604124681SGustavo F. Padovan mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0, 111704124681SGustavo F. Padovan rp->status); 111856e5cb86SJohan Hedberg 111956e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1120a5c29683SJohan Hedberg } 1121a5c29683SJohan Hedberg 1122a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, 1123a5c29683SJohan Hedberg struct sk_buff *skb) 1124a5c29683SJohan Hedberg { 1125a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 1126a5c29683SJohan Hedberg 11279f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1128a5c29683SJohan Hedberg 112956e5cb86SJohan Hedberg hci_dev_lock(hdev); 113056e5cb86SJohan Hedberg 1131a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1132744cf19eSJohan Hedberg mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr, 113304124681SGustavo F. Padovan ACL_LINK, 0, rp->status); 113456e5cb86SJohan Hedberg 113556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1136a5c29683SJohan Hedberg } 1137a5c29683SJohan Hedberg 11381143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb) 11391143d458SBrian Gix { 11401143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 11411143d458SBrian Gix 11429f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 11431143d458SBrian Gix 11441143d458SBrian Gix hci_dev_lock(hdev); 11451143d458SBrian Gix 1146a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1147272d90dfSJohan Hedberg mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 1148272d90dfSJohan Hedberg 0, rp->status); 11491143d458SBrian Gix 11501143d458SBrian Gix hci_dev_unlock(hdev); 11511143d458SBrian Gix } 11521143d458SBrian Gix 11531143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, 11541143d458SBrian Gix struct sk_buff *skb) 11551143d458SBrian Gix { 11561143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 11571143d458SBrian Gix 11589f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 11591143d458SBrian Gix 11601143d458SBrian Gix hci_dev_lock(hdev); 11611143d458SBrian Gix 1162a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 11631143d458SBrian Gix mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr, 116404124681SGustavo F. Padovan ACL_LINK, 0, rp->status); 11651143d458SBrian Gix 11661143d458SBrian Gix hci_dev_unlock(hdev); 11671143d458SBrian Gix } 11681143d458SBrian Gix 1169c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, 1170c35938b2SSzymon Janc struct sk_buff *skb) 1171c35938b2SSzymon Janc { 1172c35938b2SSzymon Janc struct hci_rp_read_local_oob_data *rp = (void *) skb->data; 1173c35938b2SSzymon Janc 11749f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1175c35938b2SSzymon Janc 117656e5cb86SJohan Hedberg hci_dev_lock(hdev); 1177744cf19eSJohan Hedberg mgmt_read_local_oob_data_reply_complete(hdev, rp->hash, 1178c35938b2SSzymon Janc rp->randomizer, rp->status); 117956e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1180c35938b2SSzymon Janc } 1181c35938b2SSzymon Janc 118207f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) 118307f7fa5dSAndre Guedes { 118407f7fa5dSAndre Guedes __u8 status = *((__u8 *) skb->data); 118507f7fa5dSAndre Guedes 11869f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 11877ba8b4beSAndre Guedes 11887ba8b4beSAndre Guedes hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status); 11893fd24153SAndre Guedes 11903fd24153SAndre Guedes if (status) { 11913fd24153SAndre Guedes hci_dev_lock(hdev); 11923fd24153SAndre Guedes mgmt_start_discovery_failed(hdev, status); 11933fd24153SAndre Guedes hci_dev_unlock(hdev); 11943fd24153SAndre Guedes return; 11953fd24153SAndre Guedes } 119607f7fa5dSAndre Guedes } 119707f7fa5dSAndre Guedes 1198eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, 1199eb9d91f5SAndre Guedes struct sk_buff *skb) 1200eb9d91f5SAndre Guedes { 1201eb9d91f5SAndre Guedes struct hci_cp_le_set_scan_enable *cp; 1202eb9d91f5SAndre Guedes __u8 status = *((__u8 *) skb->data); 1203eb9d91f5SAndre Guedes 12049f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1205eb9d91f5SAndre Guedes 1206eb9d91f5SAndre Guedes cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE); 1207eb9d91f5SAndre Guedes if (!cp) 1208eb9d91f5SAndre Guedes return; 1209eb9d91f5SAndre Guedes 121068a8aea4SAndrei Emeltchenko switch (cp->enable) { 121168a8aea4SAndrei Emeltchenko case LE_SCANNING_ENABLED: 12127ba8b4beSAndre Guedes hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status); 12137ba8b4beSAndre Guedes 12143fd24153SAndre Guedes if (status) { 12153fd24153SAndre Guedes hci_dev_lock(hdev); 12163fd24153SAndre Guedes mgmt_start_discovery_failed(hdev, status); 12173fd24153SAndre Guedes hci_dev_unlock(hdev); 12187ba8b4beSAndre Guedes return; 12193fd24153SAndre Guedes } 12207ba8b4beSAndre Guedes 1221d23264a8SAndre Guedes set_bit(HCI_LE_SCAN, &hdev->dev_flags); 1222d23264a8SAndre Guedes 1223a8f13c8cSAndre Guedes hci_dev_lock(hdev); 1224343f935bSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_FINDING); 1225a8f13c8cSAndre Guedes hci_dev_unlock(hdev); 122668a8aea4SAndrei Emeltchenko break; 122768a8aea4SAndrei Emeltchenko 122868a8aea4SAndrei Emeltchenko case LE_SCANNING_DISABLED: 1229c9ecc48eSAndre Guedes if (status) { 1230c9ecc48eSAndre Guedes hci_dev_lock(hdev); 1231c9ecc48eSAndre Guedes mgmt_stop_discovery_failed(hdev, status); 1232c9ecc48eSAndre Guedes hci_dev_unlock(hdev); 12337ba8b4beSAndre Guedes return; 1234c9ecc48eSAndre Guedes } 12357ba8b4beSAndre Guedes 1236d23264a8SAndre Guedes clear_bit(HCI_LE_SCAN, &hdev->dev_flags); 1237d23264a8SAndre Guedes 1238bc3dd33cSAndre Guedes if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED && 1239bc3dd33cSAndre Guedes hdev->discovery.state == DISCOVERY_FINDING) { 12405e0452c0SAndre Guedes mgmt_interleaved_discovery(hdev); 12415e0452c0SAndre Guedes } else { 1242c599008fSAndre Guedes hci_dev_lock(hdev); 1243c599008fSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 1244c599008fSAndre Guedes hci_dev_unlock(hdev); 12455e0452c0SAndre Guedes } 1246c599008fSAndre Guedes 124768a8aea4SAndrei Emeltchenko break; 124868a8aea4SAndrei Emeltchenko 124968a8aea4SAndrei Emeltchenko default: 125068a8aea4SAndrei Emeltchenko BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable); 125168a8aea4SAndrei Emeltchenko break; 125235815085SAndre Guedes } 1253eb9d91f5SAndre Guedes } 1254eb9d91f5SAndre Guedes 1255a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb) 1256a7a595f6SVinicius Costa Gomes { 1257a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_reply *rp = (void *) skb->data; 1258a7a595f6SVinicius Costa Gomes 12599f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1260a7a595f6SVinicius Costa Gomes 1261a7a595f6SVinicius Costa Gomes if (rp->status) 1262a7a595f6SVinicius Costa Gomes return; 1263a7a595f6SVinicius Costa Gomes 1264a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status); 1265a7a595f6SVinicius Costa Gomes } 1266a7a595f6SVinicius Costa Gomes 1267a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 1268a7a595f6SVinicius Costa Gomes { 1269a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data; 1270a7a595f6SVinicius Costa Gomes 12719f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1272a7a595f6SVinicius Costa Gomes 1273a7a595f6SVinicius Costa Gomes if (rp->status) 1274a7a595f6SVinicius Costa Gomes return; 1275a7a595f6SVinicius Costa Gomes 1276a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status); 1277a7a595f6SVinicius Costa Gomes } 1278a7a595f6SVinicius Costa Gomes 12796039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev, 1280f9b49306SAndre Guedes struct sk_buff *skb) 1281f9b49306SAndre Guedes { 128206199cf8SJohan Hedberg struct hci_cp_write_le_host_supported *sent; 1283f9b49306SAndre Guedes __u8 status = *((__u8 *) skb->data); 1284f9b49306SAndre Guedes 12859f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1286f9b49306SAndre Guedes 128706199cf8SJohan Hedberg sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED); 12888f984dfaSJohan Hedberg if (!sent) 1289f9b49306SAndre Guedes return; 1290f9b49306SAndre Guedes 12918f984dfaSJohan Hedberg if (!status) { 12928f984dfaSJohan Hedberg if (sent->le) 12938f984dfaSJohan Hedberg hdev->host_features[0] |= LMP_HOST_LE; 12948f984dfaSJohan Hedberg else 12958f984dfaSJohan Hedberg hdev->host_features[0] &= ~LMP_HOST_LE; 129653b2caabSJohan Hedberg 129753b2caabSJohan Hedberg if (sent->simul) 129853b2caabSJohan Hedberg hdev->host_features[0] |= LMP_HOST_LE_BREDR; 129953b2caabSJohan Hedberg else 130053b2caabSJohan Hedberg hdev->host_features[0] &= ~LMP_HOST_LE_BREDR; 13018f984dfaSJohan Hedberg } 13028f984dfaSJohan Hedberg 13038f984dfaSJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags) && 13048f984dfaSJohan Hedberg !test_bit(HCI_INIT, &hdev->flags)) 13058f984dfaSJohan Hedberg mgmt_le_enable_complete(hdev, sent->le, status); 13068f984dfaSJohan Hedberg 13078f984dfaSJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status); 1308f9b49306SAndre Guedes } 1309f9b49306SAndre Guedes 131093c284eeSAndrei Emeltchenko static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev, 131193c284eeSAndrei Emeltchenko struct sk_buff *skb) 131293c284eeSAndrei Emeltchenko { 131393c284eeSAndrei Emeltchenko struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data; 131493c284eeSAndrei Emeltchenko 131593c284eeSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x", 131693c284eeSAndrei Emeltchenko hdev->name, rp->status, rp->phy_handle); 131793c284eeSAndrei Emeltchenko 131893c284eeSAndrei Emeltchenko if (rp->status) 131993c284eeSAndrei Emeltchenko return; 132093c284eeSAndrei Emeltchenko 132193c284eeSAndrei Emeltchenko amp_write_rem_assoc_continue(hdev, rp->phy_handle); 132293c284eeSAndrei Emeltchenko } 132393c284eeSAndrei Emeltchenko 13246039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 1325a9de9248SMarcel Holtmann { 13269f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1327a9de9248SMarcel Holtmann 1328a9de9248SMarcel Holtmann if (status) { 132923bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 1330a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 133156e5cb86SJohan Hedberg hci_dev_lock(hdev); 1332a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 13337a135109SAndre Guedes mgmt_start_discovery_failed(hdev, status); 133456e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1335314b2381SJohan Hedberg return; 1336314b2381SJohan Hedberg } 1337314b2381SJohan Hedberg 133889352e7dSAndre Guedes set_bit(HCI_INQUIRY, &hdev->flags); 133989352e7dSAndre Guedes 134056e5cb86SJohan Hedberg hci_dev_lock(hdev); 1341343f935bSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_FINDING); 134256e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1343a9de9248SMarcel Holtmann } 1344a9de9248SMarcel Holtmann 13456039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 13461da177e4SLinus Torvalds { 1347a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 13481da177e4SLinus Torvalds struct hci_conn *conn; 13491da177e4SLinus Torvalds 13509f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1351a9de9248SMarcel Holtmann 1352a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 13531da177e4SLinus Torvalds if (!cp) 13541da177e4SLinus Torvalds return; 13551da177e4SLinus Torvalds 13561da177e4SLinus Torvalds hci_dev_lock(hdev); 13571da177e4SLinus Torvalds 13581da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 13591da177e4SLinus Torvalds 13606ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn); 13611da177e4SLinus Torvalds 13621da177e4SLinus Torvalds if (status) { 13631da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 13644c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 13651da177e4SLinus Torvalds conn->state = BT_CLOSED; 13661da177e4SLinus Torvalds hci_proto_connect_cfm(conn, status); 13671da177e4SLinus Torvalds hci_conn_del(conn); 13684c67bc74SMarcel Holtmann } else 13694c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 13701da177e4SLinus Torvalds } 13711da177e4SLinus Torvalds } else { 13721da177e4SLinus Torvalds if (!conn) { 13731da177e4SLinus Torvalds conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); 13741da177e4SLinus Torvalds if (conn) { 1375a0c808b3SJohan Hedberg conn->out = true; 13761da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 13771da177e4SLinus Torvalds } else 1378893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 13791da177e4SLinus Torvalds } 13801da177e4SLinus Torvalds } 13811da177e4SLinus Torvalds 13821da177e4SLinus Torvalds hci_dev_unlock(hdev); 13831da177e4SLinus Torvalds } 13841da177e4SLinus Torvalds 1385a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 13861da177e4SLinus Torvalds { 1387a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 13881da177e4SLinus Torvalds struct hci_conn *acl, *sco; 13891da177e4SLinus Torvalds __u16 handle; 13901da177e4SLinus Torvalds 13919f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1392b6a0dc82SMarcel Holtmann 1393a9de9248SMarcel Holtmann if (!status) 1394a9de9248SMarcel Holtmann return; 1395a9de9248SMarcel Holtmann 1396a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 13971da177e4SLinus Torvalds if (!cp) 1398a9de9248SMarcel Holtmann return; 13991da177e4SLinus Torvalds 14001da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 14011da177e4SLinus Torvalds 14029f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, handle); 14031da177e4SLinus Torvalds 14041da177e4SLinus Torvalds hci_dev_lock(hdev); 14051da177e4SLinus Torvalds 14061da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 14075a08ecceSAndrei Emeltchenko if (acl) { 14085a08ecceSAndrei Emeltchenko sco = acl->link; 14095a08ecceSAndrei Emeltchenko if (sco) { 14101da177e4SLinus Torvalds sco->state = BT_CLOSED; 14111da177e4SLinus Torvalds 14121da177e4SLinus Torvalds hci_proto_connect_cfm(sco, status); 14131da177e4SLinus Torvalds hci_conn_del(sco); 14141da177e4SLinus Torvalds } 14155a08ecceSAndrei Emeltchenko } 14161da177e4SLinus Torvalds 14171da177e4SLinus Torvalds hci_dev_unlock(hdev); 14181da177e4SLinus Torvalds } 14191da177e4SLinus Torvalds 1420f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 1421f8558555SMarcel Holtmann { 1422f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 1423f8558555SMarcel Holtmann struct hci_conn *conn; 1424f8558555SMarcel Holtmann 14259f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1426f8558555SMarcel Holtmann 1427f8558555SMarcel Holtmann if (!status) 1428f8558555SMarcel Holtmann return; 1429f8558555SMarcel Holtmann 1430f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 1431f8558555SMarcel Holtmann if (!cp) 1432f8558555SMarcel Holtmann return; 1433f8558555SMarcel Holtmann 1434f8558555SMarcel Holtmann hci_dev_lock(hdev); 1435f8558555SMarcel Holtmann 1436f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1437f8558555SMarcel Holtmann if (conn) { 1438f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1439f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1440f8558555SMarcel Holtmann hci_conn_put(conn); 1441f8558555SMarcel Holtmann } 1442f8558555SMarcel Holtmann } 1443f8558555SMarcel Holtmann 1444f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1445f8558555SMarcel Holtmann } 1446f8558555SMarcel Holtmann 1447f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 1448f8558555SMarcel Holtmann { 1449f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 1450f8558555SMarcel Holtmann struct hci_conn *conn; 1451f8558555SMarcel Holtmann 14529f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1453f8558555SMarcel Holtmann 1454f8558555SMarcel Holtmann if (!status) 1455f8558555SMarcel Holtmann return; 1456f8558555SMarcel Holtmann 1457f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 1458f8558555SMarcel Holtmann if (!cp) 1459f8558555SMarcel Holtmann return; 1460f8558555SMarcel Holtmann 1461f8558555SMarcel Holtmann hci_dev_lock(hdev); 1462f8558555SMarcel Holtmann 1463f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1464f8558555SMarcel Holtmann if (conn) { 1465f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1466f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1467f8558555SMarcel Holtmann hci_conn_put(conn); 1468f8558555SMarcel Holtmann } 1469f8558555SMarcel Holtmann } 1470f8558555SMarcel Holtmann 1471f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1472f8558555SMarcel Holtmann } 1473f8558555SMarcel Holtmann 1474127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev, 1475392599b9SJohan Hedberg struct hci_conn *conn) 1476392599b9SJohan Hedberg { 1477392599b9SJohan Hedberg if (conn->state != BT_CONFIG || !conn->out) 1478392599b9SJohan Hedberg return 0; 1479392599b9SJohan Hedberg 1480765c2a96SJohan Hedberg if (conn->pending_sec_level == BT_SECURITY_SDP) 1481392599b9SJohan Hedberg return 0; 1482392599b9SJohan Hedberg 1483392599b9SJohan Hedberg /* Only request authentication for SSP connections or non-SSP 1484e9bf2bf0SVinicius Costa Gomes * devices with sec_level HIGH or if MITM protection is requested */ 1485807deac2SGustavo Padovan if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) && 1486807deac2SGustavo Padovan conn->pending_sec_level != BT_SECURITY_HIGH) 1487392599b9SJohan Hedberg return 0; 1488392599b9SJohan Hedberg 1489392599b9SJohan Hedberg return 1; 1490392599b9SJohan Hedberg } 1491392599b9SJohan Hedberg 14926039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev, 149300abfe44SGustavo F. Padovan struct inquiry_entry *e) 149430dc78e1SJohan Hedberg { 149530dc78e1SJohan Hedberg struct hci_cp_remote_name_req cp; 149630dc78e1SJohan Hedberg 149730dc78e1SJohan Hedberg memset(&cp, 0, sizeof(cp)); 149830dc78e1SJohan Hedberg 149930dc78e1SJohan Hedberg bacpy(&cp.bdaddr, &e->data.bdaddr); 150030dc78e1SJohan Hedberg cp.pscan_rep_mode = e->data.pscan_rep_mode; 150130dc78e1SJohan Hedberg cp.pscan_mode = e->data.pscan_mode; 150230dc78e1SJohan Hedberg cp.clock_offset = e->data.clock_offset; 150330dc78e1SJohan Hedberg 150430dc78e1SJohan Hedberg return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 150530dc78e1SJohan Hedberg } 150630dc78e1SJohan Hedberg 1507b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev) 150830dc78e1SJohan Hedberg { 150930dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 151030dc78e1SJohan Hedberg struct inquiry_entry *e; 151130dc78e1SJohan Hedberg 1512b644ba33SJohan Hedberg if (list_empty(&discov->resolve)) 1513b644ba33SJohan Hedberg return false; 1514b644ba33SJohan Hedberg 1515b644ba33SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 1516c810089cSRam Malovany if (!e) 1517c810089cSRam Malovany return false; 1518c810089cSRam Malovany 1519b644ba33SJohan Hedberg if (hci_resolve_name(hdev, e) == 0) { 1520b644ba33SJohan Hedberg e->name_state = NAME_PENDING; 1521b644ba33SJohan Hedberg return true; 1522b644ba33SJohan Hedberg } 1523b644ba33SJohan Hedberg 1524b644ba33SJohan Hedberg return false; 1525b644ba33SJohan Hedberg } 1526b644ba33SJohan Hedberg 1527b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn, 1528b644ba33SJohan Hedberg bdaddr_t *bdaddr, u8 *name, u8 name_len) 1529b644ba33SJohan Hedberg { 1530b644ba33SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 1531b644ba33SJohan Hedberg struct inquiry_entry *e; 1532b644ba33SJohan Hedberg 1533b644ba33SJohan Hedberg if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 153404124681SGustavo F. Padovan mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name, 153504124681SGustavo F. Padovan name_len, conn->dev_class); 1536b644ba33SJohan Hedberg 1537b644ba33SJohan Hedberg if (discov->state == DISCOVERY_STOPPED) 1538b644ba33SJohan Hedberg return; 1539b644ba33SJohan Hedberg 154030dc78e1SJohan Hedberg if (discov->state == DISCOVERY_STOPPING) 154130dc78e1SJohan Hedberg goto discov_complete; 154230dc78e1SJohan Hedberg 154330dc78e1SJohan Hedberg if (discov->state != DISCOVERY_RESOLVING) 154430dc78e1SJohan Hedberg return; 154530dc78e1SJohan Hedberg 154630dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING); 15477cc8380eSRam Malovany /* If the device was not found in a list of found devices names of which 15487cc8380eSRam Malovany * are pending. there is no need to continue resolving a next name as it 15497cc8380eSRam Malovany * will be done upon receiving another Remote Name Request Complete 15507cc8380eSRam Malovany * Event */ 15517cc8380eSRam Malovany if (!e) 15527cc8380eSRam Malovany return; 15537cc8380eSRam Malovany 155430dc78e1SJohan Hedberg list_del(&e->list); 15557cc8380eSRam Malovany if (name) { 15567cc8380eSRam Malovany e->name_state = NAME_KNOWN; 1557b644ba33SJohan Hedberg mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, 1558b644ba33SJohan Hedberg e->data.rssi, name, name_len); 1559c3e7c0d9SRam Malovany } else { 1560c3e7c0d9SRam Malovany e->name_state = NAME_NOT_KNOWN; 156130dc78e1SJohan Hedberg } 156230dc78e1SJohan Hedberg 1563b644ba33SJohan Hedberg if (hci_resolve_next_name(hdev)) 156430dc78e1SJohan Hedberg return; 156530dc78e1SJohan Hedberg 156630dc78e1SJohan Hedberg discov_complete: 156730dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 156830dc78e1SJohan Hedberg } 156930dc78e1SJohan Hedberg 1570a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 15711da177e4SLinus Torvalds { 1572127178d2SJohan Hedberg struct hci_cp_remote_name_req *cp; 1573127178d2SJohan Hedberg struct hci_conn *conn; 1574127178d2SJohan Hedberg 15759f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1576127178d2SJohan Hedberg 1577127178d2SJohan Hedberg /* If successful wait for the name req complete event before 1578127178d2SJohan Hedberg * checking for the need to do authentication */ 1579127178d2SJohan Hedberg if (!status) 1580127178d2SJohan Hedberg return; 1581127178d2SJohan Hedberg 1582127178d2SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); 1583127178d2SJohan Hedberg if (!cp) 1584127178d2SJohan Hedberg return; 1585127178d2SJohan Hedberg 1586127178d2SJohan Hedberg hci_dev_lock(hdev); 1587127178d2SJohan Hedberg 1588127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 1589b644ba33SJohan Hedberg 1590b644ba33SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1591b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0); 1592b644ba33SJohan Hedberg 159379c6c70cSJohan Hedberg if (!conn) 159479c6c70cSJohan Hedberg goto unlock; 159579c6c70cSJohan Hedberg 159679c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 159779c6c70cSJohan Hedberg goto unlock; 159879c6c70cSJohan Hedberg 159951a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 1600127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1601127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1602127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1603127178d2SJohan Hedberg } 1604127178d2SJohan Hedberg 160579c6c70cSJohan Hedberg unlock: 1606127178d2SJohan Hedberg hci_dev_unlock(hdev); 1607a9de9248SMarcel Holtmann } 16081da177e4SLinus Torvalds 1609769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 1610769be974SMarcel Holtmann { 1611769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 1612769be974SMarcel Holtmann struct hci_conn *conn; 1613769be974SMarcel Holtmann 16149f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1615769be974SMarcel Holtmann 1616769be974SMarcel Holtmann if (!status) 1617769be974SMarcel Holtmann return; 1618769be974SMarcel Holtmann 1619769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 1620769be974SMarcel Holtmann if (!cp) 1621769be974SMarcel Holtmann return; 1622769be974SMarcel Holtmann 1623769be974SMarcel Holtmann hci_dev_lock(hdev); 1624769be974SMarcel Holtmann 1625769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1626769be974SMarcel Holtmann if (conn) { 1627769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1628769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1629769be974SMarcel Holtmann hci_conn_put(conn); 1630769be974SMarcel Holtmann } 1631769be974SMarcel Holtmann } 1632769be974SMarcel Holtmann 1633769be974SMarcel Holtmann hci_dev_unlock(hdev); 1634769be974SMarcel Holtmann } 1635769be974SMarcel Holtmann 1636769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 1637769be974SMarcel Holtmann { 1638769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features *cp; 1639769be974SMarcel Holtmann struct hci_conn *conn; 1640769be974SMarcel Holtmann 16419f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1642769be974SMarcel Holtmann 1643769be974SMarcel Holtmann if (!status) 1644769be974SMarcel Holtmann return; 1645769be974SMarcel Holtmann 1646769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 1647769be974SMarcel Holtmann if (!cp) 1648769be974SMarcel Holtmann return; 1649769be974SMarcel Holtmann 1650769be974SMarcel Holtmann hci_dev_lock(hdev); 1651769be974SMarcel Holtmann 1652769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1653769be974SMarcel Holtmann if (conn) { 1654769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1655769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1656769be974SMarcel Holtmann hci_conn_put(conn); 1657769be974SMarcel Holtmann } 1658769be974SMarcel Holtmann } 1659769be974SMarcel Holtmann 1660769be974SMarcel Holtmann hci_dev_unlock(hdev); 1661769be974SMarcel Holtmann } 1662769be974SMarcel Holtmann 1663a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 1664a9de9248SMarcel Holtmann { 1665b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 1666b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 1667b6a0dc82SMarcel Holtmann __u16 handle; 1668b6a0dc82SMarcel Holtmann 16699f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1670b6a0dc82SMarcel Holtmann 1671b6a0dc82SMarcel Holtmann if (!status) 1672b6a0dc82SMarcel Holtmann return; 1673b6a0dc82SMarcel Holtmann 1674b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 1675b6a0dc82SMarcel Holtmann if (!cp) 1676b6a0dc82SMarcel Holtmann return; 1677b6a0dc82SMarcel Holtmann 1678b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 1679b6a0dc82SMarcel Holtmann 16809f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, handle); 1681b6a0dc82SMarcel Holtmann 1682b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 1683b6a0dc82SMarcel Holtmann 1684b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 16855a08ecceSAndrei Emeltchenko if (acl) { 16865a08ecceSAndrei Emeltchenko sco = acl->link; 16875a08ecceSAndrei Emeltchenko if (sco) { 1688b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 1689b6a0dc82SMarcel Holtmann 1690b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(sco, status); 1691b6a0dc82SMarcel Holtmann hci_conn_del(sco); 1692b6a0dc82SMarcel Holtmann } 16935a08ecceSAndrei Emeltchenko } 1694b6a0dc82SMarcel Holtmann 1695b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 1696a9de9248SMarcel Holtmann } 1697a9de9248SMarcel Holtmann 1698a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 1699a9de9248SMarcel Holtmann { 1700a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 170104837f64SMarcel Holtmann struct hci_conn *conn; 170204837f64SMarcel Holtmann 17039f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1704a9de9248SMarcel Holtmann 1705a9de9248SMarcel Holtmann if (!status) 1706a9de9248SMarcel Holtmann return; 1707a9de9248SMarcel Holtmann 1708a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 170904837f64SMarcel Holtmann if (!cp) 1710a9de9248SMarcel Holtmann return; 171104837f64SMarcel Holtmann 171204837f64SMarcel Holtmann hci_dev_lock(hdev); 171304837f64SMarcel Holtmann 171404837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1715e73439d8SMarcel Holtmann if (conn) { 171651a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 171704837f64SMarcel Holtmann 171851a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1719e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1720e73439d8SMarcel Holtmann } 1721e73439d8SMarcel Holtmann 172204837f64SMarcel Holtmann hci_dev_unlock(hdev); 172304837f64SMarcel Holtmann } 172404837f64SMarcel Holtmann 1725a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 1726a9de9248SMarcel Holtmann { 1727a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 172804837f64SMarcel Holtmann struct hci_conn *conn; 172904837f64SMarcel Holtmann 17309f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1731a9de9248SMarcel Holtmann 1732a9de9248SMarcel Holtmann if (!status) 1733a9de9248SMarcel Holtmann return; 1734a9de9248SMarcel Holtmann 1735a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 173604837f64SMarcel Holtmann if (!cp) 1737a9de9248SMarcel Holtmann return; 173804837f64SMarcel Holtmann 173904837f64SMarcel Holtmann hci_dev_lock(hdev); 174004837f64SMarcel Holtmann 174104837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1742e73439d8SMarcel Holtmann if (conn) { 174351a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 174404837f64SMarcel Holtmann 174551a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1746e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1747e73439d8SMarcel Holtmann } 1748e73439d8SMarcel Holtmann 174904837f64SMarcel Holtmann hci_dev_unlock(hdev); 175004837f64SMarcel Holtmann } 175104837f64SMarcel Holtmann 175288c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) 175388c3df13SJohan Hedberg { 175488c3df13SJohan Hedberg struct hci_cp_disconnect *cp; 175588c3df13SJohan Hedberg struct hci_conn *conn; 175688c3df13SJohan Hedberg 175788c3df13SJohan Hedberg if (!status) 175888c3df13SJohan Hedberg return; 175988c3df13SJohan Hedberg 176088c3df13SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT); 176188c3df13SJohan Hedberg if (!cp) 176288c3df13SJohan Hedberg return; 176388c3df13SJohan Hedberg 176488c3df13SJohan Hedberg hci_dev_lock(hdev); 176588c3df13SJohan Hedberg 176688c3df13SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 176788c3df13SJohan Hedberg if (conn) 176888c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 176988c3df13SJohan Hedberg conn->dst_type, status); 177088c3df13SJohan Hedberg 177188c3df13SJohan Hedberg hci_dev_unlock(hdev); 177288c3df13SJohan Hedberg } 177388c3df13SJohan Hedberg 1774fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) 1775fcd89c09SVille Tervo { 1776fcd89c09SVille Tervo struct hci_conn *conn; 1777fcd89c09SVille Tervo 17789f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1779fcd89c09SVille Tervo 1780f00a06acSAndre Guedes if (status) { 1781fcd89c09SVille Tervo hci_dev_lock(hdev); 1782fcd89c09SVille Tervo 17830c95ab78SAndre Guedes conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); 1784f00a06acSAndre Guedes if (!conn) { 1785f00a06acSAndre Guedes hci_dev_unlock(hdev); 1786f00a06acSAndre Guedes return; 1787f00a06acSAndre Guedes } 1788fcd89c09SVille Tervo 17896ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn); 1790fcd89c09SVille Tervo 1791fcd89c09SVille Tervo conn->state = BT_CLOSED; 17920c95ab78SAndre Guedes mgmt_connect_failed(hdev, &conn->dst, conn->type, 1793328c9248SHemant Gupta conn->dst_type, status); 1794fcd89c09SVille Tervo hci_proto_connect_cfm(conn, status); 1795fcd89c09SVille Tervo hci_conn_del(conn); 1796fcd89c09SVille Tervo 1797fcd89c09SVille Tervo hci_dev_unlock(hdev); 1798fcd89c09SVille Tervo } 1799f00a06acSAndre Guedes } 1800fcd89c09SVille Tervo 1801a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) 1802a7a595f6SVinicius Costa Gomes { 18039f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1804a7a595f6SVinicius Costa Gomes } 1805a7a595f6SVinicius Costa Gomes 1806a02226d6SAndrei Emeltchenko static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status) 1807a02226d6SAndrei Emeltchenko { 180893c284eeSAndrei Emeltchenko struct hci_cp_create_phy_link *cp; 180993c284eeSAndrei Emeltchenko 1810a02226d6SAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 181193c284eeSAndrei Emeltchenko 181293c284eeSAndrei Emeltchenko cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK); 181393c284eeSAndrei Emeltchenko if (!cp) 181493c284eeSAndrei Emeltchenko return; 181593c284eeSAndrei Emeltchenko 1816e58917b9SAndrei Emeltchenko hci_dev_lock(hdev); 1817e58917b9SAndrei Emeltchenko 1818e58917b9SAndrei Emeltchenko if (status) { 1819e58917b9SAndrei Emeltchenko struct hci_conn *hcon; 1820e58917b9SAndrei Emeltchenko 1821e58917b9SAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle); 1822e58917b9SAndrei Emeltchenko if (hcon) 1823e58917b9SAndrei Emeltchenko hci_conn_del(hcon); 1824e58917b9SAndrei Emeltchenko } else { 182593c284eeSAndrei Emeltchenko amp_write_remote_assoc(hdev, cp->phy_handle); 1826a02226d6SAndrei Emeltchenko } 1827a02226d6SAndrei Emeltchenko 1828e58917b9SAndrei Emeltchenko hci_dev_unlock(hdev); 1829e58917b9SAndrei Emeltchenko } 1830e58917b9SAndrei Emeltchenko 18310b26ab9dSAndrei Emeltchenko static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status) 18320b26ab9dSAndrei Emeltchenko { 18330b26ab9dSAndrei Emeltchenko struct hci_cp_accept_phy_link *cp; 18340b26ab9dSAndrei Emeltchenko 18350b26ab9dSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 18360b26ab9dSAndrei Emeltchenko 18370b26ab9dSAndrei Emeltchenko if (status) 18380b26ab9dSAndrei Emeltchenko return; 18390b26ab9dSAndrei Emeltchenko 18400b26ab9dSAndrei Emeltchenko cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK); 18410b26ab9dSAndrei Emeltchenko if (!cp) 18420b26ab9dSAndrei Emeltchenko return; 18430b26ab9dSAndrei Emeltchenko 18440b26ab9dSAndrei Emeltchenko amp_write_remote_assoc(hdev, cp->phy_handle); 18450b26ab9dSAndrei Emeltchenko } 18460b26ab9dSAndrei Emeltchenko 18475ce66b59SAndrei Emeltchenko static void hci_cs_create_logical_link(struct hci_dev *hdev, u8 status) 18485ce66b59SAndrei Emeltchenko { 18495ce66b59SAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 18505ce66b59SAndrei Emeltchenko } 18515ce66b59SAndrei Emeltchenko 18526039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 18531da177e4SLinus Torvalds { 18541da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 185530dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 185630dc78e1SJohan Hedberg struct inquiry_entry *e; 18571da177e4SLinus Torvalds 18589f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 18591da177e4SLinus Torvalds 186023bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 18616bd57416SMarcel Holtmann 1862a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 186389352e7dSAndre Guedes 186489352e7dSAndre Guedes if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) 186589352e7dSAndre Guedes return; 186689352e7dSAndre Guedes 1867a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 186830dc78e1SJohan Hedberg return; 186930dc78e1SJohan Hedberg 187056e5cb86SJohan Hedberg hci_dev_lock(hdev); 187130dc78e1SJohan Hedberg 1872343f935bSAndre Guedes if (discov->state != DISCOVERY_FINDING) 187330dc78e1SJohan Hedberg goto unlock; 187430dc78e1SJohan Hedberg 187530dc78e1SJohan Hedberg if (list_empty(&discov->resolve)) { 1876ff9ef578SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 187730dc78e1SJohan Hedberg goto unlock; 187830dc78e1SJohan Hedberg } 187930dc78e1SJohan Hedberg 188030dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 188130dc78e1SJohan Hedberg if (e && hci_resolve_name(hdev, e) == 0) { 188230dc78e1SJohan Hedberg e->name_state = NAME_PENDING; 188330dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_RESOLVING); 188430dc78e1SJohan Hedberg } else { 188530dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 188630dc78e1SJohan Hedberg } 188730dc78e1SJohan Hedberg 188830dc78e1SJohan Hedberg unlock: 188956e5cb86SJohan Hedberg hci_dev_unlock(hdev); 18901da177e4SLinus Torvalds } 18911da177e4SLinus Torvalds 18926039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 18931da177e4SLinus Torvalds { 189445bb4bf0SMarcel Holtmann struct inquiry_data data; 1895a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 18961da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 18971da177e4SLinus Torvalds 18981da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 18991da177e4SLinus Torvalds 190045bb4bf0SMarcel Holtmann if (!num_rsp) 190145bb4bf0SMarcel Holtmann return; 190245bb4bf0SMarcel Holtmann 19031519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 19041519cc17SAndre Guedes return; 19051519cc17SAndre Guedes 19061da177e4SLinus Torvalds hci_dev_lock(hdev); 190745bb4bf0SMarcel Holtmann 1908e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 1909388fc8faSJohan Hedberg bool name_known, ssp; 19103175405bSJohan Hedberg 19111da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 19121da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 19131da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 19141da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 19151da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 19161da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 19171da177e4SLinus Torvalds data.rssi = 0x00; 191841a96212SMarcel Holtmann data.ssp_mode = 0x00; 19193175405bSJohan Hedberg 1920388fc8faSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp); 192148264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 192204124681SGustavo F. Padovan info->dev_class, 0, !name_known, ssp, NULL, 192304124681SGustavo F. Padovan 0); 19241da177e4SLinus Torvalds } 192545bb4bf0SMarcel Holtmann 19261da177e4SLinus Torvalds hci_dev_unlock(hdev); 19271da177e4SLinus Torvalds } 19281da177e4SLinus Torvalds 19296039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 19301da177e4SLinus Torvalds { 1931a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 1932a9de9248SMarcel Holtmann struct hci_conn *conn; 19331da177e4SLinus Torvalds 1934a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 193545bb4bf0SMarcel Holtmann 19361da177e4SLinus Torvalds hci_dev_lock(hdev); 193745bb4bf0SMarcel Holtmann 1938a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 19399499237aSMarcel Holtmann if (!conn) { 19409499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 19419499237aSMarcel Holtmann goto unlock; 19429499237aSMarcel Holtmann 19439499237aSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 1944a9de9248SMarcel Holtmann if (!conn) 1945a9de9248SMarcel Holtmann goto unlock; 194645bb4bf0SMarcel Holtmann 19479499237aSMarcel Holtmann conn->type = SCO_LINK; 19489499237aSMarcel Holtmann } 19499499237aSMarcel Holtmann 1950a9de9248SMarcel Holtmann if (!ev->status) { 1951a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 1952769be974SMarcel Holtmann 1953769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 1954769be974SMarcel Holtmann conn->state = BT_CONFIG; 1955769be974SMarcel Holtmann hci_conn_hold(conn); 1956a9ea3ed9SSzymon Janc 1957a9ea3ed9SSzymon Janc if (!conn->out && !hci_conn_ssp_enabled(conn) && 1958a9ea3ed9SSzymon Janc !hci_find_link_key(hdev, &ev->bdaddr)) 1959a9ea3ed9SSzymon Janc conn->disc_timeout = HCI_PAIRING_TIMEOUT; 1960a9ea3ed9SSzymon Janc else 1961052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1962769be974SMarcel Holtmann } else 1963a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 1964a9de9248SMarcel Holtmann 19659eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 19667d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 19677d0db0a3SMarcel Holtmann 1968a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 1969a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1970a9de9248SMarcel Holtmann 1971a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 1972a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1973a9de9248SMarcel Holtmann 1974a9de9248SMarcel Holtmann /* Get remote features */ 1975a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 1976a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 1977a9de9248SMarcel Holtmann cp.handle = ev->handle; 1978769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 1979769be974SMarcel Holtmann sizeof(cp), &cp); 198045bb4bf0SMarcel Holtmann } 1981a9de9248SMarcel Holtmann 1982a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 1983d095c1ebSAndrei Emeltchenko if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) { 1984a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 1985a9de9248SMarcel Holtmann cp.handle = ev->handle; 1986a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 198704124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp), 198804124681SGustavo F. Padovan &cp); 1989a9de9248SMarcel Holtmann } 199017d5c04cSJohan Hedberg } else { 1991a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 199217d5c04cSJohan Hedberg if (conn->type == ACL_LINK) 1993744cf19eSJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 199448264f06SJohan Hedberg conn->dst_type, ev->status); 199517d5c04cSJohan Hedberg } 199645bb4bf0SMarcel Holtmann 1997e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 1998e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 199945bb4bf0SMarcel Holtmann 2000769be974SMarcel Holtmann if (ev->status) { 2001a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2002a9de9248SMarcel Holtmann hci_conn_del(conn); 2003c89b6e6bSMarcel Holtmann } else if (ev->link_type != ACL_LINK) 2004c89b6e6bSMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2005a9de9248SMarcel Holtmann 2006a9de9248SMarcel Holtmann unlock: 20071da177e4SLinus Torvalds hci_dev_unlock(hdev); 2008a9de9248SMarcel Holtmann 2009a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 20101da177e4SLinus Torvalds } 20111da177e4SLinus Torvalds 20126039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 20131da177e4SLinus Torvalds { 2014a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 20151da177e4SLinus Torvalds int mask = hdev->link_mode; 20161da177e4SLinus Torvalds 20176ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr, 2018807deac2SGustavo Padovan ev->link_type); 20191da177e4SLinus Torvalds 20201da177e4SLinus Torvalds mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); 20211da177e4SLinus Torvalds 2022138d22efSSzymon Janc if ((mask & HCI_LM_ACCEPT) && 2023138d22efSSzymon Janc !hci_blacklist_lookup(hdev, &ev->bdaddr)) { 20241da177e4SLinus Torvalds /* Connection accepted */ 2025c7bdd502SMarcel Holtmann struct inquiry_entry *ie; 20261da177e4SLinus Torvalds struct hci_conn *conn; 20271da177e4SLinus Torvalds 20281da177e4SLinus Torvalds hci_dev_lock(hdev); 2029b6a0dc82SMarcel Holtmann 2030cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2031cc11b9c1SAndrei Emeltchenko if (ie) 2032c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 2033c7bdd502SMarcel Holtmann 20348fc9ced3SGustavo Padovan conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, 20358fc9ced3SGustavo Padovan &ev->bdaddr); 20361da177e4SLinus Torvalds if (!conn) { 2037cc11b9c1SAndrei Emeltchenko conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); 2038cc11b9c1SAndrei Emeltchenko if (!conn) { 2039893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 20401da177e4SLinus Torvalds hci_dev_unlock(hdev); 20411da177e4SLinus Torvalds return; 20421da177e4SLinus Torvalds } 20431da177e4SLinus Torvalds } 2044b6a0dc82SMarcel Holtmann 20451da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 20461da177e4SLinus Torvalds conn->state = BT_CONNECT; 2047b6a0dc82SMarcel Holtmann 20481da177e4SLinus Torvalds hci_dev_unlock(hdev); 20491da177e4SLinus Torvalds 2050b6a0dc82SMarcel Holtmann if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) { 2051b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 2052b6a0dc82SMarcel Holtmann 20531da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 20541da177e4SLinus Torvalds 20551da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 20561da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 20571da177e4SLinus Torvalds else 20581da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 20591da177e4SLinus Torvalds 206004124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), 206104124681SGustavo F. Padovan &cp); 2062b6a0dc82SMarcel Holtmann } else { 2063b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 2064b6a0dc82SMarcel Holtmann 2065b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 2066a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 2067b6a0dc82SMarcel Holtmann 206882781e63SAndrei Emeltchenko cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40); 206982781e63SAndrei Emeltchenko cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40); 207082781e63SAndrei Emeltchenko cp.max_latency = __constant_cpu_to_le16(0xffff); 2071b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 2072b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 2073b6a0dc82SMarcel Holtmann 2074b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 2075b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 2076b6a0dc82SMarcel Holtmann } 20771da177e4SLinus Torvalds } else { 20781da177e4SLinus Torvalds /* Connection rejected */ 20791da177e4SLinus Torvalds struct hci_cp_reject_conn_req cp; 20801da177e4SLinus Torvalds 20811da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 20829f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_REJ_BAD_ADDR; 2083a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 20841da177e4SLinus Torvalds } 20851da177e4SLinus Torvalds } 20861da177e4SLinus Torvalds 2087f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err) 2088f0d6a0eaSMikel Astiz { 2089f0d6a0eaSMikel Astiz switch (err) { 2090f0d6a0eaSMikel Astiz case HCI_ERROR_CONNECTION_TIMEOUT: 2091f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_TIMEOUT; 2092f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_USER_TERM: 2093f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_LOW_RESOURCES: 2094f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_POWER_OFF: 2095f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_REMOTE; 2096f0d6a0eaSMikel Astiz case HCI_ERROR_LOCAL_HOST_TERM: 2097f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_LOCAL_HOST; 2098f0d6a0eaSMikel Astiz default: 2099f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_UNKNOWN; 2100f0d6a0eaSMikel Astiz } 2101f0d6a0eaSMikel Astiz } 2102f0d6a0eaSMikel Astiz 21036039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 21041da177e4SLinus Torvalds { 2105a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 210604837f64SMarcel Holtmann struct hci_conn *conn; 21071da177e4SLinus Torvalds 21089f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 21091da177e4SLinus Torvalds 21101da177e4SLinus Torvalds hci_dev_lock(hdev); 21111da177e4SLinus Torvalds 211204837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2113f7520543SJohan Hedberg if (!conn) 2114f7520543SJohan Hedberg goto unlock; 2115f7520543SJohan Hedberg 211637d9ef76SJohan Hedberg if (ev->status == 0) 21171da177e4SLinus Torvalds conn->state = BT_CLOSED; 21187d0db0a3SMarcel Holtmann 2119b644ba33SJohan Hedberg if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) && 2120b644ba33SJohan Hedberg (conn->type == ACL_LINK || conn->type == LE_LINK)) { 2121f0d6a0eaSMikel Astiz if (ev->status) { 212288c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 212388c3df13SJohan Hedberg conn->dst_type, ev->status); 2124f0d6a0eaSMikel Astiz } else { 2125f0d6a0eaSMikel Astiz u8 reason = hci_to_mgmt_reason(ev->reason); 2126f0d6a0eaSMikel Astiz 2127afc747a6SJohan Hedberg mgmt_device_disconnected(hdev, &conn->dst, conn->type, 2128f0d6a0eaSMikel Astiz conn->dst_type, reason); 2129f0d6a0eaSMikel Astiz } 213037d9ef76SJohan Hedberg } 2131f7520543SJohan Hedberg 213237d9ef76SJohan Hedberg if (ev->status == 0) { 21336ec5bcadSVishal Agarwal if (conn->type == ACL_LINK && conn->flush_key) 21346ec5bcadSVishal Agarwal hci_remove_link_key(hdev, &conn->dst); 21352950f21aSMarcel Holtmann hci_proto_disconn_cfm(conn, ev->reason); 21361da177e4SLinus Torvalds hci_conn_del(conn); 213737d9ef76SJohan Hedberg } 21381da177e4SLinus Torvalds 2139f7520543SJohan Hedberg unlock: 21401da177e4SLinus Torvalds hci_dev_unlock(hdev); 21411da177e4SLinus Torvalds } 21421da177e4SLinus Torvalds 21436039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2144a9de9248SMarcel Holtmann { 2145a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 2146a9de9248SMarcel Holtmann struct hci_conn *conn; 2147a9de9248SMarcel Holtmann 21489f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2149a9de9248SMarcel Holtmann 2150a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2151a9de9248SMarcel Holtmann 2152a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2153d7556e20SWaldemar Rymarkiewicz if (!conn) 2154d7556e20SWaldemar Rymarkiewicz goto unlock; 2155d7556e20SWaldemar Rymarkiewicz 2156765c2a96SJohan Hedberg if (!ev->status) { 2157aa64a8b5SJohan Hedberg if (!hci_conn_ssp_enabled(conn) && 215851a8efd7SJohan Hedberg test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) { 2159d7556e20SWaldemar Rymarkiewicz BT_INFO("re-auth of legacy device is not possible."); 216019f8def0SWaldemar Rymarkiewicz } else { 2161a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 2162765c2a96SJohan Hedberg conn->sec_level = conn->pending_sec_level; 216319f8def0SWaldemar Rymarkiewicz } 21642a611692SJohan Hedberg } else { 2165bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 2166bab73cb6SJohan Hedberg ev->status); 21672a611692SJohan Hedberg } 2168a9de9248SMarcel Holtmann 216951a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 217051a8efd7SJohan Hedberg clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags); 2171a9de9248SMarcel Holtmann 2172f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 2173aa64a8b5SJohan Hedberg if (!ev->status && hci_conn_ssp_enabled(conn)) { 2174f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 2175f8558555SMarcel Holtmann cp.handle = ev->handle; 2176f8558555SMarcel Holtmann cp.encrypt = 0x01; 2177d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 2178d7556e20SWaldemar Rymarkiewicz &cp); 2179f8558555SMarcel Holtmann } else { 2180f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 2181f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2182f8558555SMarcel Holtmann hci_conn_put(conn); 2183f8558555SMarcel Holtmann } 2184052b30b0SMarcel Holtmann } else { 2185a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 2186a9de9248SMarcel Holtmann 2187052b30b0SMarcel Holtmann hci_conn_hold(conn); 2188052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2189052b30b0SMarcel Holtmann hci_conn_put(conn); 2190052b30b0SMarcel Holtmann } 2191052b30b0SMarcel Holtmann 219251a8efd7SJohan Hedberg if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) { 2193a9de9248SMarcel Holtmann if (!ev->status) { 2194a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 2195f8558555SMarcel Holtmann cp.handle = ev->handle; 2196f8558555SMarcel Holtmann cp.encrypt = 0x01; 2197d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 2198d7556e20SWaldemar Rymarkiewicz &cp); 2199a9de9248SMarcel Holtmann } else { 220051a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 2201a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 2202a9de9248SMarcel Holtmann } 2203a9de9248SMarcel Holtmann } 2204a9de9248SMarcel Holtmann 2205d7556e20SWaldemar Rymarkiewicz unlock: 2206a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2207a9de9248SMarcel Holtmann } 2208a9de9248SMarcel Holtmann 22096039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 2210a9de9248SMarcel Holtmann { 2211127178d2SJohan Hedberg struct hci_ev_remote_name *ev = (void *) skb->data; 2212127178d2SJohan Hedberg struct hci_conn *conn; 2213127178d2SJohan Hedberg 2214a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2215a9de9248SMarcel Holtmann 2216a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 2217127178d2SJohan Hedberg 2218127178d2SJohan Hedberg hci_dev_lock(hdev); 2219127178d2SJohan Hedberg 2220127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2221b644ba33SJohan Hedberg 2222b644ba33SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 2223b644ba33SJohan Hedberg goto check_auth; 2224b644ba33SJohan Hedberg 2225b644ba33SJohan Hedberg if (ev->status == 0) 2226b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name, 2227b644ba33SJohan Hedberg strnlen(ev->name, HCI_MAX_NAME_LENGTH)); 2228b644ba33SJohan Hedberg else 2229b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0); 2230b644ba33SJohan Hedberg 2231b644ba33SJohan Hedberg check_auth: 223279c6c70cSJohan Hedberg if (!conn) 223379c6c70cSJohan Hedberg goto unlock; 223479c6c70cSJohan Hedberg 223579c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 223679c6c70cSJohan Hedberg goto unlock; 223779c6c70cSJohan Hedberg 223851a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 2239127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 2240127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 2241127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 2242127178d2SJohan Hedberg } 2243127178d2SJohan Hedberg 224479c6c70cSJohan Hedberg unlock: 2245127178d2SJohan Hedberg hci_dev_unlock(hdev); 2246a9de9248SMarcel Holtmann } 2247a9de9248SMarcel Holtmann 22486039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2249a9de9248SMarcel Holtmann { 2250a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 2251a9de9248SMarcel Holtmann struct hci_conn *conn; 2252a9de9248SMarcel Holtmann 22539f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2254a9de9248SMarcel Holtmann 2255a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2256a9de9248SMarcel Holtmann 2257a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2258a9de9248SMarcel Holtmann if (conn) { 2259a9de9248SMarcel Holtmann if (!ev->status) { 2260ae293196SMarcel Holtmann if (ev->encrypt) { 2261ae293196SMarcel Holtmann /* Encryption implies authentication */ 2262ae293196SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 2263a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 2264da85e5e5SVinicius Costa Gomes conn->sec_level = conn->pending_sec_level; 2265ae293196SMarcel Holtmann } else 2266a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_ENCRYPT; 2267a9de9248SMarcel Holtmann } 2268a9de9248SMarcel Holtmann 226951a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 2270a9de9248SMarcel Holtmann 2271a7d7723aSGustavo Padovan if (ev->status && conn->state == BT_CONNECTED) { 2272d839c813SGustavo Padovan hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE); 2273a7d7723aSGustavo Padovan hci_conn_put(conn); 2274a7d7723aSGustavo Padovan goto unlock; 2275a7d7723aSGustavo Padovan } 2276a7d7723aSGustavo Padovan 2277f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 2278f8558555SMarcel Holtmann if (!ev->status) 2279f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 2280f8558555SMarcel Holtmann 2281f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2282f8558555SMarcel Holtmann hci_conn_put(conn); 2283f8558555SMarcel Holtmann } else 2284a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 2285a9de9248SMarcel Holtmann } 2286a9de9248SMarcel Holtmann 2287a7d7723aSGustavo Padovan unlock: 2288a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2289a9de9248SMarcel Holtmann } 2290a9de9248SMarcel Holtmann 22916039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev, 2292807deac2SGustavo Padovan struct sk_buff *skb) 2293a9de9248SMarcel Holtmann { 2294a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 2295a9de9248SMarcel Holtmann struct hci_conn *conn; 2296a9de9248SMarcel Holtmann 22979f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2298a9de9248SMarcel Holtmann 2299a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2300a9de9248SMarcel Holtmann 2301a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2302a9de9248SMarcel Holtmann if (conn) { 2303a9de9248SMarcel Holtmann if (!ev->status) 2304a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_SECURE; 2305a9de9248SMarcel Holtmann 230651a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 2307a9de9248SMarcel Holtmann 2308a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 2309a9de9248SMarcel Holtmann } 2310a9de9248SMarcel Holtmann 2311a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2312a9de9248SMarcel Holtmann } 2313a9de9248SMarcel Holtmann 23146039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev, 2315807deac2SGustavo Padovan struct sk_buff *skb) 2316a9de9248SMarcel Holtmann { 2317a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 2318a9de9248SMarcel Holtmann struct hci_conn *conn; 2319a9de9248SMarcel Holtmann 23209f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2321a9de9248SMarcel Holtmann 2322a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2323a9de9248SMarcel Holtmann 2324a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2325ccd556feSJohan Hedberg if (!conn) 2326ccd556feSJohan Hedberg goto unlock; 2327ccd556feSJohan Hedberg 2328769be974SMarcel Holtmann if (!ev->status) 2329a9de9248SMarcel Holtmann memcpy(conn->features, ev->features, 8); 2330a9de9248SMarcel Holtmann 2331ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2332ccd556feSJohan Hedberg goto unlock; 2333ccd556feSJohan Hedberg 2334ccd556feSJohan Hedberg if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { 2335769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 2336769be974SMarcel Holtmann cp.handle = ev->handle; 2337769be974SMarcel Holtmann cp.page = 0x01; 2338ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 2339769be974SMarcel Holtmann sizeof(cp), &cp); 2340392599b9SJohan Hedberg goto unlock; 2341392599b9SJohan Hedberg } 2342392599b9SJohan Hedberg 2343671267bfSJohan Hedberg if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { 2344127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2345127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2346127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2347127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2348127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2349b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 2350b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 235108c79b61SJohan Hedberg conn->dst_type, 0, NULL, 0, 2352b644ba33SJohan Hedberg conn->dev_class); 2353392599b9SJohan Hedberg 2354127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2355769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2356769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2357769be974SMarcel Holtmann hci_conn_put(conn); 2358769be974SMarcel Holtmann } 2359769be974SMarcel Holtmann 2360ccd556feSJohan Hedberg unlock: 2361a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2362a9de9248SMarcel Holtmann } 2363a9de9248SMarcel Holtmann 23646039aa73SGustavo Padovan static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) 23656039aa73SGustavo Padovan { 23666039aa73SGustavo Padovan BT_DBG("%s", hdev->name); 23676039aa73SGustavo Padovan } 23686039aa73SGustavo Padovan 23696039aa73SGustavo Padovan static void hci_qos_setup_complete_evt(struct hci_dev *hdev, 2370807deac2SGustavo Padovan struct sk_buff *skb) 2371a9de9248SMarcel Holtmann { 2372a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2373a9de9248SMarcel Holtmann } 2374a9de9248SMarcel Holtmann 23756039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2376a9de9248SMarcel Holtmann { 2377a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 2378a9de9248SMarcel Holtmann __u16 opcode; 2379a9de9248SMarcel Holtmann 2380a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2381a9de9248SMarcel Holtmann 2382a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2383a9de9248SMarcel Holtmann 2384a9de9248SMarcel Holtmann switch (opcode) { 2385a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 2386a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 2387a9de9248SMarcel Holtmann break; 2388a9de9248SMarcel Holtmann 23894d93483bSAndre Guedes case HCI_OP_PERIODIC_INQ: 23904d93483bSAndre Guedes hci_cc_periodic_inq(hdev, skb); 23914d93483bSAndre Guedes break; 23924d93483bSAndre Guedes 2393a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 2394a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 2395a9de9248SMarcel Holtmann break; 2396a9de9248SMarcel Holtmann 2397a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 2398a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 2399a9de9248SMarcel Holtmann break; 2400a9de9248SMarcel Holtmann 2401a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 2402a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 2403a9de9248SMarcel Holtmann break; 2404a9de9248SMarcel Holtmann 2405e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 2406e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 2407e4e8e37cSMarcel Holtmann break; 2408e4e8e37cSMarcel Holtmann 2409a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 2410a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 2411a9de9248SMarcel Holtmann break; 2412a9de9248SMarcel Holtmann 2413e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 2414e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 2415e4e8e37cSMarcel Holtmann break; 2416e4e8e37cSMarcel Holtmann 2417e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 2418e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 2419e4e8e37cSMarcel Holtmann break; 2420e4e8e37cSMarcel Holtmann 2421a9de9248SMarcel Holtmann case HCI_OP_RESET: 2422a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 2423a9de9248SMarcel Holtmann break; 2424a9de9248SMarcel Holtmann 2425a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 2426a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 2427a9de9248SMarcel Holtmann break; 2428a9de9248SMarcel Holtmann 2429a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 2430a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 2431a9de9248SMarcel Holtmann break; 2432a9de9248SMarcel Holtmann 2433a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 2434a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 2435a9de9248SMarcel Holtmann break; 2436a9de9248SMarcel Holtmann 2437a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 2438a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 2439a9de9248SMarcel Holtmann break; 2440a9de9248SMarcel Holtmann 2441a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 2442a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 2443a9de9248SMarcel Holtmann break; 2444a9de9248SMarcel Holtmann 2445a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 2446a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 2447a9de9248SMarcel Holtmann break; 2448a9de9248SMarcel Holtmann 2449a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 2450a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 2451a9de9248SMarcel Holtmann break; 2452a9de9248SMarcel Holtmann 2453a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 2454a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 2455a9de9248SMarcel Holtmann break; 2456a9de9248SMarcel Holtmann 2457a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 2458a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 2459a9de9248SMarcel Holtmann break; 2460a9de9248SMarcel Holtmann 2461a9de9248SMarcel Holtmann case HCI_OP_HOST_BUFFER_SIZE: 2462a9de9248SMarcel Holtmann hci_cc_host_buffer_size(hdev, skb); 2463a9de9248SMarcel Holtmann break; 2464a9de9248SMarcel Holtmann 2465333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 2466333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 2467333140b5SMarcel Holtmann break; 2468333140b5SMarcel Holtmann 2469a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 2470a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 2471a9de9248SMarcel Holtmann break; 2472a9de9248SMarcel Holtmann 2473a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 2474a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 2475a9de9248SMarcel Holtmann break; 2476a9de9248SMarcel Holtmann 2477a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 2478a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 2479a9de9248SMarcel Holtmann break; 2480a9de9248SMarcel Holtmann 2481971e3a4bSAndre Guedes case HCI_OP_READ_LOCAL_EXT_FEATURES: 2482971e3a4bSAndre Guedes hci_cc_read_local_ext_features(hdev, skb); 2483971e3a4bSAndre Guedes break; 2484971e3a4bSAndre Guedes 2485a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 2486a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 2487a9de9248SMarcel Holtmann break; 2488a9de9248SMarcel Holtmann 2489a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 2490a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 2491a9de9248SMarcel Holtmann break; 2492a9de9248SMarcel Holtmann 2493350ee4cfSAndrei Emeltchenko case HCI_OP_READ_DATA_BLOCK_SIZE: 2494350ee4cfSAndrei Emeltchenko hci_cc_read_data_block_size(hdev, skb); 2495350ee4cfSAndrei Emeltchenko break; 2496350ee4cfSAndrei Emeltchenko 249723bb5763SJohan Hedberg case HCI_OP_WRITE_CA_TIMEOUT: 249823bb5763SJohan Hedberg hci_cc_write_ca_timeout(hdev, skb); 249923bb5763SJohan Hedberg break; 250023bb5763SJohan Hedberg 25011e89cffbSAndrei Emeltchenko case HCI_OP_READ_FLOW_CONTROL_MODE: 25021e89cffbSAndrei Emeltchenko hci_cc_read_flow_control_mode(hdev, skb); 25031e89cffbSAndrei Emeltchenko break; 25041e89cffbSAndrei Emeltchenko 2505928abaa7SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_INFO: 2506928abaa7SAndrei Emeltchenko hci_cc_read_local_amp_info(hdev, skb); 2507928abaa7SAndrei Emeltchenko break; 2508928abaa7SAndrei Emeltchenko 2509903e4541SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_ASSOC: 2510903e4541SAndrei Emeltchenko hci_cc_read_local_amp_assoc(hdev, skb); 2511903e4541SAndrei Emeltchenko break; 2512903e4541SAndrei Emeltchenko 2513b0916ea0SJohan Hedberg case HCI_OP_DELETE_STORED_LINK_KEY: 2514b0916ea0SJohan Hedberg hci_cc_delete_stored_link_key(hdev, skb); 2515b0916ea0SJohan Hedberg break; 2516b0916ea0SJohan Hedberg 2517d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_MASK: 2518d5859e22SJohan Hedberg hci_cc_set_event_mask(hdev, skb); 2519d5859e22SJohan Hedberg break; 2520d5859e22SJohan Hedberg 2521d5859e22SJohan Hedberg case HCI_OP_WRITE_INQUIRY_MODE: 2522d5859e22SJohan Hedberg hci_cc_write_inquiry_mode(hdev, skb); 2523d5859e22SJohan Hedberg break; 2524d5859e22SJohan Hedberg 2525d5859e22SJohan Hedberg case HCI_OP_READ_INQ_RSP_TX_POWER: 2526d5859e22SJohan Hedberg hci_cc_read_inq_rsp_tx_power(hdev, skb); 2527d5859e22SJohan Hedberg break; 2528d5859e22SJohan Hedberg 2529d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_FLT: 2530d5859e22SJohan Hedberg hci_cc_set_event_flt(hdev, skb); 2531d5859e22SJohan Hedberg break; 2532d5859e22SJohan Hedberg 2533980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_REPLY: 2534980e1a53SJohan Hedberg hci_cc_pin_code_reply(hdev, skb); 2535980e1a53SJohan Hedberg break; 2536980e1a53SJohan Hedberg 2537980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_NEG_REPLY: 2538980e1a53SJohan Hedberg hci_cc_pin_code_neg_reply(hdev, skb); 2539980e1a53SJohan Hedberg break; 2540980e1a53SJohan Hedberg 2541c35938b2SSzymon Janc case HCI_OP_READ_LOCAL_OOB_DATA: 2542c35938b2SSzymon Janc hci_cc_read_local_oob_data_reply(hdev, skb); 2543c35938b2SSzymon Janc break; 2544c35938b2SSzymon Janc 25456ed58ec5SVille Tervo case HCI_OP_LE_READ_BUFFER_SIZE: 25466ed58ec5SVille Tervo hci_cc_le_read_buffer_size(hdev, skb); 25476ed58ec5SVille Tervo break; 25486ed58ec5SVille Tervo 25498fa19098SJohan Hedberg case HCI_OP_LE_READ_ADV_TX_POWER: 25508fa19098SJohan Hedberg hci_cc_le_read_adv_tx_power(hdev, skb); 25518fa19098SJohan Hedberg break; 25528fa19098SJohan Hedberg 2553e36b04c8SJohan Hedberg case HCI_OP_LE_SET_EVENT_MASK: 2554e36b04c8SJohan Hedberg hci_cc_le_set_event_mask(hdev, skb); 2555e36b04c8SJohan Hedberg break; 2556e36b04c8SJohan Hedberg 2557a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_REPLY: 2558a5c29683SJohan Hedberg hci_cc_user_confirm_reply(hdev, skb); 2559a5c29683SJohan Hedberg break; 2560a5c29683SJohan Hedberg 2561a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_NEG_REPLY: 2562a5c29683SJohan Hedberg hci_cc_user_confirm_neg_reply(hdev, skb); 2563a5c29683SJohan Hedberg break; 2564a5c29683SJohan Hedberg 25651143d458SBrian Gix case HCI_OP_USER_PASSKEY_REPLY: 25661143d458SBrian Gix hci_cc_user_passkey_reply(hdev, skb); 25671143d458SBrian Gix break; 25681143d458SBrian Gix 25691143d458SBrian Gix case HCI_OP_USER_PASSKEY_NEG_REPLY: 25701143d458SBrian Gix hci_cc_user_passkey_neg_reply(hdev, skb); 257116cde993SSzymon Janc break; 257207f7fa5dSAndre Guedes 257307f7fa5dSAndre Guedes case HCI_OP_LE_SET_SCAN_PARAM: 257407f7fa5dSAndre Guedes hci_cc_le_set_scan_param(hdev, skb); 25751143d458SBrian Gix break; 25761143d458SBrian Gix 2577eb9d91f5SAndre Guedes case HCI_OP_LE_SET_SCAN_ENABLE: 2578eb9d91f5SAndre Guedes hci_cc_le_set_scan_enable(hdev, skb); 2579eb9d91f5SAndre Guedes break; 2580eb9d91f5SAndre Guedes 2581a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_REPLY: 2582a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_reply(hdev, skb); 2583a7a595f6SVinicius Costa Gomes break; 2584a7a595f6SVinicius Costa Gomes 2585a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_NEG_REPLY: 2586a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_neg_reply(hdev, skb); 2587a7a595f6SVinicius Costa Gomes break; 2588a7a595f6SVinicius Costa Gomes 2589f9b49306SAndre Guedes case HCI_OP_WRITE_LE_HOST_SUPPORTED: 2590f9b49306SAndre Guedes hci_cc_write_le_host_supported(hdev, skb); 2591f9b49306SAndre Guedes break; 2592f9b49306SAndre Guedes 259393c284eeSAndrei Emeltchenko case HCI_OP_WRITE_REMOTE_AMP_ASSOC: 259493c284eeSAndrei Emeltchenko hci_cc_write_remote_amp_assoc(hdev, skb); 259593c284eeSAndrei Emeltchenko break; 259693c284eeSAndrei Emeltchenko 2597a9de9248SMarcel Holtmann default: 25989f1db00cSAndrei Emeltchenko BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); 2599a9de9248SMarcel Holtmann break; 2600a9de9248SMarcel Holtmann } 2601a9de9248SMarcel Holtmann 26026bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 26036bd32326SVille Tervo del_timer(&hdev->cmd_timer); 26046bd32326SVille Tervo 2605a9de9248SMarcel Holtmann if (ev->ncmd) { 2606a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2607a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2608c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2609a9de9248SMarcel Holtmann } 2610a9de9248SMarcel Holtmann } 2611a9de9248SMarcel Holtmann 26126039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 2613a9de9248SMarcel Holtmann { 2614a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 2615a9de9248SMarcel Holtmann __u16 opcode; 2616a9de9248SMarcel Holtmann 2617a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2618a9de9248SMarcel Holtmann 2619a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2620a9de9248SMarcel Holtmann 2621a9de9248SMarcel Holtmann switch (opcode) { 2622a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 2623a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 2624a9de9248SMarcel Holtmann break; 2625a9de9248SMarcel Holtmann 2626a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 2627a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 2628a9de9248SMarcel Holtmann break; 2629a9de9248SMarcel Holtmann 2630a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 2631a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 2632a9de9248SMarcel Holtmann break; 2633a9de9248SMarcel Holtmann 2634f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 2635f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 2636f8558555SMarcel Holtmann break; 2637f8558555SMarcel Holtmann 2638f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 2639f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 2640f8558555SMarcel Holtmann break; 2641f8558555SMarcel Holtmann 2642a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 2643a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 2644a9de9248SMarcel Holtmann break; 2645a9de9248SMarcel Holtmann 2646769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 2647769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 2648769be974SMarcel Holtmann break; 2649769be974SMarcel Holtmann 2650769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 2651769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 2652769be974SMarcel Holtmann break; 2653769be974SMarcel Holtmann 2654a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 2655a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 2656a9de9248SMarcel Holtmann break; 2657a9de9248SMarcel Holtmann 2658a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 2659a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 2660a9de9248SMarcel Holtmann break; 2661a9de9248SMarcel Holtmann 2662a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 2663a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 2664a9de9248SMarcel Holtmann break; 2665a9de9248SMarcel Holtmann 26668962ee74SJohan Hedberg case HCI_OP_DISCONNECT: 266788c3df13SJohan Hedberg hci_cs_disconnect(hdev, ev->status); 26688962ee74SJohan Hedberg break; 26698962ee74SJohan Hedberg 2670fcd89c09SVille Tervo case HCI_OP_LE_CREATE_CONN: 2671fcd89c09SVille Tervo hci_cs_le_create_conn(hdev, ev->status); 2672fcd89c09SVille Tervo break; 2673fcd89c09SVille Tervo 2674a7a595f6SVinicius Costa Gomes case HCI_OP_LE_START_ENC: 2675a7a595f6SVinicius Costa Gomes hci_cs_le_start_enc(hdev, ev->status); 2676a7a595f6SVinicius Costa Gomes break; 2677a7a595f6SVinicius Costa Gomes 2678a02226d6SAndrei Emeltchenko case HCI_OP_CREATE_PHY_LINK: 2679a02226d6SAndrei Emeltchenko hci_cs_create_phylink(hdev, ev->status); 2680a02226d6SAndrei Emeltchenko break; 2681a02226d6SAndrei Emeltchenko 26820b26ab9dSAndrei Emeltchenko case HCI_OP_ACCEPT_PHY_LINK: 26830b26ab9dSAndrei Emeltchenko hci_cs_accept_phylink(hdev, ev->status); 26840b26ab9dSAndrei Emeltchenko break; 26850b26ab9dSAndrei Emeltchenko 26865ce66b59SAndrei Emeltchenko case HCI_OP_CREATE_LOGICAL_LINK: 26875ce66b59SAndrei Emeltchenko hci_cs_create_logical_link(hdev, ev->status); 26885ce66b59SAndrei Emeltchenko break; 26895ce66b59SAndrei Emeltchenko 2690a9de9248SMarcel Holtmann default: 26919f1db00cSAndrei Emeltchenko BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); 2692a9de9248SMarcel Holtmann break; 2693a9de9248SMarcel Holtmann } 2694a9de9248SMarcel Holtmann 26956bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 26966bd32326SVille Tervo del_timer(&hdev->cmd_timer); 26976bd32326SVille Tervo 269810572132SGustavo F. Padovan if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2699a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2700a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2701c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2702a9de9248SMarcel Holtmann } 2703a9de9248SMarcel Holtmann } 2704a9de9248SMarcel Holtmann 27056039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2706a9de9248SMarcel Holtmann { 2707a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 2708a9de9248SMarcel Holtmann struct hci_conn *conn; 2709a9de9248SMarcel Holtmann 27109f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2711a9de9248SMarcel Holtmann 2712a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2713a9de9248SMarcel Holtmann 2714a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2715a9de9248SMarcel Holtmann if (conn) { 2716a9de9248SMarcel Holtmann if (!ev->status) { 2717a9de9248SMarcel Holtmann if (ev->role) 2718a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_MASTER; 2719a9de9248SMarcel Holtmann else 2720a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_MASTER; 2721a9de9248SMarcel Holtmann } 2722a9de9248SMarcel Holtmann 272351a8efd7SJohan Hedberg clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); 2724a9de9248SMarcel Holtmann 2725a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 2726a9de9248SMarcel Holtmann } 2727a9de9248SMarcel Holtmann 2728a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2729a9de9248SMarcel Holtmann } 2730a9de9248SMarcel Holtmann 27316039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 27321da177e4SLinus Torvalds { 2733a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 27341da177e4SLinus Torvalds int i; 27351da177e4SLinus Torvalds 273632ac5b9bSAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) { 273732ac5b9bSAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 273832ac5b9bSAndrei Emeltchenko return; 273932ac5b9bSAndrei Emeltchenko } 274032ac5b9bSAndrei Emeltchenko 2741c5993de8SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 2742c5993de8SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_pkts_info)) { 27431da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 27441da177e4SLinus Torvalds return; 27451da177e4SLinus Torvalds } 27461da177e4SLinus Torvalds 2747c5993de8SAndrei Emeltchenko BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 2748c5993de8SAndrei Emeltchenko 2749613a1c0cSAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 2750613a1c0cSAndrei Emeltchenko struct hci_comp_pkts_info *info = &ev->handles[i]; 27511da177e4SLinus Torvalds struct hci_conn *conn; 27521da177e4SLinus Torvalds __u16 handle, count; 27531da177e4SLinus Torvalds 2754613a1c0cSAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 2755613a1c0cSAndrei Emeltchenko count = __le16_to_cpu(info->count); 27561da177e4SLinus Torvalds 27571da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 2758f4280918SAndrei Emeltchenko if (!conn) 2759f4280918SAndrei Emeltchenko continue; 2760f4280918SAndrei Emeltchenko 27611da177e4SLinus Torvalds conn->sent -= count; 27621da177e4SLinus Torvalds 2763f4280918SAndrei Emeltchenko switch (conn->type) { 2764f4280918SAndrei Emeltchenko case ACL_LINK: 276570f23020SAndrei Emeltchenko hdev->acl_cnt += count; 276670f23020SAndrei Emeltchenko if (hdev->acl_cnt > hdev->acl_pkts) 27671da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 2768f4280918SAndrei Emeltchenko break; 2769f4280918SAndrei Emeltchenko 2770f4280918SAndrei Emeltchenko case LE_LINK: 27716ed58ec5SVille Tervo if (hdev->le_pkts) { 27726ed58ec5SVille Tervo hdev->le_cnt += count; 27736ed58ec5SVille Tervo if (hdev->le_cnt > hdev->le_pkts) 27746ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 27756ed58ec5SVille Tervo } else { 27766ed58ec5SVille Tervo hdev->acl_cnt += count; 27776ed58ec5SVille Tervo if (hdev->acl_cnt > hdev->acl_pkts) 27786ed58ec5SVille Tervo hdev->acl_cnt = hdev->acl_pkts; 27796ed58ec5SVille Tervo } 2780f4280918SAndrei Emeltchenko break; 2781f4280918SAndrei Emeltchenko 2782f4280918SAndrei Emeltchenko case SCO_LINK: 278370f23020SAndrei Emeltchenko hdev->sco_cnt += count; 278470f23020SAndrei Emeltchenko if (hdev->sco_cnt > hdev->sco_pkts) 27855b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 2786f4280918SAndrei Emeltchenko break; 2787f4280918SAndrei Emeltchenko 2788f4280918SAndrei Emeltchenko default: 2789f4280918SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 2790f4280918SAndrei Emeltchenko break; 27911da177e4SLinus Torvalds } 27921da177e4SLinus Torvalds } 2793a9de9248SMarcel Holtmann 27943eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 27951da177e4SLinus Torvalds } 27961da177e4SLinus Torvalds 279776ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev, 279876ef7cf7SAndrei Emeltchenko __u16 handle) 279976ef7cf7SAndrei Emeltchenko { 280076ef7cf7SAndrei Emeltchenko struct hci_chan *chan; 280176ef7cf7SAndrei Emeltchenko 280276ef7cf7SAndrei Emeltchenko switch (hdev->dev_type) { 280376ef7cf7SAndrei Emeltchenko case HCI_BREDR: 280476ef7cf7SAndrei Emeltchenko return hci_conn_hash_lookup_handle(hdev, handle); 280576ef7cf7SAndrei Emeltchenko case HCI_AMP: 280676ef7cf7SAndrei Emeltchenko chan = hci_chan_lookup_handle(hdev, handle); 280776ef7cf7SAndrei Emeltchenko if (chan) 280876ef7cf7SAndrei Emeltchenko return chan->conn; 280976ef7cf7SAndrei Emeltchenko break; 281076ef7cf7SAndrei Emeltchenko default: 281176ef7cf7SAndrei Emeltchenko BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type); 281276ef7cf7SAndrei Emeltchenko break; 281376ef7cf7SAndrei Emeltchenko } 281476ef7cf7SAndrei Emeltchenko 281576ef7cf7SAndrei Emeltchenko return NULL; 281676ef7cf7SAndrei Emeltchenko } 281776ef7cf7SAndrei Emeltchenko 28186039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb) 281925e89e99SAndrei Emeltchenko { 282025e89e99SAndrei Emeltchenko struct hci_ev_num_comp_blocks *ev = (void *) skb->data; 282125e89e99SAndrei Emeltchenko int i; 282225e89e99SAndrei Emeltchenko 282325e89e99SAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) { 282425e89e99SAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 282525e89e99SAndrei Emeltchenko return; 282625e89e99SAndrei Emeltchenko } 282725e89e99SAndrei Emeltchenko 282825e89e99SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 282925e89e99SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_blocks_info)) { 283025e89e99SAndrei Emeltchenko BT_DBG("%s bad parameters", hdev->name); 283125e89e99SAndrei Emeltchenko return; 283225e89e99SAndrei Emeltchenko } 283325e89e99SAndrei Emeltchenko 283425e89e99SAndrei Emeltchenko BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks, 283525e89e99SAndrei Emeltchenko ev->num_hndl); 283625e89e99SAndrei Emeltchenko 283725e89e99SAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 283825e89e99SAndrei Emeltchenko struct hci_comp_blocks_info *info = &ev->handles[i]; 283976ef7cf7SAndrei Emeltchenko struct hci_conn *conn = NULL; 284025e89e99SAndrei Emeltchenko __u16 handle, block_count; 284125e89e99SAndrei Emeltchenko 284225e89e99SAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 284325e89e99SAndrei Emeltchenko block_count = __le16_to_cpu(info->blocks); 284425e89e99SAndrei Emeltchenko 284576ef7cf7SAndrei Emeltchenko conn = __hci_conn_lookup_handle(hdev, handle); 284625e89e99SAndrei Emeltchenko if (!conn) 284725e89e99SAndrei Emeltchenko continue; 284825e89e99SAndrei Emeltchenko 284925e89e99SAndrei Emeltchenko conn->sent -= block_count; 285025e89e99SAndrei Emeltchenko 285125e89e99SAndrei Emeltchenko switch (conn->type) { 285225e89e99SAndrei Emeltchenko case ACL_LINK: 2853bd1eb66bSAndrei Emeltchenko case AMP_LINK: 285425e89e99SAndrei Emeltchenko hdev->block_cnt += block_count; 285525e89e99SAndrei Emeltchenko if (hdev->block_cnt > hdev->num_blocks) 285625e89e99SAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 285725e89e99SAndrei Emeltchenko break; 285825e89e99SAndrei Emeltchenko 285925e89e99SAndrei Emeltchenko default: 286025e89e99SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 286125e89e99SAndrei Emeltchenko break; 286225e89e99SAndrei Emeltchenko } 286325e89e99SAndrei Emeltchenko } 286425e89e99SAndrei Emeltchenko 286525e89e99SAndrei Emeltchenko queue_work(hdev->workqueue, &hdev->tx_work); 286625e89e99SAndrei Emeltchenko } 286725e89e99SAndrei Emeltchenko 28686039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 28691da177e4SLinus Torvalds { 2870a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 287104837f64SMarcel Holtmann struct hci_conn *conn; 28721da177e4SLinus Torvalds 28739f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 28741da177e4SLinus Torvalds 28751da177e4SLinus Torvalds hci_dev_lock(hdev); 28761da177e4SLinus Torvalds 287704837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 287804837f64SMarcel Holtmann if (conn) { 287904837f64SMarcel Holtmann conn->mode = ev->mode; 288004837f64SMarcel Holtmann conn->interval = __le16_to_cpu(ev->interval); 288104837f64SMarcel Holtmann 28828fc9ced3SGustavo Padovan if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, 28838fc9ced3SGustavo Padovan &conn->flags)) { 288404837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 288558a681efSJohan Hedberg set_bit(HCI_CONN_POWER_SAVE, &conn->flags); 288604837f64SMarcel Holtmann else 288758a681efSJohan Hedberg clear_bit(HCI_CONN_POWER_SAVE, &conn->flags); 288804837f64SMarcel Holtmann } 2889e73439d8SMarcel Holtmann 289051a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 2891e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 289204837f64SMarcel Holtmann } 289304837f64SMarcel Holtmann 289404837f64SMarcel Holtmann hci_dev_unlock(hdev); 289504837f64SMarcel Holtmann } 289604837f64SMarcel Holtmann 28976039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 28981da177e4SLinus Torvalds { 2899052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 2900052b30b0SMarcel Holtmann struct hci_conn *conn; 2901052b30b0SMarcel Holtmann 2902a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2903052b30b0SMarcel Holtmann 2904052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2905052b30b0SMarcel Holtmann 2906052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2907b6f98044SWaldemar Rymarkiewicz if (!conn) 2908b6f98044SWaldemar Rymarkiewicz goto unlock; 2909b6f98044SWaldemar Rymarkiewicz 2910b6f98044SWaldemar Rymarkiewicz if (conn->state == BT_CONNECTED) { 2911052b30b0SMarcel Holtmann hci_conn_hold(conn); 2912052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 2913052b30b0SMarcel Holtmann hci_conn_put(conn); 2914052b30b0SMarcel Holtmann } 2915052b30b0SMarcel Holtmann 2916a8b2d5c2SJohan Hedberg if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags)) 291703b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 291803b555e1SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 2919a8b2d5c2SJohan Hedberg else if (test_bit(HCI_MGMT, &hdev->dev_flags)) { 2920a770bb5aSWaldemar Rymarkiewicz u8 secure; 2921a770bb5aSWaldemar Rymarkiewicz 2922a770bb5aSWaldemar Rymarkiewicz if (conn->pending_sec_level == BT_SECURITY_HIGH) 2923a770bb5aSWaldemar Rymarkiewicz secure = 1; 2924a770bb5aSWaldemar Rymarkiewicz else 2925a770bb5aSWaldemar Rymarkiewicz secure = 0; 2926a770bb5aSWaldemar Rymarkiewicz 2927744cf19eSJohan Hedberg mgmt_pin_code_request(hdev, &ev->bdaddr, secure); 2928a770bb5aSWaldemar Rymarkiewicz } 2929980e1a53SJohan Hedberg 2930b6f98044SWaldemar Rymarkiewicz unlock: 2931052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 29321da177e4SLinus Torvalds } 29331da177e4SLinus Torvalds 29346039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 29351da177e4SLinus Torvalds { 293655ed8ca1SJohan Hedberg struct hci_ev_link_key_req *ev = (void *) skb->data; 293755ed8ca1SJohan Hedberg struct hci_cp_link_key_reply cp; 293855ed8ca1SJohan Hedberg struct hci_conn *conn; 293955ed8ca1SJohan Hedberg struct link_key *key; 294055ed8ca1SJohan Hedberg 2941a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 294255ed8ca1SJohan Hedberg 2943a8b2d5c2SJohan Hedberg if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) 294455ed8ca1SJohan Hedberg return; 294555ed8ca1SJohan Hedberg 294655ed8ca1SJohan Hedberg hci_dev_lock(hdev); 294755ed8ca1SJohan Hedberg 294855ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, &ev->bdaddr); 294955ed8ca1SJohan Hedberg if (!key) { 29506ed93dc6SAndrei Emeltchenko BT_DBG("%s link key not found for %pMR", hdev->name, 29516ed93dc6SAndrei Emeltchenko &ev->bdaddr); 295255ed8ca1SJohan Hedberg goto not_found; 295355ed8ca1SJohan Hedberg } 295455ed8ca1SJohan Hedberg 29556ed93dc6SAndrei Emeltchenko BT_DBG("%s found key type %u for %pMR", hdev->name, key->type, 29566ed93dc6SAndrei Emeltchenko &ev->bdaddr); 295755ed8ca1SJohan Hedberg 2958a8b2d5c2SJohan Hedberg if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) && 2959b6020ba0SWaldemar Rymarkiewicz key->type == HCI_LK_DEBUG_COMBINATION) { 296055ed8ca1SJohan Hedberg BT_DBG("%s ignoring debug key", hdev->name); 296155ed8ca1SJohan Hedberg goto not_found; 296255ed8ca1SJohan Hedberg } 296355ed8ca1SJohan Hedberg 296455ed8ca1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 296560b83f57SWaldemar Rymarkiewicz if (conn) { 296660b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_UNAUTH_COMBINATION && 2967807deac2SGustavo Padovan conn->auth_type != 0xff && (conn->auth_type & 0x01)) { 296855ed8ca1SJohan Hedberg BT_DBG("%s ignoring unauthenticated key", hdev->name); 296955ed8ca1SJohan Hedberg goto not_found; 297055ed8ca1SJohan Hedberg } 297155ed8ca1SJohan Hedberg 297260b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && 297360b83f57SWaldemar Rymarkiewicz conn->pending_sec_level == BT_SECURITY_HIGH) { 29748fc9ced3SGustavo Padovan BT_DBG("%s ignoring key unauthenticated for high security", 29758fc9ced3SGustavo Padovan hdev->name); 297660b83f57SWaldemar Rymarkiewicz goto not_found; 297760b83f57SWaldemar Rymarkiewicz } 297860b83f57SWaldemar Rymarkiewicz 297960b83f57SWaldemar Rymarkiewicz conn->key_type = key->type; 298060b83f57SWaldemar Rymarkiewicz conn->pin_length = key->pin_len; 298160b83f57SWaldemar Rymarkiewicz } 298260b83f57SWaldemar Rymarkiewicz 298355ed8ca1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 29849b3b4460SAndrei Emeltchenko memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE); 298555ed8ca1SJohan Hedberg 298655ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 298755ed8ca1SJohan Hedberg 298855ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 298955ed8ca1SJohan Hedberg 299055ed8ca1SJohan Hedberg return; 299155ed8ca1SJohan Hedberg 299255ed8ca1SJohan Hedberg not_found: 299355ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 299455ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 29951da177e4SLinus Torvalds } 29961da177e4SLinus Torvalds 29976039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 29981da177e4SLinus Torvalds { 2999052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 3000052b30b0SMarcel Holtmann struct hci_conn *conn; 300155ed8ca1SJohan Hedberg u8 pin_len = 0; 3002052b30b0SMarcel Holtmann 3003a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 3004052b30b0SMarcel Holtmann 3005052b30b0SMarcel Holtmann hci_dev_lock(hdev); 3006052b30b0SMarcel Holtmann 3007052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 3008052b30b0SMarcel Holtmann if (conn) { 3009052b30b0SMarcel Holtmann hci_conn_hold(conn); 3010052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 3011980e1a53SJohan Hedberg pin_len = conn->pin_length; 301213d39315SWaldemar Rymarkiewicz 301313d39315SWaldemar Rymarkiewicz if (ev->key_type != HCI_LK_CHANGED_COMBINATION) 301413d39315SWaldemar Rymarkiewicz conn->key_type = ev->key_type; 301513d39315SWaldemar Rymarkiewicz 3016052b30b0SMarcel Holtmann hci_conn_put(conn); 3017052b30b0SMarcel Holtmann } 3018052b30b0SMarcel Holtmann 3019a8b2d5c2SJohan Hedberg if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) 3020d25e28abSJohan Hedberg hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, 302155ed8ca1SJohan Hedberg ev->key_type, pin_len); 302255ed8ca1SJohan Hedberg 3023052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 30241da177e4SLinus Torvalds } 30251da177e4SLinus Torvalds 30266039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 302704837f64SMarcel Holtmann { 3028a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 302904837f64SMarcel Holtmann struct hci_conn *conn; 303004837f64SMarcel Holtmann 30319f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 303204837f64SMarcel Holtmann 303304837f64SMarcel Holtmann hci_dev_lock(hdev); 303404837f64SMarcel Holtmann 303504837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 30361da177e4SLinus Torvalds if (conn && !ev->status) { 30371da177e4SLinus Torvalds struct inquiry_entry *ie; 30381da177e4SLinus Torvalds 3039cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 3040cc11b9c1SAndrei Emeltchenko if (ie) { 30411da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 30421da177e4SLinus Torvalds ie->timestamp = jiffies; 30431da177e4SLinus Torvalds } 30441da177e4SLinus Torvalds } 30451da177e4SLinus Torvalds 30461da177e4SLinus Torvalds hci_dev_unlock(hdev); 30471da177e4SLinus Torvalds } 30481da177e4SLinus Torvalds 30496039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 3050a8746417SMarcel Holtmann { 3051a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 3052a8746417SMarcel Holtmann struct hci_conn *conn; 3053a8746417SMarcel Holtmann 30549f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 3055a8746417SMarcel Holtmann 3056a8746417SMarcel Holtmann hci_dev_lock(hdev); 3057a8746417SMarcel Holtmann 3058a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3059a8746417SMarcel Holtmann if (conn && !ev->status) 3060a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 3061a8746417SMarcel Holtmann 3062a8746417SMarcel Holtmann hci_dev_unlock(hdev); 3063a8746417SMarcel Holtmann } 3064a8746417SMarcel Holtmann 30656039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 306685a1e930SMarcel Holtmann { 3067a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 306885a1e930SMarcel Holtmann struct inquiry_entry *ie; 306985a1e930SMarcel Holtmann 307085a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 307185a1e930SMarcel Holtmann 307285a1e930SMarcel Holtmann hci_dev_lock(hdev); 307385a1e930SMarcel Holtmann 3074cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 3075cc11b9c1SAndrei Emeltchenko if (ie) { 307685a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 307785a1e930SMarcel Holtmann ie->timestamp = jiffies; 307885a1e930SMarcel Holtmann } 307985a1e930SMarcel Holtmann 308085a1e930SMarcel Holtmann hci_dev_unlock(hdev); 308185a1e930SMarcel Holtmann } 308285a1e930SMarcel Holtmann 30836039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, 3084807deac2SGustavo Padovan struct sk_buff *skb) 3085a9de9248SMarcel Holtmann { 3086a9de9248SMarcel Holtmann struct inquiry_data data; 3087a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 3088388fc8faSJohan Hedberg bool name_known, ssp; 3089a9de9248SMarcel Holtmann 3090a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 3091a9de9248SMarcel Holtmann 3092a9de9248SMarcel Holtmann if (!num_rsp) 3093a9de9248SMarcel Holtmann return; 3094a9de9248SMarcel Holtmann 30951519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 30961519cc17SAndre Guedes return; 30971519cc17SAndre Guedes 3098a9de9248SMarcel Holtmann hci_dev_lock(hdev); 3099a9de9248SMarcel Holtmann 3100a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 3101138d22efSSzymon Janc struct inquiry_info_with_rssi_and_pscan_mode *info; 3102138d22efSSzymon Janc info = (void *) (skb->data + 1); 3103a9de9248SMarcel Holtmann 3104e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 3105a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 3106a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 3107a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 3108a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 3109a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 3110a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 3111a9de9248SMarcel Holtmann data.rssi = info->rssi; 311241a96212SMarcel Holtmann data.ssp_mode = 0x00; 31133175405bSJohan Hedberg 31143175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 3115388fc8faSJohan Hedberg false, &ssp); 311648264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 3117e17acd40SJohan Hedberg info->dev_class, info->rssi, 3118388fc8faSJohan Hedberg !name_known, ssp, NULL, 0); 3119a9de9248SMarcel Holtmann } 3120a9de9248SMarcel Holtmann } else { 3121a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 3122a9de9248SMarcel Holtmann 3123e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 3124a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 3125a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 3126a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 3127a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 3128a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 3129a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 3130a9de9248SMarcel Holtmann data.rssi = info->rssi; 313141a96212SMarcel Holtmann data.ssp_mode = 0x00; 31323175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 3133388fc8faSJohan Hedberg false, &ssp); 313448264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 3135e17acd40SJohan Hedberg info->dev_class, info->rssi, 3136388fc8faSJohan Hedberg !name_known, ssp, NULL, 0); 3137a9de9248SMarcel Holtmann } 3138a9de9248SMarcel Holtmann } 3139a9de9248SMarcel Holtmann 3140a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 3141a9de9248SMarcel Holtmann } 3142a9de9248SMarcel Holtmann 31436039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev, 3144807deac2SGustavo Padovan struct sk_buff *skb) 3145a9de9248SMarcel Holtmann { 314641a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 314741a96212SMarcel Holtmann struct hci_conn *conn; 314841a96212SMarcel Holtmann 3149a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 315041a96212SMarcel Holtmann 315141a96212SMarcel Holtmann hci_dev_lock(hdev); 315241a96212SMarcel Holtmann 315341a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3154ccd556feSJohan Hedberg if (!conn) 3155ccd556feSJohan Hedberg goto unlock; 3156ccd556feSJohan Hedberg 3157769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 315841a96212SMarcel Holtmann struct inquiry_entry *ie; 315941a96212SMarcel Holtmann 3160cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 3161cc11b9c1SAndrei Emeltchenko if (ie) 316202b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 316341a96212SMarcel Holtmann 316402b7cc62SJohan Hedberg if (ev->features[0] & LMP_HOST_SSP) 316558a681efSJohan Hedberg set_bit(HCI_CONN_SSP_ENABLED, &conn->flags); 316641a96212SMarcel Holtmann } 316741a96212SMarcel Holtmann 3168ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 3169ccd556feSJohan Hedberg goto unlock; 3170ccd556feSJohan Hedberg 3171671267bfSJohan Hedberg if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { 3172127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 3173127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 3174127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 3175127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 3176127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 3177b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 3178b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 317908c79b61SJohan Hedberg conn->dst_type, 0, NULL, 0, 3180b644ba33SJohan Hedberg conn->dev_class); 3181392599b9SJohan Hedberg 3182127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 3183769be974SMarcel Holtmann conn->state = BT_CONNECTED; 3184769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 3185769be974SMarcel Holtmann hci_conn_put(conn); 3186769be974SMarcel Holtmann } 3187769be974SMarcel Holtmann 3188ccd556feSJohan Hedberg unlock: 318941a96212SMarcel Holtmann hci_dev_unlock(hdev); 3190a9de9248SMarcel Holtmann } 3191a9de9248SMarcel Holtmann 31926039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev, 3193807deac2SGustavo Padovan struct sk_buff *skb) 3194a9de9248SMarcel Holtmann { 3195b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 3196b6a0dc82SMarcel Holtmann struct hci_conn *conn; 3197b6a0dc82SMarcel Holtmann 31989f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 3199b6a0dc82SMarcel Holtmann 3200b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 3201b6a0dc82SMarcel Holtmann 3202b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 32039dc0a3afSMarcel Holtmann if (!conn) { 32049dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 32059dc0a3afSMarcel Holtmann goto unlock; 32069dc0a3afSMarcel Holtmann 32079dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 3208b6a0dc82SMarcel Holtmann if (!conn) 3209b6a0dc82SMarcel Holtmann goto unlock; 3210b6a0dc82SMarcel Holtmann 32119dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 32129dc0a3afSMarcel Holtmann } 32139dc0a3afSMarcel Holtmann 3214732547f9SMarcel Holtmann switch (ev->status) { 3215732547f9SMarcel Holtmann case 0x00: 3216732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 3217732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 3218732547f9SMarcel Holtmann 32199eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 3220732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 3221732547f9SMarcel Holtmann break; 3222732547f9SMarcel Holtmann 3223705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 3224732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 32251038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 3226732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 3227732547f9SMarcel Holtmann if (conn->out && conn->attempt < 2) { 3228efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 3229efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 3230efc7688bSMarcel Holtmann hci_setup_sync(conn, conn->link->handle); 3231efc7688bSMarcel Holtmann goto unlock; 3232efc7688bSMarcel Holtmann } 3233732547f9SMarcel Holtmann /* fall through */ 3234efc7688bSMarcel Holtmann 3235732547f9SMarcel Holtmann default: 3236b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 3237732547f9SMarcel Holtmann break; 3238732547f9SMarcel Holtmann } 3239b6a0dc82SMarcel Holtmann 3240b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 3241b6a0dc82SMarcel Holtmann if (ev->status) 3242b6a0dc82SMarcel Holtmann hci_conn_del(conn); 3243b6a0dc82SMarcel Holtmann 3244b6a0dc82SMarcel Holtmann unlock: 3245b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 3246a9de9248SMarcel Holtmann } 3247a9de9248SMarcel Holtmann 32486039aa73SGustavo Padovan static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) 3249a9de9248SMarcel Holtmann { 3250a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 3251a9de9248SMarcel Holtmann } 3252a9de9248SMarcel Holtmann 32536039aa73SGustavo Padovan static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) 325404837f64SMarcel Holtmann { 3255a9de9248SMarcel Holtmann struct hci_ev_sniff_subrate *ev = (void *) skb->data; 325604837f64SMarcel Holtmann 32579f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 325804837f64SMarcel Holtmann } 325904837f64SMarcel Holtmann 32606039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, 3261807deac2SGustavo Padovan struct sk_buff *skb) 3262a9de9248SMarcel Holtmann { 3263a9de9248SMarcel Holtmann struct inquiry_data data; 3264a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 3265a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 32669d939d94SVishal Agarwal size_t eir_len; 3267a9de9248SMarcel Holtmann 3268a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 3269a9de9248SMarcel Holtmann 3270a9de9248SMarcel Holtmann if (!num_rsp) 3271a9de9248SMarcel Holtmann return; 3272a9de9248SMarcel Holtmann 32731519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 32741519cc17SAndre Guedes return; 32751519cc17SAndre Guedes 3276a9de9248SMarcel Holtmann hci_dev_lock(hdev); 3277a9de9248SMarcel Holtmann 3278e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 3279388fc8faSJohan Hedberg bool name_known, ssp; 3280561aafbcSJohan Hedberg 3281a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 3282a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 3283a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 3284a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 3285a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 3286a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 3287a9de9248SMarcel Holtmann data.rssi = info->rssi; 328841a96212SMarcel Holtmann data.ssp_mode = 0x01; 3289561aafbcSJohan Hedberg 3290a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 32914ddb1930SJohan Hedberg name_known = eir_has_data_type(info->data, 32924ddb1930SJohan Hedberg sizeof(info->data), 32934ddb1930SJohan Hedberg EIR_NAME_COMPLETE); 3294561aafbcSJohan Hedberg else 3295561aafbcSJohan Hedberg name_known = true; 3296561aafbcSJohan Hedberg 3297388fc8faSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, name_known, 3298388fc8faSJohan Hedberg &ssp); 32999d939d94SVishal Agarwal eir_len = eir_get_length(info->data, sizeof(info->data)); 330048264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 330104124681SGustavo F. Padovan info->dev_class, info->rssi, !name_known, 33029d939d94SVishal Agarwal ssp, info->data, eir_len); 3303a9de9248SMarcel Holtmann } 3304a9de9248SMarcel Holtmann 3305a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 3306a9de9248SMarcel Holtmann } 3307a9de9248SMarcel Holtmann 33081c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev, 33091c2e0041SJohan Hedberg struct sk_buff *skb) 33101c2e0041SJohan Hedberg { 33111c2e0041SJohan Hedberg struct hci_ev_key_refresh_complete *ev = (void *) skb->data; 33121c2e0041SJohan Hedberg struct hci_conn *conn; 33131c2e0041SJohan Hedberg 33149f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status, 33151c2e0041SJohan Hedberg __le16_to_cpu(ev->handle)); 33161c2e0041SJohan Hedberg 33171c2e0041SJohan Hedberg hci_dev_lock(hdev); 33181c2e0041SJohan Hedberg 33191c2e0041SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 33201c2e0041SJohan Hedberg if (!conn) 33211c2e0041SJohan Hedberg goto unlock; 33221c2e0041SJohan Hedberg 33231c2e0041SJohan Hedberg if (!ev->status) 33241c2e0041SJohan Hedberg conn->sec_level = conn->pending_sec_level; 33251c2e0041SJohan Hedberg 33261c2e0041SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 33271c2e0041SJohan Hedberg 33281c2e0041SJohan Hedberg if (ev->status && conn->state == BT_CONNECTED) { 33291c2e0041SJohan Hedberg hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE); 33301c2e0041SJohan Hedberg hci_conn_put(conn); 33311c2e0041SJohan Hedberg goto unlock; 33321c2e0041SJohan Hedberg } 33331c2e0041SJohan Hedberg 33341c2e0041SJohan Hedberg if (conn->state == BT_CONFIG) { 33351c2e0041SJohan Hedberg if (!ev->status) 33361c2e0041SJohan Hedberg conn->state = BT_CONNECTED; 33371c2e0041SJohan Hedberg 33381c2e0041SJohan Hedberg hci_proto_connect_cfm(conn, ev->status); 33391c2e0041SJohan Hedberg hci_conn_put(conn); 33401c2e0041SJohan Hedberg } else { 33411c2e0041SJohan Hedberg hci_auth_cfm(conn, ev->status); 33421c2e0041SJohan Hedberg 33431c2e0041SJohan Hedberg hci_conn_hold(conn); 33441c2e0041SJohan Hedberg conn->disc_timeout = HCI_DISCONN_TIMEOUT; 33451c2e0041SJohan Hedberg hci_conn_put(conn); 33461c2e0041SJohan Hedberg } 33471c2e0041SJohan Hedberg 33481c2e0041SJohan Hedberg unlock: 33491c2e0041SJohan Hedberg hci_dev_unlock(hdev); 33501c2e0041SJohan Hedberg } 33511c2e0041SJohan Hedberg 33526039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn) 335317fa4b9dSJohan Hedberg { 335417fa4b9dSJohan Hedberg /* If remote requests dedicated bonding follow that lead */ 335517fa4b9dSJohan Hedberg if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) { 335617fa4b9dSJohan Hedberg /* If both remote and local IO capabilities allow MITM 335717fa4b9dSJohan Hedberg * protection then require it, otherwise don't */ 335817fa4b9dSJohan Hedberg if (conn->remote_cap == 0x03 || conn->io_capability == 0x03) 335917fa4b9dSJohan Hedberg return 0x02; 336017fa4b9dSJohan Hedberg else 336117fa4b9dSJohan Hedberg return 0x03; 336217fa4b9dSJohan Hedberg } 336317fa4b9dSJohan Hedberg 336417fa4b9dSJohan Hedberg /* If remote requests no-bonding follow that lead */ 336517fa4b9dSJohan Hedberg if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01) 336658797bf7SWaldemar Rymarkiewicz return conn->remote_auth | (conn->auth_type & 0x01); 336717fa4b9dSJohan Hedberg 336817fa4b9dSJohan Hedberg return conn->auth_type; 336917fa4b9dSJohan Hedberg } 337017fa4b9dSJohan Hedberg 33716039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 33720493684eSMarcel Holtmann { 33730493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 33740493684eSMarcel Holtmann struct hci_conn *conn; 33750493684eSMarcel Holtmann 33760493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 33770493684eSMarcel Holtmann 33780493684eSMarcel Holtmann hci_dev_lock(hdev); 33790493684eSMarcel Holtmann 33800493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 338103b555e1SJohan Hedberg if (!conn) 338203b555e1SJohan Hedberg goto unlock; 338303b555e1SJohan Hedberg 33840493684eSMarcel Holtmann hci_conn_hold(conn); 33850493684eSMarcel Holtmann 3386a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 338703b555e1SJohan Hedberg goto unlock; 338803b555e1SJohan Hedberg 3389a8b2d5c2SJohan Hedberg if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) || 339003b555e1SJohan Hedberg (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 339117fa4b9dSJohan Hedberg struct hci_cp_io_capability_reply cp; 339217fa4b9dSJohan Hedberg 339317fa4b9dSJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 33947a7f1e7cSHemant Gupta /* Change the IO capability from KeyboardDisplay 33957a7f1e7cSHemant Gupta * to DisplayYesNo as it is not supported by BT spec. */ 33967a7f1e7cSHemant Gupta cp.capability = (conn->io_capability == 0x04) ? 33977a7f1e7cSHemant Gupta 0x01 : conn->io_capability; 33987cbc9bd9SJohan Hedberg conn->auth_type = hci_get_auth_req(conn); 33997cbc9bd9SJohan Hedberg cp.authentication = conn->auth_type; 340017fa4b9dSJohan Hedberg 34018fc9ced3SGustavo Padovan if (hci_find_remote_oob_data(hdev, &conn->dst) && 34028fc9ced3SGustavo Padovan (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags))) 3403ce85ee13SSzymon Janc cp.oob_data = 0x01; 3404ce85ee13SSzymon Janc else 3405ce85ee13SSzymon Janc cp.oob_data = 0x00; 3406ce85ee13SSzymon Janc 340717fa4b9dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, 340817fa4b9dSJohan Hedberg sizeof(cp), &cp); 340903b555e1SJohan Hedberg } else { 341003b555e1SJohan Hedberg struct hci_cp_io_capability_neg_reply cp; 341103b555e1SJohan Hedberg 341203b555e1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 34139f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED; 341403b555e1SJohan Hedberg 341503b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 341603b555e1SJohan Hedberg sizeof(cp), &cp); 341703b555e1SJohan Hedberg } 341803b555e1SJohan Hedberg 341903b555e1SJohan Hedberg unlock: 342003b555e1SJohan Hedberg hci_dev_unlock(hdev); 342103b555e1SJohan Hedberg } 342203b555e1SJohan Hedberg 34236039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 342403b555e1SJohan Hedberg { 342503b555e1SJohan Hedberg struct hci_ev_io_capa_reply *ev = (void *) skb->data; 342603b555e1SJohan Hedberg struct hci_conn *conn; 342703b555e1SJohan Hedberg 342803b555e1SJohan Hedberg BT_DBG("%s", hdev->name); 342903b555e1SJohan Hedberg 343003b555e1SJohan Hedberg hci_dev_lock(hdev); 343103b555e1SJohan Hedberg 343203b555e1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 343303b555e1SJohan Hedberg if (!conn) 343403b555e1SJohan Hedberg goto unlock; 343503b555e1SJohan Hedberg 343603b555e1SJohan Hedberg conn->remote_cap = ev->capability; 343703b555e1SJohan Hedberg conn->remote_auth = ev->authentication; 343858a681efSJohan Hedberg if (ev->oob_data) 343958a681efSJohan Hedberg set_bit(HCI_CONN_REMOTE_OOB, &conn->flags); 344003b555e1SJohan Hedberg 344103b555e1SJohan Hedberg unlock: 34420493684eSMarcel Holtmann hci_dev_unlock(hdev); 34430493684eSMarcel Holtmann } 34440493684eSMarcel Holtmann 34456039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev, 3446a5c29683SJohan Hedberg struct sk_buff *skb) 3447a5c29683SJohan Hedberg { 3448a5c29683SJohan Hedberg struct hci_ev_user_confirm_req *ev = (void *) skb->data; 344955bc1a37SJohan Hedberg int loc_mitm, rem_mitm, confirm_hint = 0; 34507a828908SJohan Hedberg struct hci_conn *conn; 3451a5c29683SJohan Hedberg 3452a5c29683SJohan Hedberg BT_DBG("%s", hdev->name); 3453a5c29683SJohan Hedberg 3454a5c29683SJohan Hedberg hci_dev_lock(hdev); 3455a5c29683SJohan Hedberg 3456a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 34577a828908SJohan Hedberg goto unlock; 34587a828908SJohan Hedberg 34597a828908SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 34607a828908SJohan Hedberg if (!conn) 34617a828908SJohan Hedberg goto unlock; 34627a828908SJohan Hedberg 34637a828908SJohan Hedberg loc_mitm = (conn->auth_type & 0x01); 34647a828908SJohan Hedberg rem_mitm = (conn->remote_auth & 0x01); 34657a828908SJohan Hedberg 34667a828908SJohan Hedberg /* If we require MITM but the remote device can't provide that 34677a828908SJohan Hedberg * (it has NoInputNoOutput) then reject the confirmation 34687a828908SJohan Hedberg * request. The only exception is when we're dedicated bonding 34697a828908SJohan Hedberg * initiators (connect_cfm_cb set) since then we always have the MITM 34707a828908SJohan Hedberg * bit set. */ 34717a828908SJohan Hedberg if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) { 34727a828908SJohan Hedberg BT_DBG("Rejecting request: remote device can't provide MITM"); 34737a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, 34747a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 34757a828908SJohan Hedberg goto unlock; 34767a828908SJohan Hedberg } 34777a828908SJohan Hedberg 34787a828908SJohan Hedberg /* If no side requires MITM protection; auto-accept */ 34797a828908SJohan Hedberg if ((!loc_mitm || conn->remote_cap == 0x03) && 34807a828908SJohan Hedberg (!rem_mitm || conn->io_capability == 0x03)) { 348155bc1a37SJohan Hedberg 348255bc1a37SJohan Hedberg /* If we're not the initiators request authorization to 348355bc1a37SJohan Hedberg * proceed from user space (mgmt_user_confirm with 348455bc1a37SJohan Hedberg * confirm_hint set to 1). */ 348551a8efd7SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 348655bc1a37SJohan Hedberg BT_DBG("Confirming auto-accept as acceptor"); 348755bc1a37SJohan Hedberg confirm_hint = 1; 348855bc1a37SJohan Hedberg goto confirm; 348955bc1a37SJohan Hedberg } 349055bc1a37SJohan Hedberg 34919f61656aSJohan Hedberg BT_DBG("Auto-accept of user confirmation with %ums delay", 34929f61656aSJohan Hedberg hdev->auto_accept_delay); 34939f61656aSJohan Hedberg 34949f61656aSJohan Hedberg if (hdev->auto_accept_delay > 0) { 34959f61656aSJohan Hedberg int delay = msecs_to_jiffies(hdev->auto_accept_delay); 34969f61656aSJohan Hedberg mod_timer(&conn->auto_accept_timer, jiffies + delay); 34979f61656aSJohan Hedberg goto unlock; 34989f61656aSJohan Hedberg } 34999f61656aSJohan Hedberg 35007a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, 35017a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 35027a828908SJohan Hedberg goto unlock; 35037a828908SJohan Hedberg } 35047a828908SJohan Hedberg 350555bc1a37SJohan Hedberg confirm: 3506272d90dfSJohan Hedberg mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey, 350755bc1a37SJohan Hedberg confirm_hint); 3508a5c29683SJohan Hedberg 35097a828908SJohan Hedberg unlock: 3510a5c29683SJohan Hedberg hci_dev_unlock(hdev); 3511a5c29683SJohan Hedberg } 3512a5c29683SJohan Hedberg 35136039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev, 35141143d458SBrian Gix struct sk_buff *skb) 35151143d458SBrian Gix { 35161143d458SBrian Gix struct hci_ev_user_passkey_req *ev = (void *) skb->data; 35171143d458SBrian Gix 35181143d458SBrian Gix BT_DBG("%s", hdev->name); 35191143d458SBrian Gix 3520a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 3521272d90dfSJohan Hedberg mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); 35221143d458SBrian Gix } 35231143d458SBrian Gix 352492a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev, 352592a25256SJohan Hedberg struct sk_buff *skb) 352692a25256SJohan Hedberg { 352792a25256SJohan Hedberg struct hci_ev_user_passkey_notify *ev = (void *) skb->data; 352892a25256SJohan Hedberg struct hci_conn *conn; 352992a25256SJohan Hedberg 353092a25256SJohan Hedberg BT_DBG("%s", hdev->name); 353192a25256SJohan Hedberg 353292a25256SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 353392a25256SJohan Hedberg if (!conn) 353492a25256SJohan Hedberg return; 353592a25256SJohan Hedberg 353692a25256SJohan Hedberg conn->passkey_notify = __le32_to_cpu(ev->passkey); 353792a25256SJohan Hedberg conn->passkey_entered = 0; 353892a25256SJohan Hedberg 353992a25256SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 354092a25256SJohan Hedberg mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, 354192a25256SJohan Hedberg conn->dst_type, conn->passkey_notify, 354292a25256SJohan Hedberg conn->passkey_entered); 354392a25256SJohan Hedberg } 354492a25256SJohan Hedberg 354592a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 354692a25256SJohan Hedberg { 354792a25256SJohan Hedberg struct hci_ev_keypress_notify *ev = (void *) skb->data; 354892a25256SJohan Hedberg struct hci_conn *conn; 354992a25256SJohan Hedberg 355092a25256SJohan Hedberg BT_DBG("%s", hdev->name); 355192a25256SJohan Hedberg 355292a25256SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 355392a25256SJohan Hedberg if (!conn) 355492a25256SJohan Hedberg return; 355592a25256SJohan Hedberg 355692a25256SJohan Hedberg switch (ev->type) { 355792a25256SJohan Hedberg case HCI_KEYPRESS_STARTED: 355892a25256SJohan Hedberg conn->passkey_entered = 0; 355992a25256SJohan Hedberg return; 356092a25256SJohan Hedberg 356192a25256SJohan Hedberg case HCI_KEYPRESS_ENTERED: 356292a25256SJohan Hedberg conn->passkey_entered++; 356392a25256SJohan Hedberg break; 356492a25256SJohan Hedberg 356592a25256SJohan Hedberg case HCI_KEYPRESS_ERASED: 356692a25256SJohan Hedberg conn->passkey_entered--; 356792a25256SJohan Hedberg break; 356892a25256SJohan Hedberg 356992a25256SJohan Hedberg case HCI_KEYPRESS_CLEARED: 357092a25256SJohan Hedberg conn->passkey_entered = 0; 357192a25256SJohan Hedberg break; 357292a25256SJohan Hedberg 357392a25256SJohan Hedberg case HCI_KEYPRESS_COMPLETED: 357492a25256SJohan Hedberg return; 357592a25256SJohan Hedberg } 357692a25256SJohan Hedberg 357792a25256SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 357892a25256SJohan Hedberg mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, 357992a25256SJohan Hedberg conn->dst_type, conn->passkey_notify, 358092a25256SJohan Hedberg conn->passkey_entered); 358192a25256SJohan Hedberg } 358292a25256SJohan Hedberg 35836039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev, 3584807deac2SGustavo Padovan struct sk_buff *skb) 35850493684eSMarcel Holtmann { 35860493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 35870493684eSMarcel Holtmann struct hci_conn *conn; 35880493684eSMarcel Holtmann 35890493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 35900493684eSMarcel Holtmann 35910493684eSMarcel Holtmann hci_dev_lock(hdev); 35920493684eSMarcel Holtmann 35930493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 35942a611692SJohan Hedberg if (!conn) 35952a611692SJohan Hedberg goto unlock; 35962a611692SJohan Hedberg 35972a611692SJohan Hedberg /* To avoid duplicate auth_failed events to user space we check 35982a611692SJohan Hedberg * the HCI_CONN_AUTH_PEND flag which will be set if we 35992a611692SJohan Hedberg * initiated the authentication. A traditional auth_complete 36002a611692SJohan Hedberg * event gets always produced as initiator and is also mapped to 36012a611692SJohan Hedberg * the mgmt_auth_failed event */ 3602fa1bd918SMikel Astiz if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status) 3603bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 3604bab73cb6SJohan Hedberg ev->status); 36052a611692SJohan Hedberg 36060493684eSMarcel Holtmann hci_conn_put(conn); 36070493684eSMarcel Holtmann 36082a611692SJohan Hedberg unlock: 36090493684eSMarcel Holtmann hci_dev_unlock(hdev); 36100493684eSMarcel Holtmann } 36110493684eSMarcel Holtmann 36126039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev, 3613807deac2SGustavo Padovan struct sk_buff *skb) 361441a96212SMarcel Holtmann { 361541a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 361641a96212SMarcel Holtmann struct inquiry_entry *ie; 361741a96212SMarcel Holtmann 361841a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 361941a96212SMarcel Holtmann 362041a96212SMarcel Holtmann hci_dev_lock(hdev); 362141a96212SMarcel Holtmann 3622cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 3623cc11b9c1SAndrei Emeltchenko if (ie) 362402b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 362541a96212SMarcel Holtmann 362641a96212SMarcel Holtmann hci_dev_unlock(hdev); 362741a96212SMarcel Holtmann } 362841a96212SMarcel Holtmann 36296039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev, 36302763eda6SSzymon Janc struct sk_buff *skb) 36312763eda6SSzymon Janc { 36322763eda6SSzymon Janc struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; 36332763eda6SSzymon Janc struct oob_data *data; 36342763eda6SSzymon Janc 36352763eda6SSzymon Janc BT_DBG("%s", hdev->name); 36362763eda6SSzymon Janc 36372763eda6SSzymon Janc hci_dev_lock(hdev); 36382763eda6SSzymon Janc 3639a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 3640e1ba1f15SSzymon Janc goto unlock; 3641e1ba1f15SSzymon Janc 36422763eda6SSzymon Janc data = hci_find_remote_oob_data(hdev, &ev->bdaddr); 36432763eda6SSzymon Janc if (data) { 36442763eda6SSzymon Janc struct hci_cp_remote_oob_data_reply cp; 36452763eda6SSzymon Janc 36462763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 36472763eda6SSzymon Janc memcpy(cp.hash, data->hash, sizeof(cp.hash)); 36482763eda6SSzymon Janc memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); 36492763eda6SSzymon Janc 36502763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), 36512763eda6SSzymon Janc &cp); 36522763eda6SSzymon Janc } else { 36532763eda6SSzymon Janc struct hci_cp_remote_oob_data_neg_reply cp; 36542763eda6SSzymon Janc 36552763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 36562763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), 36572763eda6SSzymon Janc &cp); 36582763eda6SSzymon Janc } 36592763eda6SSzymon Janc 3660e1ba1f15SSzymon Janc unlock: 36612763eda6SSzymon Janc hci_dev_unlock(hdev); 36622763eda6SSzymon Janc } 36632763eda6SSzymon Janc 3664d5e91192SAndrei Emeltchenko static void hci_phy_link_complete_evt(struct hci_dev *hdev, 3665d5e91192SAndrei Emeltchenko struct sk_buff *skb) 3666d5e91192SAndrei Emeltchenko { 3667d5e91192SAndrei Emeltchenko struct hci_ev_phy_link_complete *ev = (void *) skb->data; 3668d5e91192SAndrei Emeltchenko struct hci_conn *hcon, *bredr_hcon; 3669d5e91192SAndrei Emeltchenko 3670d5e91192SAndrei Emeltchenko BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle, 3671d5e91192SAndrei Emeltchenko ev->status); 3672d5e91192SAndrei Emeltchenko 3673d5e91192SAndrei Emeltchenko hci_dev_lock(hdev); 3674d5e91192SAndrei Emeltchenko 3675d5e91192SAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 3676d5e91192SAndrei Emeltchenko if (!hcon) { 3677d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 3678d5e91192SAndrei Emeltchenko return; 3679d5e91192SAndrei Emeltchenko } 3680d5e91192SAndrei Emeltchenko 3681d5e91192SAndrei Emeltchenko if (ev->status) { 3682d5e91192SAndrei Emeltchenko hci_conn_del(hcon); 3683d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 3684d5e91192SAndrei Emeltchenko return; 3685d5e91192SAndrei Emeltchenko } 3686d5e91192SAndrei Emeltchenko 3687d5e91192SAndrei Emeltchenko bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon; 3688d5e91192SAndrei Emeltchenko 3689d5e91192SAndrei Emeltchenko hcon->state = BT_CONNECTED; 3690d5e91192SAndrei Emeltchenko bacpy(&hcon->dst, &bredr_hcon->dst); 3691d5e91192SAndrei Emeltchenko 3692d5e91192SAndrei Emeltchenko hci_conn_hold(hcon); 3693d5e91192SAndrei Emeltchenko hcon->disc_timeout = HCI_DISCONN_TIMEOUT; 3694d5e91192SAndrei Emeltchenko hci_conn_put(hcon); 3695d5e91192SAndrei Emeltchenko 3696d5e91192SAndrei Emeltchenko hci_conn_hold_device(hcon); 3697d5e91192SAndrei Emeltchenko hci_conn_add_sysfs(hcon); 3698d5e91192SAndrei Emeltchenko 3699d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 3700d5e91192SAndrei Emeltchenko 3701d5e91192SAndrei Emeltchenko if (hcon->out) { 3702d5e91192SAndrei Emeltchenko struct hci_dev *bredr_hdev = hci_dev_hold(bredr_hcon->hdev); 3703d5e91192SAndrei Emeltchenko 3704d5e91192SAndrei Emeltchenko if (!bredr_hdev) 3705d5e91192SAndrei Emeltchenko return; 3706d5e91192SAndrei Emeltchenko 3707d5e91192SAndrei Emeltchenko /* Placeholder - create chan req 3708d5e91192SAndrei Emeltchenko l2cap_chan_create_cfm(bredr_hcon, hcon->remote_id); 3709d5e91192SAndrei Emeltchenko */ 3710d5e91192SAndrei Emeltchenko 3711d5e91192SAndrei Emeltchenko hci_dev_put(bredr_hdev); 3712d5e91192SAndrei Emeltchenko } 3713d5e91192SAndrei Emeltchenko } 3714d5e91192SAndrei Emeltchenko 371527695fb4SAndrei Emeltchenko static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 371627695fb4SAndrei Emeltchenko { 371727695fb4SAndrei Emeltchenko struct hci_ev_logical_link_complete *ev = (void *) skb->data; 371827695fb4SAndrei Emeltchenko struct hci_conn *hcon; 371927695fb4SAndrei Emeltchenko struct hci_chan *hchan; 372027695fb4SAndrei Emeltchenko struct amp_mgr *mgr; 372127695fb4SAndrei Emeltchenko 372227695fb4SAndrei Emeltchenko BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x", 372327695fb4SAndrei Emeltchenko hdev->name, le16_to_cpu(ev->handle), ev->phy_handle, 372427695fb4SAndrei Emeltchenko ev->status); 372527695fb4SAndrei Emeltchenko 372627695fb4SAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 372727695fb4SAndrei Emeltchenko if (!hcon) 372827695fb4SAndrei Emeltchenko return; 372927695fb4SAndrei Emeltchenko 373027695fb4SAndrei Emeltchenko /* Create AMP hchan */ 373127695fb4SAndrei Emeltchenko hchan = hci_chan_create(hcon); 373227695fb4SAndrei Emeltchenko if (!hchan) 373327695fb4SAndrei Emeltchenko return; 373427695fb4SAndrei Emeltchenko 373527695fb4SAndrei Emeltchenko hchan->handle = le16_to_cpu(ev->handle); 373627695fb4SAndrei Emeltchenko 373727695fb4SAndrei Emeltchenko BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan); 373827695fb4SAndrei Emeltchenko 373927695fb4SAndrei Emeltchenko mgr = hcon->amp_mgr; 374027695fb4SAndrei Emeltchenko if (mgr && mgr->bredr_chan) { 374127695fb4SAndrei Emeltchenko struct l2cap_chan *bredr_chan = mgr->bredr_chan; 374227695fb4SAndrei Emeltchenko 374327695fb4SAndrei Emeltchenko l2cap_chan_lock(bredr_chan); 374427695fb4SAndrei Emeltchenko 374527695fb4SAndrei Emeltchenko bredr_chan->conn->mtu = hdev->block_mtu; 374627695fb4SAndrei Emeltchenko l2cap_logical_cfm(bredr_chan, hchan, 0); 374727695fb4SAndrei Emeltchenko hci_conn_hold(hcon); 374827695fb4SAndrei Emeltchenko 374927695fb4SAndrei Emeltchenko l2cap_chan_unlock(bredr_chan); 375027695fb4SAndrei Emeltchenko } 375127695fb4SAndrei Emeltchenko } 375227695fb4SAndrei Emeltchenko 3753606e2a10SAndrei Emeltchenko static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev, 3754606e2a10SAndrei Emeltchenko struct sk_buff *skb) 3755606e2a10SAndrei Emeltchenko { 3756606e2a10SAndrei Emeltchenko struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data; 3757606e2a10SAndrei Emeltchenko struct hci_chan *hchan; 3758606e2a10SAndrei Emeltchenko 3759606e2a10SAndrei Emeltchenko BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name, 3760606e2a10SAndrei Emeltchenko le16_to_cpu(ev->handle), ev->status); 3761606e2a10SAndrei Emeltchenko 3762606e2a10SAndrei Emeltchenko if (ev->status) 3763606e2a10SAndrei Emeltchenko return; 3764606e2a10SAndrei Emeltchenko 3765606e2a10SAndrei Emeltchenko hci_dev_lock(hdev); 3766606e2a10SAndrei Emeltchenko 3767606e2a10SAndrei Emeltchenko hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle)); 3768606e2a10SAndrei Emeltchenko if (!hchan) 3769606e2a10SAndrei Emeltchenko goto unlock; 3770606e2a10SAndrei Emeltchenko 3771606e2a10SAndrei Emeltchenko amp_destroy_logical_link(hchan, ev->reason); 3772606e2a10SAndrei Emeltchenko 3773606e2a10SAndrei Emeltchenko unlock: 3774606e2a10SAndrei Emeltchenko hci_dev_unlock(hdev); 3775606e2a10SAndrei Emeltchenko } 3776606e2a10SAndrei Emeltchenko 37779eef6b3aSAndrei Emeltchenko static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev, 37789eef6b3aSAndrei Emeltchenko struct sk_buff *skb) 37799eef6b3aSAndrei Emeltchenko { 37809eef6b3aSAndrei Emeltchenko struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data; 37819eef6b3aSAndrei Emeltchenko struct hci_conn *hcon; 37829eef6b3aSAndrei Emeltchenko 37839eef6b3aSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 37849eef6b3aSAndrei Emeltchenko 37859eef6b3aSAndrei Emeltchenko if (ev->status) 37869eef6b3aSAndrei Emeltchenko return; 37879eef6b3aSAndrei Emeltchenko 37889eef6b3aSAndrei Emeltchenko hci_dev_lock(hdev); 37899eef6b3aSAndrei Emeltchenko 37909eef6b3aSAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 37919eef6b3aSAndrei Emeltchenko if (hcon) { 37929eef6b3aSAndrei Emeltchenko hcon->state = BT_CLOSED; 37939eef6b3aSAndrei Emeltchenko hci_conn_del(hcon); 37949eef6b3aSAndrei Emeltchenko } 37959eef6b3aSAndrei Emeltchenko 37969eef6b3aSAndrei Emeltchenko hci_dev_unlock(hdev); 37979eef6b3aSAndrei Emeltchenko } 37989eef6b3aSAndrei Emeltchenko 37996039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 3800fcd89c09SVille Tervo { 3801fcd89c09SVille Tervo struct hci_ev_le_conn_complete *ev = (void *) skb->data; 3802fcd89c09SVille Tervo struct hci_conn *conn; 3803fcd89c09SVille Tervo 38049f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 3805fcd89c09SVille Tervo 3806fcd89c09SVille Tervo hci_dev_lock(hdev); 3807fcd89c09SVille Tervo 38084f72b329SAndrzej Kaczmarek conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); 3809b62f328bSVille Tervo if (!conn) { 3810b62f328bSVille Tervo conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); 3811b62f328bSVille Tervo if (!conn) { 3812b62f328bSVille Tervo BT_ERR("No memory for new connection"); 3813230fd16aSAndre Guedes goto unlock; 3814b62f328bSVille Tervo } 381529b7988aSAndre Guedes 381629b7988aSAndre Guedes conn->dst_type = ev->bdaddr_type; 3817b9b343d2SAndre Guedes 3818b9b343d2SAndre Guedes if (ev->role == LE_CONN_ROLE_MASTER) { 3819b9b343d2SAndre Guedes conn->out = true; 3820b9b343d2SAndre Guedes conn->link_mode |= HCI_LM_MASTER; 3821b9b343d2SAndre Guedes } 3822b62f328bSVille Tervo } 3823fcd89c09SVille Tervo 3824cd17decbSAndre Guedes if (ev->status) { 3825cd17decbSAndre Guedes mgmt_connect_failed(hdev, &conn->dst, conn->type, 3826cd17decbSAndre Guedes conn->dst_type, ev->status); 3827cd17decbSAndre Guedes hci_proto_connect_cfm(conn, ev->status); 3828cd17decbSAndre Guedes conn->state = BT_CLOSED; 3829cd17decbSAndre Guedes hci_conn_del(conn); 3830cd17decbSAndre Guedes goto unlock; 3831cd17decbSAndre Guedes } 3832cd17decbSAndre Guedes 3833b644ba33SJohan Hedberg if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 3834b644ba33SJohan Hedberg mgmt_device_connected(hdev, &ev->bdaddr, conn->type, 383595b23582SSzymon Janc conn->dst_type, 0, NULL, 0, NULL); 383683bc71b4SVinicius Costa Gomes 38377b5c0d52SVinicius Costa Gomes conn->sec_level = BT_SECURITY_LOW; 3838fcd89c09SVille Tervo conn->handle = __le16_to_cpu(ev->handle); 3839fcd89c09SVille Tervo conn->state = BT_CONNECTED; 3840fcd89c09SVille Tervo 3841fcd89c09SVille Tervo hci_conn_hold_device(conn); 3842fcd89c09SVille Tervo hci_conn_add_sysfs(conn); 3843fcd89c09SVille Tervo 3844fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 3845fcd89c09SVille Tervo 3846fcd89c09SVille Tervo unlock: 3847fcd89c09SVille Tervo hci_dev_unlock(hdev); 3848fcd89c09SVille Tervo } 3849fcd89c09SVille Tervo 38506039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) 38519aa04c91SAndre Guedes { 3852e95beb41SAndre Guedes u8 num_reports = skb->data[0]; 3853e95beb41SAndre Guedes void *ptr = &skb->data[1]; 38543c9e9195SAndre Guedes s8 rssi; 38559aa04c91SAndre Guedes 38569aa04c91SAndre Guedes hci_dev_lock(hdev); 38579aa04c91SAndre Guedes 3858e95beb41SAndre Guedes while (num_reports--) { 3859e95beb41SAndre Guedes struct hci_ev_le_advertising_info *ev = ptr; 3860e95beb41SAndre Guedes 38613c9e9195SAndre Guedes rssi = ev->data[ev->length]; 38623c9e9195SAndre Guedes mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type, 386304124681SGustavo F. Padovan NULL, rssi, 0, 1, ev->data, ev->length); 38643c9e9195SAndre Guedes 3865e95beb41SAndre Guedes ptr += sizeof(*ev) + ev->length + 1; 38669aa04c91SAndre Guedes } 38679aa04c91SAndre Guedes 38689aa04c91SAndre Guedes hci_dev_unlock(hdev); 38699aa04c91SAndre Guedes } 38709aa04c91SAndre Guedes 38716039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 3872a7a595f6SVinicius Costa Gomes { 3873a7a595f6SVinicius Costa Gomes struct hci_ev_le_ltk_req *ev = (void *) skb->data; 3874a7a595f6SVinicius Costa Gomes struct hci_cp_le_ltk_reply cp; 3875bea710feSVinicius Costa Gomes struct hci_cp_le_ltk_neg_reply neg; 3876a7a595f6SVinicius Costa Gomes struct hci_conn *conn; 3877c9839a11SVinicius Costa Gomes struct smp_ltk *ltk; 3878a7a595f6SVinicius Costa Gomes 38799f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle)); 3880a7a595f6SVinicius Costa Gomes 3881a7a595f6SVinicius Costa Gomes hci_dev_lock(hdev); 3882a7a595f6SVinicius Costa Gomes 3883a7a595f6SVinicius Costa Gomes conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3884bea710feSVinicius Costa Gomes if (conn == NULL) 3885bea710feSVinicius Costa Gomes goto not_found; 3886a7a595f6SVinicius Costa Gomes 3887bea710feSVinicius Costa Gomes ltk = hci_find_ltk(hdev, ev->ediv, ev->random); 3888bea710feSVinicius Costa Gomes if (ltk == NULL) 3889bea710feSVinicius Costa Gomes goto not_found; 3890bea710feSVinicius Costa Gomes 3891bea710feSVinicius Costa Gomes memcpy(cp.ltk, ltk->val, sizeof(ltk->val)); 3892a7a595f6SVinicius Costa Gomes cp.handle = cpu_to_le16(conn->handle); 3893c9839a11SVinicius Costa Gomes 3894c9839a11SVinicius Costa Gomes if (ltk->authenticated) 3895c9839a11SVinicius Costa Gomes conn->sec_level = BT_SECURITY_HIGH; 3896a7a595f6SVinicius Costa Gomes 3897a7a595f6SVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); 3898a7a595f6SVinicius Costa Gomes 3899c9839a11SVinicius Costa Gomes if (ltk->type & HCI_SMP_STK) { 3900c9839a11SVinicius Costa Gomes list_del(<k->list); 3901c9839a11SVinicius Costa Gomes kfree(ltk); 3902c9839a11SVinicius Costa Gomes } 3903c9839a11SVinicius Costa Gomes 3904a7a595f6SVinicius Costa Gomes hci_dev_unlock(hdev); 3905bea710feSVinicius Costa Gomes 3906bea710feSVinicius Costa Gomes return; 3907bea710feSVinicius Costa Gomes 3908bea710feSVinicius Costa Gomes not_found: 3909bea710feSVinicius Costa Gomes neg.handle = ev->handle; 3910bea710feSVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg); 3911bea710feSVinicius Costa Gomes hci_dev_unlock(hdev); 3912a7a595f6SVinicius Costa Gomes } 3913a7a595f6SVinicius Costa Gomes 39146039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 3915fcd89c09SVille Tervo { 3916fcd89c09SVille Tervo struct hci_ev_le_meta *le_ev = (void *) skb->data; 3917fcd89c09SVille Tervo 3918fcd89c09SVille Tervo skb_pull(skb, sizeof(*le_ev)); 3919fcd89c09SVille Tervo 3920fcd89c09SVille Tervo switch (le_ev->subevent) { 3921fcd89c09SVille Tervo case HCI_EV_LE_CONN_COMPLETE: 3922fcd89c09SVille Tervo hci_le_conn_complete_evt(hdev, skb); 3923fcd89c09SVille Tervo break; 3924fcd89c09SVille Tervo 39259aa04c91SAndre Guedes case HCI_EV_LE_ADVERTISING_REPORT: 39269aa04c91SAndre Guedes hci_le_adv_report_evt(hdev, skb); 39279aa04c91SAndre Guedes break; 39289aa04c91SAndre Guedes 3929a7a595f6SVinicius Costa Gomes case HCI_EV_LE_LTK_REQ: 3930a7a595f6SVinicius Costa Gomes hci_le_ltk_request_evt(hdev, skb); 3931a7a595f6SVinicius Costa Gomes break; 3932a7a595f6SVinicius Costa Gomes 3933fcd89c09SVille Tervo default: 3934fcd89c09SVille Tervo break; 3935fcd89c09SVille Tervo } 3936fcd89c09SVille Tervo } 3937fcd89c09SVille Tervo 39389495b2eeSAndrei Emeltchenko static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb) 39399495b2eeSAndrei Emeltchenko { 39409495b2eeSAndrei Emeltchenko struct hci_ev_channel_selected *ev = (void *) skb->data; 39419495b2eeSAndrei Emeltchenko struct hci_conn *hcon; 39429495b2eeSAndrei Emeltchenko 39439495b2eeSAndrei Emeltchenko BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle); 39449495b2eeSAndrei Emeltchenko 39459495b2eeSAndrei Emeltchenko skb_pull(skb, sizeof(*ev)); 39469495b2eeSAndrei Emeltchenko 39479495b2eeSAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 39489495b2eeSAndrei Emeltchenko if (!hcon) 39499495b2eeSAndrei Emeltchenko return; 39509495b2eeSAndrei Emeltchenko 39519495b2eeSAndrei Emeltchenko amp_read_loc_assoc_final_data(hdev, hcon); 39529495b2eeSAndrei Emeltchenko } 39539495b2eeSAndrei Emeltchenko 39541da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 39551da177e4SLinus Torvalds { 3956a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 3957a9de9248SMarcel Holtmann __u8 event = hdr->evt; 39581da177e4SLinus Torvalds 39591da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 39601da177e4SLinus Torvalds 3961a9de9248SMarcel Holtmann switch (event) { 39621da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 39631da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 39641da177e4SLinus Torvalds break; 39651da177e4SLinus Torvalds 39661da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 39671da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 39681da177e4SLinus Torvalds break; 39691da177e4SLinus Torvalds 3970a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 3971a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 397221d9e30eSMarcel Holtmann break; 397321d9e30eSMarcel Holtmann 39741da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 39751da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 39761da177e4SLinus Torvalds break; 39771da177e4SLinus Torvalds 39781da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 39791da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 39801da177e4SLinus Torvalds break; 39811da177e4SLinus Torvalds 39821da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 39831da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 39841da177e4SLinus Torvalds break; 39851da177e4SLinus Torvalds 3986a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 3987a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 3988a9de9248SMarcel Holtmann break; 3989a9de9248SMarcel Holtmann 39901da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 39911da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 39921da177e4SLinus Torvalds break; 39931da177e4SLinus Torvalds 3994a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 3995a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 3996a9de9248SMarcel Holtmann break; 3997a9de9248SMarcel Holtmann 3998a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 3999a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 4000a9de9248SMarcel Holtmann break; 4001a9de9248SMarcel Holtmann 4002a9de9248SMarcel Holtmann case HCI_EV_REMOTE_VERSION: 4003a9de9248SMarcel Holtmann hci_remote_version_evt(hdev, skb); 4004a9de9248SMarcel Holtmann break; 4005a9de9248SMarcel Holtmann 4006a9de9248SMarcel Holtmann case HCI_EV_QOS_SETUP_COMPLETE: 4007a9de9248SMarcel Holtmann hci_qos_setup_complete_evt(hdev, skb); 4008a9de9248SMarcel Holtmann break; 4009a9de9248SMarcel Holtmann 4010a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 4011a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 4012a9de9248SMarcel Holtmann break; 4013a9de9248SMarcel Holtmann 4014a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 4015a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 4016a9de9248SMarcel Holtmann break; 4017a9de9248SMarcel Holtmann 4018a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 4019a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 4020a9de9248SMarcel Holtmann break; 4021a9de9248SMarcel Holtmann 4022a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 4023a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 4024a9de9248SMarcel Holtmann break; 4025a9de9248SMarcel Holtmann 4026a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 4027a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 40281da177e4SLinus Torvalds break; 40291da177e4SLinus Torvalds 40301da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 40311da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 40321da177e4SLinus Torvalds break; 40331da177e4SLinus Torvalds 40341da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 40351da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 40361da177e4SLinus Torvalds break; 40371da177e4SLinus Torvalds 40381da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 40391da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 40401da177e4SLinus Torvalds break; 40411da177e4SLinus Torvalds 40421da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 40431da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 40441da177e4SLinus Torvalds break; 40451da177e4SLinus Torvalds 4046a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 4047a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 4048a8746417SMarcel Holtmann break; 4049a8746417SMarcel Holtmann 405085a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 405185a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 405285a1e930SMarcel Holtmann break; 405385a1e930SMarcel Holtmann 4054a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 4055a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 4056a9de9248SMarcel Holtmann break; 4057a9de9248SMarcel Holtmann 4058a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 4059a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 4060a9de9248SMarcel Holtmann break; 4061a9de9248SMarcel Holtmann 4062a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 4063a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 4064a9de9248SMarcel Holtmann break; 4065a9de9248SMarcel Holtmann 4066a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_CHANGED: 4067a9de9248SMarcel Holtmann hci_sync_conn_changed_evt(hdev, skb); 4068a9de9248SMarcel Holtmann break; 4069a9de9248SMarcel Holtmann 407004837f64SMarcel Holtmann case HCI_EV_SNIFF_SUBRATE: 407104837f64SMarcel Holtmann hci_sniff_subrate_evt(hdev, skb); 407204837f64SMarcel Holtmann break; 407304837f64SMarcel Holtmann 4074a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 4075a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 40761da177e4SLinus Torvalds break; 40771da177e4SLinus Torvalds 40781c2e0041SJohan Hedberg case HCI_EV_KEY_REFRESH_COMPLETE: 40791c2e0041SJohan Hedberg hci_key_refresh_complete_evt(hdev, skb); 40801c2e0041SJohan Hedberg break; 40811c2e0041SJohan Hedberg 40820493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 40830493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 40840493684eSMarcel Holtmann break; 40850493684eSMarcel Holtmann 408603b555e1SJohan Hedberg case HCI_EV_IO_CAPA_REPLY: 408703b555e1SJohan Hedberg hci_io_capa_reply_evt(hdev, skb); 408803b555e1SJohan Hedberg break; 408903b555e1SJohan Hedberg 4090a5c29683SJohan Hedberg case HCI_EV_USER_CONFIRM_REQUEST: 4091a5c29683SJohan Hedberg hci_user_confirm_request_evt(hdev, skb); 4092a5c29683SJohan Hedberg break; 4093a5c29683SJohan Hedberg 40941143d458SBrian Gix case HCI_EV_USER_PASSKEY_REQUEST: 40951143d458SBrian Gix hci_user_passkey_request_evt(hdev, skb); 40961143d458SBrian Gix break; 40971143d458SBrian Gix 409892a25256SJohan Hedberg case HCI_EV_USER_PASSKEY_NOTIFY: 409992a25256SJohan Hedberg hci_user_passkey_notify_evt(hdev, skb); 410092a25256SJohan Hedberg break; 410192a25256SJohan Hedberg 410292a25256SJohan Hedberg case HCI_EV_KEYPRESS_NOTIFY: 410392a25256SJohan Hedberg hci_keypress_notify_evt(hdev, skb); 410492a25256SJohan Hedberg break; 410592a25256SJohan Hedberg 41060493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 41070493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 41080493684eSMarcel Holtmann break; 41090493684eSMarcel Holtmann 411041a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 411141a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 411241a96212SMarcel Holtmann break; 411341a96212SMarcel Holtmann 4114fcd89c09SVille Tervo case HCI_EV_LE_META: 4115fcd89c09SVille Tervo hci_le_meta_evt(hdev, skb); 4116fcd89c09SVille Tervo break; 4117fcd89c09SVille Tervo 41189495b2eeSAndrei Emeltchenko case HCI_EV_CHANNEL_SELECTED: 41199495b2eeSAndrei Emeltchenko hci_chan_selected_evt(hdev, skb); 41209495b2eeSAndrei Emeltchenko break; 41219495b2eeSAndrei Emeltchenko 41222763eda6SSzymon Janc case HCI_EV_REMOTE_OOB_DATA_REQUEST: 41232763eda6SSzymon Janc hci_remote_oob_data_request_evt(hdev, skb); 41242763eda6SSzymon Janc break; 41252763eda6SSzymon Janc 4126d5e91192SAndrei Emeltchenko case HCI_EV_PHY_LINK_COMPLETE: 4127d5e91192SAndrei Emeltchenko hci_phy_link_complete_evt(hdev, skb); 4128d5e91192SAndrei Emeltchenko break; 4129d5e91192SAndrei Emeltchenko 413027695fb4SAndrei Emeltchenko case HCI_EV_LOGICAL_LINK_COMPLETE: 413127695fb4SAndrei Emeltchenko hci_loglink_complete_evt(hdev, skb); 413227695fb4SAndrei Emeltchenko break; 413327695fb4SAndrei Emeltchenko 4134606e2a10SAndrei Emeltchenko case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE: 4135606e2a10SAndrei Emeltchenko hci_disconn_loglink_complete_evt(hdev, skb); 4136606e2a10SAndrei Emeltchenko break; 4137606e2a10SAndrei Emeltchenko 41389eef6b3aSAndrei Emeltchenko case HCI_EV_DISCONN_PHY_LINK_COMPLETE: 41399eef6b3aSAndrei Emeltchenko hci_disconn_phylink_complete_evt(hdev, skb); 41409eef6b3aSAndrei Emeltchenko break; 41419eef6b3aSAndrei Emeltchenko 414225e89e99SAndrei Emeltchenko case HCI_EV_NUM_COMP_BLOCKS: 414325e89e99SAndrei Emeltchenko hci_num_comp_blocks_evt(hdev, skb); 414425e89e99SAndrei Emeltchenko break; 414525e89e99SAndrei Emeltchenko 41461da177e4SLinus Torvalds default: 41479f1db00cSAndrei Emeltchenko BT_DBG("%s event 0x%2.2x", hdev->name, event); 41481da177e4SLinus Torvalds break; 41491da177e4SLinus Torvalds } 41501da177e4SLinus Torvalds 41511da177e4SLinus Torvalds kfree_skb(skb); 41521da177e4SLinus Torvalds hdev->stat.evt_rx++; 41531da177e4SLinus Torvalds } 4154