xref: /openbmc/linux/net/bluetooth/hci_conn.c (revision 620ad5219c0f0aa43731b2fd8fd9efac78c10deb)
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