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> 327ef9fbf0SMarcel Holtmann 337024728eSMarcel Holtmann #include "a2mp.h" 347ef9fbf0SMarcel Holtmann #include "amp.h" 351da177e4SLinus Torvalds 361da177e4SLinus Torvalds /* Handle HCI Event packets */ 371da177e4SLinus Torvalds 38a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb) 391da177e4SLinus Torvalds { 40a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 411da177e4SLinus Torvalds 429f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 431da177e4SLinus Torvalds 4482f4785cSAndre Guedes if (status) 45a9de9248SMarcel Holtmann return; 461da177e4SLinus Torvalds 4789352e7dSAndre Guedes clear_bit(HCI_INQUIRY, &hdev->flags); 483e13fa1eSAndre Guedes smp_mb__after_clear_bit(); /* wake_up_bit advises about this barrier */ 493e13fa1eSAndre Guedes wake_up_bit(&hdev->flags, HCI_INQUIRY); 5089352e7dSAndre Guedes 51a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 521da177e4SLinus Torvalds } 536bd57416SMarcel Holtmann 544d93483bSAndre Guedes static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 554d93483bSAndre Guedes { 564d93483bSAndre Guedes __u8 status = *((__u8 *) skb->data); 574d93483bSAndre Guedes 589f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 59ae854a70SAndre Guedes 60ae854a70SAndre Guedes if (status) 61ae854a70SAndre Guedes return; 62ae854a70SAndre Guedes 63ae854a70SAndre Guedes set_bit(HCI_PERIODIC_INQ, &hdev->dev_flags); 644d93483bSAndre Guedes } 654d93483bSAndre Guedes 66a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 671da177e4SLinus Torvalds { 68a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 69a9de9248SMarcel Holtmann 709f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 71a9de9248SMarcel Holtmann 72a9de9248SMarcel Holtmann if (status) 73a9de9248SMarcel Holtmann return; 74a9de9248SMarcel Holtmann 75ae854a70SAndre Guedes clear_bit(HCI_PERIODIC_INQ, &hdev->dev_flags); 76ae854a70SAndre Guedes 77a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 78a9de9248SMarcel Holtmann } 79a9de9248SMarcel Holtmann 80807deac2SGustavo Padovan static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, 81807deac2SGustavo Padovan struct sk_buff *skb) 82a9de9248SMarcel Holtmann { 83a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 84a9de9248SMarcel Holtmann } 85a9de9248SMarcel Holtmann 86a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb) 87a9de9248SMarcel Holtmann { 88a9de9248SMarcel Holtmann struct hci_rp_role_discovery *rp = (void *) skb->data; 891da177e4SLinus Torvalds struct hci_conn *conn; 901da177e4SLinus Torvalds 919f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 921da177e4SLinus Torvalds 93a9de9248SMarcel Holtmann if (rp->status) 94a9de9248SMarcel Holtmann return; 951da177e4SLinus Torvalds 961da177e4SLinus Torvalds hci_dev_lock(hdev); 971da177e4SLinus Torvalds 98a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 991da177e4SLinus Torvalds if (conn) { 100a9de9248SMarcel Holtmann if (rp->role) 1011da177e4SLinus Torvalds conn->link_mode &= ~HCI_LM_MASTER; 1021da177e4SLinus Torvalds else 1031da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 1041da177e4SLinus Torvalds } 1051da177e4SLinus Torvalds 1061da177e4SLinus Torvalds hci_dev_unlock(hdev); 107a9de9248SMarcel Holtmann } 1081da177e4SLinus Torvalds 109e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 110e4e8e37cSMarcel Holtmann { 111e4e8e37cSMarcel Holtmann struct hci_rp_read_link_policy *rp = (void *) skb->data; 112e4e8e37cSMarcel Holtmann struct hci_conn *conn; 113e4e8e37cSMarcel Holtmann 1149f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 115e4e8e37cSMarcel Holtmann 116e4e8e37cSMarcel Holtmann if (rp->status) 117e4e8e37cSMarcel Holtmann return; 118e4e8e37cSMarcel Holtmann 119e4e8e37cSMarcel Holtmann hci_dev_lock(hdev); 120e4e8e37cSMarcel Holtmann 121e4e8e37cSMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 122e4e8e37cSMarcel Holtmann if (conn) 123e4e8e37cSMarcel Holtmann conn->link_policy = __le16_to_cpu(rp->policy); 124e4e8e37cSMarcel Holtmann 125e4e8e37cSMarcel Holtmann hci_dev_unlock(hdev); 126e4e8e37cSMarcel Holtmann } 127e4e8e37cSMarcel Holtmann 128a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 129a9de9248SMarcel Holtmann { 130a9de9248SMarcel Holtmann struct hci_rp_write_link_policy *rp = (void *) skb->data; 131a9de9248SMarcel Holtmann struct hci_conn *conn; 132a9de9248SMarcel Holtmann void *sent; 133a9de9248SMarcel Holtmann 1349f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 135a9de9248SMarcel Holtmann 136a9de9248SMarcel Holtmann if (rp->status) 137a9de9248SMarcel Holtmann return; 138a9de9248SMarcel Holtmann 139a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY); 14004837f64SMarcel Holtmann if (!sent) 141a9de9248SMarcel Holtmann return; 14204837f64SMarcel Holtmann 14304837f64SMarcel Holtmann hci_dev_lock(hdev); 14404837f64SMarcel Holtmann 145a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 146e4e8e37cSMarcel Holtmann if (conn) 14783985319SHarvey Harrison conn->link_policy = get_unaligned_le16(sent + 2); 14804837f64SMarcel Holtmann 14904837f64SMarcel Holtmann hci_dev_unlock(hdev); 1501da177e4SLinus Torvalds } 1511da177e4SLinus Torvalds 152807deac2SGustavo Padovan static void hci_cc_read_def_link_policy(struct hci_dev *hdev, 153807deac2SGustavo Padovan struct sk_buff *skb) 154e4e8e37cSMarcel Holtmann { 155e4e8e37cSMarcel Holtmann struct hci_rp_read_def_link_policy *rp = (void *) skb->data; 156e4e8e37cSMarcel Holtmann 1579f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 158e4e8e37cSMarcel Holtmann 159e4e8e37cSMarcel Holtmann if (rp->status) 160e4e8e37cSMarcel Holtmann return; 161e4e8e37cSMarcel Holtmann 162e4e8e37cSMarcel Holtmann hdev->link_policy = __le16_to_cpu(rp->policy); 163e4e8e37cSMarcel Holtmann } 164e4e8e37cSMarcel Holtmann 165807deac2SGustavo Padovan static void hci_cc_write_def_link_policy(struct hci_dev *hdev, 166807deac2SGustavo Padovan struct sk_buff *skb) 167e4e8e37cSMarcel Holtmann { 168e4e8e37cSMarcel Holtmann __u8 status = *((__u8 *) skb->data); 169e4e8e37cSMarcel Holtmann void *sent; 170e4e8e37cSMarcel Holtmann 1719f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 172e4e8e37cSMarcel Holtmann 173e4e8e37cSMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY); 174e4e8e37cSMarcel Holtmann if (!sent) 175e4e8e37cSMarcel Holtmann return; 176e4e8e37cSMarcel Holtmann 177e4e8e37cSMarcel Holtmann if (!status) 178e4e8e37cSMarcel Holtmann hdev->link_policy = get_unaligned_le16(sent); 179e4e8e37cSMarcel Holtmann } 180e4e8e37cSMarcel Holtmann 181a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) 1821da177e4SLinus Torvalds { 183a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 184a9de9248SMarcel Holtmann 1859f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 186a9de9248SMarcel Holtmann 18710572132SGustavo F. Padovan clear_bit(HCI_RESET, &hdev->flags); 18810572132SGustavo F. Padovan 189a297e97cSJohan Hedberg /* Reset all non-persistent flags */ 1902cc6fb00SJohan Hedberg hdev->dev_flags &= ~HCI_PERSISTENT_MASK; 19169775ff6SAndre Guedes 19269775ff6SAndre Guedes hdev->discovery.state = DISCOVERY_STOPPED; 193bbaf444aSJohan Hedberg hdev->inq_tx_power = HCI_TX_POWER_INVALID; 194bbaf444aSJohan Hedberg hdev->adv_tx_power = HCI_TX_POWER_INVALID; 1953f0f524bSJohan Hedberg 1963f0f524bSJohan Hedberg memset(hdev->adv_data, 0, sizeof(hdev->adv_data)); 1973f0f524bSJohan Hedberg hdev->adv_data_len = 0; 198a9de9248SMarcel Holtmann } 199a9de9248SMarcel Holtmann 200a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) 201a9de9248SMarcel Holtmann { 202a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 2031da177e4SLinus Torvalds void *sent; 2041da177e4SLinus Torvalds 2059f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 2061da177e4SLinus Torvalds 207a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); 2081da177e4SLinus Torvalds if (!sent) 209a9de9248SMarcel Holtmann return; 2101da177e4SLinus Torvalds 21156e5cb86SJohan Hedberg hci_dev_lock(hdev); 21256e5cb86SJohan Hedberg 213f51d5b24SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 214f51d5b24SJohan Hedberg mgmt_set_local_name_complete(hdev, sent, status); 21528cc7bdeSJohan Hedberg else if (!status) 21628cc7bdeSJohan Hedberg memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); 217f51d5b24SJohan Hedberg 21856e5cb86SJohan Hedberg hci_dev_unlock(hdev); 219a9de9248SMarcel Holtmann } 220a9de9248SMarcel Holtmann 221a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) 222a9de9248SMarcel Holtmann { 223a9de9248SMarcel Holtmann struct hci_rp_read_local_name *rp = (void *) skb->data; 224a9de9248SMarcel Holtmann 2259f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 226a9de9248SMarcel Holtmann 227a9de9248SMarcel Holtmann if (rp->status) 228a9de9248SMarcel Holtmann return; 229a9de9248SMarcel Holtmann 230db99b5fcSJohan Hedberg if (test_bit(HCI_SETUP, &hdev->dev_flags)) 2311f6c6378SJohan Hedberg memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); 232a9de9248SMarcel Holtmann } 233a9de9248SMarcel Holtmann 234a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) 235a9de9248SMarcel Holtmann { 236a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 237a9de9248SMarcel Holtmann void *sent; 238a9de9248SMarcel Holtmann 2399f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 240a9de9248SMarcel Holtmann 241a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); 242a9de9248SMarcel Holtmann if (!sent) 243a9de9248SMarcel Holtmann return; 2441da177e4SLinus Torvalds 2451da177e4SLinus Torvalds if (!status) { 246a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 247a9de9248SMarcel Holtmann 2481da177e4SLinus Torvalds if (param == AUTH_ENABLED) 2491da177e4SLinus Torvalds set_bit(HCI_AUTH, &hdev->flags); 2501da177e4SLinus Torvalds else 2511da177e4SLinus Torvalds clear_bit(HCI_AUTH, &hdev->flags); 2521da177e4SLinus Torvalds } 253a9de9248SMarcel Holtmann 25433ef95edSJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 25533ef95edSJohan Hedberg mgmt_auth_enable_complete(hdev, status); 256a9de9248SMarcel Holtmann } 2571da177e4SLinus Torvalds 258a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) 259a9de9248SMarcel Holtmann { 260a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 261a9de9248SMarcel Holtmann void *sent; 262a9de9248SMarcel Holtmann 2639f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 264a9de9248SMarcel Holtmann 265a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); 2661da177e4SLinus Torvalds if (!sent) 267a9de9248SMarcel Holtmann return; 2681da177e4SLinus Torvalds 2691da177e4SLinus Torvalds if (!status) { 270a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 271a9de9248SMarcel Holtmann 2721da177e4SLinus Torvalds if (param) 2731da177e4SLinus Torvalds set_bit(HCI_ENCRYPT, &hdev->flags); 2741da177e4SLinus Torvalds else 2751da177e4SLinus Torvalds clear_bit(HCI_ENCRYPT, &hdev->flags); 2761da177e4SLinus Torvalds } 2771da177e4SLinus Torvalds } 2781da177e4SLinus Torvalds 279a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) 280a9de9248SMarcel Holtmann { 28136f7fc7eSJohan Hedberg __u8 param, status = *((__u8 *) skb->data); 28236f7fc7eSJohan Hedberg int old_pscan, old_iscan; 283a9de9248SMarcel Holtmann void *sent; 2841da177e4SLinus Torvalds 2859f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 286a9de9248SMarcel Holtmann 287a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); 2881da177e4SLinus Torvalds if (!sent) 289a9de9248SMarcel Holtmann return; 2901da177e4SLinus Torvalds 29136f7fc7eSJohan Hedberg param = *((__u8 *) sent); 292a9de9248SMarcel Holtmann 29356e5cb86SJohan Hedberg hci_dev_lock(hdev); 29456e5cb86SJohan Hedberg 295fa1bd918SMikel Astiz if (status) { 296744cf19eSJohan Hedberg mgmt_write_scan_failed(hdev, param, status); 2972d7cee58SJohan Hedberg hdev->discov_timeout = 0; 2982d7cee58SJohan Hedberg goto done; 2992d7cee58SJohan Hedberg } 3002d7cee58SJohan Hedberg 3010663ca2aSJohan Hedberg /* We need to ensure that we set this back on if someone changed 3020663ca2aSJohan Hedberg * the scan mode through a raw HCI socket. 3030663ca2aSJohan Hedberg */ 3040663ca2aSJohan Hedberg set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags); 3050663ca2aSJohan Hedberg 3069fbcbb45SJohan Hedberg old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags); 3079fbcbb45SJohan Hedberg old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags); 308a9de9248SMarcel Holtmann 30973f22f62SJohan Hedberg if (param & SCAN_INQUIRY) { 3101da177e4SLinus Torvalds set_bit(HCI_ISCAN, &hdev->flags); 3119fbcbb45SJohan Hedberg if (!old_iscan) 312744cf19eSJohan Hedberg mgmt_discoverable(hdev, 1); 31316ab91abSJohan Hedberg if (hdev->discov_timeout > 0) { 31416ab91abSJohan Hedberg int to = msecs_to_jiffies(hdev->discov_timeout * 1000); 31516ab91abSJohan Hedberg queue_delayed_work(hdev->workqueue, &hdev->discov_off, 31616ab91abSJohan Hedberg to); 31716ab91abSJohan Hedberg } 3189fbcbb45SJohan Hedberg } else if (old_iscan) 319744cf19eSJohan Hedberg mgmt_discoverable(hdev, 0); 3201da177e4SLinus Torvalds 3219fbcbb45SJohan Hedberg if (param & SCAN_PAGE) { 3221da177e4SLinus Torvalds set_bit(HCI_PSCAN, &hdev->flags); 3239fbcbb45SJohan Hedberg if (!old_pscan) 324744cf19eSJohan Hedberg mgmt_connectable(hdev, 1); 3259fbcbb45SJohan Hedberg } else if (old_pscan) 326744cf19eSJohan Hedberg mgmt_connectable(hdev, 0); 327a9de9248SMarcel Holtmann 32836f7fc7eSJohan Hedberg done: 32956e5cb86SJohan Hedberg hci_dev_unlock(hdev); 3301da177e4SLinus Torvalds } 3311da177e4SLinus Torvalds 332a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 333a9de9248SMarcel Holtmann { 334a9de9248SMarcel Holtmann struct hci_rp_read_class_of_dev *rp = (void *) skb->data; 335a9de9248SMarcel Holtmann 3369f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 337a9de9248SMarcel Holtmann 338a9de9248SMarcel Holtmann if (rp->status) 339a9de9248SMarcel Holtmann return; 340a9de9248SMarcel Holtmann 341a9de9248SMarcel Holtmann memcpy(hdev->dev_class, rp->dev_class, 3); 342a9de9248SMarcel Holtmann 343a9de9248SMarcel Holtmann BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, 344a9de9248SMarcel Holtmann hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); 345a9de9248SMarcel Holtmann } 346a9de9248SMarcel Holtmann 347a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 348a9de9248SMarcel Holtmann { 349a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 350a9de9248SMarcel Holtmann void *sent; 351a9de9248SMarcel Holtmann 3529f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 353a9de9248SMarcel Holtmann 354a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); 355a9de9248SMarcel Holtmann if (!sent) 356a9de9248SMarcel Holtmann return; 357a9de9248SMarcel Holtmann 3587f9a903cSMarcel Holtmann hci_dev_lock(hdev); 3597f9a903cSMarcel Holtmann 3607f9a903cSMarcel Holtmann if (status == 0) 361a9de9248SMarcel Holtmann memcpy(hdev->dev_class, sent, 3); 3627f9a903cSMarcel Holtmann 3637f9a903cSMarcel Holtmann if (test_bit(HCI_MGMT, &hdev->dev_flags)) 3647f9a903cSMarcel Holtmann mgmt_set_class_of_dev_complete(hdev, sent, status); 3657f9a903cSMarcel Holtmann 3667f9a903cSMarcel Holtmann hci_dev_unlock(hdev); 367a9de9248SMarcel Holtmann } 368a9de9248SMarcel Holtmann 369a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 370a9de9248SMarcel Holtmann { 371a9de9248SMarcel Holtmann struct hci_rp_read_voice_setting *rp = (void *) skb->data; 372a9de9248SMarcel Holtmann __u16 setting; 373a9de9248SMarcel Holtmann 3749f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 375a9de9248SMarcel Holtmann 376a9de9248SMarcel Holtmann if (rp->status) 377a9de9248SMarcel Holtmann return; 378a9de9248SMarcel Holtmann 379a9de9248SMarcel Holtmann setting = __le16_to_cpu(rp->voice_setting); 380a9de9248SMarcel Holtmann 381a9de9248SMarcel Holtmann if (hdev->voice_setting == setting) 382a9de9248SMarcel Holtmann return; 383a9de9248SMarcel Holtmann 384a9de9248SMarcel Holtmann hdev->voice_setting = setting; 385a9de9248SMarcel Holtmann 3869f1db00cSAndrei Emeltchenko BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting); 387a9de9248SMarcel Holtmann 3883c54711cSGustavo F. Padovan if (hdev->notify) 389a9de9248SMarcel Holtmann hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 390a9de9248SMarcel Holtmann } 391a9de9248SMarcel Holtmann 3928fc9ced3SGustavo Padovan static void hci_cc_write_voice_setting(struct hci_dev *hdev, 3938fc9ced3SGustavo Padovan struct sk_buff *skb) 394a9de9248SMarcel Holtmann { 395a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 396f383f275SMarcel Holtmann __u16 setting; 397a9de9248SMarcel Holtmann void *sent; 398a9de9248SMarcel Holtmann 3999f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 400a9de9248SMarcel Holtmann 401f383f275SMarcel Holtmann if (status) 402f383f275SMarcel Holtmann return; 403f383f275SMarcel Holtmann 404a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); 405a9de9248SMarcel Holtmann if (!sent) 406a9de9248SMarcel Holtmann return; 407a9de9248SMarcel Holtmann 408f383f275SMarcel Holtmann setting = get_unaligned_le16(sent); 4091da177e4SLinus Torvalds 410f383f275SMarcel Holtmann if (hdev->voice_setting == setting) 411f383f275SMarcel Holtmann return; 412f383f275SMarcel Holtmann 4131da177e4SLinus Torvalds hdev->voice_setting = setting; 4141da177e4SLinus Torvalds 4159f1db00cSAndrei Emeltchenko BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting); 4161da177e4SLinus Torvalds 4173c54711cSGustavo F. Padovan if (hdev->notify) 4181da177e4SLinus Torvalds hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 4191da177e4SLinus Torvalds } 4201da177e4SLinus Torvalds 421333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 422333140b5SMarcel Holtmann { 423333140b5SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 4245ed8eb2fSJohan Hedberg struct hci_cp_write_ssp_mode *sent; 425333140b5SMarcel Holtmann 4269f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 427333140b5SMarcel Holtmann 428333140b5SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); 429333140b5SMarcel Holtmann if (!sent) 430333140b5SMarcel Holtmann return; 431333140b5SMarcel Holtmann 4325ed8eb2fSJohan Hedberg if (!status) { 4335ed8eb2fSJohan Hedberg if (sent->mode) 434cad718edSJohan Hedberg hdev->features[1][0] |= LMP_HOST_SSP; 4355ed8eb2fSJohan Hedberg else 436cad718edSJohan Hedberg hdev->features[1][0] &= ~LMP_HOST_SSP; 4375ed8eb2fSJohan Hedberg } 4385ed8eb2fSJohan Hedberg 439c0ecddc2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 4405ed8eb2fSJohan Hedberg mgmt_ssp_enable_complete(hdev, sent->mode, status); 441c0ecddc2SJohan Hedberg else if (!status) { 4425ed8eb2fSJohan Hedberg if (sent->mode) 44384bde9d6SJohan Hedberg set_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 44484bde9d6SJohan Hedberg else 44584bde9d6SJohan Hedberg clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 446c0ecddc2SJohan Hedberg } 447333140b5SMarcel Holtmann } 448333140b5SMarcel Holtmann 449a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) 450a9de9248SMarcel Holtmann { 451a9de9248SMarcel Holtmann struct hci_rp_read_local_version *rp = (void *) skb->data; 4521143e5a6SMarcel Holtmann 4539f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 4541143e5a6SMarcel Holtmann 455a9de9248SMarcel Holtmann if (rp->status) 45642c6b129SJohan Hedberg return; 4571143e5a6SMarcel Holtmann 458a9de9248SMarcel Holtmann hdev->hci_ver = rp->hci_ver; 459e4e8e37cSMarcel Holtmann hdev->hci_rev = __le16_to_cpu(rp->hci_rev); 460d5859e22SJohan Hedberg hdev->lmp_ver = rp->lmp_ver; 461e4e8e37cSMarcel Holtmann hdev->manufacturer = __le16_to_cpu(rp->manufacturer); 462d5859e22SJohan Hedberg hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); 4631da177e4SLinus Torvalds 4649f1db00cSAndrei Emeltchenko BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name, 465807deac2SGustavo Padovan hdev->manufacturer, hdev->hci_ver, hdev->hci_rev); 466d5859e22SJohan Hedberg } 467d5859e22SJohan Hedberg 4688fc9ced3SGustavo Padovan static void hci_cc_read_local_commands(struct hci_dev *hdev, 4698fc9ced3SGustavo Padovan struct sk_buff *skb) 470a9de9248SMarcel Holtmann { 471a9de9248SMarcel Holtmann struct hci_rp_read_local_commands *rp = (void *) skb->data; 472a9de9248SMarcel Holtmann 4739f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 474a9de9248SMarcel Holtmann 4752177bab5SJohan Hedberg if (!rp->status) 476a9de9248SMarcel Holtmann memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); 477a9de9248SMarcel Holtmann } 478a9de9248SMarcel Holtmann 4798fc9ced3SGustavo Padovan static void hci_cc_read_local_features(struct hci_dev *hdev, 4808fc9ced3SGustavo Padovan struct sk_buff *skb) 481a9de9248SMarcel Holtmann { 482a9de9248SMarcel Holtmann struct hci_rp_read_local_features *rp = (void *) skb->data; 483a9de9248SMarcel Holtmann 4849f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 485a9de9248SMarcel Holtmann 486a9de9248SMarcel Holtmann if (rp->status) 487a9de9248SMarcel Holtmann return; 488a9de9248SMarcel Holtmann 489a9de9248SMarcel Holtmann memcpy(hdev->features, rp->features, 8); 4901da177e4SLinus Torvalds 4911da177e4SLinus Torvalds /* Adjust default settings according to features 4921da177e4SLinus Torvalds * supported by device. */ 493a9de9248SMarcel Holtmann 494cad718edSJohan Hedberg if (hdev->features[0][0] & LMP_3SLOT) 4951da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM3 | HCI_DH3); 4961da177e4SLinus Torvalds 497cad718edSJohan Hedberg if (hdev->features[0][0] & LMP_5SLOT) 4981da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM5 | HCI_DH5); 4991da177e4SLinus Torvalds 500cad718edSJohan Hedberg if (hdev->features[0][1] & LMP_HV2) { 5011da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV2); 5025b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV2); 5035b7f9909SMarcel Holtmann } 5041da177e4SLinus Torvalds 505cad718edSJohan Hedberg if (hdev->features[0][1] & LMP_HV3) { 5061da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV3); 5075b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV3); 5085b7f9909SMarcel Holtmann } 5095b7f9909SMarcel Holtmann 51045db810fSAndre Guedes if (lmp_esco_capable(hdev)) 5115b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV3); 5125b7f9909SMarcel Holtmann 513cad718edSJohan Hedberg if (hdev->features[0][4] & LMP_EV4) 5145b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV4); 5155b7f9909SMarcel Holtmann 516cad718edSJohan Hedberg if (hdev->features[0][4] & LMP_EV5) 5175b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV5); 5181da177e4SLinus Torvalds 519cad718edSJohan Hedberg if (hdev->features[0][5] & LMP_EDR_ESCO_2M) 520efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV3); 521efc7688bSMarcel Holtmann 522cad718edSJohan Hedberg if (hdev->features[0][5] & LMP_EDR_ESCO_3M) 523efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_3EV3); 524efc7688bSMarcel Holtmann 525cad718edSJohan Hedberg if (hdev->features[0][5] & LMP_EDR_3S_ESCO) 526efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); 527efc7688bSMarcel Holtmann 528a9de9248SMarcel Holtmann BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, 529cad718edSJohan Hedberg hdev->features[0][0], hdev->features[0][1], 530cad718edSJohan Hedberg hdev->features[0][2], hdev->features[0][3], 531cad718edSJohan Hedberg hdev->features[0][4], hdev->features[0][5], 532cad718edSJohan Hedberg hdev->features[0][6], hdev->features[0][7]); 5331da177e4SLinus Torvalds } 5341da177e4SLinus Torvalds 535971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev, 536971e3a4bSAndre Guedes struct sk_buff *skb) 537971e3a4bSAndre Guedes { 538971e3a4bSAndre Guedes struct hci_rp_read_local_ext_features *rp = (void *) skb->data; 539971e3a4bSAndre Guedes 5409f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 541971e3a4bSAndre Guedes 542971e3a4bSAndre Guedes if (rp->status) 54342c6b129SJohan Hedberg return; 544971e3a4bSAndre Guedes 545d2c5d77fSJohan Hedberg hdev->max_page = rp->max_page; 546d2c5d77fSJohan Hedberg 547cad718edSJohan Hedberg if (rp->page < HCI_MAX_PAGES) 548cad718edSJohan Hedberg memcpy(hdev->features[rp->page], rp->features, 8); 549971e3a4bSAndre Guedes } 550971e3a4bSAndre Guedes 5511e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, 5521e89cffbSAndrei Emeltchenko struct sk_buff *skb) 5531e89cffbSAndrei Emeltchenko { 5541e89cffbSAndrei Emeltchenko struct hci_rp_read_flow_control_mode *rp = (void *) skb->data; 5551e89cffbSAndrei Emeltchenko 5569f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 5571e89cffbSAndrei Emeltchenko 55842c6b129SJohan Hedberg if (!rp->status) 5591e89cffbSAndrei Emeltchenko hdev->flow_ctl_mode = rp->mode; 5601e89cffbSAndrei Emeltchenko } 5611e89cffbSAndrei Emeltchenko 562a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 563a9de9248SMarcel Holtmann { 564a9de9248SMarcel Holtmann struct hci_rp_read_buffer_size *rp = (void *) skb->data; 565a9de9248SMarcel Holtmann 5669f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 567a9de9248SMarcel Holtmann 568a9de9248SMarcel Holtmann if (rp->status) 569a9de9248SMarcel Holtmann return; 570a9de9248SMarcel Holtmann 571a9de9248SMarcel Holtmann hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); 572a9de9248SMarcel Holtmann hdev->sco_mtu = rp->sco_mtu; 573a9de9248SMarcel Holtmann hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); 574a9de9248SMarcel Holtmann hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); 575da1f5198SMarcel Holtmann 576da1f5198SMarcel Holtmann if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { 577da1f5198SMarcel Holtmann hdev->sco_mtu = 64; 578da1f5198SMarcel Holtmann hdev->sco_pkts = 8; 579da1f5198SMarcel Holtmann } 580da1f5198SMarcel Holtmann 581da1f5198SMarcel Holtmann hdev->acl_cnt = hdev->acl_pkts; 582da1f5198SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 5831da177e4SLinus Torvalds 584807deac2SGustavo Padovan BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu, 585807deac2SGustavo Padovan hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts); 5861da177e4SLinus Torvalds } 5871da177e4SLinus Torvalds 588a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) 589a9de9248SMarcel Holtmann { 590a9de9248SMarcel Holtmann struct hci_rp_read_bd_addr *rp = (void *) skb->data; 5911da177e4SLinus Torvalds 5929f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 593a9de9248SMarcel Holtmann 594a9de9248SMarcel Holtmann if (!rp->status) 595a9de9248SMarcel Holtmann bacpy(&hdev->bdaddr, &rp->bdaddr); 59623bb5763SJohan Hedberg } 59723bb5763SJohan Hedberg 598f332ec66SJohan Hedberg static void hci_cc_read_page_scan_activity(struct hci_dev *hdev, 599f332ec66SJohan Hedberg struct sk_buff *skb) 600f332ec66SJohan Hedberg { 601f332ec66SJohan Hedberg struct hci_rp_read_page_scan_activity *rp = (void *) skb->data; 602f332ec66SJohan Hedberg 603f332ec66SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 604f332ec66SJohan Hedberg 605f332ec66SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags) && !rp->status) { 606f332ec66SJohan Hedberg hdev->page_scan_interval = __le16_to_cpu(rp->interval); 607f332ec66SJohan Hedberg hdev->page_scan_window = __le16_to_cpu(rp->window); 608f332ec66SJohan Hedberg } 609f332ec66SJohan Hedberg } 610f332ec66SJohan Hedberg 6114a3ee763SJohan Hedberg static void hci_cc_write_page_scan_activity(struct hci_dev *hdev, 6124a3ee763SJohan Hedberg struct sk_buff *skb) 6134a3ee763SJohan Hedberg { 6144a3ee763SJohan Hedberg u8 status = *((u8 *) skb->data); 6154a3ee763SJohan Hedberg struct hci_cp_write_page_scan_activity *sent; 6164a3ee763SJohan Hedberg 6174a3ee763SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 6184a3ee763SJohan Hedberg 6194a3ee763SJohan Hedberg if (status) 6204a3ee763SJohan Hedberg return; 6214a3ee763SJohan Hedberg 6224a3ee763SJohan Hedberg sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY); 6234a3ee763SJohan Hedberg if (!sent) 6244a3ee763SJohan Hedberg return; 6254a3ee763SJohan Hedberg 6264a3ee763SJohan Hedberg hdev->page_scan_interval = __le16_to_cpu(sent->interval); 6274a3ee763SJohan Hedberg hdev->page_scan_window = __le16_to_cpu(sent->window); 6284a3ee763SJohan Hedberg } 6294a3ee763SJohan Hedberg 630f332ec66SJohan Hedberg static void hci_cc_read_page_scan_type(struct hci_dev *hdev, 631f332ec66SJohan Hedberg struct sk_buff *skb) 632f332ec66SJohan Hedberg { 633f332ec66SJohan Hedberg struct hci_rp_read_page_scan_type *rp = (void *) skb->data; 634f332ec66SJohan Hedberg 635f332ec66SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 636f332ec66SJohan Hedberg 637f332ec66SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags) && !rp->status) 638f332ec66SJohan Hedberg hdev->page_scan_type = rp->type; 639f332ec66SJohan Hedberg } 640f332ec66SJohan Hedberg 6414a3ee763SJohan Hedberg static void hci_cc_write_page_scan_type(struct hci_dev *hdev, 6424a3ee763SJohan Hedberg struct sk_buff *skb) 6434a3ee763SJohan Hedberg { 6444a3ee763SJohan Hedberg u8 status = *((u8 *) skb->data); 6454a3ee763SJohan Hedberg u8 *type; 6464a3ee763SJohan Hedberg 6474a3ee763SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 6484a3ee763SJohan Hedberg 6494a3ee763SJohan Hedberg if (status) 6504a3ee763SJohan Hedberg return; 6514a3ee763SJohan Hedberg 6524a3ee763SJohan Hedberg type = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE); 6534a3ee763SJohan Hedberg if (type) 6544a3ee763SJohan Hedberg hdev->page_scan_type = *type; 6554a3ee763SJohan Hedberg } 6564a3ee763SJohan Hedberg 657350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev, 658350ee4cfSAndrei Emeltchenko struct sk_buff *skb) 659350ee4cfSAndrei Emeltchenko { 660350ee4cfSAndrei Emeltchenko struct hci_rp_read_data_block_size *rp = (void *) skb->data; 661350ee4cfSAndrei Emeltchenko 6629f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 663350ee4cfSAndrei Emeltchenko 664350ee4cfSAndrei Emeltchenko if (rp->status) 665350ee4cfSAndrei Emeltchenko return; 666350ee4cfSAndrei Emeltchenko 667350ee4cfSAndrei Emeltchenko hdev->block_mtu = __le16_to_cpu(rp->max_acl_len); 668350ee4cfSAndrei Emeltchenko hdev->block_len = __le16_to_cpu(rp->block_len); 669350ee4cfSAndrei Emeltchenko hdev->num_blocks = __le16_to_cpu(rp->num_blocks); 670350ee4cfSAndrei Emeltchenko 671350ee4cfSAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 672350ee4cfSAndrei Emeltchenko 673350ee4cfSAndrei Emeltchenko BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu, 674350ee4cfSAndrei Emeltchenko hdev->block_cnt, hdev->block_len); 675350ee4cfSAndrei Emeltchenko } 676350ee4cfSAndrei Emeltchenko 677928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev, 678928abaa7SAndrei Emeltchenko struct sk_buff *skb) 679928abaa7SAndrei Emeltchenko { 680928abaa7SAndrei Emeltchenko struct hci_rp_read_local_amp_info *rp = (void *) skb->data; 681928abaa7SAndrei Emeltchenko 6829f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 683928abaa7SAndrei Emeltchenko 684928abaa7SAndrei Emeltchenko if (rp->status) 6858e2a0d92SAndrei Emeltchenko goto a2mp_rsp; 686928abaa7SAndrei Emeltchenko 687928abaa7SAndrei Emeltchenko hdev->amp_status = rp->amp_status; 688928abaa7SAndrei Emeltchenko hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); 689928abaa7SAndrei Emeltchenko hdev->amp_max_bw = __le32_to_cpu(rp->max_bw); 690928abaa7SAndrei Emeltchenko hdev->amp_min_latency = __le32_to_cpu(rp->min_latency); 691928abaa7SAndrei Emeltchenko hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu); 692928abaa7SAndrei Emeltchenko hdev->amp_type = rp->amp_type; 693928abaa7SAndrei Emeltchenko hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap); 694928abaa7SAndrei Emeltchenko hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size); 695928abaa7SAndrei Emeltchenko hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); 696928abaa7SAndrei Emeltchenko hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); 697928abaa7SAndrei Emeltchenko 6988e2a0d92SAndrei Emeltchenko a2mp_rsp: 6998e2a0d92SAndrei Emeltchenko a2mp_send_getinfo_rsp(hdev); 700928abaa7SAndrei Emeltchenko } 701928abaa7SAndrei Emeltchenko 702903e4541SAndrei Emeltchenko static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev, 703903e4541SAndrei Emeltchenko struct sk_buff *skb) 704903e4541SAndrei Emeltchenko { 705903e4541SAndrei Emeltchenko struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data; 706903e4541SAndrei Emeltchenko struct amp_assoc *assoc = &hdev->loc_assoc; 707903e4541SAndrei Emeltchenko size_t rem_len, frag_len; 708903e4541SAndrei Emeltchenko 709903e4541SAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 710903e4541SAndrei Emeltchenko 711903e4541SAndrei Emeltchenko if (rp->status) 712903e4541SAndrei Emeltchenko goto a2mp_rsp; 713903e4541SAndrei Emeltchenko 714903e4541SAndrei Emeltchenko frag_len = skb->len - sizeof(*rp); 715903e4541SAndrei Emeltchenko rem_len = __le16_to_cpu(rp->rem_len); 716903e4541SAndrei Emeltchenko 717903e4541SAndrei Emeltchenko if (rem_len > frag_len) { 7182e430be3SAndrei Emeltchenko BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len); 719903e4541SAndrei Emeltchenko 720903e4541SAndrei Emeltchenko memcpy(assoc->data + assoc->offset, rp->frag, frag_len); 721903e4541SAndrei Emeltchenko assoc->offset += frag_len; 722903e4541SAndrei Emeltchenko 723903e4541SAndrei Emeltchenko /* Read other fragments */ 724903e4541SAndrei Emeltchenko amp_read_loc_assoc_frag(hdev, rp->phy_handle); 725903e4541SAndrei Emeltchenko 726903e4541SAndrei Emeltchenko return; 727903e4541SAndrei Emeltchenko } 728903e4541SAndrei Emeltchenko 729903e4541SAndrei Emeltchenko memcpy(assoc->data + assoc->offset, rp->frag, rem_len); 730903e4541SAndrei Emeltchenko assoc->len = assoc->offset + rem_len; 731903e4541SAndrei Emeltchenko assoc->offset = 0; 732903e4541SAndrei Emeltchenko 733903e4541SAndrei Emeltchenko a2mp_rsp: 734903e4541SAndrei Emeltchenko /* Send A2MP Rsp when all fragments are received */ 735903e4541SAndrei Emeltchenko a2mp_send_getampassoc_rsp(hdev, rp->status); 7369495b2eeSAndrei Emeltchenko a2mp_send_create_phy_link_req(hdev, rp->status); 737903e4541SAndrei Emeltchenko } 738903e4541SAndrei Emeltchenko 739d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, 740d5859e22SJohan Hedberg struct sk_buff *skb) 741d5859e22SJohan Hedberg { 74291c4e9b1SMarcel Holtmann struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data; 743d5859e22SJohan Hedberg 7449f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 745d5859e22SJohan Hedberg 74691c4e9b1SMarcel Holtmann if (!rp->status) 74791c4e9b1SMarcel Holtmann hdev->inq_tx_power = rp->tx_power; 748d5859e22SJohan Hedberg } 749d5859e22SJohan Hedberg 750980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) 751980e1a53SJohan Hedberg { 752980e1a53SJohan Hedberg struct hci_rp_pin_code_reply *rp = (void *) skb->data; 753980e1a53SJohan Hedberg struct hci_cp_pin_code_reply *cp; 754980e1a53SJohan Hedberg struct hci_conn *conn; 755980e1a53SJohan Hedberg 7569f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 757980e1a53SJohan Hedberg 75856e5cb86SJohan Hedberg hci_dev_lock(hdev); 75956e5cb86SJohan Hedberg 760a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 761744cf19eSJohan Hedberg mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); 762980e1a53SJohan Hedberg 763fa1bd918SMikel Astiz if (rp->status) 76456e5cb86SJohan Hedberg goto unlock; 765980e1a53SJohan Hedberg 766980e1a53SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); 767980e1a53SJohan Hedberg if (!cp) 76856e5cb86SJohan Hedberg goto unlock; 769980e1a53SJohan Hedberg 770980e1a53SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 771980e1a53SJohan Hedberg if (conn) 772980e1a53SJohan Hedberg conn->pin_length = cp->pin_len; 77356e5cb86SJohan Hedberg 77456e5cb86SJohan Hedberg unlock: 77556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 776980e1a53SJohan Hedberg } 777980e1a53SJohan Hedberg 778980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 779980e1a53SJohan Hedberg { 780980e1a53SJohan Hedberg struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data; 781980e1a53SJohan Hedberg 7829f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 783980e1a53SJohan Hedberg 78456e5cb86SJohan Hedberg hci_dev_lock(hdev); 78556e5cb86SJohan Hedberg 786a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 787744cf19eSJohan Hedberg mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr, 788980e1a53SJohan Hedberg rp->status); 78956e5cb86SJohan Hedberg 79056e5cb86SJohan Hedberg hci_dev_unlock(hdev); 791980e1a53SJohan Hedberg } 79256e5cb86SJohan Hedberg 7936ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, 7946ed58ec5SVille Tervo struct sk_buff *skb) 7956ed58ec5SVille Tervo { 7966ed58ec5SVille Tervo struct hci_rp_le_read_buffer_size *rp = (void *) skb->data; 7976ed58ec5SVille Tervo 7989f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 7996ed58ec5SVille Tervo 8006ed58ec5SVille Tervo if (rp->status) 8016ed58ec5SVille Tervo return; 8026ed58ec5SVille Tervo 8036ed58ec5SVille Tervo hdev->le_mtu = __le16_to_cpu(rp->le_mtu); 8046ed58ec5SVille Tervo hdev->le_pkts = rp->le_max_pkt; 8056ed58ec5SVille Tervo 8066ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 8076ed58ec5SVille Tervo 8086ed58ec5SVille Tervo BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); 8096ed58ec5SVille Tervo } 810980e1a53SJohan Hedberg 81160e77321SJohan Hedberg static void hci_cc_le_read_local_features(struct hci_dev *hdev, 81260e77321SJohan Hedberg struct sk_buff *skb) 81360e77321SJohan Hedberg { 81460e77321SJohan Hedberg struct hci_rp_le_read_local_features *rp = (void *) skb->data; 81560e77321SJohan Hedberg 81660e77321SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 81760e77321SJohan Hedberg 81860e77321SJohan Hedberg if (!rp->status) 81960e77321SJohan Hedberg memcpy(hdev->le_features, rp->features, 8); 82060e77321SJohan Hedberg } 82160e77321SJohan Hedberg 8228fa19098SJohan Hedberg static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, 8238fa19098SJohan Hedberg struct sk_buff *skb) 8248fa19098SJohan Hedberg { 8258fa19098SJohan Hedberg struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data; 8268fa19098SJohan Hedberg 8278fa19098SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 8288fa19098SJohan Hedberg 82904b4edcbSJohan Hedberg if (!rp->status) 8308fa19098SJohan Hedberg hdev->adv_tx_power = rp->tx_power; 8318fa19098SJohan Hedberg } 8328fa19098SJohan Hedberg 833a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) 834a5c29683SJohan Hedberg { 835a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 836a5c29683SJohan Hedberg 8379f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 838a5c29683SJohan Hedberg 83956e5cb86SJohan Hedberg hci_dev_lock(hdev); 84056e5cb86SJohan Hedberg 841a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 84204124681SGustavo F. Padovan mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0, 84304124681SGustavo F. Padovan rp->status); 84456e5cb86SJohan Hedberg 84556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 846a5c29683SJohan Hedberg } 847a5c29683SJohan Hedberg 848a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, 849a5c29683SJohan Hedberg struct sk_buff *skb) 850a5c29683SJohan Hedberg { 851a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 852a5c29683SJohan Hedberg 8539f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 854a5c29683SJohan Hedberg 85556e5cb86SJohan Hedberg hci_dev_lock(hdev); 85656e5cb86SJohan Hedberg 857a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 858744cf19eSJohan Hedberg mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr, 85904124681SGustavo F. Padovan ACL_LINK, 0, rp->status); 86056e5cb86SJohan Hedberg 86156e5cb86SJohan Hedberg hci_dev_unlock(hdev); 862a5c29683SJohan Hedberg } 863a5c29683SJohan Hedberg 8641143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb) 8651143d458SBrian Gix { 8661143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 8671143d458SBrian Gix 8689f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 8691143d458SBrian Gix 8701143d458SBrian Gix hci_dev_lock(hdev); 8711143d458SBrian Gix 872a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 873272d90dfSJohan Hedberg mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 874272d90dfSJohan Hedberg 0, rp->status); 8751143d458SBrian Gix 8761143d458SBrian Gix hci_dev_unlock(hdev); 8771143d458SBrian Gix } 8781143d458SBrian Gix 8791143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, 8801143d458SBrian Gix struct sk_buff *skb) 8811143d458SBrian Gix { 8821143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 8831143d458SBrian Gix 8849f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 8851143d458SBrian Gix 8861143d458SBrian Gix hci_dev_lock(hdev); 8871143d458SBrian Gix 888a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 8891143d458SBrian Gix mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr, 89004124681SGustavo F. Padovan ACL_LINK, 0, rp->status); 8911143d458SBrian Gix 8921143d458SBrian Gix hci_dev_unlock(hdev); 8931143d458SBrian Gix } 8941143d458SBrian Gix 895c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, 896c35938b2SSzymon Janc struct sk_buff *skb) 897c35938b2SSzymon Janc { 898c35938b2SSzymon Janc struct hci_rp_read_local_oob_data *rp = (void *) skb->data; 899c35938b2SSzymon Janc 9009f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 901c35938b2SSzymon Janc 90256e5cb86SJohan Hedberg hci_dev_lock(hdev); 903744cf19eSJohan Hedberg mgmt_read_local_oob_data_reply_complete(hdev, rp->hash, 904c35938b2SSzymon Janc rp->randomizer, rp->status); 90556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 906c35938b2SSzymon Janc } 907c35938b2SSzymon Janc 908c1d5dc4aSJohan Hedberg static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb) 909c1d5dc4aSJohan Hedberg { 910c1d5dc4aSJohan Hedberg __u8 *sent, status = *((__u8 *) skb->data); 911c1d5dc4aSJohan Hedberg 912c1d5dc4aSJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 913c1d5dc4aSJohan Hedberg 914c1d5dc4aSJohan Hedberg sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE); 915c1d5dc4aSJohan Hedberg if (!sent) 916c1d5dc4aSJohan Hedberg return; 917c1d5dc4aSJohan Hedberg 918c1d5dc4aSJohan Hedberg hci_dev_lock(hdev); 919c1d5dc4aSJohan Hedberg 920c1d5dc4aSJohan Hedberg if (!status) { 921c1d5dc4aSJohan Hedberg if (*sent) 922f3d3444aSJohan Hedberg set_bit(HCI_ADVERTISING, &hdev->dev_flags); 923c1d5dc4aSJohan Hedberg else 924f3d3444aSJohan Hedberg clear_bit(HCI_ADVERTISING, &hdev->dev_flags); 925c1d5dc4aSJohan Hedberg } 926c1d5dc4aSJohan Hedberg 92704b4edcbSJohan Hedberg if (!test_bit(HCI_INIT, &hdev->flags)) { 92804b4edcbSJohan Hedberg struct hci_request req; 929c1d5dc4aSJohan Hedberg 93004b4edcbSJohan Hedberg hci_req_init(&req, hdev); 93104b4edcbSJohan Hedberg hci_update_ad(&req); 93204b4edcbSJohan Hedberg hci_req_run(&req, NULL); 93304b4edcbSJohan Hedberg } 93404b4edcbSJohan Hedberg 93504b4edcbSJohan Hedberg hci_dev_unlock(hdev); 936c1d5dc4aSJohan Hedberg } 937c1d5dc4aSJohan Hedberg 938eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, 939eb9d91f5SAndre Guedes struct sk_buff *skb) 940eb9d91f5SAndre Guedes { 941eb9d91f5SAndre Guedes struct hci_cp_le_set_scan_enable *cp; 942eb9d91f5SAndre Guedes __u8 status = *((__u8 *) skb->data); 943eb9d91f5SAndre Guedes 9449f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 945eb9d91f5SAndre Guedes 946eb9d91f5SAndre Guedes cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE); 947eb9d91f5SAndre Guedes if (!cp) 948eb9d91f5SAndre Guedes return; 949eb9d91f5SAndre Guedes 950fef5234aSAndre Guedes if (status) 9517ba8b4beSAndre Guedes return; 9527ba8b4beSAndre Guedes 9533fd319b8SAndre Guedes switch (cp->enable) { 9543fd319b8SAndre Guedes case LE_SCAN_ENABLE: 955d23264a8SAndre Guedes set_bit(HCI_LE_SCAN, &hdev->dev_flags); 95668a8aea4SAndrei Emeltchenko break; 95768a8aea4SAndrei Emeltchenko 95876a388beSAndre Guedes case LE_SCAN_DISABLE: 959d23264a8SAndre Guedes clear_bit(HCI_LE_SCAN, &hdev->dev_flags); 96068a8aea4SAndrei Emeltchenko break; 96168a8aea4SAndrei Emeltchenko 96268a8aea4SAndrei Emeltchenko default: 96368a8aea4SAndrei Emeltchenko BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable); 96468a8aea4SAndrei Emeltchenko break; 96535815085SAndre Guedes } 966eb9d91f5SAndre Guedes } 967eb9d91f5SAndre Guedes 968cf1d081fSJohan Hedberg static void hci_cc_le_read_white_list_size(struct hci_dev *hdev, 969cf1d081fSJohan Hedberg struct sk_buff *skb) 970cf1d081fSJohan Hedberg { 971cf1d081fSJohan Hedberg struct hci_rp_le_read_white_list_size *rp = (void *) skb->data; 972cf1d081fSJohan Hedberg 973cf1d081fSJohan Hedberg BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size); 974cf1d081fSJohan Hedberg 975cf1d081fSJohan Hedberg if (!rp->status) 976cf1d081fSJohan Hedberg hdev->le_white_list_size = rp->size; 977cf1d081fSJohan Hedberg } 978cf1d081fSJohan Hedberg 9799b008c04SJohan Hedberg static void hci_cc_le_read_supported_states(struct hci_dev *hdev, 9809b008c04SJohan Hedberg struct sk_buff *skb) 9819b008c04SJohan Hedberg { 9829b008c04SJohan Hedberg struct hci_rp_le_read_supported_states *rp = (void *) skb->data; 9839b008c04SJohan Hedberg 9849b008c04SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 9859b008c04SJohan Hedberg 9869b008c04SJohan Hedberg if (!rp->status) 9879b008c04SJohan Hedberg memcpy(hdev->le_states, rp->le_states, 8); 9889b008c04SJohan Hedberg } 9899b008c04SJohan Hedberg 9906039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev, 991f9b49306SAndre Guedes struct sk_buff *skb) 992f9b49306SAndre Guedes { 99306199cf8SJohan Hedberg struct hci_cp_write_le_host_supported *sent; 994f9b49306SAndre Guedes __u8 status = *((__u8 *) skb->data); 995f9b49306SAndre Guedes 9969f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 997f9b49306SAndre Guedes 99806199cf8SJohan Hedberg sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED); 9998f984dfaSJohan Hedberg if (!sent) 1000f9b49306SAndre Guedes return; 1001f9b49306SAndre Guedes 10028f984dfaSJohan Hedberg if (!status) { 1003416a4ae5SJohan Hedberg if (sent->le) { 1004cad718edSJohan Hedberg hdev->features[1][0] |= LMP_HOST_LE; 1005416a4ae5SJohan Hedberg set_bit(HCI_LE_ENABLED, &hdev->dev_flags); 1006416a4ae5SJohan Hedberg } else { 1007cad718edSJohan Hedberg hdev->features[1][0] &= ~LMP_HOST_LE; 1008416a4ae5SJohan Hedberg clear_bit(HCI_LE_ENABLED, &hdev->dev_flags); 1009f3d3444aSJohan Hedberg clear_bit(HCI_ADVERTISING, &hdev->dev_flags); 1010416a4ae5SJohan Hedberg } 101153b2caabSJohan Hedberg 101253b2caabSJohan Hedberg if (sent->simul) 1013cad718edSJohan Hedberg hdev->features[1][0] |= LMP_HOST_LE_BREDR; 101453b2caabSJohan Hedberg else 1015cad718edSJohan Hedberg hdev->features[1][0] &= ~LMP_HOST_LE_BREDR; 10168f984dfaSJohan Hedberg } 1017f9b49306SAndre Guedes } 1018f9b49306SAndre Guedes 101993c284eeSAndrei Emeltchenko static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev, 102093c284eeSAndrei Emeltchenko struct sk_buff *skb) 102193c284eeSAndrei Emeltchenko { 102293c284eeSAndrei Emeltchenko struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data; 102393c284eeSAndrei Emeltchenko 102493c284eeSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x", 102593c284eeSAndrei Emeltchenko hdev->name, rp->status, rp->phy_handle); 102693c284eeSAndrei Emeltchenko 102793c284eeSAndrei Emeltchenko if (rp->status) 102893c284eeSAndrei Emeltchenko return; 102993c284eeSAndrei Emeltchenko 103093c284eeSAndrei Emeltchenko amp_write_rem_assoc_continue(hdev, rp->phy_handle); 103193c284eeSAndrei Emeltchenko } 103293c284eeSAndrei Emeltchenko 10336039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 1034a9de9248SMarcel Holtmann { 10359f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1036a9de9248SMarcel Holtmann 1037a9de9248SMarcel Holtmann if (status) { 1038a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 1039314b2381SJohan Hedberg return; 1040314b2381SJohan Hedberg } 1041314b2381SJohan Hedberg 104289352e7dSAndre Guedes set_bit(HCI_INQUIRY, &hdev->flags); 1043a9de9248SMarcel Holtmann } 1044a9de9248SMarcel Holtmann 10456039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 10461da177e4SLinus Torvalds { 1047a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 10481da177e4SLinus Torvalds struct hci_conn *conn; 10491da177e4SLinus Torvalds 10509f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1051a9de9248SMarcel Holtmann 1052a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 10531da177e4SLinus Torvalds if (!cp) 10541da177e4SLinus Torvalds return; 10551da177e4SLinus Torvalds 10561da177e4SLinus Torvalds hci_dev_lock(hdev); 10571da177e4SLinus Torvalds 10581da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 10591da177e4SLinus Torvalds 10606ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn); 10611da177e4SLinus Torvalds 10621da177e4SLinus Torvalds if (status) { 10631da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 10644c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 10651da177e4SLinus Torvalds conn->state = BT_CLOSED; 10661da177e4SLinus Torvalds hci_proto_connect_cfm(conn, status); 10671da177e4SLinus Torvalds hci_conn_del(conn); 10684c67bc74SMarcel Holtmann } else 10694c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 10701da177e4SLinus Torvalds } 10711da177e4SLinus Torvalds } else { 10721da177e4SLinus Torvalds if (!conn) { 10731da177e4SLinus Torvalds conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); 10741da177e4SLinus Torvalds if (conn) { 1075a0c808b3SJohan Hedberg conn->out = true; 10761da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 10771da177e4SLinus Torvalds } else 1078893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 10791da177e4SLinus Torvalds } 10801da177e4SLinus Torvalds } 10811da177e4SLinus Torvalds 10821da177e4SLinus Torvalds hci_dev_unlock(hdev); 10831da177e4SLinus Torvalds } 10841da177e4SLinus Torvalds 1085a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 10861da177e4SLinus Torvalds { 1087a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 10881da177e4SLinus Torvalds struct hci_conn *acl, *sco; 10891da177e4SLinus Torvalds __u16 handle; 10901da177e4SLinus Torvalds 10919f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1092b6a0dc82SMarcel Holtmann 1093a9de9248SMarcel Holtmann if (!status) 1094a9de9248SMarcel Holtmann return; 1095a9de9248SMarcel Holtmann 1096a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 10971da177e4SLinus Torvalds if (!cp) 1098a9de9248SMarcel Holtmann return; 10991da177e4SLinus Torvalds 11001da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 11011da177e4SLinus Torvalds 11029f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, handle); 11031da177e4SLinus Torvalds 11041da177e4SLinus Torvalds hci_dev_lock(hdev); 11051da177e4SLinus Torvalds 11061da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 11075a08ecceSAndrei Emeltchenko if (acl) { 11085a08ecceSAndrei Emeltchenko sco = acl->link; 11095a08ecceSAndrei Emeltchenko if (sco) { 11101da177e4SLinus Torvalds sco->state = BT_CLOSED; 11111da177e4SLinus Torvalds 11121da177e4SLinus Torvalds hci_proto_connect_cfm(sco, status); 11131da177e4SLinus Torvalds hci_conn_del(sco); 11141da177e4SLinus Torvalds } 11155a08ecceSAndrei Emeltchenko } 11161da177e4SLinus Torvalds 11171da177e4SLinus Torvalds hci_dev_unlock(hdev); 11181da177e4SLinus Torvalds } 11191da177e4SLinus Torvalds 1120f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 1121f8558555SMarcel Holtmann { 1122f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 1123f8558555SMarcel Holtmann struct hci_conn *conn; 1124f8558555SMarcel Holtmann 11259f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1126f8558555SMarcel Holtmann 1127f8558555SMarcel Holtmann if (!status) 1128f8558555SMarcel Holtmann return; 1129f8558555SMarcel Holtmann 1130f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 1131f8558555SMarcel Holtmann if (!cp) 1132f8558555SMarcel Holtmann return; 1133f8558555SMarcel Holtmann 1134f8558555SMarcel Holtmann hci_dev_lock(hdev); 1135f8558555SMarcel Holtmann 1136f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1137f8558555SMarcel Holtmann if (conn) { 1138f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1139f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 114076a68ba0SDavid Herrmann hci_conn_drop(conn); 1141f8558555SMarcel Holtmann } 1142f8558555SMarcel Holtmann } 1143f8558555SMarcel Holtmann 1144f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1145f8558555SMarcel Holtmann } 1146f8558555SMarcel Holtmann 1147f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 1148f8558555SMarcel Holtmann { 1149f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 1150f8558555SMarcel Holtmann struct hci_conn *conn; 1151f8558555SMarcel Holtmann 11529f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1153f8558555SMarcel Holtmann 1154f8558555SMarcel Holtmann if (!status) 1155f8558555SMarcel Holtmann return; 1156f8558555SMarcel Holtmann 1157f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 1158f8558555SMarcel Holtmann if (!cp) 1159f8558555SMarcel Holtmann return; 1160f8558555SMarcel Holtmann 1161f8558555SMarcel Holtmann hci_dev_lock(hdev); 1162f8558555SMarcel Holtmann 1163f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1164f8558555SMarcel Holtmann if (conn) { 1165f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1166f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 116776a68ba0SDavid Herrmann hci_conn_drop(conn); 1168f8558555SMarcel Holtmann } 1169f8558555SMarcel Holtmann } 1170f8558555SMarcel Holtmann 1171f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1172f8558555SMarcel Holtmann } 1173f8558555SMarcel Holtmann 1174127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev, 1175392599b9SJohan Hedberg struct hci_conn *conn) 1176392599b9SJohan Hedberg { 1177392599b9SJohan Hedberg if (conn->state != BT_CONFIG || !conn->out) 1178392599b9SJohan Hedberg return 0; 1179392599b9SJohan Hedberg 1180765c2a96SJohan Hedberg if (conn->pending_sec_level == BT_SECURITY_SDP) 1181392599b9SJohan Hedberg return 0; 1182392599b9SJohan Hedberg 1183392599b9SJohan Hedberg /* Only request authentication for SSP connections or non-SSP 1184e9bf2bf0SVinicius Costa Gomes * devices with sec_level HIGH or if MITM protection is requested */ 1185807deac2SGustavo Padovan if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) && 1186807deac2SGustavo Padovan conn->pending_sec_level != BT_SECURITY_HIGH) 1187392599b9SJohan Hedberg return 0; 1188392599b9SJohan Hedberg 1189392599b9SJohan Hedberg return 1; 1190392599b9SJohan Hedberg } 1191392599b9SJohan Hedberg 11926039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev, 119300abfe44SGustavo F. Padovan struct inquiry_entry *e) 119430dc78e1SJohan Hedberg { 119530dc78e1SJohan Hedberg struct hci_cp_remote_name_req cp; 119630dc78e1SJohan Hedberg 119730dc78e1SJohan Hedberg memset(&cp, 0, sizeof(cp)); 119830dc78e1SJohan Hedberg 119930dc78e1SJohan Hedberg bacpy(&cp.bdaddr, &e->data.bdaddr); 120030dc78e1SJohan Hedberg cp.pscan_rep_mode = e->data.pscan_rep_mode; 120130dc78e1SJohan Hedberg cp.pscan_mode = e->data.pscan_mode; 120230dc78e1SJohan Hedberg cp.clock_offset = e->data.clock_offset; 120330dc78e1SJohan Hedberg 120430dc78e1SJohan Hedberg return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 120530dc78e1SJohan Hedberg } 120630dc78e1SJohan Hedberg 1207b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev) 120830dc78e1SJohan Hedberg { 120930dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 121030dc78e1SJohan Hedberg struct inquiry_entry *e; 121130dc78e1SJohan Hedberg 1212b644ba33SJohan Hedberg if (list_empty(&discov->resolve)) 1213b644ba33SJohan Hedberg return false; 1214b644ba33SJohan Hedberg 1215b644ba33SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 1216c810089cSRam Malovany if (!e) 1217c810089cSRam Malovany return false; 1218c810089cSRam Malovany 1219b644ba33SJohan Hedberg if (hci_resolve_name(hdev, e) == 0) { 1220b644ba33SJohan Hedberg e->name_state = NAME_PENDING; 1221b644ba33SJohan Hedberg return true; 1222b644ba33SJohan Hedberg } 1223b644ba33SJohan Hedberg 1224b644ba33SJohan Hedberg return false; 1225b644ba33SJohan Hedberg } 1226b644ba33SJohan Hedberg 1227b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn, 1228b644ba33SJohan Hedberg bdaddr_t *bdaddr, u8 *name, u8 name_len) 1229b644ba33SJohan Hedberg { 1230b644ba33SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 1231b644ba33SJohan Hedberg struct inquiry_entry *e; 1232b644ba33SJohan Hedberg 1233b644ba33SJohan Hedberg if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 123404124681SGustavo F. Padovan mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name, 123504124681SGustavo F. Padovan name_len, conn->dev_class); 1236b644ba33SJohan Hedberg 1237b644ba33SJohan Hedberg if (discov->state == DISCOVERY_STOPPED) 1238b644ba33SJohan Hedberg return; 1239b644ba33SJohan Hedberg 124030dc78e1SJohan Hedberg if (discov->state == DISCOVERY_STOPPING) 124130dc78e1SJohan Hedberg goto discov_complete; 124230dc78e1SJohan Hedberg 124330dc78e1SJohan Hedberg if (discov->state != DISCOVERY_RESOLVING) 124430dc78e1SJohan Hedberg return; 124530dc78e1SJohan Hedberg 124630dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING); 12477cc8380eSRam Malovany /* If the device was not found in a list of found devices names of which 12487cc8380eSRam Malovany * are pending. there is no need to continue resolving a next name as it 12497cc8380eSRam Malovany * will be done upon receiving another Remote Name Request Complete 12507cc8380eSRam Malovany * Event */ 12517cc8380eSRam Malovany if (!e) 12527cc8380eSRam Malovany return; 12537cc8380eSRam Malovany 125430dc78e1SJohan Hedberg list_del(&e->list); 12557cc8380eSRam Malovany if (name) { 12567cc8380eSRam Malovany e->name_state = NAME_KNOWN; 1257b644ba33SJohan Hedberg mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, 1258b644ba33SJohan Hedberg e->data.rssi, name, name_len); 1259c3e7c0d9SRam Malovany } else { 1260c3e7c0d9SRam Malovany e->name_state = NAME_NOT_KNOWN; 126130dc78e1SJohan Hedberg } 126230dc78e1SJohan Hedberg 1263b644ba33SJohan Hedberg if (hci_resolve_next_name(hdev)) 126430dc78e1SJohan Hedberg return; 126530dc78e1SJohan Hedberg 126630dc78e1SJohan Hedberg discov_complete: 126730dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 126830dc78e1SJohan Hedberg } 126930dc78e1SJohan Hedberg 1270a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 12711da177e4SLinus Torvalds { 1272127178d2SJohan Hedberg struct hci_cp_remote_name_req *cp; 1273127178d2SJohan Hedberg struct hci_conn *conn; 1274127178d2SJohan Hedberg 12759f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1276127178d2SJohan Hedberg 1277127178d2SJohan Hedberg /* If successful wait for the name req complete event before 1278127178d2SJohan Hedberg * checking for the need to do authentication */ 1279127178d2SJohan Hedberg if (!status) 1280127178d2SJohan Hedberg return; 1281127178d2SJohan Hedberg 1282127178d2SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); 1283127178d2SJohan Hedberg if (!cp) 1284127178d2SJohan Hedberg return; 1285127178d2SJohan Hedberg 1286127178d2SJohan Hedberg hci_dev_lock(hdev); 1287127178d2SJohan Hedberg 1288127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 1289b644ba33SJohan Hedberg 1290b644ba33SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1291b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0); 1292b644ba33SJohan Hedberg 129379c6c70cSJohan Hedberg if (!conn) 129479c6c70cSJohan Hedberg goto unlock; 129579c6c70cSJohan Hedberg 129679c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 129779c6c70cSJohan Hedberg goto unlock; 129879c6c70cSJohan Hedberg 129951a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 1300c1f23a2bSJohannes Berg struct hci_cp_auth_requested auth_cp; 1301c1f23a2bSJohannes Berg 1302c1f23a2bSJohannes Berg auth_cp.handle = __cpu_to_le16(conn->handle); 1303c1f23a2bSJohannes Berg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, 1304c1f23a2bSJohannes Berg sizeof(auth_cp), &auth_cp); 1305127178d2SJohan Hedberg } 1306127178d2SJohan Hedberg 130779c6c70cSJohan Hedberg unlock: 1308127178d2SJohan Hedberg hci_dev_unlock(hdev); 1309a9de9248SMarcel Holtmann } 13101da177e4SLinus Torvalds 1311769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 1312769be974SMarcel Holtmann { 1313769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 1314769be974SMarcel Holtmann struct hci_conn *conn; 1315769be974SMarcel Holtmann 13169f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1317769be974SMarcel Holtmann 1318769be974SMarcel Holtmann if (!status) 1319769be974SMarcel Holtmann return; 1320769be974SMarcel Holtmann 1321769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 1322769be974SMarcel Holtmann if (!cp) 1323769be974SMarcel Holtmann return; 1324769be974SMarcel Holtmann 1325769be974SMarcel Holtmann hci_dev_lock(hdev); 1326769be974SMarcel Holtmann 1327769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1328769be974SMarcel Holtmann if (conn) { 1329769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1330769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 133176a68ba0SDavid Herrmann hci_conn_drop(conn); 1332769be974SMarcel Holtmann } 1333769be974SMarcel Holtmann } 1334769be974SMarcel Holtmann 1335769be974SMarcel Holtmann hci_dev_unlock(hdev); 1336769be974SMarcel Holtmann } 1337769be974SMarcel Holtmann 1338769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 1339769be974SMarcel Holtmann { 1340769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features *cp; 1341769be974SMarcel Holtmann struct hci_conn *conn; 1342769be974SMarcel Holtmann 13439f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1344769be974SMarcel Holtmann 1345769be974SMarcel Holtmann if (!status) 1346769be974SMarcel Holtmann return; 1347769be974SMarcel Holtmann 1348769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 1349769be974SMarcel Holtmann if (!cp) 1350769be974SMarcel Holtmann return; 1351769be974SMarcel Holtmann 1352769be974SMarcel Holtmann hci_dev_lock(hdev); 1353769be974SMarcel Holtmann 1354769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1355769be974SMarcel Holtmann if (conn) { 1356769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1357769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 135876a68ba0SDavid Herrmann hci_conn_drop(conn); 1359769be974SMarcel Holtmann } 1360769be974SMarcel Holtmann } 1361769be974SMarcel Holtmann 1362769be974SMarcel Holtmann hci_dev_unlock(hdev); 1363769be974SMarcel Holtmann } 1364769be974SMarcel Holtmann 1365a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 1366a9de9248SMarcel Holtmann { 1367b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 1368b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 1369b6a0dc82SMarcel Holtmann __u16 handle; 1370b6a0dc82SMarcel Holtmann 13719f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1372b6a0dc82SMarcel Holtmann 1373b6a0dc82SMarcel Holtmann if (!status) 1374b6a0dc82SMarcel Holtmann return; 1375b6a0dc82SMarcel Holtmann 1376b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 1377b6a0dc82SMarcel Holtmann if (!cp) 1378b6a0dc82SMarcel Holtmann return; 1379b6a0dc82SMarcel Holtmann 1380b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 1381b6a0dc82SMarcel Holtmann 13829f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, handle); 1383b6a0dc82SMarcel Holtmann 1384b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 1385b6a0dc82SMarcel Holtmann 1386b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 13875a08ecceSAndrei Emeltchenko if (acl) { 13885a08ecceSAndrei Emeltchenko sco = acl->link; 13895a08ecceSAndrei Emeltchenko if (sco) { 1390b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 1391b6a0dc82SMarcel Holtmann 1392b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(sco, status); 1393b6a0dc82SMarcel Holtmann hci_conn_del(sco); 1394b6a0dc82SMarcel Holtmann } 13955a08ecceSAndrei Emeltchenko } 1396b6a0dc82SMarcel Holtmann 1397b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 1398a9de9248SMarcel Holtmann } 1399a9de9248SMarcel Holtmann 1400a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 1401a9de9248SMarcel Holtmann { 1402a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 140304837f64SMarcel Holtmann struct hci_conn *conn; 140404837f64SMarcel Holtmann 14059f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1406a9de9248SMarcel Holtmann 1407a9de9248SMarcel Holtmann if (!status) 1408a9de9248SMarcel Holtmann return; 1409a9de9248SMarcel Holtmann 1410a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 141104837f64SMarcel Holtmann if (!cp) 1412a9de9248SMarcel Holtmann return; 141304837f64SMarcel Holtmann 141404837f64SMarcel Holtmann hci_dev_lock(hdev); 141504837f64SMarcel Holtmann 141604837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1417e73439d8SMarcel Holtmann if (conn) { 141851a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 141904837f64SMarcel Holtmann 142051a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1421e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1422e73439d8SMarcel Holtmann } 1423e73439d8SMarcel Holtmann 142404837f64SMarcel Holtmann hci_dev_unlock(hdev); 142504837f64SMarcel Holtmann } 142604837f64SMarcel Holtmann 1427a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 1428a9de9248SMarcel Holtmann { 1429a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 143004837f64SMarcel Holtmann struct hci_conn *conn; 143104837f64SMarcel Holtmann 14329f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1433a9de9248SMarcel Holtmann 1434a9de9248SMarcel Holtmann if (!status) 1435a9de9248SMarcel Holtmann return; 1436a9de9248SMarcel Holtmann 1437a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 143804837f64SMarcel Holtmann if (!cp) 1439a9de9248SMarcel Holtmann return; 144004837f64SMarcel Holtmann 144104837f64SMarcel Holtmann hci_dev_lock(hdev); 144204837f64SMarcel Holtmann 144304837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1444e73439d8SMarcel Holtmann if (conn) { 144551a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 144604837f64SMarcel Holtmann 144751a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1448e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1449e73439d8SMarcel Holtmann } 1450e73439d8SMarcel Holtmann 145104837f64SMarcel Holtmann hci_dev_unlock(hdev); 145204837f64SMarcel Holtmann } 145304837f64SMarcel Holtmann 145488c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) 145588c3df13SJohan Hedberg { 145688c3df13SJohan Hedberg struct hci_cp_disconnect *cp; 145788c3df13SJohan Hedberg struct hci_conn *conn; 145888c3df13SJohan Hedberg 145988c3df13SJohan Hedberg if (!status) 146088c3df13SJohan Hedberg return; 146188c3df13SJohan Hedberg 146288c3df13SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT); 146388c3df13SJohan Hedberg if (!cp) 146488c3df13SJohan Hedberg return; 146588c3df13SJohan Hedberg 146688c3df13SJohan Hedberg hci_dev_lock(hdev); 146788c3df13SJohan Hedberg 146888c3df13SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 146988c3df13SJohan Hedberg if (conn) 147088c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 147188c3df13SJohan Hedberg conn->dst_type, status); 147288c3df13SJohan Hedberg 147388c3df13SJohan Hedberg hci_dev_unlock(hdev); 147488c3df13SJohan Hedberg } 147588c3df13SJohan Hedberg 1476a02226d6SAndrei Emeltchenko static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status) 1477a02226d6SAndrei Emeltchenko { 147893c284eeSAndrei Emeltchenko struct hci_cp_create_phy_link *cp; 147993c284eeSAndrei Emeltchenko 1480a02226d6SAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 148193c284eeSAndrei Emeltchenko 148293c284eeSAndrei Emeltchenko cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK); 148393c284eeSAndrei Emeltchenko if (!cp) 148493c284eeSAndrei Emeltchenko return; 148593c284eeSAndrei Emeltchenko 1486e58917b9SAndrei Emeltchenko hci_dev_lock(hdev); 1487e58917b9SAndrei Emeltchenko 1488e58917b9SAndrei Emeltchenko if (status) { 1489e58917b9SAndrei Emeltchenko struct hci_conn *hcon; 1490e58917b9SAndrei Emeltchenko 1491e58917b9SAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle); 1492e58917b9SAndrei Emeltchenko if (hcon) 1493e58917b9SAndrei Emeltchenko hci_conn_del(hcon); 1494e58917b9SAndrei Emeltchenko } else { 149593c284eeSAndrei Emeltchenko amp_write_remote_assoc(hdev, cp->phy_handle); 1496a02226d6SAndrei Emeltchenko } 1497a02226d6SAndrei Emeltchenko 1498e58917b9SAndrei Emeltchenko hci_dev_unlock(hdev); 1499e58917b9SAndrei Emeltchenko } 1500e58917b9SAndrei Emeltchenko 15010b26ab9dSAndrei Emeltchenko static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status) 15020b26ab9dSAndrei Emeltchenko { 15030b26ab9dSAndrei Emeltchenko struct hci_cp_accept_phy_link *cp; 15040b26ab9dSAndrei Emeltchenko 15050b26ab9dSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 15060b26ab9dSAndrei Emeltchenko 15070b26ab9dSAndrei Emeltchenko if (status) 15080b26ab9dSAndrei Emeltchenko return; 15090b26ab9dSAndrei Emeltchenko 15100b26ab9dSAndrei Emeltchenko cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK); 15110b26ab9dSAndrei Emeltchenko if (!cp) 15120b26ab9dSAndrei Emeltchenko return; 15130b26ab9dSAndrei Emeltchenko 15140b26ab9dSAndrei Emeltchenko amp_write_remote_assoc(hdev, cp->phy_handle); 15150b26ab9dSAndrei Emeltchenko } 15160b26ab9dSAndrei Emeltchenko 15176039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 15181da177e4SLinus Torvalds { 15191da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 152030dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 152130dc78e1SJohan Hedberg struct inquiry_entry *e; 15221da177e4SLinus Torvalds 15239f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 15241da177e4SLinus Torvalds 1525a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 152689352e7dSAndre Guedes 152789352e7dSAndre Guedes if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) 152889352e7dSAndre Guedes return; 152989352e7dSAndre Guedes 15303e13fa1eSAndre Guedes smp_mb__after_clear_bit(); /* wake_up_bit advises about this barrier */ 15313e13fa1eSAndre Guedes wake_up_bit(&hdev->flags, HCI_INQUIRY); 15323e13fa1eSAndre Guedes 1533a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 153430dc78e1SJohan Hedberg return; 153530dc78e1SJohan Hedberg 153656e5cb86SJohan Hedberg hci_dev_lock(hdev); 153730dc78e1SJohan Hedberg 1538343f935bSAndre Guedes if (discov->state != DISCOVERY_FINDING) 153930dc78e1SJohan Hedberg goto unlock; 154030dc78e1SJohan Hedberg 154130dc78e1SJohan Hedberg if (list_empty(&discov->resolve)) { 1542ff9ef578SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 154330dc78e1SJohan Hedberg goto unlock; 154430dc78e1SJohan Hedberg } 154530dc78e1SJohan Hedberg 154630dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 154730dc78e1SJohan Hedberg if (e && hci_resolve_name(hdev, e) == 0) { 154830dc78e1SJohan Hedberg e->name_state = NAME_PENDING; 154930dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_RESOLVING); 155030dc78e1SJohan Hedberg } else { 155130dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 155230dc78e1SJohan Hedberg } 155330dc78e1SJohan Hedberg 155430dc78e1SJohan Hedberg unlock: 155556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 15561da177e4SLinus Torvalds } 15571da177e4SLinus Torvalds 15586039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 15591da177e4SLinus Torvalds { 156045bb4bf0SMarcel Holtmann struct inquiry_data data; 1561a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 15621da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 15631da177e4SLinus Torvalds 15641da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 15651da177e4SLinus Torvalds 156645bb4bf0SMarcel Holtmann if (!num_rsp) 156745bb4bf0SMarcel Holtmann return; 156845bb4bf0SMarcel Holtmann 15691519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 15701519cc17SAndre Guedes return; 15711519cc17SAndre Guedes 15721da177e4SLinus Torvalds hci_dev_lock(hdev); 157345bb4bf0SMarcel Holtmann 1574e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 1575388fc8faSJohan Hedberg bool name_known, ssp; 15763175405bSJohan Hedberg 15771da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 15781da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 15791da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 15801da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 15811da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 15821da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 15831da177e4SLinus Torvalds data.rssi = 0x00; 158441a96212SMarcel Holtmann data.ssp_mode = 0x00; 15853175405bSJohan Hedberg 1586388fc8faSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp); 158748264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 158804124681SGustavo F. Padovan info->dev_class, 0, !name_known, ssp, NULL, 158904124681SGustavo F. Padovan 0); 15901da177e4SLinus Torvalds } 159145bb4bf0SMarcel Holtmann 15921da177e4SLinus Torvalds hci_dev_unlock(hdev); 15931da177e4SLinus Torvalds } 15941da177e4SLinus Torvalds 15956039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 15961da177e4SLinus Torvalds { 1597a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 1598a9de9248SMarcel Holtmann struct hci_conn *conn; 15991da177e4SLinus Torvalds 1600a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 160145bb4bf0SMarcel Holtmann 16021da177e4SLinus Torvalds hci_dev_lock(hdev); 160345bb4bf0SMarcel Holtmann 1604a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 16059499237aSMarcel Holtmann if (!conn) { 16069499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 16079499237aSMarcel Holtmann goto unlock; 16089499237aSMarcel Holtmann 16099499237aSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 1610a9de9248SMarcel Holtmann if (!conn) 1611a9de9248SMarcel Holtmann goto unlock; 161245bb4bf0SMarcel Holtmann 16139499237aSMarcel Holtmann conn->type = SCO_LINK; 16149499237aSMarcel Holtmann } 16159499237aSMarcel Holtmann 1616a9de9248SMarcel Holtmann if (!ev->status) { 1617a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 1618769be974SMarcel Holtmann 1619769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 1620769be974SMarcel Holtmann conn->state = BT_CONFIG; 1621769be974SMarcel Holtmann hci_conn_hold(conn); 1622a9ea3ed9SSzymon Janc 1623a9ea3ed9SSzymon Janc if (!conn->out && !hci_conn_ssp_enabled(conn) && 1624a9ea3ed9SSzymon Janc !hci_find_link_key(hdev, &ev->bdaddr)) 1625a9ea3ed9SSzymon Janc conn->disc_timeout = HCI_PAIRING_TIMEOUT; 1626a9ea3ed9SSzymon Janc else 1627052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1628769be974SMarcel Holtmann } else 1629a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 1630a9de9248SMarcel Holtmann 16317d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 16327d0db0a3SMarcel Holtmann 1633a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 1634a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1635a9de9248SMarcel Holtmann 1636a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 1637a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1638a9de9248SMarcel Holtmann 1639a9de9248SMarcel Holtmann /* Get remote features */ 1640a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 1641a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 1642a9de9248SMarcel Holtmann cp.handle = ev->handle; 1643769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 1644769be974SMarcel Holtmann sizeof(cp), &cp); 164545bb4bf0SMarcel Holtmann } 1646a9de9248SMarcel Holtmann 1647a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 1648d095c1ebSAndrei Emeltchenko if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) { 1649a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 1650a9de9248SMarcel Holtmann cp.handle = ev->handle; 1651a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 165204124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp), 165304124681SGustavo F. Padovan &cp); 1654a9de9248SMarcel Holtmann } 165517d5c04cSJohan Hedberg } else { 1656a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 165717d5c04cSJohan Hedberg if (conn->type == ACL_LINK) 1658744cf19eSJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 165948264f06SJohan Hedberg conn->dst_type, ev->status); 166017d5c04cSJohan Hedberg } 166145bb4bf0SMarcel Holtmann 1662e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 1663e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 166445bb4bf0SMarcel Holtmann 1665769be974SMarcel Holtmann if (ev->status) { 1666a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1667a9de9248SMarcel Holtmann hci_conn_del(conn); 1668c89b6e6bSMarcel Holtmann } else if (ev->link_type != ACL_LINK) 1669c89b6e6bSMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1670a9de9248SMarcel Holtmann 1671a9de9248SMarcel Holtmann unlock: 16721da177e4SLinus Torvalds hci_dev_unlock(hdev); 1673a9de9248SMarcel Holtmann 1674a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 16751da177e4SLinus Torvalds } 16761da177e4SLinus Torvalds 16776039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 16781da177e4SLinus Torvalds { 1679a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 16801da177e4SLinus Torvalds int mask = hdev->link_mode; 168120714bfeSFrédéric Dalleau __u8 flags = 0; 16821da177e4SLinus Torvalds 16836ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr, 1684807deac2SGustavo Padovan ev->link_type); 16851da177e4SLinus Torvalds 168620714bfeSFrédéric Dalleau mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type, 168720714bfeSFrédéric Dalleau &flags); 16881da177e4SLinus Torvalds 1689138d22efSSzymon Janc if ((mask & HCI_LM_ACCEPT) && 1690138d22efSSzymon Janc !hci_blacklist_lookup(hdev, &ev->bdaddr)) { 16911da177e4SLinus Torvalds /* Connection accepted */ 1692c7bdd502SMarcel Holtmann struct inquiry_entry *ie; 16931da177e4SLinus Torvalds struct hci_conn *conn; 16941da177e4SLinus Torvalds 16951da177e4SLinus Torvalds hci_dev_lock(hdev); 1696b6a0dc82SMarcel Holtmann 1697cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 1698cc11b9c1SAndrei Emeltchenko if (ie) 1699c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 1700c7bdd502SMarcel Holtmann 17018fc9ced3SGustavo Padovan conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, 17028fc9ced3SGustavo Padovan &ev->bdaddr); 17031da177e4SLinus Torvalds if (!conn) { 1704cc11b9c1SAndrei Emeltchenko conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); 1705cc11b9c1SAndrei Emeltchenko if (!conn) { 1706893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 17071da177e4SLinus Torvalds hci_dev_unlock(hdev); 17081da177e4SLinus Torvalds return; 17091da177e4SLinus Torvalds } 17101da177e4SLinus Torvalds } 1711b6a0dc82SMarcel Holtmann 17121da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 1713b6a0dc82SMarcel Holtmann 17141da177e4SLinus Torvalds hci_dev_unlock(hdev); 17151da177e4SLinus Torvalds 171620714bfeSFrédéric Dalleau if (ev->link_type == ACL_LINK || 171720714bfeSFrédéric Dalleau (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) { 1718b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 171920714bfeSFrédéric Dalleau conn->state = BT_CONNECT; 1720b6a0dc82SMarcel Holtmann 17211da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 17221da177e4SLinus Torvalds 17231da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 17241da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 17251da177e4SLinus Torvalds else 17261da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 17271da177e4SLinus Torvalds 172804124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), 172904124681SGustavo F. Padovan &cp); 173020714bfeSFrédéric Dalleau } else if (!(flags & HCI_PROTO_DEFER)) { 1731b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 173220714bfeSFrédéric Dalleau conn->state = BT_CONNECT; 1733b6a0dc82SMarcel Holtmann 1734b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 1735a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1736b6a0dc82SMarcel Holtmann 173782781e63SAndrei Emeltchenko cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40); 173882781e63SAndrei Emeltchenko cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40); 173982781e63SAndrei Emeltchenko cp.max_latency = __constant_cpu_to_le16(0xffff); 1740b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 1741b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 1742b6a0dc82SMarcel Holtmann 1743b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 1744b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 174520714bfeSFrédéric Dalleau } else { 174620714bfeSFrédéric Dalleau conn->state = BT_CONNECT2; 174720714bfeSFrédéric Dalleau hci_proto_connect_cfm(conn, 0); 1748b6a0dc82SMarcel Holtmann } 17491da177e4SLinus Torvalds } else { 17501da177e4SLinus Torvalds /* Connection rejected */ 17511da177e4SLinus Torvalds struct hci_cp_reject_conn_req cp; 17521da177e4SLinus Torvalds 17531da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 17549f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_REJ_BAD_ADDR; 1755a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 17561da177e4SLinus Torvalds } 17571da177e4SLinus Torvalds } 17581da177e4SLinus Torvalds 1759f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err) 1760f0d6a0eaSMikel Astiz { 1761f0d6a0eaSMikel Astiz switch (err) { 1762f0d6a0eaSMikel Astiz case HCI_ERROR_CONNECTION_TIMEOUT: 1763f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_TIMEOUT; 1764f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_USER_TERM: 1765f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_LOW_RESOURCES: 1766f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_POWER_OFF: 1767f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_REMOTE; 1768f0d6a0eaSMikel Astiz case HCI_ERROR_LOCAL_HOST_TERM: 1769f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_LOCAL_HOST; 1770f0d6a0eaSMikel Astiz default: 1771f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_UNKNOWN; 1772f0d6a0eaSMikel Astiz } 1773f0d6a0eaSMikel Astiz } 1774f0d6a0eaSMikel Astiz 17756039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 17761da177e4SLinus Torvalds { 1777a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 177804837f64SMarcel Holtmann struct hci_conn *conn; 17791da177e4SLinus Torvalds 17809f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 17811da177e4SLinus Torvalds 17821da177e4SLinus Torvalds hci_dev_lock(hdev); 17831da177e4SLinus Torvalds 178404837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1785f7520543SJohan Hedberg if (!conn) 1786f7520543SJohan Hedberg goto unlock; 1787f7520543SJohan Hedberg 178837d9ef76SJohan Hedberg if (ev->status == 0) 17891da177e4SLinus Torvalds conn->state = BT_CLOSED; 17907d0db0a3SMarcel Holtmann 1791b644ba33SJohan Hedberg if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) && 1792b644ba33SJohan Hedberg (conn->type == ACL_LINK || conn->type == LE_LINK)) { 1793f0d6a0eaSMikel Astiz if (ev->status) { 179488c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 179588c3df13SJohan Hedberg conn->dst_type, ev->status); 1796f0d6a0eaSMikel Astiz } else { 1797f0d6a0eaSMikel Astiz u8 reason = hci_to_mgmt_reason(ev->reason); 1798f0d6a0eaSMikel Astiz 1799afc747a6SJohan Hedberg mgmt_device_disconnected(hdev, &conn->dst, conn->type, 1800f0d6a0eaSMikel Astiz conn->dst_type, reason); 1801f0d6a0eaSMikel Astiz } 180237d9ef76SJohan Hedberg } 1803f7520543SJohan Hedberg 180437d9ef76SJohan Hedberg if (ev->status == 0) { 18052210246cSJohan Hedberg u8 type = conn->type; 18062210246cSJohan Hedberg 18072210246cSJohan Hedberg if (type == ACL_LINK && conn->flush_key) 18086ec5bcadSVishal Agarwal hci_remove_link_key(hdev, &conn->dst); 18092950f21aSMarcel Holtmann hci_proto_disconn_cfm(conn, ev->reason); 18101da177e4SLinus Torvalds hci_conn_del(conn); 18112210246cSJohan Hedberg 18122210246cSJohan Hedberg /* Re-enable advertising if necessary, since it might 18132210246cSJohan Hedberg * have been disabled by the connection. From the 18142210246cSJohan Hedberg * HCI_LE_Set_Advertise_Enable command description in 18152210246cSJohan Hedberg * the core specification (v4.0): 18162210246cSJohan Hedberg * "The Controller shall continue advertising until the Host 18172210246cSJohan Hedberg * issues an LE_Set_Advertise_Enable command with 18182210246cSJohan Hedberg * Advertising_Enable set to 0x00 (Advertising is disabled) 18192210246cSJohan Hedberg * or until a connection is created or until the Advertising 18202210246cSJohan Hedberg * is timed out due to Directed Advertising." 18212210246cSJohan Hedberg */ 18222210246cSJohan Hedberg if (type == LE_LINK) 18235976e608SMarcel Holtmann mgmt_reenable_advertising(hdev); 182437d9ef76SJohan Hedberg } 18251da177e4SLinus Torvalds 1826f7520543SJohan Hedberg unlock: 18271da177e4SLinus Torvalds hci_dev_unlock(hdev); 18281da177e4SLinus Torvalds } 18291da177e4SLinus Torvalds 18306039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1831a9de9248SMarcel Holtmann { 1832a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 1833a9de9248SMarcel Holtmann struct hci_conn *conn; 1834a9de9248SMarcel Holtmann 18359f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 1836a9de9248SMarcel Holtmann 1837a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1838a9de9248SMarcel Holtmann 1839a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1840d7556e20SWaldemar Rymarkiewicz if (!conn) 1841d7556e20SWaldemar Rymarkiewicz goto unlock; 1842d7556e20SWaldemar Rymarkiewicz 1843765c2a96SJohan Hedberg if (!ev->status) { 1844aa64a8b5SJohan Hedberg if (!hci_conn_ssp_enabled(conn) && 184551a8efd7SJohan Hedberg test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) { 1846d7556e20SWaldemar Rymarkiewicz BT_INFO("re-auth of legacy device is not possible."); 184719f8def0SWaldemar Rymarkiewicz } else { 1848a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1849765c2a96SJohan Hedberg conn->sec_level = conn->pending_sec_level; 185019f8def0SWaldemar Rymarkiewicz } 18512a611692SJohan Hedberg } else { 1852bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 1853bab73cb6SJohan Hedberg ev->status); 18542a611692SJohan Hedberg } 1855a9de9248SMarcel Holtmann 185651a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 185751a8efd7SJohan Hedberg clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags); 1858a9de9248SMarcel Holtmann 1859f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1860aa64a8b5SJohan Hedberg if (!ev->status && hci_conn_ssp_enabled(conn)) { 1861f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1862f8558555SMarcel Holtmann cp.handle = ev->handle; 1863f8558555SMarcel Holtmann cp.encrypt = 0x01; 1864d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1865d7556e20SWaldemar Rymarkiewicz &cp); 1866f8558555SMarcel Holtmann } else { 1867f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1868f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 186976a68ba0SDavid Herrmann hci_conn_drop(conn); 1870f8558555SMarcel Holtmann } 1871052b30b0SMarcel Holtmann } else { 1872a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 1873a9de9248SMarcel Holtmann 1874052b30b0SMarcel Holtmann hci_conn_hold(conn); 1875052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 187676a68ba0SDavid Herrmann hci_conn_drop(conn); 1877052b30b0SMarcel Holtmann } 1878052b30b0SMarcel Holtmann 187951a8efd7SJohan Hedberg if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) { 1880a9de9248SMarcel Holtmann if (!ev->status) { 1881a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1882f8558555SMarcel Holtmann cp.handle = ev->handle; 1883f8558555SMarcel Holtmann cp.encrypt = 0x01; 1884d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1885d7556e20SWaldemar Rymarkiewicz &cp); 1886a9de9248SMarcel Holtmann } else { 188751a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 1888a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 1889a9de9248SMarcel Holtmann } 1890a9de9248SMarcel Holtmann } 1891a9de9248SMarcel Holtmann 1892d7556e20SWaldemar Rymarkiewicz unlock: 1893a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1894a9de9248SMarcel Holtmann } 1895a9de9248SMarcel Holtmann 18966039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 1897a9de9248SMarcel Holtmann { 1898127178d2SJohan Hedberg struct hci_ev_remote_name *ev = (void *) skb->data; 1899127178d2SJohan Hedberg struct hci_conn *conn; 1900127178d2SJohan Hedberg 1901a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1902a9de9248SMarcel Holtmann 1903a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 1904127178d2SJohan Hedberg 1905127178d2SJohan Hedberg hci_dev_lock(hdev); 1906127178d2SJohan Hedberg 1907127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 1908b644ba33SJohan Hedberg 1909b644ba33SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 1910b644ba33SJohan Hedberg goto check_auth; 1911b644ba33SJohan Hedberg 1912b644ba33SJohan Hedberg if (ev->status == 0) 1913b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name, 1914b644ba33SJohan Hedberg strnlen(ev->name, HCI_MAX_NAME_LENGTH)); 1915b644ba33SJohan Hedberg else 1916b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0); 1917b644ba33SJohan Hedberg 1918b644ba33SJohan Hedberg check_auth: 191979c6c70cSJohan Hedberg if (!conn) 192079c6c70cSJohan Hedberg goto unlock; 192179c6c70cSJohan Hedberg 192279c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 192379c6c70cSJohan Hedberg goto unlock; 192479c6c70cSJohan Hedberg 192551a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 1926127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1927127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1928127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1929127178d2SJohan Hedberg } 1930127178d2SJohan Hedberg 193179c6c70cSJohan Hedberg unlock: 1932127178d2SJohan Hedberg hci_dev_unlock(hdev); 1933a9de9248SMarcel Holtmann } 1934a9de9248SMarcel Holtmann 19356039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 1936a9de9248SMarcel Holtmann { 1937a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 1938a9de9248SMarcel Holtmann struct hci_conn *conn; 1939a9de9248SMarcel Holtmann 19409f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 1941a9de9248SMarcel Holtmann 1942a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1943a9de9248SMarcel Holtmann 1944a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1945a9de9248SMarcel Holtmann if (conn) { 1946a9de9248SMarcel Holtmann if (!ev->status) { 1947ae293196SMarcel Holtmann if (ev->encrypt) { 1948ae293196SMarcel Holtmann /* Encryption implies authentication */ 1949ae293196SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1950a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1951da85e5e5SVinicius Costa Gomes conn->sec_level = conn->pending_sec_level; 1952ae293196SMarcel Holtmann } else 1953a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_ENCRYPT; 1954a9de9248SMarcel Holtmann } 1955a9de9248SMarcel Holtmann 195651a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 1957a9de9248SMarcel Holtmann 1958a7d7723aSGustavo Padovan if (ev->status && conn->state == BT_CONNECTED) { 1959bed71748SAndre Guedes hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); 196076a68ba0SDavid Herrmann hci_conn_drop(conn); 1961a7d7723aSGustavo Padovan goto unlock; 1962a7d7723aSGustavo Padovan } 1963a7d7723aSGustavo Padovan 1964f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1965f8558555SMarcel Holtmann if (!ev->status) 1966f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1967f8558555SMarcel Holtmann 1968f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 196976a68ba0SDavid Herrmann hci_conn_drop(conn); 1970f8558555SMarcel Holtmann } else 1971a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 1972a9de9248SMarcel Holtmann } 1973a9de9248SMarcel Holtmann 1974a7d7723aSGustavo Padovan unlock: 1975a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1976a9de9248SMarcel Holtmann } 1977a9de9248SMarcel Holtmann 19786039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev, 1979807deac2SGustavo Padovan struct sk_buff *skb) 1980a9de9248SMarcel Holtmann { 1981a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 1982a9de9248SMarcel Holtmann struct hci_conn *conn; 1983a9de9248SMarcel Holtmann 19849f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 1985a9de9248SMarcel Holtmann 1986a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1987a9de9248SMarcel Holtmann 1988a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1989a9de9248SMarcel Holtmann if (conn) { 1990a9de9248SMarcel Holtmann if (!ev->status) 1991a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_SECURE; 1992a9de9248SMarcel Holtmann 199351a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 1994a9de9248SMarcel Holtmann 1995a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 1996a9de9248SMarcel Holtmann } 1997a9de9248SMarcel Holtmann 1998a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1999a9de9248SMarcel Holtmann } 2000a9de9248SMarcel Holtmann 20016039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev, 2002807deac2SGustavo Padovan struct sk_buff *skb) 2003a9de9248SMarcel Holtmann { 2004a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 2005a9de9248SMarcel Holtmann struct hci_conn *conn; 2006a9de9248SMarcel Holtmann 20079f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2008a9de9248SMarcel Holtmann 2009a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2010a9de9248SMarcel Holtmann 2011a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2012ccd556feSJohan Hedberg if (!conn) 2013ccd556feSJohan Hedberg goto unlock; 2014ccd556feSJohan Hedberg 2015769be974SMarcel Holtmann if (!ev->status) 2016cad718edSJohan Hedberg memcpy(conn->features[0], ev->features, 8); 2017a9de9248SMarcel Holtmann 2018ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2019ccd556feSJohan Hedberg goto unlock; 2020ccd556feSJohan Hedberg 2021ccd556feSJohan Hedberg if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { 2022769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 2023769be974SMarcel Holtmann cp.handle = ev->handle; 2024769be974SMarcel Holtmann cp.page = 0x01; 2025ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 2026769be974SMarcel Holtmann sizeof(cp), &cp); 2027392599b9SJohan Hedberg goto unlock; 2028392599b9SJohan Hedberg } 2029392599b9SJohan Hedberg 2030671267bfSJohan Hedberg if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { 2031127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2032127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2033127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2034127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2035127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2036b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 2037b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 203808c79b61SJohan Hedberg conn->dst_type, 0, NULL, 0, 2039b644ba33SJohan Hedberg conn->dev_class); 2040392599b9SJohan Hedberg 2041127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2042769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2043769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 204476a68ba0SDavid Herrmann hci_conn_drop(conn); 2045769be974SMarcel Holtmann } 2046769be974SMarcel Holtmann 2047ccd556feSJohan Hedberg unlock: 2048a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2049a9de9248SMarcel Holtmann } 2050a9de9248SMarcel Holtmann 20516039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2052a9de9248SMarcel Holtmann { 2053a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 20549238f36aSJohan Hedberg u8 status = skb->data[sizeof(*ev)]; 2055a9de9248SMarcel Holtmann __u16 opcode; 2056a9de9248SMarcel Holtmann 2057a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2058a9de9248SMarcel Holtmann 2059a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2060a9de9248SMarcel Holtmann 2061a9de9248SMarcel Holtmann switch (opcode) { 2062a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 2063a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 2064a9de9248SMarcel Holtmann break; 2065a9de9248SMarcel Holtmann 20664d93483bSAndre Guedes case HCI_OP_PERIODIC_INQ: 20674d93483bSAndre Guedes hci_cc_periodic_inq(hdev, skb); 20684d93483bSAndre Guedes break; 20694d93483bSAndre Guedes 2070a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 2071a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 2072a9de9248SMarcel Holtmann break; 2073a9de9248SMarcel Holtmann 2074a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 2075a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 2076a9de9248SMarcel Holtmann break; 2077a9de9248SMarcel Holtmann 2078a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 2079a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 2080a9de9248SMarcel Holtmann break; 2081a9de9248SMarcel Holtmann 2082e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 2083e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 2084e4e8e37cSMarcel Holtmann break; 2085e4e8e37cSMarcel Holtmann 2086a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 2087a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 2088a9de9248SMarcel Holtmann break; 2089a9de9248SMarcel Holtmann 2090e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 2091e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 2092e4e8e37cSMarcel Holtmann break; 2093e4e8e37cSMarcel Holtmann 2094e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 2095e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 2096e4e8e37cSMarcel Holtmann break; 2097e4e8e37cSMarcel Holtmann 2098a9de9248SMarcel Holtmann case HCI_OP_RESET: 2099a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 2100a9de9248SMarcel Holtmann break; 2101a9de9248SMarcel Holtmann 2102a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 2103a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 2104a9de9248SMarcel Holtmann break; 2105a9de9248SMarcel Holtmann 2106a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 2107a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 2108a9de9248SMarcel Holtmann break; 2109a9de9248SMarcel Holtmann 2110a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 2111a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 2112a9de9248SMarcel Holtmann break; 2113a9de9248SMarcel Holtmann 2114a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 2115a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 2116a9de9248SMarcel Holtmann break; 2117a9de9248SMarcel Holtmann 2118a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 2119a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 2120a9de9248SMarcel Holtmann break; 2121a9de9248SMarcel Holtmann 2122a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 2123a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 2124a9de9248SMarcel Holtmann break; 2125a9de9248SMarcel Holtmann 2126a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 2127a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 2128a9de9248SMarcel Holtmann break; 2129a9de9248SMarcel Holtmann 2130a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 2131a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 2132a9de9248SMarcel Holtmann break; 2133a9de9248SMarcel Holtmann 2134a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 2135a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 2136a9de9248SMarcel Holtmann break; 2137a9de9248SMarcel Holtmann 2138333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 2139333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 2140333140b5SMarcel Holtmann break; 2141333140b5SMarcel Holtmann 2142a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 2143a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 2144a9de9248SMarcel Holtmann break; 2145a9de9248SMarcel Holtmann 2146a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 2147a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 2148a9de9248SMarcel Holtmann break; 2149a9de9248SMarcel Holtmann 2150a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 2151a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 2152a9de9248SMarcel Holtmann break; 2153a9de9248SMarcel Holtmann 2154971e3a4bSAndre Guedes case HCI_OP_READ_LOCAL_EXT_FEATURES: 2155971e3a4bSAndre Guedes hci_cc_read_local_ext_features(hdev, skb); 2156971e3a4bSAndre Guedes break; 2157971e3a4bSAndre Guedes 2158a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 2159a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 2160a9de9248SMarcel Holtmann break; 2161a9de9248SMarcel Holtmann 2162a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 2163a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 2164a9de9248SMarcel Holtmann break; 2165a9de9248SMarcel Holtmann 2166f332ec66SJohan Hedberg case HCI_OP_READ_PAGE_SCAN_ACTIVITY: 2167f332ec66SJohan Hedberg hci_cc_read_page_scan_activity(hdev, skb); 2168f332ec66SJohan Hedberg break; 2169f332ec66SJohan Hedberg 21704a3ee763SJohan Hedberg case HCI_OP_WRITE_PAGE_SCAN_ACTIVITY: 21714a3ee763SJohan Hedberg hci_cc_write_page_scan_activity(hdev, skb); 21724a3ee763SJohan Hedberg break; 21734a3ee763SJohan Hedberg 2174f332ec66SJohan Hedberg case HCI_OP_READ_PAGE_SCAN_TYPE: 2175f332ec66SJohan Hedberg hci_cc_read_page_scan_type(hdev, skb); 2176f332ec66SJohan Hedberg break; 2177f332ec66SJohan Hedberg 21784a3ee763SJohan Hedberg case HCI_OP_WRITE_PAGE_SCAN_TYPE: 21794a3ee763SJohan Hedberg hci_cc_write_page_scan_type(hdev, skb); 21804a3ee763SJohan Hedberg break; 21814a3ee763SJohan Hedberg 2182350ee4cfSAndrei Emeltchenko case HCI_OP_READ_DATA_BLOCK_SIZE: 2183350ee4cfSAndrei Emeltchenko hci_cc_read_data_block_size(hdev, skb); 2184350ee4cfSAndrei Emeltchenko break; 2185350ee4cfSAndrei Emeltchenko 21861e89cffbSAndrei Emeltchenko case HCI_OP_READ_FLOW_CONTROL_MODE: 21871e89cffbSAndrei Emeltchenko hci_cc_read_flow_control_mode(hdev, skb); 21881e89cffbSAndrei Emeltchenko break; 21891e89cffbSAndrei Emeltchenko 2190928abaa7SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_INFO: 2191928abaa7SAndrei Emeltchenko hci_cc_read_local_amp_info(hdev, skb); 2192928abaa7SAndrei Emeltchenko break; 2193928abaa7SAndrei Emeltchenko 2194903e4541SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_ASSOC: 2195903e4541SAndrei Emeltchenko hci_cc_read_local_amp_assoc(hdev, skb); 2196903e4541SAndrei Emeltchenko break; 2197903e4541SAndrei Emeltchenko 2198d5859e22SJohan Hedberg case HCI_OP_READ_INQ_RSP_TX_POWER: 2199d5859e22SJohan Hedberg hci_cc_read_inq_rsp_tx_power(hdev, skb); 2200d5859e22SJohan Hedberg break; 2201d5859e22SJohan Hedberg 2202980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_REPLY: 2203980e1a53SJohan Hedberg hci_cc_pin_code_reply(hdev, skb); 2204980e1a53SJohan Hedberg break; 2205980e1a53SJohan Hedberg 2206980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_NEG_REPLY: 2207980e1a53SJohan Hedberg hci_cc_pin_code_neg_reply(hdev, skb); 2208980e1a53SJohan Hedberg break; 2209980e1a53SJohan Hedberg 2210c35938b2SSzymon Janc case HCI_OP_READ_LOCAL_OOB_DATA: 2211c35938b2SSzymon Janc hci_cc_read_local_oob_data_reply(hdev, skb); 2212c35938b2SSzymon Janc break; 2213c35938b2SSzymon Janc 22146ed58ec5SVille Tervo case HCI_OP_LE_READ_BUFFER_SIZE: 22156ed58ec5SVille Tervo hci_cc_le_read_buffer_size(hdev, skb); 22166ed58ec5SVille Tervo break; 22176ed58ec5SVille Tervo 221860e77321SJohan Hedberg case HCI_OP_LE_READ_LOCAL_FEATURES: 221960e77321SJohan Hedberg hci_cc_le_read_local_features(hdev, skb); 222060e77321SJohan Hedberg break; 222160e77321SJohan Hedberg 22228fa19098SJohan Hedberg case HCI_OP_LE_READ_ADV_TX_POWER: 22238fa19098SJohan Hedberg hci_cc_le_read_adv_tx_power(hdev, skb); 22248fa19098SJohan Hedberg break; 22258fa19098SJohan Hedberg 2226a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_REPLY: 2227a5c29683SJohan Hedberg hci_cc_user_confirm_reply(hdev, skb); 2228a5c29683SJohan Hedberg break; 2229a5c29683SJohan Hedberg 2230a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_NEG_REPLY: 2231a5c29683SJohan Hedberg hci_cc_user_confirm_neg_reply(hdev, skb); 2232a5c29683SJohan Hedberg break; 2233a5c29683SJohan Hedberg 22341143d458SBrian Gix case HCI_OP_USER_PASSKEY_REPLY: 22351143d458SBrian Gix hci_cc_user_passkey_reply(hdev, skb); 22361143d458SBrian Gix break; 22371143d458SBrian Gix 22381143d458SBrian Gix case HCI_OP_USER_PASSKEY_NEG_REPLY: 22391143d458SBrian Gix hci_cc_user_passkey_neg_reply(hdev, skb); 224016cde993SSzymon Janc break; 224107f7fa5dSAndre Guedes 2242c1d5dc4aSJohan Hedberg case HCI_OP_LE_SET_ADV_ENABLE: 2243c1d5dc4aSJohan Hedberg hci_cc_le_set_adv_enable(hdev, skb); 2244c1d5dc4aSJohan Hedberg break; 2245c1d5dc4aSJohan Hedberg 2246eb9d91f5SAndre Guedes case HCI_OP_LE_SET_SCAN_ENABLE: 2247eb9d91f5SAndre Guedes hci_cc_le_set_scan_enable(hdev, skb); 2248eb9d91f5SAndre Guedes break; 2249eb9d91f5SAndre Guedes 2250cf1d081fSJohan Hedberg case HCI_OP_LE_READ_WHITE_LIST_SIZE: 2251cf1d081fSJohan Hedberg hci_cc_le_read_white_list_size(hdev, skb); 2252cf1d081fSJohan Hedberg break; 2253cf1d081fSJohan Hedberg 22549b008c04SJohan Hedberg case HCI_OP_LE_READ_SUPPORTED_STATES: 22559b008c04SJohan Hedberg hci_cc_le_read_supported_states(hdev, skb); 22569b008c04SJohan Hedberg break; 22579b008c04SJohan Hedberg 2258f9b49306SAndre Guedes case HCI_OP_WRITE_LE_HOST_SUPPORTED: 2259f9b49306SAndre Guedes hci_cc_write_le_host_supported(hdev, skb); 2260f9b49306SAndre Guedes break; 2261f9b49306SAndre Guedes 226293c284eeSAndrei Emeltchenko case HCI_OP_WRITE_REMOTE_AMP_ASSOC: 226393c284eeSAndrei Emeltchenko hci_cc_write_remote_amp_assoc(hdev, skb); 226493c284eeSAndrei Emeltchenko break; 226593c284eeSAndrei Emeltchenko 2266a9de9248SMarcel Holtmann default: 22679f1db00cSAndrei Emeltchenko BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); 2268a9de9248SMarcel Holtmann break; 2269a9de9248SMarcel Holtmann } 2270a9de9248SMarcel Holtmann 2271ad82cdd1SJohan Hedberg if (opcode != HCI_OP_NOP) 22726bd32326SVille Tervo del_timer(&hdev->cmd_timer); 22736bd32326SVille Tervo 2274ad82cdd1SJohan Hedberg hci_req_cmd_complete(hdev, opcode, status); 22759238f36aSJohan Hedberg 2276dbccd791SSzymon Janc if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2277a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2278a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2279c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2280a9de9248SMarcel Holtmann } 2281a9de9248SMarcel Holtmann } 2282a9de9248SMarcel Holtmann 22836039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 2284a9de9248SMarcel Holtmann { 2285a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 2286a9de9248SMarcel Holtmann __u16 opcode; 2287a9de9248SMarcel Holtmann 2288a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2289a9de9248SMarcel Holtmann 2290a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2291a9de9248SMarcel Holtmann 2292a9de9248SMarcel Holtmann switch (opcode) { 2293a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 2294a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 2295a9de9248SMarcel Holtmann break; 2296a9de9248SMarcel Holtmann 2297a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 2298a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 2299a9de9248SMarcel Holtmann break; 2300a9de9248SMarcel Holtmann 2301a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 2302a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 2303a9de9248SMarcel Holtmann break; 2304a9de9248SMarcel Holtmann 2305f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 2306f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 2307f8558555SMarcel Holtmann break; 2308f8558555SMarcel Holtmann 2309f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 2310f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 2311f8558555SMarcel Holtmann break; 2312f8558555SMarcel Holtmann 2313a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 2314a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 2315a9de9248SMarcel Holtmann break; 2316a9de9248SMarcel Holtmann 2317769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 2318769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 2319769be974SMarcel Holtmann break; 2320769be974SMarcel Holtmann 2321769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 2322769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 2323769be974SMarcel Holtmann break; 2324769be974SMarcel Holtmann 2325a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 2326a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 2327a9de9248SMarcel Holtmann break; 2328a9de9248SMarcel Holtmann 2329a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 2330a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 2331a9de9248SMarcel Holtmann break; 2332a9de9248SMarcel Holtmann 2333a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 2334a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 2335a9de9248SMarcel Holtmann break; 2336a9de9248SMarcel Holtmann 23378962ee74SJohan Hedberg case HCI_OP_DISCONNECT: 233888c3df13SJohan Hedberg hci_cs_disconnect(hdev, ev->status); 23398962ee74SJohan Hedberg break; 23408962ee74SJohan Hedberg 2341a02226d6SAndrei Emeltchenko case HCI_OP_CREATE_PHY_LINK: 2342a02226d6SAndrei Emeltchenko hci_cs_create_phylink(hdev, ev->status); 2343a02226d6SAndrei Emeltchenko break; 2344a02226d6SAndrei Emeltchenko 23450b26ab9dSAndrei Emeltchenko case HCI_OP_ACCEPT_PHY_LINK: 23460b26ab9dSAndrei Emeltchenko hci_cs_accept_phylink(hdev, ev->status); 23470b26ab9dSAndrei Emeltchenko break; 23480b26ab9dSAndrei Emeltchenko 2349a9de9248SMarcel Holtmann default: 23509f1db00cSAndrei Emeltchenko BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); 2351a9de9248SMarcel Holtmann break; 2352a9de9248SMarcel Holtmann } 2353a9de9248SMarcel Holtmann 2354ad82cdd1SJohan Hedberg if (opcode != HCI_OP_NOP) 23556bd32326SVille Tervo del_timer(&hdev->cmd_timer); 23566bd32326SVille Tervo 235702350a72SJohan Hedberg if (ev->status || 235802350a72SJohan Hedberg (hdev->sent_cmd && !bt_cb(hdev->sent_cmd)->req.event)) 235933720450SAndre Guedes hci_req_cmd_complete(hdev, opcode, ev->status); 23609238f36aSJohan Hedberg 236110572132SGustavo F. Padovan if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2362a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2363a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2364c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2365a9de9248SMarcel Holtmann } 2366a9de9248SMarcel Holtmann } 2367a9de9248SMarcel Holtmann 23686039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2369a9de9248SMarcel Holtmann { 2370a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 2371a9de9248SMarcel Holtmann struct hci_conn *conn; 2372a9de9248SMarcel Holtmann 23739f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2374a9de9248SMarcel Holtmann 2375a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2376a9de9248SMarcel Holtmann 2377a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2378a9de9248SMarcel Holtmann if (conn) { 2379a9de9248SMarcel Holtmann if (!ev->status) { 2380a9de9248SMarcel Holtmann if (ev->role) 2381a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_MASTER; 2382a9de9248SMarcel Holtmann else 2383a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_MASTER; 2384a9de9248SMarcel Holtmann } 2385a9de9248SMarcel Holtmann 238651a8efd7SJohan Hedberg clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); 2387a9de9248SMarcel Holtmann 2388a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 2389a9de9248SMarcel Holtmann } 2390a9de9248SMarcel Holtmann 2391a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2392a9de9248SMarcel Holtmann } 2393a9de9248SMarcel Holtmann 23946039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 23951da177e4SLinus Torvalds { 2396a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 23971da177e4SLinus Torvalds int i; 23981da177e4SLinus Torvalds 239932ac5b9bSAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) { 240032ac5b9bSAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 240132ac5b9bSAndrei Emeltchenko return; 240232ac5b9bSAndrei Emeltchenko } 240332ac5b9bSAndrei Emeltchenko 2404c5993de8SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 2405c5993de8SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_pkts_info)) { 24061da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 24071da177e4SLinus Torvalds return; 24081da177e4SLinus Torvalds } 24091da177e4SLinus Torvalds 2410c5993de8SAndrei Emeltchenko BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 2411c5993de8SAndrei Emeltchenko 2412613a1c0cSAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 2413613a1c0cSAndrei Emeltchenko struct hci_comp_pkts_info *info = &ev->handles[i]; 24141da177e4SLinus Torvalds struct hci_conn *conn; 24151da177e4SLinus Torvalds __u16 handle, count; 24161da177e4SLinus Torvalds 2417613a1c0cSAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 2418613a1c0cSAndrei Emeltchenko count = __le16_to_cpu(info->count); 24191da177e4SLinus Torvalds 24201da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 2421f4280918SAndrei Emeltchenko if (!conn) 2422f4280918SAndrei Emeltchenko continue; 2423f4280918SAndrei Emeltchenko 24241da177e4SLinus Torvalds conn->sent -= count; 24251da177e4SLinus Torvalds 2426f4280918SAndrei Emeltchenko switch (conn->type) { 2427f4280918SAndrei Emeltchenko case ACL_LINK: 242870f23020SAndrei Emeltchenko hdev->acl_cnt += count; 242970f23020SAndrei Emeltchenko if (hdev->acl_cnt > hdev->acl_pkts) 24301da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 2431f4280918SAndrei Emeltchenko break; 2432f4280918SAndrei Emeltchenko 2433f4280918SAndrei Emeltchenko case LE_LINK: 24346ed58ec5SVille Tervo if (hdev->le_pkts) { 24356ed58ec5SVille Tervo hdev->le_cnt += count; 24366ed58ec5SVille Tervo if (hdev->le_cnt > hdev->le_pkts) 24376ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 24386ed58ec5SVille Tervo } else { 24396ed58ec5SVille Tervo hdev->acl_cnt += count; 24406ed58ec5SVille Tervo if (hdev->acl_cnt > hdev->acl_pkts) 24416ed58ec5SVille Tervo hdev->acl_cnt = hdev->acl_pkts; 24426ed58ec5SVille Tervo } 2443f4280918SAndrei Emeltchenko break; 2444f4280918SAndrei Emeltchenko 2445f4280918SAndrei Emeltchenko case SCO_LINK: 244670f23020SAndrei Emeltchenko hdev->sco_cnt += count; 244770f23020SAndrei Emeltchenko if (hdev->sco_cnt > hdev->sco_pkts) 24485b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 2449f4280918SAndrei Emeltchenko break; 2450f4280918SAndrei Emeltchenko 2451f4280918SAndrei Emeltchenko default: 2452f4280918SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 2453f4280918SAndrei Emeltchenko break; 24541da177e4SLinus Torvalds } 24551da177e4SLinus Torvalds } 2456a9de9248SMarcel Holtmann 24573eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 24581da177e4SLinus Torvalds } 24591da177e4SLinus Torvalds 246076ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev, 246176ef7cf7SAndrei Emeltchenko __u16 handle) 246276ef7cf7SAndrei Emeltchenko { 246376ef7cf7SAndrei Emeltchenko struct hci_chan *chan; 246476ef7cf7SAndrei Emeltchenko 246576ef7cf7SAndrei Emeltchenko switch (hdev->dev_type) { 246676ef7cf7SAndrei Emeltchenko case HCI_BREDR: 246776ef7cf7SAndrei Emeltchenko return hci_conn_hash_lookup_handle(hdev, handle); 246876ef7cf7SAndrei Emeltchenko case HCI_AMP: 246976ef7cf7SAndrei Emeltchenko chan = hci_chan_lookup_handle(hdev, handle); 247076ef7cf7SAndrei Emeltchenko if (chan) 247176ef7cf7SAndrei Emeltchenko return chan->conn; 247276ef7cf7SAndrei Emeltchenko break; 247376ef7cf7SAndrei Emeltchenko default: 247476ef7cf7SAndrei Emeltchenko BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type); 247576ef7cf7SAndrei Emeltchenko break; 247676ef7cf7SAndrei Emeltchenko } 247776ef7cf7SAndrei Emeltchenko 247876ef7cf7SAndrei Emeltchenko return NULL; 247976ef7cf7SAndrei Emeltchenko } 248076ef7cf7SAndrei Emeltchenko 24816039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb) 248225e89e99SAndrei Emeltchenko { 248325e89e99SAndrei Emeltchenko struct hci_ev_num_comp_blocks *ev = (void *) skb->data; 248425e89e99SAndrei Emeltchenko int i; 248525e89e99SAndrei Emeltchenko 248625e89e99SAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) { 248725e89e99SAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 248825e89e99SAndrei Emeltchenko return; 248925e89e99SAndrei Emeltchenko } 249025e89e99SAndrei Emeltchenko 249125e89e99SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 249225e89e99SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_blocks_info)) { 249325e89e99SAndrei Emeltchenko BT_DBG("%s bad parameters", hdev->name); 249425e89e99SAndrei Emeltchenko return; 249525e89e99SAndrei Emeltchenko } 249625e89e99SAndrei Emeltchenko 249725e89e99SAndrei Emeltchenko BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks, 249825e89e99SAndrei Emeltchenko ev->num_hndl); 249925e89e99SAndrei Emeltchenko 250025e89e99SAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 250125e89e99SAndrei Emeltchenko struct hci_comp_blocks_info *info = &ev->handles[i]; 250276ef7cf7SAndrei Emeltchenko struct hci_conn *conn = NULL; 250325e89e99SAndrei Emeltchenko __u16 handle, block_count; 250425e89e99SAndrei Emeltchenko 250525e89e99SAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 250625e89e99SAndrei Emeltchenko block_count = __le16_to_cpu(info->blocks); 250725e89e99SAndrei Emeltchenko 250876ef7cf7SAndrei Emeltchenko conn = __hci_conn_lookup_handle(hdev, handle); 250925e89e99SAndrei Emeltchenko if (!conn) 251025e89e99SAndrei Emeltchenko continue; 251125e89e99SAndrei Emeltchenko 251225e89e99SAndrei Emeltchenko conn->sent -= block_count; 251325e89e99SAndrei Emeltchenko 251425e89e99SAndrei Emeltchenko switch (conn->type) { 251525e89e99SAndrei Emeltchenko case ACL_LINK: 2516bd1eb66bSAndrei Emeltchenko case AMP_LINK: 251725e89e99SAndrei Emeltchenko hdev->block_cnt += block_count; 251825e89e99SAndrei Emeltchenko if (hdev->block_cnt > hdev->num_blocks) 251925e89e99SAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 252025e89e99SAndrei Emeltchenko break; 252125e89e99SAndrei Emeltchenko 252225e89e99SAndrei Emeltchenko default: 252325e89e99SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 252425e89e99SAndrei Emeltchenko break; 252525e89e99SAndrei Emeltchenko } 252625e89e99SAndrei Emeltchenko } 252725e89e99SAndrei Emeltchenko 252825e89e99SAndrei Emeltchenko queue_work(hdev->workqueue, &hdev->tx_work); 252925e89e99SAndrei Emeltchenko } 253025e89e99SAndrei Emeltchenko 25316039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 25321da177e4SLinus Torvalds { 2533a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 253404837f64SMarcel Holtmann struct hci_conn *conn; 25351da177e4SLinus Torvalds 25369f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 25371da177e4SLinus Torvalds 25381da177e4SLinus Torvalds hci_dev_lock(hdev); 25391da177e4SLinus Torvalds 254004837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 254104837f64SMarcel Holtmann if (conn) { 254204837f64SMarcel Holtmann conn->mode = ev->mode; 254304837f64SMarcel Holtmann conn->interval = __le16_to_cpu(ev->interval); 254404837f64SMarcel Holtmann 25458fc9ced3SGustavo Padovan if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, 25468fc9ced3SGustavo Padovan &conn->flags)) { 254704837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 254858a681efSJohan Hedberg set_bit(HCI_CONN_POWER_SAVE, &conn->flags); 254904837f64SMarcel Holtmann else 255058a681efSJohan Hedberg clear_bit(HCI_CONN_POWER_SAVE, &conn->flags); 255104837f64SMarcel Holtmann } 2552e73439d8SMarcel Holtmann 255351a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 2554e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 255504837f64SMarcel Holtmann } 255604837f64SMarcel Holtmann 255704837f64SMarcel Holtmann hci_dev_unlock(hdev); 255804837f64SMarcel Holtmann } 255904837f64SMarcel Holtmann 25606039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 25611da177e4SLinus Torvalds { 2562052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 2563052b30b0SMarcel Holtmann struct hci_conn *conn; 2564052b30b0SMarcel Holtmann 2565a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2566052b30b0SMarcel Holtmann 2567052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2568052b30b0SMarcel Holtmann 2569052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2570b6f98044SWaldemar Rymarkiewicz if (!conn) 2571b6f98044SWaldemar Rymarkiewicz goto unlock; 2572b6f98044SWaldemar Rymarkiewicz 2573b6f98044SWaldemar Rymarkiewicz if (conn->state == BT_CONNECTED) { 2574052b30b0SMarcel Holtmann hci_conn_hold(conn); 2575052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 257676a68ba0SDavid Herrmann hci_conn_drop(conn); 2577052b30b0SMarcel Holtmann } 2578052b30b0SMarcel Holtmann 2579a8b2d5c2SJohan Hedberg if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags)) 258003b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 258103b555e1SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 2582a8b2d5c2SJohan Hedberg else if (test_bit(HCI_MGMT, &hdev->dev_flags)) { 2583a770bb5aSWaldemar Rymarkiewicz u8 secure; 2584a770bb5aSWaldemar Rymarkiewicz 2585a770bb5aSWaldemar Rymarkiewicz if (conn->pending_sec_level == BT_SECURITY_HIGH) 2586a770bb5aSWaldemar Rymarkiewicz secure = 1; 2587a770bb5aSWaldemar Rymarkiewicz else 2588a770bb5aSWaldemar Rymarkiewicz secure = 0; 2589a770bb5aSWaldemar Rymarkiewicz 2590744cf19eSJohan Hedberg mgmt_pin_code_request(hdev, &ev->bdaddr, secure); 2591a770bb5aSWaldemar Rymarkiewicz } 2592980e1a53SJohan Hedberg 2593b6f98044SWaldemar Rymarkiewicz unlock: 2594052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 25951da177e4SLinus Torvalds } 25961da177e4SLinus Torvalds 25976039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 25981da177e4SLinus Torvalds { 259955ed8ca1SJohan Hedberg struct hci_ev_link_key_req *ev = (void *) skb->data; 260055ed8ca1SJohan Hedberg struct hci_cp_link_key_reply cp; 260155ed8ca1SJohan Hedberg struct hci_conn *conn; 260255ed8ca1SJohan Hedberg struct link_key *key; 260355ed8ca1SJohan Hedberg 2604a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 260555ed8ca1SJohan Hedberg 2606034cbea0SAndrei Emeltchenko if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 260755ed8ca1SJohan Hedberg return; 260855ed8ca1SJohan Hedberg 260955ed8ca1SJohan Hedberg hci_dev_lock(hdev); 261055ed8ca1SJohan Hedberg 261155ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, &ev->bdaddr); 261255ed8ca1SJohan Hedberg if (!key) { 26136ed93dc6SAndrei Emeltchenko BT_DBG("%s link key not found for %pMR", hdev->name, 26146ed93dc6SAndrei Emeltchenko &ev->bdaddr); 261555ed8ca1SJohan Hedberg goto not_found; 261655ed8ca1SJohan Hedberg } 261755ed8ca1SJohan Hedberg 26186ed93dc6SAndrei Emeltchenko BT_DBG("%s found key type %u for %pMR", hdev->name, key->type, 26196ed93dc6SAndrei Emeltchenko &ev->bdaddr); 262055ed8ca1SJohan Hedberg 2621a8b2d5c2SJohan Hedberg if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) && 2622b6020ba0SWaldemar Rymarkiewicz key->type == HCI_LK_DEBUG_COMBINATION) { 262355ed8ca1SJohan Hedberg BT_DBG("%s ignoring debug key", hdev->name); 262455ed8ca1SJohan Hedberg goto not_found; 262555ed8ca1SJohan Hedberg } 262655ed8ca1SJohan Hedberg 262755ed8ca1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 262860b83f57SWaldemar Rymarkiewicz if (conn) { 262960b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_UNAUTH_COMBINATION && 2630807deac2SGustavo Padovan conn->auth_type != 0xff && (conn->auth_type & 0x01)) { 263155ed8ca1SJohan Hedberg BT_DBG("%s ignoring unauthenticated key", hdev->name); 263255ed8ca1SJohan Hedberg goto not_found; 263355ed8ca1SJohan Hedberg } 263455ed8ca1SJohan Hedberg 263560b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && 263660b83f57SWaldemar Rymarkiewicz conn->pending_sec_level == BT_SECURITY_HIGH) { 26378fc9ced3SGustavo Padovan BT_DBG("%s ignoring key unauthenticated for high security", 26388fc9ced3SGustavo Padovan hdev->name); 263960b83f57SWaldemar Rymarkiewicz goto not_found; 264060b83f57SWaldemar Rymarkiewicz } 264160b83f57SWaldemar Rymarkiewicz 264260b83f57SWaldemar Rymarkiewicz conn->key_type = key->type; 264360b83f57SWaldemar Rymarkiewicz conn->pin_length = key->pin_len; 264460b83f57SWaldemar Rymarkiewicz } 264560b83f57SWaldemar Rymarkiewicz 264655ed8ca1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 26479b3b4460SAndrei Emeltchenko memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE); 264855ed8ca1SJohan Hedberg 264955ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 265055ed8ca1SJohan Hedberg 265155ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 265255ed8ca1SJohan Hedberg 265355ed8ca1SJohan Hedberg return; 265455ed8ca1SJohan Hedberg 265555ed8ca1SJohan Hedberg not_found: 265655ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 265755ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 26581da177e4SLinus Torvalds } 26591da177e4SLinus Torvalds 26606039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 26611da177e4SLinus Torvalds { 2662052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 2663052b30b0SMarcel Holtmann struct hci_conn *conn; 266455ed8ca1SJohan Hedberg u8 pin_len = 0; 2665052b30b0SMarcel Holtmann 2666a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2667052b30b0SMarcel Holtmann 2668052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2669052b30b0SMarcel Holtmann 2670052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2671052b30b0SMarcel Holtmann if (conn) { 2672052b30b0SMarcel Holtmann hci_conn_hold(conn); 2673052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2674980e1a53SJohan Hedberg pin_len = conn->pin_length; 267513d39315SWaldemar Rymarkiewicz 267613d39315SWaldemar Rymarkiewicz if (ev->key_type != HCI_LK_CHANGED_COMBINATION) 267713d39315SWaldemar Rymarkiewicz conn->key_type = ev->key_type; 267813d39315SWaldemar Rymarkiewicz 267976a68ba0SDavid Herrmann hci_conn_drop(conn); 2680052b30b0SMarcel Holtmann } 2681052b30b0SMarcel Holtmann 2682034cbea0SAndrei Emeltchenko if (test_bit(HCI_MGMT, &hdev->dev_flags)) 2683d25e28abSJohan Hedberg hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, 268455ed8ca1SJohan Hedberg ev->key_type, pin_len); 268555ed8ca1SJohan Hedberg 2686052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 26871da177e4SLinus Torvalds } 26881da177e4SLinus Torvalds 26896039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 269004837f64SMarcel Holtmann { 2691a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 269204837f64SMarcel Holtmann struct hci_conn *conn; 269304837f64SMarcel Holtmann 26949f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 269504837f64SMarcel Holtmann 269604837f64SMarcel Holtmann hci_dev_lock(hdev); 269704837f64SMarcel Holtmann 269804837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 26991da177e4SLinus Torvalds if (conn && !ev->status) { 27001da177e4SLinus Torvalds struct inquiry_entry *ie; 27011da177e4SLinus Torvalds 2702cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2703cc11b9c1SAndrei Emeltchenko if (ie) { 27041da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 27051da177e4SLinus Torvalds ie->timestamp = jiffies; 27061da177e4SLinus Torvalds } 27071da177e4SLinus Torvalds } 27081da177e4SLinus Torvalds 27091da177e4SLinus Torvalds hci_dev_unlock(hdev); 27101da177e4SLinus Torvalds } 27111da177e4SLinus Torvalds 27126039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2713a8746417SMarcel Holtmann { 2714a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 2715a8746417SMarcel Holtmann struct hci_conn *conn; 2716a8746417SMarcel Holtmann 27179f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2718a8746417SMarcel Holtmann 2719a8746417SMarcel Holtmann hci_dev_lock(hdev); 2720a8746417SMarcel Holtmann 2721a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2722a8746417SMarcel Holtmann if (conn && !ev->status) 2723a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 2724a8746417SMarcel Holtmann 2725a8746417SMarcel Holtmann hci_dev_unlock(hdev); 2726a8746417SMarcel Holtmann } 2727a8746417SMarcel Holtmann 27286039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 272985a1e930SMarcel Holtmann { 2730a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 273185a1e930SMarcel Holtmann struct inquiry_entry *ie; 273285a1e930SMarcel Holtmann 273385a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 273485a1e930SMarcel Holtmann 273585a1e930SMarcel Holtmann hci_dev_lock(hdev); 273685a1e930SMarcel Holtmann 2737cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2738cc11b9c1SAndrei Emeltchenko if (ie) { 273985a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 274085a1e930SMarcel Holtmann ie->timestamp = jiffies; 274185a1e930SMarcel Holtmann } 274285a1e930SMarcel Holtmann 274385a1e930SMarcel Holtmann hci_dev_unlock(hdev); 274485a1e930SMarcel Holtmann } 274585a1e930SMarcel Holtmann 27466039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, 2747807deac2SGustavo Padovan struct sk_buff *skb) 2748a9de9248SMarcel Holtmann { 2749a9de9248SMarcel Holtmann struct inquiry_data data; 2750a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2751388fc8faSJohan Hedberg bool name_known, ssp; 2752a9de9248SMarcel Holtmann 2753a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2754a9de9248SMarcel Holtmann 2755a9de9248SMarcel Holtmann if (!num_rsp) 2756a9de9248SMarcel Holtmann return; 2757a9de9248SMarcel Holtmann 27581519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 27591519cc17SAndre Guedes return; 27601519cc17SAndre Guedes 2761a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2762a9de9248SMarcel Holtmann 2763a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 2764138d22efSSzymon Janc struct inquiry_info_with_rssi_and_pscan_mode *info; 2765138d22efSSzymon Janc info = (void *) (skb->data + 1); 2766a9de9248SMarcel Holtmann 2767e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2768a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2769a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2770a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2771a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 2772a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2773a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2774a9de9248SMarcel Holtmann data.rssi = info->rssi; 277541a96212SMarcel Holtmann data.ssp_mode = 0x00; 27763175405bSJohan Hedberg 27773175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 2778388fc8faSJohan Hedberg false, &ssp); 277948264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2780e17acd40SJohan Hedberg info->dev_class, info->rssi, 2781388fc8faSJohan Hedberg !name_known, ssp, NULL, 0); 2782a9de9248SMarcel Holtmann } 2783a9de9248SMarcel Holtmann } else { 2784a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 2785a9de9248SMarcel Holtmann 2786e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2787a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2788a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2789a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2790a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2791a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2792a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2793a9de9248SMarcel Holtmann data.rssi = info->rssi; 279441a96212SMarcel Holtmann data.ssp_mode = 0x00; 27953175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 2796388fc8faSJohan Hedberg false, &ssp); 279748264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2798e17acd40SJohan Hedberg info->dev_class, info->rssi, 2799388fc8faSJohan Hedberg !name_known, ssp, NULL, 0); 2800a9de9248SMarcel Holtmann } 2801a9de9248SMarcel Holtmann } 2802a9de9248SMarcel Holtmann 2803a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2804a9de9248SMarcel Holtmann } 2805a9de9248SMarcel Holtmann 28066039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev, 2807807deac2SGustavo Padovan struct sk_buff *skb) 2808a9de9248SMarcel Holtmann { 280941a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 281041a96212SMarcel Holtmann struct hci_conn *conn; 281141a96212SMarcel Holtmann 2812a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 281341a96212SMarcel Holtmann 281441a96212SMarcel Holtmann hci_dev_lock(hdev); 281541a96212SMarcel Holtmann 281641a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2817ccd556feSJohan Hedberg if (!conn) 2818ccd556feSJohan Hedberg goto unlock; 2819ccd556feSJohan Hedberg 2820cad718edSJohan Hedberg if (ev->page < HCI_MAX_PAGES) 2821cad718edSJohan Hedberg memcpy(conn->features[ev->page], ev->features, 8); 2822cad718edSJohan Hedberg 2823769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 282441a96212SMarcel Holtmann struct inquiry_entry *ie; 282541a96212SMarcel Holtmann 2826cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2827cc11b9c1SAndrei Emeltchenko if (ie) 282802b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 282941a96212SMarcel Holtmann 2830bbb0eadaSJaganath Kanakkassery if (ev->features[0] & LMP_HOST_SSP) { 283158a681efSJohan Hedberg set_bit(HCI_CONN_SSP_ENABLED, &conn->flags); 2832bbb0eadaSJaganath Kanakkassery } else { 2833bbb0eadaSJaganath Kanakkassery /* It is mandatory by the Bluetooth specification that 2834bbb0eadaSJaganath Kanakkassery * Extended Inquiry Results are only used when Secure 2835bbb0eadaSJaganath Kanakkassery * Simple Pairing is enabled, but some devices violate 2836bbb0eadaSJaganath Kanakkassery * this. 2837bbb0eadaSJaganath Kanakkassery * 2838bbb0eadaSJaganath Kanakkassery * To make these devices work, the internal SSP 2839bbb0eadaSJaganath Kanakkassery * enabled flag needs to be cleared if the remote host 2840bbb0eadaSJaganath Kanakkassery * features do not indicate SSP support */ 2841bbb0eadaSJaganath Kanakkassery clear_bit(HCI_CONN_SSP_ENABLED, &conn->flags); 2842bbb0eadaSJaganath Kanakkassery } 284341a96212SMarcel Holtmann } 284441a96212SMarcel Holtmann 2845ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2846ccd556feSJohan Hedberg goto unlock; 2847ccd556feSJohan Hedberg 2848671267bfSJohan Hedberg if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { 2849127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2850127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2851127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2852127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2853127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2854b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 2855b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 285608c79b61SJohan Hedberg conn->dst_type, 0, NULL, 0, 2857b644ba33SJohan Hedberg conn->dev_class); 2858392599b9SJohan Hedberg 2859127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2860769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2861769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 286276a68ba0SDavid Herrmann hci_conn_drop(conn); 2863769be974SMarcel Holtmann } 2864769be974SMarcel Holtmann 2865ccd556feSJohan Hedberg unlock: 286641a96212SMarcel Holtmann hci_dev_unlock(hdev); 2867a9de9248SMarcel Holtmann } 2868a9de9248SMarcel Holtmann 28696039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev, 2870807deac2SGustavo Padovan struct sk_buff *skb) 2871a9de9248SMarcel Holtmann { 2872b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 2873b6a0dc82SMarcel Holtmann struct hci_conn *conn; 2874b6a0dc82SMarcel Holtmann 28759f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2876b6a0dc82SMarcel Holtmann 2877b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 2878b6a0dc82SMarcel Holtmann 2879b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 28809dc0a3afSMarcel Holtmann if (!conn) { 28819dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 28829dc0a3afSMarcel Holtmann goto unlock; 28839dc0a3afSMarcel Holtmann 28849dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 2885b6a0dc82SMarcel Holtmann if (!conn) 2886b6a0dc82SMarcel Holtmann goto unlock; 2887b6a0dc82SMarcel Holtmann 28889dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 28899dc0a3afSMarcel Holtmann } 28909dc0a3afSMarcel Holtmann 2891732547f9SMarcel Holtmann switch (ev->status) { 2892732547f9SMarcel Holtmann case 0x00: 2893732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 2894732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 2895732547f9SMarcel Holtmann 2896732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 2897732547f9SMarcel Holtmann break; 2898732547f9SMarcel Holtmann 28991a4c958cSFrédéric Dalleau case 0x0d: /* Connection Rejected due to Limited Resources */ 2900705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 2901732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 29021038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 2903732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 29042dea632fSFrédéric Dalleau if (conn->out) { 2905efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 2906efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 29072dea632fSFrédéric Dalleau if (hci_setup_sync(conn, conn->link->handle)) 2908efc7688bSMarcel Holtmann goto unlock; 2909efc7688bSMarcel Holtmann } 2910732547f9SMarcel Holtmann /* fall through */ 2911efc7688bSMarcel Holtmann 2912732547f9SMarcel Holtmann default: 2913b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 2914732547f9SMarcel Holtmann break; 2915732547f9SMarcel Holtmann } 2916b6a0dc82SMarcel Holtmann 2917b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2918b6a0dc82SMarcel Holtmann if (ev->status) 2919b6a0dc82SMarcel Holtmann hci_conn_del(conn); 2920b6a0dc82SMarcel Holtmann 2921b6a0dc82SMarcel Holtmann unlock: 2922b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 2923a9de9248SMarcel Holtmann } 2924a9de9248SMarcel Holtmann 29256039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, 2926807deac2SGustavo Padovan struct sk_buff *skb) 2927a9de9248SMarcel Holtmann { 2928a9de9248SMarcel Holtmann struct inquiry_data data; 2929a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 2930a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 29319d939d94SVishal Agarwal size_t eir_len; 2932a9de9248SMarcel Holtmann 2933a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2934a9de9248SMarcel Holtmann 2935a9de9248SMarcel Holtmann if (!num_rsp) 2936a9de9248SMarcel Holtmann return; 2937a9de9248SMarcel Holtmann 29381519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 29391519cc17SAndre Guedes return; 29401519cc17SAndre Guedes 2941a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2942a9de9248SMarcel Holtmann 2943e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2944388fc8faSJohan Hedberg bool name_known, ssp; 2945561aafbcSJohan Hedberg 2946a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2947a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2948a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2949a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2950a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2951a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2952a9de9248SMarcel Holtmann data.rssi = info->rssi; 295341a96212SMarcel Holtmann data.ssp_mode = 0x01; 2954561aafbcSJohan Hedberg 2955a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 29564ddb1930SJohan Hedberg name_known = eir_has_data_type(info->data, 29574ddb1930SJohan Hedberg sizeof(info->data), 29584ddb1930SJohan Hedberg EIR_NAME_COMPLETE); 2959561aafbcSJohan Hedberg else 2960561aafbcSJohan Hedberg name_known = true; 2961561aafbcSJohan Hedberg 2962388fc8faSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, name_known, 2963388fc8faSJohan Hedberg &ssp); 29649d939d94SVishal Agarwal eir_len = eir_get_length(info->data, sizeof(info->data)); 296548264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 296604124681SGustavo F. Padovan info->dev_class, info->rssi, !name_known, 29679d939d94SVishal Agarwal ssp, info->data, eir_len); 2968a9de9248SMarcel Holtmann } 2969a9de9248SMarcel Holtmann 2970a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2971a9de9248SMarcel Holtmann } 2972a9de9248SMarcel Holtmann 29731c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev, 29741c2e0041SJohan Hedberg struct sk_buff *skb) 29751c2e0041SJohan Hedberg { 29761c2e0041SJohan Hedberg struct hci_ev_key_refresh_complete *ev = (void *) skb->data; 29771c2e0041SJohan Hedberg struct hci_conn *conn; 29781c2e0041SJohan Hedberg 29799f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status, 29801c2e0041SJohan Hedberg __le16_to_cpu(ev->handle)); 29811c2e0041SJohan Hedberg 29821c2e0041SJohan Hedberg hci_dev_lock(hdev); 29831c2e0041SJohan Hedberg 29841c2e0041SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 29851c2e0041SJohan Hedberg if (!conn) 29861c2e0041SJohan Hedberg goto unlock; 29871c2e0041SJohan Hedberg 29881c2e0041SJohan Hedberg if (!ev->status) 29891c2e0041SJohan Hedberg conn->sec_level = conn->pending_sec_level; 29901c2e0041SJohan Hedberg 29911c2e0041SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 29921c2e0041SJohan Hedberg 29931c2e0041SJohan Hedberg if (ev->status && conn->state == BT_CONNECTED) { 2994bed71748SAndre Guedes hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); 299576a68ba0SDavid Herrmann hci_conn_drop(conn); 29961c2e0041SJohan Hedberg goto unlock; 29971c2e0041SJohan Hedberg } 29981c2e0041SJohan Hedberg 29991c2e0041SJohan Hedberg if (conn->state == BT_CONFIG) { 30001c2e0041SJohan Hedberg if (!ev->status) 30011c2e0041SJohan Hedberg conn->state = BT_CONNECTED; 30021c2e0041SJohan Hedberg 30031c2e0041SJohan Hedberg hci_proto_connect_cfm(conn, ev->status); 300476a68ba0SDavid Herrmann hci_conn_drop(conn); 30051c2e0041SJohan Hedberg } else { 30061c2e0041SJohan Hedberg hci_auth_cfm(conn, ev->status); 30071c2e0041SJohan Hedberg 30081c2e0041SJohan Hedberg hci_conn_hold(conn); 30091c2e0041SJohan Hedberg conn->disc_timeout = HCI_DISCONN_TIMEOUT; 301076a68ba0SDavid Herrmann hci_conn_drop(conn); 30111c2e0041SJohan Hedberg } 30121c2e0041SJohan Hedberg 30131c2e0041SJohan Hedberg unlock: 30141c2e0041SJohan Hedberg hci_dev_unlock(hdev); 30151c2e0041SJohan Hedberg } 30161c2e0041SJohan Hedberg 30176039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn) 301817fa4b9dSJohan Hedberg { 301917fa4b9dSJohan Hedberg /* If remote requests dedicated bonding follow that lead */ 3020acabae96SMikel Astiz if (conn->remote_auth == HCI_AT_DEDICATED_BONDING || 3021acabae96SMikel Astiz conn->remote_auth == HCI_AT_DEDICATED_BONDING_MITM) { 302217fa4b9dSJohan Hedberg /* If both remote and local IO capabilities allow MITM 302317fa4b9dSJohan Hedberg * protection then require it, otherwise don't */ 3024acabae96SMikel Astiz if (conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT || 3025acabae96SMikel Astiz conn->io_capability == HCI_IO_NO_INPUT_OUTPUT) 3026acabae96SMikel Astiz return HCI_AT_DEDICATED_BONDING; 302717fa4b9dSJohan Hedberg else 3028acabae96SMikel Astiz return HCI_AT_DEDICATED_BONDING_MITM; 302917fa4b9dSJohan Hedberg } 303017fa4b9dSJohan Hedberg 303117fa4b9dSJohan Hedberg /* If remote requests no-bonding follow that lead */ 3032acabae96SMikel Astiz if (conn->remote_auth == HCI_AT_NO_BONDING || 3033acabae96SMikel Astiz conn->remote_auth == HCI_AT_NO_BONDING_MITM) 303458797bf7SWaldemar Rymarkiewicz return conn->remote_auth | (conn->auth_type & 0x01); 303517fa4b9dSJohan Hedberg 303617fa4b9dSJohan Hedberg return conn->auth_type; 303717fa4b9dSJohan Hedberg } 303817fa4b9dSJohan Hedberg 30396039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 30400493684eSMarcel Holtmann { 30410493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 30420493684eSMarcel Holtmann struct hci_conn *conn; 30430493684eSMarcel Holtmann 30440493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 30450493684eSMarcel Holtmann 30460493684eSMarcel Holtmann hci_dev_lock(hdev); 30470493684eSMarcel Holtmann 30480493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 304903b555e1SJohan Hedberg if (!conn) 305003b555e1SJohan Hedberg goto unlock; 305103b555e1SJohan Hedberg 30520493684eSMarcel Holtmann hci_conn_hold(conn); 30530493684eSMarcel Holtmann 3054a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 305503b555e1SJohan Hedberg goto unlock; 305603b555e1SJohan Hedberg 3057a8b2d5c2SJohan Hedberg if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) || 305803b555e1SJohan Hedberg (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 305917fa4b9dSJohan Hedberg struct hci_cp_io_capability_reply cp; 306017fa4b9dSJohan Hedberg 306117fa4b9dSJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 30627a7f1e7cSHemant Gupta /* Change the IO capability from KeyboardDisplay 30637a7f1e7cSHemant Gupta * to DisplayYesNo as it is not supported by BT spec. */ 30647a7f1e7cSHemant Gupta cp.capability = (conn->io_capability == 0x04) ? 3065a767631aSMikel Astiz HCI_IO_DISPLAY_YESNO : conn->io_capability; 30667cbc9bd9SJohan Hedberg conn->auth_type = hci_get_auth_req(conn); 30677cbc9bd9SJohan Hedberg cp.authentication = conn->auth_type; 306817fa4b9dSJohan Hedberg 30698fc9ced3SGustavo Padovan if (hci_find_remote_oob_data(hdev, &conn->dst) && 30708fc9ced3SGustavo Padovan (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags))) 3071ce85ee13SSzymon Janc cp.oob_data = 0x01; 3072ce85ee13SSzymon Janc else 3073ce85ee13SSzymon Janc cp.oob_data = 0x00; 3074ce85ee13SSzymon Janc 307517fa4b9dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, 307617fa4b9dSJohan Hedberg sizeof(cp), &cp); 307703b555e1SJohan Hedberg } else { 307803b555e1SJohan Hedberg struct hci_cp_io_capability_neg_reply cp; 307903b555e1SJohan Hedberg 308003b555e1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 30819f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED; 308203b555e1SJohan Hedberg 308303b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 308403b555e1SJohan Hedberg sizeof(cp), &cp); 308503b555e1SJohan Hedberg } 308603b555e1SJohan Hedberg 308703b555e1SJohan Hedberg unlock: 308803b555e1SJohan Hedberg hci_dev_unlock(hdev); 308903b555e1SJohan Hedberg } 309003b555e1SJohan Hedberg 30916039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 309203b555e1SJohan Hedberg { 309303b555e1SJohan Hedberg struct hci_ev_io_capa_reply *ev = (void *) skb->data; 309403b555e1SJohan Hedberg struct hci_conn *conn; 309503b555e1SJohan Hedberg 309603b555e1SJohan Hedberg BT_DBG("%s", hdev->name); 309703b555e1SJohan Hedberg 309803b555e1SJohan Hedberg hci_dev_lock(hdev); 309903b555e1SJohan Hedberg 310003b555e1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 310103b555e1SJohan Hedberg if (!conn) 310203b555e1SJohan Hedberg goto unlock; 310303b555e1SJohan Hedberg 310403b555e1SJohan Hedberg conn->remote_cap = ev->capability; 310503b555e1SJohan Hedberg conn->remote_auth = ev->authentication; 310658a681efSJohan Hedberg if (ev->oob_data) 310758a681efSJohan Hedberg set_bit(HCI_CONN_REMOTE_OOB, &conn->flags); 310803b555e1SJohan Hedberg 310903b555e1SJohan Hedberg unlock: 31100493684eSMarcel Holtmann hci_dev_unlock(hdev); 31110493684eSMarcel Holtmann } 31120493684eSMarcel Holtmann 31136039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev, 3114a5c29683SJohan Hedberg struct sk_buff *skb) 3115a5c29683SJohan Hedberg { 3116a5c29683SJohan Hedberg struct hci_ev_user_confirm_req *ev = (void *) skb->data; 311755bc1a37SJohan Hedberg int loc_mitm, rem_mitm, confirm_hint = 0; 31187a828908SJohan Hedberg struct hci_conn *conn; 3119a5c29683SJohan Hedberg 3120a5c29683SJohan Hedberg BT_DBG("%s", hdev->name); 3121a5c29683SJohan Hedberg 3122a5c29683SJohan Hedberg hci_dev_lock(hdev); 3123a5c29683SJohan Hedberg 3124a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 31257a828908SJohan Hedberg goto unlock; 31267a828908SJohan Hedberg 31277a828908SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 31287a828908SJohan Hedberg if (!conn) 31297a828908SJohan Hedberg goto unlock; 31307a828908SJohan Hedberg 31317a828908SJohan Hedberg loc_mitm = (conn->auth_type & 0x01); 31327a828908SJohan Hedberg rem_mitm = (conn->remote_auth & 0x01); 31337a828908SJohan Hedberg 31347a828908SJohan Hedberg /* If we require MITM but the remote device can't provide that 31357a828908SJohan Hedberg * (it has NoInputNoOutput) then reject the confirmation 31367a828908SJohan Hedberg * request. The only exception is when we're dedicated bonding 31377a828908SJohan Hedberg * initiators (connect_cfm_cb set) since then we always have the MITM 31387a828908SJohan Hedberg * bit set. */ 3139a767631aSMikel Astiz if (!conn->connect_cfm_cb && loc_mitm && 3140a767631aSMikel Astiz conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) { 31417a828908SJohan Hedberg BT_DBG("Rejecting request: remote device can't provide MITM"); 31427a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, 31437a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 31447a828908SJohan Hedberg goto unlock; 31457a828908SJohan Hedberg } 31467a828908SJohan Hedberg 31477a828908SJohan Hedberg /* If no side requires MITM protection; auto-accept */ 3148a767631aSMikel Astiz if ((!loc_mitm || conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) && 3149a767631aSMikel Astiz (!rem_mitm || conn->io_capability == HCI_IO_NO_INPUT_OUTPUT)) { 315055bc1a37SJohan Hedberg 315155bc1a37SJohan Hedberg /* If we're not the initiators request authorization to 315255bc1a37SJohan Hedberg * proceed from user space (mgmt_user_confirm with 315355bc1a37SJohan Hedberg * confirm_hint set to 1). */ 315451a8efd7SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 315555bc1a37SJohan Hedberg BT_DBG("Confirming auto-accept as acceptor"); 315655bc1a37SJohan Hedberg confirm_hint = 1; 315755bc1a37SJohan Hedberg goto confirm; 315855bc1a37SJohan Hedberg } 315955bc1a37SJohan Hedberg 31609f61656aSJohan Hedberg BT_DBG("Auto-accept of user confirmation with %ums delay", 31619f61656aSJohan Hedberg hdev->auto_accept_delay); 31629f61656aSJohan Hedberg 31639f61656aSJohan Hedberg if (hdev->auto_accept_delay > 0) { 31649f61656aSJohan Hedberg int delay = msecs_to_jiffies(hdev->auto_accept_delay); 31659f61656aSJohan Hedberg mod_timer(&conn->auto_accept_timer, jiffies + delay); 31669f61656aSJohan Hedberg goto unlock; 31679f61656aSJohan Hedberg } 31689f61656aSJohan Hedberg 31697a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, 31707a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 31717a828908SJohan Hedberg goto unlock; 31727a828908SJohan Hedberg } 31737a828908SJohan Hedberg 317455bc1a37SJohan Hedberg confirm: 3175272d90dfSJohan Hedberg mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey, 317655bc1a37SJohan Hedberg confirm_hint); 3177a5c29683SJohan Hedberg 31787a828908SJohan Hedberg unlock: 3179a5c29683SJohan Hedberg hci_dev_unlock(hdev); 3180a5c29683SJohan Hedberg } 3181a5c29683SJohan Hedberg 31826039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev, 31831143d458SBrian Gix struct sk_buff *skb) 31841143d458SBrian Gix { 31851143d458SBrian Gix struct hci_ev_user_passkey_req *ev = (void *) skb->data; 31861143d458SBrian Gix 31871143d458SBrian Gix BT_DBG("%s", hdev->name); 31881143d458SBrian Gix 3189a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 3190272d90dfSJohan Hedberg mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); 31911143d458SBrian Gix } 31921143d458SBrian Gix 319392a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev, 319492a25256SJohan Hedberg struct sk_buff *skb) 319592a25256SJohan Hedberg { 319692a25256SJohan Hedberg struct hci_ev_user_passkey_notify *ev = (void *) skb->data; 319792a25256SJohan Hedberg struct hci_conn *conn; 319892a25256SJohan Hedberg 319992a25256SJohan Hedberg BT_DBG("%s", hdev->name); 320092a25256SJohan Hedberg 320192a25256SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 320292a25256SJohan Hedberg if (!conn) 320392a25256SJohan Hedberg return; 320492a25256SJohan Hedberg 320592a25256SJohan Hedberg conn->passkey_notify = __le32_to_cpu(ev->passkey); 320692a25256SJohan Hedberg conn->passkey_entered = 0; 320792a25256SJohan Hedberg 320892a25256SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 320992a25256SJohan Hedberg mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, 321092a25256SJohan Hedberg conn->dst_type, conn->passkey_notify, 321192a25256SJohan Hedberg conn->passkey_entered); 321292a25256SJohan Hedberg } 321392a25256SJohan Hedberg 321492a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 321592a25256SJohan Hedberg { 321692a25256SJohan Hedberg struct hci_ev_keypress_notify *ev = (void *) skb->data; 321792a25256SJohan Hedberg struct hci_conn *conn; 321892a25256SJohan Hedberg 321992a25256SJohan Hedberg BT_DBG("%s", hdev->name); 322092a25256SJohan Hedberg 322192a25256SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 322292a25256SJohan Hedberg if (!conn) 322392a25256SJohan Hedberg return; 322492a25256SJohan Hedberg 322592a25256SJohan Hedberg switch (ev->type) { 322692a25256SJohan Hedberg case HCI_KEYPRESS_STARTED: 322792a25256SJohan Hedberg conn->passkey_entered = 0; 322892a25256SJohan Hedberg return; 322992a25256SJohan Hedberg 323092a25256SJohan Hedberg case HCI_KEYPRESS_ENTERED: 323192a25256SJohan Hedberg conn->passkey_entered++; 323292a25256SJohan Hedberg break; 323392a25256SJohan Hedberg 323492a25256SJohan Hedberg case HCI_KEYPRESS_ERASED: 323592a25256SJohan Hedberg conn->passkey_entered--; 323692a25256SJohan Hedberg break; 323792a25256SJohan Hedberg 323892a25256SJohan Hedberg case HCI_KEYPRESS_CLEARED: 323992a25256SJohan Hedberg conn->passkey_entered = 0; 324092a25256SJohan Hedberg break; 324192a25256SJohan Hedberg 324292a25256SJohan Hedberg case HCI_KEYPRESS_COMPLETED: 324392a25256SJohan Hedberg return; 324492a25256SJohan Hedberg } 324592a25256SJohan Hedberg 324692a25256SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 324792a25256SJohan Hedberg mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, 324892a25256SJohan Hedberg conn->dst_type, conn->passkey_notify, 324992a25256SJohan Hedberg conn->passkey_entered); 325092a25256SJohan Hedberg } 325192a25256SJohan Hedberg 32526039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev, 3253807deac2SGustavo Padovan struct sk_buff *skb) 32540493684eSMarcel Holtmann { 32550493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 32560493684eSMarcel Holtmann struct hci_conn *conn; 32570493684eSMarcel Holtmann 32580493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 32590493684eSMarcel Holtmann 32600493684eSMarcel Holtmann hci_dev_lock(hdev); 32610493684eSMarcel Holtmann 32620493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 32632a611692SJohan Hedberg if (!conn) 32642a611692SJohan Hedberg goto unlock; 32652a611692SJohan Hedberg 32662a611692SJohan Hedberg /* To avoid duplicate auth_failed events to user space we check 32672a611692SJohan Hedberg * the HCI_CONN_AUTH_PEND flag which will be set if we 32682a611692SJohan Hedberg * initiated the authentication. A traditional auth_complete 32692a611692SJohan Hedberg * event gets always produced as initiator and is also mapped to 32702a611692SJohan Hedberg * the mgmt_auth_failed event */ 3271fa1bd918SMikel Astiz if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status) 3272bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 3273bab73cb6SJohan Hedberg ev->status); 32742a611692SJohan Hedberg 327576a68ba0SDavid Herrmann hci_conn_drop(conn); 32760493684eSMarcel Holtmann 32772a611692SJohan Hedberg unlock: 32780493684eSMarcel Holtmann hci_dev_unlock(hdev); 32790493684eSMarcel Holtmann } 32800493684eSMarcel Holtmann 32816039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev, 3282807deac2SGustavo Padovan struct sk_buff *skb) 328341a96212SMarcel Holtmann { 328441a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 328541a96212SMarcel Holtmann struct inquiry_entry *ie; 3286cad718edSJohan Hedberg struct hci_conn *conn; 328741a96212SMarcel Holtmann 328841a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 328941a96212SMarcel Holtmann 329041a96212SMarcel Holtmann hci_dev_lock(hdev); 329141a96212SMarcel Holtmann 3292cad718edSJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 3293cad718edSJohan Hedberg if (conn) 3294cad718edSJohan Hedberg memcpy(conn->features[1], ev->features, 8); 3295cad718edSJohan Hedberg 3296cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 3297cc11b9c1SAndrei Emeltchenko if (ie) 329802b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 329941a96212SMarcel Holtmann 330041a96212SMarcel Holtmann hci_dev_unlock(hdev); 330141a96212SMarcel Holtmann } 330241a96212SMarcel Holtmann 33036039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev, 33042763eda6SSzymon Janc struct sk_buff *skb) 33052763eda6SSzymon Janc { 33062763eda6SSzymon Janc struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; 33072763eda6SSzymon Janc struct oob_data *data; 33082763eda6SSzymon Janc 33092763eda6SSzymon Janc BT_DBG("%s", hdev->name); 33102763eda6SSzymon Janc 33112763eda6SSzymon Janc hci_dev_lock(hdev); 33122763eda6SSzymon Janc 3313a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 3314e1ba1f15SSzymon Janc goto unlock; 3315e1ba1f15SSzymon Janc 33162763eda6SSzymon Janc data = hci_find_remote_oob_data(hdev, &ev->bdaddr); 33172763eda6SSzymon Janc if (data) { 33182763eda6SSzymon Janc struct hci_cp_remote_oob_data_reply cp; 33192763eda6SSzymon Janc 33202763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 33212763eda6SSzymon Janc memcpy(cp.hash, data->hash, sizeof(cp.hash)); 33222763eda6SSzymon Janc memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); 33232763eda6SSzymon Janc 33242763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), 33252763eda6SSzymon Janc &cp); 33262763eda6SSzymon Janc } else { 33272763eda6SSzymon Janc struct hci_cp_remote_oob_data_neg_reply cp; 33282763eda6SSzymon Janc 33292763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 33302763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), 33312763eda6SSzymon Janc &cp); 33322763eda6SSzymon Janc } 33332763eda6SSzymon Janc 3334e1ba1f15SSzymon Janc unlock: 33352763eda6SSzymon Janc hci_dev_unlock(hdev); 33362763eda6SSzymon Janc } 33372763eda6SSzymon Janc 3338d5e91192SAndrei Emeltchenko static void hci_phy_link_complete_evt(struct hci_dev *hdev, 3339d5e91192SAndrei Emeltchenko struct sk_buff *skb) 3340d5e91192SAndrei Emeltchenko { 3341d5e91192SAndrei Emeltchenko struct hci_ev_phy_link_complete *ev = (void *) skb->data; 3342d5e91192SAndrei Emeltchenko struct hci_conn *hcon, *bredr_hcon; 3343d5e91192SAndrei Emeltchenko 3344d5e91192SAndrei Emeltchenko BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle, 3345d5e91192SAndrei Emeltchenko ev->status); 3346d5e91192SAndrei Emeltchenko 3347d5e91192SAndrei Emeltchenko hci_dev_lock(hdev); 3348d5e91192SAndrei Emeltchenko 3349d5e91192SAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 3350d5e91192SAndrei Emeltchenko if (!hcon) { 3351d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 3352d5e91192SAndrei Emeltchenko return; 3353d5e91192SAndrei Emeltchenko } 3354d5e91192SAndrei Emeltchenko 3355d5e91192SAndrei Emeltchenko if (ev->status) { 3356d5e91192SAndrei Emeltchenko hci_conn_del(hcon); 3357d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 3358d5e91192SAndrei Emeltchenko return; 3359d5e91192SAndrei Emeltchenko } 3360d5e91192SAndrei Emeltchenko 3361d5e91192SAndrei Emeltchenko bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon; 3362d5e91192SAndrei Emeltchenko 3363d5e91192SAndrei Emeltchenko hcon->state = BT_CONNECTED; 3364d5e91192SAndrei Emeltchenko bacpy(&hcon->dst, &bredr_hcon->dst); 3365d5e91192SAndrei Emeltchenko 3366d5e91192SAndrei Emeltchenko hci_conn_hold(hcon); 3367d5e91192SAndrei Emeltchenko hcon->disc_timeout = HCI_DISCONN_TIMEOUT; 336876a68ba0SDavid Herrmann hci_conn_drop(hcon); 3369d5e91192SAndrei Emeltchenko 3370d5e91192SAndrei Emeltchenko hci_conn_add_sysfs(hcon); 3371d5e91192SAndrei Emeltchenko 3372cf70ff22SAndrei Emeltchenko amp_physical_cfm(bredr_hcon, hcon); 3373cf70ff22SAndrei Emeltchenko 3374d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 3375d5e91192SAndrei Emeltchenko } 3376d5e91192SAndrei Emeltchenko 337727695fb4SAndrei Emeltchenko static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 337827695fb4SAndrei Emeltchenko { 337927695fb4SAndrei Emeltchenko struct hci_ev_logical_link_complete *ev = (void *) skb->data; 338027695fb4SAndrei Emeltchenko struct hci_conn *hcon; 338127695fb4SAndrei Emeltchenko struct hci_chan *hchan; 338227695fb4SAndrei Emeltchenko struct amp_mgr *mgr; 338327695fb4SAndrei Emeltchenko 338427695fb4SAndrei Emeltchenko BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x", 338527695fb4SAndrei Emeltchenko hdev->name, le16_to_cpu(ev->handle), ev->phy_handle, 338627695fb4SAndrei Emeltchenko ev->status); 338727695fb4SAndrei Emeltchenko 338827695fb4SAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 338927695fb4SAndrei Emeltchenko if (!hcon) 339027695fb4SAndrei Emeltchenko return; 339127695fb4SAndrei Emeltchenko 339227695fb4SAndrei Emeltchenko /* Create AMP hchan */ 339327695fb4SAndrei Emeltchenko hchan = hci_chan_create(hcon); 339427695fb4SAndrei Emeltchenko if (!hchan) 339527695fb4SAndrei Emeltchenko return; 339627695fb4SAndrei Emeltchenko 339727695fb4SAndrei Emeltchenko hchan->handle = le16_to_cpu(ev->handle); 339827695fb4SAndrei Emeltchenko 339927695fb4SAndrei Emeltchenko BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan); 340027695fb4SAndrei Emeltchenko 340127695fb4SAndrei Emeltchenko mgr = hcon->amp_mgr; 340227695fb4SAndrei Emeltchenko if (mgr && mgr->bredr_chan) { 340327695fb4SAndrei Emeltchenko struct l2cap_chan *bredr_chan = mgr->bredr_chan; 340427695fb4SAndrei Emeltchenko 340527695fb4SAndrei Emeltchenko l2cap_chan_lock(bredr_chan); 340627695fb4SAndrei Emeltchenko 340727695fb4SAndrei Emeltchenko bredr_chan->conn->mtu = hdev->block_mtu; 340827695fb4SAndrei Emeltchenko l2cap_logical_cfm(bredr_chan, hchan, 0); 340927695fb4SAndrei Emeltchenko hci_conn_hold(hcon); 341027695fb4SAndrei Emeltchenko 341127695fb4SAndrei Emeltchenko l2cap_chan_unlock(bredr_chan); 341227695fb4SAndrei Emeltchenko } 341327695fb4SAndrei Emeltchenko } 341427695fb4SAndrei Emeltchenko 3415606e2a10SAndrei Emeltchenko static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev, 3416606e2a10SAndrei Emeltchenko struct sk_buff *skb) 3417606e2a10SAndrei Emeltchenko { 3418606e2a10SAndrei Emeltchenko struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data; 3419606e2a10SAndrei Emeltchenko struct hci_chan *hchan; 3420606e2a10SAndrei Emeltchenko 3421606e2a10SAndrei Emeltchenko BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name, 3422606e2a10SAndrei Emeltchenko le16_to_cpu(ev->handle), ev->status); 3423606e2a10SAndrei Emeltchenko 3424606e2a10SAndrei Emeltchenko if (ev->status) 3425606e2a10SAndrei Emeltchenko return; 3426606e2a10SAndrei Emeltchenko 3427606e2a10SAndrei Emeltchenko hci_dev_lock(hdev); 3428606e2a10SAndrei Emeltchenko 3429606e2a10SAndrei Emeltchenko hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle)); 3430606e2a10SAndrei Emeltchenko if (!hchan) 3431606e2a10SAndrei Emeltchenko goto unlock; 3432606e2a10SAndrei Emeltchenko 3433606e2a10SAndrei Emeltchenko amp_destroy_logical_link(hchan, ev->reason); 3434606e2a10SAndrei Emeltchenko 3435606e2a10SAndrei Emeltchenko unlock: 3436606e2a10SAndrei Emeltchenko hci_dev_unlock(hdev); 3437606e2a10SAndrei Emeltchenko } 3438606e2a10SAndrei Emeltchenko 34399eef6b3aSAndrei Emeltchenko static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev, 34409eef6b3aSAndrei Emeltchenko struct sk_buff *skb) 34419eef6b3aSAndrei Emeltchenko { 34429eef6b3aSAndrei Emeltchenko struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data; 34439eef6b3aSAndrei Emeltchenko struct hci_conn *hcon; 34449eef6b3aSAndrei Emeltchenko 34459eef6b3aSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 34469eef6b3aSAndrei Emeltchenko 34479eef6b3aSAndrei Emeltchenko if (ev->status) 34489eef6b3aSAndrei Emeltchenko return; 34499eef6b3aSAndrei Emeltchenko 34509eef6b3aSAndrei Emeltchenko hci_dev_lock(hdev); 34519eef6b3aSAndrei Emeltchenko 34529eef6b3aSAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 34539eef6b3aSAndrei Emeltchenko if (hcon) { 34549eef6b3aSAndrei Emeltchenko hcon->state = BT_CLOSED; 34559eef6b3aSAndrei Emeltchenko hci_conn_del(hcon); 34569eef6b3aSAndrei Emeltchenko } 34579eef6b3aSAndrei Emeltchenko 34589eef6b3aSAndrei Emeltchenko hci_dev_unlock(hdev); 34599eef6b3aSAndrei Emeltchenko } 34609eef6b3aSAndrei Emeltchenko 34616039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 3462fcd89c09SVille Tervo { 3463fcd89c09SVille Tervo struct hci_ev_le_conn_complete *ev = (void *) skb->data; 3464fcd89c09SVille Tervo struct hci_conn *conn; 3465fcd89c09SVille Tervo 34669f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 3467fcd89c09SVille Tervo 3468fcd89c09SVille Tervo hci_dev_lock(hdev); 3469fcd89c09SVille Tervo 34704f72b329SAndrzej Kaczmarek conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); 3471b62f328bSVille Tervo if (!conn) { 3472b62f328bSVille Tervo conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); 3473b62f328bSVille Tervo if (!conn) { 3474b62f328bSVille Tervo BT_ERR("No memory for new connection"); 3475230fd16aSAndre Guedes goto unlock; 3476b62f328bSVille Tervo } 347729b7988aSAndre Guedes 347829b7988aSAndre Guedes conn->dst_type = ev->bdaddr_type; 3479b9b343d2SAndre Guedes 3480b9b343d2SAndre Guedes if (ev->role == LE_CONN_ROLE_MASTER) { 3481b9b343d2SAndre Guedes conn->out = true; 3482b9b343d2SAndre Guedes conn->link_mode |= HCI_LM_MASTER; 3483b9b343d2SAndre Guedes } 3484b62f328bSVille Tervo } 3485fcd89c09SVille Tervo 3486cd17decbSAndre Guedes if (ev->status) { 3487cd17decbSAndre Guedes mgmt_connect_failed(hdev, &conn->dst, conn->type, 3488cd17decbSAndre Guedes conn->dst_type, ev->status); 3489cd17decbSAndre Guedes hci_proto_connect_cfm(conn, ev->status); 3490cd17decbSAndre Guedes conn->state = BT_CLOSED; 3491cd17decbSAndre Guedes hci_conn_del(conn); 3492cd17decbSAndre Guedes goto unlock; 3493cd17decbSAndre Guedes } 3494cd17decbSAndre Guedes 3495b644ba33SJohan Hedberg if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 3496b644ba33SJohan Hedberg mgmt_device_connected(hdev, &ev->bdaddr, conn->type, 349795b23582SSzymon Janc conn->dst_type, 0, NULL, 0, NULL); 349883bc71b4SVinicius Costa Gomes 34997b5c0d52SVinicius Costa Gomes conn->sec_level = BT_SECURITY_LOW; 3500fcd89c09SVille Tervo conn->handle = __le16_to_cpu(ev->handle); 3501fcd89c09SVille Tervo conn->state = BT_CONNECTED; 3502fcd89c09SVille Tervo 3503fcd89c09SVille Tervo hci_conn_add_sysfs(conn); 3504fcd89c09SVille Tervo 3505fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 3506fcd89c09SVille Tervo 3507fcd89c09SVille Tervo unlock: 3508fcd89c09SVille Tervo hci_dev_unlock(hdev); 3509fcd89c09SVille Tervo } 3510fcd89c09SVille Tervo 35116039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) 35129aa04c91SAndre Guedes { 3513e95beb41SAndre Guedes u8 num_reports = skb->data[0]; 3514e95beb41SAndre Guedes void *ptr = &skb->data[1]; 35153c9e9195SAndre Guedes s8 rssi; 35169aa04c91SAndre Guedes 3517e95beb41SAndre Guedes while (num_reports--) { 3518e95beb41SAndre Guedes struct hci_ev_le_advertising_info *ev = ptr; 3519e95beb41SAndre Guedes 35203c9e9195SAndre Guedes rssi = ev->data[ev->length]; 35213c9e9195SAndre Guedes mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type, 352204124681SGustavo F. Padovan NULL, rssi, 0, 1, ev->data, ev->length); 35233c9e9195SAndre Guedes 3524e95beb41SAndre Guedes ptr += sizeof(*ev) + ev->length + 1; 35259aa04c91SAndre Guedes } 35269aa04c91SAndre Guedes } 35279aa04c91SAndre Guedes 35286039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 3529a7a595f6SVinicius Costa Gomes { 3530a7a595f6SVinicius Costa Gomes struct hci_ev_le_ltk_req *ev = (void *) skb->data; 3531a7a595f6SVinicius Costa Gomes struct hci_cp_le_ltk_reply cp; 3532bea710feSVinicius Costa Gomes struct hci_cp_le_ltk_neg_reply neg; 3533a7a595f6SVinicius Costa Gomes struct hci_conn *conn; 3534c9839a11SVinicius Costa Gomes struct smp_ltk *ltk; 3535a7a595f6SVinicius Costa Gomes 35369f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle)); 3537a7a595f6SVinicius Costa Gomes 3538a7a595f6SVinicius Costa Gomes hci_dev_lock(hdev); 3539a7a595f6SVinicius Costa Gomes 3540a7a595f6SVinicius Costa Gomes conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3541bea710feSVinicius Costa Gomes if (conn == NULL) 3542bea710feSVinicius Costa Gomes goto not_found; 3543a7a595f6SVinicius Costa Gomes 3544bea710feSVinicius Costa Gomes ltk = hci_find_ltk(hdev, ev->ediv, ev->random); 3545bea710feSVinicius Costa Gomes if (ltk == NULL) 3546bea710feSVinicius Costa Gomes goto not_found; 3547bea710feSVinicius Costa Gomes 3548bea710feSVinicius Costa Gomes memcpy(cp.ltk, ltk->val, sizeof(ltk->val)); 3549a7a595f6SVinicius Costa Gomes cp.handle = cpu_to_le16(conn->handle); 3550c9839a11SVinicius Costa Gomes 3551c9839a11SVinicius Costa Gomes if (ltk->authenticated) 3552f8776218SAndre Guedes conn->pending_sec_level = BT_SECURITY_HIGH; 3553f8776218SAndre Guedes else 3554f8776218SAndre Guedes conn->pending_sec_level = BT_SECURITY_MEDIUM; 3555a7a595f6SVinicius Costa Gomes 355689cbb4daSAndre Guedes conn->enc_key_size = ltk->enc_size; 3557a7a595f6SVinicius Costa Gomes 3558a7a595f6SVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); 3559a7a595f6SVinicius Costa Gomes 3560c9839a11SVinicius Costa Gomes if (ltk->type & HCI_SMP_STK) { 3561c9839a11SVinicius Costa Gomes list_del(<k->list); 3562c9839a11SVinicius Costa Gomes kfree(ltk); 3563c9839a11SVinicius Costa Gomes } 3564c9839a11SVinicius Costa Gomes 3565a7a595f6SVinicius Costa Gomes hci_dev_unlock(hdev); 3566bea710feSVinicius Costa Gomes 3567bea710feSVinicius Costa Gomes return; 3568bea710feSVinicius Costa Gomes 3569bea710feSVinicius Costa Gomes not_found: 3570bea710feSVinicius Costa Gomes neg.handle = ev->handle; 3571bea710feSVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg); 3572bea710feSVinicius Costa Gomes hci_dev_unlock(hdev); 3573a7a595f6SVinicius Costa Gomes } 3574a7a595f6SVinicius Costa Gomes 35756039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 3576fcd89c09SVille Tervo { 3577fcd89c09SVille Tervo struct hci_ev_le_meta *le_ev = (void *) skb->data; 3578fcd89c09SVille Tervo 3579fcd89c09SVille Tervo skb_pull(skb, sizeof(*le_ev)); 3580fcd89c09SVille Tervo 3581fcd89c09SVille Tervo switch (le_ev->subevent) { 3582fcd89c09SVille Tervo case HCI_EV_LE_CONN_COMPLETE: 3583fcd89c09SVille Tervo hci_le_conn_complete_evt(hdev, skb); 3584fcd89c09SVille Tervo break; 3585fcd89c09SVille Tervo 35869aa04c91SAndre Guedes case HCI_EV_LE_ADVERTISING_REPORT: 35879aa04c91SAndre Guedes hci_le_adv_report_evt(hdev, skb); 35889aa04c91SAndre Guedes break; 35899aa04c91SAndre Guedes 3590a7a595f6SVinicius Costa Gomes case HCI_EV_LE_LTK_REQ: 3591a7a595f6SVinicius Costa Gomes hci_le_ltk_request_evt(hdev, skb); 3592a7a595f6SVinicius Costa Gomes break; 3593a7a595f6SVinicius Costa Gomes 3594fcd89c09SVille Tervo default: 3595fcd89c09SVille Tervo break; 3596fcd89c09SVille Tervo } 3597fcd89c09SVille Tervo } 3598fcd89c09SVille Tervo 35999495b2eeSAndrei Emeltchenko static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb) 36009495b2eeSAndrei Emeltchenko { 36019495b2eeSAndrei Emeltchenko struct hci_ev_channel_selected *ev = (void *) skb->data; 36029495b2eeSAndrei Emeltchenko struct hci_conn *hcon; 36039495b2eeSAndrei Emeltchenko 36049495b2eeSAndrei Emeltchenko BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle); 36059495b2eeSAndrei Emeltchenko 36069495b2eeSAndrei Emeltchenko skb_pull(skb, sizeof(*ev)); 36079495b2eeSAndrei Emeltchenko 36089495b2eeSAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 36099495b2eeSAndrei Emeltchenko if (!hcon) 36109495b2eeSAndrei Emeltchenko return; 36119495b2eeSAndrei Emeltchenko 36129495b2eeSAndrei Emeltchenko amp_read_loc_assoc_final_data(hdev, hcon); 36139495b2eeSAndrei Emeltchenko } 36149495b2eeSAndrei Emeltchenko 36151da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 36161da177e4SLinus Torvalds { 3617a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 3618a9de9248SMarcel Holtmann __u8 event = hdr->evt; 36191da177e4SLinus Torvalds 3620b6ddb638SJohan Hedberg hci_dev_lock(hdev); 3621b6ddb638SJohan Hedberg 3622b6ddb638SJohan Hedberg /* Received events are (currently) only needed when a request is 3623b6ddb638SJohan Hedberg * ongoing so avoid unnecessary memory allocation. 3624b6ddb638SJohan Hedberg */ 3625b6ddb638SJohan Hedberg if (hdev->req_status == HCI_REQ_PEND) { 3626b6ddb638SJohan Hedberg kfree_skb(hdev->recv_evt); 3627b6ddb638SJohan Hedberg hdev->recv_evt = skb_clone(skb, GFP_KERNEL); 3628b6ddb638SJohan Hedberg } 3629b6ddb638SJohan Hedberg 3630b6ddb638SJohan Hedberg hci_dev_unlock(hdev); 3631b6ddb638SJohan Hedberg 36321da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 36331da177e4SLinus Torvalds 363402350a72SJohan Hedberg if (hdev->sent_cmd && bt_cb(hdev->sent_cmd)->req.event == event) { 3635c1f23a2bSJohannes Berg struct hci_command_hdr *cmd_hdr = (void *) hdev->sent_cmd->data; 3636c1f23a2bSJohannes Berg u16 opcode = __le16_to_cpu(cmd_hdr->opcode); 363702350a72SJohan Hedberg 363802350a72SJohan Hedberg hci_req_cmd_complete(hdev, opcode, 0); 363902350a72SJohan Hedberg } 364002350a72SJohan Hedberg 3641a9de9248SMarcel Holtmann switch (event) { 36421da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 36431da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 36441da177e4SLinus Torvalds break; 36451da177e4SLinus Torvalds 36461da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 36471da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 36481da177e4SLinus Torvalds break; 36491da177e4SLinus Torvalds 3650a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 3651a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 365221d9e30eSMarcel Holtmann break; 365321d9e30eSMarcel Holtmann 36541da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 36551da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 36561da177e4SLinus Torvalds break; 36571da177e4SLinus Torvalds 36581da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 36591da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 36601da177e4SLinus Torvalds break; 36611da177e4SLinus Torvalds 36621da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 36631da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 36641da177e4SLinus Torvalds break; 36651da177e4SLinus Torvalds 3666a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 3667a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 3668a9de9248SMarcel Holtmann break; 3669a9de9248SMarcel Holtmann 36701da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 36711da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 36721da177e4SLinus Torvalds break; 36731da177e4SLinus Torvalds 3674a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 3675a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 3676a9de9248SMarcel Holtmann break; 3677a9de9248SMarcel Holtmann 3678a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 3679a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 3680a9de9248SMarcel Holtmann break; 3681a9de9248SMarcel Holtmann 3682a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 3683a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 3684a9de9248SMarcel Holtmann break; 3685a9de9248SMarcel Holtmann 3686a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 3687a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 3688a9de9248SMarcel Holtmann break; 3689a9de9248SMarcel Holtmann 3690a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 3691a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 3692a9de9248SMarcel Holtmann break; 3693a9de9248SMarcel Holtmann 3694a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 3695a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 3696a9de9248SMarcel Holtmann break; 3697a9de9248SMarcel Holtmann 3698a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 3699a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 37001da177e4SLinus Torvalds break; 37011da177e4SLinus Torvalds 37021da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 37031da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 37041da177e4SLinus Torvalds break; 37051da177e4SLinus Torvalds 37061da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 37071da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 37081da177e4SLinus Torvalds break; 37091da177e4SLinus Torvalds 37101da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 37111da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 37121da177e4SLinus Torvalds break; 37131da177e4SLinus Torvalds 37141da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 37151da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 37161da177e4SLinus Torvalds break; 37171da177e4SLinus Torvalds 3718a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 3719a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 3720a8746417SMarcel Holtmann break; 3721a8746417SMarcel Holtmann 372285a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 372385a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 372485a1e930SMarcel Holtmann break; 372585a1e930SMarcel Holtmann 3726a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 3727a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 3728a9de9248SMarcel Holtmann break; 3729a9de9248SMarcel Holtmann 3730a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 3731a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 3732a9de9248SMarcel Holtmann break; 3733a9de9248SMarcel Holtmann 3734a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 3735a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 3736a9de9248SMarcel Holtmann break; 3737a9de9248SMarcel Holtmann 3738a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 3739a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 37401da177e4SLinus Torvalds break; 37411da177e4SLinus Torvalds 37421c2e0041SJohan Hedberg case HCI_EV_KEY_REFRESH_COMPLETE: 37431c2e0041SJohan Hedberg hci_key_refresh_complete_evt(hdev, skb); 37441c2e0041SJohan Hedberg break; 37451c2e0041SJohan Hedberg 37460493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 37470493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 37480493684eSMarcel Holtmann break; 37490493684eSMarcel Holtmann 375003b555e1SJohan Hedberg case HCI_EV_IO_CAPA_REPLY: 375103b555e1SJohan Hedberg hci_io_capa_reply_evt(hdev, skb); 375203b555e1SJohan Hedberg break; 375303b555e1SJohan Hedberg 3754a5c29683SJohan Hedberg case HCI_EV_USER_CONFIRM_REQUEST: 3755a5c29683SJohan Hedberg hci_user_confirm_request_evt(hdev, skb); 3756a5c29683SJohan Hedberg break; 3757a5c29683SJohan Hedberg 37581143d458SBrian Gix case HCI_EV_USER_PASSKEY_REQUEST: 37591143d458SBrian Gix hci_user_passkey_request_evt(hdev, skb); 37601143d458SBrian Gix break; 37611143d458SBrian Gix 376292a25256SJohan Hedberg case HCI_EV_USER_PASSKEY_NOTIFY: 376392a25256SJohan Hedberg hci_user_passkey_notify_evt(hdev, skb); 376492a25256SJohan Hedberg break; 376592a25256SJohan Hedberg 376692a25256SJohan Hedberg case HCI_EV_KEYPRESS_NOTIFY: 376792a25256SJohan Hedberg hci_keypress_notify_evt(hdev, skb); 376892a25256SJohan Hedberg break; 376992a25256SJohan Hedberg 37700493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 37710493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 37720493684eSMarcel Holtmann break; 37730493684eSMarcel Holtmann 377441a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 377541a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 377641a96212SMarcel Holtmann break; 377741a96212SMarcel Holtmann 3778fcd89c09SVille Tervo case HCI_EV_LE_META: 3779fcd89c09SVille Tervo hci_le_meta_evt(hdev, skb); 3780fcd89c09SVille Tervo break; 3781fcd89c09SVille Tervo 37829495b2eeSAndrei Emeltchenko case HCI_EV_CHANNEL_SELECTED: 37839495b2eeSAndrei Emeltchenko hci_chan_selected_evt(hdev, skb); 37849495b2eeSAndrei Emeltchenko break; 37859495b2eeSAndrei Emeltchenko 37862763eda6SSzymon Janc case HCI_EV_REMOTE_OOB_DATA_REQUEST: 37872763eda6SSzymon Janc hci_remote_oob_data_request_evt(hdev, skb); 37882763eda6SSzymon Janc break; 37892763eda6SSzymon Janc 3790d5e91192SAndrei Emeltchenko case HCI_EV_PHY_LINK_COMPLETE: 3791d5e91192SAndrei Emeltchenko hci_phy_link_complete_evt(hdev, skb); 3792d5e91192SAndrei Emeltchenko break; 3793d5e91192SAndrei Emeltchenko 379427695fb4SAndrei Emeltchenko case HCI_EV_LOGICAL_LINK_COMPLETE: 379527695fb4SAndrei Emeltchenko hci_loglink_complete_evt(hdev, skb); 379627695fb4SAndrei Emeltchenko break; 379727695fb4SAndrei Emeltchenko 3798606e2a10SAndrei Emeltchenko case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE: 3799606e2a10SAndrei Emeltchenko hci_disconn_loglink_complete_evt(hdev, skb); 3800606e2a10SAndrei Emeltchenko break; 3801606e2a10SAndrei Emeltchenko 38029eef6b3aSAndrei Emeltchenko case HCI_EV_DISCONN_PHY_LINK_COMPLETE: 38039eef6b3aSAndrei Emeltchenko hci_disconn_phylink_complete_evt(hdev, skb); 38049eef6b3aSAndrei Emeltchenko break; 38059eef6b3aSAndrei Emeltchenko 380625e89e99SAndrei Emeltchenko case HCI_EV_NUM_COMP_BLOCKS: 380725e89e99SAndrei Emeltchenko hci_num_comp_blocks_evt(hdev, skb); 380825e89e99SAndrei Emeltchenko break; 380925e89e99SAndrei Emeltchenko 38101da177e4SLinus Torvalds default: 38119f1db00cSAndrei Emeltchenko BT_DBG("%s event 0x%2.2x", hdev->name, event); 38121da177e4SLinus Torvalds break; 38131da177e4SLinus Torvalds } 38141da177e4SLinus Torvalds 38151da177e4SLinus Torvalds kfree_skb(skb); 38161da177e4SLinus Torvalds hdev->stat.evt_rx++; 38171da177e4SLinus Torvalds } 3818