Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fdf51784 authored by Arman Uguray's avatar Arman Uguray Committed by Marcel Holtmann
Browse files

Bluetooth: Unify advertising data code paths



This patch simplifies the code paths for assembling the advertising data
used by advertising instances 0 and 1.

Signed-off-by: default avatarArman Uguray <armansito@chromium.org>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 089fa8c0
Loading
Loading
Loading
Loading
+64 −91
Original line number Diff line number Diff line
@@ -941,52 +941,73 @@ static u8 get_adv_discov_flags(struct hci_dev *hdev)
	return 0;
}

static u8 create_default_adv_data(struct hci_dev *hdev, u8 *ptr)
static u8 get_current_adv_instance(struct hci_dev *hdev)
{
	u8 ad_len = 0, flags = 0;
	/* The "Set Advertising" setting supersedes the "Add Advertising"
	 * setting. Here we set the advertising data based on which
	 * setting was set. When neither apply, default to the global settings,
	 * represented by instance "0".
	 */
	if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) &&
	    !hci_dev_test_flag(hdev, HCI_ADVERTISING))
		return 0x01;

	flags |= get_adv_discov_flags(hdev);
	return 0x00;
}

	if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
		flags |= LE_AD_NO_BREDR;
static bool get_connectable(struct hci_dev *hdev)
{
	struct mgmt_pending_cmd *cmd;

	if (flags) {
		BT_DBG("adv flags 0x%02x", flags);
	/* If there's a pending mgmt command the flag will not yet have
	 * it's final value, so check for this first.
	 */
	cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
	if (cmd) {
		struct mgmt_mode *cp = cmd->param;

		ptr[0] = 2;
		ptr[1] = EIR_FLAGS;
		ptr[2] = flags;
		return cp->val;
	}

		ad_len += 3;
		ptr += 3;
	return hci_dev_test_flag(hdev, HCI_CONNECTABLE);
}

	if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
		ptr[0] = 2;
		ptr[1] = EIR_TX_POWER;
		ptr[2] = (u8) hdev->adv_tx_power;
static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance)
{
	u32 flags;

		ad_len += 3;
		ptr += 3;
	}
	if (instance > 0x01)
		return 0;

	return ad_len;
	if (instance == 0x01)
		return hdev->adv_instance.flags;

	/* Instance 0 always manages the "Tx Power" and "Flags" fields */
	flags = MGMT_ADV_FLAG_TX_POWER | MGMT_ADV_FLAG_MANAGED_FLAGS;

	/* For instance 0, assemble the flags from global settings */
	if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE) ||
	    get_connectable(hdev))
		flags |= MGMT_ADV_FLAG_CONNECTABLE;

	return flags;
}

static u8 create_instance_adv_data(struct hci_dev *hdev, u8 *ptr)
static u8 create_instance_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr)
{
	u8 ad_len = 0, flags = 0;
	u32 instance_flags = get_adv_instance_flags(hdev, instance);

	/* The Add Advertising command allows userspace to set both the general
	 * and limited discoverable flags.
	 */
	if (hdev->adv_instance.flags & MGMT_ADV_FLAG_DISCOV)
	if (instance_flags & MGMT_ADV_FLAG_DISCOV)
		flags |= LE_AD_GENERAL;

	if (hdev->adv_instance.flags & MGMT_ADV_FLAG_LIMITED_DISCOV)
	if (instance_flags & MGMT_ADV_FLAG_LIMITED_DISCOV)
		flags |= LE_AD_LIMITED;

	if (flags || (hdev->adv_instance.flags & MGMT_ADV_FLAG_MANAGED_FLAGS)) {
	if (flags || (instance_flags & MGMT_ADV_FLAG_MANAGED_FLAGS)) {
		/* If a discovery flag wasn't provided, simply use the global
		 * settings.
		 */
@@ -996,6 +1017,10 @@ static u8 create_instance_adv_data(struct hci_dev *hdev, u8 *ptr)
		if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
			flags |= LE_AD_NO_BREDR;

		/* If flags would still be empty, then there is no need to
		 * include the "Flags" AD field".
		 */
		if (flags) {
			ptr[0] = 0x02;
			ptr[1] = EIR_FLAGS;
			ptr[2] = flags;
@@ -1003,9 +1028,11 @@ static u8 create_instance_adv_data(struct hci_dev *hdev, u8 *ptr)
			ad_len += 3;
			ptr += 3;
		}
	}

	/* Provide Tx Power only if we can provide a valid value for it */
	if (hdev->adv_tx_power != HCI_TX_POWER_INVALID &&
	    (hdev->adv_instance.flags & MGMT_ADV_FLAG_TX_POWER)) {
	    (instance_flags & MGMT_ADV_FLAG_TX_POWER)) {
		ptr[0] = 0x02;
		ptr[1] = EIR_TX_POWER;
		ptr[2] = (u8)hdev->adv_tx_power;
@@ -1014,9 +1041,11 @@ static u8 create_instance_adv_data(struct hci_dev *hdev, u8 *ptr)
		ptr += 3;
	}

	if (instance) {
		memcpy(ptr, hdev->adv_instance.adv_data,
		       hdev->adv_instance.adv_data_len);
		ad_len += hdev->adv_instance.adv_data_len;
	}

	return ad_len;
}
@@ -1032,10 +1061,7 @@ static void update_adv_data_for_instance(struct hci_request *req, u8 instance)

	memset(&cp, 0, sizeof(cp));

	if (instance)
		len = create_instance_adv_data(hdev, cp.data);
	else
		len = create_default_adv_data(hdev, cp.data);
	len = create_instance_adv_data(hdev, instance, cp.data);

	/* There's nothing to do if the data hasn't changed */
	if (hdev->adv_data_len == len &&
@@ -1050,59 +1076,6 @@ static void update_adv_data_for_instance(struct hci_request *req, u8 instance)
	hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
}

static u8 get_current_adv_instance(struct hci_dev *hdev)
{
	/* The "Set Advertising" setting supersedes the "Add Advertising"
	 * setting. Here we set the advertising data based on which
	 * setting was set. When neither apply, default to the global settings,
	 * represented by instance "0".
	 */
	if (hci_dev_test_flag(hdev, HCI_ADVERTISING_INSTANCE) &&
	    !hci_dev_test_flag(hdev, HCI_ADVERTISING))
		return 0x01;

	return 0x00;
}

static bool get_connectable(struct hci_dev *hdev)
{
	struct mgmt_pending_cmd *cmd;

	/* If there's a pending mgmt command the flag will not yet have
	 * it's final value, so check for this first.
	 */
	cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
	if (cmd) {
		struct mgmt_mode *cp = cmd->param;

		return cp->val;
	}

	return hci_dev_test_flag(hdev, HCI_CONNECTABLE);
}

static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance)
{
	u32 flags;

	if (instance > 0x01)
		return 0;

	if (instance == 1)
		return hdev->adv_instance.flags;

	flags = 0;

	/* For instance 0, assemble the flags from global settings */
	if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE) ||
	    get_connectable(hdev))
		flags |= MGMT_ADV_FLAG_CONNECTABLE;

	/* TODO: Add the rest of the flags */

	return flags;
}

static void update_adv_data(struct hci_request *req)
{
	struct hci_dev *hdev = req->hdev;