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; 198f8e808bdSMarcel Holtmann 199f8e808bdSMarcel Holtmann memset(hdev->scan_rsp_data, 0, sizeof(hdev->scan_rsp_data)); 200f8e808bdSMarcel Holtmann hdev->scan_rsp_data_len = 0; 20106f5b778SMarcel Holtmann 20206f5b778SMarcel Holtmann hdev->ssp_debug_mode = 0; 203a9de9248SMarcel Holtmann } 204a9de9248SMarcel Holtmann 205a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) 206a9de9248SMarcel Holtmann { 207a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 2081da177e4SLinus Torvalds void *sent; 2091da177e4SLinus Torvalds 2109f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 2111da177e4SLinus Torvalds 212a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); 2131da177e4SLinus Torvalds if (!sent) 214a9de9248SMarcel Holtmann return; 2151da177e4SLinus Torvalds 21656e5cb86SJohan Hedberg hci_dev_lock(hdev); 21756e5cb86SJohan Hedberg 218f51d5b24SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 219f51d5b24SJohan Hedberg mgmt_set_local_name_complete(hdev, sent, status); 22028cc7bdeSJohan Hedberg else if (!status) 22128cc7bdeSJohan Hedberg memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); 222f51d5b24SJohan Hedberg 22356e5cb86SJohan Hedberg hci_dev_unlock(hdev); 224a9de9248SMarcel Holtmann } 225a9de9248SMarcel Holtmann 226a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) 227a9de9248SMarcel Holtmann { 228a9de9248SMarcel Holtmann struct hci_rp_read_local_name *rp = (void *) skb->data; 229a9de9248SMarcel Holtmann 2309f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 231a9de9248SMarcel Holtmann 232a9de9248SMarcel Holtmann if (rp->status) 233a9de9248SMarcel Holtmann return; 234a9de9248SMarcel Holtmann 235db99b5fcSJohan Hedberg if (test_bit(HCI_SETUP, &hdev->dev_flags)) 2361f6c6378SJohan Hedberg memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); 237a9de9248SMarcel Holtmann } 238a9de9248SMarcel Holtmann 239a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) 240a9de9248SMarcel Holtmann { 241a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 242a9de9248SMarcel Holtmann void *sent; 243a9de9248SMarcel Holtmann 2449f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 245a9de9248SMarcel Holtmann 246a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); 247a9de9248SMarcel Holtmann if (!sent) 248a9de9248SMarcel Holtmann return; 2491da177e4SLinus Torvalds 2501da177e4SLinus Torvalds if (!status) { 251a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 252a9de9248SMarcel Holtmann 2531da177e4SLinus Torvalds if (param == AUTH_ENABLED) 2541da177e4SLinus Torvalds set_bit(HCI_AUTH, &hdev->flags); 2551da177e4SLinus Torvalds else 2561da177e4SLinus Torvalds clear_bit(HCI_AUTH, &hdev->flags); 2571da177e4SLinus Torvalds } 258a9de9248SMarcel Holtmann 25933ef95edSJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 26033ef95edSJohan Hedberg mgmt_auth_enable_complete(hdev, status); 261a9de9248SMarcel Holtmann } 2621da177e4SLinus Torvalds 263a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) 264a9de9248SMarcel Holtmann { 265a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 266a9de9248SMarcel Holtmann void *sent; 267a9de9248SMarcel Holtmann 2689f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 269a9de9248SMarcel Holtmann 270a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); 2711da177e4SLinus Torvalds if (!sent) 272a9de9248SMarcel Holtmann return; 2731da177e4SLinus Torvalds 2741da177e4SLinus Torvalds if (!status) { 275a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 276a9de9248SMarcel Holtmann 2771da177e4SLinus Torvalds if (param) 2781da177e4SLinus Torvalds set_bit(HCI_ENCRYPT, &hdev->flags); 2791da177e4SLinus Torvalds else 2801da177e4SLinus Torvalds clear_bit(HCI_ENCRYPT, &hdev->flags); 2811da177e4SLinus Torvalds } 2821da177e4SLinus Torvalds } 2831da177e4SLinus Torvalds 284a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) 285a9de9248SMarcel Holtmann { 28636f7fc7eSJohan Hedberg __u8 param, status = *((__u8 *) skb->data); 28736f7fc7eSJohan Hedberg int old_pscan, old_iscan; 288a9de9248SMarcel Holtmann void *sent; 2891da177e4SLinus Torvalds 2909f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 291a9de9248SMarcel Holtmann 292a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); 2931da177e4SLinus Torvalds if (!sent) 294a9de9248SMarcel Holtmann return; 2951da177e4SLinus Torvalds 29636f7fc7eSJohan Hedberg param = *((__u8 *) sent); 297a9de9248SMarcel Holtmann 29856e5cb86SJohan Hedberg hci_dev_lock(hdev); 29956e5cb86SJohan Hedberg 300fa1bd918SMikel Astiz if (status) { 301744cf19eSJohan Hedberg mgmt_write_scan_failed(hdev, param, status); 3022d7cee58SJohan Hedberg hdev->discov_timeout = 0; 3032d7cee58SJohan Hedberg goto done; 3042d7cee58SJohan Hedberg } 3052d7cee58SJohan Hedberg 3060663ca2aSJohan Hedberg /* We need to ensure that we set this back on if someone changed 3070663ca2aSJohan Hedberg * the scan mode through a raw HCI socket. 3080663ca2aSJohan Hedberg */ 3090663ca2aSJohan Hedberg set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags); 3100663ca2aSJohan Hedberg 3119fbcbb45SJohan Hedberg old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags); 3129fbcbb45SJohan Hedberg old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags); 313a9de9248SMarcel Holtmann 31473f22f62SJohan Hedberg if (param & SCAN_INQUIRY) { 3151da177e4SLinus Torvalds set_bit(HCI_ISCAN, &hdev->flags); 3169fbcbb45SJohan Hedberg if (!old_iscan) 317744cf19eSJohan Hedberg mgmt_discoverable(hdev, 1); 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 421b4cb9fb2SMarcel Holtmann static void hci_cc_read_num_supported_iac(struct hci_dev *hdev, 422b4cb9fb2SMarcel Holtmann struct sk_buff *skb) 423b4cb9fb2SMarcel Holtmann { 424b4cb9fb2SMarcel Holtmann struct hci_rp_read_num_supported_iac *rp = (void *) skb->data; 425b4cb9fb2SMarcel Holtmann 426b4cb9fb2SMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 427b4cb9fb2SMarcel Holtmann 428b4cb9fb2SMarcel Holtmann if (rp->status) 429b4cb9fb2SMarcel Holtmann return; 430b4cb9fb2SMarcel Holtmann 431b4cb9fb2SMarcel Holtmann hdev->num_iac = rp->num_iac; 432b4cb9fb2SMarcel Holtmann 433b4cb9fb2SMarcel Holtmann BT_DBG("%s num iac %d", hdev->name, hdev->num_iac); 434b4cb9fb2SMarcel Holtmann } 435b4cb9fb2SMarcel Holtmann 436333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 437333140b5SMarcel Holtmann { 438333140b5SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 4395ed8eb2fSJohan Hedberg struct hci_cp_write_ssp_mode *sent; 440333140b5SMarcel Holtmann 4419f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 442333140b5SMarcel Holtmann 443333140b5SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); 444333140b5SMarcel Holtmann if (!sent) 445333140b5SMarcel Holtmann return; 446333140b5SMarcel Holtmann 4475ed8eb2fSJohan Hedberg if (!status) { 4485ed8eb2fSJohan Hedberg if (sent->mode) 449cad718edSJohan Hedberg hdev->features[1][0] |= LMP_HOST_SSP; 4505ed8eb2fSJohan Hedberg else 451cad718edSJohan Hedberg hdev->features[1][0] &= ~LMP_HOST_SSP; 4525ed8eb2fSJohan Hedberg } 4535ed8eb2fSJohan Hedberg 454c0ecddc2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 4555ed8eb2fSJohan Hedberg mgmt_ssp_enable_complete(hdev, sent->mode, status); 456c0ecddc2SJohan Hedberg else if (!status) { 4575ed8eb2fSJohan Hedberg if (sent->mode) 45884bde9d6SJohan Hedberg set_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 45984bde9d6SJohan Hedberg else 46084bde9d6SJohan Hedberg clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 461c0ecddc2SJohan Hedberg } 462333140b5SMarcel Holtmann } 463333140b5SMarcel Holtmann 464eac83dc6SMarcel Holtmann static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb) 465eac83dc6SMarcel Holtmann { 466eac83dc6SMarcel Holtmann u8 status = *((u8 *) skb->data); 467eac83dc6SMarcel Holtmann struct hci_cp_write_sc_support *sent; 468eac83dc6SMarcel Holtmann 469eac83dc6SMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, status); 470eac83dc6SMarcel Holtmann 471eac83dc6SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SC_SUPPORT); 472eac83dc6SMarcel Holtmann if (!sent) 473eac83dc6SMarcel Holtmann return; 474eac83dc6SMarcel Holtmann 475eac83dc6SMarcel Holtmann if (!status) { 476eac83dc6SMarcel Holtmann if (sent->support) 477eac83dc6SMarcel Holtmann hdev->features[1][0] |= LMP_HOST_SC; 478eac83dc6SMarcel Holtmann else 479eac83dc6SMarcel Holtmann hdev->features[1][0] &= ~LMP_HOST_SC; 480eac83dc6SMarcel Holtmann } 481eac83dc6SMarcel Holtmann 482eac83dc6SMarcel Holtmann if (test_bit(HCI_MGMT, &hdev->dev_flags)) 483eac83dc6SMarcel Holtmann mgmt_sc_enable_complete(hdev, sent->support, status); 484eac83dc6SMarcel Holtmann else if (!status) { 485eac83dc6SMarcel Holtmann if (sent->support) 486eac83dc6SMarcel Holtmann set_bit(HCI_SC_ENABLED, &hdev->dev_flags); 487eac83dc6SMarcel Holtmann else 488eac83dc6SMarcel Holtmann clear_bit(HCI_SC_ENABLED, &hdev->dev_flags); 489eac83dc6SMarcel Holtmann } 490eac83dc6SMarcel Holtmann } 491eac83dc6SMarcel Holtmann 492a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) 493a9de9248SMarcel Holtmann { 494a9de9248SMarcel Holtmann struct hci_rp_read_local_version *rp = (void *) skb->data; 4951143e5a6SMarcel Holtmann 4969f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 4971143e5a6SMarcel Holtmann 498a9de9248SMarcel Holtmann if (rp->status) 49942c6b129SJohan Hedberg return; 5001143e5a6SMarcel Holtmann 5010d5551f5SMarcel Holtmann if (test_bit(HCI_SETUP, &hdev->dev_flags)) { 502a9de9248SMarcel Holtmann hdev->hci_ver = rp->hci_ver; 503e4e8e37cSMarcel Holtmann hdev->hci_rev = __le16_to_cpu(rp->hci_rev); 504d5859e22SJohan Hedberg hdev->lmp_ver = rp->lmp_ver; 505e4e8e37cSMarcel Holtmann hdev->manufacturer = __le16_to_cpu(rp->manufacturer); 506d5859e22SJohan Hedberg hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); 5070d5551f5SMarcel Holtmann } 508d5859e22SJohan Hedberg } 509d5859e22SJohan Hedberg 5108fc9ced3SGustavo Padovan static void hci_cc_read_local_commands(struct hci_dev *hdev, 5118fc9ced3SGustavo Padovan struct sk_buff *skb) 512a9de9248SMarcel Holtmann { 513a9de9248SMarcel Holtmann struct hci_rp_read_local_commands *rp = (void *) skb->data; 514a9de9248SMarcel Holtmann 5159f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 516a9de9248SMarcel Holtmann 5176a070e6eSMarcel Holtmann if (rp->status) 5186a070e6eSMarcel Holtmann return; 5196a070e6eSMarcel Holtmann 5206a070e6eSMarcel Holtmann if (test_bit(HCI_SETUP, &hdev->dev_flags)) 521a9de9248SMarcel Holtmann memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); 522a9de9248SMarcel Holtmann } 523a9de9248SMarcel Holtmann 5248fc9ced3SGustavo Padovan static void hci_cc_read_local_features(struct hci_dev *hdev, 5258fc9ced3SGustavo Padovan struct sk_buff *skb) 526a9de9248SMarcel Holtmann { 527a9de9248SMarcel Holtmann struct hci_rp_read_local_features *rp = (void *) skb->data; 528a9de9248SMarcel Holtmann 5299f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 530a9de9248SMarcel Holtmann 531a9de9248SMarcel Holtmann if (rp->status) 532a9de9248SMarcel Holtmann return; 533a9de9248SMarcel Holtmann 534a9de9248SMarcel Holtmann memcpy(hdev->features, rp->features, 8); 5351da177e4SLinus Torvalds 5361da177e4SLinus Torvalds /* Adjust default settings according to features 5371da177e4SLinus Torvalds * supported by device. */ 538a9de9248SMarcel Holtmann 539cad718edSJohan Hedberg if (hdev->features[0][0] & LMP_3SLOT) 5401da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM3 | HCI_DH3); 5411da177e4SLinus Torvalds 542cad718edSJohan Hedberg if (hdev->features[0][0] & LMP_5SLOT) 5431da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM5 | HCI_DH5); 5441da177e4SLinus Torvalds 545cad718edSJohan Hedberg if (hdev->features[0][1] & LMP_HV2) { 5461da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV2); 5475b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV2); 5485b7f9909SMarcel Holtmann } 5491da177e4SLinus Torvalds 550cad718edSJohan Hedberg if (hdev->features[0][1] & LMP_HV3) { 5511da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV3); 5525b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV3); 5535b7f9909SMarcel Holtmann } 5545b7f9909SMarcel Holtmann 55545db810fSAndre Guedes if (lmp_esco_capable(hdev)) 5565b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV3); 5575b7f9909SMarcel Holtmann 558cad718edSJohan Hedberg if (hdev->features[0][4] & LMP_EV4) 5595b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV4); 5605b7f9909SMarcel Holtmann 561cad718edSJohan Hedberg if (hdev->features[0][4] & LMP_EV5) 5625b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV5); 5631da177e4SLinus Torvalds 564cad718edSJohan Hedberg if (hdev->features[0][5] & LMP_EDR_ESCO_2M) 565efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV3); 566efc7688bSMarcel Holtmann 567cad718edSJohan Hedberg if (hdev->features[0][5] & LMP_EDR_ESCO_3M) 568efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_3EV3); 569efc7688bSMarcel Holtmann 570cad718edSJohan Hedberg if (hdev->features[0][5] & LMP_EDR_3S_ESCO) 571efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); 5721da177e4SLinus Torvalds } 5731da177e4SLinus Torvalds 574971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev, 575971e3a4bSAndre Guedes struct sk_buff *skb) 576971e3a4bSAndre Guedes { 577971e3a4bSAndre Guedes struct hci_rp_read_local_ext_features *rp = (void *) skb->data; 578971e3a4bSAndre Guedes 5799f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 580971e3a4bSAndre Guedes 581971e3a4bSAndre Guedes if (rp->status) 58242c6b129SJohan Hedberg return; 583971e3a4bSAndre Guedes 58457af75a8SMarcel Holtmann if (hdev->max_page < rp->max_page) 585d2c5d77fSJohan Hedberg hdev->max_page = rp->max_page; 586d2c5d77fSJohan Hedberg 587cad718edSJohan Hedberg if (rp->page < HCI_MAX_PAGES) 588cad718edSJohan Hedberg memcpy(hdev->features[rp->page], rp->features, 8); 589971e3a4bSAndre Guedes } 590971e3a4bSAndre Guedes 5911e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, 5921e89cffbSAndrei Emeltchenko struct sk_buff *skb) 5931e89cffbSAndrei Emeltchenko { 5941e89cffbSAndrei Emeltchenko struct hci_rp_read_flow_control_mode *rp = (void *) skb->data; 5951e89cffbSAndrei Emeltchenko 5969f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 5971e89cffbSAndrei Emeltchenko 59842c6b129SJohan Hedberg if (!rp->status) 5991e89cffbSAndrei Emeltchenko hdev->flow_ctl_mode = rp->mode; 6001e89cffbSAndrei Emeltchenko } 6011e89cffbSAndrei Emeltchenko 602a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 603a9de9248SMarcel Holtmann { 604a9de9248SMarcel Holtmann struct hci_rp_read_buffer_size *rp = (void *) skb->data; 605a9de9248SMarcel Holtmann 6069f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 607a9de9248SMarcel Holtmann 608a9de9248SMarcel Holtmann if (rp->status) 609a9de9248SMarcel Holtmann return; 610a9de9248SMarcel Holtmann 611a9de9248SMarcel Holtmann hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); 612a9de9248SMarcel Holtmann hdev->sco_mtu = rp->sco_mtu; 613a9de9248SMarcel Holtmann hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); 614a9de9248SMarcel Holtmann hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); 615da1f5198SMarcel Holtmann 616da1f5198SMarcel Holtmann if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { 617da1f5198SMarcel Holtmann hdev->sco_mtu = 64; 618da1f5198SMarcel Holtmann hdev->sco_pkts = 8; 619da1f5198SMarcel Holtmann } 620da1f5198SMarcel Holtmann 621da1f5198SMarcel Holtmann hdev->acl_cnt = hdev->acl_pkts; 622da1f5198SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 6231da177e4SLinus Torvalds 624807deac2SGustavo Padovan BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu, 625807deac2SGustavo Padovan hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts); 6261da177e4SLinus Torvalds } 6271da177e4SLinus Torvalds 628a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) 629a9de9248SMarcel Holtmann { 630a9de9248SMarcel Holtmann struct hci_rp_read_bd_addr *rp = (void *) skb->data; 6311da177e4SLinus Torvalds 6329f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 633a9de9248SMarcel Holtmann 634a9de9248SMarcel Holtmann if (!rp->status) 635a9de9248SMarcel Holtmann bacpy(&hdev->bdaddr, &rp->bdaddr); 63623bb5763SJohan Hedberg } 63723bb5763SJohan Hedberg 638f332ec66SJohan Hedberg static void hci_cc_read_page_scan_activity(struct hci_dev *hdev, 639f332ec66SJohan Hedberg struct sk_buff *skb) 640f332ec66SJohan Hedberg { 641f332ec66SJohan Hedberg struct hci_rp_read_page_scan_activity *rp = (void *) skb->data; 642f332ec66SJohan Hedberg 643f332ec66SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 644f332ec66SJohan Hedberg 645f332ec66SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags) && !rp->status) { 646f332ec66SJohan Hedberg hdev->page_scan_interval = __le16_to_cpu(rp->interval); 647f332ec66SJohan Hedberg hdev->page_scan_window = __le16_to_cpu(rp->window); 648f332ec66SJohan Hedberg } 649f332ec66SJohan Hedberg } 650f332ec66SJohan Hedberg 6514a3ee763SJohan Hedberg static void hci_cc_write_page_scan_activity(struct hci_dev *hdev, 6524a3ee763SJohan Hedberg struct sk_buff *skb) 6534a3ee763SJohan Hedberg { 6544a3ee763SJohan Hedberg u8 status = *((u8 *) skb->data); 6554a3ee763SJohan Hedberg struct hci_cp_write_page_scan_activity *sent; 6564a3ee763SJohan Hedberg 6574a3ee763SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 6584a3ee763SJohan Hedberg 6594a3ee763SJohan Hedberg if (status) 6604a3ee763SJohan Hedberg return; 6614a3ee763SJohan Hedberg 6624a3ee763SJohan Hedberg sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY); 6634a3ee763SJohan Hedberg if (!sent) 6644a3ee763SJohan Hedberg return; 6654a3ee763SJohan Hedberg 6664a3ee763SJohan Hedberg hdev->page_scan_interval = __le16_to_cpu(sent->interval); 6674a3ee763SJohan Hedberg hdev->page_scan_window = __le16_to_cpu(sent->window); 6684a3ee763SJohan Hedberg } 6694a3ee763SJohan Hedberg 670f332ec66SJohan Hedberg static void hci_cc_read_page_scan_type(struct hci_dev *hdev, 671f332ec66SJohan Hedberg struct sk_buff *skb) 672f332ec66SJohan Hedberg { 673f332ec66SJohan Hedberg struct hci_rp_read_page_scan_type *rp = (void *) skb->data; 674f332ec66SJohan Hedberg 675f332ec66SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 676f332ec66SJohan Hedberg 677f332ec66SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags) && !rp->status) 678f332ec66SJohan Hedberg hdev->page_scan_type = rp->type; 679f332ec66SJohan Hedberg } 680f332ec66SJohan Hedberg 6814a3ee763SJohan Hedberg static void hci_cc_write_page_scan_type(struct hci_dev *hdev, 6824a3ee763SJohan Hedberg struct sk_buff *skb) 6834a3ee763SJohan Hedberg { 6844a3ee763SJohan Hedberg u8 status = *((u8 *) skb->data); 6854a3ee763SJohan Hedberg u8 *type; 6864a3ee763SJohan Hedberg 6874a3ee763SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 6884a3ee763SJohan Hedberg 6894a3ee763SJohan Hedberg if (status) 6904a3ee763SJohan Hedberg return; 6914a3ee763SJohan Hedberg 6924a3ee763SJohan Hedberg type = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE); 6934a3ee763SJohan Hedberg if (type) 6944a3ee763SJohan Hedberg hdev->page_scan_type = *type; 6954a3ee763SJohan Hedberg } 6964a3ee763SJohan Hedberg 697350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev, 698350ee4cfSAndrei Emeltchenko struct sk_buff *skb) 699350ee4cfSAndrei Emeltchenko { 700350ee4cfSAndrei Emeltchenko struct hci_rp_read_data_block_size *rp = (void *) skb->data; 701350ee4cfSAndrei Emeltchenko 7029f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 703350ee4cfSAndrei Emeltchenko 704350ee4cfSAndrei Emeltchenko if (rp->status) 705350ee4cfSAndrei Emeltchenko return; 706350ee4cfSAndrei Emeltchenko 707350ee4cfSAndrei Emeltchenko hdev->block_mtu = __le16_to_cpu(rp->max_acl_len); 708350ee4cfSAndrei Emeltchenko hdev->block_len = __le16_to_cpu(rp->block_len); 709350ee4cfSAndrei Emeltchenko hdev->num_blocks = __le16_to_cpu(rp->num_blocks); 710350ee4cfSAndrei Emeltchenko 711350ee4cfSAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 712350ee4cfSAndrei Emeltchenko 713350ee4cfSAndrei Emeltchenko BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu, 714350ee4cfSAndrei Emeltchenko hdev->block_cnt, hdev->block_len); 715350ee4cfSAndrei Emeltchenko } 716350ee4cfSAndrei Emeltchenko 717928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev, 718928abaa7SAndrei Emeltchenko struct sk_buff *skb) 719928abaa7SAndrei Emeltchenko { 720928abaa7SAndrei Emeltchenko struct hci_rp_read_local_amp_info *rp = (void *) skb->data; 721928abaa7SAndrei Emeltchenko 7229f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 723928abaa7SAndrei Emeltchenko 724928abaa7SAndrei Emeltchenko if (rp->status) 7258e2a0d92SAndrei Emeltchenko goto a2mp_rsp; 726928abaa7SAndrei Emeltchenko 727928abaa7SAndrei Emeltchenko hdev->amp_status = rp->amp_status; 728928abaa7SAndrei Emeltchenko hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); 729928abaa7SAndrei Emeltchenko hdev->amp_max_bw = __le32_to_cpu(rp->max_bw); 730928abaa7SAndrei Emeltchenko hdev->amp_min_latency = __le32_to_cpu(rp->min_latency); 731928abaa7SAndrei Emeltchenko hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu); 732928abaa7SAndrei Emeltchenko hdev->amp_type = rp->amp_type; 733928abaa7SAndrei Emeltchenko hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap); 734928abaa7SAndrei Emeltchenko hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size); 735928abaa7SAndrei Emeltchenko hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); 736928abaa7SAndrei Emeltchenko hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); 737928abaa7SAndrei Emeltchenko 7388e2a0d92SAndrei Emeltchenko a2mp_rsp: 7398e2a0d92SAndrei Emeltchenko a2mp_send_getinfo_rsp(hdev); 740928abaa7SAndrei Emeltchenko } 741928abaa7SAndrei Emeltchenko 742903e4541SAndrei Emeltchenko static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev, 743903e4541SAndrei Emeltchenko struct sk_buff *skb) 744903e4541SAndrei Emeltchenko { 745903e4541SAndrei Emeltchenko struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data; 746903e4541SAndrei Emeltchenko struct amp_assoc *assoc = &hdev->loc_assoc; 747903e4541SAndrei Emeltchenko size_t rem_len, frag_len; 748903e4541SAndrei Emeltchenko 749903e4541SAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 750903e4541SAndrei Emeltchenko 751903e4541SAndrei Emeltchenko if (rp->status) 752903e4541SAndrei Emeltchenko goto a2mp_rsp; 753903e4541SAndrei Emeltchenko 754903e4541SAndrei Emeltchenko frag_len = skb->len - sizeof(*rp); 755903e4541SAndrei Emeltchenko rem_len = __le16_to_cpu(rp->rem_len); 756903e4541SAndrei Emeltchenko 757903e4541SAndrei Emeltchenko if (rem_len > frag_len) { 7582e430be3SAndrei Emeltchenko BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len); 759903e4541SAndrei Emeltchenko 760903e4541SAndrei Emeltchenko memcpy(assoc->data + assoc->offset, rp->frag, frag_len); 761903e4541SAndrei Emeltchenko assoc->offset += frag_len; 762903e4541SAndrei Emeltchenko 763903e4541SAndrei Emeltchenko /* Read other fragments */ 764903e4541SAndrei Emeltchenko amp_read_loc_assoc_frag(hdev, rp->phy_handle); 765903e4541SAndrei Emeltchenko 766903e4541SAndrei Emeltchenko return; 767903e4541SAndrei Emeltchenko } 768903e4541SAndrei Emeltchenko 769903e4541SAndrei Emeltchenko memcpy(assoc->data + assoc->offset, rp->frag, rem_len); 770903e4541SAndrei Emeltchenko assoc->len = assoc->offset + rem_len; 771903e4541SAndrei Emeltchenko assoc->offset = 0; 772903e4541SAndrei Emeltchenko 773903e4541SAndrei Emeltchenko a2mp_rsp: 774903e4541SAndrei Emeltchenko /* Send A2MP Rsp when all fragments are received */ 775903e4541SAndrei Emeltchenko a2mp_send_getampassoc_rsp(hdev, rp->status); 7769495b2eeSAndrei Emeltchenko a2mp_send_create_phy_link_req(hdev, rp->status); 777903e4541SAndrei Emeltchenko } 778903e4541SAndrei Emeltchenko 779d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, 780d5859e22SJohan Hedberg struct sk_buff *skb) 781d5859e22SJohan Hedberg { 78291c4e9b1SMarcel Holtmann struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data; 783d5859e22SJohan Hedberg 7849f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 785d5859e22SJohan Hedberg 78691c4e9b1SMarcel Holtmann if (!rp->status) 78791c4e9b1SMarcel Holtmann hdev->inq_tx_power = rp->tx_power; 788d5859e22SJohan Hedberg } 789d5859e22SJohan Hedberg 790980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) 791980e1a53SJohan Hedberg { 792980e1a53SJohan Hedberg struct hci_rp_pin_code_reply *rp = (void *) skb->data; 793980e1a53SJohan Hedberg struct hci_cp_pin_code_reply *cp; 794980e1a53SJohan Hedberg struct hci_conn *conn; 795980e1a53SJohan Hedberg 7969f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 797980e1a53SJohan Hedberg 79856e5cb86SJohan Hedberg hci_dev_lock(hdev); 79956e5cb86SJohan Hedberg 800a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 801744cf19eSJohan Hedberg mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); 802980e1a53SJohan Hedberg 803fa1bd918SMikel Astiz if (rp->status) 80456e5cb86SJohan Hedberg goto unlock; 805980e1a53SJohan Hedberg 806980e1a53SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); 807980e1a53SJohan Hedberg if (!cp) 80856e5cb86SJohan Hedberg goto unlock; 809980e1a53SJohan Hedberg 810980e1a53SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 811980e1a53SJohan Hedberg if (conn) 812980e1a53SJohan Hedberg conn->pin_length = cp->pin_len; 81356e5cb86SJohan Hedberg 81456e5cb86SJohan Hedberg unlock: 81556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 816980e1a53SJohan Hedberg } 817980e1a53SJohan Hedberg 818980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 819980e1a53SJohan Hedberg { 820980e1a53SJohan Hedberg struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data; 821980e1a53SJohan Hedberg 8229f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 823980e1a53SJohan Hedberg 82456e5cb86SJohan Hedberg hci_dev_lock(hdev); 82556e5cb86SJohan Hedberg 826a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 827744cf19eSJohan Hedberg mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr, 828980e1a53SJohan Hedberg rp->status); 82956e5cb86SJohan Hedberg 83056e5cb86SJohan Hedberg hci_dev_unlock(hdev); 831980e1a53SJohan Hedberg } 83256e5cb86SJohan Hedberg 8336ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, 8346ed58ec5SVille Tervo struct sk_buff *skb) 8356ed58ec5SVille Tervo { 8366ed58ec5SVille Tervo struct hci_rp_le_read_buffer_size *rp = (void *) skb->data; 8376ed58ec5SVille Tervo 8389f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 8396ed58ec5SVille Tervo 8406ed58ec5SVille Tervo if (rp->status) 8416ed58ec5SVille Tervo return; 8426ed58ec5SVille Tervo 8436ed58ec5SVille Tervo hdev->le_mtu = __le16_to_cpu(rp->le_mtu); 8446ed58ec5SVille Tervo hdev->le_pkts = rp->le_max_pkt; 8456ed58ec5SVille Tervo 8466ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 8476ed58ec5SVille Tervo 8486ed58ec5SVille Tervo BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); 8496ed58ec5SVille Tervo } 850980e1a53SJohan Hedberg 85160e77321SJohan Hedberg static void hci_cc_le_read_local_features(struct hci_dev *hdev, 85260e77321SJohan Hedberg struct sk_buff *skb) 85360e77321SJohan Hedberg { 85460e77321SJohan Hedberg struct hci_rp_le_read_local_features *rp = (void *) skb->data; 85560e77321SJohan Hedberg 85660e77321SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 85760e77321SJohan Hedberg 85860e77321SJohan Hedberg if (!rp->status) 85960e77321SJohan Hedberg memcpy(hdev->le_features, rp->features, 8); 86060e77321SJohan Hedberg } 86160e77321SJohan Hedberg 8628fa19098SJohan Hedberg static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, 8638fa19098SJohan Hedberg struct sk_buff *skb) 8648fa19098SJohan Hedberg { 8658fa19098SJohan Hedberg struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data; 8668fa19098SJohan Hedberg 8678fa19098SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 8688fa19098SJohan Hedberg 86904b4edcbSJohan Hedberg if (!rp->status) 8708fa19098SJohan Hedberg hdev->adv_tx_power = rp->tx_power; 8718fa19098SJohan Hedberg } 8728fa19098SJohan Hedberg 873a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) 874a5c29683SJohan Hedberg { 875a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 876a5c29683SJohan Hedberg 8779f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 878a5c29683SJohan Hedberg 87956e5cb86SJohan Hedberg hci_dev_lock(hdev); 88056e5cb86SJohan Hedberg 881a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 88204124681SGustavo F. Padovan mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0, 88304124681SGustavo F. Padovan rp->status); 88456e5cb86SJohan Hedberg 88556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 886a5c29683SJohan Hedberg } 887a5c29683SJohan Hedberg 888a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, 889a5c29683SJohan Hedberg struct sk_buff *skb) 890a5c29683SJohan Hedberg { 891a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 892a5c29683SJohan Hedberg 8939f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 894a5c29683SJohan Hedberg 89556e5cb86SJohan Hedberg hci_dev_lock(hdev); 89656e5cb86SJohan Hedberg 897a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 898744cf19eSJohan Hedberg mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr, 89904124681SGustavo F. Padovan ACL_LINK, 0, rp->status); 90056e5cb86SJohan Hedberg 90156e5cb86SJohan Hedberg hci_dev_unlock(hdev); 902a5c29683SJohan Hedberg } 903a5c29683SJohan Hedberg 9041143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb) 9051143d458SBrian Gix { 9061143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 9071143d458SBrian Gix 9089f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 9091143d458SBrian Gix 9101143d458SBrian Gix hci_dev_lock(hdev); 9111143d458SBrian Gix 912a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 913272d90dfSJohan Hedberg mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 914272d90dfSJohan Hedberg 0, rp->status); 9151143d458SBrian Gix 9161143d458SBrian Gix hci_dev_unlock(hdev); 9171143d458SBrian Gix } 9181143d458SBrian Gix 9191143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, 9201143d458SBrian Gix struct sk_buff *skb) 9211143d458SBrian Gix { 9221143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 9231143d458SBrian Gix 9249f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 9251143d458SBrian Gix 9261143d458SBrian Gix hci_dev_lock(hdev); 9271143d458SBrian Gix 928a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 9291143d458SBrian Gix mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr, 93004124681SGustavo F. Padovan ACL_LINK, 0, rp->status); 9311143d458SBrian Gix 9321143d458SBrian Gix hci_dev_unlock(hdev); 9331143d458SBrian Gix } 9341143d458SBrian Gix 9354d2d2796SMarcel Holtmann static void hci_cc_read_local_oob_data(struct hci_dev *hdev, 936c35938b2SSzymon Janc struct sk_buff *skb) 937c35938b2SSzymon Janc { 938c35938b2SSzymon Janc struct hci_rp_read_local_oob_data *rp = (void *) skb->data; 939c35938b2SSzymon Janc 9409f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 941c35938b2SSzymon Janc 94256e5cb86SJohan Hedberg hci_dev_lock(hdev); 9434d2d2796SMarcel Holtmann mgmt_read_local_oob_data_complete(hdev, rp->hash, rp->randomizer, 9444d2d2796SMarcel Holtmann NULL, NULL, rp->status); 9454d2d2796SMarcel Holtmann hci_dev_unlock(hdev); 9464d2d2796SMarcel Holtmann } 9474d2d2796SMarcel Holtmann 9484d2d2796SMarcel Holtmann static void hci_cc_read_local_oob_ext_data(struct hci_dev *hdev, 9494d2d2796SMarcel Holtmann struct sk_buff *skb) 9504d2d2796SMarcel Holtmann { 9514d2d2796SMarcel Holtmann struct hci_rp_read_local_oob_ext_data *rp = (void *) skb->data; 9524d2d2796SMarcel Holtmann 9534d2d2796SMarcel Holtmann BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 9544d2d2796SMarcel Holtmann 9554d2d2796SMarcel Holtmann hci_dev_lock(hdev); 9564d2d2796SMarcel Holtmann mgmt_read_local_oob_data_complete(hdev, rp->hash192, rp->randomizer192, 9574d2d2796SMarcel Holtmann rp->hash256, rp->randomizer256, 9584d2d2796SMarcel Holtmann rp->status); 95956e5cb86SJohan Hedberg hci_dev_unlock(hdev); 960c35938b2SSzymon Janc } 961c35938b2SSzymon Janc 962c1d5dc4aSJohan Hedberg static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb) 963c1d5dc4aSJohan Hedberg { 964c1d5dc4aSJohan Hedberg __u8 *sent, status = *((__u8 *) skb->data); 965c1d5dc4aSJohan Hedberg 966c1d5dc4aSJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 967c1d5dc4aSJohan Hedberg 968c1d5dc4aSJohan Hedberg sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE); 969c1d5dc4aSJohan Hedberg if (!sent) 970c1d5dc4aSJohan Hedberg return; 971c1d5dc4aSJohan Hedberg 972c1d5dc4aSJohan Hedberg hci_dev_lock(hdev); 973c1d5dc4aSJohan Hedberg 974c1d5dc4aSJohan Hedberg if (!status) { 975c1d5dc4aSJohan Hedberg if (*sent) 976f3d3444aSJohan Hedberg set_bit(HCI_ADVERTISING, &hdev->dev_flags); 977c1d5dc4aSJohan Hedberg else 978f3d3444aSJohan Hedberg clear_bit(HCI_ADVERTISING, &hdev->dev_flags); 979c1d5dc4aSJohan Hedberg } 980c1d5dc4aSJohan Hedberg 98104b4edcbSJohan Hedberg hci_dev_unlock(hdev); 982c1d5dc4aSJohan Hedberg } 983c1d5dc4aSJohan Hedberg 984eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, 985eb9d91f5SAndre Guedes struct sk_buff *skb) 986eb9d91f5SAndre Guedes { 987eb9d91f5SAndre Guedes struct hci_cp_le_set_scan_enable *cp; 988eb9d91f5SAndre Guedes __u8 status = *((__u8 *) skb->data); 989eb9d91f5SAndre Guedes 9909f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 991eb9d91f5SAndre Guedes 992eb9d91f5SAndre Guedes cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE); 993eb9d91f5SAndre Guedes if (!cp) 994eb9d91f5SAndre Guedes return; 995eb9d91f5SAndre Guedes 996fef5234aSAndre Guedes if (status) 9977ba8b4beSAndre Guedes return; 9987ba8b4beSAndre Guedes 9993fd319b8SAndre Guedes switch (cp->enable) { 10003fd319b8SAndre Guedes case LE_SCAN_ENABLE: 1001d23264a8SAndre Guedes set_bit(HCI_LE_SCAN, &hdev->dev_flags); 100268a8aea4SAndrei Emeltchenko break; 100368a8aea4SAndrei Emeltchenko 100476a388beSAndre Guedes case LE_SCAN_DISABLE: 1005d23264a8SAndre Guedes clear_bit(HCI_LE_SCAN, &hdev->dev_flags); 100668a8aea4SAndrei Emeltchenko break; 100768a8aea4SAndrei Emeltchenko 100868a8aea4SAndrei Emeltchenko default: 100968a8aea4SAndrei Emeltchenko BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable); 101068a8aea4SAndrei Emeltchenko break; 101135815085SAndre Guedes } 1012eb9d91f5SAndre Guedes } 1013eb9d91f5SAndre Guedes 1014cf1d081fSJohan Hedberg static void hci_cc_le_read_white_list_size(struct hci_dev *hdev, 1015cf1d081fSJohan Hedberg struct sk_buff *skb) 1016cf1d081fSJohan Hedberg { 1017cf1d081fSJohan Hedberg struct hci_rp_le_read_white_list_size *rp = (void *) skb->data; 1018cf1d081fSJohan Hedberg 1019cf1d081fSJohan Hedberg BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size); 1020cf1d081fSJohan Hedberg 1021cf1d081fSJohan Hedberg if (!rp->status) 1022cf1d081fSJohan Hedberg hdev->le_white_list_size = rp->size; 1023cf1d081fSJohan Hedberg } 1024cf1d081fSJohan Hedberg 10259b008c04SJohan Hedberg static void hci_cc_le_read_supported_states(struct hci_dev *hdev, 10269b008c04SJohan Hedberg struct sk_buff *skb) 10279b008c04SJohan Hedberg { 10289b008c04SJohan Hedberg struct hci_rp_le_read_supported_states *rp = (void *) skb->data; 10299b008c04SJohan Hedberg 10309b008c04SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 10319b008c04SJohan Hedberg 10329b008c04SJohan Hedberg if (!rp->status) 10339b008c04SJohan Hedberg memcpy(hdev->le_states, rp->le_states, 8); 10349b008c04SJohan Hedberg } 10359b008c04SJohan Hedberg 10366039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev, 1037f9b49306SAndre Guedes struct sk_buff *skb) 1038f9b49306SAndre Guedes { 103906199cf8SJohan Hedberg struct hci_cp_write_le_host_supported *sent; 1040f9b49306SAndre Guedes __u8 status = *((__u8 *) skb->data); 1041f9b49306SAndre Guedes 10429f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1043f9b49306SAndre Guedes 104406199cf8SJohan Hedberg sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED); 10458f984dfaSJohan Hedberg if (!sent) 1046f9b49306SAndre Guedes return; 1047f9b49306SAndre Guedes 10488f984dfaSJohan Hedberg if (!status) { 1049416a4ae5SJohan Hedberg if (sent->le) { 1050cad718edSJohan Hedberg hdev->features[1][0] |= LMP_HOST_LE; 1051416a4ae5SJohan Hedberg set_bit(HCI_LE_ENABLED, &hdev->dev_flags); 1052416a4ae5SJohan Hedberg } else { 1053cad718edSJohan Hedberg hdev->features[1][0] &= ~LMP_HOST_LE; 1054416a4ae5SJohan Hedberg clear_bit(HCI_LE_ENABLED, &hdev->dev_flags); 1055f3d3444aSJohan Hedberg clear_bit(HCI_ADVERTISING, &hdev->dev_flags); 1056416a4ae5SJohan Hedberg } 105753b2caabSJohan Hedberg 105853b2caabSJohan Hedberg if (sent->simul) 1059cad718edSJohan Hedberg hdev->features[1][0] |= LMP_HOST_LE_BREDR; 106053b2caabSJohan Hedberg else 1061cad718edSJohan Hedberg hdev->features[1][0] &= ~LMP_HOST_LE_BREDR; 10628f984dfaSJohan Hedberg } 1063f9b49306SAndre Guedes } 1064f9b49306SAndre Guedes 106593c284eeSAndrei Emeltchenko static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev, 106693c284eeSAndrei Emeltchenko struct sk_buff *skb) 106793c284eeSAndrei Emeltchenko { 106893c284eeSAndrei Emeltchenko struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data; 106993c284eeSAndrei Emeltchenko 107093c284eeSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x", 107193c284eeSAndrei Emeltchenko hdev->name, rp->status, rp->phy_handle); 107293c284eeSAndrei Emeltchenko 107393c284eeSAndrei Emeltchenko if (rp->status) 107493c284eeSAndrei Emeltchenko return; 107593c284eeSAndrei Emeltchenko 107693c284eeSAndrei Emeltchenko amp_write_rem_assoc_continue(hdev, rp->phy_handle); 107793c284eeSAndrei Emeltchenko } 107893c284eeSAndrei Emeltchenko 10796039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 1080a9de9248SMarcel Holtmann { 10819f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1082a9de9248SMarcel Holtmann 1083a9de9248SMarcel Holtmann if (status) { 1084a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 1085314b2381SJohan Hedberg return; 1086314b2381SJohan Hedberg } 1087314b2381SJohan Hedberg 108889352e7dSAndre Guedes set_bit(HCI_INQUIRY, &hdev->flags); 1089a9de9248SMarcel Holtmann } 1090a9de9248SMarcel Holtmann 10916039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 10921da177e4SLinus Torvalds { 1093a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 10941da177e4SLinus Torvalds struct hci_conn *conn; 10951da177e4SLinus Torvalds 10969f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1097a9de9248SMarcel Holtmann 1098a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 10991da177e4SLinus Torvalds if (!cp) 11001da177e4SLinus Torvalds return; 11011da177e4SLinus Torvalds 11021da177e4SLinus Torvalds hci_dev_lock(hdev); 11031da177e4SLinus Torvalds 11041da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 11051da177e4SLinus Torvalds 11066ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn); 11071da177e4SLinus Torvalds 11081da177e4SLinus Torvalds if (status) { 11091da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 11104c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 11111da177e4SLinus Torvalds conn->state = BT_CLOSED; 11121da177e4SLinus Torvalds hci_proto_connect_cfm(conn, status); 11131da177e4SLinus Torvalds hci_conn_del(conn); 11144c67bc74SMarcel Holtmann } else 11154c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 11161da177e4SLinus Torvalds } 11171da177e4SLinus Torvalds } else { 11181da177e4SLinus Torvalds if (!conn) { 11191da177e4SLinus Torvalds conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); 11201da177e4SLinus Torvalds if (conn) { 1121a0c808b3SJohan Hedberg conn->out = true; 11221da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 11231da177e4SLinus Torvalds } else 1124893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 11251da177e4SLinus Torvalds } 11261da177e4SLinus Torvalds } 11271da177e4SLinus Torvalds 11281da177e4SLinus Torvalds hci_dev_unlock(hdev); 11291da177e4SLinus Torvalds } 11301da177e4SLinus Torvalds 1131a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 11321da177e4SLinus Torvalds { 1133a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 11341da177e4SLinus Torvalds struct hci_conn *acl, *sco; 11351da177e4SLinus Torvalds __u16 handle; 11361da177e4SLinus Torvalds 11379f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1138b6a0dc82SMarcel Holtmann 1139a9de9248SMarcel Holtmann if (!status) 1140a9de9248SMarcel Holtmann return; 1141a9de9248SMarcel Holtmann 1142a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 11431da177e4SLinus Torvalds if (!cp) 1144a9de9248SMarcel Holtmann return; 11451da177e4SLinus Torvalds 11461da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 11471da177e4SLinus Torvalds 11489f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, handle); 11491da177e4SLinus Torvalds 11501da177e4SLinus Torvalds hci_dev_lock(hdev); 11511da177e4SLinus Torvalds 11521da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 11535a08ecceSAndrei Emeltchenko if (acl) { 11545a08ecceSAndrei Emeltchenko sco = acl->link; 11555a08ecceSAndrei Emeltchenko if (sco) { 11561da177e4SLinus Torvalds sco->state = BT_CLOSED; 11571da177e4SLinus Torvalds 11581da177e4SLinus Torvalds hci_proto_connect_cfm(sco, status); 11591da177e4SLinus Torvalds hci_conn_del(sco); 11601da177e4SLinus Torvalds } 11615a08ecceSAndrei Emeltchenko } 11621da177e4SLinus Torvalds 11631da177e4SLinus Torvalds hci_dev_unlock(hdev); 11641da177e4SLinus Torvalds } 11651da177e4SLinus Torvalds 1166f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 1167f8558555SMarcel Holtmann { 1168f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 1169f8558555SMarcel Holtmann struct hci_conn *conn; 1170f8558555SMarcel Holtmann 11719f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1172f8558555SMarcel Holtmann 1173f8558555SMarcel Holtmann if (!status) 1174f8558555SMarcel Holtmann return; 1175f8558555SMarcel Holtmann 1176f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 1177f8558555SMarcel Holtmann if (!cp) 1178f8558555SMarcel Holtmann return; 1179f8558555SMarcel Holtmann 1180f8558555SMarcel Holtmann hci_dev_lock(hdev); 1181f8558555SMarcel Holtmann 1182f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1183f8558555SMarcel Holtmann if (conn) { 1184f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1185f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 118676a68ba0SDavid Herrmann hci_conn_drop(conn); 1187f8558555SMarcel Holtmann } 1188f8558555SMarcel Holtmann } 1189f8558555SMarcel Holtmann 1190f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1191f8558555SMarcel Holtmann } 1192f8558555SMarcel Holtmann 1193f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 1194f8558555SMarcel Holtmann { 1195f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 1196f8558555SMarcel Holtmann struct hci_conn *conn; 1197f8558555SMarcel Holtmann 11989f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1199f8558555SMarcel Holtmann 1200f8558555SMarcel Holtmann if (!status) 1201f8558555SMarcel Holtmann return; 1202f8558555SMarcel Holtmann 1203f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 1204f8558555SMarcel Holtmann if (!cp) 1205f8558555SMarcel Holtmann return; 1206f8558555SMarcel Holtmann 1207f8558555SMarcel Holtmann hci_dev_lock(hdev); 1208f8558555SMarcel Holtmann 1209f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1210f8558555SMarcel Holtmann if (conn) { 1211f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1212f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 121376a68ba0SDavid Herrmann hci_conn_drop(conn); 1214f8558555SMarcel Holtmann } 1215f8558555SMarcel Holtmann } 1216f8558555SMarcel Holtmann 1217f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1218f8558555SMarcel Holtmann } 1219f8558555SMarcel Holtmann 1220127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev, 1221392599b9SJohan Hedberg struct hci_conn *conn) 1222392599b9SJohan Hedberg { 1223392599b9SJohan Hedberg if (conn->state != BT_CONFIG || !conn->out) 1224392599b9SJohan Hedberg return 0; 1225392599b9SJohan Hedberg 1226765c2a96SJohan Hedberg if (conn->pending_sec_level == BT_SECURITY_SDP) 1227392599b9SJohan Hedberg return 0; 1228392599b9SJohan Hedberg 1229392599b9SJohan Hedberg /* Only request authentication for SSP connections or non-SSP 1230264b8b4eSJohan Hedberg * devices with sec_level MEDIUM or HIGH or if MITM protection 1231264b8b4eSJohan Hedberg * is requested. 1232264b8b4eSJohan Hedberg */ 1233807deac2SGustavo Padovan if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) && 1234264b8b4eSJohan Hedberg conn->pending_sec_level != BT_SECURITY_HIGH && 1235264b8b4eSJohan Hedberg conn->pending_sec_level != BT_SECURITY_MEDIUM) 1236392599b9SJohan Hedberg return 0; 1237392599b9SJohan Hedberg 1238392599b9SJohan Hedberg return 1; 1239392599b9SJohan Hedberg } 1240392599b9SJohan Hedberg 12416039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev, 124200abfe44SGustavo F. Padovan struct inquiry_entry *e) 124330dc78e1SJohan Hedberg { 124430dc78e1SJohan Hedberg struct hci_cp_remote_name_req cp; 124530dc78e1SJohan Hedberg 124630dc78e1SJohan Hedberg memset(&cp, 0, sizeof(cp)); 124730dc78e1SJohan Hedberg 124830dc78e1SJohan Hedberg bacpy(&cp.bdaddr, &e->data.bdaddr); 124930dc78e1SJohan Hedberg cp.pscan_rep_mode = e->data.pscan_rep_mode; 125030dc78e1SJohan Hedberg cp.pscan_mode = e->data.pscan_mode; 125130dc78e1SJohan Hedberg cp.clock_offset = e->data.clock_offset; 125230dc78e1SJohan Hedberg 125330dc78e1SJohan Hedberg return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 125430dc78e1SJohan Hedberg } 125530dc78e1SJohan Hedberg 1256b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev) 125730dc78e1SJohan Hedberg { 125830dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 125930dc78e1SJohan Hedberg struct inquiry_entry *e; 126030dc78e1SJohan Hedberg 1261b644ba33SJohan Hedberg if (list_empty(&discov->resolve)) 1262b644ba33SJohan Hedberg return false; 1263b644ba33SJohan Hedberg 1264b644ba33SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 1265c810089cSRam Malovany if (!e) 1266c810089cSRam Malovany return false; 1267c810089cSRam Malovany 1268b644ba33SJohan Hedberg if (hci_resolve_name(hdev, e) == 0) { 1269b644ba33SJohan Hedberg e->name_state = NAME_PENDING; 1270b644ba33SJohan Hedberg return true; 1271b644ba33SJohan Hedberg } 1272b644ba33SJohan Hedberg 1273b644ba33SJohan Hedberg return false; 1274b644ba33SJohan Hedberg } 1275b644ba33SJohan Hedberg 1276b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn, 1277b644ba33SJohan Hedberg bdaddr_t *bdaddr, u8 *name, u8 name_len) 1278b644ba33SJohan Hedberg { 1279b644ba33SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 1280b644ba33SJohan Hedberg struct inquiry_entry *e; 1281b644ba33SJohan Hedberg 1282b644ba33SJohan Hedberg if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 128304124681SGustavo F. Padovan mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name, 128404124681SGustavo F. Padovan name_len, conn->dev_class); 1285b644ba33SJohan Hedberg 1286b644ba33SJohan Hedberg if (discov->state == DISCOVERY_STOPPED) 1287b644ba33SJohan Hedberg return; 1288b644ba33SJohan Hedberg 128930dc78e1SJohan Hedberg if (discov->state == DISCOVERY_STOPPING) 129030dc78e1SJohan Hedberg goto discov_complete; 129130dc78e1SJohan Hedberg 129230dc78e1SJohan Hedberg if (discov->state != DISCOVERY_RESOLVING) 129330dc78e1SJohan Hedberg return; 129430dc78e1SJohan Hedberg 129530dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING); 12967cc8380eSRam Malovany /* If the device was not found in a list of found devices names of which 12977cc8380eSRam Malovany * are pending. there is no need to continue resolving a next name as it 12987cc8380eSRam Malovany * will be done upon receiving another Remote Name Request Complete 12997cc8380eSRam Malovany * Event */ 13007cc8380eSRam Malovany if (!e) 13017cc8380eSRam Malovany return; 13027cc8380eSRam Malovany 130330dc78e1SJohan Hedberg list_del(&e->list); 13047cc8380eSRam Malovany if (name) { 13057cc8380eSRam Malovany e->name_state = NAME_KNOWN; 1306b644ba33SJohan Hedberg mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, 1307b644ba33SJohan Hedberg e->data.rssi, name, name_len); 1308c3e7c0d9SRam Malovany } else { 1309c3e7c0d9SRam Malovany e->name_state = NAME_NOT_KNOWN; 131030dc78e1SJohan Hedberg } 131130dc78e1SJohan Hedberg 1312b644ba33SJohan Hedberg if (hci_resolve_next_name(hdev)) 131330dc78e1SJohan Hedberg return; 131430dc78e1SJohan Hedberg 131530dc78e1SJohan Hedberg discov_complete: 131630dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 131730dc78e1SJohan Hedberg } 131830dc78e1SJohan Hedberg 1319a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 13201da177e4SLinus Torvalds { 1321127178d2SJohan Hedberg struct hci_cp_remote_name_req *cp; 1322127178d2SJohan Hedberg struct hci_conn *conn; 1323127178d2SJohan Hedberg 13249f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1325127178d2SJohan Hedberg 1326127178d2SJohan Hedberg /* If successful wait for the name req complete event before 1327127178d2SJohan Hedberg * checking for the need to do authentication */ 1328127178d2SJohan Hedberg if (!status) 1329127178d2SJohan Hedberg return; 1330127178d2SJohan Hedberg 1331127178d2SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); 1332127178d2SJohan Hedberg if (!cp) 1333127178d2SJohan Hedberg return; 1334127178d2SJohan Hedberg 1335127178d2SJohan Hedberg hci_dev_lock(hdev); 1336127178d2SJohan Hedberg 1337127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 1338b644ba33SJohan Hedberg 1339b644ba33SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1340b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0); 1341b644ba33SJohan Hedberg 134279c6c70cSJohan Hedberg if (!conn) 134379c6c70cSJohan Hedberg goto unlock; 134479c6c70cSJohan Hedberg 134579c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 134679c6c70cSJohan Hedberg goto unlock; 134779c6c70cSJohan Hedberg 134851a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 1349c1f23a2bSJohannes Berg struct hci_cp_auth_requested auth_cp; 1350c1f23a2bSJohannes Berg 1351c1f23a2bSJohannes Berg auth_cp.handle = __cpu_to_le16(conn->handle); 1352c1f23a2bSJohannes Berg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, 1353c1f23a2bSJohannes Berg sizeof(auth_cp), &auth_cp); 1354127178d2SJohan Hedberg } 1355127178d2SJohan Hedberg 135679c6c70cSJohan Hedberg unlock: 1357127178d2SJohan Hedberg hci_dev_unlock(hdev); 1358a9de9248SMarcel Holtmann } 13591da177e4SLinus Torvalds 1360769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 1361769be974SMarcel Holtmann { 1362769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 1363769be974SMarcel Holtmann struct hci_conn *conn; 1364769be974SMarcel Holtmann 13659f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1366769be974SMarcel Holtmann 1367769be974SMarcel Holtmann if (!status) 1368769be974SMarcel Holtmann return; 1369769be974SMarcel Holtmann 1370769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 1371769be974SMarcel Holtmann if (!cp) 1372769be974SMarcel Holtmann return; 1373769be974SMarcel Holtmann 1374769be974SMarcel Holtmann hci_dev_lock(hdev); 1375769be974SMarcel Holtmann 1376769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1377769be974SMarcel Holtmann if (conn) { 1378769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1379769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 138076a68ba0SDavid Herrmann hci_conn_drop(conn); 1381769be974SMarcel Holtmann } 1382769be974SMarcel Holtmann } 1383769be974SMarcel Holtmann 1384769be974SMarcel Holtmann hci_dev_unlock(hdev); 1385769be974SMarcel Holtmann } 1386769be974SMarcel Holtmann 1387769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 1388769be974SMarcel Holtmann { 1389769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features *cp; 1390769be974SMarcel Holtmann struct hci_conn *conn; 1391769be974SMarcel Holtmann 13929f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1393769be974SMarcel Holtmann 1394769be974SMarcel Holtmann if (!status) 1395769be974SMarcel Holtmann return; 1396769be974SMarcel Holtmann 1397769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 1398769be974SMarcel Holtmann if (!cp) 1399769be974SMarcel Holtmann return; 1400769be974SMarcel Holtmann 1401769be974SMarcel Holtmann hci_dev_lock(hdev); 1402769be974SMarcel Holtmann 1403769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1404769be974SMarcel Holtmann if (conn) { 1405769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1406769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 140776a68ba0SDavid Herrmann hci_conn_drop(conn); 1408769be974SMarcel Holtmann } 1409769be974SMarcel Holtmann } 1410769be974SMarcel Holtmann 1411769be974SMarcel Holtmann hci_dev_unlock(hdev); 1412769be974SMarcel Holtmann } 1413769be974SMarcel Holtmann 1414a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 1415a9de9248SMarcel Holtmann { 1416b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 1417b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 1418b6a0dc82SMarcel Holtmann __u16 handle; 1419b6a0dc82SMarcel Holtmann 14209f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1421b6a0dc82SMarcel Holtmann 1422b6a0dc82SMarcel Holtmann if (!status) 1423b6a0dc82SMarcel Holtmann return; 1424b6a0dc82SMarcel Holtmann 1425b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 1426b6a0dc82SMarcel Holtmann if (!cp) 1427b6a0dc82SMarcel Holtmann return; 1428b6a0dc82SMarcel Holtmann 1429b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 1430b6a0dc82SMarcel Holtmann 14319f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, handle); 1432b6a0dc82SMarcel Holtmann 1433b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 1434b6a0dc82SMarcel Holtmann 1435b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 14365a08ecceSAndrei Emeltchenko if (acl) { 14375a08ecceSAndrei Emeltchenko sco = acl->link; 14385a08ecceSAndrei Emeltchenko if (sco) { 1439b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 1440b6a0dc82SMarcel Holtmann 1441b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(sco, status); 1442b6a0dc82SMarcel Holtmann hci_conn_del(sco); 1443b6a0dc82SMarcel Holtmann } 14445a08ecceSAndrei Emeltchenko } 1445b6a0dc82SMarcel Holtmann 1446b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 1447a9de9248SMarcel Holtmann } 1448a9de9248SMarcel Holtmann 1449a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 1450a9de9248SMarcel Holtmann { 1451a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 145204837f64SMarcel Holtmann struct hci_conn *conn; 145304837f64SMarcel Holtmann 14549f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1455a9de9248SMarcel Holtmann 1456a9de9248SMarcel Holtmann if (!status) 1457a9de9248SMarcel Holtmann return; 1458a9de9248SMarcel Holtmann 1459a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 146004837f64SMarcel Holtmann if (!cp) 1461a9de9248SMarcel Holtmann return; 146204837f64SMarcel Holtmann 146304837f64SMarcel Holtmann hci_dev_lock(hdev); 146404837f64SMarcel Holtmann 146504837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1466e73439d8SMarcel Holtmann if (conn) { 146751a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 146804837f64SMarcel Holtmann 146951a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1470e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1471e73439d8SMarcel Holtmann } 1472e73439d8SMarcel Holtmann 147304837f64SMarcel Holtmann hci_dev_unlock(hdev); 147404837f64SMarcel Holtmann } 147504837f64SMarcel Holtmann 1476a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 1477a9de9248SMarcel Holtmann { 1478a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 147904837f64SMarcel Holtmann struct hci_conn *conn; 148004837f64SMarcel Holtmann 14819f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1482a9de9248SMarcel Holtmann 1483a9de9248SMarcel Holtmann if (!status) 1484a9de9248SMarcel Holtmann return; 1485a9de9248SMarcel Holtmann 1486a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 148704837f64SMarcel Holtmann if (!cp) 1488a9de9248SMarcel Holtmann return; 148904837f64SMarcel Holtmann 149004837f64SMarcel Holtmann hci_dev_lock(hdev); 149104837f64SMarcel Holtmann 149204837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1493e73439d8SMarcel Holtmann if (conn) { 149451a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 149504837f64SMarcel Holtmann 149651a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1497e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1498e73439d8SMarcel Holtmann } 1499e73439d8SMarcel Holtmann 150004837f64SMarcel Holtmann hci_dev_unlock(hdev); 150104837f64SMarcel Holtmann } 150204837f64SMarcel Holtmann 150388c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) 150488c3df13SJohan Hedberg { 150588c3df13SJohan Hedberg struct hci_cp_disconnect *cp; 150688c3df13SJohan Hedberg struct hci_conn *conn; 150788c3df13SJohan Hedberg 150888c3df13SJohan Hedberg if (!status) 150988c3df13SJohan Hedberg return; 151088c3df13SJohan Hedberg 151188c3df13SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT); 151288c3df13SJohan Hedberg if (!cp) 151388c3df13SJohan Hedberg return; 151488c3df13SJohan Hedberg 151588c3df13SJohan Hedberg hci_dev_lock(hdev); 151688c3df13SJohan Hedberg 151788c3df13SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 151888c3df13SJohan Hedberg if (conn) 151988c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 152088c3df13SJohan Hedberg conn->dst_type, status); 152188c3df13SJohan Hedberg 152288c3df13SJohan Hedberg hci_dev_unlock(hdev); 152388c3df13SJohan Hedberg } 152488c3df13SJohan Hedberg 1525a02226d6SAndrei Emeltchenko static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status) 1526a02226d6SAndrei Emeltchenko { 152793c284eeSAndrei Emeltchenko struct hci_cp_create_phy_link *cp; 152893c284eeSAndrei Emeltchenko 1529a02226d6SAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 153093c284eeSAndrei Emeltchenko 153193c284eeSAndrei Emeltchenko cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK); 153293c284eeSAndrei Emeltchenko if (!cp) 153393c284eeSAndrei Emeltchenko return; 153493c284eeSAndrei Emeltchenko 1535e58917b9SAndrei Emeltchenko hci_dev_lock(hdev); 1536e58917b9SAndrei Emeltchenko 1537e58917b9SAndrei Emeltchenko if (status) { 1538e58917b9SAndrei Emeltchenko struct hci_conn *hcon; 1539e58917b9SAndrei Emeltchenko 1540e58917b9SAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle); 1541e58917b9SAndrei Emeltchenko if (hcon) 1542e58917b9SAndrei Emeltchenko hci_conn_del(hcon); 1543e58917b9SAndrei Emeltchenko } else { 154493c284eeSAndrei Emeltchenko amp_write_remote_assoc(hdev, cp->phy_handle); 1545a02226d6SAndrei Emeltchenko } 1546a02226d6SAndrei Emeltchenko 1547e58917b9SAndrei Emeltchenko hci_dev_unlock(hdev); 1548e58917b9SAndrei Emeltchenko } 1549e58917b9SAndrei Emeltchenko 15500b26ab9dSAndrei Emeltchenko static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status) 15510b26ab9dSAndrei Emeltchenko { 15520b26ab9dSAndrei Emeltchenko struct hci_cp_accept_phy_link *cp; 15530b26ab9dSAndrei Emeltchenko 15540b26ab9dSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 15550b26ab9dSAndrei Emeltchenko 15560b26ab9dSAndrei Emeltchenko if (status) 15570b26ab9dSAndrei Emeltchenko return; 15580b26ab9dSAndrei Emeltchenko 15590b26ab9dSAndrei Emeltchenko cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK); 15600b26ab9dSAndrei Emeltchenko if (!cp) 15610b26ab9dSAndrei Emeltchenko return; 15620b26ab9dSAndrei Emeltchenko 15630b26ab9dSAndrei Emeltchenko amp_write_remote_assoc(hdev, cp->phy_handle); 15640b26ab9dSAndrei Emeltchenko } 15650b26ab9dSAndrei Emeltchenko 15666039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 15671da177e4SLinus Torvalds { 15681da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 156930dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 157030dc78e1SJohan Hedberg struct inquiry_entry *e; 15711da177e4SLinus Torvalds 15729f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 15731da177e4SLinus Torvalds 1574a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 157589352e7dSAndre Guedes 157689352e7dSAndre Guedes if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) 157789352e7dSAndre Guedes return; 157889352e7dSAndre Guedes 15793e13fa1eSAndre Guedes smp_mb__after_clear_bit(); /* wake_up_bit advises about this barrier */ 15803e13fa1eSAndre Guedes wake_up_bit(&hdev->flags, HCI_INQUIRY); 15813e13fa1eSAndre Guedes 1582a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 158330dc78e1SJohan Hedberg return; 158430dc78e1SJohan Hedberg 158556e5cb86SJohan Hedberg hci_dev_lock(hdev); 158630dc78e1SJohan Hedberg 1587343f935bSAndre Guedes if (discov->state != DISCOVERY_FINDING) 158830dc78e1SJohan Hedberg goto unlock; 158930dc78e1SJohan Hedberg 159030dc78e1SJohan Hedberg if (list_empty(&discov->resolve)) { 1591ff9ef578SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 159230dc78e1SJohan Hedberg goto unlock; 159330dc78e1SJohan Hedberg } 159430dc78e1SJohan Hedberg 159530dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 159630dc78e1SJohan Hedberg if (e && hci_resolve_name(hdev, e) == 0) { 159730dc78e1SJohan Hedberg e->name_state = NAME_PENDING; 159830dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_RESOLVING); 159930dc78e1SJohan Hedberg } else { 160030dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 160130dc78e1SJohan Hedberg } 160230dc78e1SJohan Hedberg 160330dc78e1SJohan Hedberg unlock: 160456e5cb86SJohan Hedberg hci_dev_unlock(hdev); 16051da177e4SLinus Torvalds } 16061da177e4SLinus Torvalds 16076039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 16081da177e4SLinus Torvalds { 160945bb4bf0SMarcel Holtmann struct inquiry_data data; 1610a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 16111da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 16121da177e4SLinus Torvalds 16131da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 16141da177e4SLinus Torvalds 161545bb4bf0SMarcel Holtmann if (!num_rsp) 161645bb4bf0SMarcel Holtmann return; 161745bb4bf0SMarcel Holtmann 16181519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 16191519cc17SAndre Guedes return; 16201519cc17SAndre Guedes 16211da177e4SLinus Torvalds hci_dev_lock(hdev); 162245bb4bf0SMarcel Holtmann 1623e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 1624388fc8faSJohan Hedberg bool name_known, ssp; 16253175405bSJohan Hedberg 16261da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 16271da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 16281da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 16291da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 16301da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 16311da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 16321da177e4SLinus Torvalds data.rssi = 0x00; 163341a96212SMarcel Holtmann data.ssp_mode = 0x00; 16343175405bSJohan Hedberg 1635388fc8faSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp); 163648264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 163704124681SGustavo F. Padovan info->dev_class, 0, !name_known, ssp, NULL, 163804124681SGustavo F. Padovan 0); 16391da177e4SLinus Torvalds } 164045bb4bf0SMarcel Holtmann 16411da177e4SLinus Torvalds hci_dev_unlock(hdev); 16421da177e4SLinus Torvalds } 16431da177e4SLinus Torvalds 16446039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 16451da177e4SLinus Torvalds { 1646a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 1647a9de9248SMarcel Holtmann struct hci_conn *conn; 16481da177e4SLinus Torvalds 1649a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 165045bb4bf0SMarcel Holtmann 16511da177e4SLinus Torvalds hci_dev_lock(hdev); 165245bb4bf0SMarcel Holtmann 1653a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 16549499237aSMarcel Holtmann if (!conn) { 16559499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 16569499237aSMarcel Holtmann goto unlock; 16579499237aSMarcel Holtmann 16589499237aSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 1659a9de9248SMarcel Holtmann if (!conn) 1660a9de9248SMarcel Holtmann goto unlock; 166145bb4bf0SMarcel Holtmann 16629499237aSMarcel Holtmann conn->type = SCO_LINK; 16639499237aSMarcel Holtmann } 16649499237aSMarcel Holtmann 1665a9de9248SMarcel Holtmann if (!ev->status) { 1666a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 1667769be974SMarcel Holtmann 1668769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 1669769be974SMarcel Holtmann conn->state = BT_CONFIG; 1670769be974SMarcel Holtmann hci_conn_hold(conn); 1671a9ea3ed9SSzymon Janc 1672a9ea3ed9SSzymon Janc if (!conn->out && !hci_conn_ssp_enabled(conn) && 1673a9ea3ed9SSzymon Janc !hci_find_link_key(hdev, &ev->bdaddr)) 1674a9ea3ed9SSzymon Janc conn->disc_timeout = HCI_PAIRING_TIMEOUT; 1675a9ea3ed9SSzymon Janc else 1676052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1677769be974SMarcel Holtmann } else 1678a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 1679a9de9248SMarcel Holtmann 16807d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 16817d0db0a3SMarcel Holtmann 1682a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 1683a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1684a9de9248SMarcel Holtmann 1685a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 1686a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1687a9de9248SMarcel Holtmann 1688a9de9248SMarcel Holtmann /* Get remote features */ 1689a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 1690a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 1691a9de9248SMarcel Holtmann cp.handle = ev->handle; 1692769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 1693769be974SMarcel Holtmann sizeof(cp), &cp); 169445bb4bf0SMarcel Holtmann } 1695a9de9248SMarcel Holtmann 1696a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 1697d095c1ebSAndrei Emeltchenko if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) { 1698a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 1699a9de9248SMarcel Holtmann cp.handle = ev->handle; 1700a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 170104124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp), 170204124681SGustavo F. Padovan &cp); 1703a9de9248SMarcel Holtmann } 170417d5c04cSJohan Hedberg } else { 1705a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 170617d5c04cSJohan Hedberg if (conn->type == ACL_LINK) 1707744cf19eSJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 170848264f06SJohan Hedberg conn->dst_type, ev->status); 170917d5c04cSJohan Hedberg } 171045bb4bf0SMarcel Holtmann 1711e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 1712e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 171345bb4bf0SMarcel Holtmann 1714769be974SMarcel Holtmann if (ev->status) { 1715a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1716a9de9248SMarcel Holtmann hci_conn_del(conn); 1717c89b6e6bSMarcel Holtmann } else if (ev->link_type != ACL_LINK) 1718c89b6e6bSMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1719a9de9248SMarcel Holtmann 1720a9de9248SMarcel Holtmann unlock: 17211da177e4SLinus Torvalds hci_dev_unlock(hdev); 1722a9de9248SMarcel Holtmann 1723a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 17241da177e4SLinus Torvalds } 17251da177e4SLinus Torvalds 17266039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 17271da177e4SLinus Torvalds { 1728a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 17291da177e4SLinus Torvalds int mask = hdev->link_mode; 173020714bfeSFrédéric Dalleau __u8 flags = 0; 17311da177e4SLinus Torvalds 17326ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr, 1733807deac2SGustavo Padovan ev->link_type); 17341da177e4SLinus Torvalds 173520714bfeSFrédéric Dalleau mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type, 173620714bfeSFrédéric Dalleau &flags); 17371da177e4SLinus Torvalds 1738138d22efSSzymon Janc if ((mask & HCI_LM_ACCEPT) && 1739b9ee0a78SMarcel Holtmann !hci_blacklist_lookup(hdev, &ev->bdaddr, BDADDR_BREDR)) { 17401da177e4SLinus Torvalds /* Connection accepted */ 1741c7bdd502SMarcel Holtmann struct inquiry_entry *ie; 17421da177e4SLinus Torvalds struct hci_conn *conn; 17431da177e4SLinus Torvalds 17441da177e4SLinus Torvalds hci_dev_lock(hdev); 1745b6a0dc82SMarcel Holtmann 1746cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 1747cc11b9c1SAndrei Emeltchenko if (ie) 1748c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 1749c7bdd502SMarcel Holtmann 17508fc9ced3SGustavo Padovan conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, 17518fc9ced3SGustavo Padovan &ev->bdaddr); 17521da177e4SLinus Torvalds if (!conn) { 1753cc11b9c1SAndrei Emeltchenko conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); 1754cc11b9c1SAndrei Emeltchenko if (!conn) { 1755893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 17561da177e4SLinus Torvalds hci_dev_unlock(hdev); 17571da177e4SLinus Torvalds return; 17581da177e4SLinus Torvalds } 17591da177e4SLinus Torvalds } 1760b6a0dc82SMarcel Holtmann 17611da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 1762b6a0dc82SMarcel Holtmann 17631da177e4SLinus Torvalds hci_dev_unlock(hdev); 17641da177e4SLinus Torvalds 176520714bfeSFrédéric Dalleau if (ev->link_type == ACL_LINK || 176620714bfeSFrédéric Dalleau (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) { 1767b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 176820714bfeSFrédéric Dalleau conn->state = BT_CONNECT; 1769b6a0dc82SMarcel Holtmann 17701da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 17711da177e4SLinus Torvalds 17721da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 17731da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 17741da177e4SLinus Torvalds else 17751da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 17761da177e4SLinus Torvalds 177704124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), 177804124681SGustavo F. Padovan &cp); 177920714bfeSFrédéric Dalleau } else if (!(flags & HCI_PROTO_DEFER)) { 1780b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 178120714bfeSFrédéric Dalleau conn->state = BT_CONNECT; 1782b6a0dc82SMarcel Holtmann 1783b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 1784a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1785b6a0dc82SMarcel Holtmann 178682781e63SAndrei Emeltchenko cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40); 178782781e63SAndrei Emeltchenko cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40); 178882781e63SAndrei Emeltchenko cp.max_latency = __constant_cpu_to_le16(0xffff); 1789b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 1790b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 1791b6a0dc82SMarcel Holtmann 1792b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 1793b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 179420714bfeSFrédéric Dalleau } else { 179520714bfeSFrédéric Dalleau conn->state = BT_CONNECT2; 179620714bfeSFrédéric Dalleau hci_proto_connect_cfm(conn, 0); 1797b6a0dc82SMarcel Holtmann } 17981da177e4SLinus Torvalds } else { 17991da177e4SLinus Torvalds /* Connection rejected */ 18001da177e4SLinus Torvalds struct hci_cp_reject_conn_req cp; 18011da177e4SLinus Torvalds 18021da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 18039f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_REJ_BAD_ADDR; 1804a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 18051da177e4SLinus Torvalds } 18061da177e4SLinus Torvalds } 18071da177e4SLinus Torvalds 1808f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err) 1809f0d6a0eaSMikel Astiz { 1810f0d6a0eaSMikel Astiz switch (err) { 1811f0d6a0eaSMikel Astiz case HCI_ERROR_CONNECTION_TIMEOUT: 1812f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_TIMEOUT; 1813f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_USER_TERM: 1814f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_LOW_RESOURCES: 1815f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_POWER_OFF: 1816f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_REMOTE; 1817f0d6a0eaSMikel Astiz case HCI_ERROR_LOCAL_HOST_TERM: 1818f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_LOCAL_HOST; 1819f0d6a0eaSMikel Astiz default: 1820f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_UNKNOWN; 1821f0d6a0eaSMikel Astiz } 1822f0d6a0eaSMikel Astiz } 1823f0d6a0eaSMikel Astiz 18246039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 18251da177e4SLinus Torvalds { 1826a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 1827abf54a50SAndre Guedes u8 reason = hci_to_mgmt_reason(ev->reason); 182804837f64SMarcel Holtmann struct hci_conn *conn; 18293846220bSAndre Guedes u8 type; 18301da177e4SLinus Torvalds 18319f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 18321da177e4SLinus Torvalds 18331da177e4SLinus Torvalds hci_dev_lock(hdev); 18341da177e4SLinus Torvalds 183504837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1836f7520543SJohan Hedberg if (!conn) 1837f7520543SJohan Hedberg goto unlock; 1838f7520543SJohan Hedberg 1839f0d6a0eaSMikel Astiz if (ev->status) { 184088c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 184188c3df13SJohan Hedberg conn->dst_type, ev->status); 1842abf54a50SAndre Guedes goto unlock; 1843abf54a50SAndre Guedes } 1844f0d6a0eaSMikel Astiz 18453846220bSAndre Guedes conn->state = BT_CLOSED; 18463846220bSAndre Guedes 1847abf54a50SAndre Guedes if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 1848afc747a6SJohan Hedberg mgmt_device_disconnected(hdev, &conn->dst, conn->type, 1849f0d6a0eaSMikel Astiz conn->dst_type, reason); 1850f7520543SJohan Hedberg 18513846220bSAndre Guedes if (conn->type == ACL_LINK && conn->flush_key) 18526ec5bcadSVishal Agarwal hci_remove_link_key(hdev, &conn->dst); 18533846220bSAndre Guedes 18543846220bSAndre Guedes type = conn->type; 18553846220bSAndre Guedes 18562950f21aSMarcel Holtmann hci_proto_disconn_cfm(conn, ev->reason); 18571da177e4SLinus Torvalds hci_conn_del(conn); 18582210246cSJohan Hedberg 18592210246cSJohan Hedberg /* Re-enable advertising if necessary, since it might 18602210246cSJohan Hedberg * have been disabled by the connection. From the 18612210246cSJohan Hedberg * HCI_LE_Set_Advertise_Enable command description in 18622210246cSJohan Hedberg * the core specification (v4.0): 18632210246cSJohan Hedberg * "The Controller shall continue advertising until the Host 18642210246cSJohan Hedberg * issues an LE_Set_Advertise_Enable command with 18652210246cSJohan Hedberg * Advertising_Enable set to 0x00 (Advertising is disabled) 18662210246cSJohan Hedberg * or until a connection is created or until the Advertising 18672210246cSJohan Hedberg * is timed out due to Directed Advertising." 18682210246cSJohan Hedberg */ 18692210246cSJohan Hedberg if (type == LE_LINK) 18705976e608SMarcel Holtmann mgmt_reenable_advertising(hdev); 18711da177e4SLinus Torvalds 1872f7520543SJohan Hedberg unlock: 18731da177e4SLinus Torvalds hci_dev_unlock(hdev); 18741da177e4SLinus Torvalds } 18751da177e4SLinus Torvalds 18766039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1877a9de9248SMarcel Holtmann { 1878a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 1879a9de9248SMarcel Holtmann struct hci_conn *conn; 1880a9de9248SMarcel Holtmann 18819f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 1882a9de9248SMarcel Holtmann 1883a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1884a9de9248SMarcel Holtmann 1885a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1886d7556e20SWaldemar Rymarkiewicz if (!conn) 1887d7556e20SWaldemar Rymarkiewicz goto unlock; 1888d7556e20SWaldemar Rymarkiewicz 1889765c2a96SJohan Hedberg if (!ev->status) { 1890aa64a8b5SJohan Hedberg if (!hci_conn_ssp_enabled(conn) && 189151a8efd7SJohan Hedberg test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) { 1892d7556e20SWaldemar Rymarkiewicz BT_INFO("re-auth of legacy device is not possible."); 189319f8def0SWaldemar Rymarkiewicz } else { 1894a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1895765c2a96SJohan Hedberg conn->sec_level = conn->pending_sec_level; 189619f8def0SWaldemar Rymarkiewicz } 18972a611692SJohan Hedberg } else { 1898bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 1899bab73cb6SJohan Hedberg ev->status); 19002a611692SJohan Hedberg } 1901a9de9248SMarcel Holtmann 190251a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 190351a8efd7SJohan Hedberg clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags); 1904a9de9248SMarcel Holtmann 1905f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1906aa64a8b5SJohan Hedberg if (!ev->status && hci_conn_ssp_enabled(conn)) { 1907f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1908f8558555SMarcel Holtmann cp.handle = ev->handle; 1909f8558555SMarcel Holtmann cp.encrypt = 0x01; 1910d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1911d7556e20SWaldemar Rymarkiewicz &cp); 1912f8558555SMarcel Holtmann } else { 1913f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1914f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 191576a68ba0SDavid Herrmann hci_conn_drop(conn); 1916f8558555SMarcel Holtmann } 1917052b30b0SMarcel Holtmann } else { 1918a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 1919a9de9248SMarcel Holtmann 1920052b30b0SMarcel Holtmann hci_conn_hold(conn); 1921052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 192276a68ba0SDavid Herrmann hci_conn_drop(conn); 1923052b30b0SMarcel Holtmann } 1924052b30b0SMarcel Holtmann 192551a8efd7SJohan Hedberg if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) { 1926a9de9248SMarcel Holtmann if (!ev->status) { 1927a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1928f8558555SMarcel Holtmann cp.handle = ev->handle; 1929f8558555SMarcel Holtmann cp.encrypt = 0x01; 1930d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1931d7556e20SWaldemar Rymarkiewicz &cp); 1932a9de9248SMarcel Holtmann } else { 193351a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 1934a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 1935a9de9248SMarcel Holtmann } 1936a9de9248SMarcel Holtmann } 1937a9de9248SMarcel Holtmann 1938d7556e20SWaldemar Rymarkiewicz unlock: 1939a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1940a9de9248SMarcel Holtmann } 1941a9de9248SMarcel Holtmann 19426039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 1943a9de9248SMarcel Holtmann { 1944127178d2SJohan Hedberg struct hci_ev_remote_name *ev = (void *) skb->data; 1945127178d2SJohan Hedberg struct hci_conn *conn; 1946127178d2SJohan Hedberg 1947a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1948a9de9248SMarcel Holtmann 1949a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 1950127178d2SJohan Hedberg 1951127178d2SJohan Hedberg hci_dev_lock(hdev); 1952127178d2SJohan Hedberg 1953127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 1954b644ba33SJohan Hedberg 1955b644ba33SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 1956b644ba33SJohan Hedberg goto check_auth; 1957b644ba33SJohan Hedberg 1958b644ba33SJohan Hedberg if (ev->status == 0) 1959b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name, 1960b644ba33SJohan Hedberg strnlen(ev->name, HCI_MAX_NAME_LENGTH)); 1961b644ba33SJohan Hedberg else 1962b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0); 1963b644ba33SJohan Hedberg 1964b644ba33SJohan Hedberg check_auth: 196579c6c70cSJohan Hedberg if (!conn) 196679c6c70cSJohan Hedberg goto unlock; 196779c6c70cSJohan Hedberg 196879c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 196979c6c70cSJohan Hedberg goto unlock; 197079c6c70cSJohan Hedberg 197151a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 1972127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1973127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1974127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1975127178d2SJohan Hedberg } 1976127178d2SJohan Hedberg 197779c6c70cSJohan Hedberg unlock: 1978127178d2SJohan Hedberg hci_dev_unlock(hdev); 1979a9de9248SMarcel Holtmann } 1980a9de9248SMarcel Holtmann 19816039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 1982a9de9248SMarcel Holtmann { 1983a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 1984a9de9248SMarcel Holtmann struct hci_conn *conn; 1985a9de9248SMarcel Holtmann 19869f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 1987a9de9248SMarcel Holtmann 1988a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1989a9de9248SMarcel Holtmann 1990a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1991a9de9248SMarcel Holtmann if (conn) { 1992a9de9248SMarcel Holtmann if (!ev->status) { 1993ae293196SMarcel Holtmann if (ev->encrypt) { 1994ae293196SMarcel Holtmann /* Encryption implies authentication */ 1995ae293196SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1996a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1997da85e5e5SVinicius Costa Gomes conn->sec_level = conn->pending_sec_level; 1998ae293196SMarcel Holtmann } else 1999a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_ENCRYPT; 2000a9de9248SMarcel Holtmann } 2001a9de9248SMarcel Holtmann 200251a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 2003a9de9248SMarcel Holtmann 2004a7d7723aSGustavo Padovan if (ev->status && conn->state == BT_CONNECTED) { 2005bed71748SAndre Guedes hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); 200676a68ba0SDavid Herrmann hci_conn_drop(conn); 2007a7d7723aSGustavo Padovan goto unlock; 2008a7d7723aSGustavo Padovan } 2009a7d7723aSGustavo Padovan 2010f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 2011f8558555SMarcel Holtmann if (!ev->status) 2012f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 2013f8558555SMarcel Holtmann 2014f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 201576a68ba0SDavid Herrmann hci_conn_drop(conn); 2016f8558555SMarcel Holtmann } else 2017a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 2018a9de9248SMarcel Holtmann } 2019a9de9248SMarcel Holtmann 2020a7d7723aSGustavo Padovan unlock: 2021a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2022a9de9248SMarcel Holtmann } 2023a9de9248SMarcel Holtmann 20246039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev, 2025807deac2SGustavo Padovan struct sk_buff *skb) 2026a9de9248SMarcel Holtmann { 2027a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 2028a9de9248SMarcel Holtmann struct hci_conn *conn; 2029a9de9248SMarcel Holtmann 20309f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2031a9de9248SMarcel Holtmann 2032a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2033a9de9248SMarcel Holtmann 2034a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2035a9de9248SMarcel Holtmann if (conn) { 2036a9de9248SMarcel Holtmann if (!ev->status) 2037a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_SECURE; 2038a9de9248SMarcel Holtmann 203951a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 2040a9de9248SMarcel Holtmann 2041a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 2042a9de9248SMarcel Holtmann } 2043a9de9248SMarcel Holtmann 2044a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2045a9de9248SMarcel Holtmann } 2046a9de9248SMarcel Holtmann 20476039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev, 2048807deac2SGustavo Padovan struct sk_buff *skb) 2049a9de9248SMarcel Holtmann { 2050a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 2051a9de9248SMarcel Holtmann struct hci_conn *conn; 2052a9de9248SMarcel Holtmann 20539f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2054a9de9248SMarcel Holtmann 2055a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2056a9de9248SMarcel Holtmann 2057a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2058ccd556feSJohan Hedberg if (!conn) 2059ccd556feSJohan Hedberg goto unlock; 2060ccd556feSJohan Hedberg 2061769be974SMarcel Holtmann if (!ev->status) 2062cad718edSJohan Hedberg memcpy(conn->features[0], ev->features, 8); 2063a9de9248SMarcel Holtmann 2064ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2065ccd556feSJohan Hedberg goto unlock; 2066ccd556feSJohan Hedberg 2067ccd556feSJohan Hedberg if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { 2068769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 2069769be974SMarcel Holtmann cp.handle = ev->handle; 2070769be974SMarcel Holtmann cp.page = 0x01; 2071ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 2072769be974SMarcel Holtmann sizeof(cp), &cp); 2073392599b9SJohan Hedberg goto unlock; 2074392599b9SJohan Hedberg } 2075392599b9SJohan Hedberg 2076671267bfSJohan Hedberg if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { 2077127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2078127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2079127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2080127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2081127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2082b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 2083b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 208408c79b61SJohan Hedberg conn->dst_type, 0, NULL, 0, 2085b644ba33SJohan Hedberg conn->dev_class); 2086392599b9SJohan Hedberg 2087127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2088769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2089769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 209076a68ba0SDavid Herrmann hci_conn_drop(conn); 2091769be974SMarcel Holtmann } 2092769be974SMarcel Holtmann 2093ccd556feSJohan Hedberg unlock: 2094a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2095a9de9248SMarcel Holtmann } 2096a9de9248SMarcel Holtmann 20976039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2098a9de9248SMarcel Holtmann { 2099a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 21009238f36aSJohan Hedberg u8 status = skb->data[sizeof(*ev)]; 2101a9de9248SMarcel Holtmann __u16 opcode; 2102a9de9248SMarcel Holtmann 2103a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2104a9de9248SMarcel Holtmann 2105a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2106a9de9248SMarcel Holtmann 2107a9de9248SMarcel Holtmann switch (opcode) { 2108a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 2109a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 2110a9de9248SMarcel Holtmann break; 2111a9de9248SMarcel Holtmann 21124d93483bSAndre Guedes case HCI_OP_PERIODIC_INQ: 21134d93483bSAndre Guedes hci_cc_periodic_inq(hdev, skb); 21144d93483bSAndre Guedes break; 21154d93483bSAndre Guedes 2116a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 2117a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 2118a9de9248SMarcel Holtmann break; 2119a9de9248SMarcel Holtmann 2120a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 2121a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 2122a9de9248SMarcel Holtmann break; 2123a9de9248SMarcel Holtmann 2124a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 2125a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 2126a9de9248SMarcel Holtmann break; 2127a9de9248SMarcel Holtmann 2128e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 2129e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 2130e4e8e37cSMarcel Holtmann break; 2131e4e8e37cSMarcel Holtmann 2132a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 2133a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 2134a9de9248SMarcel Holtmann break; 2135a9de9248SMarcel Holtmann 2136e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 2137e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 2138e4e8e37cSMarcel Holtmann break; 2139e4e8e37cSMarcel Holtmann 2140e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 2141e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 2142e4e8e37cSMarcel Holtmann break; 2143e4e8e37cSMarcel Holtmann 2144a9de9248SMarcel Holtmann case HCI_OP_RESET: 2145a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 2146a9de9248SMarcel Holtmann break; 2147a9de9248SMarcel Holtmann 2148a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 2149a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 2150a9de9248SMarcel Holtmann break; 2151a9de9248SMarcel Holtmann 2152a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 2153a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 2154a9de9248SMarcel Holtmann break; 2155a9de9248SMarcel Holtmann 2156a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 2157a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 2158a9de9248SMarcel Holtmann break; 2159a9de9248SMarcel Holtmann 2160a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 2161a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 2162a9de9248SMarcel Holtmann break; 2163a9de9248SMarcel Holtmann 2164a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 2165a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 2166a9de9248SMarcel Holtmann break; 2167a9de9248SMarcel Holtmann 2168a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 2169a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 2170a9de9248SMarcel Holtmann break; 2171a9de9248SMarcel Holtmann 2172a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 2173a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 2174a9de9248SMarcel Holtmann break; 2175a9de9248SMarcel Holtmann 2176a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 2177a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 2178a9de9248SMarcel Holtmann break; 2179a9de9248SMarcel Holtmann 2180a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 2181a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 2182a9de9248SMarcel Holtmann break; 2183a9de9248SMarcel Holtmann 2184b4cb9fb2SMarcel Holtmann case HCI_OP_READ_NUM_SUPPORTED_IAC: 2185b4cb9fb2SMarcel Holtmann hci_cc_read_num_supported_iac(hdev, skb); 2186b4cb9fb2SMarcel Holtmann break; 2187b4cb9fb2SMarcel Holtmann 2188333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 2189333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 2190333140b5SMarcel Holtmann break; 2191333140b5SMarcel Holtmann 2192eac83dc6SMarcel Holtmann case HCI_OP_WRITE_SC_SUPPORT: 2193eac83dc6SMarcel Holtmann hci_cc_write_sc_support(hdev, skb); 2194eac83dc6SMarcel Holtmann break; 2195eac83dc6SMarcel Holtmann 2196a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 2197a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 2198a9de9248SMarcel Holtmann break; 2199a9de9248SMarcel Holtmann 2200a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 2201a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 2202a9de9248SMarcel Holtmann break; 2203a9de9248SMarcel Holtmann 2204a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 2205a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 2206a9de9248SMarcel Holtmann break; 2207a9de9248SMarcel Holtmann 2208971e3a4bSAndre Guedes case HCI_OP_READ_LOCAL_EXT_FEATURES: 2209971e3a4bSAndre Guedes hci_cc_read_local_ext_features(hdev, skb); 2210971e3a4bSAndre Guedes break; 2211971e3a4bSAndre Guedes 2212a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 2213a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 2214a9de9248SMarcel Holtmann break; 2215a9de9248SMarcel Holtmann 2216a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 2217a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 2218a9de9248SMarcel Holtmann break; 2219a9de9248SMarcel Holtmann 2220f332ec66SJohan Hedberg case HCI_OP_READ_PAGE_SCAN_ACTIVITY: 2221f332ec66SJohan Hedberg hci_cc_read_page_scan_activity(hdev, skb); 2222f332ec66SJohan Hedberg break; 2223f332ec66SJohan Hedberg 22244a3ee763SJohan Hedberg case HCI_OP_WRITE_PAGE_SCAN_ACTIVITY: 22254a3ee763SJohan Hedberg hci_cc_write_page_scan_activity(hdev, skb); 22264a3ee763SJohan Hedberg break; 22274a3ee763SJohan Hedberg 2228f332ec66SJohan Hedberg case HCI_OP_READ_PAGE_SCAN_TYPE: 2229f332ec66SJohan Hedberg hci_cc_read_page_scan_type(hdev, skb); 2230f332ec66SJohan Hedberg break; 2231f332ec66SJohan Hedberg 22324a3ee763SJohan Hedberg case HCI_OP_WRITE_PAGE_SCAN_TYPE: 22334a3ee763SJohan Hedberg hci_cc_write_page_scan_type(hdev, skb); 22344a3ee763SJohan Hedberg break; 22354a3ee763SJohan Hedberg 2236350ee4cfSAndrei Emeltchenko case HCI_OP_READ_DATA_BLOCK_SIZE: 2237350ee4cfSAndrei Emeltchenko hci_cc_read_data_block_size(hdev, skb); 2238350ee4cfSAndrei Emeltchenko break; 2239350ee4cfSAndrei Emeltchenko 22401e89cffbSAndrei Emeltchenko case HCI_OP_READ_FLOW_CONTROL_MODE: 22411e89cffbSAndrei Emeltchenko hci_cc_read_flow_control_mode(hdev, skb); 22421e89cffbSAndrei Emeltchenko break; 22431e89cffbSAndrei Emeltchenko 2244928abaa7SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_INFO: 2245928abaa7SAndrei Emeltchenko hci_cc_read_local_amp_info(hdev, skb); 2246928abaa7SAndrei Emeltchenko break; 2247928abaa7SAndrei Emeltchenko 2248903e4541SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_ASSOC: 2249903e4541SAndrei Emeltchenko hci_cc_read_local_amp_assoc(hdev, skb); 2250903e4541SAndrei Emeltchenko break; 2251903e4541SAndrei Emeltchenko 2252d5859e22SJohan Hedberg case HCI_OP_READ_INQ_RSP_TX_POWER: 2253d5859e22SJohan Hedberg hci_cc_read_inq_rsp_tx_power(hdev, skb); 2254d5859e22SJohan Hedberg break; 2255d5859e22SJohan Hedberg 2256980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_REPLY: 2257980e1a53SJohan Hedberg hci_cc_pin_code_reply(hdev, skb); 2258980e1a53SJohan Hedberg break; 2259980e1a53SJohan Hedberg 2260980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_NEG_REPLY: 2261980e1a53SJohan Hedberg hci_cc_pin_code_neg_reply(hdev, skb); 2262980e1a53SJohan Hedberg break; 2263980e1a53SJohan Hedberg 2264c35938b2SSzymon Janc case HCI_OP_READ_LOCAL_OOB_DATA: 22654d2d2796SMarcel Holtmann hci_cc_read_local_oob_data(hdev, skb); 22664d2d2796SMarcel Holtmann break; 22674d2d2796SMarcel Holtmann 22684d2d2796SMarcel Holtmann case HCI_OP_READ_LOCAL_OOB_EXT_DATA: 22694d2d2796SMarcel Holtmann hci_cc_read_local_oob_ext_data(hdev, skb); 2270c35938b2SSzymon Janc break; 2271c35938b2SSzymon Janc 22726ed58ec5SVille Tervo case HCI_OP_LE_READ_BUFFER_SIZE: 22736ed58ec5SVille Tervo hci_cc_le_read_buffer_size(hdev, skb); 22746ed58ec5SVille Tervo break; 22756ed58ec5SVille Tervo 227660e77321SJohan Hedberg case HCI_OP_LE_READ_LOCAL_FEATURES: 227760e77321SJohan Hedberg hci_cc_le_read_local_features(hdev, skb); 227860e77321SJohan Hedberg break; 227960e77321SJohan Hedberg 22808fa19098SJohan Hedberg case HCI_OP_LE_READ_ADV_TX_POWER: 22818fa19098SJohan Hedberg hci_cc_le_read_adv_tx_power(hdev, skb); 22828fa19098SJohan Hedberg break; 22838fa19098SJohan Hedberg 2284a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_REPLY: 2285a5c29683SJohan Hedberg hci_cc_user_confirm_reply(hdev, skb); 2286a5c29683SJohan Hedberg break; 2287a5c29683SJohan Hedberg 2288a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_NEG_REPLY: 2289a5c29683SJohan Hedberg hci_cc_user_confirm_neg_reply(hdev, skb); 2290a5c29683SJohan Hedberg break; 2291a5c29683SJohan Hedberg 22921143d458SBrian Gix case HCI_OP_USER_PASSKEY_REPLY: 22931143d458SBrian Gix hci_cc_user_passkey_reply(hdev, skb); 22941143d458SBrian Gix break; 22951143d458SBrian Gix 22961143d458SBrian Gix case HCI_OP_USER_PASSKEY_NEG_REPLY: 22971143d458SBrian Gix hci_cc_user_passkey_neg_reply(hdev, skb); 229816cde993SSzymon Janc break; 229907f7fa5dSAndre Guedes 2300c1d5dc4aSJohan Hedberg case HCI_OP_LE_SET_ADV_ENABLE: 2301c1d5dc4aSJohan Hedberg hci_cc_le_set_adv_enable(hdev, skb); 2302c1d5dc4aSJohan Hedberg break; 2303c1d5dc4aSJohan Hedberg 2304eb9d91f5SAndre Guedes case HCI_OP_LE_SET_SCAN_ENABLE: 2305eb9d91f5SAndre Guedes hci_cc_le_set_scan_enable(hdev, skb); 2306eb9d91f5SAndre Guedes break; 2307eb9d91f5SAndre Guedes 2308cf1d081fSJohan Hedberg case HCI_OP_LE_READ_WHITE_LIST_SIZE: 2309cf1d081fSJohan Hedberg hci_cc_le_read_white_list_size(hdev, skb); 2310cf1d081fSJohan Hedberg break; 2311cf1d081fSJohan Hedberg 23129b008c04SJohan Hedberg case HCI_OP_LE_READ_SUPPORTED_STATES: 23139b008c04SJohan Hedberg hci_cc_le_read_supported_states(hdev, skb); 23149b008c04SJohan Hedberg break; 23159b008c04SJohan Hedberg 2316f9b49306SAndre Guedes case HCI_OP_WRITE_LE_HOST_SUPPORTED: 2317f9b49306SAndre Guedes hci_cc_write_le_host_supported(hdev, skb); 2318f9b49306SAndre Guedes break; 2319f9b49306SAndre Guedes 232093c284eeSAndrei Emeltchenko case HCI_OP_WRITE_REMOTE_AMP_ASSOC: 232193c284eeSAndrei Emeltchenko hci_cc_write_remote_amp_assoc(hdev, skb); 232293c284eeSAndrei Emeltchenko break; 232393c284eeSAndrei Emeltchenko 2324a9de9248SMarcel Holtmann default: 23259f1db00cSAndrei Emeltchenko BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); 2326a9de9248SMarcel Holtmann break; 2327a9de9248SMarcel Holtmann } 2328a9de9248SMarcel Holtmann 2329ad82cdd1SJohan Hedberg if (opcode != HCI_OP_NOP) 23306bd32326SVille Tervo del_timer(&hdev->cmd_timer); 23316bd32326SVille Tervo 2332ad82cdd1SJohan Hedberg hci_req_cmd_complete(hdev, opcode, status); 23339238f36aSJohan Hedberg 2334dbccd791SSzymon Janc if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2335a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2336a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2337c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2338a9de9248SMarcel Holtmann } 2339a9de9248SMarcel Holtmann } 2340a9de9248SMarcel Holtmann 23416039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 2342a9de9248SMarcel Holtmann { 2343a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 2344a9de9248SMarcel Holtmann __u16 opcode; 2345a9de9248SMarcel Holtmann 2346a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2347a9de9248SMarcel Holtmann 2348a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2349a9de9248SMarcel Holtmann 2350a9de9248SMarcel Holtmann switch (opcode) { 2351a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 2352a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 2353a9de9248SMarcel Holtmann break; 2354a9de9248SMarcel Holtmann 2355a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 2356a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 2357a9de9248SMarcel Holtmann break; 2358a9de9248SMarcel Holtmann 2359a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 2360a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 2361a9de9248SMarcel Holtmann break; 2362a9de9248SMarcel Holtmann 2363f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 2364f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 2365f8558555SMarcel Holtmann break; 2366f8558555SMarcel Holtmann 2367f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 2368f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 2369f8558555SMarcel Holtmann break; 2370f8558555SMarcel Holtmann 2371a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 2372a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 2373a9de9248SMarcel Holtmann break; 2374a9de9248SMarcel Holtmann 2375769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 2376769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 2377769be974SMarcel Holtmann break; 2378769be974SMarcel Holtmann 2379769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 2380769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 2381769be974SMarcel Holtmann break; 2382769be974SMarcel Holtmann 2383a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 2384a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 2385a9de9248SMarcel Holtmann break; 2386a9de9248SMarcel Holtmann 2387a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 2388a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 2389a9de9248SMarcel Holtmann break; 2390a9de9248SMarcel Holtmann 2391a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 2392a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 2393a9de9248SMarcel Holtmann break; 2394a9de9248SMarcel Holtmann 23958962ee74SJohan Hedberg case HCI_OP_DISCONNECT: 239688c3df13SJohan Hedberg hci_cs_disconnect(hdev, ev->status); 23978962ee74SJohan Hedberg break; 23988962ee74SJohan Hedberg 2399a02226d6SAndrei Emeltchenko case HCI_OP_CREATE_PHY_LINK: 2400a02226d6SAndrei Emeltchenko hci_cs_create_phylink(hdev, ev->status); 2401a02226d6SAndrei Emeltchenko break; 2402a02226d6SAndrei Emeltchenko 24030b26ab9dSAndrei Emeltchenko case HCI_OP_ACCEPT_PHY_LINK: 24040b26ab9dSAndrei Emeltchenko hci_cs_accept_phylink(hdev, ev->status); 24050b26ab9dSAndrei Emeltchenko break; 24060b26ab9dSAndrei Emeltchenko 2407a9de9248SMarcel Holtmann default: 24089f1db00cSAndrei Emeltchenko BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); 2409a9de9248SMarcel Holtmann break; 2410a9de9248SMarcel Holtmann } 2411a9de9248SMarcel Holtmann 2412ad82cdd1SJohan Hedberg if (opcode != HCI_OP_NOP) 24136bd32326SVille Tervo del_timer(&hdev->cmd_timer); 24146bd32326SVille Tervo 241502350a72SJohan Hedberg if (ev->status || 241602350a72SJohan Hedberg (hdev->sent_cmd && !bt_cb(hdev->sent_cmd)->req.event)) 241733720450SAndre Guedes hci_req_cmd_complete(hdev, opcode, ev->status); 24189238f36aSJohan Hedberg 241910572132SGustavo F. Padovan if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2420a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2421a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2422c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2423a9de9248SMarcel Holtmann } 2424a9de9248SMarcel Holtmann } 2425a9de9248SMarcel Holtmann 24266039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2427a9de9248SMarcel Holtmann { 2428a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 2429a9de9248SMarcel Holtmann struct hci_conn *conn; 2430a9de9248SMarcel Holtmann 24319f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2432a9de9248SMarcel Holtmann 2433a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2434a9de9248SMarcel Holtmann 2435a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2436a9de9248SMarcel Holtmann if (conn) { 2437a9de9248SMarcel Holtmann if (!ev->status) { 2438a9de9248SMarcel Holtmann if (ev->role) 2439a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_MASTER; 2440a9de9248SMarcel Holtmann else 2441a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_MASTER; 2442a9de9248SMarcel Holtmann } 2443a9de9248SMarcel Holtmann 244451a8efd7SJohan Hedberg clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); 2445a9de9248SMarcel Holtmann 2446a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 2447a9de9248SMarcel Holtmann } 2448a9de9248SMarcel Holtmann 2449a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2450a9de9248SMarcel Holtmann } 2451a9de9248SMarcel Holtmann 24526039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 24531da177e4SLinus Torvalds { 2454a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 24551da177e4SLinus Torvalds int i; 24561da177e4SLinus Torvalds 245732ac5b9bSAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) { 245832ac5b9bSAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 245932ac5b9bSAndrei Emeltchenko return; 246032ac5b9bSAndrei Emeltchenko } 246132ac5b9bSAndrei Emeltchenko 2462c5993de8SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 2463c5993de8SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_pkts_info)) { 24641da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 24651da177e4SLinus Torvalds return; 24661da177e4SLinus Torvalds } 24671da177e4SLinus Torvalds 2468c5993de8SAndrei Emeltchenko BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 2469c5993de8SAndrei Emeltchenko 2470613a1c0cSAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 2471613a1c0cSAndrei Emeltchenko struct hci_comp_pkts_info *info = &ev->handles[i]; 24721da177e4SLinus Torvalds struct hci_conn *conn; 24731da177e4SLinus Torvalds __u16 handle, count; 24741da177e4SLinus Torvalds 2475613a1c0cSAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 2476613a1c0cSAndrei Emeltchenko count = __le16_to_cpu(info->count); 24771da177e4SLinus Torvalds 24781da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 2479f4280918SAndrei Emeltchenko if (!conn) 2480f4280918SAndrei Emeltchenko continue; 2481f4280918SAndrei Emeltchenko 24821da177e4SLinus Torvalds conn->sent -= count; 24831da177e4SLinus Torvalds 2484f4280918SAndrei Emeltchenko switch (conn->type) { 2485f4280918SAndrei Emeltchenko case ACL_LINK: 248670f23020SAndrei Emeltchenko hdev->acl_cnt += count; 248770f23020SAndrei Emeltchenko if (hdev->acl_cnt > hdev->acl_pkts) 24881da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 2489f4280918SAndrei Emeltchenko break; 2490f4280918SAndrei Emeltchenko 2491f4280918SAndrei Emeltchenko case LE_LINK: 24926ed58ec5SVille Tervo if (hdev->le_pkts) { 24936ed58ec5SVille Tervo hdev->le_cnt += count; 24946ed58ec5SVille Tervo if (hdev->le_cnt > hdev->le_pkts) 24956ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 24966ed58ec5SVille Tervo } else { 24976ed58ec5SVille Tervo hdev->acl_cnt += count; 24986ed58ec5SVille Tervo if (hdev->acl_cnt > hdev->acl_pkts) 24996ed58ec5SVille Tervo hdev->acl_cnt = hdev->acl_pkts; 25006ed58ec5SVille Tervo } 2501f4280918SAndrei Emeltchenko break; 2502f4280918SAndrei Emeltchenko 2503f4280918SAndrei Emeltchenko case SCO_LINK: 250470f23020SAndrei Emeltchenko hdev->sco_cnt += count; 250570f23020SAndrei Emeltchenko if (hdev->sco_cnt > hdev->sco_pkts) 25065b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 2507f4280918SAndrei Emeltchenko break; 2508f4280918SAndrei Emeltchenko 2509f4280918SAndrei Emeltchenko default: 2510f4280918SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 2511f4280918SAndrei Emeltchenko break; 25121da177e4SLinus Torvalds } 25131da177e4SLinus Torvalds } 2514a9de9248SMarcel Holtmann 25153eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 25161da177e4SLinus Torvalds } 25171da177e4SLinus Torvalds 251876ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev, 251976ef7cf7SAndrei Emeltchenko __u16 handle) 252076ef7cf7SAndrei Emeltchenko { 252176ef7cf7SAndrei Emeltchenko struct hci_chan *chan; 252276ef7cf7SAndrei Emeltchenko 252376ef7cf7SAndrei Emeltchenko switch (hdev->dev_type) { 252476ef7cf7SAndrei Emeltchenko case HCI_BREDR: 252576ef7cf7SAndrei Emeltchenko return hci_conn_hash_lookup_handle(hdev, handle); 252676ef7cf7SAndrei Emeltchenko case HCI_AMP: 252776ef7cf7SAndrei Emeltchenko chan = hci_chan_lookup_handle(hdev, handle); 252876ef7cf7SAndrei Emeltchenko if (chan) 252976ef7cf7SAndrei Emeltchenko return chan->conn; 253076ef7cf7SAndrei Emeltchenko break; 253176ef7cf7SAndrei Emeltchenko default: 253276ef7cf7SAndrei Emeltchenko BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type); 253376ef7cf7SAndrei Emeltchenko break; 253476ef7cf7SAndrei Emeltchenko } 253576ef7cf7SAndrei Emeltchenko 253676ef7cf7SAndrei Emeltchenko return NULL; 253776ef7cf7SAndrei Emeltchenko } 253876ef7cf7SAndrei Emeltchenko 25396039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb) 254025e89e99SAndrei Emeltchenko { 254125e89e99SAndrei Emeltchenko struct hci_ev_num_comp_blocks *ev = (void *) skb->data; 254225e89e99SAndrei Emeltchenko int i; 254325e89e99SAndrei Emeltchenko 254425e89e99SAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) { 254525e89e99SAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 254625e89e99SAndrei Emeltchenko return; 254725e89e99SAndrei Emeltchenko } 254825e89e99SAndrei Emeltchenko 254925e89e99SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 255025e89e99SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_blocks_info)) { 255125e89e99SAndrei Emeltchenko BT_DBG("%s bad parameters", hdev->name); 255225e89e99SAndrei Emeltchenko return; 255325e89e99SAndrei Emeltchenko } 255425e89e99SAndrei Emeltchenko 255525e89e99SAndrei Emeltchenko BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks, 255625e89e99SAndrei Emeltchenko ev->num_hndl); 255725e89e99SAndrei Emeltchenko 255825e89e99SAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 255925e89e99SAndrei Emeltchenko struct hci_comp_blocks_info *info = &ev->handles[i]; 256076ef7cf7SAndrei Emeltchenko struct hci_conn *conn = NULL; 256125e89e99SAndrei Emeltchenko __u16 handle, block_count; 256225e89e99SAndrei Emeltchenko 256325e89e99SAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 256425e89e99SAndrei Emeltchenko block_count = __le16_to_cpu(info->blocks); 256525e89e99SAndrei Emeltchenko 256676ef7cf7SAndrei Emeltchenko conn = __hci_conn_lookup_handle(hdev, handle); 256725e89e99SAndrei Emeltchenko if (!conn) 256825e89e99SAndrei Emeltchenko continue; 256925e89e99SAndrei Emeltchenko 257025e89e99SAndrei Emeltchenko conn->sent -= block_count; 257125e89e99SAndrei Emeltchenko 257225e89e99SAndrei Emeltchenko switch (conn->type) { 257325e89e99SAndrei Emeltchenko case ACL_LINK: 2574bd1eb66bSAndrei Emeltchenko case AMP_LINK: 257525e89e99SAndrei Emeltchenko hdev->block_cnt += block_count; 257625e89e99SAndrei Emeltchenko if (hdev->block_cnt > hdev->num_blocks) 257725e89e99SAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 257825e89e99SAndrei Emeltchenko break; 257925e89e99SAndrei Emeltchenko 258025e89e99SAndrei Emeltchenko default: 258125e89e99SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 258225e89e99SAndrei Emeltchenko break; 258325e89e99SAndrei Emeltchenko } 258425e89e99SAndrei Emeltchenko } 258525e89e99SAndrei Emeltchenko 258625e89e99SAndrei Emeltchenko queue_work(hdev->workqueue, &hdev->tx_work); 258725e89e99SAndrei Emeltchenko } 258825e89e99SAndrei Emeltchenko 25896039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 25901da177e4SLinus Torvalds { 2591a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 259204837f64SMarcel Holtmann struct hci_conn *conn; 25931da177e4SLinus Torvalds 25949f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 25951da177e4SLinus Torvalds 25961da177e4SLinus Torvalds hci_dev_lock(hdev); 25971da177e4SLinus Torvalds 259804837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 259904837f64SMarcel Holtmann if (conn) { 260004837f64SMarcel Holtmann conn->mode = ev->mode; 260104837f64SMarcel Holtmann 26028fc9ced3SGustavo Padovan if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, 26038fc9ced3SGustavo Padovan &conn->flags)) { 260404837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 260558a681efSJohan Hedberg set_bit(HCI_CONN_POWER_SAVE, &conn->flags); 260604837f64SMarcel Holtmann else 260758a681efSJohan Hedberg clear_bit(HCI_CONN_POWER_SAVE, &conn->flags); 260804837f64SMarcel Holtmann } 2609e73439d8SMarcel Holtmann 261051a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 2611e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 261204837f64SMarcel Holtmann } 261304837f64SMarcel Holtmann 261404837f64SMarcel Holtmann hci_dev_unlock(hdev); 261504837f64SMarcel Holtmann } 261604837f64SMarcel Holtmann 26176039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 26181da177e4SLinus Torvalds { 2619052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 2620052b30b0SMarcel Holtmann struct hci_conn *conn; 2621052b30b0SMarcel Holtmann 2622a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2623052b30b0SMarcel Holtmann 2624052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2625052b30b0SMarcel Holtmann 2626052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2627b6f98044SWaldemar Rymarkiewicz if (!conn) 2628b6f98044SWaldemar Rymarkiewicz goto unlock; 2629b6f98044SWaldemar Rymarkiewicz 2630b6f98044SWaldemar Rymarkiewicz if (conn->state == BT_CONNECTED) { 2631052b30b0SMarcel Holtmann hci_conn_hold(conn); 2632052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 263376a68ba0SDavid Herrmann hci_conn_drop(conn); 2634052b30b0SMarcel Holtmann } 2635052b30b0SMarcel Holtmann 2636a8b2d5c2SJohan Hedberg if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags)) 263703b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 263803b555e1SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 2639a8b2d5c2SJohan Hedberg else if (test_bit(HCI_MGMT, &hdev->dev_flags)) { 2640a770bb5aSWaldemar Rymarkiewicz u8 secure; 2641a770bb5aSWaldemar Rymarkiewicz 2642a770bb5aSWaldemar Rymarkiewicz if (conn->pending_sec_level == BT_SECURITY_HIGH) 2643a770bb5aSWaldemar Rymarkiewicz secure = 1; 2644a770bb5aSWaldemar Rymarkiewicz else 2645a770bb5aSWaldemar Rymarkiewicz secure = 0; 2646a770bb5aSWaldemar Rymarkiewicz 2647744cf19eSJohan Hedberg mgmt_pin_code_request(hdev, &ev->bdaddr, secure); 2648a770bb5aSWaldemar Rymarkiewicz } 2649980e1a53SJohan Hedberg 2650b6f98044SWaldemar Rymarkiewicz unlock: 2651052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 26521da177e4SLinus Torvalds } 26531da177e4SLinus Torvalds 26546039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 26551da177e4SLinus Torvalds { 265655ed8ca1SJohan Hedberg struct hci_ev_link_key_req *ev = (void *) skb->data; 265755ed8ca1SJohan Hedberg struct hci_cp_link_key_reply cp; 265855ed8ca1SJohan Hedberg struct hci_conn *conn; 265955ed8ca1SJohan Hedberg struct link_key *key; 266055ed8ca1SJohan Hedberg 2661a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 266255ed8ca1SJohan Hedberg 2663034cbea0SAndrei Emeltchenko if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 266455ed8ca1SJohan Hedberg return; 266555ed8ca1SJohan Hedberg 266655ed8ca1SJohan Hedberg hci_dev_lock(hdev); 266755ed8ca1SJohan Hedberg 266855ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, &ev->bdaddr); 266955ed8ca1SJohan Hedberg if (!key) { 26706ed93dc6SAndrei Emeltchenko BT_DBG("%s link key not found for %pMR", hdev->name, 26716ed93dc6SAndrei Emeltchenko &ev->bdaddr); 267255ed8ca1SJohan Hedberg goto not_found; 267355ed8ca1SJohan Hedberg } 267455ed8ca1SJohan Hedberg 26756ed93dc6SAndrei Emeltchenko BT_DBG("%s found key type %u for %pMR", hdev->name, key->type, 26766ed93dc6SAndrei Emeltchenko &ev->bdaddr); 267755ed8ca1SJohan Hedberg 2678a8b2d5c2SJohan Hedberg if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) && 2679b6020ba0SWaldemar Rymarkiewicz key->type == HCI_LK_DEBUG_COMBINATION) { 268055ed8ca1SJohan Hedberg BT_DBG("%s ignoring debug key", hdev->name); 268155ed8ca1SJohan Hedberg goto not_found; 268255ed8ca1SJohan Hedberg } 268355ed8ca1SJohan Hedberg 268455ed8ca1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 268560b83f57SWaldemar Rymarkiewicz if (conn) { 268666138ce8SMarcel Holtmann if ((key->type == HCI_LK_UNAUTH_COMBINATION_P192 || 268766138ce8SMarcel Holtmann key->type == HCI_LK_UNAUTH_COMBINATION_P256) && 2688807deac2SGustavo Padovan conn->auth_type != 0xff && (conn->auth_type & 0x01)) { 268955ed8ca1SJohan Hedberg BT_DBG("%s ignoring unauthenticated key", hdev->name); 269055ed8ca1SJohan Hedberg goto not_found; 269155ed8ca1SJohan Hedberg } 269255ed8ca1SJohan Hedberg 269360b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && 269460b83f57SWaldemar Rymarkiewicz conn->pending_sec_level == BT_SECURITY_HIGH) { 26958fc9ced3SGustavo Padovan BT_DBG("%s ignoring key unauthenticated for high security", 26968fc9ced3SGustavo Padovan hdev->name); 269760b83f57SWaldemar Rymarkiewicz goto not_found; 269860b83f57SWaldemar Rymarkiewicz } 269960b83f57SWaldemar Rymarkiewicz 270060b83f57SWaldemar Rymarkiewicz conn->key_type = key->type; 270160b83f57SWaldemar Rymarkiewicz conn->pin_length = key->pin_len; 270260b83f57SWaldemar Rymarkiewicz } 270360b83f57SWaldemar Rymarkiewicz 270455ed8ca1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 27059b3b4460SAndrei Emeltchenko memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE); 270655ed8ca1SJohan Hedberg 270755ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 270855ed8ca1SJohan Hedberg 270955ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 271055ed8ca1SJohan Hedberg 271155ed8ca1SJohan Hedberg return; 271255ed8ca1SJohan Hedberg 271355ed8ca1SJohan Hedberg not_found: 271455ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 271555ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 27161da177e4SLinus Torvalds } 27171da177e4SLinus Torvalds 27186039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 27191da177e4SLinus Torvalds { 2720052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 2721052b30b0SMarcel Holtmann struct hci_conn *conn; 272255ed8ca1SJohan Hedberg u8 pin_len = 0; 2723052b30b0SMarcel Holtmann 2724a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2725052b30b0SMarcel Holtmann 2726052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2727052b30b0SMarcel Holtmann 2728052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2729052b30b0SMarcel Holtmann if (conn) { 2730052b30b0SMarcel Holtmann hci_conn_hold(conn); 2731052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2732980e1a53SJohan Hedberg pin_len = conn->pin_length; 273313d39315SWaldemar Rymarkiewicz 273413d39315SWaldemar Rymarkiewicz if (ev->key_type != HCI_LK_CHANGED_COMBINATION) 273513d39315SWaldemar Rymarkiewicz conn->key_type = ev->key_type; 273613d39315SWaldemar Rymarkiewicz 273776a68ba0SDavid Herrmann hci_conn_drop(conn); 2738052b30b0SMarcel Holtmann } 2739052b30b0SMarcel Holtmann 2740034cbea0SAndrei Emeltchenko if (test_bit(HCI_MGMT, &hdev->dev_flags)) 2741d25e28abSJohan Hedberg hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, 274255ed8ca1SJohan Hedberg ev->key_type, pin_len); 274355ed8ca1SJohan Hedberg 2744052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 27451da177e4SLinus Torvalds } 27461da177e4SLinus Torvalds 27476039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 274804837f64SMarcel Holtmann { 2749a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 275004837f64SMarcel Holtmann struct hci_conn *conn; 275104837f64SMarcel Holtmann 27529f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 275304837f64SMarcel Holtmann 275404837f64SMarcel Holtmann hci_dev_lock(hdev); 275504837f64SMarcel Holtmann 275604837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 27571da177e4SLinus Torvalds if (conn && !ev->status) { 27581da177e4SLinus Torvalds struct inquiry_entry *ie; 27591da177e4SLinus Torvalds 2760cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2761cc11b9c1SAndrei Emeltchenko if (ie) { 27621da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 27631da177e4SLinus Torvalds ie->timestamp = jiffies; 27641da177e4SLinus Torvalds } 27651da177e4SLinus Torvalds } 27661da177e4SLinus Torvalds 27671da177e4SLinus Torvalds hci_dev_unlock(hdev); 27681da177e4SLinus Torvalds } 27691da177e4SLinus Torvalds 27706039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2771a8746417SMarcel Holtmann { 2772a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 2773a8746417SMarcel Holtmann struct hci_conn *conn; 2774a8746417SMarcel Holtmann 27759f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2776a8746417SMarcel Holtmann 2777a8746417SMarcel Holtmann hci_dev_lock(hdev); 2778a8746417SMarcel Holtmann 2779a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2780a8746417SMarcel Holtmann if (conn && !ev->status) 2781a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 2782a8746417SMarcel Holtmann 2783a8746417SMarcel Holtmann hci_dev_unlock(hdev); 2784a8746417SMarcel Holtmann } 2785a8746417SMarcel Holtmann 27866039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 278785a1e930SMarcel Holtmann { 2788a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 278985a1e930SMarcel Holtmann struct inquiry_entry *ie; 279085a1e930SMarcel Holtmann 279185a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 279285a1e930SMarcel Holtmann 279385a1e930SMarcel Holtmann hci_dev_lock(hdev); 279485a1e930SMarcel Holtmann 2795cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2796cc11b9c1SAndrei Emeltchenko if (ie) { 279785a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 279885a1e930SMarcel Holtmann ie->timestamp = jiffies; 279985a1e930SMarcel Holtmann } 280085a1e930SMarcel Holtmann 280185a1e930SMarcel Holtmann hci_dev_unlock(hdev); 280285a1e930SMarcel Holtmann } 280385a1e930SMarcel Holtmann 28046039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, 2805807deac2SGustavo Padovan struct sk_buff *skb) 2806a9de9248SMarcel Holtmann { 2807a9de9248SMarcel Holtmann struct inquiry_data data; 2808a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2809388fc8faSJohan Hedberg bool name_known, ssp; 2810a9de9248SMarcel Holtmann 2811a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2812a9de9248SMarcel Holtmann 2813a9de9248SMarcel Holtmann if (!num_rsp) 2814a9de9248SMarcel Holtmann return; 2815a9de9248SMarcel Holtmann 28161519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 28171519cc17SAndre Guedes return; 28181519cc17SAndre Guedes 2819a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2820a9de9248SMarcel Holtmann 2821a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 2822138d22efSSzymon Janc struct inquiry_info_with_rssi_and_pscan_mode *info; 2823138d22efSSzymon Janc info = (void *) (skb->data + 1); 2824a9de9248SMarcel Holtmann 2825e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2826a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2827a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2828a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2829a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 2830a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2831a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2832a9de9248SMarcel Holtmann data.rssi = info->rssi; 283341a96212SMarcel Holtmann data.ssp_mode = 0x00; 28343175405bSJohan Hedberg 28353175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 2836388fc8faSJohan Hedberg false, &ssp); 283748264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2838e17acd40SJohan Hedberg info->dev_class, info->rssi, 2839388fc8faSJohan Hedberg !name_known, ssp, NULL, 0); 2840a9de9248SMarcel Holtmann } 2841a9de9248SMarcel Holtmann } else { 2842a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 2843a9de9248SMarcel Holtmann 2844e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2845a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2846a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2847a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2848a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2849a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2850a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2851a9de9248SMarcel Holtmann data.rssi = info->rssi; 285241a96212SMarcel Holtmann data.ssp_mode = 0x00; 28533175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 2854388fc8faSJohan Hedberg false, &ssp); 285548264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2856e17acd40SJohan Hedberg info->dev_class, info->rssi, 2857388fc8faSJohan Hedberg !name_known, ssp, NULL, 0); 2858a9de9248SMarcel Holtmann } 2859a9de9248SMarcel Holtmann } 2860a9de9248SMarcel Holtmann 2861a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2862a9de9248SMarcel Holtmann } 2863a9de9248SMarcel Holtmann 28646039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev, 2865807deac2SGustavo Padovan struct sk_buff *skb) 2866a9de9248SMarcel Holtmann { 286741a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 286841a96212SMarcel Holtmann struct hci_conn *conn; 286941a96212SMarcel Holtmann 2870a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 287141a96212SMarcel Holtmann 287241a96212SMarcel Holtmann hci_dev_lock(hdev); 287341a96212SMarcel Holtmann 287441a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2875ccd556feSJohan Hedberg if (!conn) 2876ccd556feSJohan Hedberg goto unlock; 2877ccd556feSJohan Hedberg 2878cad718edSJohan Hedberg if (ev->page < HCI_MAX_PAGES) 2879cad718edSJohan Hedberg memcpy(conn->features[ev->page], ev->features, 8); 2880cad718edSJohan Hedberg 2881769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 288241a96212SMarcel Holtmann struct inquiry_entry *ie; 288341a96212SMarcel Holtmann 2884cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2885cc11b9c1SAndrei Emeltchenko if (ie) 288602b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 288741a96212SMarcel Holtmann 2888bbb0eadaSJaganath Kanakkassery if (ev->features[0] & LMP_HOST_SSP) { 288958a681efSJohan Hedberg set_bit(HCI_CONN_SSP_ENABLED, &conn->flags); 2890bbb0eadaSJaganath Kanakkassery } else { 2891bbb0eadaSJaganath Kanakkassery /* It is mandatory by the Bluetooth specification that 2892bbb0eadaSJaganath Kanakkassery * Extended Inquiry Results are only used when Secure 2893bbb0eadaSJaganath Kanakkassery * Simple Pairing is enabled, but some devices violate 2894bbb0eadaSJaganath Kanakkassery * this. 2895bbb0eadaSJaganath Kanakkassery * 2896bbb0eadaSJaganath Kanakkassery * To make these devices work, the internal SSP 2897bbb0eadaSJaganath Kanakkassery * enabled flag needs to be cleared if the remote host 2898bbb0eadaSJaganath Kanakkassery * features do not indicate SSP support */ 2899bbb0eadaSJaganath Kanakkassery clear_bit(HCI_CONN_SSP_ENABLED, &conn->flags); 2900bbb0eadaSJaganath Kanakkassery } 2901eb9a8f3fSMarcel Holtmann 2902eb9a8f3fSMarcel Holtmann if (ev->features[0] & LMP_HOST_SC) 2903eb9a8f3fSMarcel Holtmann set_bit(HCI_CONN_SC_ENABLED, &conn->flags); 290441a96212SMarcel Holtmann } 290541a96212SMarcel Holtmann 2906ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2907ccd556feSJohan Hedberg goto unlock; 2908ccd556feSJohan Hedberg 2909671267bfSJohan Hedberg if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { 2910127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2911127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2912127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2913127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2914127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2915b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 2916b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 291708c79b61SJohan Hedberg conn->dst_type, 0, NULL, 0, 2918b644ba33SJohan Hedberg conn->dev_class); 2919392599b9SJohan Hedberg 2920127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2921769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2922769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 292376a68ba0SDavid Herrmann hci_conn_drop(conn); 2924769be974SMarcel Holtmann } 2925769be974SMarcel Holtmann 2926ccd556feSJohan Hedberg unlock: 292741a96212SMarcel Holtmann hci_dev_unlock(hdev); 2928a9de9248SMarcel Holtmann } 2929a9de9248SMarcel Holtmann 29306039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev, 2931807deac2SGustavo Padovan struct sk_buff *skb) 2932a9de9248SMarcel Holtmann { 2933b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 2934b6a0dc82SMarcel Holtmann struct hci_conn *conn; 2935b6a0dc82SMarcel Holtmann 29369f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2937b6a0dc82SMarcel Holtmann 2938b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 2939b6a0dc82SMarcel Holtmann 2940b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 29419dc0a3afSMarcel Holtmann if (!conn) { 29429dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 29439dc0a3afSMarcel Holtmann goto unlock; 29449dc0a3afSMarcel Holtmann 29459dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 2946b6a0dc82SMarcel Holtmann if (!conn) 2947b6a0dc82SMarcel Holtmann goto unlock; 2948b6a0dc82SMarcel Holtmann 29499dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 29509dc0a3afSMarcel Holtmann } 29519dc0a3afSMarcel Holtmann 2952732547f9SMarcel Holtmann switch (ev->status) { 2953732547f9SMarcel Holtmann case 0x00: 2954732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 2955732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 2956732547f9SMarcel Holtmann 2957732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 2958732547f9SMarcel Holtmann break; 2959732547f9SMarcel Holtmann 29601a4c958cSFrédéric Dalleau case 0x0d: /* Connection Rejected due to Limited Resources */ 2961705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 2962732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 29631038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 2964732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 29652dea632fSFrédéric Dalleau if (conn->out) { 2966efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 2967efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 29682dea632fSFrédéric Dalleau if (hci_setup_sync(conn, conn->link->handle)) 2969efc7688bSMarcel Holtmann goto unlock; 2970efc7688bSMarcel Holtmann } 2971732547f9SMarcel Holtmann /* fall through */ 2972efc7688bSMarcel Holtmann 2973732547f9SMarcel Holtmann default: 2974b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 2975732547f9SMarcel Holtmann break; 2976732547f9SMarcel Holtmann } 2977b6a0dc82SMarcel Holtmann 2978b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2979b6a0dc82SMarcel Holtmann if (ev->status) 2980b6a0dc82SMarcel Holtmann hci_conn_del(conn); 2981b6a0dc82SMarcel Holtmann 2982b6a0dc82SMarcel Holtmann unlock: 2983b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 2984a9de9248SMarcel Holtmann } 2985a9de9248SMarcel Holtmann 2986efdcf8e3SMarcel Holtmann static inline size_t eir_get_length(u8 *eir, size_t eir_len) 2987efdcf8e3SMarcel Holtmann { 2988efdcf8e3SMarcel Holtmann size_t parsed = 0; 2989efdcf8e3SMarcel Holtmann 2990efdcf8e3SMarcel Holtmann while (parsed < eir_len) { 2991efdcf8e3SMarcel Holtmann u8 field_len = eir[0]; 2992efdcf8e3SMarcel Holtmann 2993efdcf8e3SMarcel Holtmann if (field_len == 0) 2994efdcf8e3SMarcel Holtmann return parsed; 2995efdcf8e3SMarcel Holtmann 2996efdcf8e3SMarcel Holtmann parsed += field_len + 1; 2997efdcf8e3SMarcel Holtmann eir += field_len + 1; 2998efdcf8e3SMarcel Holtmann } 2999efdcf8e3SMarcel Holtmann 3000efdcf8e3SMarcel Holtmann return eir_len; 3001efdcf8e3SMarcel Holtmann } 3002efdcf8e3SMarcel Holtmann 30036039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, 3004807deac2SGustavo Padovan struct sk_buff *skb) 3005a9de9248SMarcel Holtmann { 3006a9de9248SMarcel Holtmann struct inquiry_data data; 3007a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 3008a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 30099d939d94SVishal Agarwal size_t eir_len; 3010a9de9248SMarcel Holtmann 3011a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 3012a9de9248SMarcel Holtmann 3013a9de9248SMarcel Holtmann if (!num_rsp) 3014a9de9248SMarcel Holtmann return; 3015a9de9248SMarcel Holtmann 30161519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 30171519cc17SAndre Guedes return; 30181519cc17SAndre Guedes 3019a9de9248SMarcel Holtmann hci_dev_lock(hdev); 3020a9de9248SMarcel Holtmann 3021e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 3022388fc8faSJohan Hedberg bool name_known, ssp; 3023561aafbcSJohan Hedberg 3024a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 3025a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 3026a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 3027a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 3028a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 3029a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 3030a9de9248SMarcel Holtmann data.rssi = info->rssi; 303141a96212SMarcel Holtmann data.ssp_mode = 0x01; 3032561aafbcSJohan Hedberg 3033a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 30344ddb1930SJohan Hedberg name_known = eir_has_data_type(info->data, 30354ddb1930SJohan Hedberg sizeof(info->data), 30364ddb1930SJohan Hedberg EIR_NAME_COMPLETE); 3037561aafbcSJohan Hedberg else 3038561aafbcSJohan Hedberg name_known = true; 3039561aafbcSJohan Hedberg 3040388fc8faSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, name_known, 3041388fc8faSJohan Hedberg &ssp); 30429d939d94SVishal Agarwal eir_len = eir_get_length(info->data, sizeof(info->data)); 304348264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 304404124681SGustavo F. Padovan info->dev_class, info->rssi, !name_known, 30459d939d94SVishal Agarwal ssp, info->data, eir_len); 3046a9de9248SMarcel Holtmann } 3047a9de9248SMarcel Holtmann 3048a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 3049a9de9248SMarcel Holtmann } 3050a9de9248SMarcel Holtmann 30511c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev, 30521c2e0041SJohan Hedberg struct sk_buff *skb) 30531c2e0041SJohan Hedberg { 30541c2e0041SJohan Hedberg struct hci_ev_key_refresh_complete *ev = (void *) skb->data; 30551c2e0041SJohan Hedberg struct hci_conn *conn; 30561c2e0041SJohan Hedberg 30579f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status, 30581c2e0041SJohan Hedberg __le16_to_cpu(ev->handle)); 30591c2e0041SJohan Hedberg 30601c2e0041SJohan Hedberg hci_dev_lock(hdev); 30611c2e0041SJohan Hedberg 30621c2e0041SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 30631c2e0041SJohan Hedberg if (!conn) 30641c2e0041SJohan Hedberg goto unlock; 30651c2e0041SJohan Hedberg 30661c2e0041SJohan Hedberg if (!ev->status) 30671c2e0041SJohan Hedberg conn->sec_level = conn->pending_sec_level; 30681c2e0041SJohan Hedberg 30691c2e0041SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 30701c2e0041SJohan Hedberg 30711c2e0041SJohan Hedberg if (ev->status && conn->state == BT_CONNECTED) { 3072bed71748SAndre Guedes hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); 307376a68ba0SDavid Herrmann hci_conn_drop(conn); 30741c2e0041SJohan Hedberg goto unlock; 30751c2e0041SJohan Hedberg } 30761c2e0041SJohan Hedberg 30771c2e0041SJohan Hedberg if (conn->state == BT_CONFIG) { 30781c2e0041SJohan Hedberg if (!ev->status) 30791c2e0041SJohan Hedberg conn->state = BT_CONNECTED; 30801c2e0041SJohan Hedberg 30811c2e0041SJohan Hedberg hci_proto_connect_cfm(conn, ev->status); 308276a68ba0SDavid Herrmann hci_conn_drop(conn); 30831c2e0041SJohan Hedberg } else { 30841c2e0041SJohan Hedberg hci_auth_cfm(conn, ev->status); 30851c2e0041SJohan Hedberg 30861c2e0041SJohan Hedberg hci_conn_hold(conn); 30871c2e0041SJohan Hedberg conn->disc_timeout = HCI_DISCONN_TIMEOUT; 308876a68ba0SDavid Herrmann hci_conn_drop(conn); 30891c2e0041SJohan Hedberg } 30901c2e0041SJohan Hedberg 30911c2e0041SJohan Hedberg unlock: 30921c2e0041SJohan Hedberg hci_dev_unlock(hdev); 30931c2e0041SJohan Hedberg } 30941c2e0041SJohan Hedberg 30956039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn) 309617fa4b9dSJohan Hedberg { 309717fa4b9dSJohan Hedberg /* If remote requests dedicated bonding follow that lead */ 3098acabae96SMikel Astiz if (conn->remote_auth == HCI_AT_DEDICATED_BONDING || 3099acabae96SMikel Astiz conn->remote_auth == HCI_AT_DEDICATED_BONDING_MITM) { 310017fa4b9dSJohan Hedberg /* If both remote and local IO capabilities allow MITM 310117fa4b9dSJohan Hedberg * protection then require it, otherwise don't */ 3102acabae96SMikel Astiz if (conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT || 3103acabae96SMikel Astiz conn->io_capability == HCI_IO_NO_INPUT_OUTPUT) 3104acabae96SMikel Astiz return HCI_AT_DEDICATED_BONDING; 310517fa4b9dSJohan Hedberg else 3106acabae96SMikel Astiz return HCI_AT_DEDICATED_BONDING_MITM; 310717fa4b9dSJohan Hedberg } 310817fa4b9dSJohan Hedberg 310917fa4b9dSJohan Hedberg /* If remote requests no-bonding follow that lead */ 3110acabae96SMikel Astiz if (conn->remote_auth == HCI_AT_NO_BONDING || 3111acabae96SMikel Astiz conn->remote_auth == HCI_AT_NO_BONDING_MITM) 311258797bf7SWaldemar Rymarkiewicz return conn->remote_auth | (conn->auth_type & 0x01); 311317fa4b9dSJohan Hedberg 311417fa4b9dSJohan Hedberg return conn->auth_type; 311517fa4b9dSJohan Hedberg } 311617fa4b9dSJohan Hedberg 31176039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 31180493684eSMarcel Holtmann { 31190493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 31200493684eSMarcel Holtmann struct hci_conn *conn; 31210493684eSMarcel Holtmann 31220493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 31230493684eSMarcel Holtmann 31240493684eSMarcel Holtmann hci_dev_lock(hdev); 31250493684eSMarcel Holtmann 31260493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 312703b555e1SJohan Hedberg if (!conn) 312803b555e1SJohan Hedberg goto unlock; 312903b555e1SJohan Hedberg 31300493684eSMarcel Holtmann hci_conn_hold(conn); 31310493684eSMarcel Holtmann 3132a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 313303b555e1SJohan Hedberg goto unlock; 313403b555e1SJohan Hedberg 3135a8b2d5c2SJohan Hedberg if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) || 313603b555e1SJohan Hedberg (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 313717fa4b9dSJohan Hedberg struct hci_cp_io_capability_reply cp; 313817fa4b9dSJohan Hedberg 313917fa4b9dSJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 31407a7f1e7cSHemant Gupta /* Change the IO capability from KeyboardDisplay 31417a7f1e7cSHemant Gupta * to DisplayYesNo as it is not supported by BT spec. */ 31427a7f1e7cSHemant Gupta cp.capability = (conn->io_capability == 0x04) ? 3143a767631aSMikel Astiz HCI_IO_DISPLAY_YESNO : conn->io_capability; 31447cbc9bd9SJohan Hedberg conn->auth_type = hci_get_auth_req(conn); 31457cbc9bd9SJohan Hedberg cp.authentication = conn->auth_type; 314617fa4b9dSJohan Hedberg 31478fc9ced3SGustavo Padovan if (hci_find_remote_oob_data(hdev, &conn->dst) && 31488fc9ced3SGustavo Padovan (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags))) 3149ce85ee13SSzymon Janc cp.oob_data = 0x01; 3150ce85ee13SSzymon Janc else 3151ce85ee13SSzymon Janc cp.oob_data = 0x00; 3152ce85ee13SSzymon Janc 315317fa4b9dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, 315417fa4b9dSJohan Hedberg sizeof(cp), &cp); 315503b555e1SJohan Hedberg } else { 315603b555e1SJohan Hedberg struct hci_cp_io_capability_neg_reply cp; 315703b555e1SJohan Hedberg 315803b555e1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 31599f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED; 316003b555e1SJohan Hedberg 316103b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 316203b555e1SJohan Hedberg sizeof(cp), &cp); 316303b555e1SJohan Hedberg } 316403b555e1SJohan Hedberg 316503b555e1SJohan Hedberg unlock: 316603b555e1SJohan Hedberg hci_dev_unlock(hdev); 316703b555e1SJohan Hedberg } 316803b555e1SJohan Hedberg 31696039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 317003b555e1SJohan Hedberg { 317103b555e1SJohan Hedberg struct hci_ev_io_capa_reply *ev = (void *) skb->data; 317203b555e1SJohan Hedberg struct hci_conn *conn; 317303b555e1SJohan Hedberg 317403b555e1SJohan Hedberg BT_DBG("%s", hdev->name); 317503b555e1SJohan Hedberg 317603b555e1SJohan Hedberg hci_dev_lock(hdev); 317703b555e1SJohan Hedberg 317803b555e1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 317903b555e1SJohan Hedberg if (!conn) 318003b555e1SJohan Hedberg goto unlock; 318103b555e1SJohan Hedberg 318203b555e1SJohan Hedberg conn->remote_cap = ev->capability; 318303b555e1SJohan Hedberg conn->remote_auth = ev->authentication; 318458a681efSJohan Hedberg if (ev->oob_data) 318558a681efSJohan Hedberg set_bit(HCI_CONN_REMOTE_OOB, &conn->flags); 318603b555e1SJohan Hedberg 318703b555e1SJohan Hedberg unlock: 31880493684eSMarcel Holtmann hci_dev_unlock(hdev); 31890493684eSMarcel Holtmann } 31900493684eSMarcel Holtmann 31916039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev, 3192a5c29683SJohan Hedberg struct sk_buff *skb) 3193a5c29683SJohan Hedberg { 3194a5c29683SJohan Hedberg struct hci_ev_user_confirm_req *ev = (void *) skb->data; 319555bc1a37SJohan Hedberg int loc_mitm, rem_mitm, confirm_hint = 0; 31967a828908SJohan Hedberg struct hci_conn *conn; 3197a5c29683SJohan Hedberg 3198a5c29683SJohan Hedberg BT_DBG("%s", hdev->name); 3199a5c29683SJohan Hedberg 3200a5c29683SJohan Hedberg hci_dev_lock(hdev); 3201a5c29683SJohan Hedberg 3202a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 32037a828908SJohan Hedberg goto unlock; 32047a828908SJohan Hedberg 32057a828908SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 32067a828908SJohan Hedberg if (!conn) 32077a828908SJohan Hedberg goto unlock; 32087a828908SJohan Hedberg 32097a828908SJohan Hedberg loc_mitm = (conn->auth_type & 0x01); 32107a828908SJohan Hedberg rem_mitm = (conn->remote_auth & 0x01); 32117a828908SJohan Hedberg 32127a828908SJohan Hedberg /* If we require MITM but the remote device can't provide that 32137a828908SJohan Hedberg * (it has NoInputNoOutput) then reject the confirmation 32147a828908SJohan Hedberg * request. The only exception is when we're dedicated bonding 32157a828908SJohan Hedberg * initiators (connect_cfm_cb set) since then we always have the MITM 32167a828908SJohan Hedberg * bit set. */ 3217a767631aSMikel Astiz if (!conn->connect_cfm_cb && loc_mitm && 3218a767631aSMikel Astiz conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) { 32197a828908SJohan Hedberg BT_DBG("Rejecting request: remote device can't provide MITM"); 32207a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, 32217a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 32227a828908SJohan Hedberg goto unlock; 32237a828908SJohan Hedberg } 32247a828908SJohan Hedberg 32257a828908SJohan Hedberg /* If no side requires MITM protection; auto-accept */ 3226a767631aSMikel Astiz if ((!loc_mitm || conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) && 3227a767631aSMikel Astiz (!rem_mitm || conn->io_capability == HCI_IO_NO_INPUT_OUTPUT)) { 322855bc1a37SJohan Hedberg 322955bc1a37SJohan Hedberg /* If we're not the initiators request authorization to 323055bc1a37SJohan Hedberg * proceed from user space (mgmt_user_confirm with 323155bc1a37SJohan Hedberg * confirm_hint set to 1). */ 323251a8efd7SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 323355bc1a37SJohan Hedberg BT_DBG("Confirming auto-accept as acceptor"); 323455bc1a37SJohan Hedberg confirm_hint = 1; 323555bc1a37SJohan Hedberg goto confirm; 323655bc1a37SJohan Hedberg } 323755bc1a37SJohan Hedberg 32389f61656aSJohan Hedberg BT_DBG("Auto-accept of user confirmation with %ums delay", 32399f61656aSJohan Hedberg hdev->auto_accept_delay); 32409f61656aSJohan Hedberg 32419f61656aSJohan Hedberg if (hdev->auto_accept_delay > 0) { 32429f61656aSJohan Hedberg int delay = msecs_to_jiffies(hdev->auto_accept_delay); 32437bc18d9dSJohan Hedberg queue_delayed_work(conn->hdev->workqueue, 32447bc18d9dSJohan Hedberg &conn->auto_accept_work, delay); 32459f61656aSJohan Hedberg goto unlock; 32469f61656aSJohan Hedberg } 32479f61656aSJohan Hedberg 32487a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, 32497a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 32507a828908SJohan Hedberg goto unlock; 32517a828908SJohan Hedberg } 32527a828908SJohan Hedberg 325355bc1a37SJohan Hedberg confirm: 3254272d90dfSJohan Hedberg mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey, 325555bc1a37SJohan Hedberg confirm_hint); 3256a5c29683SJohan Hedberg 32577a828908SJohan Hedberg unlock: 3258a5c29683SJohan Hedberg hci_dev_unlock(hdev); 3259a5c29683SJohan Hedberg } 3260a5c29683SJohan Hedberg 32616039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev, 32621143d458SBrian Gix struct sk_buff *skb) 32631143d458SBrian Gix { 32641143d458SBrian Gix struct hci_ev_user_passkey_req *ev = (void *) skb->data; 32651143d458SBrian Gix 32661143d458SBrian Gix BT_DBG("%s", hdev->name); 32671143d458SBrian Gix 3268a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 3269272d90dfSJohan Hedberg mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); 32701143d458SBrian Gix } 32711143d458SBrian Gix 327292a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev, 327392a25256SJohan Hedberg struct sk_buff *skb) 327492a25256SJohan Hedberg { 327592a25256SJohan Hedberg struct hci_ev_user_passkey_notify *ev = (void *) skb->data; 327692a25256SJohan Hedberg struct hci_conn *conn; 327792a25256SJohan Hedberg 327892a25256SJohan Hedberg BT_DBG("%s", hdev->name); 327992a25256SJohan Hedberg 328092a25256SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 328192a25256SJohan Hedberg if (!conn) 328292a25256SJohan Hedberg return; 328392a25256SJohan Hedberg 328492a25256SJohan Hedberg conn->passkey_notify = __le32_to_cpu(ev->passkey); 328592a25256SJohan Hedberg conn->passkey_entered = 0; 328692a25256SJohan Hedberg 328792a25256SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 328892a25256SJohan Hedberg mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, 328992a25256SJohan Hedberg conn->dst_type, conn->passkey_notify, 329092a25256SJohan Hedberg conn->passkey_entered); 329192a25256SJohan Hedberg } 329292a25256SJohan Hedberg 329392a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 329492a25256SJohan Hedberg { 329592a25256SJohan Hedberg struct hci_ev_keypress_notify *ev = (void *) skb->data; 329692a25256SJohan Hedberg struct hci_conn *conn; 329792a25256SJohan Hedberg 329892a25256SJohan Hedberg BT_DBG("%s", hdev->name); 329992a25256SJohan Hedberg 330092a25256SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 330192a25256SJohan Hedberg if (!conn) 330292a25256SJohan Hedberg return; 330392a25256SJohan Hedberg 330492a25256SJohan Hedberg switch (ev->type) { 330592a25256SJohan Hedberg case HCI_KEYPRESS_STARTED: 330692a25256SJohan Hedberg conn->passkey_entered = 0; 330792a25256SJohan Hedberg return; 330892a25256SJohan Hedberg 330992a25256SJohan Hedberg case HCI_KEYPRESS_ENTERED: 331092a25256SJohan Hedberg conn->passkey_entered++; 331192a25256SJohan Hedberg break; 331292a25256SJohan Hedberg 331392a25256SJohan Hedberg case HCI_KEYPRESS_ERASED: 331492a25256SJohan Hedberg conn->passkey_entered--; 331592a25256SJohan Hedberg break; 331692a25256SJohan Hedberg 331792a25256SJohan Hedberg case HCI_KEYPRESS_CLEARED: 331892a25256SJohan Hedberg conn->passkey_entered = 0; 331992a25256SJohan Hedberg break; 332092a25256SJohan Hedberg 332192a25256SJohan Hedberg case HCI_KEYPRESS_COMPLETED: 332292a25256SJohan Hedberg return; 332392a25256SJohan Hedberg } 332492a25256SJohan Hedberg 332592a25256SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 332692a25256SJohan Hedberg mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, 332792a25256SJohan Hedberg conn->dst_type, conn->passkey_notify, 332892a25256SJohan Hedberg conn->passkey_entered); 332992a25256SJohan Hedberg } 333092a25256SJohan Hedberg 33316039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev, 3332807deac2SGustavo Padovan struct sk_buff *skb) 33330493684eSMarcel Holtmann { 33340493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 33350493684eSMarcel Holtmann struct hci_conn *conn; 33360493684eSMarcel Holtmann 33370493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 33380493684eSMarcel Holtmann 33390493684eSMarcel Holtmann hci_dev_lock(hdev); 33400493684eSMarcel Holtmann 33410493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 33422a611692SJohan Hedberg if (!conn) 33432a611692SJohan Hedberg goto unlock; 33442a611692SJohan Hedberg 33452a611692SJohan Hedberg /* To avoid duplicate auth_failed events to user space we check 33462a611692SJohan Hedberg * the HCI_CONN_AUTH_PEND flag which will be set if we 33472a611692SJohan Hedberg * initiated the authentication. A traditional auth_complete 33482a611692SJohan Hedberg * event gets always produced as initiator and is also mapped to 33492a611692SJohan Hedberg * the mgmt_auth_failed event */ 3350fa1bd918SMikel Astiz if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status) 3351bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 3352bab73cb6SJohan Hedberg ev->status); 33532a611692SJohan Hedberg 335476a68ba0SDavid Herrmann hci_conn_drop(conn); 33550493684eSMarcel Holtmann 33562a611692SJohan Hedberg unlock: 33570493684eSMarcel Holtmann hci_dev_unlock(hdev); 33580493684eSMarcel Holtmann } 33590493684eSMarcel Holtmann 33606039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev, 3361807deac2SGustavo Padovan struct sk_buff *skb) 336241a96212SMarcel Holtmann { 336341a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 336441a96212SMarcel Holtmann struct inquiry_entry *ie; 3365cad718edSJohan Hedberg struct hci_conn *conn; 336641a96212SMarcel Holtmann 336741a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 336841a96212SMarcel Holtmann 336941a96212SMarcel Holtmann hci_dev_lock(hdev); 337041a96212SMarcel Holtmann 3371cad718edSJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 3372cad718edSJohan Hedberg if (conn) 3373cad718edSJohan Hedberg memcpy(conn->features[1], ev->features, 8); 3374cad718edSJohan Hedberg 3375cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 3376cc11b9c1SAndrei Emeltchenko if (ie) 337702b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 337841a96212SMarcel Holtmann 337941a96212SMarcel Holtmann hci_dev_unlock(hdev); 338041a96212SMarcel Holtmann } 338141a96212SMarcel Holtmann 33826039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev, 33832763eda6SSzymon Janc struct sk_buff *skb) 33842763eda6SSzymon Janc { 33852763eda6SSzymon Janc struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; 33862763eda6SSzymon Janc struct oob_data *data; 33872763eda6SSzymon Janc 33882763eda6SSzymon Janc BT_DBG("%s", hdev->name); 33892763eda6SSzymon Janc 33902763eda6SSzymon Janc hci_dev_lock(hdev); 33912763eda6SSzymon Janc 3392a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 3393e1ba1f15SSzymon Janc goto unlock; 3394e1ba1f15SSzymon Janc 33952763eda6SSzymon Janc data = hci_find_remote_oob_data(hdev, &ev->bdaddr); 33962763eda6SSzymon Janc if (data) { 3397519ca9d0SMarcel Holtmann if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) { 3398519ca9d0SMarcel Holtmann struct hci_cp_remote_oob_ext_data_reply cp; 3399519ca9d0SMarcel Holtmann 3400519ca9d0SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 3401519ca9d0SMarcel Holtmann memcpy(cp.hash192, data->hash192, sizeof(cp.hash192)); 3402519ca9d0SMarcel Holtmann memcpy(cp.randomizer192, data->randomizer192, 3403519ca9d0SMarcel Holtmann sizeof(cp.randomizer192)); 3404519ca9d0SMarcel Holtmann memcpy(cp.hash256, data->hash256, sizeof(cp.hash256)); 3405519ca9d0SMarcel Holtmann memcpy(cp.randomizer256, data->randomizer256, 3406519ca9d0SMarcel Holtmann sizeof(cp.randomizer256)); 3407519ca9d0SMarcel Holtmann 3408519ca9d0SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_EXT_DATA_REPLY, 3409519ca9d0SMarcel Holtmann sizeof(cp), &cp); 3410519ca9d0SMarcel Holtmann } else { 34112763eda6SSzymon Janc struct hci_cp_remote_oob_data_reply cp; 34122763eda6SSzymon Janc 34132763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 3414519ca9d0SMarcel Holtmann memcpy(cp.hash, data->hash192, sizeof(cp.hash)); 3415519ca9d0SMarcel Holtmann memcpy(cp.randomizer, data->randomizer192, 3416519ca9d0SMarcel Holtmann sizeof(cp.randomizer)); 34172763eda6SSzymon Janc 3418519ca9d0SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, 3419519ca9d0SMarcel Holtmann sizeof(cp), &cp); 3420519ca9d0SMarcel Holtmann } 34212763eda6SSzymon Janc } else { 34222763eda6SSzymon Janc struct hci_cp_remote_oob_data_neg_reply cp; 34232763eda6SSzymon Janc 34242763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 3425519ca9d0SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, 3426519ca9d0SMarcel Holtmann sizeof(cp), &cp); 34272763eda6SSzymon Janc } 34282763eda6SSzymon Janc 3429e1ba1f15SSzymon Janc unlock: 34302763eda6SSzymon Janc hci_dev_unlock(hdev); 34312763eda6SSzymon Janc } 34322763eda6SSzymon Janc 3433d5e91192SAndrei Emeltchenko static void hci_phy_link_complete_evt(struct hci_dev *hdev, 3434d5e91192SAndrei Emeltchenko struct sk_buff *skb) 3435d5e91192SAndrei Emeltchenko { 3436d5e91192SAndrei Emeltchenko struct hci_ev_phy_link_complete *ev = (void *) skb->data; 3437d5e91192SAndrei Emeltchenko struct hci_conn *hcon, *bredr_hcon; 3438d5e91192SAndrei Emeltchenko 3439d5e91192SAndrei Emeltchenko BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle, 3440d5e91192SAndrei Emeltchenko ev->status); 3441d5e91192SAndrei Emeltchenko 3442d5e91192SAndrei Emeltchenko hci_dev_lock(hdev); 3443d5e91192SAndrei Emeltchenko 3444d5e91192SAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 3445d5e91192SAndrei Emeltchenko if (!hcon) { 3446d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 3447d5e91192SAndrei Emeltchenko return; 3448d5e91192SAndrei Emeltchenko } 3449d5e91192SAndrei Emeltchenko 3450d5e91192SAndrei Emeltchenko if (ev->status) { 3451d5e91192SAndrei Emeltchenko hci_conn_del(hcon); 3452d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 3453d5e91192SAndrei Emeltchenko return; 3454d5e91192SAndrei Emeltchenko } 3455d5e91192SAndrei Emeltchenko 3456d5e91192SAndrei Emeltchenko bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon; 3457d5e91192SAndrei Emeltchenko 3458d5e91192SAndrei Emeltchenko hcon->state = BT_CONNECTED; 3459d5e91192SAndrei Emeltchenko bacpy(&hcon->dst, &bredr_hcon->dst); 3460d5e91192SAndrei Emeltchenko 3461d5e91192SAndrei Emeltchenko hci_conn_hold(hcon); 3462d5e91192SAndrei Emeltchenko hcon->disc_timeout = HCI_DISCONN_TIMEOUT; 346376a68ba0SDavid Herrmann hci_conn_drop(hcon); 3464d5e91192SAndrei Emeltchenko 3465d5e91192SAndrei Emeltchenko hci_conn_add_sysfs(hcon); 3466d5e91192SAndrei Emeltchenko 3467cf70ff22SAndrei Emeltchenko amp_physical_cfm(bredr_hcon, hcon); 3468cf70ff22SAndrei Emeltchenko 3469d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 3470d5e91192SAndrei Emeltchenko } 3471d5e91192SAndrei Emeltchenko 347227695fb4SAndrei Emeltchenko static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 347327695fb4SAndrei Emeltchenko { 347427695fb4SAndrei Emeltchenko struct hci_ev_logical_link_complete *ev = (void *) skb->data; 347527695fb4SAndrei Emeltchenko struct hci_conn *hcon; 347627695fb4SAndrei Emeltchenko struct hci_chan *hchan; 347727695fb4SAndrei Emeltchenko struct amp_mgr *mgr; 347827695fb4SAndrei Emeltchenko 347927695fb4SAndrei Emeltchenko BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x", 348027695fb4SAndrei Emeltchenko hdev->name, le16_to_cpu(ev->handle), ev->phy_handle, 348127695fb4SAndrei Emeltchenko ev->status); 348227695fb4SAndrei Emeltchenko 348327695fb4SAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 348427695fb4SAndrei Emeltchenko if (!hcon) 348527695fb4SAndrei Emeltchenko return; 348627695fb4SAndrei Emeltchenko 348727695fb4SAndrei Emeltchenko /* Create AMP hchan */ 348827695fb4SAndrei Emeltchenko hchan = hci_chan_create(hcon); 348927695fb4SAndrei Emeltchenko if (!hchan) 349027695fb4SAndrei Emeltchenko return; 349127695fb4SAndrei Emeltchenko 349227695fb4SAndrei Emeltchenko hchan->handle = le16_to_cpu(ev->handle); 349327695fb4SAndrei Emeltchenko 349427695fb4SAndrei Emeltchenko BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan); 349527695fb4SAndrei Emeltchenko 349627695fb4SAndrei Emeltchenko mgr = hcon->amp_mgr; 349727695fb4SAndrei Emeltchenko if (mgr && mgr->bredr_chan) { 349827695fb4SAndrei Emeltchenko struct l2cap_chan *bredr_chan = mgr->bredr_chan; 349927695fb4SAndrei Emeltchenko 350027695fb4SAndrei Emeltchenko l2cap_chan_lock(bredr_chan); 350127695fb4SAndrei Emeltchenko 350227695fb4SAndrei Emeltchenko bredr_chan->conn->mtu = hdev->block_mtu; 350327695fb4SAndrei Emeltchenko l2cap_logical_cfm(bredr_chan, hchan, 0); 350427695fb4SAndrei Emeltchenko hci_conn_hold(hcon); 350527695fb4SAndrei Emeltchenko 350627695fb4SAndrei Emeltchenko l2cap_chan_unlock(bredr_chan); 350727695fb4SAndrei Emeltchenko } 350827695fb4SAndrei Emeltchenko } 350927695fb4SAndrei Emeltchenko 3510606e2a10SAndrei Emeltchenko static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev, 3511606e2a10SAndrei Emeltchenko struct sk_buff *skb) 3512606e2a10SAndrei Emeltchenko { 3513606e2a10SAndrei Emeltchenko struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data; 3514606e2a10SAndrei Emeltchenko struct hci_chan *hchan; 3515606e2a10SAndrei Emeltchenko 3516606e2a10SAndrei Emeltchenko BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name, 3517606e2a10SAndrei Emeltchenko le16_to_cpu(ev->handle), ev->status); 3518606e2a10SAndrei Emeltchenko 3519606e2a10SAndrei Emeltchenko if (ev->status) 3520606e2a10SAndrei Emeltchenko return; 3521606e2a10SAndrei Emeltchenko 3522606e2a10SAndrei Emeltchenko hci_dev_lock(hdev); 3523606e2a10SAndrei Emeltchenko 3524606e2a10SAndrei Emeltchenko hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle)); 3525606e2a10SAndrei Emeltchenko if (!hchan) 3526606e2a10SAndrei Emeltchenko goto unlock; 3527606e2a10SAndrei Emeltchenko 3528606e2a10SAndrei Emeltchenko amp_destroy_logical_link(hchan, ev->reason); 3529606e2a10SAndrei Emeltchenko 3530606e2a10SAndrei Emeltchenko unlock: 3531606e2a10SAndrei Emeltchenko hci_dev_unlock(hdev); 3532606e2a10SAndrei Emeltchenko } 3533606e2a10SAndrei Emeltchenko 35349eef6b3aSAndrei Emeltchenko static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev, 35359eef6b3aSAndrei Emeltchenko struct sk_buff *skb) 35369eef6b3aSAndrei Emeltchenko { 35379eef6b3aSAndrei Emeltchenko struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data; 35389eef6b3aSAndrei Emeltchenko struct hci_conn *hcon; 35399eef6b3aSAndrei Emeltchenko 35409eef6b3aSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 35419eef6b3aSAndrei Emeltchenko 35429eef6b3aSAndrei Emeltchenko if (ev->status) 35439eef6b3aSAndrei Emeltchenko return; 35449eef6b3aSAndrei Emeltchenko 35459eef6b3aSAndrei Emeltchenko hci_dev_lock(hdev); 35469eef6b3aSAndrei Emeltchenko 35479eef6b3aSAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 35489eef6b3aSAndrei Emeltchenko if (hcon) { 35499eef6b3aSAndrei Emeltchenko hcon->state = BT_CLOSED; 35509eef6b3aSAndrei Emeltchenko hci_conn_del(hcon); 35519eef6b3aSAndrei Emeltchenko } 35529eef6b3aSAndrei Emeltchenko 35539eef6b3aSAndrei Emeltchenko hci_dev_unlock(hdev); 35549eef6b3aSAndrei Emeltchenko } 35559eef6b3aSAndrei Emeltchenko 35566039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 3557fcd89c09SVille Tervo { 3558fcd89c09SVille Tervo struct hci_ev_le_conn_complete *ev = (void *) skb->data; 3559fcd89c09SVille Tervo struct hci_conn *conn; 3560fcd89c09SVille Tervo 35619f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 3562fcd89c09SVille Tervo 3563fcd89c09SVille Tervo hci_dev_lock(hdev); 3564fcd89c09SVille Tervo 35654f72b329SAndrzej Kaczmarek conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); 3566b62f328bSVille Tervo if (!conn) { 3567b62f328bSVille Tervo conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); 3568b62f328bSVille Tervo if (!conn) { 3569b62f328bSVille Tervo BT_ERR("No memory for new connection"); 3570230fd16aSAndre Guedes goto unlock; 3571b62f328bSVille Tervo } 357229b7988aSAndre Guedes 357329b7988aSAndre Guedes conn->dst_type = ev->bdaddr_type; 3574b9b343d2SAndre Guedes 3575880be4e8SMarcel Holtmann /* The advertising parameters for own address type 3576880be4e8SMarcel Holtmann * define which source address and source address 3577880be4e8SMarcel Holtmann * type this connections has. 3578880be4e8SMarcel Holtmann */ 3579880be4e8SMarcel Holtmann if (bacmp(&conn->src, BDADDR_ANY)) { 3580880be4e8SMarcel Holtmann conn->src_type = ADDR_LE_DEV_PUBLIC; 3581880be4e8SMarcel Holtmann } else { 3582880be4e8SMarcel Holtmann bacpy(&conn->src, &hdev->static_addr); 3583880be4e8SMarcel Holtmann conn->src_type = ADDR_LE_DEV_RANDOM; 3584880be4e8SMarcel Holtmann } 3585880be4e8SMarcel Holtmann 3586b9b343d2SAndre Guedes if (ev->role == LE_CONN_ROLE_MASTER) { 3587b9b343d2SAndre Guedes conn->out = true; 3588b9b343d2SAndre Guedes conn->link_mode |= HCI_LM_MASTER; 3589b9b343d2SAndre Guedes } 3590b62f328bSVille Tervo } 3591fcd89c09SVille Tervo 3592cd17decbSAndre Guedes if (ev->status) { 3593cd17decbSAndre Guedes mgmt_connect_failed(hdev, &conn->dst, conn->type, 3594cd17decbSAndre Guedes conn->dst_type, ev->status); 3595cd17decbSAndre Guedes hci_proto_connect_cfm(conn, ev->status); 3596cd17decbSAndre Guedes conn->state = BT_CLOSED; 3597cd17decbSAndre Guedes hci_conn_del(conn); 3598cd17decbSAndre Guedes goto unlock; 3599cd17decbSAndre Guedes } 3600cd17decbSAndre Guedes 3601b644ba33SJohan Hedberg if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 3602b644ba33SJohan Hedberg mgmt_device_connected(hdev, &ev->bdaddr, conn->type, 360395b23582SSzymon Janc conn->dst_type, 0, NULL, 0, NULL); 360483bc71b4SVinicius Costa Gomes 36057b5c0d52SVinicius Costa Gomes conn->sec_level = BT_SECURITY_LOW; 3606fcd89c09SVille Tervo conn->handle = __le16_to_cpu(ev->handle); 3607fcd89c09SVille Tervo conn->state = BT_CONNECTED; 3608fcd89c09SVille Tervo 360918722c24SJukka Rissanen if (test_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags)) 361018722c24SJukka Rissanen set_bit(HCI_CONN_6LOWPAN, &conn->flags); 361118722c24SJukka Rissanen 3612fcd89c09SVille Tervo hci_conn_add_sysfs(conn); 3613fcd89c09SVille Tervo 3614fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 3615fcd89c09SVille Tervo 3616fcd89c09SVille Tervo unlock: 3617fcd89c09SVille Tervo hci_dev_unlock(hdev); 3618fcd89c09SVille Tervo } 3619fcd89c09SVille Tervo 36206039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) 36219aa04c91SAndre Guedes { 3622e95beb41SAndre Guedes u8 num_reports = skb->data[0]; 3623e95beb41SAndre Guedes void *ptr = &skb->data[1]; 36243c9e9195SAndre Guedes s8 rssi; 36259aa04c91SAndre Guedes 3626e95beb41SAndre Guedes while (num_reports--) { 3627e95beb41SAndre Guedes struct hci_ev_le_advertising_info *ev = ptr; 3628e95beb41SAndre Guedes 36293c9e9195SAndre Guedes rssi = ev->data[ev->length]; 36303c9e9195SAndre Guedes mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type, 363104124681SGustavo F. Padovan NULL, rssi, 0, 1, ev->data, ev->length); 36323c9e9195SAndre Guedes 3633e95beb41SAndre Guedes ptr += sizeof(*ev) + ev->length + 1; 36349aa04c91SAndre Guedes } 36359aa04c91SAndre Guedes } 36369aa04c91SAndre Guedes 36376039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 3638a7a595f6SVinicius Costa Gomes { 3639a7a595f6SVinicius Costa Gomes struct hci_ev_le_ltk_req *ev = (void *) skb->data; 3640a7a595f6SVinicius Costa Gomes struct hci_cp_le_ltk_reply cp; 3641bea710feSVinicius Costa Gomes struct hci_cp_le_ltk_neg_reply neg; 3642a7a595f6SVinicius Costa Gomes struct hci_conn *conn; 3643c9839a11SVinicius Costa Gomes struct smp_ltk *ltk; 3644a7a595f6SVinicius Costa Gomes 36459f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle)); 3646a7a595f6SVinicius Costa Gomes 3647a7a595f6SVinicius Costa Gomes hci_dev_lock(hdev); 3648a7a595f6SVinicius Costa Gomes 3649a7a595f6SVinicius Costa Gomes conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3650bea710feSVinicius Costa Gomes if (conn == NULL) 3651bea710feSVinicius Costa Gomes goto not_found; 3652a7a595f6SVinicius Costa Gomes 365398a0b845SJohan Hedberg ltk = hci_find_ltk(hdev, ev->ediv, ev->random, conn->out); 3654bea710feSVinicius Costa Gomes if (ltk == NULL) 3655bea710feSVinicius Costa Gomes goto not_found; 3656bea710feSVinicius Costa Gomes 3657bea710feSVinicius Costa Gomes memcpy(cp.ltk, ltk->val, sizeof(ltk->val)); 3658a7a595f6SVinicius Costa Gomes cp.handle = cpu_to_le16(conn->handle); 3659c9839a11SVinicius Costa Gomes 3660c9839a11SVinicius Costa Gomes if (ltk->authenticated) 3661f8776218SAndre Guedes conn->pending_sec_level = BT_SECURITY_HIGH; 3662f8776218SAndre Guedes else 3663f8776218SAndre Guedes conn->pending_sec_level = BT_SECURITY_MEDIUM; 3664a7a595f6SVinicius Costa Gomes 366589cbb4daSAndre Guedes conn->enc_key_size = ltk->enc_size; 3666a7a595f6SVinicius Costa Gomes 3667a7a595f6SVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); 3668a7a595f6SVinicius Costa Gomes 3669c9839a11SVinicius Costa Gomes if (ltk->type & HCI_SMP_STK) { 3670c9839a11SVinicius Costa Gomes list_del(<k->list); 3671c9839a11SVinicius Costa Gomes kfree(ltk); 3672c9839a11SVinicius Costa Gomes } 3673c9839a11SVinicius Costa Gomes 3674a7a595f6SVinicius Costa Gomes hci_dev_unlock(hdev); 3675bea710feSVinicius Costa Gomes 3676bea710feSVinicius Costa Gomes return; 3677bea710feSVinicius Costa Gomes 3678bea710feSVinicius Costa Gomes not_found: 3679bea710feSVinicius Costa Gomes neg.handle = ev->handle; 3680bea710feSVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg); 3681bea710feSVinicius Costa Gomes hci_dev_unlock(hdev); 3682a7a595f6SVinicius Costa Gomes } 3683a7a595f6SVinicius Costa Gomes 36846039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 3685fcd89c09SVille Tervo { 3686fcd89c09SVille Tervo struct hci_ev_le_meta *le_ev = (void *) skb->data; 3687fcd89c09SVille Tervo 3688fcd89c09SVille Tervo skb_pull(skb, sizeof(*le_ev)); 3689fcd89c09SVille Tervo 3690fcd89c09SVille Tervo switch (le_ev->subevent) { 3691fcd89c09SVille Tervo case HCI_EV_LE_CONN_COMPLETE: 3692fcd89c09SVille Tervo hci_le_conn_complete_evt(hdev, skb); 3693fcd89c09SVille Tervo break; 3694fcd89c09SVille Tervo 36959aa04c91SAndre Guedes case HCI_EV_LE_ADVERTISING_REPORT: 36969aa04c91SAndre Guedes hci_le_adv_report_evt(hdev, skb); 36979aa04c91SAndre Guedes break; 36989aa04c91SAndre Guedes 3699a7a595f6SVinicius Costa Gomes case HCI_EV_LE_LTK_REQ: 3700a7a595f6SVinicius Costa Gomes hci_le_ltk_request_evt(hdev, skb); 3701a7a595f6SVinicius Costa Gomes break; 3702a7a595f6SVinicius Costa Gomes 3703fcd89c09SVille Tervo default: 3704fcd89c09SVille Tervo break; 3705fcd89c09SVille Tervo } 3706fcd89c09SVille Tervo } 3707fcd89c09SVille Tervo 37089495b2eeSAndrei Emeltchenko static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb) 37099495b2eeSAndrei Emeltchenko { 37109495b2eeSAndrei Emeltchenko struct hci_ev_channel_selected *ev = (void *) skb->data; 37119495b2eeSAndrei Emeltchenko struct hci_conn *hcon; 37129495b2eeSAndrei Emeltchenko 37139495b2eeSAndrei Emeltchenko BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle); 37149495b2eeSAndrei Emeltchenko 37159495b2eeSAndrei Emeltchenko skb_pull(skb, sizeof(*ev)); 37169495b2eeSAndrei Emeltchenko 37179495b2eeSAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 37189495b2eeSAndrei Emeltchenko if (!hcon) 37199495b2eeSAndrei Emeltchenko return; 37209495b2eeSAndrei Emeltchenko 37219495b2eeSAndrei Emeltchenko amp_read_loc_assoc_final_data(hdev, hcon); 37229495b2eeSAndrei Emeltchenko } 37239495b2eeSAndrei Emeltchenko 37241da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 37251da177e4SLinus Torvalds { 3726a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 3727a9de9248SMarcel Holtmann __u8 event = hdr->evt; 37281da177e4SLinus Torvalds 3729b6ddb638SJohan Hedberg hci_dev_lock(hdev); 3730b6ddb638SJohan Hedberg 3731b6ddb638SJohan Hedberg /* Received events are (currently) only needed when a request is 3732b6ddb638SJohan Hedberg * ongoing so avoid unnecessary memory allocation. 3733b6ddb638SJohan Hedberg */ 3734b6ddb638SJohan Hedberg if (hdev->req_status == HCI_REQ_PEND) { 3735b6ddb638SJohan Hedberg kfree_skb(hdev->recv_evt); 3736b6ddb638SJohan Hedberg hdev->recv_evt = skb_clone(skb, GFP_KERNEL); 3737b6ddb638SJohan Hedberg } 3738b6ddb638SJohan Hedberg 3739b6ddb638SJohan Hedberg hci_dev_unlock(hdev); 3740b6ddb638SJohan Hedberg 37411da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 37421da177e4SLinus Torvalds 374302350a72SJohan Hedberg if (hdev->sent_cmd && bt_cb(hdev->sent_cmd)->req.event == event) { 3744c1f23a2bSJohannes Berg struct hci_command_hdr *cmd_hdr = (void *) hdev->sent_cmd->data; 3745c1f23a2bSJohannes Berg u16 opcode = __le16_to_cpu(cmd_hdr->opcode); 374602350a72SJohan Hedberg 374702350a72SJohan Hedberg hci_req_cmd_complete(hdev, opcode, 0); 374802350a72SJohan Hedberg } 374902350a72SJohan Hedberg 3750a9de9248SMarcel Holtmann switch (event) { 37511da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 37521da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 37531da177e4SLinus Torvalds break; 37541da177e4SLinus Torvalds 37551da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 37561da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 37571da177e4SLinus Torvalds break; 37581da177e4SLinus Torvalds 3759a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 3760a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 376121d9e30eSMarcel Holtmann break; 376221d9e30eSMarcel Holtmann 37631da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 37641da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 37651da177e4SLinus Torvalds break; 37661da177e4SLinus Torvalds 37671da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 37681da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 37691da177e4SLinus Torvalds break; 37701da177e4SLinus Torvalds 37711da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 37721da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 37731da177e4SLinus Torvalds break; 37741da177e4SLinus Torvalds 3775a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 3776a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 3777a9de9248SMarcel Holtmann break; 3778a9de9248SMarcel Holtmann 37791da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 37801da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 37811da177e4SLinus Torvalds break; 37821da177e4SLinus Torvalds 3783a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 3784a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 3785a9de9248SMarcel Holtmann break; 3786a9de9248SMarcel Holtmann 3787a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 3788a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 3789a9de9248SMarcel Holtmann break; 3790a9de9248SMarcel Holtmann 3791a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 3792a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 3793a9de9248SMarcel Holtmann break; 3794a9de9248SMarcel Holtmann 3795a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 3796a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 3797a9de9248SMarcel Holtmann break; 3798a9de9248SMarcel Holtmann 3799a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 3800a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 3801a9de9248SMarcel Holtmann break; 3802a9de9248SMarcel Holtmann 3803a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 3804a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 3805a9de9248SMarcel Holtmann break; 3806a9de9248SMarcel Holtmann 3807a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 3808a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 38091da177e4SLinus Torvalds break; 38101da177e4SLinus Torvalds 38111da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 38121da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 38131da177e4SLinus Torvalds break; 38141da177e4SLinus Torvalds 38151da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 38161da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 38171da177e4SLinus Torvalds break; 38181da177e4SLinus Torvalds 38191da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 38201da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 38211da177e4SLinus Torvalds break; 38221da177e4SLinus Torvalds 38231da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 38241da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 38251da177e4SLinus Torvalds break; 38261da177e4SLinus Torvalds 3827a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 3828a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 3829a8746417SMarcel Holtmann break; 3830a8746417SMarcel Holtmann 383185a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 383285a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 383385a1e930SMarcel Holtmann break; 383485a1e930SMarcel Holtmann 3835a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 3836a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 3837a9de9248SMarcel Holtmann break; 3838a9de9248SMarcel Holtmann 3839a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 3840a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 3841a9de9248SMarcel Holtmann break; 3842a9de9248SMarcel Holtmann 3843a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 3844a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 3845a9de9248SMarcel Holtmann break; 3846a9de9248SMarcel Holtmann 3847a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 3848a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 38491da177e4SLinus Torvalds break; 38501da177e4SLinus Torvalds 38511c2e0041SJohan Hedberg case HCI_EV_KEY_REFRESH_COMPLETE: 38521c2e0041SJohan Hedberg hci_key_refresh_complete_evt(hdev, skb); 38531c2e0041SJohan Hedberg break; 38541c2e0041SJohan Hedberg 38550493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 38560493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 38570493684eSMarcel Holtmann break; 38580493684eSMarcel Holtmann 385903b555e1SJohan Hedberg case HCI_EV_IO_CAPA_REPLY: 386003b555e1SJohan Hedberg hci_io_capa_reply_evt(hdev, skb); 386103b555e1SJohan Hedberg break; 386203b555e1SJohan Hedberg 3863a5c29683SJohan Hedberg case HCI_EV_USER_CONFIRM_REQUEST: 3864a5c29683SJohan Hedberg hci_user_confirm_request_evt(hdev, skb); 3865a5c29683SJohan Hedberg break; 3866a5c29683SJohan Hedberg 38671143d458SBrian Gix case HCI_EV_USER_PASSKEY_REQUEST: 38681143d458SBrian Gix hci_user_passkey_request_evt(hdev, skb); 38691143d458SBrian Gix break; 38701143d458SBrian Gix 387192a25256SJohan Hedberg case HCI_EV_USER_PASSKEY_NOTIFY: 387292a25256SJohan Hedberg hci_user_passkey_notify_evt(hdev, skb); 387392a25256SJohan Hedberg break; 387492a25256SJohan Hedberg 387592a25256SJohan Hedberg case HCI_EV_KEYPRESS_NOTIFY: 387692a25256SJohan Hedberg hci_keypress_notify_evt(hdev, skb); 387792a25256SJohan Hedberg break; 387892a25256SJohan Hedberg 38790493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 38800493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 38810493684eSMarcel Holtmann break; 38820493684eSMarcel Holtmann 388341a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 388441a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 388541a96212SMarcel Holtmann break; 388641a96212SMarcel Holtmann 3887fcd89c09SVille Tervo case HCI_EV_LE_META: 3888fcd89c09SVille Tervo hci_le_meta_evt(hdev, skb); 3889fcd89c09SVille Tervo break; 3890fcd89c09SVille Tervo 38919495b2eeSAndrei Emeltchenko case HCI_EV_CHANNEL_SELECTED: 38929495b2eeSAndrei Emeltchenko hci_chan_selected_evt(hdev, skb); 38939495b2eeSAndrei Emeltchenko break; 38949495b2eeSAndrei Emeltchenko 38952763eda6SSzymon Janc case HCI_EV_REMOTE_OOB_DATA_REQUEST: 38962763eda6SSzymon Janc hci_remote_oob_data_request_evt(hdev, skb); 38972763eda6SSzymon Janc break; 38982763eda6SSzymon Janc 3899d5e91192SAndrei Emeltchenko case HCI_EV_PHY_LINK_COMPLETE: 3900d5e91192SAndrei Emeltchenko hci_phy_link_complete_evt(hdev, skb); 3901d5e91192SAndrei Emeltchenko break; 3902d5e91192SAndrei Emeltchenko 390327695fb4SAndrei Emeltchenko case HCI_EV_LOGICAL_LINK_COMPLETE: 390427695fb4SAndrei Emeltchenko hci_loglink_complete_evt(hdev, skb); 390527695fb4SAndrei Emeltchenko break; 390627695fb4SAndrei Emeltchenko 3907606e2a10SAndrei Emeltchenko case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE: 3908606e2a10SAndrei Emeltchenko hci_disconn_loglink_complete_evt(hdev, skb); 3909606e2a10SAndrei Emeltchenko break; 3910606e2a10SAndrei Emeltchenko 39119eef6b3aSAndrei Emeltchenko case HCI_EV_DISCONN_PHY_LINK_COMPLETE: 39129eef6b3aSAndrei Emeltchenko hci_disconn_phylink_complete_evt(hdev, skb); 39139eef6b3aSAndrei Emeltchenko break; 39149eef6b3aSAndrei Emeltchenko 391525e89e99SAndrei Emeltchenko case HCI_EV_NUM_COMP_BLOCKS: 391625e89e99SAndrei Emeltchenko hci_num_comp_blocks_evt(hdev, skb); 391725e89e99SAndrei Emeltchenko break; 391825e89e99SAndrei Emeltchenko 39191da177e4SLinus Torvalds default: 39209f1db00cSAndrei Emeltchenko BT_DBG("%s event 0x%2.2x", hdev->name, event); 39211da177e4SLinus Torvalds break; 39221da177e4SLinus Torvalds } 39231da177e4SLinus Torvalds 39241da177e4SLinus Torvalds kfree_skb(skb); 39251da177e4SLinus Torvalds hdev->stat.evt_rx++; 39261da177e4SLinus Torvalds } 3927