11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds BlueZ - Bluetooth protocol stack for Linux 32d0a0346SRon Shaffer Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved. 41da177e4SLinus Torvalds 51da177e4SLinus Torvalds Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> 61da177e4SLinus Torvalds 71da177e4SLinus Torvalds This program is free software; you can redistribute it and/or modify 81da177e4SLinus Torvalds it under the terms of the GNU General Public License version 2 as 91da177e4SLinus Torvalds published by the Free Software Foundation; 101da177e4SLinus Torvalds 111da177e4SLinus Torvalds THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 121da177e4SLinus Torvalds OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 131da177e4SLinus Torvalds FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 141da177e4SLinus Torvalds IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 151da177e4SLinus Torvalds CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 161da177e4SLinus Torvalds WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 171da177e4SLinus Torvalds ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 181da177e4SLinus Torvalds OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 211da177e4SLinus Torvalds COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 221da177e4SLinus Torvalds SOFTWARE IS DISCLAIMED. 231da177e4SLinus Torvalds */ 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds /* Bluetooth HCI event handling. */ 261da177e4SLinus Torvalds 271da177e4SLinus Torvalds #include <asm/unaligned.h> 281da177e4SLinus Torvalds 291da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h> 301da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h> 31f0d6a0eaSMikel Astiz #include <net/bluetooth/mgmt.h> 328e2a0d92SAndrei Emeltchenko #include <net/bluetooth/a2mp.h> 33903e4541SAndrei Emeltchenko #include <net/bluetooth/amp.h> 341da177e4SLinus Torvalds 351da177e4SLinus Torvalds /* Handle HCI Event packets */ 361da177e4SLinus Torvalds 37a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb) 381da177e4SLinus Torvalds { 39a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 401da177e4SLinus Torvalds 419f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 421da177e4SLinus Torvalds 43e6d465cbSAndre Guedes if (status) { 44e6d465cbSAndre Guedes hci_dev_lock(hdev); 45e6d465cbSAndre Guedes mgmt_stop_discovery_failed(hdev, status); 46e6d465cbSAndre Guedes hci_dev_unlock(hdev); 47a9de9248SMarcel Holtmann return; 48e6d465cbSAndre Guedes } 491da177e4SLinus Torvalds 5089352e7dSAndre Guedes clear_bit(HCI_INQUIRY, &hdev->flags); 5189352e7dSAndre Guedes 5256e5cb86SJohan Hedberg hci_dev_lock(hdev); 53ff9ef578SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 5456e5cb86SJohan Hedberg hci_dev_unlock(hdev); 55a9de9248SMarcel Holtmann 5623bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status); 57a9de9248SMarcel Holtmann 58a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 591da177e4SLinus Torvalds } 606bd57416SMarcel Holtmann 614d93483bSAndre Guedes static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 624d93483bSAndre Guedes { 634d93483bSAndre Guedes __u8 status = *((__u8 *) skb->data); 644d93483bSAndre Guedes 659f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 66ae854a70SAndre Guedes 67ae854a70SAndre Guedes if (status) 68ae854a70SAndre Guedes return; 69ae854a70SAndre Guedes 70ae854a70SAndre Guedes set_bit(HCI_PERIODIC_INQ, &hdev->dev_flags); 714d93483bSAndre Guedes } 724d93483bSAndre Guedes 73a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 741da177e4SLinus Torvalds { 75a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 76a9de9248SMarcel Holtmann 779f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 78a9de9248SMarcel Holtmann 79a9de9248SMarcel Holtmann if (status) 80a9de9248SMarcel Holtmann return; 81a9de9248SMarcel Holtmann 82ae854a70SAndre Guedes clear_bit(HCI_PERIODIC_INQ, &hdev->dev_flags); 83ae854a70SAndre Guedes 84a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 85a9de9248SMarcel Holtmann } 86a9de9248SMarcel Holtmann 87807deac2SGustavo Padovan static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, 88807deac2SGustavo Padovan struct sk_buff *skb) 89a9de9248SMarcel Holtmann { 90a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 91a9de9248SMarcel Holtmann } 92a9de9248SMarcel Holtmann 93a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb) 94a9de9248SMarcel Holtmann { 95a9de9248SMarcel Holtmann struct hci_rp_role_discovery *rp = (void *) skb->data; 961da177e4SLinus Torvalds struct hci_conn *conn; 971da177e4SLinus Torvalds 989f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 991da177e4SLinus Torvalds 100a9de9248SMarcel Holtmann if (rp->status) 101a9de9248SMarcel Holtmann return; 1021da177e4SLinus Torvalds 1031da177e4SLinus Torvalds hci_dev_lock(hdev); 1041da177e4SLinus Torvalds 105a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 1061da177e4SLinus Torvalds if (conn) { 107a9de9248SMarcel Holtmann if (rp->role) 1081da177e4SLinus Torvalds conn->link_mode &= ~HCI_LM_MASTER; 1091da177e4SLinus Torvalds else 1101da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 1111da177e4SLinus Torvalds } 1121da177e4SLinus Torvalds 1131da177e4SLinus Torvalds hci_dev_unlock(hdev); 114a9de9248SMarcel Holtmann } 1151da177e4SLinus Torvalds 116e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 117e4e8e37cSMarcel Holtmann { 118e4e8e37cSMarcel Holtmann struct hci_rp_read_link_policy *rp = (void *) skb->data; 119e4e8e37cSMarcel Holtmann struct hci_conn *conn; 120e4e8e37cSMarcel Holtmann 1219f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 122e4e8e37cSMarcel Holtmann 123e4e8e37cSMarcel Holtmann if (rp->status) 124e4e8e37cSMarcel Holtmann return; 125e4e8e37cSMarcel Holtmann 126e4e8e37cSMarcel Holtmann hci_dev_lock(hdev); 127e4e8e37cSMarcel Holtmann 128e4e8e37cSMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 129e4e8e37cSMarcel Holtmann if (conn) 130e4e8e37cSMarcel Holtmann conn->link_policy = __le16_to_cpu(rp->policy); 131e4e8e37cSMarcel Holtmann 132e4e8e37cSMarcel Holtmann hci_dev_unlock(hdev); 133e4e8e37cSMarcel Holtmann } 134e4e8e37cSMarcel Holtmann 135a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 136a9de9248SMarcel Holtmann { 137a9de9248SMarcel Holtmann struct hci_rp_write_link_policy *rp = (void *) skb->data; 138a9de9248SMarcel Holtmann struct hci_conn *conn; 139a9de9248SMarcel Holtmann void *sent; 140a9de9248SMarcel Holtmann 1419f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 142a9de9248SMarcel Holtmann 143a9de9248SMarcel Holtmann if (rp->status) 144a9de9248SMarcel Holtmann return; 145a9de9248SMarcel Holtmann 146a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY); 14704837f64SMarcel Holtmann if (!sent) 148a9de9248SMarcel Holtmann return; 14904837f64SMarcel Holtmann 15004837f64SMarcel Holtmann hci_dev_lock(hdev); 15104837f64SMarcel Holtmann 152a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 153e4e8e37cSMarcel Holtmann if (conn) 15483985319SHarvey Harrison conn->link_policy = get_unaligned_le16(sent + 2); 15504837f64SMarcel Holtmann 15604837f64SMarcel Holtmann hci_dev_unlock(hdev); 1571da177e4SLinus Torvalds } 1581da177e4SLinus Torvalds 159807deac2SGustavo Padovan static void hci_cc_read_def_link_policy(struct hci_dev *hdev, 160807deac2SGustavo Padovan struct sk_buff *skb) 161e4e8e37cSMarcel Holtmann { 162e4e8e37cSMarcel Holtmann struct hci_rp_read_def_link_policy *rp = (void *) skb->data; 163e4e8e37cSMarcel Holtmann 1649f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 165e4e8e37cSMarcel Holtmann 166e4e8e37cSMarcel Holtmann if (rp->status) 167e4e8e37cSMarcel Holtmann return; 168e4e8e37cSMarcel Holtmann 169e4e8e37cSMarcel Holtmann hdev->link_policy = __le16_to_cpu(rp->policy); 170e4e8e37cSMarcel Holtmann } 171e4e8e37cSMarcel Holtmann 172807deac2SGustavo Padovan static void hci_cc_write_def_link_policy(struct hci_dev *hdev, 173807deac2SGustavo Padovan struct sk_buff *skb) 174e4e8e37cSMarcel Holtmann { 175e4e8e37cSMarcel Holtmann __u8 status = *((__u8 *) skb->data); 176e4e8e37cSMarcel Holtmann void *sent; 177e4e8e37cSMarcel Holtmann 1789f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 179e4e8e37cSMarcel Holtmann 180e4e8e37cSMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY); 181e4e8e37cSMarcel Holtmann if (!sent) 182e4e8e37cSMarcel Holtmann return; 183e4e8e37cSMarcel Holtmann 184e4e8e37cSMarcel Holtmann if (!status) 185e4e8e37cSMarcel Holtmann hdev->link_policy = get_unaligned_le16(sent); 186e4e8e37cSMarcel Holtmann 18723bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, status); 188e4e8e37cSMarcel Holtmann } 189e4e8e37cSMarcel Holtmann 190a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) 1911da177e4SLinus Torvalds { 192a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 193a9de9248SMarcel Holtmann 1949f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 195a9de9248SMarcel Holtmann 19610572132SGustavo F. Padovan clear_bit(HCI_RESET, &hdev->flags); 19710572132SGustavo F. Padovan 19823bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_RESET, status); 199d23264a8SAndre Guedes 200a297e97cSJohan Hedberg /* Reset all non-persistent flags */ 201ae854a70SAndre Guedes hdev->dev_flags &= ~(BIT(HCI_LE_SCAN) | BIT(HCI_PENDING_CLASS) | 202ae854a70SAndre Guedes BIT(HCI_PERIODIC_INQ)); 20369775ff6SAndre Guedes 20469775ff6SAndre Guedes hdev->discovery.state = DISCOVERY_STOPPED; 205*bbaf444aSJohan Hedberg hdev->inq_tx_power = HCI_TX_POWER_INVALID; 206*bbaf444aSJohan Hedberg hdev->adv_tx_power = HCI_TX_POWER_INVALID; 207a9de9248SMarcel Holtmann } 208a9de9248SMarcel Holtmann 209a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) 210a9de9248SMarcel Holtmann { 211a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 2121da177e4SLinus Torvalds void *sent; 2131da177e4SLinus Torvalds 2149f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 2151da177e4SLinus Torvalds 216a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); 2171da177e4SLinus Torvalds if (!sent) 218a9de9248SMarcel Holtmann return; 2191da177e4SLinus Torvalds 22056e5cb86SJohan Hedberg hci_dev_lock(hdev); 22156e5cb86SJohan Hedberg 222f51d5b24SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 223f51d5b24SJohan Hedberg mgmt_set_local_name_complete(hdev, sent, status); 22428cc7bdeSJohan Hedberg else if (!status) 22528cc7bdeSJohan Hedberg memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); 226f51d5b24SJohan Hedberg 22756e5cb86SJohan Hedberg hci_dev_unlock(hdev); 2283159d384SJohan Hedberg 2293159d384SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status); 230a9de9248SMarcel Holtmann } 231a9de9248SMarcel Holtmann 232a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) 233a9de9248SMarcel Holtmann { 234a9de9248SMarcel Holtmann struct hci_rp_read_local_name *rp = (void *) skb->data; 235a9de9248SMarcel Holtmann 2369f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 237a9de9248SMarcel Holtmann 238a9de9248SMarcel Holtmann if (rp->status) 239a9de9248SMarcel Holtmann return; 240a9de9248SMarcel Holtmann 241db99b5fcSJohan Hedberg if (test_bit(HCI_SETUP, &hdev->dev_flags)) 2421f6c6378SJohan Hedberg memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); 243a9de9248SMarcel Holtmann } 244a9de9248SMarcel Holtmann 245a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) 246a9de9248SMarcel Holtmann { 247a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 248a9de9248SMarcel Holtmann void *sent; 249a9de9248SMarcel Holtmann 2509f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 251a9de9248SMarcel Holtmann 252a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); 253a9de9248SMarcel Holtmann if (!sent) 254a9de9248SMarcel Holtmann return; 2551da177e4SLinus Torvalds 2561da177e4SLinus Torvalds if (!status) { 257a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 258a9de9248SMarcel Holtmann 2591da177e4SLinus Torvalds if (param == AUTH_ENABLED) 2601da177e4SLinus Torvalds set_bit(HCI_AUTH, &hdev->flags); 2611da177e4SLinus Torvalds else 2621da177e4SLinus Torvalds clear_bit(HCI_AUTH, &hdev->flags); 2631da177e4SLinus Torvalds } 264a9de9248SMarcel Holtmann 26533ef95edSJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 26633ef95edSJohan Hedberg mgmt_auth_enable_complete(hdev, status); 26733ef95edSJohan Hedberg 26823bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status); 269a9de9248SMarcel Holtmann } 2701da177e4SLinus Torvalds 271a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) 272a9de9248SMarcel Holtmann { 273a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 274a9de9248SMarcel Holtmann void *sent; 275a9de9248SMarcel Holtmann 2769f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 277a9de9248SMarcel Holtmann 278a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); 2791da177e4SLinus Torvalds if (!sent) 280a9de9248SMarcel Holtmann return; 2811da177e4SLinus Torvalds 2821da177e4SLinus Torvalds if (!status) { 283a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 284a9de9248SMarcel Holtmann 2851da177e4SLinus Torvalds if (param) 2861da177e4SLinus Torvalds set_bit(HCI_ENCRYPT, &hdev->flags); 2871da177e4SLinus Torvalds else 2881da177e4SLinus Torvalds clear_bit(HCI_ENCRYPT, &hdev->flags); 2891da177e4SLinus Torvalds } 290a9de9248SMarcel Holtmann 29123bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status); 2921da177e4SLinus Torvalds } 2931da177e4SLinus Torvalds 294a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) 295a9de9248SMarcel Holtmann { 29636f7fc7eSJohan Hedberg __u8 param, status = *((__u8 *) skb->data); 29736f7fc7eSJohan Hedberg int old_pscan, old_iscan; 298a9de9248SMarcel Holtmann void *sent; 2991da177e4SLinus Torvalds 3009f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 301a9de9248SMarcel Holtmann 302a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); 3031da177e4SLinus Torvalds if (!sent) 304a9de9248SMarcel Holtmann return; 3051da177e4SLinus Torvalds 30636f7fc7eSJohan Hedberg param = *((__u8 *) sent); 307a9de9248SMarcel Holtmann 30856e5cb86SJohan Hedberg hci_dev_lock(hdev); 30956e5cb86SJohan Hedberg 310fa1bd918SMikel Astiz if (status) { 311744cf19eSJohan Hedberg mgmt_write_scan_failed(hdev, param, status); 3122d7cee58SJohan Hedberg hdev->discov_timeout = 0; 3132d7cee58SJohan Hedberg goto done; 3142d7cee58SJohan Hedberg } 3152d7cee58SJohan Hedberg 3169fbcbb45SJohan Hedberg old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags); 3179fbcbb45SJohan Hedberg old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags); 318a9de9248SMarcel Holtmann 31973f22f62SJohan Hedberg if (param & SCAN_INQUIRY) { 3201da177e4SLinus Torvalds set_bit(HCI_ISCAN, &hdev->flags); 3219fbcbb45SJohan Hedberg if (!old_iscan) 322744cf19eSJohan Hedberg mgmt_discoverable(hdev, 1); 32316ab91abSJohan Hedberg if (hdev->discov_timeout > 0) { 32416ab91abSJohan Hedberg int to = msecs_to_jiffies(hdev->discov_timeout * 1000); 32516ab91abSJohan Hedberg queue_delayed_work(hdev->workqueue, &hdev->discov_off, 32616ab91abSJohan Hedberg to); 32716ab91abSJohan Hedberg } 3289fbcbb45SJohan Hedberg } else if (old_iscan) 329744cf19eSJohan Hedberg mgmt_discoverable(hdev, 0); 3301da177e4SLinus Torvalds 3319fbcbb45SJohan Hedberg if (param & SCAN_PAGE) { 3321da177e4SLinus Torvalds set_bit(HCI_PSCAN, &hdev->flags); 3339fbcbb45SJohan Hedberg if (!old_pscan) 334744cf19eSJohan Hedberg mgmt_connectable(hdev, 1); 3359fbcbb45SJohan Hedberg } else if (old_pscan) 336744cf19eSJohan Hedberg mgmt_connectable(hdev, 0); 337a9de9248SMarcel Holtmann 33836f7fc7eSJohan Hedberg done: 33956e5cb86SJohan Hedberg hci_dev_unlock(hdev); 34023bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status); 3411da177e4SLinus Torvalds } 3421da177e4SLinus Torvalds 343a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 344a9de9248SMarcel Holtmann { 345a9de9248SMarcel Holtmann struct hci_rp_read_class_of_dev *rp = (void *) skb->data; 346a9de9248SMarcel Holtmann 3479f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 348a9de9248SMarcel Holtmann 349a9de9248SMarcel Holtmann if (rp->status) 350a9de9248SMarcel Holtmann return; 351a9de9248SMarcel Holtmann 352a9de9248SMarcel Holtmann memcpy(hdev->dev_class, rp->dev_class, 3); 353a9de9248SMarcel Holtmann 354a9de9248SMarcel Holtmann BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, 355a9de9248SMarcel Holtmann hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); 356a9de9248SMarcel Holtmann } 357a9de9248SMarcel Holtmann 358a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 359a9de9248SMarcel Holtmann { 360a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 361a9de9248SMarcel Holtmann void *sent; 362a9de9248SMarcel Holtmann 3639f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 364a9de9248SMarcel Holtmann 365a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); 366a9de9248SMarcel Holtmann if (!sent) 367a9de9248SMarcel Holtmann return; 368a9de9248SMarcel Holtmann 3697f9a903cSMarcel Holtmann hci_dev_lock(hdev); 3707f9a903cSMarcel Holtmann 3717f9a903cSMarcel Holtmann if (status == 0) 372a9de9248SMarcel Holtmann memcpy(hdev->dev_class, sent, 3); 3737f9a903cSMarcel Holtmann 3747f9a903cSMarcel Holtmann if (test_bit(HCI_MGMT, &hdev->dev_flags)) 3757f9a903cSMarcel Holtmann mgmt_set_class_of_dev_complete(hdev, sent, status); 3767f9a903cSMarcel Holtmann 3777f9a903cSMarcel Holtmann hci_dev_unlock(hdev); 378a9de9248SMarcel Holtmann } 379a9de9248SMarcel Holtmann 380a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 381a9de9248SMarcel Holtmann { 382a9de9248SMarcel Holtmann struct hci_rp_read_voice_setting *rp = (void *) skb->data; 383a9de9248SMarcel Holtmann __u16 setting; 384a9de9248SMarcel Holtmann 3859f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 386a9de9248SMarcel Holtmann 387a9de9248SMarcel Holtmann if (rp->status) 388a9de9248SMarcel Holtmann return; 389a9de9248SMarcel Holtmann 390a9de9248SMarcel Holtmann setting = __le16_to_cpu(rp->voice_setting); 391a9de9248SMarcel Holtmann 392a9de9248SMarcel Holtmann if (hdev->voice_setting == setting) 393a9de9248SMarcel Holtmann return; 394a9de9248SMarcel Holtmann 395a9de9248SMarcel Holtmann hdev->voice_setting = setting; 396a9de9248SMarcel Holtmann 3979f1db00cSAndrei Emeltchenko BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting); 398a9de9248SMarcel Holtmann 3993c54711cSGustavo F. Padovan if (hdev->notify) 400a9de9248SMarcel Holtmann hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 401a9de9248SMarcel Holtmann } 402a9de9248SMarcel Holtmann 4038fc9ced3SGustavo Padovan static void hci_cc_write_voice_setting(struct hci_dev *hdev, 4048fc9ced3SGustavo Padovan struct sk_buff *skb) 405a9de9248SMarcel Holtmann { 406a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 407f383f275SMarcel Holtmann __u16 setting; 408a9de9248SMarcel Holtmann void *sent; 409a9de9248SMarcel Holtmann 4109f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 411a9de9248SMarcel Holtmann 412f383f275SMarcel Holtmann if (status) 413f383f275SMarcel Holtmann return; 414f383f275SMarcel Holtmann 415a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); 416a9de9248SMarcel Holtmann if (!sent) 417a9de9248SMarcel Holtmann return; 418a9de9248SMarcel Holtmann 419f383f275SMarcel Holtmann setting = get_unaligned_le16(sent); 4201da177e4SLinus Torvalds 421f383f275SMarcel Holtmann if (hdev->voice_setting == setting) 422f383f275SMarcel Holtmann return; 423f383f275SMarcel Holtmann 4241da177e4SLinus Torvalds hdev->voice_setting = setting; 4251da177e4SLinus Torvalds 4269f1db00cSAndrei Emeltchenko BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting); 4271da177e4SLinus Torvalds 4283c54711cSGustavo F. Padovan if (hdev->notify) 4291da177e4SLinus Torvalds hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 4301da177e4SLinus Torvalds } 4311da177e4SLinus Torvalds 432a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 4331da177e4SLinus Torvalds { 434a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 4351da177e4SLinus Torvalds 4369f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 4371da177e4SLinus Torvalds 43823bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status); 4391143e5a6SMarcel Holtmann } 4401143e5a6SMarcel Holtmann 441333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 442333140b5SMarcel Holtmann { 443333140b5SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 4445ed8eb2fSJohan Hedberg struct hci_cp_write_ssp_mode *sent; 445333140b5SMarcel Holtmann 4469f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 447333140b5SMarcel Holtmann 448333140b5SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); 449333140b5SMarcel Holtmann if (!sent) 450333140b5SMarcel Holtmann return; 451333140b5SMarcel Holtmann 4525ed8eb2fSJohan Hedberg if (!status) { 4535ed8eb2fSJohan Hedberg if (sent->mode) 4545ed8eb2fSJohan Hedberg hdev->host_features[0] |= LMP_HOST_SSP; 4555ed8eb2fSJohan Hedberg else 4565ed8eb2fSJohan Hedberg hdev->host_features[0] &= ~LMP_HOST_SSP; 4575ed8eb2fSJohan Hedberg } 4585ed8eb2fSJohan Hedberg 459c0ecddc2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 4605ed8eb2fSJohan Hedberg mgmt_ssp_enable_complete(hdev, sent->mode, status); 461c0ecddc2SJohan Hedberg else if (!status) { 4625ed8eb2fSJohan Hedberg if (sent->mode) 46384bde9d6SJohan Hedberg set_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 46484bde9d6SJohan Hedberg else 46584bde9d6SJohan Hedberg clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 466c0ecddc2SJohan Hedberg } 467333140b5SMarcel Holtmann } 468333140b5SMarcel Holtmann 469d5859e22SJohan Hedberg static u8 hci_get_inquiry_mode(struct hci_dev *hdev) 470d5859e22SJohan Hedberg { 471976eb20eSJohan Hedberg if (lmp_ext_inq_capable(hdev)) 472d5859e22SJohan Hedberg return 2; 473d5859e22SJohan Hedberg 474976eb20eSJohan Hedberg if (lmp_inq_rssi_capable(hdev)) 475d5859e22SJohan Hedberg return 1; 476d5859e22SJohan Hedberg 477d5859e22SJohan Hedberg if (hdev->manufacturer == 11 && hdev->hci_rev == 0x00 && 478d5859e22SJohan Hedberg hdev->lmp_subver == 0x0757) 479d5859e22SJohan Hedberg return 1; 480d5859e22SJohan Hedberg 481d5859e22SJohan Hedberg if (hdev->manufacturer == 15) { 482d5859e22SJohan Hedberg if (hdev->hci_rev == 0x03 && hdev->lmp_subver == 0x6963) 483d5859e22SJohan Hedberg return 1; 484d5859e22SJohan Hedberg if (hdev->hci_rev == 0x09 && hdev->lmp_subver == 0x6963) 485d5859e22SJohan Hedberg return 1; 486d5859e22SJohan Hedberg if (hdev->hci_rev == 0x00 && hdev->lmp_subver == 0x6965) 487d5859e22SJohan Hedberg return 1; 488d5859e22SJohan Hedberg } 489d5859e22SJohan Hedberg 490d5859e22SJohan Hedberg if (hdev->manufacturer == 31 && hdev->hci_rev == 0x2005 && 491d5859e22SJohan Hedberg hdev->lmp_subver == 0x1805) 492d5859e22SJohan Hedberg return 1; 493d5859e22SJohan Hedberg 494d5859e22SJohan Hedberg return 0; 495d5859e22SJohan Hedberg } 496d5859e22SJohan Hedberg 497d5859e22SJohan Hedberg static void hci_setup_inquiry_mode(struct hci_dev *hdev) 498d5859e22SJohan Hedberg { 499d5859e22SJohan Hedberg u8 mode; 500d5859e22SJohan Hedberg 501d5859e22SJohan Hedberg mode = hci_get_inquiry_mode(hdev); 502d5859e22SJohan Hedberg 503d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_INQUIRY_MODE, 1, &mode); 504d5859e22SJohan Hedberg } 505d5859e22SJohan Hedberg 506d5859e22SJohan Hedberg static void hci_setup_event_mask(struct hci_dev *hdev) 507d5859e22SJohan Hedberg { 508d5859e22SJohan Hedberg /* The second byte is 0xff instead of 0x9f (two reserved bits 509d5859e22SJohan Hedberg * disabled) since a Broadcom 1.2 dongle doesn't respond to the 510d5859e22SJohan Hedberg * command otherwise */ 511d5859e22SJohan Hedberg u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 }; 512d5859e22SJohan Hedberg 5136de6c18dSVille Tervo /* CSR 1.1 dongles does not accept any bitfield so don't try to set 5146de6c18dSVille Tervo * any event mask for pre 1.2 devices */ 5155a13b095SAndrei Emeltchenko if (hdev->hci_ver < BLUETOOTH_VER_1_2) 5166de6c18dSVille Tervo return; 5176de6c18dSVille Tervo 518e1171e8dSJohan Hedberg if (lmp_bredr_capable(hdev)) { 519d5859e22SJohan Hedberg events[4] |= 0x01; /* Flow Specification Complete */ 520d5859e22SJohan Hedberg events[4] |= 0x02; /* Inquiry Result with RSSI */ 521d5859e22SJohan Hedberg events[4] |= 0x04; /* Read Remote Extended Features Complete */ 522d5859e22SJohan Hedberg events[5] |= 0x08; /* Synchronous Connection Complete */ 523d5859e22SJohan Hedberg events[5] |= 0x10; /* Synchronous Connection Changed */ 524e1171e8dSJohan Hedberg } 525d5859e22SJohan Hedberg 526976eb20eSJohan Hedberg if (lmp_inq_rssi_capable(hdev)) 527a24299e6SJohan Hedberg events[4] |= 0x02; /* Inquiry Result with RSSI */ 528d5859e22SJohan Hedberg 529999dcd10SAndre Guedes if (lmp_sniffsubr_capable(hdev)) 530d5859e22SJohan Hedberg events[5] |= 0x20; /* Sniff Subrating */ 531d5859e22SJohan Hedberg 532976eb20eSJohan Hedberg if (lmp_pause_enc_capable(hdev)) 533d5859e22SJohan Hedberg events[5] |= 0x80; /* Encryption Key Refresh Complete */ 534d5859e22SJohan Hedberg 535976eb20eSJohan Hedberg if (lmp_ext_inq_capable(hdev)) 536d5859e22SJohan Hedberg events[5] |= 0x40; /* Extended Inquiry Result */ 537d5859e22SJohan Hedberg 538c58e810eSAndre Guedes if (lmp_no_flush_capable(hdev)) 539d5859e22SJohan Hedberg events[7] |= 0x01; /* Enhanced Flush Complete */ 540d5859e22SJohan Hedberg 541976eb20eSJohan Hedberg if (lmp_lsto_capable(hdev)) 542d5859e22SJohan Hedberg events[6] |= 0x80; /* Link Supervision Timeout Changed */ 543d5859e22SJohan Hedberg 5449a1a1996SAndre Guedes if (lmp_ssp_capable(hdev)) { 545d5859e22SJohan Hedberg events[6] |= 0x01; /* IO Capability Request */ 546d5859e22SJohan Hedberg events[6] |= 0x02; /* IO Capability Response */ 547d5859e22SJohan Hedberg events[6] |= 0x04; /* User Confirmation Request */ 548d5859e22SJohan Hedberg events[6] |= 0x08; /* User Passkey Request */ 549d5859e22SJohan Hedberg events[6] |= 0x10; /* Remote OOB Data Request */ 550d5859e22SJohan Hedberg events[6] |= 0x20; /* Simple Pairing Complete */ 551d5859e22SJohan Hedberg events[7] |= 0x04; /* User Passkey Notification */ 552d5859e22SJohan Hedberg events[7] |= 0x08; /* Keypress Notification */ 553d5859e22SJohan Hedberg events[7] |= 0x10; /* Remote Host Supported 554d5859e22SJohan Hedberg * Features Notification */ 555d5859e22SJohan Hedberg } 556d5859e22SJohan Hedberg 557c383ddc4SAndre Guedes if (lmp_le_capable(hdev)) 558d5859e22SJohan Hedberg events[7] |= 0x20; /* LE Meta-Event */ 559d5859e22SJohan Hedberg 560d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); 561e36b04c8SJohan Hedberg 562e36b04c8SJohan Hedberg if (lmp_le_capable(hdev)) { 563e36b04c8SJohan Hedberg memset(events, 0, sizeof(events)); 564e36b04c8SJohan Hedberg events[0] = 0x1f; 565e36b04c8SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LE_SET_EVENT_MASK, 566e36b04c8SJohan Hedberg sizeof(events), events); 567e36b04c8SJohan Hedberg } 568d5859e22SJohan Hedberg } 569d5859e22SJohan Hedberg 5704611dfa8SGustavo Padovan static void bredr_setup(struct hci_dev *hdev) 571e1171e8dSJohan Hedberg { 572e1171e8dSJohan Hedberg struct hci_cp_delete_stored_link_key cp; 573e1171e8dSJohan Hedberg __le16 param; 574e1171e8dSJohan Hedberg __u8 flt_type; 575e1171e8dSJohan Hedberg 576e1171e8dSJohan Hedberg /* Read Buffer Size (ACL mtu, max pkt, etc.) */ 577e1171e8dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL); 578e1171e8dSJohan Hedberg 579e1171e8dSJohan Hedberg /* Read Class of Device */ 580e1171e8dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL); 581e1171e8dSJohan Hedberg 582e1171e8dSJohan Hedberg /* Read Local Name */ 583e1171e8dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL); 584e1171e8dSJohan Hedberg 585e1171e8dSJohan Hedberg /* Read Voice Setting */ 586e1171e8dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL); 587e1171e8dSJohan Hedberg 588e1171e8dSJohan Hedberg /* Clear Event Filters */ 589e1171e8dSJohan Hedberg flt_type = HCI_FLT_CLEAR_ALL; 590e1171e8dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type); 591e1171e8dSJohan Hedberg 592e1171e8dSJohan Hedberg /* Connection accept timeout ~20 secs */ 593e1171e8dSJohan Hedberg param = __constant_cpu_to_le16(0x7d00); 594e1171e8dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m); 595e1171e8dSJohan Hedberg 596e1171e8dSJohan Hedberg bacpy(&cp.bdaddr, BDADDR_ANY); 597e1171e8dSJohan Hedberg cp.delete_all = 1; 598e1171e8dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp); 599e1171e8dSJohan Hedberg } 600e1171e8dSJohan Hedberg 6014611dfa8SGustavo Padovan static void le_setup(struct hci_dev *hdev) 602e1171e8dSJohan Hedberg { 603e1171e8dSJohan Hedberg /* Read LE Buffer Size */ 604e1171e8dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL); 6058fa19098SJohan Hedberg 6068fa19098SJohan Hedberg /* Read LE Advertising Channel TX Power */ 6078fa19098SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL); 608e1171e8dSJohan Hedberg } 609e1171e8dSJohan Hedberg 610d5859e22SJohan Hedberg static void hci_setup(struct hci_dev *hdev) 611d5859e22SJohan Hedberg { 612e61ef499SAndrei Emeltchenko if (hdev->dev_type != HCI_BREDR) 613e61ef499SAndrei Emeltchenko return; 614e61ef499SAndrei Emeltchenko 615e1171e8dSJohan Hedberg /* Read BD Address */ 616e1171e8dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL); 617e1171e8dSJohan Hedberg 618e1171e8dSJohan Hedberg if (lmp_bredr_capable(hdev)) 6194611dfa8SGustavo Padovan bredr_setup(hdev); 620e1171e8dSJohan Hedberg 621e1171e8dSJohan Hedberg if (lmp_le_capable(hdev)) 6224611dfa8SGustavo Padovan le_setup(hdev); 623e1171e8dSJohan Hedberg 624d5859e22SJohan Hedberg hci_setup_event_mask(hdev); 625d5859e22SJohan Hedberg 626d095c1ebSAndrei Emeltchenko if (hdev->hci_ver > BLUETOOTH_VER_1_1) 627d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); 628d5859e22SJohan Hedberg 6296d3c730fSGustavo Padovan if (lmp_ssp_capable(hdev)) { 63054d04dbbSJohan Hedberg if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { 631d5859e22SJohan Hedberg u8 mode = 0x01; 63254d04dbbSJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 63354d04dbbSJohan Hedberg sizeof(mode), &mode); 63454d04dbbSJohan Hedberg } else { 63554d04dbbSJohan Hedberg struct hci_cp_write_eir cp; 63654d04dbbSJohan Hedberg 63754d04dbbSJohan Hedberg memset(hdev->eir, 0, sizeof(hdev->eir)); 63854d04dbbSJohan Hedberg memset(&cp, 0, sizeof(cp)); 63954d04dbbSJohan Hedberg 64054d04dbbSJohan Hedberg hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp); 64154d04dbbSJohan Hedberg } 642d5859e22SJohan Hedberg } 643d5859e22SJohan Hedberg 644976eb20eSJohan Hedberg if (lmp_inq_rssi_capable(hdev)) 645d5859e22SJohan Hedberg hci_setup_inquiry_mode(hdev); 646d5859e22SJohan Hedberg 647976eb20eSJohan Hedberg if (lmp_inq_tx_pwr_capable(hdev)) 648d5859e22SJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL); 649971e3a4bSAndre Guedes 650976eb20eSJohan Hedberg if (lmp_ext_feat_capable(hdev)) { 651971e3a4bSAndre Guedes struct hci_cp_read_local_ext_features cp; 652971e3a4bSAndre Guedes 653971e3a4bSAndre Guedes cp.page = 0x01; 65404124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(cp), 65504124681SGustavo F. Padovan &cp); 656971e3a4bSAndre Guedes } 657e6100a25SAndre Guedes 65847990ea0SJohan Hedberg if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) { 65947990ea0SJohan Hedberg u8 enable = 1; 66004124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(enable), 66104124681SGustavo F. Padovan &enable); 66247990ea0SJohan Hedberg } 663d5859e22SJohan Hedberg } 664d5859e22SJohan Hedberg 665a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) 666a9de9248SMarcel Holtmann { 667a9de9248SMarcel Holtmann struct hci_rp_read_local_version *rp = (void *) skb->data; 6681143e5a6SMarcel Holtmann 6699f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 6701143e5a6SMarcel Holtmann 671a9de9248SMarcel Holtmann if (rp->status) 67228b8df77SAndrei Emeltchenko goto done; 6731143e5a6SMarcel Holtmann 674a9de9248SMarcel Holtmann hdev->hci_ver = rp->hci_ver; 675e4e8e37cSMarcel Holtmann hdev->hci_rev = __le16_to_cpu(rp->hci_rev); 676d5859e22SJohan Hedberg hdev->lmp_ver = rp->lmp_ver; 677e4e8e37cSMarcel Holtmann hdev->manufacturer = __le16_to_cpu(rp->manufacturer); 678d5859e22SJohan Hedberg hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); 6791da177e4SLinus Torvalds 6809f1db00cSAndrei Emeltchenko BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name, 681807deac2SGustavo Padovan hdev->manufacturer, hdev->hci_ver, hdev->hci_rev); 682d5859e22SJohan Hedberg 683d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags)) 684d5859e22SJohan Hedberg hci_setup(hdev); 68528b8df77SAndrei Emeltchenko 68628b8df77SAndrei Emeltchenko done: 68728b8df77SAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status); 688d5859e22SJohan Hedberg } 689d5859e22SJohan Hedberg 690d5859e22SJohan Hedberg static void hci_setup_link_policy(struct hci_dev *hdev) 691d5859e22SJohan Hedberg { 692035100c8SAndrei Emeltchenko struct hci_cp_write_def_link_policy cp; 693d5859e22SJohan Hedberg u16 link_policy = 0; 694d5859e22SJohan Hedberg 6959f92ebf6SAndre Guedes if (lmp_rswitch_capable(hdev)) 696d5859e22SJohan Hedberg link_policy |= HCI_LP_RSWITCH; 697976eb20eSJohan Hedberg if (lmp_hold_capable(hdev)) 698d5859e22SJohan Hedberg link_policy |= HCI_LP_HOLD; 6996eded100SAndre Guedes if (lmp_sniff_capable(hdev)) 700d5859e22SJohan Hedberg link_policy |= HCI_LP_SNIFF; 701976eb20eSJohan Hedberg if (lmp_park_capable(hdev)) 702d5859e22SJohan Hedberg link_policy |= HCI_LP_PARK; 703d5859e22SJohan Hedberg 704035100c8SAndrei Emeltchenko cp.policy = cpu_to_le16(link_policy); 705035100c8SAndrei Emeltchenko hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY, sizeof(cp), &cp); 7061da177e4SLinus Torvalds } 7071da177e4SLinus Torvalds 7088fc9ced3SGustavo Padovan static void hci_cc_read_local_commands(struct hci_dev *hdev, 7098fc9ced3SGustavo Padovan struct sk_buff *skb) 710a9de9248SMarcel Holtmann { 711a9de9248SMarcel Holtmann struct hci_rp_read_local_commands *rp = (void *) skb->data; 712a9de9248SMarcel Holtmann 7139f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 714a9de9248SMarcel Holtmann 715a9de9248SMarcel Holtmann if (rp->status) 716d5859e22SJohan Hedberg goto done; 717a9de9248SMarcel Holtmann 718a9de9248SMarcel Holtmann memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); 719d5859e22SJohan Hedberg 720d5859e22SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags) && (hdev->commands[5] & 0x10)) 721d5859e22SJohan Hedberg hci_setup_link_policy(hdev); 722d5859e22SJohan Hedberg 723d5859e22SJohan Hedberg done: 724d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status); 725a9de9248SMarcel Holtmann } 726a9de9248SMarcel Holtmann 7278fc9ced3SGustavo Padovan static void hci_cc_read_local_features(struct hci_dev *hdev, 7288fc9ced3SGustavo Padovan struct sk_buff *skb) 729a9de9248SMarcel Holtmann { 730a9de9248SMarcel Holtmann struct hci_rp_read_local_features *rp = (void *) skb->data; 731a9de9248SMarcel Holtmann 7329f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 733a9de9248SMarcel Holtmann 734a9de9248SMarcel Holtmann if (rp->status) 735a9de9248SMarcel Holtmann return; 736a9de9248SMarcel Holtmann 737a9de9248SMarcel Holtmann memcpy(hdev->features, rp->features, 8); 7381da177e4SLinus Torvalds 7391da177e4SLinus Torvalds /* Adjust default settings according to features 7401da177e4SLinus Torvalds * supported by device. */ 741a9de9248SMarcel Holtmann 7421da177e4SLinus Torvalds if (hdev->features[0] & LMP_3SLOT) 7431da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM3 | HCI_DH3); 7441da177e4SLinus Torvalds 7451da177e4SLinus Torvalds if (hdev->features[0] & LMP_5SLOT) 7461da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM5 | HCI_DH5); 7471da177e4SLinus Torvalds 7485b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV2) { 7491da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV2); 7505b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV2); 7515b7f9909SMarcel Holtmann } 7521da177e4SLinus Torvalds 7535b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV3) { 7541da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV3); 7555b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV3); 7565b7f9909SMarcel Holtmann } 7575b7f9909SMarcel Holtmann 75845db810fSAndre Guedes if (lmp_esco_capable(hdev)) 7595b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV3); 7605b7f9909SMarcel Holtmann 7615b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV4) 7625b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV4); 7635b7f9909SMarcel Holtmann 7645b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV5) 7655b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV5); 7661da177e4SLinus Torvalds 767efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_2M) 768efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV3); 769efc7688bSMarcel Holtmann 770efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_3M) 771efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_3EV3); 772efc7688bSMarcel Holtmann 773efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_3S_ESCO) 774efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); 775efc7688bSMarcel Holtmann 776a9de9248SMarcel Holtmann BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, 777a9de9248SMarcel Holtmann hdev->features[0], hdev->features[1], 778a9de9248SMarcel Holtmann hdev->features[2], hdev->features[3], 779a9de9248SMarcel Holtmann hdev->features[4], hdev->features[5], 780a9de9248SMarcel Holtmann hdev->features[6], hdev->features[7]); 7811da177e4SLinus Torvalds } 7821da177e4SLinus Torvalds 7838f984dfaSJohan Hedberg static void hci_set_le_support(struct hci_dev *hdev) 7848f984dfaSJohan Hedberg { 7858f984dfaSJohan Hedberg struct hci_cp_write_le_host_supported cp; 7868f984dfaSJohan Hedberg 7878f984dfaSJohan Hedberg memset(&cp, 0, sizeof(cp)); 7888f984dfaSJohan Hedberg 7899d42820fSMarcel Holtmann if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { 7908f984dfaSJohan Hedberg cp.le = 1; 791976eb20eSJohan Hedberg cp.simul = !!lmp_le_br_capable(hdev); 7928f984dfaSJohan Hedberg } 7938f984dfaSJohan Hedberg 794976eb20eSJohan Hedberg if (cp.le != !!lmp_host_le_capable(hdev)) 79504124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(cp), 79604124681SGustavo F. Padovan &cp); 7978f984dfaSJohan Hedberg } 7988f984dfaSJohan Hedberg 799971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev, 800971e3a4bSAndre Guedes struct sk_buff *skb) 801971e3a4bSAndre Guedes { 802971e3a4bSAndre Guedes struct hci_rp_read_local_ext_features *rp = (void *) skb->data; 803971e3a4bSAndre Guedes 8049f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 805971e3a4bSAndre Guedes 806971e3a4bSAndre Guedes if (rp->status) 8078f984dfaSJohan Hedberg goto done; 808971e3a4bSAndre Guedes 809b5b32b65SAndre Guedes switch (rp->page) { 810b5b32b65SAndre Guedes case 0: 811b5b32b65SAndre Guedes memcpy(hdev->features, rp->features, 8); 812b5b32b65SAndre Guedes break; 813b5b32b65SAndre Guedes case 1: 81459e29406SAndre Guedes memcpy(hdev->host_features, rp->features, 8); 815b5b32b65SAndre Guedes break; 816b5b32b65SAndre Guedes } 817971e3a4bSAndre Guedes 818c383ddc4SAndre Guedes if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev)) 8198f984dfaSJohan Hedberg hci_set_le_support(hdev); 8208f984dfaSJohan Hedberg 8218f984dfaSJohan Hedberg done: 822971e3a4bSAndre Guedes hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status); 823971e3a4bSAndre Guedes } 824971e3a4bSAndre Guedes 8251e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, 8261e89cffbSAndrei Emeltchenko struct sk_buff *skb) 8271e89cffbSAndrei Emeltchenko { 8281e89cffbSAndrei Emeltchenko struct hci_rp_read_flow_control_mode *rp = (void *) skb->data; 8291e89cffbSAndrei Emeltchenko 8309f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 8311e89cffbSAndrei Emeltchenko 8321e89cffbSAndrei Emeltchenko if (rp->status) 8331e89cffbSAndrei Emeltchenko return; 8341e89cffbSAndrei Emeltchenko 8351e89cffbSAndrei Emeltchenko hdev->flow_ctl_mode = rp->mode; 8361e89cffbSAndrei Emeltchenko 8371e89cffbSAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status); 8381e89cffbSAndrei Emeltchenko } 8391e89cffbSAndrei Emeltchenko 840a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 841a9de9248SMarcel Holtmann { 842a9de9248SMarcel Holtmann struct hci_rp_read_buffer_size *rp = (void *) skb->data; 843a9de9248SMarcel Holtmann 8449f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 845a9de9248SMarcel Holtmann 846a9de9248SMarcel Holtmann if (rp->status) 847a9de9248SMarcel Holtmann return; 848a9de9248SMarcel Holtmann 849a9de9248SMarcel Holtmann hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); 850a9de9248SMarcel Holtmann hdev->sco_mtu = rp->sco_mtu; 851a9de9248SMarcel Holtmann hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); 852a9de9248SMarcel Holtmann hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); 853da1f5198SMarcel Holtmann 854da1f5198SMarcel Holtmann if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { 855da1f5198SMarcel Holtmann hdev->sco_mtu = 64; 856da1f5198SMarcel Holtmann hdev->sco_pkts = 8; 857da1f5198SMarcel Holtmann } 858da1f5198SMarcel Holtmann 859da1f5198SMarcel Holtmann hdev->acl_cnt = hdev->acl_pkts; 860da1f5198SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 8611da177e4SLinus Torvalds 862807deac2SGustavo Padovan BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu, 863807deac2SGustavo Padovan hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts); 8641da177e4SLinus Torvalds } 8651da177e4SLinus Torvalds 866a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) 867a9de9248SMarcel Holtmann { 868a9de9248SMarcel Holtmann struct hci_rp_read_bd_addr *rp = (void *) skb->data; 8691da177e4SLinus Torvalds 8709f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 871a9de9248SMarcel Holtmann 872a9de9248SMarcel Holtmann if (!rp->status) 873a9de9248SMarcel Holtmann bacpy(&hdev->bdaddr, &rp->bdaddr); 874a9de9248SMarcel Holtmann 87523bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status); 87623bb5763SJohan Hedberg } 87723bb5763SJohan Hedberg 878350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev, 879350ee4cfSAndrei Emeltchenko struct sk_buff *skb) 880350ee4cfSAndrei Emeltchenko { 881350ee4cfSAndrei Emeltchenko struct hci_rp_read_data_block_size *rp = (void *) skb->data; 882350ee4cfSAndrei Emeltchenko 8839f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 884350ee4cfSAndrei Emeltchenko 885350ee4cfSAndrei Emeltchenko if (rp->status) 886350ee4cfSAndrei Emeltchenko return; 887350ee4cfSAndrei Emeltchenko 888350ee4cfSAndrei Emeltchenko hdev->block_mtu = __le16_to_cpu(rp->max_acl_len); 889350ee4cfSAndrei Emeltchenko hdev->block_len = __le16_to_cpu(rp->block_len); 890350ee4cfSAndrei Emeltchenko hdev->num_blocks = __le16_to_cpu(rp->num_blocks); 891350ee4cfSAndrei Emeltchenko 892350ee4cfSAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 893350ee4cfSAndrei Emeltchenko 894350ee4cfSAndrei Emeltchenko BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu, 895350ee4cfSAndrei Emeltchenko hdev->block_cnt, hdev->block_len); 896350ee4cfSAndrei Emeltchenko 897350ee4cfSAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status); 898350ee4cfSAndrei Emeltchenko } 899350ee4cfSAndrei Emeltchenko 90023bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb) 90123bb5763SJohan Hedberg { 90223bb5763SJohan Hedberg __u8 status = *((__u8 *) skb->data); 90323bb5763SJohan Hedberg 9049f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 90523bb5763SJohan Hedberg 90623bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status); 9071da177e4SLinus Torvalds } 9081da177e4SLinus Torvalds 909928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev, 910928abaa7SAndrei Emeltchenko struct sk_buff *skb) 911928abaa7SAndrei Emeltchenko { 912928abaa7SAndrei Emeltchenko struct hci_rp_read_local_amp_info *rp = (void *) skb->data; 913928abaa7SAndrei Emeltchenko 9149f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 915928abaa7SAndrei Emeltchenko 916928abaa7SAndrei Emeltchenko if (rp->status) 9178e2a0d92SAndrei Emeltchenko goto a2mp_rsp; 918928abaa7SAndrei Emeltchenko 919928abaa7SAndrei Emeltchenko hdev->amp_status = rp->amp_status; 920928abaa7SAndrei Emeltchenko hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); 921928abaa7SAndrei Emeltchenko hdev->amp_max_bw = __le32_to_cpu(rp->max_bw); 922928abaa7SAndrei Emeltchenko hdev->amp_min_latency = __le32_to_cpu(rp->min_latency); 923928abaa7SAndrei Emeltchenko hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu); 924928abaa7SAndrei Emeltchenko hdev->amp_type = rp->amp_type; 925928abaa7SAndrei Emeltchenko hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap); 926928abaa7SAndrei Emeltchenko hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size); 927928abaa7SAndrei Emeltchenko hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); 928928abaa7SAndrei Emeltchenko hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); 929928abaa7SAndrei Emeltchenko 930928abaa7SAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status); 9318e2a0d92SAndrei Emeltchenko 9328e2a0d92SAndrei Emeltchenko a2mp_rsp: 9338e2a0d92SAndrei Emeltchenko a2mp_send_getinfo_rsp(hdev); 934928abaa7SAndrei Emeltchenko } 935928abaa7SAndrei Emeltchenko 936903e4541SAndrei Emeltchenko static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev, 937903e4541SAndrei Emeltchenko struct sk_buff *skb) 938903e4541SAndrei Emeltchenko { 939903e4541SAndrei Emeltchenko struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data; 940903e4541SAndrei Emeltchenko struct amp_assoc *assoc = &hdev->loc_assoc; 941903e4541SAndrei Emeltchenko size_t rem_len, frag_len; 942903e4541SAndrei Emeltchenko 943903e4541SAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 944903e4541SAndrei Emeltchenko 945903e4541SAndrei Emeltchenko if (rp->status) 946903e4541SAndrei Emeltchenko goto a2mp_rsp; 947903e4541SAndrei Emeltchenko 948903e4541SAndrei Emeltchenko frag_len = skb->len - sizeof(*rp); 949903e4541SAndrei Emeltchenko rem_len = __le16_to_cpu(rp->rem_len); 950903e4541SAndrei Emeltchenko 951903e4541SAndrei Emeltchenko if (rem_len > frag_len) { 9522e430be3SAndrei Emeltchenko BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len); 953903e4541SAndrei Emeltchenko 954903e4541SAndrei Emeltchenko memcpy(assoc->data + assoc->offset, rp->frag, frag_len); 955903e4541SAndrei Emeltchenko assoc->offset += frag_len; 956903e4541SAndrei Emeltchenko 957903e4541SAndrei Emeltchenko /* Read other fragments */ 958903e4541SAndrei Emeltchenko amp_read_loc_assoc_frag(hdev, rp->phy_handle); 959903e4541SAndrei Emeltchenko 960903e4541SAndrei Emeltchenko return; 961903e4541SAndrei Emeltchenko } 962903e4541SAndrei Emeltchenko 963903e4541SAndrei Emeltchenko memcpy(assoc->data + assoc->offset, rp->frag, rem_len); 964903e4541SAndrei Emeltchenko assoc->len = assoc->offset + rem_len; 965903e4541SAndrei Emeltchenko assoc->offset = 0; 966903e4541SAndrei Emeltchenko 967903e4541SAndrei Emeltchenko a2mp_rsp: 968903e4541SAndrei Emeltchenko /* Send A2MP Rsp when all fragments are received */ 969903e4541SAndrei Emeltchenko a2mp_send_getampassoc_rsp(hdev, rp->status); 9709495b2eeSAndrei Emeltchenko a2mp_send_create_phy_link_req(hdev, rp->status); 971903e4541SAndrei Emeltchenko } 972903e4541SAndrei Emeltchenko 973b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, 974b0916ea0SJohan Hedberg struct sk_buff *skb) 975b0916ea0SJohan Hedberg { 976b0916ea0SJohan Hedberg __u8 status = *((__u8 *) skb->data); 977b0916ea0SJohan Hedberg 9789f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 979b0916ea0SJohan Hedberg 980b0916ea0SJohan Hedberg hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status); 981b0916ea0SJohan Hedberg } 982b0916ea0SJohan Hedberg 983d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb) 984d5859e22SJohan Hedberg { 985d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 986d5859e22SJohan Hedberg 9879f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 988d5859e22SJohan Hedberg 989d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status); 990d5859e22SJohan Hedberg } 991d5859e22SJohan Hedberg 992d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev, 993d5859e22SJohan Hedberg struct sk_buff *skb) 994d5859e22SJohan Hedberg { 995d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 996d5859e22SJohan Hedberg 9979f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 998d5859e22SJohan Hedberg 999d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status); 1000d5859e22SJohan Hedberg } 1001d5859e22SJohan Hedberg 1002d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, 1003d5859e22SJohan Hedberg struct sk_buff *skb) 1004d5859e22SJohan Hedberg { 100591c4e9b1SMarcel Holtmann struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data; 1006d5859e22SJohan Hedberg 10079f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1008d5859e22SJohan Hedberg 100991c4e9b1SMarcel Holtmann if (!rp->status) 101091c4e9b1SMarcel Holtmann hdev->inq_tx_power = rp->tx_power; 101191c4e9b1SMarcel Holtmann 101291c4e9b1SMarcel Holtmann hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status); 1013d5859e22SJohan Hedberg } 1014d5859e22SJohan Hedberg 1015d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb) 1016d5859e22SJohan Hedberg { 1017d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 1018d5859e22SJohan Hedberg 10199f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1020d5859e22SJohan Hedberg 1021d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status); 1022d5859e22SJohan Hedberg } 1023d5859e22SJohan Hedberg 1024980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) 1025980e1a53SJohan Hedberg { 1026980e1a53SJohan Hedberg struct hci_rp_pin_code_reply *rp = (void *) skb->data; 1027980e1a53SJohan Hedberg struct hci_cp_pin_code_reply *cp; 1028980e1a53SJohan Hedberg struct hci_conn *conn; 1029980e1a53SJohan Hedberg 10309f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1031980e1a53SJohan Hedberg 103256e5cb86SJohan Hedberg hci_dev_lock(hdev); 103356e5cb86SJohan Hedberg 1034a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1035744cf19eSJohan Hedberg mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); 1036980e1a53SJohan Hedberg 1037fa1bd918SMikel Astiz if (rp->status) 103856e5cb86SJohan Hedberg goto unlock; 1039980e1a53SJohan Hedberg 1040980e1a53SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); 1041980e1a53SJohan Hedberg if (!cp) 104256e5cb86SJohan Hedberg goto unlock; 1043980e1a53SJohan Hedberg 1044980e1a53SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 1045980e1a53SJohan Hedberg if (conn) 1046980e1a53SJohan Hedberg conn->pin_length = cp->pin_len; 104756e5cb86SJohan Hedberg 104856e5cb86SJohan Hedberg unlock: 104956e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1050980e1a53SJohan Hedberg } 1051980e1a53SJohan Hedberg 1052980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 1053980e1a53SJohan Hedberg { 1054980e1a53SJohan Hedberg struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data; 1055980e1a53SJohan Hedberg 10569f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1057980e1a53SJohan Hedberg 105856e5cb86SJohan Hedberg hci_dev_lock(hdev); 105956e5cb86SJohan Hedberg 1060a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1061744cf19eSJohan Hedberg mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr, 1062980e1a53SJohan Hedberg rp->status); 106356e5cb86SJohan Hedberg 106456e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1065980e1a53SJohan Hedberg } 106656e5cb86SJohan Hedberg 10676ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, 10686ed58ec5SVille Tervo struct sk_buff *skb) 10696ed58ec5SVille Tervo { 10706ed58ec5SVille Tervo struct hci_rp_le_read_buffer_size *rp = (void *) skb->data; 10716ed58ec5SVille Tervo 10729f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 10736ed58ec5SVille Tervo 10746ed58ec5SVille Tervo if (rp->status) 10756ed58ec5SVille Tervo return; 10766ed58ec5SVille Tervo 10776ed58ec5SVille Tervo hdev->le_mtu = __le16_to_cpu(rp->le_mtu); 10786ed58ec5SVille Tervo hdev->le_pkts = rp->le_max_pkt; 10796ed58ec5SVille Tervo 10806ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 10816ed58ec5SVille Tervo 10826ed58ec5SVille Tervo BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); 10836ed58ec5SVille Tervo 10846ed58ec5SVille Tervo hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status); 10856ed58ec5SVille Tervo } 1086980e1a53SJohan Hedberg 10878fa19098SJohan Hedberg static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, 10888fa19098SJohan Hedberg struct sk_buff *skb) 10898fa19098SJohan Hedberg { 10908fa19098SJohan Hedberg struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data; 10918fa19098SJohan Hedberg 10928fa19098SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 10938fa19098SJohan Hedberg 10948fa19098SJohan Hedberg if (!rp->status) 10958fa19098SJohan Hedberg hdev->adv_tx_power = rp->tx_power; 10968fa19098SJohan Hedberg 10978fa19098SJohan Hedberg hci_req_complete(hdev, HCI_OP_LE_READ_ADV_TX_POWER, rp->status); 10988fa19098SJohan Hedberg } 10998fa19098SJohan Hedberg 1100e36b04c8SJohan Hedberg static void hci_cc_le_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb) 1101e36b04c8SJohan Hedberg { 1102e36b04c8SJohan Hedberg __u8 status = *((__u8 *) skb->data); 1103e36b04c8SJohan Hedberg 1104e36b04c8SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 1105e36b04c8SJohan Hedberg 1106e36b04c8SJohan Hedberg hci_req_complete(hdev, HCI_OP_LE_SET_EVENT_MASK, status); 1107e36b04c8SJohan Hedberg } 1108e36b04c8SJohan Hedberg 1109a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) 1110a5c29683SJohan Hedberg { 1111a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 1112a5c29683SJohan Hedberg 11139f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1114a5c29683SJohan Hedberg 111556e5cb86SJohan Hedberg hci_dev_lock(hdev); 111656e5cb86SJohan Hedberg 1117a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 111804124681SGustavo F. Padovan mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0, 111904124681SGustavo F. Padovan rp->status); 112056e5cb86SJohan Hedberg 112156e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1122a5c29683SJohan Hedberg } 1123a5c29683SJohan Hedberg 1124a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, 1125a5c29683SJohan Hedberg struct sk_buff *skb) 1126a5c29683SJohan Hedberg { 1127a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 1128a5c29683SJohan Hedberg 11299f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1130a5c29683SJohan Hedberg 113156e5cb86SJohan Hedberg hci_dev_lock(hdev); 113256e5cb86SJohan Hedberg 1133a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1134744cf19eSJohan Hedberg mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr, 113504124681SGustavo F. Padovan ACL_LINK, 0, rp->status); 113656e5cb86SJohan Hedberg 113756e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1138a5c29683SJohan Hedberg } 1139a5c29683SJohan Hedberg 11401143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb) 11411143d458SBrian Gix { 11421143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 11431143d458SBrian Gix 11449f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 11451143d458SBrian Gix 11461143d458SBrian Gix hci_dev_lock(hdev); 11471143d458SBrian Gix 1148a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1149272d90dfSJohan Hedberg mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 1150272d90dfSJohan Hedberg 0, rp->status); 11511143d458SBrian Gix 11521143d458SBrian Gix hci_dev_unlock(hdev); 11531143d458SBrian Gix } 11541143d458SBrian Gix 11551143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, 11561143d458SBrian Gix struct sk_buff *skb) 11571143d458SBrian Gix { 11581143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 11591143d458SBrian Gix 11609f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 11611143d458SBrian Gix 11621143d458SBrian Gix hci_dev_lock(hdev); 11631143d458SBrian Gix 1164a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 11651143d458SBrian Gix mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr, 116604124681SGustavo F. Padovan ACL_LINK, 0, rp->status); 11671143d458SBrian Gix 11681143d458SBrian Gix hci_dev_unlock(hdev); 11691143d458SBrian Gix } 11701143d458SBrian Gix 1171c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, 1172c35938b2SSzymon Janc struct sk_buff *skb) 1173c35938b2SSzymon Janc { 1174c35938b2SSzymon Janc struct hci_rp_read_local_oob_data *rp = (void *) skb->data; 1175c35938b2SSzymon Janc 11769f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1177c35938b2SSzymon Janc 117856e5cb86SJohan Hedberg hci_dev_lock(hdev); 1179744cf19eSJohan Hedberg mgmt_read_local_oob_data_reply_complete(hdev, rp->hash, 1180c35938b2SSzymon Janc rp->randomizer, rp->status); 118156e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1182c35938b2SSzymon Janc } 1183c35938b2SSzymon Janc 118407f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) 118507f7fa5dSAndre Guedes { 118607f7fa5dSAndre Guedes __u8 status = *((__u8 *) skb->data); 118707f7fa5dSAndre Guedes 11889f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 11897ba8b4beSAndre Guedes 11907ba8b4beSAndre Guedes hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status); 11913fd24153SAndre Guedes 11923fd24153SAndre Guedes if (status) { 11933fd24153SAndre Guedes hci_dev_lock(hdev); 11943fd24153SAndre Guedes mgmt_start_discovery_failed(hdev, status); 11953fd24153SAndre Guedes hci_dev_unlock(hdev); 11963fd24153SAndre Guedes return; 11973fd24153SAndre Guedes } 119807f7fa5dSAndre Guedes } 119907f7fa5dSAndre Guedes 1200eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, 1201eb9d91f5SAndre Guedes struct sk_buff *skb) 1202eb9d91f5SAndre Guedes { 1203eb9d91f5SAndre Guedes struct hci_cp_le_set_scan_enable *cp; 1204eb9d91f5SAndre Guedes __u8 status = *((__u8 *) skb->data); 1205eb9d91f5SAndre Guedes 12069f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1207eb9d91f5SAndre Guedes 1208eb9d91f5SAndre Guedes cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE); 1209eb9d91f5SAndre Guedes if (!cp) 1210eb9d91f5SAndre Guedes return; 1211eb9d91f5SAndre Guedes 121268a8aea4SAndrei Emeltchenko switch (cp->enable) { 121368a8aea4SAndrei Emeltchenko case LE_SCANNING_ENABLED: 12147ba8b4beSAndre Guedes hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status); 12157ba8b4beSAndre Guedes 12163fd24153SAndre Guedes if (status) { 12173fd24153SAndre Guedes hci_dev_lock(hdev); 12183fd24153SAndre Guedes mgmt_start_discovery_failed(hdev, status); 12193fd24153SAndre Guedes hci_dev_unlock(hdev); 12207ba8b4beSAndre Guedes return; 12213fd24153SAndre Guedes } 12227ba8b4beSAndre Guedes 1223d23264a8SAndre Guedes set_bit(HCI_LE_SCAN, &hdev->dev_flags); 1224d23264a8SAndre Guedes 1225a8f13c8cSAndre Guedes hci_dev_lock(hdev); 1226343f935bSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_FINDING); 1227a8f13c8cSAndre Guedes hci_dev_unlock(hdev); 122868a8aea4SAndrei Emeltchenko break; 122968a8aea4SAndrei Emeltchenko 123068a8aea4SAndrei Emeltchenko case LE_SCANNING_DISABLED: 1231c9ecc48eSAndre Guedes if (status) { 1232c9ecc48eSAndre Guedes hci_dev_lock(hdev); 1233c9ecc48eSAndre Guedes mgmt_stop_discovery_failed(hdev, status); 1234c9ecc48eSAndre Guedes hci_dev_unlock(hdev); 12357ba8b4beSAndre Guedes return; 1236c9ecc48eSAndre Guedes } 12377ba8b4beSAndre Guedes 1238d23264a8SAndre Guedes clear_bit(HCI_LE_SCAN, &hdev->dev_flags); 1239d23264a8SAndre Guedes 1240bc3dd33cSAndre Guedes if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED && 1241bc3dd33cSAndre Guedes hdev->discovery.state == DISCOVERY_FINDING) { 12425e0452c0SAndre Guedes mgmt_interleaved_discovery(hdev); 12435e0452c0SAndre Guedes } else { 1244c599008fSAndre Guedes hci_dev_lock(hdev); 1245c599008fSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 1246c599008fSAndre Guedes hci_dev_unlock(hdev); 12475e0452c0SAndre Guedes } 1248c599008fSAndre Guedes 124968a8aea4SAndrei Emeltchenko break; 125068a8aea4SAndrei Emeltchenko 125168a8aea4SAndrei Emeltchenko default: 125268a8aea4SAndrei Emeltchenko BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable); 125368a8aea4SAndrei Emeltchenko break; 125435815085SAndre Guedes } 1255eb9d91f5SAndre Guedes } 1256eb9d91f5SAndre Guedes 1257a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb) 1258a7a595f6SVinicius Costa Gomes { 1259a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_reply *rp = (void *) skb->data; 1260a7a595f6SVinicius Costa Gomes 12619f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1262a7a595f6SVinicius Costa Gomes 1263a7a595f6SVinicius Costa Gomes if (rp->status) 1264a7a595f6SVinicius Costa Gomes return; 1265a7a595f6SVinicius Costa Gomes 1266a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status); 1267a7a595f6SVinicius Costa Gomes } 1268a7a595f6SVinicius Costa Gomes 1269a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 1270a7a595f6SVinicius Costa Gomes { 1271a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data; 1272a7a595f6SVinicius Costa Gomes 12739f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1274a7a595f6SVinicius Costa Gomes 1275a7a595f6SVinicius Costa Gomes if (rp->status) 1276a7a595f6SVinicius Costa Gomes return; 1277a7a595f6SVinicius Costa Gomes 1278a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status); 1279a7a595f6SVinicius Costa Gomes } 1280a7a595f6SVinicius Costa Gomes 12816039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev, 1282f9b49306SAndre Guedes struct sk_buff *skb) 1283f9b49306SAndre Guedes { 128406199cf8SJohan Hedberg struct hci_cp_write_le_host_supported *sent; 1285f9b49306SAndre Guedes __u8 status = *((__u8 *) skb->data); 1286f9b49306SAndre Guedes 12879f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1288f9b49306SAndre Guedes 128906199cf8SJohan Hedberg sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED); 12908f984dfaSJohan Hedberg if (!sent) 1291f9b49306SAndre Guedes return; 1292f9b49306SAndre Guedes 12938f984dfaSJohan Hedberg if (!status) { 12948f984dfaSJohan Hedberg if (sent->le) 12958f984dfaSJohan Hedberg hdev->host_features[0] |= LMP_HOST_LE; 12968f984dfaSJohan Hedberg else 12978f984dfaSJohan Hedberg hdev->host_features[0] &= ~LMP_HOST_LE; 129853b2caabSJohan Hedberg 129953b2caabSJohan Hedberg if (sent->simul) 130053b2caabSJohan Hedberg hdev->host_features[0] |= LMP_HOST_LE_BREDR; 130153b2caabSJohan Hedberg else 130253b2caabSJohan Hedberg hdev->host_features[0] &= ~LMP_HOST_LE_BREDR; 13038f984dfaSJohan Hedberg } 13048f984dfaSJohan Hedberg 13058f984dfaSJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags) && 13068f984dfaSJohan Hedberg !test_bit(HCI_INIT, &hdev->flags)) 13078f984dfaSJohan Hedberg mgmt_le_enable_complete(hdev, sent->le, status); 13088f984dfaSJohan Hedberg 13098f984dfaSJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status); 1310f9b49306SAndre Guedes } 1311f9b49306SAndre Guedes 131293c284eeSAndrei Emeltchenko static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev, 131393c284eeSAndrei Emeltchenko struct sk_buff *skb) 131493c284eeSAndrei Emeltchenko { 131593c284eeSAndrei Emeltchenko struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data; 131693c284eeSAndrei Emeltchenko 131793c284eeSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x", 131893c284eeSAndrei Emeltchenko hdev->name, rp->status, rp->phy_handle); 131993c284eeSAndrei Emeltchenko 132093c284eeSAndrei Emeltchenko if (rp->status) 132193c284eeSAndrei Emeltchenko return; 132293c284eeSAndrei Emeltchenko 132393c284eeSAndrei Emeltchenko amp_write_rem_assoc_continue(hdev, rp->phy_handle); 132493c284eeSAndrei Emeltchenko } 132593c284eeSAndrei Emeltchenko 13266039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 1327a9de9248SMarcel Holtmann { 13289f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1329a9de9248SMarcel Holtmann 1330a9de9248SMarcel Holtmann if (status) { 133123bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 1332a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 133356e5cb86SJohan Hedberg hci_dev_lock(hdev); 1334a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 13357a135109SAndre Guedes mgmt_start_discovery_failed(hdev, status); 133656e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1337314b2381SJohan Hedberg return; 1338314b2381SJohan Hedberg } 1339314b2381SJohan Hedberg 134089352e7dSAndre Guedes set_bit(HCI_INQUIRY, &hdev->flags); 134189352e7dSAndre Guedes 134256e5cb86SJohan Hedberg hci_dev_lock(hdev); 1343343f935bSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_FINDING); 134456e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1345a9de9248SMarcel Holtmann } 1346a9de9248SMarcel Holtmann 13476039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 13481da177e4SLinus Torvalds { 1349a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 13501da177e4SLinus Torvalds struct hci_conn *conn; 13511da177e4SLinus Torvalds 13529f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1353a9de9248SMarcel Holtmann 1354a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 13551da177e4SLinus Torvalds if (!cp) 13561da177e4SLinus Torvalds return; 13571da177e4SLinus Torvalds 13581da177e4SLinus Torvalds hci_dev_lock(hdev); 13591da177e4SLinus Torvalds 13601da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 13611da177e4SLinus Torvalds 13626ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn); 13631da177e4SLinus Torvalds 13641da177e4SLinus Torvalds if (status) { 13651da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 13664c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 13671da177e4SLinus Torvalds conn->state = BT_CLOSED; 13681da177e4SLinus Torvalds hci_proto_connect_cfm(conn, status); 13691da177e4SLinus Torvalds hci_conn_del(conn); 13704c67bc74SMarcel Holtmann } else 13714c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 13721da177e4SLinus Torvalds } 13731da177e4SLinus Torvalds } else { 13741da177e4SLinus Torvalds if (!conn) { 13751da177e4SLinus Torvalds conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); 13761da177e4SLinus Torvalds if (conn) { 1377a0c808b3SJohan Hedberg conn->out = true; 13781da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 13791da177e4SLinus Torvalds } else 1380893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 13811da177e4SLinus Torvalds } 13821da177e4SLinus Torvalds } 13831da177e4SLinus Torvalds 13841da177e4SLinus Torvalds hci_dev_unlock(hdev); 13851da177e4SLinus Torvalds } 13861da177e4SLinus Torvalds 1387a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 13881da177e4SLinus Torvalds { 1389a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 13901da177e4SLinus Torvalds struct hci_conn *acl, *sco; 13911da177e4SLinus Torvalds __u16 handle; 13921da177e4SLinus Torvalds 13939f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1394b6a0dc82SMarcel Holtmann 1395a9de9248SMarcel Holtmann if (!status) 1396a9de9248SMarcel Holtmann return; 1397a9de9248SMarcel Holtmann 1398a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 13991da177e4SLinus Torvalds if (!cp) 1400a9de9248SMarcel Holtmann return; 14011da177e4SLinus Torvalds 14021da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 14031da177e4SLinus Torvalds 14049f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, handle); 14051da177e4SLinus Torvalds 14061da177e4SLinus Torvalds hci_dev_lock(hdev); 14071da177e4SLinus Torvalds 14081da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 14095a08ecceSAndrei Emeltchenko if (acl) { 14105a08ecceSAndrei Emeltchenko sco = acl->link; 14115a08ecceSAndrei Emeltchenko if (sco) { 14121da177e4SLinus Torvalds sco->state = BT_CLOSED; 14131da177e4SLinus Torvalds 14141da177e4SLinus Torvalds hci_proto_connect_cfm(sco, status); 14151da177e4SLinus Torvalds hci_conn_del(sco); 14161da177e4SLinus Torvalds } 14175a08ecceSAndrei Emeltchenko } 14181da177e4SLinus Torvalds 14191da177e4SLinus Torvalds hci_dev_unlock(hdev); 14201da177e4SLinus Torvalds } 14211da177e4SLinus Torvalds 1422f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 1423f8558555SMarcel Holtmann { 1424f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 1425f8558555SMarcel Holtmann struct hci_conn *conn; 1426f8558555SMarcel Holtmann 14279f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1428f8558555SMarcel Holtmann 1429f8558555SMarcel Holtmann if (!status) 1430f8558555SMarcel Holtmann return; 1431f8558555SMarcel Holtmann 1432f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 1433f8558555SMarcel Holtmann if (!cp) 1434f8558555SMarcel Holtmann return; 1435f8558555SMarcel Holtmann 1436f8558555SMarcel Holtmann hci_dev_lock(hdev); 1437f8558555SMarcel Holtmann 1438f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1439f8558555SMarcel Holtmann if (conn) { 1440f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1441f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1442f8558555SMarcel Holtmann hci_conn_put(conn); 1443f8558555SMarcel Holtmann } 1444f8558555SMarcel Holtmann } 1445f8558555SMarcel Holtmann 1446f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1447f8558555SMarcel Holtmann } 1448f8558555SMarcel Holtmann 1449f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 1450f8558555SMarcel Holtmann { 1451f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 1452f8558555SMarcel Holtmann struct hci_conn *conn; 1453f8558555SMarcel Holtmann 14549f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1455f8558555SMarcel Holtmann 1456f8558555SMarcel Holtmann if (!status) 1457f8558555SMarcel Holtmann return; 1458f8558555SMarcel Holtmann 1459f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 1460f8558555SMarcel Holtmann if (!cp) 1461f8558555SMarcel Holtmann return; 1462f8558555SMarcel Holtmann 1463f8558555SMarcel Holtmann hci_dev_lock(hdev); 1464f8558555SMarcel Holtmann 1465f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1466f8558555SMarcel Holtmann if (conn) { 1467f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1468f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1469f8558555SMarcel Holtmann hci_conn_put(conn); 1470f8558555SMarcel Holtmann } 1471f8558555SMarcel Holtmann } 1472f8558555SMarcel Holtmann 1473f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1474f8558555SMarcel Holtmann } 1475f8558555SMarcel Holtmann 1476127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev, 1477392599b9SJohan Hedberg struct hci_conn *conn) 1478392599b9SJohan Hedberg { 1479392599b9SJohan Hedberg if (conn->state != BT_CONFIG || !conn->out) 1480392599b9SJohan Hedberg return 0; 1481392599b9SJohan Hedberg 1482765c2a96SJohan Hedberg if (conn->pending_sec_level == BT_SECURITY_SDP) 1483392599b9SJohan Hedberg return 0; 1484392599b9SJohan Hedberg 1485392599b9SJohan Hedberg /* Only request authentication for SSP connections or non-SSP 1486e9bf2bf0SVinicius Costa Gomes * devices with sec_level HIGH or if MITM protection is requested */ 1487807deac2SGustavo Padovan if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) && 1488807deac2SGustavo Padovan conn->pending_sec_level != BT_SECURITY_HIGH) 1489392599b9SJohan Hedberg return 0; 1490392599b9SJohan Hedberg 1491392599b9SJohan Hedberg return 1; 1492392599b9SJohan Hedberg } 1493392599b9SJohan Hedberg 14946039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev, 149500abfe44SGustavo F. Padovan struct inquiry_entry *e) 149630dc78e1SJohan Hedberg { 149730dc78e1SJohan Hedberg struct hci_cp_remote_name_req cp; 149830dc78e1SJohan Hedberg 149930dc78e1SJohan Hedberg memset(&cp, 0, sizeof(cp)); 150030dc78e1SJohan Hedberg 150130dc78e1SJohan Hedberg bacpy(&cp.bdaddr, &e->data.bdaddr); 150230dc78e1SJohan Hedberg cp.pscan_rep_mode = e->data.pscan_rep_mode; 150330dc78e1SJohan Hedberg cp.pscan_mode = e->data.pscan_mode; 150430dc78e1SJohan Hedberg cp.clock_offset = e->data.clock_offset; 150530dc78e1SJohan Hedberg 150630dc78e1SJohan Hedberg return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 150730dc78e1SJohan Hedberg } 150830dc78e1SJohan Hedberg 1509b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev) 151030dc78e1SJohan Hedberg { 151130dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 151230dc78e1SJohan Hedberg struct inquiry_entry *e; 151330dc78e1SJohan Hedberg 1514b644ba33SJohan Hedberg if (list_empty(&discov->resolve)) 1515b644ba33SJohan Hedberg return false; 1516b644ba33SJohan Hedberg 1517b644ba33SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 1518c810089cSRam Malovany if (!e) 1519c810089cSRam Malovany return false; 1520c810089cSRam Malovany 1521b644ba33SJohan Hedberg if (hci_resolve_name(hdev, e) == 0) { 1522b644ba33SJohan Hedberg e->name_state = NAME_PENDING; 1523b644ba33SJohan Hedberg return true; 1524b644ba33SJohan Hedberg } 1525b644ba33SJohan Hedberg 1526b644ba33SJohan Hedberg return false; 1527b644ba33SJohan Hedberg } 1528b644ba33SJohan Hedberg 1529b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn, 1530b644ba33SJohan Hedberg bdaddr_t *bdaddr, u8 *name, u8 name_len) 1531b644ba33SJohan Hedberg { 1532b644ba33SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 1533b644ba33SJohan Hedberg struct inquiry_entry *e; 1534b644ba33SJohan Hedberg 1535b644ba33SJohan Hedberg if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 153604124681SGustavo F. Padovan mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name, 153704124681SGustavo F. Padovan name_len, conn->dev_class); 1538b644ba33SJohan Hedberg 1539b644ba33SJohan Hedberg if (discov->state == DISCOVERY_STOPPED) 1540b644ba33SJohan Hedberg return; 1541b644ba33SJohan Hedberg 154230dc78e1SJohan Hedberg if (discov->state == DISCOVERY_STOPPING) 154330dc78e1SJohan Hedberg goto discov_complete; 154430dc78e1SJohan Hedberg 154530dc78e1SJohan Hedberg if (discov->state != DISCOVERY_RESOLVING) 154630dc78e1SJohan Hedberg return; 154730dc78e1SJohan Hedberg 154830dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING); 15497cc8380eSRam Malovany /* If the device was not found in a list of found devices names of which 15507cc8380eSRam Malovany * are pending. there is no need to continue resolving a next name as it 15517cc8380eSRam Malovany * will be done upon receiving another Remote Name Request Complete 15527cc8380eSRam Malovany * Event */ 15537cc8380eSRam Malovany if (!e) 15547cc8380eSRam Malovany return; 15557cc8380eSRam Malovany 155630dc78e1SJohan Hedberg list_del(&e->list); 15577cc8380eSRam Malovany if (name) { 15587cc8380eSRam Malovany e->name_state = NAME_KNOWN; 1559b644ba33SJohan Hedberg mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, 1560b644ba33SJohan Hedberg e->data.rssi, name, name_len); 1561c3e7c0d9SRam Malovany } else { 1562c3e7c0d9SRam Malovany e->name_state = NAME_NOT_KNOWN; 156330dc78e1SJohan Hedberg } 156430dc78e1SJohan Hedberg 1565b644ba33SJohan Hedberg if (hci_resolve_next_name(hdev)) 156630dc78e1SJohan Hedberg return; 156730dc78e1SJohan Hedberg 156830dc78e1SJohan Hedberg discov_complete: 156930dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 157030dc78e1SJohan Hedberg } 157130dc78e1SJohan Hedberg 1572a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 15731da177e4SLinus Torvalds { 1574127178d2SJohan Hedberg struct hci_cp_remote_name_req *cp; 1575127178d2SJohan Hedberg struct hci_conn *conn; 1576127178d2SJohan Hedberg 15779f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1578127178d2SJohan Hedberg 1579127178d2SJohan Hedberg /* If successful wait for the name req complete event before 1580127178d2SJohan Hedberg * checking for the need to do authentication */ 1581127178d2SJohan Hedberg if (!status) 1582127178d2SJohan Hedberg return; 1583127178d2SJohan Hedberg 1584127178d2SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); 1585127178d2SJohan Hedberg if (!cp) 1586127178d2SJohan Hedberg return; 1587127178d2SJohan Hedberg 1588127178d2SJohan Hedberg hci_dev_lock(hdev); 1589127178d2SJohan Hedberg 1590127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 1591b644ba33SJohan Hedberg 1592b644ba33SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1593b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0); 1594b644ba33SJohan Hedberg 159579c6c70cSJohan Hedberg if (!conn) 159679c6c70cSJohan Hedberg goto unlock; 159779c6c70cSJohan Hedberg 159879c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 159979c6c70cSJohan Hedberg goto unlock; 160079c6c70cSJohan Hedberg 160151a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 1602127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1603127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1604127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1605127178d2SJohan Hedberg } 1606127178d2SJohan Hedberg 160779c6c70cSJohan Hedberg unlock: 1608127178d2SJohan Hedberg hci_dev_unlock(hdev); 1609a9de9248SMarcel Holtmann } 16101da177e4SLinus Torvalds 1611769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 1612769be974SMarcel Holtmann { 1613769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 1614769be974SMarcel Holtmann struct hci_conn *conn; 1615769be974SMarcel Holtmann 16169f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1617769be974SMarcel Holtmann 1618769be974SMarcel Holtmann if (!status) 1619769be974SMarcel Holtmann return; 1620769be974SMarcel Holtmann 1621769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 1622769be974SMarcel Holtmann if (!cp) 1623769be974SMarcel Holtmann return; 1624769be974SMarcel Holtmann 1625769be974SMarcel Holtmann hci_dev_lock(hdev); 1626769be974SMarcel Holtmann 1627769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1628769be974SMarcel Holtmann if (conn) { 1629769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1630769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1631769be974SMarcel Holtmann hci_conn_put(conn); 1632769be974SMarcel Holtmann } 1633769be974SMarcel Holtmann } 1634769be974SMarcel Holtmann 1635769be974SMarcel Holtmann hci_dev_unlock(hdev); 1636769be974SMarcel Holtmann } 1637769be974SMarcel Holtmann 1638769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 1639769be974SMarcel Holtmann { 1640769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features *cp; 1641769be974SMarcel Holtmann struct hci_conn *conn; 1642769be974SMarcel Holtmann 16439f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1644769be974SMarcel Holtmann 1645769be974SMarcel Holtmann if (!status) 1646769be974SMarcel Holtmann return; 1647769be974SMarcel Holtmann 1648769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 1649769be974SMarcel Holtmann if (!cp) 1650769be974SMarcel Holtmann return; 1651769be974SMarcel Holtmann 1652769be974SMarcel Holtmann hci_dev_lock(hdev); 1653769be974SMarcel Holtmann 1654769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1655769be974SMarcel Holtmann if (conn) { 1656769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1657769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1658769be974SMarcel Holtmann hci_conn_put(conn); 1659769be974SMarcel Holtmann } 1660769be974SMarcel Holtmann } 1661769be974SMarcel Holtmann 1662769be974SMarcel Holtmann hci_dev_unlock(hdev); 1663769be974SMarcel Holtmann } 1664769be974SMarcel Holtmann 1665a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 1666a9de9248SMarcel Holtmann { 1667b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 1668b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 1669b6a0dc82SMarcel Holtmann __u16 handle; 1670b6a0dc82SMarcel Holtmann 16719f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1672b6a0dc82SMarcel Holtmann 1673b6a0dc82SMarcel Holtmann if (!status) 1674b6a0dc82SMarcel Holtmann return; 1675b6a0dc82SMarcel Holtmann 1676b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 1677b6a0dc82SMarcel Holtmann if (!cp) 1678b6a0dc82SMarcel Holtmann return; 1679b6a0dc82SMarcel Holtmann 1680b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 1681b6a0dc82SMarcel Holtmann 16829f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, handle); 1683b6a0dc82SMarcel Holtmann 1684b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 1685b6a0dc82SMarcel Holtmann 1686b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 16875a08ecceSAndrei Emeltchenko if (acl) { 16885a08ecceSAndrei Emeltchenko sco = acl->link; 16895a08ecceSAndrei Emeltchenko if (sco) { 1690b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 1691b6a0dc82SMarcel Holtmann 1692b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(sco, status); 1693b6a0dc82SMarcel Holtmann hci_conn_del(sco); 1694b6a0dc82SMarcel Holtmann } 16955a08ecceSAndrei Emeltchenko } 1696b6a0dc82SMarcel Holtmann 1697b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 1698a9de9248SMarcel Holtmann } 1699a9de9248SMarcel Holtmann 1700a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 1701a9de9248SMarcel Holtmann { 1702a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 170304837f64SMarcel Holtmann struct hci_conn *conn; 170404837f64SMarcel Holtmann 17059f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1706a9de9248SMarcel Holtmann 1707a9de9248SMarcel Holtmann if (!status) 1708a9de9248SMarcel Holtmann return; 1709a9de9248SMarcel Holtmann 1710a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 171104837f64SMarcel Holtmann if (!cp) 1712a9de9248SMarcel Holtmann return; 171304837f64SMarcel Holtmann 171404837f64SMarcel Holtmann hci_dev_lock(hdev); 171504837f64SMarcel Holtmann 171604837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1717e73439d8SMarcel Holtmann if (conn) { 171851a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 171904837f64SMarcel Holtmann 172051a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1721e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1722e73439d8SMarcel Holtmann } 1723e73439d8SMarcel Holtmann 172404837f64SMarcel Holtmann hci_dev_unlock(hdev); 172504837f64SMarcel Holtmann } 172604837f64SMarcel Holtmann 1727a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 1728a9de9248SMarcel Holtmann { 1729a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 173004837f64SMarcel Holtmann struct hci_conn *conn; 173104837f64SMarcel Holtmann 17329f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1733a9de9248SMarcel Holtmann 1734a9de9248SMarcel Holtmann if (!status) 1735a9de9248SMarcel Holtmann return; 1736a9de9248SMarcel Holtmann 1737a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 173804837f64SMarcel Holtmann if (!cp) 1739a9de9248SMarcel Holtmann return; 174004837f64SMarcel Holtmann 174104837f64SMarcel Holtmann hci_dev_lock(hdev); 174204837f64SMarcel Holtmann 174304837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1744e73439d8SMarcel Holtmann if (conn) { 174551a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 174604837f64SMarcel Holtmann 174751a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1748e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1749e73439d8SMarcel Holtmann } 1750e73439d8SMarcel Holtmann 175104837f64SMarcel Holtmann hci_dev_unlock(hdev); 175204837f64SMarcel Holtmann } 175304837f64SMarcel Holtmann 175488c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) 175588c3df13SJohan Hedberg { 175688c3df13SJohan Hedberg struct hci_cp_disconnect *cp; 175788c3df13SJohan Hedberg struct hci_conn *conn; 175888c3df13SJohan Hedberg 175988c3df13SJohan Hedberg if (!status) 176088c3df13SJohan Hedberg return; 176188c3df13SJohan Hedberg 176288c3df13SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT); 176388c3df13SJohan Hedberg if (!cp) 176488c3df13SJohan Hedberg return; 176588c3df13SJohan Hedberg 176688c3df13SJohan Hedberg hci_dev_lock(hdev); 176788c3df13SJohan Hedberg 176888c3df13SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 176988c3df13SJohan Hedberg if (conn) 177088c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 177188c3df13SJohan Hedberg conn->dst_type, status); 177288c3df13SJohan Hedberg 177388c3df13SJohan Hedberg hci_dev_unlock(hdev); 177488c3df13SJohan Hedberg } 177588c3df13SJohan Hedberg 1776fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) 1777fcd89c09SVille Tervo { 1778fcd89c09SVille Tervo struct hci_conn *conn; 1779fcd89c09SVille Tervo 17809f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1781fcd89c09SVille Tervo 1782f00a06acSAndre Guedes if (status) { 1783fcd89c09SVille Tervo hci_dev_lock(hdev); 1784fcd89c09SVille Tervo 17850c95ab78SAndre Guedes conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); 1786f00a06acSAndre Guedes if (!conn) { 1787f00a06acSAndre Guedes hci_dev_unlock(hdev); 1788f00a06acSAndre Guedes return; 1789f00a06acSAndre Guedes } 1790fcd89c09SVille Tervo 17916ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn); 1792fcd89c09SVille Tervo 1793fcd89c09SVille Tervo conn->state = BT_CLOSED; 17940c95ab78SAndre Guedes mgmt_connect_failed(hdev, &conn->dst, conn->type, 1795328c9248SHemant Gupta conn->dst_type, status); 1796fcd89c09SVille Tervo hci_proto_connect_cfm(conn, status); 1797fcd89c09SVille Tervo hci_conn_del(conn); 1798fcd89c09SVille Tervo 1799fcd89c09SVille Tervo hci_dev_unlock(hdev); 1800fcd89c09SVille Tervo } 1801f00a06acSAndre Guedes } 1802fcd89c09SVille Tervo 1803a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) 1804a7a595f6SVinicius Costa Gomes { 18059f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1806a7a595f6SVinicius Costa Gomes } 1807a7a595f6SVinicius Costa Gomes 1808a02226d6SAndrei Emeltchenko static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status) 1809a02226d6SAndrei Emeltchenko { 181093c284eeSAndrei Emeltchenko struct hci_cp_create_phy_link *cp; 181193c284eeSAndrei Emeltchenko 1812a02226d6SAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 181393c284eeSAndrei Emeltchenko 181493c284eeSAndrei Emeltchenko cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK); 181593c284eeSAndrei Emeltchenko if (!cp) 181693c284eeSAndrei Emeltchenko return; 181793c284eeSAndrei Emeltchenko 1818e58917b9SAndrei Emeltchenko hci_dev_lock(hdev); 1819e58917b9SAndrei Emeltchenko 1820e58917b9SAndrei Emeltchenko if (status) { 1821e58917b9SAndrei Emeltchenko struct hci_conn *hcon; 1822e58917b9SAndrei Emeltchenko 1823e58917b9SAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle); 1824e58917b9SAndrei Emeltchenko if (hcon) 1825e58917b9SAndrei Emeltchenko hci_conn_del(hcon); 1826e58917b9SAndrei Emeltchenko } else { 182793c284eeSAndrei Emeltchenko amp_write_remote_assoc(hdev, cp->phy_handle); 1828a02226d6SAndrei Emeltchenko } 1829a02226d6SAndrei Emeltchenko 1830e58917b9SAndrei Emeltchenko hci_dev_unlock(hdev); 1831e58917b9SAndrei Emeltchenko } 1832e58917b9SAndrei Emeltchenko 18330b26ab9dSAndrei Emeltchenko static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status) 18340b26ab9dSAndrei Emeltchenko { 18350b26ab9dSAndrei Emeltchenko struct hci_cp_accept_phy_link *cp; 18360b26ab9dSAndrei Emeltchenko 18370b26ab9dSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 18380b26ab9dSAndrei Emeltchenko 18390b26ab9dSAndrei Emeltchenko if (status) 18400b26ab9dSAndrei Emeltchenko return; 18410b26ab9dSAndrei Emeltchenko 18420b26ab9dSAndrei Emeltchenko cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK); 18430b26ab9dSAndrei Emeltchenko if (!cp) 18440b26ab9dSAndrei Emeltchenko return; 18450b26ab9dSAndrei Emeltchenko 18460b26ab9dSAndrei Emeltchenko amp_write_remote_assoc(hdev, cp->phy_handle); 18470b26ab9dSAndrei Emeltchenko } 18480b26ab9dSAndrei Emeltchenko 18495ce66b59SAndrei Emeltchenko static void hci_cs_create_logical_link(struct hci_dev *hdev, u8 status) 18505ce66b59SAndrei Emeltchenko { 18515ce66b59SAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 18525ce66b59SAndrei Emeltchenko } 18535ce66b59SAndrei Emeltchenko 18546039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 18551da177e4SLinus Torvalds { 18561da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 185730dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 185830dc78e1SJohan Hedberg struct inquiry_entry *e; 18591da177e4SLinus Torvalds 18609f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 18611da177e4SLinus Torvalds 186223bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 18636bd57416SMarcel Holtmann 1864a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 186589352e7dSAndre Guedes 186689352e7dSAndre Guedes if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) 186789352e7dSAndre Guedes return; 186889352e7dSAndre Guedes 1869a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 187030dc78e1SJohan Hedberg return; 187130dc78e1SJohan Hedberg 187256e5cb86SJohan Hedberg hci_dev_lock(hdev); 187330dc78e1SJohan Hedberg 1874343f935bSAndre Guedes if (discov->state != DISCOVERY_FINDING) 187530dc78e1SJohan Hedberg goto unlock; 187630dc78e1SJohan Hedberg 187730dc78e1SJohan Hedberg if (list_empty(&discov->resolve)) { 1878ff9ef578SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 187930dc78e1SJohan Hedberg goto unlock; 188030dc78e1SJohan Hedberg } 188130dc78e1SJohan Hedberg 188230dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 188330dc78e1SJohan Hedberg if (e && hci_resolve_name(hdev, e) == 0) { 188430dc78e1SJohan Hedberg e->name_state = NAME_PENDING; 188530dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_RESOLVING); 188630dc78e1SJohan Hedberg } else { 188730dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 188830dc78e1SJohan Hedberg } 188930dc78e1SJohan Hedberg 189030dc78e1SJohan Hedberg unlock: 189156e5cb86SJohan Hedberg hci_dev_unlock(hdev); 18921da177e4SLinus Torvalds } 18931da177e4SLinus Torvalds 18946039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 18951da177e4SLinus Torvalds { 189645bb4bf0SMarcel Holtmann struct inquiry_data data; 1897a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 18981da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 18991da177e4SLinus Torvalds 19001da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 19011da177e4SLinus Torvalds 190245bb4bf0SMarcel Holtmann if (!num_rsp) 190345bb4bf0SMarcel Holtmann return; 190445bb4bf0SMarcel Holtmann 19051519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 19061519cc17SAndre Guedes return; 19071519cc17SAndre Guedes 19081da177e4SLinus Torvalds hci_dev_lock(hdev); 190945bb4bf0SMarcel Holtmann 1910e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 1911388fc8faSJohan Hedberg bool name_known, ssp; 19123175405bSJohan Hedberg 19131da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 19141da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 19151da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 19161da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 19171da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 19181da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 19191da177e4SLinus Torvalds data.rssi = 0x00; 192041a96212SMarcel Holtmann data.ssp_mode = 0x00; 19213175405bSJohan Hedberg 1922388fc8faSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp); 192348264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 192404124681SGustavo F. Padovan info->dev_class, 0, !name_known, ssp, NULL, 192504124681SGustavo F. Padovan 0); 19261da177e4SLinus Torvalds } 192745bb4bf0SMarcel Holtmann 19281da177e4SLinus Torvalds hci_dev_unlock(hdev); 19291da177e4SLinus Torvalds } 19301da177e4SLinus Torvalds 19316039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 19321da177e4SLinus Torvalds { 1933a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 1934a9de9248SMarcel Holtmann struct hci_conn *conn; 19351da177e4SLinus Torvalds 1936a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 193745bb4bf0SMarcel Holtmann 19381da177e4SLinus Torvalds hci_dev_lock(hdev); 193945bb4bf0SMarcel Holtmann 1940a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 19419499237aSMarcel Holtmann if (!conn) { 19429499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 19439499237aSMarcel Holtmann goto unlock; 19449499237aSMarcel Holtmann 19459499237aSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 1946a9de9248SMarcel Holtmann if (!conn) 1947a9de9248SMarcel Holtmann goto unlock; 194845bb4bf0SMarcel Holtmann 19499499237aSMarcel Holtmann conn->type = SCO_LINK; 19509499237aSMarcel Holtmann } 19519499237aSMarcel Holtmann 1952a9de9248SMarcel Holtmann if (!ev->status) { 1953a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 1954769be974SMarcel Holtmann 1955769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 1956769be974SMarcel Holtmann conn->state = BT_CONFIG; 1957769be974SMarcel Holtmann hci_conn_hold(conn); 1958a9ea3ed9SSzymon Janc 1959a9ea3ed9SSzymon Janc if (!conn->out && !hci_conn_ssp_enabled(conn) && 1960a9ea3ed9SSzymon Janc !hci_find_link_key(hdev, &ev->bdaddr)) 1961a9ea3ed9SSzymon Janc conn->disc_timeout = HCI_PAIRING_TIMEOUT; 1962a9ea3ed9SSzymon Janc else 1963052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1964769be974SMarcel Holtmann } else 1965a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 1966a9de9248SMarcel Holtmann 19679eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 19687d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 19697d0db0a3SMarcel Holtmann 1970a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 1971a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1972a9de9248SMarcel Holtmann 1973a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 1974a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1975a9de9248SMarcel Holtmann 1976a9de9248SMarcel Holtmann /* Get remote features */ 1977a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 1978a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 1979a9de9248SMarcel Holtmann cp.handle = ev->handle; 1980769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 1981769be974SMarcel Holtmann sizeof(cp), &cp); 198245bb4bf0SMarcel Holtmann } 1983a9de9248SMarcel Holtmann 1984a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 1985d095c1ebSAndrei Emeltchenko if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) { 1986a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 1987a9de9248SMarcel Holtmann cp.handle = ev->handle; 1988a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 198904124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp), 199004124681SGustavo F. Padovan &cp); 1991a9de9248SMarcel Holtmann } 199217d5c04cSJohan Hedberg } else { 1993a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 199417d5c04cSJohan Hedberg if (conn->type == ACL_LINK) 1995744cf19eSJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 199648264f06SJohan Hedberg conn->dst_type, ev->status); 199717d5c04cSJohan Hedberg } 199845bb4bf0SMarcel Holtmann 1999e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 2000e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 200145bb4bf0SMarcel Holtmann 2002769be974SMarcel Holtmann if (ev->status) { 2003a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2004a9de9248SMarcel Holtmann hci_conn_del(conn); 2005c89b6e6bSMarcel Holtmann } else if (ev->link_type != ACL_LINK) 2006c89b6e6bSMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2007a9de9248SMarcel Holtmann 2008a9de9248SMarcel Holtmann unlock: 20091da177e4SLinus Torvalds hci_dev_unlock(hdev); 2010a9de9248SMarcel Holtmann 2011a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 20121da177e4SLinus Torvalds } 20131da177e4SLinus Torvalds 20146039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 20151da177e4SLinus Torvalds { 2016a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 20171da177e4SLinus Torvalds int mask = hdev->link_mode; 20181da177e4SLinus Torvalds 20196ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr, 2020807deac2SGustavo Padovan ev->link_type); 20211da177e4SLinus Torvalds 20221da177e4SLinus Torvalds mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); 20231da177e4SLinus Torvalds 2024138d22efSSzymon Janc if ((mask & HCI_LM_ACCEPT) && 2025138d22efSSzymon Janc !hci_blacklist_lookup(hdev, &ev->bdaddr)) { 20261da177e4SLinus Torvalds /* Connection accepted */ 2027c7bdd502SMarcel Holtmann struct inquiry_entry *ie; 20281da177e4SLinus Torvalds struct hci_conn *conn; 20291da177e4SLinus Torvalds 20301da177e4SLinus Torvalds hci_dev_lock(hdev); 2031b6a0dc82SMarcel Holtmann 2032cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2033cc11b9c1SAndrei Emeltchenko if (ie) 2034c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 2035c7bdd502SMarcel Holtmann 20368fc9ced3SGustavo Padovan conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, 20378fc9ced3SGustavo Padovan &ev->bdaddr); 20381da177e4SLinus Torvalds if (!conn) { 2039cc11b9c1SAndrei Emeltchenko conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); 2040cc11b9c1SAndrei Emeltchenko if (!conn) { 2041893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 20421da177e4SLinus Torvalds hci_dev_unlock(hdev); 20431da177e4SLinus Torvalds return; 20441da177e4SLinus Torvalds } 20451da177e4SLinus Torvalds } 2046b6a0dc82SMarcel Holtmann 20471da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 20481da177e4SLinus Torvalds conn->state = BT_CONNECT; 2049b6a0dc82SMarcel Holtmann 20501da177e4SLinus Torvalds hci_dev_unlock(hdev); 20511da177e4SLinus Torvalds 2052b6a0dc82SMarcel Holtmann if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) { 2053b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 2054b6a0dc82SMarcel Holtmann 20551da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 20561da177e4SLinus Torvalds 20571da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 20581da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 20591da177e4SLinus Torvalds else 20601da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 20611da177e4SLinus Torvalds 206204124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), 206304124681SGustavo F. Padovan &cp); 2064b6a0dc82SMarcel Holtmann } else { 2065b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 2066b6a0dc82SMarcel Holtmann 2067b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 2068a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 2069b6a0dc82SMarcel Holtmann 207082781e63SAndrei Emeltchenko cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40); 207182781e63SAndrei Emeltchenko cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40); 207282781e63SAndrei Emeltchenko cp.max_latency = __constant_cpu_to_le16(0xffff); 2073b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 2074b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 2075b6a0dc82SMarcel Holtmann 2076b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 2077b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 2078b6a0dc82SMarcel Holtmann } 20791da177e4SLinus Torvalds } else { 20801da177e4SLinus Torvalds /* Connection rejected */ 20811da177e4SLinus Torvalds struct hci_cp_reject_conn_req cp; 20821da177e4SLinus Torvalds 20831da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 20849f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_REJ_BAD_ADDR; 2085a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 20861da177e4SLinus Torvalds } 20871da177e4SLinus Torvalds } 20881da177e4SLinus Torvalds 2089f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err) 2090f0d6a0eaSMikel Astiz { 2091f0d6a0eaSMikel Astiz switch (err) { 2092f0d6a0eaSMikel Astiz case HCI_ERROR_CONNECTION_TIMEOUT: 2093f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_TIMEOUT; 2094f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_USER_TERM: 2095f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_LOW_RESOURCES: 2096f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_POWER_OFF: 2097f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_REMOTE; 2098f0d6a0eaSMikel Astiz case HCI_ERROR_LOCAL_HOST_TERM: 2099f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_LOCAL_HOST; 2100f0d6a0eaSMikel Astiz default: 2101f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_UNKNOWN; 2102f0d6a0eaSMikel Astiz } 2103f0d6a0eaSMikel Astiz } 2104f0d6a0eaSMikel Astiz 21056039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 21061da177e4SLinus Torvalds { 2107a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 210804837f64SMarcel Holtmann struct hci_conn *conn; 21091da177e4SLinus Torvalds 21109f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 21111da177e4SLinus Torvalds 21121da177e4SLinus Torvalds hci_dev_lock(hdev); 21131da177e4SLinus Torvalds 211404837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2115f7520543SJohan Hedberg if (!conn) 2116f7520543SJohan Hedberg goto unlock; 2117f7520543SJohan Hedberg 211837d9ef76SJohan Hedberg if (ev->status == 0) 21191da177e4SLinus Torvalds conn->state = BT_CLOSED; 21207d0db0a3SMarcel Holtmann 2121b644ba33SJohan Hedberg if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) && 2122b644ba33SJohan Hedberg (conn->type == ACL_LINK || conn->type == LE_LINK)) { 2123f0d6a0eaSMikel Astiz if (ev->status) { 212488c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 212588c3df13SJohan Hedberg conn->dst_type, ev->status); 2126f0d6a0eaSMikel Astiz } else { 2127f0d6a0eaSMikel Astiz u8 reason = hci_to_mgmt_reason(ev->reason); 2128f0d6a0eaSMikel Astiz 2129afc747a6SJohan Hedberg mgmt_device_disconnected(hdev, &conn->dst, conn->type, 2130f0d6a0eaSMikel Astiz conn->dst_type, reason); 2131f0d6a0eaSMikel Astiz } 213237d9ef76SJohan Hedberg } 2133f7520543SJohan Hedberg 213437d9ef76SJohan Hedberg if (ev->status == 0) { 21356ec5bcadSVishal Agarwal if (conn->type == ACL_LINK && conn->flush_key) 21366ec5bcadSVishal Agarwal hci_remove_link_key(hdev, &conn->dst); 21372950f21aSMarcel Holtmann hci_proto_disconn_cfm(conn, ev->reason); 21381da177e4SLinus Torvalds hci_conn_del(conn); 213937d9ef76SJohan Hedberg } 21401da177e4SLinus Torvalds 2141f7520543SJohan Hedberg unlock: 21421da177e4SLinus Torvalds hci_dev_unlock(hdev); 21431da177e4SLinus Torvalds } 21441da177e4SLinus Torvalds 21456039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2146a9de9248SMarcel Holtmann { 2147a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 2148a9de9248SMarcel Holtmann struct hci_conn *conn; 2149a9de9248SMarcel Holtmann 21509f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2151a9de9248SMarcel Holtmann 2152a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2153a9de9248SMarcel Holtmann 2154a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2155d7556e20SWaldemar Rymarkiewicz if (!conn) 2156d7556e20SWaldemar Rymarkiewicz goto unlock; 2157d7556e20SWaldemar Rymarkiewicz 2158765c2a96SJohan Hedberg if (!ev->status) { 2159aa64a8b5SJohan Hedberg if (!hci_conn_ssp_enabled(conn) && 216051a8efd7SJohan Hedberg test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) { 2161d7556e20SWaldemar Rymarkiewicz BT_INFO("re-auth of legacy device is not possible."); 216219f8def0SWaldemar Rymarkiewicz } else { 2163a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 2164765c2a96SJohan Hedberg conn->sec_level = conn->pending_sec_level; 216519f8def0SWaldemar Rymarkiewicz } 21662a611692SJohan Hedberg } else { 2167bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 2168bab73cb6SJohan Hedberg ev->status); 21692a611692SJohan Hedberg } 2170a9de9248SMarcel Holtmann 217151a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 217251a8efd7SJohan Hedberg clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags); 2173a9de9248SMarcel Holtmann 2174f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 2175aa64a8b5SJohan Hedberg if (!ev->status && hci_conn_ssp_enabled(conn)) { 2176f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 2177f8558555SMarcel Holtmann cp.handle = ev->handle; 2178f8558555SMarcel Holtmann cp.encrypt = 0x01; 2179d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 2180d7556e20SWaldemar Rymarkiewicz &cp); 2181f8558555SMarcel Holtmann } else { 2182f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 2183f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2184f8558555SMarcel Holtmann hci_conn_put(conn); 2185f8558555SMarcel Holtmann } 2186052b30b0SMarcel Holtmann } else { 2187a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 2188a9de9248SMarcel Holtmann 2189052b30b0SMarcel Holtmann hci_conn_hold(conn); 2190052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2191052b30b0SMarcel Holtmann hci_conn_put(conn); 2192052b30b0SMarcel Holtmann } 2193052b30b0SMarcel Holtmann 219451a8efd7SJohan Hedberg if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) { 2195a9de9248SMarcel Holtmann if (!ev->status) { 2196a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 2197f8558555SMarcel Holtmann cp.handle = ev->handle; 2198f8558555SMarcel Holtmann cp.encrypt = 0x01; 2199d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 2200d7556e20SWaldemar Rymarkiewicz &cp); 2201a9de9248SMarcel Holtmann } else { 220251a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 2203a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 2204a9de9248SMarcel Holtmann } 2205a9de9248SMarcel Holtmann } 2206a9de9248SMarcel Holtmann 2207d7556e20SWaldemar Rymarkiewicz unlock: 2208a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2209a9de9248SMarcel Holtmann } 2210a9de9248SMarcel Holtmann 22116039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 2212a9de9248SMarcel Holtmann { 2213127178d2SJohan Hedberg struct hci_ev_remote_name *ev = (void *) skb->data; 2214127178d2SJohan Hedberg struct hci_conn *conn; 2215127178d2SJohan Hedberg 2216a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2217a9de9248SMarcel Holtmann 2218a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 2219127178d2SJohan Hedberg 2220127178d2SJohan Hedberg hci_dev_lock(hdev); 2221127178d2SJohan Hedberg 2222127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2223b644ba33SJohan Hedberg 2224b644ba33SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 2225b644ba33SJohan Hedberg goto check_auth; 2226b644ba33SJohan Hedberg 2227b644ba33SJohan Hedberg if (ev->status == 0) 2228b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name, 2229b644ba33SJohan Hedberg strnlen(ev->name, HCI_MAX_NAME_LENGTH)); 2230b644ba33SJohan Hedberg else 2231b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0); 2232b644ba33SJohan Hedberg 2233b644ba33SJohan Hedberg check_auth: 223479c6c70cSJohan Hedberg if (!conn) 223579c6c70cSJohan Hedberg goto unlock; 223679c6c70cSJohan Hedberg 223779c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 223879c6c70cSJohan Hedberg goto unlock; 223979c6c70cSJohan Hedberg 224051a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 2241127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 2242127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 2243127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 2244127178d2SJohan Hedberg } 2245127178d2SJohan Hedberg 224679c6c70cSJohan Hedberg unlock: 2247127178d2SJohan Hedberg hci_dev_unlock(hdev); 2248a9de9248SMarcel Holtmann } 2249a9de9248SMarcel Holtmann 22506039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2251a9de9248SMarcel Holtmann { 2252a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 2253a9de9248SMarcel Holtmann struct hci_conn *conn; 2254a9de9248SMarcel Holtmann 22559f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2256a9de9248SMarcel Holtmann 2257a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2258a9de9248SMarcel Holtmann 2259a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2260a9de9248SMarcel Holtmann if (conn) { 2261a9de9248SMarcel Holtmann if (!ev->status) { 2262ae293196SMarcel Holtmann if (ev->encrypt) { 2263ae293196SMarcel Holtmann /* Encryption implies authentication */ 2264ae293196SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 2265a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 2266da85e5e5SVinicius Costa Gomes conn->sec_level = conn->pending_sec_level; 2267ae293196SMarcel Holtmann } else 2268a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_ENCRYPT; 2269a9de9248SMarcel Holtmann } 2270a9de9248SMarcel Holtmann 227151a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 2272a9de9248SMarcel Holtmann 2273a7d7723aSGustavo Padovan if (ev->status && conn->state == BT_CONNECTED) { 2274d839c813SGustavo Padovan hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE); 2275a7d7723aSGustavo Padovan hci_conn_put(conn); 2276a7d7723aSGustavo Padovan goto unlock; 2277a7d7723aSGustavo Padovan } 2278a7d7723aSGustavo Padovan 2279f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 2280f8558555SMarcel Holtmann if (!ev->status) 2281f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 2282f8558555SMarcel Holtmann 2283f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2284f8558555SMarcel Holtmann hci_conn_put(conn); 2285f8558555SMarcel Holtmann } else 2286a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 2287a9de9248SMarcel Holtmann } 2288a9de9248SMarcel Holtmann 2289a7d7723aSGustavo Padovan unlock: 2290a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2291a9de9248SMarcel Holtmann } 2292a9de9248SMarcel Holtmann 22936039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev, 2294807deac2SGustavo Padovan struct sk_buff *skb) 2295a9de9248SMarcel Holtmann { 2296a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 2297a9de9248SMarcel Holtmann struct hci_conn *conn; 2298a9de9248SMarcel Holtmann 22999f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2300a9de9248SMarcel Holtmann 2301a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2302a9de9248SMarcel Holtmann 2303a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2304a9de9248SMarcel Holtmann if (conn) { 2305a9de9248SMarcel Holtmann if (!ev->status) 2306a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_SECURE; 2307a9de9248SMarcel Holtmann 230851a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 2309a9de9248SMarcel Holtmann 2310a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 2311a9de9248SMarcel Holtmann } 2312a9de9248SMarcel Holtmann 2313a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2314a9de9248SMarcel Holtmann } 2315a9de9248SMarcel Holtmann 23166039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev, 2317807deac2SGustavo Padovan struct sk_buff *skb) 2318a9de9248SMarcel Holtmann { 2319a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 2320a9de9248SMarcel Holtmann struct hci_conn *conn; 2321a9de9248SMarcel Holtmann 23229f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2323a9de9248SMarcel Holtmann 2324a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2325a9de9248SMarcel Holtmann 2326a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2327ccd556feSJohan Hedberg if (!conn) 2328ccd556feSJohan Hedberg goto unlock; 2329ccd556feSJohan Hedberg 2330769be974SMarcel Holtmann if (!ev->status) 2331a9de9248SMarcel Holtmann memcpy(conn->features, ev->features, 8); 2332a9de9248SMarcel Holtmann 2333ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2334ccd556feSJohan Hedberg goto unlock; 2335ccd556feSJohan Hedberg 2336ccd556feSJohan Hedberg if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { 2337769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 2338769be974SMarcel Holtmann cp.handle = ev->handle; 2339769be974SMarcel Holtmann cp.page = 0x01; 2340ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 2341769be974SMarcel Holtmann sizeof(cp), &cp); 2342392599b9SJohan Hedberg goto unlock; 2343392599b9SJohan Hedberg } 2344392599b9SJohan Hedberg 2345671267bfSJohan Hedberg if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { 2346127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2347127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2348127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2349127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2350127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2351b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 2352b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 235308c79b61SJohan Hedberg conn->dst_type, 0, NULL, 0, 2354b644ba33SJohan Hedberg conn->dev_class); 2355392599b9SJohan Hedberg 2356127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2357769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2358769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2359769be974SMarcel Holtmann hci_conn_put(conn); 2360769be974SMarcel Holtmann } 2361769be974SMarcel Holtmann 2362ccd556feSJohan Hedberg unlock: 2363a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2364a9de9248SMarcel Holtmann } 2365a9de9248SMarcel Holtmann 23666039aa73SGustavo Padovan static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) 23676039aa73SGustavo Padovan { 23686039aa73SGustavo Padovan BT_DBG("%s", hdev->name); 23696039aa73SGustavo Padovan } 23706039aa73SGustavo Padovan 23716039aa73SGustavo Padovan static void hci_qos_setup_complete_evt(struct hci_dev *hdev, 2372807deac2SGustavo Padovan struct sk_buff *skb) 2373a9de9248SMarcel Holtmann { 2374a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2375a9de9248SMarcel Holtmann } 2376a9de9248SMarcel Holtmann 23776039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2378a9de9248SMarcel Holtmann { 2379a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 2380a9de9248SMarcel Holtmann __u16 opcode; 2381a9de9248SMarcel Holtmann 2382a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2383a9de9248SMarcel Holtmann 2384a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2385a9de9248SMarcel Holtmann 2386a9de9248SMarcel Holtmann switch (opcode) { 2387a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 2388a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 2389a9de9248SMarcel Holtmann break; 2390a9de9248SMarcel Holtmann 23914d93483bSAndre Guedes case HCI_OP_PERIODIC_INQ: 23924d93483bSAndre Guedes hci_cc_periodic_inq(hdev, skb); 23934d93483bSAndre Guedes break; 23944d93483bSAndre Guedes 2395a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 2396a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 2397a9de9248SMarcel Holtmann break; 2398a9de9248SMarcel Holtmann 2399a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 2400a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 2401a9de9248SMarcel Holtmann break; 2402a9de9248SMarcel Holtmann 2403a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 2404a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 2405a9de9248SMarcel Holtmann break; 2406a9de9248SMarcel Holtmann 2407e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 2408e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 2409e4e8e37cSMarcel Holtmann break; 2410e4e8e37cSMarcel Holtmann 2411a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 2412a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 2413a9de9248SMarcel Holtmann break; 2414a9de9248SMarcel Holtmann 2415e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 2416e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 2417e4e8e37cSMarcel Holtmann break; 2418e4e8e37cSMarcel Holtmann 2419e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 2420e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 2421e4e8e37cSMarcel Holtmann break; 2422e4e8e37cSMarcel Holtmann 2423a9de9248SMarcel Holtmann case HCI_OP_RESET: 2424a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 2425a9de9248SMarcel Holtmann break; 2426a9de9248SMarcel Holtmann 2427a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 2428a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 2429a9de9248SMarcel Holtmann break; 2430a9de9248SMarcel Holtmann 2431a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 2432a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 2433a9de9248SMarcel Holtmann break; 2434a9de9248SMarcel Holtmann 2435a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 2436a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 2437a9de9248SMarcel Holtmann break; 2438a9de9248SMarcel Holtmann 2439a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 2440a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 2441a9de9248SMarcel Holtmann break; 2442a9de9248SMarcel Holtmann 2443a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 2444a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 2445a9de9248SMarcel Holtmann break; 2446a9de9248SMarcel Holtmann 2447a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 2448a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 2449a9de9248SMarcel Holtmann break; 2450a9de9248SMarcel Holtmann 2451a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 2452a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 2453a9de9248SMarcel Holtmann break; 2454a9de9248SMarcel Holtmann 2455a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 2456a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 2457a9de9248SMarcel Holtmann break; 2458a9de9248SMarcel Holtmann 2459a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 2460a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 2461a9de9248SMarcel Holtmann break; 2462a9de9248SMarcel Holtmann 2463a9de9248SMarcel Holtmann case HCI_OP_HOST_BUFFER_SIZE: 2464a9de9248SMarcel Holtmann hci_cc_host_buffer_size(hdev, skb); 2465a9de9248SMarcel Holtmann break; 2466a9de9248SMarcel Holtmann 2467333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 2468333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 2469333140b5SMarcel Holtmann break; 2470333140b5SMarcel Holtmann 2471a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 2472a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 2473a9de9248SMarcel Holtmann break; 2474a9de9248SMarcel Holtmann 2475a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 2476a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 2477a9de9248SMarcel Holtmann break; 2478a9de9248SMarcel Holtmann 2479a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 2480a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 2481a9de9248SMarcel Holtmann break; 2482a9de9248SMarcel Holtmann 2483971e3a4bSAndre Guedes case HCI_OP_READ_LOCAL_EXT_FEATURES: 2484971e3a4bSAndre Guedes hci_cc_read_local_ext_features(hdev, skb); 2485971e3a4bSAndre Guedes break; 2486971e3a4bSAndre Guedes 2487a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 2488a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 2489a9de9248SMarcel Holtmann break; 2490a9de9248SMarcel Holtmann 2491a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 2492a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 2493a9de9248SMarcel Holtmann break; 2494a9de9248SMarcel Holtmann 2495350ee4cfSAndrei Emeltchenko case HCI_OP_READ_DATA_BLOCK_SIZE: 2496350ee4cfSAndrei Emeltchenko hci_cc_read_data_block_size(hdev, skb); 2497350ee4cfSAndrei Emeltchenko break; 2498350ee4cfSAndrei Emeltchenko 249923bb5763SJohan Hedberg case HCI_OP_WRITE_CA_TIMEOUT: 250023bb5763SJohan Hedberg hci_cc_write_ca_timeout(hdev, skb); 250123bb5763SJohan Hedberg break; 250223bb5763SJohan Hedberg 25031e89cffbSAndrei Emeltchenko case HCI_OP_READ_FLOW_CONTROL_MODE: 25041e89cffbSAndrei Emeltchenko hci_cc_read_flow_control_mode(hdev, skb); 25051e89cffbSAndrei Emeltchenko break; 25061e89cffbSAndrei Emeltchenko 2507928abaa7SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_INFO: 2508928abaa7SAndrei Emeltchenko hci_cc_read_local_amp_info(hdev, skb); 2509928abaa7SAndrei Emeltchenko break; 2510928abaa7SAndrei Emeltchenko 2511903e4541SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_ASSOC: 2512903e4541SAndrei Emeltchenko hci_cc_read_local_amp_assoc(hdev, skb); 2513903e4541SAndrei Emeltchenko break; 2514903e4541SAndrei Emeltchenko 2515b0916ea0SJohan Hedberg case HCI_OP_DELETE_STORED_LINK_KEY: 2516b0916ea0SJohan Hedberg hci_cc_delete_stored_link_key(hdev, skb); 2517b0916ea0SJohan Hedberg break; 2518b0916ea0SJohan Hedberg 2519d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_MASK: 2520d5859e22SJohan Hedberg hci_cc_set_event_mask(hdev, skb); 2521d5859e22SJohan Hedberg break; 2522d5859e22SJohan Hedberg 2523d5859e22SJohan Hedberg case HCI_OP_WRITE_INQUIRY_MODE: 2524d5859e22SJohan Hedberg hci_cc_write_inquiry_mode(hdev, skb); 2525d5859e22SJohan Hedberg break; 2526d5859e22SJohan Hedberg 2527d5859e22SJohan Hedberg case HCI_OP_READ_INQ_RSP_TX_POWER: 2528d5859e22SJohan Hedberg hci_cc_read_inq_rsp_tx_power(hdev, skb); 2529d5859e22SJohan Hedberg break; 2530d5859e22SJohan Hedberg 2531d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_FLT: 2532d5859e22SJohan Hedberg hci_cc_set_event_flt(hdev, skb); 2533d5859e22SJohan Hedberg break; 2534d5859e22SJohan Hedberg 2535980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_REPLY: 2536980e1a53SJohan Hedberg hci_cc_pin_code_reply(hdev, skb); 2537980e1a53SJohan Hedberg break; 2538980e1a53SJohan Hedberg 2539980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_NEG_REPLY: 2540980e1a53SJohan Hedberg hci_cc_pin_code_neg_reply(hdev, skb); 2541980e1a53SJohan Hedberg break; 2542980e1a53SJohan Hedberg 2543c35938b2SSzymon Janc case HCI_OP_READ_LOCAL_OOB_DATA: 2544c35938b2SSzymon Janc hci_cc_read_local_oob_data_reply(hdev, skb); 2545c35938b2SSzymon Janc break; 2546c35938b2SSzymon Janc 25476ed58ec5SVille Tervo case HCI_OP_LE_READ_BUFFER_SIZE: 25486ed58ec5SVille Tervo hci_cc_le_read_buffer_size(hdev, skb); 25496ed58ec5SVille Tervo break; 25506ed58ec5SVille Tervo 25518fa19098SJohan Hedberg case HCI_OP_LE_READ_ADV_TX_POWER: 25528fa19098SJohan Hedberg hci_cc_le_read_adv_tx_power(hdev, skb); 25538fa19098SJohan Hedberg break; 25548fa19098SJohan Hedberg 2555e36b04c8SJohan Hedberg case HCI_OP_LE_SET_EVENT_MASK: 2556e36b04c8SJohan Hedberg hci_cc_le_set_event_mask(hdev, skb); 2557e36b04c8SJohan Hedberg break; 2558e36b04c8SJohan Hedberg 2559a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_REPLY: 2560a5c29683SJohan Hedberg hci_cc_user_confirm_reply(hdev, skb); 2561a5c29683SJohan Hedberg break; 2562a5c29683SJohan Hedberg 2563a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_NEG_REPLY: 2564a5c29683SJohan Hedberg hci_cc_user_confirm_neg_reply(hdev, skb); 2565a5c29683SJohan Hedberg break; 2566a5c29683SJohan Hedberg 25671143d458SBrian Gix case HCI_OP_USER_PASSKEY_REPLY: 25681143d458SBrian Gix hci_cc_user_passkey_reply(hdev, skb); 25691143d458SBrian Gix break; 25701143d458SBrian Gix 25711143d458SBrian Gix case HCI_OP_USER_PASSKEY_NEG_REPLY: 25721143d458SBrian Gix hci_cc_user_passkey_neg_reply(hdev, skb); 257316cde993SSzymon Janc break; 257407f7fa5dSAndre Guedes 257507f7fa5dSAndre Guedes case HCI_OP_LE_SET_SCAN_PARAM: 257607f7fa5dSAndre Guedes hci_cc_le_set_scan_param(hdev, skb); 25771143d458SBrian Gix break; 25781143d458SBrian Gix 2579eb9d91f5SAndre Guedes case HCI_OP_LE_SET_SCAN_ENABLE: 2580eb9d91f5SAndre Guedes hci_cc_le_set_scan_enable(hdev, skb); 2581eb9d91f5SAndre Guedes break; 2582eb9d91f5SAndre Guedes 2583a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_REPLY: 2584a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_reply(hdev, skb); 2585a7a595f6SVinicius Costa Gomes break; 2586a7a595f6SVinicius Costa Gomes 2587a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_NEG_REPLY: 2588a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_neg_reply(hdev, skb); 2589a7a595f6SVinicius Costa Gomes break; 2590a7a595f6SVinicius Costa Gomes 2591f9b49306SAndre Guedes case HCI_OP_WRITE_LE_HOST_SUPPORTED: 2592f9b49306SAndre Guedes hci_cc_write_le_host_supported(hdev, skb); 2593f9b49306SAndre Guedes break; 2594f9b49306SAndre Guedes 259593c284eeSAndrei Emeltchenko case HCI_OP_WRITE_REMOTE_AMP_ASSOC: 259693c284eeSAndrei Emeltchenko hci_cc_write_remote_amp_assoc(hdev, skb); 259793c284eeSAndrei Emeltchenko break; 259893c284eeSAndrei Emeltchenko 2599a9de9248SMarcel Holtmann default: 26009f1db00cSAndrei Emeltchenko BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); 2601a9de9248SMarcel Holtmann break; 2602a9de9248SMarcel Holtmann } 2603a9de9248SMarcel Holtmann 26046bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 26056bd32326SVille Tervo del_timer(&hdev->cmd_timer); 26066bd32326SVille Tervo 2607a9de9248SMarcel Holtmann if (ev->ncmd) { 2608a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2609a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2610c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2611a9de9248SMarcel Holtmann } 2612a9de9248SMarcel Holtmann } 2613a9de9248SMarcel Holtmann 26146039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 2615a9de9248SMarcel Holtmann { 2616a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 2617a9de9248SMarcel Holtmann __u16 opcode; 2618a9de9248SMarcel Holtmann 2619a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2620a9de9248SMarcel Holtmann 2621a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2622a9de9248SMarcel Holtmann 2623a9de9248SMarcel Holtmann switch (opcode) { 2624a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 2625a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 2626a9de9248SMarcel Holtmann break; 2627a9de9248SMarcel Holtmann 2628a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 2629a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 2630a9de9248SMarcel Holtmann break; 2631a9de9248SMarcel Holtmann 2632a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 2633a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 2634a9de9248SMarcel Holtmann break; 2635a9de9248SMarcel Holtmann 2636f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 2637f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 2638f8558555SMarcel Holtmann break; 2639f8558555SMarcel Holtmann 2640f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 2641f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 2642f8558555SMarcel Holtmann break; 2643f8558555SMarcel Holtmann 2644a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 2645a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 2646a9de9248SMarcel Holtmann break; 2647a9de9248SMarcel Holtmann 2648769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 2649769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 2650769be974SMarcel Holtmann break; 2651769be974SMarcel Holtmann 2652769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 2653769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 2654769be974SMarcel Holtmann break; 2655769be974SMarcel Holtmann 2656a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 2657a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 2658a9de9248SMarcel Holtmann break; 2659a9de9248SMarcel Holtmann 2660a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 2661a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 2662a9de9248SMarcel Holtmann break; 2663a9de9248SMarcel Holtmann 2664a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 2665a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 2666a9de9248SMarcel Holtmann break; 2667a9de9248SMarcel Holtmann 26688962ee74SJohan Hedberg case HCI_OP_DISCONNECT: 266988c3df13SJohan Hedberg hci_cs_disconnect(hdev, ev->status); 26708962ee74SJohan Hedberg break; 26718962ee74SJohan Hedberg 2672fcd89c09SVille Tervo case HCI_OP_LE_CREATE_CONN: 2673fcd89c09SVille Tervo hci_cs_le_create_conn(hdev, ev->status); 2674fcd89c09SVille Tervo break; 2675fcd89c09SVille Tervo 2676a7a595f6SVinicius Costa Gomes case HCI_OP_LE_START_ENC: 2677a7a595f6SVinicius Costa Gomes hci_cs_le_start_enc(hdev, ev->status); 2678a7a595f6SVinicius Costa Gomes break; 2679a7a595f6SVinicius Costa Gomes 2680a02226d6SAndrei Emeltchenko case HCI_OP_CREATE_PHY_LINK: 2681a02226d6SAndrei Emeltchenko hci_cs_create_phylink(hdev, ev->status); 2682a02226d6SAndrei Emeltchenko break; 2683a02226d6SAndrei Emeltchenko 26840b26ab9dSAndrei Emeltchenko case HCI_OP_ACCEPT_PHY_LINK: 26850b26ab9dSAndrei Emeltchenko hci_cs_accept_phylink(hdev, ev->status); 26860b26ab9dSAndrei Emeltchenko break; 26870b26ab9dSAndrei Emeltchenko 26885ce66b59SAndrei Emeltchenko case HCI_OP_CREATE_LOGICAL_LINK: 26895ce66b59SAndrei Emeltchenko hci_cs_create_logical_link(hdev, ev->status); 26905ce66b59SAndrei Emeltchenko break; 26915ce66b59SAndrei Emeltchenko 2692a9de9248SMarcel Holtmann default: 26939f1db00cSAndrei Emeltchenko BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); 2694a9de9248SMarcel Holtmann break; 2695a9de9248SMarcel Holtmann } 2696a9de9248SMarcel Holtmann 26976bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 26986bd32326SVille Tervo del_timer(&hdev->cmd_timer); 26996bd32326SVille Tervo 270010572132SGustavo F. Padovan if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2701a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2702a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2703c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2704a9de9248SMarcel Holtmann } 2705a9de9248SMarcel Holtmann } 2706a9de9248SMarcel Holtmann 27076039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2708a9de9248SMarcel Holtmann { 2709a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 2710a9de9248SMarcel Holtmann struct hci_conn *conn; 2711a9de9248SMarcel Holtmann 27129f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2713a9de9248SMarcel Holtmann 2714a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2715a9de9248SMarcel Holtmann 2716a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2717a9de9248SMarcel Holtmann if (conn) { 2718a9de9248SMarcel Holtmann if (!ev->status) { 2719a9de9248SMarcel Holtmann if (ev->role) 2720a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_MASTER; 2721a9de9248SMarcel Holtmann else 2722a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_MASTER; 2723a9de9248SMarcel Holtmann } 2724a9de9248SMarcel Holtmann 272551a8efd7SJohan Hedberg clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); 2726a9de9248SMarcel Holtmann 2727a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 2728a9de9248SMarcel Holtmann } 2729a9de9248SMarcel Holtmann 2730a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2731a9de9248SMarcel Holtmann } 2732a9de9248SMarcel Holtmann 27336039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 27341da177e4SLinus Torvalds { 2735a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 27361da177e4SLinus Torvalds int i; 27371da177e4SLinus Torvalds 273832ac5b9bSAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) { 273932ac5b9bSAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 274032ac5b9bSAndrei Emeltchenko return; 274132ac5b9bSAndrei Emeltchenko } 274232ac5b9bSAndrei Emeltchenko 2743c5993de8SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 2744c5993de8SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_pkts_info)) { 27451da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 27461da177e4SLinus Torvalds return; 27471da177e4SLinus Torvalds } 27481da177e4SLinus Torvalds 2749c5993de8SAndrei Emeltchenko BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 2750c5993de8SAndrei Emeltchenko 2751613a1c0cSAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 2752613a1c0cSAndrei Emeltchenko struct hci_comp_pkts_info *info = &ev->handles[i]; 27531da177e4SLinus Torvalds struct hci_conn *conn; 27541da177e4SLinus Torvalds __u16 handle, count; 27551da177e4SLinus Torvalds 2756613a1c0cSAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 2757613a1c0cSAndrei Emeltchenko count = __le16_to_cpu(info->count); 27581da177e4SLinus Torvalds 27591da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 2760f4280918SAndrei Emeltchenko if (!conn) 2761f4280918SAndrei Emeltchenko continue; 2762f4280918SAndrei Emeltchenko 27631da177e4SLinus Torvalds conn->sent -= count; 27641da177e4SLinus Torvalds 2765f4280918SAndrei Emeltchenko switch (conn->type) { 2766f4280918SAndrei Emeltchenko case ACL_LINK: 276770f23020SAndrei Emeltchenko hdev->acl_cnt += count; 276870f23020SAndrei Emeltchenko if (hdev->acl_cnt > hdev->acl_pkts) 27691da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 2770f4280918SAndrei Emeltchenko break; 2771f4280918SAndrei Emeltchenko 2772f4280918SAndrei Emeltchenko case LE_LINK: 27736ed58ec5SVille Tervo if (hdev->le_pkts) { 27746ed58ec5SVille Tervo hdev->le_cnt += count; 27756ed58ec5SVille Tervo if (hdev->le_cnt > hdev->le_pkts) 27766ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 27776ed58ec5SVille Tervo } else { 27786ed58ec5SVille Tervo hdev->acl_cnt += count; 27796ed58ec5SVille Tervo if (hdev->acl_cnt > hdev->acl_pkts) 27806ed58ec5SVille Tervo hdev->acl_cnt = hdev->acl_pkts; 27816ed58ec5SVille Tervo } 2782f4280918SAndrei Emeltchenko break; 2783f4280918SAndrei Emeltchenko 2784f4280918SAndrei Emeltchenko case SCO_LINK: 278570f23020SAndrei Emeltchenko hdev->sco_cnt += count; 278670f23020SAndrei Emeltchenko if (hdev->sco_cnt > hdev->sco_pkts) 27875b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 2788f4280918SAndrei Emeltchenko break; 2789f4280918SAndrei Emeltchenko 2790f4280918SAndrei Emeltchenko default: 2791f4280918SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 2792f4280918SAndrei Emeltchenko break; 27931da177e4SLinus Torvalds } 27941da177e4SLinus Torvalds } 2795a9de9248SMarcel Holtmann 27963eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 27971da177e4SLinus Torvalds } 27981da177e4SLinus Torvalds 279976ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev, 280076ef7cf7SAndrei Emeltchenko __u16 handle) 280176ef7cf7SAndrei Emeltchenko { 280276ef7cf7SAndrei Emeltchenko struct hci_chan *chan; 280376ef7cf7SAndrei Emeltchenko 280476ef7cf7SAndrei Emeltchenko switch (hdev->dev_type) { 280576ef7cf7SAndrei Emeltchenko case HCI_BREDR: 280676ef7cf7SAndrei Emeltchenko return hci_conn_hash_lookup_handle(hdev, handle); 280776ef7cf7SAndrei Emeltchenko case HCI_AMP: 280876ef7cf7SAndrei Emeltchenko chan = hci_chan_lookup_handle(hdev, handle); 280976ef7cf7SAndrei Emeltchenko if (chan) 281076ef7cf7SAndrei Emeltchenko return chan->conn; 281176ef7cf7SAndrei Emeltchenko break; 281276ef7cf7SAndrei Emeltchenko default: 281376ef7cf7SAndrei Emeltchenko BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type); 281476ef7cf7SAndrei Emeltchenko break; 281576ef7cf7SAndrei Emeltchenko } 281676ef7cf7SAndrei Emeltchenko 281776ef7cf7SAndrei Emeltchenko return NULL; 281876ef7cf7SAndrei Emeltchenko } 281976ef7cf7SAndrei Emeltchenko 28206039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb) 282125e89e99SAndrei Emeltchenko { 282225e89e99SAndrei Emeltchenko struct hci_ev_num_comp_blocks *ev = (void *) skb->data; 282325e89e99SAndrei Emeltchenko int i; 282425e89e99SAndrei Emeltchenko 282525e89e99SAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) { 282625e89e99SAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 282725e89e99SAndrei Emeltchenko return; 282825e89e99SAndrei Emeltchenko } 282925e89e99SAndrei Emeltchenko 283025e89e99SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 283125e89e99SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_blocks_info)) { 283225e89e99SAndrei Emeltchenko BT_DBG("%s bad parameters", hdev->name); 283325e89e99SAndrei Emeltchenko return; 283425e89e99SAndrei Emeltchenko } 283525e89e99SAndrei Emeltchenko 283625e89e99SAndrei Emeltchenko BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks, 283725e89e99SAndrei Emeltchenko ev->num_hndl); 283825e89e99SAndrei Emeltchenko 283925e89e99SAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 284025e89e99SAndrei Emeltchenko struct hci_comp_blocks_info *info = &ev->handles[i]; 284176ef7cf7SAndrei Emeltchenko struct hci_conn *conn = NULL; 284225e89e99SAndrei Emeltchenko __u16 handle, block_count; 284325e89e99SAndrei Emeltchenko 284425e89e99SAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 284525e89e99SAndrei Emeltchenko block_count = __le16_to_cpu(info->blocks); 284625e89e99SAndrei Emeltchenko 284776ef7cf7SAndrei Emeltchenko conn = __hci_conn_lookup_handle(hdev, handle); 284825e89e99SAndrei Emeltchenko if (!conn) 284925e89e99SAndrei Emeltchenko continue; 285025e89e99SAndrei Emeltchenko 285125e89e99SAndrei Emeltchenko conn->sent -= block_count; 285225e89e99SAndrei Emeltchenko 285325e89e99SAndrei Emeltchenko switch (conn->type) { 285425e89e99SAndrei Emeltchenko case ACL_LINK: 2855bd1eb66bSAndrei Emeltchenko case AMP_LINK: 285625e89e99SAndrei Emeltchenko hdev->block_cnt += block_count; 285725e89e99SAndrei Emeltchenko if (hdev->block_cnt > hdev->num_blocks) 285825e89e99SAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 285925e89e99SAndrei Emeltchenko break; 286025e89e99SAndrei Emeltchenko 286125e89e99SAndrei Emeltchenko default: 286225e89e99SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 286325e89e99SAndrei Emeltchenko break; 286425e89e99SAndrei Emeltchenko } 286525e89e99SAndrei Emeltchenko } 286625e89e99SAndrei Emeltchenko 286725e89e99SAndrei Emeltchenko queue_work(hdev->workqueue, &hdev->tx_work); 286825e89e99SAndrei Emeltchenko } 286925e89e99SAndrei Emeltchenko 28706039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 28711da177e4SLinus Torvalds { 2872a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 287304837f64SMarcel Holtmann struct hci_conn *conn; 28741da177e4SLinus Torvalds 28759f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 28761da177e4SLinus Torvalds 28771da177e4SLinus Torvalds hci_dev_lock(hdev); 28781da177e4SLinus Torvalds 287904837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 288004837f64SMarcel Holtmann if (conn) { 288104837f64SMarcel Holtmann conn->mode = ev->mode; 288204837f64SMarcel Holtmann conn->interval = __le16_to_cpu(ev->interval); 288304837f64SMarcel Holtmann 28848fc9ced3SGustavo Padovan if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, 28858fc9ced3SGustavo Padovan &conn->flags)) { 288604837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 288758a681efSJohan Hedberg set_bit(HCI_CONN_POWER_SAVE, &conn->flags); 288804837f64SMarcel Holtmann else 288958a681efSJohan Hedberg clear_bit(HCI_CONN_POWER_SAVE, &conn->flags); 289004837f64SMarcel Holtmann } 2891e73439d8SMarcel Holtmann 289251a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 2893e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 289404837f64SMarcel Holtmann } 289504837f64SMarcel Holtmann 289604837f64SMarcel Holtmann hci_dev_unlock(hdev); 289704837f64SMarcel Holtmann } 289804837f64SMarcel Holtmann 28996039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 29001da177e4SLinus Torvalds { 2901052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 2902052b30b0SMarcel Holtmann struct hci_conn *conn; 2903052b30b0SMarcel Holtmann 2904a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2905052b30b0SMarcel Holtmann 2906052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2907052b30b0SMarcel Holtmann 2908052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2909b6f98044SWaldemar Rymarkiewicz if (!conn) 2910b6f98044SWaldemar Rymarkiewicz goto unlock; 2911b6f98044SWaldemar Rymarkiewicz 2912b6f98044SWaldemar Rymarkiewicz if (conn->state == BT_CONNECTED) { 2913052b30b0SMarcel Holtmann hci_conn_hold(conn); 2914052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 2915052b30b0SMarcel Holtmann hci_conn_put(conn); 2916052b30b0SMarcel Holtmann } 2917052b30b0SMarcel Holtmann 2918a8b2d5c2SJohan Hedberg if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags)) 291903b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 292003b555e1SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 2921a8b2d5c2SJohan Hedberg else if (test_bit(HCI_MGMT, &hdev->dev_flags)) { 2922a770bb5aSWaldemar Rymarkiewicz u8 secure; 2923a770bb5aSWaldemar Rymarkiewicz 2924a770bb5aSWaldemar Rymarkiewicz if (conn->pending_sec_level == BT_SECURITY_HIGH) 2925a770bb5aSWaldemar Rymarkiewicz secure = 1; 2926a770bb5aSWaldemar Rymarkiewicz else 2927a770bb5aSWaldemar Rymarkiewicz secure = 0; 2928a770bb5aSWaldemar Rymarkiewicz 2929744cf19eSJohan Hedberg mgmt_pin_code_request(hdev, &ev->bdaddr, secure); 2930a770bb5aSWaldemar Rymarkiewicz } 2931980e1a53SJohan Hedberg 2932b6f98044SWaldemar Rymarkiewicz unlock: 2933052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 29341da177e4SLinus Torvalds } 29351da177e4SLinus Torvalds 29366039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 29371da177e4SLinus Torvalds { 293855ed8ca1SJohan Hedberg struct hci_ev_link_key_req *ev = (void *) skb->data; 293955ed8ca1SJohan Hedberg struct hci_cp_link_key_reply cp; 294055ed8ca1SJohan Hedberg struct hci_conn *conn; 294155ed8ca1SJohan Hedberg struct link_key *key; 294255ed8ca1SJohan Hedberg 2943a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 294455ed8ca1SJohan Hedberg 2945a8b2d5c2SJohan Hedberg if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) 294655ed8ca1SJohan Hedberg return; 294755ed8ca1SJohan Hedberg 294855ed8ca1SJohan Hedberg hci_dev_lock(hdev); 294955ed8ca1SJohan Hedberg 295055ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, &ev->bdaddr); 295155ed8ca1SJohan Hedberg if (!key) { 29526ed93dc6SAndrei Emeltchenko BT_DBG("%s link key not found for %pMR", hdev->name, 29536ed93dc6SAndrei Emeltchenko &ev->bdaddr); 295455ed8ca1SJohan Hedberg goto not_found; 295555ed8ca1SJohan Hedberg } 295655ed8ca1SJohan Hedberg 29576ed93dc6SAndrei Emeltchenko BT_DBG("%s found key type %u for %pMR", hdev->name, key->type, 29586ed93dc6SAndrei Emeltchenko &ev->bdaddr); 295955ed8ca1SJohan Hedberg 2960a8b2d5c2SJohan Hedberg if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) && 2961b6020ba0SWaldemar Rymarkiewicz key->type == HCI_LK_DEBUG_COMBINATION) { 296255ed8ca1SJohan Hedberg BT_DBG("%s ignoring debug key", hdev->name); 296355ed8ca1SJohan Hedberg goto not_found; 296455ed8ca1SJohan Hedberg } 296555ed8ca1SJohan Hedberg 296655ed8ca1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 296760b83f57SWaldemar Rymarkiewicz if (conn) { 296860b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_UNAUTH_COMBINATION && 2969807deac2SGustavo Padovan conn->auth_type != 0xff && (conn->auth_type & 0x01)) { 297055ed8ca1SJohan Hedberg BT_DBG("%s ignoring unauthenticated key", hdev->name); 297155ed8ca1SJohan Hedberg goto not_found; 297255ed8ca1SJohan Hedberg } 297355ed8ca1SJohan Hedberg 297460b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && 297560b83f57SWaldemar Rymarkiewicz conn->pending_sec_level == BT_SECURITY_HIGH) { 29768fc9ced3SGustavo Padovan BT_DBG("%s ignoring key unauthenticated for high security", 29778fc9ced3SGustavo Padovan hdev->name); 297860b83f57SWaldemar Rymarkiewicz goto not_found; 297960b83f57SWaldemar Rymarkiewicz } 298060b83f57SWaldemar Rymarkiewicz 298160b83f57SWaldemar Rymarkiewicz conn->key_type = key->type; 298260b83f57SWaldemar Rymarkiewicz conn->pin_length = key->pin_len; 298360b83f57SWaldemar Rymarkiewicz } 298460b83f57SWaldemar Rymarkiewicz 298555ed8ca1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 29869b3b4460SAndrei Emeltchenko memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE); 298755ed8ca1SJohan Hedberg 298855ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 298955ed8ca1SJohan Hedberg 299055ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 299155ed8ca1SJohan Hedberg 299255ed8ca1SJohan Hedberg return; 299355ed8ca1SJohan Hedberg 299455ed8ca1SJohan Hedberg not_found: 299555ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 299655ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 29971da177e4SLinus Torvalds } 29981da177e4SLinus Torvalds 29996039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 30001da177e4SLinus Torvalds { 3001052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 3002052b30b0SMarcel Holtmann struct hci_conn *conn; 300355ed8ca1SJohan Hedberg u8 pin_len = 0; 3004052b30b0SMarcel Holtmann 3005a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 3006052b30b0SMarcel Holtmann 3007052b30b0SMarcel Holtmann hci_dev_lock(hdev); 3008052b30b0SMarcel Holtmann 3009052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 3010052b30b0SMarcel Holtmann if (conn) { 3011052b30b0SMarcel Holtmann hci_conn_hold(conn); 3012052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 3013980e1a53SJohan Hedberg pin_len = conn->pin_length; 301413d39315SWaldemar Rymarkiewicz 301513d39315SWaldemar Rymarkiewicz if (ev->key_type != HCI_LK_CHANGED_COMBINATION) 301613d39315SWaldemar Rymarkiewicz conn->key_type = ev->key_type; 301713d39315SWaldemar Rymarkiewicz 3018052b30b0SMarcel Holtmann hci_conn_put(conn); 3019052b30b0SMarcel Holtmann } 3020052b30b0SMarcel Holtmann 3021a8b2d5c2SJohan Hedberg if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) 3022d25e28abSJohan Hedberg hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, 302355ed8ca1SJohan Hedberg ev->key_type, pin_len); 302455ed8ca1SJohan Hedberg 3025052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 30261da177e4SLinus Torvalds } 30271da177e4SLinus Torvalds 30286039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 302904837f64SMarcel Holtmann { 3030a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 303104837f64SMarcel Holtmann struct hci_conn *conn; 303204837f64SMarcel Holtmann 30339f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 303404837f64SMarcel Holtmann 303504837f64SMarcel Holtmann hci_dev_lock(hdev); 303604837f64SMarcel Holtmann 303704837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 30381da177e4SLinus Torvalds if (conn && !ev->status) { 30391da177e4SLinus Torvalds struct inquiry_entry *ie; 30401da177e4SLinus Torvalds 3041cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 3042cc11b9c1SAndrei Emeltchenko if (ie) { 30431da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 30441da177e4SLinus Torvalds ie->timestamp = jiffies; 30451da177e4SLinus Torvalds } 30461da177e4SLinus Torvalds } 30471da177e4SLinus Torvalds 30481da177e4SLinus Torvalds hci_dev_unlock(hdev); 30491da177e4SLinus Torvalds } 30501da177e4SLinus Torvalds 30516039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 3052a8746417SMarcel Holtmann { 3053a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 3054a8746417SMarcel Holtmann struct hci_conn *conn; 3055a8746417SMarcel Holtmann 30569f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 3057a8746417SMarcel Holtmann 3058a8746417SMarcel Holtmann hci_dev_lock(hdev); 3059a8746417SMarcel Holtmann 3060a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3061a8746417SMarcel Holtmann if (conn && !ev->status) 3062a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 3063a8746417SMarcel Holtmann 3064a8746417SMarcel Holtmann hci_dev_unlock(hdev); 3065a8746417SMarcel Holtmann } 3066a8746417SMarcel Holtmann 30676039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 306885a1e930SMarcel Holtmann { 3069a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 307085a1e930SMarcel Holtmann struct inquiry_entry *ie; 307185a1e930SMarcel Holtmann 307285a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 307385a1e930SMarcel Holtmann 307485a1e930SMarcel Holtmann hci_dev_lock(hdev); 307585a1e930SMarcel Holtmann 3076cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 3077cc11b9c1SAndrei Emeltchenko if (ie) { 307885a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 307985a1e930SMarcel Holtmann ie->timestamp = jiffies; 308085a1e930SMarcel Holtmann } 308185a1e930SMarcel Holtmann 308285a1e930SMarcel Holtmann hci_dev_unlock(hdev); 308385a1e930SMarcel Holtmann } 308485a1e930SMarcel Holtmann 30856039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, 3086807deac2SGustavo Padovan struct sk_buff *skb) 3087a9de9248SMarcel Holtmann { 3088a9de9248SMarcel Holtmann struct inquiry_data data; 3089a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 3090388fc8faSJohan Hedberg bool name_known, ssp; 3091a9de9248SMarcel Holtmann 3092a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 3093a9de9248SMarcel Holtmann 3094a9de9248SMarcel Holtmann if (!num_rsp) 3095a9de9248SMarcel Holtmann return; 3096a9de9248SMarcel Holtmann 30971519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 30981519cc17SAndre Guedes return; 30991519cc17SAndre Guedes 3100a9de9248SMarcel Holtmann hci_dev_lock(hdev); 3101a9de9248SMarcel Holtmann 3102a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 3103138d22efSSzymon Janc struct inquiry_info_with_rssi_and_pscan_mode *info; 3104138d22efSSzymon Janc info = (void *) (skb->data + 1); 3105a9de9248SMarcel Holtmann 3106e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 3107a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 3108a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 3109a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 3110a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 3111a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 3112a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 3113a9de9248SMarcel Holtmann data.rssi = info->rssi; 311441a96212SMarcel Holtmann data.ssp_mode = 0x00; 31153175405bSJohan Hedberg 31163175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 3117388fc8faSJohan Hedberg false, &ssp); 311848264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 3119e17acd40SJohan Hedberg info->dev_class, info->rssi, 3120388fc8faSJohan Hedberg !name_known, ssp, NULL, 0); 3121a9de9248SMarcel Holtmann } 3122a9de9248SMarcel Holtmann } else { 3123a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 3124a9de9248SMarcel Holtmann 3125e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 3126a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 3127a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 3128a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 3129a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 3130a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 3131a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 3132a9de9248SMarcel Holtmann data.rssi = info->rssi; 313341a96212SMarcel Holtmann data.ssp_mode = 0x00; 31343175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 3135388fc8faSJohan Hedberg false, &ssp); 313648264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 3137e17acd40SJohan Hedberg info->dev_class, info->rssi, 3138388fc8faSJohan Hedberg !name_known, ssp, NULL, 0); 3139a9de9248SMarcel Holtmann } 3140a9de9248SMarcel Holtmann } 3141a9de9248SMarcel Holtmann 3142a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 3143a9de9248SMarcel Holtmann } 3144a9de9248SMarcel Holtmann 31456039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev, 3146807deac2SGustavo Padovan struct sk_buff *skb) 3147a9de9248SMarcel Holtmann { 314841a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 314941a96212SMarcel Holtmann struct hci_conn *conn; 315041a96212SMarcel Holtmann 3151a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 315241a96212SMarcel Holtmann 315341a96212SMarcel Holtmann hci_dev_lock(hdev); 315441a96212SMarcel Holtmann 315541a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3156ccd556feSJohan Hedberg if (!conn) 3157ccd556feSJohan Hedberg goto unlock; 3158ccd556feSJohan Hedberg 3159769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 316041a96212SMarcel Holtmann struct inquiry_entry *ie; 316141a96212SMarcel Holtmann 3162cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 3163cc11b9c1SAndrei Emeltchenko if (ie) 316402b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 316541a96212SMarcel Holtmann 316602b7cc62SJohan Hedberg if (ev->features[0] & LMP_HOST_SSP) 316758a681efSJohan Hedberg set_bit(HCI_CONN_SSP_ENABLED, &conn->flags); 316841a96212SMarcel Holtmann } 316941a96212SMarcel Holtmann 3170ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 3171ccd556feSJohan Hedberg goto unlock; 3172ccd556feSJohan Hedberg 3173671267bfSJohan Hedberg if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { 3174127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 3175127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 3176127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 3177127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 3178127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 3179b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 3180b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 318108c79b61SJohan Hedberg conn->dst_type, 0, NULL, 0, 3182b644ba33SJohan Hedberg conn->dev_class); 3183392599b9SJohan Hedberg 3184127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 3185769be974SMarcel Holtmann conn->state = BT_CONNECTED; 3186769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 3187769be974SMarcel Holtmann hci_conn_put(conn); 3188769be974SMarcel Holtmann } 3189769be974SMarcel Holtmann 3190ccd556feSJohan Hedberg unlock: 319141a96212SMarcel Holtmann hci_dev_unlock(hdev); 3192a9de9248SMarcel Holtmann } 3193a9de9248SMarcel Holtmann 31946039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev, 3195807deac2SGustavo Padovan struct sk_buff *skb) 3196a9de9248SMarcel Holtmann { 3197b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 3198b6a0dc82SMarcel Holtmann struct hci_conn *conn; 3199b6a0dc82SMarcel Holtmann 32009f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 3201b6a0dc82SMarcel Holtmann 3202b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 3203b6a0dc82SMarcel Holtmann 3204b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 32059dc0a3afSMarcel Holtmann if (!conn) { 32069dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 32079dc0a3afSMarcel Holtmann goto unlock; 32089dc0a3afSMarcel Holtmann 32099dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 3210b6a0dc82SMarcel Holtmann if (!conn) 3211b6a0dc82SMarcel Holtmann goto unlock; 3212b6a0dc82SMarcel Holtmann 32139dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 32149dc0a3afSMarcel Holtmann } 32159dc0a3afSMarcel Holtmann 3216732547f9SMarcel Holtmann switch (ev->status) { 3217732547f9SMarcel Holtmann case 0x00: 3218732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 3219732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 3220732547f9SMarcel Holtmann 32219eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 3222732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 3223732547f9SMarcel Holtmann break; 3224732547f9SMarcel Holtmann 3225705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 3226732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 32271038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 3228732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 3229732547f9SMarcel Holtmann if (conn->out && conn->attempt < 2) { 3230efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 3231efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 3232efc7688bSMarcel Holtmann hci_setup_sync(conn, conn->link->handle); 3233efc7688bSMarcel Holtmann goto unlock; 3234efc7688bSMarcel Holtmann } 3235732547f9SMarcel Holtmann /* fall through */ 3236efc7688bSMarcel Holtmann 3237732547f9SMarcel Holtmann default: 3238b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 3239732547f9SMarcel Holtmann break; 3240732547f9SMarcel Holtmann } 3241b6a0dc82SMarcel Holtmann 3242b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 3243b6a0dc82SMarcel Holtmann if (ev->status) 3244b6a0dc82SMarcel Holtmann hci_conn_del(conn); 3245b6a0dc82SMarcel Holtmann 3246b6a0dc82SMarcel Holtmann unlock: 3247b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 3248a9de9248SMarcel Holtmann } 3249a9de9248SMarcel Holtmann 32506039aa73SGustavo Padovan static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) 3251a9de9248SMarcel Holtmann { 3252a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 3253a9de9248SMarcel Holtmann } 3254a9de9248SMarcel Holtmann 32556039aa73SGustavo Padovan static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) 325604837f64SMarcel Holtmann { 3257a9de9248SMarcel Holtmann struct hci_ev_sniff_subrate *ev = (void *) skb->data; 325804837f64SMarcel Holtmann 32599f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 326004837f64SMarcel Holtmann } 326104837f64SMarcel Holtmann 32626039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, 3263807deac2SGustavo Padovan struct sk_buff *skb) 3264a9de9248SMarcel Holtmann { 3265a9de9248SMarcel Holtmann struct inquiry_data data; 3266a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 3267a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 32689d939d94SVishal Agarwal size_t eir_len; 3269a9de9248SMarcel Holtmann 3270a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 3271a9de9248SMarcel Holtmann 3272a9de9248SMarcel Holtmann if (!num_rsp) 3273a9de9248SMarcel Holtmann return; 3274a9de9248SMarcel Holtmann 32751519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 32761519cc17SAndre Guedes return; 32771519cc17SAndre Guedes 3278a9de9248SMarcel Holtmann hci_dev_lock(hdev); 3279a9de9248SMarcel Holtmann 3280e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 3281388fc8faSJohan Hedberg bool name_known, ssp; 3282561aafbcSJohan Hedberg 3283a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 3284a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 3285a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 3286a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 3287a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 3288a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 3289a9de9248SMarcel Holtmann data.rssi = info->rssi; 329041a96212SMarcel Holtmann data.ssp_mode = 0x01; 3291561aafbcSJohan Hedberg 3292a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 32934ddb1930SJohan Hedberg name_known = eir_has_data_type(info->data, 32944ddb1930SJohan Hedberg sizeof(info->data), 32954ddb1930SJohan Hedberg EIR_NAME_COMPLETE); 3296561aafbcSJohan Hedberg else 3297561aafbcSJohan Hedberg name_known = true; 3298561aafbcSJohan Hedberg 3299388fc8faSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, name_known, 3300388fc8faSJohan Hedberg &ssp); 33019d939d94SVishal Agarwal eir_len = eir_get_length(info->data, sizeof(info->data)); 330248264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 330304124681SGustavo F. Padovan info->dev_class, info->rssi, !name_known, 33049d939d94SVishal Agarwal ssp, info->data, eir_len); 3305a9de9248SMarcel Holtmann } 3306a9de9248SMarcel Holtmann 3307a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 3308a9de9248SMarcel Holtmann } 3309a9de9248SMarcel Holtmann 33101c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev, 33111c2e0041SJohan Hedberg struct sk_buff *skb) 33121c2e0041SJohan Hedberg { 33131c2e0041SJohan Hedberg struct hci_ev_key_refresh_complete *ev = (void *) skb->data; 33141c2e0041SJohan Hedberg struct hci_conn *conn; 33151c2e0041SJohan Hedberg 33169f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status, 33171c2e0041SJohan Hedberg __le16_to_cpu(ev->handle)); 33181c2e0041SJohan Hedberg 33191c2e0041SJohan Hedberg hci_dev_lock(hdev); 33201c2e0041SJohan Hedberg 33211c2e0041SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 33221c2e0041SJohan Hedberg if (!conn) 33231c2e0041SJohan Hedberg goto unlock; 33241c2e0041SJohan Hedberg 33251c2e0041SJohan Hedberg if (!ev->status) 33261c2e0041SJohan Hedberg conn->sec_level = conn->pending_sec_level; 33271c2e0041SJohan Hedberg 33281c2e0041SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 33291c2e0041SJohan Hedberg 33301c2e0041SJohan Hedberg if (ev->status && conn->state == BT_CONNECTED) { 33311c2e0041SJohan Hedberg hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE); 33321c2e0041SJohan Hedberg hci_conn_put(conn); 33331c2e0041SJohan Hedberg goto unlock; 33341c2e0041SJohan Hedberg } 33351c2e0041SJohan Hedberg 33361c2e0041SJohan Hedberg if (conn->state == BT_CONFIG) { 33371c2e0041SJohan Hedberg if (!ev->status) 33381c2e0041SJohan Hedberg conn->state = BT_CONNECTED; 33391c2e0041SJohan Hedberg 33401c2e0041SJohan Hedberg hci_proto_connect_cfm(conn, ev->status); 33411c2e0041SJohan Hedberg hci_conn_put(conn); 33421c2e0041SJohan Hedberg } else { 33431c2e0041SJohan Hedberg hci_auth_cfm(conn, ev->status); 33441c2e0041SJohan Hedberg 33451c2e0041SJohan Hedberg hci_conn_hold(conn); 33461c2e0041SJohan Hedberg conn->disc_timeout = HCI_DISCONN_TIMEOUT; 33471c2e0041SJohan Hedberg hci_conn_put(conn); 33481c2e0041SJohan Hedberg } 33491c2e0041SJohan Hedberg 33501c2e0041SJohan Hedberg unlock: 33511c2e0041SJohan Hedberg hci_dev_unlock(hdev); 33521c2e0041SJohan Hedberg } 33531c2e0041SJohan Hedberg 33546039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn) 335517fa4b9dSJohan Hedberg { 335617fa4b9dSJohan Hedberg /* If remote requests dedicated bonding follow that lead */ 335717fa4b9dSJohan Hedberg if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) { 335817fa4b9dSJohan Hedberg /* If both remote and local IO capabilities allow MITM 335917fa4b9dSJohan Hedberg * protection then require it, otherwise don't */ 336017fa4b9dSJohan Hedberg if (conn->remote_cap == 0x03 || conn->io_capability == 0x03) 336117fa4b9dSJohan Hedberg return 0x02; 336217fa4b9dSJohan Hedberg else 336317fa4b9dSJohan Hedberg return 0x03; 336417fa4b9dSJohan Hedberg } 336517fa4b9dSJohan Hedberg 336617fa4b9dSJohan Hedberg /* If remote requests no-bonding follow that lead */ 336717fa4b9dSJohan Hedberg if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01) 336858797bf7SWaldemar Rymarkiewicz return conn->remote_auth | (conn->auth_type & 0x01); 336917fa4b9dSJohan Hedberg 337017fa4b9dSJohan Hedberg return conn->auth_type; 337117fa4b9dSJohan Hedberg } 337217fa4b9dSJohan Hedberg 33736039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 33740493684eSMarcel Holtmann { 33750493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 33760493684eSMarcel Holtmann struct hci_conn *conn; 33770493684eSMarcel Holtmann 33780493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 33790493684eSMarcel Holtmann 33800493684eSMarcel Holtmann hci_dev_lock(hdev); 33810493684eSMarcel Holtmann 33820493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 338303b555e1SJohan Hedberg if (!conn) 338403b555e1SJohan Hedberg goto unlock; 338503b555e1SJohan Hedberg 33860493684eSMarcel Holtmann hci_conn_hold(conn); 33870493684eSMarcel Holtmann 3388a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 338903b555e1SJohan Hedberg goto unlock; 339003b555e1SJohan Hedberg 3391a8b2d5c2SJohan Hedberg if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) || 339203b555e1SJohan Hedberg (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 339317fa4b9dSJohan Hedberg struct hci_cp_io_capability_reply cp; 339417fa4b9dSJohan Hedberg 339517fa4b9dSJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 33967a7f1e7cSHemant Gupta /* Change the IO capability from KeyboardDisplay 33977a7f1e7cSHemant Gupta * to DisplayYesNo as it is not supported by BT spec. */ 33987a7f1e7cSHemant Gupta cp.capability = (conn->io_capability == 0x04) ? 33997a7f1e7cSHemant Gupta 0x01 : conn->io_capability; 34007cbc9bd9SJohan Hedberg conn->auth_type = hci_get_auth_req(conn); 34017cbc9bd9SJohan Hedberg cp.authentication = conn->auth_type; 340217fa4b9dSJohan Hedberg 34038fc9ced3SGustavo Padovan if (hci_find_remote_oob_data(hdev, &conn->dst) && 34048fc9ced3SGustavo Padovan (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags))) 3405ce85ee13SSzymon Janc cp.oob_data = 0x01; 3406ce85ee13SSzymon Janc else 3407ce85ee13SSzymon Janc cp.oob_data = 0x00; 3408ce85ee13SSzymon Janc 340917fa4b9dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, 341017fa4b9dSJohan Hedberg sizeof(cp), &cp); 341103b555e1SJohan Hedberg } else { 341203b555e1SJohan Hedberg struct hci_cp_io_capability_neg_reply cp; 341303b555e1SJohan Hedberg 341403b555e1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 34159f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED; 341603b555e1SJohan Hedberg 341703b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 341803b555e1SJohan Hedberg sizeof(cp), &cp); 341903b555e1SJohan Hedberg } 342003b555e1SJohan Hedberg 342103b555e1SJohan Hedberg unlock: 342203b555e1SJohan Hedberg hci_dev_unlock(hdev); 342303b555e1SJohan Hedberg } 342403b555e1SJohan Hedberg 34256039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 342603b555e1SJohan Hedberg { 342703b555e1SJohan Hedberg struct hci_ev_io_capa_reply *ev = (void *) skb->data; 342803b555e1SJohan Hedberg struct hci_conn *conn; 342903b555e1SJohan Hedberg 343003b555e1SJohan Hedberg BT_DBG("%s", hdev->name); 343103b555e1SJohan Hedberg 343203b555e1SJohan Hedberg hci_dev_lock(hdev); 343303b555e1SJohan Hedberg 343403b555e1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 343503b555e1SJohan Hedberg if (!conn) 343603b555e1SJohan Hedberg goto unlock; 343703b555e1SJohan Hedberg 343803b555e1SJohan Hedberg conn->remote_cap = ev->capability; 343903b555e1SJohan Hedberg conn->remote_auth = ev->authentication; 344058a681efSJohan Hedberg if (ev->oob_data) 344158a681efSJohan Hedberg set_bit(HCI_CONN_REMOTE_OOB, &conn->flags); 344203b555e1SJohan Hedberg 344303b555e1SJohan Hedberg unlock: 34440493684eSMarcel Holtmann hci_dev_unlock(hdev); 34450493684eSMarcel Holtmann } 34460493684eSMarcel Holtmann 34476039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev, 3448a5c29683SJohan Hedberg struct sk_buff *skb) 3449a5c29683SJohan Hedberg { 3450a5c29683SJohan Hedberg struct hci_ev_user_confirm_req *ev = (void *) skb->data; 345155bc1a37SJohan Hedberg int loc_mitm, rem_mitm, confirm_hint = 0; 34527a828908SJohan Hedberg struct hci_conn *conn; 3453a5c29683SJohan Hedberg 3454a5c29683SJohan Hedberg BT_DBG("%s", hdev->name); 3455a5c29683SJohan Hedberg 3456a5c29683SJohan Hedberg hci_dev_lock(hdev); 3457a5c29683SJohan Hedberg 3458a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 34597a828908SJohan Hedberg goto unlock; 34607a828908SJohan Hedberg 34617a828908SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 34627a828908SJohan Hedberg if (!conn) 34637a828908SJohan Hedberg goto unlock; 34647a828908SJohan Hedberg 34657a828908SJohan Hedberg loc_mitm = (conn->auth_type & 0x01); 34667a828908SJohan Hedberg rem_mitm = (conn->remote_auth & 0x01); 34677a828908SJohan Hedberg 34687a828908SJohan Hedberg /* If we require MITM but the remote device can't provide that 34697a828908SJohan Hedberg * (it has NoInputNoOutput) then reject the confirmation 34707a828908SJohan Hedberg * request. The only exception is when we're dedicated bonding 34717a828908SJohan Hedberg * initiators (connect_cfm_cb set) since then we always have the MITM 34727a828908SJohan Hedberg * bit set. */ 34737a828908SJohan Hedberg if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) { 34747a828908SJohan Hedberg BT_DBG("Rejecting request: remote device can't provide MITM"); 34757a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, 34767a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 34777a828908SJohan Hedberg goto unlock; 34787a828908SJohan Hedberg } 34797a828908SJohan Hedberg 34807a828908SJohan Hedberg /* If no side requires MITM protection; auto-accept */ 34817a828908SJohan Hedberg if ((!loc_mitm || conn->remote_cap == 0x03) && 34827a828908SJohan Hedberg (!rem_mitm || conn->io_capability == 0x03)) { 348355bc1a37SJohan Hedberg 348455bc1a37SJohan Hedberg /* If we're not the initiators request authorization to 348555bc1a37SJohan Hedberg * proceed from user space (mgmt_user_confirm with 348655bc1a37SJohan Hedberg * confirm_hint set to 1). */ 348751a8efd7SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 348855bc1a37SJohan Hedberg BT_DBG("Confirming auto-accept as acceptor"); 348955bc1a37SJohan Hedberg confirm_hint = 1; 349055bc1a37SJohan Hedberg goto confirm; 349155bc1a37SJohan Hedberg } 349255bc1a37SJohan Hedberg 34939f61656aSJohan Hedberg BT_DBG("Auto-accept of user confirmation with %ums delay", 34949f61656aSJohan Hedberg hdev->auto_accept_delay); 34959f61656aSJohan Hedberg 34969f61656aSJohan Hedberg if (hdev->auto_accept_delay > 0) { 34979f61656aSJohan Hedberg int delay = msecs_to_jiffies(hdev->auto_accept_delay); 34989f61656aSJohan Hedberg mod_timer(&conn->auto_accept_timer, jiffies + delay); 34999f61656aSJohan Hedberg goto unlock; 35009f61656aSJohan Hedberg } 35019f61656aSJohan Hedberg 35027a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, 35037a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 35047a828908SJohan Hedberg goto unlock; 35057a828908SJohan Hedberg } 35067a828908SJohan Hedberg 350755bc1a37SJohan Hedberg confirm: 3508272d90dfSJohan Hedberg mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey, 350955bc1a37SJohan Hedberg confirm_hint); 3510a5c29683SJohan Hedberg 35117a828908SJohan Hedberg unlock: 3512a5c29683SJohan Hedberg hci_dev_unlock(hdev); 3513a5c29683SJohan Hedberg } 3514a5c29683SJohan Hedberg 35156039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev, 35161143d458SBrian Gix struct sk_buff *skb) 35171143d458SBrian Gix { 35181143d458SBrian Gix struct hci_ev_user_passkey_req *ev = (void *) skb->data; 35191143d458SBrian Gix 35201143d458SBrian Gix BT_DBG("%s", hdev->name); 35211143d458SBrian Gix 3522a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 3523272d90dfSJohan Hedberg mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); 35241143d458SBrian Gix } 35251143d458SBrian Gix 352692a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev, 352792a25256SJohan Hedberg struct sk_buff *skb) 352892a25256SJohan Hedberg { 352992a25256SJohan Hedberg struct hci_ev_user_passkey_notify *ev = (void *) skb->data; 353092a25256SJohan Hedberg struct hci_conn *conn; 353192a25256SJohan Hedberg 353292a25256SJohan Hedberg BT_DBG("%s", hdev->name); 353392a25256SJohan Hedberg 353492a25256SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 353592a25256SJohan Hedberg if (!conn) 353692a25256SJohan Hedberg return; 353792a25256SJohan Hedberg 353892a25256SJohan Hedberg conn->passkey_notify = __le32_to_cpu(ev->passkey); 353992a25256SJohan Hedberg conn->passkey_entered = 0; 354092a25256SJohan Hedberg 354192a25256SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 354292a25256SJohan Hedberg mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, 354392a25256SJohan Hedberg conn->dst_type, conn->passkey_notify, 354492a25256SJohan Hedberg conn->passkey_entered); 354592a25256SJohan Hedberg } 354692a25256SJohan Hedberg 354792a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 354892a25256SJohan Hedberg { 354992a25256SJohan Hedberg struct hci_ev_keypress_notify *ev = (void *) skb->data; 355092a25256SJohan Hedberg struct hci_conn *conn; 355192a25256SJohan Hedberg 355292a25256SJohan Hedberg BT_DBG("%s", hdev->name); 355392a25256SJohan Hedberg 355492a25256SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 355592a25256SJohan Hedberg if (!conn) 355692a25256SJohan Hedberg return; 355792a25256SJohan Hedberg 355892a25256SJohan Hedberg switch (ev->type) { 355992a25256SJohan Hedberg case HCI_KEYPRESS_STARTED: 356092a25256SJohan Hedberg conn->passkey_entered = 0; 356192a25256SJohan Hedberg return; 356292a25256SJohan Hedberg 356392a25256SJohan Hedberg case HCI_KEYPRESS_ENTERED: 356492a25256SJohan Hedberg conn->passkey_entered++; 356592a25256SJohan Hedberg break; 356692a25256SJohan Hedberg 356792a25256SJohan Hedberg case HCI_KEYPRESS_ERASED: 356892a25256SJohan Hedberg conn->passkey_entered--; 356992a25256SJohan Hedberg break; 357092a25256SJohan Hedberg 357192a25256SJohan Hedberg case HCI_KEYPRESS_CLEARED: 357292a25256SJohan Hedberg conn->passkey_entered = 0; 357392a25256SJohan Hedberg break; 357492a25256SJohan Hedberg 357592a25256SJohan Hedberg case HCI_KEYPRESS_COMPLETED: 357692a25256SJohan Hedberg return; 357792a25256SJohan Hedberg } 357892a25256SJohan Hedberg 357992a25256SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 358092a25256SJohan Hedberg mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, 358192a25256SJohan Hedberg conn->dst_type, conn->passkey_notify, 358292a25256SJohan Hedberg conn->passkey_entered); 358392a25256SJohan Hedberg } 358492a25256SJohan Hedberg 35856039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev, 3586807deac2SGustavo Padovan struct sk_buff *skb) 35870493684eSMarcel Holtmann { 35880493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 35890493684eSMarcel Holtmann struct hci_conn *conn; 35900493684eSMarcel Holtmann 35910493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 35920493684eSMarcel Holtmann 35930493684eSMarcel Holtmann hci_dev_lock(hdev); 35940493684eSMarcel Holtmann 35950493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 35962a611692SJohan Hedberg if (!conn) 35972a611692SJohan Hedberg goto unlock; 35982a611692SJohan Hedberg 35992a611692SJohan Hedberg /* To avoid duplicate auth_failed events to user space we check 36002a611692SJohan Hedberg * the HCI_CONN_AUTH_PEND flag which will be set if we 36012a611692SJohan Hedberg * initiated the authentication. A traditional auth_complete 36022a611692SJohan Hedberg * event gets always produced as initiator and is also mapped to 36032a611692SJohan Hedberg * the mgmt_auth_failed event */ 3604fa1bd918SMikel Astiz if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status) 3605bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 3606bab73cb6SJohan Hedberg ev->status); 36072a611692SJohan Hedberg 36080493684eSMarcel Holtmann hci_conn_put(conn); 36090493684eSMarcel Holtmann 36102a611692SJohan Hedberg unlock: 36110493684eSMarcel Holtmann hci_dev_unlock(hdev); 36120493684eSMarcel Holtmann } 36130493684eSMarcel Holtmann 36146039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev, 3615807deac2SGustavo Padovan struct sk_buff *skb) 361641a96212SMarcel Holtmann { 361741a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 361841a96212SMarcel Holtmann struct inquiry_entry *ie; 361941a96212SMarcel Holtmann 362041a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 362141a96212SMarcel Holtmann 362241a96212SMarcel Holtmann hci_dev_lock(hdev); 362341a96212SMarcel Holtmann 3624cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 3625cc11b9c1SAndrei Emeltchenko if (ie) 362602b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 362741a96212SMarcel Holtmann 362841a96212SMarcel Holtmann hci_dev_unlock(hdev); 362941a96212SMarcel Holtmann } 363041a96212SMarcel Holtmann 36316039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev, 36322763eda6SSzymon Janc struct sk_buff *skb) 36332763eda6SSzymon Janc { 36342763eda6SSzymon Janc struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; 36352763eda6SSzymon Janc struct oob_data *data; 36362763eda6SSzymon Janc 36372763eda6SSzymon Janc BT_DBG("%s", hdev->name); 36382763eda6SSzymon Janc 36392763eda6SSzymon Janc hci_dev_lock(hdev); 36402763eda6SSzymon Janc 3641a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 3642e1ba1f15SSzymon Janc goto unlock; 3643e1ba1f15SSzymon Janc 36442763eda6SSzymon Janc data = hci_find_remote_oob_data(hdev, &ev->bdaddr); 36452763eda6SSzymon Janc if (data) { 36462763eda6SSzymon Janc struct hci_cp_remote_oob_data_reply cp; 36472763eda6SSzymon Janc 36482763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 36492763eda6SSzymon Janc memcpy(cp.hash, data->hash, sizeof(cp.hash)); 36502763eda6SSzymon Janc memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); 36512763eda6SSzymon Janc 36522763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), 36532763eda6SSzymon Janc &cp); 36542763eda6SSzymon Janc } else { 36552763eda6SSzymon Janc struct hci_cp_remote_oob_data_neg_reply cp; 36562763eda6SSzymon Janc 36572763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 36582763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), 36592763eda6SSzymon Janc &cp); 36602763eda6SSzymon Janc } 36612763eda6SSzymon Janc 3662e1ba1f15SSzymon Janc unlock: 36632763eda6SSzymon Janc hci_dev_unlock(hdev); 36642763eda6SSzymon Janc } 36652763eda6SSzymon Janc 3666d5e91192SAndrei Emeltchenko static void hci_phy_link_complete_evt(struct hci_dev *hdev, 3667d5e91192SAndrei Emeltchenko struct sk_buff *skb) 3668d5e91192SAndrei Emeltchenko { 3669d5e91192SAndrei Emeltchenko struct hci_ev_phy_link_complete *ev = (void *) skb->data; 3670d5e91192SAndrei Emeltchenko struct hci_conn *hcon, *bredr_hcon; 3671d5e91192SAndrei Emeltchenko 3672d5e91192SAndrei Emeltchenko BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle, 3673d5e91192SAndrei Emeltchenko ev->status); 3674d5e91192SAndrei Emeltchenko 3675d5e91192SAndrei Emeltchenko hci_dev_lock(hdev); 3676d5e91192SAndrei Emeltchenko 3677d5e91192SAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 3678d5e91192SAndrei Emeltchenko if (!hcon) { 3679d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 3680d5e91192SAndrei Emeltchenko return; 3681d5e91192SAndrei Emeltchenko } 3682d5e91192SAndrei Emeltchenko 3683d5e91192SAndrei Emeltchenko if (ev->status) { 3684d5e91192SAndrei Emeltchenko hci_conn_del(hcon); 3685d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 3686d5e91192SAndrei Emeltchenko return; 3687d5e91192SAndrei Emeltchenko } 3688d5e91192SAndrei Emeltchenko 3689d5e91192SAndrei Emeltchenko bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon; 3690d5e91192SAndrei Emeltchenko 3691d5e91192SAndrei Emeltchenko hcon->state = BT_CONNECTED; 3692d5e91192SAndrei Emeltchenko bacpy(&hcon->dst, &bredr_hcon->dst); 3693d5e91192SAndrei Emeltchenko 3694d5e91192SAndrei Emeltchenko hci_conn_hold(hcon); 3695d5e91192SAndrei Emeltchenko hcon->disc_timeout = HCI_DISCONN_TIMEOUT; 3696d5e91192SAndrei Emeltchenko hci_conn_put(hcon); 3697d5e91192SAndrei Emeltchenko 3698d5e91192SAndrei Emeltchenko hci_conn_hold_device(hcon); 3699d5e91192SAndrei Emeltchenko hci_conn_add_sysfs(hcon); 3700d5e91192SAndrei Emeltchenko 3701cf70ff22SAndrei Emeltchenko amp_physical_cfm(bredr_hcon, hcon); 3702cf70ff22SAndrei Emeltchenko 3703d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 3704d5e91192SAndrei Emeltchenko } 3705d5e91192SAndrei Emeltchenko 370627695fb4SAndrei Emeltchenko static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 370727695fb4SAndrei Emeltchenko { 370827695fb4SAndrei Emeltchenko struct hci_ev_logical_link_complete *ev = (void *) skb->data; 370927695fb4SAndrei Emeltchenko struct hci_conn *hcon; 371027695fb4SAndrei Emeltchenko struct hci_chan *hchan; 371127695fb4SAndrei Emeltchenko struct amp_mgr *mgr; 371227695fb4SAndrei Emeltchenko 371327695fb4SAndrei Emeltchenko BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x", 371427695fb4SAndrei Emeltchenko hdev->name, le16_to_cpu(ev->handle), ev->phy_handle, 371527695fb4SAndrei Emeltchenko ev->status); 371627695fb4SAndrei Emeltchenko 371727695fb4SAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 371827695fb4SAndrei Emeltchenko if (!hcon) 371927695fb4SAndrei Emeltchenko return; 372027695fb4SAndrei Emeltchenko 372127695fb4SAndrei Emeltchenko /* Create AMP hchan */ 372227695fb4SAndrei Emeltchenko hchan = hci_chan_create(hcon); 372327695fb4SAndrei Emeltchenko if (!hchan) 372427695fb4SAndrei Emeltchenko return; 372527695fb4SAndrei Emeltchenko 372627695fb4SAndrei Emeltchenko hchan->handle = le16_to_cpu(ev->handle); 372727695fb4SAndrei Emeltchenko 372827695fb4SAndrei Emeltchenko BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan); 372927695fb4SAndrei Emeltchenko 373027695fb4SAndrei Emeltchenko mgr = hcon->amp_mgr; 373127695fb4SAndrei Emeltchenko if (mgr && mgr->bredr_chan) { 373227695fb4SAndrei Emeltchenko struct l2cap_chan *bredr_chan = mgr->bredr_chan; 373327695fb4SAndrei Emeltchenko 373427695fb4SAndrei Emeltchenko l2cap_chan_lock(bredr_chan); 373527695fb4SAndrei Emeltchenko 373627695fb4SAndrei Emeltchenko bredr_chan->conn->mtu = hdev->block_mtu; 373727695fb4SAndrei Emeltchenko l2cap_logical_cfm(bredr_chan, hchan, 0); 373827695fb4SAndrei Emeltchenko hci_conn_hold(hcon); 373927695fb4SAndrei Emeltchenko 374027695fb4SAndrei Emeltchenko l2cap_chan_unlock(bredr_chan); 374127695fb4SAndrei Emeltchenko } 374227695fb4SAndrei Emeltchenko } 374327695fb4SAndrei Emeltchenko 3744606e2a10SAndrei Emeltchenko static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev, 3745606e2a10SAndrei Emeltchenko struct sk_buff *skb) 3746606e2a10SAndrei Emeltchenko { 3747606e2a10SAndrei Emeltchenko struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data; 3748606e2a10SAndrei Emeltchenko struct hci_chan *hchan; 3749606e2a10SAndrei Emeltchenko 3750606e2a10SAndrei Emeltchenko BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name, 3751606e2a10SAndrei Emeltchenko le16_to_cpu(ev->handle), ev->status); 3752606e2a10SAndrei Emeltchenko 3753606e2a10SAndrei Emeltchenko if (ev->status) 3754606e2a10SAndrei Emeltchenko return; 3755606e2a10SAndrei Emeltchenko 3756606e2a10SAndrei Emeltchenko hci_dev_lock(hdev); 3757606e2a10SAndrei Emeltchenko 3758606e2a10SAndrei Emeltchenko hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle)); 3759606e2a10SAndrei Emeltchenko if (!hchan) 3760606e2a10SAndrei Emeltchenko goto unlock; 3761606e2a10SAndrei Emeltchenko 3762606e2a10SAndrei Emeltchenko amp_destroy_logical_link(hchan, ev->reason); 3763606e2a10SAndrei Emeltchenko 3764606e2a10SAndrei Emeltchenko unlock: 3765606e2a10SAndrei Emeltchenko hci_dev_unlock(hdev); 3766606e2a10SAndrei Emeltchenko } 3767606e2a10SAndrei Emeltchenko 37689eef6b3aSAndrei Emeltchenko static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev, 37699eef6b3aSAndrei Emeltchenko struct sk_buff *skb) 37709eef6b3aSAndrei Emeltchenko { 37719eef6b3aSAndrei Emeltchenko struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data; 37729eef6b3aSAndrei Emeltchenko struct hci_conn *hcon; 37739eef6b3aSAndrei Emeltchenko 37749eef6b3aSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 37759eef6b3aSAndrei Emeltchenko 37769eef6b3aSAndrei Emeltchenko if (ev->status) 37779eef6b3aSAndrei Emeltchenko return; 37789eef6b3aSAndrei Emeltchenko 37799eef6b3aSAndrei Emeltchenko hci_dev_lock(hdev); 37809eef6b3aSAndrei Emeltchenko 37819eef6b3aSAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 37829eef6b3aSAndrei Emeltchenko if (hcon) { 37839eef6b3aSAndrei Emeltchenko hcon->state = BT_CLOSED; 37849eef6b3aSAndrei Emeltchenko hci_conn_del(hcon); 37859eef6b3aSAndrei Emeltchenko } 37869eef6b3aSAndrei Emeltchenko 37879eef6b3aSAndrei Emeltchenko hci_dev_unlock(hdev); 37889eef6b3aSAndrei Emeltchenko } 37899eef6b3aSAndrei Emeltchenko 37906039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 3791fcd89c09SVille Tervo { 3792fcd89c09SVille Tervo struct hci_ev_le_conn_complete *ev = (void *) skb->data; 3793fcd89c09SVille Tervo struct hci_conn *conn; 3794fcd89c09SVille Tervo 37959f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 3796fcd89c09SVille Tervo 3797fcd89c09SVille Tervo hci_dev_lock(hdev); 3798fcd89c09SVille Tervo 37994f72b329SAndrzej Kaczmarek conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); 3800b62f328bSVille Tervo if (!conn) { 3801b62f328bSVille Tervo conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); 3802b62f328bSVille Tervo if (!conn) { 3803b62f328bSVille Tervo BT_ERR("No memory for new connection"); 3804230fd16aSAndre Guedes goto unlock; 3805b62f328bSVille Tervo } 380629b7988aSAndre Guedes 380729b7988aSAndre Guedes conn->dst_type = ev->bdaddr_type; 3808b9b343d2SAndre Guedes 3809b9b343d2SAndre Guedes if (ev->role == LE_CONN_ROLE_MASTER) { 3810b9b343d2SAndre Guedes conn->out = true; 3811b9b343d2SAndre Guedes conn->link_mode |= HCI_LM_MASTER; 3812b9b343d2SAndre Guedes } 3813b62f328bSVille Tervo } 3814fcd89c09SVille Tervo 3815cd17decbSAndre Guedes if (ev->status) { 3816cd17decbSAndre Guedes mgmt_connect_failed(hdev, &conn->dst, conn->type, 3817cd17decbSAndre Guedes conn->dst_type, ev->status); 3818cd17decbSAndre Guedes hci_proto_connect_cfm(conn, ev->status); 3819cd17decbSAndre Guedes conn->state = BT_CLOSED; 3820cd17decbSAndre Guedes hci_conn_del(conn); 3821cd17decbSAndre Guedes goto unlock; 3822cd17decbSAndre Guedes } 3823cd17decbSAndre Guedes 3824b644ba33SJohan Hedberg if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 3825b644ba33SJohan Hedberg mgmt_device_connected(hdev, &ev->bdaddr, conn->type, 382695b23582SSzymon Janc conn->dst_type, 0, NULL, 0, NULL); 382783bc71b4SVinicius Costa Gomes 38287b5c0d52SVinicius Costa Gomes conn->sec_level = BT_SECURITY_LOW; 3829fcd89c09SVille Tervo conn->handle = __le16_to_cpu(ev->handle); 3830fcd89c09SVille Tervo conn->state = BT_CONNECTED; 3831fcd89c09SVille Tervo 3832fcd89c09SVille Tervo hci_conn_hold_device(conn); 3833fcd89c09SVille Tervo hci_conn_add_sysfs(conn); 3834fcd89c09SVille Tervo 3835fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 3836fcd89c09SVille Tervo 3837fcd89c09SVille Tervo unlock: 3838fcd89c09SVille Tervo hci_dev_unlock(hdev); 3839fcd89c09SVille Tervo } 3840fcd89c09SVille Tervo 38416039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) 38429aa04c91SAndre Guedes { 3843e95beb41SAndre Guedes u8 num_reports = skb->data[0]; 3844e95beb41SAndre Guedes void *ptr = &skb->data[1]; 38453c9e9195SAndre Guedes s8 rssi; 38469aa04c91SAndre Guedes 38479aa04c91SAndre Guedes hci_dev_lock(hdev); 38489aa04c91SAndre Guedes 3849e95beb41SAndre Guedes while (num_reports--) { 3850e95beb41SAndre Guedes struct hci_ev_le_advertising_info *ev = ptr; 3851e95beb41SAndre Guedes 38523c9e9195SAndre Guedes rssi = ev->data[ev->length]; 38533c9e9195SAndre Guedes mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type, 385404124681SGustavo F. Padovan NULL, rssi, 0, 1, ev->data, ev->length); 38553c9e9195SAndre Guedes 3856e95beb41SAndre Guedes ptr += sizeof(*ev) + ev->length + 1; 38579aa04c91SAndre Guedes } 38589aa04c91SAndre Guedes 38599aa04c91SAndre Guedes hci_dev_unlock(hdev); 38609aa04c91SAndre Guedes } 38619aa04c91SAndre Guedes 38626039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 3863a7a595f6SVinicius Costa Gomes { 3864a7a595f6SVinicius Costa Gomes struct hci_ev_le_ltk_req *ev = (void *) skb->data; 3865a7a595f6SVinicius Costa Gomes struct hci_cp_le_ltk_reply cp; 3866bea710feSVinicius Costa Gomes struct hci_cp_le_ltk_neg_reply neg; 3867a7a595f6SVinicius Costa Gomes struct hci_conn *conn; 3868c9839a11SVinicius Costa Gomes struct smp_ltk *ltk; 3869a7a595f6SVinicius Costa Gomes 38709f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle)); 3871a7a595f6SVinicius Costa Gomes 3872a7a595f6SVinicius Costa Gomes hci_dev_lock(hdev); 3873a7a595f6SVinicius Costa Gomes 3874a7a595f6SVinicius Costa Gomes conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3875bea710feSVinicius Costa Gomes if (conn == NULL) 3876bea710feSVinicius Costa Gomes goto not_found; 3877a7a595f6SVinicius Costa Gomes 3878bea710feSVinicius Costa Gomes ltk = hci_find_ltk(hdev, ev->ediv, ev->random); 3879bea710feSVinicius Costa Gomes if (ltk == NULL) 3880bea710feSVinicius Costa Gomes goto not_found; 3881bea710feSVinicius Costa Gomes 3882bea710feSVinicius Costa Gomes memcpy(cp.ltk, ltk->val, sizeof(ltk->val)); 3883a7a595f6SVinicius Costa Gomes cp.handle = cpu_to_le16(conn->handle); 3884c9839a11SVinicius Costa Gomes 3885c9839a11SVinicius Costa Gomes if (ltk->authenticated) 3886c9839a11SVinicius Costa Gomes conn->sec_level = BT_SECURITY_HIGH; 3887a7a595f6SVinicius Costa Gomes 3888a7a595f6SVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); 3889a7a595f6SVinicius Costa Gomes 3890c9839a11SVinicius Costa Gomes if (ltk->type & HCI_SMP_STK) { 3891c9839a11SVinicius Costa Gomes list_del(<k->list); 3892c9839a11SVinicius Costa Gomes kfree(ltk); 3893c9839a11SVinicius Costa Gomes } 3894c9839a11SVinicius Costa Gomes 3895a7a595f6SVinicius Costa Gomes hci_dev_unlock(hdev); 3896bea710feSVinicius Costa Gomes 3897bea710feSVinicius Costa Gomes return; 3898bea710feSVinicius Costa Gomes 3899bea710feSVinicius Costa Gomes not_found: 3900bea710feSVinicius Costa Gomes neg.handle = ev->handle; 3901bea710feSVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg); 3902bea710feSVinicius Costa Gomes hci_dev_unlock(hdev); 3903a7a595f6SVinicius Costa Gomes } 3904a7a595f6SVinicius Costa Gomes 39056039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 3906fcd89c09SVille Tervo { 3907fcd89c09SVille Tervo struct hci_ev_le_meta *le_ev = (void *) skb->data; 3908fcd89c09SVille Tervo 3909fcd89c09SVille Tervo skb_pull(skb, sizeof(*le_ev)); 3910fcd89c09SVille Tervo 3911fcd89c09SVille Tervo switch (le_ev->subevent) { 3912fcd89c09SVille Tervo case HCI_EV_LE_CONN_COMPLETE: 3913fcd89c09SVille Tervo hci_le_conn_complete_evt(hdev, skb); 3914fcd89c09SVille Tervo break; 3915fcd89c09SVille Tervo 39169aa04c91SAndre Guedes case HCI_EV_LE_ADVERTISING_REPORT: 39179aa04c91SAndre Guedes hci_le_adv_report_evt(hdev, skb); 39189aa04c91SAndre Guedes break; 39199aa04c91SAndre Guedes 3920a7a595f6SVinicius Costa Gomes case HCI_EV_LE_LTK_REQ: 3921a7a595f6SVinicius Costa Gomes hci_le_ltk_request_evt(hdev, skb); 3922a7a595f6SVinicius Costa Gomes break; 3923a7a595f6SVinicius Costa Gomes 3924fcd89c09SVille Tervo default: 3925fcd89c09SVille Tervo break; 3926fcd89c09SVille Tervo } 3927fcd89c09SVille Tervo } 3928fcd89c09SVille Tervo 39299495b2eeSAndrei Emeltchenko static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb) 39309495b2eeSAndrei Emeltchenko { 39319495b2eeSAndrei Emeltchenko struct hci_ev_channel_selected *ev = (void *) skb->data; 39329495b2eeSAndrei Emeltchenko struct hci_conn *hcon; 39339495b2eeSAndrei Emeltchenko 39349495b2eeSAndrei Emeltchenko BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle); 39359495b2eeSAndrei Emeltchenko 39369495b2eeSAndrei Emeltchenko skb_pull(skb, sizeof(*ev)); 39379495b2eeSAndrei Emeltchenko 39389495b2eeSAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 39399495b2eeSAndrei Emeltchenko if (!hcon) 39409495b2eeSAndrei Emeltchenko return; 39419495b2eeSAndrei Emeltchenko 39429495b2eeSAndrei Emeltchenko amp_read_loc_assoc_final_data(hdev, hcon); 39439495b2eeSAndrei Emeltchenko } 39449495b2eeSAndrei Emeltchenko 39451da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 39461da177e4SLinus Torvalds { 3947a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 3948a9de9248SMarcel Holtmann __u8 event = hdr->evt; 39491da177e4SLinus Torvalds 39501da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 39511da177e4SLinus Torvalds 3952a9de9248SMarcel Holtmann switch (event) { 39531da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 39541da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 39551da177e4SLinus Torvalds break; 39561da177e4SLinus Torvalds 39571da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 39581da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 39591da177e4SLinus Torvalds break; 39601da177e4SLinus Torvalds 3961a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 3962a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 396321d9e30eSMarcel Holtmann break; 396421d9e30eSMarcel Holtmann 39651da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 39661da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 39671da177e4SLinus Torvalds break; 39681da177e4SLinus Torvalds 39691da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 39701da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 39711da177e4SLinus Torvalds break; 39721da177e4SLinus Torvalds 39731da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 39741da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 39751da177e4SLinus Torvalds break; 39761da177e4SLinus Torvalds 3977a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 3978a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 3979a9de9248SMarcel Holtmann break; 3980a9de9248SMarcel Holtmann 39811da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 39821da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 39831da177e4SLinus Torvalds break; 39841da177e4SLinus Torvalds 3985a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 3986a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 3987a9de9248SMarcel Holtmann break; 3988a9de9248SMarcel Holtmann 3989a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 3990a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 3991a9de9248SMarcel Holtmann break; 3992a9de9248SMarcel Holtmann 3993a9de9248SMarcel Holtmann case HCI_EV_REMOTE_VERSION: 3994a9de9248SMarcel Holtmann hci_remote_version_evt(hdev, skb); 3995a9de9248SMarcel Holtmann break; 3996a9de9248SMarcel Holtmann 3997a9de9248SMarcel Holtmann case HCI_EV_QOS_SETUP_COMPLETE: 3998a9de9248SMarcel Holtmann hci_qos_setup_complete_evt(hdev, skb); 3999a9de9248SMarcel Holtmann break; 4000a9de9248SMarcel Holtmann 4001a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 4002a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 4003a9de9248SMarcel Holtmann break; 4004a9de9248SMarcel Holtmann 4005a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 4006a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 4007a9de9248SMarcel Holtmann break; 4008a9de9248SMarcel Holtmann 4009a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 4010a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 4011a9de9248SMarcel Holtmann break; 4012a9de9248SMarcel Holtmann 4013a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 4014a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 4015a9de9248SMarcel Holtmann break; 4016a9de9248SMarcel Holtmann 4017a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 4018a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 40191da177e4SLinus Torvalds break; 40201da177e4SLinus Torvalds 40211da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 40221da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 40231da177e4SLinus Torvalds break; 40241da177e4SLinus Torvalds 40251da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 40261da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 40271da177e4SLinus Torvalds break; 40281da177e4SLinus Torvalds 40291da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 40301da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 40311da177e4SLinus Torvalds break; 40321da177e4SLinus Torvalds 40331da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 40341da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 40351da177e4SLinus Torvalds break; 40361da177e4SLinus Torvalds 4037a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 4038a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 4039a8746417SMarcel Holtmann break; 4040a8746417SMarcel Holtmann 404185a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 404285a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 404385a1e930SMarcel Holtmann break; 404485a1e930SMarcel Holtmann 4045a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 4046a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 4047a9de9248SMarcel Holtmann break; 4048a9de9248SMarcel Holtmann 4049a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 4050a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 4051a9de9248SMarcel Holtmann break; 4052a9de9248SMarcel Holtmann 4053a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 4054a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 4055a9de9248SMarcel Holtmann break; 4056a9de9248SMarcel Holtmann 4057a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_CHANGED: 4058a9de9248SMarcel Holtmann hci_sync_conn_changed_evt(hdev, skb); 4059a9de9248SMarcel Holtmann break; 4060a9de9248SMarcel Holtmann 406104837f64SMarcel Holtmann case HCI_EV_SNIFF_SUBRATE: 406204837f64SMarcel Holtmann hci_sniff_subrate_evt(hdev, skb); 406304837f64SMarcel Holtmann break; 406404837f64SMarcel Holtmann 4065a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 4066a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 40671da177e4SLinus Torvalds break; 40681da177e4SLinus Torvalds 40691c2e0041SJohan Hedberg case HCI_EV_KEY_REFRESH_COMPLETE: 40701c2e0041SJohan Hedberg hci_key_refresh_complete_evt(hdev, skb); 40711c2e0041SJohan Hedberg break; 40721c2e0041SJohan Hedberg 40730493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 40740493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 40750493684eSMarcel Holtmann break; 40760493684eSMarcel Holtmann 407703b555e1SJohan Hedberg case HCI_EV_IO_CAPA_REPLY: 407803b555e1SJohan Hedberg hci_io_capa_reply_evt(hdev, skb); 407903b555e1SJohan Hedberg break; 408003b555e1SJohan Hedberg 4081a5c29683SJohan Hedberg case HCI_EV_USER_CONFIRM_REQUEST: 4082a5c29683SJohan Hedberg hci_user_confirm_request_evt(hdev, skb); 4083a5c29683SJohan Hedberg break; 4084a5c29683SJohan Hedberg 40851143d458SBrian Gix case HCI_EV_USER_PASSKEY_REQUEST: 40861143d458SBrian Gix hci_user_passkey_request_evt(hdev, skb); 40871143d458SBrian Gix break; 40881143d458SBrian Gix 408992a25256SJohan Hedberg case HCI_EV_USER_PASSKEY_NOTIFY: 409092a25256SJohan Hedberg hci_user_passkey_notify_evt(hdev, skb); 409192a25256SJohan Hedberg break; 409292a25256SJohan Hedberg 409392a25256SJohan Hedberg case HCI_EV_KEYPRESS_NOTIFY: 409492a25256SJohan Hedberg hci_keypress_notify_evt(hdev, skb); 409592a25256SJohan Hedberg break; 409692a25256SJohan Hedberg 40970493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 40980493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 40990493684eSMarcel Holtmann break; 41000493684eSMarcel Holtmann 410141a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 410241a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 410341a96212SMarcel Holtmann break; 410441a96212SMarcel Holtmann 4105fcd89c09SVille Tervo case HCI_EV_LE_META: 4106fcd89c09SVille Tervo hci_le_meta_evt(hdev, skb); 4107fcd89c09SVille Tervo break; 4108fcd89c09SVille Tervo 41099495b2eeSAndrei Emeltchenko case HCI_EV_CHANNEL_SELECTED: 41109495b2eeSAndrei Emeltchenko hci_chan_selected_evt(hdev, skb); 41119495b2eeSAndrei Emeltchenko break; 41129495b2eeSAndrei Emeltchenko 41132763eda6SSzymon Janc case HCI_EV_REMOTE_OOB_DATA_REQUEST: 41142763eda6SSzymon Janc hci_remote_oob_data_request_evt(hdev, skb); 41152763eda6SSzymon Janc break; 41162763eda6SSzymon Janc 4117d5e91192SAndrei Emeltchenko case HCI_EV_PHY_LINK_COMPLETE: 4118d5e91192SAndrei Emeltchenko hci_phy_link_complete_evt(hdev, skb); 4119d5e91192SAndrei Emeltchenko break; 4120d5e91192SAndrei Emeltchenko 412127695fb4SAndrei Emeltchenko case HCI_EV_LOGICAL_LINK_COMPLETE: 412227695fb4SAndrei Emeltchenko hci_loglink_complete_evt(hdev, skb); 412327695fb4SAndrei Emeltchenko break; 412427695fb4SAndrei Emeltchenko 4125606e2a10SAndrei Emeltchenko case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE: 4126606e2a10SAndrei Emeltchenko hci_disconn_loglink_complete_evt(hdev, skb); 4127606e2a10SAndrei Emeltchenko break; 4128606e2a10SAndrei Emeltchenko 41299eef6b3aSAndrei Emeltchenko case HCI_EV_DISCONN_PHY_LINK_COMPLETE: 41309eef6b3aSAndrei Emeltchenko hci_disconn_phylink_complete_evt(hdev, skb); 41319eef6b3aSAndrei Emeltchenko break; 41329eef6b3aSAndrei Emeltchenko 413325e89e99SAndrei Emeltchenko case HCI_EV_NUM_COMP_BLOCKS: 413425e89e99SAndrei Emeltchenko hci_num_comp_blocks_evt(hdev, skb); 413525e89e99SAndrei Emeltchenko break; 413625e89e99SAndrei Emeltchenko 41371da177e4SLinus Torvalds default: 41389f1db00cSAndrei Emeltchenko BT_DBG("%s event 0x%2.2x", hdev->name, event); 41391da177e4SLinus Torvalds break; 41401da177e4SLinus Torvalds } 41411da177e4SLinus Torvalds 41421da177e4SLinus Torvalds kfree_skb(skb); 41431da177e4SLinus Torvalds hdev->stat.evt_rx++; 41441da177e4SLinus Torvalds } 4145