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; 205bbaf444aSJohan Hedberg hdev->inq_tx_power = HCI_TX_POWER_INVALID; 206bbaf444aSJohan Hedberg hdev->adv_tx_power = HCI_TX_POWER_INVALID; 2073f0f524bSJohan Hedberg 2083f0f524bSJohan Hedberg memset(hdev->adv_data, 0, sizeof(hdev->adv_data)); 2093f0f524bSJohan Hedberg hdev->adv_data_len = 0; 210a9de9248SMarcel Holtmann } 211a9de9248SMarcel Holtmann 212a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) 213a9de9248SMarcel Holtmann { 214a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 2151da177e4SLinus Torvalds void *sent; 2161da177e4SLinus Torvalds 2179f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 2181da177e4SLinus Torvalds 219a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); 2201da177e4SLinus Torvalds if (!sent) 221a9de9248SMarcel Holtmann return; 2221da177e4SLinus Torvalds 22356e5cb86SJohan Hedberg hci_dev_lock(hdev); 22456e5cb86SJohan Hedberg 225f51d5b24SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 226f51d5b24SJohan Hedberg mgmt_set_local_name_complete(hdev, sent, status); 22728cc7bdeSJohan Hedberg else if (!status) 22828cc7bdeSJohan Hedberg memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); 229f51d5b24SJohan Hedberg 23056e5cb86SJohan Hedberg hci_dev_unlock(hdev); 2313159d384SJohan Hedberg 2323f0f524bSJohan Hedberg if (!status && !test_bit(HCI_INIT, &hdev->flags)) 2333f0f524bSJohan Hedberg hci_update_ad(hdev); 2343f0f524bSJohan Hedberg 2353159d384SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_LOCAL_NAME, status); 236a9de9248SMarcel Holtmann } 237a9de9248SMarcel Holtmann 238a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) 239a9de9248SMarcel Holtmann { 240a9de9248SMarcel Holtmann struct hci_rp_read_local_name *rp = (void *) skb->data; 241a9de9248SMarcel Holtmann 2429f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 243a9de9248SMarcel Holtmann 244a9de9248SMarcel Holtmann if (rp->status) 245a9de9248SMarcel Holtmann return; 246a9de9248SMarcel Holtmann 247db99b5fcSJohan Hedberg if (test_bit(HCI_SETUP, &hdev->dev_flags)) 2481f6c6378SJohan Hedberg memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); 249a9de9248SMarcel Holtmann } 250a9de9248SMarcel Holtmann 251a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) 252a9de9248SMarcel Holtmann { 253a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 254a9de9248SMarcel Holtmann void *sent; 255a9de9248SMarcel Holtmann 2569f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 257a9de9248SMarcel Holtmann 258a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); 259a9de9248SMarcel Holtmann if (!sent) 260a9de9248SMarcel Holtmann return; 2611da177e4SLinus Torvalds 2621da177e4SLinus Torvalds if (!status) { 263a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 264a9de9248SMarcel Holtmann 2651da177e4SLinus Torvalds if (param == AUTH_ENABLED) 2661da177e4SLinus Torvalds set_bit(HCI_AUTH, &hdev->flags); 2671da177e4SLinus Torvalds else 2681da177e4SLinus Torvalds clear_bit(HCI_AUTH, &hdev->flags); 2691da177e4SLinus Torvalds } 270a9de9248SMarcel Holtmann 27133ef95edSJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 27233ef95edSJohan Hedberg mgmt_auth_enable_complete(hdev, status); 27333ef95edSJohan Hedberg 27423bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status); 275a9de9248SMarcel Holtmann } 2761da177e4SLinus Torvalds 277a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) 278a9de9248SMarcel Holtmann { 279a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 280a9de9248SMarcel Holtmann void *sent; 281a9de9248SMarcel Holtmann 2829f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 283a9de9248SMarcel Holtmann 284a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); 2851da177e4SLinus Torvalds if (!sent) 286a9de9248SMarcel Holtmann return; 2871da177e4SLinus Torvalds 2881da177e4SLinus Torvalds if (!status) { 289a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 290a9de9248SMarcel Holtmann 2911da177e4SLinus Torvalds if (param) 2921da177e4SLinus Torvalds set_bit(HCI_ENCRYPT, &hdev->flags); 2931da177e4SLinus Torvalds else 2941da177e4SLinus Torvalds clear_bit(HCI_ENCRYPT, &hdev->flags); 2951da177e4SLinus Torvalds } 296a9de9248SMarcel Holtmann 29723bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_ENCRYPT_MODE, status); 2981da177e4SLinus Torvalds } 2991da177e4SLinus Torvalds 300a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) 301a9de9248SMarcel Holtmann { 30236f7fc7eSJohan Hedberg __u8 param, status = *((__u8 *) skb->data); 30336f7fc7eSJohan Hedberg int old_pscan, old_iscan; 304a9de9248SMarcel Holtmann void *sent; 3051da177e4SLinus Torvalds 3069f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 307a9de9248SMarcel Holtmann 308a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); 3091da177e4SLinus Torvalds if (!sent) 310a9de9248SMarcel Holtmann return; 3111da177e4SLinus Torvalds 31236f7fc7eSJohan Hedberg param = *((__u8 *) sent); 313a9de9248SMarcel Holtmann 31456e5cb86SJohan Hedberg hci_dev_lock(hdev); 31556e5cb86SJohan Hedberg 316fa1bd918SMikel Astiz if (status) { 317744cf19eSJohan Hedberg mgmt_write_scan_failed(hdev, param, status); 3182d7cee58SJohan Hedberg hdev->discov_timeout = 0; 3192d7cee58SJohan Hedberg goto done; 3202d7cee58SJohan Hedberg } 3212d7cee58SJohan Hedberg 3229fbcbb45SJohan Hedberg old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags); 3239fbcbb45SJohan Hedberg old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags); 324a9de9248SMarcel Holtmann 32573f22f62SJohan Hedberg if (param & SCAN_INQUIRY) { 3261da177e4SLinus Torvalds set_bit(HCI_ISCAN, &hdev->flags); 3279fbcbb45SJohan Hedberg if (!old_iscan) 328744cf19eSJohan Hedberg mgmt_discoverable(hdev, 1); 32916ab91abSJohan Hedberg if (hdev->discov_timeout > 0) { 33016ab91abSJohan Hedberg int to = msecs_to_jiffies(hdev->discov_timeout * 1000); 33116ab91abSJohan Hedberg queue_delayed_work(hdev->workqueue, &hdev->discov_off, 33216ab91abSJohan Hedberg to); 33316ab91abSJohan Hedberg } 3349fbcbb45SJohan Hedberg } else if (old_iscan) 335744cf19eSJohan Hedberg mgmt_discoverable(hdev, 0); 3361da177e4SLinus Torvalds 3379fbcbb45SJohan Hedberg if (param & SCAN_PAGE) { 3381da177e4SLinus Torvalds set_bit(HCI_PSCAN, &hdev->flags); 3399fbcbb45SJohan Hedberg if (!old_pscan) 340744cf19eSJohan Hedberg mgmt_connectable(hdev, 1); 3419fbcbb45SJohan Hedberg } else if (old_pscan) 342744cf19eSJohan Hedberg mgmt_connectable(hdev, 0); 343a9de9248SMarcel Holtmann 34436f7fc7eSJohan Hedberg done: 34556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 34623bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status); 3471da177e4SLinus Torvalds } 3481da177e4SLinus Torvalds 349a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 350a9de9248SMarcel Holtmann { 351a9de9248SMarcel Holtmann struct hci_rp_read_class_of_dev *rp = (void *) skb->data; 352a9de9248SMarcel Holtmann 3539f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 354a9de9248SMarcel Holtmann 355a9de9248SMarcel Holtmann if (rp->status) 356a9de9248SMarcel Holtmann return; 357a9de9248SMarcel Holtmann 358a9de9248SMarcel Holtmann memcpy(hdev->dev_class, rp->dev_class, 3); 359a9de9248SMarcel Holtmann 360a9de9248SMarcel Holtmann BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, 361a9de9248SMarcel Holtmann hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); 362a9de9248SMarcel Holtmann } 363a9de9248SMarcel Holtmann 364a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 365a9de9248SMarcel Holtmann { 366a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 367a9de9248SMarcel Holtmann void *sent; 368a9de9248SMarcel Holtmann 3699f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 370a9de9248SMarcel Holtmann 371a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); 372a9de9248SMarcel Holtmann if (!sent) 373a9de9248SMarcel Holtmann return; 374a9de9248SMarcel Holtmann 3757f9a903cSMarcel Holtmann hci_dev_lock(hdev); 3767f9a903cSMarcel Holtmann 3777f9a903cSMarcel Holtmann if (status == 0) 378a9de9248SMarcel Holtmann memcpy(hdev->dev_class, sent, 3); 3797f9a903cSMarcel Holtmann 3807f9a903cSMarcel Holtmann if (test_bit(HCI_MGMT, &hdev->dev_flags)) 3817f9a903cSMarcel Holtmann mgmt_set_class_of_dev_complete(hdev, sent, status); 3827f9a903cSMarcel Holtmann 3837f9a903cSMarcel Holtmann hci_dev_unlock(hdev); 384a9de9248SMarcel Holtmann } 385a9de9248SMarcel Holtmann 386a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 387a9de9248SMarcel Holtmann { 388a9de9248SMarcel Holtmann struct hci_rp_read_voice_setting *rp = (void *) skb->data; 389a9de9248SMarcel Holtmann __u16 setting; 390a9de9248SMarcel Holtmann 3919f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 392a9de9248SMarcel Holtmann 393a9de9248SMarcel Holtmann if (rp->status) 394a9de9248SMarcel Holtmann return; 395a9de9248SMarcel Holtmann 396a9de9248SMarcel Holtmann setting = __le16_to_cpu(rp->voice_setting); 397a9de9248SMarcel Holtmann 398a9de9248SMarcel Holtmann if (hdev->voice_setting == setting) 399a9de9248SMarcel Holtmann return; 400a9de9248SMarcel Holtmann 401a9de9248SMarcel Holtmann hdev->voice_setting = setting; 402a9de9248SMarcel Holtmann 4039f1db00cSAndrei Emeltchenko BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting); 404a9de9248SMarcel Holtmann 4053c54711cSGustavo F. Padovan if (hdev->notify) 406a9de9248SMarcel Holtmann hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 407a9de9248SMarcel Holtmann } 408a9de9248SMarcel Holtmann 4098fc9ced3SGustavo Padovan static void hci_cc_write_voice_setting(struct hci_dev *hdev, 4108fc9ced3SGustavo Padovan struct sk_buff *skb) 411a9de9248SMarcel Holtmann { 412a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 413f383f275SMarcel Holtmann __u16 setting; 414a9de9248SMarcel Holtmann void *sent; 415a9de9248SMarcel Holtmann 4169f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 417a9de9248SMarcel Holtmann 418f383f275SMarcel Holtmann if (status) 419f383f275SMarcel Holtmann return; 420f383f275SMarcel Holtmann 421a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); 422a9de9248SMarcel Holtmann if (!sent) 423a9de9248SMarcel Holtmann return; 424a9de9248SMarcel Holtmann 425f383f275SMarcel Holtmann setting = get_unaligned_le16(sent); 4261da177e4SLinus Torvalds 427f383f275SMarcel Holtmann if (hdev->voice_setting == setting) 428f383f275SMarcel Holtmann return; 429f383f275SMarcel Holtmann 4301da177e4SLinus Torvalds hdev->voice_setting = setting; 4311da177e4SLinus Torvalds 4329f1db00cSAndrei Emeltchenko BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting); 4331da177e4SLinus Torvalds 4343c54711cSGustavo F. Padovan if (hdev->notify) 4351da177e4SLinus Torvalds hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 4361da177e4SLinus Torvalds } 4371da177e4SLinus Torvalds 438a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 4391da177e4SLinus Torvalds { 440a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 4411da177e4SLinus Torvalds 4429f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 4431da177e4SLinus Torvalds 44423bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status); 4451143e5a6SMarcel Holtmann } 4461143e5a6SMarcel Holtmann 447333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 448333140b5SMarcel Holtmann { 449333140b5SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 4505ed8eb2fSJohan Hedberg struct hci_cp_write_ssp_mode *sent; 451333140b5SMarcel Holtmann 4529f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 453333140b5SMarcel Holtmann 454333140b5SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); 455333140b5SMarcel Holtmann if (!sent) 456333140b5SMarcel Holtmann return; 457333140b5SMarcel Holtmann 4585ed8eb2fSJohan Hedberg if (!status) { 4595ed8eb2fSJohan Hedberg if (sent->mode) 4605ed8eb2fSJohan Hedberg hdev->host_features[0] |= LMP_HOST_SSP; 4615ed8eb2fSJohan Hedberg else 4625ed8eb2fSJohan Hedberg hdev->host_features[0] &= ~LMP_HOST_SSP; 4635ed8eb2fSJohan Hedberg } 4645ed8eb2fSJohan Hedberg 465c0ecddc2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 4665ed8eb2fSJohan Hedberg mgmt_ssp_enable_complete(hdev, sent->mode, status); 467c0ecddc2SJohan Hedberg else if (!status) { 4685ed8eb2fSJohan Hedberg if (sent->mode) 46984bde9d6SJohan Hedberg set_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 47084bde9d6SJohan Hedberg else 47184bde9d6SJohan Hedberg clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 472c0ecddc2SJohan Hedberg } 473333140b5SMarcel Holtmann } 474333140b5SMarcel Holtmann 475a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) 476a9de9248SMarcel Holtmann { 477a9de9248SMarcel Holtmann struct hci_rp_read_local_version *rp = (void *) skb->data; 4781143e5a6SMarcel Holtmann 4799f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 4801143e5a6SMarcel Holtmann 481a9de9248SMarcel Holtmann if (rp->status) 48228b8df77SAndrei Emeltchenko goto done; 4831143e5a6SMarcel Holtmann 484a9de9248SMarcel Holtmann hdev->hci_ver = rp->hci_ver; 485e4e8e37cSMarcel Holtmann hdev->hci_rev = __le16_to_cpu(rp->hci_rev); 486d5859e22SJohan Hedberg hdev->lmp_ver = rp->lmp_ver; 487e4e8e37cSMarcel Holtmann hdev->manufacturer = __le16_to_cpu(rp->manufacturer); 488d5859e22SJohan Hedberg hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); 4891da177e4SLinus Torvalds 4909f1db00cSAndrei Emeltchenko BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name, 491807deac2SGustavo Padovan hdev->manufacturer, hdev->hci_ver, hdev->hci_rev); 492d5859e22SJohan Hedberg 49328b8df77SAndrei Emeltchenko done: 49428b8df77SAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_LOCAL_VERSION, rp->status); 495d5859e22SJohan Hedberg } 496d5859e22SJohan Hedberg 4978fc9ced3SGustavo Padovan static void hci_cc_read_local_commands(struct hci_dev *hdev, 4988fc9ced3SGustavo Padovan struct sk_buff *skb) 499a9de9248SMarcel Holtmann { 500a9de9248SMarcel Holtmann struct hci_rp_read_local_commands *rp = (void *) skb->data; 501a9de9248SMarcel Holtmann 5029f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 503a9de9248SMarcel Holtmann 5042177bab5SJohan Hedberg if (!rp->status) 505a9de9248SMarcel Holtmann memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); 506d5859e22SJohan Hedberg 507d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_LOCAL_COMMANDS, rp->status); 508a9de9248SMarcel Holtmann } 509a9de9248SMarcel Holtmann 5108fc9ced3SGustavo Padovan static void hci_cc_read_local_features(struct hci_dev *hdev, 5118fc9ced3SGustavo Padovan struct sk_buff *skb) 512a9de9248SMarcel Holtmann { 513a9de9248SMarcel Holtmann struct hci_rp_read_local_features *rp = (void *) skb->data; 514a9de9248SMarcel Holtmann 5159f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 516a9de9248SMarcel Holtmann 517a9de9248SMarcel Holtmann if (rp->status) 518a9de9248SMarcel Holtmann return; 519a9de9248SMarcel Holtmann 520a9de9248SMarcel Holtmann memcpy(hdev->features, rp->features, 8); 5211da177e4SLinus Torvalds 5221da177e4SLinus Torvalds /* Adjust default settings according to features 5231da177e4SLinus Torvalds * supported by device. */ 524a9de9248SMarcel Holtmann 5251da177e4SLinus Torvalds if (hdev->features[0] & LMP_3SLOT) 5261da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM3 | HCI_DH3); 5271da177e4SLinus Torvalds 5281da177e4SLinus Torvalds if (hdev->features[0] & LMP_5SLOT) 5291da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM5 | HCI_DH5); 5301da177e4SLinus Torvalds 5315b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV2) { 5321da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV2); 5335b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV2); 5345b7f9909SMarcel Holtmann } 5351da177e4SLinus Torvalds 5365b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV3) { 5371da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV3); 5385b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV3); 5395b7f9909SMarcel Holtmann } 5405b7f9909SMarcel Holtmann 54145db810fSAndre Guedes if (lmp_esco_capable(hdev)) 5425b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV3); 5435b7f9909SMarcel Holtmann 5445b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV4) 5455b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV4); 5465b7f9909SMarcel Holtmann 5475b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV5) 5485b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV5); 5491da177e4SLinus Torvalds 550efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_2M) 551efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV3); 552efc7688bSMarcel Holtmann 553efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_3M) 554efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_3EV3); 555efc7688bSMarcel Holtmann 556efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_3S_ESCO) 557efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); 558efc7688bSMarcel Holtmann 559a9de9248SMarcel Holtmann BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, 560a9de9248SMarcel Holtmann hdev->features[0], hdev->features[1], 561a9de9248SMarcel Holtmann hdev->features[2], hdev->features[3], 562a9de9248SMarcel Holtmann hdev->features[4], hdev->features[5], 563a9de9248SMarcel Holtmann hdev->features[6], hdev->features[7]); 5641da177e4SLinus Torvalds } 5651da177e4SLinus Torvalds 566971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev, 567971e3a4bSAndre Guedes struct sk_buff *skb) 568971e3a4bSAndre Guedes { 569971e3a4bSAndre Guedes struct hci_rp_read_local_ext_features *rp = (void *) skb->data; 570971e3a4bSAndre Guedes 5719f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 572971e3a4bSAndre Guedes 573971e3a4bSAndre Guedes if (rp->status) 5748f984dfaSJohan Hedberg goto done; 575971e3a4bSAndre Guedes 576b5b32b65SAndre Guedes switch (rp->page) { 577b5b32b65SAndre Guedes case 0: 578b5b32b65SAndre Guedes memcpy(hdev->features, rp->features, 8); 579b5b32b65SAndre Guedes break; 580b5b32b65SAndre Guedes case 1: 58159e29406SAndre Guedes memcpy(hdev->host_features, rp->features, 8); 582b5b32b65SAndre Guedes break; 583b5b32b65SAndre Guedes } 584971e3a4bSAndre Guedes 5858f984dfaSJohan Hedberg done: 586971e3a4bSAndre Guedes hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status); 587971e3a4bSAndre Guedes } 588971e3a4bSAndre Guedes 5891e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, 5901e89cffbSAndrei Emeltchenko struct sk_buff *skb) 5911e89cffbSAndrei Emeltchenko { 5921e89cffbSAndrei Emeltchenko struct hci_rp_read_flow_control_mode *rp = (void *) skb->data; 5931e89cffbSAndrei Emeltchenko 5949f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 5951e89cffbSAndrei Emeltchenko 5961e89cffbSAndrei Emeltchenko if (rp->status) 5971e89cffbSAndrei Emeltchenko return; 5981e89cffbSAndrei Emeltchenko 5991e89cffbSAndrei Emeltchenko hdev->flow_ctl_mode = rp->mode; 6001e89cffbSAndrei Emeltchenko 6011e89cffbSAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status); 6021e89cffbSAndrei Emeltchenko } 6031e89cffbSAndrei Emeltchenko 604a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 605a9de9248SMarcel Holtmann { 606a9de9248SMarcel Holtmann struct hci_rp_read_buffer_size *rp = (void *) skb->data; 607a9de9248SMarcel Holtmann 6089f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 609a9de9248SMarcel Holtmann 610a9de9248SMarcel Holtmann if (rp->status) 611a9de9248SMarcel Holtmann return; 612a9de9248SMarcel Holtmann 613a9de9248SMarcel Holtmann hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); 614a9de9248SMarcel Holtmann hdev->sco_mtu = rp->sco_mtu; 615a9de9248SMarcel Holtmann hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); 616a9de9248SMarcel Holtmann hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); 617da1f5198SMarcel Holtmann 618da1f5198SMarcel Holtmann if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { 619da1f5198SMarcel Holtmann hdev->sco_mtu = 64; 620da1f5198SMarcel Holtmann hdev->sco_pkts = 8; 621da1f5198SMarcel Holtmann } 622da1f5198SMarcel Holtmann 623da1f5198SMarcel Holtmann hdev->acl_cnt = hdev->acl_pkts; 624da1f5198SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 6251da177e4SLinus Torvalds 626807deac2SGustavo Padovan BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu, 627807deac2SGustavo Padovan hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts); 6281da177e4SLinus Torvalds } 6291da177e4SLinus Torvalds 630a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) 631a9de9248SMarcel Holtmann { 632a9de9248SMarcel Holtmann struct hci_rp_read_bd_addr *rp = (void *) skb->data; 6331da177e4SLinus Torvalds 6349f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 635a9de9248SMarcel Holtmann 636a9de9248SMarcel Holtmann if (!rp->status) 637a9de9248SMarcel Holtmann bacpy(&hdev->bdaddr, &rp->bdaddr); 638a9de9248SMarcel Holtmann 63923bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status); 64023bb5763SJohan Hedberg } 64123bb5763SJohan Hedberg 642350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev, 643350ee4cfSAndrei Emeltchenko struct sk_buff *skb) 644350ee4cfSAndrei Emeltchenko { 645350ee4cfSAndrei Emeltchenko struct hci_rp_read_data_block_size *rp = (void *) skb->data; 646350ee4cfSAndrei Emeltchenko 6479f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 648350ee4cfSAndrei Emeltchenko 649350ee4cfSAndrei Emeltchenko if (rp->status) 650350ee4cfSAndrei Emeltchenko return; 651350ee4cfSAndrei Emeltchenko 652350ee4cfSAndrei Emeltchenko hdev->block_mtu = __le16_to_cpu(rp->max_acl_len); 653350ee4cfSAndrei Emeltchenko hdev->block_len = __le16_to_cpu(rp->block_len); 654350ee4cfSAndrei Emeltchenko hdev->num_blocks = __le16_to_cpu(rp->num_blocks); 655350ee4cfSAndrei Emeltchenko 656350ee4cfSAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 657350ee4cfSAndrei Emeltchenko 658350ee4cfSAndrei Emeltchenko BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu, 659350ee4cfSAndrei Emeltchenko hdev->block_cnt, hdev->block_len); 660350ee4cfSAndrei Emeltchenko 661350ee4cfSAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status); 662350ee4cfSAndrei Emeltchenko } 663350ee4cfSAndrei Emeltchenko 66423bb5763SJohan Hedberg static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb) 66523bb5763SJohan Hedberg { 66623bb5763SJohan Hedberg __u8 status = *((__u8 *) skb->data); 66723bb5763SJohan Hedberg 6689f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 66923bb5763SJohan Hedberg 67023bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status); 6711da177e4SLinus Torvalds } 6721da177e4SLinus Torvalds 673928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev, 674928abaa7SAndrei Emeltchenko struct sk_buff *skb) 675928abaa7SAndrei Emeltchenko { 676928abaa7SAndrei Emeltchenko struct hci_rp_read_local_amp_info *rp = (void *) skb->data; 677928abaa7SAndrei Emeltchenko 6789f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 679928abaa7SAndrei Emeltchenko 680928abaa7SAndrei Emeltchenko if (rp->status) 6818e2a0d92SAndrei Emeltchenko goto a2mp_rsp; 682928abaa7SAndrei Emeltchenko 683928abaa7SAndrei Emeltchenko hdev->amp_status = rp->amp_status; 684928abaa7SAndrei Emeltchenko hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); 685928abaa7SAndrei Emeltchenko hdev->amp_max_bw = __le32_to_cpu(rp->max_bw); 686928abaa7SAndrei Emeltchenko hdev->amp_min_latency = __le32_to_cpu(rp->min_latency); 687928abaa7SAndrei Emeltchenko hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu); 688928abaa7SAndrei Emeltchenko hdev->amp_type = rp->amp_type; 689928abaa7SAndrei Emeltchenko hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap); 690928abaa7SAndrei Emeltchenko hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size); 691928abaa7SAndrei Emeltchenko hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); 692928abaa7SAndrei Emeltchenko hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); 693928abaa7SAndrei Emeltchenko 694928abaa7SAndrei Emeltchenko hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status); 6958e2a0d92SAndrei Emeltchenko 6968e2a0d92SAndrei Emeltchenko a2mp_rsp: 6978e2a0d92SAndrei Emeltchenko a2mp_send_getinfo_rsp(hdev); 698928abaa7SAndrei Emeltchenko } 699928abaa7SAndrei Emeltchenko 700903e4541SAndrei Emeltchenko static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev, 701903e4541SAndrei Emeltchenko struct sk_buff *skb) 702903e4541SAndrei Emeltchenko { 703903e4541SAndrei Emeltchenko struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data; 704903e4541SAndrei Emeltchenko struct amp_assoc *assoc = &hdev->loc_assoc; 705903e4541SAndrei Emeltchenko size_t rem_len, frag_len; 706903e4541SAndrei Emeltchenko 707903e4541SAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 708903e4541SAndrei Emeltchenko 709903e4541SAndrei Emeltchenko if (rp->status) 710903e4541SAndrei Emeltchenko goto a2mp_rsp; 711903e4541SAndrei Emeltchenko 712903e4541SAndrei Emeltchenko frag_len = skb->len - sizeof(*rp); 713903e4541SAndrei Emeltchenko rem_len = __le16_to_cpu(rp->rem_len); 714903e4541SAndrei Emeltchenko 715903e4541SAndrei Emeltchenko if (rem_len > frag_len) { 7162e430be3SAndrei Emeltchenko BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len); 717903e4541SAndrei Emeltchenko 718903e4541SAndrei Emeltchenko memcpy(assoc->data + assoc->offset, rp->frag, frag_len); 719903e4541SAndrei Emeltchenko assoc->offset += frag_len; 720903e4541SAndrei Emeltchenko 721903e4541SAndrei Emeltchenko /* Read other fragments */ 722903e4541SAndrei Emeltchenko amp_read_loc_assoc_frag(hdev, rp->phy_handle); 723903e4541SAndrei Emeltchenko 724903e4541SAndrei Emeltchenko return; 725903e4541SAndrei Emeltchenko } 726903e4541SAndrei Emeltchenko 727903e4541SAndrei Emeltchenko memcpy(assoc->data + assoc->offset, rp->frag, rem_len); 728903e4541SAndrei Emeltchenko assoc->len = assoc->offset + rem_len; 729903e4541SAndrei Emeltchenko assoc->offset = 0; 730903e4541SAndrei Emeltchenko 731903e4541SAndrei Emeltchenko a2mp_rsp: 732903e4541SAndrei Emeltchenko /* Send A2MP Rsp when all fragments are received */ 733903e4541SAndrei Emeltchenko a2mp_send_getampassoc_rsp(hdev, rp->status); 7349495b2eeSAndrei Emeltchenko a2mp_send_create_phy_link_req(hdev, rp->status); 735903e4541SAndrei Emeltchenko } 736903e4541SAndrei Emeltchenko 737b0916ea0SJohan Hedberg static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, 738b0916ea0SJohan Hedberg struct sk_buff *skb) 739b0916ea0SJohan Hedberg { 740b0916ea0SJohan Hedberg __u8 status = *((__u8 *) skb->data); 741b0916ea0SJohan Hedberg 7429f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 743b0916ea0SJohan Hedberg 744b0916ea0SJohan Hedberg hci_req_complete(hdev, HCI_OP_DELETE_STORED_LINK_KEY, status); 745b0916ea0SJohan Hedberg } 746b0916ea0SJohan Hedberg 747d5859e22SJohan Hedberg static void hci_cc_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb) 748d5859e22SJohan Hedberg { 749d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 750d5859e22SJohan Hedberg 7519f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 752d5859e22SJohan Hedberg 753d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_MASK, status); 754d5859e22SJohan Hedberg } 755d5859e22SJohan Hedberg 756d5859e22SJohan Hedberg static void hci_cc_write_inquiry_mode(struct hci_dev *hdev, 757d5859e22SJohan Hedberg struct sk_buff *skb) 758d5859e22SJohan Hedberg { 759d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 760d5859e22SJohan Hedberg 7619f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 762d5859e22SJohan Hedberg 763d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_INQUIRY_MODE, status); 764d5859e22SJohan Hedberg } 765d5859e22SJohan Hedberg 766d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, 767d5859e22SJohan Hedberg struct sk_buff *skb) 768d5859e22SJohan Hedberg { 76991c4e9b1SMarcel Holtmann struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data; 770d5859e22SJohan Hedberg 7719f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 772d5859e22SJohan Hedberg 77391c4e9b1SMarcel Holtmann if (!rp->status) 77491c4e9b1SMarcel Holtmann hdev->inq_tx_power = rp->tx_power; 77591c4e9b1SMarcel Holtmann 77691c4e9b1SMarcel Holtmann hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, rp->status); 777d5859e22SJohan Hedberg } 778d5859e22SJohan Hedberg 779d5859e22SJohan Hedberg static void hci_cc_set_event_flt(struct hci_dev *hdev, struct sk_buff *skb) 780d5859e22SJohan Hedberg { 781d5859e22SJohan Hedberg __u8 status = *((__u8 *) skb->data); 782d5859e22SJohan Hedberg 7839f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 784d5859e22SJohan Hedberg 785d5859e22SJohan Hedberg hci_req_complete(hdev, HCI_OP_SET_EVENT_FLT, status); 786d5859e22SJohan Hedberg } 787d5859e22SJohan Hedberg 788980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) 789980e1a53SJohan Hedberg { 790980e1a53SJohan Hedberg struct hci_rp_pin_code_reply *rp = (void *) skb->data; 791980e1a53SJohan Hedberg struct hci_cp_pin_code_reply *cp; 792980e1a53SJohan Hedberg struct hci_conn *conn; 793980e1a53SJohan Hedberg 7949f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 795980e1a53SJohan Hedberg 79656e5cb86SJohan Hedberg hci_dev_lock(hdev); 79756e5cb86SJohan Hedberg 798a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 799744cf19eSJohan Hedberg mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); 800980e1a53SJohan Hedberg 801fa1bd918SMikel Astiz if (rp->status) 80256e5cb86SJohan Hedberg goto unlock; 803980e1a53SJohan Hedberg 804980e1a53SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); 805980e1a53SJohan Hedberg if (!cp) 80656e5cb86SJohan Hedberg goto unlock; 807980e1a53SJohan Hedberg 808980e1a53SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 809980e1a53SJohan Hedberg if (conn) 810980e1a53SJohan Hedberg conn->pin_length = cp->pin_len; 81156e5cb86SJohan Hedberg 81256e5cb86SJohan Hedberg unlock: 81356e5cb86SJohan Hedberg hci_dev_unlock(hdev); 814980e1a53SJohan Hedberg } 815980e1a53SJohan Hedberg 816980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 817980e1a53SJohan Hedberg { 818980e1a53SJohan Hedberg struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data; 819980e1a53SJohan Hedberg 8209f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 821980e1a53SJohan Hedberg 82256e5cb86SJohan Hedberg hci_dev_lock(hdev); 82356e5cb86SJohan Hedberg 824a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 825744cf19eSJohan Hedberg mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr, 826980e1a53SJohan Hedberg rp->status); 82756e5cb86SJohan Hedberg 82856e5cb86SJohan Hedberg hci_dev_unlock(hdev); 829980e1a53SJohan Hedberg } 83056e5cb86SJohan Hedberg 8316ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, 8326ed58ec5SVille Tervo struct sk_buff *skb) 8336ed58ec5SVille Tervo { 8346ed58ec5SVille Tervo struct hci_rp_le_read_buffer_size *rp = (void *) skb->data; 8356ed58ec5SVille Tervo 8369f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 8376ed58ec5SVille Tervo 8386ed58ec5SVille Tervo if (rp->status) 8396ed58ec5SVille Tervo return; 8406ed58ec5SVille Tervo 8416ed58ec5SVille Tervo hdev->le_mtu = __le16_to_cpu(rp->le_mtu); 8426ed58ec5SVille Tervo hdev->le_pkts = rp->le_max_pkt; 8436ed58ec5SVille Tervo 8446ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 8456ed58ec5SVille Tervo 8466ed58ec5SVille Tervo BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); 8476ed58ec5SVille Tervo 8486ed58ec5SVille Tervo hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status); 8496ed58ec5SVille Tervo } 850980e1a53SJohan Hedberg 85160e77321SJohan Hedberg static void hci_cc_le_read_local_features(struct hci_dev *hdev, 85260e77321SJohan Hedberg struct sk_buff *skb) 85360e77321SJohan Hedberg { 85460e77321SJohan Hedberg struct hci_rp_le_read_local_features *rp = (void *) skb->data; 85560e77321SJohan Hedberg 85660e77321SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 85760e77321SJohan Hedberg 85860e77321SJohan Hedberg if (!rp->status) 85960e77321SJohan Hedberg memcpy(hdev->le_features, rp->features, 8); 86060e77321SJohan Hedberg 86160e77321SJohan Hedberg hci_req_complete(hdev, HCI_OP_LE_READ_LOCAL_FEATURES, rp->status); 86260e77321SJohan Hedberg } 86360e77321SJohan Hedberg 8648fa19098SJohan Hedberg static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, 8658fa19098SJohan Hedberg struct sk_buff *skb) 8668fa19098SJohan Hedberg { 8678fa19098SJohan Hedberg struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data; 8688fa19098SJohan Hedberg 8698fa19098SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 8708fa19098SJohan Hedberg 8713f0f524bSJohan Hedberg if (!rp->status) { 8728fa19098SJohan Hedberg hdev->adv_tx_power = rp->tx_power; 8733f0f524bSJohan Hedberg if (!test_bit(HCI_INIT, &hdev->flags)) 8743f0f524bSJohan Hedberg hci_update_ad(hdev); 8753f0f524bSJohan Hedberg } 8768fa19098SJohan Hedberg 8778fa19098SJohan Hedberg hci_req_complete(hdev, HCI_OP_LE_READ_ADV_TX_POWER, rp->status); 8788fa19098SJohan Hedberg } 8798fa19098SJohan Hedberg 880e36b04c8SJohan Hedberg static void hci_cc_le_set_event_mask(struct hci_dev *hdev, struct sk_buff *skb) 881e36b04c8SJohan Hedberg { 882e36b04c8SJohan Hedberg __u8 status = *((__u8 *) skb->data); 883e36b04c8SJohan Hedberg 884e36b04c8SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 885e36b04c8SJohan Hedberg 886e36b04c8SJohan Hedberg hci_req_complete(hdev, HCI_OP_LE_SET_EVENT_MASK, status); 887e36b04c8SJohan Hedberg } 888e36b04c8SJohan Hedberg 889a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) 890a5c29683SJohan Hedberg { 891a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 892a5c29683SJohan Hedberg 8939f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 894a5c29683SJohan Hedberg 89556e5cb86SJohan Hedberg hci_dev_lock(hdev); 89656e5cb86SJohan Hedberg 897a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 89804124681SGustavo F. Padovan mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0, 89904124681SGustavo F. Padovan rp->status); 90056e5cb86SJohan Hedberg 90156e5cb86SJohan Hedberg hci_dev_unlock(hdev); 902a5c29683SJohan Hedberg } 903a5c29683SJohan Hedberg 904a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, 905a5c29683SJohan Hedberg struct sk_buff *skb) 906a5c29683SJohan Hedberg { 907a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 908a5c29683SJohan Hedberg 9099f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 910a5c29683SJohan Hedberg 91156e5cb86SJohan Hedberg hci_dev_lock(hdev); 91256e5cb86SJohan Hedberg 913a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 914744cf19eSJohan Hedberg mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr, 91504124681SGustavo F. Padovan ACL_LINK, 0, rp->status); 91656e5cb86SJohan Hedberg 91756e5cb86SJohan Hedberg hci_dev_unlock(hdev); 918a5c29683SJohan Hedberg } 919a5c29683SJohan Hedberg 9201143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb) 9211143d458SBrian Gix { 9221143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 9231143d458SBrian Gix 9249f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 9251143d458SBrian Gix 9261143d458SBrian Gix hci_dev_lock(hdev); 9271143d458SBrian Gix 928a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 929272d90dfSJohan Hedberg mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 930272d90dfSJohan Hedberg 0, rp->status); 9311143d458SBrian Gix 9321143d458SBrian Gix hci_dev_unlock(hdev); 9331143d458SBrian Gix } 9341143d458SBrian Gix 9351143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, 9361143d458SBrian Gix struct sk_buff *skb) 9371143d458SBrian Gix { 9381143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 9391143d458SBrian Gix 9409f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 9411143d458SBrian Gix 9421143d458SBrian Gix hci_dev_lock(hdev); 9431143d458SBrian Gix 944a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 9451143d458SBrian Gix mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr, 94604124681SGustavo F. Padovan ACL_LINK, 0, rp->status); 9471143d458SBrian Gix 9481143d458SBrian Gix hci_dev_unlock(hdev); 9491143d458SBrian Gix } 9501143d458SBrian Gix 951c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, 952c35938b2SSzymon Janc struct sk_buff *skb) 953c35938b2SSzymon Janc { 954c35938b2SSzymon Janc struct hci_rp_read_local_oob_data *rp = (void *) skb->data; 955c35938b2SSzymon Janc 9569f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 957c35938b2SSzymon Janc 95856e5cb86SJohan Hedberg hci_dev_lock(hdev); 959744cf19eSJohan Hedberg mgmt_read_local_oob_data_reply_complete(hdev, rp->hash, 960c35938b2SSzymon Janc rp->randomizer, rp->status); 96156e5cb86SJohan Hedberg hci_dev_unlock(hdev); 962c35938b2SSzymon Janc } 963c35938b2SSzymon Janc 964c1d5dc4aSJohan Hedberg static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb) 965c1d5dc4aSJohan Hedberg { 966c1d5dc4aSJohan Hedberg __u8 *sent, status = *((__u8 *) skb->data); 967c1d5dc4aSJohan Hedberg 968c1d5dc4aSJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 969c1d5dc4aSJohan Hedberg 970c1d5dc4aSJohan Hedberg sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE); 971c1d5dc4aSJohan Hedberg if (!sent) 972c1d5dc4aSJohan Hedberg return; 973c1d5dc4aSJohan Hedberg 974c1d5dc4aSJohan Hedberg hci_dev_lock(hdev); 975c1d5dc4aSJohan Hedberg 976c1d5dc4aSJohan Hedberg if (!status) { 977c1d5dc4aSJohan Hedberg if (*sent) 978c1d5dc4aSJohan Hedberg set_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags); 979c1d5dc4aSJohan Hedberg else 980c1d5dc4aSJohan Hedberg clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags); 981c1d5dc4aSJohan Hedberg } 982c1d5dc4aSJohan Hedberg 983c1d5dc4aSJohan Hedberg hci_dev_unlock(hdev); 984c1d5dc4aSJohan Hedberg 985c1d5dc4aSJohan Hedberg if (!test_bit(HCI_INIT, &hdev->flags)) 986c1d5dc4aSJohan Hedberg hci_update_ad(hdev); 987c1d5dc4aSJohan Hedberg 988c1d5dc4aSJohan Hedberg hci_req_complete(hdev, HCI_OP_LE_SET_ADV_ENABLE, status); 989c1d5dc4aSJohan Hedberg } 990c1d5dc4aSJohan Hedberg 99107f7fa5dSAndre Guedes static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) 99207f7fa5dSAndre Guedes { 99307f7fa5dSAndre Guedes __u8 status = *((__u8 *) skb->data); 99407f7fa5dSAndre Guedes 9959f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 9967ba8b4beSAndre Guedes 9977ba8b4beSAndre Guedes hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status); 9983fd24153SAndre Guedes 9993fd24153SAndre Guedes if (status) { 10003fd24153SAndre Guedes hci_dev_lock(hdev); 10013fd24153SAndre Guedes mgmt_start_discovery_failed(hdev, status); 10023fd24153SAndre Guedes hci_dev_unlock(hdev); 10033fd24153SAndre Guedes return; 10043fd24153SAndre Guedes } 100507f7fa5dSAndre Guedes } 100607f7fa5dSAndre Guedes 1007eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, 1008eb9d91f5SAndre Guedes struct sk_buff *skb) 1009eb9d91f5SAndre Guedes { 1010eb9d91f5SAndre Guedes struct hci_cp_le_set_scan_enable *cp; 1011eb9d91f5SAndre Guedes __u8 status = *((__u8 *) skb->data); 1012eb9d91f5SAndre Guedes 10139f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1014eb9d91f5SAndre Guedes 1015eb9d91f5SAndre Guedes cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE); 1016eb9d91f5SAndre Guedes if (!cp) 1017eb9d91f5SAndre Guedes return; 1018eb9d91f5SAndre Guedes 101968a8aea4SAndrei Emeltchenko switch (cp->enable) { 102068a8aea4SAndrei Emeltchenko case LE_SCANNING_ENABLED: 10217ba8b4beSAndre Guedes hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status); 10227ba8b4beSAndre Guedes 10233fd24153SAndre Guedes if (status) { 10243fd24153SAndre Guedes hci_dev_lock(hdev); 10253fd24153SAndre Guedes mgmt_start_discovery_failed(hdev, status); 10263fd24153SAndre Guedes hci_dev_unlock(hdev); 10277ba8b4beSAndre Guedes return; 10283fd24153SAndre Guedes } 10297ba8b4beSAndre Guedes 1030d23264a8SAndre Guedes set_bit(HCI_LE_SCAN, &hdev->dev_flags); 1031d23264a8SAndre Guedes 1032a8f13c8cSAndre Guedes hci_dev_lock(hdev); 1033343f935bSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_FINDING); 1034a8f13c8cSAndre Guedes hci_dev_unlock(hdev); 103568a8aea4SAndrei Emeltchenko break; 103668a8aea4SAndrei Emeltchenko 103768a8aea4SAndrei Emeltchenko case LE_SCANNING_DISABLED: 1038c9ecc48eSAndre Guedes if (status) { 1039c9ecc48eSAndre Guedes hci_dev_lock(hdev); 1040c9ecc48eSAndre Guedes mgmt_stop_discovery_failed(hdev, status); 1041c9ecc48eSAndre Guedes hci_dev_unlock(hdev); 10427ba8b4beSAndre Guedes return; 1043c9ecc48eSAndre Guedes } 10447ba8b4beSAndre Guedes 1045d23264a8SAndre Guedes clear_bit(HCI_LE_SCAN, &hdev->dev_flags); 1046d23264a8SAndre Guedes 1047bc3dd33cSAndre Guedes if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED && 1048bc3dd33cSAndre Guedes hdev->discovery.state == DISCOVERY_FINDING) { 10495e0452c0SAndre Guedes mgmt_interleaved_discovery(hdev); 10505e0452c0SAndre Guedes } else { 1051c599008fSAndre Guedes hci_dev_lock(hdev); 1052c599008fSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 1053c599008fSAndre Guedes hci_dev_unlock(hdev); 10545e0452c0SAndre Guedes } 1055c599008fSAndre Guedes 105668a8aea4SAndrei Emeltchenko break; 105768a8aea4SAndrei Emeltchenko 105868a8aea4SAndrei Emeltchenko default: 105968a8aea4SAndrei Emeltchenko BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable); 106068a8aea4SAndrei Emeltchenko break; 106135815085SAndre Guedes } 1062eb9d91f5SAndre Guedes } 1063eb9d91f5SAndre Guedes 1064cf1d081fSJohan Hedberg static void hci_cc_le_read_white_list_size(struct hci_dev *hdev, 1065cf1d081fSJohan Hedberg struct sk_buff *skb) 1066cf1d081fSJohan Hedberg { 1067cf1d081fSJohan Hedberg struct hci_rp_le_read_white_list_size *rp = (void *) skb->data; 1068cf1d081fSJohan Hedberg 1069cf1d081fSJohan Hedberg BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size); 1070cf1d081fSJohan Hedberg 1071cf1d081fSJohan Hedberg if (!rp->status) 1072cf1d081fSJohan Hedberg hdev->le_white_list_size = rp->size; 1073cf1d081fSJohan Hedberg 1074cf1d081fSJohan Hedberg hci_req_complete(hdev, HCI_OP_LE_READ_WHITE_LIST_SIZE, rp->status); 1075cf1d081fSJohan Hedberg } 1076cf1d081fSJohan Hedberg 1077a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb) 1078a7a595f6SVinicius Costa Gomes { 1079a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_reply *rp = (void *) skb->data; 1080a7a595f6SVinicius Costa Gomes 10819f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1082a7a595f6SVinicius Costa Gomes 1083a7a595f6SVinicius Costa Gomes if (rp->status) 1084a7a595f6SVinicius Costa Gomes return; 1085a7a595f6SVinicius Costa Gomes 1086a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status); 1087a7a595f6SVinicius Costa Gomes } 1088a7a595f6SVinicius Costa Gomes 1089a7a595f6SVinicius Costa Gomes static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 1090a7a595f6SVinicius Costa Gomes { 1091a7a595f6SVinicius Costa Gomes struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data; 1092a7a595f6SVinicius Costa Gomes 10939f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 1094a7a595f6SVinicius Costa Gomes 1095a7a595f6SVinicius Costa Gomes if (rp->status) 1096a7a595f6SVinicius Costa Gomes return; 1097a7a595f6SVinicius Costa Gomes 1098a7a595f6SVinicius Costa Gomes hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status); 1099a7a595f6SVinicius Costa Gomes } 1100a7a595f6SVinicius Costa Gomes 11019b008c04SJohan Hedberg static void hci_cc_le_read_supported_states(struct hci_dev *hdev, 11029b008c04SJohan Hedberg struct sk_buff *skb) 11039b008c04SJohan Hedberg { 11049b008c04SJohan Hedberg struct hci_rp_le_read_supported_states *rp = (void *) skb->data; 11059b008c04SJohan Hedberg 11069b008c04SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 11079b008c04SJohan Hedberg 11089b008c04SJohan Hedberg if (!rp->status) 11099b008c04SJohan Hedberg memcpy(hdev->le_states, rp->le_states, 8); 11109b008c04SJohan Hedberg 11119b008c04SJohan Hedberg hci_req_complete(hdev, HCI_OP_LE_READ_SUPPORTED_STATES, rp->status); 11129b008c04SJohan Hedberg } 11139b008c04SJohan Hedberg 11146039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev, 1115f9b49306SAndre Guedes struct sk_buff *skb) 1116f9b49306SAndre Guedes { 111706199cf8SJohan Hedberg struct hci_cp_write_le_host_supported *sent; 1118f9b49306SAndre Guedes __u8 status = *((__u8 *) skb->data); 1119f9b49306SAndre Guedes 11209f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1121f9b49306SAndre Guedes 112206199cf8SJohan Hedberg sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED); 11238f984dfaSJohan Hedberg if (!sent) 1124f9b49306SAndre Guedes return; 1125f9b49306SAndre Guedes 11268f984dfaSJohan Hedberg if (!status) { 11278f984dfaSJohan Hedberg if (sent->le) 11288f984dfaSJohan Hedberg hdev->host_features[0] |= LMP_HOST_LE; 11298f984dfaSJohan Hedberg else 11308f984dfaSJohan Hedberg hdev->host_features[0] &= ~LMP_HOST_LE; 113153b2caabSJohan Hedberg 113253b2caabSJohan Hedberg if (sent->simul) 113353b2caabSJohan Hedberg hdev->host_features[0] |= LMP_HOST_LE_BREDR; 113453b2caabSJohan Hedberg else 113553b2caabSJohan Hedberg hdev->host_features[0] &= ~LMP_HOST_LE_BREDR; 11368f984dfaSJohan Hedberg } 11378f984dfaSJohan Hedberg 11388f984dfaSJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags) && 11398f984dfaSJohan Hedberg !test_bit(HCI_INIT, &hdev->flags)) 11408f984dfaSJohan Hedberg mgmt_le_enable_complete(hdev, sent->le, status); 11418f984dfaSJohan Hedberg 11428f984dfaSJohan Hedberg hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status); 1143f9b49306SAndre Guedes } 1144f9b49306SAndre Guedes 114593c284eeSAndrei Emeltchenko static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev, 114693c284eeSAndrei Emeltchenko struct sk_buff *skb) 114793c284eeSAndrei Emeltchenko { 114893c284eeSAndrei Emeltchenko struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data; 114993c284eeSAndrei Emeltchenko 115093c284eeSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x", 115193c284eeSAndrei Emeltchenko hdev->name, rp->status, rp->phy_handle); 115293c284eeSAndrei Emeltchenko 115393c284eeSAndrei Emeltchenko if (rp->status) 115493c284eeSAndrei Emeltchenko return; 115593c284eeSAndrei Emeltchenko 115693c284eeSAndrei Emeltchenko amp_write_rem_assoc_continue(hdev, rp->phy_handle); 115793c284eeSAndrei Emeltchenko } 115893c284eeSAndrei Emeltchenko 11596039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 1160a9de9248SMarcel Holtmann { 11619f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1162a9de9248SMarcel Holtmann 1163a9de9248SMarcel Holtmann if (status) { 116423bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 1165a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 116656e5cb86SJohan Hedberg hci_dev_lock(hdev); 1167a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 11687a135109SAndre Guedes mgmt_start_discovery_failed(hdev, status); 116956e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1170314b2381SJohan Hedberg return; 1171314b2381SJohan Hedberg } 1172314b2381SJohan Hedberg 117389352e7dSAndre Guedes set_bit(HCI_INQUIRY, &hdev->flags); 117489352e7dSAndre Guedes 117556e5cb86SJohan Hedberg hci_dev_lock(hdev); 1176343f935bSAndre Guedes hci_discovery_set_state(hdev, DISCOVERY_FINDING); 117756e5cb86SJohan Hedberg hci_dev_unlock(hdev); 1178a9de9248SMarcel Holtmann } 1179a9de9248SMarcel Holtmann 11806039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 11811da177e4SLinus Torvalds { 1182a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 11831da177e4SLinus Torvalds struct hci_conn *conn; 11841da177e4SLinus Torvalds 11859f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1186a9de9248SMarcel Holtmann 1187a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 11881da177e4SLinus Torvalds if (!cp) 11891da177e4SLinus Torvalds return; 11901da177e4SLinus Torvalds 11911da177e4SLinus Torvalds hci_dev_lock(hdev); 11921da177e4SLinus Torvalds 11931da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 11941da177e4SLinus Torvalds 11956ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn); 11961da177e4SLinus Torvalds 11971da177e4SLinus Torvalds if (status) { 11981da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 11994c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 12001da177e4SLinus Torvalds conn->state = BT_CLOSED; 12011da177e4SLinus Torvalds hci_proto_connect_cfm(conn, status); 12021da177e4SLinus Torvalds hci_conn_del(conn); 12034c67bc74SMarcel Holtmann } else 12044c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 12051da177e4SLinus Torvalds } 12061da177e4SLinus Torvalds } else { 12071da177e4SLinus Torvalds if (!conn) { 12081da177e4SLinus Torvalds conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); 12091da177e4SLinus Torvalds if (conn) { 1210a0c808b3SJohan Hedberg conn->out = true; 12111da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 12121da177e4SLinus Torvalds } else 1213893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 12141da177e4SLinus Torvalds } 12151da177e4SLinus Torvalds } 12161da177e4SLinus Torvalds 12171da177e4SLinus Torvalds hci_dev_unlock(hdev); 12181da177e4SLinus Torvalds } 12191da177e4SLinus Torvalds 1220a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 12211da177e4SLinus Torvalds { 1222a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 12231da177e4SLinus Torvalds struct hci_conn *acl, *sco; 12241da177e4SLinus Torvalds __u16 handle; 12251da177e4SLinus Torvalds 12269f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1227b6a0dc82SMarcel Holtmann 1228a9de9248SMarcel Holtmann if (!status) 1229a9de9248SMarcel Holtmann return; 1230a9de9248SMarcel Holtmann 1231a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 12321da177e4SLinus Torvalds if (!cp) 1233a9de9248SMarcel Holtmann return; 12341da177e4SLinus Torvalds 12351da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 12361da177e4SLinus Torvalds 12379f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, handle); 12381da177e4SLinus Torvalds 12391da177e4SLinus Torvalds hci_dev_lock(hdev); 12401da177e4SLinus Torvalds 12411da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 12425a08ecceSAndrei Emeltchenko if (acl) { 12435a08ecceSAndrei Emeltchenko sco = acl->link; 12445a08ecceSAndrei Emeltchenko if (sco) { 12451da177e4SLinus Torvalds sco->state = BT_CLOSED; 12461da177e4SLinus Torvalds 12471da177e4SLinus Torvalds hci_proto_connect_cfm(sco, status); 12481da177e4SLinus Torvalds hci_conn_del(sco); 12491da177e4SLinus Torvalds } 12505a08ecceSAndrei Emeltchenko } 12511da177e4SLinus Torvalds 12521da177e4SLinus Torvalds hci_dev_unlock(hdev); 12531da177e4SLinus Torvalds } 12541da177e4SLinus Torvalds 1255f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 1256f8558555SMarcel Holtmann { 1257f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 1258f8558555SMarcel Holtmann struct hci_conn *conn; 1259f8558555SMarcel Holtmann 12609f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1261f8558555SMarcel Holtmann 1262f8558555SMarcel Holtmann if (!status) 1263f8558555SMarcel Holtmann return; 1264f8558555SMarcel Holtmann 1265f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 1266f8558555SMarcel Holtmann if (!cp) 1267f8558555SMarcel Holtmann return; 1268f8558555SMarcel Holtmann 1269f8558555SMarcel Holtmann hci_dev_lock(hdev); 1270f8558555SMarcel Holtmann 1271f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1272f8558555SMarcel Holtmann if (conn) { 1273f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1274f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1275f8558555SMarcel Holtmann hci_conn_put(conn); 1276f8558555SMarcel Holtmann } 1277f8558555SMarcel Holtmann } 1278f8558555SMarcel Holtmann 1279f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1280f8558555SMarcel Holtmann } 1281f8558555SMarcel Holtmann 1282f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 1283f8558555SMarcel Holtmann { 1284f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 1285f8558555SMarcel Holtmann struct hci_conn *conn; 1286f8558555SMarcel Holtmann 12879f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1288f8558555SMarcel Holtmann 1289f8558555SMarcel Holtmann if (!status) 1290f8558555SMarcel Holtmann return; 1291f8558555SMarcel Holtmann 1292f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 1293f8558555SMarcel Holtmann if (!cp) 1294f8558555SMarcel Holtmann return; 1295f8558555SMarcel Holtmann 1296f8558555SMarcel Holtmann hci_dev_lock(hdev); 1297f8558555SMarcel Holtmann 1298f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1299f8558555SMarcel Holtmann if (conn) { 1300f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1301f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1302f8558555SMarcel Holtmann hci_conn_put(conn); 1303f8558555SMarcel Holtmann } 1304f8558555SMarcel Holtmann } 1305f8558555SMarcel Holtmann 1306f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1307f8558555SMarcel Holtmann } 1308f8558555SMarcel Holtmann 1309127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev, 1310392599b9SJohan Hedberg struct hci_conn *conn) 1311392599b9SJohan Hedberg { 1312392599b9SJohan Hedberg if (conn->state != BT_CONFIG || !conn->out) 1313392599b9SJohan Hedberg return 0; 1314392599b9SJohan Hedberg 1315765c2a96SJohan Hedberg if (conn->pending_sec_level == BT_SECURITY_SDP) 1316392599b9SJohan Hedberg return 0; 1317392599b9SJohan Hedberg 1318392599b9SJohan Hedberg /* Only request authentication for SSP connections or non-SSP 1319e9bf2bf0SVinicius Costa Gomes * devices with sec_level HIGH or if MITM protection is requested */ 1320807deac2SGustavo Padovan if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) && 1321807deac2SGustavo Padovan conn->pending_sec_level != BT_SECURITY_HIGH) 1322392599b9SJohan Hedberg return 0; 1323392599b9SJohan Hedberg 1324392599b9SJohan Hedberg return 1; 1325392599b9SJohan Hedberg } 1326392599b9SJohan Hedberg 13276039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev, 132800abfe44SGustavo F. Padovan struct inquiry_entry *e) 132930dc78e1SJohan Hedberg { 133030dc78e1SJohan Hedberg struct hci_cp_remote_name_req cp; 133130dc78e1SJohan Hedberg 133230dc78e1SJohan Hedberg memset(&cp, 0, sizeof(cp)); 133330dc78e1SJohan Hedberg 133430dc78e1SJohan Hedberg bacpy(&cp.bdaddr, &e->data.bdaddr); 133530dc78e1SJohan Hedberg cp.pscan_rep_mode = e->data.pscan_rep_mode; 133630dc78e1SJohan Hedberg cp.pscan_mode = e->data.pscan_mode; 133730dc78e1SJohan Hedberg cp.clock_offset = e->data.clock_offset; 133830dc78e1SJohan Hedberg 133930dc78e1SJohan Hedberg return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 134030dc78e1SJohan Hedberg } 134130dc78e1SJohan Hedberg 1342b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev) 134330dc78e1SJohan Hedberg { 134430dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 134530dc78e1SJohan Hedberg struct inquiry_entry *e; 134630dc78e1SJohan Hedberg 1347b644ba33SJohan Hedberg if (list_empty(&discov->resolve)) 1348b644ba33SJohan Hedberg return false; 1349b644ba33SJohan Hedberg 1350b644ba33SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 1351c810089cSRam Malovany if (!e) 1352c810089cSRam Malovany return false; 1353c810089cSRam Malovany 1354b644ba33SJohan Hedberg if (hci_resolve_name(hdev, e) == 0) { 1355b644ba33SJohan Hedberg e->name_state = NAME_PENDING; 1356b644ba33SJohan Hedberg return true; 1357b644ba33SJohan Hedberg } 1358b644ba33SJohan Hedberg 1359b644ba33SJohan Hedberg return false; 1360b644ba33SJohan Hedberg } 1361b644ba33SJohan Hedberg 1362b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn, 1363b644ba33SJohan Hedberg bdaddr_t *bdaddr, u8 *name, u8 name_len) 1364b644ba33SJohan Hedberg { 1365b644ba33SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 1366b644ba33SJohan Hedberg struct inquiry_entry *e; 1367b644ba33SJohan Hedberg 1368b644ba33SJohan Hedberg if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 136904124681SGustavo F. Padovan mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name, 137004124681SGustavo F. Padovan name_len, conn->dev_class); 1371b644ba33SJohan Hedberg 1372b644ba33SJohan Hedberg if (discov->state == DISCOVERY_STOPPED) 1373b644ba33SJohan Hedberg return; 1374b644ba33SJohan Hedberg 137530dc78e1SJohan Hedberg if (discov->state == DISCOVERY_STOPPING) 137630dc78e1SJohan Hedberg goto discov_complete; 137730dc78e1SJohan Hedberg 137830dc78e1SJohan Hedberg if (discov->state != DISCOVERY_RESOLVING) 137930dc78e1SJohan Hedberg return; 138030dc78e1SJohan Hedberg 138130dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING); 13827cc8380eSRam Malovany /* If the device was not found in a list of found devices names of which 13837cc8380eSRam Malovany * are pending. there is no need to continue resolving a next name as it 13847cc8380eSRam Malovany * will be done upon receiving another Remote Name Request Complete 13857cc8380eSRam Malovany * Event */ 13867cc8380eSRam Malovany if (!e) 13877cc8380eSRam Malovany return; 13887cc8380eSRam Malovany 138930dc78e1SJohan Hedberg list_del(&e->list); 13907cc8380eSRam Malovany if (name) { 13917cc8380eSRam Malovany e->name_state = NAME_KNOWN; 1392b644ba33SJohan Hedberg mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, 1393b644ba33SJohan Hedberg e->data.rssi, name, name_len); 1394c3e7c0d9SRam Malovany } else { 1395c3e7c0d9SRam Malovany e->name_state = NAME_NOT_KNOWN; 139630dc78e1SJohan Hedberg } 139730dc78e1SJohan Hedberg 1398b644ba33SJohan Hedberg if (hci_resolve_next_name(hdev)) 139930dc78e1SJohan Hedberg return; 140030dc78e1SJohan Hedberg 140130dc78e1SJohan Hedberg discov_complete: 140230dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 140330dc78e1SJohan Hedberg } 140430dc78e1SJohan Hedberg 1405a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 14061da177e4SLinus Torvalds { 1407127178d2SJohan Hedberg struct hci_cp_remote_name_req *cp; 1408127178d2SJohan Hedberg struct hci_conn *conn; 1409127178d2SJohan Hedberg 14109f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1411127178d2SJohan Hedberg 1412127178d2SJohan Hedberg /* If successful wait for the name req complete event before 1413127178d2SJohan Hedberg * checking for the need to do authentication */ 1414127178d2SJohan Hedberg if (!status) 1415127178d2SJohan Hedberg return; 1416127178d2SJohan Hedberg 1417127178d2SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); 1418127178d2SJohan Hedberg if (!cp) 1419127178d2SJohan Hedberg return; 1420127178d2SJohan Hedberg 1421127178d2SJohan Hedberg hci_dev_lock(hdev); 1422127178d2SJohan Hedberg 1423127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 1424b644ba33SJohan Hedberg 1425b644ba33SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1426b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0); 1427b644ba33SJohan Hedberg 142879c6c70cSJohan Hedberg if (!conn) 142979c6c70cSJohan Hedberg goto unlock; 143079c6c70cSJohan Hedberg 143179c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 143279c6c70cSJohan Hedberg goto unlock; 143379c6c70cSJohan Hedberg 143451a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 1435127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1436127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1437127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1438127178d2SJohan Hedberg } 1439127178d2SJohan Hedberg 144079c6c70cSJohan Hedberg unlock: 1441127178d2SJohan Hedberg hci_dev_unlock(hdev); 1442a9de9248SMarcel Holtmann } 14431da177e4SLinus Torvalds 1444769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 1445769be974SMarcel Holtmann { 1446769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 1447769be974SMarcel Holtmann struct hci_conn *conn; 1448769be974SMarcel Holtmann 14499f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1450769be974SMarcel Holtmann 1451769be974SMarcel Holtmann if (!status) 1452769be974SMarcel Holtmann return; 1453769be974SMarcel Holtmann 1454769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 1455769be974SMarcel Holtmann if (!cp) 1456769be974SMarcel Holtmann return; 1457769be974SMarcel Holtmann 1458769be974SMarcel Holtmann hci_dev_lock(hdev); 1459769be974SMarcel Holtmann 1460769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1461769be974SMarcel Holtmann if (conn) { 1462769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1463769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1464769be974SMarcel Holtmann hci_conn_put(conn); 1465769be974SMarcel Holtmann } 1466769be974SMarcel Holtmann } 1467769be974SMarcel Holtmann 1468769be974SMarcel Holtmann hci_dev_unlock(hdev); 1469769be974SMarcel Holtmann } 1470769be974SMarcel Holtmann 1471769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 1472769be974SMarcel Holtmann { 1473769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features *cp; 1474769be974SMarcel Holtmann struct hci_conn *conn; 1475769be974SMarcel Holtmann 14769f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1477769be974SMarcel Holtmann 1478769be974SMarcel Holtmann if (!status) 1479769be974SMarcel Holtmann return; 1480769be974SMarcel Holtmann 1481769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 1482769be974SMarcel Holtmann if (!cp) 1483769be974SMarcel Holtmann return; 1484769be974SMarcel Holtmann 1485769be974SMarcel Holtmann hci_dev_lock(hdev); 1486769be974SMarcel Holtmann 1487769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1488769be974SMarcel Holtmann if (conn) { 1489769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1490769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 1491769be974SMarcel Holtmann hci_conn_put(conn); 1492769be974SMarcel Holtmann } 1493769be974SMarcel Holtmann } 1494769be974SMarcel Holtmann 1495769be974SMarcel Holtmann hci_dev_unlock(hdev); 1496769be974SMarcel Holtmann } 1497769be974SMarcel Holtmann 1498a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 1499a9de9248SMarcel Holtmann { 1500b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 1501b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 1502b6a0dc82SMarcel Holtmann __u16 handle; 1503b6a0dc82SMarcel Holtmann 15049f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1505b6a0dc82SMarcel Holtmann 1506b6a0dc82SMarcel Holtmann if (!status) 1507b6a0dc82SMarcel Holtmann return; 1508b6a0dc82SMarcel Holtmann 1509b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 1510b6a0dc82SMarcel Holtmann if (!cp) 1511b6a0dc82SMarcel Holtmann return; 1512b6a0dc82SMarcel Holtmann 1513b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 1514b6a0dc82SMarcel Holtmann 15159f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, handle); 1516b6a0dc82SMarcel Holtmann 1517b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 1518b6a0dc82SMarcel Holtmann 1519b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 15205a08ecceSAndrei Emeltchenko if (acl) { 15215a08ecceSAndrei Emeltchenko sco = acl->link; 15225a08ecceSAndrei Emeltchenko if (sco) { 1523b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 1524b6a0dc82SMarcel Holtmann 1525b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(sco, status); 1526b6a0dc82SMarcel Holtmann hci_conn_del(sco); 1527b6a0dc82SMarcel Holtmann } 15285a08ecceSAndrei Emeltchenko } 1529b6a0dc82SMarcel Holtmann 1530b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 1531a9de9248SMarcel Holtmann } 1532a9de9248SMarcel Holtmann 1533a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 1534a9de9248SMarcel Holtmann { 1535a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 153604837f64SMarcel Holtmann struct hci_conn *conn; 153704837f64SMarcel Holtmann 15389f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1539a9de9248SMarcel Holtmann 1540a9de9248SMarcel Holtmann if (!status) 1541a9de9248SMarcel Holtmann return; 1542a9de9248SMarcel Holtmann 1543a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 154404837f64SMarcel Holtmann if (!cp) 1545a9de9248SMarcel Holtmann return; 154604837f64SMarcel Holtmann 154704837f64SMarcel Holtmann hci_dev_lock(hdev); 154804837f64SMarcel Holtmann 154904837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1550e73439d8SMarcel Holtmann if (conn) { 155151a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 155204837f64SMarcel Holtmann 155351a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1554e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1555e73439d8SMarcel Holtmann } 1556e73439d8SMarcel Holtmann 155704837f64SMarcel Holtmann hci_dev_unlock(hdev); 155804837f64SMarcel Holtmann } 155904837f64SMarcel Holtmann 1560a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 1561a9de9248SMarcel Holtmann { 1562a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 156304837f64SMarcel Holtmann struct hci_conn *conn; 156404837f64SMarcel Holtmann 15659f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1566a9de9248SMarcel Holtmann 1567a9de9248SMarcel Holtmann if (!status) 1568a9de9248SMarcel Holtmann return; 1569a9de9248SMarcel Holtmann 1570a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 157104837f64SMarcel Holtmann if (!cp) 1572a9de9248SMarcel Holtmann return; 157304837f64SMarcel Holtmann 157404837f64SMarcel Holtmann hci_dev_lock(hdev); 157504837f64SMarcel Holtmann 157604837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1577e73439d8SMarcel Holtmann if (conn) { 157851a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 157904837f64SMarcel Holtmann 158051a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1581e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1582e73439d8SMarcel Holtmann } 1583e73439d8SMarcel Holtmann 158404837f64SMarcel Holtmann hci_dev_unlock(hdev); 158504837f64SMarcel Holtmann } 158604837f64SMarcel Holtmann 158788c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) 158888c3df13SJohan Hedberg { 158988c3df13SJohan Hedberg struct hci_cp_disconnect *cp; 159088c3df13SJohan Hedberg struct hci_conn *conn; 159188c3df13SJohan Hedberg 159288c3df13SJohan Hedberg if (!status) 159388c3df13SJohan Hedberg return; 159488c3df13SJohan Hedberg 159588c3df13SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT); 159688c3df13SJohan Hedberg if (!cp) 159788c3df13SJohan Hedberg return; 159888c3df13SJohan Hedberg 159988c3df13SJohan Hedberg hci_dev_lock(hdev); 160088c3df13SJohan Hedberg 160188c3df13SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 160288c3df13SJohan Hedberg if (conn) 160388c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 160488c3df13SJohan Hedberg conn->dst_type, status); 160588c3df13SJohan Hedberg 160688c3df13SJohan Hedberg hci_dev_unlock(hdev); 160788c3df13SJohan Hedberg } 160888c3df13SJohan Hedberg 1609fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) 1610fcd89c09SVille Tervo { 1611fcd89c09SVille Tervo struct hci_conn *conn; 1612fcd89c09SVille Tervo 16139f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1614fcd89c09SVille Tervo 1615f00a06acSAndre Guedes if (status) { 1616fcd89c09SVille Tervo hci_dev_lock(hdev); 1617fcd89c09SVille Tervo 16180c95ab78SAndre Guedes conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); 1619f00a06acSAndre Guedes if (!conn) { 1620f00a06acSAndre Guedes hci_dev_unlock(hdev); 1621f00a06acSAndre Guedes return; 1622f00a06acSAndre Guedes } 1623fcd89c09SVille Tervo 16246ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn); 1625fcd89c09SVille Tervo 1626fcd89c09SVille Tervo conn->state = BT_CLOSED; 16270c95ab78SAndre Guedes mgmt_connect_failed(hdev, &conn->dst, conn->type, 1628328c9248SHemant Gupta conn->dst_type, status); 1629fcd89c09SVille Tervo hci_proto_connect_cfm(conn, status); 1630fcd89c09SVille Tervo hci_conn_del(conn); 1631fcd89c09SVille Tervo 1632fcd89c09SVille Tervo hci_dev_unlock(hdev); 1633fcd89c09SVille Tervo } 1634f00a06acSAndre Guedes } 1635fcd89c09SVille Tervo 1636a7a595f6SVinicius Costa Gomes static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) 1637a7a595f6SVinicius Costa Gomes { 16389f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1639a7a595f6SVinicius Costa Gomes } 1640a7a595f6SVinicius Costa Gomes 1641a02226d6SAndrei Emeltchenko static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status) 1642a02226d6SAndrei Emeltchenko { 164393c284eeSAndrei Emeltchenko struct hci_cp_create_phy_link *cp; 164493c284eeSAndrei Emeltchenko 1645a02226d6SAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 164693c284eeSAndrei Emeltchenko 164793c284eeSAndrei Emeltchenko cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK); 164893c284eeSAndrei Emeltchenko if (!cp) 164993c284eeSAndrei Emeltchenko return; 165093c284eeSAndrei Emeltchenko 1651e58917b9SAndrei Emeltchenko hci_dev_lock(hdev); 1652e58917b9SAndrei Emeltchenko 1653e58917b9SAndrei Emeltchenko if (status) { 1654e58917b9SAndrei Emeltchenko struct hci_conn *hcon; 1655e58917b9SAndrei Emeltchenko 1656e58917b9SAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle); 1657e58917b9SAndrei Emeltchenko if (hcon) 1658e58917b9SAndrei Emeltchenko hci_conn_del(hcon); 1659e58917b9SAndrei Emeltchenko } else { 166093c284eeSAndrei Emeltchenko amp_write_remote_assoc(hdev, cp->phy_handle); 1661a02226d6SAndrei Emeltchenko } 1662a02226d6SAndrei Emeltchenko 1663e58917b9SAndrei Emeltchenko hci_dev_unlock(hdev); 1664e58917b9SAndrei Emeltchenko } 1665e58917b9SAndrei Emeltchenko 16660b26ab9dSAndrei Emeltchenko static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status) 16670b26ab9dSAndrei Emeltchenko { 16680b26ab9dSAndrei Emeltchenko struct hci_cp_accept_phy_link *cp; 16690b26ab9dSAndrei Emeltchenko 16700b26ab9dSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 16710b26ab9dSAndrei Emeltchenko 16720b26ab9dSAndrei Emeltchenko if (status) 16730b26ab9dSAndrei Emeltchenko return; 16740b26ab9dSAndrei Emeltchenko 16750b26ab9dSAndrei Emeltchenko cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK); 16760b26ab9dSAndrei Emeltchenko if (!cp) 16770b26ab9dSAndrei Emeltchenko return; 16780b26ab9dSAndrei Emeltchenko 16790b26ab9dSAndrei Emeltchenko amp_write_remote_assoc(hdev, cp->phy_handle); 16800b26ab9dSAndrei Emeltchenko } 16810b26ab9dSAndrei Emeltchenko 16825ce66b59SAndrei Emeltchenko static void hci_cs_create_logical_link(struct hci_dev *hdev, u8 status) 16835ce66b59SAndrei Emeltchenko { 16845ce66b59SAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 16855ce66b59SAndrei Emeltchenko } 16865ce66b59SAndrei Emeltchenko 16876039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 16881da177e4SLinus Torvalds { 16891da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 169030dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 169130dc78e1SJohan Hedberg struct inquiry_entry *e; 16921da177e4SLinus Torvalds 16939f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 16941da177e4SLinus Torvalds 169523bb5763SJohan Hedberg hci_req_complete(hdev, HCI_OP_INQUIRY, status); 16966bd57416SMarcel Holtmann 1697a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 169889352e7dSAndre Guedes 169989352e7dSAndre Guedes if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) 170089352e7dSAndre Guedes return; 170189352e7dSAndre Guedes 1702a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 170330dc78e1SJohan Hedberg return; 170430dc78e1SJohan Hedberg 170556e5cb86SJohan Hedberg hci_dev_lock(hdev); 170630dc78e1SJohan Hedberg 1707343f935bSAndre Guedes if (discov->state != DISCOVERY_FINDING) 170830dc78e1SJohan Hedberg goto unlock; 170930dc78e1SJohan Hedberg 171030dc78e1SJohan Hedberg if (list_empty(&discov->resolve)) { 1711ff9ef578SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 171230dc78e1SJohan Hedberg goto unlock; 171330dc78e1SJohan Hedberg } 171430dc78e1SJohan Hedberg 171530dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 171630dc78e1SJohan Hedberg if (e && hci_resolve_name(hdev, e) == 0) { 171730dc78e1SJohan Hedberg e->name_state = NAME_PENDING; 171830dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_RESOLVING); 171930dc78e1SJohan Hedberg } else { 172030dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 172130dc78e1SJohan Hedberg } 172230dc78e1SJohan Hedberg 172330dc78e1SJohan Hedberg unlock: 172456e5cb86SJohan Hedberg hci_dev_unlock(hdev); 17251da177e4SLinus Torvalds } 17261da177e4SLinus Torvalds 17276039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 17281da177e4SLinus Torvalds { 172945bb4bf0SMarcel Holtmann struct inquiry_data data; 1730a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 17311da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 17321da177e4SLinus Torvalds 17331da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 17341da177e4SLinus Torvalds 173545bb4bf0SMarcel Holtmann if (!num_rsp) 173645bb4bf0SMarcel Holtmann return; 173745bb4bf0SMarcel Holtmann 17381519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 17391519cc17SAndre Guedes return; 17401519cc17SAndre Guedes 17411da177e4SLinus Torvalds hci_dev_lock(hdev); 174245bb4bf0SMarcel Holtmann 1743e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 1744388fc8faSJohan Hedberg bool name_known, ssp; 17453175405bSJohan Hedberg 17461da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 17471da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 17481da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 17491da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 17501da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 17511da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 17521da177e4SLinus Torvalds data.rssi = 0x00; 175341a96212SMarcel Holtmann data.ssp_mode = 0x00; 17543175405bSJohan Hedberg 1755388fc8faSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp); 175648264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 175704124681SGustavo F. Padovan info->dev_class, 0, !name_known, ssp, NULL, 175804124681SGustavo F. Padovan 0); 17591da177e4SLinus Torvalds } 176045bb4bf0SMarcel Holtmann 17611da177e4SLinus Torvalds hci_dev_unlock(hdev); 17621da177e4SLinus Torvalds } 17631da177e4SLinus Torvalds 17646039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 17651da177e4SLinus Torvalds { 1766a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 1767a9de9248SMarcel Holtmann struct hci_conn *conn; 17681da177e4SLinus Torvalds 1769a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 177045bb4bf0SMarcel Holtmann 17711da177e4SLinus Torvalds hci_dev_lock(hdev); 177245bb4bf0SMarcel Holtmann 1773a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 17749499237aSMarcel Holtmann if (!conn) { 17759499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 17769499237aSMarcel Holtmann goto unlock; 17779499237aSMarcel Holtmann 17789499237aSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 1779a9de9248SMarcel Holtmann if (!conn) 1780a9de9248SMarcel Holtmann goto unlock; 178145bb4bf0SMarcel Holtmann 17829499237aSMarcel Holtmann conn->type = SCO_LINK; 17839499237aSMarcel Holtmann } 17849499237aSMarcel Holtmann 1785a9de9248SMarcel Holtmann if (!ev->status) { 1786a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 1787769be974SMarcel Holtmann 1788769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 1789769be974SMarcel Holtmann conn->state = BT_CONFIG; 1790769be974SMarcel Holtmann hci_conn_hold(conn); 1791a9ea3ed9SSzymon Janc 1792a9ea3ed9SSzymon Janc if (!conn->out && !hci_conn_ssp_enabled(conn) && 1793a9ea3ed9SSzymon Janc !hci_find_link_key(hdev, &ev->bdaddr)) 1794a9ea3ed9SSzymon Janc conn->disc_timeout = HCI_PAIRING_TIMEOUT; 1795a9ea3ed9SSzymon Janc else 1796052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1797769be974SMarcel Holtmann } else 1798a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 1799a9de9248SMarcel Holtmann 18009eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 18017d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 18027d0db0a3SMarcel Holtmann 1803a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 1804a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1805a9de9248SMarcel Holtmann 1806a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 1807a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1808a9de9248SMarcel Holtmann 1809a9de9248SMarcel Holtmann /* Get remote features */ 1810a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 1811a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 1812a9de9248SMarcel Holtmann cp.handle = ev->handle; 1813769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 1814769be974SMarcel Holtmann sizeof(cp), &cp); 181545bb4bf0SMarcel Holtmann } 1816a9de9248SMarcel Holtmann 1817a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 1818d095c1ebSAndrei Emeltchenko if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) { 1819a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 1820a9de9248SMarcel Holtmann cp.handle = ev->handle; 1821a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 182204124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp), 182304124681SGustavo F. Padovan &cp); 1824a9de9248SMarcel Holtmann } 182517d5c04cSJohan Hedberg } else { 1826a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 182717d5c04cSJohan Hedberg if (conn->type == ACL_LINK) 1828744cf19eSJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 182948264f06SJohan Hedberg conn->dst_type, ev->status); 183017d5c04cSJohan Hedberg } 183145bb4bf0SMarcel Holtmann 1832e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 1833e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 183445bb4bf0SMarcel Holtmann 1835769be974SMarcel Holtmann if (ev->status) { 1836a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1837a9de9248SMarcel Holtmann hci_conn_del(conn); 1838c89b6e6bSMarcel Holtmann } else if (ev->link_type != ACL_LINK) 1839c89b6e6bSMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1840a9de9248SMarcel Holtmann 1841a9de9248SMarcel Holtmann unlock: 18421da177e4SLinus Torvalds hci_dev_unlock(hdev); 1843a9de9248SMarcel Holtmann 1844a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 18451da177e4SLinus Torvalds } 18461da177e4SLinus Torvalds 184720714bfeSFrédéric Dalleau void hci_conn_accept(struct hci_conn *conn, int mask) 184820714bfeSFrédéric Dalleau { 184920714bfeSFrédéric Dalleau struct hci_dev *hdev = conn->hdev; 185020714bfeSFrédéric Dalleau 185120714bfeSFrédéric Dalleau BT_DBG("conn %p", conn); 185220714bfeSFrédéric Dalleau 185320714bfeSFrédéric Dalleau conn->state = BT_CONFIG; 185420714bfeSFrédéric Dalleau 185520714bfeSFrédéric Dalleau if (!lmp_esco_capable(hdev)) { 185620714bfeSFrédéric Dalleau struct hci_cp_accept_conn_req cp; 185720714bfeSFrédéric Dalleau 185820714bfeSFrédéric Dalleau bacpy(&cp.bdaddr, &conn->dst); 185920714bfeSFrédéric Dalleau 186020714bfeSFrédéric Dalleau if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 186120714bfeSFrédéric Dalleau cp.role = 0x00; /* Become master */ 186220714bfeSFrédéric Dalleau else 186320714bfeSFrédéric Dalleau cp.role = 0x01; /* Remain slave */ 186420714bfeSFrédéric Dalleau 186520714bfeSFrédéric Dalleau hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp); 186620714bfeSFrédéric Dalleau } else /* lmp_esco_capable(hdev)) */ { 186720714bfeSFrédéric Dalleau struct hci_cp_accept_sync_conn_req cp; 186820714bfeSFrédéric Dalleau 186920714bfeSFrédéric Dalleau bacpy(&cp.bdaddr, &conn->dst); 187020714bfeSFrédéric Dalleau cp.pkt_type = cpu_to_le16(conn->pkt_type); 187120714bfeSFrédéric Dalleau 187220714bfeSFrédéric Dalleau cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40); 187320714bfeSFrédéric Dalleau cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40); 187420714bfeSFrédéric Dalleau cp.max_latency = __constant_cpu_to_le16(0xffff); 187520714bfeSFrédéric Dalleau cp.content_format = cpu_to_le16(hdev->voice_setting); 187620714bfeSFrédéric Dalleau cp.retrans_effort = 0xff; 187720714bfeSFrédéric Dalleau 187820714bfeSFrédéric Dalleau hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 187920714bfeSFrédéric Dalleau sizeof(cp), &cp); 188020714bfeSFrédéric Dalleau } 188120714bfeSFrédéric Dalleau } 188220714bfeSFrédéric Dalleau 18836039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 18841da177e4SLinus Torvalds { 1885a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 18861da177e4SLinus Torvalds int mask = hdev->link_mode; 188720714bfeSFrédéric Dalleau __u8 flags = 0; 18881da177e4SLinus Torvalds 18896ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr, 1890807deac2SGustavo Padovan ev->link_type); 18911da177e4SLinus Torvalds 189220714bfeSFrédéric Dalleau mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type, 189320714bfeSFrédéric Dalleau &flags); 18941da177e4SLinus Torvalds 1895138d22efSSzymon Janc if ((mask & HCI_LM_ACCEPT) && 1896138d22efSSzymon Janc !hci_blacklist_lookup(hdev, &ev->bdaddr)) { 18971da177e4SLinus Torvalds /* Connection accepted */ 1898c7bdd502SMarcel Holtmann struct inquiry_entry *ie; 18991da177e4SLinus Torvalds struct hci_conn *conn; 19001da177e4SLinus Torvalds 19011da177e4SLinus Torvalds hci_dev_lock(hdev); 1902b6a0dc82SMarcel Holtmann 1903cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 1904cc11b9c1SAndrei Emeltchenko if (ie) 1905c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 1906c7bdd502SMarcel Holtmann 19078fc9ced3SGustavo Padovan conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, 19088fc9ced3SGustavo Padovan &ev->bdaddr); 19091da177e4SLinus Torvalds if (!conn) { 1910cc11b9c1SAndrei Emeltchenko conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); 1911cc11b9c1SAndrei Emeltchenko if (!conn) { 1912893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 19131da177e4SLinus Torvalds hci_dev_unlock(hdev); 19141da177e4SLinus Torvalds return; 19151da177e4SLinus Torvalds } 19161da177e4SLinus Torvalds } 1917b6a0dc82SMarcel Holtmann 19181da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 1919b6a0dc82SMarcel Holtmann 19201da177e4SLinus Torvalds hci_dev_unlock(hdev); 19211da177e4SLinus Torvalds 192220714bfeSFrédéric Dalleau if (ev->link_type == ACL_LINK || 192320714bfeSFrédéric Dalleau (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) { 1924b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 192520714bfeSFrédéric Dalleau conn->state = BT_CONNECT; 1926b6a0dc82SMarcel Holtmann 19271da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 19281da177e4SLinus Torvalds 19291da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 19301da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 19311da177e4SLinus Torvalds else 19321da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 19331da177e4SLinus Torvalds 193404124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), 193504124681SGustavo F. Padovan &cp); 193620714bfeSFrédéric Dalleau } else if (!(flags & HCI_PROTO_DEFER)) { 1937b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 193820714bfeSFrédéric Dalleau conn->state = BT_CONNECT; 1939b6a0dc82SMarcel Holtmann 1940b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 1941a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1942b6a0dc82SMarcel Holtmann 194382781e63SAndrei Emeltchenko cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40); 194482781e63SAndrei Emeltchenko cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40); 194582781e63SAndrei Emeltchenko cp.max_latency = __constant_cpu_to_le16(0xffff); 1946b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 1947b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 1948b6a0dc82SMarcel Holtmann 1949b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 1950b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 195120714bfeSFrédéric Dalleau } else { 195220714bfeSFrédéric Dalleau conn->state = BT_CONNECT2; 195320714bfeSFrédéric Dalleau hci_proto_connect_cfm(conn, 0); 195420714bfeSFrédéric Dalleau hci_conn_put(conn); 1955b6a0dc82SMarcel Holtmann } 19561da177e4SLinus Torvalds } else { 19571da177e4SLinus Torvalds /* Connection rejected */ 19581da177e4SLinus Torvalds struct hci_cp_reject_conn_req cp; 19591da177e4SLinus Torvalds 19601da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 19619f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_REJ_BAD_ADDR; 1962a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 19631da177e4SLinus Torvalds } 19641da177e4SLinus Torvalds } 19651da177e4SLinus Torvalds 1966f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err) 1967f0d6a0eaSMikel Astiz { 1968f0d6a0eaSMikel Astiz switch (err) { 1969f0d6a0eaSMikel Astiz case HCI_ERROR_CONNECTION_TIMEOUT: 1970f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_TIMEOUT; 1971f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_USER_TERM: 1972f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_LOW_RESOURCES: 1973f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_POWER_OFF: 1974f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_REMOTE; 1975f0d6a0eaSMikel Astiz case HCI_ERROR_LOCAL_HOST_TERM: 1976f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_LOCAL_HOST; 1977f0d6a0eaSMikel Astiz default: 1978f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_UNKNOWN; 1979f0d6a0eaSMikel Astiz } 1980f0d6a0eaSMikel Astiz } 1981f0d6a0eaSMikel Astiz 19826039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 19831da177e4SLinus Torvalds { 1984a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 198504837f64SMarcel Holtmann struct hci_conn *conn; 19861da177e4SLinus Torvalds 19879f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 19881da177e4SLinus Torvalds 19891da177e4SLinus Torvalds hci_dev_lock(hdev); 19901da177e4SLinus Torvalds 199104837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1992f7520543SJohan Hedberg if (!conn) 1993f7520543SJohan Hedberg goto unlock; 1994f7520543SJohan Hedberg 199537d9ef76SJohan Hedberg if (ev->status == 0) 19961da177e4SLinus Torvalds conn->state = BT_CLOSED; 19977d0db0a3SMarcel Holtmann 1998b644ba33SJohan Hedberg if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) && 1999b644ba33SJohan Hedberg (conn->type == ACL_LINK || conn->type == LE_LINK)) { 2000f0d6a0eaSMikel Astiz if (ev->status) { 200188c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 200288c3df13SJohan Hedberg conn->dst_type, ev->status); 2003f0d6a0eaSMikel Astiz } else { 2004f0d6a0eaSMikel Astiz u8 reason = hci_to_mgmt_reason(ev->reason); 2005f0d6a0eaSMikel Astiz 2006afc747a6SJohan Hedberg mgmt_device_disconnected(hdev, &conn->dst, conn->type, 2007f0d6a0eaSMikel Astiz conn->dst_type, reason); 2008f0d6a0eaSMikel Astiz } 200937d9ef76SJohan Hedberg } 2010f7520543SJohan Hedberg 201137d9ef76SJohan Hedberg if (ev->status == 0) { 20126ec5bcadSVishal Agarwal if (conn->type == ACL_LINK && conn->flush_key) 20136ec5bcadSVishal Agarwal hci_remove_link_key(hdev, &conn->dst); 20142950f21aSMarcel Holtmann hci_proto_disconn_cfm(conn, ev->reason); 20151da177e4SLinus Torvalds hci_conn_del(conn); 201637d9ef76SJohan Hedberg } 20171da177e4SLinus Torvalds 2018f7520543SJohan Hedberg unlock: 20191da177e4SLinus Torvalds hci_dev_unlock(hdev); 20201da177e4SLinus Torvalds } 20211da177e4SLinus Torvalds 20226039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2023a9de9248SMarcel Holtmann { 2024a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 2025a9de9248SMarcel Holtmann struct hci_conn *conn; 2026a9de9248SMarcel Holtmann 20279f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2028a9de9248SMarcel Holtmann 2029a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2030a9de9248SMarcel Holtmann 2031a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2032d7556e20SWaldemar Rymarkiewicz if (!conn) 2033d7556e20SWaldemar Rymarkiewicz goto unlock; 2034d7556e20SWaldemar Rymarkiewicz 2035765c2a96SJohan Hedberg if (!ev->status) { 2036aa64a8b5SJohan Hedberg if (!hci_conn_ssp_enabled(conn) && 203751a8efd7SJohan Hedberg test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) { 2038d7556e20SWaldemar Rymarkiewicz BT_INFO("re-auth of legacy device is not possible."); 203919f8def0SWaldemar Rymarkiewicz } else { 2040a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 2041765c2a96SJohan Hedberg conn->sec_level = conn->pending_sec_level; 204219f8def0SWaldemar Rymarkiewicz } 20432a611692SJohan Hedberg } else { 2044bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 2045bab73cb6SJohan Hedberg ev->status); 20462a611692SJohan Hedberg } 2047a9de9248SMarcel Holtmann 204851a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 204951a8efd7SJohan Hedberg clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags); 2050a9de9248SMarcel Holtmann 2051f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 2052aa64a8b5SJohan Hedberg if (!ev->status && hci_conn_ssp_enabled(conn)) { 2053f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 2054f8558555SMarcel Holtmann cp.handle = ev->handle; 2055f8558555SMarcel Holtmann cp.encrypt = 0x01; 2056d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 2057d7556e20SWaldemar Rymarkiewicz &cp); 2058f8558555SMarcel Holtmann } else { 2059f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 2060f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2061f8558555SMarcel Holtmann hci_conn_put(conn); 2062f8558555SMarcel Holtmann } 2063052b30b0SMarcel Holtmann } else { 2064a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 2065a9de9248SMarcel Holtmann 2066052b30b0SMarcel Holtmann hci_conn_hold(conn); 2067052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2068052b30b0SMarcel Holtmann hci_conn_put(conn); 2069052b30b0SMarcel Holtmann } 2070052b30b0SMarcel Holtmann 207151a8efd7SJohan Hedberg if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) { 2072a9de9248SMarcel Holtmann if (!ev->status) { 2073a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 2074f8558555SMarcel Holtmann cp.handle = ev->handle; 2075f8558555SMarcel Holtmann cp.encrypt = 0x01; 2076d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 2077d7556e20SWaldemar Rymarkiewicz &cp); 2078a9de9248SMarcel Holtmann } else { 207951a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 2080a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 2081a9de9248SMarcel Holtmann } 2082a9de9248SMarcel Holtmann } 2083a9de9248SMarcel Holtmann 2084d7556e20SWaldemar Rymarkiewicz unlock: 2085a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2086a9de9248SMarcel Holtmann } 2087a9de9248SMarcel Holtmann 20886039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 2089a9de9248SMarcel Holtmann { 2090127178d2SJohan Hedberg struct hci_ev_remote_name *ev = (void *) skb->data; 2091127178d2SJohan Hedberg struct hci_conn *conn; 2092127178d2SJohan Hedberg 2093a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2094a9de9248SMarcel Holtmann 2095a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 2096127178d2SJohan Hedberg 2097127178d2SJohan Hedberg hci_dev_lock(hdev); 2098127178d2SJohan Hedberg 2099127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2100b644ba33SJohan Hedberg 2101b644ba33SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 2102b644ba33SJohan Hedberg goto check_auth; 2103b644ba33SJohan Hedberg 2104b644ba33SJohan Hedberg if (ev->status == 0) 2105b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name, 2106b644ba33SJohan Hedberg strnlen(ev->name, HCI_MAX_NAME_LENGTH)); 2107b644ba33SJohan Hedberg else 2108b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0); 2109b644ba33SJohan Hedberg 2110b644ba33SJohan Hedberg check_auth: 211179c6c70cSJohan Hedberg if (!conn) 211279c6c70cSJohan Hedberg goto unlock; 211379c6c70cSJohan Hedberg 211479c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 211579c6c70cSJohan Hedberg goto unlock; 211679c6c70cSJohan Hedberg 211751a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 2118127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 2119127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 2120127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 2121127178d2SJohan Hedberg } 2122127178d2SJohan Hedberg 212379c6c70cSJohan Hedberg unlock: 2124127178d2SJohan Hedberg hci_dev_unlock(hdev); 2125a9de9248SMarcel Holtmann } 2126a9de9248SMarcel Holtmann 21276039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2128a9de9248SMarcel Holtmann { 2129a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 2130a9de9248SMarcel Holtmann struct hci_conn *conn; 2131a9de9248SMarcel Holtmann 21329f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2133a9de9248SMarcel Holtmann 2134a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2135a9de9248SMarcel Holtmann 2136a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2137a9de9248SMarcel Holtmann if (conn) { 2138a9de9248SMarcel Holtmann if (!ev->status) { 2139ae293196SMarcel Holtmann if (ev->encrypt) { 2140ae293196SMarcel Holtmann /* Encryption implies authentication */ 2141ae293196SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 2142a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 2143da85e5e5SVinicius Costa Gomes conn->sec_level = conn->pending_sec_level; 2144ae293196SMarcel Holtmann } else 2145a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_ENCRYPT; 2146a9de9248SMarcel Holtmann } 2147a9de9248SMarcel Holtmann 214851a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 2149a9de9248SMarcel Holtmann 2150a7d7723aSGustavo Padovan if (ev->status && conn->state == BT_CONNECTED) { 2151bed71748SAndre Guedes hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); 2152a7d7723aSGustavo Padovan hci_conn_put(conn); 2153a7d7723aSGustavo Padovan goto unlock; 2154a7d7723aSGustavo Padovan } 2155a7d7723aSGustavo Padovan 2156f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 2157f8558555SMarcel Holtmann if (!ev->status) 2158f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 2159f8558555SMarcel Holtmann 2160f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2161f8558555SMarcel Holtmann hci_conn_put(conn); 2162f8558555SMarcel Holtmann } else 2163a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 2164a9de9248SMarcel Holtmann } 2165a9de9248SMarcel Holtmann 2166a7d7723aSGustavo Padovan unlock: 2167a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2168a9de9248SMarcel Holtmann } 2169a9de9248SMarcel Holtmann 21706039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev, 2171807deac2SGustavo Padovan struct sk_buff *skb) 2172a9de9248SMarcel Holtmann { 2173a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 2174a9de9248SMarcel Holtmann struct hci_conn *conn; 2175a9de9248SMarcel Holtmann 21769f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2177a9de9248SMarcel Holtmann 2178a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2179a9de9248SMarcel Holtmann 2180a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2181a9de9248SMarcel Holtmann if (conn) { 2182a9de9248SMarcel Holtmann if (!ev->status) 2183a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_SECURE; 2184a9de9248SMarcel Holtmann 218551a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 2186a9de9248SMarcel Holtmann 2187a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 2188a9de9248SMarcel Holtmann } 2189a9de9248SMarcel Holtmann 2190a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2191a9de9248SMarcel Holtmann } 2192a9de9248SMarcel Holtmann 21936039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev, 2194807deac2SGustavo Padovan struct sk_buff *skb) 2195a9de9248SMarcel Holtmann { 2196a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 2197a9de9248SMarcel Holtmann struct hci_conn *conn; 2198a9de9248SMarcel Holtmann 21999f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2200a9de9248SMarcel Holtmann 2201a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2202a9de9248SMarcel Holtmann 2203a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2204ccd556feSJohan Hedberg if (!conn) 2205ccd556feSJohan Hedberg goto unlock; 2206ccd556feSJohan Hedberg 2207769be974SMarcel Holtmann if (!ev->status) 2208a9de9248SMarcel Holtmann memcpy(conn->features, ev->features, 8); 2209a9de9248SMarcel Holtmann 2210ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2211ccd556feSJohan Hedberg goto unlock; 2212ccd556feSJohan Hedberg 2213ccd556feSJohan Hedberg if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { 2214769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 2215769be974SMarcel Holtmann cp.handle = ev->handle; 2216769be974SMarcel Holtmann cp.page = 0x01; 2217ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 2218769be974SMarcel Holtmann sizeof(cp), &cp); 2219392599b9SJohan Hedberg goto unlock; 2220392599b9SJohan Hedberg } 2221392599b9SJohan Hedberg 2222671267bfSJohan Hedberg if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { 2223127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2224127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2225127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2226127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2227127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2228b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 2229b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 223008c79b61SJohan Hedberg conn->dst_type, 0, NULL, 0, 2231b644ba33SJohan Hedberg conn->dev_class); 2232392599b9SJohan Hedberg 2233127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2234769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2235769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2236769be974SMarcel Holtmann hci_conn_put(conn); 2237769be974SMarcel Holtmann } 2238769be974SMarcel Holtmann 2239ccd556feSJohan Hedberg unlock: 2240a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2241a9de9248SMarcel Holtmann } 2242a9de9248SMarcel Holtmann 22436039aa73SGustavo Padovan static void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) 22446039aa73SGustavo Padovan { 22456039aa73SGustavo Padovan BT_DBG("%s", hdev->name); 22466039aa73SGustavo Padovan } 22476039aa73SGustavo Padovan 22486039aa73SGustavo Padovan static void hci_qos_setup_complete_evt(struct hci_dev *hdev, 2249807deac2SGustavo Padovan struct sk_buff *skb) 2250a9de9248SMarcel Holtmann { 2251a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2252a9de9248SMarcel Holtmann } 2253a9de9248SMarcel Holtmann 22546039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2255a9de9248SMarcel Holtmann { 2256a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 2257a9de9248SMarcel Holtmann __u16 opcode; 2258a9de9248SMarcel Holtmann 2259a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2260a9de9248SMarcel Holtmann 2261a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2262a9de9248SMarcel Holtmann 2263a9de9248SMarcel Holtmann switch (opcode) { 2264a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 2265a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 2266a9de9248SMarcel Holtmann break; 2267a9de9248SMarcel Holtmann 22684d93483bSAndre Guedes case HCI_OP_PERIODIC_INQ: 22694d93483bSAndre Guedes hci_cc_periodic_inq(hdev, skb); 22704d93483bSAndre Guedes break; 22714d93483bSAndre Guedes 2272a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 2273a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 2274a9de9248SMarcel Holtmann break; 2275a9de9248SMarcel Holtmann 2276a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 2277a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 2278a9de9248SMarcel Holtmann break; 2279a9de9248SMarcel Holtmann 2280a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 2281a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 2282a9de9248SMarcel Holtmann break; 2283a9de9248SMarcel Holtmann 2284e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 2285e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 2286e4e8e37cSMarcel Holtmann break; 2287e4e8e37cSMarcel Holtmann 2288a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 2289a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 2290a9de9248SMarcel Holtmann break; 2291a9de9248SMarcel Holtmann 2292e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 2293e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 2294e4e8e37cSMarcel Holtmann break; 2295e4e8e37cSMarcel Holtmann 2296e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 2297e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 2298e4e8e37cSMarcel Holtmann break; 2299e4e8e37cSMarcel Holtmann 2300a9de9248SMarcel Holtmann case HCI_OP_RESET: 2301a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 2302a9de9248SMarcel Holtmann break; 2303a9de9248SMarcel Holtmann 2304a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 2305a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 2306a9de9248SMarcel Holtmann break; 2307a9de9248SMarcel Holtmann 2308a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 2309a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 2310a9de9248SMarcel Holtmann break; 2311a9de9248SMarcel Holtmann 2312a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 2313a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 2314a9de9248SMarcel Holtmann break; 2315a9de9248SMarcel Holtmann 2316a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 2317a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 2318a9de9248SMarcel Holtmann break; 2319a9de9248SMarcel Holtmann 2320a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 2321a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 2322a9de9248SMarcel Holtmann break; 2323a9de9248SMarcel Holtmann 2324a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 2325a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 2326a9de9248SMarcel Holtmann break; 2327a9de9248SMarcel Holtmann 2328a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 2329a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 2330a9de9248SMarcel Holtmann break; 2331a9de9248SMarcel Holtmann 2332a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 2333a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 2334a9de9248SMarcel Holtmann break; 2335a9de9248SMarcel Holtmann 2336a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 2337a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 2338a9de9248SMarcel Holtmann break; 2339a9de9248SMarcel Holtmann 2340a9de9248SMarcel Holtmann case HCI_OP_HOST_BUFFER_SIZE: 2341a9de9248SMarcel Holtmann hci_cc_host_buffer_size(hdev, skb); 2342a9de9248SMarcel Holtmann break; 2343a9de9248SMarcel Holtmann 2344333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 2345333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 2346333140b5SMarcel Holtmann break; 2347333140b5SMarcel Holtmann 2348a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 2349a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 2350a9de9248SMarcel Holtmann break; 2351a9de9248SMarcel Holtmann 2352a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 2353a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 2354a9de9248SMarcel Holtmann break; 2355a9de9248SMarcel Holtmann 2356a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 2357a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 2358a9de9248SMarcel Holtmann break; 2359a9de9248SMarcel Holtmann 2360971e3a4bSAndre Guedes case HCI_OP_READ_LOCAL_EXT_FEATURES: 2361971e3a4bSAndre Guedes hci_cc_read_local_ext_features(hdev, skb); 2362971e3a4bSAndre Guedes break; 2363971e3a4bSAndre Guedes 2364a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 2365a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 2366a9de9248SMarcel Holtmann break; 2367a9de9248SMarcel Holtmann 2368a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 2369a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 2370a9de9248SMarcel Holtmann break; 2371a9de9248SMarcel Holtmann 2372350ee4cfSAndrei Emeltchenko case HCI_OP_READ_DATA_BLOCK_SIZE: 2373350ee4cfSAndrei Emeltchenko hci_cc_read_data_block_size(hdev, skb); 2374350ee4cfSAndrei Emeltchenko break; 2375350ee4cfSAndrei Emeltchenko 237623bb5763SJohan Hedberg case HCI_OP_WRITE_CA_TIMEOUT: 237723bb5763SJohan Hedberg hci_cc_write_ca_timeout(hdev, skb); 237823bb5763SJohan Hedberg break; 237923bb5763SJohan Hedberg 23801e89cffbSAndrei Emeltchenko case HCI_OP_READ_FLOW_CONTROL_MODE: 23811e89cffbSAndrei Emeltchenko hci_cc_read_flow_control_mode(hdev, skb); 23821e89cffbSAndrei Emeltchenko break; 23831e89cffbSAndrei Emeltchenko 2384928abaa7SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_INFO: 2385928abaa7SAndrei Emeltchenko hci_cc_read_local_amp_info(hdev, skb); 2386928abaa7SAndrei Emeltchenko break; 2387928abaa7SAndrei Emeltchenko 2388903e4541SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_ASSOC: 2389903e4541SAndrei Emeltchenko hci_cc_read_local_amp_assoc(hdev, skb); 2390903e4541SAndrei Emeltchenko break; 2391903e4541SAndrei Emeltchenko 2392b0916ea0SJohan Hedberg case HCI_OP_DELETE_STORED_LINK_KEY: 2393b0916ea0SJohan Hedberg hci_cc_delete_stored_link_key(hdev, skb); 2394b0916ea0SJohan Hedberg break; 2395b0916ea0SJohan Hedberg 2396d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_MASK: 2397d5859e22SJohan Hedberg hci_cc_set_event_mask(hdev, skb); 2398d5859e22SJohan Hedberg break; 2399d5859e22SJohan Hedberg 2400d5859e22SJohan Hedberg case HCI_OP_WRITE_INQUIRY_MODE: 2401d5859e22SJohan Hedberg hci_cc_write_inquiry_mode(hdev, skb); 2402d5859e22SJohan Hedberg break; 2403d5859e22SJohan Hedberg 2404d5859e22SJohan Hedberg case HCI_OP_READ_INQ_RSP_TX_POWER: 2405d5859e22SJohan Hedberg hci_cc_read_inq_rsp_tx_power(hdev, skb); 2406d5859e22SJohan Hedberg break; 2407d5859e22SJohan Hedberg 2408d5859e22SJohan Hedberg case HCI_OP_SET_EVENT_FLT: 2409d5859e22SJohan Hedberg hci_cc_set_event_flt(hdev, skb); 2410d5859e22SJohan Hedberg break; 2411d5859e22SJohan Hedberg 2412980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_REPLY: 2413980e1a53SJohan Hedberg hci_cc_pin_code_reply(hdev, skb); 2414980e1a53SJohan Hedberg break; 2415980e1a53SJohan Hedberg 2416980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_NEG_REPLY: 2417980e1a53SJohan Hedberg hci_cc_pin_code_neg_reply(hdev, skb); 2418980e1a53SJohan Hedberg break; 2419980e1a53SJohan Hedberg 2420c35938b2SSzymon Janc case HCI_OP_READ_LOCAL_OOB_DATA: 2421c35938b2SSzymon Janc hci_cc_read_local_oob_data_reply(hdev, skb); 2422c35938b2SSzymon Janc break; 2423c35938b2SSzymon Janc 24246ed58ec5SVille Tervo case HCI_OP_LE_READ_BUFFER_SIZE: 24256ed58ec5SVille Tervo hci_cc_le_read_buffer_size(hdev, skb); 24266ed58ec5SVille Tervo break; 24276ed58ec5SVille Tervo 242860e77321SJohan Hedberg case HCI_OP_LE_READ_LOCAL_FEATURES: 242960e77321SJohan Hedberg hci_cc_le_read_local_features(hdev, skb); 243060e77321SJohan Hedberg break; 243160e77321SJohan Hedberg 24328fa19098SJohan Hedberg case HCI_OP_LE_READ_ADV_TX_POWER: 24338fa19098SJohan Hedberg hci_cc_le_read_adv_tx_power(hdev, skb); 24348fa19098SJohan Hedberg break; 24358fa19098SJohan Hedberg 2436e36b04c8SJohan Hedberg case HCI_OP_LE_SET_EVENT_MASK: 2437e36b04c8SJohan Hedberg hci_cc_le_set_event_mask(hdev, skb); 2438e36b04c8SJohan Hedberg break; 2439e36b04c8SJohan Hedberg 2440a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_REPLY: 2441a5c29683SJohan Hedberg hci_cc_user_confirm_reply(hdev, skb); 2442a5c29683SJohan Hedberg break; 2443a5c29683SJohan Hedberg 2444a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_NEG_REPLY: 2445a5c29683SJohan Hedberg hci_cc_user_confirm_neg_reply(hdev, skb); 2446a5c29683SJohan Hedberg break; 2447a5c29683SJohan Hedberg 24481143d458SBrian Gix case HCI_OP_USER_PASSKEY_REPLY: 24491143d458SBrian Gix hci_cc_user_passkey_reply(hdev, skb); 24501143d458SBrian Gix break; 24511143d458SBrian Gix 24521143d458SBrian Gix case HCI_OP_USER_PASSKEY_NEG_REPLY: 24531143d458SBrian Gix hci_cc_user_passkey_neg_reply(hdev, skb); 245416cde993SSzymon Janc break; 245507f7fa5dSAndre Guedes 245607f7fa5dSAndre Guedes case HCI_OP_LE_SET_SCAN_PARAM: 245707f7fa5dSAndre Guedes hci_cc_le_set_scan_param(hdev, skb); 24581143d458SBrian Gix break; 24591143d458SBrian Gix 2460c1d5dc4aSJohan Hedberg case HCI_OP_LE_SET_ADV_ENABLE: 2461c1d5dc4aSJohan Hedberg hci_cc_le_set_adv_enable(hdev, skb); 2462c1d5dc4aSJohan Hedberg break; 2463c1d5dc4aSJohan Hedberg 2464eb9d91f5SAndre Guedes case HCI_OP_LE_SET_SCAN_ENABLE: 2465eb9d91f5SAndre Guedes hci_cc_le_set_scan_enable(hdev, skb); 2466eb9d91f5SAndre Guedes break; 2467eb9d91f5SAndre Guedes 2468cf1d081fSJohan Hedberg case HCI_OP_LE_READ_WHITE_LIST_SIZE: 2469cf1d081fSJohan Hedberg hci_cc_le_read_white_list_size(hdev, skb); 2470cf1d081fSJohan Hedberg break; 2471cf1d081fSJohan Hedberg 2472a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_REPLY: 2473a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_reply(hdev, skb); 2474a7a595f6SVinicius Costa Gomes break; 2475a7a595f6SVinicius Costa Gomes 2476a7a595f6SVinicius Costa Gomes case HCI_OP_LE_LTK_NEG_REPLY: 2477a7a595f6SVinicius Costa Gomes hci_cc_le_ltk_neg_reply(hdev, skb); 2478a7a595f6SVinicius Costa Gomes break; 2479a7a595f6SVinicius Costa Gomes 24809b008c04SJohan Hedberg case HCI_OP_LE_READ_SUPPORTED_STATES: 24819b008c04SJohan Hedberg hci_cc_le_read_supported_states(hdev, skb); 24829b008c04SJohan Hedberg break; 24839b008c04SJohan Hedberg 2484f9b49306SAndre Guedes case HCI_OP_WRITE_LE_HOST_SUPPORTED: 2485f9b49306SAndre Guedes hci_cc_write_le_host_supported(hdev, skb); 2486f9b49306SAndre Guedes break; 2487f9b49306SAndre Guedes 248893c284eeSAndrei Emeltchenko case HCI_OP_WRITE_REMOTE_AMP_ASSOC: 248993c284eeSAndrei Emeltchenko hci_cc_write_remote_amp_assoc(hdev, skb); 249093c284eeSAndrei Emeltchenko break; 249193c284eeSAndrei Emeltchenko 2492a9de9248SMarcel Holtmann default: 24939f1db00cSAndrei Emeltchenko BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); 2494a9de9248SMarcel Holtmann break; 2495a9de9248SMarcel Holtmann } 2496a9de9248SMarcel Holtmann 24976bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 24986bd32326SVille Tervo del_timer(&hdev->cmd_timer); 24996bd32326SVille Tervo 2500dbccd791SSzymon Janc if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2501a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2502a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2503c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2504a9de9248SMarcel Holtmann } 2505a9de9248SMarcel Holtmann } 2506a9de9248SMarcel Holtmann 25076039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 2508a9de9248SMarcel Holtmann { 2509a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 2510a9de9248SMarcel Holtmann __u16 opcode; 2511a9de9248SMarcel Holtmann 2512a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2513a9de9248SMarcel Holtmann 2514a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2515a9de9248SMarcel Holtmann 2516a9de9248SMarcel Holtmann switch (opcode) { 2517a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 2518a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 2519a9de9248SMarcel Holtmann break; 2520a9de9248SMarcel Holtmann 2521a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 2522a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 2523a9de9248SMarcel Holtmann break; 2524a9de9248SMarcel Holtmann 2525a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 2526a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 2527a9de9248SMarcel Holtmann break; 2528a9de9248SMarcel Holtmann 2529f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 2530f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 2531f8558555SMarcel Holtmann break; 2532f8558555SMarcel Holtmann 2533f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 2534f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 2535f8558555SMarcel Holtmann break; 2536f8558555SMarcel Holtmann 2537a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 2538a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 2539a9de9248SMarcel Holtmann break; 2540a9de9248SMarcel Holtmann 2541769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 2542769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 2543769be974SMarcel Holtmann break; 2544769be974SMarcel Holtmann 2545769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 2546769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 2547769be974SMarcel Holtmann break; 2548769be974SMarcel Holtmann 2549a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 2550a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 2551a9de9248SMarcel Holtmann break; 2552a9de9248SMarcel Holtmann 2553a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 2554a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 2555a9de9248SMarcel Holtmann break; 2556a9de9248SMarcel Holtmann 2557a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 2558a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 2559a9de9248SMarcel Holtmann break; 2560a9de9248SMarcel Holtmann 25618962ee74SJohan Hedberg case HCI_OP_DISCONNECT: 256288c3df13SJohan Hedberg hci_cs_disconnect(hdev, ev->status); 25638962ee74SJohan Hedberg break; 25648962ee74SJohan Hedberg 2565fcd89c09SVille Tervo case HCI_OP_LE_CREATE_CONN: 2566fcd89c09SVille Tervo hci_cs_le_create_conn(hdev, ev->status); 2567fcd89c09SVille Tervo break; 2568fcd89c09SVille Tervo 2569a7a595f6SVinicius Costa Gomes case HCI_OP_LE_START_ENC: 2570a7a595f6SVinicius Costa Gomes hci_cs_le_start_enc(hdev, ev->status); 2571a7a595f6SVinicius Costa Gomes break; 2572a7a595f6SVinicius Costa Gomes 2573a02226d6SAndrei Emeltchenko case HCI_OP_CREATE_PHY_LINK: 2574a02226d6SAndrei Emeltchenko hci_cs_create_phylink(hdev, ev->status); 2575a02226d6SAndrei Emeltchenko break; 2576a02226d6SAndrei Emeltchenko 25770b26ab9dSAndrei Emeltchenko case HCI_OP_ACCEPT_PHY_LINK: 25780b26ab9dSAndrei Emeltchenko hci_cs_accept_phylink(hdev, ev->status); 25790b26ab9dSAndrei Emeltchenko break; 25800b26ab9dSAndrei Emeltchenko 25815ce66b59SAndrei Emeltchenko case HCI_OP_CREATE_LOGICAL_LINK: 25825ce66b59SAndrei Emeltchenko hci_cs_create_logical_link(hdev, ev->status); 25835ce66b59SAndrei Emeltchenko break; 25845ce66b59SAndrei Emeltchenko 2585a9de9248SMarcel Holtmann default: 25869f1db00cSAndrei Emeltchenko BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); 2587a9de9248SMarcel Holtmann break; 2588a9de9248SMarcel Holtmann } 2589a9de9248SMarcel Holtmann 25906bd32326SVille Tervo if (ev->opcode != HCI_OP_NOP) 25916bd32326SVille Tervo del_timer(&hdev->cmd_timer); 25926bd32326SVille Tervo 259310572132SGustavo F. Padovan if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2594a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2595a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2596c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2597a9de9248SMarcel Holtmann } 2598a9de9248SMarcel Holtmann } 2599a9de9248SMarcel Holtmann 26006039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2601a9de9248SMarcel Holtmann { 2602a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 2603a9de9248SMarcel Holtmann struct hci_conn *conn; 2604a9de9248SMarcel Holtmann 26059f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2606a9de9248SMarcel Holtmann 2607a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2608a9de9248SMarcel Holtmann 2609a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2610a9de9248SMarcel Holtmann if (conn) { 2611a9de9248SMarcel Holtmann if (!ev->status) { 2612a9de9248SMarcel Holtmann if (ev->role) 2613a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_MASTER; 2614a9de9248SMarcel Holtmann else 2615a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_MASTER; 2616a9de9248SMarcel Holtmann } 2617a9de9248SMarcel Holtmann 261851a8efd7SJohan Hedberg clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); 2619a9de9248SMarcel Holtmann 2620a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 2621a9de9248SMarcel Holtmann } 2622a9de9248SMarcel Holtmann 2623a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2624a9de9248SMarcel Holtmann } 2625a9de9248SMarcel Holtmann 26266039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 26271da177e4SLinus Torvalds { 2628a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 26291da177e4SLinus Torvalds int i; 26301da177e4SLinus Torvalds 263132ac5b9bSAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) { 263232ac5b9bSAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 263332ac5b9bSAndrei Emeltchenko return; 263432ac5b9bSAndrei Emeltchenko } 263532ac5b9bSAndrei Emeltchenko 2636c5993de8SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 2637c5993de8SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_pkts_info)) { 26381da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 26391da177e4SLinus Torvalds return; 26401da177e4SLinus Torvalds } 26411da177e4SLinus Torvalds 2642c5993de8SAndrei Emeltchenko BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 2643c5993de8SAndrei Emeltchenko 2644613a1c0cSAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 2645613a1c0cSAndrei Emeltchenko struct hci_comp_pkts_info *info = &ev->handles[i]; 26461da177e4SLinus Torvalds struct hci_conn *conn; 26471da177e4SLinus Torvalds __u16 handle, count; 26481da177e4SLinus Torvalds 2649613a1c0cSAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 2650613a1c0cSAndrei Emeltchenko count = __le16_to_cpu(info->count); 26511da177e4SLinus Torvalds 26521da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 2653f4280918SAndrei Emeltchenko if (!conn) 2654f4280918SAndrei Emeltchenko continue; 2655f4280918SAndrei Emeltchenko 26561da177e4SLinus Torvalds conn->sent -= count; 26571da177e4SLinus Torvalds 2658f4280918SAndrei Emeltchenko switch (conn->type) { 2659f4280918SAndrei Emeltchenko case ACL_LINK: 266070f23020SAndrei Emeltchenko hdev->acl_cnt += count; 266170f23020SAndrei Emeltchenko if (hdev->acl_cnt > hdev->acl_pkts) 26621da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 2663f4280918SAndrei Emeltchenko break; 2664f4280918SAndrei Emeltchenko 2665f4280918SAndrei Emeltchenko case LE_LINK: 26666ed58ec5SVille Tervo if (hdev->le_pkts) { 26676ed58ec5SVille Tervo hdev->le_cnt += count; 26686ed58ec5SVille Tervo if (hdev->le_cnt > hdev->le_pkts) 26696ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 26706ed58ec5SVille Tervo } else { 26716ed58ec5SVille Tervo hdev->acl_cnt += count; 26726ed58ec5SVille Tervo if (hdev->acl_cnt > hdev->acl_pkts) 26736ed58ec5SVille Tervo hdev->acl_cnt = hdev->acl_pkts; 26746ed58ec5SVille Tervo } 2675f4280918SAndrei Emeltchenko break; 2676f4280918SAndrei Emeltchenko 2677f4280918SAndrei Emeltchenko case SCO_LINK: 267870f23020SAndrei Emeltchenko hdev->sco_cnt += count; 267970f23020SAndrei Emeltchenko if (hdev->sco_cnt > hdev->sco_pkts) 26805b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 2681f4280918SAndrei Emeltchenko break; 2682f4280918SAndrei Emeltchenko 2683f4280918SAndrei Emeltchenko default: 2684f4280918SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 2685f4280918SAndrei Emeltchenko break; 26861da177e4SLinus Torvalds } 26871da177e4SLinus Torvalds } 2688a9de9248SMarcel Holtmann 26893eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 26901da177e4SLinus Torvalds } 26911da177e4SLinus Torvalds 269276ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev, 269376ef7cf7SAndrei Emeltchenko __u16 handle) 269476ef7cf7SAndrei Emeltchenko { 269576ef7cf7SAndrei Emeltchenko struct hci_chan *chan; 269676ef7cf7SAndrei Emeltchenko 269776ef7cf7SAndrei Emeltchenko switch (hdev->dev_type) { 269876ef7cf7SAndrei Emeltchenko case HCI_BREDR: 269976ef7cf7SAndrei Emeltchenko return hci_conn_hash_lookup_handle(hdev, handle); 270076ef7cf7SAndrei Emeltchenko case HCI_AMP: 270176ef7cf7SAndrei Emeltchenko chan = hci_chan_lookup_handle(hdev, handle); 270276ef7cf7SAndrei Emeltchenko if (chan) 270376ef7cf7SAndrei Emeltchenko return chan->conn; 270476ef7cf7SAndrei Emeltchenko break; 270576ef7cf7SAndrei Emeltchenko default: 270676ef7cf7SAndrei Emeltchenko BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type); 270776ef7cf7SAndrei Emeltchenko break; 270876ef7cf7SAndrei Emeltchenko } 270976ef7cf7SAndrei Emeltchenko 271076ef7cf7SAndrei Emeltchenko return NULL; 271176ef7cf7SAndrei Emeltchenko } 271276ef7cf7SAndrei Emeltchenko 27136039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb) 271425e89e99SAndrei Emeltchenko { 271525e89e99SAndrei Emeltchenko struct hci_ev_num_comp_blocks *ev = (void *) skb->data; 271625e89e99SAndrei Emeltchenko int i; 271725e89e99SAndrei Emeltchenko 271825e89e99SAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) { 271925e89e99SAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 272025e89e99SAndrei Emeltchenko return; 272125e89e99SAndrei Emeltchenko } 272225e89e99SAndrei Emeltchenko 272325e89e99SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 272425e89e99SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_blocks_info)) { 272525e89e99SAndrei Emeltchenko BT_DBG("%s bad parameters", hdev->name); 272625e89e99SAndrei Emeltchenko return; 272725e89e99SAndrei Emeltchenko } 272825e89e99SAndrei Emeltchenko 272925e89e99SAndrei Emeltchenko BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks, 273025e89e99SAndrei Emeltchenko ev->num_hndl); 273125e89e99SAndrei Emeltchenko 273225e89e99SAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 273325e89e99SAndrei Emeltchenko struct hci_comp_blocks_info *info = &ev->handles[i]; 273476ef7cf7SAndrei Emeltchenko struct hci_conn *conn = NULL; 273525e89e99SAndrei Emeltchenko __u16 handle, block_count; 273625e89e99SAndrei Emeltchenko 273725e89e99SAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 273825e89e99SAndrei Emeltchenko block_count = __le16_to_cpu(info->blocks); 273925e89e99SAndrei Emeltchenko 274076ef7cf7SAndrei Emeltchenko conn = __hci_conn_lookup_handle(hdev, handle); 274125e89e99SAndrei Emeltchenko if (!conn) 274225e89e99SAndrei Emeltchenko continue; 274325e89e99SAndrei Emeltchenko 274425e89e99SAndrei Emeltchenko conn->sent -= block_count; 274525e89e99SAndrei Emeltchenko 274625e89e99SAndrei Emeltchenko switch (conn->type) { 274725e89e99SAndrei Emeltchenko case ACL_LINK: 2748bd1eb66bSAndrei Emeltchenko case AMP_LINK: 274925e89e99SAndrei Emeltchenko hdev->block_cnt += block_count; 275025e89e99SAndrei Emeltchenko if (hdev->block_cnt > hdev->num_blocks) 275125e89e99SAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 275225e89e99SAndrei Emeltchenko break; 275325e89e99SAndrei Emeltchenko 275425e89e99SAndrei Emeltchenko default: 275525e89e99SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 275625e89e99SAndrei Emeltchenko break; 275725e89e99SAndrei Emeltchenko } 275825e89e99SAndrei Emeltchenko } 275925e89e99SAndrei Emeltchenko 276025e89e99SAndrei Emeltchenko queue_work(hdev->workqueue, &hdev->tx_work); 276125e89e99SAndrei Emeltchenko } 276225e89e99SAndrei Emeltchenko 27636039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 27641da177e4SLinus Torvalds { 2765a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 276604837f64SMarcel Holtmann struct hci_conn *conn; 27671da177e4SLinus Torvalds 27689f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 27691da177e4SLinus Torvalds 27701da177e4SLinus Torvalds hci_dev_lock(hdev); 27711da177e4SLinus Torvalds 277204837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 277304837f64SMarcel Holtmann if (conn) { 277404837f64SMarcel Holtmann conn->mode = ev->mode; 277504837f64SMarcel Holtmann conn->interval = __le16_to_cpu(ev->interval); 277604837f64SMarcel Holtmann 27778fc9ced3SGustavo Padovan if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, 27788fc9ced3SGustavo Padovan &conn->flags)) { 277904837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 278058a681efSJohan Hedberg set_bit(HCI_CONN_POWER_SAVE, &conn->flags); 278104837f64SMarcel Holtmann else 278258a681efSJohan Hedberg clear_bit(HCI_CONN_POWER_SAVE, &conn->flags); 278304837f64SMarcel Holtmann } 2784e73439d8SMarcel Holtmann 278551a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 2786e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 278704837f64SMarcel Holtmann } 278804837f64SMarcel Holtmann 278904837f64SMarcel Holtmann hci_dev_unlock(hdev); 279004837f64SMarcel Holtmann } 279104837f64SMarcel Holtmann 27926039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 27931da177e4SLinus Torvalds { 2794052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 2795052b30b0SMarcel Holtmann struct hci_conn *conn; 2796052b30b0SMarcel Holtmann 2797a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2798052b30b0SMarcel Holtmann 2799052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2800052b30b0SMarcel Holtmann 2801052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2802b6f98044SWaldemar Rymarkiewicz if (!conn) 2803b6f98044SWaldemar Rymarkiewicz goto unlock; 2804b6f98044SWaldemar Rymarkiewicz 2805b6f98044SWaldemar Rymarkiewicz if (conn->state == BT_CONNECTED) { 2806052b30b0SMarcel Holtmann hci_conn_hold(conn); 2807052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 2808052b30b0SMarcel Holtmann hci_conn_put(conn); 2809052b30b0SMarcel Holtmann } 2810052b30b0SMarcel Holtmann 2811a8b2d5c2SJohan Hedberg if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags)) 281203b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 281303b555e1SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 2814a8b2d5c2SJohan Hedberg else if (test_bit(HCI_MGMT, &hdev->dev_flags)) { 2815a770bb5aSWaldemar Rymarkiewicz u8 secure; 2816a770bb5aSWaldemar Rymarkiewicz 2817a770bb5aSWaldemar Rymarkiewicz if (conn->pending_sec_level == BT_SECURITY_HIGH) 2818a770bb5aSWaldemar Rymarkiewicz secure = 1; 2819a770bb5aSWaldemar Rymarkiewicz else 2820a770bb5aSWaldemar Rymarkiewicz secure = 0; 2821a770bb5aSWaldemar Rymarkiewicz 2822744cf19eSJohan Hedberg mgmt_pin_code_request(hdev, &ev->bdaddr, secure); 2823a770bb5aSWaldemar Rymarkiewicz } 2824980e1a53SJohan Hedberg 2825b6f98044SWaldemar Rymarkiewicz unlock: 2826052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 28271da177e4SLinus Torvalds } 28281da177e4SLinus Torvalds 28296039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 28301da177e4SLinus Torvalds { 283155ed8ca1SJohan Hedberg struct hci_ev_link_key_req *ev = (void *) skb->data; 283255ed8ca1SJohan Hedberg struct hci_cp_link_key_reply cp; 283355ed8ca1SJohan Hedberg struct hci_conn *conn; 283455ed8ca1SJohan Hedberg struct link_key *key; 283555ed8ca1SJohan Hedberg 2836a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 283755ed8ca1SJohan Hedberg 2838a8b2d5c2SJohan Hedberg if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) 283955ed8ca1SJohan Hedberg return; 284055ed8ca1SJohan Hedberg 284155ed8ca1SJohan Hedberg hci_dev_lock(hdev); 284255ed8ca1SJohan Hedberg 284355ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, &ev->bdaddr); 284455ed8ca1SJohan Hedberg if (!key) { 28456ed93dc6SAndrei Emeltchenko BT_DBG("%s link key not found for %pMR", hdev->name, 28466ed93dc6SAndrei Emeltchenko &ev->bdaddr); 284755ed8ca1SJohan Hedberg goto not_found; 284855ed8ca1SJohan Hedberg } 284955ed8ca1SJohan Hedberg 28506ed93dc6SAndrei Emeltchenko BT_DBG("%s found key type %u for %pMR", hdev->name, key->type, 28516ed93dc6SAndrei Emeltchenko &ev->bdaddr); 285255ed8ca1SJohan Hedberg 2853a8b2d5c2SJohan Hedberg if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) && 2854b6020ba0SWaldemar Rymarkiewicz key->type == HCI_LK_DEBUG_COMBINATION) { 285555ed8ca1SJohan Hedberg BT_DBG("%s ignoring debug key", hdev->name); 285655ed8ca1SJohan Hedberg goto not_found; 285755ed8ca1SJohan Hedberg } 285855ed8ca1SJohan Hedberg 285955ed8ca1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 286060b83f57SWaldemar Rymarkiewicz if (conn) { 286160b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_UNAUTH_COMBINATION && 2862807deac2SGustavo Padovan conn->auth_type != 0xff && (conn->auth_type & 0x01)) { 286355ed8ca1SJohan Hedberg BT_DBG("%s ignoring unauthenticated key", hdev->name); 286455ed8ca1SJohan Hedberg goto not_found; 286555ed8ca1SJohan Hedberg } 286655ed8ca1SJohan Hedberg 286760b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && 286860b83f57SWaldemar Rymarkiewicz conn->pending_sec_level == BT_SECURITY_HIGH) { 28698fc9ced3SGustavo Padovan BT_DBG("%s ignoring key unauthenticated for high security", 28708fc9ced3SGustavo Padovan hdev->name); 287160b83f57SWaldemar Rymarkiewicz goto not_found; 287260b83f57SWaldemar Rymarkiewicz } 287360b83f57SWaldemar Rymarkiewicz 287460b83f57SWaldemar Rymarkiewicz conn->key_type = key->type; 287560b83f57SWaldemar Rymarkiewicz conn->pin_length = key->pin_len; 287660b83f57SWaldemar Rymarkiewicz } 287760b83f57SWaldemar Rymarkiewicz 287855ed8ca1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 28799b3b4460SAndrei Emeltchenko memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE); 288055ed8ca1SJohan Hedberg 288155ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 288255ed8ca1SJohan Hedberg 288355ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 288455ed8ca1SJohan Hedberg 288555ed8ca1SJohan Hedberg return; 288655ed8ca1SJohan Hedberg 288755ed8ca1SJohan Hedberg not_found: 288855ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 288955ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 28901da177e4SLinus Torvalds } 28911da177e4SLinus Torvalds 28926039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 28931da177e4SLinus Torvalds { 2894052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 2895052b30b0SMarcel Holtmann struct hci_conn *conn; 289655ed8ca1SJohan Hedberg u8 pin_len = 0; 2897052b30b0SMarcel Holtmann 2898a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2899052b30b0SMarcel Holtmann 2900052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2901052b30b0SMarcel Holtmann 2902052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2903052b30b0SMarcel Holtmann if (conn) { 2904052b30b0SMarcel Holtmann hci_conn_hold(conn); 2905052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2906980e1a53SJohan Hedberg pin_len = conn->pin_length; 290713d39315SWaldemar Rymarkiewicz 290813d39315SWaldemar Rymarkiewicz if (ev->key_type != HCI_LK_CHANGED_COMBINATION) 290913d39315SWaldemar Rymarkiewicz conn->key_type = ev->key_type; 291013d39315SWaldemar Rymarkiewicz 2911052b30b0SMarcel Holtmann hci_conn_put(conn); 2912052b30b0SMarcel Holtmann } 2913052b30b0SMarcel Holtmann 2914a8b2d5c2SJohan Hedberg if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) 2915d25e28abSJohan Hedberg hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, 291655ed8ca1SJohan Hedberg ev->key_type, pin_len); 291755ed8ca1SJohan Hedberg 2918052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 29191da177e4SLinus Torvalds } 29201da177e4SLinus Torvalds 29216039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 292204837f64SMarcel Holtmann { 2923a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 292404837f64SMarcel Holtmann struct hci_conn *conn; 292504837f64SMarcel Holtmann 29269f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 292704837f64SMarcel Holtmann 292804837f64SMarcel Holtmann hci_dev_lock(hdev); 292904837f64SMarcel Holtmann 293004837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 29311da177e4SLinus Torvalds if (conn && !ev->status) { 29321da177e4SLinus Torvalds struct inquiry_entry *ie; 29331da177e4SLinus Torvalds 2934cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2935cc11b9c1SAndrei Emeltchenko if (ie) { 29361da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 29371da177e4SLinus Torvalds ie->timestamp = jiffies; 29381da177e4SLinus Torvalds } 29391da177e4SLinus Torvalds } 29401da177e4SLinus Torvalds 29411da177e4SLinus Torvalds hci_dev_unlock(hdev); 29421da177e4SLinus Torvalds } 29431da177e4SLinus Torvalds 29446039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2945a8746417SMarcel Holtmann { 2946a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 2947a8746417SMarcel Holtmann struct hci_conn *conn; 2948a8746417SMarcel Holtmann 29499f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2950a8746417SMarcel Holtmann 2951a8746417SMarcel Holtmann hci_dev_lock(hdev); 2952a8746417SMarcel Holtmann 2953a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2954a8746417SMarcel Holtmann if (conn && !ev->status) 2955a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 2956a8746417SMarcel Holtmann 2957a8746417SMarcel Holtmann hci_dev_unlock(hdev); 2958a8746417SMarcel Holtmann } 2959a8746417SMarcel Holtmann 29606039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 296185a1e930SMarcel Holtmann { 2962a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 296385a1e930SMarcel Holtmann struct inquiry_entry *ie; 296485a1e930SMarcel Holtmann 296585a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 296685a1e930SMarcel Holtmann 296785a1e930SMarcel Holtmann hci_dev_lock(hdev); 296885a1e930SMarcel Holtmann 2969cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2970cc11b9c1SAndrei Emeltchenko if (ie) { 297185a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 297285a1e930SMarcel Holtmann ie->timestamp = jiffies; 297385a1e930SMarcel Holtmann } 297485a1e930SMarcel Holtmann 297585a1e930SMarcel Holtmann hci_dev_unlock(hdev); 297685a1e930SMarcel Holtmann } 297785a1e930SMarcel Holtmann 29786039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, 2979807deac2SGustavo Padovan struct sk_buff *skb) 2980a9de9248SMarcel Holtmann { 2981a9de9248SMarcel Holtmann struct inquiry_data data; 2982a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2983388fc8faSJohan Hedberg bool name_known, ssp; 2984a9de9248SMarcel Holtmann 2985a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2986a9de9248SMarcel Holtmann 2987a9de9248SMarcel Holtmann if (!num_rsp) 2988a9de9248SMarcel Holtmann return; 2989a9de9248SMarcel Holtmann 29901519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 29911519cc17SAndre Guedes return; 29921519cc17SAndre Guedes 2993a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2994a9de9248SMarcel Holtmann 2995a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 2996138d22efSSzymon Janc struct inquiry_info_with_rssi_and_pscan_mode *info; 2997138d22efSSzymon Janc info = (void *) (skb->data + 1); 2998a9de9248SMarcel Holtmann 2999e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 3000a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 3001a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 3002a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 3003a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 3004a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 3005a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 3006a9de9248SMarcel Holtmann data.rssi = info->rssi; 300741a96212SMarcel Holtmann data.ssp_mode = 0x00; 30083175405bSJohan Hedberg 30093175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 3010388fc8faSJohan Hedberg false, &ssp); 301148264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 3012e17acd40SJohan Hedberg info->dev_class, info->rssi, 3013388fc8faSJohan Hedberg !name_known, ssp, NULL, 0); 3014a9de9248SMarcel Holtmann } 3015a9de9248SMarcel Holtmann } else { 3016a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 3017a9de9248SMarcel Holtmann 3018e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 3019a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 3020a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 3021a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 3022a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 3023a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 3024a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 3025a9de9248SMarcel Holtmann data.rssi = info->rssi; 302641a96212SMarcel Holtmann data.ssp_mode = 0x00; 30273175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 3028388fc8faSJohan Hedberg false, &ssp); 302948264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 3030e17acd40SJohan Hedberg info->dev_class, info->rssi, 3031388fc8faSJohan Hedberg !name_known, ssp, NULL, 0); 3032a9de9248SMarcel Holtmann } 3033a9de9248SMarcel Holtmann } 3034a9de9248SMarcel Holtmann 3035a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 3036a9de9248SMarcel Holtmann } 3037a9de9248SMarcel Holtmann 30386039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev, 3039807deac2SGustavo Padovan struct sk_buff *skb) 3040a9de9248SMarcel Holtmann { 304141a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 304241a96212SMarcel Holtmann struct hci_conn *conn; 304341a96212SMarcel Holtmann 3044a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 304541a96212SMarcel Holtmann 304641a96212SMarcel Holtmann hci_dev_lock(hdev); 304741a96212SMarcel Holtmann 304841a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3049ccd556feSJohan Hedberg if (!conn) 3050ccd556feSJohan Hedberg goto unlock; 3051ccd556feSJohan Hedberg 3052769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 305341a96212SMarcel Holtmann struct inquiry_entry *ie; 305441a96212SMarcel Holtmann 3055cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 3056cc11b9c1SAndrei Emeltchenko if (ie) 305702b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 305841a96212SMarcel Holtmann 305902b7cc62SJohan Hedberg if (ev->features[0] & LMP_HOST_SSP) 306058a681efSJohan Hedberg set_bit(HCI_CONN_SSP_ENABLED, &conn->flags); 306141a96212SMarcel Holtmann } 306241a96212SMarcel Holtmann 3063ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 3064ccd556feSJohan Hedberg goto unlock; 3065ccd556feSJohan Hedberg 3066671267bfSJohan Hedberg if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { 3067127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 3068127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 3069127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 3070127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 3071127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 3072b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 3073b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 307408c79b61SJohan Hedberg conn->dst_type, 0, NULL, 0, 3075b644ba33SJohan Hedberg conn->dev_class); 3076392599b9SJohan Hedberg 3077127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 3078769be974SMarcel Holtmann conn->state = BT_CONNECTED; 3079769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 3080769be974SMarcel Holtmann hci_conn_put(conn); 3081769be974SMarcel Holtmann } 3082769be974SMarcel Holtmann 3083ccd556feSJohan Hedberg unlock: 308441a96212SMarcel Holtmann hci_dev_unlock(hdev); 3085a9de9248SMarcel Holtmann } 3086a9de9248SMarcel Holtmann 30876039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev, 3088807deac2SGustavo Padovan struct sk_buff *skb) 3089a9de9248SMarcel Holtmann { 3090b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 3091b6a0dc82SMarcel Holtmann struct hci_conn *conn; 3092b6a0dc82SMarcel Holtmann 30939f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 3094b6a0dc82SMarcel Holtmann 3095b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 3096b6a0dc82SMarcel Holtmann 3097b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 30989dc0a3afSMarcel Holtmann if (!conn) { 30999dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 31009dc0a3afSMarcel Holtmann goto unlock; 31019dc0a3afSMarcel Holtmann 31029dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 3103b6a0dc82SMarcel Holtmann if (!conn) 3104b6a0dc82SMarcel Holtmann goto unlock; 3105b6a0dc82SMarcel Holtmann 31069dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 31079dc0a3afSMarcel Holtmann } 31089dc0a3afSMarcel Holtmann 3109732547f9SMarcel Holtmann switch (ev->status) { 3110732547f9SMarcel Holtmann case 0x00: 3111732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 3112732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 3113732547f9SMarcel Holtmann 31149eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 3115732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 3116732547f9SMarcel Holtmann break; 3117732547f9SMarcel Holtmann 3118705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 3119732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 31201038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 3121732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 3122732547f9SMarcel Holtmann if (conn->out && conn->attempt < 2) { 3123efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 3124efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 3125efc7688bSMarcel Holtmann hci_setup_sync(conn, conn->link->handle); 3126efc7688bSMarcel Holtmann goto unlock; 3127efc7688bSMarcel Holtmann } 3128732547f9SMarcel Holtmann /* fall through */ 3129efc7688bSMarcel Holtmann 3130732547f9SMarcel Holtmann default: 3131b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 3132732547f9SMarcel Holtmann break; 3133732547f9SMarcel Holtmann } 3134b6a0dc82SMarcel Holtmann 3135b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 3136b6a0dc82SMarcel Holtmann if (ev->status) 3137b6a0dc82SMarcel Holtmann hci_conn_del(conn); 3138b6a0dc82SMarcel Holtmann 3139b6a0dc82SMarcel Holtmann unlock: 3140b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 3141a9de9248SMarcel Holtmann } 3142a9de9248SMarcel Holtmann 31436039aa73SGustavo Padovan static void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) 3144a9de9248SMarcel Holtmann { 3145a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 3146a9de9248SMarcel Holtmann } 3147a9de9248SMarcel Holtmann 31486039aa73SGustavo Padovan static void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) 314904837f64SMarcel Holtmann { 3150a9de9248SMarcel Holtmann struct hci_ev_sniff_subrate *ev = (void *) skb->data; 315104837f64SMarcel Holtmann 31529f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 315304837f64SMarcel Holtmann } 315404837f64SMarcel Holtmann 31556039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, 3156807deac2SGustavo Padovan struct sk_buff *skb) 3157a9de9248SMarcel Holtmann { 3158a9de9248SMarcel Holtmann struct inquiry_data data; 3159a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 3160a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 31619d939d94SVishal Agarwal size_t eir_len; 3162a9de9248SMarcel Holtmann 3163a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 3164a9de9248SMarcel Holtmann 3165a9de9248SMarcel Holtmann if (!num_rsp) 3166a9de9248SMarcel Holtmann return; 3167a9de9248SMarcel Holtmann 31681519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 31691519cc17SAndre Guedes return; 31701519cc17SAndre Guedes 3171a9de9248SMarcel Holtmann hci_dev_lock(hdev); 3172a9de9248SMarcel Holtmann 3173e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 3174388fc8faSJohan Hedberg bool name_known, ssp; 3175561aafbcSJohan Hedberg 3176a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 3177a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 3178a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 3179a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 3180a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 3181a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 3182a9de9248SMarcel Holtmann data.rssi = info->rssi; 318341a96212SMarcel Holtmann data.ssp_mode = 0x01; 3184561aafbcSJohan Hedberg 3185a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 31864ddb1930SJohan Hedberg name_known = eir_has_data_type(info->data, 31874ddb1930SJohan Hedberg sizeof(info->data), 31884ddb1930SJohan Hedberg EIR_NAME_COMPLETE); 3189561aafbcSJohan Hedberg else 3190561aafbcSJohan Hedberg name_known = true; 3191561aafbcSJohan Hedberg 3192388fc8faSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, name_known, 3193388fc8faSJohan Hedberg &ssp); 31949d939d94SVishal Agarwal eir_len = eir_get_length(info->data, sizeof(info->data)); 319548264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 319604124681SGustavo F. Padovan info->dev_class, info->rssi, !name_known, 31979d939d94SVishal Agarwal ssp, info->data, eir_len); 3198a9de9248SMarcel Holtmann } 3199a9de9248SMarcel Holtmann 3200a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 3201a9de9248SMarcel Holtmann } 3202a9de9248SMarcel Holtmann 32031c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev, 32041c2e0041SJohan Hedberg struct sk_buff *skb) 32051c2e0041SJohan Hedberg { 32061c2e0041SJohan Hedberg struct hci_ev_key_refresh_complete *ev = (void *) skb->data; 32071c2e0041SJohan Hedberg struct hci_conn *conn; 32081c2e0041SJohan Hedberg 32099f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status, 32101c2e0041SJohan Hedberg __le16_to_cpu(ev->handle)); 32111c2e0041SJohan Hedberg 32121c2e0041SJohan Hedberg hci_dev_lock(hdev); 32131c2e0041SJohan Hedberg 32141c2e0041SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 32151c2e0041SJohan Hedberg if (!conn) 32161c2e0041SJohan Hedberg goto unlock; 32171c2e0041SJohan Hedberg 32181c2e0041SJohan Hedberg if (!ev->status) 32191c2e0041SJohan Hedberg conn->sec_level = conn->pending_sec_level; 32201c2e0041SJohan Hedberg 32211c2e0041SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 32221c2e0041SJohan Hedberg 32231c2e0041SJohan Hedberg if (ev->status && conn->state == BT_CONNECTED) { 3224bed71748SAndre Guedes hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); 32251c2e0041SJohan Hedberg hci_conn_put(conn); 32261c2e0041SJohan Hedberg goto unlock; 32271c2e0041SJohan Hedberg } 32281c2e0041SJohan Hedberg 32291c2e0041SJohan Hedberg if (conn->state == BT_CONFIG) { 32301c2e0041SJohan Hedberg if (!ev->status) 32311c2e0041SJohan Hedberg conn->state = BT_CONNECTED; 32321c2e0041SJohan Hedberg 32331c2e0041SJohan Hedberg hci_proto_connect_cfm(conn, ev->status); 32341c2e0041SJohan Hedberg hci_conn_put(conn); 32351c2e0041SJohan Hedberg } else { 32361c2e0041SJohan Hedberg hci_auth_cfm(conn, ev->status); 32371c2e0041SJohan Hedberg 32381c2e0041SJohan Hedberg hci_conn_hold(conn); 32391c2e0041SJohan Hedberg conn->disc_timeout = HCI_DISCONN_TIMEOUT; 32401c2e0041SJohan Hedberg hci_conn_put(conn); 32411c2e0041SJohan Hedberg } 32421c2e0041SJohan Hedberg 32431c2e0041SJohan Hedberg unlock: 32441c2e0041SJohan Hedberg hci_dev_unlock(hdev); 32451c2e0041SJohan Hedberg } 32461c2e0041SJohan Hedberg 32476039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn) 324817fa4b9dSJohan Hedberg { 324917fa4b9dSJohan Hedberg /* If remote requests dedicated bonding follow that lead */ 325017fa4b9dSJohan Hedberg if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) { 325117fa4b9dSJohan Hedberg /* If both remote and local IO capabilities allow MITM 325217fa4b9dSJohan Hedberg * protection then require it, otherwise don't */ 325317fa4b9dSJohan Hedberg if (conn->remote_cap == 0x03 || conn->io_capability == 0x03) 325417fa4b9dSJohan Hedberg return 0x02; 325517fa4b9dSJohan Hedberg else 325617fa4b9dSJohan Hedberg return 0x03; 325717fa4b9dSJohan Hedberg } 325817fa4b9dSJohan Hedberg 325917fa4b9dSJohan Hedberg /* If remote requests no-bonding follow that lead */ 326017fa4b9dSJohan Hedberg if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01) 326158797bf7SWaldemar Rymarkiewicz return conn->remote_auth | (conn->auth_type & 0x01); 326217fa4b9dSJohan Hedberg 326317fa4b9dSJohan Hedberg return conn->auth_type; 326417fa4b9dSJohan Hedberg } 326517fa4b9dSJohan Hedberg 32666039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 32670493684eSMarcel Holtmann { 32680493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 32690493684eSMarcel Holtmann struct hci_conn *conn; 32700493684eSMarcel Holtmann 32710493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 32720493684eSMarcel Holtmann 32730493684eSMarcel Holtmann hci_dev_lock(hdev); 32740493684eSMarcel Holtmann 32750493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 327603b555e1SJohan Hedberg if (!conn) 327703b555e1SJohan Hedberg goto unlock; 327803b555e1SJohan Hedberg 32790493684eSMarcel Holtmann hci_conn_hold(conn); 32800493684eSMarcel Holtmann 3281a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 328203b555e1SJohan Hedberg goto unlock; 328303b555e1SJohan Hedberg 3284a8b2d5c2SJohan Hedberg if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) || 328503b555e1SJohan Hedberg (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 328617fa4b9dSJohan Hedberg struct hci_cp_io_capability_reply cp; 328717fa4b9dSJohan Hedberg 328817fa4b9dSJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 32897a7f1e7cSHemant Gupta /* Change the IO capability from KeyboardDisplay 32907a7f1e7cSHemant Gupta * to DisplayYesNo as it is not supported by BT spec. */ 32917a7f1e7cSHemant Gupta cp.capability = (conn->io_capability == 0x04) ? 32927a7f1e7cSHemant Gupta 0x01 : conn->io_capability; 32937cbc9bd9SJohan Hedberg conn->auth_type = hci_get_auth_req(conn); 32947cbc9bd9SJohan Hedberg cp.authentication = conn->auth_type; 329517fa4b9dSJohan Hedberg 32968fc9ced3SGustavo Padovan if (hci_find_remote_oob_data(hdev, &conn->dst) && 32978fc9ced3SGustavo Padovan (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags))) 3298ce85ee13SSzymon Janc cp.oob_data = 0x01; 3299ce85ee13SSzymon Janc else 3300ce85ee13SSzymon Janc cp.oob_data = 0x00; 3301ce85ee13SSzymon Janc 330217fa4b9dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, 330317fa4b9dSJohan Hedberg sizeof(cp), &cp); 330403b555e1SJohan Hedberg } else { 330503b555e1SJohan Hedberg struct hci_cp_io_capability_neg_reply cp; 330603b555e1SJohan Hedberg 330703b555e1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 33089f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED; 330903b555e1SJohan Hedberg 331003b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 331103b555e1SJohan Hedberg sizeof(cp), &cp); 331203b555e1SJohan Hedberg } 331303b555e1SJohan Hedberg 331403b555e1SJohan Hedberg unlock: 331503b555e1SJohan Hedberg hci_dev_unlock(hdev); 331603b555e1SJohan Hedberg } 331703b555e1SJohan Hedberg 33186039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 331903b555e1SJohan Hedberg { 332003b555e1SJohan Hedberg struct hci_ev_io_capa_reply *ev = (void *) skb->data; 332103b555e1SJohan Hedberg struct hci_conn *conn; 332203b555e1SJohan Hedberg 332303b555e1SJohan Hedberg BT_DBG("%s", hdev->name); 332403b555e1SJohan Hedberg 332503b555e1SJohan Hedberg hci_dev_lock(hdev); 332603b555e1SJohan Hedberg 332703b555e1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 332803b555e1SJohan Hedberg if (!conn) 332903b555e1SJohan Hedberg goto unlock; 333003b555e1SJohan Hedberg 333103b555e1SJohan Hedberg conn->remote_cap = ev->capability; 333203b555e1SJohan Hedberg conn->remote_auth = ev->authentication; 333358a681efSJohan Hedberg if (ev->oob_data) 333458a681efSJohan Hedberg set_bit(HCI_CONN_REMOTE_OOB, &conn->flags); 333503b555e1SJohan Hedberg 333603b555e1SJohan Hedberg unlock: 33370493684eSMarcel Holtmann hci_dev_unlock(hdev); 33380493684eSMarcel Holtmann } 33390493684eSMarcel Holtmann 33406039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev, 3341a5c29683SJohan Hedberg struct sk_buff *skb) 3342a5c29683SJohan Hedberg { 3343a5c29683SJohan Hedberg struct hci_ev_user_confirm_req *ev = (void *) skb->data; 334455bc1a37SJohan Hedberg int loc_mitm, rem_mitm, confirm_hint = 0; 33457a828908SJohan Hedberg struct hci_conn *conn; 3346a5c29683SJohan Hedberg 3347a5c29683SJohan Hedberg BT_DBG("%s", hdev->name); 3348a5c29683SJohan Hedberg 3349a5c29683SJohan Hedberg hci_dev_lock(hdev); 3350a5c29683SJohan Hedberg 3351a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 33527a828908SJohan Hedberg goto unlock; 33537a828908SJohan Hedberg 33547a828908SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 33557a828908SJohan Hedberg if (!conn) 33567a828908SJohan Hedberg goto unlock; 33577a828908SJohan Hedberg 33587a828908SJohan Hedberg loc_mitm = (conn->auth_type & 0x01); 33597a828908SJohan Hedberg rem_mitm = (conn->remote_auth & 0x01); 33607a828908SJohan Hedberg 33617a828908SJohan Hedberg /* If we require MITM but the remote device can't provide that 33627a828908SJohan Hedberg * (it has NoInputNoOutput) then reject the confirmation 33637a828908SJohan Hedberg * request. The only exception is when we're dedicated bonding 33647a828908SJohan Hedberg * initiators (connect_cfm_cb set) since then we always have the MITM 33657a828908SJohan Hedberg * bit set. */ 33667a828908SJohan Hedberg if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) { 33677a828908SJohan Hedberg BT_DBG("Rejecting request: remote device can't provide MITM"); 33687a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, 33697a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 33707a828908SJohan Hedberg goto unlock; 33717a828908SJohan Hedberg } 33727a828908SJohan Hedberg 33737a828908SJohan Hedberg /* If no side requires MITM protection; auto-accept */ 33747a828908SJohan Hedberg if ((!loc_mitm || conn->remote_cap == 0x03) && 33757a828908SJohan Hedberg (!rem_mitm || conn->io_capability == 0x03)) { 337655bc1a37SJohan Hedberg 337755bc1a37SJohan Hedberg /* If we're not the initiators request authorization to 337855bc1a37SJohan Hedberg * proceed from user space (mgmt_user_confirm with 337955bc1a37SJohan Hedberg * confirm_hint set to 1). */ 338051a8efd7SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 338155bc1a37SJohan Hedberg BT_DBG("Confirming auto-accept as acceptor"); 338255bc1a37SJohan Hedberg confirm_hint = 1; 338355bc1a37SJohan Hedberg goto confirm; 338455bc1a37SJohan Hedberg } 338555bc1a37SJohan Hedberg 33869f61656aSJohan Hedberg BT_DBG("Auto-accept of user confirmation with %ums delay", 33879f61656aSJohan Hedberg hdev->auto_accept_delay); 33889f61656aSJohan Hedberg 33899f61656aSJohan Hedberg if (hdev->auto_accept_delay > 0) { 33909f61656aSJohan Hedberg int delay = msecs_to_jiffies(hdev->auto_accept_delay); 33919f61656aSJohan Hedberg mod_timer(&conn->auto_accept_timer, jiffies + delay); 33929f61656aSJohan Hedberg goto unlock; 33939f61656aSJohan Hedberg } 33949f61656aSJohan Hedberg 33957a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, 33967a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 33977a828908SJohan Hedberg goto unlock; 33987a828908SJohan Hedberg } 33997a828908SJohan Hedberg 340055bc1a37SJohan Hedberg confirm: 3401272d90dfSJohan Hedberg mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey, 340255bc1a37SJohan Hedberg confirm_hint); 3403a5c29683SJohan Hedberg 34047a828908SJohan Hedberg unlock: 3405a5c29683SJohan Hedberg hci_dev_unlock(hdev); 3406a5c29683SJohan Hedberg } 3407a5c29683SJohan Hedberg 34086039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev, 34091143d458SBrian Gix struct sk_buff *skb) 34101143d458SBrian Gix { 34111143d458SBrian Gix struct hci_ev_user_passkey_req *ev = (void *) skb->data; 34121143d458SBrian Gix 34131143d458SBrian Gix BT_DBG("%s", hdev->name); 34141143d458SBrian Gix 3415a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 3416272d90dfSJohan Hedberg mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); 34171143d458SBrian Gix } 34181143d458SBrian Gix 341992a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev, 342092a25256SJohan Hedberg struct sk_buff *skb) 342192a25256SJohan Hedberg { 342292a25256SJohan Hedberg struct hci_ev_user_passkey_notify *ev = (void *) skb->data; 342392a25256SJohan Hedberg struct hci_conn *conn; 342492a25256SJohan Hedberg 342592a25256SJohan Hedberg BT_DBG("%s", hdev->name); 342692a25256SJohan Hedberg 342792a25256SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 342892a25256SJohan Hedberg if (!conn) 342992a25256SJohan Hedberg return; 343092a25256SJohan Hedberg 343192a25256SJohan Hedberg conn->passkey_notify = __le32_to_cpu(ev->passkey); 343292a25256SJohan Hedberg conn->passkey_entered = 0; 343392a25256SJohan Hedberg 343492a25256SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 343592a25256SJohan Hedberg mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, 343692a25256SJohan Hedberg conn->dst_type, conn->passkey_notify, 343792a25256SJohan Hedberg conn->passkey_entered); 343892a25256SJohan Hedberg } 343992a25256SJohan Hedberg 344092a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 344192a25256SJohan Hedberg { 344292a25256SJohan Hedberg struct hci_ev_keypress_notify *ev = (void *) skb->data; 344392a25256SJohan Hedberg struct hci_conn *conn; 344492a25256SJohan Hedberg 344592a25256SJohan Hedberg BT_DBG("%s", hdev->name); 344692a25256SJohan Hedberg 344792a25256SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 344892a25256SJohan Hedberg if (!conn) 344992a25256SJohan Hedberg return; 345092a25256SJohan Hedberg 345192a25256SJohan Hedberg switch (ev->type) { 345292a25256SJohan Hedberg case HCI_KEYPRESS_STARTED: 345392a25256SJohan Hedberg conn->passkey_entered = 0; 345492a25256SJohan Hedberg return; 345592a25256SJohan Hedberg 345692a25256SJohan Hedberg case HCI_KEYPRESS_ENTERED: 345792a25256SJohan Hedberg conn->passkey_entered++; 345892a25256SJohan Hedberg break; 345992a25256SJohan Hedberg 346092a25256SJohan Hedberg case HCI_KEYPRESS_ERASED: 346192a25256SJohan Hedberg conn->passkey_entered--; 346292a25256SJohan Hedberg break; 346392a25256SJohan Hedberg 346492a25256SJohan Hedberg case HCI_KEYPRESS_CLEARED: 346592a25256SJohan Hedberg conn->passkey_entered = 0; 346692a25256SJohan Hedberg break; 346792a25256SJohan Hedberg 346892a25256SJohan Hedberg case HCI_KEYPRESS_COMPLETED: 346992a25256SJohan Hedberg return; 347092a25256SJohan Hedberg } 347192a25256SJohan Hedberg 347292a25256SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 347392a25256SJohan Hedberg mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, 347492a25256SJohan Hedberg conn->dst_type, conn->passkey_notify, 347592a25256SJohan Hedberg conn->passkey_entered); 347692a25256SJohan Hedberg } 347792a25256SJohan Hedberg 34786039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev, 3479807deac2SGustavo Padovan struct sk_buff *skb) 34800493684eSMarcel Holtmann { 34810493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 34820493684eSMarcel Holtmann struct hci_conn *conn; 34830493684eSMarcel Holtmann 34840493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 34850493684eSMarcel Holtmann 34860493684eSMarcel Holtmann hci_dev_lock(hdev); 34870493684eSMarcel Holtmann 34880493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 34892a611692SJohan Hedberg if (!conn) 34902a611692SJohan Hedberg goto unlock; 34912a611692SJohan Hedberg 34922a611692SJohan Hedberg /* To avoid duplicate auth_failed events to user space we check 34932a611692SJohan Hedberg * the HCI_CONN_AUTH_PEND flag which will be set if we 34942a611692SJohan Hedberg * initiated the authentication. A traditional auth_complete 34952a611692SJohan Hedberg * event gets always produced as initiator and is also mapped to 34962a611692SJohan Hedberg * the mgmt_auth_failed event */ 3497fa1bd918SMikel Astiz if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status) 3498bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 3499bab73cb6SJohan Hedberg ev->status); 35002a611692SJohan Hedberg 35010493684eSMarcel Holtmann hci_conn_put(conn); 35020493684eSMarcel Holtmann 35032a611692SJohan Hedberg unlock: 35040493684eSMarcel Holtmann hci_dev_unlock(hdev); 35050493684eSMarcel Holtmann } 35060493684eSMarcel Holtmann 35076039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev, 3508807deac2SGustavo Padovan struct sk_buff *skb) 350941a96212SMarcel Holtmann { 351041a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 351141a96212SMarcel Holtmann struct inquiry_entry *ie; 351241a96212SMarcel Holtmann 351341a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 351441a96212SMarcel Holtmann 351541a96212SMarcel Holtmann hci_dev_lock(hdev); 351641a96212SMarcel Holtmann 3517cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 3518cc11b9c1SAndrei Emeltchenko if (ie) 351902b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 352041a96212SMarcel Holtmann 352141a96212SMarcel Holtmann hci_dev_unlock(hdev); 352241a96212SMarcel Holtmann } 352341a96212SMarcel Holtmann 35246039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev, 35252763eda6SSzymon Janc struct sk_buff *skb) 35262763eda6SSzymon Janc { 35272763eda6SSzymon Janc struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; 35282763eda6SSzymon Janc struct oob_data *data; 35292763eda6SSzymon Janc 35302763eda6SSzymon Janc BT_DBG("%s", hdev->name); 35312763eda6SSzymon Janc 35322763eda6SSzymon Janc hci_dev_lock(hdev); 35332763eda6SSzymon Janc 3534a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 3535e1ba1f15SSzymon Janc goto unlock; 3536e1ba1f15SSzymon Janc 35372763eda6SSzymon Janc data = hci_find_remote_oob_data(hdev, &ev->bdaddr); 35382763eda6SSzymon Janc if (data) { 35392763eda6SSzymon Janc struct hci_cp_remote_oob_data_reply cp; 35402763eda6SSzymon Janc 35412763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 35422763eda6SSzymon Janc memcpy(cp.hash, data->hash, sizeof(cp.hash)); 35432763eda6SSzymon Janc memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); 35442763eda6SSzymon Janc 35452763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), 35462763eda6SSzymon Janc &cp); 35472763eda6SSzymon Janc } else { 35482763eda6SSzymon Janc struct hci_cp_remote_oob_data_neg_reply cp; 35492763eda6SSzymon Janc 35502763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 35512763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), 35522763eda6SSzymon Janc &cp); 35532763eda6SSzymon Janc } 35542763eda6SSzymon Janc 3555e1ba1f15SSzymon Janc unlock: 35562763eda6SSzymon Janc hci_dev_unlock(hdev); 35572763eda6SSzymon Janc } 35582763eda6SSzymon Janc 3559d5e91192SAndrei Emeltchenko static void hci_phy_link_complete_evt(struct hci_dev *hdev, 3560d5e91192SAndrei Emeltchenko struct sk_buff *skb) 3561d5e91192SAndrei Emeltchenko { 3562d5e91192SAndrei Emeltchenko struct hci_ev_phy_link_complete *ev = (void *) skb->data; 3563d5e91192SAndrei Emeltchenko struct hci_conn *hcon, *bredr_hcon; 3564d5e91192SAndrei Emeltchenko 3565d5e91192SAndrei Emeltchenko BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle, 3566d5e91192SAndrei Emeltchenko ev->status); 3567d5e91192SAndrei Emeltchenko 3568d5e91192SAndrei Emeltchenko hci_dev_lock(hdev); 3569d5e91192SAndrei Emeltchenko 3570d5e91192SAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 3571d5e91192SAndrei Emeltchenko if (!hcon) { 3572d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 3573d5e91192SAndrei Emeltchenko return; 3574d5e91192SAndrei Emeltchenko } 3575d5e91192SAndrei Emeltchenko 3576d5e91192SAndrei Emeltchenko if (ev->status) { 3577d5e91192SAndrei Emeltchenko hci_conn_del(hcon); 3578d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 3579d5e91192SAndrei Emeltchenko return; 3580d5e91192SAndrei Emeltchenko } 3581d5e91192SAndrei Emeltchenko 3582d5e91192SAndrei Emeltchenko bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon; 3583d5e91192SAndrei Emeltchenko 3584d5e91192SAndrei Emeltchenko hcon->state = BT_CONNECTED; 3585d5e91192SAndrei Emeltchenko bacpy(&hcon->dst, &bredr_hcon->dst); 3586d5e91192SAndrei Emeltchenko 3587d5e91192SAndrei Emeltchenko hci_conn_hold(hcon); 3588d5e91192SAndrei Emeltchenko hcon->disc_timeout = HCI_DISCONN_TIMEOUT; 3589d5e91192SAndrei Emeltchenko hci_conn_put(hcon); 3590d5e91192SAndrei Emeltchenko 3591d5e91192SAndrei Emeltchenko hci_conn_hold_device(hcon); 3592d5e91192SAndrei Emeltchenko hci_conn_add_sysfs(hcon); 3593d5e91192SAndrei Emeltchenko 3594cf70ff22SAndrei Emeltchenko amp_physical_cfm(bredr_hcon, hcon); 3595cf70ff22SAndrei Emeltchenko 3596d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 3597d5e91192SAndrei Emeltchenko } 3598d5e91192SAndrei Emeltchenko 359927695fb4SAndrei Emeltchenko static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 360027695fb4SAndrei Emeltchenko { 360127695fb4SAndrei Emeltchenko struct hci_ev_logical_link_complete *ev = (void *) skb->data; 360227695fb4SAndrei Emeltchenko struct hci_conn *hcon; 360327695fb4SAndrei Emeltchenko struct hci_chan *hchan; 360427695fb4SAndrei Emeltchenko struct amp_mgr *mgr; 360527695fb4SAndrei Emeltchenko 360627695fb4SAndrei Emeltchenko BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x", 360727695fb4SAndrei Emeltchenko hdev->name, le16_to_cpu(ev->handle), ev->phy_handle, 360827695fb4SAndrei Emeltchenko ev->status); 360927695fb4SAndrei Emeltchenko 361027695fb4SAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 361127695fb4SAndrei Emeltchenko if (!hcon) 361227695fb4SAndrei Emeltchenko return; 361327695fb4SAndrei Emeltchenko 361427695fb4SAndrei Emeltchenko /* Create AMP hchan */ 361527695fb4SAndrei Emeltchenko hchan = hci_chan_create(hcon); 361627695fb4SAndrei Emeltchenko if (!hchan) 361727695fb4SAndrei Emeltchenko return; 361827695fb4SAndrei Emeltchenko 361927695fb4SAndrei Emeltchenko hchan->handle = le16_to_cpu(ev->handle); 362027695fb4SAndrei Emeltchenko 362127695fb4SAndrei Emeltchenko BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan); 362227695fb4SAndrei Emeltchenko 362327695fb4SAndrei Emeltchenko mgr = hcon->amp_mgr; 362427695fb4SAndrei Emeltchenko if (mgr && mgr->bredr_chan) { 362527695fb4SAndrei Emeltchenko struct l2cap_chan *bredr_chan = mgr->bredr_chan; 362627695fb4SAndrei Emeltchenko 362727695fb4SAndrei Emeltchenko l2cap_chan_lock(bredr_chan); 362827695fb4SAndrei Emeltchenko 362927695fb4SAndrei Emeltchenko bredr_chan->conn->mtu = hdev->block_mtu; 363027695fb4SAndrei Emeltchenko l2cap_logical_cfm(bredr_chan, hchan, 0); 363127695fb4SAndrei Emeltchenko hci_conn_hold(hcon); 363227695fb4SAndrei Emeltchenko 363327695fb4SAndrei Emeltchenko l2cap_chan_unlock(bredr_chan); 363427695fb4SAndrei Emeltchenko } 363527695fb4SAndrei Emeltchenko } 363627695fb4SAndrei Emeltchenko 3637606e2a10SAndrei Emeltchenko static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev, 3638606e2a10SAndrei Emeltchenko struct sk_buff *skb) 3639606e2a10SAndrei Emeltchenko { 3640606e2a10SAndrei Emeltchenko struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data; 3641606e2a10SAndrei Emeltchenko struct hci_chan *hchan; 3642606e2a10SAndrei Emeltchenko 3643606e2a10SAndrei Emeltchenko BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name, 3644606e2a10SAndrei Emeltchenko le16_to_cpu(ev->handle), ev->status); 3645606e2a10SAndrei Emeltchenko 3646606e2a10SAndrei Emeltchenko if (ev->status) 3647606e2a10SAndrei Emeltchenko return; 3648606e2a10SAndrei Emeltchenko 3649606e2a10SAndrei Emeltchenko hci_dev_lock(hdev); 3650606e2a10SAndrei Emeltchenko 3651606e2a10SAndrei Emeltchenko hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle)); 3652606e2a10SAndrei Emeltchenko if (!hchan) 3653606e2a10SAndrei Emeltchenko goto unlock; 3654606e2a10SAndrei Emeltchenko 3655606e2a10SAndrei Emeltchenko amp_destroy_logical_link(hchan, ev->reason); 3656606e2a10SAndrei Emeltchenko 3657606e2a10SAndrei Emeltchenko unlock: 3658606e2a10SAndrei Emeltchenko hci_dev_unlock(hdev); 3659606e2a10SAndrei Emeltchenko } 3660606e2a10SAndrei Emeltchenko 36619eef6b3aSAndrei Emeltchenko static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev, 36629eef6b3aSAndrei Emeltchenko struct sk_buff *skb) 36639eef6b3aSAndrei Emeltchenko { 36649eef6b3aSAndrei Emeltchenko struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data; 36659eef6b3aSAndrei Emeltchenko struct hci_conn *hcon; 36669eef6b3aSAndrei Emeltchenko 36679eef6b3aSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 36689eef6b3aSAndrei Emeltchenko 36699eef6b3aSAndrei Emeltchenko if (ev->status) 36709eef6b3aSAndrei Emeltchenko return; 36719eef6b3aSAndrei Emeltchenko 36729eef6b3aSAndrei Emeltchenko hci_dev_lock(hdev); 36739eef6b3aSAndrei Emeltchenko 36749eef6b3aSAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 36759eef6b3aSAndrei Emeltchenko if (hcon) { 36769eef6b3aSAndrei Emeltchenko hcon->state = BT_CLOSED; 36779eef6b3aSAndrei Emeltchenko hci_conn_del(hcon); 36789eef6b3aSAndrei Emeltchenko } 36799eef6b3aSAndrei Emeltchenko 36809eef6b3aSAndrei Emeltchenko hci_dev_unlock(hdev); 36819eef6b3aSAndrei Emeltchenko } 36829eef6b3aSAndrei Emeltchenko 36836039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 3684fcd89c09SVille Tervo { 3685fcd89c09SVille Tervo struct hci_ev_le_conn_complete *ev = (void *) skb->data; 3686fcd89c09SVille Tervo struct hci_conn *conn; 3687fcd89c09SVille Tervo 36889f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 3689fcd89c09SVille Tervo 3690fcd89c09SVille Tervo hci_dev_lock(hdev); 3691fcd89c09SVille Tervo 36924f72b329SAndrzej Kaczmarek conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); 3693b62f328bSVille Tervo if (!conn) { 3694b62f328bSVille Tervo conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); 3695b62f328bSVille Tervo if (!conn) { 3696b62f328bSVille Tervo BT_ERR("No memory for new connection"); 3697230fd16aSAndre Guedes goto unlock; 3698b62f328bSVille Tervo } 369929b7988aSAndre Guedes 370029b7988aSAndre Guedes conn->dst_type = ev->bdaddr_type; 3701b9b343d2SAndre Guedes 3702b9b343d2SAndre Guedes if (ev->role == LE_CONN_ROLE_MASTER) { 3703b9b343d2SAndre Guedes conn->out = true; 3704b9b343d2SAndre Guedes conn->link_mode |= HCI_LM_MASTER; 3705b9b343d2SAndre Guedes } 3706b62f328bSVille Tervo } 3707fcd89c09SVille Tervo 3708cd17decbSAndre Guedes if (ev->status) { 3709cd17decbSAndre Guedes mgmt_connect_failed(hdev, &conn->dst, conn->type, 3710cd17decbSAndre Guedes conn->dst_type, ev->status); 3711cd17decbSAndre Guedes hci_proto_connect_cfm(conn, ev->status); 3712cd17decbSAndre Guedes conn->state = BT_CLOSED; 3713cd17decbSAndre Guedes hci_conn_del(conn); 3714cd17decbSAndre Guedes goto unlock; 3715cd17decbSAndre Guedes } 3716cd17decbSAndre Guedes 3717b644ba33SJohan Hedberg if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 3718b644ba33SJohan Hedberg mgmt_device_connected(hdev, &ev->bdaddr, conn->type, 371995b23582SSzymon Janc conn->dst_type, 0, NULL, 0, NULL); 372083bc71b4SVinicius Costa Gomes 37217b5c0d52SVinicius Costa Gomes conn->sec_level = BT_SECURITY_LOW; 3722fcd89c09SVille Tervo conn->handle = __le16_to_cpu(ev->handle); 3723fcd89c09SVille Tervo conn->state = BT_CONNECTED; 3724fcd89c09SVille Tervo 3725fcd89c09SVille Tervo hci_conn_hold_device(conn); 3726fcd89c09SVille Tervo hci_conn_add_sysfs(conn); 3727fcd89c09SVille Tervo 3728fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 3729fcd89c09SVille Tervo 3730fcd89c09SVille Tervo unlock: 3731fcd89c09SVille Tervo hci_dev_unlock(hdev); 3732fcd89c09SVille Tervo } 3733fcd89c09SVille Tervo 37346039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) 37359aa04c91SAndre Guedes { 3736e95beb41SAndre Guedes u8 num_reports = skb->data[0]; 3737e95beb41SAndre Guedes void *ptr = &skb->data[1]; 37383c9e9195SAndre Guedes s8 rssi; 37399aa04c91SAndre Guedes 3740e95beb41SAndre Guedes while (num_reports--) { 3741e95beb41SAndre Guedes struct hci_ev_le_advertising_info *ev = ptr; 3742e95beb41SAndre Guedes 37433c9e9195SAndre Guedes rssi = ev->data[ev->length]; 37443c9e9195SAndre Guedes mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type, 374504124681SGustavo F. Padovan NULL, rssi, 0, 1, ev->data, ev->length); 37463c9e9195SAndre Guedes 3747e95beb41SAndre Guedes ptr += sizeof(*ev) + ev->length + 1; 37489aa04c91SAndre Guedes } 37499aa04c91SAndre Guedes } 37509aa04c91SAndre Guedes 37516039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 3752a7a595f6SVinicius Costa Gomes { 3753a7a595f6SVinicius Costa Gomes struct hci_ev_le_ltk_req *ev = (void *) skb->data; 3754a7a595f6SVinicius Costa Gomes struct hci_cp_le_ltk_reply cp; 3755bea710feSVinicius Costa Gomes struct hci_cp_le_ltk_neg_reply neg; 3756a7a595f6SVinicius Costa Gomes struct hci_conn *conn; 3757c9839a11SVinicius Costa Gomes struct smp_ltk *ltk; 3758a7a595f6SVinicius Costa Gomes 37599f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle)); 3760a7a595f6SVinicius Costa Gomes 3761a7a595f6SVinicius Costa Gomes hci_dev_lock(hdev); 3762a7a595f6SVinicius Costa Gomes 3763a7a595f6SVinicius Costa Gomes conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3764bea710feSVinicius Costa Gomes if (conn == NULL) 3765bea710feSVinicius Costa Gomes goto not_found; 3766a7a595f6SVinicius Costa Gomes 3767bea710feSVinicius Costa Gomes ltk = hci_find_ltk(hdev, ev->ediv, ev->random); 3768bea710feSVinicius Costa Gomes if (ltk == NULL) 3769bea710feSVinicius Costa Gomes goto not_found; 3770bea710feSVinicius Costa Gomes 3771bea710feSVinicius Costa Gomes memcpy(cp.ltk, ltk->val, sizeof(ltk->val)); 3772a7a595f6SVinicius Costa Gomes cp.handle = cpu_to_le16(conn->handle); 3773c9839a11SVinicius Costa Gomes 3774c9839a11SVinicius Costa Gomes if (ltk->authenticated) 3775c9839a11SVinicius Costa Gomes conn->sec_level = BT_SECURITY_HIGH; 3776a7a595f6SVinicius Costa Gomes 3777a7a595f6SVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); 3778a7a595f6SVinicius Costa Gomes 3779c9839a11SVinicius Costa Gomes if (ltk->type & HCI_SMP_STK) { 3780c9839a11SVinicius Costa Gomes list_del(<k->list); 3781c9839a11SVinicius Costa Gomes kfree(ltk); 3782c9839a11SVinicius Costa Gomes } 3783c9839a11SVinicius Costa Gomes 3784a7a595f6SVinicius Costa Gomes hci_dev_unlock(hdev); 3785bea710feSVinicius Costa Gomes 3786bea710feSVinicius Costa Gomes return; 3787bea710feSVinicius Costa Gomes 3788bea710feSVinicius Costa Gomes not_found: 3789bea710feSVinicius Costa Gomes neg.handle = ev->handle; 3790bea710feSVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg); 3791bea710feSVinicius Costa Gomes hci_dev_unlock(hdev); 3792a7a595f6SVinicius Costa Gomes } 3793a7a595f6SVinicius Costa Gomes 37946039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 3795fcd89c09SVille Tervo { 3796fcd89c09SVille Tervo struct hci_ev_le_meta *le_ev = (void *) skb->data; 3797fcd89c09SVille Tervo 3798fcd89c09SVille Tervo skb_pull(skb, sizeof(*le_ev)); 3799fcd89c09SVille Tervo 3800fcd89c09SVille Tervo switch (le_ev->subevent) { 3801fcd89c09SVille Tervo case HCI_EV_LE_CONN_COMPLETE: 3802fcd89c09SVille Tervo hci_le_conn_complete_evt(hdev, skb); 3803fcd89c09SVille Tervo break; 3804fcd89c09SVille Tervo 38059aa04c91SAndre Guedes case HCI_EV_LE_ADVERTISING_REPORT: 38069aa04c91SAndre Guedes hci_le_adv_report_evt(hdev, skb); 38079aa04c91SAndre Guedes break; 38089aa04c91SAndre Guedes 3809a7a595f6SVinicius Costa Gomes case HCI_EV_LE_LTK_REQ: 3810a7a595f6SVinicius Costa Gomes hci_le_ltk_request_evt(hdev, skb); 3811a7a595f6SVinicius Costa Gomes break; 3812a7a595f6SVinicius Costa Gomes 3813fcd89c09SVille Tervo default: 3814fcd89c09SVille Tervo break; 3815fcd89c09SVille Tervo } 3816fcd89c09SVille Tervo } 3817fcd89c09SVille Tervo 38189495b2eeSAndrei Emeltchenko static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb) 38199495b2eeSAndrei Emeltchenko { 38209495b2eeSAndrei Emeltchenko struct hci_ev_channel_selected *ev = (void *) skb->data; 38219495b2eeSAndrei Emeltchenko struct hci_conn *hcon; 38229495b2eeSAndrei Emeltchenko 38239495b2eeSAndrei Emeltchenko BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle); 38249495b2eeSAndrei Emeltchenko 38259495b2eeSAndrei Emeltchenko skb_pull(skb, sizeof(*ev)); 38269495b2eeSAndrei Emeltchenko 38279495b2eeSAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 38289495b2eeSAndrei Emeltchenko if (!hcon) 38299495b2eeSAndrei Emeltchenko return; 38309495b2eeSAndrei Emeltchenko 38319495b2eeSAndrei Emeltchenko amp_read_loc_assoc_final_data(hdev, hcon); 38329495b2eeSAndrei Emeltchenko } 38339495b2eeSAndrei Emeltchenko 38341da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 38351da177e4SLinus Torvalds { 3836a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 3837a9de9248SMarcel Holtmann __u8 event = hdr->evt; 38381da177e4SLinus Torvalds 38391da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 38401da177e4SLinus Torvalds 3841a9de9248SMarcel Holtmann switch (event) { 38421da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 38431da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 38441da177e4SLinus Torvalds break; 38451da177e4SLinus Torvalds 38461da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 38471da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 38481da177e4SLinus Torvalds break; 38491da177e4SLinus Torvalds 3850a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 3851a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 385221d9e30eSMarcel Holtmann break; 385321d9e30eSMarcel Holtmann 38541da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 38551da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 38561da177e4SLinus Torvalds break; 38571da177e4SLinus Torvalds 38581da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 38591da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 38601da177e4SLinus Torvalds break; 38611da177e4SLinus Torvalds 38621da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 38631da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 38641da177e4SLinus Torvalds break; 38651da177e4SLinus Torvalds 3866a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 3867a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 3868a9de9248SMarcel Holtmann break; 3869a9de9248SMarcel Holtmann 38701da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 38711da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 38721da177e4SLinus Torvalds break; 38731da177e4SLinus Torvalds 3874a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 3875a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 3876a9de9248SMarcel Holtmann break; 3877a9de9248SMarcel Holtmann 3878a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 3879a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 3880a9de9248SMarcel Holtmann break; 3881a9de9248SMarcel Holtmann 3882a9de9248SMarcel Holtmann case HCI_EV_REMOTE_VERSION: 3883a9de9248SMarcel Holtmann hci_remote_version_evt(hdev, skb); 3884a9de9248SMarcel Holtmann break; 3885a9de9248SMarcel Holtmann 3886a9de9248SMarcel Holtmann case HCI_EV_QOS_SETUP_COMPLETE: 3887a9de9248SMarcel Holtmann hci_qos_setup_complete_evt(hdev, skb); 3888a9de9248SMarcel Holtmann break; 3889a9de9248SMarcel Holtmann 3890a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 3891a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 3892a9de9248SMarcel Holtmann break; 3893a9de9248SMarcel Holtmann 3894a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 3895a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 3896a9de9248SMarcel Holtmann break; 3897a9de9248SMarcel Holtmann 3898a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 3899a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 3900a9de9248SMarcel Holtmann break; 3901a9de9248SMarcel Holtmann 3902a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 3903a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 3904a9de9248SMarcel Holtmann break; 3905a9de9248SMarcel Holtmann 3906a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 3907a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 39081da177e4SLinus Torvalds break; 39091da177e4SLinus Torvalds 39101da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 39111da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 39121da177e4SLinus Torvalds break; 39131da177e4SLinus Torvalds 39141da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 39151da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 39161da177e4SLinus Torvalds break; 39171da177e4SLinus Torvalds 39181da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 39191da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 39201da177e4SLinus Torvalds break; 39211da177e4SLinus Torvalds 39221da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 39231da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 39241da177e4SLinus Torvalds break; 39251da177e4SLinus Torvalds 3926a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 3927a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 3928a8746417SMarcel Holtmann break; 3929a8746417SMarcel Holtmann 393085a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 393185a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 393285a1e930SMarcel Holtmann break; 393385a1e930SMarcel Holtmann 3934a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 3935a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 3936a9de9248SMarcel Holtmann break; 3937a9de9248SMarcel Holtmann 3938a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 3939a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 3940a9de9248SMarcel Holtmann break; 3941a9de9248SMarcel Holtmann 3942a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 3943a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 3944a9de9248SMarcel Holtmann break; 3945a9de9248SMarcel Holtmann 3946a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_CHANGED: 3947a9de9248SMarcel Holtmann hci_sync_conn_changed_evt(hdev, skb); 3948a9de9248SMarcel Holtmann break; 3949a9de9248SMarcel Holtmann 395004837f64SMarcel Holtmann case HCI_EV_SNIFF_SUBRATE: 395104837f64SMarcel Holtmann hci_sniff_subrate_evt(hdev, skb); 395204837f64SMarcel Holtmann break; 395304837f64SMarcel Holtmann 3954a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 3955a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 39561da177e4SLinus Torvalds break; 39571da177e4SLinus Torvalds 39581c2e0041SJohan Hedberg case HCI_EV_KEY_REFRESH_COMPLETE: 39591c2e0041SJohan Hedberg hci_key_refresh_complete_evt(hdev, skb); 39601c2e0041SJohan Hedberg break; 39611c2e0041SJohan Hedberg 39620493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 39630493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 39640493684eSMarcel Holtmann break; 39650493684eSMarcel Holtmann 396603b555e1SJohan Hedberg case HCI_EV_IO_CAPA_REPLY: 396703b555e1SJohan Hedberg hci_io_capa_reply_evt(hdev, skb); 396803b555e1SJohan Hedberg break; 396903b555e1SJohan Hedberg 3970a5c29683SJohan Hedberg case HCI_EV_USER_CONFIRM_REQUEST: 3971a5c29683SJohan Hedberg hci_user_confirm_request_evt(hdev, skb); 3972a5c29683SJohan Hedberg break; 3973a5c29683SJohan Hedberg 39741143d458SBrian Gix case HCI_EV_USER_PASSKEY_REQUEST: 39751143d458SBrian Gix hci_user_passkey_request_evt(hdev, skb); 39761143d458SBrian Gix break; 39771143d458SBrian Gix 397892a25256SJohan Hedberg case HCI_EV_USER_PASSKEY_NOTIFY: 397992a25256SJohan Hedberg hci_user_passkey_notify_evt(hdev, skb); 398092a25256SJohan Hedberg break; 398192a25256SJohan Hedberg 398292a25256SJohan Hedberg case HCI_EV_KEYPRESS_NOTIFY: 398392a25256SJohan Hedberg hci_keypress_notify_evt(hdev, skb); 398492a25256SJohan Hedberg break; 398592a25256SJohan Hedberg 39860493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 39870493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 39880493684eSMarcel Holtmann break; 39890493684eSMarcel Holtmann 399041a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 399141a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 399241a96212SMarcel Holtmann break; 399341a96212SMarcel Holtmann 3994fcd89c09SVille Tervo case HCI_EV_LE_META: 3995fcd89c09SVille Tervo hci_le_meta_evt(hdev, skb); 3996fcd89c09SVille Tervo break; 3997fcd89c09SVille Tervo 39989495b2eeSAndrei Emeltchenko case HCI_EV_CHANNEL_SELECTED: 39999495b2eeSAndrei Emeltchenko hci_chan_selected_evt(hdev, skb); 40009495b2eeSAndrei Emeltchenko break; 40019495b2eeSAndrei Emeltchenko 40022763eda6SSzymon Janc case HCI_EV_REMOTE_OOB_DATA_REQUEST: 40032763eda6SSzymon Janc hci_remote_oob_data_request_evt(hdev, skb); 40042763eda6SSzymon Janc break; 40052763eda6SSzymon Janc 4006d5e91192SAndrei Emeltchenko case HCI_EV_PHY_LINK_COMPLETE: 4007d5e91192SAndrei Emeltchenko hci_phy_link_complete_evt(hdev, skb); 4008d5e91192SAndrei Emeltchenko break; 4009d5e91192SAndrei Emeltchenko 401027695fb4SAndrei Emeltchenko case HCI_EV_LOGICAL_LINK_COMPLETE: 401127695fb4SAndrei Emeltchenko hci_loglink_complete_evt(hdev, skb); 401227695fb4SAndrei Emeltchenko break; 401327695fb4SAndrei Emeltchenko 4014606e2a10SAndrei Emeltchenko case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE: 4015606e2a10SAndrei Emeltchenko hci_disconn_loglink_complete_evt(hdev, skb); 4016606e2a10SAndrei Emeltchenko break; 4017606e2a10SAndrei Emeltchenko 40189eef6b3aSAndrei Emeltchenko case HCI_EV_DISCONN_PHY_LINK_COMPLETE: 40199eef6b3aSAndrei Emeltchenko hci_disconn_phylink_complete_evt(hdev, skb); 40209eef6b3aSAndrei Emeltchenko break; 40219eef6b3aSAndrei Emeltchenko 402225e89e99SAndrei Emeltchenko case HCI_EV_NUM_COMP_BLOCKS: 402325e89e99SAndrei Emeltchenko hci_num_comp_blocks_evt(hdev, skb); 402425e89e99SAndrei Emeltchenko break; 402525e89e99SAndrei Emeltchenko 40261da177e4SLinus Torvalds default: 40279f1db00cSAndrei Emeltchenko BT_DBG("%s event 0x%2.2x", hdev->name, event); 40281da177e4SLinus Torvalds break; 40291da177e4SLinus Torvalds } 40301da177e4SLinus Torvalds 40311da177e4SLinus Torvalds kfree_skb(skb); 40321da177e4SLinus Torvalds hdev->stat.evt_rx++; 40331da177e4SLinus Torvalds } 4034