diff --git a/config/zephyr/Kconfig b/config/zephyr/Kconfig index ad36a663b5fd1f..bdfa709592adff 100644 --- a/config/zephyr/Kconfig +++ b/config/zephyr/Kconfig @@ -533,4 +533,22 @@ config CHIP_OTA_IMAGE_EXTRA_ARGS endif +config CHIP_BLE_EXT_ADVERTISING + bool "Bluetooth LE extended advertising" + help + Enable Bluetooth LE extended advertising, which allows the device to advertise + Matter service over Bluetooth LE for a period of time longer than 15 minutes. + If this config is true, + CHIP_DEVICE_CONFIG_DISCOVERY_TIMEOUT_SECS define can be set up to 172800 seconds (48h). + +config CHIP_BLE_ADVERTISING_DURATION + int "Bluetooth LE advertising duration in minutes" + range 15 2880 if CHIP_BLE_EXT_ADVERTISING + range 0 15 + default 15 + help + Specify how long the device will advertise Matter service over Bluetooth LE in minutes. + If CHIP_BLE_EXT_ADVERTISING is set to false, the maximum duration time is 15 minutes, + else the maximum duration time can be extended to 2880 minutes (48h). + endif diff --git a/src/app/server/CommissioningWindowManager.cpp b/src/app/server/CommissioningWindowManager.cpp index a205d093c27d00..f11261ad9c444d 100644 --- a/src/app/server/CommissioningWindowManager.cpp +++ b/src/app/server/CommissioningWindowManager.cpp @@ -228,7 +228,7 @@ void CommissioningWindowManager::OnSessionEstablished(const SessionHandle & sess } } -CHIP_ERROR CommissioningWindowManager::OpenCommissioningWindow(Seconds16 commissioningTimeout) +CHIP_ERROR CommissioningWindowManager::OpenCommissioningWindow(Seconds32 commissioningTimeout) { VerifyOrReturnError(commissioningTimeout <= MaxCommissioningTimeout() && commissioningTimeout >= MinCommissioningTimeout(), CHIP_ERROR_INVALID_ARGUMENT); @@ -288,7 +288,7 @@ CHIP_ERROR CommissioningWindowManager::AdvertiseAndListenForPASE() return CHIP_NO_ERROR; } -CHIP_ERROR CommissioningWindowManager::OpenBasicCommissioningWindow(Seconds16 commissioningTimeout, +CHIP_ERROR CommissioningWindowManager::OpenBasicCommissioningWindow(Seconds32 commissioningTimeout, CommissioningWindowAdvertisement advertisementMode) { RestoreDiscriminator(); @@ -316,7 +316,7 @@ CHIP_ERROR CommissioningWindowManager::OpenBasicCommissioningWindow(Seconds16 co CHIP_ERROR CommissioningWindowManager::OpenBasicCommissioningWindowForAdministratorCommissioningCluster( - System::Clock::Seconds16 commissioningTimeout, FabricIndex fabricIndex, VendorId vendorId) + System::Clock::Seconds32 commissioningTimeout, FabricIndex fabricIndex, VendorId vendorId) { ReturnErrorOnFailure(OpenBasicCommissioningWindow(commissioningTimeout, CommissioningWindowAdvertisement::kDnssdOnly)); @@ -326,7 +326,7 @@ CommissioningWindowManager::OpenBasicCommissioningWindowForAdministratorCommissi return CHIP_NO_ERROR; } -CHIP_ERROR CommissioningWindowManager::OpenEnhancedCommissioningWindow(Seconds16 commissioningTimeout, uint16_t discriminator, +CHIP_ERROR CommissioningWindowManager::OpenEnhancedCommissioningWindow(Seconds32 commissioningTimeout, uint16_t discriminator, Spake2pVerifier & verifier, uint32_t iterations, ByteSpan salt, FabricIndex fabricIndex, VendorId vendorId) { diff --git a/src/app/server/CommissioningWindowManager.h b/src/app/server/CommissioningWindowManager.h index 6b4e1efded76f4..51efb44b19376e 100644 --- a/src/app/server/CommissioningWindowManager.h +++ b/src/app/server/CommissioningWindowManager.h @@ -58,21 +58,21 @@ class CommissioningWindowManager : public Messaging::UnsolicitedMessageHandler, return CHIP_NO_ERROR; } - static constexpr System::Clock::Seconds16 MaxCommissioningTimeout() + static constexpr System::Clock::Seconds32 MaxCommissioningTimeout() { #if CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING // Specification section 2.3.1 - Extended Announcement Duration up to 48h - return System::Clock::Seconds16(60 * 60 * 48); + return System::Clock::Seconds32(60 * 60 * 48); #else // Specification section 5.4.2.3. Announcement Duration says 15 minutes. - return System::Clock::Seconds16(15 * 60); + return System::Clock::Seconds32(15 * 60); #endif } - System::Clock::Seconds16 MinCommissioningTimeout() const + System::Clock::Seconds32 MinCommissioningTimeout() const { // Specification section 5.4.2.3. Announcement Duration says 3 minutes. - return mMinCommissioningTimeoutOverride.ValueOr(System::Clock::Seconds16(3 * 60)); + return mMinCommissioningTimeoutOverride.ValueOr(System::Clock::Seconds32(3 * 60)); } void SetAppDelegate(AppDelegate * delegate) { mAppDelegate = delegate; } @@ -82,7 +82,7 @@ class CommissioningWindowManager : public Messaging::UnsolicitedMessageHandler, */ CHIP_ERROR OpenBasicCommissioningWindow( - System::Clock::Seconds16 commissioningTimeout = System::Clock::Seconds16(CHIP_DEVICE_CONFIG_DISCOVERY_TIMEOUT_SECS), + System::Clock::Seconds32 commissioningTimeout = System::Clock::Seconds32(CHIP_DEVICE_CONFIG_DISCOVERY_TIMEOUT_SECS), CommissioningWindowAdvertisement advertisementMode = chip::CommissioningWindowAdvertisement::kAllSupported); /** @@ -90,10 +90,10 @@ class CommissioningWindowManager : public Messaging::UnsolicitedMessageHandler, * the Administrator Commmissioning cluster implementation. */ CHIP_ERROR - OpenBasicCommissioningWindowForAdministratorCommissioningCluster(System::Clock::Seconds16 commissioningTimeout, + OpenBasicCommissioningWindowForAdministratorCommissioningCluster(System::Clock::Seconds32 commissioningTimeout, FabricIndex fabricIndex, VendorId vendorId); - CHIP_ERROR OpenEnhancedCommissioningWindow(System::Clock::Seconds16 commissioningTimeout, uint16_t discriminator, + CHIP_ERROR OpenEnhancedCommissioningWindow(System::Clock::Seconds32 commissioningTimeout, uint16_t discriminator, Crypto::Spake2pVerifier & verifier, uint32_t iterations, chip::ByteSpan salt, FabricIndex fabricIndex, VendorId vendorId); @@ -128,7 +128,7 @@ class CommissioningWindowManager : public Messaging::UnsolicitedMessageHandler, // For tests only, allow overriding the spec-defined minimum value of the // commissioning window timeout. - void OverrideMinCommissioningTimeout(System::Clock::Seconds16 timeout) { mMinCommissioningTimeoutOverride.SetValue(timeout); } + void OverrideMinCommissioningTimeout(System::Clock::Seconds32 timeout) { mMinCommissioningTimeoutOverride.SetValue(timeout); } private: //////////// SessionDelegate Implementation /////////////// @@ -146,7 +146,7 @@ class CommissioningWindowManager : public Messaging::UnsolicitedMessageHandler, // Start a timer that will call HandleCommissioningWindowTimeout, and then // start advertising and listen for PASE. - CHIP_ERROR OpenCommissioningWindow(System::Clock::Seconds16 commissioningTimeout); + CHIP_ERROR OpenCommissioningWindow(System::Clock::Seconds32 commissioningTimeout); // Start advertising and listening for PASE connections. Should only be // called when a commissioning window timeout timer is running. @@ -219,7 +219,7 @@ class CommissioningWindowManager : public Messaging::UnsolicitedMessageHandler, // For tests only, so that we can test the commissioning window timeout // without having to wait 3 minutes. - Optional mMinCommissioningTimeoutOverride; + Optional mMinCommissioningTimeoutOverride; // The PASE session we are using, so we can handle CloseSession properly. SessionHolderWithDelegate mPASESession; diff --git a/src/app/tests/TestCommissionManager.cpp b/src/app/tests/TestCommissionManager.cpp index c314421d4e3a9a..0076fd6a55718f 100644 --- a/src/app/tests/TestCommissionManager.cpp +++ b/src/app/tests/TestCommissionManager.cpp @@ -239,7 +239,7 @@ void CheckCommissioningWindowManagerWindowTimeoutTask(intptr_t context) NL_TEST_ASSERT(suite, !sAdminVendorIdDirty); CommissioningWindowManager & commissionMgr = Server::GetInstance().GetCommissioningWindowManager(); - constexpr auto kTimeoutSeconds = chip::System::Clock::Seconds16(1); + constexpr auto kTimeoutSeconds = chip::System::Clock::Seconds32(1); constexpr uint16_t kTimeoutMs = 1000; constexpr unsigned kSleepPadding = 100; commissionMgr.OverrideMinCommissioningTimeout(kTimeoutSeconds); diff --git a/src/include/platform/ConnectivityManager.h b/src/include/platform/ConnectivityManager.h index 30002484c33a3d..bff2c02d2a7295 100644 --- a/src/include/platform/ConnectivityManager.h +++ b/src/include/platform/ConnectivityManager.h @@ -139,8 +139,9 @@ class ConnectivityManager enum BLEAdvertisingMode { - kFastAdvertising = 0, - kSlowAdvertising = 1, + kFastAdvertising = 0, + kSlowAdvertising = 1, + kExtendedAdvertising = 2, }; enum class SEDIntervalMode diff --git a/src/platform/Zephyr/BLEManagerImpl.cpp b/src/platform/Zephyr/BLEManagerImpl.cpp index 54cf69dc5e50fc..d4e83332452a06 100644 --- a/src/platform/Zephyr/BLEManagerImpl.cpp +++ b/src/platform/Zephyr/BLEManagerImpl.cpp @@ -252,18 +252,39 @@ inline CHIP_ERROR BLEManagerImpl::PrepareAdvertisingRequest() Encoding::LittleEndian::Put16(serviceData.uuid, UUID16_CHIPoBLEService.val); ReturnErrorOnFailure(ConfigurationMgr().GetBLEDeviceIdentificationInfo(serviceData.deviceIdInfo)); +#if CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING + if (mFlags.Has(Flags::kExtendedAdvertisingEnabled)) + { + serviceData.deviceIdInfo.SetVendorId(DEVICE_HANDLE_NULL); + serviceData.deviceIdInfo.SetProductId(DEVICE_HANDLE_NULL); + serviceData.deviceIdInfo.SetExtendedAnnouncementFlag(true); + } +#endif + advertisingData[0] = BT_DATA(BT_DATA_FLAGS, &kAdvertisingFlags, sizeof(kAdvertisingFlags)); advertisingData[1] = BT_DATA(BT_DATA_SVC_DATA16, &serviceData, sizeof(serviceData)); scanResponseData[0] = BT_DATA(BT_DATA_NAME_COMPLETE, name, nameSize); - mAdvertisingRequest.priority = CHIP_DEVICE_BLE_ADVERTISING_PRIORITY; - mAdvertisingRequest.options = kAdvertisingOptions; - mAdvertisingRequest.minInterval = mFlags.Has(Flags::kFastAdvertisingEnabled) - ? CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MIN - : CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MIN; - mAdvertisingRequest.maxInterval = mFlags.Has(Flags::kFastAdvertisingEnabled) - ? CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MAX - : CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MAX; + mAdvertisingRequest.priority = CHIP_DEVICE_BLE_ADVERTISING_PRIORITY; + mAdvertisingRequest.options = kAdvertisingOptions; + + if (mFlags.Has(Flags::kFastAdvertisingEnabled)) + { + mAdvertisingRequest.minInterval = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MIN; + mAdvertisingRequest.maxInterval = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MAX; + } +#if CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING + else if (mFlags.Has(Flags::kExtendedAdvertisingEnabled)) + { + mAdvertisingRequest.minInterval = CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_MIN; + mAdvertisingRequest.maxInterval = CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_MAX; + } +#endif + else + { + mAdvertisingRequest.minInterval = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MIN; + mAdvertisingRequest.maxInterval = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MAX; + } mAdvertisingRequest.advertisingData = Span(advertisingData); mAdvertisingRequest.scanResponseData = nameSize ? Span(scanResponseData) : Span{}; @@ -322,10 +343,17 @@ CHIP_ERROR BLEManagerImpl::StartAdvertising() if (mFlags.Has(Flags::kFastAdvertisingEnabled)) { - // Start timer to change advertising interval. + // Start timer to change advertising interval from fast to slow. DeviceLayer::SystemLayer().StartTimer( System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_BLE_ADVERTISING_INTERVAL_CHANGE_TIME), - HandleBLEAdvertisementIntervalChange, this); + HandleSlowBLEAdvertisementInterval, this); + +#if CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING + // Start timer to schedule start of the extended advertising + DeviceLayer::SystemLayer().StartTimer( + System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_CHANGE_TIME_MS), + HandleExtendedBLEAdvertisementInterval, this); +#endif } } @@ -342,6 +370,10 @@ CHIP_ERROR BLEManagerImpl::StopAdvertising() mFlags.Clear(Flags::kAdvertising); mFlags.Set(Flags::kFastAdvertisingEnabled, true); +#if CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING + mFlags.Clear(Flags::kExtendedAdvertisingEnabled); +#endif + ChipLogProgress(DeviceLayer, "CHIPoBLE advertising stopped"); // Post a CHIPoBLEAdvertisingChange(Stopped) event. @@ -353,7 +385,8 @@ CHIP_ERROR BLEManagerImpl::StopAdvertising() } // Cancel timer event changing CHIPoBLE advertisement interval - DeviceLayer::SystemLayer().CancelTimer(HandleBLEAdvertisementIntervalChange, this); + DeviceLayer::SystemLayer().CancelTimer(HandleSlowBLEAdvertisementInterval, this); + DeviceLayer::SystemLayer().CancelTimer(HandleExtendedBLEAdvertisementInterval, this); } return CHIP_NO_ERROR; @@ -366,6 +399,9 @@ CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val) ChipLogDetail(DeviceLayer, "CHIPoBLE advertising set to %s", val ? "on" : "off"); mFlags.Set(Flags::kAdvertisingEnabled, val); + // Ensure that each enabling/disabling of the standard advertising clears + // the extended mode flag. + mFlags.Set(Flags::kExtendedAdvertisingEnabled, false); PlatformMgr().ScheduleWork(DriveBLEState, 0); } @@ -378,8 +414,14 @@ CHIP_ERROR BLEManagerImpl::_SetAdvertisingMode(BLEAdvertisingMode mode) { case BLEAdvertisingMode::kFastAdvertising: mFlags.Set(Flags::kFastAdvertisingEnabled, true); + mFlags.Set(Flags::kExtendedAdvertisingEnabled, false); break; case BLEAdvertisingMode::kSlowAdvertising: + mFlags.Set(Flags::kFastAdvertisingEnabled, false); + mFlags.Set(Flags::kExtendedAdvertisingEnabled, false); + break; + case BLEAdvertisingMode::kExtendedAdvertising: + mFlags.Set(Flags::kExtendedAdvertisingEnabled, true); mFlags.Set(Flags::kFastAdvertisingEnabled, false); break; default: @@ -570,12 +612,18 @@ CHIP_ERROR BLEManagerImpl::PrepareC3CharData() } #endif -void BLEManagerImpl::HandleBLEAdvertisementIntervalChange(System::Layer * layer, void * param) +void BLEManagerImpl::HandleSlowBLEAdvertisementInterval(System::Layer * layer, void * param) { BLEMgr().SetAdvertisingMode(BLEAdvertisingMode::kSlowAdvertising); ChipLogProgress(DeviceLayer, "CHIPoBLE advertising mode changed to slow"); } +void BLEManagerImpl::HandleExtendedBLEAdvertisementInterval(System::Layer * layer, void * param) +{ + BLEMgr().SetAdvertisingMode(BLEAdvertisingMode::kExtendedAdvertising); + ChipLogProgress(DeviceLayer, "CHIPoBLE advertising mode changed to extended"); +} + void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) { CHIP_ERROR err = CHIP_NO_ERROR; diff --git a/src/platform/Zephyr/BLEManagerImpl.h b/src/platform/Zephyr/BLEManagerImpl.h index 7db469f4a5df93..4fb3352a01ee2b 100644 --- a/src/platform/Zephyr/BLEManagerImpl.h +++ b/src/platform/Zephyr/BLEManagerImpl.h @@ -91,6 +91,7 @@ class BLEManagerImpl final : public BLEManager, private BleLayer, private BlePla kAdvertisingRefreshNeeded = 0x0010, /**< The advertising state/configuration has changed, but the SoftDevice has yet to be updated. */ kChipoBleGattServiceRegister = 0x0020, /**< The system has currently CHIPoBLE GATT service registered. */ + kExtendedAdvertisingEnabled = 0x0040, /**< The application has enabled extended advertising. */ }; struct ServiceData; @@ -129,7 +130,8 @@ class BLEManagerImpl final : public BLEManager, private BleLayer, private BlePla static void HandleTXIndicated(bt_conn * conn, bt_gatt_indicate_params * attr, uint8_t err); static void HandleConnect(bt_conn * conn, uint8_t err); static void HandleDisconnect(bt_conn * conn, uint8_t reason); - static void HandleBLEAdvertisementIntervalChange(System::Layer * layer, void * param); + static void HandleSlowBLEAdvertisementInterval(System::Layer * layer, void * param); + static void HandleExtendedBLEAdvertisementInterval(System::Layer * layer, void * param); // ===== Members for internal use by the following friends. diff --git a/src/platform/Zephyr/CHIPDevicePlatformConfig.h b/src/platform/Zephyr/CHIPDevicePlatformConfig.h index 3296f3aa8f1c55..e7622f60ddf9fc 100644 --- a/src/platform/Zephyr/CHIPDevicePlatformConfig.h +++ b/src/platform/Zephyr/CHIPDevicePlatformConfig.h @@ -130,3 +130,9 @@ #ifdef CONFIG_CHIP_EXTENDED_DISCOVERY #define CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY 1 #endif // CONFIG_CHIP_EXTENDED_DISCOVERY + +#ifdef CONFIG_CHIP_BLE_EXT_ADVERTISING +#define CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING 1 +#endif // CONFIG_CHIP_BLE_EXT_ADVERTISING + +#define CHIP_DEVICE_CONFIG_DISCOVERY_TIMEOUT_SECS (CONFIG_CHIP_BLE_ADVERTISING_DURATION * 60) diff --git a/src/platform/nrfconnect/CHIPDevicePlatformConfig.h b/src/platform/nrfconnect/CHIPDevicePlatformConfig.h index 7461d3650d86a6..f9e445f35fb3d4 100644 --- a/src/platform/nrfconnect/CHIPDevicePlatformConfig.h +++ b/src/platform/nrfconnect/CHIPDevicePlatformConfig.h @@ -212,6 +212,12 @@ #define CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY 1 #endif // CONFIG_CHIP_EXTENDED_DISCOVERY +#ifdef CONFIG_CHIP_BLE_EXT_ADVERTISING +#define CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING 1 +#endif // CONFIG_CHIP_BLE_EXT_ADVERTISING + +#define CHIP_DEVICE_CONFIG_DISCOVERY_TIMEOUT_SECS (CONFIG_CHIP_BLE_ADVERTISING_DURATION * 60) + #ifndef CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID_LENGTH #ifdef CONFIG_CHIP_FACTORY_DATA // UID will be copied from the externally programmed factory data, so we don't know the actual length and we need to assume some max