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 if (status) 181393c284eeSAndrei Emeltchenko return; 181493c284eeSAndrei Emeltchenko 181593c284eeSAndrei Emeltchenko cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK); 181693c284eeSAndrei Emeltchenko if (!cp) 181793c284eeSAndrei Emeltchenko return; 181893c284eeSAndrei Emeltchenko 181993c284eeSAndrei Emeltchenko amp_write_remote_assoc(hdev, cp->phy_handle); 1820a02226d6SAndrei Emeltchenko } 1821a02226d6SAndrei Emeltchenko 18220b26ab9dSAndrei Emeltchenko static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status) 18230b26ab9dSAndrei Emeltchenko { 18240b26ab9dSAndrei Emeltchenko struct hci_cp_accept_phy_link *cp; 18250b26ab9dSAndrei Emeltchenko 18260b26ab9dSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 18270b26ab9dSAndrei Emeltchenko 18280b26ab9dSAndrei Emeltchenko if (status) 18290b26ab9dSAndrei Emeltchenko return; 18300b26ab9dSAndrei Emeltchenko 18310b26ab9dSAndrei Emeltchenko cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK); 18320b26ab9dSAndrei Emeltchenko if (!cp) 18330b26ab9dSAndrei Emeltchenko return; 18340b26ab9dSAndrei Emeltchenko 18350b26ab9dSAndrei Emeltchenko amp_write_remote_assoc(hdev, cp->phy_handle); 18360b26ab9dSAndrei Emeltchenko } 18370b26ab9dSAndrei Emeltchenko 18385ce66b59SAndrei Emeltchenko static void hci_cs_create_logical_link(struct hci_dev *hdev, u8 status) 18395ce66b59SAndrei Emeltchenko { 18405ce66b59SAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 18415ce66b59SAndrei Emeltchenko } 18425ce66b59SAndrei Emeltchenko 18436039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 18441da177e4SLinus Torvalds { 18451da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 184630dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 184730dc78e1SJohan Hedberg struct inquiry_entry *e; 18481da177e4SLinus Torvalds 18499f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 18501da177e4SLinus Torvalds 185123bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 18526bd57416SMarcel Holtmann 1853a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 185489352e7dSAndre Guedes 185589352e7dSAndre Guedes if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) 185689352e7dSAndre Guedes return; 185789352e7dSAndre Guedes 1858a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 185930dc78e1SJohan Hedberg return; 186030dc78e1SJohan Hedberg 186156e5cb86SJohan Hedberg hci_dev_lock(hdev); 186230dc78e1SJohan Hedberg 1863343f935bSAndre Guedes if (discov->state != DISCOVERY_FINDING) 186430dc78e1SJohan Hedberg goto unlock; 186530dc78e1SJohan Hedberg 186630dc78e1SJohan Hedberg if (list_empty(&discov->resolve)) { 1867ff9ef578SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 186830dc78e1SJohan Hedberg goto unlock; 186930dc78e1SJohan Hedberg } 187030dc78e1SJohan Hedberg 187130dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 187230dc78e1SJohan Hedberg if (e && hci_resolve_name(hdev, e) == 0) { 187330dc78e1SJohan Hedberg e->name_state = NAME_PENDING; 187430dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_RESOLVING); 187530dc78e1SJohan Hedberg } else { 187630dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 187730dc78e1SJohan Hedberg } 187830dc78e1SJohan Hedberg 187930dc78e1SJohan Hedberg unlock: 188056e5cb86SJohan Hedberg hci_dev_unlock(hdev); 18811da177e4SLinus Torvalds } 18821da177e4SLinus Torvalds 18836039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 18841da177e4SLinus Torvalds { 188545bb4bf0SMarcel Holtmann struct inquiry_data data; 1886a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 18871da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 18881da177e4SLinus Torvalds 18891da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 18901da177e4SLinus Torvalds 189145bb4bf0SMarcel Holtmann if (!num_rsp) 189245bb4bf0SMarcel Holtmann return; 189345bb4bf0SMarcel Holtmann 18941519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 18951519cc17SAndre Guedes return; 18961519cc17SAndre Guedes 18971da177e4SLinus Torvalds hci_dev_lock(hdev); 189845bb4bf0SMarcel Holtmann 1899e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 1900388fc8faSJohan Hedberg bool name_known, ssp; 19013175405bSJohan Hedberg 19021da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 19031da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 19041da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 19051da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 19061da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 19071da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 19081da177e4SLinus Torvalds data.rssi = 0x00; 190941a96212SMarcel Holtmann data.ssp_mode = 0x00; 19103175405bSJohan Hedberg 1911388fc8faSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp); 191248264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 191304124681SGustavo F. Padovan info->dev_class, 0, !name_known, ssp, NULL, 191404124681SGustavo F. Padovan 0); 19151da177e4SLinus Torvalds } 191645bb4bf0SMarcel Holtmann 19171da177e4SLinus Torvalds hci_dev_unlock(hdev); 19181da177e4SLinus Torvalds } 19191da177e4SLinus Torvalds 19206039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 19211da177e4SLinus Torvalds { 1922a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 1923a9de9248SMarcel Holtmann struct hci_conn *conn; 19241da177e4SLinus Torvalds 1925a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 192645bb4bf0SMarcel Holtmann 19271da177e4SLinus Torvalds hci_dev_lock(hdev); 192845bb4bf0SMarcel Holtmann 1929a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 19309499237aSMarcel Holtmann if (!conn) { 19319499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 19329499237aSMarcel Holtmann goto unlock; 19339499237aSMarcel Holtmann 19349499237aSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 1935a9de9248SMarcel Holtmann if (!conn) 1936a9de9248SMarcel Holtmann goto unlock; 193745bb4bf0SMarcel Holtmann 19389499237aSMarcel Holtmann conn->type = SCO_LINK; 19399499237aSMarcel Holtmann } 19409499237aSMarcel Holtmann 1941a9de9248SMarcel Holtmann if (!ev->status) { 1942a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 1943769be974SMarcel Holtmann 1944769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 1945769be974SMarcel Holtmann conn->state = BT_CONFIG; 1946769be974SMarcel Holtmann hci_conn_hold(conn); 1947a9ea3ed9SSzymon Janc 1948a9ea3ed9SSzymon Janc if (!conn->out && !hci_conn_ssp_enabled(conn) && 1949a9ea3ed9SSzymon Janc !hci_find_link_key(hdev, &ev->bdaddr)) 1950a9ea3ed9SSzymon Janc conn->disc_timeout = HCI_PAIRING_TIMEOUT; 1951a9ea3ed9SSzymon Janc else 1952052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1953769be974SMarcel Holtmann } else 1954a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 1955a9de9248SMarcel Holtmann 19569eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 19577d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 19587d0db0a3SMarcel Holtmann 1959a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 1960a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1961a9de9248SMarcel Holtmann 1962a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 1963a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1964a9de9248SMarcel Holtmann 1965a9de9248SMarcel Holtmann /* Get remote features */ 1966a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 1967a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 1968a9de9248SMarcel Holtmann cp.handle = ev->handle; 1969769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 1970769be974SMarcel Holtmann sizeof(cp), &cp); 197145bb4bf0SMarcel Holtmann } 1972a9de9248SMarcel Holtmann 1973a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 1974d095c1ebSAndrei Emeltchenko if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) { 1975a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 1976a9de9248SMarcel Holtmann cp.handle = ev->handle; 1977a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 197804124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp), 197904124681SGustavo F. Padovan &cp); 1980a9de9248SMarcel Holtmann } 198117d5c04cSJohan Hedberg } else { 1982a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 198317d5c04cSJohan Hedberg if (conn->type == ACL_LINK) 1984744cf19eSJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 198548264f06SJohan Hedberg conn->dst_type, ev->status); 198617d5c04cSJohan Hedberg } 198745bb4bf0SMarcel Holtmann 1988e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 1989e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 199045bb4bf0SMarcel Holtmann 1991769be974SMarcel Holtmann if (ev->status) { 1992a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1993a9de9248SMarcel Holtmann hci_conn_del(conn); 1994c89b6e6bSMarcel Holtmann } else if (ev->link_type != ACL_LINK) 1995c89b6e6bSMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1996a9de9248SMarcel Holtmann 1997a9de9248SMarcel Holtmann unlock: 19981da177e4SLinus Torvalds hci_dev_unlock(hdev); 1999a9de9248SMarcel Holtmann 2000a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 20011da177e4SLinus Torvalds } 20021da177e4SLinus Torvalds 20036039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 20041da177e4SLinus Torvalds { 2005a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 20061da177e4SLinus Torvalds int mask = hdev->link_mode; 20071da177e4SLinus Torvalds 20086ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr, 2009807deac2SGustavo Padovan ev->link_type); 20101da177e4SLinus Torvalds 20111da177e4SLinus Torvalds mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); 20121da177e4SLinus Torvalds 2013138d22efSSzymon Janc if ((mask & HCI_LM_ACCEPT) && 2014138d22efSSzymon Janc !hci_blacklist_lookup(hdev, &ev->bdaddr)) { 20151da177e4SLinus Torvalds /* Connection accepted */ 2016c7bdd502SMarcel Holtmann struct inquiry_entry *ie; 20171da177e4SLinus Torvalds struct hci_conn *conn; 20181da177e4SLinus Torvalds 20191da177e4SLinus Torvalds hci_dev_lock(hdev); 2020b6a0dc82SMarcel Holtmann 2021cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2022cc11b9c1SAndrei Emeltchenko if (ie) 2023c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 2024c7bdd502SMarcel Holtmann 20258fc9ced3SGustavo Padovan conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, 20268fc9ced3SGustavo Padovan &ev->bdaddr); 20271da177e4SLinus Torvalds if (!conn) { 2028cc11b9c1SAndrei Emeltchenko conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); 2029cc11b9c1SAndrei Emeltchenko if (!conn) { 2030893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 20311da177e4SLinus Torvalds hci_dev_unlock(hdev); 20321da177e4SLinus Torvalds return; 20331da177e4SLinus Torvalds } 20341da177e4SLinus Torvalds } 2035b6a0dc82SMarcel Holtmann 20361da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 20371da177e4SLinus Torvalds conn->state = BT_CONNECT; 2038b6a0dc82SMarcel Holtmann 20391da177e4SLinus Torvalds hci_dev_unlock(hdev); 20401da177e4SLinus Torvalds 2041b6a0dc82SMarcel Holtmann if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) { 2042b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 2043b6a0dc82SMarcel Holtmann 20441da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 20451da177e4SLinus Torvalds 20461da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 20471da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 20481da177e4SLinus Torvalds else 20491da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 20501da177e4SLinus Torvalds 205104124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), 205204124681SGustavo F. Padovan &cp); 2053b6a0dc82SMarcel Holtmann } else { 2054b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 2055b6a0dc82SMarcel Holtmann 2056b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 2057a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 2058b6a0dc82SMarcel Holtmann 205982781e63SAndrei Emeltchenko cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40); 206082781e63SAndrei Emeltchenko cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40); 206182781e63SAndrei Emeltchenko cp.max_latency = __constant_cpu_to_le16(0xffff); 2062b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 2063b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 2064b6a0dc82SMarcel Holtmann 2065b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 2066b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 2067b6a0dc82SMarcel Holtmann } 20681da177e4SLinus Torvalds } else { 20691da177e4SLinus Torvalds /* Connection rejected */ 20701da177e4SLinus Torvalds struct hci_cp_reject_conn_req cp; 20711da177e4SLinus Torvalds 20721da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 20739f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_REJ_BAD_ADDR; 2074a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 20751da177e4SLinus Torvalds } 20761da177e4SLinus Torvalds } 20771da177e4SLinus Torvalds 2078f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err) 2079f0d6a0eaSMikel Astiz { 2080f0d6a0eaSMikel Astiz switch (err) { 2081f0d6a0eaSMikel Astiz case HCI_ERROR_CONNECTION_TIMEOUT: 2082f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_TIMEOUT; 2083f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_USER_TERM: 2084f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_LOW_RESOURCES: 2085f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_POWER_OFF: 2086f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_REMOTE; 2087f0d6a0eaSMikel Astiz case HCI_ERROR_LOCAL_HOST_TERM: 2088f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_LOCAL_HOST; 2089f0d6a0eaSMikel Astiz default: 2090f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_UNKNOWN; 2091f0d6a0eaSMikel Astiz } 2092f0d6a0eaSMikel Astiz } 2093f0d6a0eaSMikel Astiz 20946039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 20951da177e4SLinus Torvalds { 2096a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 209704837f64SMarcel Holtmann struct hci_conn *conn; 20981da177e4SLinus Torvalds 20999f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 21001da177e4SLinus Torvalds 21011da177e4SLinus Torvalds hci_dev_lock(hdev); 21021da177e4SLinus Torvalds 210304837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2104f7520543SJohan Hedberg if (!conn) 2105f7520543SJohan Hedberg goto unlock; 2106f7520543SJohan Hedberg 210737d9ef76SJohan Hedberg if (ev->status == 0) 21081da177e4SLinus Torvalds conn->state = BT_CLOSED; 21097d0db0a3SMarcel Holtmann 2110b644ba33SJohan Hedberg if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) && 2111b644ba33SJohan Hedberg (conn->type == ACL_LINK || conn->type == LE_LINK)) { 2112f0d6a0eaSMikel Astiz if (ev->status) { 211388c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 211488c3df13SJohan Hedberg conn->dst_type, ev->status); 2115f0d6a0eaSMikel Astiz } else { 2116f0d6a0eaSMikel Astiz u8 reason = hci_to_mgmt_reason(ev->reason); 2117f0d6a0eaSMikel Astiz 2118afc747a6SJohan Hedberg mgmt_device_disconnected(hdev, &conn->dst, conn->type, 2119f0d6a0eaSMikel Astiz conn->dst_type, reason); 2120f0d6a0eaSMikel Astiz } 212137d9ef76SJohan Hedberg } 2122f7520543SJohan Hedberg 212337d9ef76SJohan Hedberg if (ev->status == 0) { 21246ec5bcadSVishal Agarwal if (conn->type == ACL_LINK && conn->flush_key) 21256ec5bcadSVishal Agarwal hci_remove_link_key(hdev, &conn->dst); 21262950f21aSMarcel Holtmann hci_proto_disconn_cfm(conn, ev->reason); 21271da177e4SLinus Torvalds hci_conn_del(conn); 212837d9ef76SJohan Hedberg } 21291da177e4SLinus Torvalds 2130f7520543SJohan Hedberg unlock: 21311da177e4SLinus Torvalds hci_dev_unlock(hdev); 21321da177e4SLinus Torvalds } 21331da177e4SLinus Torvalds 21346039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2135a9de9248SMarcel Holtmann { 2136a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 2137a9de9248SMarcel Holtmann struct hci_conn *conn; 2138a9de9248SMarcel Holtmann 21399f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2140a9de9248SMarcel Holtmann 2141a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2142a9de9248SMarcel Holtmann 2143a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2144d7556e20SWaldemar Rymarkiewicz if (!conn) 2145d7556e20SWaldemar Rymarkiewicz goto unlock; 2146d7556e20SWaldemar Rymarkiewicz 2147765c2a96SJohan Hedberg if (!ev->status) { 2148aa64a8b5SJohan Hedberg if (!hci_conn_ssp_enabled(conn) && 214951a8efd7SJohan Hedberg test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) { 2150d7556e20SWaldemar Rymarkiewicz BT_INFO("re-auth of legacy device is not possible."); 215119f8def0SWaldemar Rymarkiewicz } else { 2152a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 2153765c2a96SJohan Hedberg conn->sec_level = conn->pending_sec_level; 215419f8def0SWaldemar Rymarkiewicz } 21552a611692SJohan Hedberg } else { 2156bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 2157bab73cb6SJohan Hedberg ev->status); 21582a611692SJohan Hedberg } 2159a9de9248SMarcel Holtmann 216051a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 216151a8efd7SJohan Hedberg clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags); 2162a9de9248SMarcel Holtmann 2163f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 2164aa64a8b5SJohan Hedberg if (!ev->status && hci_conn_ssp_enabled(conn)) { 2165f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 2166f8558555SMarcel Holtmann cp.handle = ev->handle; 2167f8558555SMarcel Holtmann cp.encrypt = 0x01; 2168d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 2169d7556e20SWaldemar Rymarkiewicz &cp); 2170f8558555SMarcel Holtmann } else { 2171f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 2172f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2173f8558555SMarcel Holtmann hci_conn_put(conn); 2174f8558555SMarcel Holtmann } 2175052b30b0SMarcel Holtmann } else { 2176a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 2177a9de9248SMarcel Holtmann 2178052b30b0SMarcel Holtmann hci_conn_hold(conn); 2179052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2180052b30b0SMarcel Holtmann hci_conn_put(conn); 2181052b30b0SMarcel Holtmann } 2182052b30b0SMarcel Holtmann 218351a8efd7SJohan Hedberg if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) { 2184a9de9248SMarcel Holtmann if (!ev->status) { 2185a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 2186f8558555SMarcel Holtmann cp.handle = ev->handle; 2187f8558555SMarcel Holtmann cp.encrypt = 0x01; 2188d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 2189d7556e20SWaldemar Rymarkiewicz &cp); 2190a9de9248SMarcel Holtmann } else { 219151a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 2192a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 2193a9de9248SMarcel Holtmann } 2194a9de9248SMarcel Holtmann } 2195a9de9248SMarcel Holtmann 2196d7556e20SWaldemar Rymarkiewicz unlock: 2197a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2198a9de9248SMarcel Holtmann } 2199a9de9248SMarcel Holtmann 22006039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 2201a9de9248SMarcel Holtmann { 2202127178d2SJohan Hedberg struct hci_ev_remote_name *ev = (void *) skb->data; 2203127178d2SJohan Hedberg struct hci_conn *conn; 2204127178d2SJohan Hedberg 2205a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2206a9de9248SMarcel Holtmann 2207a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 2208127178d2SJohan Hedberg 2209127178d2SJohan Hedberg hci_dev_lock(hdev); 2210127178d2SJohan Hedberg 2211127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2212b644ba33SJohan Hedberg 2213b644ba33SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 2214b644ba33SJohan Hedberg goto check_auth; 2215b644ba33SJohan Hedberg 2216b644ba33SJohan Hedberg if (ev->status == 0) 2217b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name, 2218b644ba33SJohan Hedberg strnlen(ev->name, HCI_MAX_NAME_LENGTH)); 2219b644ba33SJohan Hedberg else 2220b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0); 2221b644ba33SJohan Hedberg 2222b644ba33SJohan Hedberg check_auth: 222379c6c70cSJohan Hedberg if (!conn) 222479c6c70cSJohan Hedberg goto unlock; 222579c6c70cSJohan Hedberg 222679c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 222779c6c70cSJohan Hedberg goto unlock; 222879c6c70cSJohan Hedberg 222951a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 2230127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 2231127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 2232127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 2233127178d2SJohan Hedberg } 2234127178d2SJohan Hedberg 223579c6c70cSJohan Hedberg unlock: 2236127178d2SJohan Hedberg hci_dev_unlock(hdev); 2237a9de9248SMarcel Holtmann } 2238a9de9248SMarcel Holtmann 22396039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2240a9de9248SMarcel Holtmann { 2241a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 2242a9de9248SMarcel Holtmann struct hci_conn *conn; 2243a9de9248SMarcel Holtmann 22449f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2245a9de9248SMarcel Holtmann 2246a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2247a9de9248SMarcel Holtmann 2248a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2249a9de9248SMarcel Holtmann if (conn) { 2250a9de9248SMarcel Holtmann if (!ev->status) { 2251ae293196SMarcel Holtmann if (ev->encrypt) { 2252ae293196SMarcel Holtmann /* Encryption implies authentication */ 2253ae293196SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 2254a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 2255da85e5e5SVinicius Costa Gomes conn->sec_level = conn->pending_sec_level; 2256ae293196SMarcel Holtmann } else 2257a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_ENCRYPT; 2258a9de9248SMarcel Holtmann } 2259a9de9248SMarcel Holtmann 226051a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 2261a9de9248SMarcel Holtmann 2262a7d7723aSGustavo Padovan if (ev->status && conn->state == BT_CONNECTED) { 2263d839c813SGustavo Padovan hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE); 2264a7d7723aSGustavo Padovan hci_conn_put(conn); 2265a7d7723aSGustavo Padovan goto unlock; 2266a7d7723aSGustavo Padovan } 2267a7d7723aSGustavo Padovan 2268f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 2269f8558555SMarcel Holtmann if (!ev->status) 2270f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 2271f8558555SMarcel Holtmann 2272f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2273f8558555SMarcel Holtmann hci_conn_put(conn); 2274f8558555SMarcel Holtmann } else 2275a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 2276a9de9248SMarcel Holtmann } 2277a9de9248SMarcel Holtmann 2278a7d7723aSGustavo Padovan unlock: 2279a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2280a9de9248SMarcel Holtmann } 2281a9de9248SMarcel Holtmann 22826039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev, 2283807deac2SGustavo Padovan struct sk_buff *skb) 2284a9de9248SMarcel Holtmann { 2285a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 2286a9de9248SMarcel Holtmann struct hci_conn *conn; 2287a9de9248SMarcel Holtmann 22889f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2289a9de9248SMarcel Holtmann 2290a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2291a9de9248SMarcel Holtmann 2292a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2293a9de9248SMarcel Holtmann if (conn) { 2294a9de9248SMarcel Holtmann if (!ev->status) 2295a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_SECURE; 2296a9de9248SMarcel Holtmann 229751a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 2298a9de9248SMarcel Holtmann 2299a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 2300a9de9248SMarcel Holtmann } 2301a9de9248SMarcel Holtmann 2302a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2303a9de9248SMarcel Holtmann } 2304a9de9248SMarcel Holtmann 23056039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev, 2306807deac2SGustavo Padovan struct sk_buff *skb) 2307a9de9248SMarcel Holtmann { 2308a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 2309a9de9248SMarcel Holtmann struct hci_conn *conn; 2310a9de9248SMarcel Holtmann 23119f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2312a9de9248SMarcel Holtmann 2313a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2314a9de9248SMarcel Holtmann 2315a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2316ccd556feSJohan Hedberg if (!conn) 2317ccd556feSJohan Hedberg goto unlock; 2318ccd556feSJohan Hedberg 2319769be974SMarcel Holtmann if (!ev->status) 2320a9de9248SMarcel Holtmann memcpy(conn->features, ev->features, 8); 2321a9de9248SMarcel Holtmann 2322ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2323ccd556feSJohan Hedberg goto unlock; 2324ccd556feSJohan Hedberg 2325ccd556feSJohan Hedberg if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { 2326769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 2327769be974SMarcel Holtmann cp.handle = ev->handle; 2328769be974SMarcel Holtmann cp.page = 0x01; 2329ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 2330769be974SMarcel Holtmann sizeof(cp), &cp); 2331392599b9SJohan Hedberg goto unlock; 2332392599b9SJohan Hedberg } 2333392599b9SJohan Hedberg 2334671267bfSJohan Hedberg if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { 2335127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2336127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2337127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2338127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2339127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2340b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 2341b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 234208c79b61SJohan Hedberg conn->dst_type, 0, NULL, 0, 2343b644ba33SJohan Hedberg conn->dev_class); 2344392599b9SJohan Hedberg 2345127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2346769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2347769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2348769be974SMarcel Holtmann hci_conn_put(conn); 2349769be974SMarcel Holtmann } 2350769be974SMarcel Holtmann 2351ccd556feSJohan Hedberg unlock: 2352a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2353a9de9248SMarcel Holtmann } 2354a9de9248SMarcel Holtmann 23556039aa73SGustavo Padovan static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) 23566039aa73SGustavo Padovan { 23576039aa73SGustavo Padovan BT_DBG("%s", hdev->name); 23586039aa73SGustavo Padovan } 23596039aa73SGustavo Padovan 23606039aa73SGustavo Padovan static void hci_qos_setup_complete_evt(struct hci_dev *hdev, 2361807deac2SGustavo Padovan struct sk_buff *skb) 2362a9de9248SMarcel Holtmann { 2363a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2364a9de9248SMarcel Holtmann } 2365a9de9248SMarcel Holtmann 23666039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2367a9de9248SMarcel Holtmann { 2368a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 2369a9de9248SMarcel Holtmann __u16 opcode; 2370a9de9248SMarcel Holtmann 2371a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2372a9de9248SMarcel Holtmann 2373a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2374a9de9248SMarcel Holtmann 2375a9de9248SMarcel Holtmann switch (opcode) { 2376a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 2377a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 2378a9de9248SMarcel Holtmann break; 2379a9de9248SMarcel Holtmann 23804d93483bSAndre Guedes case HCI_OP_PERIODIC_INQ: 23814d93483bSAndre Guedes hci_cc_periodic_inq(hdev, skb); 23824d93483bSAndre Guedes break; 23834d93483bSAndre Guedes 2384a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 2385a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 2386a9de9248SMarcel Holtmann break; 2387a9de9248SMarcel Holtmann 2388a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 2389a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 2390a9de9248SMarcel Holtmann break; 2391a9de9248SMarcel Holtmann 2392a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 2393a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 2394a9de9248SMarcel Holtmann break; 2395a9de9248SMarcel Holtmann 2396e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 2397e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 2398e4e8e37cSMarcel Holtmann break; 2399e4e8e37cSMarcel Holtmann 2400a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 2401a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 2402a9de9248SMarcel Holtmann break; 2403a9de9248SMarcel Holtmann 2404e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 2405e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 2406e4e8e37cSMarcel Holtmann break; 2407e4e8e37cSMarcel Holtmann 2408e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 2409e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 2410e4e8e37cSMarcel Holtmann break; 2411e4e8e37cSMarcel Holtmann 2412a9de9248SMarcel Holtmann case HCI_OP_RESET: 2413a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 2414a9de9248SMarcel Holtmann break; 2415a9de9248SMarcel Holtmann 2416a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 2417a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 2418a9de9248SMarcel Holtmann break; 2419a9de9248SMarcel Holtmann 2420a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 2421a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 2422a9de9248SMarcel Holtmann break; 2423a9de9248SMarcel Holtmann 2424a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 2425a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 2426a9de9248SMarcel Holtmann break; 2427a9de9248SMarcel Holtmann 2428a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 2429a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 2430a9de9248SMarcel Holtmann break; 2431a9de9248SMarcel Holtmann 2432a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 2433a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 2434a9de9248SMarcel Holtmann break; 2435a9de9248SMarcel Holtmann 2436a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 2437a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 2438a9de9248SMarcel Holtmann break; 2439a9de9248SMarcel Holtmann 2440a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 2441a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 2442a9de9248SMarcel Holtmann break; 2443a9de9248SMarcel Holtmann 2444a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 2445a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 2446a9de9248SMarcel Holtmann break; 2447a9de9248SMarcel Holtmann 2448a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 2449a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 2450a9de9248SMarcel Holtmann break; 2451a9de9248SMarcel Holtmann 2452a9de9248SMarcel Holtmann case HCI_OP_HOST_BUFFER_SIZE: 2453a9de9248SMarcel Holtmann hci_cc_host_buffer_size(hdev, skb); 2454a9de9248SMarcel Holtmann break; 2455a9de9248SMarcel Holtmann 2456333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 2457333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 2458333140b5SMarcel Holtmann break; 2459333140b5SMarcel Holtmann 2460a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 2461a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 2462a9de9248SMarcel Holtmann break; 2463a9de9248SMarcel Holtmann 2464a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 2465a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 2466a9de9248SMarcel Holtmann break; 2467a9de9248SMarcel Holtmann 2468a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 2469a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 2470a9de9248SMarcel Holtmann break; 2471a9de9248SMarcel Holtmann 2472971e3a4bSAndre Guedes case HCI_OP_READ_LOCAL_EXT_FEATURES: 2473971e3a4bSAndre Guedes hci_cc_read_local_ext_features(hdev, skb); 2474971e3a4bSAndre Guedes break; 2475971e3a4bSAndre Guedes 2476a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 2477a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 2478a9de9248SMarcel Holtmann break; 2479a9de9248SMarcel Holtmann 2480a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 2481a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 2482a9de9248SMarcel Holtmann break; 2483a9de9248SMarcel Holtmann 2484350ee4cfSAndrei Emeltchenko case HCI_OP_READ_DATA_BLOCK_SIZE: 2485350ee4cfSAndrei Emeltchenko hci_cc_read_data_block_size(hdev, skb); 2486350ee4cfSAndrei Emeltchenko break; 2487350ee4cfSAndrei Emeltchenko 248823bb5763SJohan Hedberg case HCI_OP_WRITE_CA_TIMEOUT: 248923bb5763SJohan Hedberg hci_cc_write_ca_timeout(hdev, skb); 249023bb5763SJohan Hedberg break; 249123bb5763SJohan Hedberg 24921e89cffbSAndrei Emeltchenko case HCI_OP_READ_FLOW_CONTROL_MODE: 24931e89cffbSAndrei Emeltchenko hci_cc_read_flow_control_mode(hdev, skb); 24941e89cffbSAndrei Emeltchenko break; 24951e89cffbSAndrei Emeltchenko 2496928abaa7SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_INFO: 2497928abaa7SAndrei Emeltchenko hci_cc_read_local_amp_info(hdev, skb); 2498928abaa7SAndrei Emeltchenko break; 2499928abaa7SAndrei Emeltchenko 2500903e4541SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_ASSOC: 2501903e4541SAndrei Emeltchenko hci_cc_read_local_amp_assoc(hdev, skb); 2502903e4541SAndrei Emeltchenko break; 2503903e4541SAndrei Emeltchenko 2504b0916ea0SJohan Hedberg case HCI_OP_DELETE_STORED_LINK_KEY: 2505b0916ea0SJohan Hedberg hci_cc_delete_stored_link_key(hdev, skb); 2506b0916ea0SJohan Hedberg break; 2507b0916ea0SJohan Hedberg 2508d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_MASK: 2509d5859e22SJohan Hedberg hci_cc_set_event_mask(hdev, skb); 2510d5859e22SJohan Hedberg break; 2511d5859e22SJohan Hedberg 2512d5859e22SJohan Hedberg case HCI_OP_WRITE_INQUIRY_MODE: 2513d5859e22SJohan Hedberg hci_cc_write_inquiry_mode(hdev, skb); 2514d5859e22SJohan Hedberg break; 2515d5859e22SJohan Hedberg 2516d5859e22SJohan Hedberg case HCI_OP_READ_INQ_RSP_TX_POWER: 2517d5859e22SJohan Hedberg hci_cc_read_inq_rsp_tx_power(hdev, skb); 2518d5859e22SJohan Hedberg break; 2519d5859e22SJohan Hedberg 2520d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_FLT: 2521d5859e22SJohan Hedberg hci_cc_set_event_flt(hdev, skb); 2522d5859e22SJohan Hedberg break; 2523d5859e22SJohan Hedberg 2524980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_REPLY: 2525980e1a53SJohan Hedberg hci_cc_pin_code_reply(hdev, skb); 2526980e1a53SJohan Hedberg break; 2527980e1a53SJohan Hedberg 2528980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_NEG_REPLY: 2529980e1a53SJohan Hedberg hci_cc_pin_code_neg_reply(hdev, skb); 2530980e1a53SJohan Hedberg break; 2531980e1a53SJohan Hedberg 2532c35938b2SSzymon Janc case HCI_OP_READ_LOCAL_OOB_DATA: 2533c35938b2SSzymon Janc hci_cc_read_local_oob_data_reply(hdev, skb); 2534c35938b2SSzymon Janc break; 2535c35938b2SSzymon Janc 25366ed58ec5SVille Tervo case HCI_OP_LE_READ_BUFFER_SIZE: 25376ed58ec5SVille Tervo hci_cc_le_read_buffer_size(hdev, skb); 25386ed58ec5SVille Tervo break; 25396ed58ec5SVille Tervo 25408fa19098SJohan Hedberg case HCI_OP_LE_READ_ADV_TX_POWER: 25418fa19098SJohan Hedberg hci_cc_le_read_adv_tx_power(hdev, skb); 25428fa19098SJohan Hedberg break; 25438fa19098SJohan Hedberg 2544e36b04c8SJohan Hedberg case HCI_OP_LE_SET_EVENT_MASK: 2545e36b04c8SJohan Hedberg hci_cc_le_set_event_mask(hdev, skb); 2546e36b04c8SJohan Hedberg break; 2547e36b04c8SJohan Hedberg 2548a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_REPLY: 2549a5c29683SJohan Hedberg hci_cc_user_confirm_reply(hdev, skb); 2550a5c29683SJohan Hedberg break; 2551a5c29683SJohan Hedberg 2552a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_NEG_REPLY: 2553a5c29683SJohan Hedberg hci_cc_user_confirm_neg_reply(hdev, skb); 2554a5c29683SJohan Hedberg break; 2555a5c29683SJohan Hedberg 25561143d458SBrian Gix case HCI_OP_USER_PASSKEY_REPLY: 25571143d458SBrian Gix hci_cc_user_passkey_reply(hdev, skb); 25581143d458SBrian Gix break; 25591143d458SBrian Gix 25601143d458SBrian Gix case HCI_OP_USER_PASSKEY_NEG_REPLY: 25611143d458SBrian Gix hci_cc_user_passkey_neg_reply(hdev, skb); 256216cde993SSzymon Janc break; 256307f7fa5dSAndre Guedes 256407f7fa5dSAndre Guedes case HCI_OP_LE_SET_SCAN_PARAM: 256507f7fa5dSAndre Guedes hci_cc_le_set_scan_param(hdev, skb); 25661143d458SBrian Gix break; 25671143d458SBrian Gix 2568eb9d91f5SAndre Guedes case HCI_OP_LE_SET_SCAN_ENABLE: 2569eb9d91f5SAndre Guedes hci_cc_le_set_scan_enable(hdev, skb); 2570eb9d91f5SAndre Guedes break; 2571eb9d91f5SAndre Guedes 2572a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_REPLY: 2573a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_reply(hdev, skb); 2574a7a595f6SVinicius Costa Gomes break; 2575a7a595f6SVinicius Costa Gomes 2576a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_NEG_REPLY: 2577a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_neg_reply(hdev, skb); 2578a7a595f6SVinicius Costa Gomes break; 2579a7a595f6SVinicius Costa Gomes 2580f9b49306SAndre Guedes case HCI_OP_WRITE_LE_HOST_SUPPORTED: 2581f9b49306SAndre Guedes hci_cc_write_le_host_supported(hdev, skb); 2582f9b49306SAndre Guedes break; 2583f9b49306SAndre Guedes 258493c284eeSAndrei Emeltchenko case HCI_OP_WRITE_REMOTE_AMP_ASSOC: 258593c284eeSAndrei Emeltchenko hci_cc_write_remote_amp_assoc(hdev, skb); 258693c284eeSAndrei Emeltchenko break; 258793c284eeSAndrei Emeltchenko 2588a9de9248SMarcel Holtmann default: 25899f1db00cSAndrei Emeltchenko BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); 2590a9de9248SMarcel Holtmann break; 2591a9de9248SMarcel Holtmann } 2592a9de9248SMarcel Holtmann 25936bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 25946bd32326SVille Tervo del_timer(&hdev->cmd_timer); 25956bd32326SVille Tervo 2596a9de9248SMarcel Holtmann if (ev->ncmd) { 2597a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2598a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2599c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2600a9de9248SMarcel Holtmann } 2601a9de9248SMarcel Holtmann } 2602a9de9248SMarcel Holtmann 26036039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 2604a9de9248SMarcel Holtmann { 2605a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 2606a9de9248SMarcel Holtmann __u16 opcode; 2607a9de9248SMarcel Holtmann 2608a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2609a9de9248SMarcel Holtmann 2610a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2611a9de9248SMarcel Holtmann 2612a9de9248SMarcel Holtmann switch (opcode) { 2613a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 2614a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 2615a9de9248SMarcel Holtmann break; 2616a9de9248SMarcel Holtmann 2617a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 2618a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 2619a9de9248SMarcel Holtmann break; 2620a9de9248SMarcel Holtmann 2621a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 2622a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 2623a9de9248SMarcel Holtmann break; 2624a9de9248SMarcel Holtmann 2625f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 2626f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 2627f8558555SMarcel Holtmann break; 2628f8558555SMarcel Holtmann 2629f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 2630f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 2631f8558555SMarcel Holtmann break; 2632f8558555SMarcel Holtmann 2633a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 2634a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 2635a9de9248SMarcel Holtmann break; 2636a9de9248SMarcel Holtmann 2637769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 2638769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 2639769be974SMarcel Holtmann break; 2640769be974SMarcel Holtmann 2641769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 2642769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 2643769be974SMarcel Holtmann break; 2644769be974SMarcel Holtmann 2645a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 2646a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 2647a9de9248SMarcel Holtmann break; 2648a9de9248SMarcel Holtmann 2649a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 2650a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 2651a9de9248SMarcel Holtmann break; 2652a9de9248SMarcel Holtmann 2653a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 2654a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 2655a9de9248SMarcel Holtmann break; 2656a9de9248SMarcel Holtmann 26578962ee74SJohan Hedberg case HCI_OP_DISCONNECT: 265888c3df13SJohan Hedberg hci_cs_disconnect(hdev, ev->status); 26598962ee74SJohan Hedberg break; 26608962ee74SJohan Hedberg 2661fcd89c09SVille Tervo case HCI_OP_LE_CREATE_CONN: 2662fcd89c09SVille Tervo hci_cs_le_create_conn(hdev, ev->status); 2663fcd89c09SVille Tervo break; 2664fcd89c09SVille Tervo 2665a7a595f6SVinicius Costa Gomes case HCI_OP_LE_START_ENC: 2666a7a595f6SVinicius Costa Gomes hci_cs_le_start_enc(hdev, ev->status); 2667a7a595f6SVinicius Costa Gomes break; 2668a7a595f6SVinicius Costa Gomes 2669a02226d6SAndrei Emeltchenko case HCI_OP_CREATE_PHY_LINK: 2670a02226d6SAndrei Emeltchenko hci_cs_create_phylink(hdev, ev->status); 2671a02226d6SAndrei Emeltchenko break; 2672a02226d6SAndrei Emeltchenko 26730b26ab9dSAndrei Emeltchenko case HCI_OP_ACCEPT_PHY_LINK: 26740b26ab9dSAndrei Emeltchenko hci_cs_accept_phylink(hdev, ev->status); 26750b26ab9dSAndrei Emeltchenko break; 26760b26ab9dSAndrei Emeltchenko 26775ce66b59SAndrei Emeltchenko case HCI_OP_CREATE_LOGICAL_LINK: 26785ce66b59SAndrei Emeltchenko hci_cs_create_logical_link(hdev, ev->status); 26795ce66b59SAndrei Emeltchenko break; 26805ce66b59SAndrei Emeltchenko 2681a9de9248SMarcel Holtmann default: 26829f1db00cSAndrei Emeltchenko BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); 2683a9de9248SMarcel Holtmann break; 2684a9de9248SMarcel Holtmann } 2685a9de9248SMarcel Holtmann 26866bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 26876bd32326SVille Tervo del_timer(&hdev->cmd_timer); 26886bd32326SVille Tervo 268910572132SGustavo F. Padovan if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2690a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2691a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2692c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2693a9de9248SMarcel Holtmann } 2694a9de9248SMarcel Holtmann } 2695a9de9248SMarcel Holtmann 26966039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2697a9de9248SMarcel Holtmann { 2698a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 2699a9de9248SMarcel Holtmann struct hci_conn *conn; 2700a9de9248SMarcel Holtmann 27019f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2702a9de9248SMarcel Holtmann 2703a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2704a9de9248SMarcel Holtmann 2705a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2706a9de9248SMarcel Holtmann if (conn) { 2707a9de9248SMarcel Holtmann if (!ev->status) { 2708a9de9248SMarcel Holtmann if (ev->role) 2709a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_MASTER; 2710a9de9248SMarcel Holtmann else 2711a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_MASTER; 2712a9de9248SMarcel Holtmann } 2713a9de9248SMarcel Holtmann 271451a8efd7SJohan Hedberg clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); 2715a9de9248SMarcel Holtmann 2716a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 2717a9de9248SMarcel Holtmann } 2718a9de9248SMarcel Holtmann 2719a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2720a9de9248SMarcel Holtmann } 2721a9de9248SMarcel Holtmann 27226039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 27231da177e4SLinus Torvalds { 2724a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 27251da177e4SLinus Torvalds int i; 27261da177e4SLinus Torvalds 272732ac5b9bSAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) { 272832ac5b9bSAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 272932ac5b9bSAndrei Emeltchenko return; 273032ac5b9bSAndrei Emeltchenko } 273132ac5b9bSAndrei Emeltchenko 2732c5993de8SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 2733c5993de8SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_pkts_info)) { 27341da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 27351da177e4SLinus Torvalds return; 27361da177e4SLinus Torvalds } 27371da177e4SLinus Torvalds 2738c5993de8SAndrei Emeltchenko BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 2739c5993de8SAndrei Emeltchenko 2740613a1c0cSAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 2741613a1c0cSAndrei Emeltchenko struct hci_comp_pkts_info *info = &ev->handles[i]; 27421da177e4SLinus Torvalds struct hci_conn *conn; 27431da177e4SLinus Torvalds __u16 handle, count; 27441da177e4SLinus Torvalds 2745613a1c0cSAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 2746613a1c0cSAndrei Emeltchenko count = __le16_to_cpu(info->count); 27471da177e4SLinus Torvalds 27481da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 2749f4280918SAndrei Emeltchenko if (!conn) 2750f4280918SAndrei Emeltchenko continue; 2751f4280918SAndrei Emeltchenko 27521da177e4SLinus Torvalds conn->sent -= count; 27531da177e4SLinus Torvalds 2754f4280918SAndrei Emeltchenko switch (conn->type) { 2755f4280918SAndrei Emeltchenko case ACL_LINK: 275670f23020SAndrei Emeltchenko hdev->acl_cnt += count; 275770f23020SAndrei Emeltchenko if (hdev->acl_cnt > hdev->acl_pkts) 27581da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 2759f4280918SAndrei Emeltchenko break; 2760f4280918SAndrei Emeltchenko 2761f4280918SAndrei Emeltchenko case LE_LINK: 27626ed58ec5SVille Tervo if (hdev->le_pkts) { 27636ed58ec5SVille Tervo hdev->le_cnt += count; 27646ed58ec5SVille Tervo if (hdev->le_cnt > hdev->le_pkts) 27656ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 27666ed58ec5SVille Tervo } else { 27676ed58ec5SVille Tervo hdev->acl_cnt += count; 27686ed58ec5SVille Tervo if (hdev->acl_cnt > hdev->acl_pkts) 27696ed58ec5SVille Tervo hdev->acl_cnt = hdev->acl_pkts; 27706ed58ec5SVille Tervo } 2771f4280918SAndrei Emeltchenko break; 2772f4280918SAndrei Emeltchenko 2773f4280918SAndrei Emeltchenko case SCO_LINK: 277470f23020SAndrei Emeltchenko hdev->sco_cnt += count; 277570f23020SAndrei Emeltchenko if (hdev->sco_cnt > hdev->sco_pkts) 27765b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 2777f4280918SAndrei Emeltchenko break; 2778f4280918SAndrei Emeltchenko 2779f4280918SAndrei Emeltchenko default: 2780f4280918SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 2781f4280918SAndrei Emeltchenko break; 27821da177e4SLinus Torvalds } 27831da177e4SLinus Torvalds } 2784a9de9248SMarcel Holtmann 27853eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 27861da177e4SLinus Torvalds } 27871da177e4SLinus Torvalds 278876ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev, 278976ef7cf7SAndrei Emeltchenko __u16 handle) 279076ef7cf7SAndrei Emeltchenko { 279176ef7cf7SAndrei Emeltchenko struct hci_chan *chan; 279276ef7cf7SAndrei Emeltchenko 279376ef7cf7SAndrei Emeltchenko switch (hdev->dev_type) { 279476ef7cf7SAndrei Emeltchenko case HCI_BREDR: 279576ef7cf7SAndrei Emeltchenko return hci_conn_hash_lookup_handle(hdev, handle); 279676ef7cf7SAndrei Emeltchenko case HCI_AMP: 279776ef7cf7SAndrei Emeltchenko chan = hci_chan_lookup_handle(hdev, handle); 279876ef7cf7SAndrei Emeltchenko if (chan) 279976ef7cf7SAndrei Emeltchenko return chan->conn; 280076ef7cf7SAndrei Emeltchenko break; 280176ef7cf7SAndrei Emeltchenko default: 280276ef7cf7SAndrei Emeltchenko BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type); 280376ef7cf7SAndrei Emeltchenko break; 280476ef7cf7SAndrei Emeltchenko } 280576ef7cf7SAndrei Emeltchenko 280676ef7cf7SAndrei Emeltchenko return NULL; 280776ef7cf7SAndrei Emeltchenko } 280876ef7cf7SAndrei Emeltchenko 28096039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb) 281025e89e99SAndrei Emeltchenko { 281125e89e99SAndrei Emeltchenko struct hci_ev_num_comp_blocks *ev = (void *) skb->data; 281225e89e99SAndrei Emeltchenko int i; 281325e89e99SAndrei Emeltchenko 281425e89e99SAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) { 281525e89e99SAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 281625e89e99SAndrei Emeltchenko return; 281725e89e99SAndrei Emeltchenko } 281825e89e99SAndrei Emeltchenko 281925e89e99SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 282025e89e99SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_blocks_info)) { 282125e89e99SAndrei Emeltchenko BT_DBG("%s bad parameters", hdev->name); 282225e89e99SAndrei Emeltchenko return; 282325e89e99SAndrei Emeltchenko } 282425e89e99SAndrei Emeltchenko 282525e89e99SAndrei Emeltchenko BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks, 282625e89e99SAndrei Emeltchenko ev->num_hndl); 282725e89e99SAndrei Emeltchenko 282825e89e99SAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 282925e89e99SAndrei Emeltchenko struct hci_comp_blocks_info *info = &ev->handles[i]; 283076ef7cf7SAndrei Emeltchenko struct hci_conn *conn = NULL; 283125e89e99SAndrei Emeltchenko __u16 handle, block_count; 283225e89e99SAndrei Emeltchenko 283325e89e99SAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 283425e89e99SAndrei Emeltchenko block_count = __le16_to_cpu(info->blocks); 283525e89e99SAndrei Emeltchenko 283676ef7cf7SAndrei Emeltchenko conn = __hci_conn_lookup_handle(hdev, handle); 283725e89e99SAndrei Emeltchenko if (!conn) 283825e89e99SAndrei Emeltchenko continue; 283925e89e99SAndrei Emeltchenko 284025e89e99SAndrei Emeltchenko conn->sent -= block_count; 284125e89e99SAndrei Emeltchenko 284225e89e99SAndrei Emeltchenko switch (conn->type) { 284325e89e99SAndrei Emeltchenko case ACL_LINK: 2844bd1eb66bSAndrei Emeltchenko case AMP_LINK: 284525e89e99SAndrei Emeltchenko hdev->block_cnt += block_count; 284625e89e99SAndrei Emeltchenko if (hdev->block_cnt > hdev->num_blocks) 284725e89e99SAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 284825e89e99SAndrei Emeltchenko break; 284925e89e99SAndrei Emeltchenko 285025e89e99SAndrei Emeltchenko default: 285125e89e99SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 285225e89e99SAndrei Emeltchenko break; 285325e89e99SAndrei Emeltchenko } 285425e89e99SAndrei Emeltchenko } 285525e89e99SAndrei Emeltchenko 285625e89e99SAndrei Emeltchenko queue_work(hdev->workqueue, &hdev->tx_work); 285725e89e99SAndrei Emeltchenko } 285825e89e99SAndrei Emeltchenko 28596039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 28601da177e4SLinus Torvalds { 2861a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 286204837f64SMarcel Holtmann struct hci_conn *conn; 28631da177e4SLinus Torvalds 28649f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 28651da177e4SLinus Torvalds 28661da177e4SLinus Torvalds hci_dev_lock(hdev); 28671da177e4SLinus Torvalds 286804837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 286904837f64SMarcel Holtmann if (conn) { 287004837f64SMarcel Holtmann conn->mode = ev->mode; 287104837f64SMarcel Holtmann conn->interval = __le16_to_cpu(ev->interval); 287204837f64SMarcel Holtmann 28738fc9ced3SGustavo Padovan if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, 28748fc9ced3SGustavo Padovan &conn->flags)) { 287504837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 287658a681efSJohan Hedberg set_bit(HCI_CONN_POWER_SAVE, &conn->flags); 287704837f64SMarcel Holtmann else 287858a681efSJohan Hedberg clear_bit(HCI_CONN_POWER_SAVE, &conn->flags); 287904837f64SMarcel Holtmann } 2880e73439d8SMarcel Holtmann 288151a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 2882e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 288304837f64SMarcel Holtmann } 288404837f64SMarcel Holtmann 288504837f64SMarcel Holtmann hci_dev_unlock(hdev); 288604837f64SMarcel Holtmann } 288704837f64SMarcel Holtmann 28886039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 28891da177e4SLinus Torvalds { 2890052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 2891052b30b0SMarcel Holtmann struct hci_conn *conn; 2892052b30b0SMarcel Holtmann 2893a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2894052b30b0SMarcel Holtmann 2895052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2896052b30b0SMarcel Holtmann 2897052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2898b6f98044SWaldemar Rymarkiewicz if (!conn) 2899b6f98044SWaldemar Rymarkiewicz goto unlock; 2900b6f98044SWaldemar Rymarkiewicz 2901b6f98044SWaldemar Rymarkiewicz if (conn->state == BT_CONNECTED) { 2902052b30b0SMarcel Holtmann hci_conn_hold(conn); 2903052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 2904052b30b0SMarcel Holtmann hci_conn_put(conn); 2905052b30b0SMarcel Holtmann } 2906052b30b0SMarcel Holtmann 2907a8b2d5c2SJohan Hedberg if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags)) 290803b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 290903b555e1SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 2910a8b2d5c2SJohan Hedberg else if (test_bit(HCI_MGMT, &hdev->dev_flags)) { 2911a770bb5aSWaldemar Rymarkiewicz u8 secure; 2912a770bb5aSWaldemar Rymarkiewicz 2913a770bb5aSWaldemar Rymarkiewicz if (conn->pending_sec_level == BT_SECURITY_HIGH) 2914a770bb5aSWaldemar Rymarkiewicz secure = 1; 2915a770bb5aSWaldemar Rymarkiewicz else 2916a770bb5aSWaldemar Rymarkiewicz secure = 0; 2917a770bb5aSWaldemar Rymarkiewicz 2918744cf19eSJohan Hedberg mgmt_pin_code_request(hdev, &ev->bdaddr, secure); 2919a770bb5aSWaldemar Rymarkiewicz } 2920980e1a53SJohan Hedberg 2921b6f98044SWaldemar Rymarkiewicz unlock: 2922052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 29231da177e4SLinus Torvalds } 29241da177e4SLinus Torvalds 29256039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 29261da177e4SLinus Torvalds { 292755ed8ca1SJohan Hedberg struct hci_ev_link_key_req *ev = (void *) skb->data; 292855ed8ca1SJohan Hedberg struct hci_cp_link_key_reply cp; 292955ed8ca1SJohan Hedberg struct hci_conn *conn; 293055ed8ca1SJohan Hedberg struct link_key *key; 293155ed8ca1SJohan Hedberg 2932a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 293355ed8ca1SJohan Hedberg 2934a8b2d5c2SJohan Hedberg if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) 293555ed8ca1SJohan Hedberg return; 293655ed8ca1SJohan Hedberg 293755ed8ca1SJohan Hedberg hci_dev_lock(hdev); 293855ed8ca1SJohan Hedberg 293955ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, &ev->bdaddr); 294055ed8ca1SJohan Hedberg if (!key) { 29416ed93dc6SAndrei Emeltchenko BT_DBG("%s link key not found for %pMR", hdev->name, 29426ed93dc6SAndrei Emeltchenko &ev->bdaddr); 294355ed8ca1SJohan Hedberg goto not_found; 294455ed8ca1SJohan Hedberg } 294555ed8ca1SJohan Hedberg 29466ed93dc6SAndrei Emeltchenko BT_DBG("%s found key type %u for %pMR", hdev->name, key->type, 29476ed93dc6SAndrei Emeltchenko &ev->bdaddr); 294855ed8ca1SJohan Hedberg 2949a8b2d5c2SJohan Hedberg if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) && 2950b6020ba0SWaldemar Rymarkiewicz key->type == HCI_LK_DEBUG_COMBINATION) { 295155ed8ca1SJohan Hedberg BT_DBG("%s ignoring debug key", hdev->name); 295255ed8ca1SJohan Hedberg goto not_found; 295355ed8ca1SJohan Hedberg } 295455ed8ca1SJohan Hedberg 295555ed8ca1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 295660b83f57SWaldemar Rymarkiewicz if (conn) { 295760b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_UNAUTH_COMBINATION && 2958807deac2SGustavo Padovan conn->auth_type != 0xff && (conn->auth_type & 0x01)) { 295955ed8ca1SJohan Hedberg BT_DBG("%s ignoring unauthenticated key", hdev->name); 296055ed8ca1SJohan Hedberg goto not_found; 296155ed8ca1SJohan Hedberg } 296255ed8ca1SJohan Hedberg 296360b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && 296460b83f57SWaldemar Rymarkiewicz conn->pending_sec_level == BT_SECURITY_HIGH) { 29658fc9ced3SGustavo Padovan BT_DBG("%s ignoring key unauthenticated for high security", 29668fc9ced3SGustavo Padovan hdev->name); 296760b83f57SWaldemar Rymarkiewicz goto not_found; 296860b83f57SWaldemar Rymarkiewicz } 296960b83f57SWaldemar Rymarkiewicz 297060b83f57SWaldemar Rymarkiewicz conn->key_type = key->type; 297160b83f57SWaldemar Rymarkiewicz conn->pin_length = key->pin_len; 297260b83f57SWaldemar Rymarkiewicz } 297360b83f57SWaldemar Rymarkiewicz 297455ed8ca1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 29759b3b4460SAndrei Emeltchenko memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE); 297655ed8ca1SJohan Hedberg 297755ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 297855ed8ca1SJohan Hedberg 297955ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 298055ed8ca1SJohan Hedberg 298155ed8ca1SJohan Hedberg return; 298255ed8ca1SJohan Hedberg 298355ed8ca1SJohan Hedberg not_found: 298455ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 298555ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 29861da177e4SLinus Torvalds } 29871da177e4SLinus Torvalds 29886039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 29891da177e4SLinus Torvalds { 2990052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 2991052b30b0SMarcel Holtmann struct hci_conn *conn; 299255ed8ca1SJohan Hedberg u8 pin_len = 0; 2993052b30b0SMarcel Holtmann 2994a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2995052b30b0SMarcel Holtmann 2996052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2997052b30b0SMarcel Holtmann 2998052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2999052b30b0SMarcel Holtmann if (conn) { 3000052b30b0SMarcel Holtmann hci_conn_hold(conn); 3001052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 3002980e1a53SJohan Hedberg pin_len = conn->pin_length; 300313d39315SWaldemar Rymarkiewicz 300413d39315SWaldemar Rymarkiewicz if (ev->key_type != HCI_LK_CHANGED_COMBINATION) 300513d39315SWaldemar Rymarkiewicz conn->key_type = ev->key_type; 300613d39315SWaldemar Rymarkiewicz 3007052b30b0SMarcel Holtmann hci_conn_put(conn); 3008052b30b0SMarcel Holtmann } 3009052b30b0SMarcel Holtmann 3010a8b2d5c2SJohan Hedberg if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) 3011d25e28abSJohan Hedberg hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, 301255ed8ca1SJohan Hedberg ev->key_type, pin_len); 301355ed8ca1SJohan Hedberg 3014052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 30151da177e4SLinus Torvalds } 30161da177e4SLinus Torvalds 30176039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 301804837f64SMarcel Holtmann { 3019a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 302004837f64SMarcel Holtmann struct hci_conn *conn; 302104837f64SMarcel Holtmann 30229f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 302304837f64SMarcel Holtmann 302404837f64SMarcel Holtmann hci_dev_lock(hdev); 302504837f64SMarcel Holtmann 302604837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 30271da177e4SLinus Torvalds if (conn && !ev->status) { 30281da177e4SLinus Torvalds struct inquiry_entry *ie; 30291da177e4SLinus Torvalds 3030cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 3031cc11b9c1SAndrei Emeltchenko if (ie) { 30321da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 30331da177e4SLinus Torvalds ie->timestamp = jiffies; 30341da177e4SLinus Torvalds } 30351da177e4SLinus Torvalds } 30361da177e4SLinus Torvalds 30371da177e4SLinus Torvalds hci_dev_unlock(hdev); 30381da177e4SLinus Torvalds } 30391da177e4SLinus Torvalds 30406039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 3041a8746417SMarcel Holtmann { 3042a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 3043a8746417SMarcel Holtmann struct hci_conn *conn; 3044a8746417SMarcel Holtmann 30459f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 3046a8746417SMarcel Holtmann 3047a8746417SMarcel Holtmann hci_dev_lock(hdev); 3048a8746417SMarcel Holtmann 3049a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3050a8746417SMarcel Holtmann if (conn && !ev->status) 3051a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 3052a8746417SMarcel Holtmann 3053a8746417SMarcel Holtmann hci_dev_unlock(hdev); 3054a8746417SMarcel Holtmann } 3055a8746417SMarcel Holtmann 30566039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 305785a1e930SMarcel Holtmann { 3058a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 305985a1e930SMarcel Holtmann struct inquiry_entry *ie; 306085a1e930SMarcel Holtmann 306185a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 306285a1e930SMarcel Holtmann 306385a1e930SMarcel Holtmann hci_dev_lock(hdev); 306485a1e930SMarcel Holtmann 3065cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 3066cc11b9c1SAndrei Emeltchenko if (ie) { 306785a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 306885a1e930SMarcel Holtmann ie->timestamp = jiffies; 306985a1e930SMarcel Holtmann } 307085a1e930SMarcel Holtmann 307185a1e930SMarcel Holtmann hci_dev_unlock(hdev); 307285a1e930SMarcel Holtmann } 307385a1e930SMarcel Holtmann 30746039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, 3075807deac2SGustavo Padovan struct sk_buff *skb) 3076a9de9248SMarcel Holtmann { 3077a9de9248SMarcel Holtmann struct inquiry_data data; 3078a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 3079388fc8faSJohan Hedberg bool name_known, ssp; 3080a9de9248SMarcel Holtmann 3081a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 3082a9de9248SMarcel Holtmann 3083a9de9248SMarcel Holtmann if (!num_rsp) 3084a9de9248SMarcel Holtmann return; 3085a9de9248SMarcel Holtmann 30861519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 30871519cc17SAndre Guedes return; 30881519cc17SAndre Guedes 3089a9de9248SMarcel Holtmann hci_dev_lock(hdev); 3090a9de9248SMarcel Holtmann 3091a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 3092138d22efSSzymon Janc struct inquiry_info_with_rssi_and_pscan_mode *info; 3093138d22efSSzymon Janc info = (void *) (skb->data + 1); 3094a9de9248SMarcel Holtmann 3095e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 3096a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 3097a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 3098a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 3099a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 3100a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 3101a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 3102a9de9248SMarcel Holtmann data.rssi = info->rssi; 310341a96212SMarcel Holtmann data.ssp_mode = 0x00; 31043175405bSJohan Hedberg 31053175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 3106388fc8faSJohan Hedberg false, &ssp); 310748264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 3108e17acd40SJohan Hedberg info->dev_class, info->rssi, 3109388fc8faSJohan Hedberg !name_known, ssp, NULL, 0); 3110a9de9248SMarcel Holtmann } 3111a9de9248SMarcel Holtmann } else { 3112a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 3113a9de9248SMarcel Holtmann 3114e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 3115a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 3116a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 3117a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 3118a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 3119a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 3120a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 3121a9de9248SMarcel Holtmann data.rssi = info->rssi; 312241a96212SMarcel Holtmann data.ssp_mode = 0x00; 31233175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 3124388fc8faSJohan Hedberg false, &ssp); 312548264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 3126e17acd40SJohan Hedberg info->dev_class, info->rssi, 3127388fc8faSJohan Hedberg !name_known, ssp, NULL, 0); 3128a9de9248SMarcel Holtmann } 3129a9de9248SMarcel Holtmann } 3130a9de9248SMarcel Holtmann 3131a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 3132a9de9248SMarcel Holtmann } 3133a9de9248SMarcel Holtmann 31346039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev, 3135807deac2SGustavo Padovan struct sk_buff *skb) 3136a9de9248SMarcel Holtmann { 313741a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 313841a96212SMarcel Holtmann struct hci_conn *conn; 313941a96212SMarcel Holtmann 3140a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 314141a96212SMarcel Holtmann 314241a96212SMarcel Holtmann hci_dev_lock(hdev); 314341a96212SMarcel Holtmann 314441a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3145ccd556feSJohan Hedberg if (!conn) 3146ccd556feSJohan Hedberg goto unlock; 3147ccd556feSJohan Hedberg 3148769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 314941a96212SMarcel Holtmann struct inquiry_entry *ie; 315041a96212SMarcel Holtmann 3151cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 3152cc11b9c1SAndrei Emeltchenko if (ie) 315302b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 315441a96212SMarcel Holtmann 315502b7cc62SJohan Hedberg if (ev->features[0] & LMP_HOST_SSP) 315658a681efSJohan Hedberg set_bit(HCI_CONN_SSP_ENABLED, &conn->flags); 315741a96212SMarcel Holtmann } 315841a96212SMarcel Holtmann 3159ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 3160ccd556feSJohan Hedberg goto unlock; 3161ccd556feSJohan Hedberg 3162671267bfSJohan Hedberg if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { 3163127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 3164127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 3165127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 3166127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 3167127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 3168b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 3169b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 317008c79b61SJohan Hedberg conn->dst_type, 0, NULL, 0, 3171b644ba33SJohan Hedberg conn->dev_class); 3172392599b9SJohan Hedberg 3173127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 3174769be974SMarcel Holtmann conn->state = BT_CONNECTED; 3175769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 3176769be974SMarcel Holtmann hci_conn_put(conn); 3177769be974SMarcel Holtmann } 3178769be974SMarcel Holtmann 3179ccd556feSJohan Hedberg unlock: 318041a96212SMarcel Holtmann hci_dev_unlock(hdev); 3181a9de9248SMarcel Holtmann } 3182a9de9248SMarcel Holtmann 31836039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev, 3184807deac2SGustavo Padovan struct sk_buff *skb) 3185a9de9248SMarcel Holtmann { 3186b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 3187b6a0dc82SMarcel Holtmann struct hci_conn *conn; 3188b6a0dc82SMarcel Holtmann 31899f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 3190b6a0dc82SMarcel Holtmann 3191b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 3192b6a0dc82SMarcel Holtmann 3193b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 31949dc0a3afSMarcel Holtmann if (!conn) { 31959dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 31969dc0a3afSMarcel Holtmann goto unlock; 31979dc0a3afSMarcel Holtmann 31989dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 3199b6a0dc82SMarcel Holtmann if (!conn) 3200b6a0dc82SMarcel Holtmann goto unlock; 3201b6a0dc82SMarcel Holtmann 32029dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 32039dc0a3afSMarcel Holtmann } 32049dc0a3afSMarcel Holtmann 3205732547f9SMarcel Holtmann switch (ev->status) { 3206732547f9SMarcel Holtmann case 0x00: 3207732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 3208732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 3209732547f9SMarcel Holtmann 32109eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 3211732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 3212732547f9SMarcel Holtmann break; 3213732547f9SMarcel Holtmann 3214705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 3215732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 32161038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 3217732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 3218732547f9SMarcel Holtmann if (conn->out && conn->attempt < 2) { 3219efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 3220efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 3221efc7688bSMarcel Holtmann hci_setup_sync(conn, conn->link->handle); 3222efc7688bSMarcel Holtmann goto unlock; 3223efc7688bSMarcel Holtmann } 3224732547f9SMarcel Holtmann /* fall through */ 3225efc7688bSMarcel Holtmann 3226732547f9SMarcel Holtmann default: 3227b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 3228732547f9SMarcel Holtmann break; 3229732547f9SMarcel Holtmann } 3230b6a0dc82SMarcel Holtmann 3231b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 3232b6a0dc82SMarcel Holtmann if (ev->status) 3233b6a0dc82SMarcel Holtmann hci_conn_del(conn); 3234b6a0dc82SMarcel Holtmann 3235b6a0dc82SMarcel Holtmann unlock: 3236b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 3237a9de9248SMarcel Holtmann } 3238a9de9248SMarcel Holtmann 32396039aa73SGustavo Padovan static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) 3240a9de9248SMarcel Holtmann { 3241a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 3242a9de9248SMarcel Holtmann } 3243a9de9248SMarcel Holtmann 32446039aa73SGustavo Padovan static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) 324504837f64SMarcel Holtmann { 3246a9de9248SMarcel Holtmann struct hci_ev_sniff_subrate *ev = (void *) skb->data; 324704837f64SMarcel Holtmann 32489f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 324904837f64SMarcel Holtmann } 325004837f64SMarcel Holtmann 32516039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, 3252807deac2SGustavo Padovan struct sk_buff *skb) 3253a9de9248SMarcel Holtmann { 3254a9de9248SMarcel Holtmann struct inquiry_data data; 3255a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 3256a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 32579d939d94SVishal Agarwal size_t eir_len; 3258a9de9248SMarcel Holtmann 3259a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 3260a9de9248SMarcel Holtmann 3261a9de9248SMarcel Holtmann if (!num_rsp) 3262a9de9248SMarcel Holtmann return; 3263a9de9248SMarcel Holtmann 32641519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 32651519cc17SAndre Guedes return; 32661519cc17SAndre Guedes 3267a9de9248SMarcel Holtmann hci_dev_lock(hdev); 3268a9de9248SMarcel Holtmann 3269e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 3270388fc8faSJohan Hedberg bool name_known, ssp; 3271561aafbcSJohan Hedberg 3272a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 3273a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 3274a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 3275a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 3276a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 3277a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 3278a9de9248SMarcel Holtmann data.rssi = info->rssi; 327941a96212SMarcel Holtmann data.ssp_mode = 0x01; 3280561aafbcSJohan Hedberg 3281a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 32824ddb1930SJohan Hedberg name_known = eir_has_data_type(info->data, 32834ddb1930SJohan Hedberg sizeof(info->data), 32844ddb1930SJohan Hedberg EIR_NAME_COMPLETE); 3285561aafbcSJohan Hedberg else 3286561aafbcSJohan Hedberg name_known = true; 3287561aafbcSJohan Hedberg 3288388fc8faSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, name_known, 3289388fc8faSJohan Hedberg &ssp); 32909d939d94SVishal Agarwal eir_len = eir_get_length(info->data, sizeof(info->data)); 329148264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 329204124681SGustavo F. Padovan info->dev_class, info->rssi, !name_known, 32939d939d94SVishal Agarwal ssp, info->data, eir_len); 3294a9de9248SMarcel Holtmann } 3295a9de9248SMarcel Holtmann 3296a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 3297a9de9248SMarcel Holtmann } 3298a9de9248SMarcel Holtmann 32991c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev, 33001c2e0041SJohan Hedberg struct sk_buff *skb) 33011c2e0041SJohan Hedberg { 33021c2e0041SJohan Hedberg struct hci_ev_key_refresh_complete *ev = (void *) skb->data; 33031c2e0041SJohan Hedberg struct hci_conn *conn; 33041c2e0041SJohan Hedberg 33059f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status, 33061c2e0041SJohan Hedberg __le16_to_cpu(ev->handle)); 33071c2e0041SJohan Hedberg 33081c2e0041SJohan Hedberg hci_dev_lock(hdev); 33091c2e0041SJohan Hedberg 33101c2e0041SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 33111c2e0041SJohan Hedberg if (!conn) 33121c2e0041SJohan Hedberg goto unlock; 33131c2e0041SJohan Hedberg 33141c2e0041SJohan Hedberg if (!ev->status) 33151c2e0041SJohan Hedberg conn->sec_level = conn->pending_sec_level; 33161c2e0041SJohan Hedberg 33171c2e0041SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 33181c2e0041SJohan Hedberg 33191c2e0041SJohan Hedberg if (ev->status && conn->state == BT_CONNECTED) { 33201c2e0041SJohan Hedberg hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE); 33211c2e0041SJohan Hedberg hci_conn_put(conn); 33221c2e0041SJohan Hedberg goto unlock; 33231c2e0041SJohan Hedberg } 33241c2e0041SJohan Hedberg 33251c2e0041SJohan Hedberg if (conn->state == BT_CONFIG) { 33261c2e0041SJohan Hedberg if (!ev->status) 33271c2e0041SJohan Hedberg conn->state = BT_CONNECTED; 33281c2e0041SJohan Hedberg 33291c2e0041SJohan Hedberg hci_proto_connect_cfm(conn, ev->status); 33301c2e0041SJohan Hedberg hci_conn_put(conn); 33311c2e0041SJohan Hedberg } else { 33321c2e0041SJohan Hedberg hci_auth_cfm(conn, ev->status); 33331c2e0041SJohan Hedberg 33341c2e0041SJohan Hedberg hci_conn_hold(conn); 33351c2e0041SJohan Hedberg conn->disc_timeout = HCI_DISCONN_TIMEOUT; 33361c2e0041SJohan Hedberg hci_conn_put(conn); 33371c2e0041SJohan Hedberg } 33381c2e0041SJohan Hedberg 33391c2e0041SJohan Hedberg unlock: 33401c2e0041SJohan Hedberg hci_dev_unlock(hdev); 33411c2e0041SJohan Hedberg } 33421c2e0041SJohan Hedberg 33436039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn) 334417fa4b9dSJohan Hedberg { 334517fa4b9dSJohan Hedberg /* If remote requests dedicated bonding follow that lead */ 334617fa4b9dSJohan Hedberg if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) { 334717fa4b9dSJohan Hedberg /* If both remote and local IO capabilities allow MITM 334817fa4b9dSJohan Hedberg * protection then require it, otherwise don't */ 334917fa4b9dSJohan Hedberg if (conn->remote_cap == 0x03 || conn->io_capability == 0x03) 335017fa4b9dSJohan Hedberg return 0x02; 335117fa4b9dSJohan Hedberg else 335217fa4b9dSJohan Hedberg return 0x03; 335317fa4b9dSJohan Hedberg } 335417fa4b9dSJohan Hedberg 335517fa4b9dSJohan Hedberg /* If remote requests no-bonding follow that lead */ 335617fa4b9dSJohan Hedberg if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01) 335758797bf7SWaldemar Rymarkiewicz return conn->remote_auth | (conn->auth_type & 0x01); 335817fa4b9dSJohan Hedberg 335917fa4b9dSJohan Hedberg return conn->auth_type; 336017fa4b9dSJohan Hedberg } 336117fa4b9dSJohan Hedberg 33626039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 33630493684eSMarcel Holtmann { 33640493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 33650493684eSMarcel Holtmann struct hci_conn *conn; 33660493684eSMarcel Holtmann 33670493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 33680493684eSMarcel Holtmann 33690493684eSMarcel Holtmann hci_dev_lock(hdev); 33700493684eSMarcel Holtmann 33710493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 337203b555e1SJohan Hedberg if (!conn) 337303b555e1SJohan Hedberg goto unlock; 337403b555e1SJohan Hedberg 33750493684eSMarcel Holtmann hci_conn_hold(conn); 33760493684eSMarcel Holtmann 3377a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 337803b555e1SJohan Hedberg goto unlock; 337903b555e1SJohan Hedberg 3380a8b2d5c2SJohan Hedberg if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) || 338103b555e1SJohan Hedberg (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 338217fa4b9dSJohan Hedberg struct hci_cp_io_capability_reply cp; 338317fa4b9dSJohan Hedberg 338417fa4b9dSJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 33857a7f1e7cSHemant Gupta /* Change the IO capability from KeyboardDisplay 33867a7f1e7cSHemant Gupta * to DisplayYesNo as it is not supported by BT spec. */ 33877a7f1e7cSHemant Gupta cp.capability = (conn->io_capability == 0x04) ? 33887a7f1e7cSHemant Gupta 0x01 : conn->io_capability; 33897cbc9bd9SJohan Hedberg conn->auth_type = hci_get_auth_req(conn); 33907cbc9bd9SJohan Hedberg cp.authentication = conn->auth_type; 339117fa4b9dSJohan Hedberg 33928fc9ced3SGustavo Padovan if (hci_find_remote_oob_data(hdev, &conn->dst) && 33938fc9ced3SGustavo Padovan (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags))) 3394ce85ee13SSzymon Janc cp.oob_data = 0x01; 3395ce85ee13SSzymon Janc else 3396ce85ee13SSzymon Janc cp.oob_data = 0x00; 3397ce85ee13SSzymon Janc 339817fa4b9dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, 339917fa4b9dSJohan Hedberg sizeof(cp), &cp); 340003b555e1SJohan Hedberg } else { 340103b555e1SJohan Hedberg struct hci_cp_io_capability_neg_reply cp; 340203b555e1SJohan Hedberg 340303b555e1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 34049f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED; 340503b555e1SJohan Hedberg 340603b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 340703b555e1SJohan Hedberg sizeof(cp), &cp); 340803b555e1SJohan Hedberg } 340903b555e1SJohan Hedberg 341003b555e1SJohan Hedberg unlock: 341103b555e1SJohan Hedberg hci_dev_unlock(hdev); 341203b555e1SJohan Hedberg } 341303b555e1SJohan Hedberg 34146039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 341503b555e1SJohan Hedberg { 341603b555e1SJohan Hedberg struct hci_ev_io_capa_reply *ev = (void *) skb->data; 341703b555e1SJohan Hedberg struct hci_conn *conn; 341803b555e1SJohan Hedberg 341903b555e1SJohan Hedberg BT_DBG("%s", hdev->name); 342003b555e1SJohan Hedberg 342103b555e1SJohan Hedberg hci_dev_lock(hdev); 342203b555e1SJohan Hedberg 342303b555e1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 342403b555e1SJohan Hedberg if (!conn) 342503b555e1SJohan Hedberg goto unlock; 342603b555e1SJohan Hedberg 342703b555e1SJohan Hedberg conn->remote_cap = ev->capability; 342803b555e1SJohan Hedberg conn->remote_auth = ev->authentication; 342958a681efSJohan Hedberg if (ev->oob_data) 343058a681efSJohan Hedberg set_bit(HCI_CONN_REMOTE_OOB, &conn->flags); 343103b555e1SJohan Hedberg 343203b555e1SJohan Hedberg unlock: 34330493684eSMarcel Holtmann hci_dev_unlock(hdev); 34340493684eSMarcel Holtmann } 34350493684eSMarcel Holtmann 34366039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev, 3437a5c29683SJohan Hedberg struct sk_buff *skb) 3438a5c29683SJohan Hedberg { 3439a5c29683SJohan Hedberg struct hci_ev_user_confirm_req *ev = (void *) skb->data; 344055bc1a37SJohan Hedberg int loc_mitm, rem_mitm, confirm_hint = 0; 34417a828908SJohan Hedberg struct hci_conn *conn; 3442a5c29683SJohan Hedberg 3443a5c29683SJohan Hedberg BT_DBG("%s", hdev->name); 3444a5c29683SJohan Hedberg 3445a5c29683SJohan Hedberg hci_dev_lock(hdev); 3446a5c29683SJohan Hedberg 3447a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 34487a828908SJohan Hedberg goto unlock; 34497a828908SJohan Hedberg 34507a828908SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 34517a828908SJohan Hedberg if (!conn) 34527a828908SJohan Hedberg goto unlock; 34537a828908SJohan Hedberg 34547a828908SJohan Hedberg loc_mitm = (conn->auth_type & 0x01); 34557a828908SJohan Hedberg rem_mitm = (conn->remote_auth & 0x01); 34567a828908SJohan Hedberg 34577a828908SJohan Hedberg /* If we require MITM but the remote device can't provide that 34587a828908SJohan Hedberg * (it has NoInputNoOutput) then reject the confirmation 34597a828908SJohan Hedberg * request. The only exception is when we're dedicated bonding 34607a828908SJohan Hedberg * initiators (connect_cfm_cb set) since then we always have the MITM 34617a828908SJohan Hedberg * bit set. */ 34627a828908SJohan Hedberg if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) { 34637a828908SJohan Hedberg BT_DBG("Rejecting request: remote device can't provide MITM"); 34647a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, 34657a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 34667a828908SJohan Hedberg goto unlock; 34677a828908SJohan Hedberg } 34687a828908SJohan Hedberg 34697a828908SJohan Hedberg /* If no side requires MITM protection; auto-accept */ 34707a828908SJohan Hedberg if ((!loc_mitm || conn->remote_cap == 0x03) && 34717a828908SJohan Hedberg (!rem_mitm || conn->io_capability == 0x03)) { 347255bc1a37SJohan Hedberg 347355bc1a37SJohan Hedberg /* If we're not the initiators request authorization to 347455bc1a37SJohan Hedberg * proceed from user space (mgmt_user_confirm with 347555bc1a37SJohan Hedberg * confirm_hint set to 1). */ 347651a8efd7SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 347755bc1a37SJohan Hedberg BT_DBG("Confirming auto-accept as acceptor"); 347855bc1a37SJohan Hedberg confirm_hint = 1; 347955bc1a37SJohan Hedberg goto confirm; 348055bc1a37SJohan Hedberg } 348155bc1a37SJohan Hedberg 34829f61656aSJohan Hedberg BT_DBG("Auto-accept of user confirmation with %ums delay", 34839f61656aSJohan Hedberg hdev->auto_accept_delay); 34849f61656aSJohan Hedberg 34859f61656aSJohan Hedberg if (hdev->auto_accept_delay > 0) { 34869f61656aSJohan Hedberg int delay = msecs_to_jiffies(hdev->auto_accept_delay); 34879f61656aSJohan Hedberg mod_timer(&conn->auto_accept_timer, jiffies + delay); 34889f61656aSJohan Hedberg goto unlock; 34899f61656aSJohan Hedberg } 34909f61656aSJohan Hedberg 34917a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, 34927a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 34937a828908SJohan Hedberg goto unlock; 34947a828908SJohan Hedberg } 34957a828908SJohan Hedberg 349655bc1a37SJohan Hedberg confirm: 3497272d90dfSJohan Hedberg mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey, 349855bc1a37SJohan Hedberg confirm_hint); 3499a5c29683SJohan Hedberg 35007a828908SJohan Hedberg unlock: 3501a5c29683SJohan Hedberg hci_dev_unlock(hdev); 3502a5c29683SJohan Hedberg } 3503a5c29683SJohan Hedberg 35046039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev, 35051143d458SBrian Gix struct sk_buff *skb) 35061143d458SBrian Gix { 35071143d458SBrian Gix struct hci_ev_user_passkey_req *ev = (void *) skb->data; 35081143d458SBrian Gix 35091143d458SBrian Gix BT_DBG("%s", hdev->name); 35101143d458SBrian Gix 3511a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 3512272d90dfSJohan Hedberg mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); 35131143d458SBrian Gix } 35141143d458SBrian Gix 351592a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev, 351692a25256SJohan Hedberg struct sk_buff *skb) 351792a25256SJohan Hedberg { 351892a25256SJohan Hedberg struct hci_ev_user_passkey_notify *ev = (void *) skb->data; 351992a25256SJohan Hedberg struct hci_conn *conn; 352092a25256SJohan Hedberg 352192a25256SJohan Hedberg BT_DBG("%s", hdev->name); 352292a25256SJohan Hedberg 352392a25256SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 352492a25256SJohan Hedberg if (!conn) 352592a25256SJohan Hedberg return; 352692a25256SJohan Hedberg 352792a25256SJohan Hedberg conn->passkey_notify = __le32_to_cpu(ev->passkey); 352892a25256SJohan Hedberg conn->passkey_entered = 0; 352992a25256SJohan Hedberg 353092a25256SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 353192a25256SJohan Hedberg mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, 353292a25256SJohan Hedberg conn->dst_type, conn->passkey_notify, 353392a25256SJohan Hedberg conn->passkey_entered); 353492a25256SJohan Hedberg } 353592a25256SJohan Hedberg 353692a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 353792a25256SJohan Hedberg { 353892a25256SJohan Hedberg struct hci_ev_keypress_notify *ev = (void *) skb->data; 353992a25256SJohan Hedberg struct hci_conn *conn; 354092a25256SJohan Hedberg 354192a25256SJohan Hedberg BT_DBG("%s", hdev->name); 354292a25256SJohan Hedberg 354392a25256SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 354492a25256SJohan Hedberg if (!conn) 354592a25256SJohan Hedberg return; 354692a25256SJohan Hedberg 354792a25256SJohan Hedberg switch (ev->type) { 354892a25256SJohan Hedberg case HCI_KEYPRESS_STARTED: 354992a25256SJohan Hedberg conn->passkey_entered = 0; 355092a25256SJohan Hedberg return; 355192a25256SJohan Hedberg 355292a25256SJohan Hedberg case HCI_KEYPRESS_ENTERED: 355392a25256SJohan Hedberg conn->passkey_entered++; 355492a25256SJohan Hedberg break; 355592a25256SJohan Hedberg 355692a25256SJohan Hedberg case HCI_KEYPRESS_ERASED: 355792a25256SJohan Hedberg conn->passkey_entered--; 355892a25256SJohan Hedberg break; 355992a25256SJohan Hedberg 356092a25256SJohan Hedberg case HCI_KEYPRESS_CLEARED: 356192a25256SJohan Hedberg conn->passkey_entered = 0; 356292a25256SJohan Hedberg break; 356392a25256SJohan Hedberg 356492a25256SJohan Hedberg case HCI_KEYPRESS_COMPLETED: 356592a25256SJohan Hedberg return; 356692a25256SJohan Hedberg } 356792a25256SJohan Hedberg 356892a25256SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 356992a25256SJohan Hedberg mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, 357092a25256SJohan Hedberg conn->dst_type, conn->passkey_notify, 357192a25256SJohan Hedberg conn->passkey_entered); 357292a25256SJohan Hedberg } 357392a25256SJohan Hedberg 35746039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev, 3575807deac2SGustavo Padovan struct sk_buff *skb) 35760493684eSMarcel Holtmann { 35770493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 35780493684eSMarcel Holtmann struct hci_conn *conn; 35790493684eSMarcel Holtmann 35800493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 35810493684eSMarcel Holtmann 35820493684eSMarcel Holtmann hci_dev_lock(hdev); 35830493684eSMarcel Holtmann 35840493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 35852a611692SJohan Hedberg if (!conn) 35862a611692SJohan Hedberg goto unlock; 35872a611692SJohan Hedberg 35882a611692SJohan Hedberg /* To avoid duplicate auth_failed events to user space we check 35892a611692SJohan Hedberg * the HCI_CONN_AUTH_PEND flag which will be set if we 35902a611692SJohan Hedberg * initiated the authentication. A traditional auth_complete 35912a611692SJohan Hedberg * event gets always produced as initiator and is also mapped to 35922a611692SJohan Hedberg * the mgmt_auth_failed event */ 3593fa1bd918SMikel Astiz if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status) 3594bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 3595bab73cb6SJohan Hedberg ev->status); 35962a611692SJohan Hedberg 35970493684eSMarcel Holtmann hci_conn_put(conn); 35980493684eSMarcel Holtmann 35992a611692SJohan Hedberg unlock: 36000493684eSMarcel Holtmann hci_dev_unlock(hdev); 36010493684eSMarcel Holtmann } 36020493684eSMarcel Holtmann 36036039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev, 3604807deac2SGustavo Padovan struct sk_buff *skb) 360541a96212SMarcel Holtmann { 360641a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 360741a96212SMarcel Holtmann struct inquiry_entry *ie; 360841a96212SMarcel Holtmann 360941a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 361041a96212SMarcel Holtmann 361141a96212SMarcel Holtmann hci_dev_lock(hdev); 361241a96212SMarcel Holtmann 3613cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 3614cc11b9c1SAndrei Emeltchenko if (ie) 361502b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 361641a96212SMarcel Holtmann 361741a96212SMarcel Holtmann hci_dev_unlock(hdev); 361841a96212SMarcel Holtmann } 361941a96212SMarcel Holtmann 36206039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev, 36212763eda6SSzymon Janc struct sk_buff *skb) 36222763eda6SSzymon Janc { 36232763eda6SSzymon Janc struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; 36242763eda6SSzymon Janc struct oob_data *data; 36252763eda6SSzymon Janc 36262763eda6SSzymon Janc BT_DBG("%s", hdev->name); 36272763eda6SSzymon Janc 36282763eda6SSzymon Janc hci_dev_lock(hdev); 36292763eda6SSzymon Janc 3630a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 3631e1ba1f15SSzymon Janc goto unlock; 3632e1ba1f15SSzymon Janc 36332763eda6SSzymon Janc data = hci_find_remote_oob_data(hdev, &ev->bdaddr); 36342763eda6SSzymon Janc if (data) { 36352763eda6SSzymon Janc struct hci_cp_remote_oob_data_reply cp; 36362763eda6SSzymon Janc 36372763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 36382763eda6SSzymon Janc memcpy(cp.hash, data->hash, sizeof(cp.hash)); 36392763eda6SSzymon Janc memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); 36402763eda6SSzymon Janc 36412763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), 36422763eda6SSzymon Janc &cp); 36432763eda6SSzymon Janc } else { 36442763eda6SSzymon Janc struct hci_cp_remote_oob_data_neg_reply cp; 36452763eda6SSzymon Janc 36462763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 36472763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), 36482763eda6SSzymon Janc &cp); 36492763eda6SSzymon Janc } 36502763eda6SSzymon Janc 3651e1ba1f15SSzymon Janc unlock: 36522763eda6SSzymon Janc hci_dev_unlock(hdev); 36532763eda6SSzymon Janc } 36542763eda6SSzymon Janc 3655d5e91192SAndrei Emeltchenko static void hci_phy_link_complete_evt(struct hci_dev *hdev, 3656d5e91192SAndrei Emeltchenko struct sk_buff *skb) 3657d5e91192SAndrei Emeltchenko { 3658d5e91192SAndrei Emeltchenko struct hci_ev_phy_link_complete *ev = (void *) skb->data; 3659d5e91192SAndrei Emeltchenko struct hci_conn *hcon, *bredr_hcon; 3660d5e91192SAndrei Emeltchenko 3661d5e91192SAndrei Emeltchenko BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle, 3662d5e91192SAndrei Emeltchenko ev->status); 3663d5e91192SAndrei Emeltchenko 3664d5e91192SAndrei Emeltchenko hci_dev_lock(hdev); 3665d5e91192SAndrei Emeltchenko 3666d5e91192SAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 3667d5e91192SAndrei Emeltchenko if (!hcon) { 3668d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 3669d5e91192SAndrei Emeltchenko return; 3670d5e91192SAndrei Emeltchenko } 3671d5e91192SAndrei Emeltchenko 3672d5e91192SAndrei Emeltchenko if (ev->status) { 3673d5e91192SAndrei Emeltchenko hci_conn_del(hcon); 3674d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 3675d5e91192SAndrei Emeltchenko return; 3676d5e91192SAndrei Emeltchenko } 3677d5e91192SAndrei Emeltchenko 3678d5e91192SAndrei Emeltchenko bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon; 3679d5e91192SAndrei Emeltchenko 3680d5e91192SAndrei Emeltchenko hcon->state = BT_CONNECTED; 3681d5e91192SAndrei Emeltchenko bacpy(&hcon->dst, &bredr_hcon->dst); 3682d5e91192SAndrei Emeltchenko 3683d5e91192SAndrei Emeltchenko hci_conn_hold(hcon); 3684d5e91192SAndrei Emeltchenko hcon->disc_timeout = HCI_DISCONN_TIMEOUT; 3685d5e91192SAndrei Emeltchenko hci_conn_put(hcon); 3686d5e91192SAndrei Emeltchenko 3687d5e91192SAndrei Emeltchenko hci_conn_hold_device(hcon); 3688d5e91192SAndrei Emeltchenko hci_conn_add_sysfs(hcon); 3689d5e91192SAndrei Emeltchenko 3690d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 3691d5e91192SAndrei Emeltchenko 3692d5e91192SAndrei Emeltchenko if (hcon->out) { 3693d5e91192SAndrei Emeltchenko struct hci_dev *bredr_hdev = hci_dev_hold(bredr_hcon->hdev); 3694d5e91192SAndrei Emeltchenko 3695d5e91192SAndrei Emeltchenko if (!bredr_hdev) 3696d5e91192SAndrei Emeltchenko return; 3697d5e91192SAndrei Emeltchenko 3698d5e91192SAndrei Emeltchenko /* Placeholder - create chan req 3699d5e91192SAndrei Emeltchenko l2cap_chan_create_cfm(bredr_hcon, hcon->remote_id); 3700d5e91192SAndrei Emeltchenko */ 3701d5e91192SAndrei Emeltchenko 3702d5e91192SAndrei Emeltchenko hci_dev_put(bredr_hdev); 3703d5e91192SAndrei Emeltchenko } 3704d5e91192SAndrei Emeltchenko } 3705d5e91192SAndrei Emeltchenko 370627695fb4SAndrei Emeltchenko static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 370727695fb4SAndrei Emeltchenko { 370827695fb4SAndrei Emeltchenko struct hci_ev_logical_link_complete *ev = (void *) skb->data; 370927695fb4SAndrei Emeltchenko struct hci_conn *hcon; 371027695fb4SAndrei Emeltchenko struct hci_chan *hchan; 371127695fb4SAndrei Emeltchenko struct amp_mgr *mgr; 371227695fb4SAndrei Emeltchenko 371327695fb4SAndrei Emeltchenko BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x", 371427695fb4SAndrei Emeltchenko hdev->name, le16_to_cpu(ev->handle), ev->phy_handle, 371527695fb4SAndrei Emeltchenko ev->status); 371627695fb4SAndrei Emeltchenko 371727695fb4SAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 371827695fb4SAndrei Emeltchenko if (!hcon) 371927695fb4SAndrei Emeltchenko return; 372027695fb4SAndrei Emeltchenko 372127695fb4SAndrei Emeltchenko /* Create AMP hchan */ 372227695fb4SAndrei Emeltchenko hchan = hci_chan_create(hcon); 372327695fb4SAndrei Emeltchenko if (!hchan) 372427695fb4SAndrei Emeltchenko return; 372527695fb4SAndrei Emeltchenko 372627695fb4SAndrei Emeltchenko hchan->handle = le16_to_cpu(ev->handle); 372727695fb4SAndrei Emeltchenko 372827695fb4SAndrei Emeltchenko BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan); 372927695fb4SAndrei Emeltchenko 373027695fb4SAndrei Emeltchenko mgr = hcon->amp_mgr; 373127695fb4SAndrei Emeltchenko if (mgr && mgr->bredr_chan) { 373227695fb4SAndrei Emeltchenko struct l2cap_chan *bredr_chan = mgr->bredr_chan; 373327695fb4SAndrei Emeltchenko 373427695fb4SAndrei Emeltchenko l2cap_chan_lock(bredr_chan); 373527695fb4SAndrei Emeltchenko 373627695fb4SAndrei Emeltchenko bredr_chan->conn->mtu = hdev->block_mtu; 373727695fb4SAndrei Emeltchenko l2cap_logical_cfm(bredr_chan, hchan, 0); 373827695fb4SAndrei Emeltchenko hci_conn_hold(hcon); 373927695fb4SAndrei Emeltchenko 374027695fb4SAndrei Emeltchenko l2cap_chan_unlock(bredr_chan); 374127695fb4SAndrei Emeltchenko } 374227695fb4SAndrei Emeltchenko } 374327695fb4SAndrei Emeltchenko 37446039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 3745fcd89c09SVille Tervo { 3746fcd89c09SVille Tervo struct hci_ev_le_conn_complete *ev = (void *) skb->data; 3747fcd89c09SVille Tervo struct hci_conn *conn; 3748fcd89c09SVille Tervo 37499f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 3750fcd89c09SVille Tervo 3751fcd89c09SVille Tervo hci_dev_lock(hdev); 3752fcd89c09SVille Tervo 37534f72b329SAndrzej Kaczmarek conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); 3754b62f328bSVille Tervo if (!conn) { 3755b62f328bSVille Tervo conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); 3756b62f328bSVille Tervo if (!conn) { 3757b62f328bSVille Tervo BT_ERR("No memory for new connection"); 3758230fd16aSAndre Guedes goto unlock; 3759b62f328bSVille Tervo } 376029b7988aSAndre Guedes 376129b7988aSAndre Guedes conn->dst_type = ev->bdaddr_type; 3762b9b343d2SAndre Guedes 3763b9b343d2SAndre Guedes if (ev->role == LE_CONN_ROLE_MASTER) { 3764b9b343d2SAndre Guedes conn->out = true; 3765b9b343d2SAndre Guedes conn->link_mode |= HCI_LM_MASTER; 3766b9b343d2SAndre Guedes } 3767b62f328bSVille Tervo } 3768fcd89c09SVille Tervo 3769cd17decbSAndre Guedes if (ev->status) { 3770cd17decbSAndre Guedes mgmt_connect_failed(hdev, &conn->dst, conn->type, 3771cd17decbSAndre Guedes conn->dst_type, ev->status); 3772cd17decbSAndre Guedes hci_proto_connect_cfm(conn, ev->status); 3773cd17decbSAndre Guedes conn->state = BT_CLOSED; 3774cd17decbSAndre Guedes hci_conn_del(conn); 3775cd17decbSAndre Guedes goto unlock; 3776cd17decbSAndre Guedes } 3777cd17decbSAndre Guedes 3778b644ba33SJohan Hedberg if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 3779b644ba33SJohan Hedberg mgmt_device_connected(hdev, &ev->bdaddr, conn->type, 378095b23582SSzymon Janc conn->dst_type, 0, NULL, 0, NULL); 378183bc71b4SVinicius Costa Gomes 37827b5c0d52SVinicius Costa Gomes conn->sec_level = BT_SECURITY_LOW; 3783fcd89c09SVille Tervo conn->handle = __le16_to_cpu(ev->handle); 3784fcd89c09SVille Tervo conn->state = BT_CONNECTED; 3785fcd89c09SVille Tervo 3786fcd89c09SVille Tervo hci_conn_hold_device(conn); 3787fcd89c09SVille Tervo hci_conn_add_sysfs(conn); 3788fcd89c09SVille Tervo 3789fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 3790fcd89c09SVille Tervo 3791fcd89c09SVille Tervo unlock: 3792fcd89c09SVille Tervo hci_dev_unlock(hdev); 3793fcd89c09SVille Tervo } 3794fcd89c09SVille Tervo 37956039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) 37969aa04c91SAndre Guedes { 3797e95beb41SAndre Guedes u8 num_reports = skb->data[0]; 3798e95beb41SAndre Guedes void *ptr = &skb->data[1]; 37993c9e9195SAndre Guedes s8 rssi; 38009aa04c91SAndre Guedes 38019aa04c91SAndre Guedes hci_dev_lock(hdev); 38029aa04c91SAndre Guedes 3803e95beb41SAndre Guedes while (num_reports--) { 3804e95beb41SAndre Guedes struct hci_ev_le_advertising_info *ev = ptr; 3805e95beb41SAndre Guedes 38063c9e9195SAndre Guedes rssi = ev->data[ev->length]; 38073c9e9195SAndre Guedes mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type, 380804124681SGustavo F. Padovan NULL, rssi, 0, 1, ev->data, ev->length); 38093c9e9195SAndre Guedes 3810e95beb41SAndre Guedes ptr += sizeof(*ev) + ev->length + 1; 38119aa04c91SAndre Guedes } 38129aa04c91SAndre Guedes 38139aa04c91SAndre Guedes hci_dev_unlock(hdev); 38149aa04c91SAndre Guedes } 38159aa04c91SAndre Guedes 38166039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 3817a7a595f6SVinicius Costa Gomes { 3818a7a595f6SVinicius Costa Gomes struct hci_ev_le_ltk_req *ev = (void *) skb->data; 3819a7a595f6SVinicius Costa Gomes struct hci_cp_le_ltk_reply cp; 3820bea710feSVinicius Costa Gomes struct hci_cp_le_ltk_neg_reply neg; 3821a7a595f6SVinicius Costa Gomes struct hci_conn *conn; 3822c9839a11SVinicius Costa Gomes struct smp_ltk *ltk; 3823a7a595f6SVinicius Costa Gomes 38249f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle)); 3825a7a595f6SVinicius Costa Gomes 3826a7a595f6SVinicius Costa Gomes hci_dev_lock(hdev); 3827a7a595f6SVinicius Costa Gomes 3828a7a595f6SVinicius Costa Gomes conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3829bea710feSVinicius Costa Gomes if (conn == NULL) 3830bea710feSVinicius Costa Gomes goto not_found; 3831a7a595f6SVinicius Costa Gomes 3832bea710feSVinicius Costa Gomes ltk = hci_find_ltk(hdev, ev->ediv, ev->random); 3833bea710feSVinicius Costa Gomes if (ltk == NULL) 3834bea710feSVinicius Costa Gomes goto not_found; 3835bea710feSVinicius Costa Gomes 3836bea710feSVinicius Costa Gomes memcpy(cp.ltk, ltk->val, sizeof(ltk->val)); 3837a7a595f6SVinicius Costa Gomes cp.handle = cpu_to_le16(conn->handle); 3838c9839a11SVinicius Costa Gomes 3839c9839a11SVinicius Costa Gomes if (ltk->authenticated) 3840c9839a11SVinicius Costa Gomes conn->sec_level = BT_SECURITY_HIGH; 3841a7a595f6SVinicius Costa Gomes 3842a7a595f6SVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); 3843a7a595f6SVinicius Costa Gomes 3844c9839a11SVinicius Costa Gomes if (ltk->type & HCI_SMP_STK) { 3845c9839a11SVinicius Costa Gomes list_del(<k->list); 3846c9839a11SVinicius Costa Gomes kfree(ltk); 3847c9839a11SVinicius Costa Gomes } 3848c9839a11SVinicius Costa Gomes 3849a7a595f6SVinicius Costa Gomes hci_dev_unlock(hdev); 3850bea710feSVinicius Costa Gomes 3851bea710feSVinicius Costa Gomes return; 3852bea710feSVinicius Costa Gomes 3853bea710feSVinicius Costa Gomes not_found: 3854bea710feSVinicius Costa Gomes neg.handle = ev->handle; 3855bea710feSVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg); 3856bea710feSVinicius Costa Gomes hci_dev_unlock(hdev); 3857a7a595f6SVinicius Costa Gomes } 3858a7a595f6SVinicius Costa Gomes 38596039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 3860fcd89c09SVille Tervo { 3861fcd89c09SVille Tervo struct hci_ev_le_meta *le_ev = (void *) skb->data; 3862fcd89c09SVille Tervo 3863fcd89c09SVille Tervo skb_pull(skb, sizeof(*le_ev)); 3864fcd89c09SVille Tervo 3865fcd89c09SVille Tervo switch (le_ev->subevent) { 3866fcd89c09SVille Tervo case HCI_EV_LE_CONN_COMPLETE: 3867fcd89c09SVille Tervo hci_le_conn_complete_evt(hdev, skb); 3868fcd89c09SVille Tervo break; 3869fcd89c09SVille Tervo 38709aa04c91SAndre Guedes case HCI_EV_LE_ADVERTISING_REPORT: 38719aa04c91SAndre Guedes hci_le_adv_report_evt(hdev, skb); 38729aa04c91SAndre Guedes break; 38739aa04c91SAndre Guedes 3874a7a595f6SVinicius Costa Gomes case HCI_EV_LE_LTK_REQ: 3875a7a595f6SVinicius Costa Gomes hci_le_ltk_request_evt(hdev, skb); 3876a7a595f6SVinicius Costa Gomes break; 3877a7a595f6SVinicius Costa Gomes 3878fcd89c09SVille Tervo default: 3879fcd89c09SVille Tervo break; 3880fcd89c09SVille Tervo } 3881fcd89c09SVille Tervo } 3882fcd89c09SVille Tervo 38839495b2eeSAndrei Emeltchenko static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb) 38849495b2eeSAndrei Emeltchenko { 38859495b2eeSAndrei Emeltchenko struct hci_ev_channel_selected *ev = (void *) skb->data; 38869495b2eeSAndrei Emeltchenko struct hci_conn *hcon; 38879495b2eeSAndrei Emeltchenko 38889495b2eeSAndrei Emeltchenko BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle); 38899495b2eeSAndrei Emeltchenko 38909495b2eeSAndrei Emeltchenko skb_pull(skb, sizeof(*ev)); 38919495b2eeSAndrei Emeltchenko 38929495b2eeSAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 38939495b2eeSAndrei Emeltchenko if (!hcon) 38949495b2eeSAndrei Emeltchenko return; 38959495b2eeSAndrei Emeltchenko 38969495b2eeSAndrei Emeltchenko amp_read_loc_assoc_final_data(hdev, hcon); 38979495b2eeSAndrei Emeltchenko } 38989495b2eeSAndrei Emeltchenko 38991da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 39001da177e4SLinus Torvalds { 3901a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 3902a9de9248SMarcel Holtmann __u8 event = hdr->evt; 39031da177e4SLinus Torvalds 39041da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 39051da177e4SLinus Torvalds 3906a9de9248SMarcel Holtmann switch (event) { 39071da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 39081da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 39091da177e4SLinus Torvalds break; 39101da177e4SLinus Torvalds 39111da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 39121da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 39131da177e4SLinus Torvalds break; 39141da177e4SLinus Torvalds 3915a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 3916a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 391721d9e30eSMarcel Holtmann break; 391821d9e30eSMarcel Holtmann 39191da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 39201da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 39211da177e4SLinus Torvalds break; 39221da177e4SLinus Torvalds 39231da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 39241da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 39251da177e4SLinus Torvalds break; 39261da177e4SLinus Torvalds 39271da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 39281da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 39291da177e4SLinus Torvalds break; 39301da177e4SLinus Torvalds 3931a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 3932a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 3933a9de9248SMarcel Holtmann break; 3934a9de9248SMarcel Holtmann 39351da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 39361da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 39371da177e4SLinus Torvalds break; 39381da177e4SLinus Torvalds 3939a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 3940a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 3941a9de9248SMarcel Holtmann break; 3942a9de9248SMarcel Holtmann 3943a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 3944a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 3945a9de9248SMarcel Holtmann break; 3946a9de9248SMarcel Holtmann 3947a9de9248SMarcel Holtmann case HCI_EV_REMOTE_VERSION: 3948a9de9248SMarcel Holtmann hci_remote_version_evt(hdev, skb); 3949a9de9248SMarcel Holtmann break; 3950a9de9248SMarcel Holtmann 3951a9de9248SMarcel Holtmann case HCI_EV_QOS_SETUP_COMPLETE: 3952a9de9248SMarcel Holtmann hci_qos_setup_complete_evt(hdev, skb); 3953a9de9248SMarcel Holtmann break; 3954a9de9248SMarcel Holtmann 3955a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 3956a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 3957a9de9248SMarcel Holtmann break; 3958a9de9248SMarcel Holtmann 3959a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 3960a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 3961a9de9248SMarcel Holtmann break; 3962a9de9248SMarcel Holtmann 3963a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 3964a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 3965a9de9248SMarcel Holtmann break; 3966a9de9248SMarcel Holtmann 3967a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 3968a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 3969a9de9248SMarcel Holtmann break; 3970a9de9248SMarcel Holtmann 3971a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 3972a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 39731da177e4SLinus Torvalds break; 39741da177e4SLinus Torvalds 39751da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 39761da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 39771da177e4SLinus Torvalds break; 39781da177e4SLinus Torvalds 39791da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 39801da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 39811da177e4SLinus Torvalds break; 39821da177e4SLinus Torvalds 39831da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 39841da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 39851da177e4SLinus Torvalds break; 39861da177e4SLinus Torvalds 39871da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 39881da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 39891da177e4SLinus Torvalds break; 39901da177e4SLinus Torvalds 3991a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 3992a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 3993a8746417SMarcel Holtmann break; 3994a8746417SMarcel Holtmann 399585a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 399685a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 399785a1e930SMarcel Holtmann break; 399885a1e930SMarcel Holtmann 3999a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 4000a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 4001a9de9248SMarcel Holtmann break; 4002a9de9248SMarcel Holtmann 4003a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 4004a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 4005a9de9248SMarcel Holtmann break; 4006a9de9248SMarcel Holtmann 4007a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 4008a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 4009a9de9248SMarcel Holtmann break; 4010a9de9248SMarcel Holtmann 4011a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_CHANGED: 4012a9de9248SMarcel Holtmann hci_sync_conn_changed_evt(hdev, skb); 4013a9de9248SMarcel Holtmann break; 4014a9de9248SMarcel Holtmann 401504837f64SMarcel Holtmann case HCI_EV_SNIFF_SUBRATE: 401604837f64SMarcel Holtmann hci_sniff_subrate_evt(hdev, skb); 401704837f64SMarcel Holtmann break; 401804837f64SMarcel Holtmann 4019a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 4020a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 40211da177e4SLinus Torvalds break; 40221da177e4SLinus Torvalds 40231c2e0041SJohan Hedberg case HCI_EV_KEY_REFRESH_COMPLETE: 40241c2e0041SJohan Hedberg hci_key_refresh_complete_evt(hdev, skb); 40251c2e0041SJohan Hedberg break; 40261c2e0041SJohan Hedberg 40270493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 40280493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 40290493684eSMarcel Holtmann break; 40300493684eSMarcel Holtmann 403103b555e1SJohan Hedberg case HCI_EV_IO_CAPA_REPLY: 403203b555e1SJohan Hedberg hci_io_capa_reply_evt(hdev, skb); 403303b555e1SJohan Hedberg break; 403403b555e1SJohan Hedberg 4035a5c29683SJohan Hedberg case HCI_EV_USER_CONFIRM_REQUEST: 4036a5c29683SJohan Hedberg hci_user_confirm_request_evt(hdev, skb); 4037a5c29683SJohan Hedberg break; 4038a5c29683SJohan Hedberg 40391143d458SBrian Gix case HCI_EV_USER_PASSKEY_REQUEST: 40401143d458SBrian Gix hci_user_passkey_request_evt(hdev, skb); 40411143d458SBrian Gix break; 40421143d458SBrian Gix 404392a25256SJohan Hedberg case HCI_EV_USER_PASSKEY_NOTIFY: 404492a25256SJohan Hedberg hci_user_passkey_notify_evt(hdev, skb); 404592a25256SJohan Hedberg break; 404692a25256SJohan Hedberg 404792a25256SJohan Hedberg case HCI_EV_KEYPRESS_NOTIFY: 404892a25256SJohan Hedberg hci_keypress_notify_evt(hdev, skb); 404992a25256SJohan Hedberg break; 405092a25256SJohan Hedberg 40510493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 40520493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 40530493684eSMarcel Holtmann break; 40540493684eSMarcel Holtmann 405541a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 405641a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 405741a96212SMarcel Holtmann break; 405841a96212SMarcel Holtmann 4059fcd89c09SVille Tervo case HCI_EV_LE_META: 4060fcd89c09SVille Tervo hci_le_meta_evt(hdev, skb); 4061fcd89c09SVille Tervo break; 4062fcd89c09SVille Tervo 40639495b2eeSAndrei Emeltchenko case HCI_EV_CHANNEL_SELECTED: 40649495b2eeSAndrei Emeltchenko hci_chan_selected_evt(hdev, skb); 40659495b2eeSAndrei Emeltchenko break; 40669495b2eeSAndrei Emeltchenko 40672763eda6SSzymon Janc case HCI_EV_REMOTE_OOB_DATA_REQUEST: 40682763eda6SSzymon Janc hci_remote_oob_data_request_evt(hdev, skb); 40692763eda6SSzymon Janc break; 40702763eda6SSzymon Janc 4071d5e91192SAndrei Emeltchenko case HCI_EV_PHY_LINK_COMPLETE: 4072d5e91192SAndrei Emeltchenko hci_phy_link_complete_evt(hdev, skb); 4073d5e91192SAndrei Emeltchenko break; 4074d5e91192SAndrei Emeltchenko 407527695fb4SAndrei Emeltchenko case HCI_EV_LOGICAL_LINK_COMPLETE: 407627695fb4SAndrei Emeltchenko hci_loglink_complete_evt(hdev, skb); 407727695fb4SAndrei Emeltchenko break; 407827695fb4SAndrei Emeltchenko 407925e89e99SAndrei Emeltchenko case HCI_EV_NUM_COMP_BLOCKS: 408025e89e99SAndrei Emeltchenko hci_num_comp_blocks_evt(hdev, skb); 408125e89e99SAndrei Emeltchenko break; 408225e89e99SAndrei Emeltchenko 40831da177e4SLinus Torvalds default: 40849f1db00cSAndrei Emeltchenko BT_DBG("%s event 0x%2.2x", hdev->name, event); 40851da177e4SLinus Torvalds break; 40861da177e4SLinus Torvalds } 40871da177e4SLinus Torvalds 40881da177e4SLinus Torvalds kfree_skb(skb); 40891da177e4SLinus Torvalds hdev->stat.evt_rx++; 40901da177e4SLinus Torvalds } 4091