11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds BlueZ - Bluetooth protocol stack for Linux 31da177e4SLinus Torvalds Copyright (C) 2000-2001 Qualcomm Incorporated 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 #ifndef CONFIG_BT_HCI_CORE_DEBUG 491da177e4SLinus Torvalds #undef BT_DBG 501da177e4SLinus Torvalds #define BT_DBG(D...) 511da177e4SLinus Torvalds #endif 521da177e4SLinus Torvalds 531da177e4SLinus Torvalds /* Handle HCI Event packets */ 541da177e4SLinus Torvalds 55a9de9248SMarcel Holtmann static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb) 561da177e4SLinus Torvalds { 57a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 581da177e4SLinus Torvalds 59a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 601da177e4SLinus Torvalds 61a9de9248SMarcel Holtmann if (status) 62a9de9248SMarcel Holtmann return; 631da177e4SLinus Torvalds 641da177e4SLinus Torvalds clear_bit(HCI_INQUIRY, &hdev->flags); 65a9de9248SMarcel Holtmann 661da177e4SLinus Torvalds hci_req_complete(hdev, status); 67a9de9248SMarcel Holtmann 68a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 691da177e4SLinus Torvalds } 706bd57416SMarcel Holtmann 71a9de9248SMarcel Holtmann static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) 721da177e4SLinus Torvalds { 73a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 74a9de9248SMarcel Holtmann 75a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 76a9de9248SMarcel Holtmann 77a9de9248SMarcel Holtmann if (status) 78a9de9248SMarcel Holtmann return; 79a9de9248SMarcel Holtmann 80a9de9248SMarcel Holtmann clear_bit(HCI_INQUIRY, &hdev->flags); 81a9de9248SMarcel Holtmann 82a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 83a9de9248SMarcel Holtmann } 84a9de9248SMarcel Holtmann 85a9de9248SMarcel Holtmann static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb) 86a9de9248SMarcel Holtmann { 87a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 88a9de9248SMarcel Holtmann } 89a9de9248SMarcel Holtmann 90a9de9248SMarcel Holtmann static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb) 91a9de9248SMarcel Holtmann { 92a9de9248SMarcel Holtmann struct hci_rp_role_discovery *rp = (void *) skb->data; 931da177e4SLinus Torvalds struct hci_conn *conn; 941da177e4SLinus Torvalds 95a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 961da177e4SLinus Torvalds 97a9de9248SMarcel Holtmann if (rp->status) 98a9de9248SMarcel Holtmann return; 991da177e4SLinus Torvalds 1001da177e4SLinus Torvalds hci_dev_lock(hdev); 1011da177e4SLinus Torvalds 102a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 1031da177e4SLinus Torvalds if (conn) { 104a9de9248SMarcel Holtmann if (rp->role) 1051da177e4SLinus Torvalds conn->link_mode &= ~HCI_LM_MASTER; 1061da177e4SLinus Torvalds else 1071da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 1081da177e4SLinus Torvalds } 1091da177e4SLinus Torvalds 1101da177e4SLinus Torvalds hci_dev_unlock(hdev); 111a9de9248SMarcel Holtmann } 1121da177e4SLinus Torvalds 113e4e8e37cSMarcel Holtmann static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 114e4e8e37cSMarcel Holtmann { 115e4e8e37cSMarcel Holtmann struct hci_rp_read_link_policy *rp = (void *) skb->data; 116e4e8e37cSMarcel Holtmann struct hci_conn *conn; 117e4e8e37cSMarcel Holtmann 118e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 119e4e8e37cSMarcel Holtmann 120e4e8e37cSMarcel Holtmann if (rp->status) 121e4e8e37cSMarcel Holtmann return; 122e4e8e37cSMarcel Holtmann 123e4e8e37cSMarcel Holtmann hci_dev_lock(hdev); 124e4e8e37cSMarcel Holtmann 125e4e8e37cSMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 126e4e8e37cSMarcel Holtmann if (conn) 127e4e8e37cSMarcel Holtmann conn->link_policy = __le16_to_cpu(rp->policy); 128e4e8e37cSMarcel Holtmann 129e4e8e37cSMarcel Holtmann hci_dev_unlock(hdev); 130e4e8e37cSMarcel Holtmann } 131e4e8e37cSMarcel Holtmann 132a9de9248SMarcel Holtmann static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 133a9de9248SMarcel Holtmann { 134a9de9248SMarcel Holtmann struct hci_rp_write_link_policy *rp = (void *) skb->data; 135a9de9248SMarcel Holtmann struct hci_conn *conn; 136a9de9248SMarcel Holtmann void *sent; 137a9de9248SMarcel Holtmann 138a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 139a9de9248SMarcel Holtmann 140a9de9248SMarcel Holtmann if (rp->status) 141a9de9248SMarcel Holtmann return; 142a9de9248SMarcel Holtmann 143a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY); 14404837f64SMarcel Holtmann if (!sent) 145a9de9248SMarcel Holtmann return; 14604837f64SMarcel Holtmann 14704837f64SMarcel Holtmann hci_dev_lock(hdev); 14804837f64SMarcel Holtmann 149a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); 150e4e8e37cSMarcel Holtmann if (conn) 15183985319SHarvey Harrison conn->link_policy = get_unaligned_le16(sent + 2); 15204837f64SMarcel Holtmann 15304837f64SMarcel Holtmann hci_dev_unlock(hdev); 1541da177e4SLinus Torvalds } 1551da177e4SLinus Torvalds 156e4e8e37cSMarcel Holtmann static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 157e4e8e37cSMarcel Holtmann { 158e4e8e37cSMarcel Holtmann struct hci_rp_read_def_link_policy *rp = (void *) skb->data; 159e4e8e37cSMarcel Holtmann 160e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 161e4e8e37cSMarcel Holtmann 162e4e8e37cSMarcel Holtmann if (rp->status) 163e4e8e37cSMarcel Holtmann return; 164e4e8e37cSMarcel Holtmann 165e4e8e37cSMarcel Holtmann hdev->link_policy = __le16_to_cpu(rp->policy); 166e4e8e37cSMarcel Holtmann } 167e4e8e37cSMarcel Holtmann 168e4e8e37cSMarcel Holtmann static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb) 169e4e8e37cSMarcel Holtmann { 170e4e8e37cSMarcel Holtmann __u8 status = *((__u8 *) skb->data); 171e4e8e37cSMarcel Holtmann void *sent; 172e4e8e37cSMarcel Holtmann 173e4e8e37cSMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 174e4e8e37cSMarcel Holtmann 175e4e8e37cSMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY); 176e4e8e37cSMarcel Holtmann if (!sent) 177e4e8e37cSMarcel Holtmann return; 178e4e8e37cSMarcel Holtmann 179e4e8e37cSMarcel Holtmann if (!status) 180e4e8e37cSMarcel Holtmann hdev->link_policy = get_unaligned_le16(sent); 181e4e8e37cSMarcel Holtmann 182e4e8e37cSMarcel Holtmann hci_req_complete(hdev, status); 183e4e8e37cSMarcel Holtmann } 184e4e8e37cSMarcel Holtmann 185a9de9248SMarcel Holtmann static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) 1861da177e4SLinus Torvalds { 187a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 188a9de9248SMarcel Holtmann 189a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 190a9de9248SMarcel Holtmann 191a9de9248SMarcel Holtmann hci_req_complete(hdev, status); 192a9de9248SMarcel Holtmann } 193a9de9248SMarcel Holtmann 194a9de9248SMarcel Holtmann static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) 195a9de9248SMarcel Holtmann { 196a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 1971da177e4SLinus Torvalds void *sent; 1981da177e4SLinus Torvalds 199a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 2001da177e4SLinus Torvalds 201f383f275SMarcel Holtmann if (status) 202f383f275SMarcel Holtmann return; 203f383f275SMarcel Holtmann 204a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); 2051da177e4SLinus Torvalds if (!sent) 206a9de9248SMarcel Holtmann return; 2071da177e4SLinus Torvalds 208a9de9248SMarcel Holtmann memcpy(hdev->dev_name, sent, 248); 209a9de9248SMarcel Holtmann } 210a9de9248SMarcel Holtmann 211a9de9248SMarcel Holtmann static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) 212a9de9248SMarcel Holtmann { 213a9de9248SMarcel Holtmann struct hci_rp_read_local_name *rp = (void *) skb->data; 214a9de9248SMarcel Holtmann 215a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 216a9de9248SMarcel Holtmann 217a9de9248SMarcel Holtmann if (rp->status) 218a9de9248SMarcel Holtmann return; 219a9de9248SMarcel Holtmann 220a9de9248SMarcel Holtmann memcpy(hdev->dev_name, rp->name, 248); 221a9de9248SMarcel Holtmann } 222a9de9248SMarcel Holtmann 223a9de9248SMarcel Holtmann static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) 224a9de9248SMarcel Holtmann { 225a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 226a9de9248SMarcel Holtmann void *sent; 227a9de9248SMarcel Holtmann 228a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 229a9de9248SMarcel Holtmann 230a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); 231a9de9248SMarcel Holtmann if (!sent) 232a9de9248SMarcel Holtmann return; 2331da177e4SLinus Torvalds 2341da177e4SLinus Torvalds if (!status) { 235a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 236a9de9248SMarcel Holtmann 2371da177e4SLinus Torvalds if (param == AUTH_ENABLED) 2381da177e4SLinus Torvalds set_bit(HCI_AUTH, &hdev->flags); 2391da177e4SLinus Torvalds else 2401da177e4SLinus Torvalds clear_bit(HCI_AUTH, &hdev->flags); 2411da177e4SLinus Torvalds } 242a9de9248SMarcel Holtmann 2431da177e4SLinus Torvalds hci_req_complete(hdev, status); 244a9de9248SMarcel Holtmann } 2451da177e4SLinus Torvalds 246a9de9248SMarcel Holtmann static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) 247a9de9248SMarcel Holtmann { 248a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 249a9de9248SMarcel Holtmann void *sent; 250a9de9248SMarcel Holtmann 251a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 252a9de9248SMarcel Holtmann 253a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); 2541da177e4SLinus Torvalds if (!sent) 255a9de9248SMarcel Holtmann return; 2561da177e4SLinus Torvalds 2571da177e4SLinus Torvalds if (!status) { 258a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 259a9de9248SMarcel Holtmann 2601da177e4SLinus Torvalds if (param) 2611da177e4SLinus Torvalds set_bit(HCI_ENCRYPT, &hdev->flags); 2621da177e4SLinus Torvalds else 2631da177e4SLinus Torvalds clear_bit(HCI_ENCRYPT, &hdev->flags); 2641da177e4SLinus Torvalds } 265a9de9248SMarcel Holtmann 2661da177e4SLinus Torvalds hci_req_complete(hdev, status); 2671da177e4SLinus Torvalds } 2681da177e4SLinus Torvalds 269a9de9248SMarcel Holtmann static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) 270a9de9248SMarcel Holtmann { 271a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 272a9de9248SMarcel Holtmann void *sent; 2731da177e4SLinus Torvalds 274a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 275a9de9248SMarcel Holtmann 276a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); 2771da177e4SLinus Torvalds if (!sent) 278a9de9248SMarcel Holtmann return; 2791da177e4SLinus Torvalds 2801da177e4SLinus Torvalds if (!status) { 281a9de9248SMarcel Holtmann __u8 param = *((__u8 *) sent); 282a9de9248SMarcel Holtmann 2831da177e4SLinus Torvalds clear_bit(HCI_PSCAN, &hdev->flags); 2841da177e4SLinus Torvalds clear_bit(HCI_ISCAN, &hdev->flags); 285a9de9248SMarcel Holtmann 2861da177e4SLinus Torvalds if (param & SCAN_INQUIRY) 2871da177e4SLinus Torvalds set_bit(HCI_ISCAN, &hdev->flags); 2881da177e4SLinus Torvalds 2891da177e4SLinus Torvalds if (param & SCAN_PAGE) 2901da177e4SLinus Torvalds set_bit(HCI_PSCAN, &hdev->flags); 2911da177e4SLinus Torvalds } 292a9de9248SMarcel Holtmann 2931da177e4SLinus Torvalds hci_req_complete(hdev, status); 2941da177e4SLinus Torvalds } 2951da177e4SLinus Torvalds 296a9de9248SMarcel Holtmann static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 297a9de9248SMarcel Holtmann { 298a9de9248SMarcel Holtmann struct hci_rp_read_class_of_dev *rp = (void *) skb->data; 299a9de9248SMarcel Holtmann 300a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 301a9de9248SMarcel Holtmann 302a9de9248SMarcel Holtmann if (rp->status) 303a9de9248SMarcel Holtmann return; 304a9de9248SMarcel Holtmann 305a9de9248SMarcel Holtmann memcpy(hdev->dev_class, rp->dev_class, 3); 306a9de9248SMarcel Holtmann 307a9de9248SMarcel Holtmann BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, 308a9de9248SMarcel Holtmann hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); 309a9de9248SMarcel Holtmann } 310a9de9248SMarcel Holtmann 311a9de9248SMarcel Holtmann static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) 312a9de9248SMarcel Holtmann { 313a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 314a9de9248SMarcel Holtmann void *sent; 315a9de9248SMarcel Holtmann 316a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 317a9de9248SMarcel Holtmann 318f383f275SMarcel Holtmann if (status) 319f383f275SMarcel Holtmann return; 320f383f275SMarcel Holtmann 321a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); 322a9de9248SMarcel Holtmann if (!sent) 323a9de9248SMarcel Holtmann return; 324a9de9248SMarcel Holtmann 325a9de9248SMarcel Holtmann memcpy(hdev->dev_class, sent, 3); 326a9de9248SMarcel Holtmann } 327a9de9248SMarcel Holtmann 328a9de9248SMarcel Holtmann static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 329a9de9248SMarcel Holtmann { 330a9de9248SMarcel Holtmann struct hci_rp_read_voice_setting *rp = (void *) skb->data; 331a9de9248SMarcel Holtmann __u16 setting; 332a9de9248SMarcel Holtmann 333a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 334a9de9248SMarcel Holtmann 335a9de9248SMarcel Holtmann if (rp->status) 336a9de9248SMarcel Holtmann return; 337a9de9248SMarcel Holtmann 338a9de9248SMarcel Holtmann setting = __le16_to_cpu(rp->voice_setting); 339a9de9248SMarcel Holtmann 340a9de9248SMarcel Holtmann if (hdev->voice_setting == setting) 341a9de9248SMarcel Holtmann return; 342a9de9248SMarcel Holtmann 343a9de9248SMarcel Holtmann hdev->voice_setting = setting; 344a9de9248SMarcel Holtmann 345a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 346a9de9248SMarcel Holtmann 347a9de9248SMarcel Holtmann if (hdev->notify) { 348a9de9248SMarcel Holtmann tasklet_disable(&hdev->tx_task); 349a9de9248SMarcel Holtmann hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 350a9de9248SMarcel Holtmann tasklet_enable(&hdev->tx_task); 351a9de9248SMarcel Holtmann } 352a9de9248SMarcel Holtmann } 353a9de9248SMarcel Holtmann 354a9de9248SMarcel Holtmann static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) 355a9de9248SMarcel Holtmann { 356a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 357f383f275SMarcel Holtmann __u16 setting; 358a9de9248SMarcel Holtmann void *sent; 359a9de9248SMarcel Holtmann 360a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 361a9de9248SMarcel Holtmann 362f383f275SMarcel Holtmann if (status) 363f383f275SMarcel Holtmann return; 364f383f275SMarcel Holtmann 365a9de9248SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); 366a9de9248SMarcel Holtmann if (!sent) 367a9de9248SMarcel Holtmann return; 368a9de9248SMarcel Holtmann 369f383f275SMarcel Holtmann setting = get_unaligned_le16(sent); 3701da177e4SLinus Torvalds 371f383f275SMarcel Holtmann if (hdev->voice_setting == setting) 372f383f275SMarcel Holtmann return; 373f383f275SMarcel Holtmann 3741da177e4SLinus Torvalds hdev->voice_setting = setting; 3751da177e4SLinus Torvalds 376a9de9248SMarcel Holtmann BT_DBG("%s voice setting 0x%04x", hdev->name, setting); 3771da177e4SLinus Torvalds 3781da177e4SLinus Torvalds if (hdev->notify) { 3791da177e4SLinus Torvalds tasklet_disable(&hdev->tx_task); 3801da177e4SLinus Torvalds hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); 3811da177e4SLinus Torvalds tasklet_enable(&hdev->tx_task); 3821da177e4SLinus Torvalds } 3831da177e4SLinus Torvalds } 3841da177e4SLinus Torvalds 385a9de9248SMarcel Holtmann static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 3861da177e4SLinus Torvalds { 387a9de9248SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 3881da177e4SLinus Torvalds 389a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 3901da177e4SLinus Torvalds 391a9de9248SMarcel Holtmann hci_req_complete(hdev, status); 3921143e5a6SMarcel Holtmann } 3931143e5a6SMarcel Holtmann 394333140b5SMarcel Holtmann static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 395333140b5SMarcel Holtmann { 396333140b5SMarcel Holtmann struct hci_rp_read_ssp_mode *rp = (void *) skb->data; 397333140b5SMarcel Holtmann 398333140b5SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 399333140b5SMarcel Holtmann 400333140b5SMarcel Holtmann if (rp->status) 401333140b5SMarcel Holtmann return; 402333140b5SMarcel Holtmann 403333140b5SMarcel Holtmann hdev->ssp_mode = rp->mode; 404333140b5SMarcel Holtmann } 405333140b5SMarcel Holtmann 406333140b5SMarcel Holtmann static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) 407333140b5SMarcel Holtmann { 408333140b5SMarcel Holtmann __u8 status = *((__u8 *) skb->data); 409333140b5SMarcel Holtmann void *sent; 410333140b5SMarcel Holtmann 411333140b5SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 412333140b5SMarcel Holtmann 413333140b5SMarcel Holtmann if (status) 414333140b5SMarcel Holtmann return; 415333140b5SMarcel Holtmann 416333140b5SMarcel Holtmann sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); 417333140b5SMarcel Holtmann if (!sent) 418333140b5SMarcel Holtmann return; 419333140b5SMarcel Holtmann 420333140b5SMarcel Holtmann hdev->ssp_mode = *((__u8 *) sent); 421333140b5SMarcel Holtmann } 422333140b5SMarcel Holtmann 423a9de9248SMarcel Holtmann static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) 424a9de9248SMarcel Holtmann { 425a9de9248SMarcel Holtmann struct hci_rp_read_local_version *rp = (void *) skb->data; 4261143e5a6SMarcel Holtmann 427a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 4281143e5a6SMarcel Holtmann 429a9de9248SMarcel Holtmann if (rp->status) 430a9de9248SMarcel Holtmann return; 4311143e5a6SMarcel Holtmann 432a9de9248SMarcel Holtmann hdev->hci_ver = rp->hci_ver; 433e4e8e37cSMarcel Holtmann hdev->hci_rev = __le16_to_cpu(rp->hci_rev); 434e4e8e37cSMarcel Holtmann hdev->manufacturer = __le16_to_cpu(rp->manufacturer); 4351da177e4SLinus Torvalds 436a9de9248SMarcel Holtmann BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name, 437a9de9248SMarcel Holtmann hdev->manufacturer, 438a9de9248SMarcel Holtmann hdev->hci_ver, hdev->hci_rev); 4391da177e4SLinus Torvalds } 4401da177e4SLinus Torvalds 441a9de9248SMarcel Holtmann static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb) 442a9de9248SMarcel Holtmann { 443a9de9248SMarcel Holtmann struct hci_rp_read_local_commands *rp = (void *) skb->data; 444a9de9248SMarcel Holtmann 445a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 446a9de9248SMarcel Holtmann 447a9de9248SMarcel Holtmann if (rp->status) 448a9de9248SMarcel Holtmann return; 449a9de9248SMarcel Holtmann 450a9de9248SMarcel Holtmann memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); 451a9de9248SMarcel Holtmann } 452a9de9248SMarcel Holtmann 453a9de9248SMarcel Holtmann static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb) 454a9de9248SMarcel Holtmann { 455a9de9248SMarcel Holtmann struct hci_rp_read_local_features *rp = (void *) skb->data; 456a9de9248SMarcel Holtmann 457a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 458a9de9248SMarcel Holtmann 459a9de9248SMarcel Holtmann if (rp->status) 460a9de9248SMarcel Holtmann return; 461a9de9248SMarcel Holtmann 462a9de9248SMarcel Holtmann memcpy(hdev->features, rp->features, 8); 4631da177e4SLinus Torvalds 4641da177e4SLinus Torvalds /* Adjust default settings according to features 4651da177e4SLinus Torvalds * supported by device. */ 466a9de9248SMarcel Holtmann 4671da177e4SLinus Torvalds if (hdev->features[0] & LMP_3SLOT) 4681da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM3 | HCI_DH3); 4691da177e4SLinus Torvalds 4701da177e4SLinus Torvalds if (hdev->features[0] & LMP_5SLOT) 4711da177e4SLinus Torvalds hdev->pkt_type |= (HCI_DM5 | HCI_DH5); 4721da177e4SLinus Torvalds 4735b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV2) { 4741da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV2); 4755b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV2); 4765b7f9909SMarcel Holtmann } 4771da177e4SLinus Torvalds 4785b7f9909SMarcel Holtmann if (hdev->features[1] & LMP_HV3) { 4791da177e4SLinus Torvalds hdev->pkt_type |= (HCI_HV3); 4805b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_HV3); 4815b7f9909SMarcel Holtmann } 4825b7f9909SMarcel Holtmann 4835b7f9909SMarcel Holtmann if (hdev->features[3] & LMP_ESCO) 4845b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV3); 4855b7f9909SMarcel Holtmann 4865b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV4) 4875b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV4); 4885b7f9909SMarcel Holtmann 4895b7f9909SMarcel Holtmann if (hdev->features[4] & LMP_EV5) 4905b7f9909SMarcel Holtmann hdev->esco_type |= (ESCO_EV5); 4911da177e4SLinus Torvalds 492a9de9248SMarcel Holtmann BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, 493a9de9248SMarcel Holtmann hdev->features[0], hdev->features[1], 494a9de9248SMarcel Holtmann hdev->features[2], hdev->features[3], 495a9de9248SMarcel Holtmann hdev->features[4], hdev->features[5], 496a9de9248SMarcel Holtmann hdev->features[6], hdev->features[7]); 4971da177e4SLinus Torvalds } 4981da177e4SLinus Torvalds 499a9de9248SMarcel Holtmann static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) 500a9de9248SMarcel Holtmann { 501a9de9248SMarcel Holtmann struct hci_rp_read_buffer_size *rp = (void *) skb->data; 502a9de9248SMarcel Holtmann 503a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 504a9de9248SMarcel Holtmann 505a9de9248SMarcel Holtmann if (rp->status) 506a9de9248SMarcel Holtmann return; 507a9de9248SMarcel Holtmann 508a9de9248SMarcel Holtmann hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); 509a9de9248SMarcel Holtmann hdev->sco_mtu = rp->sco_mtu; 510a9de9248SMarcel Holtmann hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); 511a9de9248SMarcel Holtmann hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); 512da1f5198SMarcel Holtmann 513da1f5198SMarcel Holtmann if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { 514da1f5198SMarcel Holtmann hdev->sco_mtu = 64; 515da1f5198SMarcel Holtmann hdev->sco_pkts = 8; 516da1f5198SMarcel Holtmann } 517da1f5198SMarcel Holtmann 518da1f5198SMarcel Holtmann hdev->acl_cnt = hdev->acl_pkts; 519da1f5198SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 5201da177e4SLinus Torvalds 521a9de9248SMarcel Holtmann BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, 522a9de9248SMarcel Holtmann hdev->acl_mtu, hdev->acl_pkts, 523a9de9248SMarcel Holtmann hdev->sco_mtu, hdev->sco_pkts); 5241da177e4SLinus Torvalds } 5251da177e4SLinus Torvalds 526a9de9248SMarcel Holtmann static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) 527a9de9248SMarcel Holtmann { 528a9de9248SMarcel Holtmann struct hci_rp_read_bd_addr *rp = (void *) skb->data; 5291da177e4SLinus Torvalds 530a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, rp->status); 531a9de9248SMarcel Holtmann 532a9de9248SMarcel Holtmann if (!rp->status) 533a9de9248SMarcel Holtmann bacpy(&hdev->bdaddr, &rp->bdaddr); 534a9de9248SMarcel Holtmann 535a9de9248SMarcel Holtmann hci_req_complete(hdev, rp->status); 5361da177e4SLinus Torvalds } 5371da177e4SLinus Torvalds 538a9de9248SMarcel Holtmann static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 539a9de9248SMarcel Holtmann { 540a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 541a9de9248SMarcel Holtmann 542a9de9248SMarcel Holtmann if (status) { 543a9de9248SMarcel Holtmann hci_req_complete(hdev, status); 544a9de9248SMarcel Holtmann 545a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 546a9de9248SMarcel Holtmann } else 547a9de9248SMarcel Holtmann set_bit(HCI_INQUIRY, &hdev->flags); 548a9de9248SMarcel Holtmann } 549a9de9248SMarcel Holtmann 5501da177e4SLinus Torvalds static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) 5511da177e4SLinus Torvalds { 552a9de9248SMarcel Holtmann struct hci_cp_create_conn *cp; 5531da177e4SLinus Torvalds struct hci_conn *conn; 5541da177e4SLinus Torvalds 555a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 556a9de9248SMarcel Holtmann 557a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); 5581da177e4SLinus Torvalds if (!cp) 5591da177e4SLinus Torvalds return; 5601da177e4SLinus Torvalds 5611da177e4SLinus Torvalds hci_dev_lock(hdev); 5621da177e4SLinus Torvalds 5631da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); 5641da177e4SLinus Torvalds 565a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn); 5661da177e4SLinus Torvalds 5671da177e4SLinus Torvalds if (status) { 5681da177e4SLinus Torvalds if (conn && conn->state == BT_CONNECT) { 5694c67bc74SMarcel Holtmann if (status != 0x0c || conn->attempt > 2) { 5701da177e4SLinus Torvalds conn->state = BT_CLOSED; 5711da177e4SLinus Torvalds hci_proto_connect_cfm(conn, status); 5721da177e4SLinus Torvalds hci_conn_del(conn); 5734c67bc74SMarcel Holtmann } else 5744c67bc74SMarcel Holtmann conn->state = BT_CONNECT2; 5751da177e4SLinus Torvalds } 5761da177e4SLinus Torvalds } else { 5771da177e4SLinus Torvalds if (!conn) { 5781da177e4SLinus Torvalds conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); 5791da177e4SLinus Torvalds if (conn) { 5801da177e4SLinus Torvalds conn->out = 1; 5811da177e4SLinus Torvalds conn->link_mode |= HCI_LM_MASTER; 5821da177e4SLinus Torvalds } else 5831da177e4SLinus Torvalds BT_ERR("No memmory for new connection"); 5841da177e4SLinus Torvalds } 5851da177e4SLinus Torvalds } 5861da177e4SLinus Torvalds 5871da177e4SLinus Torvalds hci_dev_unlock(hdev); 5881da177e4SLinus Torvalds } 5891da177e4SLinus Torvalds 590a9de9248SMarcel Holtmann static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) 5911da177e4SLinus Torvalds { 592a9de9248SMarcel Holtmann struct hci_cp_add_sco *cp; 5931da177e4SLinus Torvalds struct hci_conn *acl, *sco; 5941da177e4SLinus Torvalds __u16 handle; 5951da177e4SLinus Torvalds 596b6a0dc82SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 597b6a0dc82SMarcel Holtmann 598a9de9248SMarcel Holtmann if (!status) 599a9de9248SMarcel Holtmann return; 600a9de9248SMarcel Holtmann 601a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); 6021da177e4SLinus Torvalds if (!cp) 603a9de9248SMarcel Holtmann return; 6041da177e4SLinus Torvalds 6051da177e4SLinus Torvalds handle = __le16_to_cpu(cp->handle); 6061da177e4SLinus Torvalds 607a9de9248SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 6081da177e4SLinus Torvalds 6091da177e4SLinus Torvalds hci_dev_lock(hdev); 6101da177e4SLinus Torvalds 6111da177e4SLinus Torvalds acl = hci_conn_hash_lookup_handle(hdev, handle); 6121da177e4SLinus Torvalds if (acl && (sco = acl->link)) { 6131da177e4SLinus Torvalds sco->state = BT_CLOSED; 6141da177e4SLinus Torvalds 6151da177e4SLinus Torvalds hci_proto_connect_cfm(sco, status); 6161da177e4SLinus Torvalds hci_conn_del(sco); 6171da177e4SLinus Torvalds } 6181da177e4SLinus Torvalds 6191da177e4SLinus Torvalds hci_dev_unlock(hdev); 6201da177e4SLinus Torvalds } 6211da177e4SLinus Torvalds 622f8558555SMarcel Holtmann static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) 623f8558555SMarcel Holtmann { 624f8558555SMarcel Holtmann struct hci_cp_auth_requested *cp; 625f8558555SMarcel Holtmann struct hci_conn *conn; 626f8558555SMarcel Holtmann 627f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 628f8558555SMarcel Holtmann 629f8558555SMarcel Holtmann if (!status) 630f8558555SMarcel Holtmann return; 631f8558555SMarcel Holtmann 632f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED); 633f8558555SMarcel Holtmann if (!cp) 634f8558555SMarcel Holtmann return; 635f8558555SMarcel Holtmann 636f8558555SMarcel Holtmann hci_dev_lock(hdev); 637f8558555SMarcel Holtmann 638f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 639f8558555SMarcel Holtmann if (conn) { 640f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 641f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 642f8558555SMarcel Holtmann hci_conn_put(conn); 643f8558555SMarcel Holtmann } 644f8558555SMarcel Holtmann } 645f8558555SMarcel Holtmann 646f8558555SMarcel Holtmann hci_dev_unlock(hdev); 647f8558555SMarcel Holtmann } 648f8558555SMarcel Holtmann 649f8558555SMarcel Holtmann static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) 650f8558555SMarcel Holtmann { 651f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt *cp; 652f8558555SMarcel Holtmann struct hci_conn *conn; 653f8558555SMarcel Holtmann 654f8558555SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 655f8558555SMarcel Holtmann 656f8558555SMarcel Holtmann if (!status) 657f8558555SMarcel Holtmann return; 658f8558555SMarcel Holtmann 659f8558555SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT); 660f8558555SMarcel Holtmann if (!cp) 661f8558555SMarcel Holtmann return; 662f8558555SMarcel Holtmann 663f8558555SMarcel Holtmann hci_dev_lock(hdev); 664f8558555SMarcel Holtmann 665f8558555SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 666f8558555SMarcel Holtmann if (conn) { 667f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 668f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, status); 669f8558555SMarcel Holtmann hci_conn_put(conn); 670f8558555SMarcel Holtmann } 671f8558555SMarcel Holtmann } 672f8558555SMarcel Holtmann 673f8558555SMarcel Holtmann hci_dev_unlock(hdev); 674f8558555SMarcel Holtmann } 675f8558555SMarcel Holtmann 676a9de9248SMarcel Holtmann static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) 6771da177e4SLinus Torvalds { 678a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 679a9de9248SMarcel Holtmann } 6801da177e4SLinus Torvalds 681769be974SMarcel Holtmann static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) 682769be974SMarcel Holtmann { 683769be974SMarcel Holtmann struct hci_cp_read_remote_features *cp; 684769be974SMarcel Holtmann struct hci_conn *conn; 685769be974SMarcel Holtmann 686769be974SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 687769be974SMarcel Holtmann 688769be974SMarcel Holtmann if (!status) 689769be974SMarcel Holtmann return; 690769be974SMarcel Holtmann 691769be974SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES); 692769be974SMarcel Holtmann if (!cp) 693769be974SMarcel Holtmann return; 694769be974SMarcel Holtmann 695769be974SMarcel Holtmann hci_dev_lock(hdev); 696769be974SMarcel Holtmann 697769be974SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 698769be974SMarcel Holtmann if (conn) { 699769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 700769be974SMarcel Holtmann hci_proto_connect_cfm(conn, status); 701769be974SMarcel Holtmann hci_conn_put(conn); 702769be974SMarcel Holtmann } 703769be974SMarcel Holtmann } 704769be974SMarcel Holtmann 705769be974SMarcel Holtmann hci_dev_unlock(hdev); 706769be974SMarcel Holtmann } 707769be974SMarcel Holtmann 708769be974SMarcel Holtmann static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) 709769be974SMarcel Holtmann { 710769be974SMarcel Holtmann struct hci_cp_read_remote_ext_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_EXT_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 735a9de9248SMarcel Holtmann static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) 736a9de9248SMarcel Holtmann { 737b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn *cp; 738b6a0dc82SMarcel Holtmann struct hci_conn *acl, *sco; 739b6a0dc82SMarcel Holtmann __u16 handle; 740b6a0dc82SMarcel Holtmann 741a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 742b6a0dc82SMarcel Holtmann 743b6a0dc82SMarcel Holtmann if (!status) 744b6a0dc82SMarcel Holtmann return; 745b6a0dc82SMarcel Holtmann 746b6a0dc82SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); 747b6a0dc82SMarcel Holtmann if (!cp) 748b6a0dc82SMarcel Holtmann return; 749b6a0dc82SMarcel Holtmann 750b6a0dc82SMarcel Holtmann handle = __le16_to_cpu(cp->handle); 751b6a0dc82SMarcel Holtmann 752b6a0dc82SMarcel Holtmann BT_DBG("%s handle %d", hdev->name, handle); 753b6a0dc82SMarcel Holtmann 754b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 755b6a0dc82SMarcel Holtmann 756b6a0dc82SMarcel Holtmann acl = hci_conn_hash_lookup_handle(hdev, handle); 757b6a0dc82SMarcel Holtmann if (acl && (sco = acl->link)) { 758b6a0dc82SMarcel Holtmann sco->state = BT_CLOSED; 759b6a0dc82SMarcel Holtmann 760b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(sco, status); 761b6a0dc82SMarcel Holtmann hci_conn_del(sco); 762b6a0dc82SMarcel Holtmann } 763b6a0dc82SMarcel Holtmann 764b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 765a9de9248SMarcel Holtmann } 766a9de9248SMarcel Holtmann 767a9de9248SMarcel Holtmann static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) 768a9de9248SMarcel Holtmann { 769a9de9248SMarcel Holtmann struct hci_cp_sniff_mode *cp; 77004837f64SMarcel Holtmann struct hci_conn *conn; 77104837f64SMarcel Holtmann 772a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 773a9de9248SMarcel Holtmann 774a9de9248SMarcel Holtmann if (!status) 775a9de9248SMarcel Holtmann return; 776a9de9248SMarcel Holtmann 777a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); 77804837f64SMarcel Holtmann if (!cp) 779a9de9248SMarcel Holtmann return; 78004837f64SMarcel Holtmann 78104837f64SMarcel Holtmann hci_dev_lock(hdev); 78204837f64SMarcel Holtmann 78304837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 784a9de9248SMarcel Holtmann if (conn) 78504837f64SMarcel Holtmann clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); 78604837f64SMarcel Holtmann 78704837f64SMarcel Holtmann hci_dev_unlock(hdev); 78804837f64SMarcel Holtmann } 78904837f64SMarcel Holtmann 790a9de9248SMarcel Holtmann static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) 791a9de9248SMarcel Holtmann { 792a9de9248SMarcel Holtmann struct hci_cp_exit_sniff_mode *cp; 79304837f64SMarcel Holtmann struct hci_conn *conn; 79404837f64SMarcel Holtmann 795a9de9248SMarcel Holtmann BT_DBG("%s status 0x%x", hdev->name, status); 796a9de9248SMarcel Holtmann 797a9de9248SMarcel Holtmann if (!status) 798a9de9248SMarcel Holtmann return; 799a9de9248SMarcel Holtmann 800a9de9248SMarcel Holtmann cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE); 80104837f64SMarcel Holtmann if (!cp) 802a9de9248SMarcel Holtmann return; 80304837f64SMarcel Holtmann 80404837f64SMarcel Holtmann hci_dev_lock(hdev); 80504837f64SMarcel Holtmann 80604837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); 807a9de9248SMarcel Holtmann if (conn) 80804837f64SMarcel Holtmann clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); 80904837f64SMarcel Holtmann 81004837f64SMarcel Holtmann hci_dev_unlock(hdev); 81104837f64SMarcel Holtmann } 81204837f64SMarcel Holtmann 8131da177e4SLinus Torvalds static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 8141da177e4SLinus Torvalds { 8151da177e4SLinus Torvalds __u8 status = *((__u8 *) skb->data); 8161da177e4SLinus Torvalds 8171da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, status); 8181da177e4SLinus Torvalds 8191da177e4SLinus Torvalds clear_bit(HCI_INQUIRY, &hdev->flags); 820a9de9248SMarcel Holtmann 8211da177e4SLinus Torvalds hci_req_complete(hdev, status); 8226bd57416SMarcel Holtmann 823a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 8241da177e4SLinus Torvalds } 8251da177e4SLinus Torvalds 8261da177e4SLinus Torvalds static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 8271da177e4SLinus Torvalds { 82845bb4bf0SMarcel Holtmann struct inquiry_data data; 829a9de9248SMarcel Holtmann struct inquiry_info *info = (void *) (skb->data + 1); 8301da177e4SLinus Torvalds int num_rsp = *((__u8 *) skb->data); 8311da177e4SLinus Torvalds 8321da177e4SLinus Torvalds BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 8331da177e4SLinus Torvalds 83445bb4bf0SMarcel Holtmann if (!num_rsp) 83545bb4bf0SMarcel Holtmann return; 83645bb4bf0SMarcel Holtmann 8371da177e4SLinus Torvalds hci_dev_lock(hdev); 83845bb4bf0SMarcel Holtmann 8391da177e4SLinus Torvalds for (; num_rsp; num_rsp--) { 8401da177e4SLinus Torvalds bacpy(&data.bdaddr, &info->bdaddr); 8411da177e4SLinus Torvalds data.pscan_rep_mode = info->pscan_rep_mode; 8421da177e4SLinus Torvalds data.pscan_period_mode = info->pscan_period_mode; 8431da177e4SLinus Torvalds data.pscan_mode = info->pscan_mode; 8441da177e4SLinus Torvalds memcpy(data.dev_class, info->dev_class, 3); 8451da177e4SLinus Torvalds data.clock_offset = info->clock_offset; 8461da177e4SLinus Torvalds data.rssi = 0x00; 84741a96212SMarcel Holtmann data.ssp_mode = 0x00; 8481da177e4SLinus Torvalds info++; 8491da177e4SLinus Torvalds hci_inquiry_cache_update(hdev, &data); 8501da177e4SLinus Torvalds } 85145bb4bf0SMarcel Holtmann 8521da177e4SLinus Torvalds hci_dev_unlock(hdev); 8531da177e4SLinus Torvalds } 8541da177e4SLinus Torvalds 855a9de9248SMarcel Holtmann static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 8561da177e4SLinus Torvalds { 857a9de9248SMarcel Holtmann struct hci_ev_conn_complete *ev = (void *) skb->data; 858a9de9248SMarcel Holtmann struct hci_conn *conn; 8591da177e4SLinus Torvalds 860a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 86145bb4bf0SMarcel Holtmann 8621da177e4SLinus Torvalds hci_dev_lock(hdev); 86345bb4bf0SMarcel Holtmann 864a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 865a9de9248SMarcel Holtmann if (!conn) 866a9de9248SMarcel Holtmann goto unlock; 86745bb4bf0SMarcel Holtmann 868a9de9248SMarcel Holtmann if (!ev->status) { 869a9de9248SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 870769be974SMarcel Holtmann 871769be974SMarcel Holtmann if (conn->type == ACL_LINK) { 872769be974SMarcel Holtmann conn->state = BT_CONFIG; 873769be974SMarcel Holtmann hci_conn_hold(conn); 874769be974SMarcel Holtmann } else 875a9de9248SMarcel Holtmann conn->state = BT_CONNECTED; 876a9de9248SMarcel Holtmann 8777d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 8787d0db0a3SMarcel Holtmann 879a9de9248SMarcel Holtmann if (test_bit(HCI_AUTH, &hdev->flags)) 880a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 881a9de9248SMarcel Holtmann 882a9de9248SMarcel Holtmann if (test_bit(HCI_ENCRYPT, &hdev->flags)) 883a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 884a9de9248SMarcel Holtmann 885a9de9248SMarcel Holtmann /* Get remote features */ 886a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 887a9de9248SMarcel Holtmann struct hci_cp_read_remote_features cp; 888a9de9248SMarcel Holtmann cp.handle = ev->handle; 889769be974SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, 890769be974SMarcel Holtmann sizeof(cp), &cp); 89145bb4bf0SMarcel Holtmann } 892a9de9248SMarcel Holtmann 893a9de9248SMarcel Holtmann /* Set packet type for incoming connection */ 894a8746417SMarcel Holtmann if (!conn->out && hdev->hci_ver < 3) { 895a9de9248SMarcel Holtmann struct hci_cp_change_conn_ptype cp; 896a9de9248SMarcel Holtmann cp.handle = ev->handle; 897a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 898a8746417SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, 899a8746417SMarcel Holtmann sizeof(cp), &cp); 900a9de9248SMarcel Holtmann } 901a9de9248SMarcel Holtmann } else 902a9de9248SMarcel Holtmann conn->state = BT_CLOSED; 90345bb4bf0SMarcel Holtmann 904a9de9248SMarcel Holtmann if (conn->type == ACL_LINK) { 905a9de9248SMarcel Holtmann struct hci_conn *sco = conn->link; 906a9de9248SMarcel Holtmann if (sco) { 907b6a0dc82SMarcel Holtmann if (!ev->status) { 908b6a0dc82SMarcel Holtmann if (lmp_esco_capable(hdev)) 909b6a0dc82SMarcel Holtmann hci_setup_sync(sco, conn->handle); 910b6a0dc82SMarcel Holtmann else 911a9de9248SMarcel Holtmann hci_add_sco(sco, conn->handle); 912b6a0dc82SMarcel Holtmann } else { 913a9de9248SMarcel Holtmann hci_proto_connect_cfm(sco, ev->status); 914a9de9248SMarcel Holtmann hci_conn_del(sco); 915a9de9248SMarcel Holtmann } 9161da177e4SLinus Torvalds } 91745bb4bf0SMarcel Holtmann } 91845bb4bf0SMarcel Holtmann 919769be974SMarcel Holtmann if (ev->status) { 920a9de9248SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 921a9de9248SMarcel Holtmann hci_conn_del(conn); 922769be974SMarcel Holtmann } 923a9de9248SMarcel Holtmann 924a9de9248SMarcel Holtmann unlock: 9251da177e4SLinus Torvalds hci_dev_unlock(hdev); 926a9de9248SMarcel Holtmann 927a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 9281da177e4SLinus Torvalds } 9291da177e4SLinus Torvalds 9301da177e4SLinus Torvalds static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 9311da177e4SLinus Torvalds { 932a9de9248SMarcel Holtmann struct hci_ev_conn_request *ev = (void *) skb->data; 9331da177e4SLinus Torvalds int mask = hdev->link_mode; 9341da177e4SLinus Torvalds 935a9de9248SMarcel Holtmann BT_DBG("%s bdaddr %s type 0x%x", hdev->name, 9361da177e4SLinus Torvalds batostr(&ev->bdaddr), ev->link_type); 9371da177e4SLinus Torvalds 9381da177e4SLinus Torvalds mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); 9391da177e4SLinus Torvalds 9401da177e4SLinus Torvalds if (mask & HCI_LM_ACCEPT) { 9411da177e4SLinus Torvalds /* Connection accepted */ 942c7bdd502SMarcel Holtmann struct inquiry_entry *ie; 9431da177e4SLinus Torvalds struct hci_conn *conn; 9441da177e4SLinus Torvalds 9451da177e4SLinus Torvalds hci_dev_lock(hdev); 946b6a0dc82SMarcel Holtmann 947c7bdd502SMarcel Holtmann if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr))) 948c7bdd502SMarcel Holtmann memcpy(ie->data.dev_class, ev->dev_class, 3); 949c7bdd502SMarcel Holtmann 9501da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 9511da177e4SLinus Torvalds if (!conn) { 9521da177e4SLinus Torvalds if (!(conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr))) { 9531da177e4SLinus Torvalds BT_ERR("No memmory for new connection"); 9541da177e4SLinus Torvalds hci_dev_unlock(hdev); 9551da177e4SLinus Torvalds return; 9561da177e4SLinus Torvalds } 9571da177e4SLinus Torvalds } 958b6a0dc82SMarcel Holtmann 9591da177e4SLinus Torvalds memcpy(conn->dev_class, ev->dev_class, 3); 9601da177e4SLinus Torvalds conn->state = BT_CONNECT; 961b6a0dc82SMarcel Holtmann 9621da177e4SLinus Torvalds hci_dev_unlock(hdev); 9631da177e4SLinus Torvalds 964b6a0dc82SMarcel Holtmann if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) { 965b6a0dc82SMarcel Holtmann struct hci_cp_accept_conn_req cp; 966b6a0dc82SMarcel Holtmann 9671da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 9681da177e4SLinus Torvalds 9691da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) 9701da177e4SLinus Torvalds cp.role = 0x00; /* Become master */ 9711da177e4SLinus Torvalds else 9721da177e4SLinus Torvalds cp.role = 0x01; /* Remain slave */ 9731da177e4SLinus Torvalds 974b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, 975b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 976b6a0dc82SMarcel Holtmann } else { 977b6a0dc82SMarcel Holtmann struct hci_cp_accept_sync_conn_req cp; 978b6a0dc82SMarcel Holtmann 979b6a0dc82SMarcel Holtmann bacpy(&cp.bdaddr, &ev->bdaddr); 980a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 981b6a0dc82SMarcel Holtmann 982b6a0dc82SMarcel Holtmann cp.tx_bandwidth = cpu_to_le32(0x00001f40); 983b6a0dc82SMarcel Holtmann cp.rx_bandwidth = cpu_to_le32(0x00001f40); 984b6a0dc82SMarcel Holtmann cp.max_latency = cpu_to_le16(0xffff); 985b6a0dc82SMarcel Holtmann cp.content_format = cpu_to_le16(hdev->voice_setting); 986b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 987b6a0dc82SMarcel Holtmann 988b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, 989b6a0dc82SMarcel Holtmann sizeof(cp), &cp); 990b6a0dc82SMarcel Holtmann } 9911da177e4SLinus Torvalds } else { 9921da177e4SLinus Torvalds /* Connection rejected */ 9931da177e4SLinus Torvalds struct hci_cp_reject_conn_req cp; 9941da177e4SLinus Torvalds 9951da177e4SLinus Torvalds bacpy(&cp.bdaddr, &ev->bdaddr); 9961da177e4SLinus Torvalds cp.reason = 0x0f; 997a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); 9981da177e4SLinus Torvalds } 9991da177e4SLinus Torvalds } 10001da177e4SLinus Torvalds 10011da177e4SLinus Torvalds static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 10021da177e4SLinus Torvalds { 1003a9de9248SMarcel Holtmann struct hci_ev_disconn_complete *ev = (void *) skb->data; 100404837f64SMarcel Holtmann struct hci_conn *conn; 10051da177e4SLinus Torvalds 10061da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 10071da177e4SLinus Torvalds 10081da177e4SLinus Torvalds if (ev->status) 10091da177e4SLinus Torvalds return; 10101da177e4SLinus Torvalds 10111da177e4SLinus Torvalds hci_dev_lock(hdev); 10121da177e4SLinus Torvalds 101304837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 10141da177e4SLinus Torvalds if (conn) { 10151da177e4SLinus Torvalds conn->state = BT_CLOSED; 10167d0db0a3SMarcel Holtmann 10177d0db0a3SMarcel Holtmann hci_conn_del_sysfs(conn); 10187d0db0a3SMarcel Holtmann 10191da177e4SLinus Torvalds hci_proto_disconn_ind(conn, ev->reason); 10201da177e4SLinus Torvalds hci_conn_del(conn); 10211da177e4SLinus Torvalds } 10221da177e4SLinus Torvalds 10231da177e4SLinus Torvalds hci_dev_unlock(hdev); 10241da177e4SLinus Torvalds } 10251da177e4SLinus Torvalds 1026a9de9248SMarcel Holtmann static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1027a9de9248SMarcel Holtmann { 1028a9de9248SMarcel Holtmann struct hci_ev_auth_complete *ev = (void *) skb->data; 1029a9de9248SMarcel Holtmann struct hci_conn *conn; 1030a9de9248SMarcel Holtmann 1031a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1032a9de9248SMarcel Holtmann 1033a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1034a9de9248SMarcel Holtmann 1035a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1036a9de9248SMarcel Holtmann if (conn) { 1037a9de9248SMarcel Holtmann if (!ev->status) 1038a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1039a9de9248SMarcel Holtmann 1040a9de9248SMarcel Holtmann clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); 1041a9de9248SMarcel Holtmann 1042f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1043f8558555SMarcel Holtmann if (!ev->status && hdev->ssp_mode > 0 && 1044f8558555SMarcel Holtmann conn->ssp_mode > 0) { 1045f8558555SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1046f8558555SMarcel Holtmann cp.handle = ev->handle; 1047f8558555SMarcel Holtmann cp.encrypt = 0x01; 1048f8558555SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, 1049f8558555SMarcel Holtmann sizeof(cp), &cp); 1050f8558555SMarcel Holtmann } else { 1051f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1052f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1053f8558555SMarcel Holtmann hci_conn_put(conn); 1054f8558555SMarcel Holtmann } 1055f8558555SMarcel Holtmann } else 1056a9de9248SMarcel Holtmann hci_auth_cfm(conn, ev->status); 1057a9de9248SMarcel Holtmann 1058a9de9248SMarcel Holtmann if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) { 1059a9de9248SMarcel Holtmann if (!ev->status) { 1060a9de9248SMarcel Holtmann struct hci_cp_set_conn_encrypt cp; 1061f8558555SMarcel Holtmann cp.handle = ev->handle; 1062f8558555SMarcel Holtmann cp.encrypt = 0x01; 1063f8558555SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, 1064f8558555SMarcel Holtmann sizeof(cp), &cp); 1065a9de9248SMarcel Holtmann } else { 1066a9de9248SMarcel Holtmann clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); 1067a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, 0x00); 1068a9de9248SMarcel Holtmann } 1069a9de9248SMarcel Holtmann } 1070a9de9248SMarcel Holtmann } 1071a9de9248SMarcel Holtmann 1072a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1073a9de9248SMarcel Holtmann } 1074a9de9248SMarcel Holtmann 1075a9de9248SMarcel Holtmann static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) 1076a9de9248SMarcel Holtmann { 1077a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1078a9de9248SMarcel Holtmann 1079a9de9248SMarcel Holtmann hci_conn_check_pending(hdev); 1080a9de9248SMarcel Holtmann } 1081a9de9248SMarcel Holtmann 1082a9de9248SMarcel Holtmann static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 1083a9de9248SMarcel Holtmann { 1084a9de9248SMarcel Holtmann struct hci_ev_encrypt_change *ev = (void *) skb->data; 1085a9de9248SMarcel Holtmann struct hci_conn *conn; 1086a9de9248SMarcel Holtmann 1087a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1088a9de9248SMarcel Holtmann 1089a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1090a9de9248SMarcel Holtmann 1091a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1092a9de9248SMarcel Holtmann if (conn) { 1093a9de9248SMarcel Holtmann if (!ev->status) { 1094ae293196SMarcel Holtmann if (ev->encrypt) { 1095ae293196SMarcel Holtmann /* Encryption implies authentication */ 1096ae293196SMarcel Holtmann conn->link_mode |= HCI_LM_AUTH; 1097a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_ENCRYPT; 1098ae293196SMarcel Holtmann } else 1099a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_ENCRYPT; 1100a9de9248SMarcel Holtmann } 1101a9de9248SMarcel Holtmann 1102a9de9248SMarcel Holtmann clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); 1103a9de9248SMarcel Holtmann 1104f8558555SMarcel Holtmann if (conn->state == BT_CONFIG) { 1105f8558555SMarcel Holtmann if (!ev->status) 1106f8558555SMarcel Holtmann conn->state = BT_CONNECTED; 1107f8558555SMarcel Holtmann 1108f8558555SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1109f8558555SMarcel Holtmann hci_conn_put(conn); 1110f8558555SMarcel Holtmann } else 1111a9de9248SMarcel Holtmann hci_encrypt_cfm(conn, ev->status, ev->encrypt); 1112a9de9248SMarcel Holtmann } 1113a9de9248SMarcel Holtmann 1114a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1115a9de9248SMarcel Holtmann } 1116a9de9248SMarcel Holtmann 1117a9de9248SMarcel Holtmann static inline void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1118a9de9248SMarcel Holtmann { 1119a9de9248SMarcel Holtmann struct hci_ev_change_link_key_complete *ev = (void *) skb->data; 1120a9de9248SMarcel Holtmann struct hci_conn *conn; 1121a9de9248SMarcel Holtmann 1122a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1123a9de9248SMarcel Holtmann 1124a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1125a9de9248SMarcel Holtmann 1126a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1127a9de9248SMarcel Holtmann if (conn) { 1128a9de9248SMarcel Holtmann if (!ev->status) 1129a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_SECURE; 1130a9de9248SMarcel Holtmann 1131a9de9248SMarcel Holtmann clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); 1132a9de9248SMarcel Holtmann 1133a9de9248SMarcel Holtmann hci_key_change_cfm(conn, ev->status); 1134a9de9248SMarcel Holtmann } 1135a9de9248SMarcel Holtmann 1136a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1137a9de9248SMarcel Holtmann } 1138a9de9248SMarcel Holtmann 1139a9de9248SMarcel Holtmann static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 1140a9de9248SMarcel Holtmann { 1141a9de9248SMarcel Holtmann struct hci_ev_remote_features *ev = (void *) skb->data; 1142a9de9248SMarcel Holtmann struct hci_conn *conn; 1143a9de9248SMarcel Holtmann 1144a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1145a9de9248SMarcel Holtmann 1146a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1147a9de9248SMarcel Holtmann 1148a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1149769be974SMarcel Holtmann if (conn) { 1150769be974SMarcel Holtmann if (!ev->status) 1151a9de9248SMarcel Holtmann memcpy(conn->features, ev->features, 8); 1152a9de9248SMarcel Holtmann 1153769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1154769be974SMarcel Holtmann if (!ev->status && lmp_ssp_capable(hdev) && 1155769be974SMarcel Holtmann lmp_ssp_capable(conn)) { 1156769be974SMarcel Holtmann struct hci_cp_read_remote_ext_features cp; 1157769be974SMarcel Holtmann cp.handle = ev->handle; 1158769be974SMarcel Holtmann cp.page = 0x01; 1159769be974SMarcel Holtmann hci_send_cmd(hdev, 1160769be974SMarcel Holtmann HCI_OP_READ_REMOTE_EXT_FEATURES, 1161769be974SMarcel Holtmann sizeof(cp), &cp); 1162769be974SMarcel Holtmann } else { 1163769be974SMarcel Holtmann conn->state = BT_CONNECTED; 1164769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1165769be974SMarcel Holtmann hci_conn_put(conn); 1166769be974SMarcel Holtmann } 1167769be974SMarcel Holtmann } 1168769be974SMarcel Holtmann } 1169769be974SMarcel Holtmann 1170a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1171a9de9248SMarcel Holtmann } 1172a9de9248SMarcel Holtmann 1173a9de9248SMarcel Holtmann static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) 1174a9de9248SMarcel Holtmann { 1175a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1176a9de9248SMarcel Holtmann } 1177a9de9248SMarcel Holtmann 1178a9de9248SMarcel Holtmann static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1179a9de9248SMarcel Holtmann { 1180a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1181a9de9248SMarcel Holtmann } 1182a9de9248SMarcel Holtmann 1183a9de9248SMarcel Holtmann static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1184a9de9248SMarcel Holtmann { 1185a9de9248SMarcel Holtmann struct hci_ev_cmd_complete *ev = (void *) skb->data; 1186a9de9248SMarcel Holtmann __u16 opcode; 1187a9de9248SMarcel Holtmann 1188a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 1189a9de9248SMarcel Holtmann 1190a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 1191a9de9248SMarcel Holtmann 1192a9de9248SMarcel Holtmann switch (opcode) { 1193a9de9248SMarcel Holtmann case HCI_OP_INQUIRY_CANCEL: 1194a9de9248SMarcel Holtmann hci_cc_inquiry_cancel(hdev, skb); 1195a9de9248SMarcel Holtmann break; 1196a9de9248SMarcel Holtmann 1197a9de9248SMarcel Holtmann case HCI_OP_EXIT_PERIODIC_INQ: 1198a9de9248SMarcel Holtmann hci_cc_exit_periodic_inq(hdev, skb); 1199a9de9248SMarcel Holtmann break; 1200a9de9248SMarcel Holtmann 1201a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ_CANCEL: 1202a9de9248SMarcel Holtmann hci_cc_remote_name_req_cancel(hdev, skb); 1203a9de9248SMarcel Holtmann break; 1204a9de9248SMarcel Holtmann 1205a9de9248SMarcel Holtmann case HCI_OP_ROLE_DISCOVERY: 1206a9de9248SMarcel Holtmann hci_cc_role_discovery(hdev, skb); 1207a9de9248SMarcel Holtmann break; 1208a9de9248SMarcel Holtmann 1209e4e8e37cSMarcel Holtmann case HCI_OP_READ_LINK_POLICY: 1210e4e8e37cSMarcel Holtmann hci_cc_read_link_policy(hdev, skb); 1211e4e8e37cSMarcel Holtmann break; 1212e4e8e37cSMarcel Holtmann 1213a9de9248SMarcel Holtmann case HCI_OP_WRITE_LINK_POLICY: 1214a9de9248SMarcel Holtmann hci_cc_write_link_policy(hdev, skb); 1215a9de9248SMarcel Holtmann break; 1216a9de9248SMarcel Holtmann 1217e4e8e37cSMarcel Holtmann case HCI_OP_READ_DEF_LINK_POLICY: 1218e4e8e37cSMarcel Holtmann hci_cc_read_def_link_policy(hdev, skb); 1219e4e8e37cSMarcel Holtmann break; 1220e4e8e37cSMarcel Holtmann 1221e4e8e37cSMarcel Holtmann case HCI_OP_WRITE_DEF_LINK_POLICY: 1222e4e8e37cSMarcel Holtmann hci_cc_write_def_link_policy(hdev, skb); 1223e4e8e37cSMarcel Holtmann break; 1224e4e8e37cSMarcel Holtmann 1225a9de9248SMarcel Holtmann case HCI_OP_RESET: 1226a9de9248SMarcel Holtmann hci_cc_reset(hdev, skb); 1227a9de9248SMarcel Holtmann break; 1228a9de9248SMarcel Holtmann 1229a9de9248SMarcel Holtmann case HCI_OP_WRITE_LOCAL_NAME: 1230a9de9248SMarcel Holtmann hci_cc_write_local_name(hdev, skb); 1231a9de9248SMarcel Holtmann break; 1232a9de9248SMarcel Holtmann 1233a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_NAME: 1234a9de9248SMarcel Holtmann hci_cc_read_local_name(hdev, skb); 1235a9de9248SMarcel Holtmann break; 1236a9de9248SMarcel Holtmann 1237a9de9248SMarcel Holtmann case HCI_OP_WRITE_AUTH_ENABLE: 1238a9de9248SMarcel Holtmann hci_cc_write_auth_enable(hdev, skb); 1239a9de9248SMarcel Holtmann break; 1240a9de9248SMarcel Holtmann 1241a9de9248SMarcel Holtmann case HCI_OP_WRITE_ENCRYPT_MODE: 1242a9de9248SMarcel Holtmann hci_cc_write_encrypt_mode(hdev, skb); 1243a9de9248SMarcel Holtmann break; 1244a9de9248SMarcel Holtmann 1245a9de9248SMarcel Holtmann case HCI_OP_WRITE_SCAN_ENABLE: 1246a9de9248SMarcel Holtmann hci_cc_write_scan_enable(hdev, skb); 1247a9de9248SMarcel Holtmann break; 1248a9de9248SMarcel Holtmann 1249a9de9248SMarcel Holtmann case HCI_OP_READ_CLASS_OF_DEV: 1250a9de9248SMarcel Holtmann hci_cc_read_class_of_dev(hdev, skb); 1251a9de9248SMarcel Holtmann break; 1252a9de9248SMarcel Holtmann 1253a9de9248SMarcel Holtmann case HCI_OP_WRITE_CLASS_OF_DEV: 1254a9de9248SMarcel Holtmann hci_cc_write_class_of_dev(hdev, skb); 1255a9de9248SMarcel Holtmann break; 1256a9de9248SMarcel Holtmann 1257a9de9248SMarcel Holtmann case HCI_OP_READ_VOICE_SETTING: 1258a9de9248SMarcel Holtmann hci_cc_read_voice_setting(hdev, skb); 1259a9de9248SMarcel Holtmann break; 1260a9de9248SMarcel Holtmann 1261a9de9248SMarcel Holtmann case HCI_OP_WRITE_VOICE_SETTING: 1262a9de9248SMarcel Holtmann hci_cc_write_voice_setting(hdev, skb); 1263a9de9248SMarcel Holtmann break; 1264a9de9248SMarcel Holtmann 1265a9de9248SMarcel Holtmann case HCI_OP_HOST_BUFFER_SIZE: 1266a9de9248SMarcel Holtmann hci_cc_host_buffer_size(hdev, skb); 1267a9de9248SMarcel Holtmann break; 1268a9de9248SMarcel Holtmann 1269333140b5SMarcel Holtmann case HCI_OP_READ_SSP_MODE: 1270333140b5SMarcel Holtmann hci_cc_read_ssp_mode(hdev, skb); 1271333140b5SMarcel Holtmann break; 1272333140b5SMarcel Holtmann 1273333140b5SMarcel Holtmann case HCI_OP_WRITE_SSP_MODE: 1274333140b5SMarcel Holtmann hci_cc_write_ssp_mode(hdev, skb); 1275333140b5SMarcel Holtmann break; 1276333140b5SMarcel Holtmann 1277a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_VERSION: 1278a9de9248SMarcel Holtmann hci_cc_read_local_version(hdev, skb); 1279a9de9248SMarcel Holtmann break; 1280a9de9248SMarcel Holtmann 1281a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_COMMANDS: 1282a9de9248SMarcel Holtmann hci_cc_read_local_commands(hdev, skb); 1283a9de9248SMarcel Holtmann break; 1284a9de9248SMarcel Holtmann 1285a9de9248SMarcel Holtmann case HCI_OP_READ_LOCAL_FEATURES: 1286a9de9248SMarcel Holtmann hci_cc_read_local_features(hdev, skb); 1287a9de9248SMarcel Holtmann break; 1288a9de9248SMarcel Holtmann 1289a9de9248SMarcel Holtmann case HCI_OP_READ_BUFFER_SIZE: 1290a9de9248SMarcel Holtmann hci_cc_read_buffer_size(hdev, skb); 1291a9de9248SMarcel Holtmann break; 1292a9de9248SMarcel Holtmann 1293a9de9248SMarcel Holtmann case HCI_OP_READ_BD_ADDR: 1294a9de9248SMarcel Holtmann hci_cc_read_bd_addr(hdev, skb); 1295a9de9248SMarcel Holtmann break; 1296a9de9248SMarcel Holtmann 1297a9de9248SMarcel Holtmann default: 1298a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 1299a9de9248SMarcel Holtmann break; 1300a9de9248SMarcel Holtmann } 1301a9de9248SMarcel Holtmann 1302a9de9248SMarcel Holtmann if (ev->ncmd) { 1303a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 1304a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 1305a9de9248SMarcel Holtmann hci_sched_cmd(hdev); 1306a9de9248SMarcel Holtmann } 1307a9de9248SMarcel Holtmann } 1308a9de9248SMarcel Holtmann 1309a9de9248SMarcel Holtmann static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) 1310a9de9248SMarcel Holtmann { 1311a9de9248SMarcel Holtmann struct hci_ev_cmd_status *ev = (void *) skb->data; 1312a9de9248SMarcel Holtmann __u16 opcode; 1313a9de9248SMarcel Holtmann 1314a9de9248SMarcel Holtmann skb_pull(skb, sizeof(*ev)); 1315a9de9248SMarcel Holtmann 1316a9de9248SMarcel Holtmann opcode = __le16_to_cpu(ev->opcode); 1317a9de9248SMarcel Holtmann 1318a9de9248SMarcel Holtmann switch (opcode) { 1319a9de9248SMarcel Holtmann case HCI_OP_INQUIRY: 1320a9de9248SMarcel Holtmann hci_cs_inquiry(hdev, ev->status); 1321a9de9248SMarcel Holtmann break; 1322a9de9248SMarcel Holtmann 1323a9de9248SMarcel Holtmann case HCI_OP_CREATE_CONN: 1324a9de9248SMarcel Holtmann hci_cs_create_conn(hdev, ev->status); 1325a9de9248SMarcel Holtmann break; 1326a9de9248SMarcel Holtmann 1327a9de9248SMarcel Holtmann case HCI_OP_ADD_SCO: 1328a9de9248SMarcel Holtmann hci_cs_add_sco(hdev, ev->status); 1329a9de9248SMarcel Holtmann break; 1330a9de9248SMarcel Holtmann 1331f8558555SMarcel Holtmann case HCI_OP_AUTH_REQUESTED: 1332f8558555SMarcel Holtmann hci_cs_auth_requested(hdev, ev->status); 1333f8558555SMarcel Holtmann break; 1334f8558555SMarcel Holtmann 1335f8558555SMarcel Holtmann case HCI_OP_SET_CONN_ENCRYPT: 1336f8558555SMarcel Holtmann hci_cs_set_conn_encrypt(hdev, ev->status); 1337f8558555SMarcel Holtmann break; 1338f8558555SMarcel Holtmann 1339a9de9248SMarcel Holtmann case HCI_OP_REMOTE_NAME_REQ: 1340a9de9248SMarcel Holtmann hci_cs_remote_name_req(hdev, ev->status); 1341a9de9248SMarcel Holtmann break; 1342a9de9248SMarcel Holtmann 1343769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_FEATURES: 1344769be974SMarcel Holtmann hci_cs_read_remote_features(hdev, ev->status); 1345769be974SMarcel Holtmann break; 1346769be974SMarcel Holtmann 1347769be974SMarcel Holtmann case HCI_OP_READ_REMOTE_EXT_FEATURES: 1348769be974SMarcel Holtmann hci_cs_read_remote_ext_features(hdev, ev->status); 1349769be974SMarcel Holtmann break; 1350769be974SMarcel Holtmann 1351a9de9248SMarcel Holtmann case HCI_OP_SETUP_SYNC_CONN: 1352a9de9248SMarcel Holtmann hci_cs_setup_sync_conn(hdev, ev->status); 1353a9de9248SMarcel Holtmann break; 1354a9de9248SMarcel Holtmann 1355a9de9248SMarcel Holtmann case HCI_OP_SNIFF_MODE: 1356a9de9248SMarcel Holtmann hci_cs_sniff_mode(hdev, ev->status); 1357a9de9248SMarcel Holtmann break; 1358a9de9248SMarcel Holtmann 1359a9de9248SMarcel Holtmann case HCI_OP_EXIT_SNIFF_MODE: 1360a9de9248SMarcel Holtmann hci_cs_exit_sniff_mode(hdev, ev->status); 1361a9de9248SMarcel Holtmann break; 1362a9de9248SMarcel Holtmann 1363a9de9248SMarcel Holtmann default: 1364a9de9248SMarcel Holtmann BT_DBG("%s opcode 0x%x", hdev->name, opcode); 1365a9de9248SMarcel Holtmann break; 1366a9de9248SMarcel Holtmann } 1367a9de9248SMarcel Holtmann 1368a9de9248SMarcel Holtmann if (ev->ncmd) { 1369a9de9248SMarcel Holtmann atomic_set(&hdev->cmd_cnt, 1); 1370a9de9248SMarcel Holtmann if (!skb_queue_empty(&hdev->cmd_q)) 1371a9de9248SMarcel Holtmann hci_sched_cmd(hdev); 1372a9de9248SMarcel Holtmann } 1373a9de9248SMarcel Holtmann } 1374a9de9248SMarcel Holtmann 1375a9de9248SMarcel Holtmann static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 1376a9de9248SMarcel Holtmann { 1377a9de9248SMarcel Holtmann struct hci_ev_role_change *ev = (void *) skb->data; 1378a9de9248SMarcel Holtmann struct hci_conn *conn; 1379a9de9248SMarcel Holtmann 1380a9de9248SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1381a9de9248SMarcel Holtmann 1382a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1383a9de9248SMarcel Holtmann 1384a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 1385a9de9248SMarcel Holtmann if (conn) { 1386a9de9248SMarcel Holtmann if (!ev->status) { 1387a9de9248SMarcel Holtmann if (ev->role) 1388a9de9248SMarcel Holtmann conn->link_mode &= ~HCI_LM_MASTER; 1389a9de9248SMarcel Holtmann else 1390a9de9248SMarcel Holtmann conn->link_mode |= HCI_LM_MASTER; 1391a9de9248SMarcel Holtmann } 1392a9de9248SMarcel Holtmann 1393a9de9248SMarcel Holtmann clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend); 1394a9de9248SMarcel Holtmann 1395a9de9248SMarcel Holtmann hci_role_switch_cfm(conn, ev->status, ev->role); 1396a9de9248SMarcel Holtmann } 1397a9de9248SMarcel Holtmann 1398a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1399a9de9248SMarcel Holtmann } 1400a9de9248SMarcel Holtmann 14011da177e4SLinus Torvalds static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) 14021da177e4SLinus Torvalds { 1403a9de9248SMarcel Holtmann struct hci_ev_num_comp_pkts *ev = (void *) skb->data; 14041ebb9252SMarcel Holtmann __le16 *ptr; 14051da177e4SLinus Torvalds int i; 14061da177e4SLinus Torvalds 14071da177e4SLinus Torvalds skb_pull(skb, sizeof(*ev)); 14081da177e4SLinus Torvalds 14091da177e4SLinus Torvalds BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); 14101da177e4SLinus Torvalds 14111da177e4SLinus Torvalds if (skb->len < ev->num_hndl * 4) { 14121da177e4SLinus Torvalds BT_DBG("%s bad parameters", hdev->name); 14131da177e4SLinus Torvalds return; 14141da177e4SLinus Torvalds } 14151da177e4SLinus Torvalds 14161da177e4SLinus Torvalds tasklet_disable(&hdev->tx_task); 14171da177e4SLinus Torvalds 14181ebb9252SMarcel Holtmann for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) { 14191da177e4SLinus Torvalds struct hci_conn *conn; 14201da177e4SLinus Torvalds __u16 handle, count; 14211da177e4SLinus Torvalds 142283985319SHarvey Harrison handle = get_unaligned_le16(ptr++); 142383985319SHarvey Harrison count = get_unaligned_le16(ptr++); 14241da177e4SLinus Torvalds 14251da177e4SLinus Torvalds conn = hci_conn_hash_lookup_handle(hdev, handle); 14261da177e4SLinus Torvalds if (conn) { 14271da177e4SLinus Torvalds conn->sent -= count; 14281da177e4SLinus Torvalds 14295b7f9909SMarcel Holtmann if (conn->type == ACL_LINK) { 14301da177e4SLinus Torvalds if ((hdev->acl_cnt += count) > hdev->acl_pkts) 14311da177e4SLinus Torvalds hdev->acl_cnt = hdev->acl_pkts; 14325b7f9909SMarcel Holtmann } else { 14335b7f9909SMarcel Holtmann if ((hdev->sco_cnt += count) > hdev->sco_pkts) 14345b7f9909SMarcel Holtmann hdev->sco_cnt = hdev->sco_pkts; 14351da177e4SLinus Torvalds } 14361da177e4SLinus Torvalds } 14371da177e4SLinus Torvalds } 1438a9de9248SMarcel Holtmann 14391da177e4SLinus Torvalds hci_sched_tx(hdev); 14401da177e4SLinus Torvalds 14411da177e4SLinus Torvalds tasklet_enable(&hdev->tx_task); 14421da177e4SLinus Torvalds } 14431da177e4SLinus Torvalds 144404837f64SMarcel Holtmann static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 14451da177e4SLinus Torvalds { 1446a9de9248SMarcel Holtmann struct hci_ev_mode_change *ev = (void *) skb->data; 144704837f64SMarcel Holtmann struct hci_conn *conn; 14481da177e4SLinus Torvalds 14491da177e4SLinus Torvalds BT_DBG("%s status %d", hdev->name, ev->status); 14501da177e4SLinus Torvalds 14511da177e4SLinus Torvalds hci_dev_lock(hdev); 14521da177e4SLinus Torvalds 145304837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 145404837f64SMarcel Holtmann if (conn) { 145504837f64SMarcel Holtmann conn->mode = ev->mode; 145604837f64SMarcel Holtmann conn->interval = __le16_to_cpu(ev->interval); 145704837f64SMarcel Holtmann 145804837f64SMarcel Holtmann if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) { 145904837f64SMarcel Holtmann if (conn->mode == HCI_CM_ACTIVE) 146004837f64SMarcel Holtmann conn->power_save = 1; 146104837f64SMarcel Holtmann else 146204837f64SMarcel Holtmann conn->power_save = 0; 146304837f64SMarcel Holtmann } 146404837f64SMarcel Holtmann } 146504837f64SMarcel Holtmann 146604837f64SMarcel Holtmann hci_dev_unlock(hdev); 146704837f64SMarcel Holtmann } 146804837f64SMarcel Holtmann 14691da177e4SLinus Torvalds static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 14701da177e4SLinus Torvalds { 1471a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 14721da177e4SLinus Torvalds } 14731da177e4SLinus Torvalds 14741da177e4SLinus Torvalds static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 14751da177e4SLinus Torvalds { 1476a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 14771da177e4SLinus Torvalds } 14781da177e4SLinus Torvalds 14791da177e4SLinus Torvalds static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) 14801da177e4SLinus Torvalds { 1481a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 14821da177e4SLinus Torvalds } 14831da177e4SLinus Torvalds 148404837f64SMarcel Holtmann static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) 148504837f64SMarcel Holtmann { 1486a9de9248SMarcel Holtmann struct hci_ev_clock_offset *ev = (void *) skb->data; 148704837f64SMarcel Holtmann struct hci_conn *conn; 148804837f64SMarcel Holtmann 148904837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 149004837f64SMarcel Holtmann 149104837f64SMarcel Holtmann hci_dev_lock(hdev); 149204837f64SMarcel Holtmann 149304837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 14941da177e4SLinus Torvalds if (conn && !ev->status) { 14951da177e4SLinus Torvalds struct inquiry_entry *ie; 14961da177e4SLinus Torvalds 14971da177e4SLinus Torvalds if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst))) { 14981da177e4SLinus Torvalds ie->data.clock_offset = ev->clock_offset; 14991da177e4SLinus Torvalds ie->timestamp = jiffies; 15001da177e4SLinus Torvalds } 15011da177e4SLinus Torvalds } 15021da177e4SLinus Torvalds 15031da177e4SLinus Torvalds hci_dev_unlock(hdev); 15041da177e4SLinus Torvalds } 15051da177e4SLinus Torvalds 1506a8746417SMarcel Holtmann static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) 1507a8746417SMarcel Holtmann { 1508a8746417SMarcel Holtmann struct hci_ev_pkt_type_change *ev = (void *) skb->data; 1509a8746417SMarcel Holtmann struct hci_conn *conn; 1510a8746417SMarcel Holtmann 1511a8746417SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1512a8746417SMarcel Holtmann 1513a8746417SMarcel Holtmann hci_dev_lock(hdev); 1514a8746417SMarcel Holtmann 1515a8746417SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 1516a8746417SMarcel Holtmann if (conn && !ev->status) 1517a8746417SMarcel Holtmann conn->pkt_type = __le16_to_cpu(ev->pkt_type); 1518a8746417SMarcel Holtmann 1519a8746417SMarcel Holtmann hci_dev_unlock(hdev); 1520a8746417SMarcel Holtmann } 1521a8746417SMarcel Holtmann 152285a1e930SMarcel Holtmann static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) 152385a1e930SMarcel Holtmann { 1524a9de9248SMarcel Holtmann struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; 152585a1e930SMarcel Holtmann struct inquiry_entry *ie; 152685a1e930SMarcel Holtmann 152785a1e930SMarcel Holtmann BT_DBG("%s", hdev->name); 152885a1e930SMarcel Holtmann 152985a1e930SMarcel Holtmann hci_dev_lock(hdev); 153085a1e930SMarcel Holtmann 153185a1e930SMarcel Holtmann if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr))) { 153285a1e930SMarcel Holtmann ie->data.pscan_rep_mode = ev->pscan_rep_mode; 153385a1e930SMarcel Holtmann ie->timestamp = jiffies; 153485a1e930SMarcel Holtmann } 153585a1e930SMarcel Holtmann 153685a1e930SMarcel Holtmann hci_dev_unlock(hdev); 153785a1e930SMarcel Holtmann } 153885a1e930SMarcel Holtmann 1539a9de9248SMarcel Holtmann static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb) 1540a9de9248SMarcel Holtmann { 1541a9de9248SMarcel Holtmann struct inquiry_data data; 1542a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 1543a9de9248SMarcel Holtmann 1544a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 1545a9de9248SMarcel Holtmann 1546a9de9248SMarcel Holtmann if (!num_rsp) 1547a9de9248SMarcel Holtmann return; 1548a9de9248SMarcel Holtmann 1549a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1550a9de9248SMarcel Holtmann 1551a9de9248SMarcel Holtmann if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { 1552a9de9248SMarcel Holtmann struct inquiry_info_with_rssi_and_pscan_mode *info = (void *) (skb->data + 1); 1553a9de9248SMarcel Holtmann 1554a9de9248SMarcel Holtmann for (; num_rsp; num_rsp--) { 1555a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 1556a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 1557a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 1558a9de9248SMarcel Holtmann data.pscan_mode = info->pscan_mode; 1559a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 1560a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 1561a9de9248SMarcel Holtmann data.rssi = info->rssi; 156241a96212SMarcel Holtmann data.ssp_mode = 0x00; 1563a9de9248SMarcel Holtmann info++; 1564a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 1565a9de9248SMarcel Holtmann } 1566a9de9248SMarcel Holtmann } else { 1567a9de9248SMarcel Holtmann struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); 1568a9de9248SMarcel Holtmann 1569a9de9248SMarcel Holtmann for (; num_rsp; num_rsp--) { 1570a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 1571a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 1572a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 1573a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 1574a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 1575a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 1576a9de9248SMarcel Holtmann data.rssi = info->rssi; 157741a96212SMarcel Holtmann data.ssp_mode = 0x00; 1578a9de9248SMarcel Holtmann info++; 1579a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 1580a9de9248SMarcel Holtmann } 1581a9de9248SMarcel Holtmann } 1582a9de9248SMarcel Holtmann 1583a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1584a9de9248SMarcel Holtmann } 1585a9de9248SMarcel Holtmann 1586a9de9248SMarcel Holtmann static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 1587a9de9248SMarcel Holtmann { 158841a96212SMarcel Holtmann struct hci_ev_remote_ext_features *ev = (void *) skb->data; 158941a96212SMarcel Holtmann struct hci_conn *conn; 159041a96212SMarcel Holtmann 1591a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 159241a96212SMarcel Holtmann 159341a96212SMarcel Holtmann hci_dev_lock(hdev); 159441a96212SMarcel Holtmann 159541a96212SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 159641a96212SMarcel Holtmann if (conn) { 1597769be974SMarcel Holtmann if (!ev->status && ev->page == 0x01) { 159841a96212SMarcel Holtmann struct inquiry_entry *ie; 159941a96212SMarcel Holtmann 160041a96212SMarcel Holtmann if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst))) 160141a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 160241a96212SMarcel Holtmann 160341a96212SMarcel Holtmann conn->ssp_mode = (ev->features[0] & 0x01); 160441a96212SMarcel Holtmann } 160541a96212SMarcel Holtmann 1606769be974SMarcel Holtmann if (conn->state == BT_CONFIG) { 1607f8558555SMarcel Holtmann if (!ev->status && hdev->ssp_mode > 0 && 1608f8558555SMarcel Holtmann conn->ssp_mode > 0) { 1609f8558555SMarcel Holtmann if (conn->out) { 1610f8558555SMarcel Holtmann struct hci_cp_auth_requested cp; 1611f8558555SMarcel Holtmann cp.handle = ev->handle; 1612f8558555SMarcel Holtmann hci_send_cmd(hdev, 1613f8558555SMarcel Holtmann HCI_OP_AUTH_REQUESTED, 1614f8558555SMarcel Holtmann sizeof(cp), &cp); 1615f8558555SMarcel Holtmann } 1616f8558555SMarcel Holtmann } else { 1617769be974SMarcel Holtmann conn->state = BT_CONNECTED; 1618769be974SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1619769be974SMarcel Holtmann hci_conn_put(conn); 1620769be974SMarcel Holtmann } 1621769be974SMarcel Holtmann } 1622f8558555SMarcel Holtmann } 1623769be974SMarcel Holtmann 162441a96212SMarcel Holtmann hci_dev_unlock(hdev); 1625a9de9248SMarcel Holtmann } 1626a9de9248SMarcel Holtmann 1627a9de9248SMarcel Holtmann static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1628a9de9248SMarcel Holtmann { 1629b6a0dc82SMarcel Holtmann struct hci_ev_sync_conn_complete *ev = (void *) skb->data; 1630b6a0dc82SMarcel Holtmann struct hci_conn *conn; 1631b6a0dc82SMarcel Holtmann 1632b6a0dc82SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 1633b6a0dc82SMarcel Holtmann 1634b6a0dc82SMarcel Holtmann hci_dev_lock(hdev); 1635b6a0dc82SMarcel Holtmann 1636b6a0dc82SMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); 16379dc0a3afSMarcel Holtmann if (!conn) { 16389dc0a3afSMarcel Holtmann if (ev->link_type == ESCO_LINK) 16399dc0a3afSMarcel Holtmann goto unlock; 16409dc0a3afSMarcel Holtmann 16419dc0a3afSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); 1642b6a0dc82SMarcel Holtmann if (!conn) 1643b6a0dc82SMarcel Holtmann goto unlock; 1644b6a0dc82SMarcel Holtmann 16459dc0a3afSMarcel Holtmann conn->type = SCO_LINK; 16469dc0a3afSMarcel Holtmann } 16479dc0a3afSMarcel Holtmann 1648b6a0dc82SMarcel Holtmann if (!ev->status) { 1649b6a0dc82SMarcel Holtmann conn->handle = __le16_to_cpu(ev->handle); 1650b6a0dc82SMarcel Holtmann conn->state = BT_CONNECTED; 16517d0db0a3SMarcel Holtmann 16527d0db0a3SMarcel Holtmann hci_conn_add_sysfs(conn); 1653b6a0dc82SMarcel Holtmann } else 1654b6a0dc82SMarcel Holtmann conn->state = BT_CLOSED; 1655b6a0dc82SMarcel Holtmann 1656b6a0dc82SMarcel Holtmann hci_proto_connect_cfm(conn, ev->status); 1657b6a0dc82SMarcel Holtmann if (ev->status) 1658b6a0dc82SMarcel Holtmann hci_conn_del(conn); 1659b6a0dc82SMarcel Holtmann 1660b6a0dc82SMarcel Holtmann unlock: 1661b6a0dc82SMarcel Holtmann hci_dev_unlock(hdev); 1662a9de9248SMarcel Holtmann } 1663a9de9248SMarcel Holtmann 1664a9de9248SMarcel Holtmann static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) 1665a9de9248SMarcel Holtmann { 1666a9de9248SMarcel Holtmann BT_DBG("%s", hdev->name); 1667a9de9248SMarcel Holtmann } 1668a9de9248SMarcel Holtmann 166904837f64SMarcel Holtmann static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) 167004837f64SMarcel Holtmann { 1671a9de9248SMarcel Holtmann struct hci_ev_sniff_subrate *ev = (void *) skb->data; 167204837f64SMarcel Holtmann struct hci_conn *conn; 167304837f64SMarcel Holtmann 167404837f64SMarcel Holtmann BT_DBG("%s status %d", hdev->name, ev->status); 167504837f64SMarcel Holtmann 167604837f64SMarcel Holtmann hci_dev_lock(hdev); 167704837f64SMarcel Holtmann 167804837f64SMarcel Holtmann conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); 167904837f64SMarcel Holtmann if (conn) { 168004837f64SMarcel Holtmann } 168104837f64SMarcel Holtmann 168204837f64SMarcel Holtmann hci_dev_unlock(hdev); 168304837f64SMarcel Holtmann } 168404837f64SMarcel Holtmann 1685a9de9248SMarcel Holtmann static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) 1686a9de9248SMarcel Holtmann { 1687a9de9248SMarcel Holtmann struct inquiry_data data; 1688a9de9248SMarcel Holtmann struct extended_inquiry_info *info = (void *) (skb->data + 1); 1689a9de9248SMarcel Holtmann int num_rsp = *((__u8 *) skb->data); 1690a9de9248SMarcel Holtmann 1691a9de9248SMarcel Holtmann BT_DBG("%s num_rsp %d", hdev->name, num_rsp); 1692a9de9248SMarcel Holtmann 1693a9de9248SMarcel Holtmann if (!num_rsp) 1694a9de9248SMarcel Holtmann return; 1695a9de9248SMarcel Holtmann 1696a9de9248SMarcel Holtmann hci_dev_lock(hdev); 1697a9de9248SMarcel Holtmann 1698a9de9248SMarcel Holtmann for (; num_rsp; num_rsp--) { 1699a9de9248SMarcel Holtmann bacpy(&data.bdaddr, &info->bdaddr); 1700a9de9248SMarcel Holtmann data.pscan_rep_mode = info->pscan_rep_mode; 1701a9de9248SMarcel Holtmann data.pscan_period_mode = info->pscan_period_mode; 1702a9de9248SMarcel Holtmann data.pscan_mode = 0x00; 1703a9de9248SMarcel Holtmann memcpy(data.dev_class, info->dev_class, 3); 1704a9de9248SMarcel Holtmann data.clock_offset = info->clock_offset; 1705a9de9248SMarcel Holtmann data.rssi = info->rssi; 170641a96212SMarcel Holtmann data.ssp_mode = 0x01; 1707a9de9248SMarcel Holtmann info++; 1708a9de9248SMarcel Holtmann hci_inquiry_cache_update(hdev, &data); 1709a9de9248SMarcel Holtmann } 1710a9de9248SMarcel Holtmann 1711a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 1712a9de9248SMarcel Holtmann } 1713a9de9248SMarcel Holtmann 17140493684eSMarcel Holtmann static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) 17150493684eSMarcel Holtmann { 17160493684eSMarcel Holtmann struct hci_ev_io_capa_request *ev = (void *) skb->data; 17170493684eSMarcel Holtmann struct hci_conn *conn; 17180493684eSMarcel Holtmann 17190493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 17200493684eSMarcel Holtmann 17210493684eSMarcel Holtmann hci_dev_lock(hdev); 17220493684eSMarcel Holtmann 17230493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 17240493684eSMarcel Holtmann if (conn) 17250493684eSMarcel Holtmann hci_conn_hold(conn); 17260493684eSMarcel Holtmann 17270493684eSMarcel Holtmann hci_dev_unlock(hdev); 17280493684eSMarcel Holtmann } 17290493684eSMarcel Holtmann 17300493684eSMarcel Holtmann static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 17310493684eSMarcel Holtmann { 17320493684eSMarcel Holtmann struct hci_ev_simple_pair_complete *ev = (void *) skb->data; 17330493684eSMarcel Holtmann struct hci_conn *conn; 17340493684eSMarcel Holtmann 17350493684eSMarcel Holtmann BT_DBG("%s", hdev->name); 17360493684eSMarcel Holtmann 17370493684eSMarcel Holtmann hci_dev_lock(hdev); 17380493684eSMarcel Holtmann 17390493684eSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); 17400493684eSMarcel Holtmann if (conn) 17410493684eSMarcel Holtmann hci_conn_put(conn); 17420493684eSMarcel Holtmann 17430493684eSMarcel Holtmann hci_dev_unlock(hdev); 17440493684eSMarcel Holtmann } 17450493684eSMarcel Holtmann 174641a96212SMarcel Holtmann static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb) 174741a96212SMarcel Holtmann { 174841a96212SMarcel Holtmann struct hci_ev_remote_host_features *ev = (void *) skb->data; 174941a96212SMarcel Holtmann struct inquiry_entry *ie; 175041a96212SMarcel Holtmann 175141a96212SMarcel Holtmann BT_DBG("%s", hdev->name); 175241a96212SMarcel Holtmann 175341a96212SMarcel Holtmann hci_dev_lock(hdev); 175441a96212SMarcel Holtmann 175541a96212SMarcel Holtmann if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr))) 175641a96212SMarcel Holtmann ie->data.ssp_mode = (ev->features[0] & 0x01); 175741a96212SMarcel Holtmann 175841a96212SMarcel Holtmann hci_dev_unlock(hdev); 175941a96212SMarcel Holtmann } 176041a96212SMarcel Holtmann 17611da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 17621da177e4SLinus Torvalds { 1763a9de9248SMarcel Holtmann struct hci_event_hdr *hdr = (void *) skb->data; 1764a9de9248SMarcel Holtmann __u8 event = hdr->evt; 17651da177e4SLinus Torvalds 17661da177e4SLinus Torvalds skb_pull(skb, HCI_EVENT_HDR_SIZE); 17671da177e4SLinus Torvalds 1768a9de9248SMarcel Holtmann switch (event) { 17691da177e4SLinus Torvalds case HCI_EV_INQUIRY_COMPLETE: 17701da177e4SLinus Torvalds hci_inquiry_complete_evt(hdev, skb); 17711da177e4SLinus Torvalds break; 17721da177e4SLinus Torvalds 17731da177e4SLinus Torvalds case HCI_EV_INQUIRY_RESULT: 17741da177e4SLinus Torvalds hci_inquiry_result_evt(hdev, skb); 17751da177e4SLinus Torvalds break; 17761da177e4SLinus Torvalds 1777a9de9248SMarcel Holtmann case HCI_EV_CONN_COMPLETE: 1778a9de9248SMarcel Holtmann hci_conn_complete_evt(hdev, skb); 177921d9e30eSMarcel Holtmann break; 178021d9e30eSMarcel Holtmann 17811da177e4SLinus Torvalds case HCI_EV_CONN_REQUEST: 17821da177e4SLinus Torvalds hci_conn_request_evt(hdev, skb); 17831da177e4SLinus Torvalds break; 17841da177e4SLinus Torvalds 17851da177e4SLinus Torvalds case HCI_EV_DISCONN_COMPLETE: 17861da177e4SLinus Torvalds hci_disconn_complete_evt(hdev, skb); 17871da177e4SLinus Torvalds break; 17881da177e4SLinus Torvalds 17891da177e4SLinus Torvalds case HCI_EV_AUTH_COMPLETE: 17901da177e4SLinus Torvalds hci_auth_complete_evt(hdev, skb); 17911da177e4SLinus Torvalds break; 17921da177e4SLinus Torvalds 1793a9de9248SMarcel Holtmann case HCI_EV_REMOTE_NAME: 1794a9de9248SMarcel Holtmann hci_remote_name_evt(hdev, skb); 1795a9de9248SMarcel Holtmann break; 1796a9de9248SMarcel Holtmann 17971da177e4SLinus Torvalds case HCI_EV_ENCRYPT_CHANGE: 17981da177e4SLinus Torvalds hci_encrypt_change_evt(hdev, skb); 17991da177e4SLinus Torvalds break; 18001da177e4SLinus Torvalds 1801a9de9248SMarcel Holtmann case HCI_EV_CHANGE_LINK_KEY_COMPLETE: 1802a9de9248SMarcel Holtmann hci_change_link_key_complete_evt(hdev, skb); 1803a9de9248SMarcel Holtmann break; 1804a9de9248SMarcel Holtmann 1805a9de9248SMarcel Holtmann case HCI_EV_REMOTE_FEATURES: 1806a9de9248SMarcel Holtmann hci_remote_features_evt(hdev, skb); 1807a9de9248SMarcel Holtmann break; 1808a9de9248SMarcel Holtmann 1809a9de9248SMarcel Holtmann case HCI_EV_REMOTE_VERSION: 1810a9de9248SMarcel Holtmann hci_remote_version_evt(hdev, skb); 1811a9de9248SMarcel Holtmann break; 1812a9de9248SMarcel Holtmann 1813a9de9248SMarcel Holtmann case HCI_EV_QOS_SETUP_COMPLETE: 1814a9de9248SMarcel Holtmann hci_qos_setup_complete_evt(hdev, skb); 1815a9de9248SMarcel Holtmann break; 1816a9de9248SMarcel Holtmann 1817a9de9248SMarcel Holtmann case HCI_EV_CMD_COMPLETE: 1818a9de9248SMarcel Holtmann hci_cmd_complete_evt(hdev, skb); 1819a9de9248SMarcel Holtmann break; 1820a9de9248SMarcel Holtmann 1821a9de9248SMarcel Holtmann case HCI_EV_CMD_STATUS: 1822a9de9248SMarcel Holtmann hci_cmd_status_evt(hdev, skb); 1823a9de9248SMarcel Holtmann break; 1824a9de9248SMarcel Holtmann 1825a9de9248SMarcel Holtmann case HCI_EV_ROLE_CHANGE: 1826a9de9248SMarcel Holtmann hci_role_change_evt(hdev, skb); 1827a9de9248SMarcel Holtmann break; 1828a9de9248SMarcel Holtmann 1829a9de9248SMarcel Holtmann case HCI_EV_NUM_COMP_PKTS: 1830a9de9248SMarcel Holtmann hci_num_comp_pkts_evt(hdev, skb); 1831a9de9248SMarcel Holtmann break; 1832a9de9248SMarcel Holtmann 1833a9de9248SMarcel Holtmann case HCI_EV_MODE_CHANGE: 1834a9de9248SMarcel Holtmann hci_mode_change_evt(hdev, skb); 18351da177e4SLinus Torvalds break; 18361da177e4SLinus Torvalds 18371da177e4SLinus Torvalds case HCI_EV_PIN_CODE_REQ: 18381da177e4SLinus Torvalds hci_pin_code_request_evt(hdev, skb); 18391da177e4SLinus Torvalds break; 18401da177e4SLinus Torvalds 18411da177e4SLinus Torvalds case HCI_EV_LINK_KEY_REQ: 18421da177e4SLinus Torvalds hci_link_key_request_evt(hdev, skb); 18431da177e4SLinus Torvalds break; 18441da177e4SLinus Torvalds 18451da177e4SLinus Torvalds case HCI_EV_LINK_KEY_NOTIFY: 18461da177e4SLinus Torvalds hci_link_key_notify_evt(hdev, skb); 18471da177e4SLinus Torvalds break; 18481da177e4SLinus Torvalds 18491da177e4SLinus Torvalds case HCI_EV_CLOCK_OFFSET: 18501da177e4SLinus Torvalds hci_clock_offset_evt(hdev, skb); 18511da177e4SLinus Torvalds break; 18521da177e4SLinus Torvalds 1853a8746417SMarcel Holtmann case HCI_EV_PKT_TYPE_CHANGE: 1854a8746417SMarcel Holtmann hci_pkt_type_change_evt(hdev, skb); 1855a8746417SMarcel Holtmann break; 1856a8746417SMarcel Holtmann 185785a1e930SMarcel Holtmann case HCI_EV_PSCAN_REP_MODE: 185885a1e930SMarcel Holtmann hci_pscan_rep_mode_evt(hdev, skb); 185985a1e930SMarcel Holtmann break; 186085a1e930SMarcel Holtmann 1861a9de9248SMarcel Holtmann case HCI_EV_INQUIRY_RESULT_WITH_RSSI: 1862a9de9248SMarcel Holtmann hci_inquiry_result_with_rssi_evt(hdev, skb); 1863a9de9248SMarcel Holtmann break; 1864a9de9248SMarcel Holtmann 1865a9de9248SMarcel Holtmann case HCI_EV_REMOTE_EXT_FEATURES: 1866a9de9248SMarcel Holtmann hci_remote_ext_features_evt(hdev, skb); 1867a9de9248SMarcel Holtmann break; 1868a9de9248SMarcel Holtmann 1869a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_COMPLETE: 1870a9de9248SMarcel Holtmann hci_sync_conn_complete_evt(hdev, skb); 1871a9de9248SMarcel Holtmann break; 1872a9de9248SMarcel Holtmann 1873a9de9248SMarcel Holtmann case HCI_EV_SYNC_CONN_CHANGED: 1874a9de9248SMarcel Holtmann hci_sync_conn_changed_evt(hdev, skb); 1875a9de9248SMarcel Holtmann break; 1876a9de9248SMarcel Holtmann 187704837f64SMarcel Holtmann case HCI_EV_SNIFF_SUBRATE: 187804837f64SMarcel Holtmann hci_sniff_subrate_evt(hdev, skb); 187904837f64SMarcel Holtmann break; 188004837f64SMarcel Holtmann 1881a9de9248SMarcel Holtmann case HCI_EV_EXTENDED_INQUIRY_RESULT: 1882a9de9248SMarcel Holtmann hci_extended_inquiry_result_evt(hdev, skb); 18831da177e4SLinus Torvalds break; 18841da177e4SLinus Torvalds 18850493684eSMarcel Holtmann case HCI_EV_IO_CAPA_REQUEST: 18860493684eSMarcel Holtmann hci_io_capa_request_evt(hdev, skb); 18870493684eSMarcel Holtmann break; 18880493684eSMarcel Holtmann 18890493684eSMarcel Holtmann case HCI_EV_SIMPLE_PAIR_COMPLETE: 18900493684eSMarcel Holtmann hci_simple_pair_complete_evt(hdev, skb); 18910493684eSMarcel Holtmann break; 18920493684eSMarcel Holtmann 189341a96212SMarcel Holtmann case HCI_EV_REMOTE_HOST_FEATURES: 189441a96212SMarcel Holtmann hci_remote_host_features_evt(hdev, skb); 189541a96212SMarcel Holtmann break; 189641a96212SMarcel Holtmann 18971da177e4SLinus Torvalds default: 1898a9de9248SMarcel Holtmann BT_DBG("%s event 0x%x", hdev->name, event); 18991da177e4SLinus Torvalds break; 19001da177e4SLinus Torvalds } 19011da177e4SLinus Torvalds 19021da177e4SLinus Torvalds kfree_skb(skb); 19031da177e4SLinus Torvalds hdev->stat.evt_rx++; 19041da177e4SLinus Torvalds } 19051da177e4SLinus Torvalds 19061da177e4SLinus Torvalds /* Generate internal stack event */ 19071da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data) 19081da177e4SLinus Torvalds { 19091da177e4SLinus Torvalds struct hci_event_hdr *hdr; 19101da177e4SLinus Torvalds struct hci_ev_stack_internal *ev; 19111da177e4SLinus Torvalds struct sk_buff *skb; 19121da177e4SLinus Torvalds 19131da177e4SLinus Torvalds skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC); 19141da177e4SLinus Torvalds if (!skb) 19151da177e4SLinus Torvalds return; 19161da177e4SLinus Torvalds 19171da177e4SLinus Torvalds hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE); 19181da177e4SLinus Torvalds hdr->evt = HCI_EV_STACK_INTERNAL; 19191da177e4SLinus Torvalds hdr->plen = sizeof(*ev) + dlen; 19201da177e4SLinus Torvalds 19211da177e4SLinus Torvalds ev = (void *) skb_put(skb, sizeof(*ev) + dlen); 19221da177e4SLinus Torvalds ev->type = type; 19231da177e4SLinus Torvalds memcpy(ev->data, data, dlen); 19241da177e4SLinus Torvalds 1925576c7d85SMarcel Holtmann bt_cb(skb)->incoming = 1; 1926a61bbcf2SPatrick McHardy __net_timestamp(skb); 1927576c7d85SMarcel Holtmann 19280d48d939SMarcel Holtmann bt_cb(skb)->pkt_type = HCI_EVENT_PKT; 19291da177e4SLinus Torvalds skb->dev = (void *) hdev; 19301da177e4SLinus Torvalds hci_send_to_sock(hdev, skb); 19311da177e4SLinus Torvalds kfree_skb(skb); 19321da177e4SLinus Torvalds } 1933