diff options
Diffstat (limited to 'net/bluetooth/hci_sync.c')
| -rw-r--r-- | net/bluetooth/hci_sync.c | 222 | 
1 files changed, 52 insertions, 170 deletions
diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c index 8fe02921adf1..16daa79b7981 100644 --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c @@ -1043,11 +1043,10 @@ static int hci_disable_ext_adv_instance_sync(struct hci_dev *hdev, u8 instance)  	struct hci_cp_ext_adv_set *set;  	u8 data[sizeof(*cp) + sizeof(*set) * 1];  	u8 size; +	struct adv_info *adv = NULL;  	/* If request specifies an instance that doesn't exist, fail */  	if (instance > 0) { -		struct adv_info *adv; -  		adv = hci_find_adv_instance(hdev, instance);  		if (!adv)  			return -EINVAL; @@ -1066,7 +1065,7 @@ static int hci_disable_ext_adv_instance_sync(struct hci_dev *hdev, u8 instance)  	cp->num_of_sets = !!instance;  	cp->enable = 0x00; -	set->handle = instance; +	set->handle = adv ? adv->handle : instance;  	size = sizeof(*cp) + sizeof(*set) * cp->num_of_sets; @@ -1235,31 +1234,27 @@ int hci_setup_ext_adv_instance_sync(struct hci_dev *hdev, u8 instance)  static int hci_set_ext_scan_rsp_data_sync(struct hci_dev *hdev, u8 instance)  { -	struct { -		struct hci_cp_le_set_ext_scan_rsp_data cp; -		u8 data[HCI_MAX_EXT_AD_LENGTH]; -	} pdu; +	DEFINE_FLEX(struct hci_cp_le_set_ext_scan_rsp_data, pdu, data, length, +		    HCI_MAX_EXT_AD_LENGTH);  	u8 len;  	struct adv_info *adv = NULL;  	int err; -	memset(&pdu, 0, sizeof(pdu)); -  	if (instance) {  		adv = hci_find_adv_instance(hdev, instance);  		if (!adv || !adv->scan_rsp_changed)  			return 0;  	} -	len = eir_create_scan_rsp(hdev, instance, pdu.data); +	len = eir_create_scan_rsp(hdev, instance, pdu->data); -	pdu.cp.handle = instance; -	pdu.cp.length = len; -	pdu.cp.operation = LE_SET_ADV_DATA_OP_COMPLETE; -	pdu.cp.frag_pref = LE_SET_ADV_DATA_NO_FRAG; +	pdu->handle = adv ? adv->handle : instance; +	pdu->length = len; +	pdu->operation = LE_SET_ADV_DATA_OP_COMPLETE; +	pdu->frag_pref = LE_SET_ADV_DATA_NO_FRAG;  	err = __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_EXT_SCAN_RSP_DATA, -				    sizeof(pdu.cp) + len, &pdu.cp, +				    struct_size(pdu, data, len), pdu,  				    HCI_CMD_TIMEOUT);  	if (err)  		return err; @@ -1267,7 +1262,7 @@ static int hci_set_ext_scan_rsp_data_sync(struct hci_dev *hdev, u8 instance)  	if (adv) {  		adv->scan_rsp_changed = false;  	} else { -		memcpy(hdev->scan_rsp_data, pdu.data, len); +		memcpy(hdev->scan_rsp_data, pdu->data, len);  		hdev->scan_rsp_data_len = len;  	} @@ -1335,7 +1330,7 @@ int hci_enable_ext_advertising_sync(struct hci_dev *hdev, u8 instance)  	memset(set, 0, sizeof(*set)); -	set->handle = instance; +	set->handle = adv ? adv->handle : instance;  	/* Set duration per instance since controller is responsible for  	 * scheduling it. @@ -1411,29 +1406,25 @@ static int hci_set_per_adv_params_sync(struct hci_dev *hdev, u8 instance,  static int hci_set_per_adv_data_sync(struct hci_dev *hdev, u8 instance)  { -	struct { -		struct hci_cp_le_set_per_adv_data cp; -		u8 data[HCI_MAX_PER_AD_LENGTH]; -	} pdu; +	DEFINE_FLEX(struct hci_cp_le_set_per_adv_data, pdu, data, length, +		    HCI_MAX_PER_AD_LENGTH);  	u8 len; - -	memset(&pdu, 0, sizeof(pdu)); +	struct adv_info *adv = NULL;  	if (instance) { -		struct adv_info *adv = hci_find_adv_instance(hdev, instance); - +		adv = hci_find_adv_instance(hdev, instance);  		if (!adv || !adv->periodic)  			return 0;  	} -	len = eir_create_per_adv_data(hdev, instance, pdu.data); +	len = eir_create_per_adv_data(hdev, instance, pdu->data); -	pdu.cp.length = len; -	pdu.cp.handle = instance; -	pdu.cp.operation = LE_SET_ADV_DATA_OP_COMPLETE; +	pdu->length = len; +	pdu->handle = adv ? adv->handle : instance; +	pdu->operation = LE_SET_ADV_DATA_OP_COMPLETE;  	return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_PER_ADV_DATA, -				     sizeof(pdu.cp) + len, &pdu, +				     struct_size(pdu, data, len), pdu,  				     HCI_CMD_TIMEOUT);  } @@ -1727,31 +1718,27 @@ int hci_le_terminate_big_sync(struct hci_dev *hdev, u8 handle, u8 reason)  static int hci_set_ext_adv_data_sync(struct hci_dev *hdev, u8 instance)  { -	struct { -		struct hci_cp_le_set_ext_adv_data cp; -		u8 data[HCI_MAX_EXT_AD_LENGTH]; -	} pdu; +	DEFINE_FLEX(struct hci_cp_le_set_ext_adv_data, pdu, data, length, +		    HCI_MAX_EXT_AD_LENGTH);  	u8 len;  	struct adv_info *adv = NULL;  	int err; -	memset(&pdu, 0, sizeof(pdu)); -  	if (instance) {  		adv = hci_find_adv_instance(hdev, instance);  		if (!adv || !adv->adv_data_changed)  			return 0;  	} -	len = eir_create_adv_data(hdev, instance, pdu.data); +	len = eir_create_adv_data(hdev, instance, pdu->data); -	pdu.cp.length = len; -	pdu.cp.handle = instance; -	pdu.cp.operation = LE_SET_ADV_DATA_OP_COMPLETE; -	pdu.cp.frag_pref = LE_SET_ADV_DATA_NO_FRAG; +	pdu->length = len; +	pdu->handle = adv ? adv->handle : instance; +	pdu->operation = LE_SET_ADV_DATA_OP_COMPLETE; +	pdu->frag_pref = LE_SET_ADV_DATA_NO_FRAG;  	err = __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_EXT_ADV_DATA, -				    sizeof(pdu.cp) + len, &pdu.cp, +				    struct_size(pdu, data, len), pdu,  				    HCI_CMD_TIMEOUT);  	if (err)  		return err; @@ -1760,7 +1747,7 @@ static int hci_set_ext_adv_data_sync(struct hci_dev *hdev, u8 instance)  	if (adv) {  		adv->adv_data_changed = false;  	} else { -		memcpy(hdev->adv_data, pdu.data, len); +		memcpy(hdev->adv_data, pdu->data, len);  		hdev->adv_data_len = len;  	} @@ -2814,8 +2801,8 @@ static int hci_le_set_ext_scan_param_sync(struct hci_dev *hdev, u8 type,  				if (qos->bcast.in.phy & BT_ISO_PHY_CODED) {  					cp->scanning_phys |= LE_SCAN_PHY_CODED;  					hci_le_scan_phy_params(phy, type, -							       interval, -							       window); +							       interval * 3, +							       window * 3);  					num_phy++;  					phy++;  				} @@ -2835,7 +2822,7 @@ static int hci_le_set_ext_scan_param_sync(struct hci_dev *hdev, u8 type,  	if (scan_coded(hdev)) {  		cp->scanning_phys |= LE_SCAN_PHY_CODED; -		hci_le_scan_phy_params(phy, type, interval, window); +		hci_le_scan_phy_params(phy, type, interval * 3, window * 3);  		num_phy++;  		phy++;  	} @@ -3523,10 +3510,6 @@ static int hci_unconf_init_sync(struct hci_dev *hdev)  /* Read Local Supported Features. */  static int hci_read_local_features_sync(struct hci_dev *hdev)  { -	 /* Not all AMP controllers support this command */ -	if (hdev->dev_type == HCI_AMP && !(hdev->commands[14] & 0x20)) -		return 0; -  	return __hci_cmd_sync_status(hdev, HCI_OP_READ_LOCAL_FEATURES,  				     0, NULL, HCI_CMD_TIMEOUT);  } @@ -3561,51 +3544,6 @@ static int hci_read_local_cmds_sync(struct hci_dev *hdev)  	return 0;  } -/* Read Local AMP Info */ -static int hci_read_local_amp_info_sync(struct hci_dev *hdev) -{ -	return __hci_cmd_sync_status(hdev, HCI_OP_READ_LOCAL_AMP_INFO, -				     0, NULL, HCI_CMD_TIMEOUT); -} - -/* Read Data Blk size */ -static int hci_read_data_block_size_sync(struct hci_dev *hdev) -{ -	return __hci_cmd_sync_status(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, -				     0, NULL, HCI_CMD_TIMEOUT); -} - -/* Read Flow Control Mode */ -static int hci_read_flow_control_mode_sync(struct hci_dev *hdev) -{ -	return __hci_cmd_sync_status(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, -				     0, NULL, HCI_CMD_TIMEOUT); -} - -/* Read Location Data */ -static int hci_read_location_data_sync(struct hci_dev *hdev) -{ -	return __hci_cmd_sync_status(hdev, HCI_OP_READ_LOCATION_DATA, -				     0, NULL, HCI_CMD_TIMEOUT); -} - -/* AMP Controller init stage 1 command sequence */ -static const struct hci_init_stage amp_init1[] = { -	/* HCI_OP_READ_LOCAL_VERSION */ -	HCI_INIT(hci_read_local_version_sync), -	/* HCI_OP_READ_LOCAL_COMMANDS */ -	HCI_INIT(hci_read_local_cmds_sync), -	/* HCI_OP_READ_LOCAL_AMP_INFO */ -	HCI_INIT(hci_read_local_amp_info_sync), -	/* HCI_OP_READ_DATA_BLOCK_SIZE */ -	HCI_INIT(hci_read_data_block_size_sync), -	/* HCI_OP_READ_FLOW_CONTROL_MODE */ -	HCI_INIT(hci_read_flow_control_mode_sync), -	/* HCI_OP_READ_LOCATION_DATA */ -	HCI_INIT(hci_read_location_data_sync), -	{} -}; -  static int hci_init1_sync(struct hci_dev *hdev)  {  	int err; @@ -3619,28 +3557,9 @@ static int hci_init1_sync(struct hci_dev *hdev)  			return err;  	} -	switch (hdev->dev_type) { -	case HCI_PRIMARY: -		hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_PACKET_BASED; -		return hci_init_stage_sync(hdev, br_init1); -	case HCI_AMP: -		hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_BLOCK_BASED; -		return hci_init_stage_sync(hdev, amp_init1); -	default: -		bt_dev_err(hdev, "Unknown device type %d", hdev->dev_type); -		break; -	} - -	return 0; +	return hci_init_stage_sync(hdev, br_init1);  } -/* AMP Controller init stage 2 command sequence */ -static const struct hci_init_stage amp_init2[] = { -	/* HCI_OP_READ_LOCAL_FEATURES */ -	HCI_INIT(hci_read_local_features_sync), -	{} -}; -  /* Read Buffer Size (ACL mtu, max pkt, etc.) */  static int hci_read_buffer_size_sync(struct hci_dev *hdev)  { @@ -3898,9 +3817,6 @@ static int hci_init2_sync(struct hci_dev *hdev)  	bt_dev_dbg(hdev, ""); -	if (hdev->dev_type == HCI_AMP) -		return hci_init_stage_sync(hdev, amp_init2); -  	err = hci_init_stage_sync(hdev, hci_init2);  	if (err)  		return err; @@ -4728,13 +4644,6 @@ static int hci_init_sync(struct hci_dev *hdev)  	if (err < 0)  		return err; -	/* HCI_PRIMARY covers both single-mode LE, BR/EDR and dual-mode -	 * BR/EDR/LE type controllers. AMP controllers only need the -	 * first two stages of init. -	 */ -	if (hdev->dev_type != HCI_PRIMARY) -		return 0; -  	err = hci_init3_sync(hdev);  	if (err < 0)  		return err; @@ -4963,12 +4872,8 @@ int hci_dev_open_sync(struct hci_dev *hdev)  		 * In case of user channel usage, it is not important  		 * if a public address or static random address is  		 * available. -		 * -		 * This check is only valid for BR/EDR controllers -		 * since AMP controllers do not have an address.  		 */  		if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL) && -		    hdev->dev_type == HCI_PRIMARY &&  		    !bacmp(&hdev->bdaddr, BDADDR_ANY) &&  		    !bacmp(&hdev->static_addr, BDADDR_ANY)) {  			ret = -EADDRNOTAVAIL; @@ -5003,8 +4908,7 @@ int hci_dev_open_sync(struct hci_dev *hdev)  		    !hci_dev_test_flag(hdev, HCI_CONFIG) &&  		    !hci_dev_test_flag(hdev, HCI_UNCONFIGURED) &&  		    !hci_dev_test_flag(hdev, HCI_USER_CHANNEL) && -		    hci_dev_test_flag(hdev, HCI_MGMT) && -		    hdev->dev_type == HCI_PRIMARY) { +		    hci_dev_test_flag(hdev, HCI_MGMT)) {  			ret = hci_powered_update_sync(hdev);  			mgmt_power_on(hdev, ret);  		} @@ -5149,8 +5053,7 @@ int hci_dev_close_sync(struct hci_dev *hdev)  	auto_off = hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF); -	if (!auto_off && hdev->dev_type == HCI_PRIMARY && -	    !hci_dev_test_flag(hdev, HCI_USER_CHANNEL) && +	if (!auto_off && !hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&  	    hci_dev_test_flag(hdev, HCI_MGMT))  		__mgmt_power_off(hdev); @@ -5212,9 +5115,6 @@ int hci_dev_close_sync(struct hci_dev *hdev)  	hdev->flags &= BIT(HCI_RAW);  	hci_dev_clear_volatile_flags(hdev); -	/* Controller radio is available but is currently powered down */ -	hdev->amp_status = AMP_STATUS_POWERED_DOWN; -  	memset(hdev->eir, 0, sizeof(hdev->eir));  	memset(hdev->dev_class, 0, sizeof(hdev->dev_class));  	bacpy(&hdev->random_addr, BDADDR_ANY); @@ -5251,8 +5151,7 @@ static int hci_power_on_sync(struct hci_dev *hdev)  	 */  	if (hci_dev_test_flag(hdev, HCI_RFKILLED) ||  	    hci_dev_test_flag(hdev, HCI_UNCONFIGURED) || -	    (hdev->dev_type == HCI_PRIMARY && -	     !bacmp(&hdev->bdaddr, BDADDR_ANY) && +	    (!bacmp(&hdev->bdaddr, BDADDR_ANY) &&  	     !bacmp(&hdev->static_addr, BDADDR_ANY))) {  		hci_dev_clear_flag(hdev, HCI_AUTO_OFF);  		hci_dev_close_sync(hdev); @@ -5354,27 +5253,11 @@ int hci_stop_discovery_sync(struct hci_dev *hdev)  	return 0;  } -static int hci_disconnect_phy_link_sync(struct hci_dev *hdev, u16 handle, -					u8 reason) -{ -	struct hci_cp_disconn_phy_link cp; - -	memset(&cp, 0, sizeof(cp)); -	cp.phy_handle = HCI_PHY_HANDLE(handle); -	cp.reason = reason; - -	return __hci_cmd_sync_status(hdev, HCI_OP_DISCONN_PHY_LINK, -				     sizeof(cp), &cp, HCI_CMD_TIMEOUT); -} -  static int hci_disconnect_sync(struct hci_dev *hdev, struct hci_conn *conn,  			       u8 reason)  {  	struct hci_cp_disconnect cp; -	if (conn->type == AMP_LINK) -		return hci_disconnect_phy_link_sync(hdev, conn->handle, reason); -  	if (test_bit(HCI_CONN_BIG_CREATED, &conn->flags)) {  		/* This is a BIS connection, hci_conn_del will  		 * do the necessary cleanup. @@ -6346,7 +6229,8 @@ static int hci_le_ext_create_conn_sync(struct hci_dev *hdev,  	plen = sizeof(*cp); -	if (scan_1m(hdev)) { +	if (scan_1m(hdev) && (conn->le_adv_phy == HCI_ADV_PHY_1M || +			      conn->le_adv_sec_phy == HCI_ADV_PHY_1M)) {  		cp->phys |= LE_SCAN_PHY_1M;  		set_ext_conn_params(conn, p); @@ -6354,7 +6238,8 @@ static int hci_le_ext_create_conn_sync(struct hci_dev *hdev,  		plen += sizeof(*p);  	} -	if (scan_2m(hdev)) { +	if (scan_2m(hdev) && (conn->le_adv_phy == HCI_ADV_PHY_2M || +			      conn->le_adv_sec_phy == HCI_ADV_PHY_2M)) {  		cp->phys |= LE_SCAN_PHY_2M;  		set_ext_conn_params(conn, p); @@ -6362,7 +6247,8 @@ static int hci_le_ext_create_conn_sync(struct hci_dev *hdev,  		plen += sizeof(*p);  	} -	if (scan_coded(hdev)) { +	if (scan_coded(hdev) && (conn->le_adv_phy == HCI_ADV_PHY_CODED || +				 conn->le_adv_sec_phy == HCI_ADV_PHY_CODED)) {  		cp->phys |= LE_SCAN_PHY_CODED;  		set_ext_conn_params(conn, p); @@ -6490,10 +6376,8 @@ done:  int hci_le_create_cis_sync(struct hci_dev *hdev)  { -	struct { -		struct hci_cp_le_create_cis cp; -		struct hci_cis cis[0x1f]; -	} cmd; +	DEFINE_FLEX(struct hci_cp_le_create_cis, cmd, cis, num_cis, 0x1f); +	size_t aux_num_cis = 0;  	struct hci_conn *conn;  	u8 cig = BT_ISO_QOS_CIG_UNSET; @@ -6520,8 +6404,6 @@ int hci_le_create_cis_sync(struct hci_dev *hdev)  	 * remains pending.  	 */ -	memset(&cmd, 0, sizeof(cmd)); -  	hci_dev_lock(hdev);  	rcu_read_lock(); @@ -6558,7 +6440,7 @@ int hci_le_create_cis_sync(struct hci_dev *hdev)  		goto done;  	list_for_each_entry_rcu(conn, &hdev->conn_hash.list, list) { -		struct hci_cis *cis = &cmd.cis[cmd.cp.num_cis]; +		struct hci_cis *cis = &cmd->cis[aux_num_cis];  		if (hci_conn_check_create_cis(conn) ||  		    conn->iso_qos.ucast.cig != cig) @@ -6567,25 +6449,25 @@ int hci_le_create_cis_sync(struct hci_dev *hdev)  		set_bit(HCI_CONN_CREATE_CIS, &conn->flags);  		cis->acl_handle = cpu_to_le16(conn->parent->handle);  		cis->cis_handle = cpu_to_le16(conn->handle); -		cmd.cp.num_cis++; +		aux_num_cis++; -		if (cmd.cp.num_cis >= ARRAY_SIZE(cmd.cis)) +		if (aux_num_cis >= cmd->num_cis)  			break;  	} +	cmd->num_cis = aux_num_cis;  done:  	rcu_read_unlock();  	hci_dev_unlock(hdev); -	if (!cmd.cp.num_cis) +	if (!aux_num_cis)  		return 0;  	/* Wait for HCI_LE_CIS_Established */  	return __hci_cmd_sync_status_sk(hdev, HCI_OP_LE_CREATE_CIS, -					sizeof(cmd.cp) + sizeof(cmd.cis[0]) * -					cmd.cp.num_cis, &cmd, -					HCI_EVT_LE_CIS_ESTABLISHED, +					struct_size(cmd, cis, cmd->num_cis), +					cmd, HCI_EVT_LE_CIS_ESTABLISHED,  					conn->conn_timeout, NULL);  }  |