Bluetooth: Update advertising data without advertising restart

This adds new API fuction to update running advertising data.
It will remove the need of advertising restarting.

Signed-off-by: Mariusz Skamra <mariusz.skamra@codecoup.pl>
This commit is contained in:
Mariusz Skamra 2018-10-25 15:20:09 +02:00 committed by Johan Hedberg
commit 45411bc08d
3 changed files with 95 additions and 46 deletions

View file

@ -348,6 +348,20 @@ int bt_le_adv_start(const struct bt_le_adv_param *param,
const struct bt_data *ad, size_t ad_len,
const struct bt_data *sd, size_t sd_len);
/** @brief Update advertising
*
* Update advertisement and scan response data.
*
* @param ad Data to be used in advertisement packets.
* @param ad_len Number of elements in ad
* @param sd Data to be used in scan response packets.
* @param sd_len Number of elements in sd
*
* @return Zero on success or (negative) error code otherwise.
*/
int bt_le_adv_update_data(const struct bt_data *ad, size_t ad_len,
const struct bt_data *sd, size_t sd_len);
/** @brief Stop advertising
*
* Stops ongoing advertising.

View file

@ -5125,6 +5125,79 @@ static inline bool ad_has_name(const struct bt_data *ad, size_t ad_len)
return false;
}
static int le_adv_update(const struct bt_data *ad, size_t ad_len,
const struct bt_data *sd, size_t sd_len,
bool connectable, bool use_name)
{
struct bt_ad d[2] = {};
int err;
d[0].data = ad;
d[0].len = ad_len;
err = set_ad(BT_HCI_OP_LE_SET_ADV_DATA, d, 1);
if (err) {
return err;
}
d[0].data = sd;
d[0].len = sd_len;
if (use_name) {
const char *name;
if (sd) {
/* Cannot use name if name is already set */
if (ad_has_name(sd, sd_len)) {
return -EINVAL;
}
}
name = bt_get_name();
d[1].data = (&(struct bt_data)BT_DATA(
BT_DATA_NAME_COMPLETE,
name, strlen(name)));
d[1].len = 1;
}
/*
* We need to set SCAN_RSP when enabling advertising type that
* allows for Scan Requests.
*
* If any data was not provided but we enable connectable
* undirected advertising sd needs to be cleared from values set
* by previous calls.
* Clearing sd is done by calling set_ad() with NULL data and
* zero len.
* So following condition check is unusual but correct.
*/
if (d[0].data || d[1].data || connectable) {
err = set_ad(BT_HCI_OP_LE_SET_SCAN_RSP_DATA, d, 2);
if (err) {
return err;
}
}
return 0;
}
int bt_le_adv_update_data(const struct bt_data *ad, size_t ad_len,
const struct bt_data *sd, size_t sd_len)
{
bool connectable, use_name;
if (!atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) {
return -EAGAIN;
}
connectable = atomic_test_bit(bt_dev.flags,
BT_DEV_ADVERTISING_CONNECTABLE);
use_name = atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING_NAME);
return le_adv_update(ad, ad_len, sd, sd_len, connectable, use_name);
}
int bt_le_adv_start_internal(const struct bt_le_adv_param *param,
const struct bt_data *ad, size_t ad_len,
const struct bt_data *sd, size_t sd_len,
@ -5145,55 +5218,12 @@ int bt_le_adv_start_internal(const struct bt_le_adv_param *param,
}
if (!dir_adv) {
struct bt_ad d[2] = {};
d[0].data = ad;
d[0].len = ad_len;
err = set_ad(BT_HCI_OP_LE_SET_ADV_DATA, d, 1);
err = le_adv_update(ad, ad_len, sd, sd_len,
param->options & BT_LE_ADV_OPT_CONNECTABLE,
param->options & BT_LE_ADV_OPT_USE_NAME);
if (err) {
return err;
}
d[0].data = sd;
d[0].len = sd_len;
if (param->options & BT_LE_ADV_OPT_USE_NAME) {
const char *name;
if (sd) {
/* Cannot use name if name is already set */
if (ad_has_name(sd, sd_len)) {
return -EINVAL;
}
}
name = bt_get_name();
d[1].data = (&(struct bt_data)BT_DATA(
BT_DATA_NAME_COMPLETE,
name, strlen(name)));
d[1].len = 1;
}
/*
* We need to set SCAN_RSP when enabling advertising type that
* allows for Scan Requests.
*
* If any data was not provided but we enable connectable
* undirected advertising sd needs to be cleared from values set
* by previous calls.
* Clearing sd is done by calling set_ad() with NULL data and
* zero len.
* So following condition check is unusual but correct.
*/
if (d[0].data || d[1].data ||
(param->options & BT_LE_ADV_OPT_CONNECTABLE)) {
err = set_ad(BT_HCI_OP_LE_SET_SCAN_RSP_DATA, d, 2);
if (err) {
return err;
}
}
}
(void)memset(&set_param, 0, sizeof(set_param));
@ -5292,6 +5322,10 @@ int bt_le_adv_start_internal(const struct bt_le_adv_param *param,
atomic_set_bit(bt_dev.flags, BT_DEV_ADVERTISING_NAME);
}
if (param->options & BT_LE_ADV_OPT_CONNECTABLE) {
atomic_set_bit(bt_dev.flags, BT_DEV_ADVERTISING_CONNECTABLE);
}
return 0;
}

View file

@ -37,6 +37,7 @@ enum {
BT_DEV_ADVERTISING,
BT_DEV_ADVERTISING_NAME,
BT_DEV_ADVERTISING_CONNECTABLE,
BT_DEV_KEEP_ADVERTISING,
BT_DEV_SCANNING,
BT_DEV_EXPLICIT_SCAN,