11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds BlueZ - Bluetooth protocol stack for Linux 32d0a0346SRon Shaffer Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved. 41da177e4SLinus Torvalds 51da177e4SLinus Torvalds Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> 61da177e4SLinus Torvalds 71da177e4SLinus Torvalds This program is free software; you can redistribute it and/or modify 81da177e4SLinus Torvalds it under the terms of the GNU General Public License version 2 as 91da177e4SLinus Torvalds published by the Free Software Foundation; 101da177e4SLinus Torvalds 111da177e4SLinus Torvalds THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 121da177e4SLinus Torvalds OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 131da177e4SLinus Torvalds FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 141da177e4SLinus Torvalds IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 151da177e4SLinus Torvalds CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 161da177e4SLinus Torvalds WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 171da177e4SLinus Torvalds ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 181da177e4SLinus Torvalds OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 211da177e4SLinus Torvalds COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 221da177e4SLinus Torvalds SOFTWARE IS DISCLAIMED. 231da177e4SLinus Torvalds */ 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds /* Bluetooth HCI connection 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> 4270f23020SAndrei Emeltchenko #include <linux/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 48fcd89c09SVille Tervo static void hci_le_connect(struct hci_conn *conn) 49fcd89c09SVille Tervo { 50fcd89c09SVille Tervo struct hci_dev *hdev = conn->hdev; 51fcd89c09SVille Tervo struct hci_cp_le_create_conn cp; 52fcd89c09SVille Tervo 53fcd89c09SVille Tervo conn->state = BT_CONNECT; 54fcd89c09SVille Tervo conn->out = 1; 55b92a6223SVinicius Costa Gomes conn->link_mode |= HCI_LM_MASTER; 56fcd89c09SVille Tervo 57fcd89c09SVille Tervo memset(&cp, 0, sizeof(cp)); 58fcd89c09SVille Tervo cp.scan_interval = cpu_to_le16(0x0004); 59fcd89c09SVille Tervo cp.scan_window = cpu_to_le16(0x0004); 60fcd89c09SVille Tervo bacpy(&cp.peer_addr, &conn->dst); 61fcd89c09SVille Tervo cp.conn_interval_min = cpu_to_le16(0x0008); 62fcd89c09SVille Tervo cp.conn_interval_max = cpu_to_le16(0x0100); 63fcd89c09SVille Tervo cp.supervision_timeout = cpu_to_le16(0x0064); 64fcd89c09SVille Tervo cp.min_ce_len = cpu_to_le16(0x0001); 65fcd89c09SVille Tervo cp.max_ce_len = cpu_to_le16(0x0001); 66fcd89c09SVille Tervo 67fcd89c09SVille Tervo hci_send_cmd(hdev, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp); 68fcd89c09SVille Tervo } 69fcd89c09SVille Tervo 70fcd89c09SVille Tervo static void hci_le_connect_cancel(struct hci_conn *conn) 71fcd89c09SVille Tervo { 72fcd89c09SVille Tervo hci_send_cmd(conn->hdev, HCI_OP_LE_CREATE_CONN_CANCEL, 0, NULL); 73fcd89c09SVille Tervo } 74fcd89c09SVille Tervo 754c67bc74SMarcel Holtmann void hci_acl_connect(struct hci_conn *conn) 761da177e4SLinus Torvalds { 771da177e4SLinus Torvalds struct hci_dev *hdev = conn->hdev; 781da177e4SLinus Torvalds struct inquiry_entry *ie; 791da177e4SLinus Torvalds struct hci_cp_create_conn cp; 801da177e4SLinus Torvalds 811da177e4SLinus Torvalds BT_DBG("%p", conn); 821da177e4SLinus Torvalds 831da177e4SLinus Torvalds conn->state = BT_CONNECT; 841da177e4SLinus Torvalds conn->out = 1; 85a8746417SMarcel Holtmann 861da177e4SLinus Torvalds conn->link_mode = HCI_LM_MASTER; 871da177e4SLinus Torvalds 884c67bc74SMarcel Holtmann conn->attempt++; 894c67bc74SMarcel Holtmann 90e4e8e37cSMarcel Holtmann conn->link_policy = hdev->link_policy; 91e4e8e37cSMarcel Holtmann 921da177e4SLinus Torvalds memset(&cp, 0, sizeof(cp)); 931da177e4SLinus Torvalds bacpy(&cp.bdaddr, &conn->dst); 941da177e4SLinus Torvalds cp.pscan_rep_mode = 0x02; 951da177e4SLinus Torvalds 9670f23020SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 9770f23020SAndrei Emeltchenko if (ie) { 9841a96212SMarcel Holtmann if (inquiry_entry_age(ie) <= INQUIRY_ENTRY_AGE_MAX) { 991da177e4SLinus Torvalds cp.pscan_rep_mode = ie->data.pscan_rep_mode; 1001da177e4SLinus Torvalds cp.pscan_mode = ie->data.pscan_mode; 10141a96212SMarcel Holtmann cp.clock_offset = ie->data.clock_offset | 10241a96212SMarcel Holtmann cpu_to_le16(0x8000); 10341a96212SMarcel Holtmann } 10441a96212SMarcel Holtmann 1051da177e4SLinus Torvalds memcpy(conn->dev_class, ie->data.dev_class, 3); 10641a96212SMarcel Holtmann conn->ssp_mode = ie->data.ssp_mode; 1071da177e4SLinus Torvalds } 1081da177e4SLinus Torvalds 109a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1101da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && !(hdev->link_mode & HCI_LM_MASTER)) 1111da177e4SLinus Torvalds cp.role_switch = 0x01; 1121da177e4SLinus Torvalds else 1131da177e4SLinus Torvalds cp.role_switch = 0x00; 1141da177e4SLinus Torvalds 115a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_CREATE_CONN, sizeof(cp), &cp); 1161da177e4SLinus Torvalds } 1171da177e4SLinus Torvalds 1186ac59344SMarcel Holtmann static void hci_acl_connect_cancel(struct hci_conn *conn) 1196ac59344SMarcel Holtmann { 1206ac59344SMarcel Holtmann struct hci_cp_create_conn_cancel cp; 1216ac59344SMarcel Holtmann 1226ac59344SMarcel Holtmann BT_DBG("%p", conn); 1236ac59344SMarcel Holtmann 1246ac59344SMarcel Holtmann if (conn->hdev->hci_ver < 2) 1256ac59344SMarcel Holtmann return; 1266ac59344SMarcel Holtmann 1276ac59344SMarcel Holtmann bacpy(&cp.bdaddr, &conn->dst); 128a9de9248SMarcel Holtmann hci_send_cmd(conn->hdev, HCI_OP_CREATE_CONN_CANCEL, sizeof(cp), &cp); 1296ac59344SMarcel Holtmann } 1306ac59344SMarcel Holtmann 1311da177e4SLinus Torvalds void hci_acl_disconn(struct hci_conn *conn, __u8 reason) 1321da177e4SLinus Torvalds { 1331da177e4SLinus Torvalds struct hci_cp_disconnect cp; 1341da177e4SLinus Torvalds 1351da177e4SLinus Torvalds BT_DBG("%p", conn); 1361da177e4SLinus Torvalds 1371da177e4SLinus Torvalds conn->state = BT_DISCONN; 1381da177e4SLinus Torvalds 139aca3192cSYOSHIFUJI Hideaki cp.handle = cpu_to_le16(conn->handle); 1401da177e4SLinus Torvalds cp.reason = reason; 141a9de9248SMarcel Holtmann hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp); 1421da177e4SLinus Torvalds } 1431da177e4SLinus Torvalds 1441da177e4SLinus Torvalds void hci_add_sco(struct hci_conn *conn, __u16 handle) 1451da177e4SLinus Torvalds { 1461da177e4SLinus Torvalds struct hci_dev *hdev = conn->hdev; 1471da177e4SLinus Torvalds struct hci_cp_add_sco cp; 1481da177e4SLinus Torvalds 1491da177e4SLinus Torvalds BT_DBG("%p", conn); 1501da177e4SLinus Torvalds 1511da177e4SLinus Torvalds conn->state = BT_CONNECT; 1521da177e4SLinus Torvalds conn->out = 1; 1531da177e4SLinus Torvalds 154efc7688bSMarcel Holtmann conn->attempt++; 155efc7688bSMarcel Holtmann 156aca3192cSYOSHIFUJI Hideaki cp.handle = cpu_to_le16(handle); 157a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1581da177e4SLinus Torvalds 159a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ADD_SCO, sizeof(cp), &cp); 1601da177e4SLinus Torvalds } 1611da177e4SLinus Torvalds 162b6a0dc82SMarcel Holtmann void hci_setup_sync(struct hci_conn *conn, __u16 handle) 163b6a0dc82SMarcel Holtmann { 164b6a0dc82SMarcel Holtmann struct hci_dev *hdev = conn->hdev; 165b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn cp; 166b6a0dc82SMarcel Holtmann 167b6a0dc82SMarcel Holtmann BT_DBG("%p", conn); 168b6a0dc82SMarcel Holtmann 169b6a0dc82SMarcel Holtmann conn->state = BT_CONNECT; 170b6a0dc82SMarcel Holtmann conn->out = 1; 171b6a0dc82SMarcel Holtmann 172efc7688bSMarcel Holtmann conn->attempt++; 173efc7688bSMarcel Holtmann 174b6a0dc82SMarcel Holtmann cp.handle = cpu_to_le16(handle); 175a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 176b6a0dc82SMarcel Holtmann 177b6a0dc82SMarcel Holtmann cp.tx_bandwidth = cpu_to_le32(0x00001f40); 178b6a0dc82SMarcel Holtmann cp.rx_bandwidth = cpu_to_le32(0x00001f40); 179b6a0dc82SMarcel Holtmann cp.max_latency = cpu_to_le16(0xffff); 180b6a0dc82SMarcel Holtmann cp.voice_setting = cpu_to_le16(hdev->voice_setting); 181b6a0dc82SMarcel Holtmann cp.retrans_effort = 0xff; 182b6a0dc82SMarcel Holtmann 183b6a0dc82SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp); 184b6a0dc82SMarcel Holtmann } 185b6a0dc82SMarcel Holtmann 1862ce603ebSClaudio Takahasi void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, 1872ce603ebSClaudio Takahasi u16 latency, u16 to_multiplier) 1882ce603ebSClaudio Takahasi { 1892ce603ebSClaudio Takahasi struct hci_cp_le_conn_update cp; 1902ce603ebSClaudio Takahasi struct hci_dev *hdev = conn->hdev; 1912ce603ebSClaudio Takahasi 1922ce603ebSClaudio Takahasi memset(&cp, 0, sizeof(cp)); 1932ce603ebSClaudio Takahasi 1942ce603ebSClaudio Takahasi cp.handle = cpu_to_le16(conn->handle); 1952ce603ebSClaudio Takahasi cp.conn_interval_min = cpu_to_le16(min); 1962ce603ebSClaudio Takahasi cp.conn_interval_max = cpu_to_le16(max); 1972ce603ebSClaudio Takahasi cp.conn_latency = cpu_to_le16(latency); 1982ce603ebSClaudio Takahasi cp.supervision_timeout = cpu_to_le16(to_multiplier); 1992ce603ebSClaudio Takahasi cp.min_ce_len = cpu_to_le16(0x0001); 2002ce603ebSClaudio Takahasi cp.max_ce_len = cpu_to_le16(0x0001); 2012ce603ebSClaudio Takahasi 2022ce603ebSClaudio Takahasi hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp); 2032ce603ebSClaudio Takahasi } 2042ce603ebSClaudio Takahasi EXPORT_SYMBOL(hci_le_conn_update); 2052ce603ebSClaudio Takahasi 206e73439d8SMarcel Holtmann /* Device _must_ be locked */ 207e73439d8SMarcel Holtmann void hci_sco_setup(struct hci_conn *conn, __u8 status) 208e73439d8SMarcel Holtmann { 209e73439d8SMarcel Holtmann struct hci_conn *sco = conn->link; 210e73439d8SMarcel Holtmann 211e73439d8SMarcel Holtmann BT_DBG("%p", conn); 212e73439d8SMarcel Holtmann 213e73439d8SMarcel Holtmann if (!sco) 214e73439d8SMarcel Holtmann return; 215e73439d8SMarcel Holtmann 216e73439d8SMarcel Holtmann if (!status) { 217e73439d8SMarcel Holtmann if (lmp_esco_capable(conn->hdev)) 218e73439d8SMarcel Holtmann hci_setup_sync(sco, conn->handle); 219e73439d8SMarcel Holtmann else 220e73439d8SMarcel Holtmann hci_add_sco(sco, conn->handle); 221e73439d8SMarcel Holtmann } else { 222e73439d8SMarcel Holtmann hci_proto_connect_cfm(sco, status); 223e73439d8SMarcel Holtmann hci_conn_del(sco); 224e73439d8SMarcel Holtmann } 225e73439d8SMarcel Holtmann } 226e73439d8SMarcel Holtmann 2271da177e4SLinus Torvalds static void hci_conn_timeout(unsigned long arg) 2281da177e4SLinus Torvalds { 2291da177e4SLinus Torvalds struct hci_conn *conn = (void *) arg; 2301da177e4SLinus Torvalds struct hci_dev *hdev = conn->hdev; 2312950f21aSMarcel Holtmann __u8 reason; 2321da177e4SLinus Torvalds 2331da177e4SLinus Torvalds BT_DBG("conn %p state %d", conn, conn->state); 2341da177e4SLinus Torvalds 2351da177e4SLinus Torvalds if (atomic_read(&conn->refcnt)) 2361da177e4SLinus Torvalds return; 2371da177e4SLinus Torvalds 2381da177e4SLinus Torvalds hci_dev_lock(hdev); 2396ac59344SMarcel Holtmann 2406ac59344SMarcel Holtmann switch (conn->state) { 2416ac59344SMarcel Holtmann case BT_CONNECT: 242769be974SMarcel Holtmann case BT_CONNECT2: 243fcd89c09SVille Tervo if (conn->out) { 244fcd89c09SVille Tervo if (conn->type == ACL_LINK) 2456ac59344SMarcel Holtmann hci_acl_connect_cancel(conn); 246fcd89c09SVille Tervo else if (conn->type == LE_LINK) 247fcd89c09SVille Tervo hci_le_connect_cancel(conn); 248fcd89c09SVille Tervo } 2496ac59344SMarcel Holtmann break; 250769be974SMarcel Holtmann case BT_CONFIG: 2516ac59344SMarcel Holtmann case BT_CONNECTED: 2522950f21aSMarcel Holtmann reason = hci_proto_disconn_ind(conn); 2532950f21aSMarcel Holtmann hci_acl_disconn(conn, reason); 2546ac59344SMarcel Holtmann break; 2556ac59344SMarcel Holtmann default: 2561da177e4SLinus Torvalds conn->state = BT_CLOSED; 2576ac59344SMarcel Holtmann break; 2586ac59344SMarcel Holtmann } 2596ac59344SMarcel Holtmann 2601da177e4SLinus Torvalds hci_dev_unlock(hdev); 2611da177e4SLinus Torvalds } 2621da177e4SLinus Torvalds 26304837f64SMarcel Holtmann static void hci_conn_idle(unsigned long arg) 2641da177e4SLinus Torvalds { 26504837f64SMarcel Holtmann struct hci_conn *conn = (void *) arg; 26604837f64SMarcel Holtmann 26704837f64SMarcel Holtmann BT_DBG("conn %p mode %d", conn, conn->mode); 26804837f64SMarcel Holtmann 26904837f64SMarcel Holtmann hci_conn_enter_sniff_mode(conn); 2701da177e4SLinus Torvalds } 2711da177e4SLinus Torvalds 2729f61656aSJohan Hedberg static void hci_conn_auto_accept(unsigned long arg) 2739f61656aSJohan Hedberg { 2749f61656aSJohan Hedberg struct hci_conn *conn = (void *) arg; 2759f61656aSJohan Hedberg struct hci_dev *hdev = conn->hdev; 2769f61656aSJohan Hedberg 2779f61656aSJohan Hedberg hci_dev_lock(hdev); 2789f61656aSJohan Hedberg 2799f61656aSJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, sizeof(conn->dst), 2809f61656aSJohan Hedberg &conn->dst); 2819f61656aSJohan Hedberg 2829f61656aSJohan Hedberg hci_dev_unlock(hdev); 2839f61656aSJohan Hedberg } 2849f61656aSJohan Hedberg 2851da177e4SLinus Torvalds struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) 2861da177e4SLinus Torvalds { 2871da177e4SLinus Torvalds struct hci_conn *conn; 2881da177e4SLinus Torvalds 2891da177e4SLinus Torvalds BT_DBG("%s dst %s", hdev->name, batostr(dst)); 2901da177e4SLinus Torvalds 29104837f64SMarcel Holtmann conn = kzalloc(sizeof(struct hci_conn), GFP_ATOMIC); 29204837f64SMarcel Holtmann if (!conn) 2931da177e4SLinus Torvalds return NULL; 2941da177e4SLinus Torvalds 2951da177e4SLinus Torvalds bacpy(&conn->dst, dst); 2961da177e4SLinus Torvalds conn->hdev = hdev; 29704837f64SMarcel Holtmann conn->type = type; 29804837f64SMarcel Holtmann conn->mode = HCI_CM_ACTIVE; 2991da177e4SLinus Torvalds conn->state = BT_OPEN; 30093f19c9fSAndrei Emeltchenko conn->auth_type = HCI_AT_GENERAL_BONDING; 30117fa4b9dSJohan Hedberg conn->io_capability = hdev->io_capability; 302a9583556SJohan Hedberg conn->remote_auth = 0xff; 30313d39315SWaldemar Rymarkiewicz conn->key_type = 0xff; 3041da177e4SLinus Torvalds 30504837f64SMarcel Holtmann conn->power_save = 1; 306052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 30704837f64SMarcel Holtmann 308a8746417SMarcel Holtmann switch (type) { 309a8746417SMarcel Holtmann case ACL_LINK: 310a8746417SMarcel Holtmann conn->pkt_type = hdev->pkt_type & ACL_PTYPE_MASK; 311a8746417SMarcel Holtmann break; 312a8746417SMarcel Holtmann case SCO_LINK: 313a8746417SMarcel Holtmann if (lmp_esco_capable(hdev)) 314efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 315efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 316a8746417SMarcel Holtmann else 317a8746417SMarcel Holtmann conn->pkt_type = hdev->pkt_type & SCO_PTYPE_MASK; 318a8746417SMarcel Holtmann break; 319a8746417SMarcel Holtmann case ESCO_LINK: 320efc7688bSMarcel Holtmann conn->pkt_type = hdev->esco_type & ~EDR_ESCO_MASK; 321a8746417SMarcel Holtmann break; 322a8746417SMarcel Holtmann } 323a8746417SMarcel Holtmann 3241da177e4SLinus Torvalds skb_queue_head_init(&conn->data_q); 32504837f64SMarcel Holtmann 326b24b8a24SPavel Emelyanov setup_timer(&conn->disc_timer, hci_conn_timeout, (unsigned long)conn); 327b24b8a24SPavel Emelyanov setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn); 3289f61656aSJohan Hedberg setup_timer(&conn->auto_accept_timer, hci_conn_auto_accept, 3299f61656aSJohan Hedberg (unsigned long) conn); 3301da177e4SLinus Torvalds 3311da177e4SLinus Torvalds atomic_set(&conn->refcnt, 0); 3321da177e4SLinus Torvalds 3331da177e4SLinus Torvalds hci_dev_hold(hdev); 3341da177e4SLinus Torvalds 3351da177e4SLinus Torvalds tasklet_disable(&hdev->tx_task); 3361da177e4SLinus Torvalds 3371da177e4SLinus Torvalds hci_conn_hash_add(hdev, conn); 3381da177e4SLinus Torvalds if (hdev->notify) 3391da177e4SLinus Torvalds hdev->notify(hdev, HCI_NOTIFY_CONN_ADD); 3401da177e4SLinus Torvalds 3419eba32b8SMarcel Holtmann atomic_set(&conn->devref, 0); 3429eba32b8SMarcel Holtmann 343a67e899cSMarcel Holtmann hci_conn_init_sysfs(conn); 344a67e899cSMarcel Holtmann 3451da177e4SLinus Torvalds tasklet_enable(&hdev->tx_task); 3461da177e4SLinus Torvalds 3471da177e4SLinus Torvalds return conn; 3481da177e4SLinus Torvalds } 3491da177e4SLinus Torvalds 3501da177e4SLinus Torvalds int hci_conn_del(struct hci_conn *conn) 3511da177e4SLinus Torvalds { 3521da177e4SLinus Torvalds struct hci_dev *hdev = conn->hdev; 3531da177e4SLinus Torvalds 3541da177e4SLinus Torvalds BT_DBG("%s conn %p handle %d", hdev->name, conn, conn->handle); 3551da177e4SLinus Torvalds 35604837f64SMarcel Holtmann del_timer(&conn->idle_timer); 35704837f64SMarcel Holtmann 35804837f64SMarcel Holtmann del_timer(&conn->disc_timer); 3591da177e4SLinus Torvalds 3609f61656aSJohan Hedberg del_timer(&conn->auto_accept_timer); 3619f61656aSJohan Hedberg 3625b7f9909SMarcel Holtmann if (conn->type == ACL_LINK) { 3631da177e4SLinus Torvalds struct hci_conn *sco = conn->link; 3641da177e4SLinus Torvalds if (sco) 3651da177e4SLinus Torvalds sco->link = NULL; 3661da177e4SLinus Torvalds 3671da177e4SLinus Torvalds /* Unacked frames */ 3681da177e4SLinus Torvalds hdev->acl_cnt += conn->sent; 3696ed58ec5SVille Tervo } else if (conn->type == LE_LINK) { 3706ed58ec5SVille Tervo if (hdev->le_pkts) 3716ed58ec5SVille Tervo hdev->le_cnt += conn->sent; 3726ed58ec5SVille Tervo else 3736ed58ec5SVille Tervo hdev->acl_cnt += conn->sent; 3745b7f9909SMarcel Holtmann } else { 3755b7f9909SMarcel Holtmann struct hci_conn *acl = conn->link; 3765b7f9909SMarcel Holtmann if (acl) { 3775b7f9909SMarcel Holtmann acl->link = NULL; 3785b7f9909SMarcel Holtmann hci_conn_put(acl); 3795b7f9909SMarcel Holtmann } 3801da177e4SLinus Torvalds } 3811da177e4SLinus Torvalds 3821da177e4SLinus Torvalds tasklet_disable(&hdev->tx_task); 3837d0db0a3SMarcel Holtmann 3841da177e4SLinus Torvalds hci_conn_hash_del(hdev, conn); 3851da177e4SLinus Torvalds if (hdev->notify) 3861da177e4SLinus Torvalds hdev->notify(hdev, HCI_NOTIFY_CONN_DEL); 3877d0db0a3SMarcel Holtmann 3881da177e4SLinus Torvalds tasklet_enable(&hdev->tx_task); 3897d0db0a3SMarcel Holtmann 3901da177e4SLinus Torvalds skb_queue_purge(&conn->data_q); 3911da177e4SLinus Torvalds 3929eba32b8SMarcel Holtmann hci_conn_put_device(conn); 3932ae9a6beSDave Young 394384943ecSMarcel Holtmann hci_dev_put(hdev); 395384943ecSMarcel Holtmann 3961da177e4SLinus Torvalds return 0; 3971da177e4SLinus Torvalds } 3981da177e4SLinus Torvalds 3991da177e4SLinus Torvalds struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src) 4001da177e4SLinus Torvalds { 4011da177e4SLinus Torvalds int use_src = bacmp(src, BDADDR_ANY); 4021da177e4SLinus Torvalds struct hci_dev *hdev = NULL; 4031da177e4SLinus Torvalds struct list_head *p; 4041da177e4SLinus Torvalds 4051da177e4SLinus Torvalds BT_DBG("%s -> %s", batostr(src), batostr(dst)); 4061da177e4SLinus Torvalds 4071da177e4SLinus Torvalds read_lock_bh(&hci_dev_list_lock); 4081da177e4SLinus Torvalds 4091da177e4SLinus Torvalds list_for_each(p, &hci_dev_list) { 4101da177e4SLinus Torvalds struct hci_dev *d = list_entry(p, struct hci_dev, list); 4111da177e4SLinus Torvalds 4121da177e4SLinus Torvalds if (!test_bit(HCI_UP, &d->flags) || test_bit(HCI_RAW, &d->flags)) 4131da177e4SLinus Torvalds continue; 4141da177e4SLinus Torvalds 4151da177e4SLinus Torvalds /* Simple routing: 4161da177e4SLinus Torvalds * No source address - find interface with bdaddr != dst 4171da177e4SLinus Torvalds * Source address - find interface with bdaddr == src 4181da177e4SLinus Torvalds */ 4191da177e4SLinus Torvalds 4201da177e4SLinus Torvalds if (use_src) { 4211da177e4SLinus Torvalds if (!bacmp(&d->bdaddr, src)) { 4221da177e4SLinus Torvalds hdev = d; break; 4231da177e4SLinus Torvalds } 4241da177e4SLinus Torvalds } else { 4251da177e4SLinus Torvalds if (bacmp(&d->bdaddr, dst)) { 4261da177e4SLinus Torvalds hdev = d; break; 4271da177e4SLinus Torvalds } 4281da177e4SLinus Torvalds } 4291da177e4SLinus Torvalds } 4301da177e4SLinus Torvalds 4311da177e4SLinus Torvalds if (hdev) 4321da177e4SLinus Torvalds hdev = hci_dev_hold(hdev); 4331da177e4SLinus Torvalds 4341da177e4SLinus Torvalds read_unlock_bh(&hci_dev_list_lock); 4351da177e4SLinus Torvalds return hdev; 4361da177e4SLinus Torvalds } 4371da177e4SLinus Torvalds EXPORT_SYMBOL(hci_get_route); 4381da177e4SLinus Torvalds 439fcd89c09SVille Tervo /* Create SCO, ACL or LE connection. 4401da177e4SLinus Torvalds * Device _must_ be locked */ 4418c1b2355SMarcel Holtmann struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 sec_level, __u8 auth_type) 4421da177e4SLinus Torvalds { 4431da177e4SLinus Torvalds struct hci_conn *acl; 4445b7f9909SMarcel Holtmann struct hci_conn *sco; 445fcd89c09SVille Tervo struct hci_conn *le; 4461da177e4SLinus Torvalds 4471da177e4SLinus Torvalds BT_DBG("%s dst %s", hdev->name, batostr(dst)); 4481da177e4SLinus Torvalds 449fcd89c09SVille Tervo if (type == LE_LINK) { 450fcd89c09SVille Tervo le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst); 45115c4794fSAnderson Briglia if (le) 45230e76272SVille Tervo return ERR_PTR(-EBUSY); 453fcd89c09SVille Tervo le = hci_conn_add(hdev, LE_LINK, dst); 454fcd89c09SVille Tervo if (!le) 45530e76272SVille Tervo return ERR_PTR(-ENOMEM); 456*893d6751SAndre Guedes 457fcd89c09SVille Tervo hci_le_connect(le); 458fcd89c09SVille Tervo 459fcd89c09SVille Tervo hci_conn_hold(le); 460fcd89c09SVille Tervo 461fcd89c09SVille Tervo return le; 462fcd89c09SVille Tervo } 463fcd89c09SVille Tervo 46470f23020SAndrei Emeltchenko acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst); 46570f23020SAndrei Emeltchenko if (!acl) { 46670f23020SAndrei Emeltchenko acl = hci_conn_add(hdev, ACL_LINK, dst); 46770f23020SAndrei Emeltchenko if (!acl) 4681da177e4SLinus Torvalds return NULL; 4691da177e4SLinus Torvalds } 4701da177e4SLinus Torvalds 4711da177e4SLinus Torvalds hci_conn_hold(acl); 4721da177e4SLinus Torvalds 47309ab6f4cSMarcel Holtmann if (acl->state == BT_OPEN || acl->state == BT_CLOSED) { 474765c2a96SJohan Hedberg acl->sec_level = BT_SECURITY_LOW; 475765c2a96SJohan Hedberg acl->pending_sec_level = sec_level; 47609ab6f4cSMarcel Holtmann acl->auth_type = auth_type; 4771da177e4SLinus Torvalds hci_acl_connect(acl); 47809ab6f4cSMarcel Holtmann } 4791da177e4SLinus Torvalds 4805b7f9909SMarcel Holtmann if (type == ACL_LINK) 4815b7f9909SMarcel Holtmann return acl; 4821da177e4SLinus Torvalds 48370f23020SAndrei Emeltchenko sco = hci_conn_hash_lookup_ba(hdev, type, dst); 48470f23020SAndrei Emeltchenko if (!sco) { 48570f23020SAndrei Emeltchenko sco = hci_conn_add(hdev, type, dst); 48670f23020SAndrei Emeltchenko if (!sco) { 4871da177e4SLinus Torvalds hci_conn_put(acl); 4881da177e4SLinus Torvalds return NULL; 4891da177e4SLinus Torvalds } 4901da177e4SLinus Torvalds } 4915b7f9909SMarcel Holtmann 4921da177e4SLinus Torvalds acl->link = sco; 4931da177e4SLinus Torvalds sco->link = acl; 4941da177e4SLinus Torvalds 4951da177e4SLinus Torvalds hci_conn_hold(sco); 4961da177e4SLinus Torvalds 4971da177e4SLinus Torvalds if (acl->state == BT_CONNECTED && 498b6a0dc82SMarcel Holtmann (sco->state == BT_OPEN || sco->state == BT_CLOSED)) { 499c390216bSNick Pelly acl->power_save = 1; 500c390216bSNick Pelly hci_conn_enter_active_mode(acl); 501c390216bSNick Pelly 502e73439d8SMarcel Holtmann if (test_bit(HCI_CONN_MODE_CHANGE_PEND, &acl->pend)) { 503e73439d8SMarcel Holtmann /* defer SCO setup until mode change completed */ 504e73439d8SMarcel Holtmann set_bit(HCI_CONN_SCO_SETUP_PEND, &acl->pend); 505e73439d8SMarcel Holtmann return sco; 506e73439d8SMarcel Holtmann } 507e73439d8SMarcel Holtmann 508e73439d8SMarcel Holtmann hci_sco_setup(acl, 0x00); 509b6a0dc82SMarcel Holtmann } 5101da177e4SLinus Torvalds 5111da177e4SLinus Torvalds return sco; 5121da177e4SLinus Torvalds } 5131da177e4SLinus Torvalds EXPORT_SYMBOL(hci_connect); 5141da177e4SLinus Torvalds 515e7c29cb1SMarcel Holtmann /* Check link security requirement */ 516e7c29cb1SMarcel Holtmann int hci_conn_check_link_mode(struct hci_conn *conn) 517e7c29cb1SMarcel Holtmann { 518e7c29cb1SMarcel Holtmann BT_DBG("conn %p", conn); 519e7c29cb1SMarcel Holtmann 520e7c29cb1SMarcel Holtmann if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0 && 521e7c29cb1SMarcel Holtmann !(conn->link_mode & HCI_LM_ENCRYPT)) 522e7c29cb1SMarcel Holtmann return 0; 523e7c29cb1SMarcel Holtmann 524e7c29cb1SMarcel Holtmann return 1; 525e7c29cb1SMarcel Holtmann } 526e7c29cb1SMarcel Holtmann EXPORT_SYMBOL(hci_conn_check_link_mode); 527e7c29cb1SMarcel Holtmann 5281da177e4SLinus Torvalds /* Authenticate remote device */ 5290684e5f9SMarcel Holtmann static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) 5301da177e4SLinus Torvalds { 5311da177e4SLinus Torvalds BT_DBG("conn %p", conn); 5321da177e4SLinus Torvalds 533765c2a96SJohan Hedberg if (conn->pending_sec_level > sec_level) 534765c2a96SJohan Hedberg sec_level = conn->pending_sec_level; 535765c2a96SJohan Hedberg 53696a31833SMarcel Holtmann if (sec_level > conn->sec_level) 537765c2a96SJohan Hedberg conn->pending_sec_level = sec_level; 53896a31833SMarcel Holtmann else if (conn->link_mode & HCI_LM_AUTH) 5391da177e4SLinus Torvalds return 1; 5401da177e4SLinus Torvalds 54165cf686eSJohan Hedberg /* Make sure we preserve an existing MITM requirement*/ 54265cf686eSJohan Hedberg auth_type |= (conn->auth_type & 0x01); 54365cf686eSJohan Hedberg 54496a31833SMarcel Holtmann conn->auth_type = auth_type; 54596a31833SMarcel Holtmann 5461da177e4SLinus Torvalds if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { 5471da177e4SLinus Torvalds struct hci_cp_auth_requested cp; 548aca3192cSYOSHIFUJI Hideaki cp.handle = cpu_to_le16(conn->handle); 54940be492fSMarcel Holtmann hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED, 55040be492fSMarcel Holtmann sizeof(cp), &cp); 55119f8def0SWaldemar Rymarkiewicz if (conn->key_type != 0xff) 55219f8def0SWaldemar Rymarkiewicz set_bit(HCI_CONN_REAUTH_PEND, &conn->pend); 5531da177e4SLinus Torvalds } 5548c1b2355SMarcel Holtmann 5551da177e4SLinus Torvalds return 0; 5561da177e4SLinus Torvalds } 5571da177e4SLinus Torvalds 55813d39315SWaldemar Rymarkiewicz /* Encrypt the the link */ 55913d39315SWaldemar Rymarkiewicz static void hci_conn_encrypt(struct hci_conn *conn) 56013d39315SWaldemar Rymarkiewicz { 56113d39315SWaldemar Rymarkiewicz BT_DBG("conn %p", conn); 56213d39315SWaldemar Rymarkiewicz 56313d39315SWaldemar Rymarkiewicz if (!test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) { 56413d39315SWaldemar Rymarkiewicz struct hci_cp_set_conn_encrypt cp; 56513d39315SWaldemar Rymarkiewicz cp.handle = cpu_to_le16(conn->handle); 56613d39315SWaldemar Rymarkiewicz cp.encrypt = 0x01; 56713d39315SWaldemar Rymarkiewicz hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 56813d39315SWaldemar Rymarkiewicz &cp); 56913d39315SWaldemar Rymarkiewicz } 57013d39315SWaldemar Rymarkiewicz } 57113d39315SWaldemar Rymarkiewicz 5728c1b2355SMarcel Holtmann /* Enable security */ 5730684e5f9SMarcel Holtmann int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) 5741da177e4SLinus Torvalds { 5751da177e4SLinus Torvalds BT_DBG("conn %p", conn); 5761da177e4SLinus Torvalds 57713d39315SWaldemar Rymarkiewicz /* For sdp we don't need the link key. */ 5788c1b2355SMarcel Holtmann if (sec_level == BT_SECURITY_SDP) 5798c1b2355SMarcel Holtmann return 1; 5808c1b2355SMarcel Holtmann 58113d39315SWaldemar Rymarkiewicz /* For non 2.1 devices and low security level we don't need the link 58213d39315SWaldemar Rymarkiewicz key. */ 5833fdca1e1SMarcel Holtmann if (sec_level == BT_SECURITY_LOW && 5843fdca1e1SMarcel Holtmann (!conn->ssp_mode || !conn->hdev->ssp_mode)) 5858c1b2355SMarcel Holtmann return 1; 5868c1b2355SMarcel Holtmann 58713d39315SWaldemar Rymarkiewicz /* For other security levels we need the link key. */ 58813d39315SWaldemar Rymarkiewicz if (!(conn->link_mode & HCI_LM_AUTH)) 58913d39315SWaldemar Rymarkiewicz goto auth; 5901da177e4SLinus Torvalds 59113d39315SWaldemar Rymarkiewicz /* An authenticated combination key has sufficient security for any 59213d39315SWaldemar Rymarkiewicz security level. */ 59313d39315SWaldemar Rymarkiewicz if (conn->key_type == HCI_LK_AUTH_COMBINATION) 59413d39315SWaldemar Rymarkiewicz goto encrypt; 59513d39315SWaldemar Rymarkiewicz 59613d39315SWaldemar Rymarkiewicz /* An unauthenticated combination key has sufficient security for 59713d39315SWaldemar Rymarkiewicz security level 1 and 2. */ 59813d39315SWaldemar Rymarkiewicz if (conn->key_type == HCI_LK_UNAUTH_COMBINATION && 59913d39315SWaldemar Rymarkiewicz (sec_level == BT_SECURITY_MEDIUM || 60013d39315SWaldemar Rymarkiewicz sec_level == BT_SECURITY_LOW)) 60113d39315SWaldemar Rymarkiewicz goto encrypt; 60213d39315SWaldemar Rymarkiewicz 60313d39315SWaldemar Rymarkiewicz /* A combination key has always sufficient security for the security 60413d39315SWaldemar Rymarkiewicz levels 1 or 2. High security level requires the combination key 60513d39315SWaldemar Rymarkiewicz is generated using maximum PIN code length (16). 60613d39315SWaldemar Rymarkiewicz For pre 2.1 units. */ 60713d39315SWaldemar Rymarkiewicz if (conn->key_type == HCI_LK_COMBINATION && 60813d39315SWaldemar Rymarkiewicz (sec_level != BT_SECURITY_HIGH || 60913d39315SWaldemar Rymarkiewicz conn->pin_length == 16)) 61013d39315SWaldemar Rymarkiewicz goto encrypt; 61113d39315SWaldemar Rymarkiewicz 61213d39315SWaldemar Rymarkiewicz auth: 6131da177e4SLinus Torvalds if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) 6141da177e4SLinus Torvalds return 0; 6151da177e4SLinus Torvalds 61613d39315SWaldemar Rymarkiewicz hci_conn_auth(conn, sec_level, auth_type); 61713d39315SWaldemar Rymarkiewicz return 0; 6188c1b2355SMarcel Holtmann 61913d39315SWaldemar Rymarkiewicz encrypt: 62013d39315SWaldemar Rymarkiewicz if (conn->link_mode & HCI_LM_ENCRYPT) 62113d39315SWaldemar Rymarkiewicz return 1; 62213d39315SWaldemar Rymarkiewicz 62313d39315SWaldemar Rymarkiewicz hci_conn_encrypt(conn); 6241da177e4SLinus Torvalds return 0; 6251da177e4SLinus Torvalds } 6268c1b2355SMarcel Holtmann EXPORT_SYMBOL(hci_conn_security); 6271da177e4SLinus Torvalds 628b3b1b061SWaldemar Rymarkiewicz /* Check secure link requirement */ 629b3b1b061SWaldemar Rymarkiewicz int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level) 630b3b1b061SWaldemar Rymarkiewicz { 631b3b1b061SWaldemar Rymarkiewicz BT_DBG("conn %p", conn); 632b3b1b061SWaldemar Rymarkiewicz 633b3b1b061SWaldemar Rymarkiewicz if (sec_level != BT_SECURITY_HIGH) 634b3b1b061SWaldemar Rymarkiewicz return 1; /* Accept if non-secure is required */ 635b3b1b061SWaldemar Rymarkiewicz 636b3b1b061SWaldemar Rymarkiewicz if (conn->key_type == HCI_LK_AUTH_COMBINATION || 637b3b1b061SWaldemar Rymarkiewicz (conn->key_type == HCI_LK_COMBINATION && 638b3b1b061SWaldemar Rymarkiewicz conn->pin_length == 16)) 639b3b1b061SWaldemar Rymarkiewicz return 1; 640b3b1b061SWaldemar Rymarkiewicz 641b3b1b061SWaldemar Rymarkiewicz return 0; /* Reject not secure link */ 642b3b1b061SWaldemar Rymarkiewicz } 643b3b1b061SWaldemar Rymarkiewicz EXPORT_SYMBOL(hci_conn_check_secure); 644b3b1b061SWaldemar Rymarkiewicz 6451da177e4SLinus Torvalds /* Change link key */ 6461da177e4SLinus Torvalds int hci_conn_change_link_key(struct hci_conn *conn) 6471da177e4SLinus Torvalds { 6481da177e4SLinus Torvalds BT_DBG("conn %p", conn); 6491da177e4SLinus Torvalds 6501da177e4SLinus Torvalds if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { 6511da177e4SLinus Torvalds struct hci_cp_change_conn_link_key cp; 652aca3192cSYOSHIFUJI Hideaki cp.handle = cpu_to_le16(conn->handle); 65340be492fSMarcel Holtmann hci_send_cmd(conn->hdev, HCI_OP_CHANGE_CONN_LINK_KEY, 65440be492fSMarcel Holtmann sizeof(cp), &cp); 6551da177e4SLinus Torvalds } 6568c1b2355SMarcel Holtmann 6571da177e4SLinus Torvalds return 0; 6581da177e4SLinus Torvalds } 6591da177e4SLinus Torvalds EXPORT_SYMBOL(hci_conn_change_link_key); 6601da177e4SLinus Torvalds 6611da177e4SLinus Torvalds /* Switch role */ 6628c1b2355SMarcel Holtmann int hci_conn_switch_role(struct hci_conn *conn, __u8 role) 6631da177e4SLinus Torvalds { 6641da177e4SLinus Torvalds BT_DBG("conn %p", conn); 6651da177e4SLinus Torvalds 6661da177e4SLinus Torvalds if (!role && conn->link_mode & HCI_LM_MASTER) 6671da177e4SLinus Torvalds return 1; 6681da177e4SLinus Torvalds 6691da177e4SLinus Torvalds if (!test_and_set_bit(HCI_CONN_RSWITCH_PEND, &conn->pend)) { 6701da177e4SLinus Torvalds struct hci_cp_switch_role cp; 6711da177e4SLinus Torvalds bacpy(&cp.bdaddr, &conn->dst); 6721da177e4SLinus Torvalds cp.role = role; 673a9de9248SMarcel Holtmann hci_send_cmd(conn->hdev, HCI_OP_SWITCH_ROLE, sizeof(cp), &cp); 6741da177e4SLinus Torvalds } 6758c1b2355SMarcel Holtmann 6761da177e4SLinus Torvalds return 0; 6771da177e4SLinus Torvalds } 6781da177e4SLinus Torvalds EXPORT_SYMBOL(hci_conn_switch_role); 6791da177e4SLinus Torvalds 68004837f64SMarcel Holtmann /* Enter active mode */ 68104837f64SMarcel Holtmann void hci_conn_enter_active_mode(struct hci_conn *conn) 68204837f64SMarcel Holtmann { 68304837f64SMarcel Holtmann struct hci_dev *hdev = conn->hdev; 68404837f64SMarcel Holtmann 68504837f64SMarcel Holtmann BT_DBG("conn %p mode %d", conn, conn->mode); 68604837f64SMarcel Holtmann 68704837f64SMarcel Holtmann if (test_bit(HCI_RAW, &hdev->flags)) 68804837f64SMarcel Holtmann return; 68904837f64SMarcel Holtmann 69004837f64SMarcel Holtmann if (conn->mode != HCI_CM_SNIFF || !conn->power_save) 69104837f64SMarcel Holtmann goto timer; 69204837f64SMarcel Holtmann 69304837f64SMarcel Holtmann if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) { 69404837f64SMarcel Holtmann struct hci_cp_exit_sniff_mode cp; 695aca3192cSYOSHIFUJI Hideaki cp.handle = cpu_to_le16(conn->handle); 696a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_EXIT_SNIFF_MODE, sizeof(cp), &cp); 69704837f64SMarcel Holtmann } 69804837f64SMarcel Holtmann 69904837f64SMarcel Holtmann timer: 70004837f64SMarcel Holtmann if (hdev->idle_timeout > 0) 70104837f64SMarcel Holtmann mod_timer(&conn->idle_timer, 70204837f64SMarcel Holtmann jiffies + msecs_to_jiffies(hdev->idle_timeout)); 70304837f64SMarcel Holtmann } 70404837f64SMarcel Holtmann 70504837f64SMarcel Holtmann /* Enter sniff mode */ 70604837f64SMarcel Holtmann void hci_conn_enter_sniff_mode(struct hci_conn *conn) 70704837f64SMarcel Holtmann { 70804837f64SMarcel Holtmann struct hci_dev *hdev = conn->hdev; 70904837f64SMarcel Holtmann 71004837f64SMarcel Holtmann BT_DBG("conn %p mode %d", conn, conn->mode); 71104837f64SMarcel Holtmann 71204837f64SMarcel Holtmann if (test_bit(HCI_RAW, &hdev->flags)) 71304837f64SMarcel Holtmann return; 71404837f64SMarcel Holtmann 71504837f64SMarcel Holtmann if (!lmp_sniff_capable(hdev) || !lmp_sniff_capable(conn)) 71604837f64SMarcel Holtmann return; 71704837f64SMarcel Holtmann 71804837f64SMarcel Holtmann if (conn->mode != HCI_CM_ACTIVE || !(conn->link_policy & HCI_LP_SNIFF)) 71904837f64SMarcel Holtmann return; 72004837f64SMarcel Holtmann 72104837f64SMarcel Holtmann if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) { 72204837f64SMarcel Holtmann struct hci_cp_sniff_subrate cp; 723aca3192cSYOSHIFUJI Hideaki cp.handle = cpu_to_le16(conn->handle); 724aca3192cSYOSHIFUJI Hideaki cp.max_latency = cpu_to_le16(0); 725aca3192cSYOSHIFUJI Hideaki cp.min_remote_timeout = cpu_to_le16(0); 726aca3192cSYOSHIFUJI Hideaki cp.min_local_timeout = cpu_to_le16(0); 727a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp); 72804837f64SMarcel Holtmann } 72904837f64SMarcel Holtmann 73004837f64SMarcel Holtmann if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) { 73104837f64SMarcel Holtmann struct hci_cp_sniff_mode cp; 732aca3192cSYOSHIFUJI Hideaki cp.handle = cpu_to_le16(conn->handle); 733aca3192cSYOSHIFUJI Hideaki cp.max_interval = cpu_to_le16(hdev->sniff_max_interval); 734aca3192cSYOSHIFUJI Hideaki cp.min_interval = cpu_to_le16(hdev->sniff_min_interval); 735aca3192cSYOSHIFUJI Hideaki cp.attempt = cpu_to_le16(4); 736aca3192cSYOSHIFUJI Hideaki cp.timeout = cpu_to_le16(1); 737a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp); 73804837f64SMarcel Holtmann } 73904837f64SMarcel Holtmann } 74004837f64SMarcel Holtmann 7411da177e4SLinus Torvalds /* Drop all connection on the device */ 7421da177e4SLinus Torvalds void hci_conn_hash_flush(struct hci_dev *hdev) 7431da177e4SLinus Torvalds { 7441da177e4SLinus Torvalds struct hci_conn_hash *h = &hdev->conn_hash; 7451da177e4SLinus Torvalds struct list_head *p; 7461da177e4SLinus Torvalds 7471da177e4SLinus Torvalds BT_DBG("hdev %s", hdev->name); 7481da177e4SLinus Torvalds 7491da177e4SLinus Torvalds p = h->list.next; 7501da177e4SLinus Torvalds while (p != &h->list) { 7511da177e4SLinus Torvalds struct hci_conn *c; 7521da177e4SLinus Torvalds 7531da177e4SLinus Torvalds c = list_entry(p, struct hci_conn, list); 7541da177e4SLinus Torvalds p = p->next; 7551da177e4SLinus Torvalds 7561da177e4SLinus Torvalds c->state = BT_CLOSED; 7571da177e4SLinus Torvalds 7582950f21aSMarcel Holtmann hci_proto_disconn_cfm(c, 0x16); 7591da177e4SLinus Torvalds hci_conn_del(c); 7601da177e4SLinus Torvalds } 7611da177e4SLinus Torvalds } 7621da177e4SLinus Torvalds 763a9de9248SMarcel Holtmann /* Check pending connect attempts */ 764a9de9248SMarcel Holtmann void hci_conn_check_pending(struct hci_dev *hdev) 765a9de9248SMarcel Holtmann { 766a9de9248SMarcel Holtmann struct hci_conn *conn; 767a9de9248SMarcel Holtmann 768a9de9248SMarcel Holtmann BT_DBG("hdev %s", hdev->name); 769a9de9248SMarcel Holtmann 770a9de9248SMarcel Holtmann hci_dev_lock(hdev); 771a9de9248SMarcel Holtmann 772a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2); 773a9de9248SMarcel Holtmann if (conn) 774a9de9248SMarcel Holtmann hci_acl_connect(conn); 775a9de9248SMarcel Holtmann 776a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 777a9de9248SMarcel Holtmann } 778a9de9248SMarcel Holtmann 7799eba32b8SMarcel Holtmann void hci_conn_hold_device(struct hci_conn *conn) 7809eba32b8SMarcel Holtmann { 7819eba32b8SMarcel Holtmann atomic_inc(&conn->devref); 7829eba32b8SMarcel Holtmann } 7839eba32b8SMarcel Holtmann EXPORT_SYMBOL(hci_conn_hold_device); 7849eba32b8SMarcel Holtmann 7859eba32b8SMarcel Holtmann void hci_conn_put_device(struct hci_conn *conn) 7869eba32b8SMarcel Holtmann { 7879eba32b8SMarcel Holtmann if (atomic_dec_and_test(&conn->devref)) 7889eba32b8SMarcel Holtmann hci_conn_del_sysfs(conn); 7899eba32b8SMarcel Holtmann } 7909eba32b8SMarcel Holtmann EXPORT_SYMBOL(hci_conn_put_device); 7919eba32b8SMarcel Holtmann 7921da177e4SLinus Torvalds int hci_get_conn_list(void __user *arg) 7931da177e4SLinus Torvalds { 7941da177e4SLinus Torvalds struct hci_conn_list_req req, *cl; 7951da177e4SLinus Torvalds struct hci_conn_info *ci; 7961da177e4SLinus Torvalds struct hci_dev *hdev; 7971da177e4SLinus Torvalds struct list_head *p; 7981da177e4SLinus Torvalds int n = 0, size, err; 7991da177e4SLinus Torvalds 8001da177e4SLinus Torvalds if (copy_from_user(&req, arg, sizeof(req))) 8011da177e4SLinus Torvalds return -EFAULT; 8021da177e4SLinus Torvalds 8031da177e4SLinus Torvalds if (!req.conn_num || req.conn_num > (PAGE_SIZE * 2) / sizeof(*ci)) 8041da177e4SLinus Torvalds return -EINVAL; 8051da177e4SLinus Torvalds 8061da177e4SLinus Torvalds size = sizeof(req) + req.conn_num * sizeof(*ci); 8071da177e4SLinus Torvalds 80870f23020SAndrei Emeltchenko cl = kmalloc(size, GFP_KERNEL); 80970f23020SAndrei Emeltchenko if (!cl) 8101da177e4SLinus Torvalds return -ENOMEM; 8111da177e4SLinus Torvalds 81270f23020SAndrei Emeltchenko hdev = hci_dev_get(req.dev_id); 81370f23020SAndrei Emeltchenko if (!hdev) { 8141da177e4SLinus Torvalds kfree(cl); 8151da177e4SLinus Torvalds return -ENODEV; 8161da177e4SLinus Torvalds } 8171da177e4SLinus Torvalds 8181da177e4SLinus Torvalds ci = cl->conn_info; 8191da177e4SLinus Torvalds 8201da177e4SLinus Torvalds hci_dev_lock_bh(hdev); 8211da177e4SLinus Torvalds list_for_each(p, &hdev->conn_hash.list) { 8221da177e4SLinus Torvalds register struct hci_conn *c; 8231da177e4SLinus Torvalds c = list_entry(p, struct hci_conn, list); 8241da177e4SLinus Torvalds 8251da177e4SLinus Torvalds bacpy(&(ci + n)->bdaddr, &c->dst); 8261da177e4SLinus Torvalds (ci + n)->handle = c->handle; 8271da177e4SLinus Torvalds (ci + n)->type = c->type; 8281da177e4SLinus Torvalds (ci + n)->out = c->out; 8291da177e4SLinus Torvalds (ci + n)->state = c->state; 8301da177e4SLinus Torvalds (ci + n)->link_mode = c->link_mode; 8311da177e4SLinus Torvalds if (++n >= req.conn_num) 8321da177e4SLinus Torvalds break; 8331da177e4SLinus Torvalds } 8341da177e4SLinus Torvalds hci_dev_unlock_bh(hdev); 8351da177e4SLinus Torvalds 8361da177e4SLinus Torvalds cl->dev_id = hdev->id; 8371da177e4SLinus Torvalds cl->conn_num = n; 8381da177e4SLinus Torvalds size = sizeof(req) + n * sizeof(*ci); 8391da177e4SLinus Torvalds 8401da177e4SLinus Torvalds hci_dev_put(hdev); 8411da177e4SLinus Torvalds 8421da177e4SLinus Torvalds err = copy_to_user(arg, cl, size); 8431da177e4SLinus Torvalds kfree(cl); 8441da177e4SLinus Torvalds 8451da177e4SLinus Torvalds return err ? -EFAULT : 0; 8461da177e4SLinus Torvalds } 8471da177e4SLinus Torvalds 8481da177e4SLinus Torvalds int hci_get_conn_info(struct hci_dev *hdev, void __user *arg) 8491da177e4SLinus Torvalds { 8501da177e4SLinus Torvalds struct hci_conn_info_req req; 8511da177e4SLinus Torvalds struct hci_conn_info ci; 8521da177e4SLinus Torvalds struct hci_conn *conn; 8531da177e4SLinus Torvalds char __user *ptr = arg + sizeof(req); 8541da177e4SLinus Torvalds 8551da177e4SLinus Torvalds if (copy_from_user(&req, arg, sizeof(req))) 8561da177e4SLinus Torvalds return -EFAULT; 8571da177e4SLinus Torvalds 8581da177e4SLinus Torvalds hci_dev_lock_bh(hdev); 8591da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, req.type, &req.bdaddr); 8601da177e4SLinus Torvalds if (conn) { 8611da177e4SLinus Torvalds bacpy(&ci.bdaddr, &conn->dst); 8621da177e4SLinus Torvalds ci.handle = conn->handle; 8631da177e4SLinus Torvalds ci.type = conn->type; 8641da177e4SLinus Torvalds ci.out = conn->out; 8651da177e4SLinus Torvalds ci.state = conn->state; 8661da177e4SLinus Torvalds ci.link_mode = conn->link_mode; 8671da177e4SLinus Torvalds } 8681da177e4SLinus Torvalds hci_dev_unlock_bh(hdev); 8691da177e4SLinus Torvalds 8701da177e4SLinus Torvalds if (!conn) 8711da177e4SLinus Torvalds return -ENOENT; 8721da177e4SLinus Torvalds 8731da177e4SLinus Torvalds return copy_to_user(ptr, &ci, sizeof(ci)) ? -EFAULT : 0; 8741da177e4SLinus Torvalds } 87540be492fSMarcel Holtmann 87640be492fSMarcel Holtmann int hci_get_auth_info(struct hci_dev *hdev, void __user *arg) 87740be492fSMarcel Holtmann { 87840be492fSMarcel Holtmann struct hci_auth_info_req req; 87940be492fSMarcel Holtmann struct hci_conn *conn; 88040be492fSMarcel Holtmann 88140be492fSMarcel Holtmann if (copy_from_user(&req, arg, sizeof(req))) 88240be492fSMarcel Holtmann return -EFAULT; 88340be492fSMarcel Holtmann 88440be492fSMarcel Holtmann hci_dev_lock_bh(hdev); 88540be492fSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &req.bdaddr); 88640be492fSMarcel Holtmann if (conn) 88740be492fSMarcel Holtmann req.type = conn->auth_type; 88840be492fSMarcel Holtmann hci_dev_unlock_bh(hdev); 88940be492fSMarcel Holtmann 89040be492fSMarcel Holtmann if (!conn) 89140be492fSMarcel Holtmann return -ENOENT; 89240be492fSMarcel Holtmann 89340be492fSMarcel Holtmann return copy_to_user(arg, &req, sizeof(req)) ? -EFAULT : 0; 89440be492fSMarcel Holtmann } 895