diff --git a/src/platform/Zephyr/BLEAdvertisingArbiter.cpp b/src/platform/Zephyr/BLEAdvertisingArbiter.cpp index 29f55168f1..5dab391c5d 100644 --- a/src/platform/Zephyr/BLEAdvertisingArbiter.cpp +++ b/src/platform/Zephyr/BLEAdvertisingArbiter.cpp @@ -29,6 +29,9 @@ namespace { // List of advertising requests ordered by priority sys_slist_t sRequests; +bool sIsInitialized; +uint8_t sBtId; + // Cast an intrusive list node to the containing request object const BLEAdvertisingArbiter::Request & ToRequest(const sys_snode_t * node) { @@ -55,8 +58,9 @@ CHIP_ERROR RestartAdvertising() ReturnErrorOnFailure(System::MapErrorZephyr(bt_le_adv_stop())); ReturnErrorCodeIf(sys_slist_is_empty(&sRequests), CHIP_NO_ERROR); - const Request & top = ToRequest(sys_slist_peek_head(&sRequests)); - const bt_le_adv_param params = BT_LE_ADV_PARAM_INIT(top.options, top.minInterval, top.maxInterval, nullptr); + const Request & top = ToRequest(sys_slist_peek_head(&sRequests)); + bt_le_adv_param params = BT_LE_ADV_PARAM_INIT(top.options, top.minInterval, top.maxInterval, nullptr); + params.id = sBtId; const int result = bt_le_adv_start(¶ms, top.advertisingData.data(), top.advertisingData.size(), top.scanResponseData.data(), top.scanResponseData.size()); @@ -70,8 +74,26 @@ CHIP_ERROR RestartAdvertising() } // namespace +CHIP_ERROR Init(uint8_t btId) +{ + if (sIsInitialized) + { + return CHIP_ERROR_INCORRECT_STATE; + } + + sBtId = btId; + sIsInitialized = true; + + return CHIP_NO_ERROR; +} + CHIP_ERROR InsertRequest(Request & request) { + if (!sIsInitialized) + { + return CHIP_ERROR_INCORRECT_STATE; + } + CancelRequest(request); sys_snode_t * prev = nullptr; @@ -109,6 +131,11 @@ CHIP_ERROR InsertRequest(Request & request) void CancelRequest(Request & request) { + if (!sIsInitialized) + { + return; + } + const bool isTopPriority = (sys_slist_peek_head(&sRequests) == &request); VerifyOrReturn(sys_slist_find_and_remove(&sRequests, &request)); diff --git a/src/platform/Zephyr/BLEAdvertisingArbiter.h b/src/platform/Zephyr/BLEAdvertisingArbiter.h index 6176c6cedb..be2620b2ab 100644 --- a/src/platform/Zephyr/BLEAdvertisingArbiter.h +++ b/src/platform/Zephyr/BLEAdvertisingArbiter.h @@ -61,6 +61,17 @@ struct Request : public sys_snode_t OnAdvertisingStopped onStopped; ///< (Optional) Callback invoked when the request stops being top-priority. }; +/** + * @brief Initialize BLE advertising arbiter + * + * @note This method must be called before trying to insert or cancel any requests. + * + * @param btId Local Bluetooth LE identifier to be used for the advertising parameters. + * @return error If the module is already initialized. + * @return success Otherwise. + */ +CHIP_ERROR Init(uint8_t btId); + /** * @brief Request BLE advertising * @@ -74,6 +85,9 @@ struct Request : public sys_snode_t * @note This method does not take ownership of the request object so the object * must not get destroyed before it is cancelled. * + * @note The arbiter module has to be initialized using Init() method before + * invoking this method. + * * @param request Reference to advertising request that contains priority and * other advertising parameters. * @return error If the request is top-priority and failed to restart the @@ -94,6 +108,9 @@ CHIP_ERROR InsertRequest(Request & request); * An attempt to cancel a request that has not been registered at the * advertising arbiter is a no-op. That is, it returns immediately. * + * @note The arbiter module has to be initialized using Init() method before + * invoking this method. + * * @param request Reference to advertising request that contains priority and * other advertising parameters. */ diff --git a/src/platform/Zephyr/BLEManagerImpl.cpp b/src/platform/Zephyr/BLEManagerImpl.cpp index 518919d8e8..cd81119cd9 100644 --- a/src/platform/Zephyr/BLEManagerImpl.cpp +++ b/src/platform/Zephyr/BLEManagerImpl.cpp @@ -43,6 +43,8 @@ #include #include +#include + #include using namespace ::chip; @@ -106,7 +108,13 @@ bt_gatt_service sChipoBleService = BT_GATT_SERVICE(sChipoBleAttributes); // This value should be adjusted accordingly if the service declaration changes. constexpr int kCHIPoBLE_CCC_AttributeIndex = 3; -CHIP_ERROR InitRandomStaticAddress() +#ifdef CONFIG_BT_BONDABLE +constexpr uint8_t kMatterBleIdentity = 1; +#else +constexpr uint8_t kMatterBleIdentity = 0; +#endif // CONFIG_BT_BONDABLE + +int InitRandomStaticAddress(bool idPresent, int & id) { // Generate a random static address for the default identity. // This must be done before bt_enable() as after that updating the default identity is not possible. @@ -121,20 +129,29 @@ CHIP_ERROR InitRandomStaticAddress() if (error) { ChipLogError(DeviceLayer, "Failed to create BLE address: %d", error); - return System::MapErrorZephyr(error); + return error; } - error = bt_id_create(&addr, nullptr); + if (!idPresent) + { + id = bt_id_create(&addr, nullptr); + } +#if CONFIG_BT_ID_MAX == 2 + else + { + id = bt_id_reset(1, &addr, nullptr); + } +#endif // CONFIG_BT_BONDABLE - if (error < 0) + if (id < 0) { ChipLogError(DeviceLayer, "Failed to create BLE identity: %d", error); - return System::MapErrorZephyr(error); + return id; } ChipLogProgress(DeviceLayer, "BLE address: %02X:%02X:%02X:%02X:%02X:%02X", addr.a.val[5], addr.a.val[4], addr.a.val[3], addr.a.val[2], addr.a.val[1], addr.a.val[0]); - return CHIP_NO_ERROR; + return 0; } } // unnamed namespace @@ -143,6 +160,9 @@ BLEManagerImpl BLEManagerImpl::sInstance; CHIP_ERROR BLEManagerImpl::_Init() { + int err = 0; + int id = 0; + mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled; mFlags.ClearAll().Set(Flags::kAdvertisingEnabled, CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART); mFlags.Set(Flags::kFastAdvertisingEnabled, true); @@ -151,10 +171,31 @@ CHIP_ERROR BLEManagerImpl::_Init() memset(mSubscribedConns, 0, sizeof(mSubscribedConns)); - ReturnErrorOnFailure(InitRandomStaticAddress()); - int err = bt_enable(NULL); +#ifdef CONFIG_BT_BONDABLE + bt_addr_le_t idsAddr[CONFIG_BT_ID_MAX]; + size_t idsCount = CONFIG_BT_ID_MAX; + + err = bt_enable(nullptr); + VerifyOrReturnError(err == 0, MapErrorZephyr(err)); + settings_load(); + + bt_id_get(idsAddr, &idsCount); + + err = InitRandomStaticAddress(idsCount > 1, id); + + VerifyOrReturnError(err == 0 && id == kMatterBleIdentity, MapErrorZephyr(err)); + +#else + err = InitRandomStaticAddress(false, id); + VerifyOrReturnError(err == 0 && id == kMatterBleIdentity, MapErrorZephyr(err)); + err = bt_enable(nullptr); + VerifyOrReturnError(err == 0, MapErrorZephyr(err)); +#endif // CONFIG_BT_BONDABLE + + BLEAdvertisingArbiter::Init(static_cast(id)); + memset(&mConnCallbacks, 0, sizeof(mConnCallbacks)); mConnCallbacks.connected = HandleConnect; mConnCallbacks.disconnected = HandleDisconnect;