11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds BlueZ - Bluetooth protocol stack for Linux 32d0a0346SRon Shaffer Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved. 41da177e4SLinus Torvalds 51da177e4SLinus Torvalds Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> 61da177e4SLinus Torvalds 71da177e4SLinus Torvalds This program is free software; you can redistribute it and/or modify 81da177e4SLinus Torvalds it under the terms of the GNU General Public License version 2 as 91da177e4SLinus Torvalds published by the Free Software Foundation; 101da177e4SLinus Torvalds 111da177e4SLinus Torvalds THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 121da177e4SLinus Torvalds OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 131da177e4SLinus Torvalds FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 141da177e4SLinus Torvalds IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 151da177e4SLinus Torvalds CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 161da177e4SLinus Torvalds WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 171da177e4SLinus Torvalds ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 181da177e4SLinus Torvalds OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 211da177e4SLinus Torvalds COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 221da177e4SLinus Torvalds SOFTWARE IS DISCLAIMED. 231da177e4SLinus Torvalds */ 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds /* Bluetooth HCI event handling. */ 261da177e4SLinus Torvalds 271da177e4SLinus Torvalds #include <asm/unaligned.h> 281da177e4SLinus Torvalds 291da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h> 301da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h> 31f0d6a0eaSMikel Astiz #include <net/bluetooth/mgmt.h> 328e2a0d92SAndrei Emeltchenko #include <net/bluetooth/a2mp.h> 33903e4541SAndrei Emeltchenko #include <net/bluetooth/amp.h> 341da177e4SLinus Torvalds 351da177e4SLinus Torvalds /* Handle HCI Event packets */ 361da177e4SLinus Torvalds 37a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb) 381da177e4SLinus Torvalds { 39a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 401da177e4SLinus Torvalds 419f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 421da177e4SLinus Torvalds 4382f4785cSAndre Guedes if (status) 44a9de9248SMarcel Holtmann return; 451da177e4SLinus Torvalds 4689352e7dSAndre Guedes clear_bit(HCI_INQUIRY, &hdev->flags); 473e13fa1eSAndre Guedes smp_mb__after_clear_bit(); /* wake_up_bit advises about this barrier */ 483e13fa1eSAndre Guedes wake_up_bit(&hdev->flags, HCI_INQUIRY); 4989352e7dSAndre Guedes 50a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 511da177e4SLinus Torvalds } 526bd57416SMarcel Holtmann 534d93483bSAndre Guedes static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 544d93483bSAndre Guedes { 554d93483bSAndre Guedes __u8 status = *((__u8 *) skb->data); 564d93483bSAndre Guedes 579f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 58ae854a70SAndre Guedes 59ae854a70SAndre Guedes if (status) 60ae854a70SAndre Guedes return; 61ae854a70SAndre Guedes 62ae854a70SAndre Guedes set_bit(HCI_PERIODIC_INQ, &hdev->dev_flags); 634d93483bSAndre Guedes } 644d93483bSAndre Guedes 65a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 661da177e4SLinus Torvalds { 67a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 68a9de9248SMarcel Holtmann 699f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 70a9de9248SMarcel Holtmann 71a9de9248SMarcel Holtmann if (status) 72a9de9248SMarcel Holtmann return; 73a9de9248SMarcel Holtmann 74ae854a70SAndre Guedes clear_bit(HCI_PERIODIC_INQ, &hdev->dev_flags); 75ae854a70SAndre Guedes 76a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 77a9de9248SMarcel Holtmann } 78a9de9248SMarcel Holtmann 79807deac2SGustavo Padovan static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, 80807deac2SGustavo Padovan struct sk_buff *skb) 81a9de9248SMarcel Holtmann { 82a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 83a9de9248SMarcel Holtmann } 84a9de9248SMarcel Holtmann 85a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb) 86a9de9248SMarcel Holtmann { 87a9de9248SMarcel Holtmann struct hci_rp_role_discovery *rp = (void *) skb->data; 881da177e4SLinus Torvalds struct hci_conn *conn; 891da177e4SLinus Torvalds 909f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 911da177e4SLinus Torvalds 92a9de9248SMarcel Holtmann if (rp->status) 93a9de9248SMarcel Holtmann return; 941da177e4SLinus Torvalds 951da177e4SLinus Torvalds hci_dev_lock(hdev); 961da177e4SLinus Torvalds 97a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 981da177e4SLinus Torvalds if (conn) { 99a9de9248SMarcel Holtmann if (rp->role) 1001da177e4SLinus Torvalds conn->link_mode &= ~HCI_LM_MASTER; 1011da177e4SLinus Torvalds else 1021da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 1031da177e4SLinus Torvalds } 1041da177e4SLinus Torvalds 1051da177e4SLinus Torvalds hci_dev_unlock(hdev); 106a9de9248SMarcel Holtmann } 1071da177e4SLinus Torvalds 108e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 109e4e8e37cSMarcel Holtmann { 110e4e8e37cSMarcel Holtmann struct hci_rp_read_link_policy *rp = (void *) skb->data; 111e4e8e37cSMarcel Holtmann struct hci_conn *conn; 112e4e8e37cSMarcel Holtmann 1139f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 114e4e8e37cSMarcel Holtmann 115e4e8e37cSMarcel Holtmann if (rp->status) 116e4e8e37cSMarcel Holtmann return; 117e4e8e37cSMarcel Holtmann 118e4e8e37cSMarcel Holtmann hci_dev_lock(hdev); 119e4e8e37cSMarcel Holtmann 120e4e8e37cSMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 121e4e8e37cSMarcel Holtmann if (conn) 122e4e8e37cSMarcel Holtmann conn->link_policy = __le16_to_cpu(rp->policy); 123e4e8e37cSMarcel Holtmann 124e4e8e37cSMarcel Holtmann hci_dev_unlock(hdev); 125e4e8e37cSMarcel Holtmann } 126e4e8e37cSMarcel Holtmann 127a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 128a9de9248SMarcel Holtmann { 129a9de9248SMarcel Holtmann struct hci_rp_write_link_policy *rp = (void *) skb->data; 130a9de9248SMarcel Holtmann struct hci_conn *conn; 131a9de9248SMarcel Holtmann void *sent; 132a9de9248SMarcel Holtmann 1339f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 134a9de9248SMarcel Holtmann 135a9de9248SMarcel Holtmann if (rp->status) 136a9de9248SMarcel Holtmann return; 137a9de9248SMarcel Holtmann 138a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY); 13904837f64SMarcel Holtmann if (!sent) 140a9de9248SMarcel Holtmann return; 14104837f64SMarcel Holtmann 14204837f64SMarcel Holtmann hci_dev_lock(hdev); 14304837f64SMarcel Holtmann 144a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 145e4e8e37cSMarcel Holtmann if (conn) 14683985319SHarvey Harrison conn->link_policy = get_unaligned_le16(sent + 2); 14704837f64SMarcel Holtmann 14804837f64SMarcel Holtmann hci_dev_unlock(hdev); 1491da177e4SLinus Torvalds } 1501da177e4SLinus Torvalds 151807deac2SGustavo Padovan static void hci_cc_read_def_link_policy(struct hci_dev *hdev, 152807deac2SGustavo Padovan struct sk_buff *skb) 153e4e8e37cSMarcel Holtmann { 154e4e8e37cSMarcel Holtmann struct hci_rp_read_def_link_policy *rp = (void *) skb->data; 155e4e8e37cSMarcel Holtmann 1569f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 157e4e8e37cSMarcel Holtmann 158e4e8e37cSMarcel Holtmann if (rp->status) 159e4e8e37cSMarcel Holtmann return; 160e4e8e37cSMarcel Holtmann 161e4e8e37cSMarcel Holtmann hdev->link_policy = __le16_to_cpu(rp->policy); 162e4e8e37cSMarcel Holtmann } 163e4e8e37cSMarcel Holtmann 164807deac2SGustavo Padovan static void hci_cc_write_def_link_policy(struct hci_dev *hdev, 165807deac2SGustavo Padovan struct sk_buff *skb) 166e4e8e37cSMarcel Holtmann { 167e4e8e37cSMarcel Holtmann __u8 status = *((__u8 *) skb->data); 168e4e8e37cSMarcel Holtmann void *sent; 169e4e8e37cSMarcel Holtmann 1709f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 171e4e8e37cSMarcel Holtmann 172e4e8e37cSMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY); 173e4e8e37cSMarcel Holtmann if (!sent) 174e4e8e37cSMarcel Holtmann return; 175e4e8e37cSMarcel Holtmann 176e4e8e37cSMarcel Holtmann if (!status) 177e4e8e37cSMarcel Holtmann hdev->link_policy = get_unaligned_le16(sent); 178e4e8e37cSMarcel Holtmann } 179e4e8e37cSMarcel Holtmann 180a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) 1811da177e4SLinus Torvalds { 182a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 183a9de9248SMarcel Holtmann 1849f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 185a9de9248SMarcel Holtmann 18610572132SGustavo F. Padovan clear_bit(HCI_RESET, &hdev->flags); 18710572132SGustavo F. Padovan 188a297e97cSJohan Hedberg /* Reset all non-persistent flags */ 1892cc6fb00SJohan Hedberg hdev->dev_flags &= ~HCI_PERSISTENT_MASK; 19069775ff6SAndre Guedes 19169775ff6SAndre Guedes hdev->discovery.state = DISCOVERY_STOPPED; 192bbaf444aSJohan Hedberg hdev->inq_tx_power = HCI_TX_POWER_INVALID; 193bbaf444aSJohan Hedberg hdev->adv_tx_power = HCI_TX_POWER_INVALID; 1943f0f524bSJohan Hedberg 1953f0f524bSJohan Hedberg memset(hdev->adv_data, 0, sizeof(hdev->adv_data)); 1963f0f524bSJohan Hedberg hdev->adv_data_len = 0; 197a9de9248SMarcel Holtmann } 198a9de9248SMarcel Holtmann 199a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) 200a9de9248SMarcel Holtmann { 201a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 2021da177e4SLinus Torvalds void *sent; 2031da177e4SLinus Torvalds 2049f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 2051da177e4SLinus Torvalds 206a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); 2071da177e4SLinus Torvalds if (!sent) 208a9de9248SMarcel Holtmann return; 2091da177e4SLinus Torvalds 21056e5cb86SJohan Hedberg hci_dev_lock(hdev); 21156e5cb86SJohan Hedberg 212f51d5b24SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 213f51d5b24SJohan Hedberg mgmt_set_local_name_complete(hdev, sent, status); 21428cc7bdeSJohan Hedberg else if (!status) 21528cc7bdeSJohan Hedberg memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); 216f51d5b24SJohan Hedberg 21756e5cb86SJohan Hedberg hci_dev_unlock(hdev); 218a9de9248SMarcel Holtmann } 219a9de9248SMarcel Holtmann 220a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) 221a9de9248SMarcel Holtmann { 222a9de9248SMarcel Holtmann struct hci_rp_read_local_name *rp = (void *) skb->data; 223a9de9248SMarcel Holtmann 2249f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 225a9de9248SMarcel Holtmann 226a9de9248SMarcel Holtmann if (rp->status) 227a9de9248SMarcel Holtmann return; 228a9de9248SMarcel Holtmann 229db99b5fcSJohan Hedberg if (test_bit(HCI_SETUP, &hdev->dev_flags)) 2301f6c6378SJohan Hedberg memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); 231a9de9248SMarcel Holtmann } 232a9de9248SMarcel Holtmann 233a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) 234a9de9248SMarcel Holtmann { 235a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 236a9de9248SMarcel Holtmann void *sent; 237a9de9248SMarcel Holtmann 2389f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 239a9de9248SMarcel Holtmann 240a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); 241a9de9248SMarcel Holtmann if (!sent) 242a9de9248SMarcel Holtmann return; 2431da177e4SLinus Torvalds 2441da177e4SLinus Torvalds if (!status) { 245a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 246a9de9248SMarcel Holtmann 2471da177e4SLinus Torvalds if (param == AUTH_ENABLED) 2481da177e4SLinus Torvalds set_bit(HCI_AUTH, &hdev->flags); 2491da177e4SLinus Torvalds else 2501da177e4SLinus Torvalds clear_bit(HCI_AUTH, &hdev->flags); 2511da177e4SLinus Torvalds } 252a9de9248SMarcel Holtmann 25333ef95edSJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 25433ef95edSJohan Hedberg mgmt_auth_enable_complete(hdev, status); 255a9de9248SMarcel Holtmann } 2561da177e4SLinus Torvalds 257a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) 258a9de9248SMarcel Holtmann { 259a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 260a9de9248SMarcel Holtmann void *sent; 261a9de9248SMarcel Holtmann 2629f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 263a9de9248SMarcel Holtmann 264a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); 2651da177e4SLinus Torvalds if (!sent) 266a9de9248SMarcel Holtmann return; 2671da177e4SLinus Torvalds 2681da177e4SLinus Torvalds if (!status) { 269a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 270a9de9248SMarcel Holtmann 2711da177e4SLinus Torvalds if (param) 2721da177e4SLinus Torvalds set_bit(HCI_ENCRYPT, &hdev->flags); 2731da177e4SLinus Torvalds else 2741da177e4SLinus Torvalds clear_bit(HCI_ENCRYPT, &hdev->flags); 2751da177e4SLinus Torvalds } 2761da177e4SLinus Torvalds } 2771da177e4SLinus Torvalds 278a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) 279a9de9248SMarcel Holtmann { 28036f7fc7eSJohan Hedberg __u8 param, status = *((__u8 *) skb->data); 28136f7fc7eSJohan Hedberg int old_pscan, old_iscan; 282a9de9248SMarcel Holtmann void *sent; 2831da177e4SLinus Torvalds 2849f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 285a9de9248SMarcel Holtmann 286a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); 2871da177e4SLinus Torvalds if (!sent) 288a9de9248SMarcel Holtmann return; 2891da177e4SLinus Torvalds 29036f7fc7eSJohan Hedberg param = *((__u8 *) sent); 291a9de9248SMarcel Holtmann 29256e5cb86SJohan Hedberg hci_dev_lock(hdev); 29356e5cb86SJohan Hedberg 294fa1bd918SMikel Astiz if (status) { 295744cf19eSJohan Hedberg mgmt_write_scan_failed(hdev, param, status); 2962d7cee58SJohan Hedberg hdev->discov_timeout = 0; 2972d7cee58SJohan Hedberg goto done; 2982d7cee58SJohan Hedberg } 2992d7cee58SJohan Hedberg 3009fbcbb45SJohan Hedberg old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags); 3019fbcbb45SJohan Hedberg old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags); 302a9de9248SMarcel Holtmann 30373f22f62SJohan Hedberg if (param & SCAN_INQUIRY) { 3041da177e4SLinus Torvalds set_bit(HCI_ISCAN, &hdev->flags); 3059fbcbb45SJohan Hedberg if (!old_iscan) 306744cf19eSJohan Hedberg mgmt_discoverable(hdev, 1); 30716ab91abSJohan Hedberg if (hdev->discov_timeout > 0) { 30816ab91abSJohan Hedberg int to = msecs_to_jiffies(hdev->discov_timeout * 1000); 30916ab91abSJohan Hedberg queue_delayed_work(hdev->workqueue, &hdev->discov_off, 31016ab91abSJohan Hedberg to); 31116ab91abSJohan Hedberg } 3129fbcbb45SJohan Hedberg } else if (old_iscan) 313744cf19eSJohan Hedberg mgmt_discoverable(hdev, 0); 3141da177e4SLinus Torvalds 3159fbcbb45SJohan Hedberg if (param & SCAN_PAGE) { 3161da177e4SLinus Torvalds set_bit(HCI_PSCAN, &hdev->flags); 3179fbcbb45SJohan Hedberg if (!old_pscan) 318744cf19eSJohan Hedberg mgmt_connectable(hdev, 1); 3199fbcbb45SJohan Hedberg } else if (old_pscan) 320744cf19eSJohan Hedberg mgmt_connectable(hdev, 0); 321a9de9248SMarcel Holtmann 32236f7fc7eSJohan Hedberg done: 32356e5cb86SJohan Hedberg hci_dev_unlock(hdev); 3241da177e4SLinus Torvalds } 3251da177e4SLinus Torvalds 326a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 327a9de9248SMarcel Holtmann { 328a9de9248SMarcel Holtmann struct hci_rp_read_class_of_dev *rp = (void *) skb->data; 329a9de9248SMarcel Holtmann 3309f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 331a9de9248SMarcel Holtmann 332a9de9248SMarcel Holtmann if (rp->status) 333a9de9248SMarcel Holtmann return; 334a9de9248SMarcel Holtmann 335a9de9248SMarcel Holtmann memcpy(hdev->dev_class, rp->dev_class, 3); 336a9de9248SMarcel Holtmann 337a9de9248SMarcel Holtmann BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, 338a9de9248SMarcel Holtmann hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); 339a9de9248SMarcel Holtmann } 340a9de9248SMarcel Holtmann 341a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 342a9de9248SMarcel Holtmann { 343a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 344a9de9248SMarcel Holtmann void *sent; 345a9de9248SMarcel Holtmann 3469f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 347a9de9248SMarcel Holtmann 348a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); 349a9de9248SMarcel Holtmann if (!sent) 350a9de9248SMarcel Holtmann return; 351a9de9248SMarcel Holtmann 3527f9a903cSMarcel Holtmann hci_dev_lock(hdev); 3537f9a903cSMarcel Holtmann 3547f9a903cSMarcel Holtmann if (status == 0) 355a9de9248SMarcel Holtmann memcpy(hdev->dev_class, sent, 3); 3567f9a903cSMarcel Holtmann 3577f9a903cSMarcel Holtmann if (test_bit(HCI_MGMT, &hdev->dev_flags)) 3587f9a903cSMarcel Holtmann mgmt_set_class_of_dev_complete(hdev, sent, status); 3597f9a903cSMarcel Holtmann 3607f9a903cSMarcel Holtmann hci_dev_unlock(hdev); 361a9de9248SMarcel Holtmann } 362a9de9248SMarcel Holtmann 363a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 364a9de9248SMarcel Holtmann { 365a9de9248SMarcel Holtmann struct hci_rp_read_voice_setting *rp = (void *) skb->data; 366a9de9248SMarcel Holtmann __u16 setting; 367a9de9248SMarcel Holtmann 3689f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 369a9de9248SMarcel Holtmann 370a9de9248SMarcel Holtmann if (rp->status) 371a9de9248SMarcel Holtmann return; 372a9de9248SMarcel Holtmann 373a9de9248SMarcel Holtmann setting = __le16_to_cpu(rp->voice_setting); 374a9de9248SMarcel Holtmann 375a9de9248SMarcel Holtmann if (hdev->voice_setting == setting) 376a9de9248SMarcel Holtmann return; 377a9de9248SMarcel Holtmann 378a9de9248SMarcel Holtmann hdev->voice_setting = setting; 379a9de9248SMarcel Holtmann 3809f1db00cSAndrei Emeltchenko BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting); 381a9de9248SMarcel Holtmann 3823c54711cSGustavo F. Padovan if (hdev->notify) 383a9de9248SMarcel Holtmann hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 384a9de9248SMarcel Holtmann } 385a9de9248SMarcel Holtmann 3868fc9ced3SGustavo Padovan static void hci_cc_write_voice_setting(struct hci_dev *hdev, 3878fc9ced3SGustavo Padovan struct sk_buff *skb) 388a9de9248SMarcel Holtmann { 389a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 390f383f275SMarcel Holtmann __u16 setting; 391a9de9248SMarcel Holtmann void *sent; 392a9de9248SMarcel Holtmann 3939f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 394a9de9248SMarcel Holtmann 395f383f275SMarcel Holtmann if (status) 396f383f275SMarcel Holtmann return; 397f383f275SMarcel Holtmann 398a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); 399a9de9248SMarcel Holtmann if (!sent) 400a9de9248SMarcel Holtmann return; 401a9de9248SMarcel Holtmann 402f383f275SMarcel Holtmann setting = get_unaligned_le16(sent); 4031da177e4SLinus Torvalds 404f383f275SMarcel Holtmann if (hdev->voice_setting == setting) 405f383f275SMarcel Holtmann return; 406f383f275SMarcel Holtmann 4071da177e4SLinus Torvalds hdev->voice_setting = setting; 4081da177e4SLinus Torvalds 4099f1db00cSAndrei Emeltchenko BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting); 4101da177e4SLinus Torvalds 4113c54711cSGustavo F. Padovan if (hdev->notify) 4121da177e4SLinus Torvalds hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 4131da177e4SLinus Torvalds } 4141da177e4SLinus Torvalds 415333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 416333140b5SMarcel Holtmann { 417333140b5SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 4185ed8eb2fSJohan Hedberg struct hci_cp_write_ssp_mode *sent; 419333140b5SMarcel Holtmann 4209f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 421333140b5SMarcel Holtmann 422333140b5SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); 423333140b5SMarcel Holtmann if (!sent) 424333140b5SMarcel Holtmann return; 425333140b5SMarcel Holtmann 4265ed8eb2fSJohan Hedberg if (!status) { 4275ed8eb2fSJohan Hedberg if (sent->mode) 428cad718edSJohan Hedberg hdev->features[1][0] |= LMP_HOST_SSP; 4295ed8eb2fSJohan Hedberg else 430cad718edSJohan Hedberg hdev->features[1][0] &= ~LMP_HOST_SSP; 4315ed8eb2fSJohan Hedberg } 4325ed8eb2fSJohan Hedberg 433c0ecddc2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 4345ed8eb2fSJohan Hedberg mgmt_ssp_enable_complete(hdev, sent->mode, status); 435c0ecddc2SJohan Hedberg else if (!status) { 4365ed8eb2fSJohan Hedberg if (sent->mode) 43784bde9d6SJohan Hedberg set_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 43884bde9d6SJohan Hedberg else 43984bde9d6SJohan Hedberg clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags); 440c0ecddc2SJohan Hedberg } 441333140b5SMarcel Holtmann } 442333140b5SMarcel Holtmann 443a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) 444a9de9248SMarcel Holtmann { 445a9de9248SMarcel Holtmann struct hci_rp_read_local_version *rp = (void *) skb->data; 4461143e5a6SMarcel Holtmann 4479f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 4481143e5a6SMarcel Holtmann 449a9de9248SMarcel Holtmann if (rp->status) 45042c6b129SJohan Hedberg return; 4511143e5a6SMarcel Holtmann 452a9de9248SMarcel Holtmann hdev->hci_ver = rp->hci_ver; 453e4e8e37cSMarcel Holtmann hdev->hci_rev = __le16_to_cpu(rp->hci_rev); 454d5859e22SJohan Hedberg hdev->lmp_ver = rp->lmp_ver; 455e4e8e37cSMarcel Holtmann hdev->manufacturer = __le16_to_cpu(rp->manufacturer); 456d5859e22SJohan Hedberg hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); 4571da177e4SLinus Torvalds 4589f1db00cSAndrei Emeltchenko BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name, 459807deac2SGustavo Padovan hdev->manufacturer, hdev->hci_ver, hdev->hci_rev); 460d5859e22SJohan Hedberg } 461d5859e22SJohan Hedberg 4628fc9ced3SGustavo Padovan static void hci_cc_read_local_commands(struct hci_dev *hdev, 4638fc9ced3SGustavo Padovan struct sk_buff *skb) 464a9de9248SMarcel Holtmann { 465a9de9248SMarcel Holtmann struct hci_rp_read_local_commands *rp = (void *) skb->data; 466a9de9248SMarcel Holtmann 4679f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 468a9de9248SMarcel Holtmann 4692177bab5SJohan Hedberg if (!rp->status) 470a9de9248SMarcel Holtmann memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); 471a9de9248SMarcel Holtmann } 472a9de9248SMarcel Holtmann 4738fc9ced3SGustavo Padovan static void hci_cc_read_local_features(struct hci_dev *hdev, 4748fc9ced3SGustavo Padovan struct sk_buff *skb) 475a9de9248SMarcel Holtmann { 476a9de9248SMarcel Holtmann struct hci_rp_read_local_features *rp = (void *) skb->data; 477a9de9248SMarcel Holtmann 4789f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 479a9de9248SMarcel Holtmann 480a9de9248SMarcel Holtmann if (rp->status) 481a9de9248SMarcel Holtmann return; 482a9de9248SMarcel Holtmann 483a9de9248SMarcel Holtmann memcpy(hdev->features, rp->features, 8); 4841da177e4SLinus Torvalds 4851da177e4SLinus Torvalds /* Adjust default settings according to features 4861da177e4SLinus Torvalds * supported by device. */ 487a9de9248SMarcel Holtmann 488cad718edSJohan Hedberg if (hdev->features[0][0] & LMP_3SLOT) 4891da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM3 | HCI_DH3); 4901da177e4SLinus Torvalds 491cad718edSJohan Hedberg if (hdev->features[0][0] & LMP_5SLOT) 4921da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM5 | HCI_DH5); 4931da177e4SLinus Torvalds 494cad718edSJohan Hedberg if (hdev->features[0][1] & LMP_HV2) { 4951da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV2); 4965b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV2); 4975b7f9909SMarcel Holtmann } 4981da177e4SLinus Torvalds 499cad718edSJohan Hedberg if (hdev->features[0][1] & LMP_HV3) { 5001da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV3); 5015b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV3); 5025b7f9909SMarcel Holtmann } 5035b7f9909SMarcel Holtmann 50445db810fSAndre Guedes if (lmp_esco_capable(hdev)) 5055b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV3); 5065b7f9909SMarcel Holtmann 507cad718edSJohan Hedberg if (hdev->features[0][4] & LMP_EV4) 5085b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV4); 5095b7f9909SMarcel Holtmann 510cad718edSJohan Hedberg if (hdev->features[0][4] & LMP_EV5) 5115b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV5); 5121da177e4SLinus Torvalds 513cad718edSJohan Hedberg if (hdev->features[0][5] & LMP_EDR_ESCO_2M) 514efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV3); 515efc7688bSMarcel Holtmann 516cad718edSJohan Hedberg if (hdev->features[0][5] & LMP_EDR_ESCO_3M) 517efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_3EV3); 518efc7688bSMarcel Holtmann 519cad718edSJohan Hedberg if (hdev->features[0][5] & LMP_EDR_3S_ESCO) 520efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); 521efc7688bSMarcel Holtmann 522a9de9248SMarcel Holtmann BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, 523cad718edSJohan Hedberg hdev->features[0][0], hdev->features[0][1], 524cad718edSJohan Hedberg hdev->features[0][2], hdev->features[0][3], 525cad718edSJohan Hedberg hdev->features[0][4], hdev->features[0][5], 526cad718edSJohan Hedberg hdev->features[0][6], hdev->features[0][7]); 5271da177e4SLinus Torvalds } 5281da177e4SLinus Torvalds 529971e3a4bSAndre Guedes static void hci_cc_read_local_ext_features(struct hci_dev *hdev, 530971e3a4bSAndre Guedes struct sk_buff *skb) 531971e3a4bSAndre Guedes { 532971e3a4bSAndre Guedes struct hci_rp_read_local_ext_features *rp = (void *) skb->data; 533971e3a4bSAndre Guedes 5349f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 535971e3a4bSAndre Guedes 536971e3a4bSAndre Guedes if (rp->status) 53742c6b129SJohan Hedberg return; 538971e3a4bSAndre Guedes 539d2c5d77fSJohan Hedberg hdev->max_page = rp->max_page; 540d2c5d77fSJohan Hedberg 541cad718edSJohan Hedberg if (rp->page < HCI_MAX_PAGES) 542cad718edSJohan Hedberg memcpy(hdev->features[rp->page], rp->features, 8); 543971e3a4bSAndre Guedes } 544971e3a4bSAndre Guedes 5451e89cffbSAndrei Emeltchenko static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, 5461e89cffbSAndrei Emeltchenko struct sk_buff *skb) 5471e89cffbSAndrei Emeltchenko { 5481e89cffbSAndrei Emeltchenko struct hci_rp_read_flow_control_mode *rp = (void *) skb->data; 5491e89cffbSAndrei Emeltchenko 5509f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 5511e89cffbSAndrei Emeltchenko 55242c6b129SJohan Hedberg if (!rp->status) 5531e89cffbSAndrei Emeltchenko hdev->flow_ctl_mode = rp->mode; 5541e89cffbSAndrei Emeltchenko } 5551e89cffbSAndrei Emeltchenko 556a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 557a9de9248SMarcel Holtmann { 558a9de9248SMarcel Holtmann struct hci_rp_read_buffer_size *rp = (void *) skb->data; 559a9de9248SMarcel Holtmann 5609f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 561a9de9248SMarcel Holtmann 562a9de9248SMarcel Holtmann if (rp->status) 563a9de9248SMarcel Holtmann return; 564a9de9248SMarcel Holtmann 565a9de9248SMarcel Holtmann hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); 566a9de9248SMarcel Holtmann hdev->sco_mtu = rp->sco_mtu; 567a9de9248SMarcel Holtmann hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); 568a9de9248SMarcel Holtmann hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); 569da1f5198SMarcel Holtmann 570da1f5198SMarcel Holtmann if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { 571da1f5198SMarcel Holtmann hdev->sco_mtu = 64; 572da1f5198SMarcel Holtmann hdev->sco_pkts = 8; 573da1f5198SMarcel Holtmann } 574da1f5198SMarcel Holtmann 575da1f5198SMarcel Holtmann hdev->acl_cnt = hdev->acl_pkts; 576da1f5198SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 5771da177e4SLinus Torvalds 578807deac2SGustavo Padovan BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu, 579807deac2SGustavo Padovan hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts); 5801da177e4SLinus Torvalds } 5811da177e4SLinus Torvalds 582a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) 583a9de9248SMarcel Holtmann { 584a9de9248SMarcel Holtmann struct hci_rp_read_bd_addr *rp = (void *) skb->data; 5851da177e4SLinus Torvalds 5869f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 587a9de9248SMarcel Holtmann 588a9de9248SMarcel Holtmann if (!rp->status) 589a9de9248SMarcel Holtmann bacpy(&hdev->bdaddr, &rp->bdaddr); 59023bb5763SJohan Hedberg } 59123bb5763SJohan Hedberg 592f332ec66SJohan Hedberg static void hci_cc_read_page_scan_activity(struct hci_dev *hdev, 593f332ec66SJohan Hedberg struct sk_buff *skb) 594f332ec66SJohan Hedberg { 595f332ec66SJohan Hedberg struct hci_rp_read_page_scan_activity *rp = (void *) skb->data; 596f332ec66SJohan Hedberg 597f332ec66SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 598f332ec66SJohan Hedberg 599f332ec66SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags) && !rp->status) { 600f332ec66SJohan Hedberg hdev->page_scan_interval = __le16_to_cpu(rp->interval); 601f332ec66SJohan Hedberg hdev->page_scan_window = __le16_to_cpu(rp->window); 602f332ec66SJohan Hedberg } 603f332ec66SJohan Hedberg } 604f332ec66SJohan Hedberg 6054a3ee763SJohan Hedberg static void hci_cc_write_page_scan_activity(struct hci_dev *hdev, 6064a3ee763SJohan Hedberg struct sk_buff *skb) 6074a3ee763SJohan Hedberg { 6084a3ee763SJohan Hedberg u8 status = *((u8 *) skb->data); 6094a3ee763SJohan Hedberg struct hci_cp_write_page_scan_activity *sent; 6104a3ee763SJohan Hedberg 6114a3ee763SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 6124a3ee763SJohan Hedberg 6134a3ee763SJohan Hedberg if (status) 6144a3ee763SJohan Hedberg return; 6154a3ee763SJohan Hedberg 6164a3ee763SJohan Hedberg sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY); 6174a3ee763SJohan Hedberg if (!sent) 6184a3ee763SJohan Hedberg return; 6194a3ee763SJohan Hedberg 6204a3ee763SJohan Hedberg hdev->page_scan_interval = __le16_to_cpu(sent->interval); 6214a3ee763SJohan Hedberg hdev->page_scan_window = __le16_to_cpu(sent->window); 6224a3ee763SJohan Hedberg } 6234a3ee763SJohan Hedberg 624f332ec66SJohan Hedberg static void hci_cc_read_page_scan_type(struct hci_dev *hdev, 625f332ec66SJohan Hedberg struct sk_buff *skb) 626f332ec66SJohan Hedberg { 627f332ec66SJohan Hedberg struct hci_rp_read_page_scan_type *rp = (void *) skb->data; 628f332ec66SJohan Hedberg 629f332ec66SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 630f332ec66SJohan Hedberg 631f332ec66SJohan Hedberg if (test_bit(HCI_INIT, &hdev->flags) && !rp->status) 632f332ec66SJohan Hedberg hdev->page_scan_type = rp->type; 633f332ec66SJohan Hedberg } 634f332ec66SJohan Hedberg 6354a3ee763SJohan Hedberg static void hci_cc_write_page_scan_type(struct hci_dev *hdev, 6364a3ee763SJohan Hedberg struct sk_buff *skb) 6374a3ee763SJohan Hedberg { 6384a3ee763SJohan Hedberg u8 status = *((u8 *) skb->data); 6394a3ee763SJohan Hedberg u8 *type; 6404a3ee763SJohan Hedberg 6414a3ee763SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 6424a3ee763SJohan Hedberg 6434a3ee763SJohan Hedberg if (status) 6444a3ee763SJohan Hedberg return; 6454a3ee763SJohan Hedberg 6464a3ee763SJohan Hedberg type = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE); 6474a3ee763SJohan Hedberg if (type) 6484a3ee763SJohan Hedberg hdev->page_scan_type = *type; 6494a3ee763SJohan Hedberg } 6504a3ee763SJohan Hedberg 651350ee4cfSAndrei Emeltchenko static void hci_cc_read_data_block_size(struct hci_dev *hdev, 652350ee4cfSAndrei Emeltchenko struct sk_buff *skb) 653350ee4cfSAndrei Emeltchenko { 654350ee4cfSAndrei Emeltchenko struct hci_rp_read_data_block_size *rp = (void *) skb->data; 655350ee4cfSAndrei Emeltchenko 6569f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 657350ee4cfSAndrei Emeltchenko 658350ee4cfSAndrei Emeltchenko if (rp->status) 659350ee4cfSAndrei Emeltchenko return; 660350ee4cfSAndrei Emeltchenko 661350ee4cfSAndrei Emeltchenko hdev->block_mtu = __le16_to_cpu(rp->max_acl_len); 662350ee4cfSAndrei Emeltchenko hdev->block_len = __le16_to_cpu(rp->block_len); 663350ee4cfSAndrei Emeltchenko hdev->num_blocks = __le16_to_cpu(rp->num_blocks); 664350ee4cfSAndrei Emeltchenko 665350ee4cfSAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 666350ee4cfSAndrei Emeltchenko 667350ee4cfSAndrei Emeltchenko BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu, 668350ee4cfSAndrei Emeltchenko hdev->block_cnt, hdev->block_len); 669350ee4cfSAndrei Emeltchenko } 670350ee4cfSAndrei Emeltchenko 671928abaa7SAndrei Emeltchenko static void hci_cc_read_local_amp_info(struct hci_dev *hdev, 672928abaa7SAndrei Emeltchenko struct sk_buff *skb) 673928abaa7SAndrei Emeltchenko { 674928abaa7SAndrei Emeltchenko struct hci_rp_read_local_amp_info *rp = (void *) skb->data; 675928abaa7SAndrei Emeltchenko 6769f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 677928abaa7SAndrei Emeltchenko 678928abaa7SAndrei Emeltchenko if (rp->status) 6798e2a0d92SAndrei Emeltchenko goto a2mp_rsp; 680928abaa7SAndrei Emeltchenko 681928abaa7SAndrei Emeltchenko hdev->amp_status = rp->amp_status; 682928abaa7SAndrei Emeltchenko hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); 683928abaa7SAndrei Emeltchenko hdev->amp_max_bw = __le32_to_cpu(rp->max_bw); 684928abaa7SAndrei Emeltchenko hdev->amp_min_latency = __le32_to_cpu(rp->min_latency); 685928abaa7SAndrei Emeltchenko hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu); 686928abaa7SAndrei Emeltchenko hdev->amp_type = rp->amp_type; 687928abaa7SAndrei Emeltchenko hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap); 688928abaa7SAndrei Emeltchenko hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size); 689928abaa7SAndrei Emeltchenko hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); 690928abaa7SAndrei Emeltchenko hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); 691928abaa7SAndrei Emeltchenko 6928e2a0d92SAndrei Emeltchenko a2mp_rsp: 6938e2a0d92SAndrei Emeltchenko a2mp_send_getinfo_rsp(hdev); 694928abaa7SAndrei Emeltchenko } 695928abaa7SAndrei Emeltchenko 696903e4541SAndrei Emeltchenko static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev, 697903e4541SAndrei Emeltchenko struct sk_buff *skb) 698903e4541SAndrei Emeltchenko { 699903e4541SAndrei Emeltchenko struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data; 700903e4541SAndrei Emeltchenko struct amp_assoc *assoc = &hdev->loc_assoc; 701903e4541SAndrei Emeltchenko size_t rem_len, frag_len; 702903e4541SAndrei Emeltchenko 703903e4541SAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 704903e4541SAndrei Emeltchenko 705903e4541SAndrei Emeltchenko if (rp->status) 706903e4541SAndrei Emeltchenko goto a2mp_rsp; 707903e4541SAndrei Emeltchenko 708903e4541SAndrei Emeltchenko frag_len = skb->len - sizeof(*rp); 709903e4541SAndrei Emeltchenko rem_len = __le16_to_cpu(rp->rem_len); 710903e4541SAndrei Emeltchenko 711903e4541SAndrei Emeltchenko if (rem_len > frag_len) { 7122e430be3SAndrei Emeltchenko BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len); 713903e4541SAndrei Emeltchenko 714903e4541SAndrei Emeltchenko memcpy(assoc->data + assoc->offset, rp->frag, frag_len); 715903e4541SAndrei Emeltchenko assoc->offset += frag_len; 716903e4541SAndrei Emeltchenko 717903e4541SAndrei Emeltchenko /* Read other fragments */ 718903e4541SAndrei Emeltchenko amp_read_loc_assoc_frag(hdev, rp->phy_handle); 719903e4541SAndrei Emeltchenko 720903e4541SAndrei Emeltchenko return; 721903e4541SAndrei Emeltchenko } 722903e4541SAndrei Emeltchenko 723903e4541SAndrei Emeltchenko memcpy(assoc->data + assoc->offset, rp->frag, rem_len); 724903e4541SAndrei Emeltchenko assoc->len = assoc->offset + rem_len; 725903e4541SAndrei Emeltchenko assoc->offset = 0; 726903e4541SAndrei Emeltchenko 727903e4541SAndrei Emeltchenko a2mp_rsp: 728903e4541SAndrei Emeltchenko /* Send A2MP Rsp when all fragments are received */ 729903e4541SAndrei Emeltchenko a2mp_send_getampassoc_rsp(hdev, rp->status); 7309495b2eeSAndrei Emeltchenko a2mp_send_create_phy_link_req(hdev, rp->status); 731903e4541SAndrei Emeltchenko } 732903e4541SAndrei Emeltchenko 733d5859e22SJohan Hedberg static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, 734d5859e22SJohan Hedberg struct sk_buff *skb) 735d5859e22SJohan Hedberg { 73691c4e9b1SMarcel Holtmann struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data; 737d5859e22SJohan Hedberg 7389f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 739d5859e22SJohan Hedberg 74091c4e9b1SMarcel Holtmann if (!rp->status) 74191c4e9b1SMarcel Holtmann hdev->inq_tx_power = rp->tx_power; 742d5859e22SJohan Hedberg } 743d5859e22SJohan Hedberg 744980e1a53SJohan Hedberg static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) 745980e1a53SJohan Hedberg { 746980e1a53SJohan Hedberg struct hci_rp_pin_code_reply *rp = (void *) skb->data; 747980e1a53SJohan Hedberg struct hci_cp_pin_code_reply *cp; 748980e1a53SJohan Hedberg struct hci_conn *conn; 749980e1a53SJohan Hedberg 7509f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 751980e1a53SJohan Hedberg 75256e5cb86SJohan Hedberg hci_dev_lock(hdev); 75356e5cb86SJohan Hedberg 754a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 755744cf19eSJohan Hedberg mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); 756980e1a53SJohan Hedberg 757fa1bd918SMikel Astiz if (rp->status) 75856e5cb86SJohan Hedberg goto unlock; 759980e1a53SJohan Hedberg 760980e1a53SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); 761980e1a53SJohan Hedberg if (!cp) 76256e5cb86SJohan Hedberg goto unlock; 763980e1a53SJohan Hedberg 764980e1a53SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 765980e1a53SJohan Hedberg if (conn) 766980e1a53SJohan Hedberg conn->pin_length = cp->pin_len; 76756e5cb86SJohan Hedberg 76856e5cb86SJohan Hedberg unlock: 76956e5cb86SJohan Hedberg hci_dev_unlock(hdev); 770980e1a53SJohan Hedberg } 771980e1a53SJohan Hedberg 772980e1a53SJohan Hedberg static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) 773980e1a53SJohan Hedberg { 774980e1a53SJohan Hedberg struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data; 775980e1a53SJohan Hedberg 7769f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 777980e1a53SJohan Hedberg 77856e5cb86SJohan Hedberg hci_dev_lock(hdev); 77956e5cb86SJohan Hedberg 780a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 781744cf19eSJohan Hedberg mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr, 782980e1a53SJohan Hedberg rp->status); 78356e5cb86SJohan Hedberg 78456e5cb86SJohan Hedberg hci_dev_unlock(hdev); 785980e1a53SJohan Hedberg } 78656e5cb86SJohan Hedberg 7876ed58ec5SVille Tervo static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, 7886ed58ec5SVille Tervo struct sk_buff *skb) 7896ed58ec5SVille Tervo { 7906ed58ec5SVille Tervo struct hci_rp_le_read_buffer_size *rp = (void *) skb->data; 7916ed58ec5SVille Tervo 7929f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 7936ed58ec5SVille Tervo 7946ed58ec5SVille Tervo if (rp->status) 7956ed58ec5SVille Tervo return; 7966ed58ec5SVille Tervo 7976ed58ec5SVille Tervo hdev->le_mtu = __le16_to_cpu(rp->le_mtu); 7986ed58ec5SVille Tervo hdev->le_pkts = rp->le_max_pkt; 7996ed58ec5SVille Tervo 8006ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 8016ed58ec5SVille Tervo 8026ed58ec5SVille Tervo BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); 8036ed58ec5SVille Tervo } 804980e1a53SJohan Hedberg 80560e77321SJohan Hedberg static void hci_cc_le_read_local_features(struct hci_dev *hdev, 80660e77321SJohan Hedberg struct sk_buff *skb) 80760e77321SJohan Hedberg { 80860e77321SJohan Hedberg struct hci_rp_le_read_local_features *rp = (void *) skb->data; 80960e77321SJohan Hedberg 81060e77321SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 81160e77321SJohan Hedberg 81260e77321SJohan Hedberg if (!rp->status) 81360e77321SJohan Hedberg memcpy(hdev->le_features, rp->features, 8); 81460e77321SJohan Hedberg } 81560e77321SJohan Hedberg 8168fa19098SJohan Hedberg static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, 8178fa19098SJohan Hedberg struct sk_buff *skb) 8188fa19098SJohan Hedberg { 8198fa19098SJohan Hedberg struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data; 8208fa19098SJohan Hedberg 8218fa19098SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 8228fa19098SJohan Hedberg 82304b4edcbSJohan Hedberg if (!rp->status) 8248fa19098SJohan Hedberg hdev->adv_tx_power = rp->tx_power; 8258fa19098SJohan Hedberg } 8268fa19098SJohan Hedberg 827a5c29683SJohan Hedberg static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) 828a5c29683SJohan Hedberg { 829a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 830a5c29683SJohan Hedberg 8319f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 832a5c29683SJohan Hedberg 83356e5cb86SJohan Hedberg hci_dev_lock(hdev); 83456e5cb86SJohan Hedberg 835a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 83604124681SGustavo F. Padovan mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0, 83704124681SGustavo F. Padovan rp->status); 83856e5cb86SJohan Hedberg 83956e5cb86SJohan Hedberg hci_dev_unlock(hdev); 840a5c29683SJohan Hedberg } 841a5c29683SJohan Hedberg 842a5c29683SJohan Hedberg static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, 843a5c29683SJohan Hedberg struct sk_buff *skb) 844a5c29683SJohan Hedberg { 845a5c29683SJohan Hedberg struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 846a5c29683SJohan Hedberg 8479f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 848a5c29683SJohan Hedberg 84956e5cb86SJohan Hedberg hci_dev_lock(hdev); 85056e5cb86SJohan Hedberg 851a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 852744cf19eSJohan Hedberg mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr, 85304124681SGustavo F. Padovan ACL_LINK, 0, rp->status); 85456e5cb86SJohan Hedberg 85556e5cb86SJohan Hedberg hci_dev_unlock(hdev); 856a5c29683SJohan Hedberg } 857a5c29683SJohan Hedberg 8581143d458SBrian Gix static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb) 8591143d458SBrian Gix { 8601143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 8611143d458SBrian Gix 8629f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 8631143d458SBrian Gix 8641143d458SBrian Gix hci_dev_lock(hdev); 8651143d458SBrian Gix 866a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 867272d90dfSJohan Hedberg mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 868272d90dfSJohan Hedberg 0, rp->status); 8691143d458SBrian Gix 8701143d458SBrian Gix hci_dev_unlock(hdev); 8711143d458SBrian Gix } 8721143d458SBrian Gix 8731143d458SBrian Gix static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, 8741143d458SBrian Gix struct sk_buff *skb) 8751143d458SBrian Gix { 8761143d458SBrian Gix struct hci_rp_user_confirm_reply *rp = (void *) skb->data; 8771143d458SBrian Gix 8789f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 8791143d458SBrian Gix 8801143d458SBrian Gix hci_dev_lock(hdev); 8811143d458SBrian Gix 882a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 8831143d458SBrian Gix mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr, 88404124681SGustavo F. Padovan ACL_LINK, 0, rp->status); 8851143d458SBrian Gix 8861143d458SBrian Gix hci_dev_unlock(hdev); 8871143d458SBrian Gix } 8881143d458SBrian Gix 889c35938b2SSzymon Janc static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, 890c35938b2SSzymon Janc struct sk_buff *skb) 891c35938b2SSzymon Janc { 892c35938b2SSzymon Janc struct hci_rp_read_local_oob_data *rp = (void *) skb->data; 893c35938b2SSzymon Janc 8949f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 895c35938b2SSzymon Janc 89656e5cb86SJohan Hedberg hci_dev_lock(hdev); 897744cf19eSJohan Hedberg mgmt_read_local_oob_data_reply_complete(hdev, rp->hash, 898c35938b2SSzymon Janc rp->randomizer, rp->status); 89956e5cb86SJohan Hedberg hci_dev_unlock(hdev); 900c35938b2SSzymon Janc } 901c35938b2SSzymon Janc 902c1d5dc4aSJohan Hedberg static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb) 903c1d5dc4aSJohan Hedberg { 904c1d5dc4aSJohan Hedberg __u8 *sent, status = *((__u8 *) skb->data); 905c1d5dc4aSJohan Hedberg 906c1d5dc4aSJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, status); 907c1d5dc4aSJohan Hedberg 908c1d5dc4aSJohan Hedberg sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE); 909c1d5dc4aSJohan Hedberg if (!sent) 910c1d5dc4aSJohan Hedberg return; 911c1d5dc4aSJohan Hedberg 912c1d5dc4aSJohan Hedberg hci_dev_lock(hdev); 913c1d5dc4aSJohan Hedberg 914c1d5dc4aSJohan Hedberg if (!status) { 915c1d5dc4aSJohan Hedberg if (*sent) 916c1d5dc4aSJohan Hedberg set_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags); 917c1d5dc4aSJohan Hedberg else 918c1d5dc4aSJohan Hedberg clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags); 919c1d5dc4aSJohan Hedberg } 920c1d5dc4aSJohan Hedberg 92104b4edcbSJohan Hedberg if (!test_bit(HCI_INIT, &hdev->flags)) { 92204b4edcbSJohan Hedberg struct hci_request req; 923c1d5dc4aSJohan Hedberg 92404b4edcbSJohan Hedberg hci_req_init(&req, hdev); 92504b4edcbSJohan Hedberg hci_update_ad(&req); 92604b4edcbSJohan Hedberg hci_req_run(&req, NULL); 92704b4edcbSJohan Hedberg } 92804b4edcbSJohan Hedberg 92904b4edcbSJohan Hedberg hci_dev_unlock(hdev); 930c1d5dc4aSJohan Hedberg } 931c1d5dc4aSJohan Hedberg 932eb9d91f5SAndre Guedes static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, 933eb9d91f5SAndre Guedes struct sk_buff *skb) 934eb9d91f5SAndre Guedes { 935eb9d91f5SAndre Guedes struct hci_cp_le_set_scan_enable *cp; 936eb9d91f5SAndre Guedes __u8 status = *((__u8 *) skb->data); 937eb9d91f5SAndre Guedes 9389f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 939eb9d91f5SAndre Guedes 940eb9d91f5SAndre Guedes cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE); 941eb9d91f5SAndre Guedes if (!cp) 942eb9d91f5SAndre Guedes return; 943eb9d91f5SAndre Guedes 944fef5234aSAndre Guedes if (status) 9457ba8b4beSAndre Guedes return; 9467ba8b4beSAndre Guedes 9473fd319b8SAndre Guedes switch (cp->enable) { 9483fd319b8SAndre Guedes case LE_SCAN_ENABLE: 949d23264a8SAndre Guedes set_bit(HCI_LE_SCAN, &hdev->dev_flags); 95068a8aea4SAndrei Emeltchenko break; 95168a8aea4SAndrei Emeltchenko 95276a388beSAndre Guedes case LE_SCAN_DISABLE: 953d23264a8SAndre Guedes clear_bit(HCI_LE_SCAN, &hdev->dev_flags); 95468a8aea4SAndrei Emeltchenko break; 95568a8aea4SAndrei Emeltchenko 95668a8aea4SAndrei Emeltchenko default: 95768a8aea4SAndrei Emeltchenko BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable); 95868a8aea4SAndrei Emeltchenko break; 95935815085SAndre Guedes } 960eb9d91f5SAndre Guedes } 961eb9d91f5SAndre Guedes 962cf1d081fSJohan Hedberg static void hci_cc_le_read_white_list_size(struct hci_dev *hdev, 963cf1d081fSJohan Hedberg struct sk_buff *skb) 964cf1d081fSJohan Hedberg { 965cf1d081fSJohan Hedberg struct hci_rp_le_read_white_list_size *rp = (void *) skb->data; 966cf1d081fSJohan Hedberg 967cf1d081fSJohan Hedberg BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size); 968cf1d081fSJohan Hedberg 969cf1d081fSJohan Hedberg if (!rp->status) 970cf1d081fSJohan Hedberg hdev->le_white_list_size = rp->size; 971cf1d081fSJohan Hedberg } 972cf1d081fSJohan Hedberg 9739b008c04SJohan Hedberg static void hci_cc_le_read_supported_states(struct hci_dev *hdev, 9749b008c04SJohan Hedberg struct sk_buff *skb) 9759b008c04SJohan Hedberg { 9769b008c04SJohan Hedberg struct hci_rp_le_read_supported_states *rp = (void *) skb->data; 9779b008c04SJohan Hedberg 9789b008c04SJohan Hedberg BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); 9799b008c04SJohan Hedberg 9809b008c04SJohan Hedberg if (!rp->status) 9819b008c04SJohan Hedberg memcpy(hdev->le_states, rp->le_states, 8); 9829b008c04SJohan Hedberg } 9839b008c04SJohan Hedberg 9846039aa73SGustavo Padovan static void hci_cc_write_le_host_supported(struct hci_dev *hdev, 985f9b49306SAndre Guedes struct sk_buff *skb) 986f9b49306SAndre Guedes { 98706199cf8SJohan Hedberg struct hci_cp_write_le_host_supported *sent; 988f9b49306SAndre Guedes __u8 status = *((__u8 *) skb->data); 989f9b49306SAndre Guedes 9909f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 991f9b49306SAndre Guedes 99206199cf8SJohan Hedberg sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED); 9938f984dfaSJohan Hedberg if (!sent) 994f9b49306SAndre Guedes return; 995f9b49306SAndre Guedes 9968f984dfaSJohan Hedberg if (!status) { 9978f984dfaSJohan Hedberg if (sent->le) 998cad718edSJohan Hedberg hdev->features[1][0] |= LMP_HOST_LE; 9998f984dfaSJohan Hedberg else 1000cad718edSJohan Hedberg hdev->features[1][0] &= ~LMP_HOST_LE; 100153b2caabSJohan Hedberg 100253b2caabSJohan Hedberg if (sent->simul) 1003cad718edSJohan Hedberg hdev->features[1][0] |= LMP_HOST_LE_BREDR; 100453b2caabSJohan Hedberg else 1005cad718edSJohan Hedberg hdev->features[1][0] &= ~LMP_HOST_LE_BREDR; 10068f984dfaSJohan Hedberg } 10078f984dfaSJohan Hedberg 10088f984dfaSJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags) && 10098f984dfaSJohan Hedberg !test_bit(HCI_INIT, &hdev->flags)) 10108f984dfaSJohan Hedberg mgmt_le_enable_complete(hdev, sent->le, status); 1011f9b49306SAndre Guedes } 1012f9b49306SAndre Guedes 101393c284eeSAndrei Emeltchenko static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev, 101493c284eeSAndrei Emeltchenko struct sk_buff *skb) 101593c284eeSAndrei Emeltchenko { 101693c284eeSAndrei Emeltchenko struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data; 101793c284eeSAndrei Emeltchenko 101893c284eeSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x", 101993c284eeSAndrei Emeltchenko hdev->name, rp->status, rp->phy_handle); 102093c284eeSAndrei Emeltchenko 102193c284eeSAndrei Emeltchenko if (rp->status) 102293c284eeSAndrei Emeltchenko return; 102393c284eeSAndrei Emeltchenko 102493c284eeSAndrei Emeltchenko amp_write_rem_assoc_continue(hdev, rp->phy_handle); 102593c284eeSAndrei Emeltchenko } 102693c284eeSAndrei Emeltchenko 10276039aa73SGustavo Padovan static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 1028a9de9248SMarcel Holtmann { 10299f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1030a9de9248SMarcel Holtmann 1031a9de9248SMarcel Holtmann if (status) { 1032a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 1033314b2381SJohan Hedberg return; 1034314b2381SJohan Hedberg } 1035314b2381SJohan Hedberg 103689352e7dSAndre Guedes set_bit(HCI_INQUIRY, &hdev->flags); 1037a9de9248SMarcel Holtmann } 1038a9de9248SMarcel Holtmann 10396039aa73SGustavo Padovan static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 10401da177e4SLinus Torvalds { 1041a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 10421da177e4SLinus Torvalds struct hci_conn *conn; 10431da177e4SLinus Torvalds 10449f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1045a9de9248SMarcel Holtmann 1046a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 10471da177e4SLinus Torvalds if (!cp) 10481da177e4SLinus Torvalds return; 10491da177e4SLinus Torvalds 10501da177e4SLinus Torvalds hci_dev_lock(hdev); 10511da177e4SLinus Torvalds 10521da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 10531da177e4SLinus Torvalds 10546ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn); 10551da177e4SLinus Torvalds 10561da177e4SLinus Torvalds if (status) { 10571da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 10584c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 10591da177e4SLinus Torvalds conn->state = BT_CLOSED; 10601da177e4SLinus Torvalds hci_proto_connect_cfm(conn, status); 10611da177e4SLinus Torvalds hci_conn_del(conn); 10624c67bc74SMarcel Holtmann } else 10634c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 10641da177e4SLinus Torvalds } 10651da177e4SLinus Torvalds } else { 10661da177e4SLinus Torvalds if (!conn) { 10671da177e4SLinus Torvalds conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); 10681da177e4SLinus Torvalds if (conn) { 1069a0c808b3SJohan Hedberg conn->out = true; 10701da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 10711da177e4SLinus Torvalds } else 1072893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 10731da177e4SLinus Torvalds } 10741da177e4SLinus Torvalds } 10751da177e4SLinus Torvalds 10761da177e4SLinus Torvalds hci_dev_unlock(hdev); 10771da177e4SLinus Torvalds } 10781da177e4SLinus Torvalds 1079a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 10801da177e4SLinus Torvalds { 1081a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 10821da177e4SLinus Torvalds struct hci_conn *acl, *sco; 10831da177e4SLinus Torvalds __u16 handle; 10841da177e4SLinus Torvalds 10859f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1086b6a0dc82SMarcel Holtmann 1087a9de9248SMarcel Holtmann if (!status) 1088a9de9248SMarcel Holtmann return; 1089a9de9248SMarcel Holtmann 1090a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 10911da177e4SLinus Torvalds if (!cp) 1092a9de9248SMarcel Holtmann return; 10931da177e4SLinus Torvalds 10941da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 10951da177e4SLinus Torvalds 10969f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, handle); 10971da177e4SLinus Torvalds 10981da177e4SLinus Torvalds hci_dev_lock(hdev); 10991da177e4SLinus Torvalds 11001da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 11015a08ecceSAndrei Emeltchenko if (acl) { 11025a08ecceSAndrei Emeltchenko sco = acl->link; 11035a08ecceSAndrei Emeltchenko if (sco) { 11041da177e4SLinus Torvalds sco->state = BT_CLOSED; 11051da177e4SLinus Torvalds 11061da177e4SLinus Torvalds hci_proto_connect_cfm(sco, status); 11071da177e4SLinus Torvalds hci_conn_del(sco); 11081da177e4SLinus Torvalds } 11095a08ecceSAndrei Emeltchenko } 11101da177e4SLinus Torvalds 11111da177e4SLinus Torvalds hci_dev_unlock(hdev); 11121da177e4SLinus Torvalds } 11131da177e4SLinus Torvalds 1114f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 1115f8558555SMarcel Holtmann { 1116f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 1117f8558555SMarcel Holtmann struct hci_conn *conn; 1118f8558555SMarcel Holtmann 11199f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1120f8558555SMarcel Holtmann 1121f8558555SMarcel Holtmann if (!status) 1122f8558555SMarcel Holtmann return; 1123f8558555SMarcel Holtmann 1124f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 1125f8558555SMarcel Holtmann if (!cp) 1126f8558555SMarcel Holtmann return; 1127f8558555SMarcel Holtmann 1128f8558555SMarcel Holtmann hci_dev_lock(hdev); 1129f8558555SMarcel Holtmann 1130f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1131f8558555SMarcel Holtmann if (conn) { 1132f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1133f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 113476a68ba0SDavid Herrmann hci_conn_drop(conn); 1135f8558555SMarcel Holtmann } 1136f8558555SMarcel Holtmann } 1137f8558555SMarcel Holtmann 1138f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1139f8558555SMarcel Holtmann } 1140f8558555SMarcel Holtmann 1141f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 1142f8558555SMarcel Holtmann { 1143f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 1144f8558555SMarcel Holtmann struct hci_conn *conn; 1145f8558555SMarcel Holtmann 11469f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1147f8558555SMarcel Holtmann 1148f8558555SMarcel Holtmann if (!status) 1149f8558555SMarcel Holtmann return; 1150f8558555SMarcel Holtmann 1151f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 1152f8558555SMarcel Holtmann if (!cp) 1153f8558555SMarcel Holtmann return; 1154f8558555SMarcel Holtmann 1155f8558555SMarcel Holtmann hci_dev_lock(hdev); 1156f8558555SMarcel Holtmann 1157f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1158f8558555SMarcel Holtmann if (conn) { 1159f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1160f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 116176a68ba0SDavid Herrmann hci_conn_drop(conn); 1162f8558555SMarcel Holtmann } 1163f8558555SMarcel Holtmann } 1164f8558555SMarcel Holtmann 1165f8558555SMarcel Holtmann hci_dev_unlock(hdev); 1166f8558555SMarcel Holtmann } 1167f8558555SMarcel Holtmann 1168127178d2SJohan Hedberg static int hci_outgoing_auth_needed(struct hci_dev *hdev, 1169392599b9SJohan Hedberg struct hci_conn *conn) 1170392599b9SJohan Hedberg { 1171392599b9SJohan Hedberg if (conn->state != BT_CONFIG || !conn->out) 1172392599b9SJohan Hedberg return 0; 1173392599b9SJohan Hedberg 1174765c2a96SJohan Hedberg if (conn->pending_sec_level == BT_SECURITY_SDP) 1175392599b9SJohan Hedberg return 0; 1176392599b9SJohan Hedberg 1177392599b9SJohan Hedberg /* Only request authentication for SSP connections or non-SSP 1178e9bf2bf0SVinicius Costa Gomes * devices with sec_level HIGH or if MITM protection is requested */ 1179807deac2SGustavo Padovan if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) && 1180807deac2SGustavo Padovan conn->pending_sec_level != BT_SECURITY_HIGH) 1181392599b9SJohan Hedberg return 0; 1182392599b9SJohan Hedberg 1183392599b9SJohan Hedberg return 1; 1184392599b9SJohan Hedberg } 1185392599b9SJohan Hedberg 11866039aa73SGustavo Padovan static int hci_resolve_name(struct hci_dev *hdev, 118700abfe44SGustavo F. Padovan struct inquiry_entry *e) 118830dc78e1SJohan Hedberg { 118930dc78e1SJohan Hedberg struct hci_cp_remote_name_req cp; 119030dc78e1SJohan Hedberg 119130dc78e1SJohan Hedberg memset(&cp, 0, sizeof(cp)); 119230dc78e1SJohan Hedberg 119330dc78e1SJohan Hedberg bacpy(&cp.bdaddr, &e->data.bdaddr); 119430dc78e1SJohan Hedberg cp.pscan_rep_mode = e->data.pscan_rep_mode; 119530dc78e1SJohan Hedberg cp.pscan_mode = e->data.pscan_mode; 119630dc78e1SJohan Hedberg cp.clock_offset = e->data.clock_offset; 119730dc78e1SJohan Hedberg 119830dc78e1SJohan Hedberg return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 119930dc78e1SJohan Hedberg } 120030dc78e1SJohan Hedberg 1201b644ba33SJohan Hedberg static bool hci_resolve_next_name(struct hci_dev *hdev) 120230dc78e1SJohan Hedberg { 120330dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 120430dc78e1SJohan Hedberg struct inquiry_entry *e; 120530dc78e1SJohan Hedberg 1206b644ba33SJohan Hedberg if (list_empty(&discov->resolve)) 1207b644ba33SJohan Hedberg return false; 1208b644ba33SJohan Hedberg 1209b644ba33SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 1210c810089cSRam Malovany if (!e) 1211c810089cSRam Malovany return false; 1212c810089cSRam Malovany 1213b644ba33SJohan Hedberg if (hci_resolve_name(hdev, e) == 0) { 1214b644ba33SJohan Hedberg e->name_state = NAME_PENDING; 1215b644ba33SJohan Hedberg return true; 1216b644ba33SJohan Hedberg } 1217b644ba33SJohan Hedberg 1218b644ba33SJohan Hedberg return false; 1219b644ba33SJohan Hedberg } 1220b644ba33SJohan Hedberg 1221b644ba33SJohan Hedberg static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn, 1222b644ba33SJohan Hedberg bdaddr_t *bdaddr, u8 *name, u8 name_len) 1223b644ba33SJohan Hedberg { 1224b644ba33SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 1225b644ba33SJohan Hedberg struct inquiry_entry *e; 1226b644ba33SJohan Hedberg 1227b644ba33SJohan Hedberg if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 122804124681SGustavo F. Padovan mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name, 122904124681SGustavo F. Padovan name_len, conn->dev_class); 1230b644ba33SJohan Hedberg 1231b644ba33SJohan Hedberg if (discov->state == DISCOVERY_STOPPED) 1232b644ba33SJohan Hedberg return; 1233b644ba33SJohan Hedberg 123430dc78e1SJohan Hedberg if (discov->state == DISCOVERY_STOPPING) 123530dc78e1SJohan Hedberg goto discov_complete; 123630dc78e1SJohan Hedberg 123730dc78e1SJohan Hedberg if (discov->state != DISCOVERY_RESOLVING) 123830dc78e1SJohan Hedberg return; 123930dc78e1SJohan Hedberg 124030dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING); 12417cc8380eSRam Malovany /* If the device was not found in a list of found devices names of which 12427cc8380eSRam Malovany * are pending. there is no need to continue resolving a next name as it 12437cc8380eSRam Malovany * will be done upon receiving another Remote Name Request Complete 12447cc8380eSRam Malovany * Event */ 12457cc8380eSRam Malovany if (!e) 12467cc8380eSRam Malovany return; 12477cc8380eSRam Malovany 124830dc78e1SJohan Hedberg list_del(&e->list); 12497cc8380eSRam Malovany if (name) { 12507cc8380eSRam Malovany e->name_state = NAME_KNOWN; 1251b644ba33SJohan Hedberg mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, 1252b644ba33SJohan Hedberg e->data.rssi, name, name_len); 1253c3e7c0d9SRam Malovany } else { 1254c3e7c0d9SRam Malovany e->name_state = NAME_NOT_KNOWN; 125530dc78e1SJohan Hedberg } 125630dc78e1SJohan Hedberg 1257b644ba33SJohan Hedberg if (hci_resolve_next_name(hdev)) 125830dc78e1SJohan Hedberg return; 125930dc78e1SJohan Hedberg 126030dc78e1SJohan Hedberg discov_complete: 126130dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 126230dc78e1SJohan Hedberg } 126330dc78e1SJohan Hedberg 1264a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 12651da177e4SLinus Torvalds { 1266127178d2SJohan Hedberg struct hci_cp_remote_name_req *cp; 1267127178d2SJohan Hedberg struct hci_conn *conn; 1268127178d2SJohan Hedberg 12699f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1270127178d2SJohan Hedberg 1271127178d2SJohan Hedberg /* If successful wait for the name req complete event before 1272127178d2SJohan Hedberg * checking for the need to do authentication */ 1273127178d2SJohan Hedberg if (!status) 1274127178d2SJohan Hedberg return; 1275127178d2SJohan Hedberg 1276127178d2SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); 1277127178d2SJohan Hedberg if (!cp) 1278127178d2SJohan Hedberg return; 1279127178d2SJohan Hedberg 1280127178d2SJohan Hedberg hci_dev_lock(hdev); 1281127178d2SJohan Hedberg 1282127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 1283b644ba33SJohan Hedberg 1284b644ba33SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 1285b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0); 1286b644ba33SJohan Hedberg 128779c6c70cSJohan Hedberg if (!conn) 128879c6c70cSJohan Hedberg goto unlock; 128979c6c70cSJohan Hedberg 129079c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 129179c6c70cSJohan Hedberg goto unlock; 129279c6c70cSJohan Hedberg 129351a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 1294127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1295127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1296127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1297127178d2SJohan Hedberg } 1298127178d2SJohan Hedberg 129979c6c70cSJohan Hedberg unlock: 1300127178d2SJohan Hedberg hci_dev_unlock(hdev); 1301a9de9248SMarcel Holtmann } 13021da177e4SLinus Torvalds 1303769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 1304769be974SMarcel Holtmann { 1305769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 1306769be974SMarcel Holtmann struct hci_conn *conn; 1307769be974SMarcel Holtmann 13089f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1309769be974SMarcel Holtmann 1310769be974SMarcel Holtmann if (!status) 1311769be974SMarcel Holtmann return; 1312769be974SMarcel Holtmann 1313769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 1314769be974SMarcel Holtmann if (!cp) 1315769be974SMarcel Holtmann return; 1316769be974SMarcel Holtmann 1317769be974SMarcel Holtmann hci_dev_lock(hdev); 1318769be974SMarcel Holtmann 1319769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1320769be974SMarcel Holtmann if (conn) { 1321769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1322769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 132376a68ba0SDavid Herrmann hci_conn_drop(conn); 1324769be974SMarcel Holtmann } 1325769be974SMarcel Holtmann } 1326769be974SMarcel Holtmann 1327769be974SMarcel Holtmann hci_dev_unlock(hdev); 1328769be974SMarcel Holtmann } 1329769be974SMarcel Holtmann 1330769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 1331769be974SMarcel Holtmann { 1332769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features *cp; 1333769be974SMarcel Holtmann struct hci_conn *conn; 1334769be974SMarcel Holtmann 13359f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1336769be974SMarcel Holtmann 1337769be974SMarcel Holtmann if (!status) 1338769be974SMarcel Holtmann return; 1339769be974SMarcel Holtmann 1340769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 1341769be974SMarcel Holtmann if (!cp) 1342769be974SMarcel Holtmann return; 1343769be974SMarcel Holtmann 1344769be974SMarcel Holtmann hci_dev_lock(hdev); 1345769be974SMarcel Holtmann 1346769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1347769be974SMarcel Holtmann if (conn) { 1348769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1349769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 135076a68ba0SDavid Herrmann hci_conn_drop(conn); 1351769be974SMarcel Holtmann } 1352769be974SMarcel Holtmann } 1353769be974SMarcel Holtmann 1354769be974SMarcel Holtmann hci_dev_unlock(hdev); 1355769be974SMarcel Holtmann } 1356769be974SMarcel Holtmann 1357a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 1358a9de9248SMarcel Holtmann { 1359b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 1360b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 1361b6a0dc82SMarcel Holtmann __u16 handle; 1362b6a0dc82SMarcel Holtmann 13639f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1364b6a0dc82SMarcel Holtmann 1365b6a0dc82SMarcel Holtmann if (!status) 1366b6a0dc82SMarcel Holtmann return; 1367b6a0dc82SMarcel Holtmann 1368b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 1369b6a0dc82SMarcel Holtmann if (!cp) 1370b6a0dc82SMarcel Holtmann return; 1371b6a0dc82SMarcel Holtmann 1372b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 1373b6a0dc82SMarcel Holtmann 13749f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, handle); 1375b6a0dc82SMarcel Holtmann 1376b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 1377b6a0dc82SMarcel Holtmann 1378b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 13795a08ecceSAndrei Emeltchenko if (acl) { 13805a08ecceSAndrei Emeltchenko sco = acl->link; 13815a08ecceSAndrei Emeltchenko if (sco) { 1382b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 1383b6a0dc82SMarcel Holtmann 1384b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(sco, status); 1385b6a0dc82SMarcel Holtmann hci_conn_del(sco); 1386b6a0dc82SMarcel Holtmann } 13875a08ecceSAndrei Emeltchenko } 1388b6a0dc82SMarcel Holtmann 1389b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 1390a9de9248SMarcel Holtmann } 1391a9de9248SMarcel Holtmann 1392a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 1393a9de9248SMarcel Holtmann { 1394a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 139504837f64SMarcel Holtmann struct hci_conn *conn; 139604837f64SMarcel Holtmann 13979f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1398a9de9248SMarcel Holtmann 1399a9de9248SMarcel Holtmann if (!status) 1400a9de9248SMarcel Holtmann return; 1401a9de9248SMarcel Holtmann 1402a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 140304837f64SMarcel Holtmann if (!cp) 1404a9de9248SMarcel Holtmann return; 140504837f64SMarcel Holtmann 140604837f64SMarcel Holtmann hci_dev_lock(hdev); 140704837f64SMarcel Holtmann 140804837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1409e73439d8SMarcel Holtmann if (conn) { 141051a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 141104837f64SMarcel Holtmann 141251a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1413e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1414e73439d8SMarcel Holtmann } 1415e73439d8SMarcel Holtmann 141604837f64SMarcel Holtmann hci_dev_unlock(hdev); 141704837f64SMarcel Holtmann } 141804837f64SMarcel Holtmann 1419a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 1420a9de9248SMarcel Holtmann { 1421a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 142204837f64SMarcel Holtmann struct hci_conn *conn; 142304837f64SMarcel Holtmann 14249f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1425a9de9248SMarcel Holtmann 1426a9de9248SMarcel Holtmann if (!status) 1427a9de9248SMarcel Holtmann return; 1428a9de9248SMarcel Holtmann 1429a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 143004837f64SMarcel Holtmann if (!cp) 1431a9de9248SMarcel Holtmann return; 143204837f64SMarcel Holtmann 143304837f64SMarcel Holtmann hci_dev_lock(hdev); 143404837f64SMarcel Holtmann 143504837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 1436e73439d8SMarcel Holtmann if (conn) { 143751a8efd7SJohan Hedberg clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags); 143804837f64SMarcel Holtmann 143951a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 1440e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 1441e73439d8SMarcel Holtmann } 1442e73439d8SMarcel Holtmann 144304837f64SMarcel Holtmann hci_dev_unlock(hdev); 144404837f64SMarcel Holtmann } 144504837f64SMarcel Holtmann 144688c3df13SJohan Hedberg static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) 144788c3df13SJohan Hedberg { 144888c3df13SJohan Hedberg struct hci_cp_disconnect *cp; 144988c3df13SJohan Hedberg struct hci_conn *conn; 145088c3df13SJohan Hedberg 145188c3df13SJohan Hedberg if (!status) 145288c3df13SJohan Hedberg return; 145388c3df13SJohan Hedberg 145488c3df13SJohan Hedberg cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT); 145588c3df13SJohan Hedberg if (!cp) 145688c3df13SJohan Hedberg return; 145788c3df13SJohan Hedberg 145888c3df13SJohan Hedberg hci_dev_lock(hdev); 145988c3df13SJohan Hedberg 146088c3df13SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 146188c3df13SJohan Hedberg if (conn) 146288c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 146388c3df13SJohan Hedberg conn->dst_type, status); 146488c3df13SJohan Hedberg 146588c3df13SJohan Hedberg hci_dev_unlock(hdev); 146688c3df13SJohan Hedberg } 146788c3df13SJohan Hedberg 1468fcd89c09SVille Tervo static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) 1469fcd89c09SVille Tervo { 1470fcd89c09SVille Tervo struct hci_conn *conn; 1471fcd89c09SVille Tervo 14729f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 1473fcd89c09SVille Tervo 1474f00a06acSAndre Guedes if (status) { 1475fcd89c09SVille Tervo hci_dev_lock(hdev); 1476fcd89c09SVille Tervo 14770c95ab78SAndre Guedes conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); 1478f00a06acSAndre Guedes if (!conn) { 1479f00a06acSAndre Guedes hci_dev_unlock(hdev); 1480f00a06acSAndre Guedes return; 1481f00a06acSAndre Guedes } 1482fcd89c09SVille Tervo 14836ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn); 1484fcd89c09SVille Tervo 1485fcd89c09SVille Tervo conn->state = BT_CLOSED; 14860c95ab78SAndre Guedes mgmt_connect_failed(hdev, &conn->dst, conn->type, 1487328c9248SHemant Gupta conn->dst_type, status); 1488fcd89c09SVille Tervo hci_proto_connect_cfm(conn, status); 1489fcd89c09SVille Tervo hci_conn_del(conn); 1490fcd89c09SVille Tervo 1491fcd89c09SVille Tervo hci_dev_unlock(hdev); 1492fcd89c09SVille Tervo } 1493f00a06acSAndre Guedes } 1494fcd89c09SVille Tervo 1495a02226d6SAndrei Emeltchenko static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status) 1496a02226d6SAndrei Emeltchenko { 149793c284eeSAndrei Emeltchenko struct hci_cp_create_phy_link *cp; 149893c284eeSAndrei Emeltchenko 1499a02226d6SAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 150093c284eeSAndrei Emeltchenko 150193c284eeSAndrei Emeltchenko cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK); 150293c284eeSAndrei Emeltchenko if (!cp) 150393c284eeSAndrei Emeltchenko return; 150493c284eeSAndrei Emeltchenko 1505e58917b9SAndrei Emeltchenko hci_dev_lock(hdev); 1506e58917b9SAndrei Emeltchenko 1507e58917b9SAndrei Emeltchenko if (status) { 1508e58917b9SAndrei Emeltchenko struct hci_conn *hcon; 1509e58917b9SAndrei Emeltchenko 1510e58917b9SAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle); 1511e58917b9SAndrei Emeltchenko if (hcon) 1512e58917b9SAndrei Emeltchenko hci_conn_del(hcon); 1513e58917b9SAndrei Emeltchenko } else { 151493c284eeSAndrei Emeltchenko amp_write_remote_assoc(hdev, cp->phy_handle); 1515a02226d6SAndrei Emeltchenko } 1516a02226d6SAndrei Emeltchenko 1517e58917b9SAndrei Emeltchenko hci_dev_unlock(hdev); 1518e58917b9SAndrei Emeltchenko } 1519e58917b9SAndrei Emeltchenko 15200b26ab9dSAndrei Emeltchenko static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status) 15210b26ab9dSAndrei Emeltchenko { 15220b26ab9dSAndrei Emeltchenko struct hci_cp_accept_phy_link *cp; 15230b26ab9dSAndrei Emeltchenko 15240b26ab9dSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 15250b26ab9dSAndrei Emeltchenko 15260b26ab9dSAndrei Emeltchenko if (status) 15270b26ab9dSAndrei Emeltchenko return; 15280b26ab9dSAndrei Emeltchenko 15290b26ab9dSAndrei Emeltchenko cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK); 15300b26ab9dSAndrei Emeltchenko if (!cp) 15310b26ab9dSAndrei Emeltchenko return; 15320b26ab9dSAndrei Emeltchenko 15330b26ab9dSAndrei Emeltchenko amp_write_remote_assoc(hdev, cp->phy_handle); 15340b26ab9dSAndrei Emeltchenko } 15350b26ab9dSAndrei Emeltchenko 15366039aa73SGustavo Padovan static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 15371da177e4SLinus Torvalds { 15381da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 153930dc78e1SJohan Hedberg struct discovery_state *discov = &hdev->discovery; 154030dc78e1SJohan Hedberg struct inquiry_entry *e; 15411da177e4SLinus Torvalds 15429f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, status); 15431da177e4SLinus Torvalds 1544a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 154589352e7dSAndre Guedes 154689352e7dSAndre Guedes if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) 154789352e7dSAndre Guedes return; 154889352e7dSAndre Guedes 15493e13fa1eSAndre Guedes smp_mb__after_clear_bit(); /* wake_up_bit advises about this barrier */ 15503e13fa1eSAndre Guedes wake_up_bit(&hdev->flags, HCI_INQUIRY); 15513e13fa1eSAndre Guedes 1552a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 155330dc78e1SJohan Hedberg return; 155430dc78e1SJohan Hedberg 155556e5cb86SJohan Hedberg hci_dev_lock(hdev); 155630dc78e1SJohan Hedberg 1557343f935bSAndre Guedes if (discov->state != DISCOVERY_FINDING) 155830dc78e1SJohan Hedberg goto unlock; 155930dc78e1SJohan Hedberg 156030dc78e1SJohan Hedberg if (list_empty(&discov->resolve)) { 1561ff9ef578SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 156230dc78e1SJohan Hedberg goto unlock; 156330dc78e1SJohan Hedberg } 156430dc78e1SJohan Hedberg 156530dc78e1SJohan Hedberg e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); 156630dc78e1SJohan Hedberg if (e && hci_resolve_name(hdev, e) == 0) { 156730dc78e1SJohan Hedberg e->name_state = NAME_PENDING; 156830dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_RESOLVING); 156930dc78e1SJohan Hedberg } else { 157030dc78e1SJohan Hedberg hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 157130dc78e1SJohan Hedberg } 157230dc78e1SJohan Hedberg 157330dc78e1SJohan Hedberg unlock: 157456e5cb86SJohan Hedberg hci_dev_unlock(hdev); 15751da177e4SLinus Torvalds } 15761da177e4SLinus Torvalds 15776039aa73SGustavo Padovan static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 15781da177e4SLinus Torvalds { 157945bb4bf0SMarcel Holtmann struct inquiry_data data; 1580a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 15811da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 15821da177e4SLinus Torvalds 15831da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 15841da177e4SLinus Torvalds 158545bb4bf0SMarcel Holtmann if (!num_rsp) 158645bb4bf0SMarcel Holtmann return; 158745bb4bf0SMarcel Holtmann 15881519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 15891519cc17SAndre Guedes return; 15901519cc17SAndre Guedes 15911da177e4SLinus Torvalds hci_dev_lock(hdev); 159245bb4bf0SMarcel Holtmann 1593e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 1594388fc8faSJohan Hedberg bool name_known, ssp; 15953175405bSJohan Hedberg 15961da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 15971da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 15981da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 15991da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 16001da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 16011da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 16021da177e4SLinus Torvalds data.rssi = 0x00; 160341a96212SMarcel Holtmann data.ssp_mode = 0x00; 16043175405bSJohan Hedberg 1605388fc8faSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp); 160648264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 160704124681SGustavo F. Padovan info->dev_class, 0, !name_known, ssp, NULL, 160804124681SGustavo F. Padovan 0); 16091da177e4SLinus Torvalds } 161045bb4bf0SMarcel Holtmann 16111da177e4SLinus Torvalds hci_dev_unlock(hdev); 16121da177e4SLinus Torvalds } 16131da177e4SLinus Torvalds 16146039aa73SGustavo Padovan static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 16151da177e4SLinus Torvalds { 1616a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 1617a9de9248SMarcel Holtmann struct hci_conn *conn; 16181da177e4SLinus Torvalds 1619a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 162045bb4bf0SMarcel Holtmann 16211da177e4SLinus Torvalds hci_dev_lock(hdev); 162245bb4bf0SMarcel Holtmann 1623a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 16249499237aSMarcel Holtmann if (!conn) { 16259499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 16269499237aSMarcel Holtmann goto unlock; 16279499237aSMarcel Holtmann 16289499237aSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 1629a9de9248SMarcel Holtmann if (!conn) 1630a9de9248SMarcel Holtmann goto unlock; 163145bb4bf0SMarcel Holtmann 16329499237aSMarcel Holtmann conn->type = SCO_LINK; 16339499237aSMarcel Holtmann } 16349499237aSMarcel Holtmann 1635a9de9248SMarcel Holtmann if (!ev->status) { 1636a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 1637769be974SMarcel Holtmann 1638769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 1639769be974SMarcel Holtmann conn->state = BT_CONFIG; 1640769be974SMarcel Holtmann hci_conn_hold(conn); 1641a9ea3ed9SSzymon Janc 1642a9ea3ed9SSzymon Janc if (!conn->out && !hci_conn_ssp_enabled(conn) && 1643a9ea3ed9SSzymon Janc !hci_find_link_key(hdev, &ev->bdaddr)) 1644a9ea3ed9SSzymon Janc conn->disc_timeout = HCI_PAIRING_TIMEOUT; 1645a9ea3ed9SSzymon Janc else 1646052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1647769be974SMarcel Holtmann } else 1648a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 1649a9de9248SMarcel Holtmann 16507d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 16517d0db0a3SMarcel Holtmann 1652a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 1653a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1654a9de9248SMarcel Holtmann 1655a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 1656a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1657a9de9248SMarcel Holtmann 1658a9de9248SMarcel Holtmann /* Get remote features */ 1659a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 1660a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 1661a9de9248SMarcel Holtmann cp.handle = ev->handle; 1662769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 1663769be974SMarcel Holtmann sizeof(cp), &cp); 166445bb4bf0SMarcel Holtmann } 1665a9de9248SMarcel Holtmann 1666a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 1667d095c1ebSAndrei Emeltchenko if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) { 1668a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 1669a9de9248SMarcel Holtmann cp.handle = ev->handle; 1670a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 167104124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp), 167204124681SGustavo F. Padovan &cp); 1673a9de9248SMarcel Holtmann } 167417d5c04cSJohan Hedberg } else { 1675a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 167617d5c04cSJohan Hedberg if (conn->type == ACL_LINK) 1677744cf19eSJohan Hedberg mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, 167848264f06SJohan Hedberg conn->dst_type, ev->status); 167917d5c04cSJohan Hedberg } 168045bb4bf0SMarcel Holtmann 1681e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 1682e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 168345bb4bf0SMarcel Holtmann 1684769be974SMarcel Holtmann if (ev->status) { 1685a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1686a9de9248SMarcel Holtmann hci_conn_del(conn); 1687c89b6e6bSMarcel Holtmann } else if (ev->link_type != ACL_LINK) 1688c89b6e6bSMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1689a9de9248SMarcel Holtmann 1690a9de9248SMarcel Holtmann unlock: 16911da177e4SLinus Torvalds hci_dev_unlock(hdev); 1692a9de9248SMarcel Holtmann 1693a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 16941da177e4SLinus Torvalds } 16951da177e4SLinus Torvalds 16966039aa73SGustavo Padovan static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 16971da177e4SLinus Torvalds { 1698a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 16991da177e4SLinus Torvalds int mask = hdev->link_mode; 170020714bfeSFrédéric Dalleau __u8 flags = 0; 17011da177e4SLinus Torvalds 17026ed93dc6SAndrei Emeltchenko BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr, 1703807deac2SGustavo Padovan ev->link_type); 17041da177e4SLinus Torvalds 170520714bfeSFrédéric Dalleau mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type, 170620714bfeSFrédéric Dalleau &flags); 17071da177e4SLinus Torvalds 1708138d22efSSzymon Janc if ((mask & HCI_LM_ACCEPT) && 1709138d22efSSzymon Janc !hci_blacklist_lookup(hdev, &ev->bdaddr)) { 17101da177e4SLinus Torvalds /* Connection accepted */ 1711c7bdd502SMarcel Holtmann struct inquiry_entry *ie; 17121da177e4SLinus Torvalds struct hci_conn *conn; 17131da177e4SLinus Torvalds 17141da177e4SLinus Torvalds hci_dev_lock(hdev); 1715b6a0dc82SMarcel Holtmann 1716cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 1717cc11b9c1SAndrei Emeltchenko if (ie) 1718c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 1719c7bdd502SMarcel Holtmann 17208fc9ced3SGustavo Padovan conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, 17218fc9ced3SGustavo Padovan &ev->bdaddr); 17221da177e4SLinus Torvalds if (!conn) { 1723cc11b9c1SAndrei Emeltchenko conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); 1724cc11b9c1SAndrei Emeltchenko if (!conn) { 1725893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 17261da177e4SLinus Torvalds hci_dev_unlock(hdev); 17271da177e4SLinus Torvalds return; 17281da177e4SLinus Torvalds } 17291da177e4SLinus Torvalds } 1730b6a0dc82SMarcel Holtmann 17311da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 1732b6a0dc82SMarcel Holtmann 17331da177e4SLinus Torvalds hci_dev_unlock(hdev); 17341da177e4SLinus Torvalds 173520714bfeSFrédéric Dalleau if (ev->link_type == ACL_LINK || 173620714bfeSFrédéric Dalleau (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) { 1737b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 173820714bfeSFrédéric Dalleau conn->state = BT_CONNECT; 1739b6a0dc82SMarcel Holtmann 17401da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 17411da177e4SLinus Torvalds 17421da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 17431da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 17441da177e4SLinus Torvalds else 17451da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 17461da177e4SLinus Torvalds 174704124681SGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), 174804124681SGustavo F. Padovan &cp); 174920714bfeSFrédéric Dalleau } else if (!(flags & HCI_PROTO_DEFER)) { 1750b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 175120714bfeSFrédéric Dalleau conn->state = BT_CONNECT; 1752b6a0dc82SMarcel Holtmann 1753b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 1754a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1755b6a0dc82SMarcel Holtmann 175682781e63SAndrei Emeltchenko cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40); 175782781e63SAndrei Emeltchenko cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40); 175882781e63SAndrei Emeltchenko cp.max_latency = __constant_cpu_to_le16(0xffff); 1759b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 1760b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 1761b6a0dc82SMarcel Holtmann 1762b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 1763b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 176420714bfeSFrédéric Dalleau } else { 176520714bfeSFrédéric Dalleau conn->state = BT_CONNECT2; 176620714bfeSFrédéric Dalleau hci_proto_connect_cfm(conn, 0); 1767b6a0dc82SMarcel Holtmann } 17681da177e4SLinus Torvalds } else { 17691da177e4SLinus Torvalds /* Connection rejected */ 17701da177e4SLinus Torvalds struct hci_cp_reject_conn_req cp; 17711da177e4SLinus Torvalds 17721da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 17739f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_REJ_BAD_ADDR; 1774a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 17751da177e4SLinus Torvalds } 17761da177e4SLinus Torvalds } 17771da177e4SLinus Torvalds 1778f0d6a0eaSMikel Astiz static u8 hci_to_mgmt_reason(u8 err) 1779f0d6a0eaSMikel Astiz { 1780f0d6a0eaSMikel Astiz switch (err) { 1781f0d6a0eaSMikel Astiz case HCI_ERROR_CONNECTION_TIMEOUT: 1782f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_TIMEOUT; 1783f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_USER_TERM: 1784f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_LOW_RESOURCES: 1785f0d6a0eaSMikel Astiz case HCI_ERROR_REMOTE_POWER_OFF: 1786f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_REMOTE; 1787f0d6a0eaSMikel Astiz case HCI_ERROR_LOCAL_HOST_TERM: 1788f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_LOCAL_HOST; 1789f0d6a0eaSMikel Astiz default: 1790f0d6a0eaSMikel Astiz return MGMT_DEV_DISCONN_UNKNOWN; 1791f0d6a0eaSMikel Astiz } 1792f0d6a0eaSMikel Astiz } 1793f0d6a0eaSMikel Astiz 17946039aa73SGustavo Padovan static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 17951da177e4SLinus Torvalds { 1796a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 179704837f64SMarcel Holtmann struct hci_conn *conn; 17981da177e4SLinus Torvalds 17999f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 18001da177e4SLinus Torvalds 18011da177e4SLinus Torvalds hci_dev_lock(hdev); 18021da177e4SLinus Torvalds 180304837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1804f7520543SJohan Hedberg if (!conn) 1805f7520543SJohan Hedberg goto unlock; 1806f7520543SJohan Hedberg 180737d9ef76SJohan Hedberg if (ev->status == 0) 18081da177e4SLinus Torvalds conn->state = BT_CLOSED; 18097d0db0a3SMarcel Holtmann 1810b644ba33SJohan Hedberg if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) && 1811b644ba33SJohan Hedberg (conn->type == ACL_LINK || conn->type == LE_LINK)) { 1812f0d6a0eaSMikel Astiz if (ev->status) { 181388c3df13SJohan Hedberg mgmt_disconnect_failed(hdev, &conn->dst, conn->type, 181488c3df13SJohan Hedberg conn->dst_type, ev->status); 1815f0d6a0eaSMikel Astiz } else { 1816f0d6a0eaSMikel Astiz u8 reason = hci_to_mgmt_reason(ev->reason); 1817f0d6a0eaSMikel Astiz 1818afc747a6SJohan Hedberg mgmt_device_disconnected(hdev, &conn->dst, conn->type, 1819f0d6a0eaSMikel Astiz conn->dst_type, reason); 1820f0d6a0eaSMikel Astiz } 182137d9ef76SJohan Hedberg } 1822f7520543SJohan Hedberg 182337d9ef76SJohan Hedberg if (ev->status == 0) { 18246ec5bcadSVishal Agarwal if (conn->type == ACL_LINK && conn->flush_key) 18256ec5bcadSVishal Agarwal hci_remove_link_key(hdev, &conn->dst); 18262950f21aSMarcel Holtmann hci_proto_disconn_cfm(conn, ev->reason); 18271da177e4SLinus Torvalds hci_conn_del(conn); 182837d9ef76SJohan Hedberg } 18291da177e4SLinus Torvalds 1830f7520543SJohan Hedberg unlock: 18311da177e4SLinus Torvalds hci_dev_unlock(hdev); 18321da177e4SLinus Torvalds } 18331da177e4SLinus Torvalds 18346039aa73SGustavo Padovan static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1835a9de9248SMarcel Holtmann { 1836a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 1837a9de9248SMarcel Holtmann struct hci_conn *conn; 1838a9de9248SMarcel Holtmann 18399f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 1840a9de9248SMarcel Holtmann 1841a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1842a9de9248SMarcel Holtmann 1843a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1844d7556e20SWaldemar Rymarkiewicz if (!conn) 1845d7556e20SWaldemar Rymarkiewicz goto unlock; 1846d7556e20SWaldemar Rymarkiewicz 1847765c2a96SJohan Hedberg if (!ev->status) { 1848aa64a8b5SJohan Hedberg if (!hci_conn_ssp_enabled(conn) && 184951a8efd7SJohan Hedberg test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) { 1850d7556e20SWaldemar Rymarkiewicz BT_INFO("re-auth of legacy device is not possible."); 185119f8def0SWaldemar Rymarkiewicz } else { 1852a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1853765c2a96SJohan Hedberg conn->sec_level = conn->pending_sec_level; 185419f8def0SWaldemar Rymarkiewicz } 18552a611692SJohan Hedberg } else { 1856bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 1857bab73cb6SJohan Hedberg ev->status); 18582a611692SJohan Hedberg } 1859a9de9248SMarcel Holtmann 186051a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 186151a8efd7SJohan Hedberg clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags); 1862a9de9248SMarcel Holtmann 1863f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1864aa64a8b5SJohan Hedberg if (!ev->status && hci_conn_ssp_enabled(conn)) { 1865f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1866f8558555SMarcel Holtmann cp.handle = ev->handle; 1867f8558555SMarcel Holtmann cp.encrypt = 0x01; 1868d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1869d7556e20SWaldemar Rymarkiewicz &cp); 1870f8558555SMarcel Holtmann } else { 1871f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1872f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 187376a68ba0SDavid Herrmann hci_conn_drop(conn); 1874f8558555SMarcel Holtmann } 1875052b30b0SMarcel Holtmann } else { 1876a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 1877a9de9248SMarcel Holtmann 1878052b30b0SMarcel Holtmann hci_conn_hold(conn); 1879052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 188076a68ba0SDavid Herrmann hci_conn_drop(conn); 1881052b30b0SMarcel Holtmann } 1882052b30b0SMarcel Holtmann 188351a8efd7SJohan Hedberg if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) { 1884a9de9248SMarcel Holtmann if (!ev->status) { 1885a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1886f8558555SMarcel Holtmann cp.handle = ev->handle; 1887f8558555SMarcel Holtmann cp.encrypt = 0x01; 1888d7556e20SWaldemar Rymarkiewicz hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 1889d7556e20SWaldemar Rymarkiewicz &cp); 1890a9de9248SMarcel Holtmann } else { 189151a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 1892a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 1893a9de9248SMarcel Holtmann } 1894a9de9248SMarcel Holtmann } 1895a9de9248SMarcel Holtmann 1896d7556e20SWaldemar Rymarkiewicz unlock: 1897a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1898a9de9248SMarcel Holtmann } 1899a9de9248SMarcel Holtmann 19006039aa73SGustavo Padovan static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 1901a9de9248SMarcel Holtmann { 1902127178d2SJohan Hedberg struct hci_ev_remote_name *ev = (void *) skb->data; 1903127178d2SJohan Hedberg struct hci_conn *conn; 1904127178d2SJohan Hedberg 1905a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1906a9de9248SMarcel Holtmann 1907a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 1908127178d2SJohan Hedberg 1909127178d2SJohan Hedberg hci_dev_lock(hdev); 1910127178d2SJohan Hedberg 1911127178d2SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 1912b644ba33SJohan Hedberg 1913b644ba33SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 1914b644ba33SJohan Hedberg goto check_auth; 1915b644ba33SJohan Hedberg 1916b644ba33SJohan Hedberg if (ev->status == 0) 1917b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name, 1918b644ba33SJohan Hedberg strnlen(ev->name, HCI_MAX_NAME_LENGTH)); 1919b644ba33SJohan Hedberg else 1920b644ba33SJohan Hedberg hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0); 1921b644ba33SJohan Hedberg 1922b644ba33SJohan Hedberg check_auth: 192379c6c70cSJohan Hedberg if (!conn) 192479c6c70cSJohan Hedberg goto unlock; 192579c6c70cSJohan Hedberg 192679c6c70cSJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) 192779c6c70cSJohan Hedberg goto unlock; 192879c6c70cSJohan Hedberg 192951a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 1930127178d2SJohan Hedberg struct hci_cp_auth_requested cp; 1931127178d2SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 1932127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 1933127178d2SJohan Hedberg } 1934127178d2SJohan Hedberg 193579c6c70cSJohan Hedberg unlock: 1936127178d2SJohan Hedberg hci_dev_unlock(hdev); 1937a9de9248SMarcel Holtmann } 1938a9de9248SMarcel Holtmann 19396039aa73SGustavo Padovan static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 1940a9de9248SMarcel Holtmann { 1941a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 1942a9de9248SMarcel Holtmann struct hci_conn *conn; 1943a9de9248SMarcel Holtmann 19449f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 1945a9de9248SMarcel Holtmann 1946a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1947a9de9248SMarcel Holtmann 1948a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1949a9de9248SMarcel Holtmann if (conn) { 1950a9de9248SMarcel Holtmann if (!ev->status) { 1951ae293196SMarcel Holtmann if (ev->encrypt) { 1952ae293196SMarcel Holtmann /* Encryption implies authentication */ 1953ae293196SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1954a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1955da85e5e5SVinicius Costa Gomes conn->sec_level = conn->pending_sec_level; 1956ae293196SMarcel Holtmann } else 1957a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_ENCRYPT; 1958a9de9248SMarcel Holtmann } 1959a9de9248SMarcel Holtmann 196051a8efd7SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 1961a9de9248SMarcel Holtmann 1962a7d7723aSGustavo Padovan if (ev->status && conn->state == BT_CONNECTED) { 1963bed71748SAndre Guedes hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); 196476a68ba0SDavid Herrmann hci_conn_drop(conn); 1965a7d7723aSGustavo Padovan goto unlock; 1966a7d7723aSGustavo Padovan } 1967a7d7723aSGustavo Padovan 1968f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1969f8558555SMarcel Holtmann if (!ev->status) 1970f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1971f8558555SMarcel Holtmann 1972f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 197376a68ba0SDavid Herrmann hci_conn_drop(conn); 1974f8558555SMarcel Holtmann } else 1975a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 1976a9de9248SMarcel Holtmann } 1977a9de9248SMarcel Holtmann 1978a7d7723aSGustavo Padovan unlock: 1979a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1980a9de9248SMarcel Holtmann } 1981a9de9248SMarcel Holtmann 19826039aa73SGustavo Padovan static void hci_change_link_key_complete_evt(struct hci_dev *hdev, 1983807deac2SGustavo Padovan struct sk_buff *skb) 1984a9de9248SMarcel Holtmann { 1985a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 1986a9de9248SMarcel Holtmann struct hci_conn *conn; 1987a9de9248SMarcel Holtmann 19889f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 1989a9de9248SMarcel Holtmann 1990a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1991a9de9248SMarcel Holtmann 1992a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1993a9de9248SMarcel Holtmann if (conn) { 1994a9de9248SMarcel Holtmann if (!ev->status) 1995a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_SECURE; 1996a9de9248SMarcel Holtmann 199751a8efd7SJohan Hedberg clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); 1998a9de9248SMarcel Holtmann 1999a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 2000a9de9248SMarcel Holtmann } 2001a9de9248SMarcel Holtmann 2002a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2003a9de9248SMarcel Holtmann } 2004a9de9248SMarcel Holtmann 20056039aa73SGustavo Padovan static void hci_remote_features_evt(struct hci_dev *hdev, 2006807deac2SGustavo Padovan struct sk_buff *skb) 2007a9de9248SMarcel Holtmann { 2008a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 2009a9de9248SMarcel Holtmann struct hci_conn *conn; 2010a9de9248SMarcel Holtmann 20119f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2012a9de9248SMarcel Holtmann 2013a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2014a9de9248SMarcel Holtmann 2015a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2016ccd556feSJohan Hedberg if (!conn) 2017ccd556feSJohan Hedberg goto unlock; 2018ccd556feSJohan Hedberg 2019769be974SMarcel Holtmann if (!ev->status) 2020cad718edSJohan Hedberg memcpy(conn->features[0], ev->features, 8); 2021a9de9248SMarcel Holtmann 2022ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2023ccd556feSJohan Hedberg goto unlock; 2024ccd556feSJohan Hedberg 2025ccd556feSJohan Hedberg if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { 2026769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 2027769be974SMarcel Holtmann cp.handle = ev->handle; 2028769be974SMarcel Holtmann cp.page = 0x01; 2029ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 2030769be974SMarcel Holtmann sizeof(cp), &cp); 2031392599b9SJohan Hedberg goto unlock; 2032392599b9SJohan Hedberg } 2033392599b9SJohan Hedberg 2034671267bfSJohan Hedberg if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { 2035127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2036127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2037127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2038127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2039127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2040b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 2041b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 204208c79b61SJohan Hedberg conn->dst_type, 0, NULL, 0, 2043b644ba33SJohan Hedberg conn->dev_class); 2044392599b9SJohan Hedberg 2045127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2046769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2047769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 204876a68ba0SDavid Herrmann hci_conn_drop(conn); 2049769be974SMarcel Holtmann } 2050769be974SMarcel Holtmann 2051ccd556feSJohan Hedberg unlock: 2052a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2053a9de9248SMarcel Holtmann } 2054a9de9248SMarcel Holtmann 20556039aa73SGustavo Padovan static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 2056a9de9248SMarcel Holtmann { 2057a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 20589238f36aSJohan Hedberg u8 status = skb->data[sizeof(*ev)]; 2059a9de9248SMarcel Holtmann __u16 opcode; 2060a9de9248SMarcel Holtmann 2061a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2062a9de9248SMarcel Holtmann 2063a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2064a9de9248SMarcel Holtmann 2065a9de9248SMarcel Holtmann switch (opcode) { 2066a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 2067a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 2068a9de9248SMarcel Holtmann break; 2069a9de9248SMarcel Holtmann 20704d93483bSAndre Guedes case HCI_OP_PERIODIC_INQ: 20714d93483bSAndre Guedes hci_cc_periodic_inq(hdev, skb); 20724d93483bSAndre Guedes break; 20734d93483bSAndre Guedes 2074a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 2075a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 2076a9de9248SMarcel Holtmann break; 2077a9de9248SMarcel Holtmann 2078a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 2079a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 2080a9de9248SMarcel Holtmann break; 2081a9de9248SMarcel Holtmann 2082a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 2083a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 2084a9de9248SMarcel Holtmann break; 2085a9de9248SMarcel Holtmann 2086e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 2087e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 2088e4e8e37cSMarcel Holtmann break; 2089e4e8e37cSMarcel Holtmann 2090a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 2091a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 2092a9de9248SMarcel Holtmann break; 2093a9de9248SMarcel Holtmann 2094e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 2095e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 2096e4e8e37cSMarcel Holtmann break; 2097e4e8e37cSMarcel Holtmann 2098e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 2099e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 2100e4e8e37cSMarcel Holtmann break; 2101e4e8e37cSMarcel Holtmann 2102a9de9248SMarcel Holtmann case HCI_OP_RESET: 2103a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 2104a9de9248SMarcel Holtmann break; 2105a9de9248SMarcel Holtmann 2106a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 2107a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 2108a9de9248SMarcel Holtmann break; 2109a9de9248SMarcel Holtmann 2110a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 2111a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 2112a9de9248SMarcel Holtmann break; 2113a9de9248SMarcel Holtmann 2114a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 2115a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 2116a9de9248SMarcel Holtmann break; 2117a9de9248SMarcel Holtmann 2118a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 2119a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 2120a9de9248SMarcel Holtmann break; 2121a9de9248SMarcel Holtmann 2122a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 2123a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 2124a9de9248SMarcel Holtmann break; 2125a9de9248SMarcel Holtmann 2126a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 2127a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 2128a9de9248SMarcel Holtmann break; 2129a9de9248SMarcel Holtmann 2130a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 2131a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 2132a9de9248SMarcel Holtmann break; 2133a9de9248SMarcel Holtmann 2134a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 2135a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 2136a9de9248SMarcel Holtmann break; 2137a9de9248SMarcel Holtmann 2138a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 2139a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 2140a9de9248SMarcel Holtmann break; 2141a9de9248SMarcel Holtmann 2142333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 2143333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 2144333140b5SMarcel Holtmann break; 2145333140b5SMarcel Holtmann 2146a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 2147a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 2148a9de9248SMarcel Holtmann break; 2149a9de9248SMarcel Holtmann 2150a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 2151a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 2152a9de9248SMarcel Holtmann break; 2153a9de9248SMarcel Holtmann 2154a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 2155a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 2156a9de9248SMarcel Holtmann break; 2157a9de9248SMarcel Holtmann 2158971e3a4bSAndre Guedes case HCI_OP_READ_LOCAL_EXT_FEATURES: 2159971e3a4bSAndre Guedes hci_cc_read_local_ext_features(hdev, skb); 2160971e3a4bSAndre Guedes break; 2161971e3a4bSAndre Guedes 2162a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 2163a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 2164a9de9248SMarcel Holtmann break; 2165a9de9248SMarcel Holtmann 2166a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 2167a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 2168a9de9248SMarcel Holtmann break; 2169a9de9248SMarcel Holtmann 2170f332ec66SJohan Hedberg case HCI_OP_READ_PAGE_SCAN_ACTIVITY: 2171f332ec66SJohan Hedberg hci_cc_read_page_scan_activity(hdev, skb); 2172f332ec66SJohan Hedberg break; 2173f332ec66SJohan Hedberg 21744a3ee763SJohan Hedberg case HCI_OP_WRITE_PAGE_SCAN_ACTIVITY: 21754a3ee763SJohan Hedberg hci_cc_write_page_scan_activity(hdev, skb); 21764a3ee763SJohan Hedberg break; 21774a3ee763SJohan Hedberg 2178f332ec66SJohan Hedberg case HCI_OP_READ_PAGE_SCAN_TYPE: 2179f332ec66SJohan Hedberg hci_cc_read_page_scan_type(hdev, skb); 2180f332ec66SJohan Hedberg break; 2181f332ec66SJohan Hedberg 21824a3ee763SJohan Hedberg case HCI_OP_WRITE_PAGE_SCAN_TYPE: 21834a3ee763SJohan Hedberg hci_cc_write_page_scan_type(hdev, skb); 21844a3ee763SJohan Hedberg break; 21854a3ee763SJohan Hedberg 2186350ee4cfSAndrei Emeltchenko case HCI_OP_READ_DATA_BLOCK_SIZE: 2187350ee4cfSAndrei Emeltchenko hci_cc_read_data_block_size(hdev, skb); 2188350ee4cfSAndrei Emeltchenko break; 2189350ee4cfSAndrei Emeltchenko 21901e89cffbSAndrei Emeltchenko case HCI_OP_READ_FLOW_CONTROL_MODE: 21911e89cffbSAndrei Emeltchenko hci_cc_read_flow_control_mode(hdev, skb); 21921e89cffbSAndrei Emeltchenko break; 21931e89cffbSAndrei Emeltchenko 2194928abaa7SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_INFO: 2195928abaa7SAndrei Emeltchenko hci_cc_read_local_amp_info(hdev, skb); 2196928abaa7SAndrei Emeltchenko break; 2197928abaa7SAndrei Emeltchenko 2198903e4541SAndrei Emeltchenko case HCI_OP_READ_LOCAL_AMP_ASSOC: 2199903e4541SAndrei Emeltchenko hci_cc_read_local_amp_assoc(hdev, skb); 2200903e4541SAndrei Emeltchenko break; 2201903e4541SAndrei Emeltchenko 2202d5859e22SJohan Hedberg case HCI_OP_READ_INQ_RSP_TX_POWER: 2203d5859e22SJohan Hedberg hci_cc_read_inq_rsp_tx_power(hdev, skb); 2204d5859e22SJohan Hedberg break; 2205d5859e22SJohan Hedberg 2206980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_REPLY: 2207980e1a53SJohan Hedberg hci_cc_pin_code_reply(hdev, skb); 2208980e1a53SJohan Hedberg break; 2209980e1a53SJohan Hedberg 2210980e1a53SJohan Hedberg case HCI_OP_PIN_CODE_NEG_REPLY: 2211980e1a53SJohan Hedberg hci_cc_pin_code_neg_reply(hdev, skb); 2212980e1a53SJohan Hedberg break; 2213980e1a53SJohan Hedberg 2214c35938b2SSzymon Janc case HCI_OP_READ_LOCAL_OOB_DATA: 2215c35938b2SSzymon Janc hci_cc_read_local_oob_data_reply(hdev, skb); 2216c35938b2SSzymon Janc break; 2217c35938b2SSzymon Janc 22186ed58ec5SVille Tervo case HCI_OP_LE_READ_BUFFER_SIZE: 22196ed58ec5SVille Tervo hci_cc_le_read_buffer_size(hdev, skb); 22206ed58ec5SVille Tervo break; 22216ed58ec5SVille Tervo 222260e77321SJohan Hedberg case HCI_OP_LE_READ_LOCAL_FEATURES: 222360e77321SJohan Hedberg hci_cc_le_read_local_features(hdev, skb); 222460e77321SJohan Hedberg break; 222560e77321SJohan Hedberg 22268fa19098SJohan Hedberg case HCI_OP_LE_READ_ADV_TX_POWER: 22278fa19098SJohan Hedberg hci_cc_le_read_adv_tx_power(hdev, skb); 22288fa19098SJohan Hedberg break; 22298fa19098SJohan Hedberg 2230a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_REPLY: 2231a5c29683SJohan Hedberg hci_cc_user_confirm_reply(hdev, skb); 2232a5c29683SJohan Hedberg break; 2233a5c29683SJohan Hedberg 2234a5c29683SJohan Hedberg case HCI_OP_USER_CONFIRM_NEG_REPLY: 2235a5c29683SJohan Hedberg hci_cc_user_confirm_neg_reply(hdev, skb); 2236a5c29683SJohan Hedberg break; 2237a5c29683SJohan Hedberg 22381143d458SBrian Gix case HCI_OP_USER_PASSKEY_REPLY: 22391143d458SBrian Gix hci_cc_user_passkey_reply(hdev, skb); 22401143d458SBrian Gix break; 22411143d458SBrian Gix 22421143d458SBrian Gix case HCI_OP_USER_PASSKEY_NEG_REPLY: 22431143d458SBrian Gix hci_cc_user_passkey_neg_reply(hdev, skb); 224416cde993SSzymon Janc break; 224507f7fa5dSAndre Guedes 2246c1d5dc4aSJohan Hedberg case HCI_OP_LE_SET_ADV_ENABLE: 2247c1d5dc4aSJohan Hedberg hci_cc_le_set_adv_enable(hdev, skb); 2248c1d5dc4aSJohan Hedberg break; 2249c1d5dc4aSJohan Hedberg 2250eb9d91f5SAndre Guedes case HCI_OP_LE_SET_SCAN_ENABLE: 2251eb9d91f5SAndre Guedes hci_cc_le_set_scan_enable(hdev, skb); 2252eb9d91f5SAndre Guedes break; 2253eb9d91f5SAndre Guedes 2254cf1d081fSJohan Hedberg case HCI_OP_LE_READ_WHITE_LIST_SIZE: 2255cf1d081fSJohan Hedberg hci_cc_le_read_white_list_size(hdev, skb); 2256cf1d081fSJohan Hedberg break; 2257cf1d081fSJohan Hedberg 22589b008c04SJohan Hedberg case HCI_OP_LE_READ_SUPPORTED_STATES: 22599b008c04SJohan Hedberg hci_cc_le_read_supported_states(hdev, skb); 22609b008c04SJohan Hedberg break; 22619b008c04SJohan Hedberg 2262f9b49306SAndre Guedes case HCI_OP_WRITE_LE_HOST_SUPPORTED: 2263f9b49306SAndre Guedes hci_cc_write_le_host_supported(hdev, skb); 2264f9b49306SAndre Guedes break; 2265f9b49306SAndre Guedes 226693c284eeSAndrei Emeltchenko case HCI_OP_WRITE_REMOTE_AMP_ASSOC: 226793c284eeSAndrei Emeltchenko hci_cc_write_remote_amp_assoc(hdev, skb); 226893c284eeSAndrei Emeltchenko break; 226993c284eeSAndrei Emeltchenko 2270a9de9248SMarcel Holtmann default: 22719f1db00cSAndrei Emeltchenko BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); 2272a9de9248SMarcel Holtmann break; 2273a9de9248SMarcel Holtmann } 2274a9de9248SMarcel Holtmann 2275ad82cdd1SJohan Hedberg if (opcode != HCI_OP_NOP) 22766bd32326SVille Tervo del_timer(&hdev->cmd_timer); 22776bd32326SVille Tervo 2278ad82cdd1SJohan Hedberg hci_req_cmd_complete(hdev, opcode, status); 22799238f36aSJohan Hedberg 2280dbccd791SSzymon Janc if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2281a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2282a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2283c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2284a9de9248SMarcel Holtmann } 2285a9de9248SMarcel Holtmann } 2286a9de9248SMarcel Holtmann 22876039aa73SGustavo Padovan static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 2288a9de9248SMarcel Holtmann { 2289a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 2290a9de9248SMarcel Holtmann __u16 opcode; 2291a9de9248SMarcel Holtmann 2292a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 2293a9de9248SMarcel Holtmann 2294a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 2295a9de9248SMarcel Holtmann 2296a9de9248SMarcel Holtmann switch (opcode) { 2297a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 2298a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 2299a9de9248SMarcel Holtmann break; 2300a9de9248SMarcel Holtmann 2301a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 2302a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 2303a9de9248SMarcel Holtmann break; 2304a9de9248SMarcel Holtmann 2305a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 2306a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 2307a9de9248SMarcel Holtmann break; 2308a9de9248SMarcel Holtmann 2309f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 2310f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 2311f8558555SMarcel Holtmann break; 2312f8558555SMarcel Holtmann 2313f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 2314f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 2315f8558555SMarcel Holtmann break; 2316f8558555SMarcel Holtmann 2317a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 2318a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 2319a9de9248SMarcel Holtmann break; 2320a9de9248SMarcel Holtmann 2321769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 2322769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 2323769be974SMarcel Holtmann break; 2324769be974SMarcel Holtmann 2325769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 2326769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 2327769be974SMarcel Holtmann break; 2328769be974SMarcel Holtmann 2329a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 2330a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 2331a9de9248SMarcel Holtmann break; 2332a9de9248SMarcel Holtmann 2333a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 2334a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 2335a9de9248SMarcel Holtmann break; 2336a9de9248SMarcel Holtmann 2337a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 2338a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 2339a9de9248SMarcel Holtmann break; 2340a9de9248SMarcel Holtmann 23418962ee74SJohan Hedberg case HCI_OP_DISCONNECT: 234288c3df13SJohan Hedberg hci_cs_disconnect(hdev, ev->status); 23438962ee74SJohan Hedberg break; 23448962ee74SJohan Hedberg 2345fcd89c09SVille Tervo case HCI_OP_LE_CREATE_CONN: 2346fcd89c09SVille Tervo hci_cs_le_create_conn(hdev, ev->status); 2347fcd89c09SVille Tervo break; 2348fcd89c09SVille Tervo 2349a02226d6SAndrei Emeltchenko case HCI_OP_CREATE_PHY_LINK: 2350a02226d6SAndrei Emeltchenko hci_cs_create_phylink(hdev, ev->status); 2351a02226d6SAndrei Emeltchenko break; 2352a02226d6SAndrei Emeltchenko 23530b26ab9dSAndrei Emeltchenko case HCI_OP_ACCEPT_PHY_LINK: 23540b26ab9dSAndrei Emeltchenko hci_cs_accept_phylink(hdev, ev->status); 23550b26ab9dSAndrei Emeltchenko break; 23560b26ab9dSAndrei Emeltchenko 2357a9de9248SMarcel Holtmann default: 23589f1db00cSAndrei Emeltchenko BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); 2359a9de9248SMarcel Holtmann break; 2360a9de9248SMarcel Holtmann } 2361a9de9248SMarcel Holtmann 2362ad82cdd1SJohan Hedberg if (opcode != HCI_OP_NOP) 23636bd32326SVille Tervo del_timer(&hdev->cmd_timer); 23646bd32326SVille Tervo 236502350a72SJohan Hedberg if (ev->status || 236602350a72SJohan Hedberg (hdev->sent_cmd && !bt_cb(hdev->sent_cmd)->req.event)) 236733720450SAndre Guedes hci_req_cmd_complete(hdev, opcode, ev->status); 23689238f36aSJohan Hedberg 236910572132SGustavo F. Padovan if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { 2370a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 2371a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 2372c347b765SGustavo F. Padovan queue_work(hdev->workqueue, &hdev->cmd_work); 2373a9de9248SMarcel Holtmann } 2374a9de9248SMarcel Holtmann } 2375a9de9248SMarcel Holtmann 23766039aa73SGustavo Padovan static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2377a9de9248SMarcel Holtmann { 2378a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 2379a9de9248SMarcel Holtmann struct hci_conn *conn; 2380a9de9248SMarcel Holtmann 23819f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2382a9de9248SMarcel Holtmann 2383a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2384a9de9248SMarcel Holtmann 2385a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2386a9de9248SMarcel Holtmann if (conn) { 2387a9de9248SMarcel Holtmann if (!ev->status) { 2388a9de9248SMarcel Holtmann if (ev->role) 2389a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_MASTER; 2390a9de9248SMarcel Holtmann else 2391a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_MASTER; 2392a9de9248SMarcel Holtmann } 2393a9de9248SMarcel Holtmann 239451a8efd7SJohan Hedberg clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); 2395a9de9248SMarcel Holtmann 2396a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 2397a9de9248SMarcel Holtmann } 2398a9de9248SMarcel Holtmann 2399a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2400a9de9248SMarcel Holtmann } 2401a9de9248SMarcel Holtmann 24026039aa73SGustavo Padovan static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 24031da177e4SLinus Torvalds { 2404a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 24051da177e4SLinus Torvalds int i; 24061da177e4SLinus Torvalds 240732ac5b9bSAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) { 240832ac5b9bSAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 240932ac5b9bSAndrei Emeltchenko return; 241032ac5b9bSAndrei Emeltchenko } 241132ac5b9bSAndrei Emeltchenko 2412c5993de8SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 2413c5993de8SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_pkts_info)) { 24141da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 24151da177e4SLinus Torvalds return; 24161da177e4SLinus Torvalds } 24171da177e4SLinus Torvalds 2418c5993de8SAndrei Emeltchenko BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 2419c5993de8SAndrei Emeltchenko 2420613a1c0cSAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 2421613a1c0cSAndrei Emeltchenko struct hci_comp_pkts_info *info = &ev->handles[i]; 24221da177e4SLinus Torvalds struct hci_conn *conn; 24231da177e4SLinus Torvalds __u16 handle, count; 24241da177e4SLinus Torvalds 2425613a1c0cSAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 2426613a1c0cSAndrei Emeltchenko count = __le16_to_cpu(info->count); 24271da177e4SLinus Torvalds 24281da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 2429f4280918SAndrei Emeltchenko if (!conn) 2430f4280918SAndrei Emeltchenko continue; 2431f4280918SAndrei Emeltchenko 24321da177e4SLinus Torvalds conn->sent -= count; 24331da177e4SLinus Torvalds 2434f4280918SAndrei Emeltchenko switch (conn->type) { 2435f4280918SAndrei Emeltchenko case ACL_LINK: 243670f23020SAndrei Emeltchenko hdev->acl_cnt += count; 243770f23020SAndrei Emeltchenko if (hdev->acl_cnt > hdev->acl_pkts) 24381da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 2439f4280918SAndrei Emeltchenko break; 2440f4280918SAndrei Emeltchenko 2441f4280918SAndrei Emeltchenko case LE_LINK: 24426ed58ec5SVille Tervo if (hdev->le_pkts) { 24436ed58ec5SVille Tervo hdev->le_cnt += count; 24446ed58ec5SVille Tervo if (hdev->le_cnt > hdev->le_pkts) 24456ed58ec5SVille Tervo hdev->le_cnt = hdev->le_pkts; 24466ed58ec5SVille Tervo } else { 24476ed58ec5SVille Tervo hdev->acl_cnt += count; 24486ed58ec5SVille Tervo if (hdev->acl_cnt > hdev->acl_pkts) 24496ed58ec5SVille Tervo hdev->acl_cnt = hdev->acl_pkts; 24506ed58ec5SVille Tervo } 2451f4280918SAndrei Emeltchenko break; 2452f4280918SAndrei Emeltchenko 2453f4280918SAndrei Emeltchenko case SCO_LINK: 245470f23020SAndrei Emeltchenko hdev->sco_cnt += count; 245570f23020SAndrei Emeltchenko if (hdev->sco_cnt > hdev->sco_pkts) 24565b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 2457f4280918SAndrei Emeltchenko break; 2458f4280918SAndrei Emeltchenko 2459f4280918SAndrei Emeltchenko default: 2460f4280918SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 2461f4280918SAndrei Emeltchenko break; 24621da177e4SLinus Torvalds } 24631da177e4SLinus Torvalds } 2464a9de9248SMarcel Holtmann 24653eff45eaSGustavo F. Padovan queue_work(hdev->workqueue, &hdev->tx_work); 24661da177e4SLinus Torvalds } 24671da177e4SLinus Torvalds 246876ef7cf7SAndrei Emeltchenko static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev, 246976ef7cf7SAndrei Emeltchenko __u16 handle) 247076ef7cf7SAndrei Emeltchenko { 247176ef7cf7SAndrei Emeltchenko struct hci_chan *chan; 247276ef7cf7SAndrei Emeltchenko 247376ef7cf7SAndrei Emeltchenko switch (hdev->dev_type) { 247476ef7cf7SAndrei Emeltchenko case HCI_BREDR: 247576ef7cf7SAndrei Emeltchenko return hci_conn_hash_lookup_handle(hdev, handle); 247676ef7cf7SAndrei Emeltchenko case HCI_AMP: 247776ef7cf7SAndrei Emeltchenko chan = hci_chan_lookup_handle(hdev, handle); 247876ef7cf7SAndrei Emeltchenko if (chan) 247976ef7cf7SAndrei Emeltchenko return chan->conn; 248076ef7cf7SAndrei Emeltchenko break; 248176ef7cf7SAndrei Emeltchenko default: 248276ef7cf7SAndrei Emeltchenko BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type); 248376ef7cf7SAndrei Emeltchenko break; 248476ef7cf7SAndrei Emeltchenko } 248576ef7cf7SAndrei Emeltchenko 248676ef7cf7SAndrei Emeltchenko return NULL; 248776ef7cf7SAndrei Emeltchenko } 248876ef7cf7SAndrei Emeltchenko 24896039aa73SGustavo Padovan static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb) 249025e89e99SAndrei Emeltchenko { 249125e89e99SAndrei Emeltchenko struct hci_ev_num_comp_blocks *ev = (void *) skb->data; 249225e89e99SAndrei Emeltchenko int i; 249325e89e99SAndrei Emeltchenko 249425e89e99SAndrei Emeltchenko if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) { 249525e89e99SAndrei Emeltchenko BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); 249625e89e99SAndrei Emeltchenko return; 249725e89e99SAndrei Emeltchenko } 249825e89e99SAndrei Emeltchenko 249925e89e99SAndrei Emeltchenko if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + 250025e89e99SAndrei Emeltchenko ev->num_hndl * sizeof(struct hci_comp_blocks_info)) { 250125e89e99SAndrei Emeltchenko BT_DBG("%s bad parameters", hdev->name); 250225e89e99SAndrei Emeltchenko return; 250325e89e99SAndrei Emeltchenko } 250425e89e99SAndrei Emeltchenko 250525e89e99SAndrei Emeltchenko BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks, 250625e89e99SAndrei Emeltchenko ev->num_hndl); 250725e89e99SAndrei Emeltchenko 250825e89e99SAndrei Emeltchenko for (i = 0; i < ev->num_hndl; i++) { 250925e89e99SAndrei Emeltchenko struct hci_comp_blocks_info *info = &ev->handles[i]; 251076ef7cf7SAndrei Emeltchenko struct hci_conn *conn = NULL; 251125e89e99SAndrei Emeltchenko __u16 handle, block_count; 251225e89e99SAndrei Emeltchenko 251325e89e99SAndrei Emeltchenko handle = __le16_to_cpu(info->handle); 251425e89e99SAndrei Emeltchenko block_count = __le16_to_cpu(info->blocks); 251525e89e99SAndrei Emeltchenko 251676ef7cf7SAndrei Emeltchenko conn = __hci_conn_lookup_handle(hdev, handle); 251725e89e99SAndrei Emeltchenko if (!conn) 251825e89e99SAndrei Emeltchenko continue; 251925e89e99SAndrei Emeltchenko 252025e89e99SAndrei Emeltchenko conn->sent -= block_count; 252125e89e99SAndrei Emeltchenko 252225e89e99SAndrei Emeltchenko switch (conn->type) { 252325e89e99SAndrei Emeltchenko case ACL_LINK: 2524bd1eb66bSAndrei Emeltchenko case AMP_LINK: 252525e89e99SAndrei Emeltchenko hdev->block_cnt += block_count; 252625e89e99SAndrei Emeltchenko if (hdev->block_cnt > hdev->num_blocks) 252725e89e99SAndrei Emeltchenko hdev->block_cnt = hdev->num_blocks; 252825e89e99SAndrei Emeltchenko break; 252925e89e99SAndrei Emeltchenko 253025e89e99SAndrei Emeltchenko default: 253125e89e99SAndrei Emeltchenko BT_ERR("Unknown type %d conn %p", conn->type, conn); 253225e89e99SAndrei Emeltchenko break; 253325e89e99SAndrei Emeltchenko } 253425e89e99SAndrei Emeltchenko } 253525e89e99SAndrei Emeltchenko 253625e89e99SAndrei Emeltchenko queue_work(hdev->workqueue, &hdev->tx_work); 253725e89e99SAndrei Emeltchenko } 253825e89e99SAndrei Emeltchenko 25396039aa73SGustavo Padovan static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 25401da177e4SLinus Torvalds { 2541a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 254204837f64SMarcel Holtmann struct hci_conn *conn; 25431da177e4SLinus Torvalds 25449f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 25451da177e4SLinus Torvalds 25461da177e4SLinus Torvalds hci_dev_lock(hdev); 25471da177e4SLinus Torvalds 254804837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 254904837f64SMarcel Holtmann if (conn) { 255004837f64SMarcel Holtmann conn->mode = ev->mode; 255104837f64SMarcel Holtmann conn->interval = __le16_to_cpu(ev->interval); 255204837f64SMarcel Holtmann 25538fc9ced3SGustavo Padovan if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, 25548fc9ced3SGustavo Padovan &conn->flags)) { 255504837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 255658a681efSJohan Hedberg set_bit(HCI_CONN_POWER_SAVE, &conn->flags); 255704837f64SMarcel Holtmann else 255858a681efSJohan Hedberg clear_bit(HCI_CONN_POWER_SAVE, &conn->flags); 255904837f64SMarcel Holtmann } 2560e73439d8SMarcel Holtmann 256151a8efd7SJohan Hedberg if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) 2562e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 256304837f64SMarcel Holtmann } 256404837f64SMarcel Holtmann 256504837f64SMarcel Holtmann hci_dev_unlock(hdev); 256604837f64SMarcel Holtmann } 256704837f64SMarcel Holtmann 25686039aa73SGustavo Padovan static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 25691da177e4SLinus Torvalds { 2570052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 2571052b30b0SMarcel Holtmann struct hci_conn *conn; 2572052b30b0SMarcel Holtmann 2573a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2574052b30b0SMarcel Holtmann 2575052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2576052b30b0SMarcel Holtmann 2577052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2578b6f98044SWaldemar Rymarkiewicz if (!conn) 2579b6f98044SWaldemar Rymarkiewicz goto unlock; 2580b6f98044SWaldemar Rymarkiewicz 2581b6f98044SWaldemar Rymarkiewicz if (conn->state == BT_CONNECTED) { 2582052b30b0SMarcel Holtmann hci_conn_hold(conn); 2583052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 258476a68ba0SDavid Herrmann hci_conn_drop(conn); 2585052b30b0SMarcel Holtmann } 2586052b30b0SMarcel Holtmann 2587a8b2d5c2SJohan Hedberg if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags)) 258803b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, 258903b555e1SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 2590a8b2d5c2SJohan Hedberg else if (test_bit(HCI_MGMT, &hdev->dev_flags)) { 2591a770bb5aSWaldemar Rymarkiewicz u8 secure; 2592a770bb5aSWaldemar Rymarkiewicz 2593a770bb5aSWaldemar Rymarkiewicz if (conn->pending_sec_level == BT_SECURITY_HIGH) 2594a770bb5aSWaldemar Rymarkiewicz secure = 1; 2595a770bb5aSWaldemar Rymarkiewicz else 2596a770bb5aSWaldemar Rymarkiewicz secure = 0; 2597a770bb5aSWaldemar Rymarkiewicz 2598744cf19eSJohan Hedberg mgmt_pin_code_request(hdev, &ev->bdaddr, secure); 2599a770bb5aSWaldemar Rymarkiewicz } 2600980e1a53SJohan Hedberg 2601b6f98044SWaldemar Rymarkiewicz unlock: 2602052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 26031da177e4SLinus Torvalds } 26041da177e4SLinus Torvalds 26056039aa73SGustavo Padovan static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 26061da177e4SLinus Torvalds { 260755ed8ca1SJohan Hedberg struct hci_ev_link_key_req *ev = (void *) skb->data; 260855ed8ca1SJohan Hedberg struct hci_cp_link_key_reply cp; 260955ed8ca1SJohan Hedberg struct hci_conn *conn; 261055ed8ca1SJohan Hedberg struct link_key *key; 261155ed8ca1SJohan Hedberg 2612a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 261355ed8ca1SJohan Hedberg 2614034cbea0SAndrei Emeltchenko if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 261555ed8ca1SJohan Hedberg return; 261655ed8ca1SJohan Hedberg 261755ed8ca1SJohan Hedberg hci_dev_lock(hdev); 261855ed8ca1SJohan Hedberg 261955ed8ca1SJohan Hedberg key = hci_find_link_key(hdev, &ev->bdaddr); 262055ed8ca1SJohan Hedberg if (!key) { 26216ed93dc6SAndrei Emeltchenko BT_DBG("%s link key not found for %pMR", hdev->name, 26226ed93dc6SAndrei Emeltchenko &ev->bdaddr); 262355ed8ca1SJohan Hedberg goto not_found; 262455ed8ca1SJohan Hedberg } 262555ed8ca1SJohan Hedberg 26266ed93dc6SAndrei Emeltchenko BT_DBG("%s found key type %u for %pMR", hdev->name, key->type, 26276ed93dc6SAndrei Emeltchenko &ev->bdaddr); 262855ed8ca1SJohan Hedberg 2629a8b2d5c2SJohan Hedberg if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) && 2630b6020ba0SWaldemar Rymarkiewicz key->type == HCI_LK_DEBUG_COMBINATION) { 263155ed8ca1SJohan Hedberg BT_DBG("%s ignoring debug key", hdev->name); 263255ed8ca1SJohan Hedberg goto not_found; 263355ed8ca1SJohan Hedberg } 263455ed8ca1SJohan Hedberg 263555ed8ca1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 263660b83f57SWaldemar Rymarkiewicz if (conn) { 263760b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_UNAUTH_COMBINATION && 2638807deac2SGustavo Padovan conn->auth_type != 0xff && (conn->auth_type & 0x01)) { 263955ed8ca1SJohan Hedberg BT_DBG("%s ignoring unauthenticated key", hdev->name); 264055ed8ca1SJohan Hedberg goto not_found; 264155ed8ca1SJohan Hedberg } 264255ed8ca1SJohan Hedberg 264360b83f57SWaldemar Rymarkiewicz if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && 264460b83f57SWaldemar Rymarkiewicz conn->pending_sec_level == BT_SECURITY_HIGH) { 26458fc9ced3SGustavo Padovan BT_DBG("%s ignoring key unauthenticated for high security", 26468fc9ced3SGustavo Padovan hdev->name); 264760b83f57SWaldemar Rymarkiewicz goto not_found; 264860b83f57SWaldemar Rymarkiewicz } 264960b83f57SWaldemar Rymarkiewicz 265060b83f57SWaldemar Rymarkiewicz conn->key_type = key->type; 265160b83f57SWaldemar Rymarkiewicz conn->pin_length = key->pin_len; 265260b83f57SWaldemar Rymarkiewicz } 265360b83f57SWaldemar Rymarkiewicz 265455ed8ca1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 26559b3b4460SAndrei Emeltchenko memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE); 265655ed8ca1SJohan Hedberg 265755ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp); 265855ed8ca1SJohan Hedberg 265955ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 266055ed8ca1SJohan Hedberg 266155ed8ca1SJohan Hedberg return; 266255ed8ca1SJohan Hedberg 266355ed8ca1SJohan Hedberg not_found: 266455ed8ca1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr); 266555ed8ca1SJohan Hedberg hci_dev_unlock(hdev); 26661da177e4SLinus Torvalds } 26671da177e4SLinus Torvalds 26686039aa73SGustavo Padovan static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 26691da177e4SLinus Torvalds { 2670052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 2671052b30b0SMarcel Holtmann struct hci_conn *conn; 267255ed8ca1SJohan Hedberg u8 pin_len = 0; 2673052b30b0SMarcel Holtmann 2674a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 2675052b30b0SMarcel Holtmann 2676052b30b0SMarcel Holtmann hci_dev_lock(hdev); 2677052b30b0SMarcel Holtmann 2678052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 2679052b30b0SMarcel Holtmann if (conn) { 2680052b30b0SMarcel Holtmann hci_conn_hold(conn); 2681052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 2682980e1a53SJohan Hedberg pin_len = conn->pin_length; 268313d39315SWaldemar Rymarkiewicz 268413d39315SWaldemar Rymarkiewicz if (ev->key_type != HCI_LK_CHANGED_COMBINATION) 268513d39315SWaldemar Rymarkiewicz conn->key_type = ev->key_type; 268613d39315SWaldemar Rymarkiewicz 268776a68ba0SDavid Herrmann hci_conn_drop(conn); 2688052b30b0SMarcel Holtmann } 2689052b30b0SMarcel Holtmann 2690034cbea0SAndrei Emeltchenko if (test_bit(HCI_MGMT, &hdev->dev_flags)) 2691d25e28abSJohan Hedberg hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, 269255ed8ca1SJohan Hedberg ev->key_type, pin_len); 269355ed8ca1SJohan Hedberg 2694052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 26951da177e4SLinus Torvalds } 26961da177e4SLinus Torvalds 26976039aa73SGustavo Padovan static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 269804837f64SMarcel Holtmann { 2699a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 270004837f64SMarcel Holtmann struct hci_conn *conn; 270104837f64SMarcel Holtmann 27029f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 270304837f64SMarcel Holtmann 270404837f64SMarcel Holtmann hci_dev_lock(hdev); 270504837f64SMarcel Holtmann 270604837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 27071da177e4SLinus Torvalds if (conn && !ev->status) { 27081da177e4SLinus Torvalds struct inquiry_entry *ie; 27091da177e4SLinus Torvalds 2710cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2711cc11b9c1SAndrei Emeltchenko if (ie) { 27121da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 27131da177e4SLinus Torvalds ie->timestamp = jiffies; 27141da177e4SLinus Torvalds } 27151da177e4SLinus Torvalds } 27161da177e4SLinus Torvalds 27171da177e4SLinus Torvalds hci_dev_unlock(hdev); 27181da177e4SLinus Torvalds } 27191da177e4SLinus Torvalds 27206039aa73SGustavo Padovan static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 2721a8746417SMarcel Holtmann { 2722a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 2723a8746417SMarcel Holtmann struct hci_conn *conn; 2724a8746417SMarcel Holtmann 27259f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2726a8746417SMarcel Holtmann 2727a8746417SMarcel Holtmann hci_dev_lock(hdev); 2728a8746417SMarcel Holtmann 2729a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2730a8746417SMarcel Holtmann if (conn && !ev->status) 2731a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 2732a8746417SMarcel Holtmann 2733a8746417SMarcel Holtmann hci_dev_unlock(hdev); 2734a8746417SMarcel Holtmann } 2735a8746417SMarcel Holtmann 27366039aa73SGustavo Padovan static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 273785a1e930SMarcel Holtmann { 2738a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 273985a1e930SMarcel Holtmann struct inquiry_entry *ie; 274085a1e930SMarcel Holtmann 274185a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 274285a1e930SMarcel Holtmann 274385a1e930SMarcel Holtmann hci_dev_lock(hdev); 274485a1e930SMarcel Holtmann 2745cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 2746cc11b9c1SAndrei Emeltchenko if (ie) { 274785a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 274885a1e930SMarcel Holtmann ie->timestamp = jiffies; 274985a1e930SMarcel Holtmann } 275085a1e930SMarcel Holtmann 275185a1e930SMarcel Holtmann hci_dev_unlock(hdev); 275285a1e930SMarcel Holtmann } 275385a1e930SMarcel Holtmann 27546039aa73SGustavo Padovan static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, 2755807deac2SGustavo Padovan struct sk_buff *skb) 2756a9de9248SMarcel Holtmann { 2757a9de9248SMarcel Holtmann struct inquiry_data data; 2758a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 2759388fc8faSJohan Hedberg bool name_known, ssp; 2760a9de9248SMarcel Holtmann 2761a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2762a9de9248SMarcel Holtmann 2763a9de9248SMarcel Holtmann if (!num_rsp) 2764a9de9248SMarcel Holtmann return; 2765a9de9248SMarcel Holtmann 27661519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 27671519cc17SAndre Guedes return; 27681519cc17SAndre Guedes 2769a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2770a9de9248SMarcel Holtmann 2771a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 2772138d22efSSzymon Janc struct inquiry_info_with_rssi_and_pscan_mode *info; 2773138d22efSSzymon Janc info = (void *) (skb->data + 1); 2774a9de9248SMarcel Holtmann 2775e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2776a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2777a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2778a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2779a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 2780a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2781a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2782a9de9248SMarcel Holtmann data.rssi = info->rssi; 278341a96212SMarcel Holtmann data.ssp_mode = 0x00; 27843175405bSJohan Hedberg 27853175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 2786388fc8faSJohan Hedberg false, &ssp); 278748264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2788e17acd40SJohan Hedberg info->dev_class, info->rssi, 2789388fc8faSJohan Hedberg !name_known, ssp, NULL, 0); 2790a9de9248SMarcel Holtmann } 2791a9de9248SMarcel Holtmann } else { 2792a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 2793a9de9248SMarcel Holtmann 2794e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2795a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2796a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2797a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2798a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2799a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2800a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2801a9de9248SMarcel Holtmann data.rssi = info->rssi; 280241a96212SMarcel Holtmann data.ssp_mode = 0x00; 28033175405bSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, 2804388fc8faSJohan Hedberg false, &ssp); 280548264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 2806e17acd40SJohan Hedberg info->dev_class, info->rssi, 2807388fc8faSJohan Hedberg !name_known, ssp, NULL, 0); 2808a9de9248SMarcel Holtmann } 2809a9de9248SMarcel Holtmann } 2810a9de9248SMarcel Holtmann 2811a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2812a9de9248SMarcel Holtmann } 2813a9de9248SMarcel Holtmann 28146039aa73SGustavo Padovan static void hci_remote_ext_features_evt(struct hci_dev *hdev, 2815807deac2SGustavo Padovan struct sk_buff *skb) 2816a9de9248SMarcel Holtmann { 281741a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 281841a96212SMarcel Holtmann struct hci_conn *conn; 281941a96212SMarcel Holtmann 2820a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 282141a96212SMarcel Holtmann 282241a96212SMarcel Holtmann hci_dev_lock(hdev); 282341a96212SMarcel Holtmann 282441a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 2825ccd556feSJohan Hedberg if (!conn) 2826ccd556feSJohan Hedberg goto unlock; 2827ccd556feSJohan Hedberg 2828cad718edSJohan Hedberg if (ev->page < HCI_MAX_PAGES) 2829cad718edSJohan Hedberg memcpy(conn->features[ev->page], ev->features, 8); 2830cad718edSJohan Hedberg 2831769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 283241a96212SMarcel Holtmann struct inquiry_entry *ie; 283341a96212SMarcel Holtmann 2834cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 2835cc11b9c1SAndrei Emeltchenko if (ie) 283602b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 283741a96212SMarcel Holtmann 2838bbb0eadaSJaganath Kanakkassery if (ev->features[0] & LMP_HOST_SSP) { 283958a681efSJohan Hedberg set_bit(HCI_CONN_SSP_ENABLED, &conn->flags); 2840bbb0eadaSJaganath Kanakkassery } else { 2841bbb0eadaSJaganath Kanakkassery /* It is mandatory by the Bluetooth specification that 2842bbb0eadaSJaganath Kanakkassery * Extended Inquiry Results are only used when Secure 2843bbb0eadaSJaganath Kanakkassery * Simple Pairing is enabled, but some devices violate 2844bbb0eadaSJaganath Kanakkassery * this. 2845bbb0eadaSJaganath Kanakkassery * 2846bbb0eadaSJaganath Kanakkassery * To make these devices work, the internal SSP 2847bbb0eadaSJaganath Kanakkassery * enabled flag needs to be cleared if the remote host 2848bbb0eadaSJaganath Kanakkassery * features do not indicate SSP support */ 2849bbb0eadaSJaganath Kanakkassery clear_bit(HCI_CONN_SSP_ENABLED, &conn->flags); 2850bbb0eadaSJaganath Kanakkassery } 285141a96212SMarcel Holtmann } 285241a96212SMarcel Holtmann 2853ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 2854ccd556feSJohan Hedberg goto unlock; 2855ccd556feSJohan Hedberg 2856671267bfSJohan Hedberg if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { 2857127178d2SJohan Hedberg struct hci_cp_remote_name_req cp; 2858127178d2SJohan Hedberg memset(&cp, 0, sizeof(cp)); 2859127178d2SJohan Hedberg bacpy(&cp.bdaddr, &conn->dst); 2860127178d2SJohan Hedberg cp.pscan_rep_mode = 0x02; 2861127178d2SJohan Hedberg hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); 2862b644ba33SJohan Hedberg } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 2863b644ba33SJohan Hedberg mgmt_device_connected(hdev, &conn->dst, conn->type, 286408c79b61SJohan Hedberg conn->dst_type, 0, NULL, 0, 2865b644ba33SJohan Hedberg conn->dev_class); 2866392599b9SJohan Hedberg 2867127178d2SJohan Hedberg if (!hci_outgoing_auth_needed(hdev, conn)) { 2868769be974SMarcel Holtmann conn->state = BT_CONNECTED; 2869769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 287076a68ba0SDavid Herrmann hci_conn_drop(conn); 2871769be974SMarcel Holtmann } 2872769be974SMarcel Holtmann 2873ccd556feSJohan Hedberg unlock: 287441a96212SMarcel Holtmann hci_dev_unlock(hdev); 2875a9de9248SMarcel Holtmann } 2876a9de9248SMarcel Holtmann 28776039aa73SGustavo Padovan static void hci_sync_conn_complete_evt(struct hci_dev *hdev, 2878807deac2SGustavo Padovan struct sk_buff *skb) 2879a9de9248SMarcel Holtmann { 2880b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 2881b6a0dc82SMarcel Holtmann struct hci_conn *conn; 2882b6a0dc82SMarcel Holtmann 28839f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 2884b6a0dc82SMarcel Holtmann 2885b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 2886b6a0dc82SMarcel Holtmann 2887b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 28889dc0a3afSMarcel Holtmann if (!conn) { 28899dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 28909dc0a3afSMarcel Holtmann goto unlock; 28919dc0a3afSMarcel Holtmann 28929dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 2893b6a0dc82SMarcel Holtmann if (!conn) 2894b6a0dc82SMarcel Holtmann goto unlock; 2895b6a0dc82SMarcel Holtmann 28969dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 28979dc0a3afSMarcel Holtmann } 28989dc0a3afSMarcel Holtmann 2899732547f9SMarcel Holtmann switch (ev->status) { 2900732547f9SMarcel Holtmann case 0x00: 2901732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 2902732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 2903732547f9SMarcel Holtmann 2904732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 2905732547f9SMarcel Holtmann break; 2906732547f9SMarcel Holtmann 2907705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 2908732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 29091038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 2910732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 2911732547f9SMarcel Holtmann if (conn->out && conn->attempt < 2) { 2912efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 2913efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 2914efc7688bSMarcel Holtmann hci_setup_sync(conn, conn->link->handle); 2915efc7688bSMarcel Holtmann goto unlock; 2916efc7688bSMarcel Holtmann } 2917732547f9SMarcel Holtmann /* fall through */ 2918efc7688bSMarcel Holtmann 2919732547f9SMarcel Holtmann default: 2920b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 2921732547f9SMarcel Holtmann break; 2922732547f9SMarcel Holtmann } 2923b6a0dc82SMarcel Holtmann 2924b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 2925b6a0dc82SMarcel Holtmann if (ev->status) 2926b6a0dc82SMarcel Holtmann hci_conn_del(conn); 2927b6a0dc82SMarcel Holtmann 2928b6a0dc82SMarcel Holtmann unlock: 2929b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 2930a9de9248SMarcel Holtmann } 2931a9de9248SMarcel Holtmann 29326039aa73SGustavo Padovan static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, 2933807deac2SGustavo Padovan struct sk_buff *skb) 2934a9de9248SMarcel Holtmann { 2935a9de9248SMarcel Holtmann struct inquiry_data data; 2936a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 2937a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 29389d939d94SVishal Agarwal size_t eir_len; 2939a9de9248SMarcel Holtmann 2940a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 2941a9de9248SMarcel Holtmann 2942a9de9248SMarcel Holtmann if (!num_rsp) 2943a9de9248SMarcel Holtmann return; 2944a9de9248SMarcel Holtmann 29451519cc17SAndre Guedes if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) 29461519cc17SAndre Guedes return; 29471519cc17SAndre Guedes 2948a9de9248SMarcel Holtmann hci_dev_lock(hdev); 2949a9de9248SMarcel Holtmann 2950e17acd40SJohan Hedberg for (; num_rsp; num_rsp--, info++) { 2951388fc8faSJohan Hedberg bool name_known, ssp; 2952561aafbcSJohan Hedberg 2953a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 2954a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 2955a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 2956a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 2957a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 2958a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 2959a9de9248SMarcel Holtmann data.rssi = info->rssi; 296041a96212SMarcel Holtmann data.ssp_mode = 0x01; 2961561aafbcSJohan Hedberg 2962a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 29634ddb1930SJohan Hedberg name_known = eir_has_data_type(info->data, 29644ddb1930SJohan Hedberg sizeof(info->data), 29654ddb1930SJohan Hedberg EIR_NAME_COMPLETE); 2966561aafbcSJohan Hedberg else 2967561aafbcSJohan Hedberg name_known = true; 2968561aafbcSJohan Hedberg 2969388fc8faSJohan Hedberg name_known = hci_inquiry_cache_update(hdev, &data, name_known, 2970388fc8faSJohan Hedberg &ssp); 29719d939d94SVishal Agarwal eir_len = eir_get_length(info->data, sizeof(info->data)); 297248264f06SJohan Hedberg mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, 297304124681SGustavo F. Padovan info->dev_class, info->rssi, !name_known, 29749d939d94SVishal Agarwal ssp, info->data, eir_len); 2975a9de9248SMarcel Holtmann } 2976a9de9248SMarcel Holtmann 2977a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 2978a9de9248SMarcel Holtmann } 2979a9de9248SMarcel Holtmann 29801c2e0041SJohan Hedberg static void hci_key_refresh_complete_evt(struct hci_dev *hdev, 29811c2e0041SJohan Hedberg struct sk_buff *skb) 29821c2e0041SJohan Hedberg { 29831c2e0041SJohan Hedberg struct hci_ev_key_refresh_complete *ev = (void *) skb->data; 29841c2e0041SJohan Hedberg struct hci_conn *conn; 29851c2e0041SJohan Hedberg 29869f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status, 29871c2e0041SJohan Hedberg __le16_to_cpu(ev->handle)); 29881c2e0041SJohan Hedberg 29891c2e0041SJohan Hedberg hci_dev_lock(hdev); 29901c2e0041SJohan Hedberg 29911c2e0041SJohan Hedberg conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 29921c2e0041SJohan Hedberg if (!conn) 29931c2e0041SJohan Hedberg goto unlock; 29941c2e0041SJohan Hedberg 29951c2e0041SJohan Hedberg if (!ev->status) 29961c2e0041SJohan Hedberg conn->sec_level = conn->pending_sec_level; 29971c2e0041SJohan Hedberg 29981c2e0041SJohan Hedberg clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 29991c2e0041SJohan Hedberg 30001c2e0041SJohan Hedberg if (ev->status && conn->state == BT_CONNECTED) { 3001bed71748SAndre Guedes hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); 300276a68ba0SDavid Herrmann hci_conn_drop(conn); 30031c2e0041SJohan Hedberg goto unlock; 30041c2e0041SJohan Hedberg } 30051c2e0041SJohan Hedberg 30061c2e0041SJohan Hedberg if (conn->state == BT_CONFIG) { 30071c2e0041SJohan Hedberg if (!ev->status) 30081c2e0041SJohan Hedberg conn->state = BT_CONNECTED; 30091c2e0041SJohan Hedberg 30101c2e0041SJohan Hedberg hci_proto_connect_cfm(conn, ev->status); 301176a68ba0SDavid Herrmann hci_conn_drop(conn); 30121c2e0041SJohan Hedberg } else { 30131c2e0041SJohan Hedberg hci_auth_cfm(conn, ev->status); 30141c2e0041SJohan Hedberg 30151c2e0041SJohan Hedberg hci_conn_hold(conn); 30161c2e0041SJohan Hedberg conn->disc_timeout = HCI_DISCONN_TIMEOUT; 301776a68ba0SDavid Herrmann hci_conn_drop(conn); 30181c2e0041SJohan Hedberg } 30191c2e0041SJohan Hedberg 30201c2e0041SJohan Hedberg unlock: 30211c2e0041SJohan Hedberg hci_dev_unlock(hdev); 30221c2e0041SJohan Hedberg } 30231c2e0041SJohan Hedberg 30246039aa73SGustavo Padovan static u8 hci_get_auth_req(struct hci_conn *conn) 302517fa4b9dSJohan Hedberg { 302617fa4b9dSJohan Hedberg /* If remote requests dedicated bonding follow that lead */ 302717fa4b9dSJohan Hedberg if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) { 302817fa4b9dSJohan Hedberg /* If both remote and local IO capabilities allow MITM 302917fa4b9dSJohan Hedberg * protection then require it, otherwise don't */ 303017fa4b9dSJohan Hedberg if (conn->remote_cap == 0x03 || conn->io_capability == 0x03) 303117fa4b9dSJohan Hedberg return 0x02; 303217fa4b9dSJohan Hedberg else 303317fa4b9dSJohan Hedberg return 0x03; 303417fa4b9dSJohan Hedberg } 303517fa4b9dSJohan Hedberg 303617fa4b9dSJohan Hedberg /* If remote requests no-bonding follow that lead */ 303717fa4b9dSJohan Hedberg if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01) 303858797bf7SWaldemar Rymarkiewicz return conn->remote_auth | (conn->auth_type & 0x01); 303917fa4b9dSJohan Hedberg 304017fa4b9dSJohan Hedberg return conn->auth_type; 304117fa4b9dSJohan Hedberg } 304217fa4b9dSJohan Hedberg 30436039aa73SGustavo Padovan static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 30440493684eSMarcel Holtmann { 30450493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 30460493684eSMarcel Holtmann struct hci_conn *conn; 30470493684eSMarcel Holtmann 30480493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 30490493684eSMarcel Holtmann 30500493684eSMarcel Holtmann hci_dev_lock(hdev); 30510493684eSMarcel Holtmann 30520493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 305303b555e1SJohan Hedberg if (!conn) 305403b555e1SJohan Hedberg goto unlock; 305503b555e1SJohan Hedberg 30560493684eSMarcel Holtmann hci_conn_hold(conn); 30570493684eSMarcel Holtmann 3058a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 305903b555e1SJohan Hedberg goto unlock; 306003b555e1SJohan Hedberg 3061a8b2d5c2SJohan Hedberg if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) || 306203b555e1SJohan Hedberg (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { 306317fa4b9dSJohan Hedberg struct hci_cp_io_capability_reply cp; 306417fa4b9dSJohan Hedberg 306517fa4b9dSJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 30667a7f1e7cSHemant Gupta /* Change the IO capability from KeyboardDisplay 30677a7f1e7cSHemant Gupta * to DisplayYesNo as it is not supported by BT spec. */ 30687a7f1e7cSHemant Gupta cp.capability = (conn->io_capability == 0x04) ? 30697a7f1e7cSHemant Gupta 0x01 : conn->io_capability; 30707cbc9bd9SJohan Hedberg conn->auth_type = hci_get_auth_req(conn); 30717cbc9bd9SJohan Hedberg cp.authentication = conn->auth_type; 307217fa4b9dSJohan Hedberg 30738fc9ced3SGustavo Padovan if (hci_find_remote_oob_data(hdev, &conn->dst) && 30748fc9ced3SGustavo Padovan (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags))) 3075ce85ee13SSzymon Janc cp.oob_data = 0x01; 3076ce85ee13SSzymon Janc else 3077ce85ee13SSzymon Janc cp.oob_data = 0x00; 3078ce85ee13SSzymon Janc 307917fa4b9dSJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, 308017fa4b9dSJohan Hedberg sizeof(cp), &cp); 308103b555e1SJohan Hedberg } else { 308203b555e1SJohan Hedberg struct hci_cp_io_capability_neg_reply cp; 308303b555e1SJohan Hedberg 308403b555e1SJohan Hedberg bacpy(&cp.bdaddr, &ev->bdaddr); 30859f5a0d7bSAndrei Emeltchenko cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED; 308603b555e1SJohan Hedberg 308703b555e1SJohan Hedberg hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, 308803b555e1SJohan Hedberg sizeof(cp), &cp); 308903b555e1SJohan Hedberg } 309003b555e1SJohan Hedberg 309103b555e1SJohan Hedberg unlock: 309203b555e1SJohan Hedberg hci_dev_unlock(hdev); 309303b555e1SJohan Hedberg } 309403b555e1SJohan Hedberg 30956039aa73SGustavo Padovan static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) 309603b555e1SJohan Hedberg { 309703b555e1SJohan Hedberg struct hci_ev_io_capa_reply *ev = (void *) skb->data; 309803b555e1SJohan Hedberg struct hci_conn *conn; 309903b555e1SJohan Hedberg 310003b555e1SJohan Hedberg BT_DBG("%s", hdev->name); 310103b555e1SJohan Hedberg 310203b555e1SJohan Hedberg hci_dev_lock(hdev); 310303b555e1SJohan Hedberg 310403b555e1SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 310503b555e1SJohan Hedberg if (!conn) 310603b555e1SJohan Hedberg goto unlock; 310703b555e1SJohan Hedberg 310803b555e1SJohan Hedberg conn->remote_cap = ev->capability; 310903b555e1SJohan Hedberg conn->remote_auth = ev->authentication; 311058a681efSJohan Hedberg if (ev->oob_data) 311158a681efSJohan Hedberg set_bit(HCI_CONN_REMOTE_OOB, &conn->flags); 311203b555e1SJohan Hedberg 311303b555e1SJohan Hedberg unlock: 31140493684eSMarcel Holtmann hci_dev_unlock(hdev); 31150493684eSMarcel Holtmann } 31160493684eSMarcel Holtmann 31176039aa73SGustavo Padovan static void hci_user_confirm_request_evt(struct hci_dev *hdev, 3118a5c29683SJohan Hedberg struct sk_buff *skb) 3119a5c29683SJohan Hedberg { 3120a5c29683SJohan Hedberg struct hci_ev_user_confirm_req *ev = (void *) skb->data; 312155bc1a37SJohan Hedberg int loc_mitm, rem_mitm, confirm_hint = 0; 31227a828908SJohan Hedberg struct hci_conn *conn; 3123a5c29683SJohan Hedberg 3124a5c29683SJohan Hedberg BT_DBG("%s", hdev->name); 3125a5c29683SJohan Hedberg 3126a5c29683SJohan Hedberg hci_dev_lock(hdev); 3127a5c29683SJohan Hedberg 3128a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 31297a828908SJohan Hedberg goto unlock; 31307a828908SJohan Hedberg 31317a828908SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 31327a828908SJohan Hedberg if (!conn) 31337a828908SJohan Hedberg goto unlock; 31347a828908SJohan Hedberg 31357a828908SJohan Hedberg loc_mitm = (conn->auth_type & 0x01); 31367a828908SJohan Hedberg rem_mitm = (conn->remote_auth & 0x01); 31377a828908SJohan Hedberg 31387a828908SJohan Hedberg /* If we require MITM but the remote device can't provide that 31397a828908SJohan Hedberg * (it has NoInputNoOutput) then reject the confirmation 31407a828908SJohan Hedberg * request. The only exception is when we're dedicated bonding 31417a828908SJohan Hedberg * initiators (connect_cfm_cb set) since then we always have the MITM 31427a828908SJohan Hedberg * bit set. */ 31437a828908SJohan Hedberg if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) { 31447a828908SJohan Hedberg BT_DBG("Rejecting request: remote device can't provide MITM"); 31457a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, 31467a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 31477a828908SJohan Hedberg goto unlock; 31487a828908SJohan Hedberg } 31497a828908SJohan Hedberg 31507a828908SJohan Hedberg /* If no side requires MITM protection; auto-accept */ 31517a828908SJohan Hedberg if ((!loc_mitm || conn->remote_cap == 0x03) && 31527a828908SJohan Hedberg (!rem_mitm || conn->io_capability == 0x03)) { 315355bc1a37SJohan Hedberg 315455bc1a37SJohan Hedberg /* If we're not the initiators request authorization to 315555bc1a37SJohan Hedberg * proceed from user space (mgmt_user_confirm with 315655bc1a37SJohan Hedberg * confirm_hint set to 1). */ 315751a8efd7SJohan Hedberg if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 315855bc1a37SJohan Hedberg BT_DBG("Confirming auto-accept as acceptor"); 315955bc1a37SJohan Hedberg confirm_hint = 1; 316055bc1a37SJohan Hedberg goto confirm; 316155bc1a37SJohan Hedberg } 316255bc1a37SJohan Hedberg 31639f61656aSJohan Hedberg BT_DBG("Auto-accept of user confirmation with %ums delay", 31649f61656aSJohan Hedberg hdev->auto_accept_delay); 31659f61656aSJohan Hedberg 31669f61656aSJohan Hedberg if (hdev->auto_accept_delay > 0) { 31679f61656aSJohan Hedberg int delay = msecs_to_jiffies(hdev->auto_accept_delay); 31689f61656aSJohan Hedberg mod_timer(&conn->auto_accept_timer, jiffies + delay); 31699f61656aSJohan Hedberg goto unlock; 31709f61656aSJohan Hedberg } 31719f61656aSJohan Hedberg 31727a828908SJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, 31737a828908SJohan Hedberg sizeof(ev->bdaddr), &ev->bdaddr); 31747a828908SJohan Hedberg goto unlock; 31757a828908SJohan Hedberg } 31767a828908SJohan Hedberg 317755bc1a37SJohan Hedberg confirm: 3178272d90dfSJohan Hedberg mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey, 317955bc1a37SJohan Hedberg confirm_hint); 3180a5c29683SJohan Hedberg 31817a828908SJohan Hedberg unlock: 3182a5c29683SJohan Hedberg hci_dev_unlock(hdev); 3183a5c29683SJohan Hedberg } 3184a5c29683SJohan Hedberg 31856039aa73SGustavo Padovan static void hci_user_passkey_request_evt(struct hci_dev *hdev, 31861143d458SBrian Gix struct sk_buff *skb) 31871143d458SBrian Gix { 31881143d458SBrian Gix struct hci_ev_user_passkey_req *ev = (void *) skb->data; 31891143d458SBrian Gix 31901143d458SBrian Gix BT_DBG("%s", hdev->name); 31911143d458SBrian Gix 3192a8b2d5c2SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 3193272d90dfSJohan Hedberg mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); 31941143d458SBrian Gix } 31951143d458SBrian Gix 319692a25256SJohan Hedberg static void hci_user_passkey_notify_evt(struct hci_dev *hdev, 319792a25256SJohan Hedberg struct sk_buff *skb) 319892a25256SJohan Hedberg { 319992a25256SJohan Hedberg struct hci_ev_user_passkey_notify *ev = (void *) skb->data; 320092a25256SJohan Hedberg struct hci_conn *conn; 320192a25256SJohan Hedberg 320292a25256SJohan Hedberg BT_DBG("%s", hdev->name); 320392a25256SJohan Hedberg 320492a25256SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 320592a25256SJohan Hedberg if (!conn) 320692a25256SJohan Hedberg return; 320792a25256SJohan Hedberg 320892a25256SJohan Hedberg conn->passkey_notify = __le32_to_cpu(ev->passkey); 320992a25256SJohan Hedberg conn->passkey_entered = 0; 321092a25256SJohan Hedberg 321192a25256SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 321292a25256SJohan Hedberg mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, 321392a25256SJohan Hedberg conn->dst_type, conn->passkey_notify, 321492a25256SJohan Hedberg conn->passkey_entered); 321592a25256SJohan Hedberg } 321692a25256SJohan Hedberg 321792a25256SJohan Hedberg static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 321892a25256SJohan Hedberg { 321992a25256SJohan Hedberg struct hci_ev_keypress_notify *ev = (void *) skb->data; 322092a25256SJohan Hedberg struct hci_conn *conn; 322192a25256SJohan Hedberg 322292a25256SJohan Hedberg BT_DBG("%s", hdev->name); 322392a25256SJohan Hedberg 322492a25256SJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 322592a25256SJohan Hedberg if (!conn) 322692a25256SJohan Hedberg return; 322792a25256SJohan Hedberg 322892a25256SJohan Hedberg switch (ev->type) { 322992a25256SJohan Hedberg case HCI_KEYPRESS_STARTED: 323092a25256SJohan Hedberg conn->passkey_entered = 0; 323192a25256SJohan Hedberg return; 323292a25256SJohan Hedberg 323392a25256SJohan Hedberg case HCI_KEYPRESS_ENTERED: 323492a25256SJohan Hedberg conn->passkey_entered++; 323592a25256SJohan Hedberg break; 323692a25256SJohan Hedberg 323792a25256SJohan Hedberg case HCI_KEYPRESS_ERASED: 323892a25256SJohan Hedberg conn->passkey_entered--; 323992a25256SJohan Hedberg break; 324092a25256SJohan Hedberg 324192a25256SJohan Hedberg case HCI_KEYPRESS_CLEARED: 324292a25256SJohan Hedberg conn->passkey_entered = 0; 324392a25256SJohan Hedberg break; 324492a25256SJohan Hedberg 324592a25256SJohan Hedberg case HCI_KEYPRESS_COMPLETED: 324692a25256SJohan Hedberg return; 324792a25256SJohan Hedberg } 324892a25256SJohan Hedberg 324992a25256SJohan Hedberg if (test_bit(HCI_MGMT, &hdev->dev_flags)) 325092a25256SJohan Hedberg mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, 325192a25256SJohan Hedberg conn->dst_type, conn->passkey_notify, 325292a25256SJohan Hedberg conn->passkey_entered); 325392a25256SJohan Hedberg } 325492a25256SJohan Hedberg 32556039aa73SGustavo Padovan static void hci_simple_pair_complete_evt(struct hci_dev *hdev, 3256807deac2SGustavo Padovan struct sk_buff *skb) 32570493684eSMarcel Holtmann { 32580493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 32590493684eSMarcel Holtmann struct hci_conn *conn; 32600493684eSMarcel Holtmann 32610493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 32620493684eSMarcel Holtmann 32630493684eSMarcel Holtmann hci_dev_lock(hdev); 32640493684eSMarcel Holtmann 32650493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 32662a611692SJohan Hedberg if (!conn) 32672a611692SJohan Hedberg goto unlock; 32682a611692SJohan Hedberg 32692a611692SJohan Hedberg /* To avoid duplicate auth_failed events to user space we check 32702a611692SJohan Hedberg * the HCI_CONN_AUTH_PEND flag which will be set if we 32712a611692SJohan Hedberg * initiated the authentication. A traditional auth_complete 32722a611692SJohan Hedberg * event gets always produced as initiator and is also mapped to 32732a611692SJohan Hedberg * the mgmt_auth_failed event */ 3274fa1bd918SMikel Astiz if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status) 3275bab73cb6SJohan Hedberg mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, 3276bab73cb6SJohan Hedberg ev->status); 32772a611692SJohan Hedberg 327876a68ba0SDavid Herrmann hci_conn_drop(conn); 32790493684eSMarcel Holtmann 32802a611692SJohan Hedberg unlock: 32810493684eSMarcel Holtmann hci_dev_unlock(hdev); 32820493684eSMarcel Holtmann } 32830493684eSMarcel Holtmann 32846039aa73SGustavo Padovan static void hci_remote_host_features_evt(struct hci_dev *hdev, 3285807deac2SGustavo Padovan struct sk_buff *skb) 328641a96212SMarcel Holtmann { 328741a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 328841a96212SMarcel Holtmann struct inquiry_entry *ie; 3289cad718edSJohan Hedberg struct hci_conn *conn; 329041a96212SMarcel Holtmann 329141a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 329241a96212SMarcel Holtmann 329341a96212SMarcel Holtmann hci_dev_lock(hdev); 329441a96212SMarcel Holtmann 3295cad718edSJohan Hedberg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 3296cad718edSJohan Hedberg if (conn) 3297cad718edSJohan Hedberg memcpy(conn->features[1], ev->features, 8); 3298cad718edSJohan Hedberg 3299cc11b9c1SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); 3300cc11b9c1SAndrei Emeltchenko if (ie) 330102b7cc62SJohan Hedberg ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP); 330241a96212SMarcel Holtmann 330341a96212SMarcel Holtmann hci_dev_unlock(hdev); 330441a96212SMarcel Holtmann } 330541a96212SMarcel Holtmann 33066039aa73SGustavo Padovan static void hci_remote_oob_data_request_evt(struct hci_dev *hdev, 33072763eda6SSzymon Janc struct sk_buff *skb) 33082763eda6SSzymon Janc { 33092763eda6SSzymon Janc struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; 33102763eda6SSzymon Janc struct oob_data *data; 33112763eda6SSzymon Janc 33122763eda6SSzymon Janc BT_DBG("%s", hdev->name); 33132763eda6SSzymon Janc 33142763eda6SSzymon Janc hci_dev_lock(hdev); 33152763eda6SSzymon Janc 3316a8b2d5c2SJohan Hedberg if (!test_bit(HCI_MGMT, &hdev->dev_flags)) 3317e1ba1f15SSzymon Janc goto unlock; 3318e1ba1f15SSzymon Janc 33192763eda6SSzymon Janc data = hci_find_remote_oob_data(hdev, &ev->bdaddr); 33202763eda6SSzymon Janc if (data) { 33212763eda6SSzymon Janc struct hci_cp_remote_oob_data_reply cp; 33222763eda6SSzymon Janc 33232763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 33242763eda6SSzymon Janc memcpy(cp.hash, data->hash, sizeof(cp.hash)); 33252763eda6SSzymon Janc memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); 33262763eda6SSzymon Janc 33272763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), 33282763eda6SSzymon Janc &cp); 33292763eda6SSzymon Janc } else { 33302763eda6SSzymon Janc struct hci_cp_remote_oob_data_neg_reply cp; 33312763eda6SSzymon Janc 33322763eda6SSzymon Janc bacpy(&cp.bdaddr, &ev->bdaddr); 33332763eda6SSzymon Janc hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), 33342763eda6SSzymon Janc &cp); 33352763eda6SSzymon Janc } 33362763eda6SSzymon Janc 3337e1ba1f15SSzymon Janc unlock: 33382763eda6SSzymon Janc hci_dev_unlock(hdev); 33392763eda6SSzymon Janc } 33402763eda6SSzymon Janc 3341d5e91192SAndrei Emeltchenko static void hci_phy_link_complete_evt(struct hci_dev *hdev, 3342d5e91192SAndrei Emeltchenko struct sk_buff *skb) 3343d5e91192SAndrei Emeltchenko { 3344d5e91192SAndrei Emeltchenko struct hci_ev_phy_link_complete *ev = (void *) skb->data; 3345d5e91192SAndrei Emeltchenko struct hci_conn *hcon, *bredr_hcon; 3346d5e91192SAndrei Emeltchenko 3347d5e91192SAndrei Emeltchenko BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle, 3348d5e91192SAndrei Emeltchenko ev->status); 3349d5e91192SAndrei Emeltchenko 3350d5e91192SAndrei Emeltchenko hci_dev_lock(hdev); 3351d5e91192SAndrei Emeltchenko 3352d5e91192SAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 3353d5e91192SAndrei Emeltchenko if (!hcon) { 3354d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 3355d5e91192SAndrei Emeltchenko return; 3356d5e91192SAndrei Emeltchenko } 3357d5e91192SAndrei Emeltchenko 3358d5e91192SAndrei Emeltchenko if (ev->status) { 3359d5e91192SAndrei Emeltchenko hci_conn_del(hcon); 3360d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 3361d5e91192SAndrei Emeltchenko return; 3362d5e91192SAndrei Emeltchenko } 3363d5e91192SAndrei Emeltchenko 3364d5e91192SAndrei Emeltchenko bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon; 3365d5e91192SAndrei Emeltchenko 3366d5e91192SAndrei Emeltchenko hcon->state = BT_CONNECTED; 3367d5e91192SAndrei Emeltchenko bacpy(&hcon->dst, &bredr_hcon->dst); 3368d5e91192SAndrei Emeltchenko 3369d5e91192SAndrei Emeltchenko hci_conn_hold(hcon); 3370d5e91192SAndrei Emeltchenko hcon->disc_timeout = HCI_DISCONN_TIMEOUT; 337176a68ba0SDavid Herrmann hci_conn_drop(hcon); 3372d5e91192SAndrei Emeltchenko 3373d5e91192SAndrei Emeltchenko hci_conn_add_sysfs(hcon); 3374d5e91192SAndrei Emeltchenko 3375cf70ff22SAndrei Emeltchenko amp_physical_cfm(bredr_hcon, hcon); 3376cf70ff22SAndrei Emeltchenko 3377d5e91192SAndrei Emeltchenko hci_dev_unlock(hdev); 3378d5e91192SAndrei Emeltchenko } 3379d5e91192SAndrei Emeltchenko 338027695fb4SAndrei Emeltchenko static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 338127695fb4SAndrei Emeltchenko { 338227695fb4SAndrei Emeltchenko struct hci_ev_logical_link_complete *ev = (void *) skb->data; 338327695fb4SAndrei Emeltchenko struct hci_conn *hcon; 338427695fb4SAndrei Emeltchenko struct hci_chan *hchan; 338527695fb4SAndrei Emeltchenko struct amp_mgr *mgr; 338627695fb4SAndrei Emeltchenko 338727695fb4SAndrei Emeltchenko BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x", 338827695fb4SAndrei Emeltchenko hdev->name, le16_to_cpu(ev->handle), ev->phy_handle, 338927695fb4SAndrei Emeltchenko ev->status); 339027695fb4SAndrei Emeltchenko 339127695fb4SAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 339227695fb4SAndrei Emeltchenko if (!hcon) 339327695fb4SAndrei Emeltchenko return; 339427695fb4SAndrei Emeltchenko 339527695fb4SAndrei Emeltchenko /* Create AMP hchan */ 339627695fb4SAndrei Emeltchenko hchan = hci_chan_create(hcon); 339727695fb4SAndrei Emeltchenko if (!hchan) 339827695fb4SAndrei Emeltchenko return; 339927695fb4SAndrei Emeltchenko 340027695fb4SAndrei Emeltchenko hchan->handle = le16_to_cpu(ev->handle); 340127695fb4SAndrei Emeltchenko 340227695fb4SAndrei Emeltchenko BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan); 340327695fb4SAndrei Emeltchenko 340427695fb4SAndrei Emeltchenko mgr = hcon->amp_mgr; 340527695fb4SAndrei Emeltchenko if (mgr && mgr->bredr_chan) { 340627695fb4SAndrei Emeltchenko struct l2cap_chan *bredr_chan = mgr->bredr_chan; 340727695fb4SAndrei Emeltchenko 340827695fb4SAndrei Emeltchenko l2cap_chan_lock(bredr_chan); 340927695fb4SAndrei Emeltchenko 341027695fb4SAndrei Emeltchenko bredr_chan->conn->mtu = hdev->block_mtu; 341127695fb4SAndrei Emeltchenko l2cap_logical_cfm(bredr_chan, hchan, 0); 341227695fb4SAndrei Emeltchenko hci_conn_hold(hcon); 341327695fb4SAndrei Emeltchenko 341427695fb4SAndrei Emeltchenko l2cap_chan_unlock(bredr_chan); 341527695fb4SAndrei Emeltchenko } 341627695fb4SAndrei Emeltchenko } 341727695fb4SAndrei Emeltchenko 3418606e2a10SAndrei Emeltchenko static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev, 3419606e2a10SAndrei Emeltchenko struct sk_buff *skb) 3420606e2a10SAndrei Emeltchenko { 3421606e2a10SAndrei Emeltchenko struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data; 3422606e2a10SAndrei Emeltchenko struct hci_chan *hchan; 3423606e2a10SAndrei Emeltchenko 3424606e2a10SAndrei Emeltchenko BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name, 3425606e2a10SAndrei Emeltchenko le16_to_cpu(ev->handle), ev->status); 3426606e2a10SAndrei Emeltchenko 3427606e2a10SAndrei Emeltchenko if (ev->status) 3428606e2a10SAndrei Emeltchenko return; 3429606e2a10SAndrei Emeltchenko 3430606e2a10SAndrei Emeltchenko hci_dev_lock(hdev); 3431606e2a10SAndrei Emeltchenko 3432606e2a10SAndrei Emeltchenko hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle)); 3433606e2a10SAndrei Emeltchenko if (!hchan) 3434606e2a10SAndrei Emeltchenko goto unlock; 3435606e2a10SAndrei Emeltchenko 3436606e2a10SAndrei Emeltchenko amp_destroy_logical_link(hchan, ev->reason); 3437606e2a10SAndrei Emeltchenko 3438606e2a10SAndrei Emeltchenko unlock: 3439606e2a10SAndrei Emeltchenko hci_dev_unlock(hdev); 3440606e2a10SAndrei Emeltchenko } 3441606e2a10SAndrei Emeltchenko 34429eef6b3aSAndrei Emeltchenko static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev, 34439eef6b3aSAndrei Emeltchenko struct sk_buff *skb) 34449eef6b3aSAndrei Emeltchenko { 34459eef6b3aSAndrei Emeltchenko struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data; 34469eef6b3aSAndrei Emeltchenko struct hci_conn *hcon; 34479eef6b3aSAndrei Emeltchenko 34489eef6b3aSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 34499eef6b3aSAndrei Emeltchenko 34509eef6b3aSAndrei Emeltchenko if (ev->status) 34519eef6b3aSAndrei Emeltchenko return; 34529eef6b3aSAndrei Emeltchenko 34539eef6b3aSAndrei Emeltchenko hci_dev_lock(hdev); 34549eef6b3aSAndrei Emeltchenko 34559eef6b3aSAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 34569eef6b3aSAndrei Emeltchenko if (hcon) { 34579eef6b3aSAndrei Emeltchenko hcon->state = BT_CLOSED; 34589eef6b3aSAndrei Emeltchenko hci_conn_del(hcon); 34599eef6b3aSAndrei Emeltchenko } 34609eef6b3aSAndrei Emeltchenko 34619eef6b3aSAndrei Emeltchenko hci_dev_unlock(hdev); 34629eef6b3aSAndrei Emeltchenko } 34639eef6b3aSAndrei Emeltchenko 34646039aa73SGustavo Padovan static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 3465fcd89c09SVille Tervo { 3466fcd89c09SVille Tervo struct hci_ev_le_conn_complete *ev = (void *) skb->data; 3467fcd89c09SVille Tervo struct hci_conn *conn; 3468fcd89c09SVille Tervo 34699f1db00cSAndrei Emeltchenko BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); 3470fcd89c09SVille Tervo 3471fcd89c09SVille Tervo hci_dev_lock(hdev); 3472fcd89c09SVille Tervo 34734f72b329SAndrzej Kaczmarek conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); 3474b62f328bSVille Tervo if (!conn) { 3475b62f328bSVille Tervo conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); 3476b62f328bSVille Tervo if (!conn) { 3477b62f328bSVille Tervo BT_ERR("No memory for new connection"); 3478230fd16aSAndre Guedes goto unlock; 3479b62f328bSVille Tervo } 348029b7988aSAndre Guedes 348129b7988aSAndre Guedes conn->dst_type = ev->bdaddr_type; 3482b9b343d2SAndre Guedes 3483b9b343d2SAndre Guedes if (ev->role == LE_CONN_ROLE_MASTER) { 3484b9b343d2SAndre Guedes conn->out = true; 3485b9b343d2SAndre Guedes conn->link_mode |= HCI_LM_MASTER; 3486b9b343d2SAndre Guedes } 3487b62f328bSVille Tervo } 3488fcd89c09SVille Tervo 3489cd17decbSAndre Guedes if (ev->status) { 3490cd17decbSAndre Guedes mgmt_connect_failed(hdev, &conn->dst, conn->type, 3491cd17decbSAndre Guedes conn->dst_type, ev->status); 3492cd17decbSAndre Guedes hci_proto_connect_cfm(conn, ev->status); 3493cd17decbSAndre Guedes conn->state = BT_CLOSED; 3494cd17decbSAndre Guedes hci_conn_del(conn); 3495cd17decbSAndre Guedes goto unlock; 3496cd17decbSAndre Guedes } 3497cd17decbSAndre Guedes 3498b644ba33SJohan Hedberg if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) 3499b644ba33SJohan Hedberg mgmt_device_connected(hdev, &ev->bdaddr, conn->type, 350095b23582SSzymon Janc conn->dst_type, 0, NULL, 0, NULL); 350183bc71b4SVinicius Costa Gomes 35027b5c0d52SVinicius Costa Gomes conn->sec_level = BT_SECURITY_LOW; 3503fcd89c09SVille Tervo conn->handle = __le16_to_cpu(ev->handle); 3504fcd89c09SVille Tervo conn->state = BT_CONNECTED; 3505fcd89c09SVille Tervo 3506fcd89c09SVille Tervo hci_conn_add_sysfs(conn); 3507fcd89c09SVille Tervo 3508fcd89c09SVille Tervo hci_proto_connect_cfm(conn, ev->status); 3509fcd89c09SVille Tervo 3510fcd89c09SVille Tervo unlock: 3511fcd89c09SVille Tervo hci_dev_unlock(hdev); 3512fcd89c09SVille Tervo } 3513fcd89c09SVille Tervo 35146039aa73SGustavo Padovan static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) 35159aa04c91SAndre Guedes { 3516e95beb41SAndre Guedes u8 num_reports = skb->data[0]; 3517e95beb41SAndre Guedes void *ptr = &skb->data[1]; 35183c9e9195SAndre Guedes s8 rssi; 35199aa04c91SAndre Guedes 3520e95beb41SAndre Guedes while (num_reports--) { 3521e95beb41SAndre Guedes struct hci_ev_le_advertising_info *ev = ptr; 3522e95beb41SAndre Guedes 35233c9e9195SAndre Guedes rssi = ev->data[ev->length]; 35243c9e9195SAndre Guedes mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type, 352504124681SGustavo F. Padovan NULL, rssi, 0, 1, ev->data, ev->length); 35263c9e9195SAndre Guedes 3527e95beb41SAndre Guedes ptr += sizeof(*ev) + ev->length + 1; 35289aa04c91SAndre Guedes } 35299aa04c91SAndre Guedes } 35309aa04c91SAndre Guedes 35316039aa73SGustavo Padovan static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 3532a7a595f6SVinicius Costa Gomes { 3533a7a595f6SVinicius Costa Gomes struct hci_ev_le_ltk_req *ev = (void *) skb->data; 3534a7a595f6SVinicius Costa Gomes struct hci_cp_le_ltk_reply cp; 3535bea710feSVinicius Costa Gomes struct hci_cp_le_ltk_neg_reply neg; 3536a7a595f6SVinicius Costa Gomes struct hci_conn *conn; 3537c9839a11SVinicius Costa Gomes struct smp_ltk *ltk; 3538a7a595f6SVinicius Costa Gomes 35399f1db00cSAndrei Emeltchenko BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle)); 3540a7a595f6SVinicius Costa Gomes 3541a7a595f6SVinicius Costa Gomes hci_dev_lock(hdev); 3542a7a595f6SVinicius Costa Gomes 3543a7a595f6SVinicius Costa Gomes conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 3544bea710feSVinicius Costa Gomes if (conn == NULL) 3545bea710feSVinicius Costa Gomes goto not_found; 3546a7a595f6SVinicius Costa Gomes 3547bea710feSVinicius Costa Gomes ltk = hci_find_ltk(hdev, ev->ediv, ev->random); 3548bea710feSVinicius Costa Gomes if (ltk == NULL) 3549bea710feSVinicius Costa Gomes goto not_found; 3550bea710feSVinicius Costa Gomes 3551bea710feSVinicius Costa Gomes memcpy(cp.ltk, ltk->val, sizeof(ltk->val)); 3552a7a595f6SVinicius Costa Gomes cp.handle = cpu_to_le16(conn->handle); 3553c9839a11SVinicius Costa Gomes 3554c9839a11SVinicius Costa Gomes if (ltk->authenticated) 3555c9839a11SVinicius Costa Gomes conn->sec_level = BT_SECURITY_HIGH; 3556a7a595f6SVinicius Costa Gomes 3557a7a595f6SVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); 3558a7a595f6SVinicius Costa Gomes 3559c9839a11SVinicius Costa Gomes if (ltk->type & HCI_SMP_STK) { 3560c9839a11SVinicius Costa Gomes list_del(<k->list); 3561c9839a11SVinicius Costa Gomes kfree(ltk); 3562c9839a11SVinicius Costa Gomes } 3563c9839a11SVinicius Costa Gomes 3564a7a595f6SVinicius Costa Gomes hci_dev_unlock(hdev); 3565bea710feSVinicius Costa Gomes 3566bea710feSVinicius Costa Gomes return; 3567bea710feSVinicius Costa Gomes 3568bea710feSVinicius Costa Gomes not_found: 3569bea710feSVinicius Costa Gomes neg.handle = ev->handle; 3570bea710feSVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg); 3571bea710feSVinicius Costa Gomes hci_dev_unlock(hdev); 3572a7a595f6SVinicius Costa Gomes } 3573a7a595f6SVinicius Costa Gomes 35746039aa73SGustavo Padovan static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 3575fcd89c09SVille Tervo { 3576fcd89c09SVille Tervo struct hci_ev_le_meta *le_ev = (void *) skb->data; 3577fcd89c09SVille Tervo 3578fcd89c09SVille Tervo skb_pull(skb, sizeof(*le_ev)); 3579fcd89c09SVille Tervo 3580fcd89c09SVille Tervo switch (le_ev->subevent) { 3581fcd89c09SVille Tervo case HCI_EV_LE_CONN_COMPLETE: 3582fcd89c09SVille Tervo hci_le_conn_complete_evt(hdev, skb); 3583fcd89c09SVille Tervo break; 3584fcd89c09SVille Tervo 35859aa04c91SAndre Guedes case HCI_EV_LE_ADVERTISING_REPORT: 35869aa04c91SAndre Guedes hci_le_adv_report_evt(hdev, skb); 35879aa04c91SAndre Guedes break; 35889aa04c91SAndre Guedes 3589a7a595f6SVinicius Costa Gomes case HCI_EV_LE_LTK_REQ: 3590a7a595f6SVinicius Costa Gomes hci_le_ltk_request_evt(hdev, skb); 3591a7a595f6SVinicius Costa Gomes break; 3592a7a595f6SVinicius Costa Gomes 3593fcd89c09SVille Tervo default: 3594fcd89c09SVille Tervo break; 3595fcd89c09SVille Tervo } 3596fcd89c09SVille Tervo } 3597fcd89c09SVille Tervo 35989495b2eeSAndrei Emeltchenko static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb) 35999495b2eeSAndrei Emeltchenko { 36009495b2eeSAndrei Emeltchenko struct hci_ev_channel_selected *ev = (void *) skb->data; 36019495b2eeSAndrei Emeltchenko struct hci_conn *hcon; 36029495b2eeSAndrei Emeltchenko 36039495b2eeSAndrei Emeltchenko BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle); 36049495b2eeSAndrei Emeltchenko 36059495b2eeSAndrei Emeltchenko skb_pull(skb, sizeof(*ev)); 36069495b2eeSAndrei Emeltchenko 36079495b2eeSAndrei Emeltchenko hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); 36089495b2eeSAndrei Emeltchenko if (!hcon) 36099495b2eeSAndrei Emeltchenko return; 36109495b2eeSAndrei Emeltchenko 36119495b2eeSAndrei Emeltchenko amp_read_loc_assoc_final_data(hdev, hcon); 36129495b2eeSAndrei Emeltchenko } 36139495b2eeSAndrei Emeltchenko 36141da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 36151da177e4SLinus Torvalds { 3616a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 3617a9de9248SMarcel Holtmann __u8 event = hdr->evt; 36181da177e4SLinus Torvalds 3619b6ddb638SJohan Hedberg hci_dev_lock(hdev); 3620b6ddb638SJohan Hedberg 3621b6ddb638SJohan Hedberg /* Received events are (currently) only needed when a request is 3622b6ddb638SJohan Hedberg * ongoing so avoid unnecessary memory allocation. 3623b6ddb638SJohan Hedberg */ 3624b6ddb638SJohan Hedberg if (hdev->req_status == HCI_REQ_PEND) { 3625b6ddb638SJohan Hedberg kfree_skb(hdev->recv_evt); 3626b6ddb638SJohan Hedberg hdev->recv_evt = skb_clone(skb, GFP_KERNEL); 3627b6ddb638SJohan Hedberg } 3628b6ddb638SJohan Hedberg 3629b6ddb638SJohan Hedberg hci_dev_unlock(hdev); 3630b6ddb638SJohan Hedberg 36311da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 36321da177e4SLinus Torvalds 363302350a72SJohan Hedberg if (hdev->sent_cmd && bt_cb(hdev->sent_cmd)->req.event == event) { 363402350a72SJohan Hedberg struct hci_command_hdr *hdr = (void *) hdev->sent_cmd->data; 363502350a72SJohan Hedberg u16 opcode = __le16_to_cpu(hdr->opcode); 363602350a72SJohan Hedberg 363702350a72SJohan Hedberg hci_req_cmd_complete(hdev, opcode, 0); 363802350a72SJohan Hedberg } 363902350a72SJohan Hedberg 3640a9de9248SMarcel Holtmann switch (event) { 36411da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 36421da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 36431da177e4SLinus Torvalds break; 36441da177e4SLinus Torvalds 36451da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 36461da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 36471da177e4SLinus Torvalds break; 36481da177e4SLinus Torvalds 3649a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 3650a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 365121d9e30eSMarcel Holtmann break; 365221d9e30eSMarcel Holtmann 36531da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 36541da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 36551da177e4SLinus Torvalds break; 36561da177e4SLinus Torvalds 36571da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 36581da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 36591da177e4SLinus Torvalds break; 36601da177e4SLinus Torvalds 36611da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 36621da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 36631da177e4SLinus Torvalds break; 36641da177e4SLinus Torvalds 3665a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 3666a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 3667a9de9248SMarcel Holtmann break; 3668a9de9248SMarcel Holtmann 36691da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 36701da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 36711da177e4SLinus Torvalds break; 36721da177e4SLinus Torvalds 3673a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 3674a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 3675a9de9248SMarcel Holtmann break; 3676a9de9248SMarcel Holtmann 3677a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 3678a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 3679a9de9248SMarcel Holtmann break; 3680a9de9248SMarcel Holtmann 3681a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 3682a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 3683a9de9248SMarcel Holtmann break; 3684a9de9248SMarcel Holtmann 3685a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 3686a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 3687a9de9248SMarcel Holtmann break; 3688a9de9248SMarcel Holtmann 3689a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 3690a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 3691a9de9248SMarcel Holtmann break; 3692a9de9248SMarcel Holtmann 3693a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 3694a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 3695a9de9248SMarcel Holtmann break; 3696a9de9248SMarcel Holtmann 3697a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 3698a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 36991da177e4SLinus Torvalds break; 37001da177e4SLinus Torvalds 37011da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 37021da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 37031da177e4SLinus Torvalds break; 37041da177e4SLinus Torvalds 37051da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 37061da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 37071da177e4SLinus Torvalds break; 37081da177e4SLinus Torvalds 37091da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 37101da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 37111da177e4SLinus Torvalds break; 37121da177e4SLinus Torvalds 37131da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 37141da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 37151da177e4SLinus Torvalds break; 37161da177e4SLinus Torvalds 3717a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 3718a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 3719a8746417SMarcel Holtmann break; 3720a8746417SMarcel Holtmann 372185a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 372285a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 372385a1e930SMarcel Holtmann break; 372485a1e930SMarcel Holtmann 3725a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 3726a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 3727a9de9248SMarcel Holtmann break; 3728a9de9248SMarcel Holtmann 3729a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 3730a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 3731a9de9248SMarcel Holtmann break; 3732a9de9248SMarcel Holtmann 3733a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 3734a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 3735a9de9248SMarcel Holtmann break; 3736a9de9248SMarcel Holtmann 3737a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 3738a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 37391da177e4SLinus Torvalds break; 37401da177e4SLinus Torvalds 37411c2e0041SJohan Hedberg case HCI_EV_KEY_REFRESH_COMPLETE: 37421c2e0041SJohan Hedberg hci_key_refresh_complete_evt(hdev, skb); 37431c2e0041SJohan Hedberg break; 37441c2e0041SJohan Hedberg 37450493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 37460493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 37470493684eSMarcel Holtmann break; 37480493684eSMarcel Holtmann 374903b555e1SJohan Hedberg case HCI_EV_IO_CAPA_REPLY: 375003b555e1SJohan Hedberg hci_io_capa_reply_evt(hdev, skb); 375103b555e1SJohan Hedberg break; 375203b555e1SJohan Hedberg 3753a5c29683SJohan Hedberg case HCI_EV_USER_CONFIRM_REQUEST: 3754a5c29683SJohan Hedberg hci_user_confirm_request_evt(hdev, skb); 3755a5c29683SJohan Hedberg break; 3756a5c29683SJohan Hedberg 37571143d458SBrian Gix case HCI_EV_USER_PASSKEY_REQUEST: 37581143d458SBrian Gix hci_user_passkey_request_evt(hdev, skb); 37591143d458SBrian Gix break; 37601143d458SBrian Gix 376192a25256SJohan Hedberg case HCI_EV_USER_PASSKEY_NOTIFY: 376292a25256SJohan Hedberg hci_user_passkey_notify_evt(hdev, skb); 376392a25256SJohan Hedberg break; 376492a25256SJohan Hedberg 376592a25256SJohan Hedberg case HCI_EV_KEYPRESS_NOTIFY: 376692a25256SJohan Hedberg hci_keypress_notify_evt(hdev, skb); 376792a25256SJohan Hedberg break; 376892a25256SJohan Hedberg 37690493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 37700493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 37710493684eSMarcel Holtmann break; 37720493684eSMarcel Holtmann 377341a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 377441a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 377541a96212SMarcel Holtmann break; 377641a96212SMarcel Holtmann 3777fcd89c09SVille Tervo case HCI_EV_LE_META: 3778fcd89c09SVille Tervo hci_le_meta_evt(hdev, skb); 3779fcd89c09SVille Tervo break; 3780fcd89c09SVille Tervo 37819495b2eeSAndrei Emeltchenko case HCI_EV_CHANNEL_SELECTED: 37829495b2eeSAndrei Emeltchenko hci_chan_selected_evt(hdev, skb); 37839495b2eeSAndrei Emeltchenko break; 37849495b2eeSAndrei Emeltchenko 37852763eda6SSzymon Janc case HCI_EV_REMOTE_OOB_DATA_REQUEST: 37862763eda6SSzymon Janc hci_remote_oob_data_request_evt(hdev, skb); 37872763eda6SSzymon Janc break; 37882763eda6SSzymon Janc 3789d5e91192SAndrei Emeltchenko case HCI_EV_PHY_LINK_COMPLETE: 3790d5e91192SAndrei Emeltchenko hci_phy_link_complete_evt(hdev, skb); 3791d5e91192SAndrei Emeltchenko break; 3792d5e91192SAndrei Emeltchenko 379327695fb4SAndrei Emeltchenko case HCI_EV_LOGICAL_LINK_COMPLETE: 379427695fb4SAndrei Emeltchenko hci_loglink_complete_evt(hdev, skb); 379527695fb4SAndrei Emeltchenko break; 379627695fb4SAndrei Emeltchenko 3797606e2a10SAndrei Emeltchenko case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE: 3798606e2a10SAndrei Emeltchenko hci_disconn_loglink_complete_evt(hdev, skb); 3799606e2a10SAndrei Emeltchenko break; 3800606e2a10SAndrei Emeltchenko 38019eef6b3aSAndrei Emeltchenko case HCI_EV_DISCONN_PHY_LINK_COMPLETE: 38029eef6b3aSAndrei Emeltchenko hci_disconn_phylink_complete_evt(hdev, skb); 38039eef6b3aSAndrei Emeltchenko break; 38049eef6b3aSAndrei Emeltchenko 380525e89e99SAndrei Emeltchenko case HCI_EV_NUM_COMP_BLOCKS: 380625e89e99SAndrei Emeltchenko hci_num_comp_blocks_evt(hdev, skb); 380725e89e99SAndrei Emeltchenko break; 380825e89e99SAndrei Emeltchenko 38091da177e4SLinus Torvalds default: 38109f1db00cSAndrei Emeltchenko BT_DBG("%s event 0x%2.2x", hdev->name, event); 38111da177e4SLinus Torvalds break; 38121da177e4SLinus Torvalds } 38131da177e4SLinus Torvalds 38141da177e4SLinus Torvalds kfree_skb(skb); 38151da177e4SLinus Torvalds hdev->stat.evt_rx++; 38161da177e4SLinus Torvalds } 3817