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 278c520a59SGustavo Padovan #include <linux/export.h> 281da177e4SLinus Torvalds #include <asm/unaligned.h> 291da177e4SLinus Torvalds 301da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h> 311da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h> 32f0d6a0eaSMikel Astiz #include <net/bluetooth/mgmt.h> 338e2a0d92SAndrei Emeltchenko #include <net/bluetooth/a2mp.h> 34903e4541SAndrei Emeltchenko #include <net/bluetooth/amp.h> 351da177e4SLinus Torvalds 361da177e4SLinus Torvalds /* Handle HCI Event packets */ 371da177e4SLinus Torvalds 38a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb) 391da177e4SLinus Torvalds { 40a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 411da177e4SLinus Torvalds 429f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 431da177e4SLinus Torvalds 44e6d465cbSAndre Guedes if (status) { 45e6d465cbSAndre Guedes hci_dev_lock(hdev); 46e6d465cbSAndre Guedes mgmt_stop_discovery_failed(hdev, status); 47e6d465cbSAndre Guedes hci_dev_unlock(hdev); 48a9de9248SMarcel Holtmann return; 49e6d465cbSAndre Guedes } 501da177e4SLinus Torvalds 5189352e7dSAndre Guedes clear_bit(HCI_INQUIRY, &hdev->flags); 5289352e7dSAndre Guedes 5356e5cb86SJohan Hedberg hci_dev_lock(hdev); 54ff9ef578SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 5556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 56a9de9248SMarcel Holtmann 5723bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status); 58a9de9248SMarcel Holtmann 59a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 601da177e4SLinus Torvalds } 616bd57416SMarcel Holtmann 624d93483bSAndre Guedes static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 634d93483bSAndre Guedes { 644d93483bSAndre Guedes __u8 status = *((__u8 *) skb->data); 654d93483bSAndre Guedes 669f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 67ae854a70SAndre Guedes 68ae854a70SAndre Guedes if (status) 69ae854a70SAndre Guedes return; 70ae854a70SAndre Guedes 71ae854a70SAndre Guedes set_bit(HCI_PERIODIC_INQ, &hdev->dev_flags); 724d93483bSAndre Guedes } 734d93483bSAndre Guedes 74a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 751da177e4SLinus Torvalds { 76a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 77a9de9248SMarcel Holtmann 789f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 79a9de9248SMarcel Holtmann 80a9de9248SMarcel Holtmann if (status) 81a9de9248SMarcel Holtmann return; 82a9de9248SMarcel Holtmann 83ae854a70SAndre Guedes clear_bit(HCI_PERIODIC_INQ, &hdev->dev_flags); 84ae854a70SAndre Guedes 85a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 86a9de9248SMarcel Holtmann } 87a9de9248SMarcel Holtmann 88807deac2SGustavo Padovan static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, 89807deac2SGustavo Padovan struct sk_buff *skb) 90a9de9248SMarcel Holtmann { 91a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 92a9de9248SMarcel Holtmann } 93a9de9248SMarcel Holtmann 94a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb) 95a9de9248SMarcel Holtmann { 96a9de9248SMarcel Holtmann struct hci_rp_role_discovery *rp = (void *) skb->data; 971da177e4SLinus Torvalds struct hci_conn *conn; 981da177e4SLinus Torvalds 999f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1001da177e4SLinus Torvalds 101a9de9248SMarcel Holtmann if (rp->status) 102a9de9248SMarcel Holtmann return; 1031da177e4SLinus Torvalds 1041da177e4SLinus Torvalds hci_dev_lock(hdev); 1051da177e4SLinus Torvalds 106a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 1071da177e4SLinus Torvalds if (conn) { 108a9de9248SMarcel Holtmann if (rp->role) 1091da177e4SLinus Torvalds conn->link_mode &= ~HCI_LM_MASTER; 1101da177e4SLinus Torvalds else 1111da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 1121da177e4SLinus Torvalds } 1131da177e4SLinus Torvalds 1141da177e4SLinus Torvalds hci_dev_unlock(hdev); 115a9de9248SMarcel Holtmann } 1161da177e4SLinus Torvalds 117e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 118e4e8e37cSMarcel Holtmann { 119e4e8e37cSMarcel Holtmann struct hci_rp_read_link_policy *rp = (void *) skb->data; 120e4e8e37cSMarcel Holtmann struct hci_conn *conn; 121e4e8e37cSMarcel Holtmann 1229f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 123e4e8e37cSMarcel Holtmann 124e4e8e37cSMarcel Holtmann if (rp->status) 125e4e8e37cSMarcel Holtmann return; 126e4e8e37cSMarcel Holtmann 127e4e8e37cSMarcel Holtmann hci_dev_lock(hdev); 128e4e8e37cSMarcel Holtmann 129e4e8e37cSMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 130e4e8e37cSMarcel Holtmann if (conn) 131e4e8e37cSMarcel Holtmann conn->link_policy = __le16_to_cpu(rp->policy); 132e4e8e37cSMarcel Holtmann 133e4e8e37cSMarcel Holtmann hci_dev_unlock(hdev); 134e4e8e37cSMarcel Holtmann } 135e4e8e37cSMarcel Holtmann 136a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 137a9de9248SMarcel Holtmann { 138a9de9248SMarcel Holtmann struct hci_rp_write_link_policy *rp = (void *) skb->data; 139a9de9248SMarcel Holtmann struct hci_conn *conn; 140a9de9248SMarcel Holtmann void *sent; 141a9de9248SMarcel Holtmann 1429f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 143a9de9248SMarcel Holtmann 144a9de9248SMarcel Holtmann if (rp->status) 145a9de9248SMarcel Holtmann return; 146a9de9248SMarcel Holtmann 147a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY); 14804837f64SMarcel Holtmann if (!sent) 149a9de9248SMarcel Holtmann return; 15004837f64SMarcel Holtmann 15104837f64SMarcel Holtmann hci_dev_lock(hdev); 15204837f64SMarcel Holtmann 153a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 154e4e8e37cSMarcel Holtmann if (conn) 15583985319SHarvey Harrison conn->link_policy = get_unaligned_le16(sent + 2); 15604837f64SMarcel Holtmann 15704837f64SMarcel Holtmann hci_dev_unlock(hdev); 1581da177e4SLinus Torvalds } 1591da177e4SLinus Torvalds 160807deac2SGustavo Padovan static void hci_cc_read_def_link_policy(struct hci_dev *hdev, 161807deac2SGustavo Padovan struct sk_buff *skb) 162e4e8e37cSMarcel Holtmann { 163e4e8e37cSMarcel Holtmann struct hci_rp_read_def_link_policy *rp = (void *) skb->data; 164e4e8e37cSMarcel Holtmann 1659f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 166e4e8e37cSMarcel Holtmann 167e4e8e37cSMarcel Holtmann if (rp->status) 168e4e8e37cSMarcel Holtmann return; 169e4e8e37cSMarcel Holtmann 170e4e8e37cSMarcel Holtmann hdev->link_policy = __le16_to_cpu(rp->policy); 171e4e8e37cSMarcel Holtmann } 172e4e8e37cSMarcel Holtmann 173807deac2SGustavo Padovan static void hci_cc_write_def_link_policy(struct hci_dev *hdev, 174807deac2SGustavo Padovan struct sk_buff *skb) 175e4e8e37cSMarcel Holtmann { 176e4e8e37cSMarcel Holtmann __u8 status = *((__u8 *) skb->data); 177e4e8e37cSMarcel Holtmann void *sent; 178e4e8e37cSMarcel Holtmann 1799f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 180e4e8e37cSMarcel Holtmann 181e4e8e37cSMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY); 182e4e8e37cSMarcel Holtmann if (!sent) 183e4e8e37cSMarcel Holtmann return; 184e4e8e37cSMarcel Holtmann 185e4e8e37cSMarcel Holtmann if (!status) 186e4e8e37cSMarcel Holtmann hdev->link_policy = get_unaligned_le16(sent); 187e4e8e37cSMarcel Holtmann 18823bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status); 189e4e8e37cSMarcel Holtmann } 190e4e8e37cSMarcel Holtmann 191a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) 1921da177e4SLinus Torvalds { 193a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 194a9de9248SMarcel Holtmann 1959f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 196a9de9248SMarcel Holtmann 19710572132SGustavo F. Padovan clear_bit(HCI_RESET, &hdev->flags); 19810572132SGustavo F. Padovan 19923bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_RESET, status); 200d23264a8SAndre Guedes 201a297e97cSJohan Hedberg /* Reset all non-persistent flags */ 202ae854a70SAndre Guedes hdev->dev_flags &= ~(BIT(HCI_LE_SCAN) | BIT(HCI_PENDING_CLASS) | 203ae854a70SAndre Guedes BIT(HCI_PERIODIC_INQ)); 20469775ff6SAndre Guedes 20569775ff6SAndre Guedes hdev->discovery.state = DISCOVERY_STOPPED; 206a9de9248SMarcel Holtmann } 207a9de9248SMarcel Holtmann 208a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) 209a9de9248SMarcel Holtmann { 210a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 2111da177e4SLinus Torvalds void *sent; 2121da177e4SLinus Torvalds 2139f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 2141da177e4SLinus Torvalds 215a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); 2161da177e4SLinus Torvalds if (!sent) 217a9de9248SMarcel Holtmann return; 2181da177e4SLinus Torvalds 21956e5cb86SJohan Hedberg hci_dev_lock(hdev); 22056e5cb86SJohan Hedberg 221f51d5b24SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 222f51d5b24SJohan Hedberg mgmt_set_local_name_complete(hdev, sent, status); 22328cc7bdeSJohan Hedberg else if (!status) 22428cc7bdeSJohan Hedberg memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); 225f51d5b24SJohan Hedberg 22656e5cb86SJohan Hedberg hci_dev_unlock(hdev); 2273159d384SJohan Hedberg 2283159d384SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status); 229a9de9248SMarcel Holtmann } 230a9de9248SMarcel Holtmann 231a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) 232a9de9248SMarcel Holtmann { 233a9de9248SMarcel Holtmann struct hci_rp_read_local_name *rp = (void *) skb->data; 234a9de9248SMarcel Holtmann 2359f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 236a9de9248SMarcel Holtmann 237a9de9248SMarcel Holtmann if (rp->status) 238a9de9248SMarcel Holtmann return; 239a9de9248SMarcel Holtmann 240db99b5fcSJohan Hedberg if (test_bit(HCI_SETUP, &hdev->dev_flags)) 2411f6c6378SJohan Hedberg memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); 242a9de9248SMarcel Holtmann } 243a9de9248SMarcel Holtmann 244a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) 245a9de9248SMarcel Holtmann { 246a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 247a9de9248SMarcel Holtmann void *sent; 248a9de9248SMarcel Holtmann 2499f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 250a9de9248SMarcel Holtmann 251a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); 252a9de9248SMarcel Holtmann if (!sent) 253a9de9248SMarcel Holtmann return; 2541da177e4SLinus Torvalds 2551da177e4SLinus Torvalds if (!status) { 256a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 257a9de9248SMarcel Holtmann 2581da177e4SLinus Torvalds if (param == AUTH_ENABLED) 2591da177e4SLinus Torvalds set_bit(HCI_AUTH, &hdev->flags); 2601da177e4SLinus Torvalds else 2611da177e4SLinus Torvalds clear_bit(HCI_AUTH, &hdev->flags); 2621da177e4SLinus Torvalds } 263a9de9248SMarcel Holtmann 26433ef95edSJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 26533ef95edSJohan Hedberg mgmt_auth_enable_complete(hdev, status); 26633ef95edSJohan Hedberg 26723bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status); 268a9de9248SMarcel Holtmann } 2691da177e4SLinus Torvalds 270a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) 271a9de9248SMarcel Holtmann { 272a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 273a9de9248SMarcel Holtmann void *sent; 274a9de9248SMarcel Holtmann 2759f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 276a9de9248SMarcel Holtmann 277a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); 2781da177e4SLinus Torvalds if (!sent) 279a9de9248SMarcel Holtmann return; 2801da177e4SLinus Torvalds 2811da177e4SLinus Torvalds if (!status) { 282a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 283a9de9248SMarcel Holtmann 2841da177e4SLinus Torvalds if (param) 2851da177e4SLinus Torvalds set_bit(HCI_ENCRYPT, &hdev->flags); 2861da177e4SLinus Torvalds else 2871da177e4SLinus Torvalds clear_bit(HCI_ENCRYPT, &hdev->flags); 2881da177e4SLinus Torvalds } 289a9de9248SMarcel Holtmann 29023bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status); 2911da177e4SLinus Torvalds } 2921da177e4SLinus Torvalds 293a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) 294a9de9248SMarcel Holtmann { 29536f7fc7eSJohan Hedberg __u8 param, status = *((__u8 *) skb->data); 29636f7fc7eSJohan Hedberg int old_pscan, old_iscan; 297a9de9248SMarcel Holtmann void *sent; 2981da177e4SLinus Torvalds 2999f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 300a9de9248SMarcel Holtmann 301a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); 3021da177e4SLinus Torvalds if (!sent) 303a9de9248SMarcel Holtmann return; 3041da177e4SLinus Torvalds 30536f7fc7eSJohan Hedberg param = *((__u8 *) sent); 306a9de9248SMarcel Holtmann 30756e5cb86SJohan Hedberg hci_dev_lock(hdev); 30856e5cb86SJohan Hedberg 309fa1bd918SMikel Astiz if (status) { 310744cf19eSJohan Hedberg mgmt_write_scan_failed(hdev, param, status); 3112d7cee58SJohan Hedberg hdev->discov_timeout = 0; 3122d7cee58SJohan Hedberg goto done; 3132d7cee58SJohan Hedberg } 3142d7cee58SJohan Hedberg 3159fbcbb45SJohan Hedberg old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags); 3169fbcbb45SJohan Hedberg old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags); 317a9de9248SMarcel Holtmann 31873f22f62SJohan Hedberg if (param & SCAN_INQUIRY) { 3191da177e4SLinus Torvalds set_bit(HCI_ISCAN, &hdev->flags); 3209fbcbb45SJohan Hedberg if (!old_iscan) 321744cf19eSJohan Hedberg mgmt_discoverable(hdev, 1); 32216ab91abSJohan Hedberg if (hdev->discov_timeout > 0) { 32316ab91abSJohan Hedberg int to = msecs_to_jiffies(hdev->discov_timeout * 1000); 32416ab91abSJohan Hedberg queue_delayed_work(hdev->workqueue, &hdev->discov_off, 32516ab91abSJohan Hedberg to); 32616ab91abSJohan Hedberg } 3279fbcbb45SJohan Hedberg } else if (old_iscan) 328744cf19eSJohan Hedberg mgmt_discoverable(hdev, 0); 3291da177e4SLinus Torvalds 3309fbcbb45SJohan Hedberg if (param & SCAN_PAGE) { 3311da177e4SLinus Torvalds set_bit(HCI_PSCAN, &hdev->flags); 3329fbcbb45SJohan Hedberg if (!old_pscan) 333744cf19eSJohan Hedberg mgmt_connectable(hdev, 1); 3349fbcbb45SJohan Hedberg } else if (old_pscan) 335744cf19eSJohan Hedberg mgmt_connectable(hdev, 0); 336a9de9248SMarcel Holtmann 33736f7fc7eSJohan Hedberg done: 33856e5cb86SJohan Hedberg hci_dev_unlock(hdev); 33923bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status); 3401da177e4SLinus Torvalds } 3411da177e4SLinus Torvalds 342a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 343a9de9248SMarcel Holtmann { 344a9de9248SMarcel Holtmann struct hci_rp_read_class_of_dev *rp = (void *) skb->data; 345a9de9248SMarcel Holtmann 3469f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 347a9de9248SMarcel Holtmann 348a9de9248SMarcel Holtmann if (rp->status) 349a9de9248SMarcel Holtmann return; 350a9de9248SMarcel Holtmann 351a9de9248SMarcel Holtmann memcpy(hdev->dev_class, rp->dev_class, 3); 352a9de9248SMarcel Holtmann 353a9de9248SMarcel Holtmann BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, 354a9de9248SMarcel Holtmann hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); 355a9de9248SMarcel Holtmann } 356a9de9248SMarcel Holtmann 357a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 358a9de9248SMarcel Holtmann { 359a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 360a9de9248SMarcel Holtmann void *sent; 361a9de9248SMarcel Holtmann 3629f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 363a9de9248SMarcel Holtmann 364a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); 365a9de9248SMarcel Holtmann if (!sent) 366a9de9248SMarcel Holtmann return; 367a9de9248SMarcel Holtmann 3687f9a903cSMarcel Holtmann hci_dev_lock(hdev); 3697f9a903cSMarcel Holtmann 3707f9a903cSMarcel Holtmann if (status == 0) 371a9de9248SMarcel Holtmann memcpy(hdev->dev_class, sent, 3); 3727f9a903cSMarcel Holtmann 3737f9a903cSMarcel Holtmann if (test_bit(HCI_MGMT, &hdev->dev_flags)) 3747f9a903cSMarcel Holtmann mgmt_set_class_of_dev_complete(hdev, sent, status); 3757f9a903cSMarcel Holtmann 3767f9a903cSMarcel Holtmann hci_dev_unlock(hdev); 377a9de9248SMarcel Holtmann } 378a9de9248SMarcel Holtmann 379a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 380a9de9248SMarcel Holtmann { 381a9de9248SMarcel Holtmann struct hci_rp_read_voice_setting *rp = (void *) skb->data; 382a9de9248SMarcel Holtmann __u16 setting; 383a9de9248SMarcel Holtmann 3849f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 385a9de9248SMarcel Holtmann 386a9de9248SMarcel Holtmann if (rp->status) 387a9de9248SMarcel Holtmann return; 388a9de9248SMarcel Holtmann 389a9de9248SMarcel Holtmann setting = __le16_to_cpu(rp->voice_setting); 390a9de9248SMarcel Holtmann 391a9de9248SMarcel Holtmann if (hdev->voice_setting == setting) 392a9de9248SMarcel Holtmann return; 393a9de9248SMarcel Holtmann 394a9de9248SMarcel Holtmann hdev->voice_setting = setting; 395a9de9248SMarcel Holtmann 3969f1db00cSAndrei Emeltchenko BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting); 397a9de9248SMarcel Holtmann 3983c54711cSGustavo F. Padovan if (hdev->notify) 399a9de9248SMarcel Holtmann hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 400a9de9248SMarcel Holtmann } 401a9de9248SMarcel Holtmann 4028fc9ced3SGustavo Padovan static void hci_cc_write_voice_setting(struct hci_dev *hdev, 4038fc9ced3SGustavo Padovan struct sk_buff *skb) 404a9de9248SMarcel Holtmann { 405a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 406f383f275SMarcel Holtmann __u16 setting; 407a9de9248SMarcel Holtmann void *sent; 408a9de9248SMarcel Holtmann 4099f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 410a9de9248SMarcel Holtmann 411f383f275SMarcel Holtmann if (status) 412f383f275SMarcel Holtmann return; 413f383f275SMarcel Holtmann 414a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); 415a9de9248SMarcel Holtmann if (!sent) 416a9de9248SMarcel Holtmann return; 417a9de9248SMarcel Holtmann 418f383f275SMarcel Holtmann setting = get_unaligned_le16(sent); 4191da177e4SLinus Torvalds 420f383f275SMarcel Holtmann if (hdev->voice_setting == setting) 421f383f275SMarcel Holtmann return; 422f383f275SMarcel Holtmann 4231da177e4SLinus Torvalds hdev->voice_setting = setting; 4241da177e4SLinus Torvalds 4259f1db00cSAndrei Emeltchenko BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting); 4261da177e4SLinus Torvalds 4273c54711cSGustavo F. Padovan if (hdev->notify) 4281da177e4SLinus Torvalds hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 4291da177e4SLinus Torvalds } 4301da177e4SLinus Torvalds 431a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 4321da177e4SLinus Torvalds { 433a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 4341da177e4SLinus Torvalds 4359f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 4361da177e4SLinus Torvalds 43723bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status); 4381143e5a6SMarcel Holtmann } 4391143e5a6SMarcel Holtmann 440333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 441333140b5SMarcel Holtmann { 442333140b5SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 443333140b5SMarcel Holtmann void *sent; 444333140b5SMarcel Holtmann 4459f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 446333140b5SMarcel Holtmann 447333140b5SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); 448333140b5SMarcel Holtmann if (!sent) 449333140b5SMarcel Holtmann return; 450333140b5SMarcel Holtmann 451c0ecddc2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 452c0ecddc2SJohan Hedberg mgmt_ssp_enable_complete(hdev, *((u8 *) sent), status); 453c0ecddc2SJohan Hedberg else if (!status) { 45484bde9d6SJohan Hedberg if (*((u8 *) sent)) 45584bde9d6SJohan Hedberg set_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 45684bde9d6SJohan Hedberg else 45784bde9d6SJohan Hedberg clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 458c0ecddc2SJohan Hedberg } 459333140b5SMarcel Holtmann } 460333140b5SMarcel Holtmann 461d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev) 462d5859e22SJohan Hedberg { 463976eb20eSJohan Hedberg if (lmp_ext_inq_capable(hdev)) 464d5859e22SJohan Hedberg return 2; 465d5859e22SJohan Hedberg 466976eb20eSJohan Hedberg if (lmp_inq_rssi_capable(hdev)) 467d5859e22SJohan Hedberg return 1; 468d5859e22SJohan Hedberg 469d5859e22SJohan Hedberg if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 && 470d5859e22SJohan Hedberg hdev->lmp_subver == 0x0757) 471d5859e22SJohan Hedberg return 1; 472d5859e22SJohan Hedberg 473d5859e22SJohan Hedberg if (hdev->manufacturer == 15) { 474d5859e22SJohan Hedberg if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963) 475d5859e22SJohan Hedberg return 1; 476d5859e22SJohan Hedberg if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963) 477d5859e22SJohan Hedberg return 1; 478d5859e22SJohan Hedberg if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965) 479d5859e22SJohan Hedberg return 1; 480d5859e22SJohan Hedberg } 481d5859e22SJohan Hedberg 482d5859e22SJohan Hedberg if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 && 483d5859e22SJohan Hedberg hdev->lmp_subver == 0x1805) 484d5859e22SJohan Hedberg return 1; 485d5859e22SJohan Hedberg 486d5859e22SJohan Hedberg return 0; 487d5859e22SJohan Hedberg } 488d5859e22SJohan Hedberg 489d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev) 490d5859e22SJohan Hedberg { 491d5859e22SJohan Hedberg u8 mode; 492d5859e22SJohan Hedberg 493d5859e22SJohan Hedberg mode = hci_get_inquiry_mode(hdev); 494d5859e22SJohan Hedberg 495d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode); 496d5859e22SJohan Hedberg } 497d5859e22SJohan Hedberg 498d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev) 499d5859e22SJohan Hedberg { 500d5859e22SJohan Hedberg /* The second byte is 0xff instead of 0x9f (two reserved bits 501d5859e22SJohan Hedberg * disabled) since a Broadcom 1.2 dongle doesn't respond to the 502d5859e22SJohan Hedberg * command otherwise */ 503d5859e22SJohan Hedberg u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 }; 504d5859e22SJohan Hedberg 5056de6c18dSVille Tervo /* CSR 1.1 dongles does not accept any bitfield so don't try to set 5066de6c18dSVille Tervo * any event mask for pre 1.2 devices */ 5075a13b095SAndrei Emeltchenko if (hdev->hci_ver < BLUETOOTH_VER_1_2) 5086de6c18dSVille Tervo return; 5096de6c18dSVille Tervo 510e1171e8dSJohan Hedberg if (lmp_bredr_capable(hdev)) { 511d5859e22SJohan Hedberg events[4] |= 0x01; /* Flow Specification Complete */ 512d5859e22SJohan Hedberg events[4] |= 0x02; /* Inquiry Result with RSSI */ 513d5859e22SJohan Hedberg events[4] |= 0x04; /* Read Remote Extended Features Complete */ 514d5859e22SJohan Hedberg events[5] |= 0x08; /* Synchronous Connection Complete */ 515d5859e22SJohan Hedberg events[5] |= 0x10; /* Synchronous Connection Changed */ 516e1171e8dSJohan Hedberg } 517d5859e22SJohan Hedberg 518976eb20eSJohan Hedberg if (lmp_inq_rssi_capable(hdev)) 519a24299e6SJohan Hedberg events[4] |= 0x02; /* Inquiry Result with RSSI */ 520d5859e22SJohan Hedberg 521999dcd10SAndre Guedes if (lmp_sniffsubr_capable(hdev)) 522d5859e22SJohan Hedberg events[5] |= 0x20; /* Sniff Subrating */ 523d5859e22SJohan Hedberg 524976eb20eSJohan Hedberg if (lmp_pause_enc_capable(hdev)) 525d5859e22SJohan Hedberg events[5] |= 0x80; /* Encryption Key Refresh Complete */ 526d5859e22SJohan Hedberg 527976eb20eSJohan Hedberg if (lmp_ext_inq_capable(hdev)) 528d5859e22SJohan Hedberg events[5] |= 0x40; /* Extended Inquiry Result */ 529d5859e22SJohan Hedberg 530c58e810eSAndre Guedes if (lmp_no_flush_capable(hdev)) 531d5859e22SJohan Hedberg events[7] |= 0x01; /* Enhanced Flush Complete */ 532d5859e22SJohan Hedberg 533976eb20eSJohan Hedberg if (lmp_lsto_capable(hdev)) 534d5859e22SJohan Hedberg events[6] |= 0x80; /* Link Supervision Timeout Changed */ 535d5859e22SJohan Hedberg 5369a1a1996SAndre Guedes if (lmp_ssp_capable(hdev)) { 537d5859e22SJohan Hedberg events[6] |= 0x01; /* IO Capability Request */ 538d5859e22SJohan Hedberg events[6] |= 0x02; /* IO Capability Response */ 539d5859e22SJohan Hedberg events[6] |= 0x04; /* User Confirmation Request */ 540d5859e22SJohan Hedberg events[6] |= 0x08; /* User Passkey Request */ 541d5859e22SJohan Hedberg events[6] |= 0x10; /* Remote OOB Data Request */ 542d5859e22SJohan Hedberg events[6] |= 0x20; /* Simple Pairing Complete */ 543d5859e22SJohan Hedberg events[7] |= 0x04; /* User Passkey Notification */ 544d5859e22SJohan Hedberg events[7] |= 0x08; /* Keypress Notification */ 545d5859e22SJohan Hedberg events[7] |= 0x10; /* Remote Host Supported 546d5859e22SJohan Hedberg * Features Notification */ 547d5859e22SJohan Hedberg } 548d5859e22SJohan Hedberg 549c383ddc4SAndre Guedes if (lmp_le_capable(hdev)) 550d5859e22SJohan Hedberg events[7] |= 0x20; /* LE Meta-Event */ 551d5859e22SJohan Hedberg 552d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); 553e36b04c8SJohan Hedberg 554e36b04c8SJohan Hedberg if (lmp_le_capable(hdev)) { 555e36b04c8SJohan Hedberg memset(events, 0, sizeof(events)); 556e36b04c8SJohan Hedberg events[0] = 0x1f; 557e36b04c8SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LE_SET_EVENT_MASK, 558e36b04c8SJohan Hedberg sizeof(events), events); 559e36b04c8SJohan Hedberg } 560d5859e22SJohan Hedberg } 561d5859e22SJohan Hedberg 5624611dfa8SGustavo Padovan static void bredr_setup(struct hci_dev *hdev) 563e1171e8dSJohan Hedberg { 564e1171e8dSJohan Hedberg struct hci_cp_delete_stored_link_key cp; 565e1171e8dSJohan Hedberg __le16 param; 566e1171e8dSJohan Hedberg __u8 flt_type; 567e1171e8dSJohan Hedberg 568e1171e8dSJohan Hedberg /* Read Buffer Size (ACL mtu, max pkt, etc.) */ 569e1171e8dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL); 570e1171e8dSJohan Hedberg 571e1171e8dSJohan Hedberg /* Read Class of Device */ 572e1171e8dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL); 573e1171e8dSJohan Hedberg 574e1171e8dSJohan Hedberg /* Read Local Name */ 575e1171e8dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL); 576e1171e8dSJohan Hedberg 577e1171e8dSJohan Hedberg /* Read Voice Setting */ 578e1171e8dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL); 579e1171e8dSJohan Hedberg 580e1171e8dSJohan Hedberg /* Clear Event Filters */ 581e1171e8dSJohan Hedberg flt_type = HCI_FLT_CLEAR_ALL; 582e1171e8dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type); 583e1171e8dSJohan Hedberg 584e1171e8dSJohan Hedberg /* Connection accept timeout ~20 secs */ 585e1171e8dSJohan Hedberg param = __constant_cpu_to_le16(0x7d00); 586e1171e8dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m); 587e1171e8dSJohan Hedberg 588e1171e8dSJohan Hedberg bacpy(&cp.bdaddr, BDADDR_ANY); 589e1171e8dSJohan Hedberg cp.delete_all = 1; 590e1171e8dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp); 591e1171e8dSJohan Hedberg } 592e1171e8dSJohan Hedberg 5934611dfa8SGustavo Padovan static void le_setup(struct hci_dev *hdev) 594e1171e8dSJohan Hedberg { 595e1171e8dSJohan Hedberg /* Read LE Buffer Size */ 596e1171e8dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL); 5978fa19098SJohan Hedberg 5988fa19098SJohan Hedberg /* Read LE Advertising Channel TX Power */ 5998fa19098SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL); 600e1171e8dSJohan Hedberg } 601e1171e8dSJohan Hedberg 602d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev) 603d5859e22SJohan Hedberg { 604e61ef499SAndrei Emeltchenko if (hdev->dev_type != HCI_BREDR) 605e61ef499SAndrei Emeltchenko return; 606e61ef499SAndrei Emeltchenko 607e1171e8dSJohan Hedberg /* Read BD Address */ 608e1171e8dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL); 609e1171e8dSJohan Hedberg 610e1171e8dSJohan Hedberg if (lmp_bredr_capable(hdev)) 6114611dfa8SGustavo Padovan bredr_setup(hdev); 612e1171e8dSJohan Hedberg 613e1171e8dSJohan Hedberg if (lmp_le_capable(hdev)) 6144611dfa8SGustavo Padovan le_setup(hdev); 615e1171e8dSJohan Hedberg 616d5859e22SJohan Hedberg hci_setup_event_mask(hdev); 617d5859e22SJohan Hedberg 618d095c1ebSAndrei Emeltchenko if (hdev->hci_ver > BLUETOOTH_VER_1_1) 619d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); 620d5859e22SJohan Hedberg 6216d3c730fSGustavo Padovan if (lmp_ssp_capable(hdev)) { 62254d04dbbSJohan Hedberg if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { 623d5859e22SJohan Hedberg u8 mode = 0x01; 62454d04dbbSJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 62554d04dbbSJohan Hedberg sizeof(mode), &mode); 62654d04dbbSJohan Hedberg } else { 62754d04dbbSJohan Hedberg struct hci_cp_write_eir cp; 62854d04dbbSJohan Hedberg 62954d04dbbSJohan Hedberg memset(hdev->eir, 0, sizeof(hdev->eir)); 63054d04dbbSJohan Hedberg memset(&cp, 0, sizeof(cp)); 63154d04dbbSJohan Hedberg 63254d04dbbSJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp); 63354d04dbbSJohan Hedberg } 634d5859e22SJohan Hedberg } 635d5859e22SJohan Hedberg 636976eb20eSJohan Hedberg if (lmp_inq_rssi_capable(hdev)) 637d5859e22SJohan Hedberg hci_setup_inquiry_mode(hdev); 638d5859e22SJohan Hedberg 639976eb20eSJohan Hedberg if (lmp_inq_tx_pwr_capable(hdev)) 640d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL); 641971e3a4bSAndre Guedes 642976eb20eSJohan Hedberg if (lmp_ext_feat_capable(hdev)) { 643971e3a4bSAndre Guedes struct hci_cp_read_local_ext_features cp; 644971e3a4bSAndre Guedes 645971e3a4bSAndre Guedes cp.page = 0x01; 64604124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), 64704124681SGustavo F. Padovan &cp); 648971e3a4bSAndre Guedes } 649e6100a25SAndre Guedes 65047990ea0SJohan Hedberg if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) { 65147990ea0SJohan Hedberg u8 enable = 1; 65204124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable), 65304124681SGustavo F. Padovan &enable); 65447990ea0SJohan Hedberg } 655d5859e22SJohan Hedberg } 656d5859e22SJohan Hedberg 657a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) 658a9de9248SMarcel Holtmann { 659a9de9248SMarcel Holtmann struct hci_rp_read_local_version *rp = (void *) skb->data; 6601143e5a6SMarcel Holtmann 6619f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 6621143e5a6SMarcel Holtmann 663a9de9248SMarcel Holtmann if (rp->status) 66428b8df77SAndrei Emeltchenko goto done; 6651143e5a6SMarcel Holtmann 666a9de9248SMarcel Holtmann hdev->hci_ver = rp->hci_ver; 667e4e8e37cSMarcel Holtmann hdev->hci_rev = __le16_to_cpu(rp->hci_rev); 668d5859e22SJohan Hedberg hdev->lmp_ver = rp->lmp_ver; 669e4e8e37cSMarcel Holtmann hdev->manufacturer = __le16_to_cpu(rp->manufacturer); 670d5859e22SJohan Hedberg hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); 6711da177e4SLinus Torvalds 6729f1db00cSAndrei Emeltchenko BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name, 673807deac2SGustavo Padovan hdev->manufacturer, hdev->hci_ver, hdev->hci_rev); 674d5859e22SJohan Hedberg 675d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags)) 676d5859e22SJohan Hedberg hci_setup(hdev); 67728b8df77SAndrei Emeltchenko 67828b8df77SAndrei Emeltchenko done: 67928b8df77SAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status); 680d5859e22SJohan Hedberg } 681d5859e22SJohan Hedberg 682d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev) 683d5859e22SJohan Hedberg { 684035100c8SAndrei Emeltchenko struct hci_cp_write_def_link_policy cp; 685d5859e22SJohan Hedberg u16 link_policy = 0; 686d5859e22SJohan Hedberg 6879f92ebf6SAndre Guedes if (lmp_rswitch_capable(hdev)) 688d5859e22SJohan Hedberg link_policy |= HCI_LP_RSWITCH; 689976eb20eSJohan Hedberg if (lmp_hold_capable(hdev)) 690d5859e22SJohan Hedberg link_policy |= HCI_LP_HOLD; 6916eded100SAndre Guedes if (lmp_sniff_capable(hdev)) 692d5859e22SJohan Hedberg link_policy |= HCI_LP_SNIFF; 693976eb20eSJohan Hedberg if (lmp_park_capable(hdev)) 694d5859e22SJohan Hedberg link_policy |= HCI_LP_PARK; 695d5859e22SJohan Hedberg 696035100c8SAndrei Emeltchenko cp.policy = cpu_to_le16(link_policy); 697035100c8SAndrei Emeltchenko hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp); 6981da177e4SLinus Torvalds } 6991da177e4SLinus Torvalds 7008fc9ced3SGustavo Padovan static void hci_cc_read_local_commands(struct hci_dev *hdev, 7018fc9ced3SGustavo Padovan struct sk_buff *skb) 702a9de9248SMarcel Holtmann { 703a9de9248SMarcel Holtmann struct hci_rp_read_local_commands *rp = (void *) skb->data; 704a9de9248SMarcel Holtmann 7059f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 706a9de9248SMarcel Holtmann 707a9de9248SMarcel Holtmann if (rp->status) 708d5859e22SJohan Hedberg goto done; 709a9de9248SMarcel Holtmann 710a9de9248SMarcel Holtmann memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); 711d5859e22SJohan Hedberg 712d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10)) 713d5859e22SJohan Hedberg hci_setup_link_policy(hdev); 714d5859e22SJohan Hedberg 715d5859e22SJohan Hedberg done: 716d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status); 717a9de9248SMarcel Holtmann } 718a9de9248SMarcel Holtmann 7198fc9ced3SGustavo Padovan static void hci_cc_read_local_features(struct hci_dev *hdev, 7208fc9ced3SGustavo Padovan struct sk_buff *skb) 721a9de9248SMarcel Holtmann { 722a9de9248SMarcel Holtmann struct hci_rp_read_local_features *rp = (void *) skb->data; 723a9de9248SMarcel Holtmann 7249f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 725a9de9248SMarcel Holtmann 726a9de9248SMarcel Holtmann if (rp->status) 727a9de9248SMarcel Holtmann return; 728a9de9248SMarcel Holtmann 729a9de9248SMarcel Holtmann memcpy(hdev->features, rp->features, 8); 7301da177e4SLinus Torvalds 7311da177e4SLinus Torvalds /* Adjust default settings according to features 7321da177e4SLinus Torvalds * supported by device. */ 733a9de9248SMarcel Holtmann 7341da177e4SLinus Torvalds if (hdev->features[0] & LMP_3SLOT) 7351da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM3 | HCI_DH3); 7361da177e4SLinus Torvalds 7371da177e4SLinus Torvalds if (hdev->features[0] & LMP_5SLOT) 7381da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM5 | HCI_DH5); 7391da177e4SLinus Torvalds 7405b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV2) { 7411da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV2); 7425b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV2); 7435b7f9909SMarcel Holtmann } 7441da177e4SLinus Torvalds 7455b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV3) { 7461da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV3); 7475b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV3); 7485b7f9909SMarcel Holtmann } 7495b7f9909SMarcel Holtmann 75045db810fSAndre Guedes if (lmp_esco_capable(hdev)) 7515b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV3); 7525b7f9909SMarcel Holtmann 7535b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV4) 7545b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV4); 7555b7f9909SMarcel Holtmann 7565b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV5) 7575b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV5); 7581da177e4SLinus Torvalds 759efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_2M) 760efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV3); 761efc7688bSMarcel Holtmann 762efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_3M) 763efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_3EV3); 764efc7688bSMarcel Holtmann 765efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_3S_ESCO) 766efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); 767efc7688bSMarcel Holtmann 768a9de9248SMarcel Holtmann BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, 769a9de9248SMarcel Holtmann hdev->features[0], hdev->features[1], 770a9de9248SMarcel Holtmann hdev->features[2], hdev->features[3], 771a9de9248SMarcel Holtmann hdev->features[4], hdev->features[5], 772a9de9248SMarcel Holtmann hdev->features[6], hdev->features[7]); 7731da177e4SLinus Torvalds } 7741da177e4SLinus Torvalds 7758f984dfaSJohan Hedberg static void hci_set_le_support(struct hci_dev *hdev) 7768f984dfaSJohan Hedberg { 7778f984dfaSJohan Hedberg struct hci_cp_write_le_host_supported cp; 7788f984dfaSJohan Hedberg 7798f984dfaSJohan Hedberg memset(&cp, 0, sizeof(cp)); 7808f984dfaSJohan Hedberg 7819d42820fSMarcel Holtmann if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { 7828f984dfaSJohan Hedberg cp.le = 1; 783976eb20eSJohan Hedberg cp.simul = !!lmp_le_br_capable(hdev); 7848f984dfaSJohan Hedberg } 7858f984dfaSJohan Hedberg 786976eb20eSJohan Hedberg if (cp.le != !!lmp_host_le_capable(hdev)) 78704124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), 78804124681SGustavo F. Padovan &cp); 7898f984dfaSJohan Hedberg } 7908f984dfaSJohan Hedberg 791971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev, 792971e3a4bSAndre Guedes struct sk_buff *skb) 793971e3a4bSAndre Guedes { 794971e3a4bSAndre Guedes struct hci_rp_read_local_ext_features *rp = (void *) skb->data; 795971e3a4bSAndre Guedes 7969f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 797971e3a4bSAndre Guedes 798971e3a4bSAndre Guedes if (rp->status) 7998f984dfaSJohan Hedberg goto done; 800971e3a4bSAndre Guedes 801b5b32b65SAndre Guedes switch (rp->page) { 802b5b32b65SAndre Guedes case 0: 803b5b32b65SAndre Guedes memcpy(hdev->features, rp->features, 8); 804b5b32b65SAndre Guedes break; 805b5b32b65SAndre Guedes case 1: 80659e29406SAndre Guedes memcpy(hdev->host_features, rp->features, 8); 807b5b32b65SAndre Guedes break; 808b5b32b65SAndre Guedes } 809971e3a4bSAndre Guedes 810c383ddc4SAndre Guedes if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev)) 8118f984dfaSJohan Hedberg hci_set_le_support(hdev); 8128f984dfaSJohan Hedberg 8138f984dfaSJohan Hedberg done: 814971e3a4bSAndre Guedes hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status); 815971e3a4bSAndre Guedes } 816971e3a4bSAndre Guedes 8171e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, 8181e89cffbSAndrei Emeltchenko struct sk_buff *skb) 8191e89cffbSAndrei Emeltchenko { 8201e89cffbSAndrei Emeltchenko struct hci_rp_read_flow_control_mode *rp = (void *) skb->data; 8211e89cffbSAndrei Emeltchenko 8229f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 8231e89cffbSAndrei Emeltchenko 8241e89cffbSAndrei Emeltchenko if (rp->status) 8251e89cffbSAndrei Emeltchenko return; 8261e89cffbSAndrei Emeltchenko 8271e89cffbSAndrei Emeltchenko hdev->flow_ctl_mode = rp->mode; 8281e89cffbSAndrei Emeltchenko 8291e89cffbSAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status); 8301e89cffbSAndrei Emeltchenko } 8311e89cffbSAndrei Emeltchenko 832a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 833a9de9248SMarcel Holtmann { 834a9de9248SMarcel Holtmann struct hci_rp_read_buffer_size *rp = (void *) skb->data; 835a9de9248SMarcel Holtmann 8369f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 837a9de9248SMarcel Holtmann 838a9de9248SMarcel Holtmann if (rp->status) 839a9de9248SMarcel Holtmann return; 840a9de9248SMarcel Holtmann 841a9de9248SMarcel Holtmann hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); 842a9de9248SMarcel Holtmann hdev->sco_mtu = rp->sco_mtu; 843a9de9248SMarcel Holtmann hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); 844a9de9248SMarcel Holtmann hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); 845da1f5198SMarcel Holtmann 846da1f5198SMarcel Holtmann if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { 847da1f5198SMarcel Holtmann hdev->sco_mtu = 64; 848da1f5198SMarcel Holtmann hdev->sco_pkts = 8; 849da1f5198SMarcel Holtmann } 850da1f5198SMarcel Holtmann 851da1f5198SMarcel Holtmann hdev->acl_cnt = hdev->acl_pkts; 852da1f5198SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 8531da177e4SLinus Torvalds 854807deac2SGustavo Padovan BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu, 855807deac2SGustavo Padovan hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts); 8561da177e4SLinus Torvalds } 8571da177e4SLinus Torvalds 858a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) 859a9de9248SMarcel Holtmann { 860a9de9248SMarcel Holtmann struct hci_rp_read_bd_addr *rp = (void *) skb->data; 8611da177e4SLinus Torvalds 8629f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 863a9de9248SMarcel Holtmann 864a9de9248SMarcel Holtmann if (!rp->status) 865a9de9248SMarcel Holtmann bacpy(&hdev->bdaddr, &rp->bdaddr); 866a9de9248SMarcel Holtmann 86723bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status); 86823bb5763SJohan Hedberg } 86923bb5763SJohan Hedberg 870350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev, 871350ee4cfSAndrei Emeltchenko struct sk_buff *skb) 872350ee4cfSAndrei Emeltchenko { 873350ee4cfSAndrei Emeltchenko struct hci_rp_read_data_block_size *rp = (void *) skb->data; 874350ee4cfSAndrei Emeltchenko 8759f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 876350ee4cfSAndrei Emeltchenko 877350ee4cfSAndrei Emeltchenko if (rp->status) 878350ee4cfSAndrei Emeltchenko return; 879350ee4cfSAndrei Emeltchenko 880350ee4cfSAndrei Emeltchenko hdev->block_mtu = __le16_to_cpu(rp->max_acl_len); 881350ee4cfSAndrei Emeltchenko hdev->block_len = __le16_to_cpu(rp->block_len); 882350ee4cfSAndrei Emeltchenko hdev->num_blocks = __le16_to_cpu(rp->num_blocks); 883350ee4cfSAndrei Emeltchenko 884350ee4cfSAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 885350ee4cfSAndrei Emeltchenko 886350ee4cfSAndrei Emeltchenko BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu, 887350ee4cfSAndrei Emeltchenko hdev->block_cnt, hdev->block_len); 888350ee4cfSAndrei Emeltchenko 889350ee4cfSAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status); 890350ee4cfSAndrei Emeltchenko } 891350ee4cfSAndrei Emeltchenko 89223bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb) 89323bb5763SJohan Hedberg { 89423bb5763SJohan Hedberg __u8 status = *((__u8 *) skb->data); 89523bb5763SJohan Hedberg 8969f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 89723bb5763SJohan Hedberg 89823bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status); 8991da177e4SLinus Torvalds } 9001da177e4SLinus Torvalds 901928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev, 902928abaa7SAndrei Emeltchenko struct sk_buff *skb) 903928abaa7SAndrei Emeltchenko { 904928abaa7SAndrei Emeltchenko struct hci_rp_read_local_amp_info *rp = (void *) skb->data; 905928abaa7SAndrei Emeltchenko 9069f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 907928abaa7SAndrei Emeltchenko 908928abaa7SAndrei Emeltchenko if (rp->status) 9098e2a0d92SAndrei Emeltchenko goto a2mp_rsp; 910928abaa7SAndrei Emeltchenko 911928abaa7SAndrei Emeltchenko hdev->amp_status = rp->amp_status; 912928abaa7SAndrei Emeltchenko hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); 913928abaa7SAndrei Emeltchenko hdev->amp_max_bw = __le32_to_cpu(rp->max_bw); 914928abaa7SAndrei Emeltchenko hdev->amp_min_latency = __le32_to_cpu(rp->min_latency); 915928abaa7SAndrei Emeltchenko hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu); 916928abaa7SAndrei Emeltchenko hdev->amp_type = rp->amp_type; 917928abaa7SAndrei Emeltchenko hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap); 918928abaa7SAndrei Emeltchenko hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size); 919928abaa7SAndrei Emeltchenko hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); 920928abaa7SAndrei Emeltchenko hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); 921928abaa7SAndrei Emeltchenko 922928abaa7SAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status); 9238e2a0d92SAndrei Emeltchenko 9248e2a0d92SAndrei Emeltchenko a2mp_rsp: 9258e2a0d92SAndrei Emeltchenko a2mp_send_getinfo_rsp(hdev); 926928abaa7SAndrei Emeltchenko } 927928abaa7SAndrei Emeltchenko 928903e4541SAndrei Emeltchenko static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev, 929903e4541SAndrei Emeltchenko struct sk_buff *skb) 930903e4541SAndrei Emeltchenko { 931903e4541SAndrei Emeltchenko struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data; 932903e4541SAndrei Emeltchenko struct amp_assoc *assoc = &hdev->loc_assoc; 933903e4541SAndrei Emeltchenko size_t rem_len, frag_len; 934903e4541SAndrei Emeltchenko 935903e4541SAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 936903e4541SAndrei Emeltchenko 937903e4541SAndrei Emeltchenko if (rp->status) 938903e4541SAndrei Emeltchenko goto a2mp_rsp; 939903e4541SAndrei Emeltchenko 940903e4541SAndrei Emeltchenko frag_len = skb->len - sizeof(*rp); 941903e4541SAndrei Emeltchenko rem_len = __le16_to_cpu(rp->rem_len); 942903e4541SAndrei Emeltchenko 943903e4541SAndrei Emeltchenko if (rem_len > frag_len) { 9442e430be3SAndrei Emeltchenko BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len); 945903e4541SAndrei Emeltchenko 946903e4541SAndrei Emeltchenko memcpy(assoc->data + assoc->offset, rp->frag, frag_len); 947903e4541SAndrei Emeltchenko assoc->offset += frag_len; 948903e4541SAndrei Emeltchenko 949903e4541SAndrei Emeltchenko /* Read other fragments */ 950903e4541SAndrei Emeltchenko amp_read_loc_assoc_frag(hdev, rp->phy_handle); 951903e4541SAndrei Emeltchenko 952903e4541SAndrei Emeltchenko return; 953903e4541SAndrei Emeltchenko } 954903e4541SAndrei Emeltchenko 955903e4541SAndrei Emeltchenko memcpy(assoc->data + assoc->offset, rp->frag, rem_len); 956903e4541SAndrei Emeltchenko assoc->len = assoc->offset + rem_len; 957903e4541SAndrei Emeltchenko assoc->offset = 0; 958903e4541SAndrei Emeltchenko 959903e4541SAndrei Emeltchenko a2mp_rsp: 960903e4541SAndrei Emeltchenko /* Send A2MP Rsp when all fragments are received */ 961903e4541SAndrei Emeltchenko a2mp_send_getampassoc_rsp(hdev, rp->status); 9629495b2eeSAndrei Emeltchenko a2mp_send_create_phy_link_req(hdev, rp->status); 963903e4541SAndrei Emeltchenko } 964903e4541SAndrei Emeltchenko 965b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, 966b0916ea0SJohan Hedberg struct sk_buff *skb) 967b0916ea0SJohan Hedberg { 968b0916ea0SJohan Hedberg __u8 status = *((__u8 *) skb->data); 969b0916ea0SJohan Hedberg 9709f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 971b0916ea0SJohan Hedberg 972b0916ea0SJohan Hedberg hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status); 973b0916ea0SJohan Hedberg } 974b0916ea0SJohan Hedberg 975d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb) 976d5859e22SJohan Hedberg { 977d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 978d5859e22SJohan Hedberg 9799f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 980d5859e22SJohan Hedberg 981d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status); 982d5859e22SJohan Hedberg } 983d5859e22SJohan Hedberg 984d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev, 985d5859e22SJohan Hedberg struct sk_buff *skb) 986d5859e22SJohan Hedberg { 987d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 988d5859e22SJohan Hedberg 9899f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 990d5859e22SJohan Hedberg 991d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status); 992d5859e22SJohan Hedberg } 993d5859e22SJohan Hedberg 994d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, 995d5859e22SJohan Hedberg struct sk_buff *skb) 996d5859e22SJohan Hedberg { 99791c4e9b1SMarcel Holtmann struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data; 998d5859e22SJohan Hedberg 9999f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1000d5859e22SJohan Hedberg 100191c4e9b1SMarcel Holtmann if (!rp->status) 100291c4e9b1SMarcel Holtmann hdev->inq_tx_power = rp->tx_power; 100391c4e9b1SMarcel Holtmann 100491c4e9b1SMarcel Holtmann hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status); 1005d5859e22SJohan Hedberg } 1006d5859e22SJohan Hedberg 1007d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb) 1008d5859e22SJohan Hedberg { 1009d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 1010d5859e22SJohan Hedberg 10119f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1012d5859e22SJohan Hedberg 1013d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status); 1014d5859e22SJohan Hedberg } 1015d5859e22SJohan Hedberg 1016980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) 1017980e1a53SJohan Hedberg { 1018980e1a53SJohan Hedberg struct hci_rp_pin_code_reply *rp = (void *) skb->data; 1019980e1a53SJohan Hedberg struct hci_cp_pin_code_reply *cp; 1020980e1a53SJohan Hedberg struct hci_conn *conn; 1021980e1a53SJohan Hedberg 10229f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1023980e1a53SJohan Hedberg 102456e5cb86SJohan Hedberg hci_dev_lock(hdev); 102556e5cb86SJohan Hedberg 1026a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1027744cf19eSJohan Hedberg mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); 1028980e1a53SJohan Hedberg 1029fa1bd918SMikel Astiz if (rp->status) 103056e5cb86SJohan Hedberg goto unlock; 1031980e1a53SJohan Hedberg 1032980e1a53SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); 1033980e1a53SJohan Hedberg if (!cp) 103456e5cb86SJohan Hedberg goto unlock; 1035980e1a53SJohan Hedberg 1036980e1a53SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 1037980e1a53SJohan Hedberg if (conn) 1038980e1a53SJohan Hedberg conn->pin_length = cp->pin_len; 103956e5cb86SJohan Hedberg 104056e5cb86SJohan Hedberg unlock: 104156e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1042980e1a53SJohan Hedberg } 1043980e1a53SJohan Hedberg 1044980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 1045980e1a53SJohan Hedberg { 1046980e1a53SJohan Hedberg struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data; 1047980e1a53SJohan Hedberg 10489f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1049980e1a53SJohan Hedberg 105056e5cb86SJohan Hedberg hci_dev_lock(hdev); 105156e5cb86SJohan Hedberg 1052a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1053744cf19eSJohan Hedberg mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr, 1054980e1a53SJohan Hedberg rp->status); 105556e5cb86SJohan Hedberg 105656e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1057980e1a53SJohan Hedberg } 105856e5cb86SJohan Hedberg 10596ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, 10606ed58ec5SVille Tervo struct sk_buff *skb) 10616ed58ec5SVille Tervo { 10626ed58ec5SVille Tervo struct hci_rp_le_read_buffer_size *rp = (void *) skb->data; 10636ed58ec5SVille Tervo 10649f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 10656ed58ec5SVille Tervo 10666ed58ec5SVille Tervo if (rp->status) 10676ed58ec5SVille Tervo return; 10686ed58ec5SVille Tervo 10696ed58ec5SVille Tervo hdev->le_mtu = __le16_to_cpu(rp->le_mtu); 10706ed58ec5SVille Tervo hdev->le_pkts = rp->le_max_pkt; 10716ed58ec5SVille Tervo 10726ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 10736ed58ec5SVille Tervo 10746ed58ec5SVille Tervo BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); 10756ed58ec5SVille Tervo 10766ed58ec5SVille Tervo hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status); 10776ed58ec5SVille Tervo } 1078980e1a53SJohan Hedberg 10798fa19098SJohan Hedberg static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, 10808fa19098SJohan Hedberg struct sk_buff *skb) 10818fa19098SJohan Hedberg { 10828fa19098SJohan Hedberg struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data; 10838fa19098SJohan Hedberg 10848fa19098SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 10858fa19098SJohan Hedberg 10868fa19098SJohan Hedberg if (!rp->status) 10878fa19098SJohan Hedberg hdev->adv_tx_power = rp->tx_power; 10888fa19098SJohan Hedberg 10898fa19098SJohan Hedberg hci_req_complete(hdev, HCI_OP_LE_READ_ADV_TX_POWER, rp->status); 10908fa19098SJohan Hedberg } 10918fa19098SJohan Hedberg 1092e36b04c8SJohan Hedberg static void hci_cc_le_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb) 1093e36b04c8SJohan Hedberg { 1094e36b04c8SJohan Hedberg __u8 status = *((__u8 *) skb->data); 1095e36b04c8SJohan Hedberg 1096e36b04c8SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 1097e36b04c8SJohan Hedberg 1098e36b04c8SJohan Hedberg hci_req_complete(hdev, HCI_OP_LE_SET_EVENT_MASK, status); 1099e36b04c8SJohan Hedberg } 1100e36b04c8SJohan Hedberg 1101a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) 1102a5c29683SJohan Hedberg { 1103a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 1104a5c29683SJohan Hedberg 11059f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1106a5c29683SJohan Hedberg 110756e5cb86SJohan Hedberg hci_dev_lock(hdev); 110856e5cb86SJohan Hedberg 1109a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 111004124681SGustavo F. Padovan mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0, 111104124681SGustavo F. Padovan rp->status); 111256e5cb86SJohan Hedberg 111356e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1114a5c29683SJohan Hedberg } 1115a5c29683SJohan Hedberg 1116a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, 1117a5c29683SJohan Hedberg struct sk_buff *skb) 1118a5c29683SJohan Hedberg { 1119a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 1120a5c29683SJohan Hedberg 11219f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1122a5c29683SJohan Hedberg 112356e5cb86SJohan Hedberg hci_dev_lock(hdev); 112456e5cb86SJohan Hedberg 1125a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1126744cf19eSJohan Hedberg mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr, 112704124681SGustavo F. Padovan ACL_LINK, 0, rp->status); 112856e5cb86SJohan Hedberg 112956e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1130a5c29683SJohan Hedberg } 1131a5c29683SJohan Hedberg 11321143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb) 11331143d458SBrian Gix { 11341143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 11351143d458SBrian Gix 11369f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 11371143d458SBrian Gix 11381143d458SBrian Gix hci_dev_lock(hdev); 11391143d458SBrian Gix 1140a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1141272d90dfSJohan Hedberg mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 1142272d90dfSJohan Hedberg 0, rp->status); 11431143d458SBrian Gix 11441143d458SBrian Gix hci_dev_unlock(hdev); 11451143d458SBrian Gix } 11461143d458SBrian Gix 11471143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, 11481143d458SBrian Gix struct sk_buff *skb) 11491143d458SBrian Gix { 11501143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 11511143d458SBrian Gix 11529f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 11531143d458SBrian Gix 11541143d458SBrian Gix hci_dev_lock(hdev); 11551143d458SBrian Gix 1156a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 11571143d458SBrian Gix mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr, 115804124681SGustavo F. Padovan ACL_LINK, 0, rp->status); 11591143d458SBrian Gix 11601143d458SBrian Gix hci_dev_unlock(hdev); 11611143d458SBrian Gix } 11621143d458SBrian Gix 1163c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, 1164c35938b2SSzymon Janc struct sk_buff *skb) 1165c35938b2SSzymon Janc { 1166c35938b2SSzymon Janc struct hci_rp_read_local_oob_data *rp = (void *) skb->data; 1167c35938b2SSzymon Janc 11689f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1169c35938b2SSzymon Janc 117056e5cb86SJohan Hedberg hci_dev_lock(hdev); 1171744cf19eSJohan Hedberg mgmt_read_local_oob_data_reply_complete(hdev, rp->hash, 1172c35938b2SSzymon Janc rp->randomizer, rp->status); 117356e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1174c35938b2SSzymon Janc } 1175c35938b2SSzymon Janc 117607f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) 117707f7fa5dSAndre Guedes { 117807f7fa5dSAndre Guedes __u8 status = *((__u8 *) skb->data); 117907f7fa5dSAndre Guedes 11809f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 11817ba8b4beSAndre Guedes 11827ba8b4beSAndre Guedes hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status); 11833fd24153SAndre Guedes 11843fd24153SAndre Guedes if (status) { 11853fd24153SAndre Guedes hci_dev_lock(hdev); 11863fd24153SAndre Guedes mgmt_start_discovery_failed(hdev, status); 11873fd24153SAndre Guedes hci_dev_unlock(hdev); 11883fd24153SAndre Guedes return; 11893fd24153SAndre Guedes } 119007f7fa5dSAndre Guedes } 119107f7fa5dSAndre Guedes 1192eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, 1193eb9d91f5SAndre Guedes struct sk_buff *skb) 1194eb9d91f5SAndre Guedes { 1195eb9d91f5SAndre Guedes struct hci_cp_le_set_scan_enable *cp; 1196eb9d91f5SAndre Guedes __u8 status = *((__u8 *) skb->data); 1197eb9d91f5SAndre Guedes 11989f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1199eb9d91f5SAndre Guedes 1200eb9d91f5SAndre Guedes cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE); 1201eb9d91f5SAndre Guedes if (!cp) 1202eb9d91f5SAndre Guedes return; 1203eb9d91f5SAndre Guedes 120468a8aea4SAndrei Emeltchenko switch (cp->enable) { 120568a8aea4SAndrei Emeltchenko case LE_SCANNING_ENABLED: 12067ba8b4beSAndre Guedes hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status); 12077ba8b4beSAndre Guedes 12083fd24153SAndre Guedes if (status) { 12093fd24153SAndre Guedes hci_dev_lock(hdev); 12103fd24153SAndre Guedes mgmt_start_discovery_failed(hdev, status); 12113fd24153SAndre Guedes hci_dev_unlock(hdev); 12127ba8b4beSAndre Guedes return; 12133fd24153SAndre Guedes } 12147ba8b4beSAndre Guedes 1215d23264a8SAndre Guedes set_bit(HCI_LE_SCAN, &hdev->dev_flags); 1216d23264a8SAndre Guedes 1217a8f13c8cSAndre Guedes hci_dev_lock(hdev); 1218343f935bSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_FINDING); 1219a8f13c8cSAndre Guedes hci_dev_unlock(hdev); 122068a8aea4SAndrei Emeltchenko break; 122168a8aea4SAndrei Emeltchenko 122268a8aea4SAndrei Emeltchenko case LE_SCANNING_DISABLED: 1223c9ecc48eSAndre Guedes if (status) { 1224c9ecc48eSAndre Guedes hci_dev_lock(hdev); 1225c9ecc48eSAndre Guedes mgmt_stop_discovery_failed(hdev, status); 1226c9ecc48eSAndre Guedes hci_dev_unlock(hdev); 12277ba8b4beSAndre Guedes return; 1228c9ecc48eSAndre Guedes } 12297ba8b4beSAndre Guedes 1230d23264a8SAndre Guedes clear_bit(HCI_LE_SCAN, &hdev->dev_flags); 1231d23264a8SAndre Guedes 1232bc3dd33cSAndre Guedes if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED && 1233bc3dd33cSAndre Guedes hdev->discovery.state == DISCOVERY_FINDING) { 12345e0452c0SAndre Guedes mgmt_interleaved_discovery(hdev); 12355e0452c0SAndre Guedes } else { 1236c599008fSAndre Guedes hci_dev_lock(hdev); 1237c599008fSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 1238c599008fSAndre Guedes hci_dev_unlock(hdev); 12395e0452c0SAndre Guedes } 1240c599008fSAndre Guedes 124168a8aea4SAndrei Emeltchenko break; 124268a8aea4SAndrei Emeltchenko 124368a8aea4SAndrei Emeltchenko default: 124468a8aea4SAndrei Emeltchenko BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable); 124568a8aea4SAndrei Emeltchenko break; 124635815085SAndre Guedes } 1247eb9d91f5SAndre Guedes } 1248eb9d91f5SAndre Guedes 1249a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb) 1250a7a595f6SVinicius Costa Gomes { 1251a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_reply *rp = (void *) skb->data; 1252a7a595f6SVinicius Costa Gomes 12539f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1254a7a595f6SVinicius Costa Gomes 1255a7a595f6SVinicius Costa Gomes if (rp->status) 1256a7a595f6SVinicius Costa Gomes return; 1257a7a595f6SVinicius Costa Gomes 1258a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status); 1259a7a595f6SVinicius Costa Gomes } 1260a7a595f6SVinicius Costa Gomes 1261a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 1262a7a595f6SVinicius Costa Gomes { 1263a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data; 1264a7a595f6SVinicius Costa Gomes 12659f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1266a7a595f6SVinicius Costa Gomes 1267a7a595f6SVinicius Costa Gomes if (rp->status) 1268a7a595f6SVinicius Costa Gomes return; 1269a7a595f6SVinicius Costa Gomes 1270a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status); 1271a7a595f6SVinicius Costa Gomes } 1272a7a595f6SVinicius Costa Gomes 12736039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev, 1274f9b49306SAndre Guedes struct sk_buff *skb) 1275f9b49306SAndre Guedes { 127606199cf8SJohan Hedberg struct hci_cp_write_le_host_supported *sent; 1277f9b49306SAndre Guedes __u8 status = *((__u8 *) skb->data); 1278f9b49306SAndre Guedes 12799f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1280f9b49306SAndre Guedes 128106199cf8SJohan Hedberg sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED); 12828f984dfaSJohan Hedberg if (!sent) 1283f9b49306SAndre Guedes return; 1284f9b49306SAndre Guedes 12858f984dfaSJohan Hedberg if (!status) { 12868f984dfaSJohan Hedberg if (sent->le) 12878f984dfaSJohan Hedberg hdev->host_features[0] |= LMP_HOST_LE; 12888f984dfaSJohan Hedberg else 12898f984dfaSJohan Hedberg hdev->host_features[0] &= ~LMP_HOST_LE; 129053b2caabSJohan Hedberg 129153b2caabSJohan Hedberg if (sent->simul) 129253b2caabSJohan Hedberg hdev->host_features[0] |= LMP_HOST_LE_BREDR; 129353b2caabSJohan Hedberg else 129453b2caabSJohan Hedberg hdev->host_features[0] &= ~LMP_HOST_LE_BREDR; 12958f984dfaSJohan Hedberg } 12968f984dfaSJohan Hedberg 12978f984dfaSJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags) && 12988f984dfaSJohan Hedberg !test_bit(HCI_INIT, &hdev->flags)) 12998f984dfaSJohan Hedberg mgmt_le_enable_complete(hdev, sent->le, status); 13008f984dfaSJohan Hedberg 13018f984dfaSJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status); 1302f9b49306SAndre Guedes } 1303f9b49306SAndre Guedes 130493c284eeSAndrei Emeltchenko static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev, 130593c284eeSAndrei Emeltchenko struct sk_buff *skb) 130693c284eeSAndrei Emeltchenko { 130793c284eeSAndrei Emeltchenko struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data; 130893c284eeSAndrei Emeltchenko 130993c284eeSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x", 131093c284eeSAndrei Emeltchenko hdev->name, rp->status, rp->phy_handle); 131193c284eeSAndrei Emeltchenko 131293c284eeSAndrei Emeltchenko if (rp->status) 131393c284eeSAndrei Emeltchenko return; 131493c284eeSAndrei Emeltchenko 131593c284eeSAndrei Emeltchenko amp_write_rem_assoc_continue(hdev, rp->phy_handle); 131693c284eeSAndrei Emeltchenko } 131793c284eeSAndrei Emeltchenko 13186039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 1319a9de9248SMarcel Holtmann { 13209f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1321a9de9248SMarcel Holtmann 1322a9de9248SMarcel Holtmann if (status) { 132323bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 1324a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 132556e5cb86SJohan Hedberg hci_dev_lock(hdev); 1326a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 13277a135109SAndre Guedes mgmt_start_discovery_failed(hdev, status); 132856e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1329314b2381SJohan Hedberg return; 1330314b2381SJohan Hedberg } 1331314b2381SJohan Hedberg 133289352e7dSAndre Guedes set_bit(HCI_INQUIRY, &hdev->flags); 133389352e7dSAndre Guedes 133456e5cb86SJohan Hedberg hci_dev_lock(hdev); 1335343f935bSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_FINDING); 133656e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1337a9de9248SMarcel Holtmann } 1338a9de9248SMarcel Holtmann 13396039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 13401da177e4SLinus Torvalds { 1341a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 13421da177e4SLinus Torvalds struct hci_conn *conn; 13431da177e4SLinus Torvalds 13449f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1345a9de9248SMarcel Holtmann 1346a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 13471da177e4SLinus Torvalds if (!cp) 13481da177e4SLinus Torvalds return; 13491da177e4SLinus Torvalds 13501da177e4SLinus Torvalds hci_dev_lock(hdev); 13511da177e4SLinus Torvalds 13521da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 13531da177e4SLinus Torvalds 13546ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn); 13551da177e4SLinus Torvalds 13561da177e4SLinus Torvalds if (status) { 13571da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 13584c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 13591da177e4SLinus Torvalds conn->state = BT_CLOSED; 13601da177e4SLinus Torvalds hci_proto_connect_cfm(conn, status); 13611da177e4SLinus Torvalds hci_conn_del(conn); 13624c67bc74SMarcel Holtmann } else 13634c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 13641da177e4SLinus Torvalds } 13651da177e4SLinus Torvalds } else { 13661da177e4SLinus Torvalds if (!conn) { 13671da177e4SLinus Torvalds conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); 13681da177e4SLinus Torvalds if (conn) { 1369a0c808b3SJohan Hedberg conn->out = true; 13701da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 13711da177e4SLinus Torvalds } else 1372893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 13731da177e4SLinus Torvalds } 13741da177e4SLinus Torvalds } 13751da177e4SLinus Torvalds 13761da177e4SLinus Torvalds hci_dev_unlock(hdev); 13771da177e4SLinus Torvalds } 13781da177e4SLinus Torvalds 1379a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 13801da177e4SLinus Torvalds { 1381a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 13821da177e4SLinus Torvalds struct hci_conn *acl, *sco; 13831da177e4SLinus Torvalds __u16 handle; 13841da177e4SLinus Torvalds 13859f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1386b6a0dc82SMarcel Holtmann 1387a9de9248SMarcel Holtmann if (!status) 1388a9de9248SMarcel Holtmann return; 1389a9de9248SMarcel Holtmann 1390a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 13911da177e4SLinus Torvalds if (!cp) 1392a9de9248SMarcel Holtmann return; 13931da177e4SLinus Torvalds 13941da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 13951da177e4SLinus Torvalds 13969f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, handle); 13971da177e4SLinus Torvalds 13981da177e4SLinus Torvalds hci_dev_lock(hdev); 13991da177e4SLinus Torvalds 14001da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 14015a08ecceSAndrei Emeltchenko if (acl) { 14025a08ecceSAndrei Emeltchenko sco = acl->link; 14035a08ecceSAndrei Emeltchenko if (sco) { 14041da177e4SLinus Torvalds sco->state = BT_CLOSED; 14051da177e4SLinus Torvalds 14061da177e4SLinus Torvalds hci_proto_connect_cfm(sco, status); 14071da177e4SLinus Torvalds hci_conn_del(sco); 14081da177e4SLinus Torvalds } 14095a08ecceSAndrei Emeltchenko } 14101da177e4SLinus Torvalds 14111da177e4SLinus Torvalds hci_dev_unlock(hdev); 14121da177e4SLinus Torvalds } 14131da177e4SLinus Torvalds 1414f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 1415f8558555SMarcel Holtmann { 1416f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 1417f8558555SMarcel Holtmann struct hci_conn *conn; 1418f8558555SMarcel Holtmann 14199f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1420f8558555SMarcel Holtmann 1421f8558555SMarcel Holtmann if (!status) 1422f8558555SMarcel Holtmann return; 1423f8558555SMarcel Holtmann 1424f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 1425f8558555SMarcel Holtmann if (!cp) 1426f8558555SMarcel Holtmann return; 1427f8558555SMarcel Holtmann 1428f8558555SMarcel Holtmann hci_dev_lock(hdev); 1429f8558555SMarcel Holtmann 1430f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1431f8558555SMarcel Holtmann if (conn) { 1432f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1433f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1434f8558555SMarcel Holtmann hci_conn_put(conn); 1435f8558555SMarcel Holtmann } 1436f8558555SMarcel Holtmann } 1437f8558555SMarcel Holtmann 1438f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1439f8558555SMarcel Holtmann } 1440f8558555SMarcel Holtmann 1441f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 1442f8558555SMarcel Holtmann { 1443f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 1444f8558555SMarcel Holtmann struct hci_conn *conn; 1445f8558555SMarcel Holtmann 14469f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1447f8558555SMarcel Holtmann 1448f8558555SMarcel Holtmann if (!status) 1449f8558555SMarcel Holtmann return; 1450f8558555SMarcel Holtmann 1451f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 1452f8558555SMarcel Holtmann if (!cp) 1453f8558555SMarcel Holtmann return; 1454f8558555SMarcel Holtmann 1455f8558555SMarcel Holtmann hci_dev_lock(hdev); 1456f8558555SMarcel Holtmann 1457f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1458f8558555SMarcel Holtmann if (conn) { 1459f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1460f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1461f8558555SMarcel Holtmann hci_conn_put(conn); 1462f8558555SMarcel Holtmann } 1463f8558555SMarcel Holtmann } 1464f8558555SMarcel Holtmann 1465f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1466f8558555SMarcel Holtmann } 1467f8558555SMarcel Holtmann 1468127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev, 1469392599b9SJohan Hedberg struct hci_conn *conn) 1470392599b9SJohan Hedberg { 1471392599b9SJohan Hedberg if (conn->state != BT_CONFIG || !conn->out) 1472392599b9SJohan Hedberg return 0; 1473392599b9SJohan Hedberg 1474765c2a96SJohan Hedberg if (conn->pending_sec_level == BT_SECURITY_SDP) 1475392599b9SJohan Hedberg return 0; 1476392599b9SJohan Hedberg 1477392599b9SJohan Hedberg /* Only request authentication for SSP connections or non-SSP 1478e9bf2bf0SVinicius Costa Gomes * devices with sec_level HIGH or if MITM protection is requested */ 1479807deac2SGustavo Padovan if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) && 1480807deac2SGustavo Padovan conn->pending_sec_level != BT_SECURITY_HIGH) 1481392599b9SJohan Hedberg return 0; 1482392599b9SJohan Hedberg 1483392599b9SJohan Hedberg return 1; 1484392599b9SJohan Hedberg } 1485392599b9SJohan Hedberg 14866039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev, 148700abfe44SGustavo F. Padovan struct inquiry_entry *e) 148830dc78e1SJohan Hedberg { 148930dc78e1SJohan Hedberg struct hci_cp_remote_name_req cp; 149030dc78e1SJohan Hedberg 149130dc78e1SJohan Hedberg memset(&cp, 0, sizeof(cp)); 149230dc78e1SJohan Hedberg 149330dc78e1SJohan Hedberg bacpy(&cp.bdaddr, &e->data.bdaddr); 149430dc78e1SJohan Hedberg cp.pscan_rep_mode = e->data.pscan_rep_mode; 149530dc78e1SJohan Hedberg cp.pscan_mode = e->data.pscan_mode; 149630dc78e1SJohan Hedberg cp.clock_offset = e->data.clock_offset; 149730dc78e1SJohan Hedberg 149830dc78e1SJohan Hedberg return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 149930dc78e1SJohan Hedberg } 150030dc78e1SJohan Hedberg 1501b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev) 150230dc78e1SJohan Hedberg { 150330dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 150430dc78e1SJohan Hedberg struct inquiry_entry *e; 150530dc78e1SJohan Hedberg 1506b644ba33SJohan Hedberg if (list_empty(&discov->resolve)) 1507b644ba33SJohan Hedberg return false; 1508b644ba33SJohan Hedberg 1509b644ba33SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 1510c810089cSRam Malovany if (!e) 1511c810089cSRam Malovany return false; 1512c810089cSRam Malovany 1513b644ba33SJohan Hedberg if (hci_resolve_name(hdev, e) == 0) { 1514b644ba33SJohan Hedberg e->name_state = NAME_PENDING; 1515b644ba33SJohan Hedberg return true; 1516b644ba33SJohan Hedberg } 1517b644ba33SJohan Hedberg 1518b644ba33SJohan Hedberg return false; 1519b644ba33SJohan Hedberg } 1520b644ba33SJohan Hedberg 1521b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn, 1522b644ba33SJohan Hedberg bdaddr_t *bdaddr, u8 *name, u8 name_len) 1523b644ba33SJohan Hedberg { 1524b644ba33SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 1525b644ba33SJohan Hedberg struct inquiry_entry *e; 1526b644ba33SJohan Hedberg 1527b644ba33SJohan Hedberg if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 152804124681SGustavo F. Padovan mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name, 152904124681SGustavo F. Padovan name_len, conn->dev_class); 1530b644ba33SJohan Hedberg 1531b644ba33SJohan Hedberg if (discov->state == DISCOVERY_STOPPED) 1532b644ba33SJohan Hedberg return; 1533b644ba33SJohan Hedberg 153430dc78e1SJohan Hedberg if (discov->state == DISCOVERY_STOPPING) 153530dc78e1SJohan Hedberg goto discov_complete; 153630dc78e1SJohan Hedberg 153730dc78e1SJohan Hedberg if (discov->state != DISCOVERY_RESOLVING) 153830dc78e1SJohan Hedberg return; 153930dc78e1SJohan Hedberg 154030dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING); 15417cc8380eSRam Malovany /* If the device was not found in a list of found devices names of which 15427cc8380eSRam Malovany * are pending. there is no need to continue resolving a next name as it 15437cc8380eSRam Malovany * will be done upon receiving another Remote Name Request Complete 15447cc8380eSRam Malovany * Event */ 15457cc8380eSRam Malovany if (!e) 15467cc8380eSRam Malovany return; 15477cc8380eSRam Malovany 154830dc78e1SJohan Hedberg list_del(&e->list); 15497cc8380eSRam Malovany if (name) { 15507cc8380eSRam Malovany e->name_state = NAME_KNOWN; 1551b644ba33SJohan Hedberg mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, 1552b644ba33SJohan Hedberg e->data.rssi, name, name_len); 1553c3e7c0d9SRam Malovany } else { 1554c3e7c0d9SRam Malovany e->name_state = NAME_NOT_KNOWN; 155530dc78e1SJohan Hedberg } 155630dc78e1SJohan Hedberg 1557b644ba33SJohan Hedberg if (hci_resolve_next_name(hdev)) 155830dc78e1SJohan Hedberg return; 155930dc78e1SJohan Hedberg 156030dc78e1SJohan Hedberg discov_complete: 156130dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 156230dc78e1SJohan Hedberg } 156330dc78e1SJohan Hedberg 1564a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 15651da177e4SLinus Torvalds { 1566127178d2SJohan Hedberg struct hci_cp_remote_name_req *cp; 1567127178d2SJohan Hedberg struct hci_conn *conn; 1568127178d2SJohan Hedberg 15699f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1570127178d2SJohan Hedberg 1571127178d2SJohan Hedberg /* If successful wait for the name req complete event before 1572127178d2SJohan Hedberg * checking for the need to do authentication */ 1573127178d2SJohan Hedberg if (!status) 1574127178d2SJohan Hedberg return; 1575127178d2SJohan Hedberg 1576127178d2SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); 1577127178d2SJohan Hedberg if (!cp) 1578127178d2SJohan Hedberg return; 1579127178d2SJohan Hedberg 1580127178d2SJohan Hedberg hci_dev_lock(hdev); 1581127178d2SJohan Hedberg 1582127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 1583b644ba33SJohan Hedberg 1584b644ba33SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1585b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0); 1586b644ba33SJohan Hedberg 158779c6c70cSJohan Hedberg if (!conn) 158879c6c70cSJohan Hedberg goto unlock; 158979c6c70cSJohan Hedberg 159079c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 159179c6c70cSJohan Hedberg goto unlock; 159279c6c70cSJohan Hedberg 159351a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 1594127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1595127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1596127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1597127178d2SJohan Hedberg } 1598127178d2SJohan Hedberg 159979c6c70cSJohan Hedberg unlock: 1600127178d2SJohan Hedberg hci_dev_unlock(hdev); 1601a9de9248SMarcel Holtmann } 16021da177e4SLinus Torvalds 1603769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 1604769be974SMarcel Holtmann { 1605769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 1606769be974SMarcel Holtmann struct hci_conn *conn; 1607769be974SMarcel Holtmann 16089f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1609769be974SMarcel Holtmann 1610769be974SMarcel Holtmann if (!status) 1611769be974SMarcel Holtmann return; 1612769be974SMarcel Holtmann 1613769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 1614769be974SMarcel Holtmann if (!cp) 1615769be974SMarcel Holtmann return; 1616769be974SMarcel Holtmann 1617769be974SMarcel Holtmann hci_dev_lock(hdev); 1618769be974SMarcel Holtmann 1619769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1620769be974SMarcel Holtmann if (conn) { 1621769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1622769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1623769be974SMarcel Holtmann hci_conn_put(conn); 1624769be974SMarcel Holtmann } 1625769be974SMarcel Holtmann } 1626769be974SMarcel Holtmann 1627769be974SMarcel Holtmann hci_dev_unlock(hdev); 1628769be974SMarcel Holtmann } 1629769be974SMarcel Holtmann 1630769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 1631769be974SMarcel Holtmann { 1632769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features *cp; 1633769be974SMarcel Holtmann struct hci_conn *conn; 1634769be974SMarcel Holtmann 16359f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1636769be974SMarcel Holtmann 1637769be974SMarcel Holtmann if (!status) 1638769be974SMarcel Holtmann return; 1639769be974SMarcel Holtmann 1640769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 1641769be974SMarcel Holtmann if (!cp) 1642769be974SMarcel Holtmann return; 1643769be974SMarcel Holtmann 1644769be974SMarcel Holtmann hci_dev_lock(hdev); 1645769be974SMarcel Holtmann 1646769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1647769be974SMarcel Holtmann if (conn) { 1648769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1649769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1650769be974SMarcel Holtmann hci_conn_put(conn); 1651769be974SMarcel Holtmann } 1652769be974SMarcel Holtmann } 1653769be974SMarcel Holtmann 1654769be974SMarcel Holtmann hci_dev_unlock(hdev); 1655769be974SMarcel Holtmann } 1656769be974SMarcel Holtmann 1657a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 1658a9de9248SMarcel Holtmann { 1659b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 1660b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 1661b6a0dc82SMarcel Holtmann __u16 handle; 1662b6a0dc82SMarcel Holtmann 16639f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1664b6a0dc82SMarcel Holtmann 1665b6a0dc82SMarcel Holtmann if (!status) 1666b6a0dc82SMarcel Holtmann return; 1667b6a0dc82SMarcel Holtmann 1668b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 1669b6a0dc82SMarcel Holtmann if (!cp) 1670b6a0dc82SMarcel Holtmann return; 1671b6a0dc82SMarcel Holtmann 1672b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 1673b6a0dc82SMarcel Holtmann 16749f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, handle); 1675b6a0dc82SMarcel Holtmann 1676b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 1677b6a0dc82SMarcel Holtmann 1678b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 16795a08ecceSAndrei Emeltchenko if (acl) { 16805a08ecceSAndrei Emeltchenko sco = acl->link; 16815a08ecceSAndrei Emeltchenko if (sco) { 1682b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 1683b6a0dc82SMarcel Holtmann 1684b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(sco, status); 1685b6a0dc82SMarcel Holtmann hci_conn_del(sco); 1686b6a0dc82SMarcel Holtmann } 16875a08ecceSAndrei Emeltchenko } 1688b6a0dc82SMarcel Holtmann 1689b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 1690a9de9248SMarcel Holtmann } 1691a9de9248SMarcel Holtmann 1692a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 1693a9de9248SMarcel Holtmann { 1694a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 169504837f64SMarcel Holtmann struct hci_conn *conn; 169604837f64SMarcel Holtmann 16979f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1698a9de9248SMarcel Holtmann 1699a9de9248SMarcel Holtmann if (!status) 1700a9de9248SMarcel Holtmann return; 1701a9de9248SMarcel Holtmann 1702a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 170304837f64SMarcel Holtmann if (!cp) 1704a9de9248SMarcel Holtmann return; 170504837f64SMarcel Holtmann 170604837f64SMarcel Holtmann hci_dev_lock(hdev); 170704837f64SMarcel Holtmann 170804837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1709e73439d8SMarcel Holtmann if (conn) { 171051a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 171104837f64SMarcel Holtmann 171251a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1713e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1714e73439d8SMarcel Holtmann } 1715e73439d8SMarcel Holtmann 171604837f64SMarcel Holtmann hci_dev_unlock(hdev); 171704837f64SMarcel Holtmann } 171804837f64SMarcel Holtmann 1719a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 1720a9de9248SMarcel Holtmann { 1721a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 172204837f64SMarcel Holtmann struct hci_conn *conn; 172304837f64SMarcel Holtmann 17249f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1725a9de9248SMarcel Holtmann 1726a9de9248SMarcel Holtmann if (!status) 1727a9de9248SMarcel Holtmann return; 1728a9de9248SMarcel Holtmann 1729a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 173004837f64SMarcel Holtmann if (!cp) 1731a9de9248SMarcel Holtmann return; 173204837f64SMarcel Holtmann 173304837f64SMarcel Holtmann hci_dev_lock(hdev); 173404837f64SMarcel Holtmann 173504837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1736e73439d8SMarcel Holtmann if (conn) { 173751a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 173804837f64SMarcel Holtmann 173951a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1740e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1741e73439d8SMarcel Holtmann } 1742e73439d8SMarcel Holtmann 174304837f64SMarcel Holtmann hci_dev_unlock(hdev); 174404837f64SMarcel Holtmann } 174504837f64SMarcel Holtmann 174688c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) 174788c3df13SJohan Hedberg { 174888c3df13SJohan Hedberg struct hci_cp_disconnect *cp; 174988c3df13SJohan Hedberg struct hci_conn *conn; 175088c3df13SJohan Hedberg 175188c3df13SJohan Hedberg if (!status) 175288c3df13SJohan Hedberg return; 175388c3df13SJohan Hedberg 175488c3df13SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT); 175588c3df13SJohan Hedberg if (!cp) 175688c3df13SJohan Hedberg return; 175788c3df13SJohan Hedberg 175888c3df13SJohan Hedberg hci_dev_lock(hdev); 175988c3df13SJohan Hedberg 176088c3df13SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 176188c3df13SJohan Hedberg if (conn) 176288c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 176388c3df13SJohan Hedberg conn->dst_type, status); 176488c3df13SJohan Hedberg 176588c3df13SJohan Hedberg hci_dev_unlock(hdev); 176688c3df13SJohan Hedberg } 176788c3df13SJohan Hedberg 1768fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) 1769fcd89c09SVille Tervo { 1770fcd89c09SVille Tervo struct hci_conn *conn; 1771fcd89c09SVille Tervo 17729f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1773fcd89c09SVille Tervo 1774f00a06acSAndre Guedes if (status) { 1775fcd89c09SVille Tervo hci_dev_lock(hdev); 1776fcd89c09SVille Tervo 17770c95ab78SAndre Guedes conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); 1778f00a06acSAndre Guedes if (!conn) { 1779f00a06acSAndre Guedes hci_dev_unlock(hdev); 1780f00a06acSAndre Guedes return; 1781f00a06acSAndre Guedes } 1782fcd89c09SVille Tervo 17836ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn); 1784fcd89c09SVille Tervo 1785fcd89c09SVille Tervo conn->state = BT_CLOSED; 17860c95ab78SAndre Guedes mgmt_connect_failed(hdev, &conn->dst, conn->type, 1787328c9248SHemant Gupta conn->dst_type, status); 1788fcd89c09SVille Tervo hci_proto_connect_cfm(conn, status); 1789fcd89c09SVille Tervo hci_conn_del(conn); 1790fcd89c09SVille Tervo 1791fcd89c09SVille Tervo hci_dev_unlock(hdev); 1792fcd89c09SVille Tervo } 1793f00a06acSAndre Guedes } 1794fcd89c09SVille Tervo 1795a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) 1796a7a595f6SVinicius Costa Gomes { 17979f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1798a7a595f6SVinicius Costa Gomes } 1799a7a595f6SVinicius Costa Gomes 1800a02226d6SAndrei Emeltchenko static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status) 1801a02226d6SAndrei Emeltchenko { 180293c284eeSAndrei Emeltchenko struct hci_cp_create_phy_link *cp; 180393c284eeSAndrei Emeltchenko 1804a02226d6SAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 180593c284eeSAndrei Emeltchenko 180693c284eeSAndrei Emeltchenko if (status) 180793c284eeSAndrei Emeltchenko return; 180893c284eeSAndrei Emeltchenko 180993c284eeSAndrei Emeltchenko cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK); 181093c284eeSAndrei Emeltchenko if (!cp) 181193c284eeSAndrei Emeltchenko return; 181293c284eeSAndrei Emeltchenko 181393c284eeSAndrei Emeltchenko amp_write_remote_assoc(hdev, cp->phy_handle); 1814a02226d6SAndrei Emeltchenko } 1815a02226d6SAndrei Emeltchenko 18160b26ab9dSAndrei Emeltchenko static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status) 18170b26ab9dSAndrei Emeltchenko { 18180b26ab9dSAndrei Emeltchenko struct hci_cp_accept_phy_link *cp; 18190b26ab9dSAndrei Emeltchenko 18200b26ab9dSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 18210b26ab9dSAndrei Emeltchenko 18220b26ab9dSAndrei Emeltchenko if (status) 18230b26ab9dSAndrei Emeltchenko return; 18240b26ab9dSAndrei Emeltchenko 18250b26ab9dSAndrei Emeltchenko cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK); 18260b26ab9dSAndrei Emeltchenko if (!cp) 18270b26ab9dSAndrei Emeltchenko return; 18280b26ab9dSAndrei Emeltchenko 18290b26ab9dSAndrei Emeltchenko amp_write_remote_assoc(hdev, cp->phy_handle); 18300b26ab9dSAndrei Emeltchenko } 18310b26ab9dSAndrei Emeltchenko 18326039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 18331da177e4SLinus Torvalds { 18341da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 183530dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 183630dc78e1SJohan Hedberg struct inquiry_entry *e; 18371da177e4SLinus Torvalds 18389f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 18391da177e4SLinus Torvalds 184023bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 18416bd57416SMarcel Holtmann 1842a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 184389352e7dSAndre Guedes 184489352e7dSAndre Guedes if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) 184589352e7dSAndre Guedes return; 184689352e7dSAndre Guedes 1847a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 184830dc78e1SJohan Hedberg return; 184930dc78e1SJohan Hedberg 185056e5cb86SJohan Hedberg hci_dev_lock(hdev); 185130dc78e1SJohan Hedberg 1852343f935bSAndre Guedes if (discov->state != DISCOVERY_FINDING) 185330dc78e1SJohan Hedberg goto unlock; 185430dc78e1SJohan Hedberg 185530dc78e1SJohan Hedberg if (list_empty(&discov->resolve)) { 1856ff9ef578SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 185730dc78e1SJohan Hedberg goto unlock; 185830dc78e1SJohan Hedberg } 185930dc78e1SJohan Hedberg 186030dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 186130dc78e1SJohan Hedberg if (e && hci_resolve_name(hdev, e) == 0) { 186230dc78e1SJohan Hedberg e->name_state = NAME_PENDING; 186330dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_RESOLVING); 186430dc78e1SJohan Hedberg } else { 186530dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 186630dc78e1SJohan Hedberg } 186730dc78e1SJohan Hedberg 186830dc78e1SJohan Hedberg unlock: 186956e5cb86SJohan Hedberg hci_dev_unlock(hdev); 18701da177e4SLinus Torvalds } 18711da177e4SLinus Torvalds 18726039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 18731da177e4SLinus Torvalds { 187445bb4bf0SMarcel Holtmann struct inquiry_data data; 1875a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 18761da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 18771da177e4SLinus Torvalds 18781da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 18791da177e4SLinus Torvalds 188045bb4bf0SMarcel Holtmann if (!num_rsp) 188145bb4bf0SMarcel Holtmann return; 188245bb4bf0SMarcel Holtmann 18831519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 18841519cc17SAndre Guedes return; 18851519cc17SAndre Guedes 18861da177e4SLinus Torvalds hci_dev_lock(hdev); 188745bb4bf0SMarcel Holtmann 1888e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 1889388fc8faSJohan Hedberg bool name_known, ssp; 18903175405bSJohan Hedberg 18911da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 18921da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 18931da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 18941da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 18951da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 18961da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 18971da177e4SLinus Torvalds data.rssi = 0x00; 189841a96212SMarcel Holtmann data.ssp_mode = 0x00; 18993175405bSJohan Hedberg 1900388fc8faSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp); 190148264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 190204124681SGustavo F. Padovan info->dev_class, 0, !name_known, ssp, NULL, 190304124681SGustavo F. Padovan 0); 19041da177e4SLinus Torvalds } 190545bb4bf0SMarcel Holtmann 19061da177e4SLinus Torvalds hci_dev_unlock(hdev); 19071da177e4SLinus Torvalds } 19081da177e4SLinus Torvalds 19096039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 19101da177e4SLinus Torvalds { 1911a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 1912a9de9248SMarcel Holtmann struct hci_conn *conn; 19131da177e4SLinus Torvalds 1914a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 191545bb4bf0SMarcel Holtmann 19161da177e4SLinus Torvalds hci_dev_lock(hdev); 191745bb4bf0SMarcel Holtmann 1918a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 19199499237aSMarcel Holtmann if (!conn) { 19209499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 19219499237aSMarcel Holtmann goto unlock; 19229499237aSMarcel Holtmann 19239499237aSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 1924a9de9248SMarcel Holtmann if (!conn) 1925a9de9248SMarcel Holtmann goto unlock; 192645bb4bf0SMarcel Holtmann 19279499237aSMarcel Holtmann conn->type = SCO_LINK; 19289499237aSMarcel Holtmann } 19299499237aSMarcel Holtmann 1930a9de9248SMarcel Holtmann if (!ev->status) { 1931a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 1932769be974SMarcel Holtmann 1933769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 1934769be974SMarcel Holtmann conn->state = BT_CONFIG; 1935769be974SMarcel Holtmann hci_conn_hold(conn); 1936a9ea3ed9SSzymon Janc 1937a9ea3ed9SSzymon Janc if (!conn->out && !hci_conn_ssp_enabled(conn) && 1938a9ea3ed9SSzymon Janc !hci_find_link_key(hdev, &ev->bdaddr)) 1939a9ea3ed9SSzymon Janc conn->disc_timeout = HCI_PAIRING_TIMEOUT; 1940a9ea3ed9SSzymon Janc else 1941052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1942769be974SMarcel Holtmann } else 1943a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 1944a9de9248SMarcel Holtmann 19459eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 19467d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 19477d0db0a3SMarcel Holtmann 1948a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 1949a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1950a9de9248SMarcel Holtmann 1951a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 1952a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1953a9de9248SMarcel Holtmann 1954a9de9248SMarcel Holtmann /* Get remote features */ 1955a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 1956a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 1957a9de9248SMarcel Holtmann cp.handle = ev->handle; 1958769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 1959769be974SMarcel Holtmann sizeof(cp), &cp); 196045bb4bf0SMarcel Holtmann } 1961a9de9248SMarcel Holtmann 1962a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 1963d095c1ebSAndrei Emeltchenko if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) { 1964a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 1965a9de9248SMarcel Holtmann cp.handle = ev->handle; 1966a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 196704124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp), 196804124681SGustavo F. Padovan &cp); 1969a9de9248SMarcel Holtmann } 197017d5c04cSJohan Hedberg } else { 1971a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 197217d5c04cSJohan Hedberg if (conn->type == ACL_LINK) 1973744cf19eSJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 197448264f06SJohan Hedberg conn->dst_type, ev->status); 197517d5c04cSJohan Hedberg } 197645bb4bf0SMarcel Holtmann 1977e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 1978e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 197945bb4bf0SMarcel Holtmann 1980769be974SMarcel Holtmann if (ev->status) { 1981a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1982a9de9248SMarcel Holtmann hci_conn_del(conn); 1983c89b6e6bSMarcel Holtmann } else if (ev->link_type != ACL_LINK) 1984c89b6e6bSMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1985a9de9248SMarcel Holtmann 1986a9de9248SMarcel Holtmann unlock: 19871da177e4SLinus Torvalds hci_dev_unlock(hdev); 1988a9de9248SMarcel Holtmann 1989a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 19901da177e4SLinus Torvalds } 19911da177e4SLinus Torvalds 19926039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 19931da177e4SLinus Torvalds { 1994a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 19951da177e4SLinus Torvalds int mask = hdev->link_mode; 19961da177e4SLinus Torvalds 19976ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr, 1998807deac2SGustavo Padovan ev->link_type); 19991da177e4SLinus Torvalds 20001da177e4SLinus Torvalds mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); 20011da177e4SLinus Torvalds 2002138d22efSSzymon Janc if ((mask & HCI_LM_ACCEPT) && 2003138d22efSSzymon Janc !hci_blacklist_lookup(hdev, &ev->bdaddr)) { 20041da177e4SLinus Torvalds /* Connection accepted */ 2005c7bdd502SMarcel Holtmann struct inquiry_entry *ie; 20061da177e4SLinus Torvalds struct hci_conn *conn; 20071da177e4SLinus Torvalds 20081da177e4SLinus Torvalds hci_dev_lock(hdev); 2009b6a0dc82SMarcel Holtmann 2010cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2011cc11b9c1SAndrei Emeltchenko if (ie) 2012c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 2013c7bdd502SMarcel Holtmann 20148fc9ced3SGustavo Padovan conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, 20158fc9ced3SGustavo Padovan &ev->bdaddr); 20161da177e4SLinus Torvalds if (!conn) { 2017cc11b9c1SAndrei Emeltchenko conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); 2018cc11b9c1SAndrei Emeltchenko if (!conn) { 2019893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 20201da177e4SLinus Torvalds hci_dev_unlock(hdev); 20211da177e4SLinus Torvalds return; 20221da177e4SLinus Torvalds } 20231da177e4SLinus Torvalds } 2024b6a0dc82SMarcel Holtmann 20251da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 20261da177e4SLinus Torvalds conn->state = BT_CONNECT; 2027b6a0dc82SMarcel Holtmann 20281da177e4SLinus Torvalds hci_dev_unlock(hdev); 20291da177e4SLinus Torvalds 2030b6a0dc82SMarcel Holtmann if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) { 2031b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 2032b6a0dc82SMarcel Holtmann 20331da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 20341da177e4SLinus Torvalds 20351da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 20361da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 20371da177e4SLinus Torvalds else 20381da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 20391da177e4SLinus Torvalds 204004124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), 204104124681SGustavo F. Padovan &cp); 2042b6a0dc82SMarcel Holtmann } else { 2043b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 2044b6a0dc82SMarcel Holtmann 2045b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 2046a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 2047b6a0dc82SMarcel Holtmann 204882781e63SAndrei Emeltchenko cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40); 204982781e63SAndrei Emeltchenko cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40); 205082781e63SAndrei Emeltchenko cp.max_latency = __constant_cpu_to_le16(0xffff); 2051b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 2052b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 2053b6a0dc82SMarcel Holtmann 2054b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 2055b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 2056b6a0dc82SMarcel Holtmann } 20571da177e4SLinus Torvalds } else { 20581da177e4SLinus Torvalds /* Connection rejected */ 20591da177e4SLinus Torvalds struct hci_cp_reject_conn_req cp; 20601da177e4SLinus Torvalds 20611da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 20629f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_REJ_BAD_ADDR; 2063a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 20641da177e4SLinus Torvalds } 20651da177e4SLinus Torvalds } 20661da177e4SLinus Torvalds 2067f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err) 2068f0d6a0eaSMikel Astiz { 2069f0d6a0eaSMikel Astiz switch (err) { 2070f0d6a0eaSMikel Astiz case HCI_ERROR_CONNECTION_TIMEOUT: 2071f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_TIMEOUT; 2072f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_USER_TERM: 2073f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_LOW_RESOURCES: 2074f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_POWER_OFF: 2075f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_REMOTE; 2076f0d6a0eaSMikel Astiz case HCI_ERROR_LOCAL_HOST_TERM: 2077f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_LOCAL_HOST; 2078f0d6a0eaSMikel Astiz default: 2079f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_UNKNOWN; 2080f0d6a0eaSMikel Astiz } 2081f0d6a0eaSMikel Astiz } 2082f0d6a0eaSMikel Astiz 20836039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 20841da177e4SLinus Torvalds { 2085a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 208604837f64SMarcel Holtmann struct hci_conn *conn; 20871da177e4SLinus Torvalds 20889f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 20891da177e4SLinus Torvalds 20901da177e4SLinus Torvalds hci_dev_lock(hdev); 20911da177e4SLinus Torvalds 209204837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2093f7520543SJohan Hedberg if (!conn) 2094f7520543SJohan Hedberg goto unlock; 2095f7520543SJohan Hedberg 209637d9ef76SJohan Hedberg if (ev->status == 0) 20971da177e4SLinus Torvalds conn->state = BT_CLOSED; 20987d0db0a3SMarcel Holtmann 2099b644ba33SJohan Hedberg if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) && 2100b644ba33SJohan Hedberg (conn->type == ACL_LINK || conn->type == LE_LINK)) { 2101f0d6a0eaSMikel Astiz if (ev->status) { 210288c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 210388c3df13SJohan Hedberg conn->dst_type, ev->status); 2104f0d6a0eaSMikel Astiz } else { 2105f0d6a0eaSMikel Astiz u8 reason = hci_to_mgmt_reason(ev->reason); 2106f0d6a0eaSMikel Astiz 2107afc747a6SJohan Hedberg mgmt_device_disconnected(hdev, &conn->dst, conn->type, 2108f0d6a0eaSMikel Astiz conn->dst_type, reason); 2109f0d6a0eaSMikel Astiz } 211037d9ef76SJohan Hedberg } 2111f7520543SJohan Hedberg 211237d9ef76SJohan Hedberg if (ev->status == 0) { 21136ec5bcadSVishal Agarwal if (conn->type == ACL_LINK && conn->flush_key) 21146ec5bcadSVishal Agarwal hci_remove_link_key(hdev, &conn->dst); 21152950f21aSMarcel Holtmann hci_proto_disconn_cfm(conn, ev->reason); 21161da177e4SLinus Torvalds hci_conn_del(conn); 211737d9ef76SJohan Hedberg } 21181da177e4SLinus Torvalds 2119f7520543SJohan Hedberg unlock: 21201da177e4SLinus Torvalds hci_dev_unlock(hdev); 21211da177e4SLinus Torvalds } 21221da177e4SLinus Torvalds 21236039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2124a9de9248SMarcel Holtmann { 2125a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 2126a9de9248SMarcel Holtmann struct hci_conn *conn; 2127a9de9248SMarcel Holtmann 21289f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2129a9de9248SMarcel Holtmann 2130a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2131a9de9248SMarcel Holtmann 2132a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2133d7556e20SWaldemar Rymarkiewicz if (!conn) 2134d7556e20SWaldemar Rymarkiewicz goto unlock; 2135d7556e20SWaldemar Rymarkiewicz 2136765c2a96SJohan Hedberg if (!ev->status) { 2137aa64a8b5SJohan Hedberg if (!hci_conn_ssp_enabled(conn) && 213851a8efd7SJohan Hedberg test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) { 2139d7556e20SWaldemar Rymarkiewicz BT_INFO("re-auth of legacy device is not possible."); 214019f8def0SWaldemar Rymarkiewicz } else { 2141a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 2142765c2a96SJohan Hedberg conn->sec_level = conn->pending_sec_level; 214319f8def0SWaldemar Rymarkiewicz } 21442a611692SJohan Hedberg } else { 2145bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 2146bab73cb6SJohan Hedberg ev->status); 21472a611692SJohan Hedberg } 2148a9de9248SMarcel Holtmann 214951a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 215051a8efd7SJohan Hedberg clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags); 2151a9de9248SMarcel Holtmann 2152f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 2153aa64a8b5SJohan Hedberg if (!ev->status && hci_conn_ssp_enabled(conn)) { 2154f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 2155f8558555SMarcel Holtmann cp.handle = ev->handle; 2156f8558555SMarcel Holtmann cp.encrypt = 0x01; 2157d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 2158d7556e20SWaldemar Rymarkiewicz &cp); 2159f8558555SMarcel Holtmann } else { 2160f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 2161f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2162f8558555SMarcel Holtmann hci_conn_put(conn); 2163f8558555SMarcel Holtmann } 2164052b30b0SMarcel Holtmann } else { 2165a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 2166a9de9248SMarcel Holtmann 2167052b30b0SMarcel Holtmann hci_conn_hold(conn); 2168052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2169052b30b0SMarcel Holtmann hci_conn_put(conn); 2170052b30b0SMarcel Holtmann } 2171052b30b0SMarcel Holtmann 217251a8efd7SJohan Hedberg if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) { 2173a9de9248SMarcel Holtmann if (!ev->status) { 2174a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 2175f8558555SMarcel Holtmann cp.handle = ev->handle; 2176f8558555SMarcel Holtmann cp.encrypt = 0x01; 2177d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 2178d7556e20SWaldemar Rymarkiewicz &cp); 2179a9de9248SMarcel Holtmann } else { 218051a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 2181a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 2182a9de9248SMarcel Holtmann } 2183a9de9248SMarcel Holtmann } 2184a9de9248SMarcel Holtmann 2185d7556e20SWaldemar Rymarkiewicz unlock: 2186a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2187a9de9248SMarcel Holtmann } 2188a9de9248SMarcel Holtmann 21896039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 2190a9de9248SMarcel Holtmann { 2191127178d2SJohan Hedberg struct hci_ev_remote_name *ev = (void *) skb->data; 2192127178d2SJohan Hedberg struct hci_conn *conn; 2193127178d2SJohan Hedberg 2194a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2195a9de9248SMarcel Holtmann 2196a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 2197127178d2SJohan Hedberg 2198127178d2SJohan Hedberg hci_dev_lock(hdev); 2199127178d2SJohan Hedberg 2200127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2201b644ba33SJohan Hedberg 2202b644ba33SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 2203b644ba33SJohan Hedberg goto check_auth; 2204b644ba33SJohan Hedberg 2205b644ba33SJohan Hedberg if (ev->status == 0) 2206b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name, 2207b644ba33SJohan Hedberg strnlen(ev->name, HCI_MAX_NAME_LENGTH)); 2208b644ba33SJohan Hedberg else 2209b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0); 2210b644ba33SJohan Hedberg 2211b644ba33SJohan Hedberg check_auth: 221279c6c70cSJohan Hedberg if (!conn) 221379c6c70cSJohan Hedberg goto unlock; 221479c6c70cSJohan Hedberg 221579c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 221679c6c70cSJohan Hedberg goto unlock; 221779c6c70cSJohan Hedberg 221851a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 2219127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 2220127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 2221127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 2222127178d2SJohan Hedberg } 2223127178d2SJohan Hedberg 222479c6c70cSJohan Hedberg unlock: 2225127178d2SJohan Hedberg hci_dev_unlock(hdev); 2226a9de9248SMarcel Holtmann } 2227a9de9248SMarcel Holtmann 22286039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2229a9de9248SMarcel Holtmann { 2230a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 2231a9de9248SMarcel Holtmann struct hci_conn *conn; 2232a9de9248SMarcel Holtmann 22339f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2234a9de9248SMarcel Holtmann 2235a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2236a9de9248SMarcel Holtmann 2237a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2238a9de9248SMarcel Holtmann if (conn) { 2239a9de9248SMarcel Holtmann if (!ev->status) { 2240ae293196SMarcel Holtmann if (ev->encrypt) { 2241ae293196SMarcel Holtmann /* Encryption implies authentication */ 2242ae293196SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 2243a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 2244da85e5e5SVinicius Costa Gomes conn->sec_level = conn->pending_sec_level; 2245ae293196SMarcel Holtmann } else 2246a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_ENCRYPT; 2247a9de9248SMarcel Holtmann } 2248a9de9248SMarcel Holtmann 224951a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 2250a9de9248SMarcel Holtmann 2251a7d7723aSGustavo Padovan if (ev->status && conn->state == BT_CONNECTED) { 2252d839c813SGustavo Padovan hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE); 2253a7d7723aSGustavo Padovan hci_conn_put(conn); 2254a7d7723aSGustavo Padovan goto unlock; 2255a7d7723aSGustavo Padovan } 2256a7d7723aSGustavo Padovan 2257f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 2258f8558555SMarcel Holtmann if (!ev->status) 2259f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 2260f8558555SMarcel Holtmann 2261f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2262f8558555SMarcel Holtmann hci_conn_put(conn); 2263f8558555SMarcel Holtmann } else 2264a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 2265a9de9248SMarcel Holtmann } 2266a9de9248SMarcel Holtmann 2267a7d7723aSGustavo Padovan unlock: 2268a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2269a9de9248SMarcel Holtmann } 2270a9de9248SMarcel Holtmann 22716039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev, 2272807deac2SGustavo Padovan struct sk_buff *skb) 2273a9de9248SMarcel Holtmann { 2274a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 2275a9de9248SMarcel Holtmann struct hci_conn *conn; 2276a9de9248SMarcel Holtmann 22779f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2278a9de9248SMarcel Holtmann 2279a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2280a9de9248SMarcel Holtmann 2281a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2282a9de9248SMarcel Holtmann if (conn) { 2283a9de9248SMarcel Holtmann if (!ev->status) 2284a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_SECURE; 2285a9de9248SMarcel Holtmann 228651a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 2287a9de9248SMarcel Holtmann 2288a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 2289a9de9248SMarcel Holtmann } 2290a9de9248SMarcel Holtmann 2291a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2292a9de9248SMarcel Holtmann } 2293a9de9248SMarcel Holtmann 22946039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev, 2295807deac2SGustavo Padovan struct sk_buff *skb) 2296a9de9248SMarcel Holtmann { 2297a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 2298a9de9248SMarcel Holtmann struct hci_conn *conn; 2299a9de9248SMarcel Holtmann 23009f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2301a9de9248SMarcel Holtmann 2302a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2303a9de9248SMarcel Holtmann 2304a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2305ccd556feSJohan Hedberg if (!conn) 2306ccd556feSJohan Hedberg goto unlock; 2307ccd556feSJohan Hedberg 2308769be974SMarcel Holtmann if (!ev->status) 2309a9de9248SMarcel Holtmann memcpy(conn->features, ev->features, 8); 2310a9de9248SMarcel Holtmann 2311ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2312ccd556feSJohan Hedberg goto unlock; 2313ccd556feSJohan Hedberg 2314ccd556feSJohan Hedberg if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { 2315769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 2316769be974SMarcel Holtmann cp.handle = ev->handle; 2317769be974SMarcel Holtmann cp.page = 0x01; 2318ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 2319769be974SMarcel Holtmann sizeof(cp), &cp); 2320392599b9SJohan Hedberg goto unlock; 2321392599b9SJohan Hedberg } 2322392599b9SJohan Hedberg 2323671267bfSJohan Hedberg if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { 2324127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2325127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2326127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2327127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2328127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2329b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 2330b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 233108c79b61SJohan Hedberg conn->dst_type, 0, NULL, 0, 2332b644ba33SJohan Hedberg conn->dev_class); 2333392599b9SJohan Hedberg 2334127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2335769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2336769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2337769be974SMarcel Holtmann hci_conn_put(conn); 2338769be974SMarcel Holtmann } 2339769be974SMarcel Holtmann 2340ccd556feSJohan Hedberg unlock: 2341a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2342a9de9248SMarcel Holtmann } 2343a9de9248SMarcel Holtmann 23446039aa73SGustavo Padovan static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) 23456039aa73SGustavo Padovan { 23466039aa73SGustavo Padovan BT_DBG("%s", hdev->name); 23476039aa73SGustavo Padovan } 23486039aa73SGustavo Padovan 23496039aa73SGustavo Padovan static void hci_qos_setup_complete_evt(struct hci_dev *hdev, 2350807deac2SGustavo Padovan struct sk_buff *skb) 2351a9de9248SMarcel Holtmann { 2352a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2353a9de9248SMarcel Holtmann } 2354a9de9248SMarcel Holtmann 23556039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2356a9de9248SMarcel Holtmann { 2357a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 2358a9de9248SMarcel Holtmann __u16 opcode; 2359a9de9248SMarcel Holtmann 2360a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2361a9de9248SMarcel Holtmann 2362a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2363a9de9248SMarcel Holtmann 2364a9de9248SMarcel Holtmann switch (opcode) { 2365a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 2366a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 2367a9de9248SMarcel Holtmann break; 2368a9de9248SMarcel Holtmann 23694d93483bSAndre Guedes case HCI_OP_PERIODIC_INQ: 23704d93483bSAndre Guedes hci_cc_periodic_inq(hdev, skb); 23714d93483bSAndre Guedes break; 23724d93483bSAndre Guedes 2373a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 2374a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 2375a9de9248SMarcel Holtmann break; 2376a9de9248SMarcel Holtmann 2377a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 2378a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 2379a9de9248SMarcel Holtmann break; 2380a9de9248SMarcel Holtmann 2381a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 2382a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 2383a9de9248SMarcel Holtmann break; 2384a9de9248SMarcel Holtmann 2385e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 2386e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 2387e4e8e37cSMarcel Holtmann break; 2388e4e8e37cSMarcel Holtmann 2389a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 2390a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 2391a9de9248SMarcel Holtmann break; 2392a9de9248SMarcel Holtmann 2393e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 2394e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 2395e4e8e37cSMarcel Holtmann break; 2396e4e8e37cSMarcel Holtmann 2397e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 2398e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 2399e4e8e37cSMarcel Holtmann break; 2400e4e8e37cSMarcel Holtmann 2401a9de9248SMarcel Holtmann case HCI_OP_RESET: 2402a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 2403a9de9248SMarcel Holtmann break; 2404a9de9248SMarcel Holtmann 2405a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 2406a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 2407a9de9248SMarcel Holtmann break; 2408a9de9248SMarcel Holtmann 2409a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 2410a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 2411a9de9248SMarcel Holtmann break; 2412a9de9248SMarcel Holtmann 2413a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 2414a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 2415a9de9248SMarcel Holtmann break; 2416a9de9248SMarcel Holtmann 2417a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 2418a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 2419a9de9248SMarcel Holtmann break; 2420a9de9248SMarcel Holtmann 2421a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 2422a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 2423a9de9248SMarcel Holtmann break; 2424a9de9248SMarcel Holtmann 2425a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 2426a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 2427a9de9248SMarcel Holtmann break; 2428a9de9248SMarcel Holtmann 2429a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 2430a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 2431a9de9248SMarcel Holtmann break; 2432a9de9248SMarcel Holtmann 2433a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 2434a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 2435a9de9248SMarcel Holtmann break; 2436a9de9248SMarcel Holtmann 2437a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 2438a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 2439a9de9248SMarcel Holtmann break; 2440a9de9248SMarcel Holtmann 2441a9de9248SMarcel Holtmann case HCI_OP_HOST_BUFFER_SIZE: 2442a9de9248SMarcel Holtmann hci_cc_host_buffer_size(hdev, skb); 2443a9de9248SMarcel Holtmann break; 2444a9de9248SMarcel Holtmann 2445333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 2446333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 2447333140b5SMarcel Holtmann break; 2448333140b5SMarcel Holtmann 2449a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 2450a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 2451a9de9248SMarcel Holtmann break; 2452a9de9248SMarcel Holtmann 2453a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 2454a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 2455a9de9248SMarcel Holtmann break; 2456a9de9248SMarcel Holtmann 2457a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 2458a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 2459a9de9248SMarcel Holtmann break; 2460a9de9248SMarcel Holtmann 2461971e3a4bSAndre Guedes case HCI_OP_READ_LOCAL_EXT_FEATURES: 2462971e3a4bSAndre Guedes hci_cc_read_local_ext_features(hdev, skb); 2463971e3a4bSAndre Guedes break; 2464971e3a4bSAndre Guedes 2465a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 2466a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 2467a9de9248SMarcel Holtmann break; 2468a9de9248SMarcel Holtmann 2469a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 2470a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 2471a9de9248SMarcel Holtmann break; 2472a9de9248SMarcel Holtmann 2473350ee4cfSAndrei Emeltchenko case HCI_OP_READ_DATA_BLOCK_SIZE: 2474350ee4cfSAndrei Emeltchenko hci_cc_read_data_block_size(hdev, skb); 2475350ee4cfSAndrei Emeltchenko break; 2476350ee4cfSAndrei Emeltchenko 247723bb5763SJohan Hedberg case HCI_OP_WRITE_CA_TIMEOUT: 247823bb5763SJohan Hedberg hci_cc_write_ca_timeout(hdev, skb); 247923bb5763SJohan Hedberg break; 248023bb5763SJohan Hedberg 24811e89cffbSAndrei Emeltchenko case HCI_OP_READ_FLOW_CONTROL_MODE: 24821e89cffbSAndrei Emeltchenko hci_cc_read_flow_control_mode(hdev, skb); 24831e89cffbSAndrei Emeltchenko break; 24841e89cffbSAndrei Emeltchenko 2485928abaa7SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_INFO: 2486928abaa7SAndrei Emeltchenko hci_cc_read_local_amp_info(hdev, skb); 2487928abaa7SAndrei Emeltchenko break; 2488928abaa7SAndrei Emeltchenko 2489903e4541SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_ASSOC: 2490903e4541SAndrei Emeltchenko hci_cc_read_local_amp_assoc(hdev, skb); 2491903e4541SAndrei Emeltchenko break; 2492903e4541SAndrei Emeltchenko 2493b0916ea0SJohan Hedberg case HCI_OP_DELETE_STORED_LINK_KEY: 2494b0916ea0SJohan Hedberg hci_cc_delete_stored_link_key(hdev, skb); 2495b0916ea0SJohan Hedberg break; 2496b0916ea0SJohan Hedberg 2497d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_MASK: 2498d5859e22SJohan Hedberg hci_cc_set_event_mask(hdev, skb); 2499d5859e22SJohan Hedberg break; 2500d5859e22SJohan Hedberg 2501d5859e22SJohan Hedberg case HCI_OP_WRITE_INQUIRY_MODE: 2502d5859e22SJohan Hedberg hci_cc_write_inquiry_mode(hdev, skb); 2503d5859e22SJohan Hedberg break; 2504d5859e22SJohan Hedberg 2505d5859e22SJohan Hedberg case HCI_OP_READ_INQ_RSP_TX_POWER: 2506d5859e22SJohan Hedberg hci_cc_read_inq_rsp_tx_power(hdev, skb); 2507d5859e22SJohan Hedberg break; 2508d5859e22SJohan Hedberg 2509d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_FLT: 2510d5859e22SJohan Hedberg hci_cc_set_event_flt(hdev, skb); 2511d5859e22SJohan Hedberg break; 2512d5859e22SJohan Hedberg 2513980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_REPLY: 2514980e1a53SJohan Hedberg hci_cc_pin_code_reply(hdev, skb); 2515980e1a53SJohan Hedberg break; 2516980e1a53SJohan Hedberg 2517980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_NEG_REPLY: 2518980e1a53SJohan Hedberg hci_cc_pin_code_neg_reply(hdev, skb); 2519980e1a53SJohan Hedberg break; 2520980e1a53SJohan Hedberg 2521c35938b2SSzymon Janc case HCI_OP_READ_LOCAL_OOB_DATA: 2522c35938b2SSzymon Janc hci_cc_read_local_oob_data_reply(hdev, skb); 2523c35938b2SSzymon Janc break; 2524c35938b2SSzymon Janc 25256ed58ec5SVille Tervo case HCI_OP_LE_READ_BUFFER_SIZE: 25266ed58ec5SVille Tervo hci_cc_le_read_buffer_size(hdev, skb); 25276ed58ec5SVille Tervo break; 25286ed58ec5SVille Tervo 25298fa19098SJohan Hedberg case HCI_OP_LE_READ_ADV_TX_POWER: 25308fa19098SJohan Hedberg hci_cc_le_read_adv_tx_power(hdev, skb); 25318fa19098SJohan Hedberg break; 25328fa19098SJohan Hedberg 2533e36b04c8SJohan Hedberg case HCI_OP_LE_SET_EVENT_MASK: 2534e36b04c8SJohan Hedberg hci_cc_le_set_event_mask(hdev, skb); 2535e36b04c8SJohan Hedberg break; 2536e36b04c8SJohan Hedberg 2537a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_REPLY: 2538a5c29683SJohan Hedberg hci_cc_user_confirm_reply(hdev, skb); 2539a5c29683SJohan Hedberg break; 2540a5c29683SJohan Hedberg 2541a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_NEG_REPLY: 2542a5c29683SJohan Hedberg hci_cc_user_confirm_neg_reply(hdev, skb); 2543a5c29683SJohan Hedberg break; 2544a5c29683SJohan Hedberg 25451143d458SBrian Gix case HCI_OP_USER_PASSKEY_REPLY: 25461143d458SBrian Gix hci_cc_user_passkey_reply(hdev, skb); 25471143d458SBrian Gix break; 25481143d458SBrian Gix 25491143d458SBrian Gix case HCI_OP_USER_PASSKEY_NEG_REPLY: 25501143d458SBrian Gix hci_cc_user_passkey_neg_reply(hdev, skb); 255116cde993SSzymon Janc break; 255207f7fa5dSAndre Guedes 255307f7fa5dSAndre Guedes case HCI_OP_LE_SET_SCAN_PARAM: 255407f7fa5dSAndre Guedes hci_cc_le_set_scan_param(hdev, skb); 25551143d458SBrian Gix break; 25561143d458SBrian Gix 2557eb9d91f5SAndre Guedes case HCI_OP_LE_SET_SCAN_ENABLE: 2558eb9d91f5SAndre Guedes hci_cc_le_set_scan_enable(hdev, skb); 2559eb9d91f5SAndre Guedes break; 2560eb9d91f5SAndre Guedes 2561a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_REPLY: 2562a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_reply(hdev, skb); 2563a7a595f6SVinicius Costa Gomes break; 2564a7a595f6SVinicius Costa Gomes 2565a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_NEG_REPLY: 2566a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_neg_reply(hdev, skb); 2567a7a595f6SVinicius Costa Gomes break; 2568a7a595f6SVinicius Costa Gomes 2569f9b49306SAndre Guedes case HCI_OP_WRITE_LE_HOST_SUPPORTED: 2570f9b49306SAndre Guedes hci_cc_write_le_host_supported(hdev, skb); 2571f9b49306SAndre Guedes break; 2572f9b49306SAndre Guedes 257393c284eeSAndrei Emeltchenko case HCI_OP_WRITE_REMOTE_AMP_ASSOC: 257493c284eeSAndrei Emeltchenko hci_cc_write_remote_amp_assoc(hdev, skb); 257593c284eeSAndrei Emeltchenko break; 257693c284eeSAndrei Emeltchenko 2577a9de9248SMarcel Holtmann default: 25789f1db00cSAndrei Emeltchenko BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); 2579a9de9248SMarcel Holtmann break; 2580a9de9248SMarcel Holtmann } 2581a9de9248SMarcel Holtmann 25826bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 25836bd32326SVille Tervo del_timer(&hdev->cmd_timer); 25846bd32326SVille Tervo 2585a9de9248SMarcel Holtmann if (ev->ncmd) { 2586a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2587a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2588c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2589a9de9248SMarcel Holtmann } 2590a9de9248SMarcel Holtmann } 2591a9de9248SMarcel Holtmann 25926039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 2593a9de9248SMarcel Holtmann { 2594a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 2595a9de9248SMarcel Holtmann __u16 opcode; 2596a9de9248SMarcel Holtmann 2597a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2598a9de9248SMarcel Holtmann 2599a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2600a9de9248SMarcel Holtmann 2601a9de9248SMarcel Holtmann switch (opcode) { 2602a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 2603a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 2604a9de9248SMarcel Holtmann break; 2605a9de9248SMarcel Holtmann 2606a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 2607a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 2608a9de9248SMarcel Holtmann break; 2609a9de9248SMarcel Holtmann 2610a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 2611a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 2612a9de9248SMarcel Holtmann break; 2613a9de9248SMarcel Holtmann 2614f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 2615f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 2616f8558555SMarcel Holtmann break; 2617f8558555SMarcel Holtmann 2618f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 2619f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 2620f8558555SMarcel Holtmann break; 2621f8558555SMarcel Holtmann 2622a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 2623a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 2624a9de9248SMarcel Holtmann break; 2625a9de9248SMarcel Holtmann 2626769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 2627769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 2628769be974SMarcel Holtmann break; 2629769be974SMarcel Holtmann 2630769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 2631769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 2632769be974SMarcel Holtmann break; 2633769be974SMarcel Holtmann 2634a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 2635a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 2636a9de9248SMarcel Holtmann break; 2637a9de9248SMarcel Holtmann 2638a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 2639a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 2640a9de9248SMarcel Holtmann break; 2641a9de9248SMarcel Holtmann 2642a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 2643a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 2644a9de9248SMarcel Holtmann break; 2645a9de9248SMarcel Holtmann 26468962ee74SJohan Hedberg case HCI_OP_DISCONNECT: 264788c3df13SJohan Hedberg hci_cs_disconnect(hdev, ev->status); 26488962ee74SJohan Hedberg break; 26498962ee74SJohan Hedberg 2650fcd89c09SVille Tervo case HCI_OP_LE_CREATE_CONN: 2651fcd89c09SVille Tervo hci_cs_le_create_conn(hdev, ev->status); 2652fcd89c09SVille Tervo break; 2653fcd89c09SVille Tervo 2654a7a595f6SVinicius Costa Gomes case HCI_OP_LE_START_ENC: 2655a7a595f6SVinicius Costa Gomes hci_cs_le_start_enc(hdev, ev->status); 2656a7a595f6SVinicius Costa Gomes break; 2657a7a595f6SVinicius Costa Gomes 2658a02226d6SAndrei Emeltchenko case HCI_OP_CREATE_PHY_LINK: 2659a02226d6SAndrei Emeltchenko hci_cs_create_phylink(hdev, ev->status); 2660a02226d6SAndrei Emeltchenko break; 2661a02226d6SAndrei Emeltchenko 26620b26ab9dSAndrei Emeltchenko case HCI_OP_ACCEPT_PHY_LINK: 26630b26ab9dSAndrei Emeltchenko hci_cs_accept_phylink(hdev, ev->status); 26640b26ab9dSAndrei Emeltchenko break; 26650b26ab9dSAndrei Emeltchenko 2666a9de9248SMarcel Holtmann default: 26679f1db00cSAndrei Emeltchenko BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); 2668a9de9248SMarcel Holtmann break; 2669a9de9248SMarcel Holtmann } 2670a9de9248SMarcel Holtmann 26716bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 26726bd32326SVille Tervo del_timer(&hdev->cmd_timer); 26736bd32326SVille Tervo 267410572132SGustavo F. Padovan if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2675a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2676a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2677c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2678a9de9248SMarcel Holtmann } 2679a9de9248SMarcel Holtmann } 2680a9de9248SMarcel Holtmann 26816039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2682a9de9248SMarcel Holtmann { 2683a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 2684a9de9248SMarcel Holtmann struct hci_conn *conn; 2685a9de9248SMarcel Holtmann 26869f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2687a9de9248SMarcel Holtmann 2688a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2689a9de9248SMarcel Holtmann 2690a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2691a9de9248SMarcel Holtmann if (conn) { 2692a9de9248SMarcel Holtmann if (!ev->status) { 2693a9de9248SMarcel Holtmann if (ev->role) 2694a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_MASTER; 2695a9de9248SMarcel Holtmann else 2696a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_MASTER; 2697a9de9248SMarcel Holtmann } 2698a9de9248SMarcel Holtmann 269951a8efd7SJohan Hedberg clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); 2700a9de9248SMarcel Holtmann 2701a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 2702a9de9248SMarcel Holtmann } 2703a9de9248SMarcel Holtmann 2704a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2705a9de9248SMarcel Holtmann } 2706a9de9248SMarcel Holtmann 27076039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 27081da177e4SLinus Torvalds { 2709a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 27101da177e4SLinus Torvalds int i; 27111da177e4SLinus Torvalds 271232ac5b9bSAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) { 271332ac5b9bSAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 271432ac5b9bSAndrei Emeltchenko return; 271532ac5b9bSAndrei Emeltchenko } 271632ac5b9bSAndrei Emeltchenko 2717c5993de8SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 2718c5993de8SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_pkts_info)) { 27191da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 27201da177e4SLinus Torvalds return; 27211da177e4SLinus Torvalds } 27221da177e4SLinus Torvalds 2723c5993de8SAndrei Emeltchenko BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 2724c5993de8SAndrei Emeltchenko 2725613a1c0cSAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 2726613a1c0cSAndrei Emeltchenko struct hci_comp_pkts_info *info = &ev->handles[i]; 27271da177e4SLinus Torvalds struct hci_conn *conn; 27281da177e4SLinus Torvalds __u16 handle, count; 27291da177e4SLinus Torvalds 2730613a1c0cSAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 2731613a1c0cSAndrei Emeltchenko count = __le16_to_cpu(info->count); 27321da177e4SLinus Torvalds 27331da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 2734f4280918SAndrei Emeltchenko if (!conn) 2735f4280918SAndrei Emeltchenko continue; 2736f4280918SAndrei Emeltchenko 27371da177e4SLinus Torvalds conn->sent -= count; 27381da177e4SLinus Torvalds 2739f4280918SAndrei Emeltchenko switch (conn->type) { 2740f4280918SAndrei Emeltchenko case ACL_LINK: 274170f23020SAndrei Emeltchenko hdev->acl_cnt += count; 274270f23020SAndrei Emeltchenko if (hdev->acl_cnt > hdev->acl_pkts) 27431da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 2744f4280918SAndrei Emeltchenko break; 2745f4280918SAndrei Emeltchenko 2746f4280918SAndrei Emeltchenko case LE_LINK: 27476ed58ec5SVille Tervo if (hdev->le_pkts) { 27486ed58ec5SVille Tervo hdev->le_cnt += count; 27496ed58ec5SVille Tervo if (hdev->le_cnt > hdev->le_pkts) 27506ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 27516ed58ec5SVille Tervo } else { 27526ed58ec5SVille Tervo hdev->acl_cnt += count; 27536ed58ec5SVille Tervo if (hdev->acl_cnt > hdev->acl_pkts) 27546ed58ec5SVille Tervo hdev->acl_cnt = hdev->acl_pkts; 27556ed58ec5SVille Tervo } 2756f4280918SAndrei Emeltchenko break; 2757f4280918SAndrei Emeltchenko 2758f4280918SAndrei Emeltchenko case SCO_LINK: 275970f23020SAndrei Emeltchenko hdev->sco_cnt += count; 276070f23020SAndrei Emeltchenko if (hdev->sco_cnt > hdev->sco_pkts) 27615b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 2762f4280918SAndrei Emeltchenko break; 2763f4280918SAndrei Emeltchenko 2764f4280918SAndrei Emeltchenko default: 2765f4280918SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 2766f4280918SAndrei Emeltchenko break; 27671da177e4SLinus Torvalds } 27681da177e4SLinus Torvalds } 2769a9de9248SMarcel Holtmann 27703eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 27711da177e4SLinus Torvalds } 27721da177e4SLinus Torvalds 277376ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev, 277476ef7cf7SAndrei Emeltchenko __u16 handle) 277576ef7cf7SAndrei Emeltchenko { 277676ef7cf7SAndrei Emeltchenko struct hci_chan *chan; 277776ef7cf7SAndrei Emeltchenko 277876ef7cf7SAndrei Emeltchenko switch (hdev->dev_type) { 277976ef7cf7SAndrei Emeltchenko case HCI_BREDR: 278076ef7cf7SAndrei Emeltchenko return hci_conn_hash_lookup_handle(hdev, handle); 278176ef7cf7SAndrei Emeltchenko case HCI_AMP: 278276ef7cf7SAndrei Emeltchenko chan = hci_chan_lookup_handle(hdev, handle); 278376ef7cf7SAndrei Emeltchenko if (chan) 278476ef7cf7SAndrei Emeltchenko return chan->conn; 278576ef7cf7SAndrei Emeltchenko break; 278676ef7cf7SAndrei Emeltchenko default: 278776ef7cf7SAndrei Emeltchenko BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type); 278876ef7cf7SAndrei Emeltchenko break; 278976ef7cf7SAndrei Emeltchenko } 279076ef7cf7SAndrei Emeltchenko 279176ef7cf7SAndrei Emeltchenko return NULL; 279276ef7cf7SAndrei Emeltchenko } 279376ef7cf7SAndrei Emeltchenko 27946039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb) 279525e89e99SAndrei Emeltchenko { 279625e89e99SAndrei Emeltchenko struct hci_ev_num_comp_blocks *ev = (void *) skb->data; 279725e89e99SAndrei Emeltchenko int i; 279825e89e99SAndrei Emeltchenko 279925e89e99SAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) { 280025e89e99SAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 280125e89e99SAndrei Emeltchenko return; 280225e89e99SAndrei Emeltchenko } 280325e89e99SAndrei Emeltchenko 280425e89e99SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 280525e89e99SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_blocks_info)) { 280625e89e99SAndrei Emeltchenko BT_DBG("%s bad parameters", hdev->name); 280725e89e99SAndrei Emeltchenko return; 280825e89e99SAndrei Emeltchenko } 280925e89e99SAndrei Emeltchenko 281025e89e99SAndrei Emeltchenko BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks, 281125e89e99SAndrei Emeltchenko ev->num_hndl); 281225e89e99SAndrei Emeltchenko 281325e89e99SAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 281425e89e99SAndrei Emeltchenko struct hci_comp_blocks_info *info = &ev->handles[i]; 281576ef7cf7SAndrei Emeltchenko struct hci_conn *conn = NULL; 281625e89e99SAndrei Emeltchenko __u16 handle, block_count; 281725e89e99SAndrei Emeltchenko 281825e89e99SAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 281925e89e99SAndrei Emeltchenko block_count = __le16_to_cpu(info->blocks); 282025e89e99SAndrei Emeltchenko 282176ef7cf7SAndrei Emeltchenko conn = __hci_conn_lookup_handle(hdev, handle); 282225e89e99SAndrei Emeltchenko if (!conn) 282325e89e99SAndrei Emeltchenko continue; 282425e89e99SAndrei Emeltchenko 282525e89e99SAndrei Emeltchenko conn->sent -= block_count; 282625e89e99SAndrei Emeltchenko 282725e89e99SAndrei Emeltchenko switch (conn->type) { 282825e89e99SAndrei Emeltchenko case ACL_LINK: 2829bd1eb66bSAndrei Emeltchenko case AMP_LINK: 283025e89e99SAndrei Emeltchenko hdev->block_cnt += block_count; 283125e89e99SAndrei Emeltchenko if (hdev->block_cnt > hdev->num_blocks) 283225e89e99SAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 283325e89e99SAndrei Emeltchenko break; 283425e89e99SAndrei Emeltchenko 283525e89e99SAndrei Emeltchenko default: 283625e89e99SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 283725e89e99SAndrei Emeltchenko break; 283825e89e99SAndrei Emeltchenko } 283925e89e99SAndrei Emeltchenko } 284025e89e99SAndrei Emeltchenko 284125e89e99SAndrei Emeltchenko queue_work(hdev->workqueue, &hdev->tx_work); 284225e89e99SAndrei Emeltchenko } 284325e89e99SAndrei Emeltchenko 28446039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 28451da177e4SLinus Torvalds { 2846a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 284704837f64SMarcel Holtmann struct hci_conn *conn; 28481da177e4SLinus Torvalds 28499f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 28501da177e4SLinus Torvalds 28511da177e4SLinus Torvalds hci_dev_lock(hdev); 28521da177e4SLinus Torvalds 285304837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 285404837f64SMarcel Holtmann if (conn) { 285504837f64SMarcel Holtmann conn->mode = ev->mode; 285604837f64SMarcel Holtmann conn->interval = __le16_to_cpu(ev->interval); 285704837f64SMarcel Holtmann 28588fc9ced3SGustavo Padovan if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, 28598fc9ced3SGustavo Padovan &conn->flags)) { 286004837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 286158a681efSJohan Hedberg set_bit(HCI_CONN_POWER_SAVE, &conn->flags); 286204837f64SMarcel Holtmann else 286358a681efSJohan Hedberg clear_bit(HCI_CONN_POWER_SAVE, &conn->flags); 286404837f64SMarcel Holtmann } 2865e73439d8SMarcel Holtmann 286651a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 2867e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 286804837f64SMarcel Holtmann } 286904837f64SMarcel Holtmann 287004837f64SMarcel Holtmann hci_dev_unlock(hdev); 287104837f64SMarcel Holtmann } 287204837f64SMarcel Holtmann 28736039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 28741da177e4SLinus Torvalds { 2875052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 2876052b30b0SMarcel Holtmann struct hci_conn *conn; 2877052b30b0SMarcel Holtmann 2878a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2879052b30b0SMarcel Holtmann 2880052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2881052b30b0SMarcel Holtmann 2882052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2883b6f98044SWaldemar Rymarkiewicz if (!conn) 2884b6f98044SWaldemar Rymarkiewicz goto unlock; 2885b6f98044SWaldemar Rymarkiewicz 2886b6f98044SWaldemar Rymarkiewicz if (conn->state == BT_CONNECTED) { 2887052b30b0SMarcel Holtmann hci_conn_hold(conn); 2888052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 2889052b30b0SMarcel Holtmann hci_conn_put(conn); 2890052b30b0SMarcel Holtmann } 2891052b30b0SMarcel Holtmann 2892a8b2d5c2SJohan Hedberg if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags)) 289303b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 289403b555e1SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 2895a8b2d5c2SJohan Hedberg else if (test_bit(HCI_MGMT, &hdev->dev_flags)) { 2896a770bb5aSWaldemar Rymarkiewicz u8 secure; 2897a770bb5aSWaldemar Rymarkiewicz 2898a770bb5aSWaldemar Rymarkiewicz if (conn->pending_sec_level == BT_SECURITY_HIGH) 2899a770bb5aSWaldemar Rymarkiewicz secure = 1; 2900a770bb5aSWaldemar Rymarkiewicz else 2901a770bb5aSWaldemar Rymarkiewicz secure = 0; 2902a770bb5aSWaldemar Rymarkiewicz 2903744cf19eSJohan Hedberg mgmt_pin_code_request(hdev, &ev->bdaddr, secure); 2904a770bb5aSWaldemar Rymarkiewicz } 2905980e1a53SJohan Hedberg 2906b6f98044SWaldemar Rymarkiewicz unlock: 2907052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 29081da177e4SLinus Torvalds } 29091da177e4SLinus Torvalds 29106039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 29111da177e4SLinus Torvalds { 291255ed8ca1SJohan Hedberg struct hci_ev_link_key_req *ev = (void *) skb->data; 291355ed8ca1SJohan Hedberg struct hci_cp_link_key_reply cp; 291455ed8ca1SJohan Hedberg struct hci_conn *conn; 291555ed8ca1SJohan Hedberg struct link_key *key; 291655ed8ca1SJohan Hedberg 2917a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 291855ed8ca1SJohan Hedberg 2919a8b2d5c2SJohan Hedberg if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) 292055ed8ca1SJohan Hedberg return; 292155ed8ca1SJohan Hedberg 292255ed8ca1SJohan Hedberg hci_dev_lock(hdev); 292355ed8ca1SJohan Hedberg 292455ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, &ev->bdaddr); 292555ed8ca1SJohan Hedberg if (!key) { 29266ed93dc6SAndrei Emeltchenko BT_DBG("%s link key not found for %pMR", hdev->name, 29276ed93dc6SAndrei Emeltchenko &ev->bdaddr); 292855ed8ca1SJohan Hedberg goto not_found; 292955ed8ca1SJohan Hedberg } 293055ed8ca1SJohan Hedberg 29316ed93dc6SAndrei Emeltchenko BT_DBG("%s found key type %u for %pMR", hdev->name, key->type, 29326ed93dc6SAndrei Emeltchenko &ev->bdaddr); 293355ed8ca1SJohan Hedberg 2934a8b2d5c2SJohan Hedberg if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) && 2935b6020ba0SWaldemar Rymarkiewicz key->type == HCI_LK_DEBUG_COMBINATION) { 293655ed8ca1SJohan Hedberg BT_DBG("%s ignoring debug key", hdev->name); 293755ed8ca1SJohan Hedberg goto not_found; 293855ed8ca1SJohan Hedberg } 293955ed8ca1SJohan Hedberg 294055ed8ca1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 294160b83f57SWaldemar Rymarkiewicz if (conn) { 294260b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_UNAUTH_COMBINATION && 2943807deac2SGustavo Padovan conn->auth_type != 0xff && (conn->auth_type & 0x01)) { 294455ed8ca1SJohan Hedberg BT_DBG("%s ignoring unauthenticated key", hdev->name); 294555ed8ca1SJohan Hedberg goto not_found; 294655ed8ca1SJohan Hedberg } 294755ed8ca1SJohan Hedberg 294860b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && 294960b83f57SWaldemar Rymarkiewicz conn->pending_sec_level == BT_SECURITY_HIGH) { 29508fc9ced3SGustavo Padovan BT_DBG("%s ignoring key unauthenticated for high security", 29518fc9ced3SGustavo Padovan hdev->name); 295260b83f57SWaldemar Rymarkiewicz goto not_found; 295360b83f57SWaldemar Rymarkiewicz } 295460b83f57SWaldemar Rymarkiewicz 295560b83f57SWaldemar Rymarkiewicz conn->key_type = key->type; 295660b83f57SWaldemar Rymarkiewicz conn->pin_length = key->pin_len; 295760b83f57SWaldemar Rymarkiewicz } 295860b83f57SWaldemar Rymarkiewicz 295955ed8ca1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 29609b3b4460SAndrei Emeltchenko memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE); 296155ed8ca1SJohan Hedberg 296255ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 296355ed8ca1SJohan Hedberg 296455ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 296555ed8ca1SJohan Hedberg 296655ed8ca1SJohan Hedberg return; 296755ed8ca1SJohan Hedberg 296855ed8ca1SJohan Hedberg not_found: 296955ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 297055ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 29711da177e4SLinus Torvalds } 29721da177e4SLinus Torvalds 29736039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 29741da177e4SLinus Torvalds { 2975052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 2976052b30b0SMarcel Holtmann struct hci_conn *conn; 297755ed8ca1SJohan Hedberg u8 pin_len = 0; 2978052b30b0SMarcel Holtmann 2979a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2980052b30b0SMarcel Holtmann 2981052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2982052b30b0SMarcel Holtmann 2983052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2984052b30b0SMarcel Holtmann if (conn) { 2985052b30b0SMarcel Holtmann hci_conn_hold(conn); 2986052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2987980e1a53SJohan Hedberg pin_len = conn->pin_length; 298813d39315SWaldemar Rymarkiewicz 298913d39315SWaldemar Rymarkiewicz if (ev->key_type != HCI_LK_CHANGED_COMBINATION) 299013d39315SWaldemar Rymarkiewicz conn->key_type = ev->key_type; 299113d39315SWaldemar Rymarkiewicz 2992052b30b0SMarcel Holtmann hci_conn_put(conn); 2993052b30b0SMarcel Holtmann } 2994052b30b0SMarcel Holtmann 2995a8b2d5c2SJohan Hedberg if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) 2996d25e28abSJohan Hedberg hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, 299755ed8ca1SJohan Hedberg ev->key_type, pin_len); 299855ed8ca1SJohan Hedberg 2999052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 30001da177e4SLinus Torvalds } 30011da177e4SLinus Torvalds 30026039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 300304837f64SMarcel Holtmann { 3004a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 300504837f64SMarcel Holtmann struct hci_conn *conn; 300604837f64SMarcel Holtmann 30079f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 300804837f64SMarcel Holtmann 300904837f64SMarcel Holtmann hci_dev_lock(hdev); 301004837f64SMarcel Holtmann 301104837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 30121da177e4SLinus Torvalds if (conn && !ev->status) { 30131da177e4SLinus Torvalds struct inquiry_entry *ie; 30141da177e4SLinus Torvalds 3015cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 3016cc11b9c1SAndrei Emeltchenko if (ie) { 30171da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 30181da177e4SLinus Torvalds ie->timestamp = jiffies; 30191da177e4SLinus Torvalds } 30201da177e4SLinus Torvalds } 30211da177e4SLinus Torvalds 30221da177e4SLinus Torvalds hci_dev_unlock(hdev); 30231da177e4SLinus Torvalds } 30241da177e4SLinus Torvalds 30256039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 3026a8746417SMarcel Holtmann { 3027a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 3028a8746417SMarcel Holtmann struct hci_conn *conn; 3029a8746417SMarcel Holtmann 30309f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 3031a8746417SMarcel Holtmann 3032a8746417SMarcel Holtmann hci_dev_lock(hdev); 3033a8746417SMarcel Holtmann 3034a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3035a8746417SMarcel Holtmann if (conn && !ev->status) 3036a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 3037a8746417SMarcel Holtmann 3038a8746417SMarcel Holtmann hci_dev_unlock(hdev); 3039a8746417SMarcel Holtmann } 3040a8746417SMarcel Holtmann 30416039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 304285a1e930SMarcel Holtmann { 3043a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 304485a1e930SMarcel Holtmann struct inquiry_entry *ie; 304585a1e930SMarcel Holtmann 304685a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 304785a1e930SMarcel Holtmann 304885a1e930SMarcel Holtmann hci_dev_lock(hdev); 304985a1e930SMarcel Holtmann 3050cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 3051cc11b9c1SAndrei Emeltchenko if (ie) { 305285a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 305385a1e930SMarcel Holtmann ie->timestamp = jiffies; 305485a1e930SMarcel Holtmann } 305585a1e930SMarcel Holtmann 305685a1e930SMarcel Holtmann hci_dev_unlock(hdev); 305785a1e930SMarcel Holtmann } 305885a1e930SMarcel Holtmann 30596039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, 3060807deac2SGustavo Padovan struct sk_buff *skb) 3061a9de9248SMarcel Holtmann { 3062a9de9248SMarcel Holtmann struct inquiry_data data; 3063a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 3064388fc8faSJohan Hedberg bool name_known, ssp; 3065a9de9248SMarcel Holtmann 3066a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 3067a9de9248SMarcel Holtmann 3068a9de9248SMarcel Holtmann if (!num_rsp) 3069a9de9248SMarcel Holtmann return; 3070a9de9248SMarcel Holtmann 30711519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 30721519cc17SAndre Guedes return; 30731519cc17SAndre Guedes 3074a9de9248SMarcel Holtmann hci_dev_lock(hdev); 3075a9de9248SMarcel Holtmann 3076a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 3077138d22efSSzymon Janc struct inquiry_info_with_rssi_and_pscan_mode *info; 3078138d22efSSzymon Janc info = (void *) (skb->data + 1); 3079a9de9248SMarcel Holtmann 3080e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 3081a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 3082a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 3083a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 3084a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 3085a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 3086a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 3087a9de9248SMarcel Holtmann data.rssi = info->rssi; 308841a96212SMarcel Holtmann data.ssp_mode = 0x00; 30893175405bSJohan Hedberg 30903175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 3091388fc8faSJohan Hedberg false, &ssp); 309248264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 3093e17acd40SJohan Hedberg info->dev_class, info->rssi, 3094388fc8faSJohan Hedberg !name_known, ssp, NULL, 0); 3095a9de9248SMarcel Holtmann } 3096a9de9248SMarcel Holtmann } else { 3097a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 3098a9de9248SMarcel Holtmann 3099e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 3100a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 3101a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 3102a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 3103a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 3104a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 3105a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 3106a9de9248SMarcel Holtmann data.rssi = info->rssi; 310741a96212SMarcel Holtmann data.ssp_mode = 0x00; 31083175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 3109388fc8faSJohan Hedberg false, &ssp); 311048264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 3111e17acd40SJohan Hedberg info->dev_class, info->rssi, 3112388fc8faSJohan Hedberg !name_known, ssp, NULL, 0); 3113a9de9248SMarcel Holtmann } 3114a9de9248SMarcel Holtmann } 3115a9de9248SMarcel Holtmann 3116a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 3117a9de9248SMarcel Holtmann } 3118a9de9248SMarcel Holtmann 31196039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev, 3120807deac2SGustavo Padovan struct sk_buff *skb) 3121a9de9248SMarcel Holtmann { 312241a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 312341a96212SMarcel Holtmann struct hci_conn *conn; 312441a96212SMarcel Holtmann 3125a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 312641a96212SMarcel Holtmann 312741a96212SMarcel Holtmann hci_dev_lock(hdev); 312841a96212SMarcel Holtmann 312941a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3130ccd556feSJohan Hedberg if (!conn) 3131ccd556feSJohan Hedberg goto unlock; 3132ccd556feSJohan Hedberg 3133769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 313441a96212SMarcel Holtmann struct inquiry_entry *ie; 313541a96212SMarcel Holtmann 3136cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 3137cc11b9c1SAndrei Emeltchenko if (ie) 313802b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 313941a96212SMarcel Holtmann 314002b7cc62SJohan Hedberg if (ev->features[0] & LMP_HOST_SSP) 314158a681efSJohan Hedberg set_bit(HCI_CONN_SSP_ENABLED, &conn->flags); 314241a96212SMarcel Holtmann } 314341a96212SMarcel Holtmann 3144ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 3145ccd556feSJohan Hedberg goto unlock; 3146ccd556feSJohan Hedberg 3147671267bfSJohan Hedberg if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { 3148127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 3149127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 3150127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 3151127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 3152127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 3153b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 3154b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 315508c79b61SJohan Hedberg conn->dst_type, 0, NULL, 0, 3156b644ba33SJohan Hedberg conn->dev_class); 3157392599b9SJohan Hedberg 3158127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 3159769be974SMarcel Holtmann conn->state = BT_CONNECTED; 3160769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 3161769be974SMarcel Holtmann hci_conn_put(conn); 3162769be974SMarcel Holtmann } 3163769be974SMarcel Holtmann 3164ccd556feSJohan Hedberg unlock: 316541a96212SMarcel Holtmann hci_dev_unlock(hdev); 3166a9de9248SMarcel Holtmann } 3167a9de9248SMarcel Holtmann 31686039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev, 3169807deac2SGustavo Padovan struct sk_buff *skb) 3170a9de9248SMarcel Holtmann { 3171b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 3172b6a0dc82SMarcel Holtmann struct hci_conn *conn; 3173b6a0dc82SMarcel Holtmann 31749f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 3175b6a0dc82SMarcel Holtmann 3176b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 3177b6a0dc82SMarcel Holtmann 3178b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 31799dc0a3afSMarcel Holtmann if (!conn) { 31809dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 31819dc0a3afSMarcel Holtmann goto unlock; 31829dc0a3afSMarcel Holtmann 31839dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 3184b6a0dc82SMarcel Holtmann if (!conn) 3185b6a0dc82SMarcel Holtmann goto unlock; 3186b6a0dc82SMarcel Holtmann 31879dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 31889dc0a3afSMarcel Holtmann } 31899dc0a3afSMarcel Holtmann 3190732547f9SMarcel Holtmann switch (ev->status) { 3191732547f9SMarcel Holtmann case 0x00: 3192732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 3193732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 3194732547f9SMarcel Holtmann 31959eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 3196732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 3197732547f9SMarcel Holtmann break; 3198732547f9SMarcel Holtmann 3199705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 3200732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 32011038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 3202732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 3203732547f9SMarcel Holtmann if (conn->out && conn->attempt < 2) { 3204efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 3205efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 3206efc7688bSMarcel Holtmann hci_setup_sync(conn, conn->link->handle); 3207efc7688bSMarcel Holtmann goto unlock; 3208efc7688bSMarcel Holtmann } 3209732547f9SMarcel Holtmann /* fall through */ 3210efc7688bSMarcel Holtmann 3211732547f9SMarcel Holtmann default: 3212b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 3213732547f9SMarcel Holtmann break; 3214732547f9SMarcel Holtmann } 3215b6a0dc82SMarcel Holtmann 3216b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 3217b6a0dc82SMarcel Holtmann if (ev->status) 3218b6a0dc82SMarcel Holtmann hci_conn_del(conn); 3219b6a0dc82SMarcel Holtmann 3220b6a0dc82SMarcel Holtmann unlock: 3221b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 3222a9de9248SMarcel Holtmann } 3223a9de9248SMarcel Holtmann 32246039aa73SGustavo Padovan static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) 3225a9de9248SMarcel Holtmann { 3226a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 3227a9de9248SMarcel Holtmann } 3228a9de9248SMarcel Holtmann 32296039aa73SGustavo Padovan static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) 323004837f64SMarcel Holtmann { 3231a9de9248SMarcel Holtmann struct hci_ev_sniff_subrate *ev = (void *) skb->data; 323204837f64SMarcel Holtmann 32339f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 323404837f64SMarcel Holtmann } 323504837f64SMarcel Holtmann 32366039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, 3237807deac2SGustavo Padovan struct sk_buff *skb) 3238a9de9248SMarcel Holtmann { 3239a9de9248SMarcel Holtmann struct inquiry_data data; 3240a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 3241a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 32429d939d94SVishal Agarwal size_t eir_len; 3243a9de9248SMarcel Holtmann 3244a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 3245a9de9248SMarcel Holtmann 3246a9de9248SMarcel Holtmann if (!num_rsp) 3247a9de9248SMarcel Holtmann return; 3248a9de9248SMarcel Holtmann 32491519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 32501519cc17SAndre Guedes return; 32511519cc17SAndre Guedes 3252a9de9248SMarcel Holtmann hci_dev_lock(hdev); 3253a9de9248SMarcel Holtmann 3254e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 3255388fc8faSJohan Hedberg bool name_known, ssp; 3256561aafbcSJohan Hedberg 3257a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 3258a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 3259a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 3260a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 3261a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 3262a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 3263a9de9248SMarcel Holtmann data.rssi = info->rssi; 326441a96212SMarcel Holtmann data.ssp_mode = 0x01; 3265561aafbcSJohan Hedberg 3266a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 32674ddb1930SJohan Hedberg name_known = eir_has_data_type(info->data, 32684ddb1930SJohan Hedberg sizeof(info->data), 32694ddb1930SJohan Hedberg EIR_NAME_COMPLETE); 3270561aafbcSJohan Hedberg else 3271561aafbcSJohan Hedberg name_known = true; 3272561aafbcSJohan Hedberg 3273388fc8faSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, name_known, 3274388fc8faSJohan Hedberg &ssp); 32759d939d94SVishal Agarwal eir_len = eir_get_length(info->data, sizeof(info->data)); 327648264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 327704124681SGustavo F. Padovan info->dev_class, info->rssi, !name_known, 32789d939d94SVishal Agarwal ssp, info->data, eir_len); 3279a9de9248SMarcel Holtmann } 3280a9de9248SMarcel Holtmann 3281a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 3282a9de9248SMarcel Holtmann } 3283a9de9248SMarcel Holtmann 32841c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev, 32851c2e0041SJohan Hedberg struct sk_buff *skb) 32861c2e0041SJohan Hedberg { 32871c2e0041SJohan Hedberg struct hci_ev_key_refresh_complete *ev = (void *) skb->data; 32881c2e0041SJohan Hedberg struct hci_conn *conn; 32891c2e0041SJohan Hedberg 32909f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status, 32911c2e0041SJohan Hedberg __le16_to_cpu(ev->handle)); 32921c2e0041SJohan Hedberg 32931c2e0041SJohan Hedberg hci_dev_lock(hdev); 32941c2e0041SJohan Hedberg 32951c2e0041SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 32961c2e0041SJohan Hedberg if (!conn) 32971c2e0041SJohan Hedberg goto unlock; 32981c2e0041SJohan Hedberg 32991c2e0041SJohan Hedberg if (!ev->status) 33001c2e0041SJohan Hedberg conn->sec_level = conn->pending_sec_level; 33011c2e0041SJohan Hedberg 33021c2e0041SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 33031c2e0041SJohan Hedberg 33041c2e0041SJohan Hedberg if (ev->status && conn->state == BT_CONNECTED) { 33051c2e0041SJohan Hedberg hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE); 33061c2e0041SJohan Hedberg hci_conn_put(conn); 33071c2e0041SJohan Hedberg goto unlock; 33081c2e0041SJohan Hedberg } 33091c2e0041SJohan Hedberg 33101c2e0041SJohan Hedberg if (conn->state == BT_CONFIG) { 33111c2e0041SJohan Hedberg if (!ev->status) 33121c2e0041SJohan Hedberg conn->state = BT_CONNECTED; 33131c2e0041SJohan Hedberg 33141c2e0041SJohan Hedberg hci_proto_connect_cfm(conn, ev->status); 33151c2e0041SJohan Hedberg hci_conn_put(conn); 33161c2e0041SJohan Hedberg } else { 33171c2e0041SJohan Hedberg hci_auth_cfm(conn, ev->status); 33181c2e0041SJohan Hedberg 33191c2e0041SJohan Hedberg hci_conn_hold(conn); 33201c2e0041SJohan Hedberg conn->disc_timeout = HCI_DISCONN_TIMEOUT; 33211c2e0041SJohan Hedberg hci_conn_put(conn); 33221c2e0041SJohan Hedberg } 33231c2e0041SJohan Hedberg 33241c2e0041SJohan Hedberg unlock: 33251c2e0041SJohan Hedberg hci_dev_unlock(hdev); 33261c2e0041SJohan Hedberg } 33271c2e0041SJohan Hedberg 33286039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn) 332917fa4b9dSJohan Hedberg { 333017fa4b9dSJohan Hedberg /* If remote requests dedicated bonding follow that lead */ 333117fa4b9dSJohan Hedberg if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) { 333217fa4b9dSJohan Hedberg /* If both remote and local IO capabilities allow MITM 333317fa4b9dSJohan Hedberg * protection then require it, otherwise don't */ 333417fa4b9dSJohan Hedberg if (conn->remote_cap == 0x03 || conn->io_capability == 0x03) 333517fa4b9dSJohan Hedberg return 0x02; 333617fa4b9dSJohan Hedberg else 333717fa4b9dSJohan Hedberg return 0x03; 333817fa4b9dSJohan Hedberg } 333917fa4b9dSJohan Hedberg 334017fa4b9dSJohan Hedberg /* If remote requests no-bonding follow that lead */ 334117fa4b9dSJohan Hedberg if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01) 334258797bf7SWaldemar Rymarkiewicz return conn->remote_auth | (conn->auth_type & 0x01); 334317fa4b9dSJohan Hedberg 334417fa4b9dSJohan Hedberg return conn->auth_type; 334517fa4b9dSJohan Hedberg } 334617fa4b9dSJohan Hedberg 33476039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 33480493684eSMarcel Holtmann { 33490493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 33500493684eSMarcel Holtmann struct hci_conn *conn; 33510493684eSMarcel Holtmann 33520493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 33530493684eSMarcel Holtmann 33540493684eSMarcel Holtmann hci_dev_lock(hdev); 33550493684eSMarcel Holtmann 33560493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 335703b555e1SJohan Hedberg if (!conn) 335803b555e1SJohan Hedberg goto unlock; 335903b555e1SJohan Hedberg 33600493684eSMarcel Holtmann hci_conn_hold(conn); 33610493684eSMarcel Holtmann 3362a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 336303b555e1SJohan Hedberg goto unlock; 336403b555e1SJohan Hedberg 3365a8b2d5c2SJohan Hedberg if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) || 336603b555e1SJohan Hedberg (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 336717fa4b9dSJohan Hedberg struct hci_cp_io_capability_reply cp; 336817fa4b9dSJohan Hedberg 336917fa4b9dSJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 33707a7f1e7cSHemant Gupta /* Change the IO capability from KeyboardDisplay 33717a7f1e7cSHemant Gupta * to DisplayYesNo as it is not supported by BT spec. */ 33727a7f1e7cSHemant Gupta cp.capability = (conn->io_capability == 0x04) ? 33737a7f1e7cSHemant Gupta 0x01 : conn->io_capability; 33747cbc9bd9SJohan Hedberg conn->auth_type = hci_get_auth_req(conn); 33757cbc9bd9SJohan Hedberg cp.authentication = conn->auth_type; 337617fa4b9dSJohan Hedberg 33778fc9ced3SGustavo Padovan if (hci_find_remote_oob_data(hdev, &conn->dst) && 33788fc9ced3SGustavo Padovan (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags))) 3379ce85ee13SSzymon Janc cp.oob_data = 0x01; 3380ce85ee13SSzymon Janc else 3381ce85ee13SSzymon Janc cp.oob_data = 0x00; 3382ce85ee13SSzymon Janc 338317fa4b9dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, 338417fa4b9dSJohan Hedberg sizeof(cp), &cp); 338503b555e1SJohan Hedberg } else { 338603b555e1SJohan Hedberg struct hci_cp_io_capability_neg_reply cp; 338703b555e1SJohan Hedberg 338803b555e1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 33899f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED; 339003b555e1SJohan Hedberg 339103b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 339203b555e1SJohan Hedberg sizeof(cp), &cp); 339303b555e1SJohan Hedberg } 339403b555e1SJohan Hedberg 339503b555e1SJohan Hedberg unlock: 339603b555e1SJohan Hedberg hci_dev_unlock(hdev); 339703b555e1SJohan Hedberg } 339803b555e1SJohan Hedberg 33996039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 340003b555e1SJohan Hedberg { 340103b555e1SJohan Hedberg struct hci_ev_io_capa_reply *ev = (void *) skb->data; 340203b555e1SJohan Hedberg struct hci_conn *conn; 340303b555e1SJohan Hedberg 340403b555e1SJohan Hedberg BT_DBG("%s", hdev->name); 340503b555e1SJohan Hedberg 340603b555e1SJohan Hedberg hci_dev_lock(hdev); 340703b555e1SJohan Hedberg 340803b555e1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 340903b555e1SJohan Hedberg if (!conn) 341003b555e1SJohan Hedberg goto unlock; 341103b555e1SJohan Hedberg 341203b555e1SJohan Hedberg conn->remote_cap = ev->capability; 341303b555e1SJohan Hedberg conn->remote_auth = ev->authentication; 341458a681efSJohan Hedberg if (ev->oob_data) 341558a681efSJohan Hedberg set_bit(HCI_CONN_REMOTE_OOB, &conn->flags); 341603b555e1SJohan Hedberg 341703b555e1SJohan Hedberg unlock: 34180493684eSMarcel Holtmann hci_dev_unlock(hdev); 34190493684eSMarcel Holtmann } 34200493684eSMarcel Holtmann 34216039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev, 3422a5c29683SJohan Hedberg struct sk_buff *skb) 3423a5c29683SJohan Hedberg { 3424a5c29683SJohan Hedberg struct hci_ev_user_confirm_req *ev = (void *) skb->data; 342555bc1a37SJohan Hedberg int loc_mitm, rem_mitm, confirm_hint = 0; 34267a828908SJohan Hedberg struct hci_conn *conn; 3427a5c29683SJohan Hedberg 3428a5c29683SJohan Hedberg BT_DBG("%s", hdev->name); 3429a5c29683SJohan Hedberg 3430a5c29683SJohan Hedberg hci_dev_lock(hdev); 3431a5c29683SJohan Hedberg 3432a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 34337a828908SJohan Hedberg goto unlock; 34347a828908SJohan Hedberg 34357a828908SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 34367a828908SJohan Hedberg if (!conn) 34377a828908SJohan Hedberg goto unlock; 34387a828908SJohan Hedberg 34397a828908SJohan Hedberg loc_mitm = (conn->auth_type & 0x01); 34407a828908SJohan Hedberg rem_mitm = (conn->remote_auth & 0x01); 34417a828908SJohan Hedberg 34427a828908SJohan Hedberg /* If we require MITM but the remote device can't provide that 34437a828908SJohan Hedberg * (it has NoInputNoOutput) then reject the confirmation 34447a828908SJohan Hedberg * request. The only exception is when we're dedicated bonding 34457a828908SJohan Hedberg * initiators (connect_cfm_cb set) since then we always have the MITM 34467a828908SJohan Hedberg * bit set. */ 34477a828908SJohan Hedberg if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) { 34487a828908SJohan Hedberg BT_DBG("Rejecting request: remote device can't provide MITM"); 34497a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, 34507a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 34517a828908SJohan Hedberg goto unlock; 34527a828908SJohan Hedberg } 34537a828908SJohan Hedberg 34547a828908SJohan Hedberg /* If no side requires MITM protection; auto-accept */ 34557a828908SJohan Hedberg if ((!loc_mitm || conn->remote_cap == 0x03) && 34567a828908SJohan Hedberg (!rem_mitm || conn->io_capability == 0x03)) { 345755bc1a37SJohan Hedberg 345855bc1a37SJohan Hedberg /* If we're not the initiators request authorization to 345955bc1a37SJohan Hedberg * proceed from user space (mgmt_user_confirm with 346055bc1a37SJohan Hedberg * confirm_hint set to 1). */ 346151a8efd7SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 346255bc1a37SJohan Hedberg BT_DBG("Confirming auto-accept as acceptor"); 346355bc1a37SJohan Hedberg confirm_hint = 1; 346455bc1a37SJohan Hedberg goto confirm; 346555bc1a37SJohan Hedberg } 346655bc1a37SJohan Hedberg 34679f61656aSJohan Hedberg BT_DBG("Auto-accept of user confirmation with %ums delay", 34689f61656aSJohan Hedberg hdev->auto_accept_delay); 34699f61656aSJohan Hedberg 34709f61656aSJohan Hedberg if (hdev->auto_accept_delay > 0) { 34719f61656aSJohan Hedberg int delay = msecs_to_jiffies(hdev->auto_accept_delay); 34729f61656aSJohan Hedberg mod_timer(&conn->auto_accept_timer, jiffies + delay); 34739f61656aSJohan Hedberg goto unlock; 34749f61656aSJohan Hedberg } 34759f61656aSJohan Hedberg 34767a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, 34777a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 34787a828908SJohan Hedberg goto unlock; 34797a828908SJohan Hedberg } 34807a828908SJohan Hedberg 348155bc1a37SJohan Hedberg confirm: 3482272d90dfSJohan Hedberg mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey, 348355bc1a37SJohan Hedberg confirm_hint); 3484a5c29683SJohan Hedberg 34857a828908SJohan Hedberg unlock: 3486a5c29683SJohan Hedberg hci_dev_unlock(hdev); 3487a5c29683SJohan Hedberg } 3488a5c29683SJohan Hedberg 34896039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev, 34901143d458SBrian Gix struct sk_buff *skb) 34911143d458SBrian Gix { 34921143d458SBrian Gix struct hci_ev_user_passkey_req *ev = (void *) skb->data; 34931143d458SBrian Gix 34941143d458SBrian Gix BT_DBG("%s", hdev->name); 34951143d458SBrian Gix 3496a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 3497272d90dfSJohan Hedberg mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); 34981143d458SBrian Gix } 34991143d458SBrian Gix 350092a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev, 350192a25256SJohan Hedberg struct sk_buff *skb) 350292a25256SJohan Hedberg { 350392a25256SJohan Hedberg struct hci_ev_user_passkey_notify *ev = (void *) skb->data; 350492a25256SJohan Hedberg struct hci_conn *conn; 350592a25256SJohan Hedberg 350692a25256SJohan Hedberg BT_DBG("%s", hdev->name); 350792a25256SJohan Hedberg 350892a25256SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 350992a25256SJohan Hedberg if (!conn) 351092a25256SJohan Hedberg return; 351192a25256SJohan Hedberg 351292a25256SJohan Hedberg conn->passkey_notify = __le32_to_cpu(ev->passkey); 351392a25256SJohan Hedberg conn->passkey_entered = 0; 351492a25256SJohan Hedberg 351592a25256SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 351692a25256SJohan Hedberg mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, 351792a25256SJohan Hedberg conn->dst_type, conn->passkey_notify, 351892a25256SJohan Hedberg conn->passkey_entered); 351992a25256SJohan Hedberg } 352092a25256SJohan Hedberg 352192a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 352292a25256SJohan Hedberg { 352392a25256SJohan Hedberg struct hci_ev_keypress_notify *ev = (void *) skb->data; 352492a25256SJohan Hedberg struct hci_conn *conn; 352592a25256SJohan Hedberg 352692a25256SJohan Hedberg BT_DBG("%s", hdev->name); 352792a25256SJohan Hedberg 352892a25256SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 352992a25256SJohan Hedberg if (!conn) 353092a25256SJohan Hedberg return; 353192a25256SJohan Hedberg 353292a25256SJohan Hedberg switch (ev->type) { 353392a25256SJohan Hedberg case HCI_KEYPRESS_STARTED: 353492a25256SJohan Hedberg conn->passkey_entered = 0; 353592a25256SJohan Hedberg return; 353692a25256SJohan Hedberg 353792a25256SJohan Hedberg case HCI_KEYPRESS_ENTERED: 353892a25256SJohan Hedberg conn->passkey_entered++; 353992a25256SJohan Hedberg break; 354092a25256SJohan Hedberg 354192a25256SJohan Hedberg case HCI_KEYPRESS_ERASED: 354292a25256SJohan Hedberg conn->passkey_entered--; 354392a25256SJohan Hedberg break; 354492a25256SJohan Hedberg 354592a25256SJohan Hedberg case HCI_KEYPRESS_CLEARED: 354692a25256SJohan Hedberg conn->passkey_entered = 0; 354792a25256SJohan Hedberg break; 354892a25256SJohan Hedberg 354992a25256SJohan Hedberg case HCI_KEYPRESS_COMPLETED: 355092a25256SJohan Hedberg return; 355192a25256SJohan Hedberg } 355292a25256SJohan Hedberg 355392a25256SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 355492a25256SJohan Hedberg mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, 355592a25256SJohan Hedberg conn->dst_type, conn->passkey_notify, 355692a25256SJohan Hedberg conn->passkey_entered); 355792a25256SJohan Hedberg } 355892a25256SJohan Hedberg 35596039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev, 3560807deac2SGustavo Padovan struct sk_buff *skb) 35610493684eSMarcel Holtmann { 35620493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 35630493684eSMarcel Holtmann struct hci_conn *conn; 35640493684eSMarcel Holtmann 35650493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 35660493684eSMarcel Holtmann 35670493684eSMarcel Holtmann hci_dev_lock(hdev); 35680493684eSMarcel Holtmann 35690493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 35702a611692SJohan Hedberg if (!conn) 35712a611692SJohan Hedberg goto unlock; 35722a611692SJohan Hedberg 35732a611692SJohan Hedberg /* To avoid duplicate auth_failed events to user space we check 35742a611692SJohan Hedberg * the HCI_CONN_AUTH_PEND flag which will be set if we 35752a611692SJohan Hedberg * initiated the authentication. A traditional auth_complete 35762a611692SJohan Hedberg * event gets always produced as initiator and is also mapped to 35772a611692SJohan Hedberg * the mgmt_auth_failed event */ 3578fa1bd918SMikel Astiz if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status) 3579bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 3580bab73cb6SJohan Hedberg ev->status); 35812a611692SJohan Hedberg 35820493684eSMarcel Holtmann hci_conn_put(conn); 35830493684eSMarcel Holtmann 35842a611692SJohan Hedberg unlock: 35850493684eSMarcel Holtmann hci_dev_unlock(hdev); 35860493684eSMarcel Holtmann } 35870493684eSMarcel Holtmann 35886039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev, 3589807deac2SGustavo Padovan struct sk_buff *skb) 359041a96212SMarcel Holtmann { 359141a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 359241a96212SMarcel Holtmann struct inquiry_entry *ie; 359341a96212SMarcel Holtmann 359441a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 359541a96212SMarcel Holtmann 359641a96212SMarcel Holtmann hci_dev_lock(hdev); 359741a96212SMarcel Holtmann 3598cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 3599cc11b9c1SAndrei Emeltchenko if (ie) 360002b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 360141a96212SMarcel Holtmann 360241a96212SMarcel Holtmann hci_dev_unlock(hdev); 360341a96212SMarcel Holtmann } 360441a96212SMarcel Holtmann 36056039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev, 36062763eda6SSzymon Janc struct sk_buff *skb) 36072763eda6SSzymon Janc { 36082763eda6SSzymon Janc struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; 36092763eda6SSzymon Janc struct oob_data *data; 36102763eda6SSzymon Janc 36112763eda6SSzymon Janc BT_DBG("%s", hdev->name); 36122763eda6SSzymon Janc 36132763eda6SSzymon Janc hci_dev_lock(hdev); 36142763eda6SSzymon Janc 3615a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 3616e1ba1f15SSzymon Janc goto unlock; 3617e1ba1f15SSzymon Janc 36182763eda6SSzymon Janc data = hci_find_remote_oob_data(hdev, &ev->bdaddr); 36192763eda6SSzymon Janc if (data) { 36202763eda6SSzymon Janc struct hci_cp_remote_oob_data_reply cp; 36212763eda6SSzymon Janc 36222763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 36232763eda6SSzymon Janc memcpy(cp.hash, data->hash, sizeof(cp.hash)); 36242763eda6SSzymon Janc memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); 36252763eda6SSzymon Janc 36262763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), 36272763eda6SSzymon Janc &cp); 36282763eda6SSzymon Janc } else { 36292763eda6SSzymon Janc struct hci_cp_remote_oob_data_neg_reply cp; 36302763eda6SSzymon Janc 36312763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 36322763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), 36332763eda6SSzymon Janc &cp); 36342763eda6SSzymon Janc } 36352763eda6SSzymon Janc 3636e1ba1f15SSzymon Janc unlock: 36372763eda6SSzymon Janc hci_dev_unlock(hdev); 36382763eda6SSzymon Janc } 36392763eda6SSzymon Janc 36406039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 3641fcd89c09SVille Tervo { 3642fcd89c09SVille Tervo struct hci_ev_le_conn_complete *ev = (void *) skb->data; 3643fcd89c09SVille Tervo struct hci_conn *conn; 3644fcd89c09SVille Tervo 36459f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 3646fcd89c09SVille Tervo 3647fcd89c09SVille Tervo hci_dev_lock(hdev); 3648fcd89c09SVille Tervo 36494f72b329SAndrzej Kaczmarek conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); 3650b62f328bSVille Tervo if (!conn) { 3651b62f328bSVille Tervo conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); 3652b62f328bSVille Tervo if (!conn) { 3653b62f328bSVille Tervo BT_ERR("No memory for new connection"); 3654230fd16aSAndre Guedes goto unlock; 3655b62f328bSVille Tervo } 365629b7988aSAndre Guedes 365729b7988aSAndre Guedes conn->dst_type = ev->bdaddr_type; 3658b9b343d2SAndre Guedes 3659b9b343d2SAndre Guedes if (ev->role == LE_CONN_ROLE_MASTER) { 3660b9b343d2SAndre Guedes conn->out = true; 3661b9b343d2SAndre Guedes conn->link_mode |= HCI_LM_MASTER; 3662b9b343d2SAndre Guedes } 3663b62f328bSVille Tervo } 3664fcd89c09SVille Tervo 3665cd17decbSAndre Guedes if (ev->status) { 3666cd17decbSAndre Guedes mgmt_connect_failed(hdev, &conn->dst, conn->type, 3667cd17decbSAndre Guedes conn->dst_type, ev->status); 3668cd17decbSAndre Guedes hci_proto_connect_cfm(conn, ev->status); 3669cd17decbSAndre Guedes conn->state = BT_CLOSED; 3670cd17decbSAndre Guedes hci_conn_del(conn); 3671cd17decbSAndre Guedes goto unlock; 3672cd17decbSAndre Guedes } 3673cd17decbSAndre Guedes 3674b644ba33SJohan Hedberg if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 3675b644ba33SJohan Hedberg mgmt_device_connected(hdev, &ev->bdaddr, conn->type, 367695b23582SSzymon Janc conn->dst_type, 0, NULL, 0, NULL); 367783bc71b4SVinicius Costa Gomes 36787b5c0d52SVinicius Costa Gomes conn->sec_level = BT_SECURITY_LOW; 3679fcd89c09SVille Tervo conn->handle = __le16_to_cpu(ev->handle); 3680fcd89c09SVille Tervo conn->state = BT_CONNECTED; 3681fcd89c09SVille Tervo 3682fcd89c09SVille Tervo hci_conn_hold_device(conn); 3683fcd89c09SVille Tervo hci_conn_add_sysfs(conn); 3684fcd89c09SVille Tervo 3685fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 3686fcd89c09SVille Tervo 3687fcd89c09SVille Tervo unlock: 3688fcd89c09SVille Tervo hci_dev_unlock(hdev); 3689fcd89c09SVille Tervo } 3690fcd89c09SVille Tervo 36916039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) 36929aa04c91SAndre Guedes { 3693e95beb41SAndre Guedes u8 num_reports = skb->data[0]; 3694e95beb41SAndre Guedes void *ptr = &skb->data[1]; 36953c9e9195SAndre Guedes s8 rssi; 36969aa04c91SAndre Guedes 36979aa04c91SAndre Guedes hci_dev_lock(hdev); 36989aa04c91SAndre Guedes 3699e95beb41SAndre Guedes while (num_reports--) { 3700e95beb41SAndre Guedes struct hci_ev_le_advertising_info *ev = ptr; 3701e95beb41SAndre Guedes 37023c9e9195SAndre Guedes rssi = ev->data[ev->length]; 37033c9e9195SAndre Guedes mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type, 370404124681SGustavo F. Padovan NULL, rssi, 0, 1, ev->data, ev->length); 37053c9e9195SAndre Guedes 3706e95beb41SAndre Guedes ptr += sizeof(*ev) + ev->length + 1; 37079aa04c91SAndre Guedes } 37089aa04c91SAndre Guedes 37099aa04c91SAndre Guedes hci_dev_unlock(hdev); 37109aa04c91SAndre Guedes } 37119aa04c91SAndre Guedes 37126039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 3713a7a595f6SVinicius Costa Gomes { 3714a7a595f6SVinicius Costa Gomes struct hci_ev_le_ltk_req *ev = (void *) skb->data; 3715a7a595f6SVinicius Costa Gomes struct hci_cp_le_ltk_reply cp; 3716bea710feSVinicius Costa Gomes struct hci_cp_le_ltk_neg_reply neg; 3717a7a595f6SVinicius Costa Gomes struct hci_conn *conn; 3718c9839a11SVinicius Costa Gomes struct smp_ltk *ltk; 3719a7a595f6SVinicius Costa Gomes 37209f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle)); 3721a7a595f6SVinicius Costa Gomes 3722a7a595f6SVinicius Costa Gomes hci_dev_lock(hdev); 3723a7a595f6SVinicius Costa Gomes 3724a7a595f6SVinicius Costa Gomes conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3725bea710feSVinicius Costa Gomes if (conn == NULL) 3726bea710feSVinicius Costa Gomes goto not_found; 3727a7a595f6SVinicius Costa Gomes 3728bea710feSVinicius Costa Gomes ltk = hci_find_ltk(hdev, ev->ediv, ev->random); 3729bea710feSVinicius Costa Gomes if (ltk == NULL) 3730bea710feSVinicius Costa Gomes goto not_found; 3731bea710feSVinicius Costa Gomes 3732bea710feSVinicius Costa Gomes memcpy(cp.ltk, ltk->val, sizeof(ltk->val)); 3733a7a595f6SVinicius Costa Gomes cp.handle = cpu_to_le16(conn->handle); 3734c9839a11SVinicius Costa Gomes 3735c9839a11SVinicius Costa Gomes if (ltk->authenticated) 3736c9839a11SVinicius Costa Gomes conn->sec_level = BT_SECURITY_HIGH; 3737a7a595f6SVinicius Costa Gomes 3738a7a595f6SVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); 3739a7a595f6SVinicius Costa Gomes 3740c9839a11SVinicius Costa Gomes if (ltk->type & HCI_SMP_STK) { 3741c9839a11SVinicius Costa Gomes list_del(<k->list); 3742c9839a11SVinicius Costa Gomes kfree(ltk); 3743c9839a11SVinicius Costa Gomes } 3744c9839a11SVinicius Costa Gomes 3745a7a595f6SVinicius Costa Gomes hci_dev_unlock(hdev); 3746bea710feSVinicius Costa Gomes 3747bea710feSVinicius Costa Gomes return; 3748bea710feSVinicius Costa Gomes 3749bea710feSVinicius Costa Gomes not_found: 3750bea710feSVinicius Costa Gomes neg.handle = ev->handle; 3751bea710feSVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg); 3752bea710feSVinicius Costa Gomes hci_dev_unlock(hdev); 3753a7a595f6SVinicius Costa Gomes } 3754a7a595f6SVinicius Costa Gomes 37556039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 3756fcd89c09SVille Tervo { 3757fcd89c09SVille Tervo struct hci_ev_le_meta *le_ev = (void *) skb->data; 3758fcd89c09SVille Tervo 3759fcd89c09SVille Tervo skb_pull(skb, sizeof(*le_ev)); 3760fcd89c09SVille Tervo 3761fcd89c09SVille Tervo switch (le_ev->subevent) { 3762fcd89c09SVille Tervo case HCI_EV_LE_CONN_COMPLETE: 3763fcd89c09SVille Tervo hci_le_conn_complete_evt(hdev, skb); 3764fcd89c09SVille Tervo break; 3765fcd89c09SVille Tervo 37669aa04c91SAndre Guedes case HCI_EV_LE_ADVERTISING_REPORT: 37679aa04c91SAndre Guedes hci_le_adv_report_evt(hdev, skb); 37689aa04c91SAndre Guedes break; 37699aa04c91SAndre Guedes 3770a7a595f6SVinicius Costa Gomes case HCI_EV_LE_LTK_REQ: 3771a7a595f6SVinicius Costa Gomes hci_le_ltk_request_evt(hdev, skb); 3772a7a595f6SVinicius Costa Gomes break; 3773a7a595f6SVinicius Costa Gomes 3774fcd89c09SVille Tervo default: 3775fcd89c09SVille Tervo break; 3776fcd89c09SVille Tervo } 3777fcd89c09SVille Tervo } 3778fcd89c09SVille Tervo 37799495b2eeSAndrei Emeltchenko static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb) 37809495b2eeSAndrei Emeltchenko { 37819495b2eeSAndrei Emeltchenko struct hci_ev_channel_selected *ev = (void *) skb->data; 37829495b2eeSAndrei Emeltchenko struct hci_conn *hcon; 37839495b2eeSAndrei Emeltchenko 37849495b2eeSAndrei Emeltchenko BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle); 37859495b2eeSAndrei Emeltchenko 37869495b2eeSAndrei Emeltchenko skb_pull(skb, sizeof(*ev)); 37879495b2eeSAndrei Emeltchenko 37889495b2eeSAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 37899495b2eeSAndrei Emeltchenko if (!hcon) 37909495b2eeSAndrei Emeltchenko return; 37919495b2eeSAndrei Emeltchenko 37929495b2eeSAndrei Emeltchenko amp_read_loc_assoc_final_data(hdev, hcon); 37939495b2eeSAndrei Emeltchenko } 37949495b2eeSAndrei Emeltchenko 37951da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 37961da177e4SLinus Torvalds { 3797a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 3798a9de9248SMarcel Holtmann __u8 event = hdr->evt; 37991da177e4SLinus Torvalds 38001da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 38011da177e4SLinus Torvalds 3802a9de9248SMarcel Holtmann switch (event) { 38031da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 38041da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 38051da177e4SLinus Torvalds break; 38061da177e4SLinus Torvalds 38071da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 38081da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 38091da177e4SLinus Torvalds break; 38101da177e4SLinus Torvalds 3811a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 3812a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 381321d9e30eSMarcel Holtmann break; 381421d9e30eSMarcel Holtmann 38151da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 38161da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 38171da177e4SLinus Torvalds break; 38181da177e4SLinus Torvalds 38191da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 38201da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 38211da177e4SLinus Torvalds break; 38221da177e4SLinus Torvalds 38231da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 38241da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 38251da177e4SLinus Torvalds break; 38261da177e4SLinus Torvalds 3827a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 3828a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 3829a9de9248SMarcel Holtmann break; 3830a9de9248SMarcel Holtmann 38311da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 38321da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 38331da177e4SLinus Torvalds break; 38341da177e4SLinus Torvalds 3835a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 3836a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 3837a9de9248SMarcel Holtmann break; 3838a9de9248SMarcel Holtmann 3839a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 3840a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 3841a9de9248SMarcel Holtmann break; 3842a9de9248SMarcel Holtmann 3843a9de9248SMarcel Holtmann case HCI_EV_REMOTE_VERSION: 3844a9de9248SMarcel Holtmann hci_remote_version_evt(hdev, skb); 3845a9de9248SMarcel Holtmann break; 3846a9de9248SMarcel Holtmann 3847a9de9248SMarcel Holtmann case HCI_EV_QOS_SETUP_COMPLETE: 3848a9de9248SMarcel Holtmann hci_qos_setup_complete_evt(hdev, skb); 3849a9de9248SMarcel Holtmann break; 3850a9de9248SMarcel Holtmann 3851a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 3852a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 3853a9de9248SMarcel Holtmann break; 3854a9de9248SMarcel Holtmann 3855a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 3856a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 3857a9de9248SMarcel Holtmann break; 3858a9de9248SMarcel Holtmann 3859a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 3860a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 3861a9de9248SMarcel Holtmann break; 3862a9de9248SMarcel Holtmann 3863a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 3864a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 3865a9de9248SMarcel Holtmann break; 3866a9de9248SMarcel Holtmann 3867a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 3868a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 38691da177e4SLinus Torvalds break; 38701da177e4SLinus Torvalds 38711da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 38721da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 38731da177e4SLinus Torvalds break; 38741da177e4SLinus Torvalds 38751da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 38761da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 38771da177e4SLinus Torvalds break; 38781da177e4SLinus Torvalds 38791da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 38801da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 38811da177e4SLinus Torvalds break; 38821da177e4SLinus Torvalds 38831da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 38841da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 38851da177e4SLinus Torvalds break; 38861da177e4SLinus Torvalds 3887a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 3888a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 3889a8746417SMarcel Holtmann break; 3890a8746417SMarcel Holtmann 389185a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 389285a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 389385a1e930SMarcel Holtmann break; 389485a1e930SMarcel Holtmann 3895a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 3896a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 3897a9de9248SMarcel Holtmann break; 3898a9de9248SMarcel Holtmann 3899a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 3900a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 3901a9de9248SMarcel Holtmann break; 3902a9de9248SMarcel Holtmann 3903a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 3904a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 3905a9de9248SMarcel Holtmann break; 3906a9de9248SMarcel Holtmann 3907a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_CHANGED: 3908a9de9248SMarcel Holtmann hci_sync_conn_changed_evt(hdev, skb); 3909a9de9248SMarcel Holtmann break; 3910a9de9248SMarcel Holtmann 391104837f64SMarcel Holtmann case HCI_EV_SNIFF_SUBRATE: 391204837f64SMarcel Holtmann hci_sniff_subrate_evt(hdev, skb); 391304837f64SMarcel Holtmann break; 391404837f64SMarcel Holtmann 3915a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 3916a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 39171da177e4SLinus Torvalds break; 39181da177e4SLinus Torvalds 39191c2e0041SJohan Hedberg case HCI_EV_KEY_REFRESH_COMPLETE: 39201c2e0041SJohan Hedberg hci_key_refresh_complete_evt(hdev, skb); 39211c2e0041SJohan Hedberg break; 39221c2e0041SJohan Hedberg 39230493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 39240493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 39250493684eSMarcel Holtmann break; 39260493684eSMarcel Holtmann 392703b555e1SJohan Hedberg case HCI_EV_IO_CAPA_REPLY: 392803b555e1SJohan Hedberg hci_io_capa_reply_evt(hdev, skb); 392903b555e1SJohan Hedberg break; 393003b555e1SJohan Hedberg 3931a5c29683SJohan Hedberg case HCI_EV_USER_CONFIRM_REQUEST: 3932a5c29683SJohan Hedberg hci_user_confirm_request_evt(hdev, skb); 3933a5c29683SJohan Hedberg break; 3934a5c29683SJohan Hedberg 39351143d458SBrian Gix case HCI_EV_USER_PASSKEY_REQUEST: 39361143d458SBrian Gix hci_user_passkey_request_evt(hdev, skb); 39371143d458SBrian Gix break; 39381143d458SBrian Gix 393992a25256SJohan Hedberg case HCI_EV_USER_PASSKEY_NOTIFY: 394092a25256SJohan Hedberg hci_user_passkey_notify_evt(hdev, skb); 394192a25256SJohan Hedberg break; 394292a25256SJohan Hedberg 394392a25256SJohan Hedberg case HCI_EV_KEYPRESS_NOTIFY: 394492a25256SJohan Hedberg hci_keypress_notify_evt(hdev, skb); 394592a25256SJohan Hedberg break; 394692a25256SJohan Hedberg 39470493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 39480493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 39490493684eSMarcel Holtmann break; 39500493684eSMarcel Holtmann 395141a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 395241a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 395341a96212SMarcel Holtmann break; 395441a96212SMarcel Holtmann 3955fcd89c09SVille Tervo case HCI_EV_LE_META: 3956fcd89c09SVille Tervo hci_le_meta_evt(hdev, skb); 3957fcd89c09SVille Tervo break; 3958fcd89c09SVille Tervo 39599495b2eeSAndrei Emeltchenko case HCI_EV_CHANNEL_SELECTED: 39609495b2eeSAndrei Emeltchenko hci_chan_selected_evt(hdev, skb); 39619495b2eeSAndrei Emeltchenko break; 39629495b2eeSAndrei Emeltchenko 39632763eda6SSzymon Janc case HCI_EV_REMOTE_OOB_DATA_REQUEST: 39642763eda6SSzymon Janc hci_remote_oob_data_request_evt(hdev, skb); 39652763eda6SSzymon Janc break; 39662763eda6SSzymon Janc 396725e89e99SAndrei Emeltchenko case HCI_EV_NUM_COMP_BLOCKS: 396825e89e99SAndrei Emeltchenko hci_num_comp_blocks_evt(hdev, skb); 396925e89e99SAndrei Emeltchenko break; 397025e89e99SAndrei Emeltchenko 39711da177e4SLinus Torvalds default: 39729f1db00cSAndrei Emeltchenko BT_DBG("%s event 0x%2.2x", hdev->name, event); 39731da177e4SLinus Torvalds break; 39741da177e4SLinus Torvalds } 39751da177e4SLinus Torvalds 39761da177e4SLinus Torvalds kfree_skb(skb); 39771da177e4SLinus Torvalds hdev->stat.evt_rx++; 39781da177e4SLinus Torvalds } 3979