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 278c520a59SGustavo Padovan #include <linux/export.h> 281da177e4SLinus Torvalds 291da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h> 301da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h> 319740e49dSAndrei Emeltchenko #include <net/bluetooth/a2mp.h> 32d8343f12SVinicius Costa Gomes #include <net/bluetooth/smp.h> 331da177e4SLinus Torvalds 342dea632fSFrédéric Dalleau struct sco_param { 352dea632fSFrédéric Dalleau u16 pkt_type; 362dea632fSFrédéric Dalleau u16 max_latency; 372dea632fSFrédéric Dalleau }; 382dea632fSFrédéric Dalleau 392dea632fSFrédéric Dalleau static const struct sco_param sco_param_cvsd[] = { 402dea632fSFrédéric Dalleau { EDR_ESCO_MASK & ~ESCO_2EV3, 0x000a }, /* S3 */ 412dea632fSFrédéric Dalleau { EDR_ESCO_MASK & ~ESCO_2EV3, 0x0007 }, /* S2 */ 422dea632fSFrédéric Dalleau { EDR_ESCO_MASK | ESCO_EV3, 0x0007 }, /* S1 */ 432dea632fSFrédéric Dalleau { EDR_ESCO_MASK | ESCO_HV3, 0xffff }, /* D1 */ 442dea632fSFrédéric Dalleau { EDR_ESCO_MASK | ESCO_HV1, 0xffff }, /* D0 */ 452dea632fSFrédéric Dalleau }; 462dea632fSFrédéric Dalleau 472dea632fSFrédéric Dalleau static const struct sco_param sco_param_wideband[] = { 482dea632fSFrédéric Dalleau { EDR_ESCO_MASK & ~ESCO_2EV3, 0x000d }, /* T2 */ 492dea632fSFrédéric Dalleau { EDR_ESCO_MASK | ESCO_EV3, 0x0008 }, /* T1 */ 502dea632fSFrédéric Dalleau }; 512dea632fSFrédéric Dalleau 521aef8669SVinicius Costa Gomes static void hci_le_create_connection_cancel(struct hci_conn *conn) 53fcd89c09SVille Tervo { 54fcd89c09SVille Tervo hci_send_cmd(conn->hdev, HCI_OP_LE_CREATE_CONN_CANCEL, 0, NULL); 55fcd89c09SVille Tervo } 56fcd89c09SVille Tervo 571aef8669SVinicius Costa Gomes static void hci_acl_create_connection(struct hci_conn *conn) 581da177e4SLinus Torvalds { 591da177e4SLinus Torvalds struct hci_dev *hdev = conn->hdev; 601da177e4SLinus Torvalds struct inquiry_entry *ie; 611da177e4SLinus Torvalds struct hci_cp_create_conn cp; 621da177e4SLinus Torvalds 6342d2d87cSAndrei Emeltchenko BT_DBG("hcon %p", conn); 641da177e4SLinus Torvalds 651da177e4SLinus Torvalds conn->state = BT_CONNECT; 66a0c808b3SJohan Hedberg conn->out = true; 67a8746417SMarcel Holtmann 681da177e4SLinus Torvalds conn->link_mode = HCI_LM_MASTER; 691da177e4SLinus Torvalds 704c67bc74SMarcel Holtmann conn->attempt++; 714c67bc74SMarcel Holtmann 72e4e8e37cSMarcel Holtmann conn->link_policy = hdev->link_policy; 73e4e8e37cSMarcel Holtmann 741da177e4SLinus Torvalds memset(&cp, 0, sizeof(cp)); 751da177e4SLinus Torvalds bacpy(&cp.bdaddr, &conn->dst); 761da177e4SLinus Torvalds cp.pscan_rep_mode = 0x02; 771da177e4SLinus Torvalds 7870f23020SAndrei Emeltchenko ie = hci_inquiry_cache_lookup(hdev, &conn->dst); 7970f23020SAndrei Emeltchenko if (ie) { 8041a96212SMarcel Holtmann if (inquiry_entry_age(ie) <= INQUIRY_ENTRY_AGE_MAX) { 811da177e4SLinus Torvalds cp.pscan_rep_mode = ie->data.pscan_rep_mode; 821da177e4SLinus Torvalds cp.pscan_mode = ie->data.pscan_mode; 8341a96212SMarcel Holtmann cp.clock_offset = ie->data.clock_offset | 8482781e63SAndrei Emeltchenko __constant_cpu_to_le16(0x8000); 8541a96212SMarcel Holtmann } 8641a96212SMarcel Holtmann 871da177e4SLinus Torvalds memcpy(conn->dev_class, ie->data.dev_class, 3); 8858a681efSJohan Hedberg if (ie->data.ssp_mode > 0) 8958a681efSJohan Hedberg set_bit(HCI_CONN_SSP_ENABLED, &conn->flags); 901da177e4SLinus Torvalds } 911da177e4SLinus Torvalds 92a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 931da177e4SLinus Torvalds if (lmp_rswitch_capable(hdev) && !(hdev->link_mode & HCI_LM_MASTER)) 941da177e4SLinus Torvalds cp.role_switch = 0x01; 951da177e4SLinus Torvalds else 961da177e4SLinus Torvalds cp.role_switch = 0x00; 971da177e4SLinus Torvalds 98a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_CREATE_CONN, sizeof(cp), &cp); 991da177e4SLinus Torvalds } 1001da177e4SLinus Torvalds 1011aef8669SVinicius Costa Gomes static void hci_acl_create_connection_cancel(struct hci_conn *conn) 1026ac59344SMarcel Holtmann { 1036ac59344SMarcel Holtmann struct hci_cp_create_conn_cancel cp; 1046ac59344SMarcel Holtmann 10538b3fef1SAndrei Emeltchenko BT_DBG("hcon %p", conn); 1066ac59344SMarcel Holtmann 107d095c1ebSAndrei Emeltchenko if (conn->hdev->hci_ver < BLUETOOTH_VER_1_2) 1086ac59344SMarcel Holtmann return; 1096ac59344SMarcel Holtmann 1106ac59344SMarcel Holtmann bacpy(&cp.bdaddr, &conn->dst); 111a9de9248SMarcel Holtmann hci_send_cmd(conn->hdev, HCI_OP_CREATE_CONN_CANCEL, sizeof(cp), &cp); 1126ac59344SMarcel Holtmann } 1136ac59344SMarcel Holtmann 11493796fa6SClaudio Takahasi static void hci_reject_sco(struct hci_conn *conn) 11593796fa6SClaudio Takahasi { 11693796fa6SClaudio Takahasi struct hci_cp_reject_sync_conn_req cp; 11793796fa6SClaudio Takahasi 11893796fa6SClaudio Takahasi cp.reason = HCI_ERROR_REMOTE_USER_TERM; 11993796fa6SClaudio Takahasi bacpy(&cp.bdaddr, &conn->dst); 12093796fa6SClaudio Takahasi 12193796fa6SClaudio Takahasi hci_send_cmd(conn->hdev, HCI_OP_REJECT_SYNC_CONN_REQ, sizeof(cp), &cp); 12293796fa6SClaudio Takahasi } 12393796fa6SClaudio Takahasi 124bed71748SAndre Guedes void hci_disconnect(struct hci_conn *conn, __u8 reason) 1251da177e4SLinus Torvalds { 1261da177e4SLinus Torvalds struct hci_cp_disconnect cp; 1271da177e4SLinus Torvalds 12838b3fef1SAndrei Emeltchenko BT_DBG("hcon %p", conn); 1291da177e4SLinus Torvalds 1301da177e4SLinus Torvalds conn->state = BT_DISCONN; 1311da177e4SLinus Torvalds 132aca3192cSYOSHIFUJI Hideaki cp.handle = cpu_to_le16(conn->handle); 1331da177e4SLinus Torvalds cp.reason = reason; 134a9de9248SMarcel Holtmann hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp); 1351da177e4SLinus Torvalds } 1361da177e4SLinus Torvalds 13753502d69SAndrei Emeltchenko static void hci_amp_disconn(struct hci_conn *conn, __u8 reason) 13853502d69SAndrei Emeltchenko { 13953502d69SAndrei Emeltchenko struct hci_cp_disconn_phy_link cp; 14053502d69SAndrei Emeltchenko 14153502d69SAndrei Emeltchenko BT_DBG("hcon %p", conn); 14253502d69SAndrei Emeltchenko 14353502d69SAndrei Emeltchenko conn->state = BT_DISCONN; 14453502d69SAndrei Emeltchenko 14553502d69SAndrei Emeltchenko cp.phy_handle = HCI_PHY_HANDLE(conn->handle); 14653502d69SAndrei Emeltchenko cp.reason = reason; 14753502d69SAndrei Emeltchenko hci_send_cmd(conn->hdev, HCI_OP_DISCONN_PHY_LINK, 14853502d69SAndrei Emeltchenko sizeof(cp), &cp); 14953502d69SAndrei Emeltchenko } 15053502d69SAndrei Emeltchenko 15157f5d0d1SVinicius Costa Gomes static void hci_add_sco(struct hci_conn *conn, __u16 handle) 1521da177e4SLinus Torvalds { 1531da177e4SLinus Torvalds struct hci_dev *hdev = conn->hdev; 1541da177e4SLinus Torvalds struct hci_cp_add_sco cp; 1551da177e4SLinus Torvalds 15638b3fef1SAndrei Emeltchenko BT_DBG("hcon %p", conn); 1571da177e4SLinus Torvalds 1581da177e4SLinus Torvalds conn->state = BT_CONNECT; 159a0c808b3SJohan Hedberg conn->out = true; 1601da177e4SLinus Torvalds 161efc7688bSMarcel Holtmann conn->attempt++; 162efc7688bSMarcel Holtmann 163aca3192cSYOSHIFUJI Hideaki cp.handle = cpu_to_le16(handle); 164a8746417SMarcel Holtmann cp.pkt_type = cpu_to_le16(conn->pkt_type); 1651da177e4SLinus Torvalds 166a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_ADD_SCO, sizeof(cp), &cp); 1671da177e4SLinus Torvalds } 1681da177e4SLinus Torvalds 1692dea632fSFrédéric Dalleau bool hci_setup_sync(struct hci_conn *conn, __u16 handle) 170b6a0dc82SMarcel Holtmann { 171b6a0dc82SMarcel Holtmann struct hci_dev *hdev = conn->hdev; 172b6a0dc82SMarcel Holtmann struct hci_cp_setup_sync_conn cp; 1732dea632fSFrédéric Dalleau const struct sco_param *param; 174b6a0dc82SMarcel Holtmann 17538b3fef1SAndrei Emeltchenko BT_DBG("hcon %p", conn); 176b6a0dc82SMarcel Holtmann 177b6a0dc82SMarcel Holtmann conn->state = BT_CONNECT; 178a0c808b3SJohan Hedberg conn->out = true; 179b6a0dc82SMarcel Holtmann 180efc7688bSMarcel Holtmann conn->attempt++; 181efc7688bSMarcel Holtmann 182b6a0dc82SMarcel Holtmann cp.handle = cpu_to_le16(handle); 183b6a0dc82SMarcel Holtmann 18482781e63SAndrei Emeltchenko cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40); 18582781e63SAndrei Emeltchenko cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40); 18610c62ddcSFrédéric Dalleau cp.voice_setting = cpu_to_le16(conn->setting); 18710c62ddcSFrédéric Dalleau 18810c62ddcSFrédéric Dalleau switch (conn->setting & SCO_AIRMODE_MASK) { 18910c62ddcSFrédéric Dalleau case SCO_AIRMODE_TRANSP: 1902dea632fSFrédéric Dalleau if (conn->attempt > ARRAY_SIZE(sco_param_wideband)) 1912dea632fSFrédéric Dalleau return false; 19210c62ddcSFrédéric Dalleau cp.retrans_effort = 0x02; 1932dea632fSFrédéric Dalleau param = &sco_param_wideband[conn->attempt - 1]; 19410c62ddcSFrédéric Dalleau break; 19510c62ddcSFrédéric Dalleau case SCO_AIRMODE_CVSD: 1962dea632fSFrédéric Dalleau if (conn->attempt > ARRAY_SIZE(sco_param_cvsd)) 1972dea632fSFrédéric Dalleau return false; 1982dea632fSFrédéric Dalleau cp.retrans_effort = 0x01; 1992dea632fSFrédéric Dalleau param = &sco_param_cvsd[conn->attempt - 1]; 20010c62ddcSFrédéric Dalleau break; 2012dea632fSFrédéric Dalleau default: 2022dea632fSFrédéric Dalleau return false; 20310c62ddcSFrédéric Dalleau } 204b6a0dc82SMarcel Holtmann 2052dea632fSFrédéric Dalleau cp.pkt_type = __cpu_to_le16(param->pkt_type); 2062dea632fSFrédéric Dalleau cp.max_latency = __cpu_to_le16(param->max_latency); 2072dea632fSFrédéric Dalleau 2082dea632fSFrédéric Dalleau if (hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp) < 0) 2092dea632fSFrédéric Dalleau return false; 2102dea632fSFrédéric Dalleau 2112dea632fSFrédéric Dalleau return true; 212b6a0dc82SMarcel Holtmann } 213b6a0dc82SMarcel Holtmann 2142ce603ebSClaudio Takahasi void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, 2152ce603ebSClaudio Takahasi u16 latency, u16 to_multiplier) 2162ce603ebSClaudio Takahasi { 2172ce603ebSClaudio Takahasi struct hci_cp_le_conn_update cp; 2182ce603ebSClaudio Takahasi struct hci_dev *hdev = conn->hdev; 2192ce603ebSClaudio Takahasi 2202ce603ebSClaudio Takahasi memset(&cp, 0, sizeof(cp)); 2212ce603ebSClaudio Takahasi 2222ce603ebSClaudio Takahasi cp.handle = cpu_to_le16(conn->handle); 2232ce603ebSClaudio Takahasi cp.conn_interval_min = cpu_to_le16(min); 2242ce603ebSClaudio Takahasi cp.conn_interval_max = cpu_to_le16(max); 2252ce603ebSClaudio Takahasi cp.conn_latency = cpu_to_le16(latency); 2262ce603ebSClaudio Takahasi cp.supervision_timeout = cpu_to_le16(to_multiplier); 22782781e63SAndrei Emeltchenko cp.min_ce_len = __constant_cpu_to_le16(0x0001); 22882781e63SAndrei Emeltchenko cp.max_ce_len = __constant_cpu_to_le16(0x0001); 2292ce603ebSClaudio Takahasi 2302ce603ebSClaudio Takahasi hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp); 2312ce603ebSClaudio Takahasi } 2322ce603ebSClaudio Takahasi 233a7a595f6SVinicius Costa Gomes void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8], 234a7a595f6SVinicius Costa Gomes __u8 ltk[16]) 235a7a595f6SVinicius Costa Gomes { 236a7a595f6SVinicius Costa Gomes struct hci_dev *hdev = conn->hdev; 237a7a595f6SVinicius Costa Gomes struct hci_cp_le_start_enc cp; 238a7a595f6SVinicius Costa Gomes 23938b3fef1SAndrei Emeltchenko BT_DBG("hcon %p", conn); 240a7a595f6SVinicius Costa Gomes 241a7a595f6SVinicius Costa Gomes memset(&cp, 0, sizeof(cp)); 242a7a595f6SVinicius Costa Gomes 243a7a595f6SVinicius Costa Gomes cp.handle = cpu_to_le16(conn->handle); 244a7a595f6SVinicius Costa Gomes memcpy(cp.ltk, ltk, sizeof(cp.ltk)); 245a7a595f6SVinicius Costa Gomes cp.ediv = ediv; 24651beabdfSAnderson Briglia memcpy(cp.rand, rand, sizeof(cp.rand)); 247a7a595f6SVinicius Costa Gomes 248a7a595f6SVinicius Costa Gomes hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp); 249a7a595f6SVinicius Costa Gomes } 250a7a595f6SVinicius Costa Gomes 251e73439d8SMarcel Holtmann /* Device _must_ be locked */ 252e73439d8SMarcel Holtmann void hci_sco_setup(struct hci_conn *conn, __u8 status) 253e73439d8SMarcel Holtmann { 254e73439d8SMarcel Holtmann struct hci_conn *sco = conn->link; 255e73439d8SMarcel Holtmann 256e73439d8SMarcel Holtmann if (!sco) 257e73439d8SMarcel Holtmann return; 258e73439d8SMarcel Holtmann 25938b3fef1SAndrei Emeltchenko BT_DBG("hcon %p", conn); 26038b3fef1SAndrei Emeltchenko 261e73439d8SMarcel Holtmann if (!status) { 262e73439d8SMarcel Holtmann if (lmp_esco_capable(conn->hdev)) 263e73439d8SMarcel Holtmann hci_setup_sync(sco, conn->handle); 264e73439d8SMarcel Holtmann else 265e73439d8SMarcel Holtmann hci_add_sco(sco, conn->handle); 266e73439d8SMarcel Holtmann } else { 267e73439d8SMarcel Holtmann hci_proto_connect_cfm(sco, status); 268e73439d8SMarcel Holtmann hci_conn_del(sco); 269e73439d8SMarcel Holtmann } 270e73439d8SMarcel Holtmann } 271e73439d8SMarcel Holtmann 27253502d69SAndrei Emeltchenko static void hci_conn_disconnect(struct hci_conn *conn) 27353502d69SAndrei Emeltchenko { 27453502d69SAndrei Emeltchenko __u8 reason = hci_proto_disconn_ind(conn); 27553502d69SAndrei Emeltchenko 27653502d69SAndrei Emeltchenko switch (conn->type) { 27753502d69SAndrei Emeltchenko case AMP_LINK: 27853502d69SAndrei Emeltchenko hci_amp_disconn(conn, reason); 27953502d69SAndrei Emeltchenko break; 2804c02e2d4SAndre Guedes default: 281bed71748SAndre Guedes hci_disconnect(conn, reason); 2824c02e2d4SAndre Guedes break; 28353502d69SAndrei Emeltchenko } 28453502d69SAndrei Emeltchenko } 28553502d69SAndrei Emeltchenko 28619c40e3bSGustavo F. Padovan static void hci_conn_timeout(struct work_struct *work) 2871da177e4SLinus Torvalds { 28819c40e3bSGustavo F. Padovan struct hci_conn *conn = container_of(work, struct hci_conn, 28919c40e3bSGustavo F. Padovan disc_work.work); 2901da177e4SLinus Torvalds 29138b3fef1SAndrei Emeltchenko BT_DBG("hcon %p state %s", conn, state_to_string(conn->state)); 2921da177e4SLinus Torvalds 2931da177e4SLinus Torvalds if (atomic_read(&conn->refcnt)) 2941da177e4SLinus Torvalds return; 2951da177e4SLinus Torvalds 2966ac59344SMarcel Holtmann switch (conn->state) { 2976ac59344SMarcel Holtmann case BT_CONNECT: 298769be974SMarcel Holtmann case BT_CONNECT2: 299fcd89c09SVille Tervo if (conn->out) { 300fcd89c09SVille Tervo if (conn->type == ACL_LINK) 3011aef8669SVinicius Costa Gomes hci_acl_create_connection_cancel(conn); 302fcd89c09SVille Tervo else if (conn->type == LE_LINK) 3031aef8669SVinicius Costa Gomes hci_le_create_connection_cancel(conn); 30493796fa6SClaudio Takahasi } else if (conn->type == SCO_LINK || conn->type == ESCO_LINK) { 30593796fa6SClaudio Takahasi hci_reject_sco(conn); 306fcd89c09SVille Tervo } 3076ac59344SMarcel Holtmann break; 308769be974SMarcel Holtmann case BT_CONFIG: 3096ac59344SMarcel Holtmann case BT_CONNECTED: 31053502d69SAndrei Emeltchenko hci_conn_disconnect(conn); 3116ac59344SMarcel Holtmann break; 3126ac59344SMarcel Holtmann default: 3131da177e4SLinus Torvalds conn->state = BT_CLOSED; 3146ac59344SMarcel Holtmann break; 3156ac59344SMarcel Holtmann } 3161da177e4SLinus Torvalds } 3171da177e4SLinus Torvalds 318416dc94bSGustavo F. Padovan /* Enter sniff mode */ 319416dc94bSGustavo F. Padovan static void hci_conn_enter_sniff_mode(struct hci_conn *conn) 320416dc94bSGustavo F. Padovan { 321416dc94bSGustavo F. Padovan struct hci_dev *hdev = conn->hdev; 322416dc94bSGustavo F. Padovan 32338b3fef1SAndrei Emeltchenko BT_DBG("hcon %p mode %d", conn, conn->mode); 324416dc94bSGustavo F. Padovan 325416dc94bSGustavo F. Padovan if (test_bit(HCI_RAW, &hdev->flags)) 326416dc94bSGustavo F. Padovan return; 327416dc94bSGustavo F. Padovan 328416dc94bSGustavo F. Padovan if (!lmp_sniff_capable(hdev) || !lmp_sniff_capable(conn)) 329416dc94bSGustavo F. Padovan return; 330416dc94bSGustavo F. Padovan 331416dc94bSGustavo F. Padovan if (conn->mode != HCI_CM_ACTIVE || !(conn->link_policy & HCI_LP_SNIFF)) 332416dc94bSGustavo F. Padovan return; 333416dc94bSGustavo F. Padovan 334416dc94bSGustavo F. Padovan if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) { 335416dc94bSGustavo F. Padovan struct hci_cp_sniff_subrate cp; 336416dc94bSGustavo F. Padovan cp.handle = cpu_to_le16(conn->handle); 33782781e63SAndrei Emeltchenko cp.max_latency = __constant_cpu_to_le16(0); 33882781e63SAndrei Emeltchenko cp.min_remote_timeout = __constant_cpu_to_le16(0); 33982781e63SAndrei Emeltchenko cp.min_local_timeout = __constant_cpu_to_le16(0); 340416dc94bSGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp); 341416dc94bSGustavo F. Padovan } 342416dc94bSGustavo F. Padovan 34351a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) { 344416dc94bSGustavo F. Padovan struct hci_cp_sniff_mode cp; 345416dc94bSGustavo F. Padovan cp.handle = cpu_to_le16(conn->handle); 346416dc94bSGustavo F. Padovan cp.max_interval = cpu_to_le16(hdev->sniff_max_interval); 347416dc94bSGustavo F. Padovan cp.min_interval = cpu_to_le16(hdev->sniff_min_interval); 34882781e63SAndrei Emeltchenko cp.attempt = __constant_cpu_to_le16(4); 34982781e63SAndrei Emeltchenko cp.timeout = __constant_cpu_to_le16(1); 350416dc94bSGustavo F. Padovan hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp); 351416dc94bSGustavo F. Padovan } 352416dc94bSGustavo F. Padovan } 353416dc94bSGustavo F. Padovan 35404837f64SMarcel Holtmann static void hci_conn_idle(unsigned long arg) 3551da177e4SLinus Torvalds { 35604837f64SMarcel Holtmann struct hci_conn *conn = (void *) arg; 35704837f64SMarcel Holtmann 35838b3fef1SAndrei Emeltchenko BT_DBG("hcon %p mode %d", conn, conn->mode); 35904837f64SMarcel Holtmann 36004837f64SMarcel Holtmann hci_conn_enter_sniff_mode(conn); 3611da177e4SLinus Torvalds } 3621da177e4SLinus Torvalds 3639f61656aSJohan Hedberg static void hci_conn_auto_accept(unsigned long arg) 3649f61656aSJohan Hedberg { 3659f61656aSJohan Hedberg struct hci_conn *conn = (void *) arg; 3669f61656aSJohan Hedberg struct hci_dev *hdev = conn->hdev; 3679f61656aSJohan Hedberg 3689f61656aSJohan Hedberg hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, sizeof(conn->dst), 3699f61656aSJohan Hedberg &conn->dst); 3709f61656aSJohan Hedberg } 3719f61656aSJohan Hedberg 3721da177e4SLinus Torvalds struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) 3731da177e4SLinus Torvalds { 3741da177e4SLinus Torvalds struct hci_conn *conn; 3751da177e4SLinus Torvalds 3766ed93dc6SAndrei Emeltchenko BT_DBG("%s dst %pMR", hdev->name, dst); 3771da177e4SLinus Torvalds 378cb601d7eSAndre Guedes conn = kzalloc(sizeof(struct hci_conn), GFP_KERNEL); 37904837f64SMarcel Holtmann if (!conn) 3801da177e4SLinus Torvalds return NULL; 3811da177e4SLinus Torvalds 3821da177e4SLinus Torvalds bacpy(&conn->dst, dst); 3831da177e4SLinus Torvalds conn->hdev = hdev; 38404837f64SMarcel Holtmann conn->type = type; 38504837f64SMarcel Holtmann conn->mode = HCI_CM_ACTIVE; 3861da177e4SLinus Torvalds conn->state = BT_OPEN; 38793f19c9fSAndrei Emeltchenko conn->auth_type = HCI_AT_GENERAL_BONDING; 38817fa4b9dSJohan Hedberg conn->io_capability = hdev->io_capability; 389a9583556SJohan Hedberg conn->remote_auth = 0xff; 39013d39315SWaldemar Rymarkiewicz conn->key_type = 0xff; 3911da177e4SLinus Torvalds 39258a681efSJohan Hedberg set_bit(HCI_CONN_POWER_SAVE, &conn->flags); 393052b30b0SMarcel Holtmann conn->disc_timeout = HCI_DISCONN_TIMEOUT; 39404837f64SMarcel Holtmann 395a8746417SMarcel Holtmann switch (type) { 396a8746417SMarcel Holtmann case ACL_LINK: 397a8746417SMarcel Holtmann conn->pkt_type = hdev->pkt_type & ACL_PTYPE_MASK; 398a8746417SMarcel Holtmann break; 399a8746417SMarcel Holtmann case SCO_LINK: 400a8746417SMarcel Holtmann if (lmp_esco_capable(hdev)) 401efc7688bSMarcel Holtmann conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | 402efc7688bSMarcel Holtmann (hdev->esco_type & EDR_ESCO_MASK); 403a8746417SMarcel Holtmann else 404a8746417SMarcel Holtmann conn->pkt_type = hdev->pkt_type & SCO_PTYPE_MASK; 405a8746417SMarcel Holtmann break; 406a8746417SMarcel Holtmann case ESCO_LINK: 407efc7688bSMarcel Holtmann conn->pkt_type = hdev->esco_type & ~EDR_ESCO_MASK; 408a8746417SMarcel Holtmann break; 409a8746417SMarcel Holtmann } 410a8746417SMarcel Holtmann 4111da177e4SLinus Torvalds skb_queue_head_init(&conn->data_q); 41204837f64SMarcel Holtmann 41370c1f20bSMarcel Holtmann INIT_LIST_HEAD(&conn->chan_list); 41473d80debSLuiz Augusto von Dentz 41519c40e3bSGustavo F. Padovan INIT_DELAYED_WORK(&conn->disc_work, hci_conn_timeout); 416b24b8a24SPavel Emelyanov setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn); 4179f61656aSJohan Hedberg setup_timer(&conn->auto_accept_timer, hci_conn_auto_accept, 4189f61656aSJohan Hedberg (unsigned long) conn); 4191da177e4SLinus Torvalds 4201da177e4SLinus Torvalds atomic_set(&conn->refcnt, 0); 4211da177e4SLinus Torvalds 4221da177e4SLinus Torvalds hci_dev_hold(hdev); 4231da177e4SLinus Torvalds 4241da177e4SLinus Torvalds hci_conn_hash_add(hdev, conn); 4253c54711cSGustavo F. Padovan if (hdev->notify) 4261da177e4SLinus Torvalds hdev->notify(hdev, HCI_NOTIFY_CONN_ADD); 4271da177e4SLinus Torvalds 428a67e899cSMarcel Holtmann hci_conn_init_sysfs(conn); 429a67e899cSMarcel Holtmann 4301da177e4SLinus Torvalds return conn; 4311da177e4SLinus Torvalds } 4321da177e4SLinus Torvalds 4331da177e4SLinus Torvalds int hci_conn_del(struct hci_conn *conn) 4341da177e4SLinus Torvalds { 4351da177e4SLinus Torvalds struct hci_dev *hdev = conn->hdev; 4361da177e4SLinus Torvalds 43738b3fef1SAndrei Emeltchenko BT_DBG("%s hcon %p handle %d", hdev->name, conn, conn->handle); 4381da177e4SLinus Torvalds 43904837f64SMarcel Holtmann del_timer(&conn->idle_timer); 44004837f64SMarcel Holtmann 44119c40e3bSGustavo F. Padovan cancel_delayed_work_sync(&conn->disc_work); 4421da177e4SLinus Torvalds 4439f61656aSJohan Hedberg del_timer(&conn->auto_accept_timer); 4449f61656aSJohan Hedberg 4455b7f9909SMarcel Holtmann if (conn->type == ACL_LINK) { 4461da177e4SLinus Torvalds struct hci_conn *sco = conn->link; 4471da177e4SLinus Torvalds if (sco) 4481da177e4SLinus Torvalds sco->link = NULL; 4491da177e4SLinus Torvalds 4501da177e4SLinus Torvalds /* Unacked frames */ 4511da177e4SLinus Torvalds hdev->acl_cnt += conn->sent; 4526ed58ec5SVille Tervo } else if (conn->type == LE_LINK) { 4536ed58ec5SVille Tervo if (hdev->le_pkts) 4546ed58ec5SVille Tervo hdev->le_cnt += conn->sent; 4556ed58ec5SVille Tervo else 4566ed58ec5SVille Tervo hdev->acl_cnt += conn->sent; 4575b7f9909SMarcel Holtmann } else { 4585b7f9909SMarcel Holtmann struct hci_conn *acl = conn->link; 4595b7f9909SMarcel Holtmann if (acl) { 4605b7f9909SMarcel Holtmann acl->link = NULL; 46176a68ba0SDavid Herrmann hci_conn_drop(acl); 4625b7f9909SMarcel Holtmann } 4631da177e4SLinus Torvalds } 4641da177e4SLinus Torvalds 4652c33c06aSGustavo F. Padovan hci_chan_list_flush(conn); 46673d80debSLuiz Augusto von Dentz 4679740e49dSAndrei Emeltchenko if (conn->amp_mgr) 4689740e49dSAndrei Emeltchenko amp_mgr_put(conn->amp_mgr); 4699740e49dSAndrei Emeltchenko 4701da177e4SLinus Torvalds hci_conn_hash_del(hdev, conn); 4713c54711cSGustavo F. Padovan if (hdev->notify) 4721da177e4SLinus Torvalds hdev->notify(hdev, HCI_NOTIFY_CONN_DEL); 4737d0db0a3SMarcel Holtmann 4741da177e4SLinus Torvalds skb_queue_purge(&conn->data_q); 4751da177e4SLinus Torvalds 476fc225c3fSDavid Herrmann hci_conn_del_sysfs(conn); 4772ae9a6beSDave Young 478384943ecSMarcel Holtmann hci_dev_put(hdev); 479384943ecSMarcel Holtmann 4808d12356fSDavid Herrmann hci_conn_put(conn); 481163f4dabSTomas Targownik 4821da177e4SLinus Torvalds return 0; 4831da177e4SLinus Torvalds } 4841da177e4SLinus Torvalds 4851da177e4SLinus Torvalds struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src) 4861da177e4SLinus Torvalds { 4871da177e4SLinus Torvalds int use_src = bacmp(src, BDADDR_ANY); 4888035ded4SLuiz Augusto von Dentz struct hci_dev *hdev = NULL, *d; 4891da177e4SLinus Torvalds 4906ed93dc6SAndrei Emeltchenko BT_DBG("%pMR -> %pMR", src, dst); 4911da177e4SLinus Torvalds 492f20d09d5SGustavo F. Padovan read_lock(&hci_dev_list_lock); 4931da177e4SLinus Torvalds 4948035ded4SLuiz Augusto von Dentz list_for_each_entry(d, &hci_dev_list, list) { 4958fc9ced3SGustavo Padovan if (!test_bit(HCI_UP, &d->flags) || 496d300fa9bSAndrei Emeltchenko test_bit(HCI_RAW, &d->flags) || 497af750e94SMarcel Holtmann test_bit(HCI_USER_CHANNEL, &d->dev_flags) || 498d300fa9bSAndrei Emeltchenko d->dev_type != HCI_BREDR) 4991da177e4SLinus Torvalds continue; 5001da177e4SLinus Torvalds 5011da177e4SLinus Torvalds /* Simple routing: 5021da177e4SLinus Torvalds * No source address - find interface with bdaddr != dst 5031da177e4SLinus Torvalds * Source address - find interface with bdaddr == src 5041da177e4SLinus Torvalds */ 5051da177e4SLinus Torvalds 5061da177e4SLinus Torvalds if (use_src) { 5071da177e4SLinus Torvalds if (!bacmp(&d->bdaddr, src)) { 5081da177e4SLinus Torvalds hdev = d; break; 5091da177e4SLinus Torvalds } 5101da177e4SLinus Torvalds } else { 5111da177e4SLinus Torvalds if (bacmp(&d->bdaddr, dst)) { 5121da177e4SLinus Torvalds hdev = d; break; 5131da177e4SLinus Torvalds } 5141da177e4SLinus Torvalds } 5151da177e4SLinus Torvalds } 5161da177e4SLinus Torvalds 5171da177e4SLinus Torvalds if (hdev) 5181da177e4SLinus Torvalds hdev = hci_dev_hold(hdev); 5191da177e4SLinus Torvalds 520f20d09d5SGustavo F. Padovan read_unlock(&hci_dev_list_lock); 5211da177e4SLinus Torvalds return hdev; 5221da177e4SLinus Torvalds } 5231da177e4SLinus Torvalds EXPORT_SYMBOL(hci_get_route); 5241da177e4SLinus Torvalds 5251d399ae5SAndre Guedes static void create_le_conn_complete(struct hci_dev *hdev, u8 status) 5261d399ae5SAndre Guedes { 5271d399ae5SAndre Guedes struct hci_conn *conn; 5281d399ae5SAndre Guedes 5291d399ae5SAndre Guedes if (status == 0) 5301d399ae5SAndre Guedes return; 5311d399ae5SAndre Guedes 5321d399ae5SAndre Guedes BT_ERR("HCI request failed to create LE connection: status 0x%2.2x", 5331d399ae5SAndre Guedes status); 5341d399ae5SAndre Guedes 5351d399ae5SAndre Guedes hci_dev_lock(hdev); 5361d399ae5SAndre Guedes 5371d399ae5SAndre Guedes conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); 5381d399ae5SAndre Guedes if (!conn) 5391d399ae5SAndre Guedes goto done; 5401d399ae5SAndre Guedes 5411d399ae5SAndre Guedes conn->state = BT_CLOSED; 5421d399ae5SAndre Guedes 5431d399ae5SAndre Guedes mgmt_connect_failed(hdev, &conn->dst, conn->type, conn->dst_type, 5441d399ae5SAndre Guedes status); 5451d399ae5SAndre Guedes 5461d399ae5SAndre Guedes hci_proto_connect_cfm(conn, status); 5471d399ae5SAndre Guedes 5481d399ae5SAndre Guedes hci_conn_del(conn); 5491d399ae5SAndre Guedes 5501d399ae5SAndre Guedes done: 5511d399ae5SAndre Guedes hci_dev_unlock(hdev); 5521d399ae5SAndre Guedes } 5531d399ae5SAndre Guedes 5541d399ae5SAndre Guedes static int hci_create_le_conn(struct hci_conn *conn) 5551d399ae5SAndre Guedes { 5561d399ae5SAndre Guedes struct hci_dev *hdev = conn->hdev; 5571d399ae5SAndre Guedes struct hci_cp_le_create_conn cp; 5581d399ae5SAndre Guedes struct hci_request req; 5591d399ae5SAndre Guedes int err; 5601d399ae5SAndre Guedes 5611d399ae5SAndre Guedes hci_req_init(&req, hdev); 5621d399ae5SAndre Guedes 5631d399ae5SAndre Guedes memset(&cp, 0, sizeof(cp)); 5641d399ae5SAndre Guedes cp.scan_interval = __constant_cpu_to_le16(0x0060); 5651d399ae5SAndre Guedes cp.scan_window = __constant_cpu_to_le16(0x0030); 5661d399ae5SAndre Guedes bacpy(&cp.peer_addr, &conn->dst); 5671d399ae5SAndre Guedes cp.peer_addr_type = conn->dst_type; 5681d399ae5SAndre Guedes if (bacmp(&hdev->bdaddr, BDADDR_ANY)) 5691d399ae5SAndre Guedes cp.own_address_type = ADDR_LE_DEV_PUBLIC; 5701d399ae5SAndre Guedes else 5711d399ae5SAndre Guedes cp.own_address_type = ADDR_LE_DEV_RANDOM; 5721d399ae5SAndre Guedes cp.conn_interval_min = __constant_cpu_to_le16(0x0028); 5731d399ae5SAndre Guedes cp.conn_interval_max = __constant_cpu_to_le16(0x0038); 5741d399ae5SAndre Guedes cp.supervision_timeout = __constant_cpu_to_le16(0x002a); 5751d399ae5SAndre Guedes cp.min_ce_len = __constant_cpu_to_le16(0x0000); 5761d399ae5SAndre Guedes cp.max_ce_len = __constant_cpu_to_le16(0x0000); 5771d399ae5SAndre Guedes hci_req_add(&req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp); 5781d399ae5SAndre Guedes 5791d399ae5SAndre Guedes err = hci_req_run(&req, create_le_conn_complete); 5801d399ae5SAndre Guedes if (err) { 5811d399ae5SAndre Guedes hci_conn_del(conn); 5821d399ae5SAndre Guedes return err; 5831d399ae5SAndre Guedes } 5841d399ae5SAndre Guedes 5851d399ae5SAndre Guedes return 0; 5861d399ae5SAndre Guedes } 5871d399ae5SAndre Guedes 588d04aef4cSVinicius Costa Gomes static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, 589d04aef4cSVinicius Costa Gomes u8 dst_type, u8 sec_level, u8 auth_type) 5901da177e4SLinus Torvalds { 591f1e5d547SAndre Guedes struct hci_conn *conn; 5921d399ae5SAndre Guedes int err; 5931da177e4SLinus Torvalds 594f3d3444aSJohan Hedberg if (test_bit(HCI_ADVERTISING, &hdev->flags)) 595f1550478SJohan Hedberg return ERR_PTR(-ENOTSUPP); 596f1550478SJohan Hedberg 597*620ad521SAndre Guedes /* Some devices send ATT messages as soon as the physical link is 598*620ad521SAndre Guedes * established. To be able to handle these ATT messages, the user- 599*620ad521SAndre Guedes * space first establishes the connection and then starts the pairing 600*620ad521SAndre Guedes * process. 601*620ad521SAndre Guedes * 602*620ad521SAndre Guedes * So if a hci_conn object already exists for the following connection 603*620ad521SAndre Guedes * attempt, we simply update pending_sec_level and auth_type fields 604*620ad521SAndre Guedes * and return the object found. 605*620ad521SAndre Guedes */ 606f1e5d547SAndre Guedes conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst); 607*620ad521SAndre Guedes if (conn) { 608*620ad521SAndre Guedes conn->pending_sec_level = sec_level; 609*620ad521SAndre Guedes conn->auth_type = auth_type; 610*620ad521SAndre Guedes goto done; 611*620ad521SAndre Guedes } 612*620ad521SAndre Guedes 613*620ad521SAndre Guedes /* Since the controller supports only one LE connection attempt at a 614*620ad521SAndre Guedes * time, we return -EBUSY if there is any connection attempt running. 615*620ad521SAndre Guedes */ 616f1e5d547SAndre Guedes conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); 617f1e5d547SAndre Guedes if (conn) 618dfc94dbdSAndrzej Kaczmarek return ERR_PTR(-EBUSY); 619dfc94dbdSAndrzej Kaczmarek 620f1e5d547SAndre Guedes conn = hci_conn_add(hdev, LE_LINK, dst); 621f1e5d547SAndre Guedes if (!conn) 62230e76272SVille Tervo return ERR_PTR(-ENOMEM); 623893d6751SAndre Guedes 624f1e5d547SAndre Guedes conn->dst_type = bdaddr_to_le(dst_type); 62546a190cbSAndre Guedes conn->state = BT_CONNECT; 62646a190cbSAndre Guedes conn->out = true; 62746a190cbSAndre Guedes conn->link_mode |= HCI_LM_MASTER; 62846a190cbSAndre Guedes conn->sec_level = BT_SECURITY_LOW; 629*620ad521SAndre Guedes conn->pending_sec_level = sec_level; 630*620ad521SAndre Guedes conn->auth_type = auth_type; 63146a190cbSAndre Guedes 6321d399ae5SAndre Guedes err = hci_create_le_conn(conn); 6331d399ae5SAndre Guedes if (err) 6341d399ae5SAndre Guedes return ERR_PTR(err); 6359f0caeb1SVinicius Costa Gomes 636*620ad521SAndre Guedes done: 637f1e5d547SAndre Guedes hci_conn_hold(conn); 638f1e5d547SAndre Guedes return conn; 639fcd89c09SVille Tervo } 640fcd89c09SVille Tervo 641db474275SVinicius Costa Gomes static struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, 642db474275SVinicius Costa Gomes u8 sec_level, u8 auth_type) 643d04aef4cSVinicius Costa Gomes { 644d04aef4cSVinicius Costa Gomes struct hci_conn *acl; 645d04aef4cSVinicius Costa Gomes 64656f87901SJohan Hedberg if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) 64756f87901SJohan Hedberg return ERR_PTR(-ENOTSUPP); 64856f87901SJohan Hedberg 64970f23020SAndrei Emeltchenko acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst); 65070f23020SAndrei Emeltchenko if (!acl) { 65170f23020SAndrei Emeltchenko acl = hci_conn_add(hdev, ACL_LINK, dst); 65270f23020SAndrei Emeltchenko if (!acl) 65348c7aba9SJohan Hedberg return ERR_PTR(-ENOMEM); 6541da177e4SLinus Torvalds } 6551da177e4SLinus Torvalds 6561da177e4SLinus Torvalds hci_conn_hold(acl); 6571da177e4SLinus Torvalds 65809ab6f4cSMarcel Holtmann if (acl->state == BT_OPEN || acl->state == BT_CLOSED) { 659765c2a96SJohan Hedberg acl->sec_level = BT_SECURITY_LOW; 660765c2a96SJohan Hedberg acl->pending_sec_level = sec_level; 66109ab6f4cSMarcel Holtmann acl->auth_type = auth_type; 6621aef8669SVinicius Costa Gomes hci_acl_create_connection(acl); 66309ab6f4cSMarcel Holtmann } 6641da177e4SLinus Torvalds 665db474275SVinicius Costa Gomes return acl; 666db474275SVinicius Costa Gomes } 667db474275SVinicius Costa Gomes 66810c62ddcSFrédéric Dalleau struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst, 66910c62ddcSFrédéric Dalleau __u16 setting) 670db474275SVinicius Costa Gomes { 671db474275SVinicius Costa Gomes struct hci_conn *acl; 672db474275SVinicius Costa Gomes struct hci_conn *sco; 673db474275SVinicius Costa Gomes 674e660ed6cSFrédéric Dalleau acl = hci_connect_acl(hdev, dst, BT_SECURITY_LOW, HCI_AT_NO_BONDING); 675db474275SVinicius Costa Gomes if (IS_ERR(acl)) 6765b7f9909SMarcel Holtmann return acl; 6771da177e4SLinus Torvalds 67870f23020SAndrei Emeltchenko sco = hci_conn_hash_lookup_ba(hdev, type, dst); 67970f23020SAndrei Emeltchenko if (!sco) { 68070f23020SAndrei Emeltchenko sco = hci_conn_add(hdev, type, dst); 68170f23020SAndrei Emeltchenko if (!sco) { 68276a68ba0SDavid Herrmann hci_conn_drop(acl); 68348c7aba9SJohan Hedberg return ERR_PTR(-ENOMEM); 6841da177e4SLinus Torvalds } 6851da177e4SLinus Torvalds } 6865b7f9909SMarcel Holtmann 6871da177e4SLinus Torvalds acl->link = sco; 6881da177e4SLinus Torvalds sco->link = acl; 6891da177e4SLinus Torvalds 6901da177e4SLinus Torvalds hci_conn_hold(sco); 6911da177e4SLinus Torvalds 69210c62ddcSFrédéric Dalleau sco->setting = setting; 69310c62ddcSFrédéric Dalleau 6941da177e4SLinus Torvalds if (acl->state == BT_CONNECTED && 695b6a0dc82SMarcel Holtmann (sco->state == BT_OPEN || sco->state == BT_CLOSED)) { 69658a681efSJohan Hedberg set_bit(HCI_CONN_POWER_SAVE, &acl->flags); 69714b12d0bSJaikumar Ganesh hci_conn_enter_active_mode(acl, BT_POWER_FORCE_ACTIVE_ON); 698c390216bSNick Pelly 69951a8efd7SJohan Hedberg if (test_bit(HCI_CONN_MODE_CHANGE_PEND, &acl->flags)) { 700e73439d8SMarcel Holtmann /* defer SCO setup until mode change completed */ 70151a8efd7SJohan Hedberg set_bit(HCI_CONN_SCO_SETUP_PEND, &acl->flags); 702e73439d8SMarcel Holtmann return sco; 703e73439d8SMarcel Holtmann } 704e73439d8SMarcel Holtmann 705e73439d8SMarcel Holtmann hci_sco_setup(acl, 0x00); 706b6a0dc82SMarcel Holtmann } 7071da177e4SLinus Torvalds 7081da177e4SLinus Torvalds return sco; 7091da177e4SLinus Torvalds } 7101da177e4SLinus Torvalds 711b7d839bfSVinicius Costa Gomes /* Create SCO, ACL or LE connection. */ 712b7d839bfSVinicius Costa Gomes struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, 713b7d839bfSVinicius Costa Gomes __u8 dst_type, __u8 sec_level, __u8 auth_type) 714b7d839bfSVinicius Costa Gomes { 7156ed93dc6SAndrei Emeltchenko BT_DBG("%s dst %pMR type 0x%x", hdev->name, dst, type); 716b7d839bfSVinicius Costa Gomes 7174cd2d983SVinicius Costa Gomes switch (type) { 7184cd2d983SVinicius Costa Gomes case LE_LINK: 719b7d839bfSVinicius Costa Gomes return hci_connect_le(hdev, dst, dst_type, sec_level, auth_type); 7204cd2d983SVinicius Costa Gomes case ACL_LINK: 721b7d839bfSVinicius Costa Gomes return hci_connect_acl(hdev, dst, sec_level, auth_type); 722b7d839bfSVinicius Costa Gomes } 723b7d839bfSVinicius Costa Gomes 7244cd2d983SVinicius Costa Gomes return ERR_PTR(-EINVAL); 7254cd2d983SVinicius Costa Gomes } 7264cd2d983SVinicius Costa Gomes 727e7c29cb1SMarcel Holtmann /* Check link security requirement */ 728e7c29cb1SMarcel Holtmann int hci_conn_check_link_mode(struct hci_conn *conn) 729e7c29cb1SMarcel Holtmann { 73038b3fef1SAndrei Emeltchenko BT_DBG("hcon %p", conn); 731e7c29cb1SMarcel Holtmann 732aa64a8b5SJohan Hedberg if (hci_conn_ssp_enabled(conn) && !(conn->link_mode & HCI_LM_ENCRYPT)) 733e7c29cb1SMarcel Holtmann return 0; 734e7c29cb1SMarcel Holtmann 735e7c29cb1SMarcel Holtmann return 1; 736e7c29cb1SMarcel Holtmann } 737e7c29cb1SMarcel Holtmann 7381da177e4SLinus Torvalds /* Authenticate remote device */ 7390684e5f9SMarcel Holtmann static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) 7401da177e4SLinus Torvalds { 74138b3fef1SAndrei Emeltchenko BT_DBG("hcon %p", conn); 7421da177e4SLinus Torvalds 743765c2a96SJohan Hedberg if (conn->pending_sec_level > sec_level) 744765c2a96SJohan Hedberg sec_level = conn->pending_sec_level; 745765c2a96SJohan Hedberg 74696a31833SMarcel Holtmann if (sec_level > conn->sec_level) 747765c2a96SJohan Hedberg conn->pending_sec_level = sec_level; 74896a31833SMarcel Holtmann else if (conn->link_mode & HCI_LM_AUTH) 7491da177e4SLinus Torvalds return 1; 7501da177e4SLinus Torvalds 75165cf686eSJohan Hedberg /* Make sure we preserve an existing MITM requirement*/ 75265cf686eSJohan Hedberg auth_type |= (conn->auth_type & 0x01); 75365cf686eSJohan Hedberg 75496a31833SMarcel Holtmann conn->auth_type = auth_type; 75596a31833SMarcel Holtmann 75651a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 7571da177e4SLinus Torvalds struct hci_cp_auth_requested cp; 758b7d05badSPeter Hurley 759b7d05badSPeter Hurley /* encrypt must be pending if auth is also pending */ 760b7d05badSPeter Hurley set_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); 761b7d05badSPeter Hurley 762aca3192cSYOSHIFUJI Hideaki cp.handle = cpu_to_le16(conn->handle); 76340be492fSMarcel Holtmann hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED, 76440be492fSMarcel Holtmann sizeof(cp), &cp); 76519f8def0SWaldemar Rymarkiewicz if (conn->key_type != 0xff) 76651a8efd7SJohan Hedberg set_bit(HCI_CONN_REAUTH_PEND, &conn->flags); 7671da177e4SLinus Torvalds } 7688c1b2355SMarcel Holtmann 7691da177e4SLinus Torvalds return 0; 7701da177e4SLinus Torvalds } 7711da177e4SLinus Torvalds 77213d39315SWaldemar Rymarkiewicz /* Encrypt the the link */ 77313d39315SWaldemar Rymarkiewicz static void hci_conn_encrypt(struct hci_conn *conn) 77413d39315SWaldemar Rymarkiewicz { 77538b3fef1SAndrei Emeltchenko BT_DBG("hcon %p", conn); 77613d39315SWaldemar Rymarkiewicz 77751a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) { 77813d39315SWaldemar Rymarkiewicz struct hci_cp_set_conn_encrypt cp; 77913d39315SWaldemar Rymarkiewicz cp.handle = cpu_to_le16(conn->handle); 78013d39315SWaldemar Rymarkiewicz cp.encrypt = 0x01; 78113d39315SWaldemar Rymarkiewicz hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), 78213d39315SWaldemar Rymarkiewicz &cp); 78313d39315SWaldemar Rymarkiewicz } 78413d39315SWaldemar Rymarkiewicz } 78513d39315SWaldemar Rymarkiewicz 7868c1b2355SMarcel Holtmann /* Enable security */ 7870684e5f9SMarcel Holtmann int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) 7881da177e4SLinus Torvalds { 78938b3fef1SAndrei Emeltchenko BT_DBG("hcon %p", conn); 7901da177e4SLinus Torvalds 791d8343f12SVinicius Costa Gomes if (conn->type == LE_LINK) 792d8343f12SVinicius Costa Gomes return smp_conn_security(conn, sec_level); 793d8343f12SVinicius Costa Gomes 79413d39315SWaldemar Rymarkiewicz /* For sdp we don't need the link key. */ 7958c1b2355SMarcel Holtmann if (sec_level == BT_SECURITY_SDP) 7968c1b2355SMarcel Holtmann return 1; 7978c1b2355SMarcel Holtmann 79813d39315SWaldemar Rymarkiewicz /* For non 2.1 devices and low security level we don't need the link 79913d39315SWaldemar Rymarkiewicz key. */ 800aa64a8b5SJohan Hedberg if (sec_level == BT_SECURITY_LOW && !hci_conn_ssp_enabled(conn)) 8018c1b2355SMarcel Holtmann return 1; 8028c1b2355SMarcel Holtmann 80313d39315SWaldemar Rymarkiewicz /* For other security levels we need the link key. */ 80413d39315SWaldemar Rymarkiewicz if (!(conn->link_mode & HCI_LM_AUTH)) 80513d39315SWaldemar Rymarkiewicz goto auth; 8061da177e4SLinus Torvalds 80713d39315SWaldemar Rymarkiewicz /* An authenticated combination key has sufficient security for any 80813d39315SWaldemar Rymarkiewicz security level. */ 80913d39315SWaldemar Rymarkiewicz if (conn->key_type == HCI_LK_AUTH_COMBINATION) 81013d39315SWaldemar Rymarkiewicz goto encrypt; 81113d39315SWaldemar Rymarkiewicz 81213d39315SWaldemar Rymarkiewicz /* An unauthenticated combination key has sufficient security for 81313d39315SWaldemar Rymarkiewicz security level 1 and 2. */ 81413d39315SWaldemar Rymarkiewicz if (conn->key_type == HCI_LK_UNAUTH_COMBINATION && 8155974e4c4SGustavo Padovan (sec_level == BT_SECURITY_MEDIUM || sec_level == BT_SECURITY_LOW)) 81613d39315SWaldemar Rymarkiewicz goto encrypt; 81713d39315SWaldemar Rymarkiewicz 81813d39315SWaldemar Rymarkiewicz /* A combination key has always sufficient security for the security 81913d39315SWaldemar Rymarkiewicz levels 1 or 2. High security level requires the combination key 82013d39315SWaldemar Rymarkiewicz is generated using maximum PIN code length (16). 82113d39315SWaldemar Rymarkiewicz For pre 2.1 units. */ 82213d39315SWaldemar Rymarkiewicz if (conn->key_type == HCI_LK_COMBINATION && 8235974e4c4SGustavo Padovan (sec_level != BT_SECURITY_HIGH || conn->pin_length == 16)) 82413d39315SWaldemar Rymarkiewicz goto encrypt; 82513d39315SWaldemar Rymarkiewicz 82613d39315SWaldemar Rymarkiewicz auth: 82751a8efd7SJohan Hedberg if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) 8281da177e4SLinus Torvalds return 0; 8291da177e4SLinus Torvalds 8306fdf658cSLuiz Augusto von Dentz if (!hci_conn_auth(conn, sec_level, auth_type)) 83113d39315SWaldemar Rymarkiewicz return 0; 8328c1b2355SMarcel Holtmann 83313d39315SWaldemar Rymarkiewicz encrypt: 83413d39315SWaldemar Rymarkiewicz if (conn->link_mode & HCI_LM_ENCRYPT) 83513d39315SWaldemar Rymarkiewicz return 1; 83613d39315SWaldemar Rymarkiewicz 83713d39315SWaldemar Rymarkiewicz hci_conn_encrypt(conn); 8381da177e4SLinus Torvalds return 0; 8391da177e4SLinus Torvalds } 8408c1b2355SMarcel Holtmann EXPORT_SYMBOL(hci_conn_security); 8411da177e4SLinus Torvalds 842b3b1b061SWaldemar Rymarkiewicz /* Check secure link requirement */ 843b3b1b061SWaldemar Rymarkiewicz int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level) 844b3b1b061SWaldemar Rymarkiewicz { 84538b3fef1SAndrei Emeltchenko BT_DBG("hcon %p", conn); 846b3b1b061SWaldemar Rymarkiewicz 847b3b1b061SWaldemar Rymarkiewicz if (sec_level != BT_SECURITY_HIGH) 848b3b1b061SWaldemar Rymarkiewicz return 1; /* Accept if non-secure is required */ 849b3b1b061SWaldemar Rymarkiewicz 850ef4177e2SWaldemar Rymarkiewicz if (conn->sec_level == BT_SECURITY_HIGH) 851b3b1b061SWaldemar Rymarkiewicz return 1; 852b3b1b061SWaldemar Rymarkiewicz 853b3b1b061SWaldemar Rymarkiewicz return 0; /* Reject not secure link */ 854b3b1b061SWaldemar Rymarkiewicz } 855b3b1b061SWaldemar Rymarkiewicz EXPORT_SYMBOL(hci_conn_check_secure); 856b3b1b061SWaldemar Rymarkiewicz 8571da177e4SLinus Torvalds /* Change link key */ 8581da177e4SLinus Torvalds int hci_conn_change_link_key(struct hci_conn *conn) 8591da177e4SLinus Torvalds { 86038b3fef1SAndrei Emeltchenko BT_DBG("hcon %p", conn); 8611da177e4SLinus Torvalds 86251a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { 8631da177e4SLinus Torvalds struct hci_cp_change_conn_link_key cp; 864aca3192cSYOSHIFUJI Hideaki cp.handle = cpu_to_le16(conn->handle); 86540be492fSMarcel Holtmann hci_send_cmd(conn->hdev, HCI_OP_CHANGE_CONN_LINK_KEY, 86640be492fSMarcel Holtmann sizeof(cp), &cp); 8671da177e4SLinus Torvalds } 8688c1b2355SMarcel Holtmann 8691da177e4SLinus Torvalds return 0; 8701da177e4SLinus Torvalds } 8711da177e4SLinus Torvalds 8721da177e4SLinus Torvalds /* Switch role */ 8738c1b2355SMarcel Holtmann int hci_conn_switch_role(struct hci_conn *conn, __u8 role) 8741da177e4SLinus Torvalds { 87538b3fef1SAndrei Emeltchenko BT_DBG("hcon %p", conn); 8761da177e4SLinus Torvalds 8771da177e4SLinus Torvalds if (!role && conn->link_mode & HCI_LM_MASTER) 8781da177e4SLinus Torvalds return 1; 8791da177e4SLinus Torvalds 88051a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_RSWITCH_PEND, &conn->flags)) { 8811da177e4SLinus Torvalds struct hci_cp_switch_role cp; 8821da177e4SLinus Torvalds bacpy(&cp.bdaddr, &conn->dst); 8831da177e4SLinus Torvalds cp.role = role; 884a9de9248SMarcel Holtmann hci_send_cmd(conn->hdev, HCI_OP_SWITCH_ROLE, sizeof(cp), &cp); 8851da177e4SLinus Torvalds } 8868c1b2355SMarcel Holtmann 8871da177e4SLinus Torvalds return 0; 8881da177e4SLinus Torvalds } 8891da177e4SLinus Torvalds EXPORT_SYMBOL(hci_conn_switch_role); 8901da177e4SLinus Torvalds 89104837f64SMarcel Holtmann /* Enter active mode */ 89214b12d0bSJaikumar Ganesh void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active) 89304837f64SMarcel Holtmann { 89404837f64SMarcel Holtmann struct hci_dev *hdev = conn->hdev; 89504837f64SMarcel Holtmann 89638b3fef1SAndrei Emeltchenko BT_DBG("hcon %p mode %d", conn, conn->mode); 89704837f64SMarcel Holtmann 89804837f64SMarcel Holtmann if (test_bit(HCI_RAW, &hdev->flags)) 89904837f64SMarcel Holtmann return; 90004837f64SMarcel Holtmann 90114b12d0bSJaikumar Ganesh if (conn->mode != HCI_CM_SNIFF) 90214b12d0bSJaikumar Ganesh goto timer; 90314b12d0bSJaikumar Ganesh 90458a681efSJohan Hedberg if (!test_bit(HCI_CONN_POWER_SAVE, &conn->flags) && !force_active) 90504837f64SMarcel Holtmann goto timer; 90604837f64SMarcel Holtmann 90751a8efd7SJohan Hedberg if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) { 90804837f64SMarcel Holtmann struct hci_cp_exit_sniff_mode cp; 909aca3192cSYOSHIFUJI Hideaki cp.handle = cpu_to_le16(conn->handle); 910a9de9248SMarcel Holtmann hci_send_cmd(hdev, HCI_OP_EXIT_SNIFF_MODE, sizeof(cp), &cp); 91104837f64SMarcel Holtmann } 91204837f64SMarcel Holtmann 91304837f64SMarcel Holtmann timer: 91404837f64SMarcel Holtmann if (hdev->idle_timeout > 0) 91504837f64SMarcel Holtmann mod_timer(&conn->idle_timer, 91604837f64SMarcel Holtmann jiffies + msecs_to_jiffies(hdev->idle_timeout)); 91704837f64SMarcel Holtmann } 91804837f64SMarcel Holtmann 9191da177e4SLinus Torvalds /* Drop all connection on the device */ 9201da177e4SLinus Torvalds void hci_conn_hash_flush(struct hci_dev *hdev) 9211da177e4SLinus Torvalds { 9221da177e4SLinus Torvalds struct hci_conn_hash *h = &hdev->conn_hash; 9233c4e0df0SAndrei Emeltchenko struct hci_conn *c, *n; 9241da177e4SLinus Torvalds 9251da177e4SLinus Torvalds BT_DBG("hdev %s", hdev->name); 9261da177e4SLinus Torvalds 9273c4e0df0SAndrei Emeltchenko list_for_each_entry_safe(c, n, &h->list, list) { 9281da177e4SLinus Torvalds c->state = BT_CLOSED; 9291da177e4SLinus Torvalds 9309f5a0d7bSAndrei Emeltchenko hci_proto_disconn_cfm(c, HCI_ERROR_LOCAL_HOST_TERM); 9311da177e4SLinus Torvalds hci_conn_del(c); 9321da177e4SLinus Torvalds } 9331da177e4SLinus Torvalds } 9341da177e4SLinus Torvalds 935a9de9248SMarcel Holtmann /* Check pending connect attempts */ 936a9de9248SMarcel Holtmann void hci_conn_check_pending(struct hci_dev *hdev) 937a9de9248SMarcel Holtmann { 938a9de9248SMarcel Holtmann struct hci_conn *conn; 939a9de9248SMarcel Holtmann 940a9de9248SMarcel Holtmann BT_DBG("hdev %s", hdev->name); 941a9de9248SMarcel Holtmann 942a9de9248SMarcel Holtmann hci_dev_lock(hdev); 943a9de9248SMarcel Holtmann 944a9de9248SMarcel Holtmann conn = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2); 945a9de9248SMarcel Holtmann if (conn) 9461aef8669SVinicius Costa Gomes hci_acl_create_connection(conn); 947a9de9248SMarcel Holtmann 948a9de9248SMarcel Holtmann hci_dev_unlock(hdev); 949a9de9248SMarcel Holtmann } 950a9de9248SMarcel Holtmann 9511da177e4SLinus Torvalds int hci_get_conn_list(void __user *arg) 9521da177e4SLinus Torvalds { 953fc5fef61SGustavo Padovan struct hci_conn *c; 9541da177e4SLinus Torvalds struct hci_conn_list_req req, *cl; 9551da177e4SLinus Torvalds struct hci_conn_info *ci; 9561da177e4SLinus Torvalds struct hci_dev *hdev; 9571da177e4SLinus Torvalds int n = 0, size, err; 9581da177e4SLinus Torvalds 9591da177e4SLinus Torvalds if (copy_from_user(&req, arg, sizeof(req))) 9601da177e4SLinus Torvalds return -EFAULT; 9611da177e4SLinus Torvalds 9621da177e4SLinus Torvalds if (!req.conn_num || req.conn_num > (PAGE_SIZE * 2) / sizeof(*ci)) 9631da177e4SLinus Torvalds return -EINVAL; 9641da177e4SLinus Torvalds 9651da177e4SLinus Torvalds size = sizeof(req) + req.conn_num * sizeof(*ci); 9661da177e4SLinus Torvalds 96770f23020SAndrei Emeltchenko cl = kmalloc(size, GFP_KERNEL); 96870f23020SAndrei Emeltchenko if (!cl) 9691da177e4SLinus Torvalds return -ENOMEM; 9701da177e4SLinus Torvalds 97170f23020SAndrei Emeltchenko hdev = hci_dev_get(req.dev_id); 97270f23020SAndrei Emeltchenko if (!hdev) { 9731da177e4SLinus Torvalds kfree(cl); 9741da177e4SLinus Torvalds return -ENODEV; 9751da177e4SLinus Torvalds } 9761da177e4SLinus Torvalds 9771da177e4SLinus Torvalds ci = cl->conn_info; 9781da177e4SLinus Torvalds 97909fd0de5SGustavo F. Padovan hci_dev_lock(hdev); 9808035ded4SLuiz Augusto von Dentz list_for_each_entry(c, &hdev->conn_hash.list, list) { 9811da177e4SLinus Torvalds bacpy(&(ci + n)->bdaddr, &c->dst); 9821da177e4SLinus Torvalds (ci + n)->handle = c->handle; 9831da177e4SLinus Torvalds (ci + n)->type = c->type; 9841da177e4SLinus Torvalds (ci + n)->out = c->out; 9851da177e4SLinus Torvalds (ci + n)->state = c->state; 9861da177e4SLinus Torvalds (ci + n)->link_mode = c->link_mode; 9871da177e4SLinus Torvalds if (++n >= req.conn_num) 9881da177e4SLinus Torvalds break; 9891da177e4SLinus Torvalds } 99009fd0de5SGustavo F. Padovan hci_dev_unlock(hdev); 9911da177e4SLinus Torvalds 9921da177e4SLinus Torvalds cl->dev_id = hdev->id; 9931da177e4SLinus Torvalds cl->conn_num = n; 9941da177e4SLinus Torvalds size = sizeof(req) + n * sizeof(*ci); 9951da177e4SLinus Torvalds 9961da177e4SLinus Torvalds hci_dev_put(hdev); 9971da177e4SLinus Torvalds 9981da177e4SLinus Torvalds err = copy_to_user(arg, cl, size); 9991da177e4SLinus Torvalds kfree(cl); 10001da177e4SLinus Torvalds 10011da177e4SLinus Torvalds return err ? -EFAULT : 0; 10021da177e4SLinus Torvalds } 10031da177e4SLinus Torvalds 10041da177e4SLinus Torvalds int hci_get_conn_info(struct hci_dev *hdev, void __user *arg) 10051da177e4SLinus Torvalds { 10061da177e4SLinus Torvalds struct hci_conn_info_req req; 10071da177e4SLinus Torvalds struct hci_conn_info ci; 10081da177e4SLinus Torvalds struct hci_conn *conn; 10091da177e4SLinus Torvalds char __user *ptr = arg + sizeof(req); 10101da177e4SLinus Torvalds 10111da177e4SLinus Torvalds if (copy_from_user(&req, arg, sizeof(req))) 10121da177e4SLinus Torvalds return -EFAULT; 10131da177e4SLinus Torvalds 101409fd0de5SGustavo F. Padovan hci_dev_lock(hdev); 10151da177e4SLinus Torvalds conn = hci_conn_hash_lookup_ba(hdev, req.type, &req.bdaddr); 10161da177e4SLinus Torvalds if (conn) { 10171da177e4SLinus Torvalds bacpy(&ci.bdaddr, &conn->dst); 10181da177e4SLinus Torvalds ci.handle = conn->handle; 10191da177e4SLinus Torvalds ci.type = conn->type; 10201da177e4SLinus Torvalds ci.out = conn->out; 10211da177e4SLinus Torvalds ci.state = conn->state; 10221da177e4SLinus Torvalds ci.link_mode = conn->link_mode; 10231da177e4SLinus Torvalds } 102409fd0de5SGustavo F. Padovan hci_dev_unlock(hdev); 10251da177e4SLinus Torvalds 10261da177e4SLinus Torvalds if (!conn) 10271da177e4SLinus Torvalds return -ENOENT; 10281da177e4SLinus Torvalds 10291da177e4SLinus Torvalds return copy_to_user(ptr, &ci, sizeof(ci)) ? -EFAULT : 0; 10301da177e4SLinus Torvalds } 103140be492fSMarcel Holtmann 103240be492fSMarcel Holtmann int hci_get_auth_info(struct hci_dev *hdev, void __user *arg) 103340be492fSMarcel Holtmann { 103440be492fSMarcel Holtmann struct hci_auth_info_req req; 103540be492fSMarcel Holtmann struct hci_conn *conn; 103640be492fSMarcel Holtmann 103740be492fSMarcel Holtmann if (copy_from_user(&req, arg, sizeof(req))) 103840be492fSMarcel Holtmann return -EFAULT; 103940be492fSMarcel Holtmann 104009fd0de5SGustavo F. Padovan hci_dev_lock(hdev); 104140be492fSMarcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &req.bdaddr); 104240be492fSMarcel Holtmann if (conn) 104340be492fSMarcel Holtmann req.type = conn->auth_type; 104409fd0de5SGustavo F. Padovan hci_dev_unlock(hdev); 104540be492fSMarcel Holtmann 104640be492fSMarcel Holtmann if (!conn) 104740be492fSMarcel Holtmann return -ENOENT; 104840be492fSMarcel Holtmann 104940be492fSMarcel Holtmann return copy_to_user(arg, &req, sizeof(req)) ? -EFAULT : 0; 105040be492fSMarcel Holtmann } 105173d80debSLuiz Augusto von Dentz 105273d80debSLuiz Augusto von Dentz struct hci_chan *hci_chan_create(struct hci_conn *conn) 105373d80debSLuiz Augusto von Dentz { 105473d80debSLuiz Augusto von Dentz struct hci_dev *hdev = conn->hdev; 105573d80debSLuiz Augusto von Dentz struct hci_chan *chan; 105673d80debSLuiz Augusto von Dentz 105738b3fef1SAndrei Emeltchenko BT_DBG("%s hcon %p", hdev->name, conn); 105873d80debSLuiz Augusto von Dentz 105975d7735cSAndre Guedes chan = kzalloc(sizeof(struct hci_chan), GFP_KERNEL); 106073d80debSLuiz Augusto von Dentz if (!chan) 106173d80debSLuiz Augusto von Dentz return NULL; 106273d80debSLuiz Augusto von Dentz 106373d80debSLuiz Augusto von Dentz chan->conn = conn; 106473d80debSLuiz Augusto von Dentz skb_queue_head_init(&chan->data_q); 1065168df8e5SMat Martineau chan->state = BT_CONNECTED; 106673d80debSLuiz Augusto von Dentz 10678192edefSGustavo F. Padovan list_add_rcu(&chan->list, &conn->chan_list); 106873d80debSLuiz Augusto von Dentz 106973d80debSLuiz Augusto von Dentz return chan; 107073d80debSLuiz Augusto von Dentz } 107173d80debSLuiz Augusto von Dentz 10729472007cSAndrei Emeltchenko void hci_chan_del(struct hci_chan *chan) 107373d80debSLuiz Augusto von Dentz { 107473d80debSLuiz Augusto von Dentz struct hci_conn *conn = chan->conn; 107573d80debSLuiz Augusto von Dentz struct hci_dev *hdev = conn->hdev; 107673d80debSLuiz Augusto von Dentz 107738b3fef1SAndrei Emeltchenko BT_DBG("%s hcon %p chan %p", hdev->name, conn, chan); 107873d80debSLuiz Augusto von Dentz 10798192edefSGustavo F. Padovan list_del_rcu(&chan->list); 10808192edefSGustavo F. Padovan 10818192edefSGustavo F. Padovan synchronize_rcu(); 108273d80debSLuiz Augusto von Dentz 108376a68ba0SDavid Herrmann hci_conn_drop(conn); 1084e9b02748SAndrei Emeltchenko 108573d80debSLuiz Augusto von Dentz skb_queue_purge(&chan->data_q); 108673d80debSLuiz Augusto von Dentz kfree(chan); 108773d80debSLuiz Augusto von Dentz } 108873d80debSLuiz Augusto von Dentz 10892c33c06aSGustavo F. Padovan void hci_chan_list_flush(struct hci_conn *conn) 109073d80debSLuiz Augusto von Dentz { 10912a5a5ec6SAndrei Emeltchenko struct hci_chan *chan, *n; 109273d80debSLuiz Augusto von Dentz 109338b3fef1SAndrei Emeltchenko BT_DBG("hcon %p", conn); 109473d80debSLuiz Augusto von Dentz 10952a5a5ec6SAndrei Emeltchenko list_for_each_entry_safe(chan, n, &conn->chan_list, list) 109673d80debSLuiz Augusto von Dentz hci_chan_del(chan); 109773d80debSLuiz Augusto von Dentz } 109842c4e53eSAndrei Emeltchenko 109942c4e53eSAndrei Emeltchenko static struct hci_chan *__hci_chan_lookup_handle(struct hci_conn *hcon, 110042c4e53eSAndrei Emeltchenko __u16 handle) 110142c4e53eSAndrei Emeltchenko { 110242c4e53eSAndrei Emeltchenko struct hci_chan *hchan; 110342c4e53eSAndrei Emeltchenko 110442c4e53eSAndrei Emeltchenko list_for_each_entry(hchan, &hcon->chan_list, list) { 110542c4e53eSAndrei Emeltchenko if (hchan->handle == handle) 110642c4e53eSAndrei Emeltchenko return hchan; 110742c4e53eSAndrei Emeltchenko } 110842c4e53eSAndrei Emeltchenko 110942c4e53eSAndrei Emeltchenko return NULL; 111042c4e53eSAndrei Emeltchenko } 111142c4e53eSAndrei Emeltchenko 111242c4e53eSAndrei Emeltchenko struct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle) 111342c4e53eSAndrei Emeltchenko { 111442c4e53eSAndrei Emeltchenko struct hci_conn_hash *h = &hdev->conn_hash; 111542c4e53eSAndrei Emeltchenko struct hci_conn *hcon; 111642c4e53eSAndrei Emeltchenko struct hci_chan *hchan = NULL; 111742c4e53eSAndrei Emeltchenko 111842c4e53eSAndrei Emeltchenko rcu_read_lock(); 111942c4e53eSAndrei Emeltchenko 112042c4e53eSAndrei Emeltchenko list_for_each_entry_rcu(hcon, &h->list, list) { 112142c4e53eSAndrei Emeltchenko hchan = __hci_chan_lookup_handle(hcon, handle); 112242c4e53eSAndrei Emeltchenko if (hchan) 112342c4e53eSAndrei Emeltchenko break; 112442c4e53eSAndrei Emeltchenko } 112542c4e53eSAndrei Emeltchenko 112642c4e53eSAndrei Emeltchenko rcu_read_unlock(); 112742c4e53eSAndrei Emeltchenko 112842c4e53eSAndrei Emeltchenko return hchan; 112942c4e53eSAndrei Emeltchenko } 1130