diff --git a/examples/platform/silabs/SiWx917/BUILD.gn b/examples/platform/silabs/SiWx917/BUILD.gn index 4ef00d2ede..2d6d3574ea 100644 --- a/examples/platform/silabs/SiWx917/BUILD.gn +++ b/examples/platform/silabs/SiWx917/BUILD.gn @@ -174,11 +174,6 @@ source_set("siwx917-common") { } } - # Sl-Only: Support for the Wi-Fi Sleep Manager - if (chip_enable_icd_server) { - public_deps += [ "${silabs_common_plat_dir}/wifi/icd:sleep-manager" ] - } - # DIC if (enable_dic) { public_deps += diff --git a/examples/platform/silabs/efr32/BUILD.gn b/examples/platform/silabs/efr32/BUILD.gn index 293c60dbc7..e0e7b45070 100644 --- a/examples/platform/silabs/efr32/BUILD.gn +++ b/examples/platform/silabs/efr32/BUILD.gn @@ -230,10 +230,6 @@ source_set("efr32-common") { ] } - if (chip_enable_icd_server && use_SiWx917) { - public_deps += [ "${silabs_common_plat_dir}/wifi/icd:sleep-manager" ] - } - if (app_data_model != "") { public_deps += [ app_data_model ] } diff --git a/examples/platform/silabs/wifi/icd/SleepManager.cpp b/examples/platform/silabs/wifi/icd/SleepManager.cpp deleted file mode 100644 index 58ed20f44c..0000000000 --- a/examples/platform/silabs/wifi/icd/SleepManager.cpp +++ /dev/null @@ -1,134 +0,0 @@ -#include "SleepManager.h" -#include -#include - -using namespace chip::app; - -namespace chip { -namespace DeviceLayer { -namespace Silabs { - -// Initialize the static instance -SleepManager SleepManager::mInstance; - -CHIP_ERROR SleepManager::Init() -{ - VerifyOrReturnError(mIMEngine != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnError(mFabricTable != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - - mIMEngine->RegisterReadHandlerAppCallback(this); - mFabricTable->AddFabricDelegate(this); - - PlatformMgr().AddEventHandler(OnPlatformEvent, reinterpret_cast(this)); - - return CHIP_NO_ERROR; -} - -void SleepManager::OnSubscriptionEstablished(ReadHandler & aReadHandler) -{ - // Implement logic for when a subscription is established -} - -void SleepManager::OnSubscriptionTerminated(ReadHandler & aReadHandler) -{ - // Implement logic for when a subscription is terminated -} - -void SleepManager::OnFabricRemoved(const chip::FabricTable & fabricTable, chip::FabricIndex fabricIndex) -{ - // Implement logic for when a fabric is removed -} - -void SleepManager::OnFabricCommitted(const chip::FabricTable & fabricTable, chip::FabricIndex fabricIndex) -{ - // Implement logic for when a fabric is committed -} - -void SleepManager::OnEnterActiveMode() -{ - // Execution logic for entering active mode -} - -void SleepManager::OnEnterIdleMode() -{ - // Execution logic for entering idle mode -} - -void SleepManager::HandleCommissioningComplete() -{ - if (wfx_power_save(RSI_SLEEP_MODE_2, ASSOCIATED_POWER_SAVE) != SL_STATUS_OK) - { - ChipLogError(AppServer, "wfx_power_save failed"); - } -} - -void SleepManager::HandleInternetConnectivityChange(const ChipDeviceEvent * event) -{ - if (event->InternetConnectivityChange.IPv6 == kConnectivity_Established) - { - if (!IsCommissioningInProgress()) - { - if (wfx_power_save(RSI_SLEEP_MODE_2, ASSOCIATED_POWER_SAVE) != SL_STATUS_OK) - { - ChipLogError(AppServer, "wfx_power_save failed"); - } - } - } -} - -void SleepManager::HandleCommissioningWindowClose() -{ - if (!ConnectivityMgr().IsWiFiStationProvisioned() && !IsCommissioningInProgress()) - { - if (wfx_power_save(RSI_SLEEP_MODE_8, DEEP_SLEEP_WITH_RAM_RETENTION) != SL_STATUS_OK) - { - ChipLogError(AppServer, "Failed to enable the TA Deep Sleep"); - } - } -} - -void SleepManager::HandleCommissioningSessionStarted() -{ - SetCommissioningInProgress(true); -} - -void SleepManager::HandleCommissioningSessionStopped() -{ - SetCommissioningInProgress(false); -} - -void SleepManager::OnPlatformEvent(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg) -{ - SleepManager * manager = reinterpret_cast(arg); - VerifyOrDie(manager != nullptr); - - switch (event->Type) - { - case DeviceEventType::kCommissioningComplete: - manager->HandleCommissioningComplete(); - break; - - case DeviceEventType::kInternetConnectivityChange: - manager->HandleInternetConnectivityChange(event); - break; - - case DeviceEventType::kCommissioningWindowClose: - manager->HandleCommissioningWindowClose(); - break; - - case DeviceEventType::kCommissioningSessionStarted: - manager->HandleCommissioningSessionStarted(); - break; - - case DeviceEventType::kCommissioningSessionStopped: - manager->HandleCommissioningSessionStopped(); - break; - - default: - break; - } -} - -} // namespace Silabs -} // namespace DeviceLayer -} // namespace chip diff --git a/examples/platform/silabs/wifi/icd/SleepManager.h b/examples/platform/silabs/wifi/icd/SleepManager.h deleted file mode 100644 index b9786ae7eb..0000000000 --- a/examples/platform/silabs/wifi/icd/SleepManager.h +++ /dev/null @@ -1,112 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -namespace chip { -namespace DeviceLayer { -namespace Silabs { - -/** - * @brief SleepManager is a singleton class that manages the sleep modes for Wi-Fi devices. - * The class contains the buisness logic associated with optimizing the sleep states based on the Matter SDK internal states - * - * The class implements two disctint optimization states; one of SIT devices and one of LIT devices - * For SIT ICDs, the logic is based on the Subscriptions established with the device. - * For LIT ICDs, the logic is based on the ICDManager operating modes. The LIT mode also utilizes the SIT mode logic. - */ -class SleepManager : public chip::app::ICDStateObserver, - public chip::app::ReadHandler::ApplicationCallback, - public chip::FabricTable::Delegate -{ -public: - SleepManager(const SleepManager &) = delete; - SleepManager & operator=(const SleepManager &) = delete; - - static SleepManager & GetInstance() { return mInstance; } - - /** - * @brief Init function that configure the SleepManager APIs based on the type of ICD - * SIT ICD: Init function registers the ReadHandler Application callback to be notified when a subscription is - * established or destroyed. - * - * LIT ICD: Init function registers with the ICDManager as an observer to be notified of the ICD mode changes. - * - * @return CHIP_ERROR - */ - CHIP_ERROR Init(); - - SleepManager & SetInteractionModelEngine(chip::app::InteractionModelEngine * engine) - { - mIMEngine = engine; - return *this; - } - - SleepManager & SetFabricTable(chip::FabricTable * fabricTable) - { - mFabricTable = fabricTable; - return *this; - } - - // ICDStateObserver implementation overrides - - void OnEnterActiveMode(); - void OnEnterIdleMode(); - void OnTransitionToIdle() - { /* No execution logic */ - } - void OnICDModeChange() - { /* No execution logic */ - } - - // ReadHandler::ApplicationCallback implementation overrides - - void OnSubscriptionEstablished(chip::app::ReadHandler & aReadHandler); - void OnSubscriptionTerminated(chip::app::ReadHandler & aReadHandler); - - // FabricTable::Delegate implementation overrides - void FabricWillBeRemoved(const chip::FabricTable & fabricTable, - chip::FabricIndex fabricIndex) override{ /* No execution logic */ }; - void OnFabricRemoved(const chip::FabricTable & fabricTable, chip::FabricIndex fabricIndex) override; - void OnFabricCommitted(const chip::FabricTable & fabricTable, chip::FabricIndex fabricIndex) override; - void OnFabricUpdated(const chip::FabricTable & fabricTable, chip::FabricIndex fabricIndex) override{ /* No execution logic*/ }; - - static void OnPlatformEvent(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg); - - /** - * @brief Set the commissioning status of the device - * - * @param[in] inProgress bool true if commissioning is in progress, false otherwise - */ - void SetCommissioningInProgress(bool inProgress) { isCommissioningInProgress = inProgress; } - - /** - * @brief Returns the current commissioning status of the device - * - * @return bool true if commissioning is in progress, false otherwise - */ - bool IsCommissioningInProgress() { return isCommissioningInProgress; } - -private: - SleepManager() = default; - ~SleepManager() = default; - - void HandleCommissioningComplete(); - void HandleInternetConnectivityChange(const chip::DeviceLayer::ChipDeviceEvent * event); - void HandleCommissioningWindowClose(); - void HandleCommissioningSessionStarted(); - void HandleCommissioningSessionStopped(); - - static SleepManager mInstance; - chip::app::InteractionModelEngine * mIMEngine = nullptr; - chip::FabricTable * mFabricTable = nullptr; - bool isCommissioningInProgress = false; -}; - -} // namespace Silabs -} // namespace DeviceLayer -} // namespace chip diff --git a/src/platform/silabs/CHIPDevicePlatformConfig.h b/src/platform/silabs/CHIPDevicePlatformConfig.h index d31ce42399..1b65cfb56e 100644 --- a/src/platform/silabs/CHIPDevicePlatformConfig.h +++ b/src/platform/silabs/CHIPDevicePlatformConfig.h @@ -115,11 +115,6 @@ #define CHIP_DEVICE_CONFIG_ENABLE_IPV4 0 #endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ -#if SL_ICD_ENABLED -#define CHIP_DEVICE_CONFIG_ICD_SLOW_POLL_INTERVAL chip::System::Clock::Milliseconds32(300) -#define CHIP_DEVICE_CONFIG_ICD_FAST_POLL_INTERVAL chip::System::Clock::Milliseconds32(10) -#endif /* SL_ICD_ENABLED */ - #endif /* SL_WIFI */ // ========== Platform-specific Configuration ========= diff --git a/src/platform/silabs/SiWx917/OTAImageProcessorImpl.cpp b/src/platform/silabs/SiWx917/OTAImageProcessorImpl.cpp index 074097bac7..d5010d4e14 100644 --- a/src/platform/silabs/SiWx917/OTAImageProcessorImpl.cpp +++ b/src/platform/silabs/SiWx917/OTAImageProcessorImpl.cpp @@ -19,9 +19,9 @@ #include #include #include - #include -#include +#include + #ifdef __cplusplus extern "C" { #endif @@ -157,13 +157,9 @@ void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context) imageProcessor->mHeaderParser.Init(); - // Setting the device is in high performace - no-sleepy mode while OTA tranfer -#if (CHIP_CONFIG_ENABLE_ICD_SERVER) - status = wfx_power_save(RSI_ACTIVE, HIGH_PERFORMANCE); - if (status != SL_STATUS_OK) - { - ChipLogError(DeviceLayer, "Failed to enable the TA Deep Sleep"); - } +#if CHIP_CONFIG_ENABLE_ICD_SERVER + // Setting the device is in high performace - no-sleepy mode during OTA tranfer + DeviceLayer::Silabs::PlatformSleepManager::GetInstance().RequestHighPerformance(); #endif /* CHIP_CONFIG_ENABLE_ICD_SERVER*/ imageProcessor->mDownloader->OnPreparedForDownload(CHIP_NO_ERROR); @@ -200,13 +196,9 @@ void OTAImageProcessorImpl::HandleFinalize(intptr_t context) } imageProcessor->ReleaseBlock(); - // Setting the device back to power save mode when transfer is completed successfully #if (CHIP_CONFIG_ENABLE_ICD_SERVER) - sl_status_t err = wfx_power_save(RSI_SLEEP_MODE_2, ASSOCIATED_POWER_SAVE); - if (err != SL_STATUS_OK) - { - ChipLogError(DeviceLayer, "Power save config for Wifi failed"); - } + // Setting the device back to power save mode when transfer is completed successfully + DeviceLayer::Silabs::PlatformSleepManager::GetInstance().RemoveHighPerformanceRequest(); #endif /* CHIP_CONFIG_ENABLE_ICD_SERVER*/ ChipLogProgress(SoftwareUpdate, "OTA image downloaded successfully"); @@ -223,13 +215,9 @@ void OTAImageProcessorImpl::HandleApply(intptr_t context) ChipLogProgress(SoftwareUpdate, "OTA image downloaded successfully in HandleApply"); +#if CHIP_CONFIG_ENABLE_ICD_SERVER // Setting the device is in high performace - no-sleepy mode before soft reset as soft reset is not happening in sleep mode -#if (CHIP_CONFIG_ENABLE_ICD_SERVER) - status = wfx_power_save(RSI_ACTIVE, HIGH_PERFORMANCE); - if (status != SL_STATUS_OK) - { - ChipLogError(DeviceLayer, "Failed to enable the TA Deep Sleep"); - } + DeviceLayer::Silabs::PlatformSleepManager::GetInstance().RequestHighPerformance(); #endif /* CHIP_CONFIG_ENABLE_ICD_SERVER*/ if (mReset) @@ -250,13 +238,9 @@ void OTAImageProcessorImpl::HandleAbort(intptr_t context) return; } +#if CHIP_CONFIG_ENABLE_ICD_SERVER // Setting the device back to power save mode when transfer is aborted in the middle -#if (CHIP_CONFIG_ENABLE_ICD_SERVER) - sl_status_t err = wfx_power_save(RSI_SLEEP_MODE_2, ASSOCIATED_POWER_SAVE); - if (err != SL_STATUS_OK) - { - ChipLogError(DeviceLayer, "Power save config for Wifi failed"); - } + DeviceLayer::Silabs::PlatformSleepManager::GetInstance().RemoveHighPerformanceRequest(); #endif /* CHIP_CONFIG_ENABLE_ICD_SERVER*/ // Not clearing the image storage area as it is done during each write diff --git a/src/platform/silabs/efr32/BUILD.gn b/src/platform/silabs/efr32/BUILD.gn index f39628d484..ac9abb0eb8 100644 --- a/src/platform/silabs/efr32/BUILD.gn +++ b/src/platform/silabs/efr32/BUILD.gn @@ -162,6 +162,16 @@ static_library("efr32") { "${silabs_platform_dir}/NetworkCommissioningWiFiDriver.h", ] + # [sl-only] Support for the Wi-Fi Sleep Manager + if (chip_enable_icd_server) { + public_deps += [ "${silabs_common_plat_dir}/wifi/icd:sleep-manager" ] + } + + # [sl-only] Support for the Wi-Fi Sleep Manager public_deps += [ "${silabs_platform_dir}/wifi:wifi-platform" ] + + if (chip_enable_icd_server && use_SiWx917) { + public_deps += [ "${silabs_common_plat_dir}/wifi/icd:sleep-manager" ] + } } } diff --git a/src/platform/silabs/wifi/SiWx/WifiInterface.cpp b/src/platform/silabs/wifi/SiWx/WifiInterface.cpp index 3244f1fd44..2bdf104a18 100644 --- a/src/platform/silabs/wifi/SiWx/WifiInterface.cpp +++ b/src/platform/silabs/wifi/SiWx/WifiInterface.cpp @@ -86,13 +86,18 @@ extern osSemaphoreId_t sl_rs_ble_init_sem; namespace { -#if CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI91X_MCU_INTERFACE +#if CHIP_CONFIG_ENABLE_ICD_SERVER + +constexpr uint32_t kTimeToFullBeaconReception = 5000; // 5 seconds + +#if SLI_SI91X_MCU_INTERFACE // TODO: should be removed once we are getting the press interrupt for button 0 with sleep bool btn0_pressed = false; #ifdef ENABLE_CHIP_SHELL bool ps_requirement_added = false; #endif // ENABLE_CHIP_SHELL -#endif // CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI91X_MCU_INTERFACE +#endif // SLI_SI91X_MCU_INTERFACE +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER bool hasNotifiedWifiConnectivity = false; bool hasNotifiedIPV6 = false; @@ -862,36 +867,47 @@ void wfx_dhcp_got_ipv4(uint32_t ip) } #endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ -#if SL_ICD_ENABLED -/********************************************************************* - * @fn sl_status_t wfx_power_save(rsi_power_save_profile_mode_t sl_si91x_ble_state, sl_si91x_performance_profile_t - sl_si91x_wifi_state) +#if CHIP_CONFIG_ENABLE_ICD_SERVER +/** * @brief - * Implements the power save in sleepy application - * @param[in] sl_si91x_ble_state : State to set for the BLE - sl_si91x_wifi_state : State to set for the WiFi - * @return SL_STATUS_OK if successful, - * SL_STATUS_FAIL otherwise - ***********************************************************************/ -sl_status_t wfx_power_save(rsi_power_save_profile_mode_t sl_si91x_ble_state, sl_si91x_performance_profile_t sl_si91x_wifi_state) + * + * @param sl_si91x_ble_state + * @param sl_si91x_wifi_state + * @param listenInterval + * @param enableBroadcastFilter + * @return sl_status_t + */ +sl_status_t wfx_power_save(rsi_power_save_profile_mode_t sl_si91x_ble_state, sl_si91x_performance_profile_t sl_si91x_wifi_state, + uint32_t listenInterval) { int32_t error = rsi_bt_power_save_profile(sl_si91x_ble_state, 0); - if (error != RSI_SUCCESS) - { - ChipLogError(DeviceLayer, "rsi_bt_power_save_profile failed: %ld", error); - return SL_STATUS_FAIL; - } + VerifyOrReturnError(error == RSI_SUCCESS, SL_STATUS_FAIL, + ChipLogError(DeviceLayer, "rsi_bt_power_save_profile failed: %ld", error)); - sl_wifi_performance_profile_t wifi_profile = { .profile = sl_si91x_wifi_state, + sl_wifi_performance_profile_t wifi_profile = { .profile = sl_si91x_wifi_state, + // TODO: Performance profile fails if not alligned with DTIM .dtim_aligned_type = SL_SI91X_ALIGN_WITH_DTIM_BEACON, - .listen_interval = 0 }; - sl_status_t status = sl_wifi_set_performance_profile(&wifi_profile); - if (status != SL_STATUS_OK) - { - ChipLogError(DeviceLayer, "sl_wifi_set_performance_profile failed: 0x%lx", static_cast(status)); - return status; - } + // TODO: Different types need to be fixe in the Wi-Fi SDK + .listen_interval = static_cast(listenInterval) }; - return SL_STATUS_OK; + sl_status_t status = sl_wifi_set_performance_profile(&wifi_profile); + VerifyOrReturnError(status == SL_STATUS_OK, status, + ChipLogError(DeviceLayer, "sl_wifi_set_performance_profile failed: 0x%lx", status)); + + return status; } -#endif + +sl_status_t ConfigureBroadcastFilter(bool enableBroadcastFilter) +{ + sl_status_t status = SL_STATUS_OK; + + uint16_t beaconDropThreshold = (enableBroadcastFilter) ? kTimeToFullBeaconReception : 0; + uint8_t filterBcastInTim = (enableBroadcastFilter) ? 1 : 0; + + status = sl_wifi_filter_broadcast(5000, 1, 1 /* valid till next update*/); + VerifyOrReturnError(status == SL_STATUS_OK, status, + ChipLogError(DeviceLayer, "sl_wifi_filter_broadcast failed: 0x%lx", static_cast(status))); + + return status; +} +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER diff --git a/src/platform/silabs/wifi/WifiInterfaceAbstraction.cpp b/src/platform/silabs/wifi/WifiInterfaceAbstraction.cpp index ad36a6c6ec..26bc1aa8f2 100644 --- a/src/platform/silabs/wifi/WifiInterfaceAbstraction.cpp +++ b/src/platform/silabs/wifi/WifiInterfaceAbstraction.cpp @@ -37,6 +37,9 @@ using namespace chip::DeviceLayer; // As such we can't depend on the platform here as well extern void HandleWFXSystemEvent(wfx_event_base_t eventBase, sl_wfx_generic_message_t * eventData); +// TODO: We shouldn't need to have access to a global variable in the interface here +extern WfxRsi_t wfx_rsi; + namespace { constexpr uint8_t kWlanMinRetryIntervalsInSec = 1; @@ -51,7 +54,7 @@ osTimerId_t sRetryTimer; void RetryConnectionTimerHandler(void * arg) { #if CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI91X_MCU_INTERFACE - wfx_power_save(RSI_ACTIVE, HIGH_PERFORMANCE); + wfx_power_save(RSI_ACTIVE, HIGH_PERFORMANCE, 0); #endif // CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI91X_MCU_INTERFACE if (wfx_connect_to_ap() != SL_STATUS_OK) { @@ -192,7 +195,7 @@ void wfx_retry_connection(uint16_t retryAttempt) return; } #if CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI91X_MCU_INTERFACE - wfx_power_save(RSI_SLEEP_MODE_8, DEEP_SLEEP_WITH_RAM_RETENTION); + wfx_power_save(RSI_SLEEP_MODE_8, DEEP_SLEEP_WITH_RAM_RETENTION, 0); #endif // CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI91X_MCU_INTERFACE ChipLogProgress(DeviceLayer, "wfx_retry_connection : Next attempt after %d Seconds", retryInterval); retryInterval += retryInterval; diff --git a/src/platform/silabs/wifi/WifiInterfaceAbstraction.h b/src/platform/silabs/wifi/WifiInterfaceAbstraction.h index d7cfb30287..8f45f1d470 100644 --- a/src/platform/silabs/wifi/WifiInterfaceAbstraction.h +++ b/src/platform/silabs/wifi/WifiInterfaceAbstraction.h @@ -195,9 +195,6 @@ typedef struct wfx_rsi_s uint8_t ip4_addr[4]; /* Not sure if this is enough */ } WfxRsi_t; -// TODO: We shouldn't need to have access to a global variable in the interface here -extern WfxRsi_t wfx_rsi; - sl_status_t wfx_wifi_start(void); void wfx_enable_sta_mode(void); void wfx_get_wifi_mac_addr(sl_wfx_interface_t interface, sl_wfx_mac_address_t * addr); @@ -253,17 +250,27 @@ int32_t wfx_rsi_send_data(void * p, uint16_t len); bool wfx_hw_ready(void); +#if CHIP_CONFIG_ENABLE_ICD_SERVER #ifdef RS911X_WIFI // for RS9116, 917 NCP and 917 SoC /* RSI Power Save */ -#if SL_ICD_ENABLED #if (SLI_SI91X_MCU_INTERFACE | EXP_BOARD) -sl_status_t wfx_power_save(rsi_power_save_profile_mode_t sl_si91x_ble_state, sl_si91x_performance_profile_t sl_si91x_wifi_state); +sl_status_t wfx_power_save(rsi_power_save_profile_mode_t sl_si91x_ble_state, sl_si91x_performance_profile_t sl_si91x_wifi_state, + uint32_t listenInterval); #else sl_status_t wfx_power_save(); #endif /* (SLI_SI91X_MCU_INTERFACE | EXP_BOARD) */ -#endif /* SL_ICD_ENABLED */ #endif /* RS911X_WIFI */ +/** + * @brief Configures the broadcast filter. + * + * @param[in] enableBroadcastFilter Boolean to enable or disable the broadcast filter. + * @return sl_status_t Returns the status of the operation. + */ +sl_status_t ConfigureBroadcastFilter(bool enableBroadcastFilter); + +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER + void sl_matter_wifi_task(void * arg); #if CHIP_DEVICE_CONFIG_ENABLE_IPV4 diff --git a/examples/platform/silabs/wifi/icd/BUILD.gn b/src/platform/silabs/wifi/icd/BUILD.gn similarity index 84% rename from examples/platform/silabs/wifi/icd/BUILD.gn rename to src/platform/silabs/wifi/icd/BUILD.gn index 40e4cf1ad7..27c1008fa9 100644 --- a/examples/platform/silabs/wifi/icd/BUILD.gn +++ b/src/platform/silabs/wifi/icd/BUILD.gn @@ -14,15 +14,15 @@ import("//build_overrides/chip.gni") -config("sleep-manager-config") { +config("platform-sleep-manager-config") { include_dirs = [ "." ] defines = [ "SL_MATTER_SLEEP_MANAGER_ENABLED=1" ] } -source_set("sleep-manager") { +source_set("platform-sleep-manager") { sources = [ - "SleepManager.cpp", - "SleepManager.h", + "PlatformSleepManager.cpp", + "PlatformSleepManager.h", ] public_deps = [ @@ -35,5 +35,5 @@ source_set("sleep-manager") { "${chip_root}/src/platform/silabs/wifi:wifi-platform", ] - public_configs = [ ":sleep-manager-config" ] + public_configs = [ ":platform-sleep-manager-config" ] } diff --git a/src/platform/silabs/wifi/icd/PlatformSleepManager.cpp b/src/platform/silabs/wifi/icd/PlatformSleepManager.cpp new file mode 100644 index 0000000000..bf33155397 --- /dev/null +++ b/src/platform/silabs/wifi/icd/PlatformSleepManager.cpp @@ -0,0 +1,140 @@ +#include "SleepManager.h" +#include +#include +#include + +using namespace chip::app; + +namespace chip { +namespace DeviceLayer { +namespace Silabs { + +// Initialize the static instance +PlatformSleepManager PlatformSleepManager::mInstance; + +CHIP_ERROR PlatformSleepManager::Init() +{ + PlatformMgr().AddEventHandler(OnPlatformEvent, reinterpret_cast(this)); + return CHIP_NO_ERROR; +} + +void PlatformSleepManager::HandleCommissioningComplete() +{ + if (wfx_power_save(RSI_SLEEP_MODE_2, ASSOCIATED_POWER_SAVE, 0) != SL_STATUS_OK) + { + ChipLogError(AppServer, "wfx_power_save failed"); + } +} + +void PlatformSleepManager::HandleInternetConnectivityChange(const ChipDeviceEvent * event) +{ + if (event->InternetConnectivityChange.IPv6 == kConnectivity_Established) + { + if (!IsCommissioningInProgress()) + { + if + { + ChipLogError(AppServer, "wfx_power_save failed"); + } + } + } +} + +void PlatformSleepManager::HandleCommissioningWindowClose() {} + +void PlatformSleepManager::HandleCommissioningSessionStarted() +{ + SetCommissioningInProgress(true); +} + +void PlatformSleepManager::HandleCommissioningSessionStopped() +{ + SetCommissioningInProgress(false); +} + +void PlatformSleepManager::OnPlatformEvent(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg) +{ + PlatformSleepManager * manager = reinterpret_cast(arg); + VerifyOrDie(manager != nullptr); + + switch (event->Type) + { + case DeviceEventType::kCommissioningComplete: + manager->HandleCommissioningComplete(); + break; + + case DeviceEventType::kInternetConnectivityChange: + manager->HandleInternetConnectivityChange(event); + break; + + case DeviceEventType::kCommissioningWindowClose: + manager->HandleCommissioningWindowClose(); + break; + + case DeviceEventType::kCommissioningSessionStarted: + manager->HandleCommissioningSessionStarted(); + break; + + case DeviceEventType::kCommissioningSessionStopped: + manager->HandleCommissioningSessionStopped(); + break; + + default: + break; + } +} + +CHIP_ERROR PlatformSleepManager::RequestHighPerformance() +{ + VerifyOrReturnError(mRequestHighPerformanceCounter < std::numeric_limits::max(), CHIP_ERROR_INTERNAL, + ChipLogError(DeviceLayer, "High performance request counter overflow")); + + if (mRequestHighPerformanceCounter == 0) + { + VerifyOrReturnError(wfx_power_save(RSI_ACTIVE, HIGH_PERFORMANCE, 0) == SL_STATUS_OK, CHIP_ERROR_INTERNAL, + ChipLogError(DeviceLayer, "Failed to set Wi-FI configuration to HighPerformance")); + VerifyOrReturnError(ConfigureBroadcastFilter(false) == SL_STATUS_OK, CHIP_ERROR_INTERNAL, + ChipLogError(DeviceLayer, "Failed to disable broadcast filter")); + } + + mRequestHighPerformanceCounter++; + return CHIP_NO_ERROR; +} + +CHIP_ERROR PlatformSleepManager::RemoveHighPerformanceRequest() +{ + VerifyOrReturnError(mHighPerformanceRequestCounter > 0, CHIP_NO_ERROR, + ChipLogError(DeviceLayer, "Wi-Fi configuration already in low power mode")); + + mHighPerformanceRequestCounter--; + + if (mHighPerformanceRequestCounter == 0) + { + ReturnErrorOnFailure(TransitionToLowPowerMode()); + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR PlatformSleepManager::TransitionToLowPowerMode() +{ + VerifyOrReturnError(mHighPerformanceRequestCounter == 0, CHIP_NO_ERROR, + ChipLogDetail(DeviceLayer, "High Performance Requested - Device cannot go to a lower power mode.")); + + if (!ConnectivityMgr().IsWiFiStationProvisioned() && !IsCommissioningInProgress()) + { + VerifyOrReturnError(wfx_power_save(RSI_SLEEP_MODE_8, DEEP_SLEEP_WITH_RAM_RETENTION, 0) != SL_STATUS_OK, + ChipLogError(DeviceLayer, "Failed to enable the TA Deep Sleep");) + } + else + { + VerifyOrReturnError(wfx_power_save(RSI_SLEEP_MODE_2, ASSOCIATED_POWER_SAVE, 0) != SL_STATUS_OK, + ChipLogError(DeviceLayer, "Failed to enable the TA Deep Sleep");) + } + + return CHIP_NO_ERROR; +} + +} // namespace Silabs +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/silabs/wifi/icd/PlatformSleepManager.h b/src/platform/silabs/wifi/icd/PlatformSleepManager.h new file mode 100644 index 0000000000..1737e7194a --- /dev/null +++ b/src/platform/silabs/wifi/icd/PlatformSleepManager.h @@ -0,0 +1,98 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace chip { +namespace DeviceLayer { +namespace Silabs { + +/** + * @brief PlatformSleepManager is a singleton class that manages the sleep modes for Wi-Fi devices. + * The class contains the buisness logic associated with optimizing the sleep states based on the Matter SDK internal states + */ +class PlatformSleepManager +{ +public: + PlatformSleepManager(const PlatformSleepManager &) = delete; + PlatformSleepManager & operator=(const PlatformSleepManager &) = delete; + + static PlatformSleepManager & GetInstance() { return mInstance; } + + /** + * @brief Init function that configure the SleepManager APIs based on the type of ICD. + * Function validates that the SleepManager configuration were correctly set as well. + * + * @return CHIP_ERROR + */ + CHIP_ERROR Init(); + + /** + * @brief Public API to request the Wi-Fi chip to transition to High Performance. + * Function increases the HighPerformance request counter to prevent the chip from going to sleep + * while the Matter SDK is in a state that requires High Performance + * + * @return CHIP_ERROR CHIP_NO_ERROR if the chip was set to high performance or already in high performance + * CHIP_ERROR_INTERNAL, if the high performance configuration failed + */ + CHIP_ERROR RequestHighPerformance(); + + /** + * @brief Public API to remove request to keep the Wi-Fi chip in High Performance. + * If calling this function removes the last High performance request, + * The chip will transition to sleep based on its lowest sleep level allowed + * + * @return CHIP_ERROR CHIP_NO_ERROR if the req removal and sleep transition succeed + * CHIP_ERROR_INTERNAL, if the req removal or the transition to sleep failed + */ + CHIP_ERROR RemoveHighPerformanceRequest(); + + static void OnPlatformEvent(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg); + +private: + PlatformSleepManager() = default; + ~PlatformSleepManager() = default; + + void HandleCommissioningComplete(); + void HandleInternetConnectivityChange(const chip::DeviceLayer::ChipDeviceEvent * event); + void HandleCommissioningWindowClose(); + void HandleCommissioningSessionStarted(); + void HandleCommissioningSessionStopped(); + + /** + * @brief Set the commissioning status of the device + * + * @param[in] inProgress bool true if commissioning is in progress, false otherwise + */ + void SetCommissioningInProgress(bool inProgress) { isCommissioningInProgress = inProgress; } + + /** + * @brief Returns the current commissioning status of the device + * + * @return bool true if commissioning is in progress, false otherwise + */ + bool IsCommissioningInProgress() { return isCommissioningInProgress; } + + /** + * @brief Transition the device to the Lowest Power State. + * The function is responsible of deciding if the device can go to a LI based sleep + * or is required to stay in a DTIM based sleep to be able to receive mDNS messages + * + * @return CHIP_ERROR CHIP_NO_ERROR if the device was transitionned to low power + * CHIP_ERROR_INTERNAL if an error occured + */ + CHIP_ERROR TransitionToLowPowerMode(); + + static PlatformSleepManager mInstance; + bool isCommissioningInProgress = false; + + uint8_t mHighPerformanceRequestCounter = 0; +}; + +} // namespace Silabs +} // namespace DeviceLayer +} // namespace chip