diff --git a/examples/platform/silabs/BaseApplication.cpp b/examples/platform/silabs/BaseApplication.cpp index b6b21012b5263d..bba2aa311a0f99 100644 --- a/examples/platform/silabs/BaseApplication.cpp +++ b/examples/platform/silabs/BaseApplication.cpp @@ -272,7 +272,7 @@ CHIP_ERROR BaseApplication::Init() * Wait for the WiFi to be initialized */ ChipLogProgress(AppServer, "APP: Wait WiFi Init"); - while (!IsStationReady()) + while (!WifiInterface::GetInstance().IsStationReady()) { osDelay(pdMS_TO_TICKS(10)); } diff --git a/examples/platform/silabs/MatterConfig.cpp b/examples/platform/silabs/MatterConfig.cpp index 87279c2c379b06..f94ad8630ecb14 100644 --- a/examples/platform/silabs/MatterConfig.cpp +++ b/examples/platform/silabs/MatterConfig.cpp @@ -318,7 +318,7 @@ CHIP_ERROR SilabsMatterConfig::InitMatter(const char * appName) #ifdef SL_WIFI CHIP_ERROR SilabsMatterConfig::InitWiFi(void) { - return InitWiFiStack(); + return WifiInterface::GetInstance().InitWiFiStack(); } #endif // SL_WIFI diff --git a/src/platform/silabs/ConfigurationManagerImpl.cpp b/src/platform/silabs/ConfigurationManagerImpl.cpp index aba5d077cbb550..4ed23084020593 100644 --- a/src/platform/silabs/ConfigurationManagerImpl.cpp +++ b/src/platform/silabs/ConfigurationManagerImpl.cpp @@ -38,6 +38,7 @@ namespace chip { namespace DeviceLayer { using namespace ::chip::DeviceLayer::Internal; +using namespace ::chip ::DeviceLayer ::Silabs; ConfigurationManagerImpl & ConfigurationManagerImpl::GetDefaultInstance() { @@ -290,14 +291,14 @@ void ConfigurationManagerImpl::DoFactoryReset(intptr_t arg) PersistedStorage::KeyValueStoreMgrImpl().ErasePartition(); #if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION - error = TriggerDisconnection(); + error = WifiInterface::GetInstance().TriggerDisconnection(); if (error != CHIP_NO_ERROR) { ChipLogError(DeviceLayer, "TriggerDisconnection() failed: %s", chip::ErrorStr(error)); } ChipLogProgress(DeviceLayer, "Clearing WiFi provision"); - ClearWifiCredentials(); + WifiInterface::GetInstance().ClearWifiCredentials(); #endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION // Restart the system. @@ -317,7 +318,7 @@ CHIP_ERROR ConfigurationManagerImpl::GetPrimaryWiFiMACAddress(uint8_t * buf) VerifyOrReturnError(buf != nullptr, CHIP_ERROR_INVALID_ARGUMENT); MutableByteSpan byteSpan(buf, kPrimaryMACAddressLength); - return GetMacAddress(SL_WFX_STA_INTERFACE, byteSpan); + return WifiInterface::GetInstance().GetMacAddress(SL_WFX_STA_INTERFACE, byteSpan); } #endif diff --git a/src/platform/silabs/ConnectivityManagerImpl_WIFI.cpp b/src/platform/silabs/ConnectivityManagerImpl_WIFI.cpp index 5ea8ddb44ca643..7998b484fd5ceb 100644 --- a/src/platform/silabs/ConnectivityManagerImpl_WIFI.cpp +++ b/src/platform/silabs/ConnectivityManagerImpl_WIFI.cpp @@ -46,6 +46,7 @@ using namespace ::chip; using namespace ::chip::Inet; using namespace ::chip::System; using namespace ::chip::DeviceLayer::Internal; +using namespace ::chip::DeviceLayer::Silabs; namespace chip { namespace DeviceLayer { @@ -65,7 +66,7 @@ CHIP_ERROR ConnectivityManagerImpl::_Init() // TODO Initialize the Chip Addressing and Routing Module. // Ensure that station mode is enabled. - ConfigureStationMode(); + WifiInterface::GetInstance().ConfigureStationMode(); err = DeviceLayer::SystemLayer().ScheduleWork(DriveStationState, NULL); @@ -84,11 +85,11 @@ void ConnectivityManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) switch (event->Platform.WFXSystemEvent.data.genericMsgEvent.header.id) { - case to_underlying(WifiEvent::kStartUp): + case to_underlying(WifiInterface::WifiEvent::kStartUp): ChipLogProgress(DeviceLayer, "WIFI_EVENT_STA_START"); DriveStationState(); break; - case to_underlying(WifiEvent::kConnect): + case to_underlying(WifiInterface::WifiEvent::kConnect): ChipLogProgress(DeviceLayer, "WIFI_EVENT_STA_CONNECTED"); if (mWiFiStationState == kWiFiStationState_Connecting) { @@ -103,7 +104,7 @@ void ConnectivityManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) } DriveStationState(); break; - case to_underlying(WifiEvent::kDisconnect): + case to_underlying(WifiInterface::WifiEvent::kDisconnect): ChipLogProgress(DeviceLayer, "WIFI_EVENT_STA_DISCONNECTED"); if (mWiFiStationState == kWiFiStationState_Connecting) { @@ -112,9 +113,9 @@ void ConnectivityManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) DriveStationState(); break; - case to_underlying(WifiEvent::kGotIPv4): - case to_underlying(WifiEvent::kLostIP): - case to_underlying(WifiEvent::kGotIPv6): + case to_underlying(WifiInterface::WifiEvent::kGotIPv4): + case to_underlying(WifiInterface::WifiEvent::kLostIP): + case to_underlying(WifiInterface::WifiEvent::kGotIPv6): ChipLogProgress(DeviceLayer, "IP Change Event"); UpdateInternetConnectivityState(); break; @@ -128,7 +129,7 @@ ConnectivityManager::WiFiStationMode ConnectivityManagerImpl::_GetWiFiStationMod { if (mWiFiStationMode != kWiFiStationMode_ApplicationControlled) { - if (IsStationModeEnabled()) + if (WifiInterface::GetInstance().IsStationModeEnabled()) { mWiFiStationMode = kWiFiStationMode_Enabled; } @@ -143,12 +144,12 @@ ConnectivityManager::WiFiStationMode ConnectivityManagerImpl::_GetWiFiStationMod bool ConnectivityManagerImpl::_IsWiFiStationProvisioned(void) { - return IsWifiProvisioned(); + return WifiInterface::GetInstance().IsWifiProvisioned(); } bool ConnectivityManagerImpl::_IsWiFiStationEnabled(void) { - return IsStationModeEnabled(); + return WifiInterface::GetInstance().IsStationModeEnabled(); } CHIP_ERROR ConnectivityManagerImpl::_SetWiFiStationMode(ConnectivityManager::WiFiStationMode val) @@ -176,7 +177,7 @@ void ConnectivityManagerImpl::_ClearWiFiStationProvision(void) { if (mWiFiStationMode != kWiFiStationMode_ApplicationControlled) { - ClearWifiCredentials(); + WifiInterface::GetInstance().ClearWifiCredentials(); DeviceLayer::SystemLayer().ScheduleWork(DriveStationState, NULL); } @@ -222,14 +223,14 @@ void ConnectivityManagerImpl::DriveStationState() if (mWiFiStationMode != kWiFiStationMode_ApplicationControlled) { // Ensure that the Wifi task is started. - CHIP_ERROR error = StartWifiTask(); + CHIP_ERROR error = WifiInterface::GetInstance().StartWifiTask(); VerifyOrReturn(error == CHIP_NO_ERROR, ChipLogError(DeviceLayer, "StartWifiTask() failed: %s", ErrorStr(error))); // Ensure that station mode is enabled in the WiFi layer. - ConfigureStationMode(); + WifiInterface::GetInstance().ConfigureStationMode(); } - stationConnected = IsStationConnected(); + stationConnected = WifiInterface::GetInstance().IsStationConnected(); // If the station interface is currently connected ... if (stationConnected) @@ -255,7 +256,7 @@ void ConnectivityManagerImpl::DriveStationState() { ChipLogProgress(DeviceLayer, "Disconnecting WiFi station interface"); - CHIP_ERROR error = TriggerDisconnection(); + CHIP_ERROR error = WifiInterface::GetInstance().TriggerDisconnection(); SuccessOrExitAction(error, ChipLogError(DeviceLayer, "TriggerDisconnection() failed: %s", ErrorStr(error))); ChangeWiFiStationState(kWiFiStationState_Disconnecting); @@ -299,7 +300,8 @@ void ConnectivityManagerImpl::DriveStationState() if (mWiFiStationState != kWiFiStationState_Connecting) { ChipLogProgress(DeviceLayer, "Attempting to connect WiFi"); - SuccessOrExitAction(ConnectToAccessPoint(), ChipLogError(DeviceLayer, "ConnectToAccessPoint() failed")); + SuccessOrExitAction(WifiInterface::GetInstance().ConnectToAccessPoint(), + ChipLogError(DeviceLayer, "ConnectToAccessPoint() failed")); ChangeWiFiStationState(kWiFiStationState_Connecting); } @@ -376,9 +378,9 @@ void ConnectivityManagerImpl::UpdateInternetConnectivityState(void) if (mWiFiStationState == kWiFiStationState_Connected) { #if CHIP_DEVICE_CONFIG_ENABLE_IPV4 - haveIPv4Conn = HasAnIPv4Address(); + haveIPv4Conn = WifiInterface::GetIstance().HasAnIPv4Address(); #endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ - haveIPv6Conn = HasAnIPv6Address(); + haveIPv6Conn = WifiInterface::GetInstance().HasAnIPv6Address(); } // If the internet connectivity state has changed... diff --git a/src/platform/silabs/DiagnosticDataProviderImpl.cpp b/src/platform/silabs/DiagnosticDataProviderImpl.cpp index 58128528fef501..4c0cf8ac751655 100644 --- a/src/platform/silabs/DiagnosticDataProviderImpl.cpp +++ b/src/platform/silabs/DiagnosticDataProviderImpl.cpp @@ -340,7 +340,7 @@ CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiBssId(MutableByteSpan & BssId) VerifyOrReturnError(BssId.size() >= bssIdSize, CHIP_ERROR_BUFFER_TOO_SMALL); - if (GetAccessPointInfo(ap) == CHIP_NO_ERROR) + if (Silabs::WifiInterface::GetInstance().GetAccessPointInfo(ap) == CHIP_NO_ERROR) { memcpy(BssId.data(), ap.bssid, bssIdSize); BssId.reduce_size(bssIdSize); @@ -355,7 +355,7 @@ CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiSecurityType(app::Clusters::WiFiNe using app::Clusters::WiFiNetworkDiagnostics::SecurityTypeEnum; wfx_wifi_scan_result_t ap = { 0 }; - CHIP_ERROR error = GetAccessPointInfo(ap); + CHIP_ERROR error = Silabs::WifiInterface::GetInstance().GetAccessPointInfo(ap); if (error == CHIP_NO_ERROR) { // TODO: Is this actually right? Do the wfx_wifi_scan_result_t values @@ -375,7 +375,7 @@ CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiVersion(app::Clusters::WiFiNetwork CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiChannelNumber(uint16_t & channelNumber) { wfx_wifi_scan_result_t ap = { 0 }; - CHIP_ERROR error = GetAccessPointInfo(ap); + CHIP_ERROR error = Silabs::WifiInterface::GetInstance().GetAccessPointInfo(ap); if (error == CHIP_NO_ERROR) { channelNumber = ap.chan; @@ -387,7 +387,7 @@ CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiChannelNumber(uint16_t & channelNu CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiRssi(int8_t & rssi) { wfx_wifi_scan_result_t ap = { 0 }; - CHIP_ERROR error = GetAccessPointInfo(ap); + CHIP_ERROR error = Silabs::WifiInterface::GetInstance().GetAccessPointInfo(ap); if (error == CHIP_NO_ERROR) { rssi = ap.rssi; @@ -399,7 +399,7 @@ CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiRssi(int8_t & rssi) CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiBeaconLostCount(uint32_t & beaconLostCount) { wfx_wifi_scan_ext_t extra_info = { 0 }; - CHIP_ERROR error = GetAccessPointExtendedInfo(extra_info); + CHIP_ERROR error = Silabs::WifiInterface::GetInstance().GetAccessPointExtendedInfo(extra_info); if (error == CHIP_NO_ERROR) { beaconLostCount = extra_info.beacon_lost_count; @@ -416,7 +416,7 @@ CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiCurrentMaxRate(uint64_t & currentM CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiPacketMulticastRxCount(uint32_t & packetMulticastRxCount) { wfx_wifi_scan_ext_t extra_info = { 0 }; - CHIP_ERROR error = GetAccessPointExtendedInfo(extra_info); + CHIP_ERROR error = Silabs::WifiInterface::GetInstance().GetAccessPointExtendedInfo(extra_info); if (error == CHIP_NO_ERROR) { packetMulticastRxCount = extra_info.mcast_rx_count; @@ -428,7 +428,7 @@ CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiPacketMulticastRxCount(uint32_t & CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiPacketMulticastTxCount(uint32_t & packetMulticastTxCount) { wfx_wifi_scan_ext_t extra_info = { 0 }; - CHIP_ERROR error = GetAccessPointExtendedInfo(extra_info); + CHIP_ERROR error = Silabs::WifiInterface::GetInstance().GetAccessPointExtendedInfo(extra_info); if (error == CHIP_NO_ERROR) { packetMulticastTxCount = extra_info.mcast_tx_count; @@ -440,7 +440,7 @@ CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiPacketMulticastTxCount(uint32_t & CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiPacketUnicastRxCount(uint32_t & packetUnicastRxCount) { wfx_wifi_scan_ext_t extra_info = { 0 }; - CHIP_ERROR error = GetAccessPointExtendedInfo(extra_info); + CHIP_ERROR error = Silabs::WifiInterface::GetInstance().GetAccessPointExtendedInfo(extra_info); if (error == CHIP_NO_ERROR) { packetUnicastRxCount = extra_info.ucast_rx_count; @@ -452,7 +452,7 @@ CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiPacketUnicastRxCount(uint32_t & pa CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiPacketUnicastTxCount(uint32_t & packetUnicastTxCount) { wfx_wifi_scan_ext_t extra_info = { 0 }; - CHIP_ERROR error = GetAccessPointExtendedInfo(extra_info); + CHIP_ERROR error = Silabs::WifiInterface::GetInstance().GetAccessPointExtendedInfo(extra_info); if (error == CHIP_NO_ERROR) { packetUnicastTxCount = extra_info.ucast_tx_count; @@ -464,7 +464,7 @@ CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiPacketUnicastTxCount(uint32_t & pa CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiOverrunCount(uint64_t & overrunCount) { wfx_wifi_scan_ext_t extra_info = { 0 }; - CHIP_ERROR error = GetAccessPointExtendedInfo(extra_info); + CHIP_ERROR error = Silabs::WifiInterface::GetInstance().GetAccessPointExtendedInfo(extra_info); if (error == CHIP_NO_ERROR) { overrunCount = extra_info.overrun_count; @@ -476,7 +476,7 @@ CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiOverrunCount(uint64_t & overrunCou CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiBeaconRxCount(uint32_t & beaconRxCount) { wfx_wifi_scan_ext_t extra_info = { 0 }; - CHIP_ERROR error = GetAccessPointExtendedInfo(extra_info); + CHIP_ERROR error = Silabs::WifiInterface::GetInstance().GetAccessPointExtendedInfo(extra_info); if (error == CHIP_NO_ERROR) { beaconRxCount = extra_info.beacon_rx_count; @@ -487,7 +487,7 @@ CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiBeaconRxCount(uint32_t & beaconRxC CHIP_ERROR DiagnosticDataProviderImpl::ResetWiFiNetworkDiagnosticsCounts() { - return ResetCounters(); + return Silabs::WifiInterface::GetInstance().ResetCounters(); } #endif // SL_WIFI diff --git a/src/platform/silabs/NetworkCommissioningWiFiDriver.cpp b/src/platform/silabs/NetworkCommissioningWiFiDriver.cpp index 3d036867fc373c..f021f9d8c3ad8f 100644 --- a/src/platform/silabs/NetworkCommissioningWiFiDriver.cpp +++ b/src/platform/silabs/NetworkCommissioningWiFiDriver.cpp @@ -25,6 +25,7 @@ using namespace ::chip; using namespace ::chip::DeviceLayer::Internal; +using namespace ::chip::DeviceLayer::Silabs; namespace chip { namespace DeviceLayer { @@ -138,14 +139,13 @@ CHIP_ERROR SlWiFiDriver::ConnectWiFiNetwork(const char * ssid, uint8_t ssidLen, { if (ConnectivityMgr().IsWiFiStationProvisioned()) { - ChipLogProgress(DeviceLayer, "Disconecting for current wifi"); - ReturnErrorOnFailure(TriggerDisconnection()); + ChipLogProgress(DeviceLayer, "Disconnecting for current wifi"); + ReturnErrorOnFailure(WifiInterface::GetInstance().TriggerDisconnection()); } ReturnErrorOnFailure(ConnectivityMgr().SetWiFiStationMode(ConnectivityManager::kWiFiStationMode_Disabled)); // Set the wifi configuration - WifiCredentials wifiConfig; - wifiConfig.Clear(); + WifiInterface::WifiCredentials wifiConfig; VerifyOrReturnError(ssidLen <= WFX_MAX_SSID_LENGTH, CHIP_ERROR_BUFFER_TOO_SMALL); memcpy(wifiConfig.ssid, ssid, ssidLen); @@ -159,7 +159,7 @@ CHIP_ERROR SlWiFiDriver::ConnectWiFiNetwork(const char * ssid, uint8_t ssidLen, ChipLogProgress(NetworkProvisioning, "Setting up connection for WiFi SSID: %.*s", static_cast(ssidLen), ssid); // Configure the WFX WiFi interface. - SetWifiCredentials(wifiConfig); + WifiInterface::GetInstance().SetWifiCredentials(wifiConfig); ReturnErrorOnFailure(ConnectivityMgr().SetWiFiStationMode(ConnectivityManager::kWiFiStationMode_Disabled)); ReturnErrorOnFailure(ConnectivityMgr().SetWiFiStationMode(ConnectivityManager::kWiFiStationMode_Enabled)); return CHIP_NO_ERROR; @@ -181,7 +181,7 @@ void SlWiFiDriver::UpdateNetworkingStatus() } ByteSpan networkId = ByteSpan((const unsigned char *) mStagingNetwork.ssid, mStagingNetwork.ssidLen); - if (!IsStationConnected()) + if (!WifiInterface::GetInstance().IsStationConnected()) { // TODO: https://github.com/project-chip/connectedhomeip/issues/26861 mpStatusChangeCallback->OnNetworkingStatusChange(Status::kUnknownError, MakeOptional(networkId), @@ -261,7 +261,7 @@ chip::BitFlags SlWiFiDriver::ConvertSecuritytype(wfx_sec_t securit bool SlWiFiDriver::StartScanWiFiNetworks(ByteSpan ssid) { ChipLogProgress(DeviceLayer, "Start Scan WiFi Networks"); - CHIP_ERROR err = StartNetworkScan(ssid, OnScanWiFiNetworkDone); + CHIP_ERROR err = WifiInterface::GetInstance().StartNetworkScan(ssid, OnScanWiFiNetworkDone); if (err != CHIP_NO_ERROR) { @@ -326,13 +326,13 @@ void SlWiFiDriver::ScanNetworks(ByteSpan ssid, WiFiDriver::ScanCallback * callba CHIP_ERROR GetConnectedNetwork(Network & network) { - WifiCredentials wifiConfig; + WifiInterface::WifiCredentials wifiConfig; network.networkIDLen = 0; network.connected = false; // we are able to fetch the wifi provision data and STA should be connected - VerifyOrReturnError(IsStationConnected(), CHIP_ERROR_NOT_CONNECTED); - ReturnErrorOnFailure(GetWifiCredentials(wifiConfig)); + VerifyOrReturnError(WifiInterface::GetInstance().IsStationConnected(), CHIP_ERROR_NOT_CONNECTED); + ReturnErrorOnFailure(WifiInterface::GetInstance().GetWifiCredentials(wifiConfig)); VerifyOrReturnError(wifiConfig.ssidLength < NetworkCommissioning::kMaxNetworkIDLen, CHIP_ERROR_BUFFER_TOO_SMALL); network.connected = true; diff --git a/src/platform/silabs/PlatformManagerImpl.cpp b/src/platform/silabs/PlatformManagerImpl.cpp index 14026796eb05c4..d8cad6e9b61824 100644 --- a/src/platform/silabs/PlatformManagerImpl.cpp +++ b/src/platform/silabs/PlatformManagerImpl.cpp @@ -31,6 +31,10 @@ #include #include +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION +#include +#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION + #if defined(SL_MBEDTLS_USE_TINYCRYPT) #include "tinycrypt/ecc.h" #endif // SL_MBEDTLS_USE_TINYCRYPT @@ -145,6 +149,7 @@ void HandleWFXSystemEvent(sl_wfx_generic_message_t * eventData) { using namespace chip; using namespace chip::DeviceLayer; + using namespace chip::DeviceLayer::Silabs; ChipDeviceEvent event; memset(&event, 0, sizeof(event)); @@ -156,26 +161,26 @@ void HandleWFXSystemEvent(sl_wfx_generic_message_t * eventData) #if WF200_WIFI case SL_WFX_STARTUP_IND_ID: #endif - case to_underlying(WifiEvent::kStartUp): + case to_underlying(WifiInterface::WifiEvent::kStartUp): memcpy(&event.Platform.WFXSystemEvent.data.startupEvent, eventData, sizeof(event.Platform.WFXSystemEvent.data.startupEvent)); // TODO: This is a workaround until we unify the Matter Data structures - event.Platform.WFXSystemEvent.data.startupEvent.header.id = to_underlying(WifiEvent::kStartUp); + event.Platform.WFXSystemEvent.data.startupEvent.header.id = to_underlying(WifiInterface::WifiEvent::kStartUp); break; - case to_underlying(WifiEvent::kConnect): + case to_underlying(WifiInterface::WifiEvent::kConnect): memcpy(&event.Platform.WFXSystemEvent.data.connectEvent, eventData, sizeof(event.Platform.WFXSystemEvent.data.connectEvent)); break; - case to_underlying(WifiEvent::kDisconnect): + case to_underlying(WifiInterface::WifiEvent::kDisconnect): memcpy(&event.Platform.WFXSystemEvent.data.disconnectEvent, eventData, sizeof(event.Platform.WFXSystemEvent.data.disconnectEvent)); break; - case to_underlying(WifiEvent::kGotIPv4): - case to_underlying(WifiEvent::kLostIP): - case to_underlying(WifiEvent::kGotIPv6): + case to_underlying(WifiInterface::WifiEvent::kGotIPv4): + case to_underlying(WifiInterface::WifiEvent::kLostIP): + case to_underlying(WifiInterface::WifiEvent::kGotIPv6): memcpy(&event.Platform.WFXSystemEvent.data.genericMsgEvent, eventData, sizeof(event.Platform.WFXSystemEvent.data.genericMsgEvent)); break; diff --git a/src/platform/silabs/wifi/BUILD.gn b/src/platform/silabs/wifi/BUILD.gn index ca891e6536ba64..32c21754223fcd 100644 --- a/src/platform/silabs/wifi/BUILD.gn +++ b/src/platform/silabs/wifi/BUILD.gn @@ -132,6 +132,7 @@ source_set("wifi-platform") { if (wifi_soc) { sources += [ "${silabs_platform_dir}/wifi/SiWx/WifiInterfaceImpl.cpp", + "${silabs_platform_dir}/wifi/SiWx/WifiInterfaceImpl.h", "${silabs_platform_dir}/wifi/wiseconnect-interface/WiseconnectWifiInterface.cpp", "${silabs_platform_dir}/wifi/wiseconnect-interface/WiseconnectWifiInterface.h", diff --git a/src/platform/silabs/wifi/SiWx/WifiInterfaceImpl.cpp b/src/platform/silabs/wifi/SiWx/WifiInterfaceImpl.cpp index b4a1f7efb00d70..e9bf54ca32262c 100644 --- a/src/platform/silabs/wifi/SiWx/WifiInterfaceImpl.cpp +++ b/src/platform/silabs/wifi/SiWx/WifiInterfaceImpl.cpp @@ -15,32 +15,17 @@ * limitations under the License. */ -/* - * This file implements the interface to the wifi sdk - */ - -#include -#include -#include - #if (SL_MATTER_GN_BUILD == 0) #include "sl_matter_wifi_config.h" #endif // SL_MATTER_GN_BUILD -#include "FreeRTOS.h" #include "ble_config.h" -#include "event_groups.h" #include "sl_status.h" #include "sl_wifi_device.h" -#include "task.h" #include #include #include -#include -#include -#include -#include -#include +#include extern "C" { #include "sl_si91x_driver.h" @@ -82,14 +67,17 @@ extern "C" { #endif // SLI_SI91X_MCU_INTERFACE #endif // CHIP_CONFIG_ENABLE_ICD_SERVER -// TODO : Temporary work-around for wifi-init failure in 917NCP and 917SOC ACX module boards. +using namespace chip::DeviceLayer::Silabs; + +// TODO : Temporary work-around for wifi-init failure in 917NCP ACX module boards. // Can be removed after Wiseconnect fixes region code for all ACX module boards. -#if (SL_SI91X_ACX_MODULE == 1) || defined(EXP_BOARD) +#if defined(EXP_BOARD) #define REGION_CODE IGNORE_REGION #else #define REGION_CODE US #endif +// TODO: This needs to be refactored so we don't need the global object WfxRsi_t wfx_rsi; namespace { @@ -245,7 +233,7 @@ sl_status_t BackgroundScanCallback(sl_wifi_event_t event, sl_wifi_scan_result_t } // cleanup and return - wfx_rsi.dev_state.Clear(WifiState::kScanStarted); + wfx_rsi.dev_state.Clear(WifiInterface::WifiState::kScanStarted); wfx_rsi.scan_cb(nullptr); wfx_rsi.scan_cb = nullptr; if (wfx_rsi.scan_ssid) @@ -258,7 +246,7 @@ sl_status_t BackgroundScanCallback(sl_wifi_event_t event, sl_wifi_scan_result_t return SL_STATUS_OK; } -sl_status_t sl_wifi_siwx917_init(void) +sl_status_t SiWxPlatformInit(void) { sl_status_t status = SL_STATUS_OK; @@ -312,7 +300,7 @@ sl_status_t sl_wifi_siwx917_init(void) ChipLogError(DeviceLayer, "sl_si91x_trng_program_key failed: 0x%lx", static_cast(status))); #endif // SL_MBEDTLS_USE_TINYCRYPT - wfx_rsi.dev_state.Set(WifiState::kStationInit); + wfx_rsi.dev_state.Set(WifiInterface::WifiState::kStationInit); return status; } @@ -439,146 +427,51 @@ sl_status_t SetWifiConfigurations() return status; } -/** - * @brief Callback function for the SL_WIFI_JOIN_EVENTS group - * - * This callback handler will be invoked when any event within join event group occurs, providing the event details and any - * associated data The callback doesn't get called when we join a network using the sl net APIs - * - * @note In case of failure, the 'result' parameter will be of type sl_status_t, and the 'resultLenght' parameter should be ignored - * - * @param[in] event sl_wifi_event_t that triggered the callback - * @param[in] result Pointer to the response data received - * @param[in] result_length Length of the data received in bytes - * @param[in] arg Optional user provided argument - * - * @return sl_status_t Returns the status of the operation - */ -sl_status_t JoinCallback(sl_wifi_event_t event, char * result, uint32_t resultLenght, void * arg) -{ - sl_status_t status = SL_STATUS_OK; - wfx_rsi.dev_state.Clear(WifiState::kStationConnecting); - if (SL_WIFI_CHECK_IF_EVENT_FAILED(event)) - { - status = *reinterpret_cast(result); - ChipLogError(DeviceLayer, "JoinCallback: failed: 0x%lx", status); - wfx_rsi.dev_state.Clear(WifiState::kStationConnected); - ScheduleConnectionAttempt(); - } - - return status; -} -sl_status_t JoinWifiNetwork(void) -{ - VerifyOrReturnError(!wfx_rsi.dev_state.HasAny(WifiState::kStationConnecting, WifiState::kStationConnected), - SL_STATUS_IN_PROGRESS); - sl_status_t status = SL_STATUS_OK; - - // Start Join Network - wfx_rsi.dev_state.Set(WifiState::kStationConnecting); - - status = SetWifiConfigurations(); - VerifyOrReturnError(status == SL_STATUS_OK, status, ChipLogError(DeviceLayer, "Failure to set the Wifi Configurations!")); - - status = sl_wifi_set_join_callback(JoinCallback, nullptr); - VerifyOrReturnError(status == SL_STATUS_OK, status); - -// To avoid IOP issues, it is recommended to enable high-performance mode before joining the network. -// TODO: Remove this once the IOP issue related to power save mode switching is fixed in the Wi-Fi SDK. -#if CHIP_CONFIG_ENABLE_ICD_SERVER - chip::DeviceLayer::Silabs::WifiSleepManager::GetInstance().RequestHighPerformance(); -#endif // CHIP_CONFIG_ENABLE_ICD_SERVER - - status = sl_net_up(SL_NET_WIFI_CLIENT_INTERFACE, SL_NET_DEFAULT_WIFI_CLIENT_PROFILE_ID); - - if (status == SL_STATUS_OK || status == SL_STATUS_IN_PROGRESS) - { -#if CHIP_CONFIG_ENABLE_ICD_SERVER - // Remove High performance request that might have been added during the connect/retry process - chip::DeviceLayer::Silabs::WifiSleepManager::GetInstance().RemoveHighPerformanceRequest(); -#endif // CHIP_CONFIG_ENABLE_ICD_SERVER - - WifiPlatformEvent event = WifiPlatformEvent::kStationConnect; - PostWifiPlatformEvent(event); - return status; - } - - // failure only happens when the firmware returns an error - ChipLogError(DeviceLayer, "sl_wifi_connect failed: 0x%lx", static_cast(status)); - - wfx_rsi.dev_state.Clear(WifiState::kStationConnecting).Clear(WifiState::kStationConnected); - ScheduleConnectionAttempt(); - - return status; -} - } // namespace -sl_status_t TriggerPlatformWifiDisconnection() -{ - return sl_net_down(SL_NET_WIFI_CLIENT_INTERFACE); -} - -CHIP_ERROR GetAccessPointInfo(wfx_wifi_scan_result_t & info) -{ - // TODO: Convert this to a int8 - int32_t rssi = 0; - info.security = wfx_rsi.credentials.security; - info.chan = wfx_rsi.ap_chan; - - chip::MutableByteSpan output(info.ssid, WFX_MAX_SSID_LENGTH); - chip::ByteSpan ssid(wfx_rsi.credentials.ssid, wfx_rsi.credentials.ssidLength); - chip::CopySpanToMutableSpan(ssid, output); - info.ssid_length = output.size(); - - chip::ByteSpan apMacSpan(wfx_rsi.ap_mac.data(), wfx_rsi.ap_mac.size()); - chip::MutableByteSpan bssidSpan(info.bssid, kWifiMacAddressLength); - chip::CopySpanToMutableSpan(apMacSpan, bssidSpan); +namespace chip { +namespace DeviceLayer { +namespace Silabs { - // TODO: add error processing - sl_wifi_get_signal_strength(SL_WIFI_CLIENT_INTERFACE, &(rssi)); - info.rssi = rssi; +WifiInterfaceImpl WifiInterfaceImpl::mInstance; - return CHIP_NO_ERROR; +WifiInterface & WifiInterface::GetInstance() +{ + return WifiInterfaceImpl::GetInstance(); } -CHIP_ERROR GetAccessPointExtendedInfo(wfx_wifi_scan_ext_t & info) +WiseconnectWifiInterface & WiseconnectWifiInterface::GetInstance() { - sl_wifi_statistics_t test = { 0 }; - - sl_status_t status = sl_wifi_get_statistics(SL_WIFI_CLIENT_INTERFACE, &test); - VerifyOrReturnError(status == SL_STATUS_OK, CHIP_ERROR_INTERNAL); - - info.beacon_lost_count = test.beacon_lost_count - temp_reset.beacon_lost_count; - info.beacon_rx_count = test.beacon_rx_count - temp_reset.beacon_rx_count; - info.mcast_rx_count = test.mcast_rx_count - temp_reset.mcast_rx_count; - info.mcast_tx_count = test.mcast_tx_count - temp_reset.mcast_tx_count; - info.ucast_rx_count = test.ucast_rx_count - temp_reset.ucast_rx_count; - info.ucast_tx_count = test.ucast_tx_count - temp_reset.ucast_tx_count; - info.overrun_count = test.overrun_count - temp_reset.overrun_count; - - return CHIP_NO_ERROR; + return WifiInterfaceImpl::GetInstance(); } -CHIP_ERROR ResetCounters() +void WiseconnectWifiInterface::MatterWifiTask(void * arg) { - sl_wifi_statistics_t test = { 0 }; + (void) arg; + WiseconnectWifiInterface::WifiPlatformEvent event; + sl_status_t status = SL_STATUS_OK; - sl_status_t status = sl_wifi_get_statistics(SL_WIFI_CLIENT_INTERFACE, &test); - VerifyOrReturnError(status == SL_STATUS_OK, CHIP_ERROR_INTERNAL); + status = SiWxPlatformInit(); + VerifyOrReturn(status == SL_STATUS_OK, + ChipLogError(DeviceLayer, "MatterWifiTask: SiWxPlatformInit failed: 0x%lx", static_cast(status))); - temp_reset.beacon_lost_count = test.beacon_lost_count; - temp_reset.beacon_rx_count = test.beacon_rx_count; - temp_reset.mcast_rx_count = test.mcast_rx_count; - temp_reset.mcast_tx_count = test.mcast_tx_count; - temp_reset.ucast_rx_count = test.ucast_rx_count; - temp_reset.ucast_tx_count = test.ucast_tx_count; - temp_reset.overrun_count = test.overrun_count; + WifiInterfaceImpl::GetInstance().NotifyWifiTaskInitialized(); - return CHIP_NO_ERROR; + ChipLogDetail(DeviceLayer, "MatterWifiTask: starting event loop"); + for (;;) + { + if (osMessageQueueGet(sWifiEventQueue, &event, nullptr, osWaitForever) == osOK) + { + WifiInterfaceImpl::GetInstance().ProcessEvent(event); + } + else + { + ChipLogError(DeviceLayer, "MatterWifiTask: get event failed: 0x%lx", static_cast(status)); + } + } } -CHIP_ERROR InitWiFiStack(void) +CHIP_ERROR WifiInterfaceImpl::InitWiFiStack(void) { sl_status_t status = SL_STATUS_OK; @@ -594,7 +487,7 @@ CHIP_ERROR InitWiFiStack(void) VerifyOrReturnError(sScanCompleteSemaphore != nullptr, CHIP_ERROR_NO_MEMORY); // Create the message queue - sWifiEventQueue = osMessageQueueNew(kWfxQueueSize, sizeof(WifiPlatformEvent), nullptr); + sWifiEventQueue = osMessageQueueNew(kWfxQueueSize, sizeof(WiseconnectWifiInterface::WifiPlatformEvent), nullptr); VerifyOrReturnError(sWifiEventQueue != nullptr, CHIP_ERROR_NO_MEMORY); status = CreateDHCPTimer(); @@ -604,76 +497,26 @@ CHIP_ERROR InitWiFiStack(void) return CHIP_NO_ERROR; } -void HandleDHCPPolling(void) +void WifiInterfaceImpl::ProcessEvent(WiseconnectWifiInterface::WifiPlatformEvent event) { - WifiPlatformEvent event; - - // TODO: Notify the application that the interface is not set up or Chipdie here because we are in an unkonwn state - struct netif * sta_netif = &wifi_client_context.netif; - VerifyOrReturn(sta_netif != nullptr, ChipLogError(DeviceLayer, "HandleDHCPPolling: failed to get STA netif")); - -#if (CHIP_DEVICE_CONFIG_ENABLE_IPV4) - uint8_t dhcp_state = dhcpclient_poll(sta_netif); - if (dhcp_state == DHCP_ADDRESS_ASSIGNED && !HasNotifiedIPv4Change()) - { - GotIPv4Address((uint32_t) sta_netif->ip_addr.u_addr.ip4.addr); - event = WifiPlatformEvent::kStationDhcpDone; - PostWifiPlatformEvent(event); - NotifyConnectivity(); - } - else if (dhcp_state == DHCP_OFF) - { - NotifyIPv4Change(false); - } -#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ - /* Checks if the assigned IPv6 address is preferred by evaluating - * the first block of IPv6 address ( block 0) - */ - if ((ip6_addr_ispreferred(netif_ip6_addr_state(sta_netif, 0))) && !HasNotifiedIPv6Change()) - { - char addrStr[chip::Inet::IPAddress::kMaxStringLength] = { 0 }; - VerifyOrReturn(ip6addr_ntoa_r(netif_ip6_addr(sta_netif, 0), addrStr, sizeof(addrStr)) != nullptr); - ChipLogProgress(DeviceLayer, "SLAAC OK: linklocal addr: %s", addrStr); - NotifyIPv6Change(true); - event = WifiPlatformEvent::kStationDhcpDone; - PostWifiPlatformEvent(event); - NotifyConnectivity(); - } -} - -void PostWifiPlatformEvent(WifiPlatformEvent event) -{ - sl_status_t status = osMessageQueuePut(sWifiEventQueue, &event, 0, 0); - - if (status != osOK) - { - ChipLogError(DeviceLayer, "PostWifiPlatformEvent: failed to post event with status: %ld", status); - // TODO: Handle error, requeue event depending on queue size or notify relevant task, - // Chipdie, etc. - } -} - -void ProcessEvent(WifiPlatformEvent event) -{ - // Process event switch (event) { - case WifiPlatformEvent::kStationConnect: + case WiseconnectWifiInterface::WifiPlatformEvent::kStationConnect: ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kStationConnect"); - wfx_rsi.dev_state.Set(WifiState::kStationConnected); + wfx_rsi.dev_state.Set(WifiInterface::WifiState::kStationConnected); ResetDHCPNotificationFlags(); break; - case WifiPlatformEvent::kStationDisconnect: { + case WiseconnectWifiInterface::WifiPlatformEvent::kStationDisconnect: { ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kStationDisconnect"); // TODO: This event is not being posted anywhere, seems to be a dead code or we are missing something - wfx_rsi.dev_state.Clear(WifiState::kStationReady) - .Clear(WifiState::kStationConnecting) - .Clear(WifiState::kStationConnected) - .Clear(WifiState::kStationDhcpDone); + wfx_rsi.dev_state.Clear(WifiInterface::WifiState::kStationReady) + .Clear(WifiInterface::WifiState::kStationConnecting) + .Clear(WifiInterface::WifiState::kStationConnected) + .Clear(WifiInterface::WifiState::kStationDhcpDone); - /* TODO: Implement disconnect notify */ + // TODO: Implement disconnect notify ResetDHCPNotificationFlags(); #if (CHIP_DEVICE_CONFIG_ENABLE_IPV4) NotifyIPv4Change(false); @@ -682,19 +525,19 @@ void ProcessEvent(WifiPlatformEvent event) } break; - case WifiPlatformEvent::kAPStart: + case WiseconnectWifiInterface::WifiPlatformEvent::kAPStart: // TODO: Currently unimplemented break; - case WifiPlatformEvent::kScan: + case WiseconnectWifiInterface::WifiPlatformEvent::kScan: ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kScan"); - if (!(wfx_rsi.dev_state.Has(WifiState::kScanStarted))) + if (!(wfx_rsi.dev_state.Has(WifiInterface::WifiState::kScanStarted))) { ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kScan"); sl_status_t status = SL_STATUS_OK; sl_wifi_scan_configuration_t wifi_scan_configuration = default_wifi_scan_configuration; - if (wfx_rsi.dev_state.Has(WifiState::kStationConnected)) + if (wfx_rsi.dev_state.Has(WifiInterface::WifiState::kStationConnected)) { /* Terminate with end of scan which is no ap sent back */ wifi_scan_configuration.type = SL_WIFI_SCAN_TYPE_ADV_SCAN; @@ -718,7 +561,7 @@ void ProcessEvent(WifiPlatformEvent event) ChipLogError(DeviceLayer, "sl_wifi_set_advanced_scan_configuration failed: 0x%lx", static_cast(status))); sl_wifi_set_scan_callback(BackgroundScanCallback, nullptr); - wfx_rsi.dev_state.Set(WifiState::kScanStarted); + wfx_rsi.dev_state.Set(WifiInterface::WifiState::kScanStarted); // If an ssid was not provided, we need to call the scan API with nullptr to scan all Wi-Fi networks sl_wifi_ssid_t ssid = { 0 }; @@ -745,24 +588,24 @@ void ProcessEvent(WifiPlatformEvent event) } break; - case WifiPlatformEvent::kStationStartJoin: + case WiseconnectWifiInterface::WifiPlatformEvent::kStationStartJoin: ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kStationStartJoin"); InitiateScan(); JoinWifiNetwork(); break; - case WifiPlatformEvent::kStationDoDhcp: + case WiseconnectWifiInterface::WifiPlatformEvent::kStationDoDhcp: ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kStationDoDhcp"); - StartDHCPTimer(WFX_RSI_DHCP_POLL_INTERVAL); + StartDHCPTimer(kDhcpPollIntervalMs); break; - case WifiPlatformEvent::kStationDhcpDone: + case WiseconnectWifiInterface::WifiPlatformEvent::kStationDhcpDone: ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kStationDhcpDone"); CancelDHCPTimer(); break; - case WifiPlatformEvent::kStationDhcpPoll: + case WiseconnectWifiInterface::WifiPlatformEvent::kStationDhcpPoll: ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kStationDhcpPoll"); HandleDHCPPolling(); break; @@ -772,46 +615,183 @@ void ProcessEvent(WifiPlatformEvent event) } } -/********************************************************************************* - * @fn void MatterWifiTask(void *arg) - * @brief - * The main WLAN task - started by StartWifiTask() that interfaces with RSI. - * The rest of RSI stuff come in call-backs. - * The initialization has been already done. - * @param[in] arg: - * @return - * None - **********************************************************************************/ -/* ARGSUSED */ -void MatterWifiTask(void * arg) +void WifiInterfaceImpl::HandleDHCPPolling(void) { - (void) arg; - WifiPlatformEvent event; + WiseconnectWifiInterface::WifiPlatformEvent event; + + // TODO: Notify the application that the interface is not set up or Chipdie here because we are in an unkonwn state + struct netif * sta_netif = &wifi_client_context.netif; + VerifyOrReturn(sta_netif != nullptr, ChipLogError(DeviceLayer, "HandleDHCPPolling: failed to get STA netif")); + +#if (CHIP_DEVICE_CONFIG_ENABLE_IPV4) + uint8_t dhcp_state = dhcpclient_poll(sta_netif); + if (dhcp_state == DHCP_ADDRESS_ASSIGNED && !mHasNotifiedIPv4) + { + GotIPv4Address((uint32_t) sta_netif->ip_addr.u_addr.ip4.addr); + event = WiseconnectWifiInterface::WifiPlatformEvent::kStationDhcpDone; + WiseconnectWifiInterface::PostWifiPlatformEvent(event); + NotifyConnectivity(); + } + else if (dhcp_state == DHCP_OFF) + { + NotifyIPv4Change(false); + } +#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ + /* Checks if the assigned IPv6 address is preferred by evaluating + * the first block of IPv6 address ( block 0) + */ + if ((ip6_addr_ispreferred(netif_ip6_addr_state(sta_netif, 0))) && !mHasNotifiedIPv6) + { + char addrStr[chip::Inet::IPAddress::kMaxStringLength] = { 0 }; + VerifyOrReturn(ip6addr_ntoa_r(netif_ip6_addr(sta_netif, 0), addrStr, sizeof(addrStr)) != nullptr); + ChipLogProgress(DeviceLayer, "SLAAC OK: linklocal addr: %s", addrStr); + NotifyIPv6Change(true); + event = WiseconnectWifiInterface::WifiPlatformEvent::kStationDhcpDone; + PostWifiPlatformEvent(event); + NotifyConnectivity(); + } +} + +sl_status_t WifiInterfaceImpl::JoinWifiNetwork(void) +{ + VerifyOrReturnError( + !wfx_rsi.dev_state.HasAny(WifiInterface::WifiState::kStationConnecting, WifiInterface::WifiState::kStationConnected), + SL_STATUS_IN_PROGRESS); sl_status_t status = SL_STATUS_OK; - status = sl_wifi_siwx917_init(); - VerifyOrReturn(status == SL_STATUS_OK, - ChipLogError(DeviceLayer, "MatterWifiTask: sl_wifi_siwx917_init failed: 0x%lx", static_cast(status))); + // Start Join Network + wfx_rsi.dev_state.Set(WifiInterface::WifiState::kStationConnecting); - NotifyWifiTaskInitialized(); + status = SetWifiConfigurations(); + VerifyOrReturnError(status == SL_STATUS_OK, status, ChipLogError(DeviceLayer, "Failure to set the Wifi Configurations!")); - ChipLogDetail(DeviceLayer, "MatterWifiTask: starting event loop"); - for (;;) + status = sl_wifi_set_join_callback(JoinCallback, nullptr); + VerifyOrReturnError(status == SL_STATUS_OK, status); + +// To avoid IOP issues, it is recommended to enable high-performance mode before joining the network. +// TODO: Remove this once the IOP issue related to power save mode switching is fixed in the Wi-Fi SDK. +#if CHIP_CONFIG_ENABLE_ICD_SERVER + chip::DeviceLayer::Silabs::WifiSleepManager::GetInstance().RequestHighPerformance(); +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER + + status = sl_net_up(SL_NET_WIFI_CLIENT_INTERFACE, SL_NET_DEFAULT_WIFI_CLIENT_PROFILE_ID); + + if (status == SL_STATUS_OK || status == SL_STATUS_IN_PROGRESS) { - if (osMessageQueueGet(sWifiEventQueue, &event, nullptr, osWaitForever) == osOK) - { - ProcessEvent(event); - } - else - { - ChipLogError(DeviceLayer, "MatterWifiTask: get event failed: 0x%lx", static_cast(status)); - } +#if CHIP_CONFIG_ENABLE_ICD_SERVER + // Remove High performance request that might have been added during the connect/retry process + chip::DeviceLayer::Silabs::WifiSleepManager::GetInstance().RemoveHighPerformanceRequest(); +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER + + WiseconnectWifiInterface::WifiPlatformEvent event = WiseconnectWifiInterface::WifiPlatformEvent::kStationConnect; + PostWifiPlatformEvent(event); + return status; + } + + // failure only happens when the firmware returns an error + ChipLogError(DeviceLayer, "sl_wifi_connect failed: 0x%lx", static_cast(status)); + + wfx_rsi.dev_state.Clear(WifiInterface::WifiState::kStationConnecting).Clear(WifiInterface::WifiState::kStationConnected); + ScheduleConnectionAttempt(); + + return status; +} + +sl_status_t WifiInterfaceImpl::JoinCallback(sl_wifi_event_t event, char * result, uint32_t resultLenght, void * arg) +{ + sl_status_t status = SL_STATUS_OK; + wfx_rsi.dev_state.Clear(WifiInterface::WifiState::kStationConnecting); + if (SL_WIFI_CHECK_IF_EVENT_FAILED(event)) + { + status = *reinterpret_cast(result); + ChipLogError(DeviceLayer, "JoinCallback: failed: 0x%lx", status); + wfx_rsi.dev_state.Clear(WifiInterface::WifiState::kStationConnected); + + mInstance.ScheduleConnectionAttempt(); } + + return status; +} + +CHIP_ERROR WifiInterfaceImpl::GetAccessPointInfo(wfx_wifi_scan_result_t & info) +{ + // TODO: Convert this to a int8 + int32_t rssi = 0; + info.security = wfx_rsi.credentials.security; + info.chan = wfx_rsi.ap_chan; + + chip::MutableByteSpan output(info.ssid, WFX_MAX_SSID_LENGTH); + chip::ByteSpan ssid(wfx_rsi.credentials.ssid, wfx_rsi.credentials.ssidLength); + chip::CopySpanToMutableSpan(ssid, output); + info.ssid_length = output.size(); + + chip::ByteSpan apMacSpan(wfx_rsi.ap_mac.data(), wfx_rsi.ap_mac.size()); + chip::MutableByteSpan bssidSpan(info.bssid, kWifiMacAddressLength); + chip::CopySpanToMutableSpan(apMacSpan, bssidSpan); + + // TODO: add error processing + sl_wifi_get_signal_strength(SL_WIFI_CLIENT_INTERFACE, &(rssi)); + info.rssi = rssi; + + return CHIP_NO_ERROR; +} + +CHIP_ERROR WifiInterfaceImpl::GetAccessPointExtendedInfo(wfx_wifi_scan_ext_t & info) +{ + sl_wifi_statistics_t test = { 0 }; + + sl_status_t status = sl_wifi_get_statistics(SL_WIFI_CLIENT_INTERFACE, &test); + VerifyOrReturnError(status == SL_STATUS_OK, CHIP_ERROR_INTERNAL); + + info.beacon_lost_count = test.beacon_lost_count - temp_reset.beacon_lost_count; + info.beacon_rx_count = test.beacon_rx_count - temp_reset.beacon_rx_count; + info.mcast_rx_count = test.mcast_rx_count - temp_reset.mcast_rx_count; + info.mcast_tx_count = test.mcast_tx_count - temp_reset.mcast_tx_count; + info.ucast_rx_count = test.ucast_rx_count - temp_reset.ucast_rx_count; + info.ucast_tx_count = test.ucast_tx_count - temp_reset.ucast_tx_count; + info.overrun_count = test.overrun_count - temp_reset.overrun_count; + + return CHIP_NO_ERROR; +} + +CHIP_ERROR WifiInterfaceImpl::ResetCounters() +{ + sl_wifi_statistics_t test = { 0 }; + + sl_status_t status = sl_wifi_get_statistics(SL_WIFI_CLIENT_INTERFACE, &test); + VerifyOrReturnError(status == SL_STATUS_OK, CHIP_ERROR_INTERNAL); + + temp_reset.beacon_lost_count = test.beacon_lost_count; + temp_reset.beacon_rx_count = test.beacon_rx_count; + temp_reset.mcast_rx_count = test.mcast_rx_count; + temp_reset.mcast_tx_count = test.mcast_tx_count; + temp_reset.ucast_rx_count = test.ucast_rx_count; + temp_reset.ucast_tx_count = test.ucast_tx_count; + temp_reset.overrun_count = test.overrun_count; + + return CHIP_NO_ERROR; +} + +void WifiInterfaceImpl::PostWifiPlatformEvent(WiseconnectWifiInterface::WifiPlatformEvent event) +{ + sl_status_t status = osMessageQueuePut(sWifiEventQueue, &event, 0, 0); + + if (status != osOK) + { + ChipLogError(DeviceLayer, "PostWifiPlatformEvent: failed to post event with status: %ld", status); + // TODO: Handle error, requeue event depending on queue size or notify relevant task, + // Chipdie, etc. + } +} + +sl_status_t WifiInterfaceImpl::TriggerPlatformWifiDisconnection() +{ + return sl_net_down(SL_NET_WIFI_CLIENT_INTERFACE); } #if CHIP_CONFIG_ENABLE_ICD_SERVER -CHIP_ERROR ConfigurePowerSave(rsi_power_save_profile_mode_t sl_si91x_ble_state, sl_si91x_performance_profile_t sl_si91x_wifi_state, - uint32_t listenInterval) +CHIP_ERROR WifiInterfaceImpl::ConfigurePowerSave(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, RSI_MAX_PSP); VerifyOrReturnError(error == RSI_SUCCESS, CHIP_ERROR_INTERNAL, @@ -830,7 +810,7 @@ CHIP_ERROR ConfigurePowerSave(rsi_power_save_profile_mode_t sl_si91x_ble_state, return CHIP_NO_ERROR; } -CHIP_ERROR ConfigureBroadcastFilter(bool enableBroadcastFilter) +CHIP_ERROR WifiInterfaceImpl::ConfigureBroadcastFilter(bool enableBroadcastFilter) { sl_status_t status = SL_STATUS_OK; @@ -844,3 +824,7 @@ CHIP_ERROR ConfigureBroadcastFilter(bool enableBroadcastFilter) return CHIP_NO_ERROR; } #endif // CHIP_CONFIG_ENABLE_ICD_SERVER + +} // namespace Silabs +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/silabs/wifi/SiWx/WifiInterfaceImpl.h b/src/platform/silabs/wifi/SiWx/WifiInterfaceImpl.h new file mode 100644 index 00000000000000..54bac8c23949a7 --- /dev/null +++ b/src/platform/silabs/wifi/SiWx/WifiInterfaceImpl.h @@ -0,0 +1,110 @@ +/* + * + * Copyright (c) 2025 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include + +namespace chip { +namespace DeviceLayer { +namespace Silabs { + +/** + * @brief WifiInterface implementation for the SiWx platform + * + */ +class WifiInterfaceImpl final : public WiseconnectWifiInterface +{ +public: + static WifiInterfaceImpl & GetInstance() { return mInstance; } + + WifiInterfaceImpl(const WifiInterfaceImpl &) = delete; + WifiInterfaceImpl & operator=(const WifiInterfaceImpl &) = delete; + + /* + * WifiInterface impl + */ + + CHIP_ERROR InitWiFiStack(void) override; + CHIP_ERROR GetAccessPointInfo(wfx_wifi_scan_result_t & info) override; + CHIP_ERROR GetAccessPointExtendedInfo(wfx_wifi_scan_ext_t & info) override; + CHIP_ERROR ResetCounters() override; +#if CHIP_CONFIG_ENABLE_ICD_SERVER + CHIP_ERROR ConfigureBroadcastFilter(bool enableBroadcastFilter) override; + CHIP_ERROR ConfigurePowerSave(rsi_power_save_profile_mode_t sl_si91x_ble_state, + sl_si91x_performance_profile_t sl_si91x_wifi_state, uint32_t listenInterval) override; +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER + + /** + * @brief Processes the wifi platform events for the SiWx platform + * + * TODO: Current inheritance structure with the task creation in the parent forces this function to be public when it shouldn't + * be. This isn't the best practice and we should try to move this to protected. + * + * @param event + */ + void ProcessEvent(WiseconnectWifiInterface::WifiPlatformEvent event); + +protected: + /* + * WiseconnectWifiInterface impl + */ + + sl_status_t TriggerPlatformWifiDisconnection() override; + void PostWifiPlatformEvent(WifiPlatformEvent event) override; + +private: + WifiInterfaceImpl() = default; + ~WifiInterfaceImpl() = default; + + /** + * @brief Callback function for the SL_WIFI_JOIN_EVENTS group + * + * This callback handler will be invoked when any event within join event group occurs, providing the event details and any + * associated data The callback doesn't get called when we join a network using the sl net APIs + * + * @note In case of failure, the 'result' parameter will be of type sl_status_t, and the 'resultLenght' parameter should be + * ignored + * + * @param[in] event sl_wifi_event_t that triggered the callback + * @param[in] result Pointer to the response data received + * @param[in] result_length Length of the data received in bytes + * @param[in] arg Optional user provided argument + * + * @return sl_status_t Returns the status of the operation + */ + static sl_status_t JoinCallback(sl_wifi_event_t event, char * result, uint32_t resultLenght, void * arg); + + /** + * @brief Triggers a synchronous connection attempt to the stored Wifi crendetials + * + * @return sl_status_t SL_STATUS_IN_PROGRESS, if the device is already connected or connecting. + * SL_STATUS_OK, on connection success. + * other error on failure, otherwise + */ + sl_status_t JoinWifiNetwork(); + + /** + * @brief Processing function responsible of executing the DHCP polling operation until we have an IPv6 or IPv4 address + * + */ + void HandleDHCPPolling(); + + static WifiInterfaceImpl mInstance; +}; + +} // namespace Silabs +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/silabs/wifi/SiWx/ncp/rs9117.gni b/src/platform/silabs/wifi/SiWx/ncp/rs9117.gni index 4d19d50b161634..6149173a42a402 100644 --- a/src/platform/silabs/wifi/SiWx/ncp/rs9117.gni +++ b/src/platform/silabs/wifi/SiWx/ncp/rs9117.gni @@ -18,6 +18,7 @@ import("${silabs_sdk_build_root}/efr32_sdk.gni") rs911x_src_plat = [ "${chip_root}/src/platform/silabs/wifi/SiWx/WifiInterfaceImpl.cpp", + "${chip_root}/src/platform/silabs/wifi/SiWx/WifiInterfaceImpl.h", "${chip_root}/src/platform/silabs/wifi/SiWx/ncp/sl_si91x_ncp_utility.c", "${chip_root}/src/platform/silabs/wifi/SiWx/ncp/sl_board_configuration.h", "${chip_root}/src/platform/silabs/wifi/wiseconnect-interface/WiseconnectWifiInterface.cpp", diff --git a/src/platform/silabs/wifi/WifiInterface.cpp b/src/platform/silabs/wifi/WifiInterface.cpp index 14cacad8e576fe..119d6e16d897f1 100644 --- a/src/platform/silabs/wifi/WifiInterface.cpp +++ b/src/platform/silabs/wifi/WifiInterface.cpp @@ -15,7 +15,6 @@ * limitations under the License. */ -#include "silabs_utils.h" #include #include #include @@ -29,8 +28,6 @@ using namespace chip; using namespace chip::DeviceLayer; -#define CONVERT_SEC_TO_MS(TimeInS) (TimeInS * 1000) - // TODO: We shouldn't need to have access to a global variable in the interface here extern WfxRsi_t wfx_rsi; @@ -43,20 +40,17 @@ namespace { constexpr uint8_t kWlanMinRetryIntervalsInSec = 1; constexpr uint8_t kWlanMaxRetryIntervalsInSec = 60; uint8_t retryInterval = kWlanMinRetryIntervalsInSec; -osTimerId_t sRetryTimer; - -bool hasNotifiedIPV6 = false; -#if (CHIP_DEVICE_CONFIG_ENABLE_IPV4) -bool hasNotifiedIPV4 = false; -#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ -/* - * Notifications to the upper-layer - * All done in the context of the RSI/WiFi task (rsi_if.c) +/** + * @brief Retry timer callback that triggers a reconnection attempt + * + * TODO: The structure of the retry needs to be redone + * + * @param arg */ void RetryConnectionTimerHandler(void * arg) { - if (ConnectToAccessPoint() != CHIP_NO_ERROR) + if (chip::DeviceLayer::Silabs::WifiInterface::GetInstance().ConnectToAccessPoint() != CHIP_NO_ERROR) { ChipLogError(DeviceLayer, "ConnectToAccessPoint() failed."); } @@ -64,9 +58,13 @@ void RetryConnectionTimerHandler(void * arg) } // namespace -void NotifyIPv6Change(bool gotIPv6Addr) +namespace chip { +namespace DeviceLayer { +namespace Silabs { + +void WifiInterface::NotifyIPv6Change(bool gotIPv6Addr) { - hasNotifiedIPV6 = gotIPv6Addr; + mHasNotifiedIPv6 = gotIPv6Addr; sl_wfx_generic_message_t eventData = {}; eventData.header.id = gotIPv6Addr ? to_underlying(WifiEvent::kGotIPv6) : to_underlying(WifiEvent::kLostIP); @@ -74,10 +72,11 @@ void NotifyIPv6Change(bool gotIPv6Addr) HandleWFXSystemEvent(&eventData); } + #if (CHIP_DEVICE_CONFIG_ENABLE_IPV4) -void NotifyIPv4Change(bool gotIPv4Addr) +void WifiInterface::NotifyIPv4Change(bool gotIPv4Addr) { - hasNotifiedIPV4 = gotIPv4Addr; + mHasNotifiedIPv4 = gotIPv4Addr; sl_wfx_generic_message_t eventData; @@ -88,7 +87,7 @@ void NotifyIPv4Change(bool gotIPv4Addr) } #endif // CHIP_DEVICE_CONFIG_ENABLE_IPV4 -void NotifyDisconnection(WifiDisconnectionReasons reason) +void WifiInterface::NotifyDisconnection(WifiDisconnectionReasons reason) { sl_wfx_disconnect_ind_t evt = {}; evt.header.id = to_underlying(WifiEvent::kDisconnect); @@ -98,7 +97,7 @@ void NotifyDisconnection(WifiDisconnectionReasons reason) HandleWFXSystemEvent((sl_wfx_generic_message_t *) &evt); } -void NotifyConnection(const MacAddress & ap) +void WifiInterface::NotifyConnection(const MacAddress & ap) { sl_wfx_connect_ind_t evt = {}; evt.header.id = to_underlying(WifiEvent::kConnect); @@ -111,34 +110,22 @@ void NotifyConnection(const MacAddress & ap) HandleWFXSystemEvent((sl_wfx_generic_message_t *) &evt); } -bool HasNotifiedIPv6Change() -{ - return hasNotifiedIPV6; -} - -#if (CHIP_DEVICE_CONFIG_ENABLE_IPV4) -bool HasNotifiedIPv4Change() +void WifiInterface::ResetIPNotificationStates() { - return hasNotifiedIPV4; -} -#endif // CHIP_DEVICE_CONFIG_ENABLE_IPV4 - -void ResetIPNotificationStates() -{ - hasNotifiedIPV6 = false; + mHasNotifiedIPv6 = false; #if (CHIP_DEVICE_CONFIG_ENABLE_IPV4) - hasNotifiedIPV4 = false; + mHasNotifiedIPv4 = false; #endif // CHIP_DEVICE_CONFIG_ENABLE_IPV4 } -void NotifyWifiTaskInitialized(void) +void WifiInterface::NotifyWifiTaskInitialized(void) { - sl_wfx_startup_ind_t evt = {}; + sl_wfx_startup_ind_t evt = { 0 }; // TODO: We should move this to the init function and not the notification function // Creating a timer which will be used to retry connection with AP - sRetryTimer = osTimerNew(RetryConnectionTimerHandler, osTimerOnce, NULL, NULL); - VerifyOrReturn(sRetryTimer != NULL); + mRetryTimer = osTimerNew(RetryConnectionTimerHandler, osTimerOnce, NULL, NULL); + VerifyOrReturn(mRetryTimer != NULL); evt.header.id = to_underlying(WifiEvent::kStartUp); evt.header.length = sizeof evt; @@ -158,13 +145,14 @@ void NotifyWifiTaskInitialized(void) } // TODO: The retry stategy needs to be re-worked -void ScheduleConnectionAttempt() +void WifiInterface::ScheduleConnectionAttempt() { if (retryInterval > kWlanMaxRetryIntervalsInSec) { retryInterval = kWlanMaxRetryIntervalsInSec; } - if (osTimerStart(sRetryTimer, pdMS_TO_TICKS(CONVERT_SEC_TO_MS(retryInterval))) != osOK) + + if (osTimerStart(mRetryTimer, pdMS_TO_TICKS(retryInterval * 1000)) != osOK) { ChipLogProgress(DeviceLayer, "Failed to start retry timer"); // Sending the join command if retry timer failed to start @@ -187,3 +175,7 @@ void ScheduleConnectionAttempt() ChipLogProgress(DeviceLayer, "ScheduleConnectionAttempt : Next attempt after %d Seconds", retryInterval); retryInterval += retryInterval; } + +} // namespace Silabs +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/silabs/wifi/WifiInterface.h b/src/platform/silabs/wifi/WifiInterface.h index aff1baf4eb599c..429e21e8ddcd27 100644 --- a/src/platform/silabs/wifi/WifiInterface.h +++ b/src/platform/silabs/wifi/WifiInterface.h @@ -23,9 +23,7 @@ #include #include #include - -#include "sl_status.h" -#include +#include #if (SLI_SI91X_MCU_INTERFACE | EXP_BOARD) #include "rsi_common_apis.h" @@ -53,47 +51,6 @@ constexpr size_t kWifiMacAddressLength = 6; #define WFX_MAX_SSID_LENGTH (32) #define MAX_JOIN_RETRIES_COUNT (5) -/* Updated types */ - -using MacAddress = std::array; - -enum class WifiEvent : uint8_t -{ - kStartUp = 0, - kConnect = 1, - kDisconnect = 2, - kScanComplete = 3, - kGotIPv4 = 4, - kGotIPv6 = 5, - kLostIP = 6, -}; - -enum class WifiState : uint16_t -{ - kStationInit = (1 << 0), - kAPReady = (1 << 1), - kStationProvisioned = (1 << 2), - kStationConnecting = (1 << 3), - kStationConnected = (1 << 4), - kStationDhcpDone = (1 << 6), /* Requested to do DHCP after conn */ - kStationMode = (1 << 7), /* Enable Station Mode */ - kAPMode = (1 << 8), /* Enable AP Mode */ - kStationReady = (kStationConnected | kStationDhcpDone), - kStationStarted = (1 << 9), - kScanStarted = (1 << 10), /* Scan Started */ -}; - -enum class WifiDisconnectionReasons : uint16_t // using uint16 to match current structure during the transition -{ - kUnknownError = 1, // Disconnation due to an internal error - kAccessPointLost = 2, // Device did not receive AP beacon too many times - kAccessPoint = 3, // AP disconnected the device - kApplication = 4, // Application requested disconnection - kWPACouterMeasures = 5, // WPA contermeasures triggered a disconnection -}; - -/* Enums to update */ - /* Note that these are same as RSI_security */ typedef enum { @@ -140,347 +97,400 @@ typedef enum } sl_wfx_interface_t; #endif -// TODO: Figure out if we need this structure. We have different strcutures for the same use -struct WifiCredentials -{ - uint8_t ssid[WFX_MAX_SSID_LENGTH] = { 0 }; - size_t ssidLength = 0; - uint8_t passkey[WFX_MAX_PASSKEY_LENGTH] = { 0 }; - size_t passkeyLength = 0; - wfx_sec_t security = WFX_SEC_UNSPECIFIED; - - WifiCredentials & operator=(const WifiCredentials & other) - { - if (this != &other) - { - memcpy(ssid, other.ssid, WFX_MAX_SSID_LENGTH); - ssidLength = other.ssidLength; - memcpy(passkey, other.passkey, WFX_MAX_PASSKEY_LENGTH); - passkeyLength = other.passkeyLength; - security = other.security; - } - return *this; - } - - void Clear() - { - memset(ssid, 0, WFX_MAX_SSID_LENGTH); - ssidLength = 0; - memset(passkey, 0, WFX_MAX_PASSKEY_LENGTH); - passkeyLength = 0; - security = WFX_SEC_UNSPECIFIED; - } -}; - -typedef struct wfx_rsi_s -{ - chip::BitFlags dev_state; - uint16_t ap_chan; /* The chan our STA is using */ - WifiCredentials credentials; - ScanCallback scan_cb; - uint8_t * scan_ssid; /* Which one are we scanning for */ - size_t scan_ssid_length; -#ifdef SL_WFX_CONFIG_SOFTAP - MacAddress softap_mac; -#endif - MacAddress sta_mac; - MacAddress ap_mac; /* To which our STA is connected */ - MacAddress ap_bssid; /* To which our STA is connected */ - uint8_t ip4_addr[4]; /* Not sure if this is enough */ -} WfxRsi_t; - -/* Updated functions */ - -/** - * @brief Function initalizes the WiFi module before starting WiFi task. - * - * @return CHIP_ERROR CHIP_NO_ERROR, if the initialization succeeded - * CHIP_ERROR_INTERNAL, if sequence failed due to internal API error - * CHIP_ERROR_NO_MEMORY, if sequence failed due to unavaliablility of memory - */ - -CHIP_ERROR InitWiFiStack(void); - -/** - * @brief Function notifies the PlatformManager that an IPv6 event occured on the WiFi interface. - * - * @param gotIPv6Addr true, got an IPv6 address - * false, lost or wasn't able to get an IPv6 address - */ -void NotifyIPv6Change(bool gotIPv6Addr); - -#if CHIP_DEVICE_CONFIG_ENABLE_IPV4 -/** - * @brief Function notifies the PlatformManager that an IPv4 event occured on the WiFi interface. - * - * @param gotIPv4Addr true, got an IPv4 address - * false, lost or wasn't able to get an IPv4 address - */ -void NotifyIPv4Change(bool gotIPv4Addr); -#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ - -/** - * @brief Function notifies the PlatformManager that a disconnection event occurred - * - * @param reason reason for the disconnection - */ -void NotifyDisconnection(WifiDisconnectionReasons reason); - -/** - * @brief Function notifies the PlatformManager that a connection event occurred - * - * @param[in] ap pointer to the structure that contains the MAC address of the AP - */ -void NotifyConnection(const MacAddress & ap); - -/** - * @brief Returns the IPv6 notification state - * - * @note This function is necessary because the class inheritance structure has not been done as of yet. - * Once the inheritance is done, sub-classes will have access to the member directly wihtout needing to use an extra guetter. - * - * @return true, IPv6 change has been notified - false, otherwise - */ -bool HasNotifiedIPv6Change(); - -/** - * @brief Returns the IPv4 notification state - * - * @note This function is necessary because the class inheritance structure has not been done as of yet. - * Once the inheritance is done, sub-classes will have access to the member directly wihtout needing to use an extra guetter. - * - * @return true, IPv4 change has been notified - false, otherwise - */ -bool HasNotifiedIPv4Change(); - -/** - * @brief Function resets the IP notification states - * - * * @note This function is necessary because the class inheritance structure has not been done as of yet. - * Once the inheritance is done, sub-classes will have access to the member directly wihtout needing to use an extra guetter. - */ -void ResetIPNotificationStates(); - -/** - * @brief Returns the provide interfaces MAC address - * Valid buffer large enough for the MAC address must be provided to the function - * - * @param[in] interface SL_WFX_STA_INTERFACE or SL_WFX_SOFTAP_INTERFACE. - * If soft AP is not enabled, the interface is ignored and the function always returns the Station MAC - * address - * @param[out] addr Interface MAC addres - * - * @return CHIP_ERROR CHIP_NO_ERROR on success - * CHIP_ERROR_BUFFER_TOO_SMALL if the provided ByteSpan size is too small - * - */ -CHIP_ERROR GetMacAddress(sl_wfx_interface_t interface, chip::MutableByteSpan & addr); - -/** - * @brief Triggers a network scan - * The function is asynchronous and the result is provided via the callback. - * - * @param ssid The SSID to scan for. If empty, all networks are scanned - * @param callback The callback to be called when the scan is complete. Cannot be nullptr. - * The callback is called asynchrounously. - * - * @return CHIP_ERROR CHIP_NO_ERROR if the network scan was successfully started - * CHIP_INVALID_ARGUMENT if the callback is nullptr - * CHIP_ERROR_IN_PROGRESS, if there is already a network scan in progress - * CHIP_ERROR_INVALID_STRING_LENGTH, if there SSID length exceeds handled limit - * other, if there is a platform error when starting the scan - */ -CHIP_ERROR StartNetworkScan(chip::ByteSpan ssid, ScanCallback callback); +/* Updated section */ -/** - * @brief Creates and starts the WiFi task that processes Wifi events and operations - * - * @return CHIP_ERROR CHIP_NO_ERROR if the task was successfully started and initialized - * CHIP_ERROR_NO_MEMORY if the task failed to be created - * CHIP_ERROR_INTERNAL if software or hardware initialization failed - */ -CHIP_ERROR StartWifiTask(); +namespace chip { +namespace DeviceLayer { +namespace Silabs { /** - * @brief Configures the Wi-Fi devices as a Wi-Fi station - */ -void ConfigureStationMode(); - -/** - * @brief Returns the state of the Wi-Fi connection + * @brief Public Interface for the Wi-Fi platform APIs * - * @return true, if the Wi-Fi device is connected to an AP - * false, otherwise */ -bool IsStationConnected(); - -/** - * @brief Returns the state of the Wi-Fi Station configuration of the Wi-Fi device - * - * @return true, if the Wi-Fi Station mode is enabled - * false, otherwise - */ -bool IsStationModeEnabled(); - -/** - * @brief Returns the state of the Wi-Fi station initialization - * - * @return true, if the initialization was successful - * false, otherwise - */ -bool IsStationReady(); - -/** - * @brief Triggers the device to disconnect from the connected Wi-Fi network - * - * @note The disconnection is not immediate. It can take a certain amount of time for the device to be in a disconnected state once - * the function is called. When the function returns, the device might not have yet disconnected from the Wi-Fi network. - * - * @return CHIP_ERROR CHIP_NO_ERROR, disconnection request was succesfully triggered - * otherwise, CHIP_ERROR_INTERNAL - */ -CHIP_ERROR TriggerDisconnection(); - -/** - * @brief Gets the connected access point information. - * See @wfx_wifi_scan_result_t for the information that is returned by the function. - * - * @param[out] info AP information - * - * @return CHIP_ERROR CHIP_NO_ERROR, device has succesfully pulled all the AP information - * CHIP_ERROR_INTERNAL, otherwise. If the function returns an error, the data in ap cannot be used. - */ -CHIP_ERROR GetAccessPointInfo(wfx_wifi_scan_result_t & info); - -/** - * @brief Gets the connected access point extended information. - * See @wfx_wifi_scan_ext_t for the information that is returned by the information - * - * @param[out] info AP extended information - * - * @return CHIP_ERROR CHIP_NO_ERROR, device has succesfully pulled all the AP information - * CHIP_ERROR_INTERNAL, otherwise. If the function returns an error, the data in ap cannot be used. - */ -CHIP_ERROR GetAccessPointExtendedInfo(wfx_wifi_scan_ext_t & info); - -/** - * @brief Function resets the BeaconLostCount, BeaconRxCount, PacketMulticastRxCount, PacketMulticastTxCount, PacketUnicastRxCount, - * PacketUnicastTxCount back to 0 - * - * @return CHIP_ERROR CHIP_NO_ERROR, the counters were succesfully reset to 0. - * CHIP_ERROR_INTERNAL, if there was an error when resetting the counter values - */ -CHIP_ERROR ResetCounters(); - -/** - * @brief Configures the broadcast filter. - * - * @param[in] enableBroadcastFilter Boolean to enable or disable the broadcast filter. - * - * @return CHIP_ERROR CHIP_NO_ERROR, the counters were succesfully reset to 0. - * CHIP_ERROR_INTERNAL, if there was an error when configuring the broadcast filter - */ -CHIP_ERROR ConfigureBroadcastFilter(bool enableBroadcastFilter); - -/** - * @brief Clears the stored Wi-Fi crendetials stored in RAM only - */ -void ClearWifiCredentials(); +class WifiInterface +{ +public: + enum class WifiEvent : uint8_t + { + kStartUp = 0, + kConnect = 1, + kDisconnect = 2, + kScanComplete = 3, + kGotIPv4 = 4, + kGotIPv6 = 5, + kLostIP = 6, + }; + + enum class WifiState : uint16_t + { + kStationInit = (1 << 0), + kAPReady = (1 << 1), + kStationProvisioned = (1 << 2), + kStationConnecting = (1 << 3), + kStationConnected = (1 << 4), + kStationDhcpDone = (1 << 6), /* Requested to do DHCP after conn */ + kStationMode = (1 << 7), /* Enable Station Mode */ + kAPMode = (1 << 8), /* Enable AP Mode */ + kStationReady = (kStationConnected | kStationDhcpDone), + kStationStarted = (1 << 9), + kScanStarted = (1 << 10), /* Scan Started */ + }; + + enum class WifiDisconnectionReasons : uint16_t // using uint16 to match current structure during the transition + { + kUnknownError = 1, // Disconnation due to an internal error + kAccessPointLost = 2, // Device did not receive AP beacon too many times + kAccessPoint = 3, // AP disconnected the device + kApplication = 4, // Application requested disconnection + kWPACouterMeasures = 5, // WPA contermeasures triggered a disconnection + }; + + // TODO: Figure out if we need this structure. We have different strcutures for the same use + struct WifiCredentials + { + WifiCredentials() { Clear(); } -/** - * @brief Stores the Wi-Fi credentials - * - * @note Function does not validate if the device already has Wi-Fi credentials. - * It is the responsibility of the caller to ensuret that. - * The function will overwrite any existing Wi-Fi credentials. - * - * @param[in] credentials - */ -void SetWifiCredentials(const WifiCredentials & credentials); + uint8_t ssid[WFX_MAX_SSID_LENGTH] = { 0 }; + size_t ssidLength = 0; + uint8_t passkey[WFX_MAX_PASSKEY_LENGTH] = { 0 }; + size_t passkeyLength = 0; + wfx_sec_t security = WFX_SEC_UNSPECIFIED; -/** - * @brief Returns the configured Wi-Fi credentials - * - * @param[out] credentials stored wifi crendetials - * - * @return CHIP_ERROR CHIP_ERROR_INCORRECT_STATE, if the device does not have any set credentials - * CHIP_NO_ERROR, otherwise - */ -CHIP_ERROR GetWifiCredentials(WifiCredentials & credentials); - -/** - * @brief Returns the state of the Wi-Fi network provisionning - * Does the device has Wi-Fi credentials or not - * - * @return true, the device has Wi-Fi credentials - * false, otherwise - */ -bool IsWifiProvisioned(); + WifiCredentials & operator=(const WifiCredentials & other) + { + if (this != &other) + { + memcpy(ssid, other.ssid, WFX_MAX_SSID_LENGTH); + ssidLength = other.ssidLength; + memcpy(passkey, other.passkey, WFX_MAX_PASSKEY_LENGTH); + passkeyLength = other.passkeyLength; + security = other.security; + } + return *this; + } -/** - * @brief Triggers a connection attempt the Access Point who's crendetials match the ones store with the SetWifiCredentials API. - * The function triggers an async connection attempt. The upper layers are notified trought a platform event if the - * connection attempt was successful or not. - * - * The returned error code only indicates if the connection attempt was triggered or not. - * - * @return CHIP_ERROR CHIP_NO_ERROR, the connection attempt was succesfully triggered - * CHIP_ERROR_INCORRECT_STATE, the Wi-Fi station does not have any Wi-Fi credentials - * CHIP_ERROR_INVALID_ARGUMENT, the provisionned crendetials do not match the Wi-Fi station requirements - * CHIP_ERROR_INTERNAL, otherwise - */ -CHIP_ERROR ConnectToAccessPoint(void); + void Clear() + { + memset(ssid, 0, WFX_MAX_SSID_LENGTH); + ssidLength = 0; + memset(passkey, 0, WFX_MAX_PASSKEY_LENGTH); + passkeyLength = 0; + security = WFX_SEC_UNSPECIFIED; + } + }; + + using MacAddress = std::array; + + virtual ~WifiInterface() = default; + + /** + * @brief Returns the singleton instance of the WiFi interface + * + * @note This function needs to be implemented in the child classes sources file + * + * @return WifiInterface& + */ + static WifiInterface & GetInstance(); + + /** + * @brief Function initalizes the WiFi module before starting the WiFi task. + * + * @return CHIP_ERROR CHIP_NO_ERROR, if the initialization succeeded + * CHIP_ERROR_INTERNAL, if sequence failed due to internal API error + * CHIP_ERROR_NO_MEMORY, if sequence failed due to unavaliablility of memory + */ + + virtual CHIP_ERROR InitWiFiStack(void) = 0; + + /** + * @brief Returns the provide interfaces MAC address + * Valid buffer large enough for the MAC address must be provided to the function + * + * @param[in] interface SL_WFX_STA_INTERFACE or SL_WFX_SOFTAP_INTERFACE. + * If soft AP is not enabled, the interface is ignored and the function always returns the Station MAC + * address + * @param[out] addr Interface MAC addres + * + * @return CHIP_ERROR CHIP_NO_ERROR on success + * CHIP_ERROR_BUFFER_TOO_SMALL if the provided ByteSpan size is too small + * + */ + virtual CHIP_ERROR GetMacAddress(sl_wfx_interface_t interface, chip::MutableByteSpan & addr) = 0; + + /** + * @brief Triggers a network scan + * The function is asynchronous and the result is provided via the callback. + * + * @param ssid The SSID to scan for. If empty, all networks are scanned + * @param callback The callback to be called when the scan is complete. Cannot be nullptr. + * The callback is called asynchrounously. + * + * @return CHIP_ERROR CHIP_NO_ERROR if the network scan was successfully started + * CHIP_INVALID_ARGUMENT if the callback is nullptr + * CHIP_ERROR_IN_PROGRESS, if there is already a network scan in progress + * CHIP_ERROR_INVALID_STRING_LENGTH, if there SSID length exceeds handled limit + * other, if there is a platform error when starting the scan + */ + virtual CHIP_ERROR StartNetworkScan(chip::ByteSpan ssid, ScanCallback callback) = 0; + + /** + * @brief Creates and starts the WiFi task that processes Wifi events and operations + * + * @return CHIP_ERROR CHIP_NO_ERROR if the task was successfully started and initialized + * CHIP_ERROR_NO_MEMORY if the task failed to be created + * CHIP_ERROR_INTERNAL if software or hardware initialization failed + */ + virtual CHIP_ERROR StartWifiTask() = 0; + + /** + * @brief Configures the Wi-Fi devices as a Wi-Fi station + */ + virtual void ConfigureStationMode() = 0; + + /** + * @brief Returns the state of the Wi-Fi connection + * + * @return true, if the Wi-Fi device is connected to an AP + * false, otherwise + */ + virtual bool IsStationConnected() = 0; + + /** + * @brief Returns the state of the Wi-Fi Station configuration of the Wi-Fi device + * + * @return true, if the Wi-Fi Station mode is enabled + * false, otherwise + */ + virtual bool IsStationModeEnabled() = 0; + + /** + * @brief Returns the state of the Wi-Fi station initialization + * + * @return true, if the initialization was successful + * false, otherwise + */ + virtual bool IsStationReady() = 0; + + /** + * @brief Triggers the device to disconnect from the connected Wi-Fi network + * + * @note The disconnection is not immediate. It can take a certain amount of time for the device to be in a disconnected state + * once the function is called. When the function returns, the device might not have yet disconnected from the Wi-Fi network. + * + * @return CHIP_ERROR CHIP_NO_ERROR, disconnection request was succesfully triggered + * otherwise, CHIP_ERROR_INTERNAL + */ + virtual CHIP_ERROR TriggerDisconnection() = 0; + + /** + * @brief Gets the connected access point information. + * See @wfx_wifi_scan_result_t for the information that is returned by the function. + * + * @param[out] info AP information + * + * @return CHIP_ERROR CHIP_NO_ERROR, device has succesfully pulled all the AP information + * CHIP_ERROR_INTERNAL, otherwise. If the function returns an error, the data in ap cannot be used. + */ + virtual CHIP_ERROR GetAccessPointInfo(wfx_wifi_scan_result_t & info) = 0; + + /** + * @brief Gets the connected access point extended information. + * See @wfx_wifi_scan_ext_t for the information that is returned by the information + * + * @param[out] info AP extended information + * + * @return CHIP_ERROR CHIP_NO_ERROR, device has succesfully pulled all the AP information + * CHIP_ERROR_INTERNAL, otherwise. If the function returns an error, the data in ap cannot be used. + */ + virtual CHIP_ERROR GetAccessPointExtendedInfo(wfx_wifi_scan_ext_t & info) = 0; + + /** + * @brief Function resets the BeaconLostCount, BeaconRxCount, PacketMulticastRxCount, PacketMulticastTxCount, + * PacketUnicastRxCount, PacketUnicastTxCount back to 0 + * + * @return CHIP_ERROR CHIP_NO_ERROR, the counters were succesfully reset to 0. + * CHIP_ERROR_INTERNAL, if there was an error when resetting the counter values + */ + virtual CHIP_ERROR ResetCounters() = 0; + + /** + * @brief Clears the stored Wi-Fi crendetials stored in RAM only + */ + virtual void ClearWifiCredentials() = 0; + + /** + * @brief Stores the Wi-Fi credentials + * + * @note Function does not validate if the device already has Wi-Fi credentials. + * It is the responsibility of the caller to ensuret that. + * The function will overwrite any existing Wi-Fi credentials. + * + * @param[in] credentials + */ + virtual void SetWifiCredentials(const WifiCredentials & credentials) = 0; + + /** + * @brief Returns the configured Wi-Fi credentials + * + * @param[out] credentials stored wifi crendetials + * + * @return CHIP_ERROR CHIP_ERROR_INCORRECT_STATE, if the device does not have any set credentials + * CHIP_NO_ERROR, otherwise + */ + virtual CHIP_ERROR GetWifiCredentials(WifiCredentials & credentials) = 0; + + /** + * @brief Returns the state of the Wi-Fi network provisionning + * Does the device has Wi-Fi credentials or not + * + * @return true, the device has Wi-Fi credentials + * false, otherwise + */ + virtual bool IsWifiProvisioned() = 0; + + /** + * @brief Triggers a connection attempt the Access Point who's crendetials match the ones store with the SetWifiCredentials API. + * The function triggers an async connection attempt. The upper layers are notified trought a platform event if the + * connection attempt was successful or not. + * + * The returned error code only indicates if the connection attempt was triggered or not. + * + * @return CHIP_ERROR CHIP_NO_ERROR, the connection attempt was succesfully triggered + * CHIP_ERROR_INCORRECT_STATE, the Wi-Fi station does not have any Wi-Fi credentials + * CHIP_ERROR_INVALID_ARGUMENT, the provisionned crendetials do not match the Wi-Fi station requirements + * CHIP_ERROR_INTERNAL, otherwise + */ + virtual CHIP_ERROR ConnectToAccessPoint(void) = 0; /* Function to update */ // TODO: Harmonize the Power Save function inputs for all platforms #if CHIP_CONFIG_ENABLE_ICD_SERVER #if (SLI_SI91X_MCU_INTERFACE | EXP_BOARD) -CHIP_ERROR ConfigurePowerSave(rsi_power_save_profile_mode_t sl_si91x_ble_state, sl_si91x_performance_profile_t sl_si91x_wifi_state, - uint32_t listenInterval); + virtual CHIP_ERROR ConfigurePowerSave(rsi_power_save_profile_mode_t sl_si91x_ble_state, + sl_si91x_performance_profile_t sl_si91x_wifi_state, uint32_t listenInterval) = 0; #else -CHIP_ERROR ConfigurePowerSave(); + virtual CHIP_ERROR ConfigurePowerSave() = 0; #endif /* (SLI_SI91X_MCU_INTERFACE | EXP_BOARD) */ + + /** + * @brief Configures the broadcast filter. + * + * @param[in] enableBroadcastFilter Boolean to enable or disable the broadcast filter. + * + * @return CHIP_ERROR CHIP_NO_ERROR, the counters were succesfully reset to 0. + * CHIP_ERROR_INTERNAL, if there was an error when configuring the broadcast filter + */ + virtual CHIP_ERROR ConfigureBroadcastFilter(bool enableBroadcastFilter) = 0; #endif // CHIP_CONFIG_ENABLE_ICD_SERVER #if CHIP_DEVICE_CONFIG_ENABLE_IPV4 -/** - * @brief Returns IP assignment status - * - - * @return true, Wi-Fi station has an IPv4 address - * false, otherwise - */ -bool HasAnIPv4Address(); + /** + * @brief Returns IP assignment status + * + + * @return true, Wi-Fi station has an IPv4 address + * false, otherwise + */ + virtual bool HasAnIPv4Address() = 0; #endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ -/** - * @brief Returns IP assignment status - * + /** + * @brief Returns IP assignment status + * + + * @return true, Wi-Fi station has an IPv6 address + * false, otherwise + */ + virtual bool HasAnIPv6Address() = 0; + + /** + * @brief Cancels the on-going network scan operation. + * If one isn't in-progress, function doesn't do anything + */ + virtual void CancelScanNetworks() = 0; + +protected: + /** + * @brief Function notifies the PlatformManager that an IPv6 event occured on the WiFi interface. + * + * @param gotIPv6Addr true, got an IPv6 address + * false, lost or wasn't able to get an IPv6 address + */ + void NotifyIPv6Change(bool gotIPv6Addr); - * @return true, Wi-Fi station has an IPv6 address - * false, otherwise - */ -bool HasAnIPv6Address(); +#if CHIP_DEVICE_CONFIG_ENABLE_IPV4 + /** + * @brief Function notifies the PlatformManager that an IPv4 event occured on the WiFi interface. + * + * @param gotIPv4Addr true, got an IPv4 address + * false, lost or wasn't able to get an IPv4 address + */ + void NotifyIPv4Change(bool gotIPv4Addr); +#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ -/** - * @brief Cancels the on-going network scan operation. - * If one isn't in-progress, function doesn't do anything - */ -void CancelScanNetworks(); + /** + * @brief Function notifies the PlatformManager that a disconnection event occurred + * + * @param reason reason for the disconnection + */ + void NotifyDisconnection(WifiDisconnectionReasons reason); + + /** + * @brief Function notifies the PlatformManager that a connection event occurred + * + * @param[in] ap pointer to the structure that contains the MAC address of the AP + */ + void NotifyConnection(const MacAddress & ap); + + /** + * @brief Function resets the IP notification states + * + */ + void ResetIPNotificationStates(); + + /** + * @brief Notifies upper-layers that Wi-Fi initialization has succesfully completed + */ + void NotifyWifiTaskInitialized(void); + + /** + * @brief Function schedules a reconnection attempt with the Access Point + * + * @note The retry interval increases exponentially with each attempt, starting from a minimum value and doubling each time, + * up to a maximum value. For example, if the initial retry interval is 1 second, the subsequent intervals will be 2 + * seconds, 4 seconds, 8 seconds, and so on, until the maximum retry interval is reached. + */ + void ScheduleConnectionAttempt(); + + bool mHasNotifiedIPv6 = false; +#if CHIP_DEVICE_CONFIG_ENABLE_IPV4 + bool mHasNotifiedIPv4 = false; +#endif // CHIP_DEVICE_CONFIG_ENABLE_IPV4 -/** - * @brief Notifies upper-layers that Wi-Fi initialization has succesfully completed - */ -void NotifyWifiTaskInitialized(void); +private: + osTimerId_t mRetryTimer; +}; -/** - * @brief Function schedules a reconnection attempt with the Access Point - * - * @note The retry interval increases exponentially with each attempt, starting from a minimum value and doubling each time, - * up to a maximum value. For example, if the initial retry interval is 1 second, the subsequent intervals will be 2 seconds, - * 4 seconds, 8 seconds, and so on, until the maximum retry interval is reached. - */ -void ScheduleConnectionAttempt(); +} // namespace Silabs +} // namespace DeviceLayer +} // namespace chip + +// TODO: This structure can be split into members of the interfaces +// This needs to be after the class definition since it depends on class members +typedef struct wfx_rsi_s +{ + chip::BitFlags dev_state; + uint16_t ap_chan; /* The chan our STA is using */ + chip::DeviceLayer::Silabs::WifiInterface::WifiCredentials credentials; + ScanCallback scan_cb; + uint8_t * scan_ssid; /* Which one are we scanning for */ + size_t scan_ssid_length; +#ifdef SL_WFX_CONFIG_SOFTAP + chip::DeviceLayer::Silabs::WifiInterface::MacAddress softap_mac; +#endif + chip::DeviceLayer::Silabs::WifiInterface::MacAddress sta_mac; + chip::DeviceLayer::Silabs::WifiInterface::MacAddress ap_mac; /* To which our STA is connected */ + chip::DeviceLayer::Silabs::WifiInterface::MacAddress ap_bssid; /* To which our STA is connected */ + uint8_t ip4_addr[4]; /* Not sure if this is enough */ +} WfxRsi_t; diff --git a/src/platform/silabs/wifi/icd/WifiSleepManager.cpp b/src/platform/silabs/wifi/icd/WifiSleepManager.cpp index 72de8a0290d4f3..d28ecde3a9e759 100644 --- a/src/platform/silabs/wifi/icd/WifiSleepManager.cpp +++ b/src/platform/silabs/wifi/icd/WifiSleepManager.cpp @@ -20,6 +20,8 @@ #include #include +using namespace chip::DeviceLayer::Silabs; + namespace { // TODO: Once the platform sleep calls are unified, we can removed this ifdef @@ -33,10 +35,10 @@ namespace { */ CHIP_ERROR ConfigureDTIMBasedSleep() { - ReturnLogErrorOnFailure(ConfigureBroadcastFilter(false)); + ReturnLogErrorOnFailure(WifiInterface::GetInstance().ConfigureBroadcastFilter(false)); // Allowing the device to go to sleep must be the last actions to avoid configuration failures. - ReturnLogErrorOnFailure(ConfigurePowerSave(RSI_SLEEP_MODE_2, ASSOCIATED_POWER_SAVE, 0)); + ReturnLogErrorOnFailure(WifiInterface::GetInstance().ConfigurePowerSave(RSI_SLEEP_MODE_2, ASSOCIATED_POWER_SAVE, 0)); return CHIP_NO_ERROR; } @@ -49,7 +51,7 @@ CHIP_ERROR ConfigureDTIMBasedSleep() */ CHIP_ERROR ConfigureDeepSleep() { - ReturnLogErrorOnFailure(ConfigurePowerSave(RSI_SLEEP_MODE_8, DEEP_SLEEP_WITH_RAM_RETENTION, 0)); + ReturnLogErrorOnFailure(WifiInterface::GetInstance().ConfigurePowerSave(RSI_SLEEP_MODE_8, DEEP_SLEEP_WITH_RAM_RETENTION, 0)); return CHIP_NO_ERROR; } @@ -61,7 +63,7 @@ CHIP_ERROR ConfigureDeepSleep() */ CHIP_ERROR ConfigureHighPerformance() { - ReturnLogErrorOnFailure(ConfigurePowerSave(RSI_ACTIVE, HIGH_PERFORMANCE, 0)); + ReturnLogErrorOnFailure(WifiInterface::GetInstance().ConfigurePowerSave(RSI_ACTIVE, HIGH_PERFORMANCE, 0)); return CHIP_NO_ERROR; } #endif // SLI_SI917 @@ -148,7 +150,7 @@ CHIP_ERROR WifiSleepManager::VerifyAndTransitionToLowPowerMode(PowerEvent event) return CHIP_NO_ERROR; } - if (!IsWifiProvisioned()) + if (!WifiInterface::GetInstance().IsWifiProvisioned()) { return ConfigureDeepSleep(); } @@ -156,7 +158,7 @@ CHIP_ERROR WifiSleepManager::VerifyAndTransitionToLowPowerMode(PowerEvent event) return ConfigureDTIMBasedSleep(); #else - ReturnErrorOnFailure(ConfigurePowerSave()); + ReturnErrorOnFailure(WifiInterface::GetInstance().ConfigurePowerSave()); return CHIP_NO_ERROR; #endif } diff --git a/src/platform/silabs/wifi/lwip-support/ethernetif.cpp b/src/platform/silabs/wifi/lwip-support/ethernetif.cpp index 60c8d8feaa369b..0ecd6ee516541b 100644 --- a/src/platform/silabs/wifi/lwip-support/ethernetif.cpp +++ b/src/platform/silabs/wifi/lwip-support/ethernetif.cpp @@ -75,7 +75,7 @@ static void low_level_init(struct netif * netif) /* Set netif MAC hardware address */ chip::MutableByteSpan byteSpan(netif->hwaddr, ETH_HWADDR_LEN); - GetMacAddress(SL_WFX_STA_INTERFACE, byteSpan); + chip::DeviceLayer::Silabs::WifiInterface::GetInstance().GetMacAddress(SL_WFX_STA_INTERFACE, byteSpan); /* Set netif maximum transfer unit */ netif->mtu = 1500; diff --git a/src/platform/silabs/wifi/rs911x/WifiInterfaceImpl.cpp b/src/platform/silabs/wifi/rs911x/WifiInterfaceImpl.cpp index d7615dbed9695b..8276360a381bc2 100644 --- a/src/platform/silabs/wifi/rs911x/WifiInterfaceImpl.cpp +++ b/src/platform/silabs/wifi/rs911x/WifiInterfaceImpl.cpp @@ -15,20 +15,16 @@ * limitations under the License. */ -#include "lwip/nd6.h" -#include "silabs_utils.h" #include "sl_status.h" #include #include #include #include -#include -#include #include #include #include #include -#include +#include extern "C" { #include "rsi_bootup_config.h" @@ -45,8 +41,6 @@ extern "C" { #include "rsi_wlan_non_rom.h" } -using WifiStateFlags = chip::BitFlags; - #define WFX_QUEUE_SIZE 10 #define WFX_RSI_BUF_SZ (1024 * 10) #define RSI_RESPONSE_MAX_SIZE (28) @@ -60,10 +54,14 @@ using WifiStateFlags = chip::BitFlags; WfxRsi_t wfx_rsi; -static osThreadId_t sDrvThread; +using namespace chip::DeviceLayer::Silabs; + +namespace { + +osThreadId_t sDrvThread; constexpr uint32_t kDrvTaskSize = 1792; -static uint8_t drvStack[kDrvTaskSize]; -static osThread_t sDrvTaskControlBlock; +uint8_t drvStack[kDrvTaskSize]; +osThread_t sDrvTaskControlBlock; osThreadAttr_t kDrvTaskAttr = { .name = "drv_rsi", .attr_bits = osThreadDetached, .cb_mem = &sDrvTaskControlBlock, @@ -72,20 +70,136 @@ osThreadAttr_t kDrvTaskAttr = { .name = "drv_rsi", .stack_size = kDrvTaskSize, .priority = osPriorityHigh }; -static osMessageQueueId_t sWifiEventQueue = NULL; -/* - * This file implements the interface to the RSI SAPIs - */ -static uint8_t wfx_rsi_drv_buf[WFX_RSI_BUF_SZ]; -static wfx_wifi_scan_ext_t temp_reset; +osMessageQueueId_t sWifiEventQueue = NULL; + +uint8_t wfx_rsi_drv_buf[WFX_RSI_BUF_SZ]; +wfx_wifi_scan_ext_t temp_reset; + +/****************************************************************** + * @fn void rsi_wireless_driver_task_wrapper(void * argument) + * @brief + * wrapper thread for the driver task + * @param[in] argument: argument + * @return + * None + *********************************************************************/ +void rsi_wireless_driver_task_wrapper(void * argument) +{ + rsi_wireless_driver_task(); +} + +/************************************************************************************* + * @fn wfx_rsi_wlan_pkt_cb(uint16_t status, uint8_t *buf, uint32_t len) + * @brief + * Got RAW WLAN data pkt + * @param[in] status: + * @param[in] buf: + * @param[in] len: + * @return + * None + *****************************************************************************************/ +void wfx_rsi_wlan_pkt_cb(uint16_t status, uint8_t * buf, uint32_t len) +{ + if (status != RSI_SUCCESS) + { + return; + } + wfx_host_received_sta_frame_cb(buf, len); +} + +/*************************************************************************************** + * @fn static void wfx_rsi_save_ap_info(void) + * @brief + * Saving the details of the AP + * @param[in] None + * @return + * None + *******************************************************************************************/ +void wfx_rsi_save_ap_info(void) // translation +{ + int32_t status; + rsi_rsp_scan_t rsp; + + status = rsi_wlan_scan_with_bitmap_options((int8_t *) &wfx_rsi.credentials.ssid[0], AP_CHANNEL_NO_0, &rsp, sizeof(rsp), + SCAN_BITMAP_OPTN_1); + if (status != RSI_SUCCESS) + { + /* + * Scan is done - failed + */ +#if WIFI_ENABLE_SECURITY_WPA3_TRANSITION + wfx_rsi.credentials.security = WFX_SEC_WPA3; +#else /* !WIFI_ENABLE_SECURITY_WPA3_TRANSITION */ + wfx_rsi.credentials.security = WFX_SEC_WPA2; +#endif /* WIFI_ENABLE_SECURITY_WPA3_TRANSITION */ + ChipLogProgress(DeviceLayer, "warn: scan failed: %ld", status); + return; + } + wfx_rsi.credentials.security = WFX_SEC_UNSPECIFIED; + wfx_rsi.ap_chan = rsp.scan_info->rf_channel; + memcpy(wfx_rsi.ap_mac.data(), &rsp.scan_info->bssid[0], kWifiMacAddressLength); + + switch (rsp.scan_info->security_mode) + { + case SME_OPEN: + wfx_rsi.credentials.security = WFX_SEC_NONE; + break; + case SME_WPA: + case SME_WPA_ENTERPRISE: + wfx_rsi.credentials.security = WFX_SEC_WPA; + break; + case SME_WPA2: + case SME_WPA2_ENTERPRISE: + wfx_rsi.credentials.security = WFX_SEC_WPA2; + break; + case SME_WPA_WPA2_MIXED_MODE: + wfx_rsi.credentials.security = WFX_SEC_WPA_WPA2_MIXED; + break; + case SME_WEP: + wfx_rsi.credentials.security = WFX_SEC_WEP; + break; + case SME_WPA3_PERSONAL_TRANSITION: +#if WIFI_ENABLE_SECURITY_WPA3_TRANSITION + case SME_WPA3_PERSONAL: + wfx_rsi.credentials.security = WFX_SEC_WPA3; +#else + wfx_rsi.credentials.security = WFX_SEC_WPA2; +#endif /* WIFI_ENABLE_SECURITY_WPA3_TRANSITION */ + break; + default: + wfx_rsi.credentials.security = WFX_SEC_UNSPECIFIED; + break; + } -sl_status_t TriggerPlatformWifiDisconnection() + ChipLogProgress(DeviceLayer, "wfx_rsi_save_ap_info: connecting to %s, sec=%d, status=%ld", &wfx_rsi.credentials.ssid[0], + wfx_rsi.credentials.security, status); +} + +} // namespace + +namespace chip { +namespace DeviceLayer { +namespace Silabs { + +WifiInterfaceImpl WifiInterfaceImpl::mInstance; + +WifiInterface & WifiInterface::GetInstance() +{ + return WifiInterfaceImpl::GetInstance(); +} + +WiseconnectWifiInterface & WiseconnectWifiInterface::GetInstance() +{ + return WifiInterfaceImpl::GetInstance(); +} + +sl_status_t WifiInterfaceImpl::TriggerPlatformWifiDisconnection() { VerifyOrReturnError(rsi_wlan_disconnect() == RSI_SUCCESS, SL_STATUS_FAIL); return SL_STATUS_OK; } -CHIP_ERROR GetAccessPointInfo(wfx_wifi_scan_result_t & info) +CHIP_ERROR WifiInterfaceImpl::GetAccessPointInfo(wfx_wifi_scan_result_t & info) { int32_t status = RSI_SUCCESS; uint8_t rssi = 0; @@ -102,7 +216,7 @@ CHIP_ERROR GetAccessPointInfo(wfx_wifi_scan_result_t & info) return CHIP_NO_ERROR; } -CHIP_ERROR GetAccessPointExtendedInfo(wfx_wifi_scan_ext_t & info) +CHIP_ERROR WifiInterfaceImpl::GetAccessPointExtendedInfo(wfx_wifi_scan_ext_t & info) { rsi_wlan_ext_stats_t stats = { 0 }; @@ -121,7 +235,7 @@ CHIP_ERROR GetAccessPointExtendedInfo(wfx_wifi_scan_ext_t & info) return CHIP_NO_ERROR; } -CHIP_ERROR ResetCounters() +CHIP_ERROR WifiInterfaceImpl::ResetCounters() { rsi_wlan_ext_stats_t stats = { 0 }; @@ -141,7 +255,7 @@ CHIP_ERROR ResetCounters() } #if CHIP_CONFIG_ENABLE_ICD_SERVER -CHIP_ERROR ConfigurePowerSave() +CHIP_ERROR WifiInterfaceImpl::ConfigurePowerSave() { int32_t status = RSI_SUCCESS; #ifdef RSI_BLE_ENABLE @@ -157,101 +271,185 @@ CHIP_ERROR ConfigurePowerSave() return CHIP_NO_ERROR; } -CHIP_ERROR ConfigureBroadcastFilter(bool enableBroadcastFilter) +CHIP_ERROR WifiInterfaceImpl::ConfigureBroadcastFilter(bool enableBroadcastFilter) { // TODO: Implement Broadcast filtering. We do a silent failure to avoid causing problems in higher layers. return CHIP_NO_ERROR; } #endif // CHIP_CONFIG_ENABLE_ICD_SERVER -/****************************************************************** - * @fn void rsi_wireless_driver_task_wrapper(void * argument) - * @brief - * wrapper thread for the driver task - * @param[in] argument: argument - * @return - * None - *********************************************************************/ -static void rsi_wireless_driver_task_wrapper(void * argument) +CHIP_ERROR WifiInterfaceImpl::InitWiFiStack(void) { - rsi_wireless_driver_task(); + int32_t status = Rs911xPlatformInit(); + VerifyOrReturnError(status == RSI_SUCCESS, CHIP_ERROR_INTERNAL, + ChipLogError(DeviceLayer, "Rs911xPlatformInit failed: %lx", status)); + return CHIP_NO_ERROR; } -/****************************************************************** - * @fn wfx_rsi_join_cb(uint16_t status, const uint8_t *buf, const uint16_t len) - * @brief - * called when driver join with cb - * @param[in] status: - * @param[in] buf: - * @param[in] len: - * @return - * None - *********************************************************************/ -static void wfx_rsi_join_cb(uint16_t status, const uint8_t * buf, const uint16_t len) +void WifiInterfaceImpl::PostWifiPlatformEvent(WifiPlatformEvent event) +{ + sl_status_t status = osMessageQueuePut(sWifiEventQueue, &event, 0, 0); + + if (status != osOK) + { + ChipLogError(DeviceLayer, "PostWifiPlatformEvent: failed to post event with status: %ld", status); + // TODO: Handle error, requeue event depending on queue size or notify relevant task, + // Chipdie, etc. + } +} + +/** + * @brief Process the Wi-Fi event. + * + * This function is responsible for processing different types of Wi-Fi events and taking appropriate actions based on the event + * type. + * + * @param event The input Wi-Fi event to be processed. + */ +void WifiInterfaceImpl::ProcessEvent(WifiPlatformEvent event) { - wfx_rsi.dev_state.Clear(WifiState::kStationConnecting); + // Process event + switch (event) + { + case WiseconnectWifiInterface::WifiPlatformEvent::kStationConnect: { + ChipLogDetail(DeviceLayer, "WiseconnectWifiInterface::WifiPlatformEvent::kStationConnect"); + wfx_rsi.dev_state.Set(WifiInterface::WifiState::kStationConnected); + ResetDHCPNotificationFlags(); + chip::DeviceLayer::Silabs::Lwip::SetLwipStationLinkUp(); + } + break; + case WiseconnectWifiInterface::WifiPlatformEvent::kStationDisconnect: { + ChipLogDetail(DeviceLayer, "WiseconnectWifiInterface::WifiPlatformEvent::kStationDisconnect"); + + wfx_rsi.dev_state.Clear(WifiInterface::WifiState::kStationReady) + .Clear(WifiInterface::WifiState::kStationConnecting) + .Clear(WifiInterface::WifiState::kStationConnected) + .Clear(WifiInterface::WifiState::kStationDhcpDone); + + /* TODO: Implement disconnect notify */ + ResetDHCPNotificationFlags(); + chip::DeviceLayer::Silabs::Lwip::SetLwipStationLinkDown(); + +#if (CHIP_DEVICE_CONFIG_ENABLE_IPV4) + NotifyIPv4Change(false); +#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ + NotifyIPv6Change(false); + } + break; + case WiseconnectWifiInterface::WifiPlatformEvent::kAPStart: + // TODO: Currently unimplemented + break; + case WiseconnectWifiInterface::WifiPlatformEvent::kScan: { + rsi_rsp_scan_t scan_rsp = { 0 }; + int32_t status = rsi_wlan_bgscan_profile(1, &scan_rsp, sizeof(scan_rsp)); + + VerifyOrReturn(status == RSI_SUCCESS, ChipLogError(DeviceLayer, "rsi_wlan_bgscan_profile failed: %ld", status)); + VerifyOrReturn(wfx_rsi.scan_cb != nullptr, ChipLogError(DeviceLayer, "wfx_rsi.scan_cb is nullptr")); + + uint8_t nbreOfScannedNetworks = scan_rsp.scan_count[0]; + for (int i = 0; i < nbreOfScannedNetworks; i++) + { + rsi_scan_info_t scan = scan_rsp.scan_info[i]; + wfx_wifi_scan_result_t ap = { 0 }; + + ap.ssid_length = strnlen(reinterpret_cast(scan.ssid), WFX_MAX_SSID_LENGTH); + + chip::ByteSpan scannedSsid(scan.ssid, ap.ssid_length); + chip::MutableByteSpan outputSsid(ap.ssid, WFX_MAX_SSID_LENGTH); + chip::CopySpanToMutableSpan(scannedSsid, outputSsid); + + // Check if the scanned ssid is the requested Ssid + chip::ByteSpan requestedSsid(wfx_rsi.scan_ssid, wfx_rsi.scan_ssid_length); + if (!requestedSsid.empty() && !requestedSsid.data_equal(scannedSsid)) + { + // Scanned SSID entry does not match the requested SSID. Continue to the next. + continue; + } + + // TODO: convert security mode from RSI to WFX + ap.security = static_cast(scan.security_mode); + ap.rssi = (-1) * scan.rssi_val; + + VerifyOrDie(sizeof(ap.bssid) == kWifiMacAddressLength); + VerifyOrDie(sizeof(scan.bssid) == kWifiMacAddressLength); + + chip::MutableByteSpan bssidSpan(ap.bssid, kWifiMacAddressLength); + chip::ByteSpan scanBssidSpan(scan.bssid, kWifiMacAddressLength); + chip::CopySpanToMutableSpan(scanBssidSpan, bssidSpan); + + wfx_rsi.scan_cb(&ap); + + // If we reach this and the requestedSsid is not empty, it means we found the requested SSID and we can exit + if (!requestedSsid.empty()) + { + break; + } + } + // Notify the stack that we have finishes scanning for Networks + wfx_rsi.scan_cb(nullptr); + + // Clean up + wfx_rsi.scan_cb = nullptr; + if (wfx_rsi.scan_ssid) + { + chip::Platform::MemoryFree(wfx_rsi.scan_ssid); + wfx_rsi.scan_ssid = NULL; + } + } + break; + case WiseconnectWifiInterface::WifiPlatformEvent::kStationStartJoin: { + // saving the AP related info + wfx_rsi_save_ap_info(); + // Joining to the network + JoinWifiNetwork(); + } + break; + case WiseconnectWifiInterface::WifiPlatformEvent::kStationDoDhcp: { + StartDHCPTimer(kDhcpPollIntervalMs); + } + break; + case WiseconnectWifiInterface::WifiPlatformEvent::kStationDhcpDone: { + CancelDHCPTimer(); + } + break; + case WiseconnectWifiInterface::WifiPlatformEvent::kStationDhcpPoll: { + HandleDHCPPolling(); + } + break; + default: + break; + } +} + +void WifiInterfaceImpl::JoinCallback(uint16_t status, const uint8_t * buf, const uint16_t len) +{ + wfx_rsi.dev_state.Clear(WifiInterface::WifiState::kStationConnecting); if (status != RSI_SUCCESS) { - ScheduleConnectionAttempt(); + WifiInterfaceImpl::GetInstance().ScheduleConnectionAttempt(); return; } /* * Join was complete - Do the DHCP */ - ChipLogProgress(DeviceLayer, "wfx_rsi_join_cb: success"); + ChipLogProgress(DeviceLayer, "JoinCallback: success"); memset(&temp_reset, 0, sizeof(wfx_wifi_scan_ext_t)); - WifiPlatformEvent event = WifiPlatformEvent::kStationConnect; - PostWifiPlatformEvent(event); + WifiPlatformEvent event = WiseconnectWifiInterface::WifiPlatformEvent::kStationConnect; + WifiInterfaceImpl::GetInstance().PostWifiPlatformEvent(event); } -/****************************************************************** - * @fn wfx_rsi_join_fail_cb(uint16_t status, uint8_t *buf, uint32_t len) - * @brief - * called when driver fail to join with cb - * @param[in] status: - * @param[in] buf: - * @param[in] len: - * @return - * None - *********************************************************************/ -static void wfx_rsi_join_fail_cb(uint16_t status, uint8_t * buf, uint32_t len) +void WifiInterfaceImpl::JoinFailCallback(uint16_t status, uint8_t * buf, uint32_t len) { - ChipLogError(DeviceLayer, "wfx_rsi_join_fail_cb: status: %d", status); + ChipLogError(DeviceLayer, "JoinFailCallback: status: %d", status); - wfx_rsi.dev_state.Clear(WifiState::kStationConnecting).Clear(WifiState::kStationConnected); + wfx_rsi.dev_state.Clear(WifiInterface::WifiState::kStationConnecting).Clear(WifiInterface::WifiState::kStationConnected); - WifiPlatformEvent event = WifiPlatformEvent::kStationStartJoin; - PostWifiPlatformEvent(event); -} -/************************************************************************************* - * @fn wfx_rsi_wlan_pkt_cb(uint16_t status, uint8_t *buf, uint32_t len) - * @brief - * Got RAW WLAN data pkt - * @param[in] status: - * @param[in] buf: - * @param[in] len: - * @return - * None - *****************************************************************************************/ -static void wfx_rsi_wlan_pkt_cb(uint16_t status, uint8_t * buf, uint32_t len) -{ - if (status != RSI_SUCCESS) - { - return; - } - wfx_host_received_sta_frame_cb(buf, len); + WiseconnectWifiInterface::WifiPlatformEvent event = WiseconnectWifiInterface::WifiPlatformEvent::kStationStartJoin; + WifiInterfaceImpl::GetInstance().PostWifiPlatformEvent(event); } -/************************************************************************************* - * @fn static int32_t sl_matter_wifi_init(void) - * @brief - * driver initialization - * @param[in] None - * @return - * None - *****************************************************************************************/ -static int32_t sl_matter_wifi_init(void) +int32_t WifiInterfaceImpl::Rs911xPlatformInit(void) { int32_t status; uint8_t buf[RSI_RESPONSE_HOLD_BUFF_SIZE]; @@ -322,7 +520,7 @@ static int32_t sl_matter_wifi_init(void) wfx_rsi.sta_mac.at(2), wfx_rsi.sta_mac.at(3), wfx_rsi.sta_mac.at(4), wfx_rsi.sta_mac.at(5)); // Create the message queue - sWifiEventQueue = osMessageQueueNew(WFX_QUEUE_SIZE, sizeof(WifiPlatformEvent), NULL); + sWifiEventQueue = osMessageQueueNew(WFX_QUEUE_SIZE, sizeof(WiseconnectWifiInterface::WifiPlatformEvent), NULL); if (sWifiEventQueue == NULL) { return SL_STATUS_ALLOCATION_FAILED; @@ -335,7 +533,7 @@ static int32_t sl_matter_wifi_init(void) /* * Register callbacks - We are only interested in the connectivity CBs */ - if ((status = rsi_wlan_register_callbacks(RSI_JOIN_FAIL_CB, wfx_rsi_join_fail_cb)) != RSI_SUCCESS) + if ((status = rsi_wlan_register_callbacks(RSI_JOIN_FAIL_CB, WifiInterfaceImpl::JoinFailCallback)) != RSI_SUCCESS) { ChipLogError(DeviceLayer, "rsi_wlan_register_callbacks failed: %ld", status); return status; @@ -346,91 +544,17 @@ static int32_t sl_matter_wifi_init(void) return status; } - wfx_rsi.dev_state.Set(WifiState::kStationInit); + wfx_rsi.dev_state.Set(WifiInterface::WifiState::kStationInit); return RSI_SUCCESS; } -/*************************************************************************************** - * @fn static void wfx_rsi_save_ap_info(void) - * @brief - * Saving the details of the AP - * @param[in] None - * @return - * None - *******************************************************************************************/ -static void wfx_rsi_save_ap_info(void) // translation -{ - int32_t status; - rsi_rsp_scan_t rsp; - - status = rsi_wlan_scan_with_bitmap_options((int8_t *) &wfx_rsi.credentials.ssid[0], AP_CHANNEL_NO_0, &rsp, sizeof(rsp), - SCAN_BITMAP_OPTN_1); - if (status != RSI_SUCCESS) - { - /* - * Scan is done - failed - */ -#if WIFI_ENABLE_SECURITY_WPA3_TRANSITION - wfx_rsi.credentials.security = WFX_SEC_WPA3; -#else /* !WIFI_ENABLE_SECURITY_WPA3_TRANSITION */ - wfx_rsi.credentials.security = WFX_SEC_WPA2; -#endif /* WIFI_ENABLE_SECURITY_WPA3_TRANSITION */ - ChipLogProgress(DeviceLayer, "warn: scan failed: %ld", status); - return; - } - wfx_rsi.credentials.security = WFX_SEC_UNSPECIFIED; - wfx_rsi.ap_chan = rsp.scan_info->rf_channel; - memcpy(wfx_rsi.ap_mac.data(), &rsp.scan_info->bssid[0], kWifiMacAddressLength); - - switch (rsp.scan_info->security_mode) - { - case SME_OPEN: - wfx_rsi.credentials.security = WFX_SEC_NONE; - break; - case SME_WPA: - case SME_WPA_ENTERPRISE: - wfx_rsi.credentials.security = WFX_SEC_WPA; - break; - case SME_WPA2: - case SME_WPA2_ENTERPRISE: - wfx_rsi.credentials.security = WFX_SEC_WPA2; - break; - case SME_WPA_WPA2_MIXED_MODE: - wfx_rsi.credentials.security = WFX_SEC_WPA_WPA2_MIXED; - break; - case SME_WEP: - wfx_rsi.credentials.security = WFX_SEC_WEP; - break; - case SME_WPA3_PERSONAL_TRANSITION: -#if WIFI_ENABLE_SECURITY_WPA3_TRANSITION - case SME_WPA3_PERSONAL: - wfx_rsi.credentials.security = WFX_SEC_WPA3; -#else - wfx_rsi.credentials.security = WFX_SEC_WPA2; -#endif /* WIFI_ENABLE_SECURITY_WPA3_TRANSITION */ - break; - default: - wfx_rsi.credentials.security = WFX_SEC_UNSPECIFIED; - break; - } - - ChipLogProgress(DeviceLayer, "wfx_rsi_save_ap_info: connecting to %s, sec=%d, status=%ld", &wfx_rsi.credentials.ssid[0], - wfx_rsi.credentials.security, status); -} - -/******************************************************************************************** - * @fn static void sl_wifi_platform_join_network(void) - * @brief - * Start an async Join command - * @return - * None - **********************************************************************************************/ -static void sl_wifi_platform_join_network(void) +void WifiInterfaceImpl::JoinWifiNetwork(void) { sl_status_t status = SL_STATUS_OK; rsi_security_mode_t connect_security_mode; - VerifyOrReturn(!wfx_rsi.dev_state.HasAny(WifiState::kStationConnecting, WifiState::kStationConnected)); + VerifyOrReturn( + !wfx_rsi.dev_state.HasAny(WifiInterface::WifiState::kStationConnecting, WifiInterface::WifiState::kStationConnected)); switch (wfx_rsi.credentials.security) { @@ -451,11 +575,11 @@ static void sl_wifi_platform_join_network(void) connect_security_mode = RSI_OPEN; break; default: - ChipLogError(DeviceLayer, "sl_wifi_platform_join_network: error: unknown security type."); + ChipLogError(DeviceLayer, "JoinWifiNetwork: error: unknown security type."); return; } - ChipLogProgress(DeviceLayer, "sl_wifi_platform_join_network: connecting to %s, sec=%d", &wfx_rsi.credentials.ssid[0], + ChipLogProgress(DeviceLayer, "JoinWifiNetwork: connecting to %s, sec=%d", &wfx_rsi.credentials.ssid[0], wfx_rsi.credentials.security); /* @@ -464,25 +588,25 @@ static void sl_wifi_platform_join_network(void) /* TODO - make the WFX_SECURITY_xxx - same as RSI_xxx * Right now it's done by hand - we need something better */ - wfx_rsi.dev_state.Set(WifiState::kStationConnecting); + wfx_rsi.dev_state.Set(WifiInterface::WifiState::kStationConnecting); - if ((status = rsi_wlan_register_callbacks(RSI_JOIN_FAIL_CB, wfx_rsi_join_fail_cb)) != RSI_SUCCESS) + if ((status = rsi_wlan_register_callbacks(RSI_JOIN_FAIL_CB, WifiInterfaceImpl::JoinFailCallback)) != RSI_SUCCESS) { - ChipLogError(DeviceLayer, "sl_wifi_platform_join_network: rsi_wlan_register_callbacks failed: %ld", status); + ChipLogError(DeviceLayer, "JoinWifiNetwork: rsi_wlan_register_callbacks failed: %ld", status); } /* Try to connect Wifi with given Credentials * until there is a success or maximum number of tries allowed */ if ((status = rsi_wlan_connect_async((int8_t *) &wfx_rsi.credentials.ssid[0], connect_security_mode, - &wfx_rsi.credentials.passkey[0], wfx_rsi_join_cb)) != RSI_SUCCESS) + &wfx_rsi.credentials.passkey[0], JoinCallback)) != RSI_SUCCESS) { - wfx_rsi.dev_state.Clear(WifiState::kStationConnecting); + wfx_rsi.dev_state.Clear(WifiInterface::WifiState::kStationConnecting); ScheduleConnectionAttempt(); } } -void HandleDHCPPolling(void) +void WifiInterfaceImpl::HandleDHCPPolling(void) { struct netif * sta_netif; @@ -496,7 +620,7 @@ void HandleDHCPPolling(void) } #if (CHIP_DEVICE_CONFIG_ENABLE_IPV4) uint8_t dhcp_state = dhcpclient_poll(sta_netif); - if (dhcp_state == DHCP_ADDRESS_ASSIGNED && !HasNotifiedIPv4Change()) + if (dhcp_state == DHCP_ADDRESS_ASSIGNED && !mHasNotifiedIPv4) { GotIPv4Address((uint32_t) sta_netif->ip_addr.u_addr.ip4.addr); NotifyConnectivity(); @@ -509,165 +633,24 @@ void HandleDHCPPolling(void) /* Checks if the assigned IPv6 address is preferred by evaluating * the first block of IPv6 address ( block 0) */ - if ((ip6_addr_ispreferred(netif_ip6_addr_state(sta_netif, 0))) && !HasNotifiedIPv6Change()) + if ((ip6_addr_ispreferred(netif_ip6_addr_state(sta_netif, 0))) && !mHasNotifiedIPv6) { char addrStr[chip::Inet::IPAddress::kMaxStringLength] = { 0 }; VerifyOrReturn(ip6addr_ntoa_r(netif_ip6_addr(sta_netif, 0), addrStr, sizeof(addrStr)) != nullptr); ChipLogProgress(DeviceLayer, "SLAAC OK: linklocal addr: %s", addrStr); NotifyIPv6Change(true); - WifiPlatformEvent event = WifiPlatformEvent::kStationDhcpDone; + WifiPlatformEvent event = WiseconnectWifiInterface::WifiPlatformEvent::kStationDhcpDone; PostWifiPlatformEvent(event); NotifyConnectivity(); } } -void PostWifiPlatformEvent(WifiPlatformEvent event) -{ - sl_status_t status = osMessageQueuePut(sWifiEventQueue, &event, 0, 0); - - if (status != osOK) - { - ChipLogError(DeviceLayer, "PostWifiPlatformEvent: failed to post event with status: %ld", status); - // TODO: Handle error, requeue event depending on queue size or notify relevant task, - // Chipdie, etc. - } -} - -/** - * @brief Process the Wi-Fi event. - * - * This function is responsible for processing different types of Wi-Fi events and taking appropriate actions based on the event - * type. - * - * @param event The input Wi-Fi event to be processed. - */ -void ProcessEvent(WifiPlatformEvent event) -{ - // Process event - switch (event) - { - case WifiPlatformEvent::kStationConnect: { - ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kStationConnect"); - wfx_rsi.dev_state.Set(WifiState::kStationConnected); - ResetDHCPNotificationFlags(); - chip::DeviceLayer::Silabs::Lwip::SetLwipStationLinkUp(); - } - break; - case WifiPlatformEvent::kStationDisconnect: { - ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kStationDisconnect"); - // TODO: This event is not being posted anywhere, seems to be a dead code or we are missing something - WifiStateFlags flagsToClear = WifiStateFlags(WifiState::kStationReady, WifiState::kStationConnecting, - WifiState::kStationConnected, WifiState::kStationDhcpDone); - wfx_rsi.dev_state.Clear(flagsToClear); - /* TODO: Implement disconnect notify */ - ResetDHCPNotificationFlags(); - chip::DeviceLayer::Silabs::Lwip::SetLwipStationLinkDown(); - -#if (CHIP_DEVICE_CONFIG_ENABLE_IPV4) - NotifyIPv4Change(false); -#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ - NotifyIPv6Change(false); - } - break; - case WifiPlatformEvent::kAPStart: - // TODO: Currently unimplemented - break; - case WifiPlatformEvent::kScan: { - rsi_rsp_scan_t scan_rsp = { 0 }; - int32_t status = rsi_wlan_bgscan_profile(1, &scan_rsp, sizeof(scan_rsp)); - - VerifyOrReturn(status == RSI_SUCCESS, ChipLogError(DeviceLayer, "rsi_wlan_bgscan_profile failed: %ld", status)); - VerifyOrReturn(wfx_rsi.scan_cb != nullptr, ChipLogError(DeviceLayer, "wfx_rsi.scan_cb is nullptr")); - - uint8_t nbreOfScannedNetworks = scan_rsp.scan_count[0]; - for (int i = 0; i < nbreOfScannedNetworks; i++) - { - rsi_scan_info_t scan = scan_rsp.scan_info[i]; - wfx_wifi_scan_result_t ap = { 0 }; - - ap.ssid_length = strnlen(reinterpret_cast(scan.ssid), WFX_MAX_SSID_LENGTH); - - chip::ByteSpan scannedSsid(scan.ssid, ap.ssid_length); - chip::MutableByteSpan outputSsid(ap.ssid, WFX_MAX_SSID_LENGTH); - chip::CopySpanToMutableSpan(scannedSsid, outputSsid); - - // Check if the scanned ssid is the requested Ssid - chip::ByteSpan requestedSsid(wfx_rsi.scan_ssid, wfx_rsi.scan_ssid_length); - if (!requestedSsid.empty() && !requestedSsid.data_equal(scannedSsid)) - { - // Scanned SSID entry does not match the requested SSID. Continue to the next. - continue; - } - - // TODO: convert security mode from RSI to WFX - ap.security = static_cast(scan.security_mode); - ap.rssi = (-1) * scan.rssi_val; - - VerifyOrDie(sizeof(ap.bssid) == kWifiMacAddressLength); - VerifyOrDie(sizeof(scan.bssid) == kWifiMacAddressLength); - - chip::MutableByteSpan bssidSpan(ap.bssid, kWifiMacAddressLength); - chip::ByteSpan scanBssidSpan(scan.bssid, kWifiMacAddressLength); - chip::CopySpanToMutableSpan(scanBssidSpan, bssidSpan); - - wfx_rsi.scan_cb(&ap); - - // If we reach this and the requestedSsid is not empty, it means we found the requested SSID and we can exit - if (!requestedSsid.empty()) - { - break; - } - } - // Notify the stack that we have finishes scanning for Networks - wfx_rsi.scan_cb(nullptr); - - // Clean up - wfx_rsi.scan_cb = nullptr; - if (wfx_rsi.scan_ssid) - { - chip::Platform::MemoryFree(wfx_rsi.scan_ssid); - wfx_rsi.scan_ssid = NULL; - } - } - break; - case WifiPlatformEvent::kStationStartJoin: { - // saving the AP related info - wfx_rsi_save_ap_info(); - // Joining to the network - sl_wifi_platform_join_network(); - } - break; - case WifiPlatformEvent::kStationDoDhcp: { - StartDHCPTimer(WFX_RSI_DHCP_POLL_INTERVAL); - } - break; - case WifiPlatformEvent::kStationDhcpDone: { - CancelDHCPTimer(); - } - break; - case WifiPlatformEvent::kStationDhcpPoll: { - HandleDHCPPolling(); - } - break; - default: - break; - } -} - -CHIP_ERROR InitWiFiStack(void) -{ - int32_t status = sl_matter_wifi_init(); - VerifyOrReturnError(status == RSI_SUCCESS, CHIP_ERROR_INTERNAL, - ChipLogError(DeviceLayer, "sl_matter_wifi_init failed: %lx", status)); - return CHIP_NO_ERROR; -} - -void MatterWifiTask(void * arg) +void WiseconnectWifiInterface::MatterWifiTask(void * arg) { (void) arg; WifiPlatformEvent event; chip::DeviceLayer::Silabs::Lwip::InitializeLwip(); - NotifyWifiTaskInitialized(); + WifiInterfaceImpl::GetInstance().NotifyWifiTaskInitialized(); ChipLogProgress(DeviceLayer, "MatterWifiTask: starting event loop"); for (;;) @@ -675,7 +658,7 @@ void MatterWifiTask(void * arg) osStatus_t status = osMessageQueueGet(sWifiEventQueue, &event, NULL, osWaitForever); if (status == osOK) { - ProcessEvent(event); + WifiInterfaceImpl::GetInstance().ProcessEvent(event); } else { @@ -683,3 +666,7 @@ void MatterWifiTask(void * arg) } } } + +} // namespace Silabs +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/silabs/wifi/rs911x/WifiInterfaceImpl.h b/src/platform/silabs/wifi/rs911x/WifiInterfaceImpl.h new file mode 100644 index 00000000000000..967732bfae153e --- /dev/null +++ b/src/platform/silabs/wifi/rs911x/WifiInterfaceImpl.h @@ -0,0 +1,111 @@ +/* + * + * Copyright (c) 2025 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include + +namespace chip { +namespace DeviceLayer { +namespace Silabs { + +/** + * @brief WifiInterface implementation for the SiWx platform + * + */ +class WifiInterfaceImpl final : public WiseconnectWifiInterface +{ +public: + static WifiInterfaceImpl & GetInstance() { return mInstance; } + + WifiInterfaceImpl(const WifiInterfaceImpl &) = delete; + WifiInterfaceImpl & operator=(const WifiInterfaceImpl &) = delete; + + /* + * WifiInterface impl + */ + + CHIP_ERROR InitWiFiStack(void) override; + CHIP_ERROR GetAccessPointInfo(wfx_wifi_scan_result_t & info) override; + CHIP_ERROR GetAccessPointExtendedInfo(wfx_wifi_scan_ext_t & info) override; + CHIP_ERROR ResetCounters() override; +#if CHIP_CONFIG_ENABLE_ICD_SERVER + CHIP_ERROR ConfigureBroadcastFilter(bool enableBroadcastFilter) override; + CHIP_ERROR ConfigurePowerSave() override; +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER + + /** + * @brief + * + * TODO: Current inheritance structure with the task creation in the parent forces this function to be public when it shouldn't + * be. This isn't the best practice and we should try to move this to protected. + * + * @param event + */ + void ProcessEvent(WiseconnectWifiInterface::WifiPlatformEvent event); + +protected: + /* + * WiseconnectWifiInterface impl + */ + + sl_status_t TriggerPlatformWifiDisconnection() override; + void PostWifiPlatformEvent(WifiPlatformEvent event) override; + +private: + WifiInterfaceImpl() = default; + ~WifiInterfaceImpl() = default; + + /** + * @brief Callback function on a succesfull join operation + * + * See the third_party/silabs/wiseconnect-wifi-bt-sdk/sapi/wlan/rsi_wlan_apis.c + * rsi_wlan_connect_async documentation for the argument definitions + */ + static void JoinCallback(uint16_t status, const uint8_t * buf, const uint16_t len); + + /** + * @brief Callback function for a failed join operation + * + * See the third_party/silabs/wiseconnect-wifi-bt-sdk/sapi/wlan/rsi_wlan_apis.c + * rsi_wlan_register_callbacks documentation for the argument definitions + */ + static void JoinFailCallback(uint16_t status, uint8_t * buf, uint32_t len); + + /** + * @brief Platform Init for the RS911x platform + * + * @return int32_t RSI_SUCCESS, on succesfull init + * RSI_FAILURE, otherwise + */ + int32_t Rs911xPlatformInit(); + + /** + * @brief Triggers a connection attempt to the Wi-Fi network with the stored credentials + */ + void JoinWifiNetwork(); + + /** + * @brief Processing function responsible of executing the DHCP polling operation + * until we have an IPv6 or IPv4 address + */ + void HandleDHCPPolling(); + + static WifiInterfaceImpl mInstance; +}; + +} // namespace Silabs +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/silabs/wifi/rs911x/rs911x.gni b/src/platform/silabs/wifi/rs911x/rs911x.gni index 38549c14b94de3..ebde627e0e1883 100644 --- a/src/platform/silabs/wifi/rs911x/rs911x.gni +++ b/src/platform/silabs/wifi/rs911x/rs911x.gni @@ -18,6 +18,7 @@ import("${silabs_sdk_build_root}/efr32_sdk.gni") rs911x_src_plat = [ "${chip_root}/src/platform/silabs/wifi/rs911x/WifiInterfaceImpl.cpp", + "${chip_root}/src/platform/silabs/wifi/rs911x/WifiInterfaceImpl.h", "${chip_root}/src/platform/silabs/wifi/rs911x/ncp/rsi_hal_mcu_interrupt.c", "${chip_root}/src/platform/silabs/wifi/rs911x/ncp/rsi_hal_mcu_ioports.c", "${chip_root}/src/platform/silabs/wifi/rs911x/ncp/rsi_hal_mcu_timer.c", diff --git a/src/platform/silabs/wifi/wf200/WifiInterfaceImpl.cpp b/src/platform/silabs/wifi/wf200/WifiInterfaceImpl.cpp index d14c9d649e6425..538e822e8234f9 100644 --- a/src/platform/silabs/wifi/wf200/WifiInterfaceImpl.cpp +++ b/src/platform/silabs/wifi/wf200/WifiInterfaceImpl.cpp @@ -30,20 +30,18 @@ #include #include #include -#include #include #include #include +#include #include #include #include #include -#include -#include -#include using namespace ::chip; using namespace ::chip::DeviceLayer; +using namespace ::chip::DeviceLayer::Silabs; // TODO: This is a workaround because we depend on the platform lib which depends on the platform implementation. // As such we can't depend on the platform here as well @@ -60,8 +58,10 @@ StaticEventGroup_t wfxEventGroup; EventGroupHandle_t sl_wfx_event_group; TaskHandle_t wfx_events_task_handle; -static MacAddress ap_mac; +static WifiInterface::MacAddress ap_mac; +#if CHIP_DEVICE_CONFIG_ENABLE_IPV4 static uint32_t sta_ip; +#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ static wfx_wifi_scan_result_t ap_info; // Set Scan Parameters @@ -104,7 +104,7 @@ uint8_t softap_channel = SOFTAP_CHANNEL_DEFAULT; /* station network interface structures */ struct netif * sta_netif; -WifiCredentials wifi_provision; +WifiInterface::WifiCredentials wifi_provision; #define PUT_COUNTER(name) ChipLogDetail(DeviceLayer, "%-24s %lu", #name, (unsigned long) counters->body.count_##name); bool hasNotifiedWifiConnectivity = false; @@ -121,13 +121,7 @@ static uint8_t * scan_ssid = nullptr; /* Which one are we scanning for */ static size_t scan_ssid_length = 0; static void sl_wfx_scan_result_callback(sl_wfx_scan_result_ind_body_t * scan_result); static void sl_wfx_scan_complete_callback(uint32_t status); -static sl_status_t wfx_wifi_hw_start(void); -static void wfx_events_task(void * p_arg); - -/* WF200 host callbacks */ -static void sl_wfx_connect_callback(sl_wfx_connect_ind_body_t connect_indication_body); -static void sl_wfx_disconnect_callback(uint8_t * mac, uint16_t reason); static void sl_wfx_generic_status_callback(sl_wfx_generic_ind_t * frame); #ifdef SL_WFX_CONFIG_SOFTAP @@ -144,7 +138,7 @@ namespace { // wfx_fmac_driver context sl_wfx_context_t wifiContext; -chip::BitFlags wifi_extra; +chip::BitFlags wifi_extra; typedef struct __attribute__((__packed__)) sl_wfx_get_counters_cnf_body_s { @@ -322,284 +316,6 @@ void GotIPv4Address(uint32_t ip) } // namespace -CHIP_ERROR GetMacAddress(sl_wfx_interface_t interface, MutableByteSpan & address) -{ - VerifyOrReturnError(address.size() >= kWifiMacAddressLength, CHIP_ERROR_BUFFER_TOO_SMALL); - -#ifdef SL_WFX_CONFIG_SOFTAP - chip::ByteSpan byteSpan((interface == SL_WFX_SOFTAP_INTERFACE) ? wifiContext.mac_addr_1.octet : wifiContext.mac_addr_0.octet); -#else - chip::ByteSpan byteSpan(wifiContext.mac_addr_0.octet); -#endif - - return CopySpanToMutableSpan(byteSpan, address); -} - -CHIP_ERROR StartNetworkScan(chip::ByteSpan ssid, ScanCallback callback) -{ - VerifyOrReturnError(callback != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - - // SSID Max Length that is supported by the Wi-Fi SDK is 32 - VerifyOrReturnError(ssid.size() <= WFX_MAX_SSID_LENGTH, CHIP_ERROR_INVALID_STRING_LENGTH); - - // Make sure memory is cleared before starting a new scan - if (scan_ssid) - { - chip::Platform::MemoryFree(scan_ssid); - scan_ssid = nullptr; - } - - if (ssid.empty()) - { - scan_ssid_length = 0; - scan_ssid = nullptr; - } - else - { - scan_ssid_length = ssid.size(); - scan_ssid = reinterpret_cast(chip::Platform::MemoryAlloc(scan_ssid_length)); - VerifyOrReturnError(scan_ssid != nullptr, CHIP_ERROR_NO_MEMORY); - - chip::MutableByteSpan scannedSsidSpan(scan_ssid, WFX_MAX_SSID_LENGTH); - chip::CopySpanToMutableSpan(ssid, scannedSsidSpan); - } - scan_cb = callback; - - xEventGroupSetBits(sl_wfx_event_group, SL_WFX_SCAN_START); - return CHIP_NO_ERROR; -} - -CHIP_ERROR StartWifiTask() -{ - if (wifi_extra.Has(WifiState::kStationInit)) - { - ChipLogDetail(DeviceLayer, "WIFI: Already started"); - return CHIP_NO_ERROR; - } - wifi_extra.Set(WifiState::kStationInit); - - VerifyOrReturnError(wfx_soft_init() == SL_STATUS_OK, CHIP_ERROR_INTERNAL, - ChipLogError(DeviceLayer, "Failed to execute the WFX software init.")); - VerifyOrReturnError(wfx_wifi_hw_start() == SL_STATUS_OK, CHIP_ERROR_INTERNAL, - ChipLogError(DeviceLayer, "Failed to execute the WFX HW start.")); - - return CHIP_NO_ERROR; -} - -void ConfigureStationMode() -{ - wifi_extra.Set(WifiState::kStationMode); -} - -bool IsStationModeEnabled(void) -{ - return wifi_extra.Has(WifiState::kStationMode); -} - -bool IsStationConnected() -{ - return wifi_extra.Has(WifiState::kStationConnected); -} - -bool IsStationReady() -{ - return wifi_extra.Has(WifiState::kStationInit); -} - -CHIP_ERROR TriggerDisconnection(void) -{ - ChipLogProgress(DeviceLayer, "STA-Disconnecting"); - - sl_status_t status = sl_wfx_send_disconnect_command(); - VerifyOrReturnError(status == SL_STATUS_OK, CHIP_ERROR_INTERNAL); - - wifi_extra.Clear(WifiState::kStationConnected); - - xEventGroupSetBits(sl_wfx_event_group, SL_WFX_RETRY_CONNECT); - return CHIP_NO_ERROR; -} - -CHIP_ERROR GetAccessPointInfo(wfx_wifi_scan_result_t & info) -{ - uint32_t signal_strength = 0; - - // TODO: The ap_info.ssid isn't populated anywhere. The returned value is always 0. - chip::ByteSpan apSsidSpan(ap_info.ssid, ap_info.ssid_length); - chip::MutableByteSpan apSsidMutableSpan(info.ssid, WFX_MAX_SSID_LENGTH); - chip::CopySpanToMutableSpan(apSsidSpan, apSsidMutableSpan); - info.ssid_length = apSsidMutableSpan.size(); - - // TODO: The ap_info.bssid isn't populated anywhere. The returned value is always 0. - chip::ByteSpan apBssidSpan(ap_info.bssid, kWifiMacAddressLength); - chip::MutableByteSpan apBssidMutableSpan(info.bssid, kWifiMacAddressLength); - chip::CopySpanToMutableSpan(apBssidSpan, apBssidMutableSpan); - - info.security = ap_info.security; - info.chan = ap_info.chan; - - sl_status_t status = sl_wfx_get_signal_strength(&signal_strength); - VerifyOrReturnError(status == SL_STATUS_OK, CHIP_ERROR_INTERNAL); - - info.rssi = ConvertRcpiToRssi(signal_strength); - - ChipLogDetail(DeviceLayer, "WIFI:SSID : %s", ap_info.ssid); - ChipLogDetail(DeviceLayer, "WIFI:BSSID : %02x:%02x:%02x:%02x:%02x:%02x", ap_info.bssid[0], ap_info.bssid[1], - ap_info.bssid[2], ap_info.bssid[3], ap_info.bssid[4], ap_info.bssid[5]); - ChipLogDetail(DeviceLayer, "WIFI:security : %d", info.security); - ChipLogDetail(DeviceLayer, "WIFI:channel : %d", info.chan); - ChipLogDetail(DeviceLayer, "signal_strength: %ld", signal_strength); - - return CHIP_NO_ERROR; -} - -CHIP_ERROR GetAccessPointExtendedInfo(wfx_wifi_scan_ext_t & info) -{ - sl_status_t status = get_all_counters(); - VerifyOrReturnError(status == SL_STATUS_OK, CHIP_ERROR_INTERNAL, ChipLogError(DeviceLayer, "Failed to get the couters")); - - info.beacon_lost_count = counters->body.count_miss_beacon; - info.beacon_rx_count = counters->body.count_rx_beacon; - info.mcast_rx_count = counters->body.count_rx_multicast_frames; - info.mcast_tx_count = counters->body.count_tx_multicast_frames; - info.ucast_rx_count = counters->body.count_rx_packets; - info.ucast_tx_count = counters->body.count_tx_packets; - info.overrun_count = gOverrunCount; - - return CHIP_NO_ERROR; -} - -#if CHIP_CONFIG_ENABLE_ICD_SERVER -CHIP_ERROR ConfigurePowerSave() -{ - // TODO: Implement Power save configuration. We do a silent failure to avoid causing problems in higher layers. - return CHIP_NO_ERROR; -} - -CHIP_ERROR ConfigureBroadcastFilter(bool enableBroadcastFilter) -{ - // TODO: Implement Broadcast filtering. We do a silent failure to avoid causing problems in higher layers. - return CHIP_NO_ERROR; -} -#endif // CHIP_CONFIG_ENABLE_ICD_SERVER - -CHIP_ERROR ResetCounters() -{ - // TODO: Implement the function - return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; -} - -void ClearWifiCredentials() -{ - wifi_provision.Clear(); -} - -CHIP_ERROR GetWifiCredentials(WifiCredentials & credentials) -{ - VerifyOrReturnError(IsWifiProvisioned(), CHIP_ERROR_INCORRECT_STATE); - credentials = wifi_provision; - - return CHIP_NO_ERROR; -} - -bool IsWifiProvisioned() -{ - // TODO: We need a better way of checking if we are provisioned or not - return wifi_provision.ssid[0] != 0; -} - -void SetWifiCredentials(const WifiCredentials & credentials) -{ - wifi_provision = credentials; -} - -CHIP_ERROR ConnectToAccessPoint(void) -{ - sl_wfx_security_mode_t connect_security_mode; - - VerifyOrReturnError(IsWifiProvisioned(), CHIP_ERROR_INCORRECT_STATE); - ChipLogDetail(DeviceLayer, "WIFI:JOIN to %s", wifi_provision.ssid); - - ChipLogDetail(DeviceLayer, - "WIFI Scan Paramter set to Active channel time %d, Passive Channel " - "Time: %d, Number of prob: %d", - ACTIVE_CHANNEL_TIME, PASSIVE_CHANNEL_TIME, NUM_PROBE_REQUEST); - (void) sl_wfx_set_scan_parameters(ACTIVE_CHANNEL_TIME, PASSIVE_CHANNEL_TIME, NUM_PROBE_REQUEST); - switch (wifi_provision.security) - { - case WFX_SEC_WEP: - connect_security_mode = sl_wfx_security_mode_e::WFM_SECURITY_MODE_WEP; - break; - case WFX_SEC_WPA: - case WFX_SEC_WPA2: - connect_security_mode = sl_wfx_security_mode_e::WFM_SECURITY_MODE_WPA2_WPA1_PSK; - break; - case WFX_SEC_WPA3: - connect_security_mode = sl_wfx_security_mode_e::WFM_SECURITY_MODE_WPA3_SAE; - break; - case WFX_SEC_NONE: - connect_security_mode = sl_wfx_security_mode_e::WFM_SECURITY_MODE_OPEN; - break; - default: - ChipLogError(DeviceLayer, "error: unknown security type."); - return CHIP_ERROR_INVALID_ARGUMENT; - } - - VerifyOrReturnError(sl_wfx_send_join_command(wifi_provision.ssid, wifi_provision.ssidLength, NULL, CHANNEL_0, - connect_security_mode, PREVENT_ROAMING, DISABLE_PMF_MODE, wifi_provision.passkey, - wifi_provision.passkeyLength, NULL, IE_DATA_LENGTH) == SL_STATUS_OK, - CHIP_ERROR_INTERNAL); - - return CHIP_NO_ERROR; -} - -bool HasAnIPv4Address() -{ - return (sta_ip == STA_IP_FAIL) ? false : true; -} - -bool HasAnIPv6Address() -{ - return IsStationConnected(); -} - -void CancelScanNetworks() -{ - struct scan_result_holder *hp, *next; - /* Not possible */ - VerifyOrReturn(scan_cb != nullptr); - sl_wfx_send_stop_scan_command(); - for (hp = scan_save; hp; hp = next) - { - next = hp->next; - chip::Platform::MemoryFree(hp); - } - scan_save = (struct scan_result_holder *) 0; - scan_count = 0; - if (scan_ssid) - { - chip::Platform::MemoryFree(scan_ssid); - scan_ssid = nullptr; - } - scan_cb = nullptr; -} - -/*************************************************************************** - * @brief - * Creates WFX events processing task. - ******************************************************************************/ -static void wfx_events_task_start(void) -{ - /* create an event group to track Wi-Fi events */ - sl_wfx_event_group = xEventGroupCreateStatic(&wfxEventGroup); - - wfx_events_task_handle = xTaskCreateStatic(wfx_events_task, "wfx_events", WLAN_TASK_STACK_SIZE, NULL, WLAN_TASK_PRIORITY, - wfxEventTaskStack, &wfxEventTaskBuffer); - if (NULL == wfx_events_task_handle) - { - ChipLogError(DeviceLayer, "Failed to create WFX wfx_events"); - } -} - /**************************************************************************** * @brief * Called when the driver needs to post an event @@ -619,12 +335,13 @@ extern "C" sl_status_t sl_wfx_host_process_event(sl_wfx_generic_message_t * even } case SL_WFX_CONNECT_IND_ID: { sl_wfx_connect_ind_t * connect_indication = (sl_wfx_connect_ind_t *) event_payload; - sl_wfx_connect_callback(connect_indication->body); + WifiInterfaceImpl::GetInstance().ConnectionEventCallback(connect_indication->body); break; } case SL_WFX_DISCONNECT_IND_ID: { sl_wfx_disconnect_ind_t * disconnect_indication = (sl_wfx_disconnect_ind_t *) event_payload; - sl_wfx_disconnect_callback(disconnect_indication->body.mac, disconnect_indication->body.reason); + WifiInterfaceImpl::GetInstance().DisconnectionEventCallback(disconnect_indication->body.mac, + disconnect_indication->body.reason); break; } case SL_WFX_RECEIVED_IND_ID: { @@ -787,84 +504,16 @@ static void sl_wfx_scan_complete_callback(uint32_t status) xEventGroupSetBits(sl_wfx_event_group, SL_WFX_SCAN_COMPLETE); } +#ifdef SL_WFX_CONFIG_SOFTAP /**************************************************************************** * @brief - * Callback when station connects - * @param[in] mac: MAC address of device - * @param[in] status: Status of connect call + * Callback for AP started + * @param[in] status: Status of wfx start ap api *****************************************************************************/ -static void sl_wfx_connect_callback(sl_wfx_connect_ind_body_t connect_indication_body) -{ - uint8_t * mac = connect_indication_body.mac; - uint32_t status = connect_indication_body.status; - ap_info.chan = connect_indication_body.channel; - memcpy(&ap_info.security, &wifi_provision.security, sizeof(wifi_provision.security)); - switch (status) - { - case WFM_STATUS_SUCCESS: { - ChipLogProgress(DeviceLayer, "STA-Connected"); - memcpy(ap_mac.data(), mac, kWifiMacAddressLength); - - wifi_extra.Set(WifiState::kStationConnected); - xEventGroupSetBits(sl_wfx_event_group, SL_WFX_CONNECT); - break; - } - case WFM_STATUS_NO_MATCHING_AP: { - ChipLogError(DeviceLayer, "Connection failed, access point not found"); - break; - } - case WFM_STATUS_CONNECTION_ABORTED: { - ChipLogError(DeviceLayer, "Connection aborted"); - break; - } - case WFM_STATUS_CONNECTION_TIMEOUT: { - ChipLogError(DeviceLayer, "Connection timeout"); - break; - } - case WFM_STATUS_CONNECTION_REJECTED_BY_AP: { - ChipLogError(DeviceLayer, "Connection rejected by the access point"); - break; - } - case WFM_STATUS_CONNECTION_AUTH_FAILURE: { - ChipLogError(DeviceLayer, "Connection authentication failure"); - break; - } - default: { - ChipLogError(DeviceLayer, "Connection attempt error"); - } - } - - if (status != WFM_STATUS_SUCCESS) - { - ScheduleConnectionAttempt(); - } -} - -/**************************************************************************** - * @brief - * Callback for station disconnect - * @param[in] mac: MAC address of device - * @param[in] reason: Reason code of disconnection - *****************************************************************************/ -static void sl_wfx_disconnect_callback(uint8_t * mac, uint16_t reason) -{ - (void) (mac); - ChipLogProgress(DeviceLayer, "Disconnected %d", reason); - wifi_extra.Clear(WifiState::kStationConnected); - - ScheduleConnectionAttempt(); -} - -#ifdef SL_WFX_CONFIG_SOFTAP -/**************************************************************************** - * @brief - * Callback for AP started - * @param[in] status: Status of wfx start ap api - *****************************************************************************/ -static void sl_wfx_start_ap_callback(uint32_t status) +static void sl_wfx_start_ap_callback(uint32_t status) { VerifyOrReturnLogError(status == AP_START_SUCCESS, CHIP_ERROR_INTERNAL); - wifi_extra.Set(WifiState::kAPReady); + wifi_extra.Set(WifiInterface::WifiState::kAPReady); xEventGroupSetBits(sl_wfx_event_group, SL_WFX_START_AP); } @@ -878,7 +527,7 @@ static void sl_wfx_stop_ap_callback(void) // TODO // dhcpserver_clear_stored_mac(); ChipLogProgress(DeviceLayer, "SoftAP stopped"); - wifi_extra.Clear(WifiState::kAPReady); + wifi_extra.Clear(WifiInterface::WifiState::kAPReady); xEventGroupSetBits(sl_wfx_event_group, SL_WFX_STOP_AP); } @@ -929,16 +578,352 @@ static void sl_wfx_generic_status_callback(sl_wfx_generic_ind_t * frame) (void) (frame); } -/*************************************************************************** - * @brief - * WFX events processing task. - * @param[in] p_arg: - * ******************************************************************************/ -static void wfx_events_task(void * p_arg) +namespace chip { +namespace DeviceLayer { +namespace Silabs { + +WifiInterfaceImpl WifiInterfaceImpl::mInstance; + +WifiInterface & WifiInterface::GetInstance() +{ + return WifiInterfaceImpl::GetInstance(); +} + +CHIP_ERROR WifiInterfaceImpl::InitWiFiStack() +{ + // TODO: This function should include sl_wfx_hw_init() and sl_wfx_init() functions. Only done now to make MatterConfig platform + // agnostic. (MATTER-4680) + // Start wfx bus communication task. + sl_status_t status = wfx_bus_start(); + VerifyOrReturnError(status == SL_STATUS_OK, CHIP_ERROR_NO_MEMORY, + ChipLogError(DeviceLayer, "wfx_bus_start failed: %lx", status)); + return CHIP_NO_ERROR; +} + +CHIP_ERROR WifiInterfaceImpl::GetMacAddress(sl_wfx_interface_t interface, MutableByteSpan & address) +{ + VerifyOrReturnError(address.size() >= kWifiMacAddressLength, CHIP_ERROR_BUFFER_TOO_SMALL); + +#ifdef SL_WFX_CONFIG_SOFTAP + chip::ByteSpan byteSpan((interface == SL_WFX_SOFTAP_INTERFACE) ? wifiContext.mac_addr_1.octet : wifiContext.mac_addr_0.octet); +#else + chip::ByteSpan byteSpan(wifiContext.mac_addr_0.octet); +#endif + + return CopySpanToMutableSpan(byteSpan, address); +} + +CHIP_ERROR WifiInterfaceImpl::StartNetworkScan(chip::ByteSpan ssid, ScanCallback callback) +{ + VerifyOrReturnError(callback != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + + // SSID Max Length that is supported by the Wi-Fi SDK is 32 + VerifyOrReturnError(ssid.size() <= WFX_MAX_SSID_LENGTH, CHIP_ERROR_INVALID_STRING_LENGTH); + + // Make sure memory is cleared before starting a new scan + if (scan_ssid) + { + chip::Platform::MemoryFree(scan_ssid); + scan_ssid = nullptr; + } + + if (ssid.empty()) + { + scan_ssid_length = 0; + scan_ssid = nullptr; + } + else + { + scan_ssid_length = ssid.size(); + scan_ssid = reinterpret_cast(chip::Platform::MemoryAlloc(scan_ssid_length)); + VerifyOrReturnError(scan_ssid != nullptr, CHIP_ERROR_NO_MEMORY); + + chip::MutableByteSpan scannedSsidSpan(scan_ssid, WFX_MAX_SSID_LENGTH); + chip::CopySpanToMutableSpan(ssid, scannedSsidSpan); + } + scan_cb = callback; + + xEventGroupSetBits(sl_wfx_event_group, SL_WFX_SCAN_START); + return CHIP_NO_ERROR; +} + +CHIP_ERROR WifiInterfaceImpl::StartWifiTask() +{ + if (wifi_extra.Has(WifiInterface::WifiState::kStationInit)) + { + ChipLogDetail(DeviceLayer, "WIFI: Already started"); + return CHIP_NO_ERROR; + } + wifi_extra.Set(WifiInterface::WifiState::kStationInit); + + VerifyOrReturnError(wfx_soft_init() == SL_STATUS_OK, CHIP_ERROR_INTERNAL, + ChipLogError(DeviceLayer, "Failed to execute the WFX software init.")); + VerifyOrReturnError(InitWf200Platform() == SL_STATUS_OK, CHIP_ERROR_INTERNAL, + ChipLogError(DeviceLayer, "Failed to execute the WFX HW start.")); + + return CHIP_NO_ERROR; +} + +void WifiInterfaceImpl::ConfigureStationMode() +{ + wifi_extra.Set(WifiInterface::WifiState::kStationMode); +} + +bool WifiInterfaceImpl::IsStationModeEnabled(void) +{ + return wifi_extra.Has(WifiInterface::WifiState::kStationMode); +} + +bool WifiInterfaceImpl::IsStationConnected() +{ + return wifi_extra.Has(WifiInterface::WifiState::kStationConnected); +} + +bool WifiInterfaceImpl::IsStationReady() +{ + return wifi_extra.Has(WifiInterface::WifiState::kStationInit); +} + +CHIP_ERROR WifiInterfaceImpl::TriggerDisconnection(void) +{ + ChipLogProgress(DeviceLayer, "STA-Disconnecting"); + + sl_status_t status = sl_wfx_send_disconnect_command(); + VerifyOrReturnError(status == SL_STATUS_OK, CHIP_ERROR_INTERNAL); + + wifi_extra.Clear(WifiInterface::WifiState::kStationConnected); + + xEventGroupSetBits(sl_wfx_event_group, SL_WFX_RETRY_CONNECT); + return CHIP_NO_ERROR; +} + +CHIP_ERROR WifiInterfaceImpl::GetAccessPointInfo(wfx_wifi_scan_result_t & info) +{ + uint32_t signal_strength = 0; + + // TODO: The ap_info.ssid isn't populated anywhere. The returned value is always 0. + chip::ByteSpan apSsidSpan(ap_info.ssid, ap_info.ssid_length); + chip::MutableByteSpan apSsidMutableSpan(info.ssid, WFX_MAX_SSID_LENGTH); + chip::CopySpanToMutableSpan(apSsidSpan, apSsidMutableSpan); + info.ssid_length = apSsidMutableSpan.size(); + + // TODO: The ap_info.bssid isn't populated anywhere. The returned value is always 0. + chip::ByteSpan apBssidSpan(ap_info.bssid, kWifiMacAddressLength); + chip::MutableByteSpan apBssidMutableSpan(info.bssid, kWifiMacAddressLength); + chip::CopySpanToMutableSpan(apBssidSpan, apBssidMutableSpan); + + info.security = ap_info.security; + info.chan = ap_info.chan; + + sl_status_t status = sl_wfx_get_signal_strength(&signal_strength); + VerifyOrReturnError(status == SL_STATUS_OK, CHIP_ERROR_INTERNAL); + + info.rssi = ConvertRcpiToRssi(signal_strength); + + ChipLogDetail(DeviceLayer, "WIFI:SSID : %s", ap_info.ssid); + ChipLogDetail(DeviceLayer, "WIFI:BSSID : %02x:%02x:%02x:%02x:%02x:%02x", ap_info.bssid[0], ap_info.bssid[1], + ap_info.bssid[2], ap_info.bssid[3], ap_info.bssid[4], ap_info.bssid[5]); + ChipLogDetail(DeviceLayer, "WIFI:security : %d", info.security); + ChipLogDetail(DeviceLayer, "WIFI:channel : %d", info.chan); + ChipLogDetail(DeviceLayer, "signal_strength: %ld", signal_strength); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR WifiInterfaceImpl::GetAccessPointExtendedInfo(wfx_wifi_scan_ext_t & info) +{ + sl_status_t status = get_all_counters(); + VerifyOrReturnError(status == SL_STATUS_OK, CHIP_ERROR_INTERNAL, ChipLogError(DeviceLayer, "Failed to get the couters")); + + info.beacon_lost_count = counters->body.count_miss_beacon; + info.beacon_rx_count = counters->body.count_rx_beacon; + info.mcast_rx_count = counters->body.count_rx_multicast_frames; + info.mcast_tx_count = counters->body.count_tx_multicast_frames; + info.ucast_rx_count = counters->body.count_rx_packets; + info.ucast_tx_count = counters->body.count_tx_packets; + info.overrun_count = gOverrunCount; + + return CHIP_NO_ERROR; +} + +#if CHIP_CONFIG_ENABLE_ICD_SERVER +CHIP_ERROR WifiInterfaceImpl::ConfigurePowerSave() +{ + // TODO: Implement Power save configuration. We do a silent failure to avoid causing problems in higher layers. + return CHIP_NO_ERROR; +} + +CHIP_ERROR WifiInterfaceImpl::ConfigureBroadcastFilter(bool enableBroadcastFilter) +{ + // TODO: Implement Broadcast filtering. We do a silent failure to avoid causing problems in higher layers. + return CHIP_NO_ERROR; +} +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER + +CHIP_ERROR WifiInterfaceImpl::ResetCounters() +{ + // TODO: Implement the function + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; +} + +void WifiInterfaceImpl::ClearWifiCredentials() +{ + wifi_provision.Clear(); +} + +CHIP_ERROR WifiInterfaceImpl::GetWifiCredentials(WifiCredentials & credentials) +{ + VerifyOrReturnError(IsWifiProvisioned(), CHIP_ERROR_INCORRECT_STATE); + credentials = wifi_provision; + + return CHIP_NO_ERROR; +} + +bool WifiInterfaceImpl::IsWifiProvisioned() +{ + // TODO: We need a better way of checking if we are provisioned or not + return wifi_provision.ssid[0] != 0; +} + +void WifiInterfaceImpl::SetWifiCredentials(const WifiCredentials & credentials) +{ + wifi_provision = credentials; +} + +CHIP_ERROR WifiInterfaceImpl::ConnectToAccessPoint(void) +{ + sl_wfx_security_mode_t connect_security_mode; + + VerifyOrReturnError(IsWifiProvisioned(), CHIP_ERROR_INCORRECT_STATE); + ChipLogDetail(DeviceLayer, "WIFI:JOIN to %s", wifi_provision.ssid); + + ChipLogDetail(DeviceLayer, + "WIFI Scan Paramter set to Active channel time %d, Passive Channel " + "Time: %d, Number of prob: %d", + ACTIVE_CHANNEL_TIME, PASSIVE_CHANNEL_TIME, NUM_PROBE_REQUEST); + (void) sl_wfx_set_scan_parameters(ACTIVE_CHANNEL_TIME, PASSIVE_CHANNEL_TIME, NUM_PROBE_REQUEST); + switch (wifi_provision.security) + { + case WFX_SEC_WEP: + connect_security_mode = sl_wfx_security_mode_e::WFM_SECURITY_MODE_WEP; + break; + case WFX_SEC_WPA: + case WFX_SEC_WPA2: + connect_security_mode = sl_wfx_security_mode_e::WFM_SECURITY_MODE_WPA2_WPA1_PSK; + break; + case WFX_SEC_WPA3: + connect_security_mode = sl_wfx_security_mode_e::WFM_SECURITY_MODE_WPA3_SAE; + break; + case WFX_SEC_NONE: + connect_security_mode = sl_wfx_security_mode_e::WFM_SECURITY_MODE_OPEN; + break; + default: + ChipLogError(DeviceLayer, "error: unknown security type."); + return CHIP_ERROR_INVALID_ARGUMENT; + } + + VerifyOrReturnError(sl_wfx_send_join_command(wifi_provision.ssid, wifi_provision.ssidLength, NULL, CHANNEL_0, + connect_security_mode, PREVENT_ROAMING, DISABLE_PMF_MODE, wifi_provision.passkey, + wifi_provision.passkeyLength, NULL, IE_DATA_LENGTH) == SL_STATUS_OK, + CHIP_ERROR_INTERNAL); + + return CHIP_NO_ERROR; +} + +#if CHIP_DEVICE_CONFIG_ENABLE_IPV4 +bool WifiInterfaceImpl::HasAnIPv4Address() +{ + return (sta_ip == STA_IP_FAIL) ? false : true; +} +#endif // CHIP_DEVICE_CONFIG_ENABLE_IPV4 + +bool WifiInterfaceImpl::HasAnIPv6Address() +{ + return IsStationConnected(); +} + +void WifiInterfaceImpl::CancelScanNetworks() +{ + struct scan_result_holder *hp, *next; + /* Not possible */ + VerifyOrReturn(scan_cb != nullptr); + sl_wfx_send_stop_scan_command(); + for (hp = scan_save; hp; hp = next) + { + next = hp->next; + chip::Platform::MemoryFree(hp); + } + scan_save = (struct scan_result_holder *) 0; + scan_count = 0; + if (scan_ssid) + { + chip::Platform::MemoryFree(scan_ssid); + scan_ssid = nullptr; + } + scan_cb = nullptr; +} + +void WifiInterfaceImpl::ConnectionEventCallback(sl_wfx_connect_ind_body_t connect_indication_body) +{ + uint8_t * mac = connect_indication_body.mac; + uint32_t status = connect_indication_body.status; + ap_info.chan = connect_indication_body.channel; + memcpy(&ap_info.security, &wifi_provision.security, sizeof(wifi_provision.security)); + switch (status) + { + case WFM_STATUS_SUCCESS: { + ChipLogProgress(DeviceLayer, "STA-Connected"); + memcpy(ap_mac.data(), mac, kWifiMacAddressLength); + + wifi_extra.Set(WifiInterface::WifiState::kStationConnected); + xEventGroupSetBits(sl_wfx_event_group, SL_WFX_CONNECT); + break; + } + case WFM_STATUS_NO_MATCHING_AP: { + ChipLogError(DeviceLayer, "Connection failed, access point not found"); + break; + } + case WFM_STATUS_CONNECTION_ABORTED: { + ChipLogError(DeviceLayer, "Connection aborted"); + break; + } + case WFM_STATUS_CONNECTION_TIMEOUT: { + ChipLogError(DeviceLayer, "Connection timeout"); + break; + } + case WFM_STATUS_CONNECTION_REJECTED_BY_AP: { + ChipLogError(DeviceLayer, "Connection rejected by the access point"); + break; + } + case WFM_STATUS_CONNECTION_AUTH_FAILURE: { + ChipLogError(DeviceLayer, "Connection authentication failure"); + break; + } + default: { + ChipLogError(DeviceLayer, "Connection attempt error"); + } + } + + if (status != WFM_STATUS_SUCCESS) + { + ScheduleConnectionAttempt(); + } +} + +void WifiInterfaceImpl::DisconnectionEventCallback(uint8_t * mac, uint16_t reason) +{ + (void) (mac); + ChipLogProgress(DeviceLayer, "Disconnected %d", reason); + wifi_extra.Clear(WifiInterface::WifiState::kStationConnected); + + ScheduleConnectionAttempt(); +} + +void WifiInterfaceImpl::ProcessEvents(void * arg) { TickType_t last_dhcp_poll, now; EventBits_t flags; - (void) p_arg; + (void) arg; sta_netif = chip::DeviceLayer::Silabs::Lwip::GetNetworkInterface(SL_WFX_STA_INTERFACE); last_dhcp_poll = xTaskGetTickCount(); @@ -954,23 +939,23 @@ static void wfx_events_task(void * p_arg) if (flags & SL_WFX_RETRY_CONNECT) { ChipLogProgress(DeviceLayer, "sending the connect command"); - ConnectToAccessPoint(); + WifiInterface::GetInstance().ConnectToAccessPoint(); } - if (wifi_extra.Has(WifiState::kStationConnected)) + if (wifi_extra.Has(WifiInterface::WifiState::kStationConnected)) { if ((now = xTaskGetTickCount()) > (last_dhcp_poll + pdMS_TO_TICKS(250))) { #if (CHIP_DEVICE_CONFIG_ENABLE_IPV4) uint8_t dhcp_state = dhcpclient_poll(sta_netif); - if ((dhcp_state == DHCP_ADDRESS_ASSIGNED) && !HasNotifiedIPv4Change()) + if ((dhcp_state == DHCP_ADDRESS_ASSIGNED) && !WifiInterfaceImpl::GetIstance().HasNotifiedIPv4()) { - GotIPv4Address((uint32_t) sta_netif->ip_addr.u_addr.ip4.addr); + WifiInterface::GetInstance().GotIPv4Address((uint32_t) sta_netif->ip_addr.u_addr.ip4.addr); if (!hasNotifiedWifiConnectivity) { ChipLogProgress(DeviceLayer, "will notify WiFi connectivity"); - NotifyConnection(ap_mac); + WifiInterfaceImpl::GetInstance().NotifyConnection(ap_mac); hasNotifiedWifiConnectivity = true; } } @@ -979,12 +964,13 @@ static void wfx_events_task(void * p_arg) NotifyIPv4Change(false); } #endif // CHIP_DEVICE_CONFIG_ENABLE_IPV4 - if ((ip6_addr_ispreferred(netif_ip6_addr_state(sta_netif, 0))) && !HasNotifiedIPv6Change()) + if ((ip6_addr_ispreferred(netif_ip6_addr_state(sta_netif, 0))) && + !WifiInterfaceImpl::GetInstance().HasNotifiedIPv6()) { - NotifyIPv6Change(true); + WifiInterfaceImpl::GetInstance().NotifyIPv6Change(true); if (!hasNotifiedWifiConnectivity) { - NotifyConnection(ap_mac); + WifiInterfaceImpl::GetInstance().NotifyConnection(ap_mac); hasNotifiedWifiConnectivity = true; } } @@ -995,15 +981,15 @@ static void wfx_events_task(void * p_arg) if (flags & SL_WFX_CONNECT) { #if (CHIP_DEVICE_CONFIG_ENABLE_IPV4) - NotifyIPv4Change(false); + WifiInterfaceImpl::GetInstance().NotifyIPv4Change(false); #endif // CHIP_DEVICE_CONFIG_ENABLE_IPV4 - NotifyIPv6Change(false); + WifiInterfaceImpl::GetInstance().NotifyIPv6Change(false); hasNotifiedWifiConnectivity = false; ChipLogProgress(DeviceLayer, "connected to AP"); - wifi_extra.Set(WifiState::kStationConnected); + wifi_extra.Set(WifiInterface::WifiState::kStationConnected); chip::DeviceLayer::Silabs::Lwip::SetLwipStationLinkUp(); #if CHIP_CONFIG_ENABLE_ICD_SERVER - if (!(wifi_extra.Has(WifiState::kAPReady))) + if (!(wifi_extra.Has(WifiInterface::WifiState::kAPReady))) { // Enable the power save ChipLogProgress(DeviceLayer, "WF200 going to DTIM based sleep"); @@ -1017,11 +1003,11 @@ static void wfx_events_task(void * p_arg) { #if (CHIP_DEVICE_CONFIG_ENABLE_IPV4) - NotifyIPv4Change(false); + WifiInterfaceImpl::GetInstance().NotifyIPv4Change(false); #endif // CHIP_DEVICE_CONFIG_ENABLE_IPV4 - NotifyIPv6Change(false); + WifiInterfaceImpl::GetInstance().NotifyIPv6Change(false); hasNotifiedWifiConnectivity = false; - wifi_extra.Clear(WifiState::kStationConnected); + wifi_extra.Clear(WifiInterface::WifiState::kStationConnected); chip::DeviceLayer::Silabs::Lwip::SetLwipStationLinkDown(); } @@ -1088,14 +1074,48 @@ static void wfx_events_task(void * p_arg) } } -/**************************************************************************** - * @brief - * Initialize the WF200 used by the two interfaces - *****************************************************************************/ -static sl_status_t wfx_init(void) +sl_status_t WifiInterfaceImpl::InitWf200Platform() +{ + sl_status_t status = SL_STATUS_OK; + + VerifyOrReturnValue(!wifi_extra.Has(WifiInterface::WifiState::kStationStarted), SL_STATUS_OK); + + ChipLogDetail(DeviceLayer, "STARTING WF200"); + + sl_wfx_host_gpio_init(); + + status = wfx_init(); + VerifyOrReturnError(status == SL_STATUS_OK, status, ChipLogError(DeviceLayer, "WF200:init failed: %ld", status)); + + /* Initialize the LwIP stack */ + ChipLogDetail(DeviceLayer, "WF200:Start LWIP"); + chip::DeviceLayer::Silabs::Lwip::InitializeLwip(); + NotifyWifiTaskInitialized(); + + ChipLogDetail(DeviceLayer, "WF200:ready."); + wifi_extra.Set(WifiInterface::WifiState::kStationStarted); + + return SL_STATUS_OK; +} + +void WifiInterfaceImpl::StartWifiProcessTask() +{ + /* create an event group to track Wi-Fi events */ + sl_wfx_event_group = xEventGroupCreateStatic(&wfxEventGroup); + + wfx_events_task_handle = xTaskCreateStatic(ProcessEvents, "wfx_events", WLAN_TASK_STACK_SIZE, NULL, WLAN_TASK_PRIORITY, + wfxEventTaskStack, &wfxEventTaskBuffer); + if (NULL == wfx_events_task_handle) + { + // TODO: Verify if this needs to be a chip-die or not. + ChipLogError(DeviceLayer, "Failed to create WFX wfx_events"); + } +} + +sl_status_t WifiInterfaceImpl::wfx_init(void) { /* Initialize the WF200 used by the two interfaces */ - wfx_events_task_start(); + StartWifiProcessTask(); sl_status_t status = sl_wfx_init(&wifiContext); ChipLogProgress(DeviceLayer, "FMAC Driver version: %s", FMAC_DRIVER_VERSION_STRING); switch (status) @@ -1107,7 +1127,7 @@ static sl_status_t wfx_init(void) wifiContext.mac_addr_0.octet[4], wifiContext.mac_addr_0.octet[5]); ChipLogProgress(DeviceLayer, "WF200 Init OK"); - if (wifi_extra.Has(WifiState::kStationConnected)) + if (wifi_extra.Has(WifiInterface::WifiState::kStationConnected)) { sl_wfx_send_disconnect_command(); } @@ -1132,46 +1152,6 @@ static sl_status_t wfx_init(void) return status; } -/***************************************************************************** - * @brief - * tcp ip, wfx and lwip stack and start dhcp client. - * @return - * sl_status_t Shows init succes or error. - ******************************************************************************/ -static sl_status_t wfx_wifi_hw_start(void) -{ - sl_status_t status = SL_STATUS_OK; - - if (wifi_extra.Has(WifiState::kStationStarted)) - { - return SL_STATUS_OK; - } - - ChipLogDetail(DeviceLayer, "STARTING WF200"); - - sl_wfx_host_gpio_init(); - - status = wfx_init(); - VerifyOrReturnError(status == SL_STATUS_OK, status, ChipLogError(DeviceLayer, "WF200:init failed")); - - /* Initialize the LwIP stack */ - ChipLogDetail(DeviceLayer, "WF200:Start LWIP"); - chip::DeviceLayer::Silabs::Lwip::InitializeLwip(); - NotifyWifiTaskInitialized(); - - ChipLogDetail(DeviceLayer, "WF200:ready."); - wifi_extra.Set(WifiState::kStationStarted); - - return SL_STATUS_OK; -} - -CHIP_ERROR InitWiFiStack(void) -{ - // TODO: This function should include sl_wfx_hw_init() and sl_wfx_init() functions. Only done now to make MatterConfig platform - // agnostic. (MATTER-4680) - // Start wfx bus communication task. - sl_status_t status = wfx_bus_start(); - VerifyOrReturnError(status == SL_STATUS_OK, CHIP_ERROR_NO_MEMORY, - ChipLogError(DeviceLayer, "wfx_bus_start failed: %lx", status)); - return CHIP_NO_ERROR; -} +} // namespace Silabs +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/silabs/wifi/wf200/WifiInterfaceImpl.h b/src/platform/silabs/wifi/wf200/WifiInterfaceImpl.h new file mode 100644 index 00000000000000..e56ed311987b9d --- /dev/null +++ b/src/platform/silabs/wifi/wf200/WifiInterfaceImpl.h @@ -0,0 +1,149 @@ +/* + * + * Copyright (c) 2025 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" + * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +#pragma once + +#include + +namespace chip { +namespace DeviceLayer { +namespace Silabs { + +/** + * @brief Wifi Interface implementation + * + */ +class WifiInterfaceImpl final : public WifiInterface +{ +public: + static WifiInterfaceImpl & GetInstance() { return mInstance; } + + WifiInterfaceImpl(const WifiInterfaceImpl &) = delete; + WifiInterfaceImpl & operator=(const WifiInterfaceImpl &) = delete; + + /* + * WifiInterface Impl + */ + + CHIP_ERROR InitWiFiStack(void) override; + CHIP_ERROR GetMacAddress(sl_wfx_interface_t interface, chip::MutableByteSpan & addr) override; + CHIP_ERROR StartNetworkScan(chip::ByteSpan ssid, ScanCallback callback) override; + CHIP_ERROR StartWifiTask() override; + void ConfigureStationMode() override; + bool IsStationConnected() override; + bool IsStationModeEnabled() override; + bool IsStationReady() override; + CHIP_ERROR TriggerDisconnection() override; + CHIP_ERROR GetAccessPointInfo(wfx_wifi_scan_result_t & info) override; + CHIP_ERROR GetAccessPointExtendedInfo(wfx_wifi_scan_ext_t & info) override; + CHIP_ERROR ResetCounters() override; + void ClearWifiCredentials() override; + void SetWifiCredentials(const WifiCredentials & credentials) override; + CHIP_ERROR GetWifiCredentials(WifiCredentials & credentials) override; + bool IsWifiProvisioned() override; + CHIP_ERROR ConnectToAccessPoint(void) override; +#if CHIP_CONFIG_ENABLE_ICD_SERVER + CHIP_ERROR ConfigurePowerSave() override; + CHIP_ERROR ConfigureBroadcastFilter(bool enableBroadcastFilter) override; +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER +#if CHIP_DEVICE_CONFIG_ENABLE_IPV4 + bool HasAnIPv4Address() override; +#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ + bool HasAnIPv6Address() override; + void CancelScanNetworks() override; + + /** + * @brief Callback function passed to the Wi-Fi stack to notify the application of a connection event. + * Function is public to allow the Wi-Fi stack to call it. In practice, it should be private but the callback structure + * needs to be reworked first. + * + * @param connect_indication_body Connection callback data + */ + void ConnectionEventCallback(sl_wfx_connect_ind_body_t connect_indication_body); + + /** + * @brief Callback function to the Wi-Fi stack to notify the application of a disconnection event. + * Function is public to allow the Wi-Fi stack to call it. In practice, it should be private but the callback + * structure needs to be reworked first. + * + * @note See the sl_wfx_disconnect_ind_body_t structure for the reason values. + * + * @param[in] mac Access Point MAC Address + * @param[in] reason disconnection reason + */ + void DisconnectionEventCallback(uint8_t * mac, uint16_t reason); + +private: + WifiInterfaceImpl() = default; + ~WifiInterfaceImpl() = default; + + /** + * @brief Initialize the WF200 platform + * Function triggers the platform int and the LwIP init. + * + * @return sl_status_t SL_STATUS_OK if the platform is initialized successfully or if it is already initialized. + * otherwise platform error code. + */ + sl_status_t InitWf200Platform(); + + /** + * @brief Wi-Fi Task process fonctions + * + * @param[in] arg + */ + static void ProcessEvents(void * arg); + + /** + * @brief Creates a new task to process Wi-Fi events + */ + void StartWifiProcessTask(void); + + /** + * @brief Wf200 Wifi Init + * + * TODO: We have multiple init function when we could have only one. + * + * @return sl_status_t SL_STATUS_OK if the platform is initialized successfully, + * SL_STATUS_WIFI_INVALID_KEY, If the firmware keyset is invalid + * SL_STATUS_WIFI_FIRMWARE_DOWNLOAD_TIMEOUT, If the firmware download times out + * SL_STATUS_TIMEOUT, If the firmware download times out + * SL_STATUS_FAIL, If there is an internal error + */ + sl_status_t wfx_init(void); + +#if (CHIP_DEVICE_CONFIG_ENABLE_IPV4) + /** + * @brief Returns IPv4 Notification state + * + * TODO: This function is necessary because the ProcessEvents is static and does all the processing as well. + * Once the processing function is reworked, it won't be necessary anymore + */ + bool HasNotifiedIPv4() { return mHasNotifiedIPv4; } +#endif // CHIP_DEVICE_CONFIG_ENABLE_IPV4 + + /** + * @brief Returns IPv6 Notification state + * + * TODO: This function is necessary because the ProcessEvents is static and does all the processing as well. + * Once the processing function is reworked, it won't be necessary anymore + */ + bool HasNotifiedIPv6() { return mHasNotifiedIPv6; } + + static WifiInterfaceImpl mInstance; +}; + +} // namespace Silabs +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/silabs/wifi/wf200/wf200.gni b/src/platform/silabs/wifi/wf200/wf200.gni index 20c01b47704f78..1196a0e6fa587f 100644 --- a/src/platform/silabs/wifi/wf200/wf200.gni +++ b/src/platform/silabs/wifi/wf200/wf200.gni @@ -18,6 +18,7 @@ import("${silabs_sdk_build_root}/efr32_sdk.gni") wf200_plat_src = [ "${chip_root}/src/platform/silabs/wifi/wf200/WifiInterfaceImpl.cpp", + "${chip_root}/src/platform/silabs/wifi/wf200/WifiInterfaceImpl.h", "${chip_root}/src/platform/silabs/wifi/wf200/ncp/sl_wfx_task.c", "${chip_root}/src/platform/silabs/wifi/wf200/ncp/wf200_init.c", "${chip_root}/src/platform/silabs/wifi/wf200/ncp/efr_spi.c", diff --git a/src/platform/silabs/wifi/wiseconnect-interface/WiseconnectWifiInterface.cpp b/src/platform/silabs/wifi/wiseconnect-interface/WiseconnectWifiInterface.cpp index f366331ce0207c..df9be69663e431 100644 --- a/src/platform/silabs/wifi/wiseconnect-interface/WiseconnectWifiInterface.cpp +++ b/src/platform/silabs/wifi/wiseconnect-interface/WiseconnectWifiInterface.cpp @@ -37,12 +37,13 @@ constexpr osThreadAttr_t kWlanTaskAttr = { .name = "wlan_rsi", .stack_size = kWlanTaskSize, .priority = osPriorityAboveNormal7 }; -osTimerId_t sDHCPTimer; -bool hasNotifiedWifiConnectivity = false; - } // namespace -CHIP_ERROR GetMacAddress(sl_wfx_interface_t interface, chip::MutableByteSpan & address) +namespace chip { +namespace DeviceLayer { +namespace Silabs { + +CHIP_ERROR WiseconnectWifiInterface::GetMacAddress(sl_wfx_interface_t interface, chip::MutableByteSpan & address) { VerifyOrReturnError(address.size() >= kWifiMacAddressLength, CHIP_ERROR_BUFFER_TOO_SMALL); @@ -55,7 +56,7 @@ CHIP_ERROR GetMacAddress(sl_wfx_interface_t interface, chip::MutableByteSpan & a return CopySpanToMutableSpan(byteSpan, address); } -CHIP_ERROR StartNetworkScan(chip::ByteSpan ssid, ScanCallback callback) +CHIP_ERROR WiseconnectWifiInterface::StartNetworkScan(chip::ByteSpan ssid, ScanCallback callback) { VerifyOrReturnError(callback != nullptr, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(!wfx_rsi.dev_state.Has(WifiState::kScanStarted), CHIP_ERROR_IN_PROGRESS); @@ -86,7 +87,7 @@ CHIP_ERROR StartNetworkScan(chip::ByteSpan ssid, ScanCallback callback) return CHIP_NO_ERROR; } -CHIP_ERROR StartWifiTask() +CHIP_ERROR WiseconnectWifiInterface::StartWifiTask() { // Verify that the Wifi task has not already been started. VerifyOrReturnError(!(wfx_rsi.dev_state.Has(WifiState::kStationStarted)), CHIP_NO_ERROR); @@ -99,27 +100,27 @@ CHIP_ERROR StartWifiTask() return CHIP_NO_ERROR; } -void ConfigureStationMode() +void WiseconnectWifiInterface::ConfigureStationMode() { wfx_rsi.dev_state.Set(WifiState::kStationMode); } -bool IsStationModeEnabled() +bool WiseconnectWifiInterface::IsStationModeEnabled() { return wfx_rsi.dev_state.Has(WifiState::kStationMode); } -bool IsStationConnected() +bool WiseconnectWifiInterface::IsStationConnected() { return wfx_rsi.dev_state.Has(WifiState::kStationConnected); } -bool IsStationReady() +bool WiseconnectWifiInterface::IsStationReady() { return wfx_rsi.dev_state.Has(WifiState::kStationInit); } -CHIP_ERROR TriggerDisconnection() +CHIP_ERROR WiseconnectWifiInterface::TriggerDisconnection() { VerifyOrReturnError(TriggerPlatformWifiDisconnection() == SL_STATUS_OK, CHIP_ERROR_INTERNAL); wfx_rsi.dev_state.Clear(WifiState::kStationConnected); @@ -127,62 +128,56 @@ CHIP_ERROR TriggerDisconnection() return CHIP_NO_ERROR; } -void DHCPTimerEventHandler(void * arg) +void WiseconnectWifiInterface::DHCPTimerEventHandler(void * arg) { WifiPlatformEvent event = WifiPlatformEvent::kStationDhcpPoll; - PostWifiPlatformEvent(event); + WiseconnectWifiInterface::GetInstance().PostWifiPlatformEvent(event); } -void CancelDHCPTimer(void) +void WiseconnectWifiInterface::CancelDHCPTimer(void) { - VerifyOrReturn(osTimerIsRunning(sDHCPTimer), ChipLogDetail(DeviceLayer, "CancelDHCPTimer: timer not running")); - VerifyOrReturn(osTimerStop(sDHCPTimer) == osOK, ChipLogError(DeviceLayer, "CancelDHCPTimer: failed to stop timer")); + VerifyOrReturn(osTimerIsRunning(mDHCPTimer), ChipLogDetail(DeviceLayer, "CancelDHCPTimer: timer not running")); + VerifyOrReturn(osTimerStop(mDHCPTimer) == osOK, ChipLogError(DeviceLayer, "CancelDHCPTimer: failed to stop timer")); } -void StartDHCPTimer(uint32_t timeout) +void WiseconnectWifiInterface::StartDHCPTimer(uint32_t timeout) { // Cancel timer if already started CancelDHCPTimer(); - VerifyOrReturn(osTimerStart(sDHCPTimer, pdMS_TO_TICKS(timeout)) == osOK, + VerifyOrReturn(osTimerStart(mDHCPTimer, pdMS_TO_TICKS(timeout)) == osOK, ChipLogError(DeviceLayer, "StartDHCPTimer: failed to start timer")); } -void NotifyConnectivity(void) +void WiseconnectWifiInterface::NotifyConnectivity(void) { - VerifyOrReturn(!hasNotifiedWifiConnectivity); + VerifyOrReturn(!mHasNotifiedWifiConnectivity); NotifyConnection(wfx_rsi.ap_mac); - hasNotifiedWifiConnectivity = true; + mHasNotifiedWifiConnectivity = true; } -sl_status_t CreateDHCPTimer() +sl_status_t WiseconnectWifiInterface::CreateDHCPTimer() { // TODO: Use LWIP timer instead of creating a new one here - sDHCPTimer = osTimerNew(DHCPTimerEventHandler, osTimerPeriodic, nullptr, nullptr); - VerifyOrReturnError(sDHCPTimer != nullptr, SL_STATUS_ALLOCATION_FAILED); + mDHCPTimer = osTimerNew(DHCPTimerEventHandler, osTimerPeriodic, nullptr, nullptr); + VerifyOrReturnError(mDHCPTimer != nullptr, SL_STATUS_ALLOCATION_FAILED); return SL_STATUS_OK; } -/** - * @brief Reset the flags that are used to notify the application about DHCP connectivity - * and emits a WifiPlatformEvent::kStationDoDhcp event to trigger DHCP polling checks. - * - * TODO: This function should be moved to the protected section once the class structure is done. - */ -void ResetDHCPNotificationFlags(void) +void WiseconnectWifiInterface::ResetDHCPNotificationFlags(void) { ResetIPNotificationStates(); - hasNotifiedWifiConnectivity = false; + mHasNotifiedWifiConnectivity = false; WifiPlatformEvent event = WifiPlatformEvent::kStationDoDhcp; PostWifiPlatformEvent(event); } #if CHIP_DEVICE_CONFIG_ENABLE_IPV4 -void GotIPv4Address(uint32_t ip) +void WiseconnectWifiInterface::GotIPv4Address(uint32_t ip) { // Acquire the new IP address for (int i = 0; i < 4; ++i) @@ -199,7 +194,7 @@ void GotIPv4Address(uint32_t ip) } #endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ -void ClearWifiCredentials() +void WiseconnectWifiInterface::ClearWifiCredentials() { ChipLogProgress(DeviceLayer, "Clear WiFi Provision"); @@ -207,7 +202,7 @@ void ClearWifiCredentials() wfx_rsi.dev_state.Clear(WifiState::kStationProvisioned); } -CHIP_ERROR GetWifiCredentials(WifiCredentials & credentials) +CHIP_ERROR WiseconnectWifiInterface::GetWifiCredentials(WifiCredentials & credentials) { VerifyOrReturnError(wfx_rsi.dev_state.Has(WifiState::kStationProvisioned), CHIP_ERROR_INCORRECT_STATE); credentials = wfx_rsi.credentials; @@ -215,18 +210,18 @@ CHIP_ERROR GetWifiCredentials(WifiCredentials & credentials) return CHIP_NO_ERROR; } -bool IsWifiProvisioned() +bool WiseconnectWifiInterface::IsWifiProvisioned() { return wfx_rsi.dev_state.Has(WifiState::kStationProvisioned); } -void SetWifiCredentials(const WifiCredentials & credentials) +void WiseconnectWifiInterface::SetWifiCredentials(const WifiCredentials & credentials) { wfx_rsi.credentials = credentials; wfx_rsi.dev_state.Set(WifiState::kStationProvisioned); } -CHIP_ERROR ConnectToAccessPoint() +CHIP_ERROR WiseconnectWifiInterface::ConnectToAccessPoint() { VerifyOrReturnError(IsWifiProvisioned(), CHIP_ERROR_INCORRECT_STATE); VerifyOrReturnError(wfx_rsi.credentials.ssidLength, CHIP_ERROR_INCORRECT_STATE); @@ -243,20 +238,24 @@ CHIP_ERROR ConnectToAccessPoint() } #if CHIP_DEVICE_CONFIG_ENABLE_IPV4 -bool HasAnIPv4Address() +bool WiseconnectWifiInterface::HasAnIPv4Address() { return wfx_rsi.dev_state.Has(WifiState::kStationDhcpDone); } #endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ -bool HasAnIPv6Address() +bool WiseconnectWifiInterface::HasAnIPv6Address() { // TODO: WifiState::kStationConnected does not guarantee SLAAC IPv6 LLA, maybe use a different FLAG // Once connect is sync instead of async, this should be fine return wfx_rsi.dev_state.Has(WifiState::kStationConnected); } -void CancelScanNetworks() +void WiseconnectWifiInterface::CancelScanNetworks() { // TODO: Implement cancel scan } + +} // namespace Silabs +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/silabs/wifi/wiseconnect-interface/WiseconnectWifiInterface.h b/src/platform/silabs/wifi/wiseconnect-interface/WiseconnectWifiInterface.h index 64b774225bb01f..cf565c508b3082 100644 --- a/src/platform/silabs/wifi/wiseconnect-interface/WiseconnectWifiInterface.h +++ b/src/platform/silabs/wifi/wiseconnect-interface/WiseconnectWifiInterface.h @@ -18,104 +18,150 @@ #include #include -#define WFX_RSI_DHCP_POLL_INTERVAL (250) /* Poll interval in ms for DHCP */ - -enum class WifiPlatformEvent : uint8_t -{ - kStationConnect = 0, - kStationDisconnect = 1, - kAPStart = 2, - kAPStop = 3, - kScan = 4, /* This combines the scan start and scan result events */ - kStationStartJoin = 5, - kStationDoDhcp = 6, - kStationDhcpDone = 7, - kStationDhcpPoll = 8, -}; +namespace chip { +namespace DeviceLayer { +namespace Silabs { /** - * @brief Function calls the underlying platforms disconnection API. - * - * @note This abstraction layer here is used to reduce the duplication for wiseconnect platforms. - * Since the only difference is the disconnection API, the common implementation is in the WiseconnectWifiInterface - * which calls this abstraction function that is implemented by the different platforms. - * - * @return sl_status_t SL_STATUS_OK, the Wi-Fi disconnection was succesfully triggered - * SL_STATUS_FAILURE, otherwise + * @brief Wiseconnect Wifi Interface implementation. + * Common implementations for Wiseconnect platforms. */ -sl_status_t TriggerPlatformWifiDisconnection(); +class WiseconnectWifiInterface : public WifiInterface +{ +public: + static constexpr uint32_t kDhcpPollIntervalMs = 250; -/** - * @brief Callback function for the DHCP timer event. - * - * TODO: Once the class structure is done, move this to the protected section. Should not be public. - */ -void DHCPTimerEventHandler(void * arg); + enum class WifiPlatformEvent : uint8_t + { + kStationConnect = 0, + kStationDisconnect = 1, + kAPStart = 2, + kAPStop = 3, + kScan = 4, /* This combines the scan start and scan result events */ + kStationStartJoin = 5, + kStationDoDhcp = 6, + kStationDhcpDone = 7, + kStationDhcpPoll = 8, + }; -/** - * @brief Function cancels the DHCP timer if it is running. - * If the timer isn't running, function doesn't do anything. - * - * TODO: Once the class structure is done, move this to the protected section. Should not be public. - */ -void CancelDHCPTimer(void); + virtual ~WiseconnectWifiInterface() = default; -/** - * @brief Function starts the DHCP timer with the given timeout. - * - * TODO: Once the class structure is done, move this to the protected section. Should not be public. - * - * @param timeout timer duration in milliseconds - */ -void StartDHCPTimer(uint32_t timeout); + /* + * WifiInterface impl + */ -/** - * @brief Reset the flags that are used to notify the application about DHCP connectivity - * and emits a WifiPlatformEvent::kStationDoDhcp event to trigger DHCP polling checks. - * - * TODO: This function should be moved to the protected section once the class structure is done. - */ -void ResetDHCPNotificationFlags(); + CHIP_ERROR GetMacAddress(sl_wfx_interface_t interface, chip::MutableByteSpan & addr) override; + CHIP_ERROR StartNetworkScan(chip::ByteSpan ssid, ScanCallback callback) override; + CHIP_ERROR StartWifiTask() override; + void ConfigureStationMode() override; + bool IsStationConnected() override; + bool IsStationModeEnabled() override; + bool IsStationReady() override; + CHIP_ERROR TriggerDisconnection() override; + void ClearWifiCredentials() override; + void SetWifiCredentials(const WifiCredentials & credentials) override; + CHIP_ERROR GetWifiCredentials(WifiCredentials & credentials) override; + CHIP_ERROR ConnectToAccessPoint(void) override; +#if CHIP_DEVICE_CONFIG_ENABLE_IPV4 + bool HasAnIPv4Address() override; +#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ + bool HasAnIPv6Address() override; + void CancelScanNetworks() override; + bool IsWifiProvisioned() override; -/** - * @brief Function creates the DHCP timer - * - * @note This function is necessary for the time being since the WifiInterface don't leverage inheritance for the time being and as - * such don't have access to all data structures. Once the class structure is done, this function will not be necessary - * anymore. - * - * @return sl_status_t SL_STATUS_OK, the timer was successfully created - */ -sl_status_t CreateDHCPTimer(); +protected: + /** + * @brief Function calls the underlying platforms disconnection API. + * + * @note This abstraction layer here is used to reduce the duplication for wiseconnect platforms. + * Since the only difference is the disconnection API, the common implementation is in the WiseconnectWifiInterface + * which calls this abstraction function that is implemented by the different platforms. + * + * @return sl_status_t SL_STATUS_OK, the Wi-Fi disconnection was succesfully triggered + * SL_STATUS_FAILURE, otherwise + */ + virtual sl_status_t TriggerPlatformWifiDisconnection() = 0; -/** - * @brief Notify the application about the connectivity status if it has not been notified yet. - * - * TODO: This function should be moved to the protected section once the class structure is done. - */ -void NotifyConnectivity(void); + /** + * @brief Posts an event to the Wi-Fi task + * + * TODO: Move the implementations the rs9116 and SiWx implementations to the interface + * Remote the pure virutal once it is done + * + * @param[in] event Event to process. + */ + virtual void PostWifiPlatformEvent(WifiPlatformEvent event) = 0; -/** - * @brief Posts an event to the Wi-Fi task - * - * TODO: Once the class structure is in place, the function implementation can be in the protected section of this class instead of - * implemented twice. - * - * @param[in] event Event to process. - */ -void PostWifiPlatformEvent(WifiPlatformEvent event); + /** + * @brief Main worker function for the Matter Wi-Fi task responsible of processing Wi-Fi platform events. + * Function is used in the StartWifiTask. + * + * @note Function must be implemented by the child classes + * + * @param[in] arg context pointer + */ + static void MatterWifiTask(void * arg); -/** - * @brief Main worker function for the Matter Wi-Fi task responsible of processing Wi-Fi platform events. - * Function is used in the StartWifiTask. - * - * @param[in] arg context pointer - */ -void MatterWifiTask(void * arg); + /** + * @brief Function cancels the DHCP timer if it is running. + * If the timer isn't running, function doesn't do anything. + */ + void CancelDHCPTimer(); -/** - * @brief Updates the IPv4 address in the Wi-Fi interface and notifies the application layer about the new IP address. - * - * @param[in] ip New IPv4 address - */ -void GotIPv4Address(uint32_t ip); + /** + * @brief Function starts the DHCP timer with the given timeout. + * + * TODO: change input to milliseconds type + * + * @param timeout timer duration in milliseconds + */ + void StartDHCPTimer(uint32_t timeout); + + /** + * @brief Function creates the DHCP timer + * + * + * @return sl_status_t SL_STATUS_OK, the timer was successfully created + */ + sl_status_t CreateDHCPTimer(); + + /** + * @brief Notify the application about the connectivity status if it has not been notified yet. + */ + void NotifyConnectivity(void); + + /** + * @brief Updates the IPv4 address in the Wi-Fi interface and notifies the application layer about the new IP address. + * + * @param[in] ip New IPv4 address + */ + void GotIPv4Address(uint32_t ip); + + /** + * @brief Function resets the IP and connectiity flags and triggers the DHCP operation + * + */ + void ResetDHCPNotificationFlags(); + +private: + /** + * @brief Returns the singleton instance of the Wiseconnect WiFi interface + * + * @note This function needs to be implemented in the child classes sources file + * + * @return WiseconnectWifiInterface& + */ + static WiseconnectWifiInterface & GetInstance(); + + /** + * @brief Callback function for the DHCP timer event. + */ + static void DHCPTimerEventHandler(void * arg); + + osTimerId_t mDHCPTimer; + bool mHasNotifiedWifiConnectivity = false; +}; + +} // namespace Silabs +} // namespace DeviceLayer +} // namespace chip