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

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
......@@ -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;
flags |= get_adv_discov_flags(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;
if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
flags |= LE_AD_NO_BREDR;
return 0x00;
}
if (flags) {
BT_DBG("adv flags 0x%02x", flags);
static bool get_connectable(struct hci_dev *hdev)
{
struct mgmt_pending_cmd *cmd;
ptr[0] = 2;
ptr[1] = EIR_FLAGS;
ptr[2] = 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;
ad_len += 3;
ptr += 3;
return cp->val;
}
if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
ptr[0] = 2;
ptr[1] = EIR_TX_POWER;
ptr[2] = (u8) hdev->adv_tx_power;
return hci_dev_test_flag(hdev, HCI_CONNECTABLE);
}
ad_len += 3;
ptr += 3;
}
static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance)
{
u32 flags;
return ad_len;
if (instance > 0x01)
return 0;
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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment