From 93c7b09ee01acf2b462165785f46dba4f9f2f293 Mon Sep 17 00:00:00 2001 From: Arkadiusz Balys Date: Wed, 26 Feb 2025 16:18:55 +0100 Subject: [PATCH] [nrf toup][Zephyr] Retry starting BLE advertising after releasing connection. In Zephyr 4.0, the BT_LE_ADV_OPT_CONNECTABLE and BT_LE_ADV_OPT_CONNECTABLE advertising options have been deprecated and we need to use BT_LE_ADV_OPT_CONN instead. Due to the fact that the automatic advertiser resumption is deprecated, we must ensure that the BLE advertising arbiter restarts advertising in a different way if the service could not be started, for example, due to an existing BLE connection, or connection has been closed. We can use the recycled callback of the BT_CONN_CB to check if there is pending request in the list and if so, try to restart advertising. Signed-off-by: Arkadiusz Balys --- src/platform/Zephyr/BLEAdvertisingArbiter.cpp | 34 +++++++++++++++++-- src/platform/Zephyr/BLEManagerImpl.cpp | 9 ++++- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/platform/Zephyr/BLEAdvertisingArbiter.cpp b/src/platform/Zephyr/BLEAdvertisingArbiter.cpp index 4356ba9aa1..7911bbbd6a 100644 --- a/src/platform/Zephyr/BLEAdvertisingArbiter.cpp +++ b/src/platform/Zephyr/BLEAdvertisingArbiter.cpp @@ -19,7 +19,9 @@ #include #include +#include #include +#include namespace chip { namespace DeviceLayer { @@ -29,8 +31,9 @@ namespace { // List of advertising requests ordered by priority sys_slist_t sRequests; -bool sIsInitialized = false; -uint8_t sBtId = 0; +bool sIsInitialized = false; +bool sWasDisconnection = false; +uint8_t sBtId = 0; // Cast an intrusive list node to the containing request object const BLEAdvertisingArbiter::Request & ToRequest(const sys_snode_t * node) @@ -64,6 +67,11 @@ CHIP_ERROR RestartAdvertising() const int result = bt_le_adv_start(¶ms, top.advertisingData.data(), top.advertisingData.size(), top.scanResponseData.data(), top.scanResponseData.size()); + if (result == -ENOMEM) + { + ChipLogProgress(DeviceLayer, "Advertising start failed, will retry once connection is released"); + } + if (top.onStarted != nullptr) { top.onStarted(result); @@ -72,6 +80,28 @@ CHIP_ERROR RestartAdvertising() return System::MapErrorZephyr(result); } +BT_CONN_CB_DEFINE(conn_callbacks) = { + .disconnected = [](struct bt_conn * conn, uint8_t reason) { sWasDisconnection = true; }, + .recycled = + []() { + // In this callback the connection object was returned to the pool and we can try to re-start connectable + // advertising, but only if the disconnection was detected. + if (sWasDisconnection) + { + SystemLayer().ScheduleLambda([] { + if (!sys_slist_is_empty(&sRequests)) + { + // Starting from Zephyr 4.0 Automatic advertiser resumption is deprecated, + // so the BLE Advertising Arbiter has to take over the responsibility of restarting the advertiser. + // Restart advertising in this callback if there are pending requests after the connection is released. + RestartAdvertising(); + } + }); + // Reset the disconnection flag to avoid restarting advertising multiple times + sWasDisconnection = false; + } + }, +}; } // namespace CHIP_ERROR Init(uint8_t btId) diff --git a/src/platform/Zephyr/BLEManagerImpl.cpp b/src/platform/Zephyr/BLEManagerImpl.cpp index 49751da624..ec6609a382 100644 --- a/src/platform/Zephyr/BLEManagerImpl.cpp +++ b/src/platform/Zephyr/BLEManagerImpl.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #ifdef CONFIG_BT_BONDABLE #include @@ -61,8 +62,14 @@ namespace Internal { namespace { +#if KERNEL_VERSION_MAJOR >= 4 +// In Zephyr 4.0 BT_LE_ADV_OPT_CONNECTABLE and BT_LE_ADV_OPT_ONE_TIME have been deprecated +// and replaced with BT_LE_ADV_OPT_CONN. +constexpr uint32_t kAdvertisingOptions = BT_LE_ADV_OPT_CONN; +#else constexpr uint32_t kAdvertisingOptions = BT_LE_ADV_OPT_CONNECTABLE | BT_LE_ADV_OPT_ONE_TIME; -constexpr uint8_t kAdvertisingFlags = BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR; +#endif +constexpr uint8_t kAdvertisingFlags = BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR; const bt_uuid_128 UUID128_CHIPoBLEChar_RX = BT_UUID_INIT_128(0x11, 0x9D, 0x9F, 0x42, 0x9C, 0x4F, 0x9F, 0x95, 0x59, 0x45, 0x3D, 0x26, 0xF5, 0x2E, 0xEE, 0x18);