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:
parent
54bdd7aee0
commit
45411bc08d
3 changed files with 95 additions and 46 deletions
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue