Skip to content

Commit

Permalink
Bluetooth: Deprecate adv auto-resume
Browse files Browse the repository at this point in the history
The host-based adv auto-resume function has both a problematic
implementation and disagreement in the community around how it should
behave. See the issue linked resolved below for details.

This patch makes the deprecation visible to the user. The user will be
better served by a auto-resume tailored their applications use case,
based on more primitive host API like `conn_cb.recycled`, which has
obvious behavior that is unlikely to change.

Resolves: #72567

Signed-off-by: Aleksander Wasaznik <[email protected]>
  • Loading branch information
alwa-nordic committed Oct 3, 2024
1 parent 9655c2f commit 1fa9f59
Show file tree
Hide file tree
Showing 96 changed files with 371 additions and 272 deletions.
72 changes: 72 additions & 0 deletions doc/releases/migration-guide-4.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,78 @@ Bluetooth Classic
Bluetooth Host
==============

Automatic advertiser resumption is deprecated
---------------------------------------------

.. note::

This deprecation is compiler-checked. If you get no warnings,
you should not be affected.

Deprecated symbols:
* :c:enumerator:`BT_LE_ADV_OPT_CONNECTABLE`
* :c:enumerator:`BT_LE_ADV_OPT_ONE_TIME`
* :c:macro:`BT_LE_ADV_CONN`

New symbols:
* :c:enumerator:`BT_LE_ADV_OPT_CONN`
* :c:macro:`BT_LE_ADV_CONN_FAST_1`
* :c:macro:`BT_LE_ADV_CONN_FAST_2`

:c:enumerator:`BT_LE_ADV_OPT_CONNECTABLE` is a combined
instruction to make the advertiser connectable and to enable
automatic resumption. To disable the automatic resumption, use
:c:enumerator:`BT_LE_ADV_OPT_CONN`.

Extended Advertising API with shorthands
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Extended Advertising API ``bt_le_ext_adv_*`` implicitly assumes
:c:enumerator:`BT_LE_ADV_OPT_ONE_TIME` and never automatically
resume advertising. Therefore, the following search/replace can
be applied without thinking:

Replace all

.. code-block:: diff
-bt_le_ext_adv_create(BT_LE_ADV_CONN, ...)
+bt_le_ext_adv_create(BT_LE_ADV_FAST_2, ...)
.. code-block:: diff
-bt_le_ext_adv_update_param(..., BT_LE_ADV_CONN)
+bt_le_ext_adv_update_param(..., BT_LE_ADV_FAST_2)
Extended Advertising API with custom parameters
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

You may have uses of :c:enumerator:`BT_LE_ADV_OPT_CONNECTABLE`
in assignments to a :c:struct:`bt_le_adv_param`. If your struct
is never passed to :c:func:`bt_le_adv_start`, you should:

* replace :c:enumerator:`BT_LE_ADV_OPT_CONNECTABLE` with
:c:enumerator:`BT_LE_ADV_OPT_CONN`.
* remove :c:enumerator:`BT_LE_ADV_OPT_ONE_TIME`.

Legacy Advertising API not using automatic resumption
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Any calls to :c:func:`bt_le_adv_start` that use the combination
:c:enumerator:`BT_LE_ADV_OPT_CONNECTABLE` and
:c:enumerator:`BT_LE_ADV_OPT_ONE_TIME` should have that
combination replaced with :c:enumerator:`BT_LE_ADV_OPT_CONN`.

Legacy Advertising API using automatic resumption
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

For this case, the application has to take over the
responsibility of restarting the advertiser.

Refer to the extended advertising sample for an example
implementation of advertiser restarting. The same technique can
be used for legacy advertising.

Bluetooth Crypto
================

Expand Down
138 changes: 114 additions & 24 deletions include/zephyr/bluetooth/bluetooth.h
Original file line number Diff line number Diff line change
Expand Up @@ -525,16 +525,42 @@ enum {
/**
* @brief Advertise as connectable.
*
* @deprecated Use @ref BT_LE_ADV_OPT_CONN instead.
*
* Advertise as connectable. If not connectable then the type of
* advertising is determined by providing scan response data.
* The advertiser address is determined by the type of advertising
* and/or enabling privacy @kconfig{CONFIG_BT_PRIVACY}.
*
* Starting connectable advertising preallocates a connection
* object. If this fails, the API returns @c -ENOMEM.
*
* When an advertiser set results in a connection creation, the
* controller automatically disables that advertising set.
*
* If the advertising set was started with @ref bt_le_adv_start
* without @ref BT_LE_ADV_OPT_ONE_TIME, the host will attempt to
* resume the advertiser under some conditions.
*/
BT_LE_ADV_OPT_CONNECTABLE __deprecated = BIT(0),

/**
* @internal
*
* Internal access to the deprecated value to maintain the
* implementation of the deprecated feature.
*
* At the end of the deprecation period, ABI will change so
* `BT_LE_ADV_OPT_CONN` is just `BIT(0)`, removing the need for this
* symbol.
*/
BT_LE_ADV_OPT_CONNECTABLE = BIT(0),
_BT_LE_ADV_OPT_CONNECTABLE = BIT(0),

/**
* @brief Advertise one time.
*
* @deprecated Use @ref BT_LE_ADV_OPT_CONN instead.
*
* Don't try to resume connectable advertising after a connection.
* This option is only meaningful when used together with
* BT_LE_ADV_OPT_CONNECTABLE. If set the advertising will be stopped
Expand All @@ -546,7 +572,35 @@ enum {
* @ref bt_le_ext_adv_start then this behavior is the default behavior
* and this flag has no effect.
*/
BT_LE_ADV_OPT_ONE_TIME = BIT(1),
BT_LE_ADV_OPT_ONE_TIME __deprecated = BIT(1),

/**
* @internal
*
* Internal access to the deprecated value to maintain
* the implementation of the deprecated feature.
*/
_BT_LE_ADV_OPT_ONE_TIME = BIT(1),

/**
* @brief Connectable advertising
*
* Starting connectable advertising preallocates a connection
* object. If this fails, the API returns @c -ENOMEM.
*
* The advertising set stops immediately after it creates a
* connection. This happens automatically in the controller.
*
* @note To continue advertising after a connection is created,
* the application should listen for the @ref bt_conn_cb.connected
* event and start the advertising set again. Note that the
* advertiser cannot be started when all connection objects are
* in use. In that case, defer starting the advertiser until
* @ref bt_conn_cb.recycled. To continue after a disconnection,
* listen for @ref bt_conn_cb.recycled.
*/
BT_LE_ADV_OPT_CONN = BIT(0) | BIT(1),

/**
* @brief Advertise using identity address.
Expand Down Expand Up @@ -625,8 +679,7 @@ enum {
* @brief Support scan response data.
*
* When used together with @ref BT_LE_ADV_OPT_EXT_ADV then this option
* cannot be used together with the @ref BT_LE_ADV_OPT_CONNECTABLE
* option.
* cannot be used together with the @ref BT_LE_ADV_OPT_CONN option.
* When used together with @ref BT_LE_ADV_OPT_EXT_ADV then scan
* response data must be set.
*/
Expand Down Expand Up @@ -914,20 +967,61 @@ struct bt_le_per_adv_param {
BT_LE_ADV_PARAM_INIT(_options, _int_min, _int_max, _peer) \
})

#define BT_LE_ADV_CONN_DIR(_peer) BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE | \
BT_LE_ADV_OPT_ONE_TIME, 0, 0,\
_peer)
#define BT_LE_ADV_CONN_DIR(_peer) BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONN, 0, 0, _peer)

/**
* @deprecated This is a convenience macro for @ref
* BT_LE_ADV_OPT_CONNECTABLE, which is deprecated. Please use
* @ref BT_LE_ADV_CONN_FAST_1 or @ref BT_LE_ADV_CONN_FAST_2
* instead.
*/
#define BT_LE_ADV_CONN \
BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE, BT_GAP_ADV_FAST_INT_MIN_2, \
BT_GAP_ADV_FAST_INT_MAX_2, NULL) \
__DEPRECATED_MACRO

#define BT_LE_ADV_CONN BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE, \
BT_GAP_ADV_FAST_INT_MIN_2, \
BT_GAP_ADV_FAST_INT_MAX_2, NULL)
/** @brief GAP recommended connectable advertising
*
* This is the recommended default for when a person is likely
* to be waiting the device to connect or be discovered.
*
* Use a longer interval to conserve battery at the cost of
* responsiveness. Consider entering a lower power state with
* longer intervals after a timeout.
*
* GAP recommends advertisers use this "when user-initiated".
* The application developer decides what this means. It can by
* any time the user interacts with the device, a press on a
* dedicated Bluetooth wakeup button, or anything in-between.
*
* This is the recommended setting for limited discoverable
* mode.
*
* See Bluetooth Core Specification:
* - 3.C.A "Timers and Constants", T_GAP(adv_fast_interval1)
* - 3.C.9.3.11 "Connection Establishment Timing parameters"
*/
#define BT_LE_ADV_CONN_FAST_1 \
BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONN, BT_GAP_ADV_FAST_INT_MIN_1, BT_GAP_ADV_FAST_INT_MAX_1, \
NULL)

/** This is the recommended default for connectable advertisers.
/** @brief Connectable advertising with
* T_GAP(adv_fast_interval2)
*
* The advertising interval corresponds to what was offered as
* `BT_LE_ADV_CONN` in Zephyr 3.6 and earlier, but unlike
* `BT_LE_ADV_CONN`, the host does not automatically resume the
* advertiser after it results in a connection.
*
* See Bluetooth Core Specification:
* - 3.C.A "Timers and Constants", T_GAP(adv_fast_interval1)
* - 3.C.9.3.11 "Connection Establishment Timing parameters"
*/
#define BT_LE_ADV_CONN_ONE_TIME \
BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE | BT_LE_ADV_OPT_ONE_TIME, \
BT_GAP_ADV_FAST_INT_MIN_2, BT_GAP_ADV_FAST_INT_MAX_2, NULL)
#define BT_LE_ADV_CONN_FAST_2 \
BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONN, BT_GAP_ADV_FAST_INT_MIN_2, BT_GAP_ADV_FAST_INT_MAX_2, \
NULL)

#define BT_LE_ADV_CONN_ONE_TIME BT_LE_ADV_CONN_FAST_2 __DEPRECATED_MACRO

/**
* @deprecated This macro will be removed in the near future, see
Expand All @@ -950,11 +1044,9 @@ struct bt_le_per_adv_param {
BT_GAP_ADV_FAST_INT_MAX_2, NULL) \
__DEPRECATED_MACRO

#define BT_LE_ADV_CONN_DIR_LOW_DUTY(_peer) \
BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE | BT_LE_ADV_OPT_ONE_TIME | \
BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY, \
BT_GAP_ADV_FAST_INT_MIN_2, BT_GAP_ADV_FAST_INT_MAX_2, \
_peer)
#define BT_LE_ADV_CONN_DIR_LOW_DUTY(_peer) \
BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONN | BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY, \
BT_GAP_ADV_FAST_INT_MIN_2, BT_GAP_ADV_FAST_INT_MAX_2, _peer)

/** Non-connectable advertising with private address */
#define BT_LE_ADV_NCONN BT_LE_ADV_PARAM(0, BT_GAP_ADV_FAST_INT_MIN_2, \
Expand All @@ -978,11 +1070,9 @@ struct bt_le_per_adv_param {
NULL)

/** Connectable extended advertising */
#define BT_LE_EXT_ADV_CONN BT_LE_ADV_PARAM(BT_LE_ADV_OPT_EXT_ADV | \
BT_LE_ADV_OPT_CONNECTABLE, \
BT_GAP_ADV_FAST_INT_MIN_2, \
BT_GAP_ADV_FAST_INT_MAX_2, \
NULL)
#define BT_LE_EXT_ADV_CONN \
BT_LE_ADV_PARAM(BT_LE_ADV_OPT_EXT_ADV | BT_LE_ADV_OPT_CONN, BT_GAP_ADV_FAST_INT_MIN_2, \
BT_GAP_ADV_FAST_INT_MAX_2, NULL)

/**
* @deprecated This macro will be removed in the near future, see
Expand Down
2 changes: 1 addition & 1 deletion samples/bluetooth/direct_adv/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ static void bt_ready(void)
adv_param.options |= BT_LE_ADV_OPT_DIR_ADDR_RPA;
err = bt_le_adv_start(&adv_param, NULL, 0, NULL, 0);
} else {
err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), NULL, 0);
err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, ad, ARRAY_SIZE(ad), NULL, 0);
}

if (err) {
Expand Down
2 changes: 1 addition & 1 deletion samples/bluetooth/direction_finding_peripheral/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ static void bt_ready(void)

printk("Bluetooth initialized\n");

err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), NULL, 0);
err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, ad, ARRAY_SIZE(ad), NULL, 0);
if (err) {
printk("Advertising failed to start (err %d)\n", err);
return;
Expand Down
4 changes: 2 additions & 2 deletions samples/bluetooth/eddystone/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ static int eds_slot_restart(struct eds_slot *slot, uint8_t type)
addr = oob.addr;
}

err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), NULL, 0);
err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, ad, ARRAY_SIZE(ad), NULL, 0);
} else {
size_t count = 1;

Expand Down Expand Up @@ -634,7 +634,7 @@ static void bt_ready(int err)
printk("Bluetooth initialized\n");

/* Start advertising */
err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
if (err) {
printk("Advertising failed to start (err %d)\n", err);
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,21 +128,10 @@ static bool rpa_expired_cb(struct bt_le_ext_adv *adv)
static int create_adv(struct bt_le_ext_adv **adv)
{
int err;
struct bt_le_adv_param params;

memset(&params, 0, sizeof(struct bt_le_adv_param));

params.options |= BT_LE_ADV_OPT_CONNECTABLE;
params.options |= BT_LE_ADV_OPT_EXT_ADV;

params.id = BT_ID_DEFAULT;
params.sid = 0;
params.interval_min = BT_GAP_ADV_FAST_INT_MIN_2;
params.interval_max = BT_GAP_ADV_FAST_INT_MAX_2;

adv_cb.rpa_expired = rpa_expired_cb;

err = bt_le_ext_adv_create(&params, &adv_cb, adv);
err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CONN, &adv_cb, adv);
if (err) {
LOG_ERR("Failed to create advertiser (%d)", err);
return -1;
Expand Down
2 changes: 1 addition & 1 deletion samples/bluetooth/hci_pwr_ctrl/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ static K_THREAD_STACK_DEFINE(pwr_thread_stack, 512);
static const int8_t txpower[DEVICE_BEACON_TXPOWER_NUM] = {4, 0, -3, -8,
-15, -18, -23, -30};
static const struct bt_le_adv_param *param =
BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE | BT_LE_ADV_OPT_ONE_TIME, 0x0020, 0x0020, NULL);
BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONN, 0x0020, 0x0020, NULL);

static void read_conn_rssi(uint16_t handle, int8_t *rssi)
{
Expand Down
5 changes: 1 addition & 4 deletions samples/bluetooth/iso_connected_benchmark/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1279,10 +1279,7 @@ static int run_peripheral(void)
}

LOG_INF("Starting advertising");
err = bt_le_adv_start(
BT_LE_ADV_PARAM(BT_LE_ADV_OPT_ONE_TIME | BT_LE_ADV_OPT_CONNECTABLE,
BT_GAP_ADV_FAST_INT_MIN_2, BT_GAP_ADV_FAST_INT_MAX_2, NULL),
NULL, 0, sd, ARRAY_SIZE(sd));
err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, NULL, 0, sd, ARRAY_SIZE(sd));
if (err != 0) {
LOG_ERR("Advertising failed to start: %d", err);
return err;
Expand Down
2 changes: 1 addition & 1 deletion samples/bluetooth/iso_peripheral/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ int main(void)
return 0;
}

err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
if (err) {
printk("Advertising failed to start (err %d)\n", err);
return 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ void run_peripheral_sample(uint8_t *notify_data, size_t notify_data_size, uint16
struct bt_gatt_attr *notify_crch =
bt_gatt_find_by_uuid(mtu_test.attrs, 0xffff, &notify_characteristic_uuid.uuid);

bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, adv_ad_data, ARRAY_SIZE(adv_ad_data), NULL, 0);
bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, adv_ad_data, ARRAY_SIZE(adv_ad_data), NULL, 0);

bool infinite = seconds == 0;

Expand Down
5 changes: 1 addition & 4 deletions samples/bluetooth/periodic_sync_rsp/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,10 +231,7 @@ int main(void)
}

do {
err = bt_le_adv_start(
BT_LE_ADV_PARAM(BT_LE_ADV_OPT_ONE_TIME | BT_LE_ADV_OPT_CONNECTABLE,
BT_GAP_ADV_FAST_INT_MIN_2, BT_GAP_ADV_FAST_INT_MAX_2, NULL),
ad, ARRAY_SIZE(ad), NULL, 0);
err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, sd, ARRAY_SIZE(sd), NULL, 0);
if (err && err != -EALREADY) {
printk("Advertising failed to start (err %d)\n", err);

Expand Down
2 changes: 1 addition & 1 deletion samples/bluetooth/peripheral/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ static void bt_ready(void)
settings_load();
}

err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
if (err) {
printk("Advertising failed to start (err %d)\n", err);
return;
Expand Down
2 changes: 1 addition & 1 deletion samples/bluetooth/peripheral_accept_list/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ static void bt_ready(void)
bond_count = 0;
bt_foreach_bond(BT_ID_DEFAULT, add_bonded_addr_to_filter_list, NULL);

adv_param = *BT_LE_ADV_CONN_ONE_TIME;
adv_param = *BT_LE_ADV_CONN_FAST_1;

/* If we have got at least one bond, activate the filter */
if (bond_count) {
Expand Down
Loading

0 comments on commit 1fa9f59

Please sign in to comment.