162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci   BlueZ - Bluetooth protocol stack for Linux
362306a36Sopenharmony_ci   Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
462306a36Sopenharmony_ci   Copyright 2023 NXP
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci   Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci   This program is free software; you can redistribute it and/or modify
962306a36Sopenharmony_ci   it under the terms of the GNU General Public License version 2 as
1062306a36Sopenharmony_ci   published by the Free Software Foundation;
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1362306a36Sopenharmony_ci   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1462306a36Sopenharmony_ci   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
1562306a36Sopenharmony_ci   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
1662306a36Sopenharmony_ci   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
1762306a36Sopenharmony_ci   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1862306a36Sopenharmony_ci   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1962306a36Sopenharmony_ci   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
2262306a36Sopenharmony_ci   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
2362306a36Sopenharmony_ci   SOFTWARE IS DISCLAIMED.
2462306a36Sopenharmony_ci*/
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci/* Bluetooth HCI connection handling. */
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#include <linux/export.h>
2962306a36Sopenharmony_ci#include <linux/debugfs.h>
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#include <net/bluetooth/bluetooth.h>
3262306a36Sopenharmony_ci#include <net/bluetooth/hci_core.h>
3362306a36Sopenharmony_ci#include <net/bluetooth/l2cap.h>
3462306a36Sopenharmony_ci#include <net/bluetooth/iso.h>
3562306a36Sopenharmony_ci#include <net/bluetooth/mgmt.h>
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci#include "hci_request.h"
3862306a36Sopenharmony_ci#include "smp.h"
3962306a36Sopenharmony_ci#include "eir.h"
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_cistruct sco_param {
4262306a36Sopenharmony_ci	u16 pkt_type;
4362306a36Sopenharmony_ci	u16 max_latency;
4462306a36Sopenharmony_ci	u8  retrans_effort;
4562306a36Sopenharmony_ci};
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_cistruct conn_handle_t {
4862306a36Sopenharmony_ci	struct hci_conn *conn;
4962306a36Sopenharmony_ci	__u16 handle;
5062306a36Sopenharmony_ci};
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_cistatic const struct sco_param esco_param_cvsd[] = {
5362306a36Sopenharmony_ci	{ EDR_ESCO_MASK & ~ESCO_2EV3, 0x000a,	0x01 }, /* S3 */
5462306a36Sopenharmony_ci	{ EDR_ESCO_MASK & ~ESCO_2EV3, 0x0007,	0x01 }, /* S2 */
5562306a36Sopenharmony_ci	{ EDR_ESCO_MASK | ESCO_EV3,   0x0007,	0x01 }, /* S1 */
5662306a36Sopenharmony_ci	{ EDR_ESCO_MASK | ESCO_HV3,   0xffff,	0x01 }, /* D1 */
5762306a36Sopenharmony_ci	{ EDR_ESCO_MASK | ESCO_HV1,   0xffff,	0x01 }, /* D0 */
5862306a36Sopenharmony_ci};
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_cistatic const struct sco_param sco_param_cvsd[] = {
6162306a36Sopenharmony_ci	{ EDR_ESCO_MASK | ESCO_HV3,   0xffff,	0xff }, /* D1 */
6262306a36Sopenharmony_ci	{ EDR_ESCO_MASK | ESCO_HV1,   0xffff,	0xff }, /* D0 */
6362306a36Sopenharmony_ci};
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_cistatic const struct sco_param esco_param_msbc[] = {
6662306a36Sopenharmony_ci	{ EDR_ESCO_MASK & ~ESCO_2EV3, 0x000d,	0x02 }, /* T2 */
6762306a36Sopenharmony_ci	{ EDR_ESCO_MASK | ESCO_EV3,   0x0008,	0x02 }, /* T1 */
6862306a36Sopenharmony_ci};
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci/* This function requires the caller holds hdev->lock */
7162306a36Sopenharmony_cistatic void hci_connect_le_scan_cleanup(struct hci_conn *conn, u8 status)
7262306a36Sopenharmony_ci{
7362306a36Sopenharmony_ci	struct hci_conn_params *params;
7462306a36Sopenharmony_ci	struct hci_dev *hdev = conn->hdev;
7562306a36Sopenharmony_ci	struct smp_irk *irk;
7662306a36Sopenharmony_ci	bdaddr_t *bdaddr;
7762306a36Sopenharmony_ci	u8 bdaddr_type;
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	bdaddr = &conn->dst;
8062306a36Sopenharmony_ci	bdaddr_type = conn->dst_type;
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	/* Check if we need to convert to identity address */
8362306a36Sopenharmony_ci	irk = hci_get_irk(hdev, bdaddr, bdaddr_type);
8462306a36Sopenharmony_ci	if (irk) {
8562306a36Sopenharmony_ci		bdaddr = &irk->bdaddr;
8662306a36Sopenharmony_ci		bdaddr_type = irk->addr_type;
8762306a36Sopenharmony_ci	}
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	params = hci_pend_le_action_lookup(&hdev->pend_le_conns, bdaddr,
9062306a36Sopenharmony_ci					   bdaddr_type);
9162306a36Sopenharmony_ci	if (!params)
9262306a36Sopenharmony_ci		return;
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	if (params->conn) {
9562306a36Sopenharmony_ci		hci_conn_drop(params->conn);
9662306a36Sopenharmony_ci		hci_conn_put(params->conn);
9762306a36Sopenharmony_ci		params->conn = NULL;
9862306a36Sopenharmony_ci	}
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci	if (!params->explicit_connect)
10162306a36Sopenharmony_ci		return;
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	/* If the status indicates successful cancellation of
10462306a36Sopenharmony_ci	 * the attempt (i.e. Unknown Connection Id) there's no point of
10562306a36Sopenharmony_ci	 * notifying failure since we'll go back to keep trying to
10662306a36Sopenharmony_ci	 * connect. The only exception is explicit connect requests
10762306a36Sopenharmony_ci	 * where a timeout + cancel does indicate an actual failure.
10862306a36Sopenharmony_ci	 */
10962306a36Sopenharmony_ci	if (status && status != HCI_ERROR_UNKNOWN_CONN_ID)
11062306a36Sopenharmony_ci		mgmt_connect_failed(hdev, &conn->dst, conn->type,
11162306a36Sopenharmony_ci				    conn->dst_type, status);
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	/* The connection attempt was doing scan for new RPA, and is
11462306a36Sopenharmony_ci	 * in scan phase. If params are not associated with any other
11562306a36Sopenharmony_ci	 * autoconnect action, remove them completely. If they are, just unmark
11662306a36Sopenharmony_ci	 * them as waiting for connection, by clearing explicit_connect field.
11762306a36Sopenharmony_ci	 */
11862306a36Sopenharmony_ci	params->explicit_connect = false;
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	hci_pend_le_list_del_init(params);
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	switch (params->auto_connect) {
12362306a36Sopenharmony_ci	case HCI_AUTO_CONN_EXPLICIT:
12462306a36Sopenharmony_ci		hci_conn_params_del(hdev, bdaddr, bdaddr_type);
12562306a36Sopenharmony_ci		/* return instead of break to avoid duplicate scan update */
12662306a36Sopenharmony_ci		return;
12762306a36Sopenharmony_ci	case HCI_AUTO_CONN_DIRECT:
12862306a36Sopenharmony_ci	case HCI_AUTO_CONN_ALWAYS:
12962306a36Sopenharmony_ci		hci_pend_le_list_add(params, &hdev->pend_le_conns);
13062306a36Sopenharmony_ci		break;
13162306a36Sopenharmony_ci	case HCI_AUTO_CONN_REPORT:
13262306a36Sopenharmony_ci		hci_pend_le_list_add(params, &hdev->pend_le_reports);
13362306a36Sopenharmony_ci		break;
13462306a36Sopenharmony_ci	default:
13562306a36Sopenharmony_ci		break;
13662306a36Sopenharmony_ci	}
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	hci_update_passive_scan(hdev);
13962306a36Sopenharmony_ci}
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_cistatic void hci_conn_cleanup(struct hci_conn *conn)
14262306a36Sopenharmony_ci{
14362306a36Sopenharmony_ci	struct hci_dev *hdev = conn->hdev;
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	if (test_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags))
14662306a36Sopenharmony_ci		hci_conn_params_del(conn->hdev, &conn->dst, conn->dst_type);
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	if (test_and_clear_bit(HCI_CONN_FLUSH_KEY, &conn->flags))
14962306a36Sopenharmony_ci		hci_remove_link_key(hdev, &conn->dst);
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	hci_chan_list_flush(conn);
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	hci_conn_hash_del(hdev, conn);
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	if (HCI_CONN_HANDLE_UNSET(conn->handle))
15662306a36Sopenharmony_ci		ida_free(&hdev->unset_handle_ida, conn->handle);
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci	if (conn->cleanup)
15962306a36Sopenharmony_ci		conn->cleanup(conn);
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	if (conn->type == SCO_LINK || conn->type == ESCO_LINK) {
16262306a36Sopenharmony_ci		switch (conn->setting & SCO_AIRMODE_MASK) {
16362306a36Sopenharmony_ci		case SCO_AIRMODE_CVSD:
16462306a36Sopenharmony_ci		case SCO_AIRMODE_TRANSP:
16562306a36Sopenharmony_ci			if (hdev->notify)
16662306a36Sopenharmony_ci				hdev->notify(hdev, HCI_NOTIFY_DISABLE_SCO);
16762306a36Sopenharmony_ci			break;
16862306a36Sopenharmony_ci		}
16962306a36Sopenharmony_ci	} else {
17062306a36Sopenharmony_ci		if (hdev->notify)
17162306a36Sopenharmony_ci			hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
17262306a36Sopenharmony_ci	}
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	debugfs_remove_recursive(conn->debugfs);
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	hci_conn_del_sysfs(conn);
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci	hci_dev_put(hdev);
17962306a36Sopenharmony_ci}
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_cistatic void hci_acl_create_connection(struct hci_conn *conn)
18262306a36Sopenharmony_ci{
18362306a36Sopenharmony_ci	struct hci_dev *hdev = conn->hdev;
18462306a36Sopenharmony_ci	struct inquiry_entry *ie;
18562306a36Sopenharmony_ci	struct hci_cp_create_conn cp;
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	BT_DBG("hcon %p", conn);
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci	/* Many controllers disallow HCI Create Connection while it is doing
19062306a36Sopenharmony_ci	 * HCI Inquiry. So we cancel the Inquiry first before issuing HCI Create
19162306a36Sopenharmony_ci	 * Connection. This may cause the MGMT discovering state to become false
19262306a36Sopenharmony_ci	 * without user space's request but it is okay since the MGMT Discovery
19362306a36Sopenharmony_ci	 * APIs do not promise that discovery should be done forever. Instead,
19462306a36Sopenharmony_ci	 * the user space monitors the status of MGMT discovering and it may
19562306a36Sopenharmony_ci	 * request for discovery again when this flag becomes false.
19662306a36Sopenharmony_ci	 */
19762306a36Sopenharmony_ci	if (test_bit(HCI_INQUIRY, &hdev->flags)) {
19862306a36Sopenharmony_ci		/* Put this connection to "pending" state so that it will be
19962306a36Sopenharmony_ci		 * executed after the inquiry cancel command complete event.
20062306a36Sopenharmony_ci		 */
20162306a36Sopenharmony_ci		conn->state = BT_CONNECT2;
20262306a36Sopenharmony_ci		hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL);
20362306a36Sopenharmony_ci		return;
20462306a36Sopenharmony_ci	}
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	conn->state = BT_CONNECT;
20762306a36Sopenharmony_ci	conn->out = true;
20862306a36Sopenharmony_ci	conn->role = HCI_ROLE_MASTER;
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	conn->attempt++;
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	conn->link_policy = hdev->link_policy;
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	memset(&cp, 0, sizeof(cp));
21562306a36Sopenharmony_ci	bacpy(&cp.bdaddr, &conn->dst);
21662306a36Sopenharmony_ci	cp.pscan_rep_mode = 0x02;
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
21962306a36Sopenharmony_ci	if (ie) {
22062306a36Sopenharmony_ci		if (inquiry_entry_age(ie) <= INQUIRY_ENTRY_AGE_MAX) {
22162306a36Sopenharmony_ci			cp.pscan_rep_mode = ie->data.pscan_rep_mode;
22262306a36Sopenharmony_ci			cp.pscan_mode     = ie->data.pscan_mode;
22362306a36Sopenharmony_ci			cp.clock_offset   = ie->data.clock_offset |
22462306a36Sopenharmony_ci					    cpu_to_le16(0x8000);
22562306a36Sopenharmony_ci		}
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci		memcpy(conn->dev_class, ie->data.dev_class, 3);
22862306a36Sopenharmony_ci	}
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci	cp.pkt_type = cpu_to_le16(conn->pkt_type);
23162306a36Sopenharmony_ci	if (lmp_rswitch_capable(hdev) && !(hdev->link_mode & HCI_LM_MASTER))
23262306a36Sopenharmony_ci		cp.role_switch = 0x01;
23362306a36Sopenharmony_ci	else
23462306a36Sopenharmony_ci		cp.role_switch = 0x00;
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci	hci_send_cmd(hdev, HCI_OP_CREATE_CONN, sizeof(cp), &cp);
23762306a36Sopenharmony_ci}
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ciint hci_disconnect(struct hci_conn *conn, __u8 reason)
24062306a36Sopenharmony_ci{
24162306a36Sopenharmony_ci	BT_DBG("hcon %p", conn);
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	/* When we are central of an established connection and it enters
24462306a36Sopenharmony_ci	 * the disconnect timeout, then go ahead and try to read the
24562306a36Sopenharmony_ci	 * current clock offset.  Processing of the result is done
24662306a36Sopenharmony_ci	 * within the event handling and hci_clock_offset_evt function.
24762306a36Sopenharmony_ci	 */
24862306a36Sopenharmony_ci	if (conn->type == ACL_LINK && conn->role == HCI_ROLE_MASTER &&
24962306a36Sopenharmony_ci	    (conn->state == BT_CONNECTED || conn->state == BT_CONFIG)) {
25062306a36Sopenharmony_ci		struct hci_dev *hdev = conn->hdev;
25162306a36Sopenharmony_ci		struct hci_cp_read_clock_offset clkoff_cp;
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci		clkoff_cp.handle = cpu_to_le16(conn->handle);
25462306a36Sopenharmony_ci		hci_send_cmd(hdev, HCI_OP_READ_CLOCK_OFFSET, sizeof(clkoff_cp),
25562306a36Sopenharmony_ci			     &clkoff_cp);
25662306a36Sopenharmony_ci	}
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	return hci_abort_conn(conn, reason);
25962306a36Sopenharmony_ci}
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_cistatic void hci_add_sco(struct hci_conn *conn, __u16 handle)
26262306a36Sopenharmony_ci{
26362306a36Sopenharmony_ci	struct hci_dev *hdev = conn->hdev;
26462306a36Sopenharmony_ci	struct hci_cp_add_sco cp;
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci	BT_DBG("hcon %p", conn);
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci	conn->state = BT_CONNECT;
26962306a36Sopenharmony_ci	conn->out = true;
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci	conn->attempt++;
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci	cp.handle   = cpu_to_le16(handle);
27462306a36Sopenharmony_ci	cp.pkt_type = cpu_to_le16(conn->pkt_type);
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci	hci_send_cmd(hdev, HCI_OP_ADD_SCO, sizeof(cp), &cp);
27762306a36Sopenharmony_ci}
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_cistatic bool find_next_esco_param(struct hci_conn *conn,
28062306a36Sopenharmony_ci				 const struct sco_param *esco_param, int size)
28162306a36Sopenharmony_ci{
28262306a36Sopenharmony_ci	if (!conn->parent)
28362306a36Sopenharmony_ci		return false;
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci	for (; conn->attempt <= size; conn->attempt++) {
28662306a36Sopenharmony_ci		if (lmp_esco_2m_capable(conn->parent) ||
28762306a36Sopenharmony_ci		    (esco_param[conn->attempt - 1].pkt_type & ESCO_2EV3))
28862306a36Sopenharmony_ci			break;
28962306a36Sopenharmony_ci		BT_DBG("hcon %p skipped attempt %d, eSCO 2M not supported",
29062306a36Sopenharmony_ci		       conn, conn->attempt);
29162306a36Sopenharmony_ci	}
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	return conn->attempt <= size;
29462306a36Sopenharmony_ci}
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_cistatic int configure_datapath_sync(struct hci_dev *hdev, struct bt_codec *codec)
29762306a36Sopenharmony_ci{
29862306a36Sopenharmony_ci	int err;
29962306a36Sopenharmony_ci	__u8 vnd_len, *vnd_data = NULL;
30062306a36Sopenharmony_ci	struct hci_op_configure_data_path *cmd = NULL;
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	err = hdev->get_codec_config_data(hdev, ESCO_LINK, codec, &vnd_len,
30362306a36Sopenharmony_ci					  &vnd_data);
30462306a36Sopenharmony_ci	if (err < 0)
30562306a36Sopenharmony_ci		goto error;
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci	cmd = kzalloc(sizeof(*cmd) + vnd_len, GFP_KERNEL);
30862306a36Sopenharmony_ci	if (!cmd) {
30962306a36Sopenharmony_ci		err = -ENOMEM;
31062306a36Sopenharmony_ci		goto error;
31162306a36Sopenharmony_ci	}
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	err = hdev->get_data_path_id(hdev, &cmd->data_path_id);
31462306a36Sopenharmony_ci	if (err < 0)
31562306a36Sopenharmony_ci		goto error;
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	cmd->vnd_len = vnd_len;
31862306a36Sopenharmony_ci	memcpy(cmd->vnd_data, vnd_data, vnd_len);
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci	cmd->direction = 0x00;
32162306a36Sopenharmony_ci	__hci_cmd_sync_status(hdev, HCI_CONFIGURE_DATA_PATH,
32262306a36Sopenharmony_ci			      sizeof(*cmd) + vnd_len, cmd, HCI_CMD_TIMEOUT);
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	cmd->direction = 0x01;
32562306a36Sopenharmony_ci	err = __hci_cmd_sync_status(hdev, HCI_CONFIGURE_DATA_PATH,
32662306a36Sopenharmony_ci				    sizeof(*cmd) + vnd_len, cmd,
32762306a36Sopenharmony_ci				    HCI_CMD_TIMEOUT);
32862306a36Sopenharmony_cierror:
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci	kfree(cmd);
33162306a36Sopenharmony_ci	kfree(vnd_data);
33262306a36Sopenharmony_ci	return err;
33362306a36Sopenharmony_ci}
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_cistatic int hci_enhanced_setup_sync(struct hci_dev *hdev, void *data)
33662306a36Sopenharmony_ci{
33762306a36Sopenharmony_ci	struct conn_handle_t *conn_handle = data;
33862306a36Sopenharmony_ci	struct hci_conn *conn = conn_handle->conn;
33962306a36Sopenharmony_ci	__u16 handle = conn_handle->handle;
34062306a36Sopenharmony_ci	struct hci_cp_enhanced_setup_sync_conn cp;
34162306a36Sopenharmony_ci	const struct sco_param *param;
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci	kfree(conn_handle);
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci	bt_dev_dbg(hdev, "hcon %p", conn);
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	/* for offload use case, codec needs to configured before opening SCO */
34862306a36Sopenharmony_ci	if (conn->codec.data_path)
34962306a36Sopenharmony_ci		configure_datapath_sync(hdev, &conn->codec);
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci	conn->state = BT_CONNECT;
35262306a36Sopenharmony_ci	conn->out = true;
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	conn->attempt++;
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci	memset(&cp, 0x00, sizeof(cp));
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci	cp.handle   = cpu_to_le16(handle);
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
36162306a36Sopenharmony_ci	cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci	switch (conn->codec.id) {
36462306a36Sopenharmony_ci	case BT_CODEC_MSBC:
36562306a36Sopenharmony_ci		if (!find_next_esco_param(conn, esco_param_msbc,
36662306a36Sopenharmony_ci					  ARRAY_SIZE(esco_param_msbc)))
36762306a36Sopenharmony_ci			return -EINVAL;
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci		param = &esco_param_msbc[conn->attempt - 1];
37062306a36Sopenharmony_ci		cp.tx_coding_format.id = 0x05;
37162306a36Sopenharmony_ci		cp.rx_coding_format.id = 0x05;
37262306a36Sopenharmony_ci		cp.tx_codec_frame_size = __cpu_to_le16(60);
37362306a36Sopenharmony_ci		cp.rx_codec_frame_size = __cpu_to_le16(60);
37462306a36Sopenharmony_ci		cp.in_bandwidth = __cpu_to_le32(32000);
37562306a36Sopenharmony_ci		cp.out_bandwidth = __cpu_to_le32(32000);
37662306a36Sopenharmony_ci		cp.in_coding_format.id = 0x04;
37762306a36Sopenharmony_ci		cp.out_coding_format.id = 0x04;
37862306a36Sopenharmony_ci		cp.in_coded_data_size = __cpu_to_le16(16);
37962306a36Sopenharmony_ci		cp.out_coded_data_size = __cpu_to_le16(16);
38062306a36Sopenharmony_ci		cp.in_pcm_data_format = 2;
38162306a36Sopenharmony_ci		cp.out_pcm_data_format = 2;
38262306a36Sopenharmony_ci		cp.in_pcm_sample_payload_msb_pos = 0;
38362306a36Sopenharmony_ci		cp.out_pcm_sample_payload_msb_pos = 0;
38462306a36Sopenharmony_ci		cp.in_data_path = conn->codec.data_path;
38562306a36Sopenharmony_ci		cp.out_data_path = conn->codec.data_path;
38662306a36Sopenharmony_ci		cp.in_transport_unit_size = 1;
38762306a36Sopenharmony_ci		cp.out_transport_unit_size = 1;
38862306a36Sopenharmony_ci		break;
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci	case BT_CODEC_TRANSPARENT:
39162306a36Sopenharmony_ci		if (!find_next_esco_param(conn, esco_param_msbc,
39262306a36Sopenharmony_ci					  ARRAY_SIZE(esco_param_msbc)))
39362306a36Sopenharmony_ci			return false;
39462306a36Sopenharmony_ci		param = &esco_param_msbc[conn->attempt - 1];
39562306a36Sopenharmony_ci		cp.tx_coding_format.id = 0x03;
39662306a36Sopenharmony_ci		cp.rx_coding_format.id = 0x03;
39762306a36Sopenharmony_ci		cp.tx_codec_frame_size = __cpu_to_le16(60);
39862306a36Sopenharmony_ci		cp.rx_codec_frame_size = __cpu_to_le16(60);
39962306a36Sopenharmony_ci		cp.in_bandwidth = __cpu_to_le32(0x1f40);
40062306a36Sopenharmony_ci		cp.out_bandwidth = __cpu_to_le32(0x1f40);
40162306a36Sopenharmony_ci		cp.in_coding_format.id = 0x03;
40262306a36Sopenharmony_ci		cp.out_coding_format.id = 0x03;
40362306a36Sopenharmony_ci		cp.in_coded_data_size = __cpu_to_le16(16);
40462306a36Sopenharmony_ci		cp.out_coded_data_size = __cpu_to_le16(16);
40562306a36Sopenharmony_ci		cp.in_pcm_data_format = 2;
40662306a36Sopenharmony_ci		cp.out_pcm_data_format = 2;
40762306a36Sopenharmony_ci		cp.in_pcm_sample_payload_msb_pos = 0;
40862306a36Sopenharmony_ci		cp.out_pcm_sample_payload_msb_pos = 0;
40962306a36Sopenharmony_ci		cp.in_data_path = conn->codec.data_path;
41062306a36Sopenharmony_ci		cp.out_data_path = conn->codec.data_path;
41162306a36Sopenharmony_ci		cp.in_transport_unit_size = 1;
41262306a36Sopenharmony_ci		cp.out_transport_unit_size = 1;
41362306a36Sopenharmony_ci		break;
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci	case BT_CODEC_CVSD:
41662306a36Sopenharmony_ci		if (conn->parent && lmp_esco_capable(conn->parent)) {
41762306a36Sopenharmony_ci			if (!find_next_esco_param(conn, esco_param_cvsd,
41862306a36Sopenharmony_ci						  ARRAY_SIZE(esco_param_cvsd)))
41962306a36Sopenharmony_ci				return -EINVAL;
42062306a36Sopenharmony_ci			param = &esco_param_cvsd[conn->attempt - 1];
42162306a36Sopenharmony_ci		} else {
42262306a36Sopenharmony_ci			if (conn->attempt > ARRAY_SIZE(sco_param_cvsd))
42362306a36Sopenharmony_ci				return -EINVAL;
42462306a36Sopenharmony_ci			param = &sco_param_cvsd[conn->attempt - 1];
42562306a36Sopenharmony_ci		}
42662306a36Sopenharmony_ci		cp.tx_coding_format.id = 2;
42762306a36Sopenharmony_ci		cp.rx_coding_format.id = 2;
42862306a36Sopenharmony_ci		cp.tx_codec_frame_size = __cpu_to_le16(60);
42962306a36Sopenharmony_ci		cp.rx_codec_frame_size = __cpu_to_le16(60);
43062306a36Sopenharmony_ci		cp.in_bandwidth = __cpu_to_le32(16000);
43162306a36Sopenharmony_ci		cp.out_bandwidth = __cpu_to_le32(16000);
43262306a36Sopenharmony_ci		cp.in_coding_format.id = 4;
43362306a36Sopenharmony_ci		cp.out_coding_format.id = 4;
43462306a36Sopenharmony_ci		cp.in_coded_data_size = __cpu_to_le16(16);
43562306a36Sopenharmony_ci		cp.out_coded_data_size = __cpu_to_le16(16);
43662306a36Sopenharmony_ci		cp.in_pcm_data_format = 2;
43762306a36Sopenharmony_ci		cp.out_pcm_data_format = 2;
43862306a36Sopenharmony_ci		cp.in_pcm_sample_payload_msb_pos = 0;
43962306a36Sopenharmony_ci		cp.out_pcm_sample_payload_msb_pos = 0;
44062306a36Sopenharmony_ci		cp.in_data_path = conn->codec.data_path;
44162306a36Sopenharmony_ci		cp.out_data_path = conn->codec.data_path;
44262306a36Sopenharmony_ci		cp.in_transport_unit_size = 16;
44362306a36Sopenharmony_ci		cp.out_transport_unit_size = 16;
44462306a36Sopenharmony_ci		break;
44562306a36Sopenharmony_ci	default:
44662306a36Sopenharmony_ci		return -EINVAL;
44762306a36Sopenharmony_ci	}
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_ci	cp.retrans_effort = param->retrans_effort;
45062306a36Sopenharmony_ci	cp.pkt_type = __cpu_to_le16(param->pkt_type);
45162306a36Sopenharmony_ci	cp.max_latency = __cpu_to_le16(param->max_latency);
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci	if (hci_send_cmd(hdev, HCI_OP_ENHANCED_SETUP_SYNC_CONN, sizeof(cp), &cp) < 0)
45462306a36Sopenharmony_ci		return -EIO;
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ci	return 0;
45762306a36Sopenharmony_ci}
45862306a36Sopenharmony_ci
45962306a36Sopenharmony_cistatic bool hci_setup_sync_conn(struct hci_conn *conn, __u16 handle)
46062306a36Sopenharmony_ci{
46162306a36Sopenharmony_ci	struct hci_dev *hdev = conn->hdev;
46262306a36Sopenharmony_ci	struct hci_cp_setup_sync_conn cp;
46362306a36Sopenharmony_ci	const struct sco_param *param;
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_ci	bt_dev_dbg(hdev, "hcon %p", conn);
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci	conn->state = BT_CONNECT;
46862306a36Sopenharmony_ci	conn->out = true;
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ci	conn->attempt++;
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci	cp.handle   = cpu_to_le16(handle);
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ci	cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
47562306a36Sopenharmony_ci	cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
47662306a36Sopenharmony_ci	cp.voice_setting  = cpu_to_le16(conn->setting);
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci	switch (conn->setting & SCO_AIRMODE_MASK) {
47962306a36Sopenharmony_ci	case SCO_AIRMODE_TRANSP:
48062306a36Sopenharmony_ci		if (!find_next_esco_param(conn, esco_param_msbc,
48162306a36Sopenharmony_ci					  ARRAY_SIZE(esco_param_msbc)))
48262306a36Sopenharmony_ci			return false;
48362306a36Sopenharmony_ci		param = &esco_param_msbc[conn->attempt - 1];
48462306a36Sopenharmony_ci		break;
48562306a36Sopenharmony_ci	case SCO_AIRMODE_CVSD:
48662306a36Sopenharmony_ci		if (conn->parent && lmp_esco_capable(conn->parent)) {
48762306a36Sopenharmony_ci			if (!find_next_esco_param(conn, esco_param_cvsd,
48862306a36Sopenharmony_ci						  ARRAY_SIZE(esco_param_cvsd)))
48962306a36Sopenharmony_ci				return false;
49062306a36Sopenharmony_ci			param = &esco_param_cvsd[conn->attempt - 1];
49162306a36Sopenharmony_ci		} else {
49262306a36Sopenharmony_ci			if (conn->attempt > ARRAY_SIZE(sco_param_cvsd))
49362306a36Sopenharmony_ci				return false;
49462306a36Sopenharmony_ci			param = &sco_param_cvsd[conn->attempt - 1];
49562306a36Sopenharmony_ci		}
49662306a36Sopenharmony_ci		break;
49762306a36Sopenharmony_ci	default:
49862306a36Sopenharmony_ci		return false;
49962306a36Sopenharmony_ci	}
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci	cp.retrans_effort = param->retrans_effort;
50262306a36Sopenharmony_ci	cp.pkt_type = __cpu_to_le16(param->pkt_type);
50362306a36Sopenharmony_ci	cp.max_latency = __cpu_to_le16(param->max_latency);
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_ci	if (hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp) < 0)
50662306a36Sopenharmony_ci		return false;
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci	return true;
50962306a36Sopenharmony_ci}
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_cibool hci_setup_sync(struct hci_conn *conn, __u16 handle)
51262306a36Sopenharmony_ci{
51362306a36Sopenharmony_ci	int result;
51462306a36Sopenharmony_ci	struct conn_handle_t *conn_handle;
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_ci	if (enhanced_sync_conn_capable(conn->hdev)) {
51762306a36Sopenharmony_ci		conn_handle = kzalloc(sizeof(*conn_handle), GFP_KERNEL);
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_ci		if (!conn_handle)
52062306a36Sopenharmony_ci			return false;
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci		conn_handle->conn = conn;
52362306a36Sopenharmony_ci		conn_handle->handle = handle;
52462306a36Sopenharmony_ci		result = hci_cmd_sync_queue(conn->hdev, hci_enhanced_setup_sync,
52562306a36Sopenharmony_ci					    conn_handle, NULL);
52662306a36Sopenharmony_ci		if (result < 0)
52762306a36Sopenharmony_ci			kfree(conn_handle);
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci		return result == 0;
53062306a36Sopenharmony_ci	}
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ci	return hci_setup_sync_conn(conn, handle);
53362306a36Sopenharmony_ci}
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ciu8 hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, u16 latency,
53662306a36Sopenharmony_ci		      u16 to_multiplier)
53762306a36Sopenharmony_ci{
53862306a36Sopenharmony_ci	struct hci_dev *hdev = conn->hdev;
53962306a36Sopenharmony_ci	struct hci_conn_params *params;
54062306a36Sopenharmony_ci	struct hci_cp_le_conn_update cp;
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci	hci_dev_lock(hdev);
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_ci	params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
54562306a36Sopenharmony_ci	if (params) {
54662306a36Sopenharmony_ci		params->conn_min_interval = min;
54762306a36Sopenharmony_ci		params->conn_max_interval = max;
54862306a36Sopenharmony_ci		params->conn_latency = latency;
54962306a36Sopenharmony_ci		params->supervision_timeout = to_multiplier;
55062306a36Sopenharmony_ci	}
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci	hci_dev_unlock(hdev);
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_ci	memset(&cp, 0, sizeof(cp));
55562306a36Sopenharmony_ci	cp.handle		= cpu_to_le16(conn->handle);
55662306a36Sopenharmony_ci	cp.conn_interval_min	= cpu_to_le16(min);
55762306a36Sopenharmony_ci	cp.conn_interval_max	= cpu_to_le16(max);
55862306a36Sopenharmony_ci	cp.conn_latency		= cpu_to_le16(latency);
55962306a36Sopenharmony_ci	cp.supervision_timeout	= cpu_to_le16(to_multiplier);
56062306a36Sopenharmony_ci	cp.min_ce_len		= cpu_to_le16(0x0000);
56162306a36Sopenharmony_ci	cp.max_ce_len		= cpu_to_le16(0x0000);
56262306a36Sopenharmony_ci
56362306a36Sopenharmony_ci	hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp);
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci	if (params)
56662306a36Sopenharmony_ci		return 0x01;
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_ci	return 0x00;
56962306a36Sopenharmony_ci}
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_civoid hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __le64 rand,
57262306a36Sopenharmony_ci		      __u8 ltk[16], __u8 key_size)
57362306a36Sopenharmony_ci{
57462306a36Sopenharmony_ci	struct hci_dev *hdev = conn->hdev;
57562306a36Sopenharmony_ci	struct hci_cp_le_start_enc cp;
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ci	BT_DBG("hcon %p", conn);
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_ci	memset(&cp, 0, sizeof(cp));
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_ci	cp.handle = cpu_to_le16(conn->handle);
58262306a36Sopenharmony_ci	cp.rand = rand;
58362306a36Sopenharmony_ci	cp.ediv = ediv;
58462306a36Sopenharmony_ci	memcpy(cp.ltk, ltk, key_size);
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_ci	hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp);
58762306a36Sopenharmony_ci}
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci/* Device _must_ be locked */
59062306a36Sopenharmony_civoid hci_sco_setup(struct hci_conn *conn, __u8 status)
59162306a36Sopenharmony_ci{
59262306a36Sopenharmony_ci	struct hci_link *link;
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_ci	link = list_first_entry_or_null(&conn->link_list, struct hci_link, list);
59562306a36Sopenharmony_ci	if (!link || !link->conn)
59662306a36Sopenharmony_ci		return;
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_ci	BT_DBG("hcon %p", conn);
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci	if (!status) {
60162306a36Sopenharmony_ci		if (lmp_esco_capable(conn->hdev))
60262306a36Sopenharmony_ci			hci_setup_sync(link->conn, conn->handle);
60362306a36Sopenharmony_ci		else
60462306a36Sopenharmony_ci			hci_add_sco(link->conn, conn->handle);
60562306a36Sopenharmony_ci	} else {
60662306a36Sopenharmony_ci		hci_connect_cfm(link->conn, status);
60762306a36Sopenharmony_ci		hci_conn_del(link->conn);
60862306a36Sopenharmony_ci	}
60962306a36Sopenharmony_ci}
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_cistatic void hci_conn_timeout(struct work_struct *work)
61262306a36Sopenharmony_ci{
61362306a36Sopenharmony_ci	struct hci_conn *conn = container_of(work, struct hci_conn,
61462306a36Sopenharmony_ci					     disc_work.work);
61562306a36Sopenharmony_ci	int refcnt = atomic_read(&conn->refcnt);
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci	BT_DBG("hcon %p state %s", conn, state_to_string(conn->state));
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_ci	WARN_ON(refcnt < 0);
62062306a36Sopenharmony_ci
62162306a36Sopenharmony_ci	/* FIXME: It was observed that in pairing failed scenario, refcnt
62262306a36Sopenharmony_ci	 * drops below 0. Probably this is because l2cap_conn_del calls
62362306a36Sopenharmony_ci	 * l2cap_chan_del for each channel, and inside l2cap_chan_del conn is
62462306a36Sopenharmony_ci	 * dropped. After that loop hci_chan_del is called which also drops
62562306a36Sopenharmony_ci	 * conn. For now make sure that ACL is alive if refcnt is higher then 0,
62662306a36Sopenharmony_ci	 * otherwise drop it.
62762306a36Sopenharmony_ci	 */
62862306a36Sopenharmony_ci	if (refcnt > 0)
62962306a36Sopenharmony_ci		return;
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_ci	hci_abort_conn(conn, hci_proto_disconn_ind(conn));
63262306a36Sopenharmony_ci}
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ci/* Enter sniff mode */
63562306a36Sopenharmony_cistatic void hci_conn_idle(struct work_struct *work)
63662306a36Sopenharmony_ci{
63762306a36Sopenharmony_ci	struct hci_conn *conn = container_of(work, struct hci_conn,
63862306a36Sopenharmony_ci					     idle_work.work);
63962306a36Sopenharmony_ci	struct hci_dev *hdev = conn->hdev;
64062306a36Sopenharmony_ci
64162306a36Sopenharmony_ci	BT_DBG("hcon %p mode %d", conn, conn->mode);
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci	if (!lmp_sniff_capable(hdev) || !lmp_sniff_capable(conn))
64462306a36Sopenharmony_ci		return;
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_ci	if (conn->mode != HCI_CM_ACTIVE || !(conn->link_policy & HCI_LP_SNIFF))
64762306a36Sopenharmony_ci		return;
64862306a36Sopenharmony_ci
64962306a36Sopenharmony_ci	if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) {
65062306a36Sopenharmony_ci		struct hci_cp_sniff_subrate cp;
65162306a36Sopenharmony_ci		cp.handle             = cpu_to_le16(conn->handle);
65262306a36Sopenharmony_ci		cp.max_latency        = cpu_to_le16(0);
65362306a36Sopenharmony_ci		cp.min_remote_timeout = cpu_to_le16(0);
65462306a36Sopenharmony_ci		cp.min_local_timeout  = cpu_to_le16(0);
65562306a36Sopenharmony_ci		hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp);
65662306a36Sopenharmony_ci	}
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_ci	if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) {
65962306a36Sopenharmony_ci		struct hci_cp_sniff_mode cp;
66062306a36Sopenharmony_ci		cp.handle       = cpu_to_le16(conn->handle);
66162306a36Sopenharmony_ci		cp.max_interval = cpu_to_le16(hdev->sniff_max_interval);
66262306a36Sopenharmony_ci		cp.min_interval = cpu_to_le16(hdev->sniff_min_interval);
66362306a36Sopenharmony_ci		cp.attempt      = cpu_to_le16(4);
66462306a36Sopenharmony_ci		cp.timeout      = cpu_to_le16(1);
66562306a36Sopenharmony_ci		hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp);
66662306a36Sopenharmony_ci	}
66762306a36Sopenharmony_ci}
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_cistatic void hci_conn_auto_accept(struct work_struct *work)
67062306a36Sopenharmony_ci{
67162306a36Sopenharmony_ci	struct hci_conn *conn = container_of(work, struct hci_conn,
67262306a36Sopenharmony_ci					     auto_accept_work.work);
67362306a36Sopenharmony_ci
67462306a36Sopenharmony_ci	hci_send_cmd(conn->hdev, HCI_OP_USER_CONFIRM_REPLY, sizeof(conn->dst),
67562306a36Sopenharmony_ci		     &conn->dst);
67662306a36Sopenharmony_ci}
67762306a36Sopenharmony_ci
67862306a36Sopenharmony_cistatic void le_disable_advertising(struct hci_dev *hdev)
67962306a36Sopenharmony_ci{
68062306a36Sopenharmony_ci	if (ext_adv_capable(hdev)) {
68162306a36Sopenharmony_ci		struct hci_cp_le_set_ext_adv_enable cp;
68262306a36Sopenharmony_ci
68362306a36Sopenharmony_ci		cp.enable = 0x00;
68462306a36Sopenharmony_ci		cp.num_of_sets = 0x00;
68562306a36Sopenharmony_ci
68662306a36Sopenharmony_ci		hci_send_cmd(hdev, HCI_OP_LE_SET_EXT_ADV_ENABLE, sizeof(cp),
68762306a36Sopenharmony_ci			     &cp);
68862306a36Sopenharmony_ci	} else {
68962306a36Sopenharmony_ci		u8 enable = 0x00;
69062306a36Sopenharmony_ci		hci_send_cmd(hdev, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable),
69162306a36Sopenharmony_ci			     &enable);
69262306a36Sopenharmony_ci	}
69362306a36Sopenharmony_ci}
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_cistatic void le_conn_timeout(struct work_struct *work)
69662306a36Sopenharmony_ci{
69762306a36Sopenharmony_ci	struct hci_conn *conn = container_of(work, struct hci_conn,
69862306a36Sopenharmony_ci					     le_conn_timeout.work);
69962306a36Sopenharmony_ci	struct hci_dev *hdev = conn->hdev;
70062306a36Sopenharmony_ci
70162306a36Sopenharmony_ci	BT_DBG("");
70262306a36Sopenharmony_ci
70362306a36Sopenharmony_ci	/* We could end up here due to having done directed advertising,
70462306a36Sopenharmony_ci	 * so clean up the state if necessary. This should however only
70562306a36Sopenharmony_ci	 * happen with broken hardware or if low duty cycle was used
70662306a36Sopenharmony_ci	 * (which doesn't have a timeout of its own).
70762306a36Sopenharmony_ci	 */
70862306a36Sopenharmony_ci	if (conn->role == HCI_ROLE_SLAVE) {
70962306a36Sopenharmony_ci		/* Disable LE Advertising */
71062306a36Sopenharmony_ci		le_disable_advertising(hdev);
71162306a36Sopenharmony_ci		hci_dev_lock(hdev);
71262306a36Sopenharmony_ci		hci_conn_failed(conn, HCI_ERROR_ADVERTISING_TIMEOUT);
71362306a36Sopenharmony_ci		hci_dev_unlock(hdev);
71462306a36Sopenharmony_ci		return;
71562306a36Sopenharmony_ci	}
71662306a36Sopenharmony_ci
71762306a36Sopenharmony_ci	hci_abort_conn(conn, HCI_ERROR_REMOTE_USER_TERM);
71862306a36Sopenharmony_ci}
71962306a36Sopenharmony_ci
72062306a36Sopenharmony_cistruct iso_cig_params {
72162306a36Sopenharmony_ci	struct hci_cp_le_set_cig_params cp;
72262306a36Sopenharmony_ci	struct hci_cis_params cis[0x1f];
72362306a36Sopenharmony_ci};
72462306a36Sopenharmony_ci
72562306a36Sopenharmony_cistruct iso_list_data {
72662306a36Sopenharmony_ci	union {
72762306a36Sopenharmony_ci		u8  cig;
72862306a36Sopenharmony_ci		u8  big;
72962306a36Sopenharmony_ci	};
73062306a36Sopenharmony_ci	union {
73162306a36Sopenharmony_ci		u8  cis;
73262306a36Sopenharmony_ci		u8  bis;
73362306a36Sopenharmony_ci		u16 sync_handle;
73462306a36Sopenharmony_ci	};
73562306a36Sopenharmony_ci	int count;
73662306a36Sopenharmony_ci	bool big_term;
73762306a36Sopenharmony_ci	bool pa_sync_term;
73862306a36Sopenharmony_ci	bool big_sync_term;
73962306a36Sopenharmony_ci};
74062306a36Sopenharmony_ci
74162306a36Sopenharmony_cistatic void bis_list(struct hci_conn *conn, void *data)
74262306a36Sopenharmony_ci{
74362306a36Sopenharmony_ci	struct iso_list_data *d = data;
74462306a36Sopenharmony_ci
74562306a36Sopenharmony_ci	/* Skip if not broadcast/ANY address */
74662306a36Sopenharmony_ci	if (bacmp(&conn->dst, BDADDR_ANY))
74762306a36Sopenharmony_ci		return;
74862306a36Sopenharmony_ci
74962306a36Sopenharmony_ci	if (d->big != conn->iso_qos.bcast.big || d->bis == BT_ISO_QOS_BIS_UNSET ||
75062306a36Sopenharmony_ci	    d->bis != conn->iso_qos.bcast.bis)
75162306a36Sopenharmony_ci		return;
75262306a36Sopenharmony_ci
75362306a36Sopenharmony_ci	d->count++;
75462306a36Sopenharmony_ci}
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_cistatic int terminate_big_sync(struct hci_dev *hdev, void *data)
75762306a36Sopenharmony_ci{
75862306a36Sopenharmony_ci	struct iso_list_data *d = data;
75962306a36Sopenharmony_ci
76062306a36Sopenharmony_ci	bt_dev_dbg(hdev, "big 0x%2.2x bis 0x%2.2x", d->big, d->bis);
76162306a36Sopenharmony_ci
76262306a36Sopenharmony_ci	hci_remove_ext_adv_instance_sync(hdev, d->bis, NULL);
76362306a36Sopenharmony_ci
76462306a36Sopenharmony_ci	/* Only terminate BIG if it has been created */
76562306a36Sopenharmony_ci	if (!d->big_term)
76662306a36Sopenharmony_ci		return 0;
76762306a36Sopenharmony_ci
76862306a36Sopenharmony_ci	return hci_le_terminate_big_sync(hdev, d->big,
76962306a36Sopenharmony_ci					 HCI_ERROR_LOCAL_HOST_TERM);
77062306a36Sopenharmony_ci}
77162306a36Sopenharmony_ci
77262306a36Sopenharmony_cistatic void terminate_big_destroy(struct hci_dev *hdev, void *data, int err)
77362306a36Sopenharmony_ci{
77462306a36Sopenharmony_ci	kfree(data);
77562306a36Sopenharmony_ci}
77662306a36Sopenharmony_ci
77762306a36Sopenharmony_cistatic int hci_le_terminate_big(struct hci_dev *hdev, struct hci_conn *conn)
77862306a36Sopenharmony_ci{
77962306a36Sopenharmony_ci	struct iso_list_data *d;
78062306a36Sopenharmony_ci	int ret;
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci	bt_dev_dbg(hdev, "big 0x%2.2x bis 0x%2.2x", conn->iso_qos.bcast.big,
78362306a36Sopenharmony_ci		   conn->iso_qos.bcast.bis);
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_ci	d = kzalloc(sizeof(*d), GFP_KERNEL);
78662306a36Sopenharmony_ci	if (!d)
78762306a36Sopenharmony_ci		return -ENOMEM;
78862306a36Sopenharmony_ci
78962306a36Sopenharmony_ci	d->big = conn->iso_qos.bcast.big;
79062306a36Sopenharmony_ci	d->bis = conn->iso_qos.bcast.bis;
79162306a36Sopenharmony_ci	d->big_term = test_and_clear_bit(HCI_CONN_BIG_CREATED, &conn->flags);
79262306a36Sopenharmony_ci
79362306a36Sopenharmony_ci	ret = hci_cmd_sync_queue(hdev, terminate_big_sync, d,
79462306a36Sopenharmony_ci				 terminate_big_destroy);
79562306a36Sopenharmony_ci	if (ret)
79662306a36Sopenharmony_ci		kfree(d);
79762306a36Sopenharmony_ci
79862306a36Sopenharmony_ci	return ret;
79962306a36Sopenharmony_ci}
80062306a36Sopenharmony_ci
80162306a36Sopenharmony_cistatic int big_terminate_sync(struct hci_dev *hdev, void *data)
80262306a36Sopenharmony_ci{
80362306a36Sopenharmony_ci	struct iso_list_data *d = data;
80462306a36Sopenharmony_ci
80562306a36Sopenharmony_ci	bt_dev_dbg(hdev, "big 0x%2.2x sync_handle 0x%4.4x", d->big,
80662306a36Sopenharmony_ci		   d->sync_handle);
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_ci	if (d->big_sync_term)
80962306a36Sopenharmony_ci		hci_le_big_terminate_sync(hdev, d->big);
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_ci	if (d->pa_sync_term)
81262306a36Sopenharmony_ci		return hci_le_pa_terminate_sync(hdev, d->sync_handle);
81362306a36Sopenharmony_ci
81462306a36Sopenharmony_ci	return 0;
81562306a36Sopenharmony_ci}
81662306a36Sopenharmony_ci
81762306a36Sopenharmony_cistatic int hci_le_big_terminate(struct hci_dev *hdev, u8 big, struct hci_conn *conn)
81862306a36Sopenharmony_ci{
81962306a36Sopenharmony_ci	struct iso_list_data *d;
82062306a36Sopenharmony_ci	int ret;
82162306a36Sopenharmony_ci
82262306a36Sopenharmony_ci	bt_dev_dbg(hdev, "big 0x%2.2x sync_handle 0x%4.4x", big, conn->sync_handle);
82362306a36Sopenharmony_ci
82462306a36Sopenharmony_ci	d = kzalloc(sizeof(*d), GFP_KERNEL);
82562306a36Sopenharmony_ci	if (!d)
82662306a36Sopenharmony_ci		return -ENOMEM;
82762306a36Sopenharmony_ci
82862306a36Sopenharmony_ci	d->big = big;
82962306a36Sopenharmony_ci	d->sync_handle = conn->sync_handle;
83062306a36Sopenharmony_ci	d->pa_sync_term = test_and_clear_bit(HCI_CONN_PA_SYNC, &conn->flags);
83162306a36Sopenharmony_ci	d->big_sync_term = test_and_clear_bit(HCI_CONN_BIG_SYNC, &conn->flags);
83262306a36Sopenharmony_ci
83362306a36Sopenharmony_ci	ret = hci_cmd_sync_queue(hdev, big_terminate_sync, d,
83462306a36Sopenharmony_ci				 terminate_big_destroy);
83562306a36Sopenharmony_ci	if (ret)
83662306a36Sopenharmony_ci		kfree(d);
83762306a36Sopenharmony_ci
83862306a36Sopenharmony_ci	return ret;
83962306a36Sopenharmony_ci}
84062306a36Sopenharmony_ci
84162306a36Sopenharmony_ci/* Cleanup BIS connection
84262306a36Sopenharmony_ci *
84362306a36Sopenharmony_ci * Detects if there any BIS left connected in a BIG
84462306a36Sopenharmony_ci * broadcaster: Remove advertising instance and terminate BIG.
84562306a36Sopenharmony_ci * broadcaster receiver: Teminate BIG sync and terminate PA sync.
84662306a36Sopenharmony_ci */
84762306a36Sopenharmony_cistatic void bis_cleanup(struct hci_conn *conn)
84862306a36Sopenharmony_ci{
84962306a36Sopenharmony_ci	struct hci_dev *hdev = conn->hdev;
85062306a36Sopenharmony_ci	struct hci_conn *bis;
85162306a36Sopenharmony_ci
85262306a36Sopenharmony_ci	bt_dev_dbg(hdev, "conn %p", conn);
85362306a36Sopenharmony_ci
85462306a36Sopenharmony_ci	if (conn->role == HCI_ROLE_MASTER) {
85562306a36Sopenharmony_ci		if (!test_and_clear_bit(HCI_CONN_PER_ADV, &conn->flags))
85662306a36Sopenharmony_ci			return;
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_ci		/* Check if ISO connection is a BIS and terminate advertising
85962306a36Sopenharmony_ci		 * set and BIG if there are no other connections using it.
86062306a36Sopenharmony_ci		 */
86162306a36Sopenharmony_ci		bis = hci_conn_hash_lookup_big(hdev, conn->iso_qos.bcast.big);
86262306a36Sopenharmony_ci		if (bis)
86362306a36Sopenharmony_ci			return;
86462306a36Sopenharmony_ci
86562306a36Sopenharmony_ci		hci_le_terminate_big(hdev, conn);
86662306a36Sopenharmony_ci	} else {
86762306a36Sopenharmony_ci		bis = hci_conn_hash_lookup_big_any_dst(hdev,
86862306a36Sopenharmony_ci						       conn->iso_qos.bcast.big);
86962306a36Sopenharmony_ci
87062306a36Sopenharmony_ci		if (bis)
87162306a36Sopenharmony_ci			return;
87262306a36Sopenharmony_ci
87362306a36Sopenharmony_ci		hci_le_big_terminate(hdev, conn->iso_qos.bcast.big,
87462306a36Sopenharmony_ci				     conn);
87562306a36Sopenharmony_ci	}
87662306a36Sopenharmony_ci}
87762306a36Sopenharmony_ci
87862306a36Sopenharmony_cistatic int remove_cig_sync(struct hci_dev *hdev, void *data)
87962306a36Sopenharmony_ci{
88062306a36Sopenharmony_ci	u8 handle = PTR_UINT(data);
88162306a36Sopenharmony_ci
88262306a36Sopenharmony_ci	return hci_le_remove_cig_sync(hdev, handle);
88362306a36Sopenharmony_ci}
88462306a36Sopenharmony_ci
88562306a36Sopenharmony_cistatic int hci_le_remove_cig(struct hci_dev *hdev, u8 handle)
88662306a36Sopenharmony_ci{
88762306a36Sopenharmony_ci	bt_dev_dbg(hdev, "handle 0x%2.2x", handle);
88862306a36Sopenharmony_ci
88962306a36Sopenharmony_ci	return hci_cmd_sync_queue(hdev, remove_cig_sync, UINT_PTR(handle),
89062306a36Sopenharmony_ci				  NULL);
89162306a36Sopenharmony_ci}
89262306a36Sopenharmony_ci
89362306a36Sopenharmony_cistatic void find_cis(struct hci_conn *conn, void *data)
89462306a36Sopenharmony_ci{
89562306a36Sopenharmony_ci	struct iso_list_data *d = data;
89662306a36Sopenharmony_ci
89762306a36Sopenharmony_ci	/* Ignore broadcast or if CIG don't match */
89862306a36Sopenharmony_ci	if (!bacmp(&conn->dst, BDADDR_ANY) || d->cig != conn->iso_qos.ucast.cig)
89962306a36Sopenharmony_ci		return;
90062306a36Sopenharmony_ci
90162306a36Sopenharmony_ci	d->count++;
90262306a36Sopenharmony_ci}
90362306a36Sopenharmony_ci
90462306a36Sopenharmony_ci/* Cleanup CIS connection:
90562306a36Sopenharmony_ci *
90662306a36Sopenharmony_ci * Detects if there any CIS left connected in a CIG and remove it.
90762306a36Sopenharmony_ci */
90862306a36Sopenharmony_cistatic void cis_cleanup(struct hci_conn *conn)
90962306a36Sopenharmony_ci{
91062306a36Sopenharmony_ci	struct hci_dev *hdev = conn->hdev;
91162306a36Sopenharmony_ci	struct iso_list_data d;
91262306a36Sopenharmony_ci
91362306a36Sopenharmony_ci	if (conn->iso_qos.ucast.cig == BT_ISO_QOS_CIG_UNSET)
91462306a36Sopenharmony_ci		return;
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_ci	memset(&d, 0, sizeof(d));
91762306a36Sopenharmony_ci	d.cig = conn->iso_qos.ucast.cig;
91862306a36Sopenharmony_ci
91962306a36Sopenharmony_ci	/* Check if ISO connection is a CIS and remove CIG if there are
92062306a36Sopenharmony_ci	 * no other connections using it.
92162306a36Sopenharmony_ci	 */
92262306a36Sopenharmony_ci	hci_conn_hash_list_state(hdev, find_cis, ISO_LINK, BT_BOUND, &d);
92362306a36Sopenharmony_ci	hci_conn_hash_list_state(hdev, find_cis, ISO_LINK, BT_CONNECT, &d);
92462306a36Sopenharmony_ci	hci_conn_hash_list_state(hdev, find_cis, ISO_LINK, BT_CONNECTED, &d);
92562306a36Sopenharmony_ci	if (d.count)
92662306a36Sopenharmony_ci		return;
92762306a36Sopenharmony_ci
92862306a36Sopenharmony_ci	hci_le_remove_cig(hdev, conn->iso_qos.ucast.cig);
92962306a36Sopenharmony_ci}
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_cistatic int hci_conn_hash_alloc_unset(struct hci_dev *hdev)
93262306a36Sopenharmony_ci{
93362306a36Sopenharmony_ci	return ida_alloc_range(&hdev->unset_handle_ida, HCI_CONN_HANDLE_MAX + 1,
93462306a36Sopenharmony_ci			       U16_MAX, GFP_ATOMIC);
93562306a36Sopenharmony_ci}
93662306a36Sopenharmony_ci
93762306a36Sopenharmony_cistruct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
93862306a36Sopenharmony_ci			      u8 role, u16 handle)
93962306a36Sopenharmony_ci{
94062306a36Sopenharmony_ci	struct hci_conn *conn;
94162306a36Sopenharmony_ci
94262306a36Sopenharmony_ci	bt_dev_dbg(hdev, "dst %pMR handle 0x%4.4x", dst, handle);
94362306a36Sopenharmony_ci
94462306a36Sopenharmony_ci	conn = kzalloc(sizeof(*conn), GFP_KERNEL);
94562306a36Sopenharmony_ci	if (!conn)
94662306a36Sopenharmony_ci		return NULL;
94762306a36Sopenharmony_ci
94862306a36Sopenharmony_ci	bacpy(&conn->dst, dst);
94962306a36Sopenharmony_ci	bacpy(&conn->src, &hdev->bdaddr);
95062306a36Sopenharmony_ci	conn->handle = handle;
95162306a36Sopenharmony_ci	conn->hdev  = hdev;
95262306a36Sopenharmony_ci	conn->type  = type;
95362306a36Sopenharmony_ci	conn->role  = role;
95462306a36Sopenharmony_ci	conn->mode  = HCI_CM_ACTIVE;
95562306a36Sopenharmony_ci	conn->state = BT_OPEN;
95662306a36Sopenharmony_ci	conn->auth_type = HCI_AT_GENERAL_BONDING;
95762306a36Sopenharmony_ci	conn->io_capability = hdev->io_capability;
95862306a36Sopenharmony_ci	conn->remote_auth = 0xff;
95962306a36Sopenharmony_ci	conn->key_type = 0xff;
96062306a36Sopenharmony_ci	conn->rssi = HCI_RSSI_INVALID;
96162306a36Sopenharmony_ci	conn->tx_power = HCI_TX_POWER_INVALID;
96262306a36Sopenharmony_ci	conn->max_tx_power = HCI_TX_POWER_INVALID;
96362306a36Sopenharmony_ci	conn->sync_handle = HCI_SYNC_HANDLE_INVALID;
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci	set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
96662306a36Sopenharmony_ci	conn->disc_timeout = HCI_DISCONN_TIMEOUT;
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_ci	/* Set Default Authenticated payload timeout to 30s */
96962306a36Sopenharmony_ci	conn->auth_payload_timeout = DEFAULT_AUTH_PAYLOAD_TIMEOUT;
97062306a36Sopenharmony_ci
97162306a36Sopenharmony_ci	if (conn->role == HCI_ROLE_MASTER)
97262306a36Sopenharmony_ci		conn->out = true;
97362306a36Sopenharmony_ci
97462306a36Sopenharmony_ci	switch (type) {
97562306a36Sopenharmony_ci	case ACL_LINK:
97662306a36Sopenharmony_ci		conn->pkt_type = hdev->pkt_type & ACL_PTYPE_MASK;
97762306a36Sopenharmony_ci		break;
97862306a36Sopenharmony_ci	case LE_LINK:
97962306a36Sopenharmony_ci		/* conn->src should reflect the local identity address */
98062306a36Sopenharmony_ci		hci_copy_identity_address(hdev, &conn->src, &conn->src_type);
98162306a36Sopenharmony_ci		break;
98262306a36Sopenharmony_ci	case ISO_LINK:
98362306a36Sopenharmony_ci		/* conn->src should reflect the local identity address */
98462306a36Sopenharmony_ci		hci_copy_identity_address(hdev, &conn->src, &conn->src_type);
98562306a36Sopenharmony_ci
98662306a36Sopenharmony_ci		/* set proper cleanup function */
98762306a36Sopenharmony_ci		if (!bacmp(dst, BDADDR_ANY))
98862306a36Sopenharmony_ci			conn->cleanup = bis_cleanup;
98962306a36Sopenharmony_ci		else if (conn->role == HCI_ROLE_MASTER)
99062306a36Sopenharmony_ci			conn->cleanup = cis_cleanup;
99162306a36Sopenharmony_ci
99262306a36Sopenharmony_ci		break;
99362306a36Sopenharmony_ci	case SCO_LINK:
99462306a36Sopenharmony_ci		if (lmp_esco_capable(hdev))
99562306a36Sopenharmony_ci			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
99662306a36Sopenharmony_ci					(hdev->esco_type & EDR_ESCO_MASK);
99762306a36Sopenharmony_ci		else
99862306a36Sopenharmony_ci			conn->pkt_type = hdev->pkt_type & SCO_PTYPE_MASK;
99962306a36Sopenharmony_ci		break;
100062306a36Sopenharmony_ci	case ESCO_LINK:
100162306a36Sopenharmony_ci		conn->pkt_type = hdev->esco_type & ~EDR_ESCO_MASK;
100262306a36Sopenharmony_ci		break;
100362306a36Sopenharmony_ci	}
100462306a36Sopenharmony_ci
100562306a36Sopenharmony_ci	skb_queue_head_init(&conn->data_q);
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_ci	INIT_LIST_HEAD(&conn->chan_list);
100862306a36Sopenharmony_ci	INIT_LIST_HEAD(&conn->link_list);
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_ci	INIT_DELAYED_WORK(&conn->disc_work, hci_conn_timeout);
101162306a36Sopenharmony_ci	INIT_DELAYED_WORK(&conn->auto_accept_work, hci_conn_auto_accept);
101262306a36Sopenharmony_ci	INIT_DELAYED_WORK(&conn->idle_work, hci_conn_idle);
101362306a36Sopenharmony_ci	INIT_DELAYED_WORK(&conn->le_conn_timeout, le_conn_timeout);
101462306a36Sopenharmony_ci
101562306a36Sopenharmony_ci	atomic_set(&conn->refcnt, 0);
101662306a36Sopenharmony_ci
101762306a36Sopenharmony_ci	hci_dev_hold(hdev);
101862306a36Sopenharmony_ci
101962306a36Sopenharmony_ci	hci_conn_hash_add(hdev, conn);
102062306a36Sopenharmony_ci
102162306a36Sopenharmony_ci	/* The SCO and eSCO connections will only be notified when their
102262306a36Sopenharmony_ci	 * setup has been completed. This is different to ACL links which
102362306a36Sopenharmony_ci	 * can be notified right away.
102462306a36Sopenharmony_ci	 */
102562306a36Sopenharmony_ci	if (conn->type != SCO_LINK && conn->type != ESCO_LINK) {
102662306a36Sopenharmony_ci		if (hdev->notify)
102762306a36Sopenharmony_ci			hdev->notify(hdev, HCI_NOTIFY_CONN_ADD);
102862306a36Sopenharmony_ci	}
102962306a36Sopenharmony_ci
103062306a36Sopenharmony_ci	hci_conn_init_sysfs(conn);
103162306a36Sopenharmony_ci
103262306a36Sopenharmony_ci	return conn;
103362306a36Sopenharmony_ci}
103462306a36Sopenharmony_ci
103562306a36Sopenharmony_cistruct hci_conn *hci_conn_add_unset(struct hci_dev *hdev, int type,
103662306a36Sopenharmony_ci				    bdaddr_t *dst, u8 role)
103762306a36Sopenharmony_ci{
103862306a36Sopenharmony_ci	int handle;
103962306a36Sopenharmony_ci
104062306a36Sopenharmony_ci	bt_dev_dbg(hdev, "dst %pMR", dst);
104162306a36Sopenharmony_ci
104262306a36Sopenharmony_ci	handle = hci_conn_hash_alloc_unset(hdev);
104362306a36Sopenharmony_ci	if (unlikely(handle < 0))
104462306a36Sopenharmony_ci		return NULL;
104562306a36Sopenharmony_ci
104662306a36Sopenharmony_ci	return hci_conn_add(hdev, type, dst, role, handle);
104762306a36Sopenharmony_ci}
104862306a36Sopenharmony_ci
104962306a36Sopenharmony_cistatic void hci_conn_cleanup_child(struct hci_conn *conn, u8 reason)
105062306a36Sopenharmony_ci{
105162306a36Sopenharmony_ci	if (!reason)
105262306a36Sopenharmony_ci		reason = HCI_ERROR_REMOTE_USER_TERM;
105362306a36Sopenharmony_ci
105462306a36Sopenharmony_ci	/* Due to race, SCO/ISO conn might be not established yet at this point,
105562306a36Sopenharmony_ci	 * and nothing else will clean it up. In other cases it is done via HCI
105662306a36Sopenharmony_ci	 * events.
105762306a36Sopenharmony_ci	 */
105862306a36Sopenharmony_ci	switch (conn->type) {
105962306a36Sopenharmony_ci	case SCO_LINK:
106062306a36Sopenharmony_ci	case ESCO_LINK:
106162306a36Sopenharmony_ci		if (HCI_CONN_HANDLE_UNSET(conn->handle))
106262306a36Sopenharmony_ci			hci_conn_failed(conn, reason);
106362306a36Sopenharmony_ci		break;
106462306a36Sopenharmony_ci	case ISO_LINK:
106562306a36Sopenharmony_ci		if (conn->state != BT_CONNECTED &&
106662306a36Sopenharmony_ci		    !test_bit(HCI_CONN_CREATE_CIS, &conn->flags))
106762306a36Sopenharmony_ci			hci_conn_failed(conn, reason);
106862306a36Sopenharmony_ci		break;
106962306a36Sopenharmony_ci	}
107062306a36Sopenharmony_ci}
107162306a36Sopenharmony_ci
107262306a36Sopenharmony_cistatic void hci_conn_unlink(struct hci_conn *conn)
107362306a36Sopenharmony_ci{
107462306a36Sopenharmony_ci	struct hci_dev *hdev = conn->hdev;
107562306a36Sopenharmony_ci
107662306a36Sopenharmony_ci	bt_dev_dbg(hdev, "hcon %p", conn);
107762306a36Sopenharmony_ci
107862306a36Sopenharmony_ci	if (!conn->parent) {
107962306a36Sopenharmony_ci		struct hci_link *link, *t;
108062306a36Sopenharmony_ci
108162306a36Sopenharmony_ci		list_for_each_entry_safe(link, t, &conn->link_list, list) {
108262306a36Sopenharmony_ci			struct hci_conn *child = link->conn;
108362306a36Sopenharmony_ci
108462306a36Sopenharmony_ci			hci_conn_unlink(child);
108562306a36Sopenharmony_ci
108662306a36Sopenharmony_ci			/* If hdev is down it means
108762306a36Sopenharmony_ci			 * hci_dev_close_sync/hci_conn_hash_flush is in progress
108862306a36Sopenharmony_ci			 * and links don't need to be cleanup as all connections
108962306a36Sopenharmony_ci			 * would be cleanup.
109062306a36Sopenharmony_ci			 */
109162306a36Sopenharmony_ci			if (!test_bit(HCI_UP, &hdev->flags))
109262306a36Sopenharmony_ci				continue;
109362306a36Sopenharmony_ci
109462306a36Sopenharmony_ci			hci_conn_cleanup_child(child, conn->abort_reason);
109562306a36Sopenharmony_ci		}
109662306a36Sopenharmony_ci
109762306a36Sopenharmony_ci		return;
109862306a36Sopenharmony_ci	}
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_ci	if (!conn->link)
110162306a36Sopenharmony_ci		return;
110262306a36Sopenharmony_ci
110362306a36Sopenharmony_ci	list_del_rcu(&conn->link->list);
110462306a36Sopenharmony_ci	synchronize_rcu();
110562306a36Sopenharmony_ci
110662306a36Sopenharmony_ci	hci_conn_drop(conn->parent);
110762306a36Sopenharmony_ci	hci_conn_put(conn->parent);
110862306a36Sopenharmony_ci	conn->parent = NULL;
110962306a36Sopenharmony_ci
111062306a36Sopenharmony_ci	kfree(conn->link);
111162306a36Sopenharmony_ci	conn->link = NULL;
111262306a36Sopenharmony_ci}
111362306a36Sopenharmony_ci
111462306a36Sopenharmony_civoid hci_conn_del(struct hci_conn *conn)
111562306a36Sopenharmony_ci{
111662306a36Sopenharmony_ci	struct hci_dev *hdev = conn->hdev;
111762306a36Sopenharmony_ci
111862306a36Sopenharmony_ci	BT_DBG("%s hcon %p handle %d", hdev->name, conn, conn->handle);
111962306a36Sopenharmony_ci
112062306a36Sopenharmony_ci	hci_conn_unlink(conn);
112162306a36Sopenharmony_ci
112262306a36Sopenharmony_ci	cancel_delayed_work_sync(&conn->disc_work);
112362306a36Sopenharmony_ci	cancel_delayed_work_sync(&conn->auto_accept_work);
112462306a36Sopenharmony_ci	cancel_delayed_work_sync(&conn->idle_work);
112562306a36Sopenharmony_ci
112662306a36Sopenharmony_ci	if (conn->type == ACL_LINK) {
112762306a36Sopenharmony_ci		/* Unacked frames */
112862306a36Sopenharmony_ci		hdev->acl_cnt += conn->sent;
112962306a36Sopenharmony_ci	} else if (conn->type == LE_LINK) {
113062306a36Sopenharmony_ci		cancel_delayed_work(&conn->le_conn_timeout);
113162306a36Sopenharmony_ci
113262306a36Sopenharmony_ci		if (hdev->le_pkts)
113362306a36Sopenharmony_ci			hdev->le_cnt += conn->sent;
113462306a36Sopenharmony_ci		else
113562306a36Sopenharmony_ci			hdev->acl_cnt += conn->sent;
113662306a36Sopenharmony_ci	} else {
113762306a36Sopenharmony_ci		/* Unacked ISO frames */
113862306a36Sopenharmony_ci		if (conn->type == ISO_LINK) {
113962306a36Sopenharmony_ci			if (hdev->iso_pkts)
114062306a36Sopenharmony_ci				hdev->iso_cnt += conn->sent;
114162306a36Sopenharmony_ci			else if (hdev->le_pkts)
114262306a36Sopenharmony_ci				hdev->le_cnt += conn->sent;
114362306a36Sopenharmony_ci			else
114462306a36Sopenharmony_ci				hdev->acl_cnt += conn->sent;
114562306a36Sopenharmony_ci		}
114662306a36Sopenharmony_ci	}
114762306a36Sopenharmony_ci
114862306a36Sopenharmony_ci	skb_queue_purge(&conn->data_q);
114962306a36Sopenharmony_ci
115062306a36Sopenharmony_ci	/* Remove the connection from the list and cleanup its remaining
115162306a36Sopenharmony_ci	 * state. This is a separate function since for some cases like
115262306a36Sopenharmony_ci	 * BT_CONNECT_SCAN we *only* want the cleanup part without the
115362306a36Sopenharmony_ci	 * rest of hci_conn_del.
115462306a36Sopenharmony_ci	 */
115562306a36Sopenharmony_ci	hci_conn_cleanup(conn);
115662306a36Sopenharmony_ci}
115762306a36Sopenharmony_ci
115862306a36Sopenharmony_cistruct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src, uint8_t src_type)
115962306a36Sopenharmony_ci{
116062306a36Sopenharmony_ci	int use_src = bacmp(src, BDADDR_ANY);
116162306a36Sopenharmony_ci	struct hci_dev *hdev = NULL, *d;
116262306a36Sopenharmony_ci
116362306a36Sopenharmony_ci	BT_DBG("%pMR -> %pMR", src, dst);
116462306a36Sopenharmony_ci
116562306a36Sopenharmony_ci	read_lock(&hci_dev_list_lock);
116662306a36Sopenharmony_ci
116762306a36Sopenharmony_ci	list_for_each_entry(d, &hci_dev_list, list) {
116862306a36Sopenharmony_ci		if (!test_bit(HCI_UP, &d->flags) ||
116962306a36Sopenharmony_ci		    hci_dev_test_flag(d, HCI_USER_CHANNEL) ||
117062306a36Sopenharmony_ci		    d->dev_type != HCI_PRIMARY)
117162306a36Sopenharmony_ci			continue;
117262306a36Sopenharmony_ci
117362306a36Sopenharmony_ci		/* Simple routing:
117462306a36Sopenharmony_ci		 *   No source address - find interface with bdaddr != dst
117562306a36Sopenharmony_ci		 *   Source address    - find interface with bdaddr == src
117662306a36Sopenharmony_ci		 */
117762306a36Sopenharmony_ci
117862306a36Sopenharmony_ci		if (use_src) {
117962306a36Sopenharmony_ci			bdaddr_t id_addr;
118062306a36Sopenharmony_ci			u8 id_addr_type;
118162306a36Sopenharmony_ci
118262306a36Sopenharmony_ci			if (src_type == BDADDR_BREDR) {
118362306a36Sopenharmony_ci				if (!lmp_bredr_capable(d))
118462306a36Sopenharmony_ci					continue;
118562306a36Sopenharmony_ci				bacpy(&id_addr, &d->bdaddr);
118662306a36Sopenharmony_ci				id_addr_type = BDADDR_BREDR;
118762306a36Sopenharmony_ci			} else {
118862306a36Sopenharmony_ci				if (!lmp_le_capable(d))
118962306a36Sopenharmony_ci					continue;
119062306a36Sopenharmony_ci
119162306a36Sopenharmony_ci				hci_copy_identity_address(d, &id_addr,
119262306a36Sopenharmony_ci							  &id_addr_type);
119362306a36Sopenharmony_ci
119462306a36Sopenharmony_ci				/* Convert from HCI to three-value type */
119562306a36Sopenharmony_ci				if (id_addr_type == ADDR_LE_DEV_PUBLIC)
119662306a36Sopenharmony_ci					id_addr_type = BDADDR_LE_PUBLIC;
119762306a36Sopenharmony_ci				else
119862306a36Sopenharmony_ci					id_addr_type = BDADDR_LE_RANDOM;
119962306a36Sopenharmony_ci			}
120062306a36Sopenharmony_ci
120162306a36Sopenharmony_ci			if (!bacmp(&id_addr, src) && id_addr_type == src_type) {
120262306a36Sopenharmony_ci				hdev = d; break;
120362306a36Sopenharmony_ci			}
120462306a36Sopenharmony_ci		} else {
120562306a36Sopenharmony_ci			if (bacmp(&d->bdaddr, dst)) {
120662306a36Sopenharmony_ci				hdev = d; break;
120762306a36Sopenharmony_ci			}
120862306a36Sopenharmony_ci		}
120962306a36Sopenharmony_ci	}
121062306a36Sopenharmony_ci
121162306a36Sopenharmony_ci	if (hdev)
121262306a36Sopenharmony_ci		hdev = hci_dev_hold(hdev);
121362306a36Sopenharmony_ci
121462306a36Sopenharmony_ci	read_unlock(&hci_dev_list_lock);
121562306a36Sopenharmony_ci	return hdev;
121662306a36Sopenharmony_ci}
121762306a36Sopenharmony_ciEXPORT_SYMBOL(hci_get_route);
121862306a36Sopenharmony_ci
121962306a36Sopenharmony_ci/* This function requires the caller holds hdev->lock */
122062306a36Sopenharmony_cistatic void hci_le_conn_failed(struct hci_conn *conn, u8 status)
122162306a36Sopenharmony_ci{
122262306a36Sopenharmony_ci	struct hci_dev *hdev = conn->hdev;
122362306a36Sopenharmony_ci
122462306a36Sopenharmony_ci	hci_connect_le_scan_cleanup(conn, status);
122562306a36Sopenharmony_ci
122662306a36Sopenharmony_ci	/* Enable advertising in case this was a failed connection
122762306a36Sopenharmony_ci	 * attempt as a peripheral.
122862306a36Sopenharmony_ci	 */
122962306a36Sopenharmony_ci	hci_enable_advertising(hdev);
123062306a36Sopenharmony_ci}
123162306a36Sopenharmony_ci
123262306a36Sopenharmony_ci/* This function requires the caller holds hdev->lock */
123362306a36Sopenharmony_civoid hci_conn_failed(struct hci_conn *conn, u8 status)
123462306a36Sopenharmony_ci{
123562306a36Sopenharmony_ci	struct hci_dev *hdev = conn->hdev;
123662306a36Sopenharmony_ci
123762306a36Sopenharmony_ci	bt_dev_dbg(hdev, "status 0x%2.2x", status);
123862306a36Sopenharmony_ci
123962306a36Sopenharmony_ci	switch (conn->type) {
124062306a36Sopenharmony_ci	case LE_LINK:
124162306a36Sopenharmony_ci		hci_le_conn_failed(conn, status);
124262306a36Sopenharmony_ci		break;
124362306a36Sopenharmony_ci	case ACL_LINK:
124462306a36Sopenharmony_ci		mgmt_connect_failed(hdev, &conn->dst, conn->type,
124562306a36Sopenharmony_ci				    conn->dst_type, status);
124662306a36Sopenharmony_ci		break;
124762306a36Sopenharmony_ci	}
124862306a36Sopenharmony_ci
124962306a36Sopenharmony_ci	conn->state = BT_CLOSED;
125062306a36Sopenharmony_ci	hci_connect_cfm(conn, status);
125162306a36Sopenharmony_ci	hci_conn_del(conn);
125262306a36Sopenharmony_ci}
125362306a36Sopenharmony_ci
125462306a36Sopenharmony_ci/* This function requires the caller holds hdev->lock */
125562306a36Sopenharmony_ciu8 hci_conn_set_handle(struct hci_conn *conn, u16 handle)
125662306a36Sopenharmony_ci{
125762306a36Sopenharmony_ci	struct hci_dev *hdev = conn->hdev;
125862306a36Sopenharmony_ci
125962306a36Sopenharmony_ci	bt_dev_dbg(hdev, "hcon %p handle 0x%4.4x", conn, handle);
126062306a36Sopenharmony_ci
126162306a36Sopenharmony_ci	if (conn->handle == handle)
126262306a36Sopenharmony_ci		return 0;
126362306a36Sopenharmony_ci
126462306a36Sopenharmony_ci	if (handle > HCI_CONN_HANDLE_MAX) {
126562306a36Sopenharmony_ci		bt_dev_err(hdev, "Invalid handle: 0x%4.4x > 0x%4.4x",
126662306a36Sopenharmony_ci			   handle, HCI_CONN_HANDLE_MAX);
126762306a36Sopenharmony_ci		return HCI_ERROR_INVALID_PARAMETERS;
126862306a36Sopenharmony_ci	}
126962306a36Sopenharmony_ci
127062306a36Sopenharmony_ci	/* If abort_reason has been sent it means the connection is being
127162306a36Sopenharmony_ci	 * aborted and the handle shall not be changed.
127262306a36Sopenharmony_ci	 */
127362306a36Sopenharmony_ci	if (conn->abort_reason)
127462306a36Sopenharmony_ci		return conn->abort_reason;
127562306a36Sopenharmony_ci
127662306a36Sopenharmony_ci	if (HCI_CONN_HANDLE_UNSET(conn->handle))
127762306a36Sopenharmony_ci		ida_free(&hdev->unset_handle_ida, conn->handle);
127862306a36Sopenharmony_ci
127962306a36Sopenharmony_ci	conn->handle = handle;
128062306a36Sopenharmony_ci
128162306a36Sopenharmony_ci	return 0;
128262306a36Sopenharmony_ci}
128362306a36Sopenharmony_ci
128462306a36Sopenharmony_cistatic void create_le_conn_complete(struct hci_dev *hdev, void *data, int err)
128562306a36Sopenharmony_ci{
128662306a36Sopenharmony_ci	struct hci_conn *conn;
128762306a36Sopenharmony_ci	u16 handle = PTR_UINT(data);
128862306a36Sopenharmony_ci
128962306a36Sopenharmony_ci	conn = hci_conn_hash_lookup_handle(hdev, handle);
129062306a36Sopenharmony_ci	if (!conn)
129162306a36Sopenharmony_ci		return;
129262306a36Sopenharmony_ci
129362306a36Sopenharmony_ci	bt_dev_dbg(hdev, "err %d", err);
129462306a36Sopenharmony_ci
129562306a36Sopenharmony_ci	hci_dev_lock(hdev);
129662306a36Sopenharmony_ci
129762306a36Sopenharmony_ci	if (!err) {
129862306a36Sopenharmony_ci		hci_connect_le_scan_cleanup(conn, 0x00);
129962306a36Sopenharmony_ci		goto done;
130062306a36Sopenharmony_ci	}
130162306a36Sopenharmony_ci
130262306a36Sopenharmony_ci	/* Check if connection is still pending */
130362306a36Sopenharmony_ci	if (conn != hci_lookup_le_connect(hdev))
130462306a36Sopenharmony_ci		goto done;
130562306a36Sopenharmony_ci
130662306a36Sopenharmony_ci	/* Flush to make sure we send create conn cancel command if needed */
130762306a36Sopenharmony_ci	flush_delayed_work(&conn->le_conn_timeout);
130862306a36Sopenharmony_ci	hci_conn_failed(conn, bt_status(err));
130962306a36Sopenharmony_ci
131062306a36Sopenharmony_cidone:
131162306a36Sopenharmony_ci	hci_dev_unlock(hdev);
131262306a36Sopenharmony_ci}
131362306a36Sopenharmony_ci
131462306a36Sopenharmony_cistatic int hci_connect_le_sync(struct hci_dev *hdev, void *data)
131562306a36Sopenharmony_ci{
131662306a36Sopenharmony_ci	struct hci_conn *conn;
131762306a36Sopenharmony_ci	u16 handle = PTR_UINT(data);
131862306a36Sopenharmony_ci
131962306a36Sopenharmony_ci	conn = hci_conn_hash_lookup_handle(hdev, handle);
132062306a36Sopenharmony_ci	if (!conn)
132162306a36Sopenharmony_ci		return 0;
132262306a36Sopenharmony_ci
132362306a36Sopenharmony_ci	bt_dev_dbg(hdev, "conn %p", conn);
132462306a36Sopenharmony_ci
132562306a36Sopenharmony_ci	clear_bit(HCI_CONN_SCANNING, &conn->flags);
132662306a36Sopenharmony_ci	conn->state = BT_CONNECT;
132762306a36Sopenharmony_ci
132862306a36Sopenharmony_ci	return hci_le_create_conn_sync(hdev, conn);
132962306a36Sopenharmony_ci}
133062306a36Sopenharmony_ci
133162306a36Sopenharmony_cistruct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
133262306a36Sopenharmony_ci				u8 dst_type, bool dst_resolved, u8 sec_level,
133362306a36Sopenharmony_ci				u16 conn_timeout, u8 role)
133462306a36Sopenharmony_ci{
133562306a36Sopenharmony_ci	struct hci_conn *conn;
133662306a36Sopenharmony_ci	struct smp_irk *irk;
133762306a36Sopenharmony_ci	int err;
133862306a36Sopenharmony_ci
133962306a36Sopenharmony_ci	/* Let's make sure that le is enabled.*/
134062306a36Sopenharmony_ci	if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
134162306a36Sopenharmony_ci		if (lmp_le_capable(hdev))
134262306a36Sopenharmony_ci			return ERR_PTR(-ECONNREFUSED);
134362306a36Sopenharmony_ci
134462306a36Sopenharmony_ci		return ERR_PTR(-EOPNOTSUPP);
134562306a36Sopenharmony_ci	}
134662306a36Sopenharmony_ci
134762306a36Sopenharmony_ci	/* Since the controller supports only one LE connection attempt at a
134862306a36Sopenharmony_ci	 * time, we return -EBUSY if there is any connection attempt running.
134962306a36Sopenharmony_ci	 */
135062306a36Sopenharmony_ci	if (hci_lookup_le_connect(hdev))
135162306a36Sopenharmony_ci		return ERR_PTR(-EBUSY);
135262306a36Sopenharmony_ci
135362306a36Sopenharmony_ci	/* If there's already a connection object but it's not in
135462306a36Sopenharmony_ci	 * scanning state it means it must already be established, in
135562306a36Sopenharmony_ci	 * which case we can't do anything else except report a failure
135662306a36Sopenharmony_ci	 * to connect.
135762306a36Sopenharmony_ci	 */
135862306a36Sopenharmony_ci	conn = hci_conn_hash_lookup_le(hdev, dst, dst_type);
135962306a36Sopenharmony_ci	if (conn && !test_bit(HCI_CONN_SCANNING, &conn->flags)) {
136062306a36Sopenharmony_ci		return ERR_PTR(-EBUSY);
136162306a36Sopenharmony_ci	}
136262306a36Sopenharmony_ci
136362306a36Sopenharmony_ci	/* Check if the destination address has been resolved by the controller
136462306a36Sopenharmony_ci	 * since if it did then the identity address shall be used.
136562306a36Sopenharmony_ci	 */
136662306a36Sopenharmony_ci	if (!dst_resolved) {
136762306a36Sopenharmony_ci		/* When given an identity address with existing identity
136862306a36Sopenharmony_ci		 * resolving key, the connection needs to be established
136962306a36Sopenharmony_ci		 * to a resolvable random address.
137062306a36Sopenharmony_ci		 *
137162306a36Sopenharmony_ci		 * Storing the resolvable random address is required here
137262306a36Sopenharmony_ci		 * to handle connection failures. The address will later
137362306a36Sopenharmony_ci		 * be resolved back into the original identity address
137462306a36Sopenharmony_ci		 * from the connect request.
137562306a36Sopenharmony_ci		 */
137662306a36Sopenharmony_ci		irk = hci_find_irk_by_addr(hdev, dst, dst_type);
137762306a36Sopenharmony_ci		if (irk && bacmp(&irk->rpa, BDADDR_ANY)) {
137862306a36Sopenharmony_ci			dst = &irk->rpa;
137962306a36Sopenharmony_ci			dst_type = ADDR_LE_DEV_RANDOM;
138062306a36Sopenharmony_ci		}
138162306a36Sopenharmony_ci	}
138262306a36Sopenharmony_ci
138362306a36Sopenharmony_ci	if (conn) {
138462306a36Sopenharmony_ci		bacpy(&conn->dst, dst);
138562306a36Sopenharmony_ci	} else {
138662306a36Sopenharmony_ci		conn = hci_conn_add_unset(hdev, LE_LINK, dst, role);
138762306a36Sopenharmony_ci		if (!conn)
138862306a36Sopenharmony_ci			return ERR_PTR(-ENOMEM);
138962306a36Sopenharmony_ci		hci_conn_hold(conn);
139062306a36Sopenharmony_ci		conn->pending_sec_level = sec_level;
139162306a36Sopenharmony_ci	}
139262306a36Sopenharmony_ci
139362306a36Sopenharmony_ci	conn->dst_type = dst_type;
139462306a36Sopenharmony_ci	conn->sec_level = BT_SECURITY_LOW;
139562306a36Sopenharmony_ci	conn->conn_timeout = conn_timeout;
139662306a36Sopenharmony_ci
139762306a36Sopenharmony_ci	err = hci_cmd_sync_queue(hdev, hci_connect_le_sync,
139862306a36Sopenharmony_ci				 UINT_PTR(conn->handle),
139962306a36Sopenharmony_ci				 create_le_conn_complete);
140062306a36Sopenharmony_ci	if (err) {
140162306a36Sopenharmony_ci		hci_conn_del(conn);
140262306a36Sopenharmony_ci		return ERR_PTR(err);
140362306a36Sopenharmony_ci	}
140462306a36Sopenharmony_ci
140562306a36Sopenharmony_ci	return conn;
140662306a36Sopenharmony_ci}
140762306a36Sopenharmony_ci
140862306a36Sopenharmony_cistatic bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
140962306a36Sopenharmony_ci{
141062306a36Sopenharmony_ci	struct hci_conn *conn;
141162306a36Sopenharmony_ci
141262306a36Sopenharmony_ci	conn = hci_conn_hash_lookup_le(hdev, addr, type);
141362306a36Sopenharmony_ci	if (!conn)
141462306a36Sopenharmony_ci		return false;
141562306a36Sopenharmony_ci
141662306a36Sopenharmony_ci	if (conn->state != BT_CONNECTED)
141762306a36Sopenharmony_ci		return false;
141862306a36Sopenharmony_ci
141962306a36Sopenharmony_ci	return true;
142062306a36Sopenharmony_ci}
142162306a36Sopenharmony_ci
142262306a36Sopenharmony_ci/* This function requires the caller holds hdev->lock */
142362306a36Sopenharmony_cistatic int hci_explicit_conn_params_set(struct hci_dev *hdev,
142462306a36Sopenharmony_ci					bdaddr_t *addr, u8 addr_type)
142562306a36Sopenharmony_ci{
142662306a36Sopenharmony_ci	struct hci_conn_params *params;
142762306a36Sopenharmony_ci
142862306a36Sopenharmony_ci	if (is_connected(hdev, addr, addr_type))
142962306a36Sopenharmony_ci		return -EISCONN;
143062306a36Sopenharmony_ci
143162306a36Sopenharmony_ci	params = hci_conn_params_lookup(hdev, addr, addr_type);
143262306a36Sopenharmony_ci	if (!params) {
143362306a36Sopenharmony_ci		params = hci_conn_params_add(hdev, addr, addr_type);
143462306a36Sopenharmony_ci		if (!params)
143562306a36Sopenharmony_ci			return -ENOMEM;
143662306a36Sopenharmony_ci
143762306a36Sopenharmony_ci		/* If we created new params, mark them to be deleted in
143862306a36Sopenharmony_ci		 * hci_connect_le_scan_cleanup. It's different case than
143962306a36Sopenharmony_ci		 * existing disabled params, those will stay after cleanup.
144062306a36Sopenharmony_ci		 */
144162306a36Sopenharmony_ci		params->auto_connect = HCI_AUTO_CONN_EXPLICIT;
144262306a36Sopenharmony_ci	}
144362306a36Sopenharmony_ci
144462306a36Sopenharmony_ci	/* We're trying to connect, so make sure params are at pend_le_conns */
144562306a36Sopenharmony_ci	if (params->auto_connect == HCI_AUTO_CONN_DISABLED ||
144662306a36Sopenharmony_ci	    params->auto_connect == HCI_AUTO_CONN_REPORT ||
144762306a36Sopenharmony_ci	    params->auto_connect == HCI_AUTO_CONN_EXPLICIT) {
144862306a36Sopenharmony_ci		hci_pend_le_list_del_init(params);
144962306a36Sopenharmony_ci		hci_pend_le_list_add(params, &hdev->pend_le_conns);
145062306a36Sopenharmony_ci	}
145162306a36Sopenharmony_ci
145262306a36Sopenharmony_ci	params->explicit_connect = true;
145362306a36Sopenharmony_ci
145462306a36Sopenharmony_ci	BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
145562306a36Sopenharmony_ci	       params->auto_connect);
145662306a36Sopenharmony_ci
145762306a36Sopenharmony_ci	return 0;
145862306a36Sopenharmony_ci}
145962306a36Sopenharmony_ci
146062306a36Sopenharmony_cistatic int qos_set_big(struct hci_dev *hdev, struct bt_iso_qos *qos)
146162306a36Sopenharmony_ci{
146262306a36Sopenharmony_ci	struct hci_conn *conn;
146362306a36Sopenharmony_ci	u8  big;
146462306a36Sopenharmony_ci
146562306a36Sopenharmony_ci	/* Allocate a BIG if not set */
146662306a36Sopenharmony_ci	if (qos->bcast.big == BT_ISO_QOS_BIG_UNSET) {
146762306a36Sopenharmony_ci		for (big = 0x00; big < 0xef; big++) {
146862306a36Sopenharmony_ci
146962306a36Sopenharmony_ci			conn = hci_conn_hash_lookup_big(hdev, big);
147062306a36Sopenharmony_ci			if (!conn)
147162306a36Sopenharmony_ci				break;
147262306a36Sopenharmony_ci		}
147362306a36Sopenharmony_ci
147462306a36Sopenharmony_ci		if (big == 0xef)
147562306a36Sopenharmony_ci			return -EADDRNOTAVAIL;
147662306a36Sopenharmony_ci
147762306a36Sopenharmony_ci		/* Update BIG */
147862306a36Sopenharmony_ci		qos->bcast.big = big;
147962306a36Sopenharmony_ci	}
148062306a36Sopenharmony_ci
148162306a36Sopenharmony_ci	return 0;
148262306a36Sopenharmony_ci}
148362306a36Sopenharmony_ci
148462306a36Sopenharmony_cistatic int qos_set_bis(struct hci_dev *hdev, struct bt_iso_qos *qos)
148562306a36Sopenharmony_ci{
148662306a36Sopenharmony_ci	struct hci_conn *conn;
148762306a36Sopenharmony_ci	u8  bis;
148862306a36Sopenharmony_ci
148962306a36Sopenharmony_ci	/* Allocate BIS if not set */
149062306a36Sopenharmony_ci	if (qos->bcast.bis == BT_ISO_QOS_BIS_UNSET) {
149162306a36Sopenharmony_ci		/* Find an unused adv set to advertise BIS, skip instance 0x00
149262306a36Sopenharmony_ci		 * since it is reserved as general purpose set.
149362306a36Sopenharmony_ci		 */
149462306a36Sopenharmony_ci		for (bis = 0x01; bis < hdev->le_num_of_adv_sets;
149562306a36Sopenharmony_ci		     bis++) {
149662306a36Sopenharmony_ci
149762306a36Sopenharmony_ci			conn = hci_conn_hash_lookup_bis(hdev, BDADDR_ANY, bis);
149862306a36Sopenharmony_ci			if (!conn)
149962306a36Sopenharmony_ci				break;
150062306a36Sopenharmony_ci		}
150162306a36Sopenharmony_ci
150262306a36Sopenharmony_ci		if (bis == hdev->le_num_of_adv_sets)
150362306a36Sopenharmony_ci			return -EADDRNOTAVAIL;
150462306a36Sopenharmony_ci
150562306a36Sopenharmony_ci		/* Update BIS */
150662306a36Sopenharmony_ci		qos->bcast.bis = bis;
150762306a36Sopenharmony_ci	}
150862306a36Sopenharmony_ci
150962306a36Sopenharmony_ci	return 0;
151062306a36Sopenharmony_ci}
151162306a36Sopenharmony_ci
151262306a36Sopenharmony_ci/* This function requires the caller holds hdev->lock */
151362306a36Sopenharmony_cistatic struct hci_conn *hci_add_bis(struct hci_dev *hdev, bdaddr_t *dst,
151462306a36Sopenharmony_ci				    struct bt_iso_qos *qos, __u8 base_len,
151562306a36Sopenharmony_ci				    __u8 *base)
151662306a36Sopenharmony_ci{
151762306a36Sopenharmony_ci	struct hci_conn *conn;
151862306a36Sopenharmony_ci	int err;
151962306a36Sopenharmony_ci
152062306a36Sopenharmony_ci	/* Let's make sure that le is enabled.*/
152162306a36Sopenharmony_ci	if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
152262306a36Sopenharmony_ci		if (lmp_le_capable(hdev))
152362306a36Sopenharmony_ci			return ERR_PTR(-ECONNREFUSED);
152462306a36Sopenharmony_ci		return ERR_PTR(-EOPNOTSUPP);
152562306a36Sopenharmony_ci	}
152662306a36Sopenharmony_ci
152762306a36Sopenharmony_ci	err = qos_set_big(hdev, qos);
152862306a36Sopenharmony_ci	if (err)
152962306a36Sopenharmony_ci		return ERR_PTR(err);
153062306a36Sopenharmony_ci
153162306a36Sopenharmony_ci	err = qos_set_bis(hdev, qos);
153262306a36Sopenharmony_ci	if (err)
153362306a36Sopenharmony_ci		return ERR_PTR(err);
153462306a36Sopenharmony_ci
153562306a36Sopenharmony_ci	/* Check if the LE Create BIG command has already been sent */
153662306a36Sopenharmony_ci	conn = hci_conn_hash_lookup_per_adv_bis(hdev, dst, qos->bcast.big,
153762306a36Sopenharmony_ci						qos->bcast.big);
153862306a36Sopenharmony_ci	if (conn)
153962306a36Sopenharmony_ci		return ERR_PTR(-EADDRINUSE);
154062306a36Sopenharmony_ci
154162306a36Sopenharmony_ci	/* Check BIS settings against other bound BISes, since all
154262306a36Sopenharmony_ci	 * BISes in a BIG must have the same value for all parameters
154362306a36Sopenharmony_ci	 */
154462306a36Sopenharmony_ci	conn = hci_conn_hash_lookup_big(hdev, qos->bcast.big);
154562306a36Sopenharmony_ci
154662306a36Sopenharmony_ci	if (conn && (memcmp(qos, &conn->iso_qos, sizeof(*qos)) ||
154762306a36Sopenharmony_ci		     base_len != conn->le_per_adv_data_len ||
154862306a36Sopenharmony_ci		     memcmp(conn->le_per_adv_data, base, base_len)))
154962306a36Sopenharmony_ci		return ERR_PTR(-EADDRINUSE);
155062306a36Sopenharmony_ci
155162306a36Sopenharmony_ci	conn = hci_conn_add_unset(hdev, ISO_LINK, dst, HCI_ROLE_MASTER);
155262306a36Sopenharmony_ci	if (!conn)
155362306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
155462306a36Sopenharmony_ci
155562306a36Sopenharmony_ci	conn->state = BT_CONNECT;
155662306a36Sopenharmony_ci
155762306a36Sopenharmony_ci	hci_conn_hold(conn);
155862306a36Sopenharmony_ci	return conn;
155962306a36Sopenharmony_ci}
156062306a36Sopenharmony_ci
156162306a36Sopenharmony_ci/* This function requires the caller holds hdev->lock */
156262306a36Sopenharmony_cistruct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst,
156362306a36Sopenharmony_ci				     u8 dst_type, u8 sec_level,
156462306a36Sopenharmony_ci				     u16 conn_timeout,
156562306a36Sopenharmony_ci				     enum conn_reasons conn_reason)
156662306a36Sopenharmony_ci{
156762306a36Sopenharmony_ci	struct hci_conn *conn;
156862306a36Sopenharmony_ci
156962306a36Sopenharmony_ci	/* Let's make sure that le is enabled.*/
157062306a36Sopenharmony_ci	if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
157162306a36Sopenharmony_ci		if (lmp_le_capable(hdev))
157262306a36Sopenharmony_ci			return ERR_PTR(-ECONNREFUSED);
157362306a36Sopenharmony_ci
157462306a36Sopenharmony_ci		return ERR_PTR(-EOPNOTSUPP);
157562306a36Sopenharmony_ci	}
157662306a36Sopenharmony_ci
157762306a36Sopenharmony_ci	/* Some devices send ATT messages as soon as the physical link is
157862306a36Sopenharmony_ci	 * established. To be able to handle these ATT messages, the user-
157962306a36Sopenharmony_ci	 * space first establishes the connection and then starts the pairing
158062306a36Sopenharmony_ci	 * process.
158162306a36Sopenharmony_ci	 *
158262306a36Sopenharmony_ci	 * So if a hci_conn object already exists for the following connection
158362306a36Sopenharmony_ci	 * attempt, we simply update pending_sec_level and auth_type fields
158462306a36Sopenharmony_ci	 * and return the object found.
158562306a36Sopenharmony_ci	 */
158662306a36Sopenharmony_ci	conn = hci_conn_hash_lookup_le(hdev, dst, dst_type);
158762306a36Sopenharmony_ci	if (conn) {
158862306a36Sopenharmony_ci		if (conn->pending_sec_level < sec_level)
158962306a36Sopenharmony_ci			conn->pending_sec_level = sec_level;
159062306a36Sopenharmony_ci		goto done;
159162306a36Sopenharmony_ci	}
159262306a36Sopenharmony_ci
159362306a36Sopenharmony_ci	BT_DBG("requesting refresh of dst_addr");
159462306a36Sopenharmony_ci
159562306a36Sopenharmony_ci	conn = hci_conn_add_unset(hdev, LE_LINK, dst, HCI_ROLE_MASTER);
159662306a36Sopenharmony_ci	if (!conn)
159762306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
159862306a36Sopenharmony_ci
159962306a36Sopenharmony_ci	if (hci_explicit_conn_params_set(hdev, dst, dst_type) < 0) {
160062306a36Sopenharmony_ci		hci_conn_del(conn);
160162306a36Sopenharmony_ci		return ERR_PTR(-EBUSY);
160262306a36Sopenharmony_ci	}
160362306a36Sopenharmony_ci
160462306a36Sopenharmony_ci	conn->state = BT_CONNECT;
160562306a36Sopenharmony_ci	set_bit(HCI_CONN_SCANNING, &conn->flags);
160662306a36Sopenharmony_ci	conn->dst_type = dst_type;
160762306a36Sopenharmony_ci	conn->sec_level = BT_SECURITY_LOW;
160862306a36Sopenharmony_ci	conn->pending_sec_level = sec_level;
160962306a36Sopenharmony_ci	conn->conn_timeout = conn_timeout;
161062306a36Sopenharmony_ci	conn->conn_reason = conn_reason;
161162306a36Sopenharmony_ci
161262306a36Sopenharmony_ci	hci_update_passive_scan(hdev);
161362306a36Sopenharmony_ci
161462306a36Sopenharmony_cidone:
161562306a36Sopenharmony_ci	hci_conn_hold(conn);
161662306a36Sopenharmony_ci	return conn;
161762306a36Sopenharmony_ci}
161862306a36Sopenharmony_ci
161962306a36Sopenharmony_cistruct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
162062306a36Sopenharmony_ci				 u8 sec_level, u8 auth_type,
162162306a36Sopenharmony_ci				 enum conn_reasons conn_reason)
162262306a36Sopenharmony_ci{
162362306a36Sopenharmony_ci	struct hci_conn *acl;
162462306a36Sopenharmony_ci
162562306a36Sopenharmony_ci	if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
162662306a36Sopenharmony_ci		if (lmp_bredr_capable(hdev))
162762306a36Sopenharmony_ci			return ERR_PTR(-ECONNREFUSED);
162862306a36Sopenharmony_ci
162962306a36Sopenharmony_ci		return ERR_PTR(-EOPNOTSUPP);
163062306a36Sopenharmony_ci	}
163162306a36Sopenharmony_ci
163262306a36Sopenharmony_ci	/* Reject outgoing connection to device with same BD ADDR against
163362306a36Sopenharmony_ci	 * CVE-2020-26555
163462306a36Sopenharmony_ci	 */
163562306a36Sopenharmony_ci	if (!bacmp(&hdev->bdaddr, dst)) {
163662306a36Sopenharmony_ci		bt_dev_dbg(hdev, "Reject connection with same BD_ADDR %pMR\n",
163762306a36Sopenharmony_ci			   dst);
163862306a36Sopenharmony_ci		return ERR_PTR(-ECONNREFUSED);
163962306a36Sopenharmony_ci	}
164062306a36Sopenharmony_ci
164162306a36Sopenharmony_ci	acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
164262306a36Sopenharmony_ci	if (!acl) {
164362306a36Sopenharmony_ci		acl = hci_conn_add_unset(hdev, ACL_LINK, dst, HCI_ROLE_MASTER);
164462306a36Sopenharmony_ci		if (!acl)
164562306a36Sopenharmony_ci			return ERR_PTR(-ENOMEM);
164662306a36Sopenharmony_ci	}
164762306a36Sopenharmony_ci
164862306a36Sopenharmony_ci	hci_conn_hold(acl);
164962306a36Sopenharmony_ci
165062306a36Sopenharmony_ci	acl->conn_reason = conn_reason;
165162306a36Sopenharmony_ci	if (acl->state == BT_OPEN || acl->state == BT_CLOSED) {
165262306a36Sopenharmony_ci		acl->sec_level = BT_SECURITY_LOW;
165362306a36Sopenharmony_ci		acl->pending_sec_level = sec_level;
165462306a36Sopenharmony_ci		acl->auth_type = auth_type;
165562306a36Sopenharmony_ci		hci_acl_create_connection(acl);
165662306a36Sopenharmony_ci	}
165762306a36Sopenharmony_ci
165862306a36Sopenharmony_ci	return acl;
165962306a36Sopenharmony_ci}
166062306a36Sopenharmony_ci
166162306a36Sopenharmony_cistatic struct hci_link *hci_conn_link(struct hci_conn *parent,
166262306a36Sopenharmony_ci				      struct hci_conn *conn)
166362306a36Sopenharmony_ci{
166462306a36Sopenharmony_ci	struct hci_dev *hdev = parent->hdev;
166562306a36Sopenharmony_ci	struct hci_link *link;
166662306a36Sopenharmony_ci
166762306a36Sopenharmony_ci	bt_dev_dbg(hdev, "parent %p hcon %p", parent, conn);
166862306a36Sopenharmony_ci
166962306a36Sopenharmony_ci	if (conn->link)
167062306a36Sopenharmony_ci		return conn->link;
167162306a36Sopenharmony_ci
167262306a36Sopenharmony_ci	if (conn->parent)
167362306a36Sopenharmony_ci		return NULL;
167462306a36Sopenharmony_ci
167562306a36Sopenharmony_ci	link = kzalloc(sizeof(*link), GFP_KERNEL);
167662306a36Sopenharmony_ci	if (!link)
167762306a36Sopenharmony_ci		return NULL;
167862306a36Sopenharmony_ci
167962306a36Sopenharmony_ci	link->conn = hci_conn_hold(conn);
168062306a36Sopenharmony_ci	conn->link = link;
168162306a36Sopenharmony_ci	conn->parent = hci_conn_get(parent);
168262306a36Sopenharmony_ci
168362306a36Sopenharmony_ci	/* Use list_add_tail_rcu append to the list */
168462306a36Sopenharmony_ci	list_add_tail_rcu(&link->list, &parent->link_list);
168562306a36Sopenharmony_ci
168662306a36Sopenharmony_ci	return link;
168762306a36Sopenharmony_ci}
168862306a36Sopenharmony_ci
168962306a36Sopenharmony_cistruct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
169062306a36Sopenharmony_ci				 __u16 setting, struct bt_codec *codec)
169162306a36Sopenharmony_ci{
169262306a36Sopenharmony_ci	struct hci_conn *acl;
169362306a36Sopenharmony_ci	struct hci_conn *sco;
169462306a36Sopenharmony_ci	struct hci_link *link;
169562306a36Sopenharmony_ci
169662306a36Sopenharmony_ci	acl = hci_connect_acl(hdev, dst, BT_SECURITY_LOW, HCI_AT_NO_BONDING,
169762306a36Sopenharmony_ci			      CONN_REASON_SCO_CONNECT);
169862306a36Sopenharmony_ci	if (IS_ERR(acl))
169962306a36Sopenharmony_ci		return acl;
170062306a36Sopenharmony_ci
170162306a36Sopenharmony_ci	sco = hci_conn_hash_lookup_ba(hdev, type, dst);
170262306a36Sopenharmony_ci	if (!sco) {
170362306a36Sopenharmony_ci		sco = hci_conn_add_unset(hdev, type, dst, HCI_ROLE_MASTER);
170462306a36Sopenharmony_ci		if (!sco) {
170562306a36Sopenharmony_ci			hci_conn_drop(acl);
170662306a36Sopenharmony_ci			return ERR_PTR(-ENOMEM);
170762306a36Sopenharmony_ci		}
170862306a36Sopenharmony_ci	}
170962306a36Sopenharmony_ci
171062306a36Sopenharmony_ci	link = hci_conn_link(acl, sco);
171162306a36Sopenharmony_ci	if (!link) {
171262306a36Sopenharmony_ci		hci_conn_drop(acl);
171362306a36Sopenharmony_ci		hci_conn_drop(sco);
171462306a36Sopenharmony_ci		return ERR_PTR(-ENOLINK);
171562306a36Sopenharmony_ci	}
171662306a36Sopenharmony_ci
171762306a36Sopenharmony_ci	sco->setting = setting;
171862306a36Sopenharmony_ci	sco->codec = *codec;
171962306a36Sopenharmony_ci
172062306a36Sopenharmony_ci	if (acl->state == BT_CONNECTED &&
172162306a36Sopenharmony_ci	    (sco->state == BT_OPEN || sco->state == BT_CLOSED)) {
172262306a36Sopenharmony_ci		set_bit(HCI_CONN_POWER_SAVE, &acl->flags);
172362306a36Sopenharmony_ci		hci_conn_enter_active_mode(acl, BT_POWER_FORCE_ACTIVE_ON);
172462306a36Sopenharmony_ci
172562306a36Sopenharmony_ci		if (test_bit(HCI_CONN_MODE_CHANGE_PEND, &acl->flags)) {
172662306a36Sopenharmony_ci			/* defer SCO setup until mode change completed */
172762306a36Sopenharmony_ci			set_bit(HCI_CONN_SCO_SETUP_PEND, &acl->flags);
172862306a36Sopenharmony_ci			return sco;
172962306a36Sopenharmony_ci		}
173062306a36Sopenharmony_ci
173162306a36Sopenharmony_ci		hci_sco_setup(acl, 0x00);
173262306a36Sopenharmony_ci	}
173362306a36Sopenharmony_ci
173462306a36Sopenharmony_ci	return sco;
173562306a36Sopenharmony_ci}
173662306a36Sopenharmony_ci
173762306a36Sopenharmony_cistatic int hci_le_create_big(struct hci_conn *conn, struct bt_iso_qos *qos)
173862306a36Sopenharmony_ci{
173962306a36Sopenharmony_ci	struct hci_dev *hdev = conn->hdev;
174062306a36Sopenharmony_ci	struct hci_cp_le_create_big cp;
174162306a36Sopenharmony_ci	struct iso_list_data data;
174262306a36Sopenharmony_ci
174362306a36Sopenharmony_ci	memset(&cp, 0, sizeof(cp));
174462306a36Sopenharmony_ci
174562306a36Sopenharmony_ci	data.big = qos->bcast.big;
174662306a36Sopenharmony_ci	data.bis = qos->bcast.bis;
174762306a36Sopenharmony_ci	data.count = 0;
174862306a36Sopenharmony_ci
174962306a36Sopenharmony_ci	/* Create a BIS for each bound connection */
175062306a36Sopenharmony_ci	hci_conn_hash_list_state(hdev, bis_list, ISO_LINK,
175162306a36Sopenharmony_ci				 BT_BOUND, &data);
175262306a36Sopenharmony_ci
175362306a36Sopenharmony_ci	cp.handle = qos->bcast.big;
175462306a36Sopenharmony_ci	cp.adv_handle = qos->bcast.bis;
175562306a36Sopenharmony_ci	cp.num_bis  = data.count;
175662306a36Sopenharmony_ci	hci_cpu_to_le24(qos->bcast.out.interval, cp.bis.sdu_interval);
175762306a36Sopenharmony_ci	cp.bis.sdu = cpu_to_le16(qos->bcast.out.sdu);
175862306a36Sopenharmony_ci	cp.bis.latency =  cpu_to_le16(qos->bcast.out.latency);
175962306a36Sopenharmony_ci	cp.bis.rtn  = qos->bcast.out.rtn;
176062306a36Sopenharmony_ci	cp.bis.phy  = qos->bcast.out.phy;
176162306a36Sopenharmony_ci	cp.bis.packing = qos->bcast.packing;
176262306a36Sopenharmony_ci	cp.bis.framing = qos->bcast.framing;
176362306a36Sopenharmony_ci	cp.bis.encryption = qos->bcast.encryption;
176462306a36Sopenharmony_ci	memcpy(cp.bis.bcode, qos->bcast.bcode, sizeof(cp.bis.bcode));
176562306a36Sopenharmony_ci
176662306a36Sopenharmony_ci	return hci_send_cmd(hdev, HCI_OP_LE_CREATE_BIG, sizeof(cp), &cp);
176762306a36Sopenharmony_ci}
176862306a36Sopenharmony_ci
176962306a36Sopenharmony_cistatic int set_cig_params_sync(struct hci_dev *hdev, void *data)
177062306a36Sopenharmony_ci{
177162306a36Sopenharmony_ci	u8 cig_id = PTR_UINT(data);
177262306a36Sopenharmony_ci	struct hci_conn *conn;
177362306a36Sopenharmony_ci	struct bt_iso_qos *qos;
177462306a36Sopenharmony_ci	struct iso_cig_params pdu;
177562306a36Sopenharmony_ci	u8 cis_id;
177662306a36Sopenharmony_ci
177762306a36Sopenharmony_ci	conn = hci_conn_hash_lookup_cig(hdev, cig_id);
177862306a36Sopenharmony_ci	if (!conn)
177962306a36Sopenharmony_ci		return 0;
178062306a36Sopenharmony_ci
178162306a36Sopenharmony_ci	memset(&pdu, 0, sizeof(pdu));
178262306a36Sopenharmony_ci
178362306a36Sopenharmony_ci	qos = &conn->iso_qos;
178462306a36Sopenharmony_ci	pdu.cp.cig_id = cig_id;
178562306a36Sopenharmony_ci	hci_cpu_to_le24(qos->ucast.out.interval, pdu.cp.c_interval);
178662306a36Sopenharmony_ci	hci_cpu_to_le24(qos->ucast.in.interval, pdu.cp.p_interval);
178762306a36Sopenharmony_ci	pdu.cp.sca = qos->ucast.sca;
178862306a36Sopenharmony_ci	pdu.cp.packing = qos->ucast.packing;
178962306a36Sopenharmony_ci	pdu.cp.framing = qos->ucast.framing;
179062306a36Sopenharmony_ci	pdu.cp.c_latency = cpu_to_le16(qos->ucast.out.latency);
179162306a36Sopenharmony_ci	pdu.cp.p_latency = cpu_to_le16(qos->ucast.in.latency);
179262306a36Sopenharmony_ci
179362306a36Sopenharmony_ci	/* Reprogram all CIS(s) with the same CIG, valid range are:
179462306a36Sopenharmony_ci	 * num_cis: 0x00 to 0x1F
179562306a36Sopenharmony_ci	 * cis_id: 0x00 to 0xEF
179662306a36Sopenharmony_ci	 */
179762306a36Sopenharmony_ci	for (cis_id = 0x00; cis_id < 0xf0 &&
179862306a36Sopenharmony_ci	     pdu.cp.num_cis < ARRAY_SIZE(pdu.cis); cis_id++) {
179962306a36Sopenharmony_ci		struct hci_cis_params *cis;
180062306a36Sopenharmony_ci
180162306a36Sopenharmony_ci		conn = hci_conn_hash_lookup_cis(hdev, NULL, 0, cig_id, cis_id);
180262306a36Sopenharmony_ci		if (!conn)
180362306a36Sopenharmony_ci			continue;
180462306a36Sopenharmony_ci
180562306a36Sopenharmony_ci		qos = &conn->iso_qos;
180662306a36Sopenharmony_ci
180762306a36Sopenharmony_ci		cis = &pdu.cis[pdu.cp.num_cis++];
180862306a36Sopenharmony_ci		cis->cis_id = cis_id;
180962306a36Sopenharmony_ci		cis->c_sdu  = cpu_to_le16(conn->iso_qos.ucast.out.sdu);
181062306a36Sopenharmony_ci		cis->p_sdu  = cpu_to_le16(conn->iso_qos.ucast.in.sdu);
181162306a36Sopenharmony_ci		cis->c_phy  = qos->ucast.out.phy ? qos->ucast.out.phy :
181262306a36Sopenharmony_ci			      qos->ucast.in.phy;
181362306a36Sopenharmony_ci		cis->p_phy  = qos->ucast.in.phy ? qos->ucast.in.phy :
181462306a36Sopenharmony_ci			      qos->ucast.out.phy;
181562306a36Sopenharmony_ci		cis->c_rtn  = qos->ucast.out.rtn;
181662306a36Sopenharmony_ci		cis->p_rtn  = qos->ucast.in.rtn;
181762306a36Sopenharmony_ci	}
181862306a36Sopenharmony_ci
181962306a36Sopenharmony_ci	if (!pdu.cp.num_cis)
182062306a36Sopenharmony_ci		return 0;
182162306a36Sopenharmony_ci
182262306a36Sopenharmony_ci	return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_CIG_PARAMS,
182362306a36Sopenharmony_ci				     sizeof(pdu.cp) +
182462306a36Sopenharmony_ci				     pdu.cp.num_cis * sizeof(pdu.cis[0]), &pdu,
182562306a36Sopenharmony_ci				     HCI_CMD_TIMEOUT);
182662306a36Sopenharmony_ci}
182762306a36Sopenharmony_ci
182862306a36Sopenharmony_cistatic bool hci_le_set_cig_params(struct hci_conn *conn, struct bt_iso_qos *qos)
182962306a36Sopenharmony_ci{
183062306a36Sopenharmony_ci	struct hci_dev *hdev = conn->hdev;
183162306a36Sopenharmony_ci	struct iso_list_data data;
183262306a36Sopenharmony_ci
183362306a36Sopenharmony_ci	memset(&data, 0, sizeof(data));
183462306a36Sopenharmony_ci
183562306a36Sopenharmony_ci	/* Allocate first still reconfigurable CIG if not set */
183662306a36Sopenharmony_ci	if (qos->ucast.cig == BT_ISO_QOS_CIG_UNSET) {
183762306a36Sopenharmony_ci		for (data.cig = 0x00; data.cig < 0xf0; data.cig++) {
183862306a36Sopenharmony_ci			data.count = 0;
183962306a36Sopenharmony_ci
184062306a36Sopenharmony_ci			hci_conn_hash_list_state(hdev, find_cis, ISO_LINK,
184162306a36Sopenharmony_ci						 BT_CONNECT, &data);
184262306a36Sopenharmony_ci			if (data.count)
184362306a36Sopenharmony_ci				continue;
184462306a36Sopenharmony_ci
184562306a36Sopenharmony_ci			hci_conn_hash_list_state(hdev, find_cis, ISO_LINK,
184662306a36Sopenharmony_ci						 BT_CONNECTED, &data);
184762306a36Sopenharmony_ci			if (!data.count)
184862306a36Sopenharmony_ci				break;
184962306a36Sopenharmony_ci		}
185062306a36Sopenharmony_ci
185162306a36Sopenharmony_ci		if (data.cig == 0xf0)
185262306a36Sopenharmony_ci			return false;
185362306a36Sopenharmony_ci
185462306a36Sopenharmony_ci		/* Update CIG */
185562306a36Sopenharmony_ci		qos->ucast.cig = data.cig;
185662306a36Sopenharmony_ci	}
185762306a36Sopenharmony_ci
185862306a36Sopenharmony_ci	if (qos->ucast.cis != BT_ISO_QOS_CIS_UNSET) {
185962306a36Sopenharmony_ci		if (hci_conn_hash_lookup_cis(hdev, NULL, 0, qos->ucast.cig,
186062306a36Sopenharmony_ci					     qos->ucast.cis))
186162306a36Sopenharmony_ci			return false;
186262306a36Sopenharmony_ci		goto done;
186362306a36Sopenharmony_ci	}
186462306a36Sopenharmony_ci
186562306a36Sopenharmony_ci	/* Allocate first available CIS if not set */
186662306a36Sopenharmony_ci	for (data.cig = qos->ucast.cig, data.cis = 0x00; data.cis < 0xf0;
186762306a36Sopenharmony_ci	     data.cis++) {
186862306a36Sopenharmony_ci		if (!hci_conn_hash_lookup_cis(hdev, NULL, 0, data.cig,
186962306a36Sopenharmony_ci					      data.cis)) {
187062306a36Sopenharmony_ci			/* Update CIS */
187162306a36Sopenharmony_ci			qos->ucast.cis = data.cis;
187262306a36Sopenharmony_ci			break;
187362306a36Sopenharmony_ci		}
187462306a36Sopenharmony_ci	}
187562306a36Sopenharmony_ci
187662306a36Sopenharmony_ci	if (qos->ucast.cis == BT_ISO_QOS_CIS_UNSET)
187762306a36Sopenharmony_ci		return false;
187862306a36Sopenharmony_ci
187962306a36Sopenharmony_cidone:
188062306a36Sopenharmony_ci	if (hci_cmd_sync_queue(hdev, set_cig_params_sync,
188162306a36Sopenharmony_ci			       UINT_PTR(qos->ucast.cig), NULL) < 0)
188262306a36Sopenharmony_ci		return false;
188362306a36Sopenharmony_ci
188462306a36Sopenharmony_ci	return true;
188562306a36Sopenharmony_ci}
188662306a36Sopenharmony_ci
188762306a36Sopenharmony_cistruct hci_conn *hci_bind_cis(struct hci_dev *hdev, bdaddr_t *dst,
188862306a36Sopenharmony_ci			      __u8 dst_type, struct bt_iso_qos *qos)
188962306a36Sopenharmony_ci{
189062306a36Sopenharmony_ci	struct hci_conn *cis;
189162306a36Sopenharmony_ci
189262306a36Sopenharmony_ci	cis = hci_conn_hash_lookup_cis(hdev, dst, dst_type, qos->ucast.cig,
189362306a36Sopenharmony_ci				       qos->ucast.cis);
189462306a36Sopenharmony_ci	if (!cis) {
189562306a36Sopenharmony_ci		cis = hci_conn_add_unset(hdev, ISO_LINK, dst, HCI_ROLE_MASTER);
189662306a36Sopenharmony_ci		if (!cis)
189762306a36Sopenharmony_ci			return ERR_PTR(-ENOMEM);
189862306a36Sopenharmony_ci		cis->cleanup = cis_cleanup;
189962306a36Sopenharmony_ci		cis->dst_type = dst_type;
190062306a36Sopenharmony_ci		cis->iso_qos.ucast.cig = BT_ISO_QOS_CIG_UNSET;
190162306a36Sopenharmony_ci		cis->iso_qos.ucast.cis = BT_ISO_QOS_CIS_UNSET;
190262306a36Sopenharmony_ci	}
190362306a36Sopenharmony_ci
190462306a36Sopenharmony_ci	if (cis->state == BT_CONNECTED)
190562306a36Sopenharmony_ci		return cis;
190662306a36Sopenharmony_ci
190762306a36Sopenharmony_ci	/* Check if CIS has been set and the settings matches */
190862306a36Sopenharmony_ci	if (cis->state == BT_BOUND &&
190962306a36Sopenharmony_ci	    !memcmp(&cis->iso_qos, qos, sizeof(*qos)))
191062306a36Sopenharmony_ci		return cis;
191162306a36Sopenharmony_ci
191262306a36Sopenharmony_ci	/* Update LINK PHYs according to QoS preference */
191362306a36Sopenharmony_ci	cis->le_tx_phy = qos->ucast.out.phy;
191462306a36Sopenharmony_ci	cis->le_rx_phy = qos->ucast.in.phy;
191562306a36Sopenharmony_ci
191662306a36Sopenharmony_ci	/* If output interval is not set use the input interval as it cannot be
191762306a36Sopenharmony_ci	 * 0x000000.
191862306a36Sopenharmony_ci	 */
191962306a36Sopenharmony_ci	if (!qos->ucast.out.interval)
192062306a36Sopenharmony_ci		qos->ucast.out.interval = qos->ucast.in.interval;
192162306a36Sopenharmony_ci
192262306a36Sopenharmony_ci	/* If input interval is not set use the output interval as it cannot be
192362306a36Sopenharmony_ci	 * 0x000000.
192462306a36Sopenharmony_ci	 */
192562306a36Sopenharmony_ci	if (!qos->ucast.in.interval)
192662306a36Sopenharmony_ci		qos->ucast.in.interval = qos->ucast.out.interval;
192762306a36Sopenharmony_ci
192862306a36Sopenharmony_ci	/* If output latency is not set use the input latency as it cannot be
192962306a36Sopenharmony_ci	 * 0x0000.
193062306a36Sopenharmony_ci	 */
193162306a36Sopenharmony_ci	if (!qos->ucast.out.latency)
193262306a36Sopenharmony_ci		qos->ucast.out.latency = qos->ucast.in.latency;
193362306a36Sopenharmony_ci
193462306a36Sopenharmony_ci	/* If input latency is not set use the output latency as it cannot be
193562306a36Sopenharmony_ci	 * 0x0000.
193662306a36Sopenharmony_ci	 */
193762306a36Sopenharmony_ci	if (!qos->ucast.in.latency)
193862306a36Sopenharmony_ci		qos->ucast.in.latency = qos->ucast.out.latency;
193962306a36Sopenharmony_ci
194062306a36Sopenharmony_ci	if (!hci_le_set_cig_params(cis, qos)) {
194162306a36Sopenharmony_ci		hci_conn_drop(cis);
194262306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
194362306a36Sopenharmony_ci	}
194462306a36Sopenharmony_ci
194562306a36Sopenharmony_ci	hci_conn_hold(cis);
194662306a36Sopenharmony_ci
194762306a36Sopenharmony_ci	cis->iso_qos = *qos;
194862306a36Sopenharmony_ci	cis->state = BT_BOUND;
194962306a36Sopenharmony_ci
195062306a36Sopenharmony_ci	return cis;
195162306a36Sopenharmony_ci}
195262306a36Sopenharmony_ci
195362306a36Sopenharmony_cibool hci_iso_setup_path(struct hci_conn *conn)
195462306a36Sopenharmony_ci{
195562306a36Sopenharmony_ci	struct hci_dev *hdev = conn->hdev;
195662306a36Sopenharmony_ci	struct hci_cp_le_setup_iso_path cmd;
195762306a36Sopenharmony_ci
195862306a36Sopenharmony_ci	memset(&cmd, 0, sizeof(cmd));
195962306a36Sopenharmony_ci
196062306a36Sopenharmony_ci	if (conn->iso_qos.ucast.out.sdu) {
196162306a36Sopenharmony_ci		cmd.handle = cpu_to_le16(conn->handle);
196262306a36Sopenharmony_ci		cmd.direction = 0x00; /* Input (Host to Controller) */
196362306a36Sopenharmony_ci		cmd.path = 0x00; /* HCI path if enabled */
196462306a36Sopenharmony_ci		cmd.codec = 0x03; /* Transparent Data */
196562306a36Sopenharmony_ci
196662306a36Sopenharmony_ci		if (hci_send_cmd(hdev, HCI_OP_LE_SETUP_ISO_PATH, sizeof(cmd),
196762306a36Sopenharmony_ci				 &cmd) < 0)
196862306a36Sopenharmony_ci			return false;
196962306a36Sopenharmony_ci	}
197062306a36Sopenharmony_ci
197162306a36Sopenharmony_ci	if (conn->iso_qos.ucast.in.sdu) {
197262306a36Sopenharmony_ci		cmd.handle = cpu_to_le16(conn->handle);
197362306a36Sopenharmony_ci		cmd.direction = 0x01; /* Output (Controller to Host) */
197462306a36Sopenharmony_ci		cmd.path = 0x00; /* HCI path if enabled */
197562306a36Sopenharmony_ci		cmd.codec = 0x03; /* Transparent Data */
197662306a36Sopenharmony_ci
197762306a36Sopenharmony_ci		if (hci_send_cmd(hdev, HCI_OP_LE_SETUP_ISO_PATH, sizeof(cmd),
197862306a36Sopenharmony_ci				 &cmd) < 0)
197962306a36Sopenharmony_ci			return false;
198062306a36Sopenharmony_ci	}
198162306a36Sopenharmony_ci
198262306a36Sopenharmony_ci	return true;
198362306a36Sopenharmony_ci}
198462306a36Sopenharmony_ci
198562306a36Sopenharmony_ciint hci_conn_check_create_cis(struct hci_conn *conn)
198662306a36Sopenharmony_ci{
198762306a36Sopenharmony_ci	if (conn->type != ISO_LINK || !bacmp(&conn->dst, BDADDR_ANY))
198862306a36Sopenharmony_ci		return -EINVAL;
198962306a36Sopenharmony_ci
199062306a36Sopenharmony_ci	if (!conn->parent || conn->parent->state != BT_CONNECTED ||
199162306a36Sopenharmony_ci	    conn->state != BT_CONNECT || HCI_CONN_HANDLE_UNSET(conn->handle))
199262306a36Sopenharmony_ci		return 1;
199362306a36Sopenharmony_ci
199462306a36Sopenharmony_ci	return 0;
199562306a36Sopenharmony_ci}
199662306a36Sopenharmony_ci
199762306a36Sopenharmony_cistatic int hci_create_cis_sync(struct hci_dev *hdev, void *data)
199862306a36Sopenharmony_ci{
199962306a36Sopenharmony_ci	return hci_le_create_cis_sync(hdev);
200062306a36Sopenharmony_ci}
200162306a36Sopenharmony_ci
200262306a36Sopenharmony_ciint hci_le_create_cis_pending(struct hci_dev *hdev)
200362306a36Sopenharmony_ci{
200462306a36Sopenharmony_ci	struct hci_conn *conn;
200562306a36Sopenharmony_ci	bool pending = false;
200662306a36Sopenharmony_ci
200762306a36Sopenharmony_ci	rcu_read_lock();
200862306a36Sopenharmony_ci
200962306a36Sopenharmony_ci	list_for_each_entry_rcu(conn, &hdev->conn_hash.list, list) {
201062306a36Sopenharmony_ci		if (test_bit(HCI_CONN_CREATE_CIS, &conn->flags)) {
201162306a36Sopenharmony_ci			rcu_read_unlock();
201262306a36Sopenharmony_ci			return -EBUSY;
201362306a36Sopenharmony_ci		}
201462306a36Sopenharmony_ci
201562306a36Sopenharmony_ci		if (!hci_conn_check_create_cis(conn))
201662306a36Sopenharmony_ci			pending = true;
201762306a36Sopenharmony_ci	}
201862306a36Sopenharmony_ci
201962306a36Sopenharmony_ci	rcu_read_unlock();
202062306a36Sopenharmony_ci
202162306a36Sopenharmony_ci	if (!pending)
202262306a36Sopenharmony_ci		return 0;
202362306a36Sopenharmony_ci
202462306a36Sopenharmony_ci	/* Queue Create CIS */
202562306a36Sopenharmony_ci	return hci_cmd_sync_queue(hdev, hci_create_cis_sync, NULL, NULL);
202662306a36Sopenharmony_ci}
202762306a36Sopenharmony_ci
202862306a36Sopenharmony_cistatic void hci_iso_qos_setup(struct hci_dev *hdev, struct hci_conn *conn,
202962306a36Sopenharmony_ci			      struct bt_iso_io_qos *qos, __u8 phy)
203062306a36Sopenharmony_ci{
203162306a36Sopenharmony_ci	/* Only set MTU if PHY is enabled */
203262306a36Sopenharmony_ci	if (!qos->sdu && qos->phy) {
203362306a36Sopenharmony_ci		if (hdev->iso_mtu > 0)
203462306a36Sopenharmony_ci			qos->sdu = hdev->iso_mtu;
203562306a36Sopenharmony_ci		else if (hdev->le_mtu > 0)
203662306a36Sopenharmony_ci			qos->sdu = hdev->le_mtu;
203762306a36Sopenharmony_ci		else
203862306a36Sopenharmony_ci			qos->sdu = hdev->acl_mtu;
203962306a36Sopenharmony_ci	}
204062306a36Sopenharmony_ci
204162306a36Sopenharmony_ci	/* Use the same PHY as ACL if set to any */
204262306a36Sopenharmony_ci	if (qos->phy == BT_ISO_PHY_ANY)
204362306a36Sopenharmony_ci		qos->phy = phy;
204462306a36Sopenharmony_ci
204562306a36Sopenharmony_ci	/* Use LE ACL connection interval if not set */
204662306a36Sopenharmony_ci	if (!qos->interval)
204762306a36Sopenharmony_ci		/* ACL interval unit in 1.25 ms to us */
204862306a36Sopenharmony_ci		qos->interval = conn->le_conn_interval * 1250;
204962306a36Sopenharmony_ci
205062306a36Sopenharmony_ci	/* Use LE ACL connection latency if not set */
205162306a36Sopenharmony_ci	if (!qos->latency)
205262306a36Sopenharmony_ci		qos->latency = conn->le_conn_latency;
205362306a36Sopenharmony_ci}
205462306a36Sopenharmony_ci
205562306a36Sopenharmony_cistatic int create_big_sync(struct hci_dev *hdev, void *data)
205662306a36Sopenharmony_ci{
205762306a36Sopenharmony_ci	struct hci_conn *conn = data;
205862306a36Sopenharmony_ci	struct bt_iso_qos *qos = &conn->iso_qos;
205962306a36Sopenharmony_ci	u16 interval, sync_interval = 0;
206062306a36Sopenharmony_ci	u32 flags = 0;
206162306a36Sopenharmony_ci	int err;
206262306a36Sopenharmony_ci
206362306a36Sopenharmony_ci	if (qos->bcast.out.phy == 0x02)
206462306a36Sopenharmony_ci		flags |= MGMT_ADV_FLAG_SEC_2M;
206562306a36Sopenharmony_ci
206662306a36Sopenharmony_ci	/* Align intervals */
206762306a36Sopenharmony_ci	interval = (qos->bcast.out.interval / 1250) * qos->bcast.sync_factor;
206862306a36Sopenharmony_ci
206962306a36Sopenharmony_ci	if (qos->bcast.bis)
207062306a36Sopenharmony_ci		sync_interval = interval * 4;
207162306a36Sopenharmony_ci
207262306a36Sopenharmony_ci	err = hci_start_per_adv_sync(hdev, qos->bcast.bis, conn->le_per_adv_data_len,
207362306a36Sopenharmony_ci				     conn->le_per_adv_data, flags, interval,
207462306a36Sopenharmony_ci				     interval, sync_interval);
207562306a36Sopenharmony_ci	if (err)
207662306a36Sopenharmony_ci		return err;
207762306a36Sopenharmony_ci
207862306a36Sopenharmony_ci	return hci_le_create_big(conn, &conn->iso_qos);
207962306a36Sopenharmony_ci}
208062306a36Sopenharmony_ci
208162306a36Sopenharmony_cistatic void create_pa_complete(struct hci_dev *hdev, void *data, int err)
208262306a36Sopenharmony_ci{
208362306a36Sopenharmony_ci	struct hci_cp_le_pa_create_sync *cp = data;
208462306a36Sopenharmony_ci
208562306a36Sopenharmony_ci	bt_dev_dbg(hdev, "");
208662306a36Sopenharmony_ci
208762306a36Sopenharmony_ci	if (err)
208862306a36Sopenharmony_ci		bt_dev_err(hdev, "Unable to create PA: %d", err);
208962306a36Sopenharmony_ci
209062306a36Sopenharmony_ci	kfree(cp);
209162306a36Sopenharmony_ci}
209262306a36Sopenharmony_ci
209362306a36Sopenharmony_cistatic int create_pa_sync(struct hci_dev *hdev, void *data)
209462306a36Sopenharmony_ci{
209562306a36Sopenharmony_ci	struct hci_cp_le_pa_create_sync *cp = data;
209662306a36Sopenharmony_ci	int err;
209762306a36Sopenharmony_ci
209862306a36Sopenharmony_ci	err = __hci_cmd_sync_status(hdev, HCI_OP_LE_PA_CREATE_SYNC,
209962306a36Sopenharmony_ci				    sizeof(*cp), cp, HCI_CMD_TIMEOUT);
210062306a36Sopenharmony_ci	if (err) {
210162306a36Sopenharmony_ci		hci_dev_clear_flag(hdev, HCI_PA_SYNC);
210262306a36Sopenharmony_ci		return err;
210362306a36Sopenharmony_ci	}
210462306a36Sopenharmony_ci
210562306a36Sopenharmony_ci	return hci_update_passive_scan_sync(hdev);
210662306a36Sopenharmony_ci}
210762306a36Sopenharmony_ci
210862306a36Sopenharmony_ciint hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst, __u8 dst_type,
210962306a36Sopenharmony_ci		       __u8 sid, struct bt_iso_qos *qos)
211062306a36Sopenharmony_ci{
211162306a36Sopenharmony_ci	struct hci_cp_le_pa_create_sync *cp;
211262306a36Sopenharmony_ci
211362306a36Sopenharmony_ci	if (hci_dev_test_and_set_flag(hdev, HCI_PA_SYNC))
211462306a36Sopenharmony_ci		return -EBUSY;
211562306a36Sopenharmony_ci
211662306a36Sopenharmony_ci	cp = kzalloc(sizeof(*cp), GFP_KERNEL);
211762306a36Sopenharmony_ci	if (!cp) {
211862306a36Sopenharmony_ci		hci_dev_clear_flag(hdev, HCI_PA_SYNC);
211962306a36Sopenharmony_ci		return -ENOMEM;
212062306a36Sopenharmony_ci	}
212162306a36Sopenharmony_ci
212262306a36Sopenharmony_ci	cp->options = qos->bcast.options;
212362306a36Sopenharmony_ci	cp->sid = sid;
212462306a36Sopenharmony_ci	cp->addr_type = dst_type;
212562306a36Sopenharmony_ci	bacpy(&cp->addr, dst);
212662306a36Sopenharmony_ci	cp->skip = cpu_to_le16(qos->bcast.skip);
212762306a36Sopenharmony_ci	cp->sync_timeout = cpu_to_le16(qos->bcast.sync_timeout);
212862306a36Sopenharmony_ci	cp->sync_cte_type = qos->bcast.sync_cte_type;
212962306a36Sopenharmony_ci
213062306a36Sopenharmony_ci	/* Queue start pa_create_sync and scan */
213162306a36Sopenharmony_ci	return hci_cmd_sync_queue(hdev, create_pa_sync, cp, create_pa_complete);
213262306a36Sopenharmony_ci}
213362306a36Sopenharmony_ci
213462306a36Sopenharmony_ciint hci_le_big_create_sync(struct hci_dev *hdev, struct hci_conn *hcon,
213562306a36Sopenharmony_ci			   struct bt_iso_qos *qos,
213662306a36Sopenharmony_ci			   __u16 sync_handle, __u8 num_bis, __u8 bis[])
213762306a36Sopenharmony_ci{
213862306a36Sopenharmony_ci	struct _packed {
213962306a36Sopenharmony_ci		struct hci_cp_le_big_create_sync cp;
214062306a36Sopenharmony_ci		__u8  bis[0x11];
214162306a36Sopenharmony_ci	} pdu;
214262306a36Sopenharmony_ci	int err;
214362306a36Sopenharmony_ci
214462306a36Sopenharmony_ci	if (num_bis > sizeof(pdu.bis))
214562306a36Sopenharmony_ci		return -EINVAL;
214662306a36Sopenharmony_ci
214762306a36Sopenharmony_ci	err = qos_set_big(hdev, qos);
214862306a36Sopenharmony_ci	if (err)
214962306a36Sopenharmony_ci		return err;
215062306a36Sopenharmony_ci
215162306a36Sopenharmony_ci	if (hcon)
215262306a36Sopenharmony_ci		hcon->iso_qos.bcast.big = qos->bcast.big;
215362306a36Sopenharmony_ci
215462306a36Sopenharmony_ci	memset(&pdu, 0, sizeof(pdu));
215562306a36Sopenharmony_ci	pdu.cp.handle = qos->bcast.big;
215662306a36Sopenharmony_ci	pdu.cp.sync_handle = cpu_to_le16(sync_handle);
215762306a36Sopenharmony_ci	pdu.cp.encryption = qos->bcast.encryption;
215862306a36Sopenharmony_ci	memcpy(pdu.cp.bcode, qos->bcast.bcode, sizeof(pdu.cp.bcode));
215962306a36Sopenharmony_ci	pdu.cp.mse = qos->bcast.mse;
216062306a36Sopenharmony_ci	pdu.cp.timeout = cpu_to_le16(qos->bcast.timeout);
216162306a36Sopenharmony_ci	pdu.cp.num_bis = num_bis;
216262306a36Sopenharmony_ci	memcpy(pdu.bis, bis, num_bis);
216362306a36Sopenharmony_ci
216462306a36Sopenharmony_ci	return hci_send_cmd(hdev, HCI_OP_LE_BIG_CREATE_SYNC,
216562306a36Sopenharmony_ci			    sizeof(pdu.cp) + num_bis, &pdu);
216662306a36Sopenharmony_ci}
216762306a36Sopenharmony_ci
216862306a36Sopenharmony_cistatic void create_big_complete(struct hci_dev *hdev, void *data, int err)
216962306a36Sopenharmony_ci{
217062306a36Sopenharmony_ci	struct hci_conn *conn = data;
217162306a36Sopenharmony_ci
217262306a36Sopenharmony_ci	bt_dev_dbg(hdev, "conn %p", conn);
217362306a36Sopenharmony_ci
217462306a36Sopenharmony_ci	if (err) {
217562306a36Sopenharmony_ci		bt_dev_err(hdev, "Unable to create BIG: %d", err);
217662306a36Sopenharmony_ci		hci_connect_cfm(conn, err);
217762306a36Sopenharmony_ci		hci_conn_del(conn);
217862306a36Sopenharmony_ci	}
217962306a36Sopenharmony_ci}
218062306a36Sopenharmony_ci
218162306a36Sopenharmony_cistruct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst,
218262306a36Sopenharmony_ci			      struct bt_iso_qos *qos,
218362306a36Sopenharmony_ci			      __u8 base_len, __u8 *base)
218462306a36Sopenharmony_ci{
218562306a36Sopenharmony_ci	struct hci_conn *conn;
218662306a36Sopenharmony_ci	__u8 eir[HCI_MAX_PER_AD_LENGTH];
218762306a36Sopenharmony_ci
218862306a36Sopenharmony_ci	if (base_len && base)
218962306a36Sopenharmony_ci		base_len = eir_append_service_data(eir, 0,  0x1851,
219062306a36Sopenharmony_ci						   base, base_len);
219162306a36Sopenharmony_ci
219262306a36Sopenharmony_ci	/* We need hci_conn object using the BDADDR_ANY as dst */
219362306a36Sopenharmony_ci	conn = hci_add_bis(hdev, dst, qos, base_len, eir);
219462306a36Sopenharmony_ci	if (IS_ERR(conn))
219562306a36Sopenharmony_ci		return conn;
219662306a36Sopenharmony_ci
219762306a36Sopenharmony_ci	/* Update LINK PHYs according to QoS preference */
219862306a36Sopenharmony_ci	conn->le_tx_phy = qos->bcast.out.phy;
219962306a36Sopenharmony_ci	conn->le_tx_phy = qos->bcast.out.phy;
220062306a36Sopenharmony_ci
220162306a36Sopenharmony_ci	/* Add Basic Announcement into Peridic Adv Data if BASE is set */
220262306a36Sopenharmony_ci	if (base_len && base) {
220362306a36Sopenharmony_ci		memcpy(conn->le_per_adv_data,  eir, sizeof(eir));
220462306a36Sopenharmony_ci		conn->le_per_adv_data_len = base_len;
220562306a36Sopenharmony_ci	}
220662306a36Sopenharmony_ci
220762306a36Sopenharmony_ci	hci_iso_qos_setup(hdev, conn, &qos->bcast.out,
220862306a36Sopenharmony_ci			  conn->le_tx_phy ? conn->le_tx_phy :
220962306a36Sopenharmony_ci			  hdev->le_tx_def_phys);
221062306a36Sopenharmony_ci
221162306a36Sopenharmony_ci	conn->iso_qos = *qos;
221262306a36Sopenharmony_ci	conn->state = BT_BOUND;
221362306a36Sopenharmony_ci
221462306a36Sopenharmony_ci	return conn;
221562306a36Sopenharmony_ci}
221662306a36Sopenharmony_ci
221762306a36Sopenharmony_cistatic void bis_mark_per_adv(struct hci_conn *conn, void *data)
221862306a36Sopenharmony_ci{
221962306a36Sopenharmony_ci	struct iso_list_data *d = data;
222062306a36Sopenharmony_ci
222162306a36Sopenharmony_ci	/* Skip if not broadcast/ANY address */
222262306a36Sopenharmony_ci	if (bacmp(&conn->dst, BDADDR_ANY))
222362306a36Sopenharmony_ci		return;
222462306a36Sopenharmony_ci
222562306a36Sopenharmony_ci	if (d->big != conn->iso_qos.bcast.big ||
222662306a36Sopenharmony_ci	    d->bis == BT_ISO_QOS_BIS_UNSET ||
222762306a36Sopenharmony_ci	    d->bis != conn->iso_qos.bcast.bis)
222862306a36Sopenharmony_ci		return;
222962306a36Sopenharmony_ci
223062306a36Sopenharmony_ci	set_bit(HCI_CONN_PER_ADV, &conn->flags);
223162306a36Sopenharmony_ci}
223262306a36Sopenharmony_ci
223362306a36Sopenharmony_cistruct hci_conn *hci_connect_bis(struct hci_dev *hdev, bdaddr_t *dst,
223462306a36Sopenharmony_ci				 __u8 dst_type, struct bt_iso_qos *qos,
223562306a36Sopenharmony_ci				 __u8 base_len, __u8 *base)
223662306a36Sopenharmony_ci{
223762306a36Sopenharmony_ci	struct hci_conn *conn;
223862306a36Sopenharmony_ci	int err;
223962306a36Sopenharmony_ci	struct iso_list_data data;
224062306a36Sopenharmony_ci
224162306a36Sopenharmony_ci	conn = hci_bind_bis(hdev, dst, qos, base_len, base);
224262306a36Sopenharmony_ci	if (IS_ERR(conn))
224362306a36Sopenharmony_ci		return conn;
224462306a36Sopenharmony_ci
224562306a36Sopenharmony_ci	data.big = qos->bcast.big;
224662306a36Sopenharmony_ci	data.bis = qos->bcast.bis;
224762306a36Sopenharmony_ci
224862306a36Sopenharmony_ci	/* Set HCI_CONN_PER_ADV for all bound connections, to mark that
224962306a36Sopenharmony_ci	 * the start periodic advertising and create BIG commands have
225062306a36Sopenharmony_ci	 * been queued
225162306a36Sopenharmony_ci	 */
225262306a36Sopenharmony_ci	hci_conn_hash_list_state(hdev, bis_mark_per_adv, ISO_LINK,
225362306a36Sopenharmony_ci				 BT_BOUND, &data);
225462306a36Sopenharmony_ci
225562306a36Sopenharmony_ci	/* Queue start periodic advertising and create BIG */
225662306a36Sopenharmony_ci	err = hci_cmd_sync_queue(hdev, create_big_sync, conn,
225762306a36Sopenharmony_ci				 create_big_complete);
225862306a36Sopenharmony_ci	if (err < 0) {
225962306a36Sopenharmony_ci		hci_conn_drop(conn);
226062306a36Sopenharmony_ci		return ERR_PTR(err);
226162306a36Sopenharmony_ci	}
226262306a36Sopenharmony_ci
226362306a36Sopenharmony_ci	return conn;
226462306a36Sopenharmony_ci}
226562306a36Sopenharmony_ci
226662306a36Sopenharmony_cistruct hci_conn *hci_connect_cis(struct hci_dev *hdev, bdaddr_t *dst,
226762306a36Sopenharmony_ci				 __u8 dst_type, struct bt_iso_qos *qos)
226862306a36Sopenharmony_ci{
226962306a36Sopenharmony_ci	struct hci_conn *le;
227062306a36Sopenharmony_ci	struct hci_conn *cis;
227162306a36Sopenharmony_ci	struct hci_link *link;
227262306a36Sopenharmony_ci
227362306a36Sopenharmony_ci	if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
227462306a36Sopenharmony_ci		le = hci_connect_le(hdev, dst, dst_type, false,
227562306a36Sopenharmony_ci				    BT_SECURITY_LOW,
227662306a36Sopenharmony_ci				    HCI_LE_CONN_TIMEOUT,
227762306a36Sopenharmony_ci				    HCI_ROLE_SLAVE);
227862306a36Sopenharmony_ci	else
227962306a36Sopenharmony_ci		le = hci_connect_le_scan(hdev, dst, dst_type,
228062306a36Sopenharmony_ci					 BT_SECURITY_LOW,
228162306a36Sopenharmony_ci					 HCI_LE_CONN_TIMEOUT,
228262306a36Sopenharmony_ci					 CONN_REASON_ISO_CONNECT);
228362306a36Sopenharmony_ci	if (IS_ERR(le))
228462306a36Sopenharmony_ci		return le;
228562306a36Sopenharmony_ci
228662306a36Sopenharmony_ci	hci_iso_qos_setup(hdev, le, &qos->ucast.out,
228762306a36Sopenharmony_ci			  le->le_tx_phy ? le->le_tx_phy : hdev->le_tx_def_phys);
228862306a36Sopenharmony_ci	hci_iso_qos_setup(hdev, le, &qos->ucast.in,
228962306a36Sopenharmony_ci			  le->le_rx_phy ? le->le_rx_phy : hdev->le_rx_def_phys);
229062306a36Sopenharmony_ci
229162306a36Sopenharmony_ci	cis = hci_bind_cis(hdev, dst, dst_type, qos);
229262306a36Sopenharmony_ci	if (IS_ERR(cis)) {
229362306a36Sopenharmony_ci		hci_conn_drop(le);
229462306a36Sopenharmony_ci		return cis;
229562306a36Sopenharmony_ci	}
229662306a36Sopenharmony_ci
229762306a36Sopenharmony_ci	link = hci_conn_link(le, cis);
229862306a36Sopenharmony_ci	if (!link) {
229962306a36Sopenharmony_ci		hci_conn_drop(le);
230062306a36Sopenharmony_ci		hci_conn_drop(cis);
230162306a36Sopenharmony_ci		return ERR_PTR(-ENOLINK);
230262306a36Sopenharmony_ci	}
230362306a36Sopenharmony_ci
230462306a36Sopenharmony_ci	/* Link takes the refcount */
230562306a36Sopenharmony_ci	hci_conn_drop(cis);
230662306a36Sopenharmony_ci
230762306a36Sopenharmony_ci	cis->state = BT_CONNECT;
230862306a36Sopenharmony_ci
230962306a36Sopenharmony_ci	hci_le_create_cis_pending(hdev);
231062306a36Sopenharmony_ci
231162306a36Sopenharmony_ci	return cis;
231262306a36Sopenharmony_ci}
231362306a36Sopenharmony_ci
231462306a36Sopenharmony_ci/* Check link security requirement */
231562306a36Sopenharmony_ciint hci_conn_check_link_mode(struct hci_conn *conn)
231662306a36Sopenharmony_ci{
231762306a36Sopenharmony_ci	BT_DBG("hcon %p", conn);
231862306a36Sopenharmony_ci
231962306a36Sopenharmony_ci	/* In Secure Connections Only mode, it is required that Secure
232062306a36Sopenharmony_ci	 * Connections is used and the link is encrypted with AES-CCM
232162306a36Sopenharmony_ci	 * using a P-256 authenticated combination key.
232262306a36Sopenharmony_ci	 */
232362306a36Sopenharmony_ci	if (hci_dev_test_flag(conn->hdev, HCI_SC_ONLY)) {
232462306a36Sopenharmony_ci		if (!hci_conn_sc_enabled(conn) ||
232562306a36Sopenharmony_ci		    !test_bit(HCI_CONN_AES_CCM, &conn->flags) ||
232662306a36Sopenharmony_ci		    conn->key_type != HCI_LK_AUTH_COMBINATION_P256)
232762306a36Sopenharmony_ci			return 0;
232862306a36Sopenharmony_ci	}
232962306a36Sopenharmony_ci
233062306a36Sopenharmony_ci	 /* AES encryption is required for Level 4:
233162306a36Sopenharmony_ci	  *
233262306a36Sopenharmony_ci	  * BLUETOOTH CORE SPECIFICATION Version 5.2 | Vol 3, Part C
233362306a36Sopenharmony_ci	  * page 1319:
233462306a36Sopenharmony_ci	  *
233562306a36Sopenharmony_ci	  * 128-bit equivalent strength for link and encryption keys
233662306a36Sopenharmony_ci	  * required using FIPS approved algorithms (E0 not allowed,
233762306a36Sopenharmony_ci	  * SAFER+ not allowed, and P-192 not allowed; encryption key
233862306a36Sopenharmony_ci	  * not shortened)
233962306a36Sopenharmony_ci	  */
234062306a36Sopenharmony_ci	if (conn->sec_level == BT_SECURITY_FIPS &&
234162306a36Sopenharmony_ci	    !test_bit(HCI_CONN_AES_CCM, &conn->flags)) {
234262306a36Sopenharmony_ci		bt_dev_err(conn->hdev,
234362306a36Sopenharmony_ci			   "Invalid security: Missing AES-CCM usage");
234462306a36Sopenharmony_ci		return 0;
234562306a36Sopenharmony_ci	}
234662306a36Sopenharmony_ci
234762306a36Sopenharmony_ci	if (hci_conn_ssp_enabled(conn) &&
234862306a36Sopenharmony_ci	    !test_bit(HCI_CONN_ENCRYPT, &conn->flags))
234962306a36Sopenharmony_ci		return 0;
235062306a36Sopenharmony_ci
235162306a36Sopenharmony_ci	return 1;
235262306a36Sopenharmony_ci}
235362306a36Sopenharmony_ci
235462306a36Sopenharmony_ci/* Authenticate remote device */
235562306a36Sopenharmony_cistatic int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
235662306a36Sopenharmony_ci{
235762306a36Sopenharmony_ci	BT_DBG("hcon %p", conn);
235862306a36Sopenharmony_ci
235962306a36Sopenharmony_ci	if (conn->pending_sec_level > sec_level)
236062306a36Sopenharmony_ci		sec_level = conn->pending_sec_level;
236162306a36Sopenharmony_ci
236262306a36Sopenharmony_ci	if (sec_level > conn->sec_level)
236362306a36Sopenharmony_ci		conn->pending_sec_level = sec_level;
236462306a36Sopenharmony_ci	else if (test_bit(HCI_CONN_AUTH, &conn->flags))
236562306a36Sopenharmony_ci		return 1;
236662306a36Sopenharmony_ci
236762306a36Sopenharmony_ci	/* Make sure we preserve an existing MITM requirement*/
236862306a36Sopenharmony_ci	auth_type |= (conn->auth_type & 0x01);
236962306a36Sopenharmony_ci
237062306a36Sopenharmony_ci	conn->auth_type = auth_type;
237162306a36Sopenharmony_ci
237262306a36Sopenharmony_ci	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
237362306a36Sopenharmony_ci		struct hci_cp_auth_requested cp;
237462306a36Sopenharmony_ci
237562306a36Sopenharmony_ci		cp.handle = cpu_to_le16(conn->handle);
237662306a36Sopenharmony_ci		hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED,
237762306a36Sopenharmony_ci			     sizeof(cp), &cp);
237862306a36Sopenharmony_ci
237962306a36Sopenharmony_ci		/* Set the ENCRYPT_PEND to trigger encryption after
238062306a36Sopenharmony_ci		 * authentication.
238162306a36Sopenharmony_ci		 */
238262306a36Sopenharmony_ci		if (!test_bit(HCI_CONN_ENCRYPT, &conn->flags))
238362306a36Sopenharmony_ci			set_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
238462306a36Sopenharmony_ci	}
238562306a36Sopenharmony_ci
238662306a36Sopenharmony_ci	return 0;
238762306a36Sopenharmony_ci}
238862306a36Sopenharmony_ci
238962306a36Sopenharmony_ci/* Encrypt the link */
239062306a36Sopenharmony_cistatic void hci_conn_encrypt(struct hci_conn *conn)
239162306a36Sopenharmony_ci{
239262306a36Sopenharmony_ci	BT_DBG("hcon %p", conn);
239362306a36Sopenharmony_ci
239462306a36Sopenharmony_ci	if (!test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
239562306a36Sopenharmony_ci		struct hci_cp_set_conn_encrypt cp;
239662306a36Sopenharmony_ci		cp.handle  = cpu_to_le16(conn->handle);
239762306a36Sopenharmony_ci		cp.encrypt = 0x01;
239862306a36Sopenharmony_ci		hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
239962306a36Sopenharmony_ci			     &cp);
240062306a36Sopenharmony_ci	}
240162306a36Sopenharmony_ci}
240262306a36Sopenharmony_ci
240362306a36Sopenharmony_ci/* Enable security */
240462306a36Sopenharmony_ciint hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type,
240562306a36Sopenharmony_ci		      bool initiator)
240662306a36Sopenharmony_ci{
240762306a36Sopenharmony_ci	BT_DBG("hcon %p", conn);
240862306a36Sopenharmony_ci
240962306a36Sopenharmony_ci	if (conn->type == LE_LINK)
241062306a36Sopenharmony_ci		return smp_conn_security(conn, sec_level);
241162306a36Sopenharmony_ci
241262306a36Sopenharmony_ci	/* For sdp we don't need the link key. */
241362306a36Sopenharmony_ci	if (sec_level == BT_SECURITY_SDP)
241462306a36Sopenharmony_ci		return 1;
241562306a36Sopenharmony_ci
241662306a36Sopenharmony_ci	/* For non 2.1 devices and low security level we don't need the link
241762306a36Sopenharmony_ci	   key. */
241862306a36Sopenharmony_ci	if (sec_level == BT_SECURITY_LOW && !hci_conn_ssp_enabled(conn))
241962306a36Sopenharmony_ci		return 1;
242062306a36Sopenharmony_ci
242162306a36Sopenharmony_ci	/* For other security levels we need the link key. */
242262306a36Sopenharmony_ci	if (!test_bit(HCI_CONN_AUTH, &conn->flags))
242362306a36Sopenharmony_ci		goto auth;
242462306a36Sopenharmony_ci
242562306a36Sopenharmony_ci	switch (conn->key_type) {
242662306a36Sopenharmony_ci	case HCI_LK_AUTH_COMBINATION_P256:
242762306a36Sopenharmony_ci		/* An authenticated FIPS approved combination key has
242862306a36Sopenharmony_ci		 * sufficient security for security level 4 or lower.
242962306a36Sopenharmony_ci		 */
243062306a36Sopenharmony_ci		if (sec_level <= BT_SECURITY_FIPS)
243162306a36Sopenharmony_ci			goto encrypt;
243262306a36Sopenharmony_ci		break;
243362306a36Sopenharmony_ci	case HCI_LK_AUTH_COMBINATION_P192:
243462306a36Sopenharmony_ci		/* An authenticated combination key has sufficient security for
243562306a36Sopenharmony_ci		 * security level 3 or lower.
243662306a36Sopenharmony_ci		 */
243762306a36Sopenharmony_ci		if (sec_level <= BT_SECURITY_HIGH)
243862306a36Sopenharmony_ci			goto encrypt;
243962306a36Sopenharmony_ci		break;
244062306a36Sopenharmony_ci	case HCI_LK_UNAUTH_COMBINATION_P192:
244162306a36Sopenharmony_ci	case HCI_LK_UNAUTH_COMBINATION_P256:
244262306a36Sopenharmony_ci		/* An unauthenticated combination key has sufficient security
244362306a36Sopenharmony_ci		 * for security level 2 or lower.
244462306a36Sopenharmony_ci		 */
244562306a36Sopenharmony_ci		if (sec_level <= BT_SECURITY_MEDIUM)
244662306a36Sopenharmony_ci			goto encrypt;
244762306a36Sopenharmony_ci		break;
244862306a36Sopenharmony_ci	case HCI_LK_COMBINATION:
244962306a36Sopenharmony_ci		/* A combination key has always sufficient security for the
245062306a36Sopenharmony_ci		 * security levels 2 or lower. High security level requires the
245162306a36Sopenharmony_ci		 * combination key is generated using maximum PIN code length
245262306a36Sopenharmony_ci		 * (16). For pre 2.1 units.
245362306a36Sopenharmony_ci		 */
245462306a36Sopenharmony_ci		if (sec_level <= BT_SECURITY_MEDIUM || conn->pin_length == 16)
245562306a36Sopenharmony_ci			goto encrypt;
245662306a36Sopenharmony_ci		break;
245762306a36Sopenharmony_ci	default:
245862306a36Sopenharmony_ci		break;
245962306a36Sopenharmony_ci	}
246062306a36Sopenharmony_ci
246162306a36Sopenharmony_ciauth:
246262306a36Sopenharmony_ci	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags))
246362306a36Sopenharmony_ci		return 0;
246462306a36Sopenharmony_ci
246562306a36Sopenharmony_ci	if (initiator)
246662306a36Sopenharmony_ci		set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags);
246762306a36Sopenharmony_ci
246862306a36Sopenharmony_ci	if (!hci_conn_auth(conn, sec_level, auth_type))
246962306a36Sopenharmony_ci		return 0;
247062306a36Sopenharmony_ci
247162306a36Sopenharmony_ciencrypt:
247262306a36Sopenharmony_ci	if (test_bit(HCI_CONN_ENCRYPT, &conn->flags)) {
247362306a36Sopenharmony_ci		/* Ensure that the encryption key size has been read,
247462306a36Sopenharmony_ci		 * otherwise stall the upper layer responses.
247562306a36Sopenharmony_ci		 */
247662306a36Sopenharmony_ci		if (!conn->enc_key_size)
247762306a36Sopenharmony_ci			return 0;
247862306a36Sopenharmony_ci
247962306a36Sopenharmony_ci		/* Nothing else needed, all requirements are met */
248062306a36Sopenharmony_ci		return 1;
248162306a36Sopenharmony_ci	}
248262306a36Sopenharmony_ci
248362306a36Sopenharmony_ci	hci_conn_encrypt(conn);
248462306a36Sopenharmony_ci	return 0;
248562306a36Sopenharmony_ci}
248662306a36Sopenharmony_ciEXPORT_SYMBOL(hci_conn_security);
248762306a36Sopenharmony_ci
248862306a36Sopenharmony_ci/* Check secure link requirement */
248962306a36Sopenharmony_ciint hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level)
249062306a36Sopenharmony_ci{
249162306a36Sopenharmony_ci	BT_DBG("hcon %p", conn);
249262306a36Sopenharmony_ci
249362306a36Sopenharmony_ci	/* Accept if non-secure or higher security level is required */
249462306a36Sopenharmony_ci	if (sec_level != BT_SECURITY_HIGH && sec_level != BT_SECURITY_FIPS)
249562306a36Sopenharmony_ci		return 1;
249662306a36Sopenharmony_ci
249762306a36Sopenharmony_ci	/* Accept if secure or higher security level is already present */
249862306a36Sopenharmony_ci	if (conn->sec_level == BT_SECURITY_HIGH ||
249962306a36Sopenharmony_ci	    conn->sec_level == BT_SECURITY_FIPS)
250062306a36Sopenharmony_ci		return 1;
250162306a36Sopenharmony_ci
250262306a36Sopenharmony_ci	/* Reject not secure link */
250362306a36Sopenharmony_ci	return 0;
250462306a36Sopenharmony_ci}
250562306a36Sopenharmony_ciEXPORT_SYMBOL(hci_conn_check_secure);
250662306a36Sopenharmony_ci
250762306a36Sopenharmony_ci/* Switch role */
250862306a36Sopenharmony_ciint hci_conn_switch_role(struct hci_conn *conn, __u8 role)
250962306a36Sopenharmony_ci{
251062306a36Sopenharmony_ci	BT_DBG("hcon %p", conn);
251162306a36Sopenharmony_ci
251262306a36Sopenharmony_ci	if (role == conn->role)
251362306a36Sopenharmony_ci		return 1;
251462306a36Sopenharmony_ci
251562306a36Sopenharmony_ci	if (!test_and_set_bit(HCI_CONN_RSWITCH_PEND, &conn->flags)) {
251662306a36Sopenharmony_ci		struct hci_cp_switch_role cp;
251762306a36Sopenharmony_ci		bacpy(&cp.bdaddr, &conn->dst);
251862306a36Sopenharmony_ci		cp.role = role;
251962306a36Sopenharmony_ci		hci_send_cmd(conn->hdev, HCI_OP_SWITCH_ROLE, sizeof(cp), &cp);
252062306a36Sopenharmony_ci	}
252162306a36Sopenharmony_ci
252262306a36Sopenharmony_ci	return 0;
252362306a36Sopenharmony_ci}
252462306a36Sopenharmony_ciEXPORT_SYMBOL(hci_conn_switch_role);
252562306a36Sopenharmony_ci
252662306a36Sopenharmony_ci/* Enter active mode */
252762306a36Sopenharmony_civoid hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active)
252862306a36Sopenharmony_ci{
252962306a36Sopenharmony_ci	struct hci_dev *hdev = conn->hdev;
253062306a36Sopenharmony_ci
253162306a36Sopenharmony_ci	BT_DBG("hcon %p mode %d", conn, conn->mode);
253262306a36Sopenharmony_ci
253362306a36Sopenharmony_ci	if (conn->mode != HCI_CM_SNIFF)
253462306a36Sopenharmony_ci		goto timer;
253562306a36Sopenharmony_ci
253662306a36Sopenharmony_ci	if (!test_bit(HCI_CONN_POWER_SAVE, &conn->flags) && !force_active)
253762306a36Sopenharmony_ci		goto timer;
253862306a36Sopenharmony_ci
253962306a36Sopenharmony_ci	if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) {
254062306a36Sopenharmony_ci		struct hci_cp_exit_sniff_mode cp;
254162306a36Sopenharmony_ci		cp.handle = cpu_to_le16(conn->handle);
254262306a36Sopenharmony_ci		hci_send_cmd(hdev, HCI_OP_EXIT_SNIFF_MODE, sizeof(cp), &cp);
254362306a36Sopenharmony_ci	}
254462306a36Sopenharmony_ci
254562306a36Sopenharmony_citimer:
254662306a36Sopenharmony_ci	if (hdev->idle_timeout > 0)
254762306a36Sopenharmony_ci		queue_delayed_work(hdev->workqueue, &conn->idle_work,
254862306a36Sopenharmony_ci				   msecs_to_jiffies(hdev->idle_timeout));
254962306a36Sopenharmony_ci}
255062306a36Sopenharmony_ci
255162306a36Sopenharmony_ci/* Drop all connection on the device */
255262306a36Sopenharmony_civoid hci_conn_hash_flush(struct hci_dev *hdev)
255362306a36Sopenharmony_ci{
255462306a36Sopenharmony_ci	struct list_head *head = &hdev->conn_hash.list;
255562306a36Sopenharmony_ci	struct hci_conn *conn;
255662306a36Sopenharmony_ci
255762306a36Sopenharmony_ci	BT_DBG("hdev %s", hdev->name);
255862306a36Sopenharmony_ci
255962306a36Sopenharmony_ci	/* We should not traverse the list here, because hci_conn_del
256062306a36Sopenharmony_ci	 * can remove extra links, which may cause the list traversal
256162306a36Sopenharmony_ci	 * to hit items that have already been released.
256262306a36Sopenharmony_ci	 */
256362306a36Sopenharmony_ci	while ((conn = list_first_entry_or_null(head,
256462306a36Sopenharmony_ci						struct hci_conn,
256562306a36Sopenharmony_ci						list)) != NULL) {
256662306a36Sopenharmony_ci		conn->state = BT_CLOSED;
256762306a36Sopenharmony_ci		hci_disconn_cfm(conn, HCI_ERROR_LOCAL_HOST_TERM);
256862306a36Sopenharmony_ci		hci_conn_del(conn);
256962306a36Sopenharmony_ci	}
257062306a36Sopenharmony_ci}
257162306a36Sopenharmony_ci
257262306a36Sopenharmony_ci/* Check pending connect attempts */
257362306a36Sopenharmony_civoid hci_conn_check_pending(struct hci_dev *hdev)
257462306a36Sopenharmony_ci{
257562306a36Sopenharmony_ci	struct hci_conn *conn;
257662306a36Sopenharmony_ci
257762306a36Sopenharmony_ci	BT_DBG("hdev %s", hdev->name);
257862306a36Sopenharmony_ci
257962306a36Sopenharmony_ci	hci_dev_lock(hdev);
258062306a36Sopenharmony_ci
258162306a36Sopenharmony_ci	conn = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
258262306a36Sopenharmony_ci	if (conn)
258362306a36Sopenharmony_ci		hci_acl_create_connection(conn);
258462306a36Sopenharmony_ci
258562306a36Sopenharmony_ci	hci_dev_unlock(hdev);
258662306a36Sopenharmony_ci}
258762306a36Sopenharmony_ci
258862306a36Sopenharmony_cistatic u32 get_link_mode(struct hci_conn *conn)
258962306a36Sopenharmony_ci{
259062306a36Sopenharmony_ci	u32 link_mode = 0;
259162306a36Sopenharmony_ci
259262306a36Sopenharmony_ci	if (conn->role == HCI_ROLE_MASTER)
259362306a36Sopenharmony_ci		link_mode |= HCI_LM_MASTER;
259462306a36Sopenharmony_ci
259562306a36Sopenharmony_ci	if (test_bit(HCI_CONN_ENCRYPT, &conn->flags))
259662306a36Sopenharmony_ci		link_mode |= HCI_LM_ENCRYPT;
259762306a36Sopenharmony_ci
259862306a36Sopenharmony_ci	if (test_bit(HCI_CONN_AUTH, &conn->flags))
259962306a36Sopenharmony_ci		link_mode |= HCI_LM_AUTH;
260062306a36Sopenharmony_ci
260162306a36Sopenharmony_ci	if (test_bit(HCI_CONN_SECURE, &conn->flags))
260262306a36Sopenharmony_ci		link_mode |= HCI_LM_SECURE;
260362306a36Sopenharmony_ci
260462306a36Sopenharmony_ci	if (test_bit(HCI_CONN_FIPS, &conn->flags))
260562306a36Sopenharmony_ci		link_mode |= HCI_LM_FIPS;
260662306a36Sopenharmony_ci
260762306a36Sopenharmony_ci	return link_mode;
260862306a36Sopenharmony_ci}
260962306a36Sopenharmony_ci
261062306a36Sopenharmony_ciint hci_get_conn_list(void __user *arg)
261162306a36Sopenharmony_ci{
261262306a36Sopenharmony_ci	struct hci_conn *c;
261362306a36Sopenharmony_ci	struct hci_conn_list_req req, *cl;
261462306a36Sopenharmony_ci	struct hci_conn_info *ci;
261562306a36Sopenharmony_ci	struct hci_dev *hdev;
261662306a36Sopenharmony_ci	int n = 0, size, err;
261762306a36Sopenharmony_ci
261862306a36Sopenharmony_ci	if (copy_from_user(&req, arg, sizeof(req)))
261962306a36Sopenharmony_ci		return -EFAULT;
262062306a36Sopenharmony_ci
262162306a36Sopenharmony_ci	if (!req.conn_num || req.conn_num > (PAGE_SIZE * 2) / sizeof(*ci))
262262306a36Sopenharmony_ci		return -EINVAL;
262362306a36Sopenharmony_ci
262462306a36Sopenharmony_ci	size = sizeof(req) + req.conn_num * sizeof(*ci);
262562306a36Sopenharmony_ci
262662306a36Sopenharmony_ci	cl = kmalloc(size, GFP_KERNEL);
262762306a36Sopenharmony_ci	if (!cl)
262862306a36Sopenharmony_ci		return -ENOMEM;
262962306a36Sopenharmony_ci
263062306a36Sopenharmony_ci	hdev = hci_dev_get(req.dev_id);
263162306a36Sopenharmony_ci	if (!hdev) {
263262306a36Sopenharmony_ci		kfree(cl);
263362306a36Sopenharmony_ci		return -ENODEV;
263462306a36Sopenharmony_ci	}
263562306a36Sopenharmony_ci
263662306a36Sopenharmony_ci	ci = cl->conn_info;
263762306a36Sopenharmony_ci
263862306a36Sopenharmony_ci	hci_dev_lock(hdev);
263962306a36Sopenharmony_ci	list_for_each_entry(c, &hdev->conn_hash.list, list) {
264062306a36Sopenharmony_ci		bacpy(&(ci + n)->bdaddr, &c->dst);
264162306a36Sopenharmony_ci		(ci + n)->handle = c->handle;
264262306a36Sopenharmony_ci		(ci + n)->type  = c->type;
264362306a36Sopenharmony_ci		(ci + n)->out   = c->out;
264462306a36Sopenharmony_ci		(ci + n)->state = c->state;
264562306a36Sopenharmony_ci		(ci + n)->link_mode = get_link_mode(c);
264662306a36Sopenharmony_ci		if (++n >= req.conn_num)
264762306a36Sopenharmony_ci			break;
264862306a36Sopenharmony_ci	}
264962306a36Sopenharmony_ci	hci_dev_unlock(hdev);
265062306a36Sopenharmony_ci
265162306a36Sopenharmony_ci	cl->dev_id = hdev->id;
265262306a36Sopenharmony_ci	cl->conn_num = n;
265362306a36Sopenharmony_ci	size = sizeof(req) + n * sizeof(*ci);
265462306a36Sopenharmony_ci
265562306a36Sopenharmony_ci	hci_dev_put(hdev);
265662306a36Sopenharmony_ci
265762306a36Sopenharmony_ci	err = copy_to_user(arg, cl, size);
265862306a36Sopenharmony_ci	kfree(cl);
265962306a36Sopenharmony_ci
266062306a36Sopenharmony_ci	return err ? -EFAULT : 0;
266162306a36Sopenharmony_ci}
266262306a36Sopenharmony_ci
266362306a36Sopenharmony_ciint hci_get_conn_info(struct hci_dev *hdev, void __user *arg)
266462306a36Sopenharmony_ci{
266562306a36Sopenharmony_ci	struct hci_conn_info_req req;
266662306a36Sopenharmony_ci	struct hci_conn_info ci;
266762306a36Sopenharmony_ci	struct hci_conn *conn;
266862306a36Sopenharmony_ci	char __user *ptr = arg + sizeof(req);
266962306a36Sopenharmony_ci
267062306a36Sopenharmony_ci	if (copy_from_user(&req, arg, sizeof(req)))
267162306a36Sopenharmony_ci		return -EFAULT;
267262306a36Sopenharmony_ci
267362306a36Sopenharmony_ci	hci_dev_lock(hdev);
267462306a36Sopenharmony_ci	conn = hci_conn_hash_lookup_ba(hdev, req.type, &req.bdaddr);
267562306a36Sopenharmony_ci	if (conn) {
267662306a36Sopenharmony_ci		bacpy(&ci.bdaddr, &conn->dst);
267762306a36Sopenharmony_ci		ci.handle = conn->handle;
267862306a36Sopenharmony_ci		ci.type  = conn->type;
267962306a36Sopenharmony_ci		ci.out   = conn->out;
268062306a36Sopenharmony_ci		ci.state = conn->state;
268162306a36Sopenharmony_ci		ci.link_mode = get_link_mode(conn);
268262306a36Sopenharmony_ci	}
268362306a36Sopenharmony_ci	hci_dev_unlock(hdev);
268462306a36Sopenharmony_ci
268562306a36Sopenharmony_ci	if (!conn)
268662306a36Sopenharmony_ci		return -ENOENT;
268762306a36Sopenharmony_ci
268862306a36Sopenharmony_ci	return copy_to_user(ptr, &ci, sizeof(ci)) ? -EFAULT : 0;
268962306a36Sopenharmony_ci}
269062306a36Sopenharmony_ci
269162306a36Sopenharmony_ciint hci_get_auth_info(struct hci_dev *hdev, void __user *arg)
269262306a36Sopenharmony_ci{
269362306a36Sopenharmony_ci	struct hci_auth_info_req req;
269462306a36Sopenharmony_ci	struct hci_conn *conn;
269562306a36Sopenharmony_ci
269662306a36Sopenharmony_ci	if (copy_from_user(&req, arg, sizeof(req)))
269762306a36Sopenharmony_ci		return -EFAULT;
269862306a36Sopenharmony_ci
269962306a36Sopenharmony_ci	hci_dev_lock(hdev);
270062306a36Sopenharmony_ci	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &req.bdaddr);
270162306a36Sopenharmony_ci	if (conn)
270262306a36Sopenharmony_ci		req.type = conn->auth_type;
270362306a36Sopenharmony_ci	hci_dev_unlock(hdev);
270462306a36Sopenharmony_ci
270562306a36Sopenharmony_ci	if (!conn)
270662306a36Sopenharmony_ci		return -ENOENT;
270762306a36Sopenharmony_ci
270862306a36Sopenharmony_ci	return copy_to_user(arg, &req, sizeof(req)) ? -EFAULT : 0;
270962306a36Sopenharmony_ci}
271062306a36Sopenharmony_ci
271162306a36Sopenharmony_cistruct hci_chan *hci_chan_create(struct hci_conn *conn)
271262306a36Sopenharmony_ci{
271362306a36Sopenharmony_ci	struct hci_dev *hdev = conn->hdev;
271462306a36Sopenharmony_ci	struct hci_chan *chan;
271562306a36Sopenharmony_ci
271662306a36Sopenharmony_ci	BT_DBG("%s hcon %p", hdev->name, conn);
271762306a36Sopenharmony_ci
271862306a36Sopenharmony_ci	if (test_bit(HCI_CONN_DROP, &conn->flags)) {
271962306a36Sopenharmony_ci		BT_DBG("Refusing to create new hci_chan");
272062306a36Sopenharmony_ci		return NULL;
272162306a36Sopenharmony_ci	}
272262306a36Sopenharmony_ci
272362306a36Sopenharmony_ci	chan = kzalloc(sizeof(*chan), GFP_KERNEL);
272462306a36Sopenharmony_ci	if (!chan)
272562306a36Sopenharmony_ci		return NULL;
272662306a36Sopenharmony_ci
272762306a36Sopenharmony_ci	chan->conn = hci_conn_get(conn);
272862306a36Sopenharmony_ci	skb_queue_head_init(&chan->data_q);
272962306a36Sopenharmony_ci	chan->state = BT_CONNECTED;
273062306a36Sopenharmony_ci
273162306a36Sopenharmony_ci	list_add_rcu(&chan->list, &conn->chan_list);
273262306a36Sopenharmony_ci
273362306a36Sopenharmony_ci	return chan;
273462306a36Sopenharmony_ci}
273562306a36Sopenharmony_ci
273662306a36Sopenharmony_civoid hci_chan_del(struct hci_chan *chan)
273762306a36Sopenharmony_ci{
273862306a36Sopenharmony_ci	struct hci_conn *conn = chan->conn;
273962306a36Sopenharmony_ci	struct hci_dev *hdev = conn->hdev;
274062306a36Sopenharmony_ci
274162306a36Sopenharmony_ci	BT_DBG("%s hcon %p chan %p", hdev->name, conn, chan);
274262306a36Sopenharmony_ci
274362306a36Sopenharmony_ci	list_del_rcu(&chan->list);
274462306a36Sopenharmony_ci
274562306a36Sopenharmony_ci	synchronize_rcu();
274662306a36Sopenharmony_ci
274762306a36Sopenharmony_ci	/* Prevent new hci_chan's to be created for this hci_conn */
274862306a36Sopenharmony_ci	set_bit(HCI_CONN_DROP, &conn->flags);
274962306a36Sopenharmony_ci
275062306a36Sopenharmony_ci	hci_conn_put(conn);
275162306a36Sopenharmony_ci
275262306a36Sopenharmony_ci	skb_queue_purge(&chan->data_q);
275362306a36Sopenharmony_ci	kfree(chan);
275462306a36Sopenharmony_ci}
275562306a36Sopenharmony_ci
275662306a36Sopenharmony_civoid hci_chan_list_flush(struct hci_conn *conn)
275762306a36Sopenharmony_ci{
275862306a36Sopenharmony_ci	struct hci_chan *chan, *n;
275962306a36Sopenharmony_ci
276062306a36Sopenharmony_ci	BT_DBG("hcon %p", conn);
276162306a36Sopenharmony_ci
276262306a36Sopenharmony_ci	list_for_each_entry_safe(chan, n, &conn->chan_list, list)
276362306a36Sopenharmony_ci		hci_chan_del(chan);
276462306a36Sopenharmony_ci}
276562306a36Sopenharmony_ci
276662306a36Sopenharmony_cistatic struct hci_chan *__hci_chan_lookup_handle(struct hci_conn *hcon,
276762306a36Sopenharmony_ci						 __u16 handle)
276862306a36Sopenharmony_ci{
276962306a36Sopenharmony_ci	struct hci_chan *hchan;
277062306a36Sopenharmony_ci
277162306a36Sopenharmony_ci	list_for_each_entry(hchan, &hcon->chan_list, list) {
277262306a36Sopenharmony_ci		if (hchan->handle == handle)
277362306a36Sopenharmony_ci			return hchan;
277462306a36Sopenharmony_ci	}
277562306a36Sopenharmony_ci
277662306a36Sopenharmony_ci	return NULL;
277762306a36Sopenharmony_ci}
277862306a36Sopenharmony_ci
277962306a36Sopenharmony_cistruct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle)
278062306a36Sopenharmony_ci{
278162306a36Sopenharmony_ci	struct hci_conn_hash *h = &hdev->conn_hash;
278262306a36Sopenharmony_ci	struct hci_conn *hcon;
278362306a36Sopenharmony_ci	struct hci_chan *hchan = NULL;
278462306a36Sopenharmony_ci
278562306a36Sopenharmony_ci	rcu_read_lock();
278662306a36Sopenharmony_ci
278762306a36Sopenharmony_ci	list_for_each_entry_rcu(hcon, &h->list, list) {
278862306a36Sopenharmony_ci		hchan = __hci_chan_lookup_handle(hcon, handle);
278962306a36Sopenharmony_ci		if (hchan)
279062306a36Sopenharmony_ci			break;
279162306a36Sopenharmony_ci	}
279262306a36Sopenharmony_ci
279362306a36Sopenharmony_ci	rcu_read_unlock();
279462306a36Sopenharmony_ci
279562306a36Sopenharmony_ci	return hchan;
279662306a36Sopenharmony_ci}
279762306a36Sopenharmony_ci
279862306a36Sopenharmony_ciu32 hci_conn_get_phy(struct hci_conn *conn)
279962306a36Sopenharmony_ci{
280062306a36Sopenharmony_ci	u32 phys = 0;
280162306a36Sopenharmony_ci
280262306a36Sopenharmony_ci	/* BLUETOOTH CORE SPECIFICATION Version 5.2 | Vol 2, Part B page 471:
280362306a36Sopenharmony_ci	 * Table 6.2: Packets defined for synchronous, asynchronous, and
280462306a36Sopenharmony_ci	 * CPB logical transport types.
280562306a36Sopenharmony_ci	 */
280662306a36Sopenharmony_ci	switch (conn->type) {
280762306a36Sopenharmony_ci	case SCO_LINK:
280862306a36Sopenharmony_ci		/* SCO logical transport (1 Mb/s):
280962306a36Sopenharmony_ci		 * HV1, HV2, HV3 and DV.
281062306a36Sopenharmony_ci		 */
281162306a36Sopenharmony_ci		phys |= BT_PHY_BR_1M_1SLOT;
281262306a36Sopenharmony_ci
281362306a36Sopenharmony_ci		break;
281462306a36Sopenharmony_ci
281562306a36Sopenharmony_ci	case ACL_LINK:
281662306a36Sopenharmony_ci		/* ACL logical transport (1 Mb/s) ptt=0:
281762306a36Sopenharmony_ci		 * DH1, DM3, DH3, DM5 and DH5.
281862306a36Sopenharmony_ci		 */
281962306a36Sopenharmony_ci		phys |= BT_PHY_BR_1M_1SLOT;
282062306a36Sopenharmony_ci
282162306a36Sopenharmony_ci		if (conn->pkt_type & (HCI_DM3 | HCI_DH3))
282262306a36Sopenharmony_ci			phys |= BT_PHY_BR_1M_3SLOT;
282362306a36Sopenharmony_ci
282462306a36Sopenharmony_ci		if (conn->pkt_type & (HCI_DM5 | HCI_DH5))
282562306a36Sopenharmony_ci			phys |= BT_PHY_BR_1M_5SLOT;
282662306a36Sopenharmony_ci
282762306a36Sopenharmony_ci		/* ACL logical transport (2 Mb/s) ptt=1:
282862306a36Sopenharmony_ci		 * 2-DH1, 2-DH3 and 2-DH5.
282962306a36Sopenharmony_ci		 */
283062306a36Sopenharmony_ci		if (!(conn->pkt_type & HCI_2DH1))
283162306a36Sopenharmony_ci			phys |= BT_PHY_EDR_2M_1SLOT;
283262306a36Sopenharmony_ci
283362306a36Sopenharmony_ci		if (!(conn->pkt_type & HCI_2DH3))
283462306a36Sopenharmony_ci			phys |= BT_PHY_EDR_2M_3SLOT;
283562306a36Sopenharmony_ci
283662306a36Sopenharmony_ci		if (!(conn->pkt_type & HCI_2DH5))
283762306a36Sopenharmony_ci			phys |= BT_PHY_EDR_2M_5SLOT;
283862306a36Sopenharmony_ci
283962306a36Sopenharmony_ci		/* ACL logical transport (3 Mb/s) ptt=1:
284062306a36Sopenharmony_ci		 * 3-DH1, 3-DH3 and 3-DH5.
284162306a36Sopenharmony_ci		 */
284262306a36Sopenharmony_ci		if (!(conn->pkt_type & HCI_3DH1))
284362306a36Sopenharmony_ci			phys |= BT_PHY_EDR_3M_1SLOT;
284462306a36Sopenharmony_ci
284562306a36Sopenharmony_ci		if (!(conn->pkt_type & HCI_3DH3))
284662306a36Sopenharmony_ci			phys |= BT_PHY_EDR_3M_3SLOT;
284762306a36Sopenharmony_ci
284862306a36Sopenharmony_ci		if (!(conn->pkt_type & HCI_3DH5))
284962306a36Sopenharmony_ci			phys |= BT_PHY_EDR_3M_5SLOT;
285062306a36Sopenharmony_ci
285162306a36Sopenharmony_ci		break;
285262306a36Sopenharmony_ci
285362306a36Sopenharmony_ci	case ESCO_LINK:
285462306a36Sopenharmony_ci		/* eSCO logical transport (1 Mb/s): EV3, EV4 and EV5 */
285562306a36Sopenharmony_ci		phys |= BT_PHY_BR_1M_1SLOT;
285662306a36Sopenharmony_ci
285762306a36Sopenharmony_ci		if (!(conn->pkt_type & (ESCO_EV4 | ESCO_EV5)))
285862306a36Sopenharmony_ci			phys |= BT_PHY_BR_1M_3SLOT;
285962306a36Sopenharmony_ci
286062306a36Sopenharmony_ci		/* eSCO logical transport (2 Mb/s): 2-EV3, 2-EV5 */
286162306a36Sopenharmony_ci		if (!(conn->pkt_type & ESCO_2EV3))
286262306a36Sopenharmony_ci			phys |= BT_PHY_EDR_2M_1SLOT;
286362306a36Sopenharmony_ci
286462306a36Sopenharmony_ci		if (!(conn->pkt_type & ESCO_2EV5))
286562306a36Sopenharmony_ci			phys |= BT_PHY_EDR_2M_3SLOT;
286662306a36Sopenharmony_ci
286762306a36Sopenharmony_ci		/* eSCO logical transport (3 Mb/s): 3-EV3, 3-EV5 */
286862306a36Sopenharmony_ci		if (!(conn->pkt_type & ESCO_3EV3))
286962306a36Sopenharmony_ci			phys |= BT_PHY_EDR_3M_1SLOT;
287062306a36Sopenharmony_ci
287162306a36Sopenharmony_ci		if (!(conn->pkt_type & ESCO_3EV5))
287262306a36Sopenharmony_ci			phys |= BT_PHY_EDR_3M_3SLOT;
287362306a36Sopenharmony_ci
287462306a36Sopenharmony_ci		break;
287562306a36Sopenharmony_ci
287662306a36Sopenharmony_ci	case LE_LINK:
287762306a36Sopenharmony_ci		if (conn->le_tx_phy & HCI_LE_SET_PHY_1M)
287862306a36Sopenharmony_ci			phys |= BT_PHY_LE_1M_TX;
287962306a36Sopenharmony_ci
288062306a36Sopenharmony_ci		if (conn->le_rx_phy & HCI_LE_SET_PHY_1M)
288162306a36Sopenharmony_ci			phys |= BT_PHY_LE_1M_RX;
288262306a36Sopenharmony_ci
288362306a36Sopenharmony_ci		if (conn->le_tx_phy & HCI_LE_SET_PHY_2M)
288462306a36Sopenharmony_ci			phys |= BT_PHY_LE_2M_TX;
288562306a36Sopenharmony_ci
288662306a36Sopenharmony_ci		if (conn->le_rx_phy & HCI_LE_SET_PHY_2M)
288762306a36Sopenharmony_ci			phys |= BT_PHY_LE_2M_RX;
288862306a36Sopenharmony_ci
288962306a36Sopenharmony_ci		if (conn->le_tx_phy & HCI_LE_SET_PHY_CODED)
289062306a36Sopenharmony_ci			phys |= BT_PHY_LE_CODED_TX;
289162306a36Sopenharmony_ci
289262306a36Sopenharmony_ci		if (conn->le_rx_phy & HCI_LE_SET_PHY_CODED)
289362306a36Sopenharmony_ci			phys |= BT_PHY_LE_CODED_RX;
289462306a36Sopenharmony_ci
289562306a36Sopenharmony_ci		break;
289662306a36Sopenharmony_ci	}
289762306a36Sopenharmony_ci
289862306a36Sopenharmony_ci	return phys;
289962306a36Sopenharmony_ci}
290062306a36Sopenharmony_ci
290162306a36Sopenharmony_cistatic int abort_conn_sync(struct hci_dev *hdev, void *data)
290262306a36Sopenharmony_ci{
290362306a36Sopenharmony_ci	struct hci_conn *conn;
290462306a36Sopenharmony_ci	u16 handle = PTR_UINT(data);
290562306a36Sopenharmony_ci
290662306a36Sopenharmony_ci	conn = hci_conn_hash_lookup_handle(hdev, handle);
290762306a36Sopenharmony_ci	if (!conn)
290862306a36Sopenharmony_ci		return 0;
290962306a36Sopenharmony_ci
291062306a36Sopenharmony_ci	return hci_abort_conn_sync(hdev, conn, conn->abort_reason);
291162306a36Sopenharmony_ci}
291262306a36Sopenharmony_ci
291362306a36Sopenharmony_ciint hci_abort_conn(struct hci_conn *conn, u8 reason)
291462306a36Sopenharmony_ci{
291562306a36Sopenharmony_ci	struct hci_dev *hdev = conn->hdev;
291662306a36Sopenharmony_ci
291762306a36Sopenharmony_ci	/* If abort_reason has already been set it means the connection is
291862306a36Sopenharmony_ci	 * already being aborted so don't attempt to overwrite it.
291962306a36Sopenharmony_ci	 */
292062306a36Sopenharmony_ci	if (conn->abort_reason)
292162306a36Sopenharmony_ci		return 0;
292262306a36Sopenharmony_ci
292362306a36Sopenharmony_ci	bt_dev_dbg(hdev, "handle 0x%2.2x reason 0x%2.2x", conn->handle, reason);
292462306a36Sopenharmony_ci
292562306a36Sopenharmony_ci	conn->abort_reason = reason;
292662306a36Sopenharmony_ci
292762306a36Sopenharmony_ci	/* If the connection is pending check the command opcode since that
292862306a36Sopenharmony_ci	 * might be blocking on hci_cmd_sync_work while waiting its respective
292962306a36Sopenharmony_ci	 * event so we need to hci_cmd_sync_cancel to cancel it.
293062306a36Sopenharmony_ci	 *
293162306a36Sopenharmony_ci	 * hci_connect_le serializes the connection attempts so only one
293262306a36Sopenharmony_ci	 * connection can be in BT_CONNECT at time.
293362306a36Sopenharmony_ci	 */
293462306a36Sopenharmony_ci	if (conn->state == BT_CONNECT && hdev->req_status == HCI_REQ_PEND) {
293562306a36Sopenharmony_ci		switch (hci_skb_event(hdev->sent_cmd)) {
293662306a36Sopenharmony_ci		case HCI_EV_LE_CONN_COMPLETE:
293762306a36Sopenharmony_ci		case HCI_EV_LE_ENHANCED_CONN_COMPLETE:
293862306a36Sopenharmony_ci		case HCI_EVT_LE_CIS_ESTABLISHED:
293962306a36Sopenharmony_ci			hci_cmd_sync_cancel(hdev, ECANCELED);
294062306a36Sopenharmony_ci			break;
294162306a36Sopenharmony_ci		}
294262306a36Sopenharmony_ci	}
294362306a36Sopenharmony_ci
294462306a36Sopenharmony_ci	return hci_cmd_sync_queue(hdev, abort_conn_sync, UINT_PTR(conn->handle),
294562306a36Sopenharmony_ci				  NULL);
294662306a36Sopenharmony_ci}
2947