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 <linux/module.h> 281da177e4SLinus Torvalds 291da177e4SLinus Torvalds #include <linux/types.h> 301da177e4SLinus Torvalds #include <linux/errno.h> 311da177e4SLinus Torvalds #include <linux/kernel.h> 321da177e4SLinus Torvalds #include <linux/slab.h> 331da177e4SLinus Torvalds #include <linux/poll.h> 341da177e4SLinus Torvalds #include <linux/fcntl.h> 351da177e4SLinus Torvalds #include <linux/init.h> 361da177e4SLinus Torvalds #include <linux/skbuff.h> 371da177e4SLinus Torvalds #include <linux/interrupt.h> 381da177e4SLinus Torvalds #include <linux/notifier.h> 391da177e4SLinus Torvalds #include <net/sock.h> 401da177e4SLinus Torvalds 411da177e4SLinus Torvalds #include <asm/system.h> 421da177e4SLinus Torvalds #include <asm/uaccess.h> 431da177e4SLinus Torvalds #include <asm/unaligned.h> 441da177e4SLinus Torvalds 451da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h> 461da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h> 471da177e4SLinus Torvalds 481da177e4SLinus Torvalds /* Handle HCI Event packets */ 491da177e4SLinus Torvalds 50a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb) 511da177e4SLinus Torvalds { 52a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 531da177e4SLinus Torvalds 54a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 551da177e4SLinus Torvalds 56a9de9248SMarcel Holtmann if (status) 57a9de9248SMarcel Holtmann return; 581da177e4SLinus Torvalds 591da177e4SLinus Torvalds clear_bit(HCI_INQUIRY, &hdev->flags); 60a9de9248SMarcel Holtmann 611da177e4SLinus Torvalds hci_req_complete(hdev, status); 62a9de9248SMarcel Holtmann 63a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 641da177e4SLinus Torvalds } 656bd57416SMarcel Holtmann 66a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 671da177e4SLinus Torvalds { 68a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 69a9de9248SMarcel Holtmann 70a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 71a9de9248SMarcel Holtmann 72a9de9248SMarcel Holtmann if (status) 73a9de9248SMarcel Holtmann return; 74a9de9248SMarcel Holtmann 75a9de9248SMarcel Holtmann clear_bit(HCI_INQUIRY, &hdev->flags); 76a9de9248SMarcel Holtmann 77a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 78a9de9248SMarcel Holtmann } 79a9de9248SMarcel Holtmann 80a9de9248SMarcel Holtmann static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, 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 90a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", 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 113e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", 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 133a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", 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 151e4e8e37cSMarcel Holtmann static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 152e4e8e37cSMarcel Holtmann { 153e4e8e37cSMarcel Holtmann struct hci_rp_read_def_link_policy *rp = (void *) skb->data; 154e4e8e37cSMarcel Holtmann 155e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 156e4e8e37cSMarcel Holtmann 157e4e8e37cSMarcel Holtmann if (rp->status) 158e4e8e37cSMarcel Holtmann return; 159e4e8e37cSMarcel Holtmann 160e4e8e37cSMarcel Holtmann hdev->link_policy = __le16_to_cpu(rp->policy); 161e4e8e37cSMarcel Holtmann } 162e4e8e37cSMarcel Holtmann 163e4e8e37cSMarcel Holtmann static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 164e4e8e37cSMarcel Holtmann { 165e4e8e37cSMarcel Holtmann __u8 status = *((__u8 *) skb->data); 166e4e8e37cSMarcel Holtmann void *sent; 167e4e8e37cSMarcel Holtmann 168e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 169e4e8e37cSMarcel Holtmann 170e4e8e37cSMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY); 171e4e8e37cSMarcel Holtmann if (!sent) 172e4e8e37cSMarcel Holtmann return; 173e4e8e37cSMarcel Holtmann 174e4e8e37cSMarcel Holtmann if (!status) 175e4e8e37cSMarcel Holtmann hdev->link_policy = get_unaligned_le16(sent); 176e4e8e37cSMarcel Holtmann 177e4e8e37cSMarcel Holtmann hci_req_complete(hdev, status); 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 184a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 185a9de9248SMarcel Holtmann 186a9de9248SMarcel Holtmann hci_req_complete(hdev, status); 187a9de9248SMarcel Holtmann } 188a9de9248SMarcel Holtmann 189a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) 190a9de9248SMarcel Holtmann { 191a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 1921da177e4SLinus Torvalds void *sent; 1931da177e4SLinus Torvalds 194a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 1951da177e4SLinus Torvalds 196f383f275SMarcel Holtmann if (status) 197f383f275SMarcel Holtmann return; 198f383f275SMarcel Holtmann 199a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); 2001da177e4SLinus Torvalds if (!sent) 201a9de9248SMarcel Holtmann return; 2021da177e4SLinus Torvalds 203a9de9248SMarcel Holtmann memcpy(hdev->dev_name, sent, 248); 204a9de9248SMarcel Holtmann } 205a9de9248SMarcel Holtmann 206a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) 207a9de9248SMarcel Holtmann { 208a9de9248SMarcel Holtmann struct hci_rp_read_local_name *rp = (void *) skb->data; 209a9de9248SMarcel Holtmann 210a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 211a9de9248SMarcel Holtmann 212a9de9248SMarcel Holtmann if (rp->status) 213a9de9248SMarcel Holtmann return; 214a9de9248SMarcel Holtmann 215a9de9248SMarcel Holtmann memcpy(hdev->dev_name, rp->name, 248); 216a9de9248SMarcel Holtmann } 217a9de9248SMarcel Holtmann 218a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) 219a9de9248SMarcel Holtmann { 220a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 221a9de9248SMarcel Holtmann void *sent; 222a9de9248SMarcel Holtmann 223a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 224a9de9248SMarcel Holtmann 225a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); 226a9de9248SMarcel Holtmann if (!sent) 227a9de9248SMarcel Holtmann return; 2281da177e4SLinus Torvalds 2291da177e4SLinus Torvalds if (!status) { 230a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 231a9de9248SMarcel Holtmann 2321da177e4SLinus Torvalds if (param == AUTH_ENABLED) 2331da177e4SLinus Torvalds set_bit(HCI_AUTH, &hdev->flags); 2341da177e4SLinus Torvalds else 2351da177e4SLinus Torvalds clear_bit(HCI_AUTH, &hdev->flags); 2361da177e4SLinus Torvalds } 237a9de9248SMarcel Holtmann 2381da177e4SLinus Torvalds hci_req_complete(hdev, status); 239a9de9248SMarcel Holtmann } 2401da177e4SLinus Torvalds 241a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) 242a9de9248SMarcel Holtmann { 243a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 244a9de9248SMarcel Holtmann void *sent; 245a9de9248SMarcel Holtmann 246a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 247a9de9248SMarcel Holtmann 248a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); 2491da177e4SLinus Torvalds if (!sent) 250a9de9248SMarcel Holtmann return; 2511da177e4SLinus Torvalds 2521da177e4SLinus Torvalds if (!status) { 253a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 254a9de9248SMarcel Holtmann 2551da177e4SLinus Torvalds if (param) 2561da177e4SLinus Torvalds set_bit(HCI_ENCRYPT, &hdev->flags); 2571da177e4SLinus Torvalds else 2581da177e4SLinus Torvalds clear_bit(HCI_ENCRYPT, &hdev->flags); 2591da177e4SLinus Torvalds } 260a9de9248SMarcel Holtmann 2611da177e4SLinus Torvalds hci_req_complete(hdev, status); 2621da177e4SLinus Torvalds } 2631da177e4SLinus Torvalds 264a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) 265a9de9248SMarcel Holtmann { 266a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 267a9de9248SMarcel Holtmann void *sent; 2681da177e4SLinus Torvalds 269a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 270a9de9248SMarcel Holtmann 271a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); 2721da177e4SLinus Torvalds if (!sent) 273a9de9248SMarcel Holtmann return; 2741da177e4SLinus Torvalds 2751da177e4SLinus Torvalds if (!status) { 276a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 277a9de9248SMarcel Holtmann 2781da177e4SLinus Torvalds clear_bit(HCI_PSCAN, &hdev->flags); 2791da177e4SLinus Torvalds clear_bit(HCI_ISCAN, &hdev->flags); 280a9de9248SMarcel Holtmann 2811da177e4SLinus Torvalds if (param & SCAN_INQUIRY) 2821da177e4SLinus Torvalds set_bit(HCI_ISCAN, &hdev->flags); 2831da177e4SLinus Torvalds 2841da177e4SLinus Torvalds if (param & SCAN_PAGE) 2851da177e4SLinus Torvalds set_bit(HCI_PSCAN, &hdev->flags); 2861da177e4SLinus Torvalds } 287a9de9248SMarcel Holtmann 2881da177e4SLinus Torvalds hci_req_complete(hdev, status); 2891da177e4SLinus Torvalds } 2901da177e4SLinus Torvalds 291a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 292a9de9248SMarcel Holtmann { 293a9de9248SMarcel Holtmann struct hci_rp_read_class_of_dev *rp = (void *) skb->data; 294a9de9248SMarcel Holtmann 295a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 296a9de9248SMarcel Holtmann 297a9de9248SMarcel Holtmann if (rp->status) 298a9de9248SMarcel Holtmann return; 299a9de9248SMarcel Holtmann 300a9de9248SMarcel Holtmann memcpy(hdev->dev_class, rp->dev_class, 3); 301a9de9248SMarcel Holtmann 302a9de9248SMarcel Holtmann BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, 303a9de9248SMarcel Holtmann hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); 304a9de9248SMarcel Holtmann } 305a9de9248SMarcel Holtmann 306a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 307a9de9248SMarcel Holtmann { 308a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 309a9de9248SMarcel Holtmann void *sent; 310a9de9248SMarcel Holtmann 311a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 312a9de9248SMarcel Holtmann 313f383f275SMarcel Holtmann if (status) 314f383f275SMarcel Holtmann return; 315f383f275SMarcel Holtmann 316a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); 317a9de9248SMarcel Holtmann if (!sent) 318a9de9248SMarcel Holtmann return; 319a9de9248SMarcel Holtmann 320a9de9248SMarcel Holtmann memcpy(hdev->dev_class, sent, 3); 321a9de9248SMarcel Holtmann } 322a9de9248SMarcel Holtmann 323a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 324a9de9248SMarcel Holtmann { 325a9de9248SMarcel Holtmann struct hci_rp_read_voice_setting *rp = (void *) skb->data; 326a9de9248SMarcel Holtmann __u16 setting; 327a9de9248SMarcel Holtmann 328a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 329a9de9248SMarcel Holtmann 330a9de9248SMarcel Holtmann if (rp->status) 331a9de9248SMarcel Holtmann return; 332a9de9248SMarcel Holtmann 333a9de9248SMarcel Holtmann setting = __le16_to_cpu(rp->voice_setting); 334a9de9248SMarcel Holtmann 335a9de9248SMarcel Holtmann if (hdev->voice_setting == setting) 336a9de9248SMarcel Holtmann return; 337a9de9248SMarcel Holtmann 338a9de9248SMarcel Holtmann hdev->voice_setting = setting; 339a9de9248SMarcel Holtmann 340a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 341a9de9248SMarcel Holtmann 342a9de9248SMarcel Holtmann if (hdev->notify) { 343a9de9248SMarcel Holtmann tasklet_disable(&hdev->tx_task); 344a9de9248SMarcel Holtmann hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 345a9de9248SMarcel Holtmann tasklet_enable(&hdev->tx_task); 346a9de9248SMarcel Holtmann } 347a9de9248SMarcel Holtmann } 348a9de9248SMarcel Holtmann 349a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 350a9de9248SMarcel Holtmann { 351a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 352f383f275SMarcel Holtmann __u16 setting; 353a9de9248SMarcel Holtmann void *sent; 354a9de9248SMarcel Holtmann 355a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 356a9de9248SMarcel Holtmann 357f383f275SMarcel Holtmann if (status) 358f383f275SMarcel Holtmann return; 359f383f275SMarcel Holtmann 360a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); 361a9de9248SMarcel Holtmann if (!sent) 362a9de9248SMarcel Holtmann return; 363a9de9248SMarcel Holtmann 364f383f275SMarcel Holtmann setting = get_unaligned_le16(sent); 3651da177e4SLinus Torvalds 366f383f275SMarcel Holtmann if (hdev->voice_setting == setting) 367f383f275SMarcel Holtmann return; 368f383f275SMarcel Holtmann 3691da177e4SLinus Torvalds hdev->voice_setting = setting; 3701da177e4SLinus Torvalds 371a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 3721da177e4SLinus Torvalds 3731da177e4SLinus Torvalds if (hdev->notify) { 3741da177e4SLinus Torvalds tasklet_disable(&hdev->tx_task); 3751da177e4SLinus Torvalds hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 3761da177e4SLinus Torvalds tasklet_enable(&hdev->tx_task); 3771da177e4SLinus Torvalds } 3781da177e4SLinus Torvalds } 3791da177e4SLinus Torvalds 380a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 3811da177e4SLinus Torvalds { 382a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 3831da177e4SLinus Torvalds 384a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 3851da177e4SLinus Torvalds 386a9de9248SMarcel Holtmann hci_req_complete(hdev, status); 3871143e5a6SMarcel Holtmann } 3881143e5a6SMarcel Holtmann 389333140b5SMarcel Holtmann static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 390333140b5SMarcel Holtmann { 391333140b5SMarcel Holtmann struct hci_rp_read_ssp_mode *rp = (void *) skb->data; 392333140b5SMarcel Holtmann 393333140b5SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 394333140b5SMarcel Holtmann 395333140b5SMarcel Holtmann if (rp->status) 396333140b5SMarcel Holtmann return; 397333140b5SMarcel Holtmann 398333140b5SMarcel Holtmann hdev->ssp_mode = rp->mode; 399333140b5SMarcel Holtmann } 400333140b5SMarcel Holtmann 401333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 402333140b5SMarcel Holtmann { 403333140b5SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 404333140b5SMarcel Holtmann void *sent; 405333140b5SMarcel Holtmann 406333140b5SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 407333140b5SMarcel Holtmann 408333140b5SMarcel Holtmann if (status) 409333140b5SMarcel Holtmann return; 410333140b5SMarcel Holtmann 411333140b5SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); 412333140b5SMarcel Holtmann if (!sent) 413333140b5SMarcel Holtmann return; 414333140b5SMarcel Holtmann 415333140b5SMarcel Holtmann hdev->ssp_mode = *((__u8 *) sent); 416333140b5SMarcel Holtmann } 417333140b5SMarcel Holtmann 418a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) 419a9de9248SMarcel Holtmann { 420a9de9248SMarcel Holtmann struct hci_rp_read_local_version *rp = (void *) skb->data; 4211143e5a6SMarcel Holtmann 422a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 4231143e5a6SMarcel Holtmann 424a9de9248SMarcel Holtmann if (rp->status) 425a9de9248SMarcel Holtmann return; 4261143e5a6SMarcel Holtmann 427a9de9248SMarcel Holtmann hdev->hci_ver = rp->hci_ver; 428e4e8e37cSMarcel Holtmann hdev->hci_rev = __le16_to_cpu(rp->hci_rev); 429e4e8e37cSMarcel Holtmann hdev->manufacturer = __le16_to_cpu(rp->manufacturer); 4301da177e4SLinus Torvalds 431a9de9248SMarcel Holtmann BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name, 432a9de9248SMarcel Holtmann hdev->manufacturer, 433a9de9248SMarcel Holtmann hdev->hci_ver, hdev->hci_rev); 4341da177e4SLinus Torvalds } 4351da177e4SLinus Torvalds 436a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb) 437a9de9248SMarcel Holtmann { 438a9de9248SMarcel Holtmann struct hci_rp_read_local_commands *rp = (void *) skb->data; 439a9de9248SMarcel Holtmann 440a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 441a9de9248SMarcel Holtmann 442a9de9248SMarcel Holtmann if (rp->status) 443a9de9248SMarcel Holtmann return; 444a9de9248SMarcel Holtmann 445a9de9248SMarcel Holtmann memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); 446a9de9248SMarcel Holtmann } 447a9de9248SMarcel Holtmann 448a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb) 449a9de9248SMarcel Holtmann { 450a9de9248SMarcel Holtmann struct hci_rp_read_local_features *rp = (void *) skb->data; 451a9de9248SMarcel Holtmann 452a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 453a9de9248SMarcel Holtmann 454a9de9248SMarcel Holtmann if (rp->status) 455a9de9248SMarcel Holtmann return; 456a9de9248SMarcel Holtmann 457a9de9248SMarcel Holtmann memcpy(hdev->features, rp->features, 8); 4581da177e4SLinus Torvalds 4591da177e4SLinus Torvalds /* Adjust default settings according to features 4601da177e4SLinus Torvalds * supported by device. */ 461a9de9248SMarcel Holtmann 4621da177e4SLinus Torvalds if (hdev->features[0] & LMP_3SLOT) 4631da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM3 | HCI_DH3); 4641da177e4SLinus Torvalds 4651da177e4SLinus Torvalds if (hdev->features[0] & LMP_5SLOT) 4661da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM5 | HCI_DH5); 4671da177e4SLinus Torvalds 4685b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV2) { 4691da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV2); 4705b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV2); 4715b7f9909SMarcel Holtmann } 4721da177e4SLinus Torvalds 4735b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV3) { 4741da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV3); 4755b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV3); 4765b7f9909SMarcel Holtmann } 4775b7f9909SMarcel Holtmann 4785b7f9909SMarcel Holtmann if (hdev->features[3] & LMP_ESCO) 4795b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV3); 4805b7f9909SMarcel Holtmann 4815b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV4) 4825b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV4); 4835b7f9909SMarcel Holtmann 4845b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV5) 4855b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV5); 4861da177e4SLinus Torvalds 487efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_2M) 488efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV3); 489efc7688bSMarcel Holtmann 490efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_ESCO_3M) 491efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_3EV3); 492efc7688bSMarcel Holtmann 493efc7688bSMarcel Holtmann if (hdev->features[5] & LMP_EDR_3S_ESCO) 494efc7688bSMarcel Holtmann hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); 495efc7688bSMarcel Holtmann 496a9de9248SMarcel Holtmann BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, 497a9de9248SMarcel Holtmann hdev->features[0], hdev->features[1], 498a9de9248SMarcel Holtmann hdev->features[2], hdev->features[3], 499a9de9248SMarcel Holtmann hdev->features[4], hdev->features[5], 500a9de9248SMarcel Holtmann hdev->features[6], hdev->features[7]); 5011da177e4SLinus Torvalds } 5021da177e4SLinus Torvalds 503a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 504a9de9248SMarcel Holtmann { 505a9de9248SMarcel Holtmann struct hci_rp_read_buffer_size *rp = (void *) skb->data; 506a9de9248SMarcel Holtmann 507a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 508a9de9248SMarcel Holtmann 509a9de9248SMarcel Holtmann if (rp->status) 510a9de9248SMarcel Holtmann return; 511a9de9248SMarcel Holtmann 512a9de9248SMarcel Holtmann hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); 513a9de9248SMarcel Holtmann hdev->sco_mtu = rp->sco_mtu; 514a9de9248SMarcel Holtmann hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); 515a9de9248SMarcel Holtmann hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); 516da1f5198SMarcel Holtmann 517da1f5198SMarcel Holtmann if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { 518da1f5198SMarcel Holtmann hdev->sco_mtu = 64; 519da1f5198SMarcel Holtmann hdev->sco_pkts = 8; 520da1f5198SMarcel Holtmann } 521da1f5198SMarcel Holtmann 522da1f5198SMarcel Holtmann hdev->acl_cnt = hdev->acl_pkts; 523da1f5198SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 5241da177e4SLinus Torvalds 525a9de9248SMarcel Holtmann BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, 526a9de9248SMarcel Holtmann hdev->acl_mtu, hdev->acl_pkts, 527a9de9248SMarcel Holtmann hdev->sco_mtu, hdev->sco_pkts); 5281da177e4SLinus Torvalds } 5291da177e4SLinus Torvalds 530a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) 531a9de9248SMarcel Holtmann { 532a9de9248SMarcel Holtmann struct hci_rp_read_bd_addr *rp = (void *) skb->data; 5331da177e4SLinus Torvalds 534a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 535a9de9248SMarcel Holtmann 536a9de9248SMarcel Holtmann if (!rp->status) 537a9de9248SMarcel Holtmann bacpy(&hdev->bdaddr, &rp->bdaddr); 538a9de9248SMarcel Holtmann 539a9de9248SMarcel Holtmann hci_req_complete(hdev, rp->status); 5401da177e4SLinus Torvalds } 5411da177e4SLinus Torvalds 542a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 543a9de9248SMarcel Holtmann { 544a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 545a9de9248SMarcel Holtmann 546a9de9248SMarcel Holtmann if (status) { 547a9de9248SMarcel Holtmann hci_req_complete(hdev, status); 548a9de9248SMarcel Holtmann 549a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 550a9de9248SMarcel Holtmann } else 551a9de9248SMarcel Holtmann set_bit(HCI_INQUIRY, &hdev->flags); 552a9de9248SMarcel Holtmann } 553a9de9248SMarcel Holtmann 5541da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 5551da177e4SLinus Torvalds { 556a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 5571da177e4SLinus Torvalds struct hci_conn *conn; 5581da177e4SLinus Torvalds 559a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 560a9de9248SMarcel Holtmann 561a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 5621da177e4SLinus Torvalds if (!cp) 5631da177e4SLinus Torvalds return; 5641da177e4SLinus Torvalds 5651da177e4SLinus Torvalds hci_dev_lock(hdev); 5661da177e4SLinus Torvalds 5671da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 5681da177e4SLinus Torvalds 569a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn); 5701da177e4SLinus Torvalds 5711da177e4SLinus Torvalds if (status) { 5721da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 5734c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 5741da177e4SLinus Torvalds conn->state = BT_CLOSED; 5751da177e4SLinus Torvalds hci_proto_connect_cfm(conn, status); 5761da177e4SLinus Torvalds hci_conn_del(conn); 5774c67bc74SMarcel Holtmann } else 5784c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 5791da177e4SLinus Torvalds } 5801da177e4SLinus Torvalds } else { 5811da177e4SLinus Torvalds if (!conn) { 5821da177e4SLinus Torvalds conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); 5831da177e4SLinus Torvalds if (conn) { 5841da177e4SLinus Torvalds conn->out = 1; 5851da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 5861da177e4SLinus Torvalds } else 587893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 5881da177e4SLinus Torvalds } 5891da177e4SLinus Torvalds } 5901da177e4SLinus Torvalds 5911da177e4SLinus Torvalds hci_dev_unlock(hdev); 5921da177e4SLinus Torvalds } 5931da177e4SLinus Torvalds 594a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 5951da177e4SLinus Torvalds { 596a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 5971da177e4SLinus Torvalds struct hci_conn *acl, *sco; 5981da177e4SLinus Torvalds __u16 handle; 5991da177e4SLinus Torvalds 600b6a0dc82SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 601b6a0dc82SMarcel Holtmann 602a9de9248SMarcel Holtmann if (!status) 603a9de9248SMarcel Holtmann return; 604a9de9248SMarcel Holtmann 605a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 6061da177e4SLinus Torvalds if (!cp) 607a9de9248SMarcel Holtmann return; 6081da177e4SLinus Torvalds 6091da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 6101da177e4SLinus Torvalds 611a9de9248SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 6121da177e4SLinus Torvalds 6131da177e4SLinus Torvalds hci_dev_lock(hdev); 6141da177e4SLinus Torvalds 6151da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 6161da177e4SLinus Torvalds if (acl && (sco = acl->link)) { 6171da177e4SLinus Torvalds sco->state = BT_CLOSED; 6181da177e4SLinus Torvalds 6191da177e4SLinus Torvalds hci_proto_connect_cfm(sco, status); 6201da177e4SLinus Torvalds hci_conn_del(sco); 6211da177e4SLinus Torvalds } 6221da177e4SLinus Torvalds 6231da177e4SLinus Torvalds hci_dev_unlock(hdev); 6241da177e4SLinus Torvalds } 6251da177e4SLinus Torvalds 626f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 627f8558555SMarcel Holtmann { 628f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 629f8558555SMarcel Holtmann struct hci_conn *conn; 630f8558555SMarcel Holtmann 631f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 632f8558555SMarcel Holtmann 633f8558555SMarcel Holtmann if (!status) 634f8558555SMarcel Holtmann return; 635f8558555SMarcel Holtmann 636f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 637f8558555SMarcel Holtmann if (!cp) 638f8558555SMarcel Holtmann return; 639f8558555SMarcel Holtmann 640f8558555SMarcel Holtmann hci_dev_lock(hdev); 641f8558555SMarcel Holtmann 642f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 643f8558555SMarcel Holtmann if (conn) { 644f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 645f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 646f8558555SMarcel Holtmann hci_conn_put(conn); 647f8558555SMarcel Holtmann } 648f8558555SMarcel Holtmann } 649f8558555SMarcel Holtmann 650f8558555SMarcel Holtmann hci_dev_unlock(hdev); 651f8558555SMarcel Holtmann } 652f8558555SMarcel Holtmann 653f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 654f8558555SMarcel Holtmann { 655f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 656f8558555SMarcel Holtmann struct hci_conn *conn; 657f8558555SMarcel Holtmann 658f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 659f8558555SMarcel Holtmann 660f8558555SMarcel Holtmann if (!status) 661f8558555SMarcel Holtmann return; 662f8558555SMarcel Holtmann 663f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 664f8558555SMarcel Holtmann if (!cp) 665f8558555SMarcel Holtmann return; 666f8558555SMarcel Holtmann 667f8558555SMarcel Holtmann hci_dev_lock(hdev); 668f8558555SMarcel Holtmann 669f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 670f8558555SMarcel Holtmann if (conn) { 671f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 672f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 673f8558555SMarcel Holtmann hci_conn_put(conn); 674f8558555SMarcel Holtmann } 675f8558555SMarcel Holtmann } 676f8558555SMarcel Holtmann 677f8558555SMarcel Holtmann hci_dev_unlock(hdev); 678f8558555SMarcel Holtmann } 679f8558555SMarcel Holtmann 680392599b9SJohan Hedberg static int hci_request_outgoing_auth(struct hci_dev *hdev, 681392599b9SJohan Hedberg struct hci_conn *conn) 682392599b9SJohan Hedberg { 683392599b9SJohan Hedberg struct hci_cp_auth_requested cp; 684392599b9SJohan Hedberg 685392599b9SJohan Hedberg if (conn->state != BT_CONFIG || !conn->out) 686392599b9SJohan Hedberg return 0; 687392599b9SJohan Hedberg 688392599b9SJohan Hedberg if (conn->sec_level == BT_SECURITY_SDP) 689392599b9SJohan Hedberg return 0; 690392599b9SJohan Hedberg 691392599b9SJohan Hedberg /* Only request authentication for SSP connections or non-SSP 692392599b9SJohan Hedberg * devices with sec_level HIGH */ 693392599b9SJohan Hedberg if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) && 694392599b9SJohan Hedberg conn->sec_level != BT_SECURITY_HIGH) 695392599b9SJohan Hedberg return 0; 696392599b9SJohan Hedberg 697392599b9SJohan Hedberg cp.handle = __cpu_to_le16(conn->handle); 698392599b9SJohan Hedberg hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); 699392599b9SJohan Hedberg 700392599b9SJohan Hedberg return 1; 701392599b9SJohan Hedberg } 702392599b9SJohan Hedberg 703a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 7041da177e4SLinus Torvalds { 705a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 706a9de9248SMarcel Holtmann } 7071da177e4SLinus Torvalds 708769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 709769be974SMarcel Holtmann { 710769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 711769be974SMarcel Holtmann struct hci_conn *conn; 712769be974SMarcel Holtmann 713769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 714769be974SMarcel Holtmann 715769be974SMarcel Holtmann if (!status) 716769be974SMarcel Holtmann return; 717769be974SMarcel Holtmann 718769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 719769be974SMarcel Holtmann if (!cp) 720769be974SMarcel Holtmann return; 721769be974SMarcel Holtmann 722769be974SMarcel Holtmann hci_dev_lock(hdev); 723769be974SMarcel Holtmann 724769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 725769be974SMarcel Holtmann if (conn) { 726769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 727769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 728769be974SMarcel Holtmann hci_conn_put(conn); 729769be974SMarcel Holtmann } 730769be974SMarcel Holtmann } 731769be974SMarcel Holtmann 732769be974SMarcel Holtmann hci_dev_unlock(hdev); 733769be974SMarcel Holtmann } 734769be974SMarcel Holtmann 735769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 736769be974SMarcel Holtmann { 737769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features *cp; 738769be974SMarcel Holtmann struct hci_conn *conn; 739769be974SMarcel Holtmann 740769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 741769be974SMarcel Holtmann 742769be974SMarcel Holtmann if (!status) 743769be974SMarcel Holtmann return; 744769be974SMarcel Holtmann 745769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES); 746769be974SMarcel Holtmann if (!cp) 747769be974SMarcel Holtmann return; 748769be974SMarcel Holtmann 749769be974SMarcel Holtmann hci_dev_lock(hdev); 750769be974SMarcel Holtmann 751769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 752769be974SMarcel Holtmann if (conn) { 753769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 754769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 755769be974SMarcel Holtmann hci_conn_put(conn); 756769be974SMarcel Holtmann } 757769be974SMarcel Holtmann } 758769be974SMarcel Holtmann 759769be974SMarcel Holtmann hci_dev_unlock(hdev); 760769be974SMarcel Holtmann } 761769be974SMarcel Holtmann 762a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 763a9de9248SMarcel Holtmann { 764b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 765b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 766b6a0dc82SMarcel Holtmann __u16 handle; 767b6a0dc82SMarcel Holtmann 768a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 769b6a0dc82SMarcel Holtmann 770b6a0dc82SMarcel Holtmann if (!status) 771b6a0dc82SMarcel Holtmann return; 772b6a0dc82SMarcel Holtmann 773b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 774b6a0dc82SMarcel Holtmann if (!cp) 775b6a0dc82SMarcel Holtmann return; 776b6a0dc82SMarcel Holtmann 777b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 778b6a0dc82SMarcel Holtmann 779b6a0dc82SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 780b6a0dc82SMarcel Holtmann 781b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 782b6a0dc82SMarcel Holtmann 783b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 784b6a0dc82SMarcel Holtmann if (acl && (sco = acl->link)) { 785b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 786b6a0dc82SMarcel Holtmann 787b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(sco, status); 788b6a0dc82SMarcel Holtmann hci_conn_del(sco); 789b6a0dc82SMarcel Holtmann } 790b6a0dc82SMarcel Holtmann 791b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 792a9de9248SMarcel Holtmann } 793a9de9248SMarcel Holtmann 794a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 795a9de9248SMarcel Holtmann { 796a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 79704837f64SMarcel Holtmann struct hci_conn *conn; 79804837f64SMarcel Holtmann 799a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 800a9de9248SMarcel Holtmann 801a9de9248SMarcel Holtmann if (!status) 802a9de9248SMarcel Holtmann return; 803a9de9248SMarcel Holtmann 804a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 80504837f64SMarcel Holtmann if (!cp) 806a9de9248SMarcel Holtmann return; 80704837f64SMarcel Holtmann 80804837f64SMarcel Holtmann hci_dev_lock(hdev); 80904837f64SMarcel Holtmann 81004837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 811e73439d8SMarcel Holtmann if (conn) { 81204837f64SMarcel Holtmann clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); 81304837f64SMarcel Holtmann 814e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 815e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 816e73439d8SMarcel Holtmann } 817e73439d8SMarcel Holtmann 81804837f64SMarcel Holtmann hci_dev_unlock(hdev); 81904837f64SMarcel Holtmann } 82004837f64SMarcel Holtmann 821a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 822a9de9248SMarcel Holtmann { 823a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 82404837f64SMarcel Holtmann struct hci_conn *conn; 82504837f64SMarcel Holtmann 826a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 827a9de9248SMarcel Holtmann 828a9de9248SMarcel Holtmann if (!status) 829a9de9248SMarcel Holtmann return; 830a9de9248SMarcel Holtmann 831a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 83204837f64SMarcel Holtmann if (!cp) 833a9de9248SMarcel Holtmann return; 83404837f64SMarcel Holtmann 83504837f64SMarcel Holtmann hci_dev_lock(hdev); 83604837f64SMarcel Holtmann 83704837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 838e73439d8SMarcel Holtmann if (conn) { 83904837f64SMarcel Holtmann clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); 84004837f64SMarcel Holtmann 841e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 842e73439d8SMarcel Holtmann hci_sco_setup(conn, status); 843e73439d8SMarcel Holtmann } 844e73439d8SMarcel Holtmann 84504837f64SMarcel Holtmann hci_dev_unlock(hdev); 84604837f64SMarcel Holtmann } 84704837f64SMarcel Holtmann 8481da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 8491da177e4SLinus Torvalds { 8501da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 8511da177e4SLinus Torvalds 8521da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, status); 8531da177e4SLinus Torvalds 8541da177e4SLinus Torvalds clear_bit(HCI_INQUIRY, &hdev->flags); 855a9de9248SMarcel Holtmann 8561da177e4SLinus Torvalds hci_req_complete(hdev, status); 8576bd57416SMarcel Holtmann 858a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 8591da177e4SLinus Torvalds } 8601da177e4SLinus Torvalds 8611da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 8621da177e4SLinus Torvalds { 86345bb4bf0SMarcel Holtmann struct inquiry_data data; 864a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 8651da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 8661da177e4SLinus Torvalds 8671da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 8681da177e4SLinus Torvalds 86945bb4bf0SMarcel Holtmann if (!num_rsp) 87045bb4bf0SMarcel Holtmann return; 87145bb4bf0SMarcel Holtmann 8721da177e4SLinus Torvalds hci_dev_lock(hdev); 87345bb4bf0SMarcel Holtmann 8741da177e4SLinus Torvalds for (; num_rsp; num_rsp--) { 8751da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 8761da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 8771da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 8781da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 8791da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 8801da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 8811da177e4SLinus Torvalds data.rssi = 0x00; 88241a96212SMarcel Holtmann data.ssp_mode = 0x00; 8831da177e4SLinus Torvalds info++; 8841da177e4SLinus Torvalds hci_inquiry_cache_update(hdev, &data); 8851da177e4SLinus Torvalds } 88645bb4bf0SMarcel Holtmann 8871da177e4SLinus Torvalds hci_dev_unlock(hdev); 8881da177e4SLinus Torvalds } 8891da177e4SLinus Torvalds 890a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 8911da177e4SLinus Torvalds { 892a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 893a9de9248SMarcel Holtmann struct hci_conn *conn; 8941da177e4SLinus Torvalds 895a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 89645bb4bf0SMarcel Holtmann 8971da177e4SLinus Torvalds hci_dev_lock(hdev); 89845bb4bf0SMarcel Holtmann 899a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 9009499237aSMarcel Holtmann if (!conn) { 9019499237aSMarcel Holtmann if (ev->link_type != SCO_LINK) 9029499237aSMarcel Holtmann goto unlock; 9039499237aSMarcel Holtmann 9049499237aSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 905a9de9248SMarcel Holtmann if (!conn) 906a9de9248SMarcel Holtmann goto unlock; 90745bb4bf0SMarcel Holtmann 9089499237aSMarcel Holtmann conn->type = SCO_LINK; 9099499237aSMarcel Holtmann } 9109499237aSMarcel Holtmann 911a9de9248SMarcel Holtmann if (!ev->status) { 912a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 913769be974SMarcel Holtmann 914769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 915769be974SMarcel Holtmann conn->state = BT_CONFIG; 916769be974SMarcel Holtmann hci_conn_hold(conn); 917052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 918769be974SMarcel Holtmann } else 919a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 920a9de9248SMarcel Holtmann 9219eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 9227d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 9237d0db0a3SMarcel Holtmann 924a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 925a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 926a9de9248SMarcel Holtmann 927a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 928a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 929a9de9248SMarcel Holtmann 930a9de9248SMarcel Holtmann /* Get remote features */ 931a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 932a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 933a9de9248SMarcel Holtmann cp.handle = ev->handle; 934769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 935769be974SMarcel Holtmann sizeof(cp), &cp); 93645bb4bf0SMarcel Holtmann } 937a9de9248SMarcel Holtmann 938a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 939a8746417SMarcel Holtmann if (!conn->out && hdev->hci_ver < 3) { 940a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 941a9de9248SMarcel Holtmann cp.handle = ev->handle; 942a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 943a8746417SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, 944a8746417SMarcel Holtmann sizeof(cp), &cp); 945a9de9248SMarcel Holtmann } 946a9de9248SMarcel Holtmann } else 947a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 94845bb4bf0SMarcel Holtmann 949e73439d8SMarcel Holtmann if (conn->type == ACL_LINK) 950e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 95145bb4bf0SMarcel Holtmann 952769be974SMarcel Holtmann if (ev->status) { 953a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 954a9de9248SMarcel Holtmann hci_conn_del(conn); 955c89b6e6bSMarcel Holtmann } else if (ev->link_type != ACL_LINK) 956c89b6e6bSMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 957a9de9248SMarcel Holtmann 958a9de9248SMarcel Holtmann unlock: 9591da177e4SLinus Torvalds hci_dev_unlock(hdev); 960a9de9248SMarcel Holtmann 961a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 9621da177e4SLinus Torvalds } 9631da177e4SLinus Torvalds 9641da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 9651da177e4SLinus Torvalds { 966a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 9671da177e4SLinus Torvalds int mask = hdev->link_mode; 9681da177e4SLinus Torvalds 969a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s type 0x%x", hdev->name, 9701da177e4SLinus Torvalds batostr(&ev->bdaddr), ev->link_type); 9711da177e4SLinus Torvalds 9721da177e4SLinus Torvalds mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); 9731da177e4SLinus Torvalds 974f0358568SJohan Hedberg if ((mask & HCI_LM_ACCEPT) && !hci_blacklist_lookup(hdev, &ev->bdaddr)) { 9751da177e4SLinus Torvalds /* Connection accepted */ 976c7bdd502SMarcel Holtmann struct inquiry_entry *ie; 9771da177e4SLinus Torvalds struct hci_conn *conn; 9781da177e4SLinus Torvalds 9791da177e4SLinus Torvalds hci_dev_lock(hdev); 980b6a0dc82SMarcel Holtmann 981c7bdd502SMarcel Holtmann if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr))) 982c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 983c7bdd502SMarcel Holtmann 9841da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 9851da177e4SLinus Torvalds if (!conn) { 9861da177e4SLinus Torvalds if (!(conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr))) { 987893ef971SGustavo F. Padovan BT_ERR("No memory for new connection"); 9881da177e4SLinus Torvalds hci_dev_unlock(hdev); 9891da177e4SLinus Torvalds return; 9901da177e4SLinus Torvalds } 9911da177e4SLinus Torvalds } 992b6a0dc82SMarcel Holtmann 9931da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 9941da177e4SLinus Torvalds conn->state = BT_CONNECT; 995b6a0dc82SMarcel Holtmann 9961da177e4SLinus Torvalds hci_dev_unlock(hdev); 9971da177e4SLinus Torvalds 998b6a0dc82SMarcel Holtmann if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) { 999b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 1000b6a0dc82SMarcel Holtmann 10011da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 10021da177e4SLinus Torvalds 10031da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 10041da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 10051da177e4SLinus Torvalds else 10061da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 10071da177e4SLinus Torvalds 1008b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, 1009b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1010b6a0dc82SMarcel Holtmann } else { 1011b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 1012b6a0dc82SMarcel Holtmann 1013b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 1014a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1015b6a0dc82SMarcel Holtmann 1016b6a0dc82SMarcel Holtmann cp.tx_bandwidth = cpu_to_le32(0x00001f40); 1017b6a0dc82SMarcel Holtmann cp.rx_bandwidth = cpu_to_le32(0x00001f40); 1018b6a0dc82SMarcel Holtmann cp.max_latency = cpu_to_le16(0xffff); 1019b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 1020b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 1021b6a0dc82SMarcel Holtmann 1022b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 1023b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 1024b6a0dc82SMarcel Holtmann } 10251da177e4SLinus Torvalds } else { 10261da177e4SLinus Torvalds /* Connection rejected */ 10271da177e4SLinus Torvalds struct hci_cp_reject_conn_req cp; 10281da177e4SLinus Torvalds 10291da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 10301da177e4SLinus Torvalds cp.reason = 0x0f; 1031a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 10321da177e4SLinus Torvalds } 10331da177e4SLinus Torvalds } 10341da177e4SLinus Torvalds 10351da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 10361da177e4SLinus Torvalds { 1037a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 103804837f64SMarcel Holtmann struct hci_conn *conn; 10391da177e4SLinus Torvalds 10401da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 10411da177e4SLinus Torvalds 10421da177e4SLinus Torvalds if (ev->status) 10431da177e4SLinus Torvalds return; 10441da177e4SLinus Torvalds 10451da177e4SLinus Torvalds hci_dev_lock(hdev); 10461da177e4SLinus Torvalds 104704837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 10481da177e4SLinus Torvalds if (conn) { 10491da177e4SLinus Torvalds conn->state = BT_CLOSED; 10507d0db0a3SMarcel Holtmann 10512950f21aSMarcel Holtmann hci_proto_disconn_cfm(conn, ev->reason); 10521da177e4SLinus Torvalds hci_conn_del(conn); 10531da177e4SLinus Torvalds } 10541da177e4SLinus Torvalds 10551da177e4SLinus Torvalds hci_dev_unlock(hdev); 10561da177e4SLinus Torvalds } 10571da177e4SLinus Torvalds 1058a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1059a9de9248SMarcel Holtmann { 1060a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 1061a9de9248SMarcel Holtmann struct hci_conn *conn; 1062a9de9248SMarcel Holtmann 1063a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1064a9de9248SMarcel Holtmann 1065a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1066a9de9248SMarcel Holtmann 1067a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1068a9de9248SMarcel Holtmann if (conn) { 1069a9de9248SMarcel Holtmann if (!ev->status) 1070a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1071da213f41SJohan Hedberg else 1072da213f41SJohan Hedberg conn->sec_level = BT_SECURITY_LOW; 1073a9de9248SMarcel Holtmann 1074a9de9248SMarcel Holtmann clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); 1075a9de9248SMarcel Holtmann 1076f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1077f8558555SMarcel Holtmann if (!ev->status && hdev->ssp_mode > 0 && 1078f8558555SMarcel Holtmann conn->ssp_mode > 0) { 1079f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1080f8558555SMarcel Holtmann cp.handle = ev->handle; 1081f8558555SMarcel Holtmann cp.encrypt = 0x01; 1082f8558555SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, 1083f8558555SMarcel Holtmann sizeof(cp), &cp); 1084f8558555SMarcel Holtmann } else { 1085f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1086f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1087f8558555SMarcel Holtmann hci_conn_put(conn); 1088f8558555SMarcel Holtmann } 1089052b30b0SMarcel Holtmann } else { 1090a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 1091a9de9248SMarcel Holtmann 1092052b30b0SMarcel Holtmann hci_conn_hold(conn); 1093052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1094052b30b0SMarcel Holtmann hci_conn_put(conn); 1095052b30b0SMarcel Holtmann } 1096052b30b0SMarcel Holtmann 1097a9de9248SMarcel Holtmann if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) { 1098a9de9248SMarcel Holtmann if (!ev->status) { 1099a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1100f8558555SMarcel Holtmann cp.handle = ev->handle; 1101f8558555SMarcel Holtmann cp.encrypt = 0x01; 1102f8558555SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, 1103f8558555SMarcel Holtmann sizeof(cp), &cp); 1104a9de9248SMarcel Holtmann } else { 1105a9de9248SMarcel Holtmann clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); 1106a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 1107a9de9248SMarcel Holtmann } 1108a9de9248SMarcel Holtmann } 1109a9de9248SMarcel Holtmann } 1110a9de9248SMarcel Holtmann 1111a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1112a9de9248SMarcel Holtmann } 1113a9de9248SMarcel Holtmann 1114a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 1115a9de9248SMarcel Holtmann { 1116a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1117a9de9248SMarcel Holtmann 1118a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 1119a9de9248SMarcel Holtmann } 1120a9de9248SMarcel Holtmann 1121a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 1122a9de9248SMarcel Holtmann { 1123a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 1124a9de9248SMarcel Holtmann struct hci_conn *conn; 1125a9de9248SMarcel Holtmann 1126a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1127a9de9248SMarcel Holtmann 1128a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1129a9de9248SMarcel Holtmann 1130a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1131a9de9248SMarcel Holtmann if (conn) { 1132a9de9248SMarcel Holtmann if (!ev->status) { 1133ae293196SMarcel Holtmann if (ev->encrypt) { 1134ae293196SMarcel Holtmann /* Encryption implies authentication */ 1135ae293196SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1136a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1137ae293196SMarcel Holtmann } else 1138a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_ENCRYPT; 1139a9de9248SMarcel Holtmann } 1140a9de9248SMarcel Holtmann 1141a9de9248SMarcel Holtmann clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); 1142a9de9248SMarcel Holtmann 1143f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1144f8558555SMarcel Holtmann if (!ev->status) 1145f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1146f8558555SMarcel Holtmann 1147f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1148f8558555SMarcel Holtmann hci_conn_put(conn); 1149f8558555SMarcel Holtmann } else 1150a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 1151a9de9248SMarcel Holtmann } 1152a9de9248SMarcel Holtmann 1153a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1154a9de9248SMarcel Holtmann } 1155a9de9248SMarcel Holtmann 1156a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1157a9de9248SMarcel Holtmann { 1158a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 1159a9de9248SMarcel Holtmann struct hci_conn *conn; 1160a9de9248SMarcel Holtmann 1161a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1162a9de9248SMarcel Holtmann 1163a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1164a9de9248SMarcel Holtmann 1165a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1166a9de9248SMarcel Holtmann if (conn) { 1167a9de9248SMarcel Holtmann if (!ev->status) 1168a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_SECURE; 1169a9de9248SMarcel Holtmann 1170a9de9248SMarcel Holtmann clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); 1171a9de9248SMarcel Holtmann 1172a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 1173a9de9248SMarcel Holtmann } 1174a9de9248SMarcel Holtmann 1175a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1176a9de9248SMarcel Holtmann } 1177a9de9248SMarcel Holtmann 1178a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 1179a9de9248SMarcel Holtmann { 1180a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 1181a9de9248SMarcel Holtmann struct hci_conn *conn; 1182392599b9SJohan Hedberg int auth_requested; 1183a9de9248SMarcel Holtmann 1184a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1185a9de9248SMarcel Holtmann 1186a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1187a9de9248SMarcel Holtmann 1188a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1189ccd556feSJohan Hedberg if (!conn) 1190ccd556feSJohan Hedberg goto unlock; 1191ccd556feSJohan Hedberg 1192769be974SMarcel Holtmann if (!ev->status) 1193a9de9248SMarcel Holtmann memcpy(conn->features, ev->features, 8); 1194a9de9248SMarcel Holtmann 1195ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 1196ccd556feSJohan Hedberg goto unlock; 1197ccd556feSJohan Hedberg 1198ccd556feSJohan Hedberg if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { 1199769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 1200769be974SMarcel Holtmann cp.handle = ev->handle; 1201769be974SMarcel Holtmann cp.page = 0x01; 1202ccd556feSJohan Hedberg hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, 1203769be974SMarcel Holtmann sizeof(cp), &cp); 1204392599b9SJohan Hedberg goto unlock; 1205392599b9SJohan Hedberg } 1206392599b9SJohan Hedberg 1207392599b9SJohan Hedberg if (!ev->status) 1208392599b9SJohan Hedberg auth_requested = hci_request_outgoing_auth(hdev, conn); 1209392599b9SJohan Hedberg else 1210392599b9SJohan Hedberg auth_requested = 0; 1211392599b9SJohan Hedberg 1212392599b9SJohan Hedberg if (!auth_requested) { 1213769be974SMarcel Holtmann conn->state = BT_CONNECTED; 1214769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1215769be974SMarcel Holtmann hci_conn_put(conn); 1216769be974SMarcel Holtmann } 1217769be974SMarcel Holtmann 1218ccd556feSJohan Hedberg unlock: 1219a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1220a9de9248SMarcel Holtmann } 1221a9de9248SMarcel Holtmann 1222a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) 1223a9de9248SMarcel Holtmann { 1224a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1225a9de9248SMarcel Holtmann } 1226a9de9248SMarcel Holtmann 1227a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1228a9de9248SMarcel Holtmann { 1229a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1230a9de9248SMarcel Holtmann } 1231a9de9248SMarcel Holtmann 1232a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1233a9de9248SMarcel Holtmann { 1234a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 1235a9de9248SMarcel Holtmann __u16 opcode; 1236a9de9248SMarcel Holtmann 1237a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 1238a9de9248SMarcel Holtmann 1239a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 1240a9de9248SMarcel Holtmann 1241a9de9248SMarcel Holtmann switch (opcode) { 1242a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 1243a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 1244a9de9248SMarcel Holtmann break; 1245a9de9248SMarcel Holtmann 1246a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 1247a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 1248a9de9248SMarcel Holtmann break; 1249a9de9248SMarcel Holtmann 1250a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 1251a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 1252a9de9248SMarcel Holtmann break; 1253a9de9248SMarcel Holtmann 1254a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 1255a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 1256a9de9248SMarcel Holtmann break; 1257a9de9248SMarcel Holtmann 1258e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 1259e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 1260e4e8e37cSMarcel Holtmann break; 1261e4e8e37cSMarcel Holtmann 1262a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 1263a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 1264a9de9248SMarcel Holtmann break; 1265a9de9248SMarcel Holtmann 1266e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 1267e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 1268e4e8e37cSMarcel Holtmann break; 1269e4e8e37cSMarcel Holtmann 1270e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 1271e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 1272e4e8e37cSMarcel Holtmann break; 1273e4e8e37cSMarcel Holtmann 1274a9de9248SMarcel Holtmann case HCI_OP_RESET: 1275a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 1276a9de9248SMarcel Holtmann break; 1277a9de9248SMarcel Holtmann 1278a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 1279a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 1280a9de9248SMarcel Holtmann break; 1281a9de9248SMarcel Holtmann 1282a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 1283a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 1284a9de9248SMarcel Holtmann break; 1285a9de9248SMarcel Holtmann 1286a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 1287a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 1288a9de9248SMarcel Holtmann break; 1289a9de9248SMarcel Holtmann 1290a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 1291a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 1292a9de9248SMarcel Holtmann break; 1293a9de9248SMarcel Holtmann 1294a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 1295a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 1296a9de9248SMarcel Holtmann break; 1297a9de9248SMarcel Holtmann 1298a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 1299a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 1300a9de9248SMarcel Holtmann break; 1301a9de9248SMarcel Holtmann 1302a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 1303a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 1304a9de9248SMarcel Holtmann break; 1305a9de9248SMarcel Holtmann 1306a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 1307a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 1308a9de9248SMarcel Holtmann break; 1309a9de9248SMarcel Holtmann 1310a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 1311a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 1312a9de9248SMarcel Holtmann break; 1313a9de9248SMarcel Holtmann 1314a9de9248SMarcel Holtmann case HCI_OP_HOST_BUFFER_SIZE: 1315a9de9248SMarcel Holtmann hci_cc_host_buffer_size(hdev, skb); 1316a9de9248SMarcel Holtmann break; 1317a9de9248SMarcel Holtmann 1318333140b5SMarcel Holtmann case HCI_OP_READ_SSP_MODE: 1319333140b5SMarcel Holtmann hci_cc_read_ssp_mode(hdev, skb); 1320333140b5SMarcel Holtmann break; 1321333140b5SMarcel Holtmann 1322333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 1323333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 1324333140b5SMarcel Holtmann break; 1325333140b5SMarcel Holtmann 1326a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 1327a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 1328a9de9248SMarcel Holtmann break; 1329a9de9248SMarcel Holtmann 1330a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 1331a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 1332a9de9248SMarcel Holtmann break; 1333a9de9248SMarcel Holtmann 1334a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 1335a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 1336a9de9248SMarcel Holtmann break; 1337a9de9248SMarcel Holtmann 1338a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 1339a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 1340a9de9248SMarcel Holtmann break; 1341a9de9248SMarcel Holtmann 1342a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 1343a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 1344a9de9248SMarcel Holtmann break; 1345a9de9248SMarcel Holtmann 1346a9de9248SMarcel Holtmann default: 1347a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 1348a9de9248SMarcel Holtmann break; 1349a9de9248SMarcel Holtmann } 1350a9de9248SMarcel Holtmann 1351a9de9248SMarcel Holtmann if (ev->ncmd) { 1352a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 1353a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 1354c78ae283SMarcel Holtmann tasklet_schedule(&hdev->cmd_task); 1355a9de9248SMarcel Holtmann } 1356a9de9248SMarcel Holtmann } 1357a9de9248SMarcel Holtmann 1358a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 1359a9de9248SMarcel Holtmann { 1360a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 1361a9de9248SMarcel Holtmann __u16 opcode; 1362a9de9248SMarcel Holtmann 1363a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 1364a9de9248SMarcel Holtmann 1365a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 1366a9de9248SMarcel Holtmann 1367a9de9248SMarcel Holtmann switch (opcode) { 1368a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 1369a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 1370a9de9248SMarcel Holtmann break; 1371a9de9248SMarcel Holtmann 1372a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 1373a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 1374a9de9248SMarcel Holtmann break; 1375a9de9248SMarcel Holtmann 1376a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 1377a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 1378a9de9248SMarcel Holtmann break; 1379a9de9248SMarcel Holtmann 1380f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 1381f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 1382f8558555SMarcel Holtmann break; 1383f8558555SMarcel Holtmann 1384f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 1385f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 1386f8558555SMarcel Holtmann break; 1387f8558555SMarcel Holtmann 1388a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 1389a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 1390a9de9248SMarcel Holtmann break; 1391a9de9248SMarcel Holtmann 1392769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 1393769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 1394769be974SMarcel Holtmann break; 1395769be974SMarcel Holtmann 1396769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 1397769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 1398769be974SMarcel Holtmann break; 1399769be974SMarcel Holtmann 1400a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 1401a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 1402a9de9248SMarcel Holtmann break; 1403a9de9248SMarcel Holtmann 1404a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 1405a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 1406a9de9248SMarcel Holtmann break; 1407a9de9248SMarcel Holtmann 1408a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 1409a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 1410a9de9248SMarcel Holtmann break; 1411a9de9248SMarcel Holtmann 1412a9de9248SMarcel Holtmann default: 1413a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 1414a9de9248SMarcel Holtmann break; 1415a9de9248SMarcel Holtmann } 1416a9de9248SMarcel Holtmann 1417a9de9248SMarcel Holtmann if (ev->ncmd) { 1418a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 1419a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 1420c78ae283SMarcel Holtmann tasklet_schedule(&hdev->cmd_task); 1421a9de9248SMarcel Holtmann } 1422a9de9248SMarcel Holtmann } 1423a9de9248SMarcel Holtmann 1424a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 1425a9de9248SMarcel Holtmann { 1426a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 1427a9de9248SMarcel Holtmann struct hci_conn *conn; 1428a9de9248SMarcel Holtmann 1429a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1430a9de9248SMarcel Holtmann 1431a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1432a9de9248SMarcel Holtmann 1433a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 1434a9de9248SMarcel Holtmann if (conn) { 1435a9de9248SMarcel Holtmann if (!ev->status) { 1436a9de9248SMarcel Holtmann if (ev->role) 1437a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_MASTER; 1438a9de9248SMarcel Holtmann else 1439a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_MASTER; 1440a9de9248SMarcel Holtmann } 1441a9de9248SMarcel Holtmann 1442a9de9248SMarcel Holtmann clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend); 1443a9de9248SMarcel Holtmann 1444a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 1445a9de9248SMarcel Holtmann } 1446a9de9248SMarcel Holtmann 1447a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1448a9de9248SMarcel Holtmann } 1449a9de9248SMarcel Holtmann 14501da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 14511da177e4SLinus Torvalds { 1452a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 14531ebb9252SMarcel Holtmann __le16 *ptr; 14541da177e4SLinus Torvalds int i; 14551da177e4SLinus Torvalds 14561da177e4SLinus Torvalds skb_pull(skb, sizeof(*ev)); 14571da177e4SLinus Torvalds 14581da177e4SLinus Torvalds BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 14591da177e4SLinus Torvalds 14601da177e4SLinus Torvalds if (skb->len < ev->num_hndl * 4) { 14611da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 14621da177e4SLinus Torvalds return; 14631da177e4SLinus Torvalds } 14641da177e4SLinus Torvalds 14651da177e4SLinus Torvalds tasklet_disable(&hdev->tx_task); 14661da177e4SLinus Torvalds 14671ebb9252SMarcel Holtmann for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) { 14681da177e4SLinus Torvalds struct hci_conn *conn; 14691da177e4SLinus Torvalds __u16 handle, count; 14701da177e4SLinus Torvalds 147183985319SHarvey Harrison handle = get_unaligned_le16(ptr++); 147283985319SHarvey Harrison count = get_unaligned_le16(ptr++); 14731da177e4SLinus Torvalds 14741da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 14751da177e4SLinus Torvalds if (conn) { 14761da177e4SLinus Torvalds conn->sent -= count; 14771da177e4SLinus Torvalds 14785b7f9909SMarcel Holtmann if (conn->type == ACL_LINK) { 14791da177e4SLinus Torvalds if ((hdev->acl_cnt += count) > hdev->acl_pkts) 14801da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 14815b7f9909SMarcel Holtmann } else { 14825b7f9909SMarcel Holtmann if ((hdev->sco_cnt += count) > hdev->sco_pkts) 14835b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 14841da177e4SLinus Torvalds } 14851da177e4SLinus Torvalds } 14861da177e4SLinus Torvalds } 1487a9de9248SMarcel Holtmann 1488c78ae283SMarcel Holtmann tasklet_schedule(&hdev->tx_task); 14891da177e4SLinus Torvalds 14901da177e4SLinus Torvalds tasklet_enable(&hdev->tx_task); 14911da177e4SLinus Torvalds } 14921da177e4SLinus Torvalds 149304837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 14941da177e4SLinus Torvalds { 1495a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 149604837f64SMarcel Holtmann struct hci_conn *conn; 14971da177e4SLinus Torvalds 14981da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 14991da177e4SLinus Torvalds 15001da177e4SLinus Torvalds hci_dev_lock(hdev); 15011da177e4SLinus Torvalds 150204837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 150304837f64SMarcel Holtmann if (conn) { 150404837f64SMarcel Holtmann conn->mode = ev->mode; 150504837f64SMarcel Holtmann conn->interval = __le16_to_cpu(ev->interval); 150604837f64SMarcel Holtmann 150704837f64SMarcel Holtmann if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) { 150804837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 150904837f64SMarcel Holtmann conn->power_save = 1; 151004837f64SMarcel Holtmann else 151104837f64SMarcel Holtmann conn->power_save = 0; 151204837f64SMarcel Holtmann } 1513e73439d8SMarcel Holtmann 1514e73439d8SMarcel Holtmann if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend)) 1515e73439d8SMarcel Holtmann hci_sco_setup(conn, ev->status); 151604837f64SMarcel Holtmann } 151704837f64SMarcel Holtmann 151804837f64SMarcel Holtmann hci_dev_unlock(hdev); 151904837f64SMarcel Holtmann } 152004837f64SMarcel Holtmann 15211da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 15221da177e4SLinus Torvalds { 1523052b30b0SMarcel Holtmann struct hci_ev_pin_code_req *ev = (void *) skb->data; 1524052b30b0SMarcel Holtmann struct hci_conn *conn; 1525052b30b0SMarcel Holtmann 1526a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1527052b30b0SMarcel Holtmann 1528052b30b0SMarcel Holtmann hci_dev_lock(hdev); 1529052b30b0SMarcel Holtmann 1530052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 15313d7a9d1cSMarcel Holtmann if (conn && conn->state == BT_CONNECTED) { 1532052b30b0SMarcel Holtmann hci_conn_hold(conn); 1533052b30b0SMarcel Holtmann conn->disc_timeout = HCI_PAIRING_TIMEOUT; 1534052b30b0SMarcel Holtmann hci_conn_put(conn); 1535052b30b0SMarcel Holtmann } 1536052b30b0SMarcel Holtmann 1537052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 15381da177e4SLinus Torvalds } 15391da177e4SLinus Torvalds 15401da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 15411da177e4SLinus Torvalds { 1542a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 15431da177e4SLinus Torvalds } 15441da177e4SLinus Torvalds 15451da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 15461da177e4SLinus Torvalds { 1547052b30b0SMarcel Holtmann struct hci_ev_link_key_notify *ev = (void *) skb->data; 1548052b30b0SMarcel Holtmann struct hci_conn *conn; 1549052b30b0SMarcel Holtmann 1550a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1551052b30b0SMarcel Holtmann 1552052b30b0SMarcel Holtmann hci_dev_lock(hdev); 1553052b30b0SMarcel Holtmann 1554052b30b0SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 1555052b30b0SMarcel Holtmann if (conn) { 1556052b30b0SMarcel Holtmann hci_conn_hold(conn); 1557052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 1558052b30b0SMarcel Holtmann hci_conn_put(conn); 1559052b30b0SMarcel Holtmann } 1560052b30b0SMarcel Holtmann 1561052b30b0SMarcel Holtmann hci_dev_unlock(hdev); 15621da177e4SLinus Torvalds } 15631da177e4SLinus Torvalds 156404837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 156504837f64SMarcel Holtmann { 1566a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 156704837f64SMarcel Holtmann struct hci_conn *conn; 156804837f64SMarcel Holtmann 156904837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 157004837f64SMarcel Holtmann 157104837f64SMarcel Holtmann hci_dev_lock(hdev); 157204837f64SMarcel Holtmann 157304837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 15741da177e4SLinus Torvalds if (conn && !ev->status) { 15751da177e4SLinus Torvalds struct inquiry_entry *ie; 15761da177e4SLinus Torvalds 15771da177e4SLinus Torvalds if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst))) { 15781da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 15791da177e4SLinus Torvalds ie->timestamp = jiffies; 15801da177e4SLinus Torvalds } 15811da177e4SLinus Torvalds } 15821da177e4SLinus Torvalds 15831da177e4SLinus Torvalds hci_dev_unlock(hdev); 15841da177e4SLinus Torvalds } 15851da177e4SLinus Torvalds 1586a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 1587a8746417SMarcel Holtmann { 1588a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 1589a8746417SMarcel Holtmann struct hci_conn *conn; 1590a8746417SMarcel Holtmann 1591a8746417SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1592a8746417SMarcel Holtmann 1593a8746417SMarcel Holtmann hci_dev_lock(hdev); 1594a8746417SMarcel Holtmann 1595a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1596a8746417SMarcel Holtmann if (conn && !ev->status) 1597a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 1598a8746417SMarcel Holtmann 1599a8746417SMarcel Holtmann hci_dev_unlock(hdev); 1600a8746417SMarcel Holtmann } 1601a8746417SMarcel Holtmann 160285a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 160385a1e930SMarcel Holtmann { 1604a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 160585a1e930SMarcel Holtmann struct inquiry_entry *ie; 160685a1e930SMarcel Holtmann 160785a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 160885a1e930SMarcel Holtmann 160985a1e930SMarcel Holtmann hci_dev_lock(hdev); 161085a1e930SMarcel Holtmann 161185a1e930SMarcel Holtmann if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr))) { 161285a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 161385a1e930SMarcel Holtmann ie->timestamp = jiffies; 161485a1e930SMarcel Holtmann } 161585a1e930SMarcel Holtmann 161685a1e930SMarcel Holtmann hci_dev_unlock(hdev); 161785a1e930SMarcel Holtmann } 161885a1e930SMarcel Holtmann 1619a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb) 1620a9de9248SMarcel Holtmann { 1621a9de9248SMarcel Holtmann struct inquiry_data data; 1622a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 1623a9de9248SMarcel Holtmann 1624a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 1625a9de9248SMarcel Holtmann 1626a9de9248SMarcel Holtmann if (!num_rsp) 1627a9de9248SMarcel Holtmann return; 1628a9de9248SMarcel Holtmann 1629a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1630a9de9248SMarcel Holtmann 1631a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 1632a9de9248SMarcel Holtmann struct inquiry_info_with_rssi_and_pscan_mode *info = (void *) (skb->data + 1); 1633a9de9248SMarcel Holtmann 1634a9de9248SMarcel Holtmann for (; num_rsp; num_rsp--) { 1635a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 1636a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 1637a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 1638a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 1639a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 1640a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 1641a9de9248SMarcel Holtmann data.rssi = info->rssi; 164241a96212SMarcel Holtmann data.ssp_mode = 0x00; 1643a9de9248SMarcel Holtmann info++; 1644a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 1645a9de9248SMarcel Holtmann } 1646a9de9248SMarcel Holtmann } else { 1647a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 1648a9de9248SMarcel Holtmann 1649a9de9248SMarcel Holtmann for (; num_rsp; num_rsp--) { 1650a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 1651a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 1652a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 1653a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 1654a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 1655a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 1656a9de9248SMarcel Holtmann data.rssi = info->rssi; 165741a96212SMarcel Holtmann data.ssp_mode = 0x00; 1658a9de9248SMarcel Holtmann info++; 1659a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 1660a9de9248SMarcel Holtmann } 1661a9de9248SMarcel Holtmann } 1662a9de9248SMarcel Holtmann 1663a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1664a9de9248SMarcel Holtmann } 1665a9de9248SMarcel Holtmann 1666a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 1667a9de9248SMarcel Holtmann { 166841a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 166941a96212SMarcel Holtmann struct hci_conn *conn; 1670392599b9SJohan Hedberg int auth_requested; 167141a96212SMarcel Holtmann 1672a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 167341a96212SMarcel Holtmann 167441a96212SMarcel Holtmann hci_dev_lock(hdev); 167541a96212SMarcel Holtmann 167641a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1677ccd556feSJohan Hedberg if (!conn) 1678ccd556feSJohan Hedberg goto unlock; 1679ccd556feSJohan Hedberg 1680769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 168141a96212SMarcel Holtmann struct inquiry_entry *ie; 168241a96212SMarcel Holtmann 168341a96212SMarcel Holtmann if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst))) 168441a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 168541a96212SMarcel Holtmann 168641a96212SMarcel Holtmann conn->ssp_mode = (ev->features[0] & 0x01); 168741a96212SMarcel Holtmann } 168841a96212SMarcel Holtmann 1689ccd556feSJohan Hedberg if (conn->state != BT_CONFIG) 1690ccd556feSJohan Hedberg goto unlock; 1691ccd556feSJohan Hedberg 1692392599b9SJohan Hedberg if (!ev->status) 1693392599b9SJohan Hedberg auth_requested = hci_request_outgoing_auth(hdev, conn); 1694392599b9SJohan Hedberg else 1695392599b9SJohan Hedberg auth_requested = 0; 1696392599b9SJohan Hedberg 1697392599b9SJohan Hedberg if (!auth_requested) { 1698769be974SMarcel Holtmann conn->state = BT_CONNECTED; 1699769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1700769be974SMarcel Holtmann hci_conn_put(conn); 1701769be974SMarcel Holtmann } 1702769be974SMarcel Holtmann 1703ccd556feSJohan Hedberg unlock: 170441a96212SMarcel Holtmann hci_dev_unlock(hdev); 1705a9de9248SMarcel Holtmann } 1706a9de9248SMarcel Holtmann 1707a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1708a9de9248SMarcel Holtmann { 1709b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 1710b6a0dc82SMarcel Holtmann struct hci_conn *conn; 1711b6a0dc82SMarcel Holtmann 1712b6a0dc82SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1713b6a0dc82SMarcel Holtmann 1714b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 1715b6a0dc82SMarcel Holtmann 1716b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 17179dc0a3afSMarcel Holtmann if (!conn) { 17189dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 17199dc0a3afSMarcel Holtmann goto unlock; 17209dc0a3afSMarcel Holtmann 17219dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 1722b6a0dc82SMarcel Holtmann if (!conn) 1723b6a0dc82SMarcel Holtmann goto unlock; 1724b6a0dc82SMarcel Holtmann 17259dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 17269dc0a3afSMarcel Holtmann } 17279dc0a3afSMarcel Holtmann 1728732547f9SMarcel Holtmann switch (ev->status) { 1729732547f9SMarcel Holtmann case 0x00: 1730732547f9SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 1731732547f9SMarcel Holtmann conn->state = BT_CONNECTED; 1732732547f9SMarcel Holtmann 17339eba32b8SMarcel Holtmann hci_conn_hold_device(conn); 1734732547f9SMarcel Holtmann hci_conn_add_sysfs(conn); 1735732547f9SMarcel Holtmann break; 1736732547f9SMarcel Holtmann 1737705e5711SStephen Coe case 0x11: /* Unsupported Feature or Parameter Value */ 1738732547f9SMarcel Holtmann case 0x1c: /* SCO interval rejected */ 17391038a00bSNick Pelly case 0x1a: /* Unsupported Remote Feature */ 1740732547f9SMarcel Holtmann case 0x1f: /* Unspecified error */ 1741732547f9SMarcel Holtmann if (conn->out && conn->attempt < 2) { 1742efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 1743efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 1744efc7688bSMarcel Holtmann hci_setup_sync(conn, conn->link->handle); 1745efc7688bSMarcel Holtmann goto unlock; 1746efc7688bSMarcel Holtmann } 1747732547f9SMarcel Holtmann /* fall through */ 1748efc7688bSMarcel Holtmann 1749732547f9SMarcel Holtmann default: 1750b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 1751732547f9SMarcel Holtmann break; 1752732547f9SMarcel Holtmann } 1753b6a0dc82SMarcel Holtmann 1754b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1755b6a0dc82SMarcel Holtmann if (ev->status) 1756b6a0dc82SMarcel Holtmann hci_conn_del(conn); 1757b6a0dc82SMarcel Holtmann 1758b6a0dc82SMarcel Holtmann unlock: 1759b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 1760a9de9248SMarcel Holtmann } 1761a9de9248SMarcel Holtmann 1762a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) 1763a9de9248SMarcel Holtmann { 1764a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1765a9de9248SMarcel Holtmann } 1766a9de9248SMarcel Holtmann 176704837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) 176804837f64SMarcel Holtmann { 1769a9de9248SMarcel Holtmann struct hci_ev_sniff_subrate *ev = (void *) skb->data; 177004837f64SMarcel Holtmann struct hci_conn *conn; 177104837f64SMarcel Holtmann 177204837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 177304837f64SMarcel Holtmann 177404837f64SMarcel Holtmann hci_dev_lock(hdev); 177504837f64SMarcel Holtmann 177604837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 177704837f64SMarcel Holtmann if (conn) { 177804837f64SMarcel Holtmann } 177904837f64SMarcel Holtmann 178004837f64SMarcel Holtmann hci_dev_unlock(hdev); 178104837f64SMarcel Holtmann } 178204837f64SMarcel Holtmann 1783a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 1784a9de9248SMarcel Holtmann { 1785a9de9248SMarcel Holtmann struct inquiry_data data; 1786a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 1787a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 1788a9de9248SMarcel Holtmann 1789a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 1790a9de9248SMarcel Holtmann 1791a9de9248SMarcel Holtmann if (!num_rsp) 1792a9de9248SMarcel Holtmann return; 1793a9de9248SMarcel Holtmann 1794a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1795a9de9248SMarcel Holtmann 1796a9de9248SMarcel Holtmann for (; num_rsp; num_rsp--) { 1797a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 1798a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 1799a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 1800a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 1801a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 1802a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 1803a9de9248SMarcel Holtmann data.rssi = info->rssi; 180441a96212SMarcel Holtmann data.ssp_mode = 0x01; 1805a9de9248SMarcel Holtmann info++; 1806a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 1807a9de9248SMarcel Holtmann } 1808a9de9248SMarcel Holtmann 1809a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1810a9de9248SMarcel Holtmann } 1811a9de9248SMarcel Holtmann 18120493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 18130493684eSMarcel Holtmann { 18140493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 18150493684eSMarcel Holtmann struct hci_conn *conn; 18160493684eSMarcel Holtmann 18170493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 18180493684eSMarcel Holtmann 18190493684eSMarcel Holtmann hci_dev_lock(hdev); 18200493684eSMarcel Holtmann 18210493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 18220493684eSMarcel Holtmann if (conn) 18230493684eSMarcel Holtmann hci_conn_hold(conn); 18240493684eSMarcel Holtmann 18250493684eSMarcel Holtmann hci_dev_unlock(hdev); 18260493684eSMarcel Holtmann } 18270493684eSMarcel Holtmann 18280493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 18290493684eSMarcel Holtmann { 18300493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 18310493684eSMarcel Holtmann struct hci_conn *conn; 18320493684eSMarcel Holtmann 18330493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 18340493684eSMarcel Holtmann 18350493684eSMarcel Holtmann hci_dev_lock(hdev); 18360493684eSMarcel Holtmann 18370493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 18380493684eSMarcel Holtmann if (conn) 18390493684eSMarcel Holtmann hci_conn_put(conn); 18400493684eSMarcel Holtmann 18410493684eSMarcel Holtmann hci_dev_unlock(hdev); 18420493684eSMarcel Holtmann } 18430493684eSMarcel Holtmann 184441a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 184541a96212SMarcel Holtmann { 184641a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 184741a96212SMarcel Holtmann struct inquiry_entry *ie; 184841a96212SMarcel Holtmann 184941a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 185041a96212SMarcel Holtmann 185141a96212SMarcel Holtmann hci_dev_lock(hdev); 185241a96212SMarcel Holtmann 185341a96212SMarcel Holtmann if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr))) 185441a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 185541a96212SMarcel Holtmann 185641a96212SMarcel Holtmann hci_dev_unlock(hdev); 185741a96212SMarcel Holtmann } 185841a96212SMarcel Holtmann 18591da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 18601da177e4SLinus Torvalds { 1861a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 1862a9de9248SMarcel Holtmann __u8 event = hdr->evt; 18631da177e4SLinus Torvalds 18641da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 18651da177e4SLinus Torvalds 1866a9de9248SMarcel Holtmann switch (event) { 18671da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 18681da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 18691da177e4SLinus Torvalds break; 18701da177e4SLinus Torvalds 18711da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 18721da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 18731da177e4SLinus Torvalds break; 18741da177e4SLinus Torvalds 1875a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 1876a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 187721d9e30eSMarcel Holtmann break; 187821d9e30eSMarcel Holtmann 18791da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 18801da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 18811da177e4SLinus Torvalds break; 18821da177e4SLinus Torvalds 18831da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 18841da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 18851da177e4SLinus Torvalds break; 18861da177e4SLinus Torvalds 18871da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 18881da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 18891da177e4SLinus Torvalds break; 18901da177e4SLinus Torvalds 1891a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 1892a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 1893a9de9248SMarcel Holtmann break; 1894a9de9248SMarcel Holtmann 18951da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 18961da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 18971da177e4SLinus Torvalds break; 18981da177e4SLinus Torvalds 1899a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 1900a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 1901a9de9248SMarcel Holtmann break; 1902a9de9248SMarcel Holtmann 1903a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 1904a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 1905a9de9248SMarcel Holtmann break; 1906a9de9248SMarcel Holtmann 1907a9de9248SMarcel Holtmann case HCI_EV_REMOTE_VERSION: 1908a9de9248SMarcel Holtmann hci_remote_version_evt(hdev, skb); 1909a9de9248SMarcel Holtmann break; 1910a9de9248SMarcel Holtmann 1911a9de9248SMarcel Holtmann case HCI_EV_QOS_SETUP_COMPLETE: 1912a9de9248SMarcel Holtmann hci_qos_setup_complete_evt(hdev, skb); 1913a9de9248SMarcel Holtmann break; 1914a9de9248SMarcel Holtmann 1915a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 1916a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 1917a9de9248SMarcel Holtmann break; 1918a9de9248SMarcel Holtmann 1919a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 1920a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 1921a9de9248SMarcel Holtmann break; 1922a9de9248SMarcel Holtmann 1923a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 1924a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 1925a9de9248SMarcel Holtmann break; 1926a9de9248SMarcel Holtmann 1927a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 1928a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 1929a9de9248SMarcel Holtmann break; 1930a9de9248SMarcel Holtmann 1931a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 1932a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 19331da177e4SLinus Torvalds break; 19341da177e4SLinus Torvalds 19351da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 19361da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 19371da177e4SLinus Torvalds break; 19381da177e4SLinus Torvalds 19391da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 19401da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 19411da177e4SLinus Torvalds break; 19421da177e4SLinus Torvalds 19431da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 19441da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 19451da177e4SLinus Torvalds break; 19461da177e4SLinus Torvalds 19471da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 19481da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 19491da177e4SLinus Torvalds break; 19501da177e4SLinus Torvalds 1951a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 1952a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 1953a8746417SMarcel Holtmann break; 1954a8746417SMarcel Holtmann 195585a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 195685a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 195785a1e930SMarcel Holtmann break; 195885a1e930SMarcel Holtmann 1959a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 1960a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 1961a9de9248SMarcel Holtmann break; 1962a9de9248SMarcel Holtmann 1963a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 1964a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 1965a9de9248SMarcel Holtmann break; 1966a9de9248SMarcel Holtmann 1967a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 1968a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 1969a9de9248SMarcel Holtmann break; 1970a9de9248SMarcel Holtmann 1971a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_CHANGED: 1972a9de9248SMarcel Holtmann hci_sync_conn_changed_evt(hdev, skb); 1973a9de9248SMarcel Holtmann break; 1974a9de9248SMarcel Holtmann 197504837f64SMarcel Holtmann case HCI_EV_SNIFF_SUBRATE: 197604837f64SMarcel Holtmann hci_sniff_subrate_evt(hdev, skb); 197704837f64SMarcel Holtmann break; 197804837f64SMarcel Holtmann 1979a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 1980a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 19811da177e4SLinus Torvalds break; 19821da177e4SLinus Torvalds 19830493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 19840493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 19850493684eSMarcel Holtmann break; 19860493684eSMarcel Holtmann 19870493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 19880493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 19890493684eSMarcel Holtmann break; 19900493684eSMarcel Holtmann 199141a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 199241a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 199341a96212SMarcel Holtmann break; 199441a96212SMarcel Holtmann 19951da177e4SLinus Torvalds default: 1996a9de9248SMarcel Holtmann BT_DBG("%s event 0x%x", hdev->name, event); 19971da177e4SLinus Torvalds break; 19981da177e4SLinus Torvalds } 19991da177e4SLinus Torvalds 20001da177e4SLinus Torvalds kfree_skb(skb); 20011da177e4SLinus Torvalds hdev->stat.evt_rx++; 20021da177e4SLinus Torvalds } 20031da177e4SLinus Torvalds 20041da177e4SLinus Torvalds /* Generate internal stack event */ 20051da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data) 20061da177e4SLinus Torvalds { 20071da177e4SLinus Torvalds struct hci_event_hdr *hdr; 20081da177e4SLinus Torvalds struct hci_ev_stack_internal *ev; 20091da177e4SLinus Torvalds struct sk_buff *skb; 20101da177e4SLinus Torvalds 20111da177e4SLinus Torvalds skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC); 20121da177e4SLinus Torvalds if (!skb) 20131da177e4SLinus Torvalds return; 20141da177e4SLinus Torvalds 20151da177e4SLinus Torvalds hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE); 20161da177e4SLinus Torvalds hdr->evt = HCI_EV_STACK_INTERNAL; 20171da177e4SLinus Torvalds hdr->plen = sizeof(*ev) + dlen; 20181da177e4SLinus Torvalds 20191da177e4SLinus Torvalds ev = (void *) skb_put(skb, sizeof(*ev) + dlen); 20201da177e4SLinus Torvalds ev->type = type; 20211da177e4SLinus Torvalds memcpy(ev->data, data, dlen); 20221da177e4SLinus Torvalds 2023576c7d85SMarcel Holtmann bt_cb(skb)->incoming = 1; 2024a61bbcf2SPatrick McHardy __net_timestamp(skb); 2025576c7d85SMarcel Holtmann 20260d48d939SMarcel Holtmann bt_cb(skb)->pkt_type = HCI_EVENT_PKT; 20271da177e4SLinus Torvalds skb->dev = (void *) hdev; 20281da177e4SLinus Torvalds hci_send_to_sock(hdev, skb); 20291da177e4SLinus Torvalds kfree_skb(skb); 20301da177e4SLinus Torvalds } 2031