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 { 463d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 464d5859e22SJohan Hedberg return 2; 465d5859e22SJohan Hedberg 466d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 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 518d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 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 524d5859e22SJohan Hedberg if (hdev->features[5] & LMP_PAUSE_ENC) 525d5859e22SJohan Hedberg events[5] |= 0x80; /* Encryption Key Refresh Complete */ 526d5859e22SJohan Hedberg 527d5859e22SJohan Hedberg if (hdev->features[6] & LMP_EXT_INQ) 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 533d5859e22SJohan Hedberg if (hdev->features[7] & LMP_LSTO) 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 636d5859e22SJohan Hedberg if (hdev->features[3] & LMP_RSSI_INQ) 637d5859e22SJohan Hedberg hci_setup_inquiry_mode(hdev); 638d5859e22SJohan Hedberg 639d5859e22SJohan Hedberg if (hdev->features[7] & LMP_INQ_TX_PWR) 640d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL); 641971e3a4bSAndre Guedes 642971e3a4bSAndre Guedes if (hdev->features[7] & LMP_EXTFEATURES) { 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; 689d5859e22SJohan Hedberg if (hdev->features[0] & LMP_HOLD) 690d5859e22SJohan Hedberg link_policy |= HCI_LP_HOLD; 6916eded100SAndre Guedes if (lmp_sniff_capable(hdev)) 692d5859e22SJohan Hedberg link_policy |= HCI_LP_SNIFF; 693d5859e22SJohan Hedberg if (hdev->features[1] & LMP_PARK) 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; 7838f984dfaSJohan Hedberg cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR); 7848f984dfaSJohan Hedberg } 7858f984dfaSJohan Hedberg 7868f984dfaSJohan Hedberg if (cp.le != !!(hdev->host_features[0] & LMP_HOST_LE)) 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; 12908f984dfaSJohan Hedberg } 12918f984dfaSJohan Hedberg 12928f984dfaSJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags) && 12938f984dfaSJohan Hedberg !test_bit(HCI_INIT, &hdev->flags)) 12948f984dfaSJohan Hedberg mgmt_le_enable_complete(hdev, sent->le, status); 12958f984dfaSJohan Hedberg 12968f984dfaSJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status); 1297f9b49306SAndre Guedes } 1298f9b49306SAndre Guedes 129993c284eeSAndrei Emeltchenko static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev, 130093c284eeSAndrei Emeltchenko struct sk_buff *skb) 130193c284eeSAndrei Emeltchenko { 130293c284eeSAndrei Emeltchenko struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data; 130393c284eeSAndrei Emeltchenko 130493c284eeSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x", 130593c284eeSAndrei Emeltchenko hdev->name, rp->status, rp->phy_handle); 130693c284eeSAndrei Emeltchenko 130793c284eeSAndrei Emeltchenko if (rp->status) 130893c284eeSAndrei Emeltchenko return; 130993c284eeSAndrei Emeltchenko 131093c284eeSAndrei Emeltchenko amp_write_rem_assoc_continue(hdev, rp->phy_handle); 131193c284eeSAndrei Emeltchenko } 131293c284eeSAndrei Emeltchenko 13136039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 1314a9de9248SMarcel Holtmann { 13159f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1316a9de9248SMarcel Holtmann 1317a9de9248SMarcel Holtmann if (status) { 131823bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 1319a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 132056e5cb86SJohan Hedberg hci_dev_lock(hdev); 1321a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 13227a135109SAndre Guedes mgmt_start_discovery_failed(hdev, status); 132356e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1324314b2381SJohan Hedberg return; 1325314b2381SJohan Hedberg } 1326314b2381SJohan Hedberg 132789352e7dSAndre Guedes set_bit(HCI_INQUIRY, &hdev->flags); 132889352e7dSAndre Guedes 132956e5cb86SJohan Hedberg hci_dev_lock(hdev); 1330343f935bSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_FINDING); 133156e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1332a9de9248SMarcel Holtmann } 1333a9de9248SMarcel Holtmann 13346039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 13351da177e4SLinus Torvalds { 1336a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 13371da177e4SLinus Torvalds struct hci_conn *conn; 13381da177e4SLinus Torvalds 13399f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1340a9de9248SMarcel Holtmann 1341a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 13421da177e4SLinus Torvalds if (!cp) 13431da177e4SLinus Torvalds return; 13441da177e4SLinus Torvalds 13451da177e4SLinus Torvalds hci_dev_lock(hdev); 13461da177e4SLinus Torvalds 13471da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 13481da177e4SLinus Torvalds 13496ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn); 13501da177e4SLinus Torvalds 13511da177e4SLinus Torvalds if (status) { 13521da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 13534c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 13541da177e4SLinus Torvalds conn->state = BT_CLOSED; 13551da177e4SLinus Torvalds hci_proto_connect_cfm(conn, status); 13561da177e4SLinus Torvalds hci_conn_del(conn); 13574c67bc74SMarcel Holtmann } else 13584c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 13591da177e4SLinus Torvalds } 13601da177e4SLinus Torvalds } else { 13611da177e4SLinus Torvalds if (!conn) { 13621da177e4SLinus Torvalds conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); 13631da177e4SLinus Torvalds if (conn) { 1364a0c808b3SJohan Hedberg conn->out = true; 13651da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 13661da177e4SLinus Torvalds } else 1367893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 13681da177e4SLinus Torvalds } 13691da177e4SLinus Torvalds } 13701da177e4SLinus Torvalds 13711da177e4SLinus Torvalds hci_dev_unlock(hdev); 13721da177e4SLinus Torvalds } 13731da177e4SLinus Torvalds 1374a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 13751da177e4SLinus Torvalds { 1376a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 13771da177e4SLinus Torvalds struct hci_conn *acl, *sco; 13781da177e4SLinus Torvalds __u16 handle; 13791da177e4SLinus Torvalds 13809f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1381b6a0dc82SMarcel Holtmann 1382a9de9248SMarcel Holtmann if (!status) 1383a9de9248SMarcel Holtmann return; 1384a9de9248SMarcel Holtmann 1385a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 13861da177e4SLinus Torvalds if (!cp) 1387a9de9248SMarcel Holtmann return; 13881da177e4SLinus Torvalds 13891da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 13901da177e4SLinus Torvalds 13919f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, handle); 13921da177e4SLinus Torvalds 13931da177e4SLinus Torvalds hci_dev_lock(hdev); 13941da177e4SLinus Torvalds 13951da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 13965a08ecceSAndrei Emeltchenko if (acl) { 13975a08ecceSAndrei Emeltchenko sco = acl->link; 13985a08ecceSAndrei Emeltchenko if (sco) { 13991da177e4SLinus Torvalds sco->state = BT_CLOSED; 14001da177e4SLinus Torvalds 14011da177e4SLinus Torvalds hci_proto_connect_cfm(sco, status); 14021da177e4SLinus Torvalds hci_conn_del(sco); 14031da177e4SLinus Torvalds } 14045a08ecceSAndrei Emeltchenko } 14051da177e4SLinus Torvalds 14061da177e4SLinus Torvalds hci_dev_unlock(hdev); 14071da177e4SLinus Torvalds } 14081da177e4SLinus Torvalds 1409f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 1410f8558555SMarcel Holtmann { 1411f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 1412f8558555SMarcel Holtmann struct hci_conn *conn; 1413f8558555SMarcel Holtmann 14149f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1415f8558555SMarcel Holtmann 1416f8558555SMarcel Holtmann if (!status) 1417f8558555SMarcel Holtmann return; 1418f8558555SMarcel Holtmann 1419f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 1420f8558555SMarcel Holtmann if (!cp) 1421f8558555SMarcel Holtmann return; 1422f8558555SMarcel Holtmann 1423f8558555SMarcel Holtmann hci_dev_lock(hdev); 1424f8558555SMarcel Holtmann 1425f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1426f8558555SMarcel Holtmann if (conn) { 1427f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1428f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1429f8558555SMarcel Holtmann hci_conn_put(conn); 1430f8558555SMarcel Holtmann } 1431f8558555SMarcel Holtmann } 1432f8558555SMarcel Holtmann 1433f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1434f8558555SMarcel Holtmann } 1435f8558555SMarcel Holtmann 1436f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 1437f8558555SMarcel Holtmann { 1438f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 1439f8558555SMarcel Holtmann struct hci_conn *conn; 1440f8558555SMarcel Holtmann 14419f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1442f8558555SMarcel Holtmann 1443f8558555SMarcel Holtmann if (!status) 1444f8558555SMarcel Holtmann return; 1445f8558555SMarcel Holtmann 1446f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 1447f8558555SMarcel Holtmann if (!cp) 1448f8558555SMarcel Holtmann return; 1449f8558555SMarcel Holtmann 1450f8558555SMarcel Holtmann hci_dev_lock(hdev); 1451f8558555SMarcel Holtmann 1452f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1453f8558555SMarcel Holtmann if (conn) { 1454f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1455f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1456f8558555SMarcel Holtmann hci_conn_put(conn); 1457f8558555SMarcel Holtmann } 1458f8558555SMarcel Holtmann } 1459f8558555SMarcel Holtmann 1460f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1461f8558555SMarcel Holtmann } 1462f8558555SMarcel Holtmann 1463127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev, 1464392599b9SJohan Hedberg struct hci_conn *conn) 1465392599b9SJohan Hedberg { 1466392599b9SJohan Hedberg if (conn->state != BT_CONFIG || !conn->out) 1467392599b9SJohan Hedberg return 0; 1468392599b9SJohan Hedberg 1469765c2a96SJohan Hedberg if (conn->pending_sec_level == BT_SECURITY_SDP) 1470392599b9SJohan Hedberg return 0; 1471392599b9SJohan Hedberg 1472392599b9SJohan Hedberg /* Only request authentication for SSP connections or non-SSP 1473e9bf2bf0SVinicius Costa Gomes * devices with sec_level HIGH or if MITM protection is requested */ 1474807deac2SGustavo Padovan if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) && 1475807deac2SGustavo Padovan conn->pending_sec_level != BT_SECURITY_HIGH) 1476392599b9SJohan Hedberg return 0; 1477392599b9SJohan Hedberg 1478392599b9SJohan Hedberg return 1; 1479392599b9SJohan Hedberg } 1480392599b9SJohan Hedberg 14816039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev, 148200abfe44SGustavo F. Padovan struct inquiry_entry *e) 148330dc78e1SJohan Hedberg { 148430dc78e1SJohan Hedberg struct hci_cp_remote_name_req cp; 148530dc78e1SJohan Hedberg 148630dc78e1SJohan Hedberg memset(&cp, 0, sizeof(cp)); 148730dc78e1SJohan Hedberg 148830dc78e1SJohan Hedberg bacpy(&cp.bdaddr, &e->data.bdaddr); 148930dc78e1SJohan Hedberg cp.pscan_rep_mode = e->data.pscan_rep_mode; 149030dc78e1SJohan Hedberg cp.pscan_mode = e->data.pscan_mode; 149130dc78e1SJohan Hedberg cp.clock_offset = e->data.clock_offset; 149230dc78e1SJohan Hedberg 149330dc78e1SJohan Hedberg return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 149430dc78e1SJohan Hedberg } 149530dc78e1SJohan Hedberg 1496b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev) 149730dc78e1SJohan Hedberg { 149830dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 149930dc78e1SJohan Hedberg struct inquiry_entry *e; 150030dc78e1SJohan Hedberg 1501b644ba33SJohan Hedberg if (list_empty(&discov->resolve)) 1502b644ba33SJohan Hedberg return false; 1503b644ba33SJohan Hedberg 1504b644ba33SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 1505c810089cSRam Malovany if (!e) 1506c810089cSRam Malovany return false; 1507c810089cSRam Malovany 1508b644ba33SJohan Hedberg if (hci_resolve_name(hdev, e) == 0) { 1509b644ba33SJohan Hedberg e->name_state = NAME_PENDING; 1510b644ba33SJohan Hedberg return true; 1511b644ba33SJohan Hedberg } 1512b644ba33SJohan Hedberg 1513b644ba33SJohan Hedberg return false; 1514b644ba33SJohan Hedberg } 1515b644ba33SJohan Hedberg 1516b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn, 1517b644ba33SJohan Hedberg bdaddr_t *bdaddr, u8 *name, u8 name_len) 1518b644ba33SJohan Hedberg { 1519b644ba33SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 1520b644ba33SJohan Hedberg struct inquiry_entry *e; 1521b644ba33SJohan Hedberg 1522b644ba33SJohan Hedberg if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 152304124681SGustavo F. Padovan mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name, 152404124681SGustavo F. Padovan name_len, conn->dev_class); 1525b644ba33SJohan Hedberg 1526b644ba33SJohan Hedberg if (discov->state == DISCOVERY_STOPPED) 1527b644ba33SJohan Hedberg return; 1528b644ba33SJohan Hedberg 152930dc78e1SJohan Hedberg if (discov->state == DISCOVERY_STOPPING) 153030dc78e1SJohan Hedberg goto discov_complete; 153130dc78e1SJohan Hedberg 153230dc78e1SJohan Hedberg if (discov->state != DISCOVERY_RESOLVING) 153330dc78e1SJohan Hedberg return; 153430dc78e1SJohan Hedberg 153530dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING); 15367cc8380eSRam Malovany /* If the device was not found in a list of found devices names of which 15377cc8380eSRam Malovany * are pending. there is no need to continue resolving a next name as it 15387cc8380eSRam Malovany * will be done upon receiving another Remote Name Request Complete 15397cc8380eSRam Malovany * Event */ 15407cc8380eSRam Malovany if (!e) 15417cc8380eSRam Malovany return; 15427cc8380eSRam Malovany 154330dc78e1SJohan Hedberg list_del(&e->list); 15447cc8380eSRam Malovany if (name) { 15457cc8380eSRam Malovany e->name_state = NAME_KNOWN; 1546b644ba33SJohan Hedberg mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, 1547b644ba33SJohan Hedberg e->data.rssi, name, name_len); 1548c3e7c0d9SRam Malovany } else { 1549c3e7c0d9SRam Malovany e->name_state = NAME_NOT_KNOWN; 155030dc78e1SJohan Hedberg } 155130dc78e1SJohan Hedberg 1552b644ba33SJohan Hedberg if (hci_resolve_next_name(hdev)) 155330dc78e1SJohan Hedberg return; 155430dc78e1SJohan Hedberg 155530dc78e1SJohan Hedberg discov_complete: 155630dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 155730dc78e1SJohan Hedberg } 155830dc78e1SJohan Hedberg 1559a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 15601da177e4SLinus Torvalds { 1561127178d2SJohan Hedberg struct hci_cp_remote_name_req *cp; 1562127178d2SJohan Hedberg struct hci_conn *conn; 1563127178d2SJohan Hedberg 15649f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1565127178d2SJohan Hedberg 1566127178d2SJohan Hedberg /* If successful wait for the name req complete event before 1567127178d2SJohan Hedberg * checking for the need to do authentication */ 1568127178d2SJohan Hedberg if (!status) 1569127178d2SJohan Hedberg return; 1570127178d2SJohan Hedberg 1571127178d2SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); 1572127178d2SJohan Hedberg if (!cp) 1573127178d2SJohan Hedberg return; 1574127178d2SJohan Hedberg 1575127178d2SJohan Hedberg hci_dev_lock(hdev); 1576127178d2SJohan Hedberg 1577127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 1578b644ba33SJohan Hedberg 1579b644ba33SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1580b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0); 1581b644ba33SJohan Hedberg 158279c6c70cSJohan Hedberg if (!conn) 158379c6c70cSJohan Hedberg goto unlock; 158479c6c70cSJohan Hedberg 158579c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 158679c6c70cSJohan Hedberg goto unlock; 158779c6c70cSJohan Hedberg 158851a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 1589127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1590127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1591127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1592127178d2SJohan Hedberg } 1593127178d2SJohan Hedberg 159479c6c70cSJohan Hedberg unlock: 1595127178d2SJohan Hedberg hci_dev_unlock(hdev); 1596a9de9248SMarcel Holtmann } 15971da177e4SLinus Torvalds 1598769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 1599769be974SMarcel Holtmann { 1600769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 1601769be974SMarcel Holtmann struct hci_conn *conn; 1602769be974SMarcel Holtmann 16039f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1604769be974SMarcel Holtmann 1605769be974SMarcel Holtmann if (!status) 1606769be974SMarcel Holtmann return; 1607769be974SMarcel Holtmann 1608769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 1609769be974SMarcel Holtmann if (!cp) 1610769be974SMarcel Holtmann return; 1611769be974SMarcel Holtmann 1612769be974SMarcel Holtmann hci_dev_lock(hdev); 1613769be974SMarcel Holtmann 1614769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1615769be974SMarcel Holtmann if (conn) { 1616769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1617769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1618769be974SMarcel Holtmann hci_conn_put(conn); 1619769be974SMarcel Holtmann } 1620769be974SMarcel Holtmann } 1621769be974SMarcel Holtmann 1622769be974SMarcel Holtmann hci_dev_unlock(hdev); 1623769be974SMarcel Holtmann } 1624769be974SMarcel Holtmann 1625769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 1626769be974SMarcel Holtmann { 1627769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features *cp; 1628769be974SMarcel Holtmann struct hci_conn *conn; 1629769be974SMarcel Holtmann 16309f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1631769be974SMarcel Holtmann 1632769be974SMarcel Holtmann if (!status) 1633769be974SMarcel Holtmann return; 1634769be974SMarcel Holtmann 1635769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 1636769be974SMarcel Holtmann if (!cp) 1637769be974SMarcel Holtmann return; 1638769be974SMarcel Holtmann 1639769be974SMarcel Holtmann hci_dev_lock(hdev); 1640769be974SMarcel Holtmann 1641769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1642769be974SMarcel Holtmann if (conn) { 1643769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1644769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1645769be974SMarcel Holtmann hci_conn_put(conn); 1646769be974SMarcel Holtmann } 1647769be974SMarcel Holtmann } 1648769be974SMarcel Holtmann 1649769be974SMarcel Holtmann hci_dev_unlock(hdev); 1650769be974SMarcel Holtmann } 1651769be974SMarcel Holtmann 1652a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 1653a9de9248SMarcel Holtmann { 1654b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 1655b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 1656b6a0dc82SMarcel Holtmann __u16 handle; 1657b6a0dc82SMarcel Holtmann 16589f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1659b6a0dc82SMarcel Holtmann 1660b6a0dc82SMarcel Holtmann if (!status) 1661b6a0dc82SMarcel Holtmann return; 1662b6a0dc82SMarcel Holtmann 1663b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 1664b6a0dc82SMarcel Holtmann if (!cp) 1665b6a0dc82SMarcel Holtmann return; 1666b6a0dc82SMarcel Holtmann 1667b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 1668b6a0dc82SMarcel Holtmann 16699f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, handle); 1670b6a0dc82SMarcel Holtmann 1671b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 1672b6a0dc82SMarcel Holtmann 1673b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 16745a08ecceSAndrei Emeltchenko if (acl) { 16755a08ecceSAndrei Emeltchenko sco = acl->link; 16765a08ecceSAndrei Emeltchenko if (sco) { 1677b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 1678b6a0dc82SMarcel Holtmann 1679b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(sco, status); 1680b6a0dc82SMarcel Holtmann hci_conn_del(sco); 1681b6a0dc82SMarcel Holtmann } 16825a08ecceSAndrei Emeltchenko } 1683b6a0dc82SMarcel Holtmann 1684b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 1685a9de9248SMarcel Holtmann } 1686a9de9248SMarcel Holtmann 1687a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 1688a9de9248SMarcel Holtmann { 1689a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 169004837f64SMarcel Holtmann struct hci_conn *conn; 169104837f64SMarcel Holtmann 16929f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1693a9de9248SMarcel Holtmann 1694a9de9248SMarcel Holtmann if (!status) 1695a9de9248SMarcel Holtmann return; 1696a9de9248SMarcel Holtmann 1697a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 169804837f64SMarcel Holtmann if (!cp) 1699a9de9248SMarcel Holtmann return; 170004837f64SMarcel Holtmann 170104837f64SMarcel Holtmann hci_dev_lock(hdev); 170204837f64SMarcel Holtmann 170304837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1704e73439d8SMarcel Holtmann if (conn) { 170551a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 170604837f64SMarcel Holtmann 170751a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1708e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1709e73439d8SMarcel Holtmann } 1710e73439d8SMarcel Holtmann 171104837f64SMarcel Holtmann hci_dev_unlock(hdev); 171204837f64SMarcel Holtmann } 171304837f64SMarcel Holtmann 1714a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 1715a9de9248SMarcel Holtmann { 1716a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 171704837f64SMarcel Holtmann struct hci_conn *conn; 171804837f64SMarcel Holtmann 17199f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1720a9de9248SMarcel Holtmann 1721a9de9248SMarcel Holtmann if (!status) 1722a9de9248SMarcel Holtmann return; 1723a9de9248SMarcel Holtmann 1724a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 172504837f64SMarcel Holtmann if (!cp) 1726a9de9248SMarcel Holtmann return; 172704837f64SMarcel Holtmann 172804837f64SMarcel Holtmann hci_dev_lock(hdev); 172904837f64SMarcel Holtmann 173004837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1731e73439d8SMarcel Holtmann if (conn) { 173251a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 173304837f64SMarcel Holtmann 173451a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1735e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1736e73439d8SMarcel Holtmann } 1737e73439d8SMarcel Holtmann 173804837f64SMarcel Holtmann hci_dev_unlock(hdev); 173904837f64SMarcel Holtmann } 174004837f64SMarcel Holtmann 174188c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) 174288c3df13SJohan Hedberg { 174388c3df13SJohan Hedberg struct hci_cp_disconnect *cp; 174488c3df13SJohan Hedberg struct hci_conn *conn; 174588c3df13SJohan Hedberg 174688c3df13SJohan Hedberg if (!status) 174788c3df13SJohan Hedberg return; 174888c3df13SJohan Hedberg 174988c3df13SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT); 175088c3df13SJohan Hedberg if (!cp) 175188c3df13SJohan Hedberg return; 175288c3df13SJohan Hedberg 175388c3df13SJohan Hedberg hci_dev_lock(hdev); 175488c3df13SJohan Hedberg 175588c3df13SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 175688c3df13SJohan Hedberg if (conn) 175788c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 175888c3df13SJohan Hedberg conn->dst_type, status); 175988c3df13SJohan Hedberg 176088c3df13SJohan Hedberg hci_dev_unlock(hdev); 176188c3df13SJohan Hedberg } 176288c3df13SJohan Hedberg 1763fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) 1764fcd89c09SVille Tervo { 1765fcd89c09SVille Tervo struct hci_conn *conn; 1766fcd89c09SVille Tervo 17679f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1768fcd89c09SVille Tervo 1769f00a06acSAndre Guedes if (status) { 1770fcd89c09SVille Tervo hci_dev_lock(hdev); 1771fcd89c09SVille Tervo 17720c95ab78SAndre Guedes conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); 1773f00a06acSAndre Guedes if (!conn) { 1774f00a06acSAndre Guedes hci_dev_unlock(hdev); 1775f00a06acSAndre Guedes return; 1776f00a06acSAndre Guedes } 1777fcd89c09SVille Tervo 17786ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn); 1779fcd89c09SVille Tervo 1780fcd89c09SVille Tervo conn->state = BT_CLOSED; 17810c95ab78SAndre Guedes mgmt_connect_failed(hdev, &conn->dst, conn->type, 1782328c9248SHemant Gupta conn->dst_type, status); 1783fcd89c09SVille Tervo hci_proto_connect_cfm(conn, status); 1784fcd89c09SVille Tervo hci_conn_del(conn); 1785fcd89c09SVille Tervo 1786fcd89c09SVille Tervo hci_dev_unlock(hdev); 1787fcd89c09SVille Tervo } 1788f00a06acSAndre Guedes } 1789fcd89c09SVille Tervo 1790a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) 1791a7a595f6SVinicius Costa Gomes { 17929f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1793a7a595f6SVinicius Costa Gomes } 1794a7a595f6SVinicius Costa Gomes 1795a02226d6SAndrei Emeltchenko static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status) 1796a02226d6SAndrei Emeltchenko { 179793c284eeSAndrei Emeltchenko struct hci_cp_create_phy_link *cp; 179893c284eeSAndrei Emeltchenko 1799a02226d6SAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 180093c284eeSAndrei Emeltchenko 180193c284eeSAndrei Emeltchenko if (status) 180293c284eeSAndrei Emeltchenko return; 180393c284eeSAndrei Emeltchenko 180493c284eeSAndrei Emeltchenko cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK); 180593c284eeSAndrei Emeltchenko if (!cp) 180693c284eeSAndrei Emeltchenko return; 180793c284eeSAndrei Emeltchenko 180893c284eeSAndrei Emeltchenko amp_write_remote_assoc(hdev, cp->phy_handle); 1809a02226d6SAndrei Emeltchenko } 1810a02226d6SAndrei Emeltchenko 18110b26ab9dSAndrei Emeltchenko static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status) 18120b26ab9dSAndrei Emeltchenko { 18130b26ab9dSAndrei Emeltchenko struct hci_cp_accept_phy_link *cp; 18140b26ab9dSAndrei Emeltchenko 18150b26ab9dSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 18160b26ab9dSAndrei Emeltchenko 18170b26ab9dSAndrei Emeltchenko if (status) 18180b26ab9dSAndrei Emeltchenko return; 18190b26ab9dSAndrei Emeltchenko 18200b26ab9dSAndrei Emeltchenko cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK); 18210b26ab9dSAndrei Emeltchenko if (!cp) 18220b26ab9dSAndrei Emeltchenko return; 18230b26ab9dSAndrei Emeltchenko 18240b26ab9dSAndrei Emeltchenko amp_write_remote_assoc(hdev, cp->phy_handle); 18250b26ab9dSAndrei Emeltchenko } 18260b26ab9dSAndrei Emeltchenko 18276039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 18281da177e4SLinus Torvalds { 18291da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 183030dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 183130dc78e1SJohan Hedberg struct inquiry_entry *e; 18321da177e4SLinus Torvalds 18339f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 18341da177e4SLinus Torvalds 183523bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 18366bd57416SMarcel Holtmann 1837a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 183889352e7dSAndre Guedes 183989352e7dSAndre Guedes if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) 184089352e7dSAndre Guedes return; 184189352e7dSAndre Guedes 1842a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 184330dc78e1SJohan Hedberg return; 184430dc78e1SJohan Hedberg 184556e5cb86SJohan Hedberg hci_dev_lock(hdev); 184630dc78e1SJohan Hedberg 1847343f935bSAndre Guedes if (discov->state != DISCOVERY_FINDING) 184830dc78e1SJohan Hedberg goto unlock; 184930dc78e1SJohan Hedberg 185030dc78e1SJohan Hedberg if (list_empty(&discov->resolve)) { 1851ff9ef578SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 185230dc78e1SJohan Hedberg goto unlock; 185330dc78e1SJohan Hedberg } 185430dc78e1SJohan Hedberg 185530dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 185630dc78e1SJohan Hedberg if (e && hci_resolve_name(hdev, e) == 0) { 185730dc78e1SJohan Hedberg e->name_state = NAME_PENDING; 185830dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_RESOLVING); 185930dc78e1SJohan Hedberg } else { 186030dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 186130dc78e1SJohan Hedberg } 186230dc78e1SJohan Hedberg 186330dc78e1SJohan Hedberg unlock: 186456e5cb86SJohan Hedberg hci_dev_unlock(hdev); 18651da177e4SLinus Torvalds } 18661da177e4SLinus Torvalds 18676039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 18681da177e4SLinus Torvalds { 186945bb4bf0SMarcel Holtmann struct inquiry_data data; 1870a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 18711da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 18721da177e4SLinus Torvalds 18731da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 18741da177e4SLinus Torvalds 187545bb4bf0SMarcel Holtmann if (!num_rsp) 187645bb4bf0SMarcel Holtmann return; 187745bb4bf0SMarcel Holtmann 18781519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 18791519cc17SAndre Guedes return; 18801519cc17SAndre Guedes 18811da177e4SLinus Torvalds hci_dev_lock(hdev); 188245bb4bf0SMarcel Holtmann 1883e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 1884388fc8faSJohan Hedberg bool name_known, ssp; 18853175405bSJohan Hedberg 18861da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 18871da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 18881da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 18891da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 18901da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 18911da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 18921da177e4SLinus Torvalds data.rssi = 0x00; 189341a96212SMarcel Holtmann data.ssp_mode = 0x00; 18943175405bSJohan Hedberg 1895388fc8faSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp); 189648264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 189704124681SGustavo F. Padovan info->dev_class, 0, !name_known, ssp, NULL, 189804124681SGustavo F. Padovan 0); 18991da177e4SLinus Torvalds } 190045bb4bf0SMarcel Holtmann 19011da177e4SLinus Torvalds hci_dev_unlock(hdev); 19021da177e4SLinus Torvalds } 19031da177e4SLinus Torvalds 19046039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 19051da177e4SLinus Torvalds { 1906a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 1907a9de9248SMarcel Holtmann struct hci_conn *conn; 19081da177e4SLinus Torvalds 1909a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 191045bb4bf0SMarcel Holtmann 19111da177e4SLinus Torvalds hci_dev_lock(hdev); 191245bb4bf0SMarcel Holtmann 1913a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 19149499237aSMarcel Holtmann if (!conn) { 19159499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 19169499237aSMarcel Holtmann goto unlock; 19179499237aSMarcel Holtmann 19189499237aSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 1919a9de9248SMarcel Holtmann if (!conn) 1920a9de9248SMarcel Holtmann goto unlock; 192145bb4bf0SMarcel Holtmann 19229499237aSMarcel Holtmann conn->type = SCO_LINK; 19239499237aSMarcel Holtmann } 19249499237aSMarcel Holtmann 1925a9de9248SMarcel Holtmann if (!ev->status) { 1926a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 1927769be974SMarcel Holtmann 1928769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 1929769be974SMarcel Holtmann conn->state = BT_CONFIG; 1930769be974SMarcel Holtmann hci_conn_hold(conn); 1931a9ea3ed9SSzymon Janc 1932a9ea3ed9SSzymon Janc if (!conn->out && !hci_conn_ssp_enabled(conn) && 1933a9ea3ed9SSzymon Janc !hci_find_link_key(hdev, &ev->bdaddr)) 1934a9ea3ed9SSzymon Janc conn->disc_timeout = HCI_PAIRING_TIMEOUT; 1935a9ea3ed9SSzymon Janc else 1936052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1937769be974SMarcel Holtmann } else 1938a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 1939a9de9248SMarcel Holtmann 19409eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 19417d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 19427d0db0a3SMarcel Holtmann 1943a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 1944a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1945a9de9248SMarcel Holtmann 1946a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 1947a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1948a9de9248SMarcel Holtmann 1949a9de9248SMarcel Holtmann /* Get remote features */ 1950a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 1951a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 1952a9de9248SMarcel Holtmann cp.handle = ev->handle; 1953769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 1954769be974SMarcel Holtmann sizeof(cp), &cp); 195545bb4bf0SMarcel Holtmann } 1956a9de9248SMarcel Holtmann 1957a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 1958d095c1ebSAndrei Emeltchenko if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) { 1959a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 1960a9de9248SMarcel Holtmann cp.handle = ev->handle; 1961a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 196204124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp), 196304124681SGustavo F. Padovan &cp); 1964a9de9248SMarcel Holtmann } 196517d5c04cSJohan Hedberg } else { 1966a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 196717d5c04cSJohan Hedberg if (conn->type == ACL_LINK) 1968744cf19eSJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 196948264f06SJohan Hedberg conn->dst_type, ev->status); 197017d5c04cSJohan Hedberg } 197145bb4bf0SMarcel Holtmann 1972e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 1973e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 197445bb4bf0SMarcel Holtmann 1975769be974SMarcel Holtmann if (ev->status) { 1976a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1977a9de9248SMarcel Holtmann hci_conn_del(conn); 1978c89b6e6bSMarcel Holtmann } else if (ev->link_type != ACL_LINK) 1979c89b6e6bSMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1980a9de9248SMarcel Holtmann 1981a9de9248SMarcel Holtmann unlock: 19821da177e4SLinus Torvalds hci_dev_unlock(hdev); 1983a9de9248SMarcel Holtmann 1984a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 19851da177e4SLinus Torvalds } 19861da177e4SLinus Torvalds 19876039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 19881da177e4SLinus Torvalds { 1989a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 19901da177e4SLinus Torvalds int mask = hdev->link_mode; 19911da177e4SLinus Torvalds 19926ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr, 1993807deac2SGustavo Padovan ev->link_type); 19941da177e4SLinus Torvalds 19951da177e4SLinus Torvalds mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); 19961da177e4SLinus Torvalds 1997138d22efSSzymon Janc if ((mask & HCI_LM_ACCEPT) && 1998138d22efSSzymon Janc !hci_blacklist_lookup(hdev, &ev->bdaddr)) { 19991da177e4SLinus Torvalds /* Connection accepted */ 2000c7bdd502SMarcel Holtmann struct inquiry_entry *ie; 20011da177e4SLinus Torvalds struct hci_conn *conn; 20021da177e4SLinus Torvalds 20031da177e4SLinus Torvalds hci_dev_lock(hdev); 2004b6a0dc82SMarcel Holtmann 2005cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2006cc11b9c1SAndrei Emeltchenko if (ie) 2007c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 2008c7bdd502SMarcel Holtmann 20098fc9ced3SGustavo Padovan conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, 20108fc9ced3SGustavo Padovan &ev->bdaddr); 20111da177e4SLinus Torvalds if (!conn) { 2012cc11b9c1SAndrei Emeltchenko conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); 2013cc11b9c1SAndrei Emeltchenko if (!conn) { 2014893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 20151da177e4SLinus Torvalds hci_dev_unlock(hdev); 20161da177e4SLinus Torvalds return; 20171da177e4SLinus Torvalds } 20181da177e4SLinus Torvalds } 2019b6a0dc82SMarcel Holtmann 20201da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 20211da177e4SLinus Torvalds conn->state = BT_CONNECT; 2022b6a0dc82SMarcel Holtmann 20231da177e4SLinus Torvalds hci_dev_unlock(hdev); 20241da177e4SLinus Torvalds 2025b6a0dc82SMarcel Holtmann if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) { 2026b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 2027b6a0dc82SMarcel Holtmann 20281da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 20291da177e4SLinus Torvalds 20301da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 20311da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 20321da177e4SLinus Torvalds else 20331da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 20341da177e4SLinus Torvalds 203504124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), 203604124681SGustavo F. Padovan &cp); 2037b6a0dc82SMarcel Holtmann } else { 2038b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 2039b6a0dc82SMarcel Holtmann 2040b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 2041a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 2042b6a0dc82SMarcel Holtmann 204382781e63SAndrei Emeltchenko cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40); 204482781e63SAndrei Emeltchenko cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40); 204582781e63SAndrei Emeltchenko cp.max_latency = __constant_cpu_to_le16(0xffff); 2046b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 2047b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 2048b6a0dc82SMarcel Holtmann 2049b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 2050b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 2051b6a0dc82SMarcel Holtmann } 20521da177e4SLinus Torvalds } else { 20531da177e4SLinus Torvalds /* Connection rejected */ 20541da177e4SLinus Torvalds struct hci_cp_reject_conn_req cp; 20551da177e4SLinus Torvalds 20561da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 20579f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_REJ_BAD_ADDR; 2058a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 20591da177e4SLinus Torvalds } 20601da177e4SLinus Torvalds } 20611da177e4SLinus Torvalds 2062f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err) 2063f0d6a0eaSMikel Astiz { 2064f0d6a0eaSMikel Astiz switch (err) { 2065f0d6a0eaSMikel Astiz case HCI_ERROR_CONNECTION_TIMEOUT: 2066f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_TIMEOUT; 2067f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_USER_TERM: 2068f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_LOW_RESOURCES: 2069f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_POWER_OFF: 2070f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_REMOTE; 2071f0d6a0eaSMikel Astiz case HCI_ERROR_LOCAL_HOST_TERM: 2072f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_LOCAL_HOST; 2073f0d6a0eaSMikel Astiz default: 2074f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_UNKNOWN; 2075f0d6a0eaSMikel Astiz } 2076f0d6a0eaSMikel Astiz } 2077f0d6a0eaSMikel Astiz 20786039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 20791da177e4SLinus Torvalds { 2080a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 208104837f64SMarcel Holtmann struct hci_conn *conn; 20821da177e4SLinus Torvalds 20839f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 20841da177e4SLinus Torvalds 20851da177e4SLinus Torvalds hci_dev_lock(hdev); 20861da177e4SLinus Torvalds 208704837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2088f7520543SJohan Hedberg if (!conn) 2089f7520543SJohan Hedberg goto unlock; 2090f7520543SJohan Hedberg 209137d9ef76SJohan Hedberg if (ev->status == 0) 20921da177e4SLinus Torvalds conn->state = BT_CLOSED; 20937d0db0a3SMarcel Holtmann 2094b644ba33SJohan Hedberg if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) && 2095b644ba33SJohan Hedberg (conn->type == ACL_LINK || conn->type == LE_LINK)) { 2096f0d6a0eaSMikel Astiz if (ev->status) { 209788c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 209888c3df13SJohan Hedberg conn->dst_type, ev->status); 2099f0d6a0eaSMikel Astiz } else { 2100f0d6a0eaSMikel Astiz u8 reason = hci_to_mgmt_reason(ev->reason); 2101f0d6a0eaSMikel Astiz 2102afc747a6SJohan Hedberg mgmt_device_disconnected(hdev, &conn->dst, conn->type, 2103f0d6a0eaSMikel Astiz conn->dst_type, reason); 2104f0d6a0eaSMikel Astiz } 210537d9ef76SJohan Hedberg } 2106f7520543SJohan Hedberg 210737d9ef76SJohan Hedberg if (ev->status == 0) { 21086ec5bcadSVishal Agarwal if (conn->type == ACL_LINK && conn->flush_key) 21096ec5bcadSVishal Agarwal hci_remove_link_key(hdev, &conn->dst); 21102950f21aSMarcel Holtmann hci_proto_disconn_cfm(conn, ev->reason); 21111da177e4SLinus Torvalds hci_conn_del(conn); 211237d9ef76SJohan Hedberg } 21131da177e4SLinus Torvalds 2114f7520543SJohan Hedberg unlock: 21151da177e4SLinus Torvalds hci_dev_unlock(hdev); 21161da177e4SLinus Torvalds } 21171da177e4SLinus Torvalds 21186039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2119a9de9248SMarcel Holtmann { 2120a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 2121a9de9248SMarcel Holtmann struct hci_conn *conn; 2122a9de9248SMarcel Holtmann 21239f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2124a9de9248SMarcel Holtmann 2125a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2126a9de9248SMarcel Holtmann 2127a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2128d7556e20SWaldemar Rymarkiewicz if (!conn) 2129d7556e20SWaldemar Rymarkiewicz goto unlock; 2130d7556e20SWaldemar Rymarkiewicz 2131765c2a96SJohan Hedberg if (!ev->status) { 2132aa64a8b5SJohan Hedberg if (!hci_conn_ssp_enabled(conn) && 213351a8efd7SJohan Hedberg test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) { 2134d7556e20SWaldemar Rymarkiewicz BT_INFO("re-auth of legacy device is not possible."); 213519f8def0SWaldemar Rymarkiewicz } else { 2136a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 2137765c2a96SJohan Hedberg conn->sec_level = conn->pending_sec_level; 213819f8def0SWaldemar Rymarkiewicz } 21392a611692SJohan Hedberg } else { 2140bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 2141bab73cb6SJohan Hedberg ev->status); 21422a611692SJohan Hedberg } 2143a9de9248SMarcel Holtmann 214451a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 214551a8efd7SJohan Hedberg clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags); 2146a9de9248SMarcel Holtmann 2147f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 2148aa64a8b5SJohan Hedberg if (!ev->status && hci_conn_ssp_enabled(conn)) { 2149f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 2150f8558555SMarcel Holtmann cp.handle = ev->handle; 2151f8558555SMarcel Holtmann cp.encrypt = 0x01; 2152d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 2153d7556e20SWaldemar Rymarkiewicz &cp); 2154f8558555SMarcel Holtmann } else { 2155f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 2156f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2157f8558555SMarcel Holtmann hci_conn_put(conn); 2158f8558555SMarcel Holtmann } 2159052b30b0SMarcel Holtmann } else { 2160a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 2161a9de9248SMarcel Holtmann 2162052b30b0SMarcel Holtmann hci_conn_hold(conn); 2163052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2164052b30b0SMarcel Holtmann hci_conn_put(conn); 2165052b30b0SMarcel Holtmann } 2166052b30b0SMarcel Holtmann 216751a8efd7SJohan Hedberg if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) { 2168a9de9248SMarcel Holtmann if (!ev->status) { 2169a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 2170f8558555SMarcel Holtmann cp.handle = ev->handle; 2171f8558555SMarcel Holtmann cp.encrypt = 0x01; 2172d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 2173d7556e20SWaldemar Rymarkiewicz &cp); 2174a9de9248SMarcel Holtmann } else { 217551a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 2176a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 2177a9de9248SMarcel Holtmann } 2178a9de9248SMarcel Holtmann } 2179a9de9248SMarcel Holtmann 2180d7556e20SWaldemar Rymarkiewicz unlock: 2181a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2182a9de9248SMarcel Holtmann } 2183a9de9248SMarcel Holtmann 21846039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 2185a9de9248SMarcel Holtmann { 2186127178d2SJohan Hedberg struct hci_ev_remote_name *ev = (void *) skb->data; 2187127178d2SJohan Hedberg struct hci_conn *conn; 2188127178d2SJohan Hedberg 2189a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2190a9de9248SMarcel Holtmann 2191a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 2192127178d2SJohan Hedberg 2193127178d2SJohan Hedberg hci_dev_lock(hdev); 2194127178d2SJohan Hedberg 2195127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2196b644ba33SJohan Hedberg 2197b644ba33SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 2198b644ba33SJohan Hedberg goto check_auth; 2199b644ba33SJohan Hedberg 2200b644ba33SJohan Hedberg if (ev->status == 0) 2201b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name, 2202b644ba33SJohan Hedberg strnlen(ev->name, HCI_MAX_NAME_LENGTH)); 2203b644ba33SJohan Hedberg else 2204b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0); 2205b644ba33SJohan Hedberg 2206b644ba33SJohan Hedberg check_auth: 220779c6c70cSJohan Hedberg if (!conn) 220879c6c70cSJohan Hedberg goto unlock; 220979c6c70cSJohan Hedberg 221079c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 221179c6c70cSJohan Hedberg goto unlock; 221279c6c70cSJohan Hedberg 221351a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 2214127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 2215127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 2216127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 2217127178d2SJohan Hedberg } 2218127178d2SJohan Hedberg 221979c6c70cSJohan Hedberg unlock: 2220127178d2SJohan Hedberg hci_dev_unlock(hdev); 2221a9de9248SMarcel Holtmann } 2222a9de9248SMarcel Holtmann 22236039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2224a9de9248SMarcel Holtmann { 2225a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 2226a9de9248SMarcel Holtmann struct hci_conn *conn; 2227a9de9248SMarcel Holtmann 22289f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2229a9de9248SMarcel Holtmann 2230a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2231a9de9248SMarcel Holtmann 2232a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2233a9de9248SMarcel Holtmann if (conn) { 2234a9de9248SMarcel Holtmann if (!ev->status) { 2235ae293196SMarcel Holtmann if (ev->encrypt) { 2236ae293196SMarcel Holtmann /* Encryption implies authentication */ 2237ae293196SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 2238a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 2239da85e5e5SVinicius Costa Gomes conn->sec_level = conn->pending_sec_level; 2240ae293196SMarcel Holtmann } else 2241a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_ENCRYPT; 2242a9de9248SMarcel Holtmann } 2243a9de9248SMarcel Holtmann 224451a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 2245a9de9248SMarcel Holtmann 2246a7d7723aSGustavo Padovan if (ev->status && conn->state == BT_CONNECTED) { 2247d839c813SGustavo Padovan hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE); 2248a7d7723aSGustavo Padovan hci_conn_put(conn); 2249a7d7723aSGustavo Padovan goto unlock; 2250a7d7723aSGustavo Padovan } 2251a7d7723aSGustavo Padovan 2252f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 2253f8558555SMarcel Holtmann if (!ev->status) 2254f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 2255f8558555SMarcel Holtmann 2256f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2257f8558555SMarcel Holtmann hci_conn_put(conn); 2258f8558555SMarcel Holtmann } else 2259a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 2260a9de9248SMarcel Holtmann } 2261a9de9248SMarcel Holtmann 2262a7d7723aSGustavo Padovan unlock: 2263a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2264a9de9248SMarcel Holtmann } 2265a9de9248SMarcel Holtmann 22666039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev, 2267807deac2SGustavo Padovan struct sk_buff *skb) 2268a9de9248SMarcel Holtmann { 2269a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 2270a9de9248SMarcel Holtmann struct hci_conn *conn; 2271a9de9248SMarcel Holtmann 22729f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2273a9de9248SMarcel Holtmann 2274a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2275a9de9248SMarcel Holtmann 2276a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2277a9de9248SMarcel Holtmann if (conn) { 2278a9de9248SMarcel Holtmann if (!ev->status) 2279a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_SECURE; 2280a9de9248SMarcel Holtmann 228151a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 2282a9de9248SMarcel Holtmann 2283a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 2284a9de9248SMarcel Holtmann } 2285a9de9248SMarcel Holtmann 2286a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2287a9de9248SMarcel Holtmann } 2288a9de9248SMarcel Holtmann 22896039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev, 2290807deac2SGustavo Padovan struct sk_buff *skb) 2291a9de9248SMarcel Holtmann { 2292a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 2293a9de9248SMarcel Holtmann struct hci_conn *conn; 2294a9de9248SMarcel Holtmann 22959f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2296a9de9248SMarcel Holtmann 2297a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2298a9de9248SMarcel Holtmann 2299a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2300ccd556feSJohan Hedberg if (!conn) 2301ccd556feSJohan Hedberg goto unlock; 2302ccd556feSJohan Hedberg 2303769be974SMarcel Holtmann if (!ev->status) 2304a9de9248SMarcel Holtmann memcpy(conn->features, ev->features, 8); 2305a9de9248SMarcel Holtmann 2306ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2307ccd556feSJohan Hedberg goto unlock; 2308ccd556feSJohan Hedberg 2309ccd556feSJohan Hedberg if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { 2310769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 2311769be974SMarcel Holtmann cp.handle = ev->handle; 2312769be974SMarcel Holtmann cp.page = 0x01; 2313ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 2314769be974SMarcel Holtmann sizeof(cp), &cp); 2315392599b9SJohan Hedberg goto unlock; 2316392599b9SJohan Hedberg } 2317392599b9SJohan Hedberg 2318671267bfSJohan Hedberg if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { 2319127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2320127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2321127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2322127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2323127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2324b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 2325b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 232608c79b61SJohan Hedberg conn->dst_type, 0, NULL, 0, 2327b644ba33SJohan Hedberg conn->dev_class); 2328392599b9SJohan Hedberg 2329127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2330769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2331769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2332769be974SMarcel Holtmann hci_conn_put(conn); 2333769be974SMarcel Holtmann } 2334769be974SMarcel Holtmann 2335ccd556feSJohan Hedberg unlock: 2336a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2337a9de9248SMarcel Holtmann } 2338a9de9248SMarcel Holtmann 23396039aa73SGustavo Padovan static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) 23406039aa73SGustavo Padovan { 23416039aa73SGustavo Padovan BT_DBG("%s", hdev->name); 23426039aa73SGustavo Padovan } 23436039aa73SGustavo Padovan 23446039aa73SGustavo Padovan static void hci_qos_setup_complete_evt(struct hci_dev *hdev, 2345807deac2SGustavo Padovan struct sk_buff *skb) 2346a9de9248SMarcel Holtmann { 2347a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2348a9de9248SMarcel Holtmann } 2349a9de9248SMarcel Holtmann 23506039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2351a9de9248SMarcel Holtmann { 2352a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 2353a9de9248SMarcel Holtmann __u16 opcode; 2354a9de9248SMarcel Holtmann 2355a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2356a9de9248SMarcel Holtmann 2357a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2358a9de9248SMarcel Holtmann 2359a9de9248SMarcel Holtmann switch (opcode) { 2360a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 2361a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 2362a9de9248SMarcel Holtmann break; 2363a9de9248SMarcel Holtmann 23644d93483bSAndre Guedes case HCI_OP_PERIODIC_INQ: 23654d93483bSAndre Guedes hci_cc_periodic_inq(hdev, skb); 23664d93483bSAndre Guedes break; 23674d93483bSAndre Guedes 2368a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 2369a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 2370a9de9248SMarcel Holtmann break; 2371a9de9248SMarcel Holtmann 2372a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 2373a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 2374a9de9248SMarcel Holtmann break; 2375a9de9248SMarcel Holtmann 2376a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 2377a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 2378a9de9248SMarcel Holtmann break; 2379a9de9248SMarcel Holtmann 2380e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 2381e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 2382e4e8e37cSMarcel Holtmann break; 2383e4e8e37cSMarcel Holtmann 2384a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 2385a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 2386a9de9248SMarcel Holtmann break; 2387a9de9248SMarcel Holtmann 2388e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 2389e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 2390e4e8e37cSMarcel Holtmann break; 2391e4e8e37cSMarcel Holtmann 2392e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 2393e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 2394e4e8e37cSMarcel Holtmann break; 2395e4e8e37cSMarcel Holtmann 2396a9de9248SMarcel Holtmann case HCI_OP_RESET: 2397a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 2398a9de9248SMarcel Holtmann break; 2399a9de9248SMarcel Holtmann 2400a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 2401a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 2402a9de9248SMarcel Holtmann break; 2403a9de9248SMarcel Holtmann 2404a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 2405a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 2406a9de9248SMarcel Holtmann break; 2407a9de9248SMarcel Holtmann 2408a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 2409a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 2410a9de9248SMarcel Holtmann break; 2411a9de9248SMarcel Holtmann 2412a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 2413a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 2414a9de9248SMarcel Holtmann break; 2415a9de9248SMarcel Holtmann 2416a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 2417a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 2418a9de9248SMarcel Holtmann break; 2419a9de9248SMarcel Holtmann 2420a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 2421a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 2422a9de9248SMarcel Holtmann break; 2423a9de9248SMarcel Holtmann 2424a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 2425a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 2426a9de9248SMarcel Holtmann break; 2427a9de9248SMarcel Holtmann 2428a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 2429a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 2430a9de9248SMarcel Holtmann break; 2431a9de9248SMarcel Holtmann 2432a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 2433a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 2434a9de9248SMarcel Holtmann break; 2435a9de9248SMarcel Holtmann 2436a9de9248SMarcel Holtmann case HCI_OP_HOST_BUFFER_SIZE: 2437a9de9248SMarcel Holtmann hci_cc_host_buffer_size(hdev, skb); 2438a9de9248SMarcel Holtmann break; 2439a9de9248SMarcel Holtmann 2440333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 2441333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 2442333140b5SMarcel Holtmann break; 2443333140b5SMarcel Holtmann 2444a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 2445a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 2446a9de9248SMarcel Holtmann break; 2447a9de9248SMarcel Holtmann 2448a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 2449a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 2450a9de9248SMarcel Holtmann break; 2451a9de9248SMarcel Holtmann 2452a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 2453a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 2454a9de9248SMarcel Holtmann break; 2455a9de9248SMarcel Holtmann 2456971e3a4bSAndre Guedes case HCI_OP_READ_LOCAL_EXT_FEATURES: 2457971e3a4bSAndre Guedes hci_cc_read_local_ext_features(hdev, skb); 2458971e3a4bSAndre Guedes break; 2459971e3a4bSAndre Guedes 2460a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 2461a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 2462a9de9248SMarcel Holtmann break; 2463a9de9248SMarcel Holtmann 2464a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 2465a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 2466a9de9248SMarcel Holtmann break; 2467a9de9248SMarcel Holtmann 2468350ee4cfSAndrei Emeltchenko case HCI_OP_READ_DATA_BLOCK_SIZE: 2469350ee4cfSAndrei Emeltchenko hci_cc_read_data_block_size(hdev, skb); 2470350ee4cfSAndrei Emeltchenko break; 2471350ee4cfSAndrei Emeltchenko 247223bb5763SJohan Hedberg case HCI_OP_WRITE_CA_TIMEOUT: 247323bb5763SJohan Hedberg hci_cc_write_ca_timeout(hdev, skb); 247423bb5763SJohan Hedberg break; 247523bb5763SJohan Hedberg 24761e89cffbSAndrei Emeltchenko case HCI_OP_READ_FLOW_CONTROL_MODE: 24771e89cffbSAndrei Emeltchenko hci_cc_read_flow_control_mode(hdev, skb); 24781e89cffbSAndrei Emeltchenko break; 24791e89cffbSAndrei Emeltchenko 2480928abaa7SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_INFO: 2481928abaa7SAndrei Emeltchenko hci_cc_read_local_amp_info(hdev, skb); 2482928abaa7SAndrei Emeltchenko break; 2483928abaa7SAndrei Emeltchenko 2484903e4541SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_ASSOC: 2485903e4541SAndrei Emeltchenko hci_cc_read_local_amp_assoc(hdev, skb); 2486903e4541SAndrei Emeltchenko break; 2487903e4541SAndrei Emeltchenko 2488b0916ea0SJohan Hedberg case HCI_OP_DELETE_STORED_LINK_KEY: 2489b0916ea0SJohan Hedberg hci_cc_delete_stored_link_key(hdev, skb); 2490b0916ea0SJohan Hedberg break; 2491b0916ea0SJohan Hedberg 2492d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_MASK: 2493d5859e22SJohan Hedberg hci_cc_set_event_mask(hdev, skb); 2494d5859e22SJohan Hedberg break; 2495d5859e22SJohan Hedberg 2496d5859e22SJohan Hedberg case HCI_OP_WRITE_INQUIRY_MODE: 2497d5859e22SJohan Hedberg hci_cc_write_inquiry_mode(hdev, skb); 2498d5859e22SJohan Hedberg break; 2499d5859e22SJohan Hedberg 2500d5859e22SJohan Hedberg case HCI_OP_READ_INQ_RSP_TX_POWER: 2501d5859e22SJohan Hedberg hci_cc_read_inq_rsp_tx_power(hdev, skb); 2502d5859e22SJohan Hedberg break; 2503d5859e22SJohan Hedberg 2504d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_FLT: 2505d5859e22SJohan Hedberg hci_cc_set_event_flt(hdev, skb); 2506d5859e22SJohan Hedberg break; 2507d5859e22SJohan Hedberg 2508980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_REPLY: 2509980e1a53SJohan Hedberg hci_cc_pin_code_reply(hdev, skb); 2510980e1a53SJohan Hedberg break; 2511980e1a53SJohan Hedberg 2512980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_NEG_REPLY: 2513980e1a53SJohan Hedberg hci_cc_pin_code_neg_reply(hdev, skb); 2514980e1a53SJohan Hedberg break; 2515980e1a53SJohan Hedberg 2516c35938b2SSzymon Janc case HCI_OP_READ_LOCAL_OOB_DATA: 2517c35938b2SSzymon Janc hci_cc_read_local_oob_data_reply(hdev, skb); 2518c35938b2SSzymon Janc break; 2519c35938b2SSzymon Janc 25206ed58ec5SVille Tervo case HCI_OP_LE_READ_BUFFER_SIZE: 25216ed58ec5SVille Tervo hci_cc_le_read_buffer_size(hdev, skb); 25226ed58ec5SVille Tervo break; 25236ed58ec5SVille Tervo 25248fa19098SJohan Hedberg case HCI_OP_LE_READ_ADV_TX_POWER: 25258fa19098SJohan Hedberg hci_cc_le_read_adv_tx_power(hdev, skb); 25268fa19098SJohan Hedberg break; 25278fa19098SJohan Hedberg 2528e36b04c8SJohan Hedberg case HCI_OP_LE_SET_EVENT_MASK: 2529e36b04c8SJohan Hedberg hci_cc_le_set_event_mask(hdev, skb); 2530e36b04c8SJohan Hedberg break; 2531e36b04c8SJohan Hedberg 2532a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_REPLY: 2533a5c29683SJohan Hedberg hci_cc_user_confirm_reply(hdev, skb); 2534a5c29683SJohan Hedberg break; 2535a5c29683SJohan Hedberg 2536a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_NEG_REPLY: 2537a5c29683SJohan Hedberg hci_cc_user_confirm_neg_reply(hdev, skb); 2538a5c29683SJohan Hedberg break; 2539a5c29683SJohan Hedberg 25401143d458SBrian Gix case HCI_OP_USER_PASSKEY_REPLY: 25411143d458SBrian Gix hci_cc_user_passkey_reply(hdev, skb); 25421143d458SBrian Gix break; 25431143d458SBrian Gix 25441143d458SBrian Gix case HCI_OP_USER_PASSKEY_NEG_REPLY: 25451143d458SBrian Gix hci_cc_user_passkey_neg_reply(hdev, skb); 254616cde993SSzymon Janc break; 254707f7fa5dSAndre Guedes 254807f7fa5dSAndre Guedes case HCI_OP_LE_SET_SCAN_PARAM: 254907f7fa5dSAndre Guedes hci_cc_le_set_scan_param(hdev, skb); 25501143d458SBrian Gix break; 25511143d458SBrian Gix 2552eb9d91f5SAndre Guedes case HCI_OP_LE_SET_SCAN_ENABLE: 2553eb9d91f5SAndre Guedes hci_cc_le_set_scan_enable(hdev, skb); 2554eb9d91f5SAndre Guedes break; 2555eb9d91f5SAndre Guedes 2556a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_REPLY: 2557a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_reply(hdev, skb); 2558a7a595f6SVinicius Costa Gomes break; 2559a7a595f6SVinicius Costa Gomes 2560a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_NEG_REPLY: 2561a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_neg_reply(hdev, skb); 2562a7a595f6SVinicius Costa Gomes break; 2563a7a595f6SVinicius Costa Gomes 2564f9b49306SAndre Guedes case HCI_OP_WRITE_LE_HOST_SUPPORTED: 2565f9b49306SAndre Guedes hci_cc_write_le_host_supported(hdev, skb); 2566f9b49306SAndre Guedes break; 2567f9b49306SAndre Guedes 256893c284eeSAndrei Emeltchenko case HCI_OP_WRITE_REMOTE_AMP_ASSOC: 256993c284eeSAndrei Emeltchenko hci_cc_write_remote_amp_assoc(hdev, skb); 257093c284eeSAndrei Emeltchenko break; 257193c284eeSAndrei Emeltchenko 2572a9de9248SMarcel Holtmann default: 25739f1db00cSAndrei Emeltchenko BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); 2574a9de9248SMarcel Holtmann break; 2575a9de9248SMarcel Holtmann } 2576a9de9248SMarcel Holtmann 25776bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 25786bd32326SVille Tervo del_timer(&hdev->cmd_timer); 25796bd32326SVille Tervo 2580a9de9248SMarcel Holtmann if (ev->ncmd) { 2581a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2582a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2583c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2584a9de9248SMarcel Holtmann } 2585a9de9248SMarcel Holtmann } 2586a9de9248SMarcel Holtmann 25876039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 2588a9de9248SMarcel Holtmann { 2589a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 2590a9de9248SMarcel Holtmann __u16 opcode; 2591a9de9248SMarcel Holtmann 2592a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2593a9de9248SMarcel Holtmann 2594a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2595a9de9248SMarcel Holtmann 2596a9de9248SMarcel Holtmann switch (opcode) { 2597a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 2598a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 2599a9de9248SMarcel Holtmann break; 2600a9de9248SMarcel Holtmann 2601a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 2602a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 2603a9de9248SMarcel Holtmann break; 2604a9de9248SMarcel Holtmann 2605a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 2606a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 2607a9de9248SMarcel Holtmann break; 2608a9de9248SMarcel Holtmann 2609f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 2610f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 2611f8558555SMarcel Holtmann break; 2612f8558555SMarcel Holtmann 2613f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 2614f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 2615f8558555SMarcel Holtmann break; 2616f8558555SMarcel Holtmann 2617a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 2618a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 2619a9de9248SMarcel Holtmann break; 2620a9de9248SMarcel Holtmann 2621769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 2622769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 2623769be974SMarcel Holtmann break; 2624769be974SMarcel Holtmann 2625769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 2626769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 2627769be974SMarcel Holtmann break; 2628769be974SMarcel Holtmann 2629a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 2630a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 2631a9de9248SMarcel Holtmann break; 2632a9de9248SMarcel Holtmann 2633a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 2634a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 2635a9de9248SMarcel Holtmann break; 2636a9de9248SMarcel Holtmann 2637a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 2638a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 2639a9de9248SMarcel Holtmann break; 2640a9de9248SMarcel Holtmann 26418962ee74SJohan Hedberg case HCI_OP_DISCONNECT: 264288c3df13SJohan Hedberg hci_cs_disconnect(hdev, ev->status); 26438962ee74SJohan Hedberg break; 26448962ee74SJohan Hedberg 2645fcd89c09SVille Tervo case HCI_OP_LE_CREATE_CONN: 2646fcd89c09SVille Tervo hci_cs_le_create_conn(hdev, ev->status); 2647fcd89c09SVille Tervo break; 2648fcd89c09SVille Tervo 2649a7a595f6SVinicius Costa Gomes case HCI_OP_LE_START_ENC: 2650a7a595f6SVinicius Costa Gomes hci_cs_le_start_enc(hdev, ev->status); 2651a7a595f6SVinicius Costa Gomes break; 2652a7a595f6SVinicius Costa Gomes 2653a02226d6SAndrei Emeltchenko case HCI_OP_CREATE_PHY_LINK: 2654a02226d6SAndrei Emeltchenko hci_cs_create_phylink(hdev, ev->status); 2655a02226d6SAndrei Emeltchenko break; 2656a02226d6SAndrei Emeltchenko 26570b26ab9dSAndrei Emeltchenko case HCI_OP_ACCEPT_PHY_LINK: 26580b26ab9dSAndrei Emeltchenko hci_cs_accept_phylink(hdev, ev->status); 26590b26ab9dSAndrei Emeltchenko break; 26600b26ab9dSAndrei Emeltchenko 2661a9de9248SMarcel Holtmann default: 26629f1db00cSAndrei Emeltchenko BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); 2663a9de9248SMarcel Holtmann break; 2664a9de9248SMarcel Holtmann } 2665a9de9248SMarcel Holtmann 26666bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 26676bd32326SVille Tervo del_timer(&hdev->cmd_timer); 26686bd32326SVille Tervo 266910572132SGustavo F. Padovan if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2670a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2671a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2672c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2673a9de9248SMarcel Holtmann } 2674a9de9248SMarcel Holtmann } 2675a9de9248SMarcel Holtmann 26766039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2677a9de9248SMarcel Holtmann { 2678a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 2679a9de9248SMarcel Holtmann struct hci_conn *conn; 2680a9de9248SMarcel Holtmann 26819f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2682a9de9248SMarcel Holtmann 2683a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2684a9de9248SMarcel Holtmann 2685a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2686a9de9248SMarcel Holtmann if (conn) { 2687a9de9248SMarcel Holtmann if (!ev->status) { 2688a9de9248SMarcel Holtmann if (ev->role) 2689a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_MASTER; 2690a9de9248SMarcel Holtmann else 2691a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_MASTER; 2692a9de9248SMarcel Holtmann } 2693a9de9248SMarcel Holtmann 269451a8efd7SJohan Hedberg clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); 2695a9de9248SMarcel Holtmann 2696a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 2697a9de9248SMarcel Holtmann } 2698a9de9248SMarcel Holtmann 2699a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2700a9de9248SMarcel Holtmann } 2701a9de9248SMarcel Holtmann 27026039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 27031da177e4SLinus Torvalds { 2704a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 27051da177e4SLinus Torvalds int i; 27061da177e4SLinus Torvalds 270732ac5b9bSAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) { 270832ac5b9bSAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 270932ac5b9bSAndrei Emeltchenko return; 271032ac5b9bSAndrei Emeltchenko } 271132ac5b9bSAndrei Emeltchenko 2712c5993de8SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 2713c5993de8SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_pkts_info)) { 27141da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 27151da177e4SLinus Torvalds return; 27161da177e4SLinus Torvalds } 27171da177e4SLinus Torvalds 2718c5993de8SAndrei Emeltchenko BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 2719c5993de8SAndrei Emeltchenko 2720613a1c0cSAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 2721613a1c0cSAndrei Emeltchenko struct hci_comp_pkts_info *info = &ev->handles[i]; 27221da177e4SLinus Torvalds struct hci_conn *conn; 27231da177e4SLinus Torvalds __u16 handle, count; 27241da177e4SLinus Torvalds 2725613a1c0cSAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 2726613a1c0cSAndrei Emeltchenko count = __le16_to_cpu(info->count); 27271da177e4SLinus Torvalds 27281da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 2729f4280918SAndrei Emeltchenko if (!conn) 2730f4280918SAndrei Emeltchenko continue; 2731f4280918SAndrei Emeltchenko 27321da177e4SLinus Torvalds conn->sent -= count; 27331da177e4SLinus Torvalds 2734f4280918SAndrei Emeltchenko switch (conn->type) { 2735f4280918SAndrei Emeltchenko case ACL_LINK: 273670f23020SAndrei Emeltchenko hdev->acl_cnt += count; 273770f23020SAndrei Emeltchenko if (hdev->acl_cnt > hdev->acl_pkts) 27381da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 2739f4280918SAndrei Emeltchenko break; 2740f4280918SAndrei Emeltchenko 2741f4280918SAndrei Emeltchenko case LE_LINK: 27426ed58ec5SVille Tervo if (hdev->le_pkts) { 27436ed58ec5SVille Tervo hdev->le_cnt += count; 27446ed58ec5SVille Tervo if (hdev->le_cnt > hdev->le_pkts) 27456ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 27466ed58ec5SVille Tervo } else { 27476ed58ec5SVille Tervo hdev->acl_cnt += count; 27486ed58ec5SVille Tervo if (hdev->acl_cnt > hdev->acl_pkts) 27496ed58ec5SVille Tervo hdev->acl_cnt = hdev->acl_pkts; 27506ed58ec5SVille Tervo } 2751f4280918SAndrei Emeltchenko break; 2752f4280918SAndrei Emeltchenko 2753f4280918SAndrei Emeltchenko case SCO_LINK: 275470f23020SAndrei Emeltchenko hdev->sco_cnt += count; 275570f23020SAndrei Emeltchenko if (hdev->sco_cnt > hdev->sco_pkts) 27565b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 2757f4280918SAndrei Emeltchenko break; 2758f4280918SAndrei Emeltchenko 2759f4280918SAndrei Emeltchenko default: 2760f4280918SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 2761f4280918SAndrei Emeltchenko break; 27621da177e4SLinus Torvalds } 27631da177e4SLinus Torvalds } 2764a9de9248SMarcel Holtmann 27653eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 27661da177e4SLinus Torvalds } 27671da177e4SLinus Torvalds 276876ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev, 276976ef7cf7SAndrei Emeltchenko __u16 handle) 277076ef7cf7SAndrei Emeltchenko { 277176ef7cf7SAndrei Emeltchenko struct hci_chan *chan; 277276ef7cf7SAndrei Emeltchenko 277376ef7cf7SAndrei Emeltchenko switch (hdev->dev_type) { 277476ef7cf7SAndrei Emeltchenko case HCI_BREDR: 277576ef7cf7SAndrei Emeltchenko return hci_conn_hash_lookup_handle(hdev, handle); 277676ef7cf7SAndrei Emeltchenko case HCI_AMP: 277776ef7cf7SAndrei Emeltchenko chan = hci_chan_lookup_handle(hdev, handle); 277876ef7cf7SAndrei Emeltchenko if (chan) 277976ef7cf7SAndrei Emeltchenko return chan->conn; 278076ef7cf7SAndrei Emeltchenko break; 278176ef7cf7SAndrei Emeltchenko default: 278276ef7cf7SAndrei Emeltchenko BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type); 278376ef7cf7SAndrei Emeltchenko break; 278476ef7cf7SAndrei Emeltchenko } 278576ef7cf7SAndrei Emeltchenko 278676ef7cf7SAndrei Emeltchenko return NULL; 278776ef7cf7SAndrei Emeltchenko } 278876ef7cf7SAndrei Emeltchenko 27896039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb) 279025e89e99SAndrei Emeltchenko { 279125e89e99SAndrei Emeltchenko struct hci_ev_num_comp_blocks *ev = (void *) skb->data; 279225e89e99SAndrei Emeltchenko int i; 279325e89e99SAndrei Emeltchenko 279425e89e99SAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) { 279525e89e99SAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 279625e89e99SAndrei Emeltchenko return; 279725e89e99SAndrei Emeltchenko } 279825e89e99SAndrei Emeltchenko 279925e89e99SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 280025e89e99SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_blocks_info)) { 280125e89e99SAndrei Emeltchenko BT_DBG("%s bad parameters", hdev->name); 280225e89e99SAndrei Emeltchenko return; 280325e89e99SAndrei Emeltchenko } 280425e89e99SAndrei Emeltchenko 280525e89e99SAndrei Emeltchenko BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks, 280625e89e99SAndrei Emeltchenko ev->num_hndl); 280725e89e99SAndrei Emeltchenko 280825e89e99SAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 280925e89e99SAndrei Emeltchenko struct hci_comp_blocks_info *info = &ev->handles[i]; 281076ef7cf7SAndrei Emeltchenko struct hci_conn *conn = NULL; 281125e89e99SAndrei Emeltchenko __u16 handle, block_count; 281225e89e99SAndrei Emeltchenko 281325e89e99SAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 281425e89e99SAndrei Emeltchenko block_count = __le16_to_cpu(info->blocks); 281525e89e99SAndrei Emeltchenko 281676ef7cf7SAndrei Emeltchenko conn = __hci_conn_lookup_handle(hdev, handle); 281725e89e99SAndrei Emeltchenko if (!conn) 281825e89e99SAndrei Emeltchenko continue; 281925e89e99SAndrei Emeltchenko 282025e89e99SAndrei Emeltchenko conn->sent -= block_count; 282125e89e99SAndrei Emeltchenko 282225e89e99SAndrei Emeltchenko switch (conn->type) { 282325e89e99SAndrei Emeltchenko case ACL_LINK: 2824bd1eb66bSAndrei Emeltchenko case AMP_LINK: 282525e89e99SAndrei Emeltchenko hdev->block_cnt += block_count; 282625e89e99SAndrei Emeltchenko if (hdev->block_cnt > hdev->num_blocks) 282725e89e99SAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 282825e89e99SAndrei Emeltchenko break; 282925e89e99SAndrei Emeltchenko 283025e89e99SAndrei Emeltchenko default: 283125e89e99SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 283225e89e99SAndrei Emeltchenko break; 283325e89e99SAndrei Emeltchenko } 283425e89e99SAndrei Emeltchenko } 283525e89e99SAndrei Emeltchenko 283625e89e99SAndrei Emeltchenko queue_work(hdev->workqueue, &hdev->tx_work); 283725e89e99SAndrei Emeltchenko } 283825e89e99SAndrei Emeltchenko 28396039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 28401da177e4SLinus Torvalds { 2841a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 284204837f64SMarcel Holtmann struct hci_conn *conn; 28431da177e4SLinus Torvalds 28449f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 28451da177e4SLinus Torvalds 28461da177e4SLinus Torvalds hci_dev_lock(hdev); 28471da177e4SLinus Torvalds 284804837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 284904837f64SMarcel Holtmann if (conn) { 285004837f64SMarcel Holtmann conn->mode = ev->mode; 285104837f64SMarcel Holtmann conn->interval = __le16_to_cpu(ev->interval); 285204837f64SMarcel Holtmann 28538fc9ced3SGustavo Padovan if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, 28548fc9ced3SGustavo Padovan &conn->flags)) { 285504837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 285658a681efSJohan Hedberg set_bit(HCI_CONN_POWER_SAVE, &conn->flags); 285704837f64SMarcel Holtmann else 285858a681efSJohan Hedberg clear_bit(HCI_CONN_POWER_SAVE, &conn->flags); 285904837f64SMarcel Holtmann } 2860e73439d8SMarcel Holtmann 286151a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 2862e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 286304837f64SMarcel Holtmann } 286404837f64SMarcel Holtmann 286504837f64SMarcel Holtmann hci_dev_unlock(hdev); 286604837f64SMarcel Holtmann } 286704837f64SMarcel Holtmann 28686039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 28691da177e4SLinus Torvalds { 2870052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 2871052b30b0SMarcel Holtmann struct hci_conn *conn; 2872052b30b0SMarcel Holtmann 2873a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2874052b30b0SMarcel Holtmann 2875052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2876052b30b0SMarcel Holtmann 2877052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2878b6f98044SWaldemar Rymarkiewicz if (!conn) 2879b6f98044SWaldemar Rymarkiewicz goto unlock; 2880b6f98044SWaldemar Rymarkiewicz 2881b6f98044SWaldemar Rymarkiewicz if (conn->state == BT_CONNECTED) { 2882052b30b0SMarcel Holtmann hci_conn_hold(conn); 2883052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 2884052b30b0SMarcel Holtmann hci_conn_put(conn); 2885052b30b0SMarcel Holtmann } 2886052b30b0SMarcel Holtmann 2887a8b2d5c2SJohan Hedberg if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags)) 288803b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 288903b555e1SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 2890a8b2d5c2SJohan Hedberg else if (test_bit(HCI_MGMT, &hdev->dev_flags)) { 2891a770bb5aSWaldemar Rymarkiewicz u8 secure; 2892a770bb5aSWaldemar Rymarkiewicz 2893a770bb5aSWaldemar Rymarkiewicz if (conn->pending_sec_level == BT_SECURITY_HIGH) 2894a770bb5aSWaldemar Rymarkiewicz secure = 1; 2895a770bb5aSWaldemar Rymarkiewicz else 2896a770bb5aSWaldemar Rymarkiewicz secure = 0; 2897a770bb5aSWaldemar Rymarkiewicz 2898744cf19eSJohan Hedberg mgmt_pin_code_request(hdev, &ev->bdaddr, secure); 2899a770bb5aSWaldemar Rymarkiewicz } 2900980e1a53SJohan Hedberg 2901b6f98044SWaldemar Rymarkiewicz unlock: 2902052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 29031da177e4SLinus Torvalds } 29041da177e4SLinus Torvalds 29056039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 29061da177e4SLinus Torvalds { 290755ed8ca1SJohan Hedberg struct hci_ev_link_key_req *ev = (void *) skb->data; 290855ed8ca1SJohan Hedberg struct hci_cp_link_key_reply cp; 290955ed8ca1SJohan Hedberg struct hci_conn *conn; 291055ed8ca1SJohan Hedberg struct link_key *key; 291155ed8ca1SJohan Hedberg 2912a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 291355ed8ca1SJohan Hedberg 2914a8b2d5c2SJohan Hedberg if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) 291555ed8ca1SJohan Hedberg return; 291655ed8ca1SJohan Hedberg 291755ed8ca1SJohan Hedberg hci_dev_lock(hdev); 291855ed8ca1SJohan Hedberg 291955ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, &ev->bdaddr); 292055ed8ca1SJohan Hedberg if (!key) { 29216ed93dc6SAndrei Emeltchenko BT_DBG("%s link key not found for %pMR", hdev->name, 29226ed93dc6SAndrei Emeltchenko &ev->bdaddr); 292355ed8ca1SJohan Hedberg goto not_found; 292455ed8ca1SJohan Hedberg } 292555ed8ca1SJohan Hedberg 29266ed93dc6SAndrei Emeltchenko BT_DBG("%s found key type %u for %pMR", hdev->name, key->type, 29276ed93dc6SAndrei Emeltchenko &ev->bdaddr); 292855ed8ca1SJohan Hedberg 2929a8b2d5c2SJohan Hedberg if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) && 2930b6020ba0SWaldemar Rymarkiewicz key->type == HCI_LK_DEBUG_COMBINATION) { 293155ed8ca1SJohan Hedberg BT_DBG("%s ignoring debug key", hdev->name); 293255ed8ca1SJohan Hedberg goto not_found; 293355ed8ca1SJohan Hedberg } 293455ed8ca1SJohan Hedberg 293555ed8ca1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 293660b83f57SWaldemar Rymarkiewicz if (conn) { 293760b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_UNAUTH_COMBINATION && 2938807deac2SGustavo Padovan conn->auth_type != 0xff && (conn->auth_type & 0x01)) { 293955ed8ca1SJohan Hedberg BT_DBG("%s ignoring unauthenticated key", hdev->name); 294055ed8ca1SJohan Hedberg goto not_found; 294155ed8ca1SJohan Hedberg } 294255ed8ca1SJohan Hedberg 294360b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && 294460b83f57SWaldemar Rymarkiewicz conn->pending_sec_level == BT_SECURITY_HIGH) { 29458fc9ced3SGustavo Padovan BT_DBG("%s ignoring key unauthenticated for high security", 29468fc9ced3SGustavo Padovan hdev->name); 294760b83f57SWaldemar Rymarkiewicz goto not_found; 294860b83f57SWaldemar Rymarkiewicz } 294960b83f57SWaldemar Rymarkiewicz 295060b83f57SWaldemar Rymarkiewicz conn->key_type = key->type; 295160b83f57SWaldemar Rymarkiewicz conn->pin_length = key->pin_len; 295260b83f57SWaldemar Rymarkiewicz } 295360b83f57SWaldemar Rymarkiewicz 295455ed8ca1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 29559b3b4460SAndrei Emeltchenko memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE); 295655ed8ca1SJohan Hedberg 295755ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 295855ed8ca1SJohan Hedberg 295955ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 296055ed8ca1SJohan Hedberg 296155ed8ca1SJohan Hedberg return; 296255ed8ca1SJohan Hedberg 296355ed8ca1SJohan Hedberg not_found: 296455ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 296555ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 29661da177e4SLinus Torvalds } 29671da177e4SLinus Torvalds 29686039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 29691da177e4SLinus Torvalds { 2970052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 2971052b30b0SMarcel Holtmann struct hci_conn *conn; 297255ed8ca1SJohan Hedberg u8 pin_len = 0; 2973052b30b0SMarcel Holtmann 2974a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2975052b30b0SMarcel Holtmann 2976052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2977052b30b0SMarcel Holtmann 2978052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2979052b30b0SMarcel Holtmann if (conn) { 2980052b30b0SMarcel Holtmann hci_conn_hold(conn); 2981052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2982980e1a53SJohan Hedberg pin_len = conn->pin_length; 298313d39315SWaldemar Rymarkiewicz 298413d39315SWaldemar Rymarkiewicz if (ev->key_type != HCI_LK_CHANGED_COMBINATION) 298513d39315SWaldemar Rymarkiewicz conn->key_type = ev->key_type; 298613d39315SWaldemar Rymarkiewicz 2987052b30b0SMarcel Holtmann hci_conn_put(conn); 2988052b30b0SMarcel Holtmann } 2989052b30b0SMarcel Holtmann 2990a8b2d5c2SJohan Hedberg if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) 2991d25e28abSJohan Hedberg hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, 299255ed8ca1SJohan Hedberg ev->key_type, pin_len); 299355ed8ca1SJohan Hedberg 2994052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 29951da177e4SLinus Torvalds } 29961da177e4SLinus Torvalds 29976039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 299804837f64SMarcel Holtmann { 2999a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 300004837f64SMarcel Holtmann struct hci_conn *conn; 300104837f64SMarcel Holtmann 30029f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 300304837f64SMarcel Holtmann 300404837f64SMarcel Holtmann hci_dev_lock(hdev); 300504837f64SMarcel Holtmann 300604837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 30071da177e4SLinus Torvalds if (conn && !ev->status) { 30081da177e4SLinus Torvalds struct inquiry_entry *ie; 30091da177e4SLinus Torvalds 3010cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 3011cc11b9c1SAndrei Emeltchenko if (ie) { 30121da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 30131da177e4SLinus Torvalds ie->timestamp = jiffies; 30141da177e4SLinus Torvalds } 30151da177e4SLinus Torvalds } 30161da177e4SLinus Torvalds 30171da177e4SLinus Torvalds hci_dev_unlock(hdev); 30181da177e4SLinus Torvalds } 30191da177e4SLinus Torvalds 30206039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 3021a8746417SMarcel Holtmann { 3022a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 3023a8746417SMarcel Holtmann struct hci_conn *conn; 3024a8746417SMarcel Holtmann 30259f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 3026a8746417SMarcel Holtmann 3027a8746417SMarcel Holtmann hci_dev_lock(hdev); 3028a8746417SMarcel Holtmann 3029a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3030a8746417SMarcel Holtmann if (conn && !ev->status) 3031a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 3032a8746417SMarcel Holtmann 3033a8746417SMarcel Holtmann hci_dev_unlock(hdev); 3034a8746417SMarcel Holtmann } 3035a8746417SMarcel Holtmann 30366039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 303785a1e930SMarcel Holtmann { 3038a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 303985a1e930SMarcel Holtmann struct inquiry_entry *ie; 304085a1e930SMarcel Holtmann 304185a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 304285a1e930SMarcel Holtmann 304385a1e930SMarcel Holtmann hci_dev_lock(hdev); 304485a1e930SMarcel Holtmann 3045cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 3046cc11b9c1SAndrei Emeltchenko if (ie) { 304785a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 304885a1e930SMarcel Holtmann ie->timestamp = jiffies; 304985a1e930SMarcel Holtmann } 305085a1e930SMarcel Holtmann 305185a1e930SMarcel Holtmann hci_dev_unlock(hdev); 305285a1e930SMarcel Holtmann } 305385a1e930SMarcel Holtmann 30546039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, 3055807deac2SGustavo Padovan struct sk_buff *skb) 3056a9de9248SMarcel Holtmann { 3057a9de9248SMarcel Holtmann struct inquiry_data data; 3058a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 3059388fc8faSJohan Hedberg bool name_known, ssp; 3060a9de9248SMarcel Holtmann 3061a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 3062a9de9248SMarcel Holtmann 3063a9de9248SMarcel Holtmann if (!num_rsp) 3064a9de9248SMarcel Holtmann return; 3065a9de9248SMarcel Holtmann 30661519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 30671519cc17SAndre Guedes return; 30681519cc17SAndre Guedes 3069a9de9248SMarcel Holtmann hci_dev_lock(hdev); 3070a9de9248SMarcel Holtmann 3071a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 3072138d22efSSzymon Janc struct inquiry_info_with_rssi_and_pscan_mode *info; 3073138d22efSSzymon Janc info = (void *) (skb->data + 1); 3074a9de9248SMarcel Holtmann 3075e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 3076a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 3077a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 3078a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 3079a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 3080a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 3081a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 3082a9de9248SMarcel Holtmann data.rssi = info->rssi; 308341a96212SMarcel Holtmann data.ssp_mode = 0x00; 30843175405bSJohan Hedberg 30853175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 3086388fc8faSJohan Hedberg false, &ssp); 308748264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 3088e17acd40SJohan Hedberg info->dev_class, info->rssi, 3089388fc8faSJohan Hedberg !name_known, ssp, NULL, 0); 3090a9de9248SMarcel Holtmann } 3091a9de9248SMarcel Holtmann } else { 3092a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 3093a9de9248SMarcel Holtmann 3094e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 3095a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 3096a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 3097a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 3098a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 3099a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 3100a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 3101a9de9248SMarcel Holtmann data.rssi = info->rssi; 310241a96212SMarcel Holtmann data.ssp_mode = 0x00; 31033175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 3104388fc8faSJohan Hedberg false, &ssp); 310548264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 3106e17acd40SJohan Hedberg info->dev_class, info->rssi, 3107388fc8faSJohan Hedberg !name_known, ssp, NULL, 0); 3108a9de9248SMarcel Holtmann } 3109a9de9248SMarcel Holtmann } 3110a9de9248SMarcel Holtmann 3111a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 3112a9de9248SMarcel Holtmann } 3113a9de9248SMarcel Holtmann 31146039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev, 3115807deac2SGustavo Padovan struct sk_buff *skb) 3116a9de9248SMarcel Holtmann { 311741a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 311841a96212SMarcel Holtmann struct hci_conn *conn; 311941a96212SMarcel Holtmann 3120a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 312141a96212SMarcel Holtmann 312241a96212SMarcel Holtmann hci_dev_lock(hdev); 312341a96212SMarcel Holtmann 312441a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3125ccd556feSJohan Hedberg if (!conn) 3126ccd556feSJohan Hedberg goto unlock; 3127ccd556feSJohan Hedberg 3128769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 312941a96212SMarcel Holtmann struct inquiry_entry *ie; 313041a96212SMarcel Holtmann 3131cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 3132cc11b9c1SAndrei Emeltchenko if (ie) 313302b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 313441a96212SMarcel Holtmann 313502b7cc62SJohan Hedberg if (ev->features[0] & LMP_HOST_SSP) 313658a681efSJohan Hedberg set_bit(HCI_CONN_SSP_ENABLED, &conn->flags); 313741a96212SMarcel Holtmann } 313841a96212SMarcel Holtmann 3139ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 3140ccd556feSJohan Hedberg goto unlock; 3141ccd556feSJohan Hedberg 3142671267bfSJohan Hedberg if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { 3143127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 3144127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 3145127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 3146127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 3147127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 3148b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 3149b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 315008c79b61SJohan Hedberg conn->dst_type, 0, NULL, 0, 3151b644ba33SJohan Hedberg conn->dev_class); 3152392599b9SJohan Hedberg 3153127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 3154769be974SMarcel Holtmann conn->state = BT_CONNECTED; 3155769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 3156769be974SMarcel Holtmann hci_conn_put(conn); 3157769be974SMarcel Holtmann } 3158769be974SMarcel Holtmann 3159ccd556feSJohan Hedberg unlock: 316041a96212SMarcel Holtmann hci_dev_unlock(hdev); 3161a9de9248SMarcel Holtmann } 3162a9de9248SMarcel Holtmann 31636039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev, 3164807deac2SGustavo Padovan struct sk_buff *skb) 3165a9de9248SMarcel Holtmann { 3166b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 3167b6a0dc82SMarcel Holtmann struct hci_conn *conn; 3168b6a0dc82SMarcel Holtmann 31699f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 3170b6a0dc82SMarcel Holtmann 3171b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 3172b6a0dc82SMarcel Holtmann 3173b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 31749dc0a3afSMarcel Holtmann if (!conn) { 31759dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 31769dc0a3afSMarcel Holtmann goto unlock; 31779dc0a3afSMarcel Holtmann 31789dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 3179b6a0dc82SMarcel Holtmann if (!conn) 3180b6a0dc82SMarcel Holtmann goto unlock; 3181b6a0dc82SMarcel Holtmann 31829dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 31839dc0a3afSMarcel Holtmann } 31849dc0a3afSMarcel Holtmann 3185732547f9SMarcel Holtmann switch (ev->status) { 3186732547f9SMarcel Holtmann case 0x00: 3187732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 3188732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 3189732547f9SMarcel Holtmann 31909eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 3191732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 3192732547f9SMarcel Holtmann break; 3193732547f9SMarcel Holtmann 3194705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 3195732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 31961038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 3197732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 3198732547f9SMarcel Holtmann if (conn->out && conn->attempt < 2) { 3199efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 3200efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 3201efc7688bSMarcel Holtmann hci_setup_sync(conn, conn->link->handle); 3202efc7688bSMarcel Holtmann goto unlock; 3203efc7688bSMarcel Holtmann } 3204732547f9SMarcel Holtmann /* fall through */ 3205efc7688bSMarcel Holtmann 3206732547f9SMarcel Holtmann default: 3207b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 3208732547f9SMarcel Holtmann break; 3209732547f9SMarcel Holtmann } 3210b6a0dc82SMarcel Holtmann 3211b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 3212b6a0dc82SMarcel Holtmann if (ev->status) 3213b6a0dc82SMarcel Holtmann hci_conn_del(conn); 3214b6a0dc82SMarcel Holtmann 3215b6a0dc82SMarcel Holtmann unlock: 3216b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 3217a9de9248SMarcel Holtmann } 3218a9de9248SMarcel Holtmann 32196039aa73SGustavo Padovan static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) 3220a9de9248SMarcel Holtmann { 3221a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 3222a9de9248SMarcel Holtmann } 3223a9de9248SMarcel Holtmann 32246039aa73SGustavo Padovan static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) 322504837f64SMarcel Holtmann { 3226a9de9248SMarcel Holtmann struct hci_ev_sniff_subrate *ev = (void *) skb->data; 322704837f64SMarcel Holtmann 32289f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 322904837f64SMarcel Holtmann } 323004837f64SMarcel Holtmann 32316039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, 3232807deac2SGustavo Padovan struct sk_buff *skb) 3233a9de9248SMarcel Holtmann { 3234a9de9248SMarcel Holtmann struct inquiry_data data; 3235a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 3236a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 32379d939d94SVishal Agarwal size_t eir_len; 3238a9de9248SMarcel Holtmann 3239a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 3240a9de9248SMarcel Holtmann 3241a9de9248SMarcel Holtmann if (!num_rsp) 3242a9de9248SMarcel Holtmann return; 3243a9de9248SMarcel Holtmann 32441519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 32451519cc17SAndre Guedes return; 32461519cc17SAndre Guedes 3247a9de9248SMarcel Holtmann hci_dev_lock(hdev); 3248a9de9248SMarcel Holtmann 3249e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 3250388fc8faSJohan Hedberg bool name_known, ssp; 3251561aafbcSJohan Hedberg 3252a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 3253a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 3254a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 3255a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 3256a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 3257a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 3258a9de9248SMarcel Holtmann data.rssi = info->rssi; 325941a96212SMarcel Holtmann data.ssp_mode = 0x01; 3260561aafbcSJohan Hedberg 3261a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 32624ddb1930SJohan Hedberg name_known = eir_has_data_type(info->data, 32634ddb1930SJohan Hedberg sizeof(info->data), 32644ddb1930SJohan Hedberg EIR_NAME_COMPLETE); 3265561aafbcSJohan Hedberg else 3266561aafbcSJohan Hedberg name_known = true; 3267561aafbcSJohan Hedberg 3268388fc8faSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, name_known, 3269388fc8faSJohan Hedberg &ssp); 32709d939d94SVishal Agarwal eir_len = eir_get_length(info->data, sizeof(info->data)); 327148264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 327204124681SGustavo F. Padovan info->dev_class, info->rssi, !name_known, 32739d939d94SVishal Agarwal ssp, info->data, eir_len); 3274a9de9248SMarcel Holtmann } 3275a9de9248SMarcel Holtmann 3276a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 3277a9de9248SMarcel Holtmann } 3278a9de9248SMarcel Holtmann 32791c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev, 32801c2e0041SJohan Hedberg struct sk_buff *skb) 32811c2e0041SJohan Hedberg { 32821c2e0041SJohan Hedberg struct hci_ev_key_refresh_complete *ev = (void *) skb->data; 32831c2e0041SJohan Hedberg struct hci_conn *conn; 32841c2e0041SJohan Hedberg 32859f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status, 32861c2e0041SJohan Hedberg __le16_to_cpu(ev->handle)); 32871c2e0041SJohan Hedberg 32881c2e0041SJohan Hedberg hci_dev_lock(hdev); 32891c2e0041SJohan Hedberg 32901c2e0041SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 32911c2e0041SJohan Hedberg if (!conn) 32921c2e0041SJohan Hedberg goto unlock; 32931c2e0041SJohan Hedberg 32941c2e0041SJohan Hedberg if (!ev->status) 32951c2e0041SJohan Hedberg conn->sec_level = conn->pending_sec_level; 32961c2e0041SJohan Hedberg 32971c2e0041SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 32981c2e0041SJohan Hedberg 32991c2e0041SJohan Hedberg if (ev->status && conn->state == BT_CONNECTED) { 33001c2e0041SJohan Hedberg hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE); 33011c2e0041SJohan Hedberg hci_conn_put(conn); 33021c2e0041SJohan Hedberg goto unlock; 33031c2e0041SJohan Hedberg } 33041c2e0041SJohan Hedberg 33051c2e0041SJohan Hedberg if (conn->state == BT_CONFIG) { 33061c2e0041SJohan Hedberg if (!ev->status) 33071c2e0041SJohan Hedberg conn->state = BT_CONNECTED; 33081c2e0041SJohan Hedberg 33091c2e0041SJohan Hedberg hci_proto_connect_cfm(conn, ev->status); 33101c2e0041SJohan Hedberg hci_conn_put(conn); 33111c2e0041SJohan Hedberg } else { 33121c2e0041SJohan Hedberg hci_auth_cfm(conn, ev->status); 33131c2e0041SJohan Hedberg 33141c2e0041SJohan Hedberg hci_conn_hold(conn); 33151c2e0041SJohan Hedberg conn->disc_timeout = HCI_DISCONN_TIMEOUT; 33161c2e0041SJohan Hedberg hci_conn_put(conn); 33171c2e0041SJohan Hedberg } 33181c2e0041SJohan Hedberg 33191c2e0041SJohan Hedberg unlock: 33201c2e0041SJohan Hedberg hci_dev_unlock(hdev); 33211c2e0041SJohan Hedberg } 33221c2e0041SJohan Hedberg 33236039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn) 332417fa4b9dSJohan Hedberg { 332517fa4b9dSJohan Hedberg /* If remote requests dedicated bonding follow that lead */ 332617fa4b9dSJohan Hedberg if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) { 332717fa4b9dSJohan Hedberg /* If both remote and local IO capabilities allow MITM 332817fa4b9dSJohan Hedberg * protection then require it, otherwise don't */ 332917fa4b9dSJohan Hedberg if (conn->remote_cap == 0x03 || conn->io_capability == 0x03) 333017fa4b9dSJohan Hedberg return 0x02; 333117fa4b9dSJohan Hedberg else 333217fa4b9dSJohan Hedberg return 0x03; 333317fa4b9dSJohan Hedberg } 333417fa4b9dSJohan Hedberg 333517fa4b9dSJohan Hedberg /* If remote requests no-bonding follow that lead */ 333617fa4b9dSJohan Hedberg if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01) 333758797bf7SWaldemar Rymarkiewicz return conn->remote_auth | (conn->auth_type & 0x01); 333817fa4b9dSJohan Hedberg 333917fa4b9dSJohan Hedberg return conn->auth_type; 334017fa4b9dSJohan Hedberg } 334117fa4b9dSJohan Hedberg 33426039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 33430493684eSMarcel Holtmann { 33440493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 33450493684eSMarcel Holtmann struct hci_conn *conn; 33460493684eSMarcel Holtmann 33470493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 33480493684eSMarcel Holtmann 33490493684eSMarcel Holtmann hci_dev_lock(hdev); 33500493684eSMarcel Holtmann 33510493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 335203b555e1SJohan Hedberg if (!conn) 335303b555e1SJohan Hedberg goto unlock; 335403b555e1SJohan Hedberg 33550493684eSMarcel Holtmann hci_conn_hold(conn); 33560493684eSMarcel Holtmann 3357a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 335803b555e1SJohan Hedberg goto unlock; 335903b555e1SJohan Hedberg 3360a8b2d5c2SJohan Hedberg if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) || 336103b555e1SJohan Hedberg (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 336217fa4b9dSJohan Hedberg struct hci_cp_io_capability_reply cp; 336317fa4b9dSJohan Hedberg 336417fa4b9dSJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 33657a7f1e7cSHemant Gupta /* Change the IO capability from KeyboardDisplay 33667a7f1e7cSHemant Gupta * to DisplayYesNo as it is not supported by BT spec. */ 33677a7f1e7cSHemant Gupta cp.capability = (conn->io_capability == 0x04) ? 33687a7f1e7cSHemant Gupta 0x01 : conn->io_capability; 33697cbc9bd9SJohan Hedberg conn->auth_type = hci_get_auth_req(conn); 33707cbc9bd9SJohan Hedberg cp.authentication = conn->auth_type; 337117fa4b9dSJohan Hedberg 33728fc9ced3SGustavo Padovan if (hci_find_remote_oob_data(hdev, &conn->dst) && 33738fc9ced3SGustavo Padovan (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags))) 3374ce85ee13SSzymon Janc cp.oob_data = 0x01; 3375ce85ee13SSzymon Janc else 3376ce85ee13SSzymon Janc cp.oob_data = 0x00; 3377ce85ee13SSzymon Janc 337817fa4b9dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, 337917fa4b9dSJohan Hedberg sizeof(cp), &cp); 338003b555e1SJohan Hedberg } else { 338103b555e1SJohan Hedberg struct hci_cp_io_capability_neg_reply cp; 338203b555e1SJohan Hedberg 338303b555e1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 33849f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED; 338503b555e1SJohan Hedberg 338603b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 338703b555e1SJohan Hedberg sizeof(cp), &cp); 338803b555e1SJohan Hedberg } 338903b555e1SJohan Hedberg 339003b555e1SJohan Hedberg unlock: 339103b555e1SJohan Hedberg hci_dev_unlock(hdev); 339203b555e1SJohan Hedberg } 339303b555e1SJohan Hedberg 33946039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 339503b555e1SJohan Hedberg { 339603b555e1SJohan Hedberg struct hci_ev_io_capa_reply *ev = (void *) skb->data; 339703b555e1SJohan Hedberg struct hci_conn *conn; 339803b555e1SJohan Hedberg 339903b555e1SJohan Hedberg BT_DBG("%s", hdev->name); 340003b555e1SJohan Hedberg 340103b555e1SJohan Hedberg hci_dev_lock(hdev); 340203b555e1SJohan Hedberg 340303b555e1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 340403b555e1SJohan Hedberg if (!conn) 340503b555e1SJohan Hedberg goto unlock; 340603b555e1SJohan Hedberg 340703b555e1SJohan Hedberg conn->remote_cap = ev->capability; 340803b555e1SJohan Hedberg conn->remote_auth = ev->authentication; 340958a681efSJohan Hedberg if (ev->oob_data) 341058a681efSJohan Hedberg set_bit(HCI_CONN_REMOTE_OOB, &conn->flags); 341103b555e1SJohan Hedberg 341203b555e1SJohan Hedberg unlock: 34130493684eSMarcel Holtmann hci_dev_unlock(hdev); 34140493684eSMarcel Holtmann } 34150493684eSMarcel Holtmann 34166039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev, 3417a5c29683SJohan Hedberg struct sk_buff *skb) 3418a5c29683SJohan Hedberg { 3419a5c29683SJohan Hedberg struct hci_ev_user_confirm_req *ev = (void *) skb->data; 342055bc1a37SJohan Hedberg int loc_mitm, rem_mitm, confirm_hint = 0; 34217a828908SJohan Hedberg struct hci_conn *conn; 3422a5c29683SJohan Hedberg 3423a5c29683SJohan Hedberg BT_DBG("%s", hdev->name); 3424a5c29683SJohan Hedberg 3425a5c29683SJohan Hedberg hci_dev_lock(hdev); 3426a5c29683SJohan Hedberg 3427a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 34287a828908SJohan Hedberg goto unlock; 34297a828908SJohan Hedberg 34307a828908SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 34317a828908SJohan Hedberg if (!conn) 34327a828908SJohan Hedberg goto unlock; 34337a828908SJohan Hedberg 34347a828908SJohan Hedberg loc_mitm = (conn->auth_type & 0x01); 34357a828908SJohan Hedberg rem_mitm = (conn->remote_auth & 0x01); 34367a828908SJohan Hedberg 34377a828908SJohan Hedberg /* If we require MITM but the remote device can't provide that 34387a828908SJohan Hedberg * (it has NoInputNoOutput) then reject the confirmation 34397a828908SJohan Hedberg * request. The only exception is when we're dedicated bonding 34407a828908SJohan Hedberg * initiators (connect_cfm_cb set) since then we always have the MITM 34417a828908SJohan Hedberg * bit set. */ 34427a828908SJohan Hedberg if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) { 34437a828908SJohan Hedberg BT_DBG("Rejecting request: remote device can't provide MITM"); 34447a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, 34457a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 34467a828908SJohan Hedberg goto unlock; 34477a828908SJohan Hedberg } 34487a828908SJohan Hedberg 34497a828908SJohan Hedberg /* If no side requires MITM protection; auto-accept */ 34507a828908SJohan Hedberg if ((!loc_mitm || conn->remote_cap == 0x03) && 34517a828908SJohan Hedberg (!rem_mitm || conn->io_capability == 0x03)) { 345255bc1a37SJohan Hedberg 345355bc1a37SJohan Hedberg /* If we're not the initiators request authorization to 345455bc1a37SJohan Hedberg * proceed from user space (mgmt_user_confirm with 345555bc1a37SJohan Hedberg * confirm_hint set to 1). */ 345651a8efd7SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 345755bc1a37SJohan Hedberg BT_DBG("Confirming auto-accept as acceptor"); 345855bc1a37SJohan Hedberg confirm_hint = 1; 345955bc1a37SJohan Hedberg goto confirm; 346055bc1a37SJohan Hedberg } 346155bc1a37SJohan Hedberg 34629f61656aSJohan Hedberg BT_DBG("Auto-accept of user confirmation with %ums delay", 34639f61656aSJohan Hedberg hdev->auto_accept_delay); 34649f61656aSJohan Hedberg 34659f61656aSJohan Hedberg if (hdev->auto_accept_delay > 0) { 34669f61656aSJohan Hedberg int delay = msecs_to_jiffies(hdev->auto_accept_delay); 34679f61656aSJohan Hedberg mod_timer(&conn->auto_accept_timer, jiffies + delay); 34689f61656aSJohan Hedberg goto unlock; 34699f61656aSJohan Hedberg } 34709f61656aSJohan Hedberg 34717a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, 34727a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 34737a828908SJohan Hedberg goto unlock; 34747a828908SJohan Hedberg } 34757a828908SJohan Hedberg 347655bc1a37SJohan Hedberg confirm: 3477272d90dfSJohan Hedberg mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey, 347855bc1a37SJohan Hedberg confirm_hint); 3479a5c29683SJohan Hedberg 34807a828908SJohan Hedberg unlock: 3481a5c29683SJohan Hedberg hci_dev_unlock(hdev); 3482a5c29683SJohan Hedberg } 3483a5c29683SJohan Hedberg 34846039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev, 34851143d458SBrian Gix struct sk_buff *skb) 34861143d458SBrian Gix { 34871143d458SBrian Gix struct hci_ev_user_passkey_req *ev = (void *) skb->data; 34881143d458SBrian Gix 34891143d458SBrian Gix BT_DBG("%s", hdev->name); 34901143d458SBrian Gix 3491a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 3492272d90dfSJohan Hedberg mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); 34931143d458SBrian Gix } 34941143d458SBrian Gix 349592a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev, 349692a25256SJohan Hedberg struct sk_buff *skb) 349792a25256SJohan Hedberg { 349892a25256SJohan Hedberg struct hci_ev_user_passkey_notify *ev = (void *) skb->data; 349992a25256SJohan Hedberg struct hci_conn *conn; 350092a25256SJohan Hedberg 350192a25256SJohan Hedberg BT_DBG("%s", hdev->name); 350292a25256SJohan Hedberg 350392a25256SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 350492a25256SJohan Hedberg if (!conn) 350592a25256SJohan Hedberg return; 350692a25256SJohan Hedberg 350792a25256SJohan Hedberg conn->passkey_notify = __le32_to_cpu(ev->passkey); 350892a25256SJohan Hedberg conn->passkey_entered = 0; 350992a25256SJohan Hedberg 351092a25256SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 351192a25256SJohan Hedberg mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, 351292a25256SJohan Hedberg conn->dst_type, conn->passkey_notify, 351392a25256SJohan Hedberg conn->passkey_entered); 351492a25256SJohan Hedberg } 351592a25256SJohan Hedberg 351692a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 351792a25256SJohan Hedberg { 351892a25256SJohan Hedberg struct hci_ev_keypress_notify *ev = (void *) skb->data; 351992a25256SJohan Hedberg struct hci_conn *conn; 352092a25256SJohan Hedberg 352192a25256SJohan Hedberg BT_DBG("%s", hdev->name); 352292a25256SJohan Hedberg 352392a25256SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 352492a25256SJohan Hedberg if (!conn) 352592a25256SJohan Hedberg return; 352692a25256SJohan Hedberg 352792a25256SJohan Hedberg switch (ev->type) { 352892a25256SJohan Hedberg case HCI_KEYPRESS_STARTED: 352992a25256SJohan Hedberg conn->passkey_entered = 0; 353092a25256SJohan Hedberg return; 353192a25256SJohan Hedberg 353292a25256SJohan Hedberg case HCI_KEYPRESS_ENTERED: 353392a25256SJohan Hedberg conn->passkey_entered++; 353492a25256SJohan Hedberg break; 353592a25256SJohan Hedberg 353692a25256SJohan Hedberg case HCI_KEYPRESS_ERASED: 353792a25256SJohan Hedberg conn->passkey_entered--; 353892a25256SJohan Hedberg break; 353992a25256SJohan Hedberg 354092a25256SJohan Hedberg case HCI_KEYPRESS_CLEARED: 354192a25256SJohan Hedberg conn->passkey_entered = 0; 354292a25256SJohan Hedberg break; 354392a25256SJohan Hedberg 354492a25256SJohan Hedberg case HCI_KEYPRESS_COMPLETED: 354592a25256SJohan Hedberg return; 354692a25256SJohan Hedberg } 354792a25256SJohan Hedberg 354892a25256SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 354992a25256SJohan Hedberg mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, 355092a25256SJohan Hedberg conn->dst_type, conn->passkey_notify, 355192a25256SJohan Hedberg conn->passkey_entered); 355292a25256SJohan Hedberg } 355392a25256SJohan Hedberg 35546039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev, 3555807deac2SGustavo Padovan struct sk_buff *skb) 35560493684eSMarcel Holtmann { 35570493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 35580493684eSMarcel Holtmann struct hci_conn *conn; 35590493684eSMarcel Holtmann 35600493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 35610493684eSMarcel Holtmann 35620493684eSMarcel Holtmann hci_dev_lock(hdev); 35630493684eSMarcel Holtmann 35640493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 35652a611692SJohan Hedberg if (!conn) 35662a611692SJohan Hedberg goto unlock; 35672a611692SJohan Hedberg 35682a611692SJohan Hedberg /* To avoid duplicate auth_failed events to user space we check 35692a611692SJohan Hedberg * the HCI_CONN_AUTH_PEND flag which will be set if we 35702a611692SJohan Hedberg * initiated the authentication. A traditional auth_complete 35712a611692SJohan Hedberg * event gets always produced as initiator and is also mapped to 35722a611692SJohan Hedberg * the mgmt_auth_failed event */ 3573fa1bd918SMikel Astiz if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status) 3574bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 3575bab73cb6SJohan Hedberg ev->status); 35762a611692SJohan Hedberg 35770493684eSMarcel Holtmann hci_conn_put(conn); 35780493684eSMarcel Holtmann 35792a611692SJohan Hedberg unlock: 35800493684eSMarcel Holtmann hci_dev_unlock(hdev); 35810493684eSMarcel Holtmann } 35820493684eSMarcel Holtmann 35836039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev, 3584807deac2SGustavo Padovan struct sk_buff *skb) 358541a96212SMarcel Holtmann { 358641a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 358741a96212SMarcel Holtmann struct inquiry_entry *ie; 358841a96212SMarcel Holtmann 358941a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 359041a96212SMarcel Holtmann 359141a96212SMarcel Holtmann hci_dev_lock(hdev); 359241a96212SMarcel Holtmann 3593cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 3594cc11b9c1SAndrei Emeltchenko if (ie) 359502b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 359641a96212SMarcel Holtmann 359741a96212SMarcel Holtmann hci_dev_unlock(hdev); 359841a96212SMarcel Holtmann } 359941a96212SMarcel Holtmann 36006039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev, 36012763eda6SSzymon Janc struct sk_buff *skb) 36022763eda6SSzymon Janc { 36032763eda6SSzymon Janc struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; 36042763eda6SSzymon Janc struct oob_data *data; 36052763eda6SSzymon Janc 36062763eda6SSzymon Janc BT_DBG("%s", hdev->name); 36072763eda6SSzymon Janc 36082763eda6SSzymon Janc hci_dev_lock(hdev); 36092763eda6SSzymon Janc 3610a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 3611e1ba1f15SSzymon Janc goto unlock; 3612e1ba1f15SSzymon Janc 36132763eda6SSzymon Janc data = hci_find_remote_oob_data(hdev, &ev->bdaddr); 36142763eda6SSzymon Janc if (data) { 36152763eda6SSzymon Janc struct hci_cp_remote_oob_data_reply cp; 36162763eda6SSzymon Janc 36172763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 36182763eda6SSzymon Janc memcpy(cp.hash, data->hash, sizeof(cp.hash)); 36192763eda6SSzymon Janc memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); 36202763eda6SSzymon Janc 36212763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), 36222763eda6SSzymon Janc &cp); 36232763eda6SSzymon Janc } else { 36242763eda6SSzymon Janc struct hci_cp_remote_oob_data_neg_reply cp; 36252763eda6SSzymon Janc 36262763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 36272763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), 36282763eda6SSzymon Janc &cp); 36292763eda6SSzymon Janc } 36302763eda6SSzymon Janc 3631e1ba1f15SSzymon Janc unlock: 36322763eda6SSzymon Janc hci_dev_unlock(hdev); 36332763eda6SSzymon Janc } 36342763eda6SSzymon Janc 36356039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 3636fcd89c09SVille Tervo { 3637fcd89c09SVille Tervo struct hci_ev_le_conn_complete *ev = (void *) skb->data; 3638fcd89c09SVille Tervo struct hci_conn *conn; 3639fcd89c09SVille Tervo 36409f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 3641fcd89c09SVille Tervo 3642fcd89c09SVille Tervo hci_dev_lock(hdev); 3643fcd89c09SVille Tervo 36444f72b329SAndrzej Kaczmarek conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); 3645b62f328bSVille Tervo if (!conn) { 3646b62f328bSVille Tervo conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); 3647b62f328bSVille Tervo if (!conn) { 3648b62f328bSVille Tervo BT_ERR("No memory for new connection"); 3649230fd16aSAndre Guedes goto unlock; 3650b62f328bSVille Tervo } 365129b7988aSAndre Guedes 365229b7988aSAndre Guedes conn->dst_type = ev->bdaddr_type; 3653b9b343d2SAndre Guedes 3654b9b343d2SAndre Guedes if (ev->role == LE_CONN_ROLE_MASTER) { 3655b9b343d2SAndre Guedes conn->out = true; 3656b9b343d2SAndre Guedes conn->link_mode |= HCI_LM_MASTER; 3657b9b343d2SAndre Guedes } 3658b62f328bSVille Tervo } 3659fcd89c09SVille Tervo 3660cd17decbSAndre Guedes if (ev->status) { 3661cd17decbSAndre Guedes mgmt_connect_failed(hdev, &conn->dst, conn->type, 3662cd17decbSAndre Guedes conn->dst_type, ev->status); 3663cd17decbSAndre Guedes hci_proto_connect_cfm(conn, ev->status); 3664cd17decbSAndre Guedes conn->state = BT_CLOSED; 3665cd17decbSAndre Guedes hci_conn_del(conn); 3666cd17decbSAndre Guedes goto unlock; 3667cd17decbSAndre Guedes } 3668cd17decbSAndre Guedes 3669b644ba33SJohan Hedberg if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 3670b644ba33SJohan Hedberg mgmt_device_connected(hdev, &ev->bdaddr, conn->type, 367195b23582SSzymon Janc conn->dst_type, 0, NULL, 0, NULL); 367283bc71b4SVinicius Costa Gomes 36737b5c0d52SVinicius Costa Gomes conn->sec_level = BT_SECURITY_LOW; 3674fcd89c09SVille Tervo conn->handle = __le16_to_cpu(ev->handle); 3675fcd89c09SVille Tervo conn->state = BT_CONNECTED; 3676fcd89c09SVille Tervo 3677fcd89c09SVille Tervo hci_conn_hold_device(conn); 3678fcd89c09SVille Tervo hci_conn_add_sysfs(conn); 3679fcd89c09SVille Tervo 3680fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 3681fcd89c09SVille Tervo 3682fcd89c09SVille Tervo unlock: 3683fcd89c09SVille Tervo hci_dev_unlock(hdev); 3684fcd89c09SVille Tervo } 3685fcd89c09SVille Tervo 36866039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) 36879aa04c91SAndre Guedes { 3688e95beb41SAndre Guedes u8 num_reports = skb->data[0]; 3689e95beb41SAndre Guedes void *ptr = &skb->data[1]; 36903c9e9195SAndre Guedes s8 rssi; 36919aa04c91SAndre Guedes 36929aa04c91SAndre Guedes hci_dev_lock(hdev); 36939aa04c91SAndre Guedes 3694e95beb41SAndre Guedes while (num_reports--) { 3695e95beb41SAndre Guedes struct hci_ev_le_advertising_info *ev = ptr; 3696e95beb41SAndre Guedes 36973c9e9195SAndre Guedes rssi = ev->data[ev->length]; 36983c9e9195SAndre Guedes mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type, 369904124681SGustavo F. Padovan NULL, rssi, 0, 1, ev->data, ev->length); 37003c9e9195SAndre Guedes 3701e95beb41SAndre Guedes ptr += sizeof(*ev) + ev->length + 1; 37029aa04c91SAndre Guedes } 37039aa04c91SAndre Guedes 37049aa04c91SAndre Guedes hci_dev_unlock(hdev); 37059aa04c91SAndre Guedes } 37069aa04c91SAndre Guedes 37076039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 3708a7a595f6SVinicius Costa Gomes { 3709a7a595f6SVinicius Costa Gomes struct hci_ev_le_ltk_req *ev = (void *) skb->data; 3710a7a595f6SVinicius Costa Gomes struct hci_cp_le_ltk_reply cp; 3711bea710feSVinicius Costa Gomes struct hci_cp_le_ltk_neg_reply neg; 3712a7a595f6SVinicius Costa Gomes struct hci_conn *conn; 3713c9839a11SVinicius Costa Gomes struct smp_ltk *ltk; 3714a7a595f6SVinicius Costa Gomes 37159f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle)); 3716a7a595f6SVinicius Costa Gomes 3717a7a595f6SVinicius Costa Gomes hci_dev_lock(hdev); 3718a7a595f6SVinicius Costa Gomes 3719a7a595f6SVinicius Costa Gomes conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3720bea710feSVinicius Costa Gomes if (conn == NULL) 3721bea710feSVinicius Costa Gomes goto not_found; 3722a7a595f6SVinicius Costa Gomes 3723bea710feSVinicius Costa Gomes ltk = hci_find_ltk(hdev, ev->ediv, ev->random); 3724bea710feSVinicius Costa Gomes if (ltk == NULL) 3725bea710feSVinicius Costa Gomes goto not_found; 3726bea710feSVinicius Costa Gomes 3727bea710feSVinicius Costa Gomes memcpy(cp.ltk, ltk->val, sizeof(ltk->val)); 3728a7a595f6SVinicius Costa Gomes cp.handle = cpu_to_le16(conn->handle); 3729c9839a11SVinicius Costa Gomes 3730c9839a11SVinicius Costa Gomes if (ltk->authenticated) 3731c9839a11SVinicius Costa Gomes conn->sec_level = BT_SECURITY_HIGH; 3732a7a595f6SVinicius Costa Gomes 3733a7a595f6SVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); 3734a7a595f6SVinicius Costa Gomes 3735c9839a11SVinicius Costa Gomes if (ltk->type & HCI_SMP_STK) { 3736c9839a11SVinicius Costa Gomes list_del(<k->list); 3737c9839a11SVinicius Costa Gomes kfree(ltk); 3738c9839a11SVinicius Costa Gomes } 3739c9839a11SVinicius Costa Gomes 3740a7a595f6SVinicius Costa Gomes hci_dev_unlock(hdev); 3741bea710feSVinicius Costa Gomes 3742bea710feSVinicius Costa Gomes return; 3743bea710feSVinicius Costa Gomes 3744bea710feSVinicius Costa Gomes not_found: 3745bea710feSVinicius Costa Gomes neg.handle = ev->handle; 3746bea710feSVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg); 3747bea710feSVinicius Costa Gomes hci_dev_unlock(hdev); 3748a7a595f6SVinicius Costa Gomes } 3749a7a595f6SVinicius Costa Gomes 37506039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 3751fcd89c09SVille Tervo { 3752fcd89c09SVille Tervo struct hci_ev_le_meta *le_ev = (void *) skb->data; 3753fcd89c09SVille Tervo 3754fcd89c09SVille Tervo skb_pull(skb, sizeof(*le_ev)); 3755fcd89c09SVille Tervo 3756fcd89c09SVille Tervo switch (le_ev->subevent) { 3757fcd89c09SVille Tervo case HCI_EV_LE_CONN_COMPLETE: 3758fcd89c09SVille Tervo hci_le_conn_complete_evt(hdev, skb); 3759fcd89c09SVille Tervo break; 3760fcd89c09SVille Tervo 37619aa04c91SAndre Guedes case HCI_EV_LE_ADVERTISING_REPORT: 37629aa04c91SAndre Guedes hci_le_adv_report_evt(hdev, skb); 37639aa04c91SAndre Guedes break; 37649aa04c91SAndre Guedes 3765a7a595f6SVinicius Costa Gomes case HCI_EV_LE_LTK_REQ: 3766a7a595f6SVinicius Costa Gomes hci_le_ltk_request_evt(hdev, skb); 3767a7a595f6SVinicius Costa Gomes break; 3768a7a595f6SVinicius Costa Gomes 3769fcd89c09SVille Tervo default: 3770fcd89c09SVille Tervo break; 3771fcd89c09SVille Tervo } 3772fcd89c09SVille Tervo } 3773fcd89c09SVille Tervo 37749495b2eeSAndrei Emeltchenko static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb) 37759495b2eeSAndrei Emeltchenko { 37769495b2eeSAndrei Emeltchenko struct hci_ev_channel_selected *ev = (void *) skb->data; 37779495b2eeSAndrei Emeltchenko struct hci_conn *hcon; 37789495b2eeSAndrei Emeltchenko 37799495b2eeSAndrei Emeltchenko BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle); 37809495b2eeSAndrei Emeltchenko 37819495b2eeSAndrei Emeltchenko skb_pull(skb, sizeof(*ev)); 37829495b2eeSAndrei Emeltchenko 37839495b2eeSAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 37849495b2eeSAndrei Emeltchenko if (!hcon) 37859495b2eeSAndrei Emeltchenko return; 37869495b2eeSAndrei Emeltchenko 37879495b2eeSAndrei Emeltchenko amp_read_loc_assoc_final_data(hdev, hcon); 37889495b2eeSAndrei Emeltchenko } 37899495b2eeSAndrei Emeltchenko 37901da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 37911da177e4SLinus Torvalds { 3792a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 3793a9de9248SMarcel Holtmann __u8 event = hdr->evt; 37941da177e4SLinus Torvalds 37951da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 37961da177e4SLinus Torvalds 3797a9de9248SMarcel Holtmann switch (event) { 37981da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 37991da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 38001da177e4SLinus Torvalds break; 38011da177e4SLinus Torvalds 38021da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 38031da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 38041da177e4SLinus Torvalds break; 38051da177e4SLinus Torvalds 3806a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 3807a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 380821d9e30eSMarcel Holtmann break; 380921d9e30eSMarcel Holtmann 38101da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 38111da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 38121da177e4SLinus Torvalds break; 38131da177e4SLinus Torvalds 38141da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 38151da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 38161da177e4SLinus Torvalds break; 38171da177e4SLinus Torvalds 38181da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 38191da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 38201da177e4SLinus Torvalds break; 38211da177e4SLinus Torvalds 3822a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 3823a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 3824a9de9248SMarcel Holtmann break; 3825a9de9248SMarcel Holtmann 38261da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 38271da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 38281da177e4SLinus Torvalds break; 38291da177e4SLinus Torvalds 3830a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 3831a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 3832a9de9248SMarcel Holtmann break; 3833a9de9248SMarcel Holtmann 3834a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 3835a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 3836a9de9248SMarcel Holtmann break; 3837a9de9248SMarcel Holtmann 3838a9de9248SMarcel Holtmann case HCI_EV_REMOTE_VERSION: 3839a9de9248SMarcel Holtmann hci_remote_version_evt(hdev, skb); 3840a9de9248SMarcel Holtmann break; 3841a9de9248SMarcel Holtmann 3842a9de9248SMarcel Holtmann case HCI_EV_QOS_SETUP_COMPLETE: 3843a9de9248SMarcel Holtmann hci_qos_setup_complete_evt(hdev, skb); 3844a9de9248SMarcel Holtmann break; 3845a9de9248SMarcel Holtmann 3846a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 3847a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 3848a9de9248SMarcel Holtmann break; 3849a9de9248SMarcel Holtmann 3850a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 3851a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 3852a9de9248SMarcel Holtmann break; 3853a9de9248SMarcel Holtmann 3854a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 3855a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 3856a9de9248SMarcel Holtmann break; 3857a9de9248SMarcel Holtmann 3858a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 3859a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 3860a9de9248SMarcel Holtmann break; 3861a9de9248SMarcel Holtmann 3862a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 3863a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 38641da177e4SLinus Torvalds break; 38651da177e4SLinus Torvalds 38661da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 38671da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 38681da177e4SLinus Torvalds break; 38691da177e4SLinus Torvalds 38701da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 38711da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 38721da177e4SLinus Torvalds break; 38731da177e4SLinus Torvalds 38741da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 38751da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 38761da177e4SLinus Torvalds break; 38771da177e4SLinus Torvalds 38781da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 38791da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 38801da177e4SLinus Torvalds break; 38811da177e4SLinus Torvalds 3882a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 3883a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 3884a8746417SMarcel Holtmann break; 3885a8746417SMarcel Holtmann 388685a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 388785a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 388885a1e930SMarcel Holtmann break; 388985a1e930SMarcel Holtmann 3890a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 3891a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 3892a9de9248SMarcel Holtmann break; 3893a9de9248SMarcel Holtmann 3894a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 3895a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 3896a9de9248SMarcel Holtmann break; 3897a9de9248SMarcel Holtmann 3898a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 3899a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 3900a9de9248SMarcel Holtmann break; 3901a9de9248SMarcel Holtmann 3902a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_CHANGED: 3903a9de9248SMarcel Holtmann hci_sync_conn_changed_evt(hdev, skb); 3904a9de9248SMarcel Holtmann break; 3905a9de9248SMarcel Holtmann 390604837f64SMarcel Holtmann case HCI_EV_SNIFF_SUBRATE: 390704837f64SMarcel Holtmann hci_sniff_subrate_evt(hdev, skb); 390804837f64SMarcel Holtmann break; 390904837f64SMarcel Holtmann 3910a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 3911a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 39121da177e4SLinus Torvalds break; 39131da177e4SLinus Torvalds 39141c2e0041SJohan Hedberg case HCI_EV_KEY_REFRESH_COMPLETE: 39151c2e0041SJohan Hedberg hci_key_refresh_complete_evt(hdev, skb); 39161c2e0041SJohan Hedberg break; 39171c2e0041SJohan Hedberg 39180493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 39190493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 39200493684eSMarcel Holtmann break; 39210493684eSMarcel Holtmann 392203b555e1SJohan Hedberg case HCI_EV_IO_CAPA_REPLY: 392303b555e1SJohan Hedberg hci_io_capa_reply_evt(hdev, skb); 392403b555e1SJohan Hedberg break; 392503b555e1SJohan Hedberg 3926a5c29683SJohan Hedberg case HCI_EV_USER_CONFIRM_REQUEST: 3927a5c29683SJohan Hedberg hci_user_confirm_request_evt(hdev, skb); 3928a5c29683SJohan Hedberg break; 3929a5c29683SJohan Hedberg 39301143d458SBrian Gix case HCI_EV_USER_PASSKEY_REQUEST: 39311143d458SBrian Gix hci_user_passkey_request_evt(hdev, skb); 39321143d458SBrian Gix break; 39331143d458SBrian Gix 393492a25256SJohan Hedberg case HCI_EV_USER_PASSKEY_NOTIFY: 393592a25256SJohan Hedberg hci_user_passkey_notify_evt(hdev, skb); 393692a25256SJohan Hedberg break; 393792a25256SJohan Hedberg 393892a25256SJohan Hedberg case HCI_EV_KEYPRESS_NOTIFY: 393992a25256SJohan Hedberg hci_keypress_notify_evt(hdev, skb); 394092a25256SJohan Hedberg break; 394192a25256SJohan Hedberg 39420493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 39430493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 39440493684eSMarcel Holtmann break; 39450493684eSMarcel Holtmann 394641a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 394741a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 394841a96212SMarcel Holtmann break; 394941a96212SMarcel Holtmann 3950fcd89c09SVille Tervo case HCI_EV_LE_META: 3951fcd89c09SVille Tervo hci_le_meta_evt(hdev, skb); 3952fcd89c09SVille Tervo break; 3953fcd89c09SVille Tervo 39549495b2eeSAndrei Emeltchenko case HCI_EV_CHANNEL_SELECTED: 39559495b2eeSAndrei Emeltchenko hci_chan_selected_evt(hdev, skb); 39569495b2eeSAndrei Emeltchenko break; 39579495b2eeSAndrei Emeltchenko 39582763eda6SSzymon Janc case HCI_EV_REMOTE_OOB_DATA_REQUEST: 39592763eda6SSzymon Janc hci_remote_oob_data_request_evt(hdev, skb); 39602763eda6SSzymon Janc break; 39612763eda6SSzymon Janc 396225e89e99SAndrei Emeltchenko case HCI_EV_NUM_COMP_BLOCKS: 396325e89e99SAndrei Emeltchenko hci_num_comp_blocks_evt(hdev, skb); 396425e89e99SAndrei Emeltchenko break; 396525e89e99SAndrei Emeltchenko 39661da177e4SLinus Torvalds default: 39679f1db00cSAndrei Emeltchenko BT_DBG("%s event 0x%2.2x", hdev->name, event); 39681da177e4SLinus Torvalds break; 39691da177e4SLinus Torvalds } 39701da177e4SLinus Torvalds 39711da177e4SLinus Torvalds kfree_skb(skb); 39721da177e4SLinus Torvalds hdev->stat.evt_rx++; 39731da177e4SLinus Torvalds } 3974