summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/mgmt.h1
-rw-r--r--src/advertising.c24
-rw-r--r--src/shared/ad.c17
-rw-r--r--src/shared/ad.h2
4 files changed, 43 insertions, 1 deletions
diff --git a/lib/mgmt.h b/lib/mgmt.h
index c0021abd8..81e54c48d 100644
--- a/lib/mgmt.h
+++ b/lib/mgmt.h
@@ -509,6 +509,7 @@ struct mgmt_rp_add_advertising {
#define MGMT_ADV_PARAM_TIMEOUT (1 << 13)
#define MGMT_ADV_PARAM_INTERVALS (1 << 14)
#define MGMT_ADV_PARAM_TX_POWER (1 << 15)
+#define MGMT_ADV_PARAM_SCAN_RSP (1 << 16)
#define MGMT_OP_REMOVE_ADVERTISING 0x003F
struct mgmt_cp_remove_advertising {
diff --git a/src/advertising.c b/src/advertising.c
index 4ab449ceb..70e60601d 100644
--- a/src/advertising.c
+++ b/src/advertising.c
@@ -793,6 +793,22 @@ static uint8_t *generate_scan_rsp(struct btd_adv_client *client,
return bt_ad_generate(client->scan, len);
}
+static bool adv_client_has_scan_response(struct btd_adv_client *client,
+ uint32_t flags)
+{
+ /* The local name isn't added into the bt_ad structure until
+ * generate_scan_rsp is called, so we must check these conditions as
+ * well.
+ */
+ if (!(flags & MGMT_ADV_FLAG_LOCAL_NAME) &&
+ !client->name &&
+ bt_ad_is_empty(client->scan)) {
+ return false;
+ }
+
+ return true;
+}
+
static int get_adv_flags(struct btd_adv_client *client)
{
uint32_t flags = 0;
@@ -917,7 +933,13 @@ static int refresh_extended_adv(struct btd_adv_client *client,
flags |= MGMT_ADV_PARAM_TX_POWER;
}
- cp.flags = htobl(flags);
+ /* Indicate that this instance will be configured as scannable */
+ if (adv_client_has_scan_response(client, flags) &&
+ client->manager->supported_flags & MGMT_ADV_PARAM_SCAN_RSP) {
+ flags |= MGMT_ADV_PARAM_SCAN_RSP;
+ }
+
+ cp.flags = cpu_to_le32(flags);
mgmt_ret = mgmt_send(client->manager->mgmt, MGMT_OP_ADD_EXT_ADV_PARAMS,
client->manager->mgmt_index, sizeof(cp), &cp,
diff --git a/src/shared/ad.c b/src/shared/ad.c
index 23c8c34f4..d40d15331 100644
--- a/src/shared/ad.c
+++ b/src/shared/ad.c
@@ -552,6 +552,23 @@ uint8_t *bt_ad_generate(struct bt_ad *ad, size_t *length)
return adv_data;
}
+bool bt_ad_is_empty(struct bt_ad *ad)
+{
+ /* If any of the bt_ad fields are non-empty or don't have the default
+ * value, then bt_ad_generate will return a non-empty buffer
+ */
+ if (!ad->name &&
+ ad->appearance == UINT16_MAX &&
+ queue_isempty(ad->service_uuids) &&
+ queue_isempty(ad->manufacturer_data) &&
+ queue_isempty(ad->solicit_uuids) &&
+ queue_isempty(ad->service_data) &&
+ queue_isempty(ad->data)) {
+ return true;
+ }
+ return false;
+}
+
static bool queue_add_uuid(struct queue *queue, const bt_uuid_t *uuid)
{
bt_uuid_t *new_uuid;
diff --git a/src/shared/ad.h b/src/shared/ad.h
index 13adcb406..84ef9dee9 100644
--- a/src/shared/ad.h
+++ b/src/shared/ad.h
@@ -105,6 +105,8 @@ void bt_ad_unref(struct bt_ad *ad);
uint8_t *bt_ad_generate(struct bt_ad *ad, size_t *length);
+bool bt_ad_is_empty(struct bt_ad *ad);
+
bool bt_ad_add_service_uuid(struct bt_ad *ad, const bt_uuid_t *uuid);
bool bt_ad_remove_service_uuid(struct bt_ad *ad, bt_uuid_t *uuid);