diff options
-rw-r--r-- | lib/mgmt.h | 1 | ||||
-rw-r--r-- | src/advertising.c | 24 | ||||
-rw-r--r-- | src/shared/ad.c | 17 | ||||
-rw-r--r-- | src/shared/ad.h | 2 |
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); |