diff --git a/examples/light-switch-app/efr32/BUILD.gn b/examples/light-switch-app/efr32/BUILD.gn index 802fc169f74094..86ffe23b5a6727 100644 --- a/examples/light-switch-app/efr32/BUILD.gn +++ b/examples/light-switch-app/efr32/BUILD.gn @@ -39,7 +39,7 @@ declare_args() { chip_print_memory_usage = false # PIN code for PASE session establishment. - setupPinCode = 73141520 + setupPinCode = 20202021 setupDiscriminator = 3840 # Monitor & log memory usage at runtime. @@ -53,7 +53,7 @@ declare_args() { use_rs911x = false use_rs911x_sockets = false sl_wfx_config_softap = false - sl_wfx_config_scan = false + sl_wfx_config_scan = true } show_qr_code = true @@ -114,9 +114,8 @@ efr32_sdk("sdk") { } else if (use_wf200) { defines += wf200_defs include_dirs += wf200_plat_incs - } else { - defines += [ "SL_HEAP_SIZE=20480" ] } + if (use_rs911x_sockets) { include_dirs += [ "${examples_plat_dir}/wifi/rsi-sockets" ] defines += rs911x_sock_defs @@ -126,11 +125,14 @@ efr32_sdk("sdk") { # defines += efr32_lwip_defs } - if (sl_wfx_config_softap) { - defines += "SL_WFX_CONFIG_SOFTAP" - } - if (sl_wfx_config_scan) { - defines += "SL_WFX_CONFIG_SCAN" + + if (use_rs911x || use_wf200) { + if (sl_wfx_config_softap) { + defines += [ "SL_WFX_CONFIG_SOFTAP" ] + } + if (sl_wfx_config_scan) { + defines += [ "SL_WFX_CONFIG_SCAN" ] + } } } diff --git a/examples/light-switch-app/efr32/src/AppTask.cpp b/examples/light-switch-app/efr32/src/AppTask.cpp index e3fc72822a301e..d7441a6f892ccc 100644 --- a/examples/light-switch-app/efr32/src/AppTask.cpp +++ b/examples/light-switch-app/efr32/src/AppTask.cpp @@ -53,6 +53,8 @@ #endif #ifdef SL_WIFI #include "wfx_host_events.h" +#include +#include #endif /* SL_WIFI */ #define FACTORY_RESET_TRIGGER_TIMEOUT 3000 @@ -67,6 +69,9 @@ #define APP_FUNCTION_BUTTON &sl_button_btn0 #define APP_LIGHT_SWITCH &sl_button_btn1 +using namespace chip; +using namespace ::chip::DeviceLayer; + namespace { TimerHandle_t sFunctionTimer; // FreeRTOS app sw timer. @@ -79,6 +84,9 @@ LEDWidget sStatusLED; bool sIsWiFiProvisioned = false; bool sIsWiFiEnabled = false; bool sIsWiFiAttached = false; + +app::Clusters::NetworkCommissioning::Instance + sWiFiNetworkCommissioningInstance(0 /* Endpoint Id */, &(NetworkCommissioning::SlWiFiDriver::GetInstance())); #endif /* SL_WIFI */ #if CHIP_ENABLE_OPENTHREAD @@ -178,6 +186,8 @@ CHIP_ERROR AppTask::Init() } EFR32_LOG("APP: Done WiFi Init"); /* We will init server when we get IP */ + + sWiFiNetworkCommissioningInstance.Init(); #endif // Init ZCL Data Model chip::Server::GetInstance().Init(); diff --git a/examples/lighting-app/efr32/BUILD.gn b/examples/lighting-app/efr32/BUILD.gn index f02894dd6d66ce..e9d207686537f6 100644 --- a/examples/lighting-app/efr32/BUILD.gn +++ b/examples/lighting-app/efr32/BUILD.gn @@ -39,7 +39,7 @@ declare_args() { chip_print_memory_usage = false # PIN code for PASE session establishment. - setupPinCode = 73141520 + setupPinCode = 20202021 setupDiscriminator = 3840 # Monitor & log memory usage at runtime. @@ -53,7 +53,7 @@ declare_args() { use_rs911x = false use_rs911x_sockets = false sl_wfx_config_softap = false - sl_wfx_config_scan = false + sl_wfx_config_scan = true } show_qr_code = true @@ -114,9 +114,8 @@ efr32_sdk("sdk") { } else if (use_wf200) { defines += wf200_defs include_dirs += wf200_plat_incs - } else { - defines += [ "SL_HEAP_SIZE=20480" ] } + if (use_rs911x_sockets) { include_dirs += [ "${examples_plat_dir}/wifi/rsi-sockets" ] defines += rs911x_sock_defs @@ -126,11 +125,13 @@ efr32_sdk("sdk") { # defines += efr32_lwip_defs } - if (sl_wfx_config_softap) { - defines += "SL_WFX_CONFIG_SOFTAP" - } - if (sl_wfx_config_scan) { - defines += "SL_WFX_CONFIG_SCAN" + if (use_rs911x || use_wf200) { + if (sl_wfx_config_softap) { + defines += [ "SL_WFX_CONFIG_SOFTAP" ] + } + if (sl_wfx_config_scan) { + defines += [ "SL_WFX_CONFIG_SCAN" ] + } } } diff --git a/examples/lighting-app/efr32/build_for_wifi_gnfile.gn b/examples/lighting-app/efr32/build_for_wifi_gnfile.gn index 9752ee73e7c91d..d391814190d09f 100644 --- a/examples/lighting-app/efr32/build_for_wifi_gnfile.gn +++ b/examples/lighting-app/efr32/build_for_wifi_gnfile.gn @@ -23,6 +23,6 @@ check_system_includes = true default_args = { target_cpu = "arm" target_os = "freertos" - use_thread = false + chip_enable_wifi = true import("//build_for_wifi_args.gni") } diff --git a/examples/lighting-app/efr32/src/AppTask.cpp b/examples/lighting-app/efr32/src/AppTask.cpp index acdf7f8c78ea4d..14fc7e0f1de65a 100644 --- a/examples/lighting-app/efr32/src/AppTask.cpp +++ b/examples/lighting-app/efr32/src/AppTask.cpp @@ -53,6 +53,8 @@ #endif #ifdef SL_WIFI #include "wfx_host_events.h" +#include +#include #endif /* SL_WIFI */ #define FACTORY_RESET_TRIGGER_TIMEOUT 3000 @@ -67,6 +69,9 @@ #define APP_FUNCTION_BUTTON &sl_button_btn0 #define APP_LIGHT_SWITCH &sl_button_btn1 +using namespace chip; +using namespace ::chip::DeviceLayer; + namespace { TimerHandle_t sFunctionTimer; // FreeRTOS app sw timer. @@ -80,6 +85,9 @@ LEDWidget sLightLED; bool sIsWiFiProvisioned = false; bool sIsWiFiEnabled = false; bool sIsWiFiAttached = false; + +app::Clusters::NetworkCommissioning::Instance + sWiFiNetworkCommissioningInstance(0 /* Endpoint Id */, &(NetworkCommissioning::SlWiFiDriver::GetInstance())); #endif /* SL_WIFI */ #if CHIP_ENABLE_OPENTHREAD @@ -231,6 +239,8 @@ CHIP_ERROR AppTask::Init() } EFR32_LOG("APP: Done WiFi Init"); /* We will init server when we get IP */ + + sWiFiNetworkCommissioningInstance.Init(); #endif // Init ZCL Data Model chip::Server::GetInstance().Init(); diff --git a/examples/lock-app/efr32/BUILD.gn b/examples/lock-app/efr32/BUILD.gn index eef337cb099c35..5f4fcf9bc314c8 100644 --- a/examples/lock-app/efr32/BUILD.gn +++ b/examples/lock-app/efr32/BUILD.gn @@ -39,7 +39,7 @@ declare_args() { chip_print_memory_usage = false # PIN code for PASE session establishment. - setupPinCode = 73141520 + setupPinCode = 20202021 # Monitor & log memory usage at runtime. enable_heap_monitoring = false @@ -52,7 +52,7 @@ declare_args() { use_rs911x = false use_rs911x_sockets = false sl_wfx_config_softap = false - sl_wfx_config_scan = false + sl_wfx_config_scan = true } show_qr_code = true @@ -112,9 +112,8 @@ efr32_sdk("sdk") { } else if (use_wf200) { defines += wf200_defs include_dirs += wf200_plat_incs - } else { - defines += [ "SL_HEAP_SIZE=20480" ] } + if (use_rs911x_sockets) { include_dirs += [ "${examples_plat_dir}/wifi/rsi-sockets" ] defines += rs911x_sock_defs @@ -124,11 +123,13 @@ efr32_sdk("sdk") { # defines += efr32_lwip_defs } - if (sl_wfx_config_softap) { - defines += "SL_WFX_CONFIG_SOFTAP" - } - if (sl_wfx_config_scan) { - defines += "SL_WFX_CONFIG_SCAN" + if (use_rs911x || use_wf200) { + if (sl_wfx_config_softap) { + defines += [ "SL_WFX_CONFIG_SOFTAP" ] + } + if (sl_wfx_config_scan) { + defines += [ "SL_WFX_CONFIG_SCAN" ] + } } } diff --git a/examples/lock-app/efr32/include/FreeRTOSConfig.h b/examples/lock-app/efr32/include/FreeRTOSConfig.h index af0b8ace973680..5c803ef4b2ae5f 100644 --- a/examples/lock-app/efr32/include/FreeRTOSConfig.h +++ b/examples/lock-app/efr32/include/FreeRTOSConfig.h @@ -193,7 +193,11 @@ See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ #define configENABLE_BACKWARD_COMPATIBILITY (1) #define configSUPPORT_STATIC_ALLOCATION (1) #define configSUPPORT_DYNAMIC_ALLOCATION (1) +#ifdef SL_WIFI +#define configTOTAL_HEAP_SIZE ((size_t)(28 * 1024)) +#else #define configTOTAL_HEAP_SIZE ((size_t)(20 * 1024)) +#endif /* Optional functions - most linkers will remove unused functions anyway. */ #define INCLUDE_vTaskPrioritySet (1) diff --git a/examples/lock-app/efr32/src/AppTask.cpp b/examples/lock-app/efr32/src/AppTask.cpp index a02b834ca0e9eb..eb96b266eb755f 100644 --- a/examples/lock-app/efr32/src/AppTask.cpp +++ b/examples/lock-app/efr32/src/AppTask.cpp @@ -49,6 +49,8 @@ #endif #ifdef SL_WIFI #include "wfx_host_events.h" +#include +#include #endif #define FACTORY_RESET_TRIGGER_TIMEOUT 3000 @@ -62,6 +64,11 @@ #define APP_FUNCTION_BUTTON &sl_button_btn0 #define APP_LOCK_BUTTON &sl_button_btn1 +using namespace chip; +using namespace chip::TLV; +using namespace ::chip::Credentials; +using namespace ::chip::DeviceLayer; + namespace { TimerHandle_t sFunctionTimer; // FreeRTOS app sw timer. @@ -75,6 +82,9 @@ LEDWidget sLockLED; bool sIsWiFiProvisioned = false; bool sIsWiFiEnabled = false; bool sIsWiFiAttached = false; + +app::Clusters::NetworkCommissioning::Instance + sWiFiNetworkCommissioningInstance(0 /* Endpoint Id */, &(NetworkCommissioning::SlWiFiDriver::GetInstance())); #endif #if CHIP_ENABLE_OPENTHREAD @@ -87,10 +97,6 @@ StackType_t appStack[APP_TASK_STACK_SIZE / sizeof(StackType_t)]; StaticTask_t appTaskStruct; } // namespace -using namespace chip::TLV; -using namespace ::chip::Credentials; -using namespace ::chip::DeviceLayer; - AppTask AppTask::sAppTask; CHIP_ERROR AppTask::StartAppTask() @@ -120,6 +126,8 @@ CHIP_ERROR AppTask::Init() } EFR32_LOG("APP: Done WiFi Init"); /* We will init server when we get IP */ + + sWiFiNetworkCommissioningInstance.Init(); #endif // Init ZCL Data Model chip::Server::GetInstance().Init(); diff --git a/examples/window-app/efr32/BUILD.gn b/examples/window-app/efr32/BUILD.gn index 9cbc1157611a95..4fa393eeaf73fd 100644 --- a/examples/window-app/efr32/BUILD.gn +++ b/examples/window-app/efr32/BUILD.gn @@ -33,7 +33,7 @@ declare_args() { chip_print_memory_usage = false # PIN code for PASE session establishment. - setupPinCode = 73141520 + setupPinCode = 20202021 # Monitor & log memory usage at runtime. enable_heap_monitoring = false @@ -46,7 +46,7 @@ declare_args() { use_rs911x = false use_rs911x_sockets = false sl_wfx_config_softap = false - sl_wfx_config_scan = false + sl_wfx_config_scan = true } show_qr_code = true @@ -99,9 +99,8 @@ efr32_sdk("sdk") { } else if (use_wf200) { defines += wf200_defs include_dirs += wf200_plat_incs - } else { - defines += [ "SL_HEAP_SIZE=20480" ] } + if (use_rs911x_sockets) { include_dirs += [ "${examples_plat_dir}/wifi/rsi-sockets" ] defines += rs911x_sock_defs @@ -111,11 +110,13 @@ efr32_sdk("sdk") { # defines += efr32_lwip_defs } - if (sl_wfx_config_softap) { - defines += "SL_WFX_CONFIG_SOFTAP" - } - if (sl_wfx_config_scan) { - defines += "SL_WFX_CONFIG_SCAN" + if (use_rs911x || use_wf200) { + if (sl_wfx_config_softap) { + defines += [ "SL_WFX_CONFIG_SOFTAP" ] + } + if (sl_wfx_config_scan) { + defines += [ "SL_WFX_CONFIG_SCAN" ] + } } } diff --git a/examples/window-app/efr32/include/CHIPProjectConfig.h b/examples/window-app/efr32/include/CHIPProjectConfig.h index fec4d129f5b3ee..c815613f9b06f4 100644 --- a/examples/window-app/efr32/include/CHIPProjectConfig.h +++ b/examples/window-app/efr32/include/CHIPProjectConfig.h @@ -30,7 +30,7 @@ // Use a default pairing code if one hasn't been provisioned in flash. #ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 12345678 +#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021 #endif #define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00 diff --git a/src/platform/EFR32/BUILD.gn b/src/platform/EFR32/BUILD.gn index 172b94bdb82dce..14fbb0013f8ff7 100644 --- a/src/platform/EFR32/BUILD.gn +++ b/src/platform/EFR32/BUILD.gn @@ -100,8 +100,8 @@ static_library("EFR32") { if (chip_enable_wifi) { sources += [ "ConnectivityManagerImpl_WIFI.cpp", - "ServiceProvisioning.cpp", - "ServiceProvisioning.h", + "NetworkCommissioningWiFiDriver.cpp", + "NetworkCommissioningWiFiDriver.h", ] } } diff --git a/src/platform/EFR32/ConnectivityManagerImpl_WIFI.cpp b/src/platform/EFR32/ConnectivityManagerImpl_WIFI.cpp index bbae58753acf5b..63bdb907a052eb 100644 --- a/src/platform/EFR32/ConnectivityManagerImpl_WIFI.cpp +++ b/src/platform/EFR32/ConnectivityManagerImpl_WIFI.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -150,17 +151,11 @@ ConnectivityManager::WiFiStationMode ConnectivityManagerImpl::_GetWiFiStationMod bool ConnectivityManagerImpl::_IsWiFiStationProvisioned(void) { - char ssid[65]; - size_t len = 0; - - /* See if we have SSID in our Keys */ - if ((Internal::EFR32Config::ReadConfigValueStr(Internal::EFR32Config::kConfigKey_WiFiSSID, ssid, sizeof(ssid) - 1, len) == - CHIP_NO_ERROR) && - (ssid[0] != 0)) + wfx_wifi_provision_t wifiConfig; + if (wfx_get_wifi_provision(&wifiConfig)) { - return true; + return (wifiConfig.ssid[0] != 0); } - return false; } @@ -168,6 +163,7 @@ bool ConnectivityManagerImpl::_IsWiFiStationEnabled(void) { return wfx_is_sta_mode_enabled(); } + CHIP_ERROR ConnectivityManagerImpl::_SetWiFiStationMode(ConnectivityManager::WiFiStationMode val) { DeviceLayer::SystemLayer().ScheduleWork(DriveStationState, NULL); @@ -182,11 +178,13 @@ CHIP_ERROR ConnectivityManagerImpl::_SetWiFiStationMode(ConnectivityManager::WiF return CHIP_NO_ERROR; } + CHIP_ERROR ConnectivityManagerImpl::_SetWiFiStationReconnectInterval(System::Clock::Timeout val) { mWiFiStationReconnectInterval = val; return CHIP_NO_ERROR; } + void ConnectivityManagerImpl::_ClearWiFiStationProvision(void) { if (mWiFiStationMode != kWiFiStationMode_ApplicationControlled) @@ -306,18 +304,7 @@ void ConnectivityManagerImpl::DriveStationState() { if (mWiFiStationState != kWiFiStationState_Connecting) { - wfx_wifi_provision_t wcfg; - size_t sz; - - (void) Internal::EFR32Config::ReadConfigValueStr(Internal::EFR32Config::kConfigKey_WiFiSSID, wcfg.ssid, - sizeof(wcfg.ssid), sz); - (void) Internal::EFR32Config::ReadConfigValueStr(Internal::EFR32Config::kConfigKey_WiFiPSK, wcfg.passkey, - sizeof(wcfg.passkey), sz); - (void) Internal::EFR32Config::ReadConfigValueBin(Internal::EFR32Config::kConfigKey_WiFiSEC, &wcfg.security, - sizeof(wcfg.security), sz); - wfx_set_wifi_provision(&wcfg); - - ChipLogProgress(DeviceLayer, "Attempting to connect WiFi (%s)", wcfg.ssid); + ChipLogProgress(DeviceLayer, "Attempting to connect WiFi"); if ((serr = wfx_connect_to_ap()) != SL_STATUS_OK) { ChipLogError(DeviceLayer, "wfx_connect_to_ap failed"); @@ -351,9 +338,9 @@ void ConnectivityManagerImpl::DriveStationState() void ConnectivityManagerImpl::OnStationConnected() { ChipDeviceEvent event; - wfx_setup_ip6_link_local(SL_WFX_STA_INTERFACE); + NetworkCommissioning::SlWiFiDriver::GetInstance().OnConnectWiFiNetwork(); // Alert other components of the new state. event.Type = DeviceEventType::kWiFiConnectivityChange; event.WiFiConnectivityChange.Result = kConnectivity_Established; diff --git a/src/platform/EFR32/DeviceNetworkProvisioningDelegateImpl.cpp b/src/platform/EFR32/DeviceNetworkProvisioningDelegateImpl.cpp index f01887563d3cdd..743dbda0eaf127 100644 --- a/src/platform/EFR32/DeviceNetworkProvisioningDelegateImpl.cpp +++ b/src/platform/EFR32/DeviceNetworkProvisioningDelegateImpl.cpp @@ -16,7 +16,7 @@ */ #include "DeviceNetworkProvisioningDelegateImpl.h" -#include "ServiceProvisioning.h" +#include "NetworkCommissioningWiFiDriver.h" #include #include @@ -49,7 +49,8 @@ CHIP_ERROR DeviceNetworkProvisioningDelegateImpl::_ProvisionWiFiNetwork(const ch CHIP_ERROR err = CHIP_NO_ERROR; ChipLogProgress(NetworkProvisioning, "EFR Wifi provision: SSID: %s", ssid); - err = SetWiFiStationProvisioning(ssid, key); + err = NetworkCommissioning::SlWiFiDriver::GetInstance().ConnectWiFiNetwork(ssid, strlen(ssid), key, strlen(key)); + if (err != CHIP_NO_ERROR) { ChipLogError(NetworkProvisioning, "ERR:WiFi:Provision network: %s", chip::ErrorStr(err)); diff --git a/src/platform/EFR32/EFR32Config.cpp b/src/platform/EFR32/EFR32Config.cpp index 24cf18a6c92730..da1734e34d898f 100644 --- a/src/platform/EFR32/EFR32Config.cpp +++ b/src/platform/EFR32/EFR32Config.cpp @@ -536,11 +536,12 @@ CHIP_ERROR EFR32Config::FactoryResetConfig(void) err = ForEachRecord(kMinConfigKey_ChipConfig, kMaxConfigKey_ChipConfig, false, [](const Key & nvm3Key, const size_t & length) -> CHIP_ERROR { CHIP_ERROR err2; - - err2 = ClearConfigValue(nvm3Key); + // Delete the nvm3 object with the given key id. + err2 = MapNvm3Error(nvm3_deleteObject(&handle, nvm3Key)); SuccessOrExit(err2); exit: + nvm3_close(&handle); return err2; }); diff --git a/src/platform/EFR32/NetworkCommissioningWiFiDriver.cpp b/src/platform/EFR32/NetworkCommissioningWiFiDriver.cpp new file mode 100644 index 00000000000000..d4c3948a7549d5 --- /dev/null +++ b/src/platform/EFR32/NetworkCommissioningWiFiDriver.cpp @@ -0,0 +1,312 @@ +/* + * + * Copyright (c) 2021 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. + */ + +#include +#include +#include +#include +#include + +#include + +using namespace ::chip; +using namespace ::chip::DeviceLayer::Internal; + +namespace chip { +namespace DeviceLayer { +namespace NetworkCommissioning { + +namespace { +NetworkCommissioning::WiFiScanResponse * sScanResult; +SlScanResponseIterator mScanResponseIter(sScanResult); +} // namespace + +CHIP_ERROR SlWiFiDriver::Init() +{ + CHIP_ERROR err; + size_t ssidLen = 0; + size_t credentialsLen = 0; + mpScanCallback = nullptr; + mpConnectCallback = nullptr; + + // If reading fails, wifi is not provisioned, no need to go further. + err = + EFR32Config::ReadConfigValueStr(EFR32Config::kConfigKey_WiFiSSID, mSavedNetwork.ssid, sizeof(mSavedNetwork.ssid), ssidLen); + VerifyOrReturnError(err == CHIP_NO_ERROR, CHIP_NO_ERROR); + + err = EFR32Config::ReadConfigValueStr(EFR32Config::kConfigKey_WiFiPSK, mSavedNetwork.credentials, + sizeof(mSavedNetwork.credentials), credentialsLen); + VerifyOrReturnError(err == CHIP_NO_ERROR, CHIP_NO_ERROR); + + mSavedNetwork.credentialsLen = credentialsLen; + mSavedNetwork.ssidLen = ssidLen; + mStagingNetwork = mSavedNetwork; + + ConnectWiFiNetwork(mSavedNetwork.ssid, ssidLen, mSavedNetwork.credentials, credentialsLen); + return err; +} + +CHIP_ERROR SlWiFiDriver::CommitConfiguration() +{ + uint8_t securityType = WFX_SEC_WPA2; + + ReturnErrorOnFailure(EFR32Config::WriteConfigValueStr(EFR32Config::kConfigKey_WiFiSSID, mStagingNetwork.ssid)); + ReturnErrorOnFailure(EFR32Config::WriteConfigValueStr(EFR32Config::kConfigKey_WiFiPSK, mStagingNetwork.credentials)); + ReturnErrorOnFailure(EFR32Config::WriteConfigValueBin(EFR32Config::kConfigKey_WiFiSEC, &securityType, sizeof(securityType))); + + mSavedNetwork = mStagingNetwork; + return CHIP_NO_ERROR; +} + +CHIP_ERROR SlWiFiDriver::RevertConfiguration() +{ + mStagingNetwork = mSavedNetwork; + return CHIP_NO_ERROR; +} + +bool SlWiFiDriver::NetworkMatch(const WiFiNetwork & network, ByteSpan networkId) +{ + return networkId.size() == network.ssidLen && memcmp(networkId.data(), network.ssid, network.ssidLen) == 0; +} + +Status SlWiFiDriver::AddOrUpdateNetwork(ByteSpan ssid, ByteSpan credentials) +{ + VerifyOrReturnError(mStagingNetwork.ssidLen == 0 || NetworkMatch(mStagingNetwork, ssid), Status::kBoundsExceeded); + VerifyOrReturnError(credentials.size() <= sizeof(mStagingNetwork.credentials), Status::kOutOfRange); + VerifyOrReturnError(ssid.size() <= sizeof(mStagingNetwork.ssid), Status::kOutOfRange); + + memset(mStagingNetwork.credentials, 0, sizeof(mStagingNetwork.credentials)); + memcpy(mStagingNetwork.credentials, credentials.data(), credentials.size()); + mStagingNetwork.credentialsLen = static_cast(credentials.size()); + + memset(mStagingNetwork.ssid, 0, sizeof(mStagingNetwork.ssid)); + memcpy(mStagingNetwork.ssid, ssid.data(), ssid.size()); + mStagingNetwork.ssidLen = static_cast(ssid.size()); + + return Status::kSuccess; +} + +Status SlWiFiDriver::RemoveNetwork(ByteSpan networkId) +{ + VerifyOrReturnError(NetworkMatch(mStagingNetwork, networkId), Status::kNetworkIDNotFound); + + // Use empty ssid for representing invalid network + mStagingNetwork.ssidLen = 0; + return Status::kSuccess; +} + +Status SlWiFiDriver::ReorderNetwork(ByteSpan networkId, uint8_t index) +{ + // Only one network is supported for now + VerifyOrReturnError(index == 0, Status::kOutOfRange); + VerifyOrReturnError(NetworkMatch(mStagingNetwork, networkId), Status::kNetworkIDNotFound); + return Status::kSuccess; +} + +CHIP_ERROR SlWiFiDriver::ConnectWiFiNetwork(const char * ssid, uint8_t ssidLen, const char * key, uint8_t keyLen) +{ + ReturnErrorOnFailure(ConnectivityMgr().SetWiFiStationMode(ConnectivityManager::kWiFiStationMode_Disabled)); + // Set the wifi configuration + wfx_wifi_provision_t wifiConfig = {}; + memcpy(wifiConfig.ssid, ssid, ssidLen); + memcpy(wifiConfig.passkey, key, keyLen); + wifiConfig.security = WFX_SEC_WPA2; + + ChipLogProgress(NetworkProvisioning, "Setting up connetion for WiFi SSID: %s", wifiConfig.ssid); + // Configure the WFX WiFi interface. + wfx_set_wifi_provision(&wifiConfig); + ReturnErrorOnFailure(ConnectivityMgr().SetWiFiStationMode(ConnectivityManager::kWiFiStationMode_Disabled)); + ReturnErrorOnFailure(ConnectivityMgr().SetWiFiStationMode(ConnectivityManager::kWiFiStationMode_Enabled)); + return CHIP_NO_ERROR; +} + +void SlWiFiDriver::OnConnectWiFiNetwork() +{ + if (mpConnectCallback) + { + CommitConfiguration(); + mpConnectCallback->OnResult(Status::kSuccess, CharSpan(), 0); + mpConnectCallback = nullptr; + } +} + +void SlWiFiDriver::ConnectNetwork(ByteSpan networkId, ConnectCallback * callback) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + Status networkingStatus = Status::kUnknownError; + + VerifyOrExit(NetworkMatch(mStagingNetwork, networkId), networkingStatus = Status::kNetworkIDNotFound); + VerifyOrExit(mpConnectCallback == nullptr, networkingStatus = Status::kUnknownError); + + err = ConnectWiFiNetwork(mStagingNetwork.ssid, mStagingNetwork.ssidLen, mStagingNetwork.credentials, + mStagingNetwork.credentialsLen); + if (err == CHIP_NO_ERROR) + { + mpConnectCallback = callback; + networkingStatus = Status::kSuccess; + } + +exit: + if (networkingStatus != Status::kSuccess) + { + ChipLogError(NetworkProvisioning, "Failed to connect to WiFi network:%s", chip::ErrorStr(err)); + mpConnectCallback = nullptr; + callback->OnResult(networkingStatus, CharSpan(), 0); + } +} + +uint8_t SlWiFiDriver::ConvertSecuritytype(uint8_t security) +{ + uint8_t securityType = EMBER_ZCL_SECURITY_TYPE_UNSPECIFIED; + if (security == WFX_SEC_NONE) + { + securityType = EMBER_ZCL_SECURITY_TYPE_NONE; + } + else if (security == WFX_SEC_WPA3) + { + securityType = EMBER_ZCL_SECURITY_TYPE_WPA3; + } + else if (security & WFX_SEC_WPA2) + { + securityType = EMBER_ZCL_SECURITY_TYPE_WPA2; + } + else if (security & WFX_SEC_WPA) + { + securityType = EMBER_ZCL_SECURITY_TYPE_WPA; + } + else if (security & WFX_SEC_WEP) + { + securityType = EMBER_ZCL_SECURITY_TYPE_WEP; + } + // wfx_sec_t support more type + + return securityType; +} + +bool SlWiFiDriver::StartScanWiFiNetworks(ByteSpan ssid) +{ + bool scanStarted = false; + ChipLogProgress(DeviceLayer, "Start Scan WiFi Networks"); + if (ssid.size()) // ssid is given, only scan this network + { + char cSsid[DeviceLayer::Internal::kMaxWiFiSSIDLength] = {}; + memcpy(cSsid, ssid.data(), ssid.size()); + scanStarted = wfx_start_scan(cSsid, OnScanWiFiNetworkDone); + } + else // scan all networks + { + scanStarted = wfx_start_scan(nullptr, OnScanWiFiNetworkDone); + } + return scanStarted; +} + +void SlWiFiDriver::OnScanWiFiNetworkDone(wfx_wifi_scan_result_t * aScanResult) +{ + ChipLogProgress(DeviceLayer, "OnScanWiFiNetworkDone"); + if (!aScanResult) + { + if (GetInstance().mpScanCallback != nullptr) + { + DeviceLayer::SystemLayer().ScheduleLambda([]() { + GetInstance().mpScanCallback->OnFinished(NetworkCommissioning::Status::kSuccess, CharSpan(), &mScanResponseIter); + GetInstance().mpScanCallback = nullptr; + }); + } + } + else + { + NetworkCommissioning::WiFiScanResponse scanResponse = { 0 }; + + scanResponse.security = GetInstance().ConvertSecuritytype(aScanResult->security); + scanResponse.channel = aScanResult->chan; + scanResponse.rssi = aScanResult->rssi; + scanResponse.ssidLen = strnlen(aScanResult->ssid, DeviceLayer::Internal::kMaxWiFiSSIDLength); + memcpy(scanResponse.ssid, aScanResult->ssid, scanResponse.ssidLen); + memcpy(scanResponse.bssid, aScanResult->bssid, sizeof(scanResponse.bssid)); + + mScanResponseIter.Add(&scanResponse); + } +} + +void SlWiFiDriver::ScanNetworks(ByteSpan ssid, WiFiDriver::ScanCallback * callback) +{ + if (callback != nullptr) + { + mpScanCallback = callback; + if (!StartScanWiFiNetworks(ssid)) + { + ChipLogError(DeviceLayer, "ScanWiFiNetworks failed to start"); + mpScanCallback = nullptr; + callback->OnFinished(Status::kUnknownError, CharSpan(), nullptr); + } + } +} + +CHIP_ERROR GetConnectedNetwork(Network & network) +{ + wfx_wifi_provision_t wifiConfig; + + if (!wfx_is_sta_connected() || !wfx_get_wifi_provision(&wifiConfig)) + { + return CHIP_ERROR_INCORRECT_STATE; + } + + uint8_t length = strnlen(wifiConfig.ssid, DeviceLayer::Internal::kMaxWiFiSSIDLength); + if (length > sizeof(network.networkID)) + { + ChipLogError(DeviceLayer, "SSID too long"); + return CHIP_ERROR_INTERNAL; + } + + memcpy(network.networkID, wifiConfig.ssid, length); + network.networkIDLen = length; + + return CHIP_NO_ERROR; +} + +size_t SlWiFiDriver::WiFiNetworkIterator::Count() +{ + return mDriver->mStagingNetwork.ssidLen == 0 ? 0 : 1; +} + +bool SlWiFiDriver::WiFiNetworkIterator::Next(Network & item) +{ + if (mExhausted || mDriver->mStagingNetwork.ssidLen == 0) + { + return false; + } + memcpy(item.networkID, mDriver->mStagingNetwork.ssid, mDriver->mStagingNetwork.ssidLen); + item.networkIDLen = mDriver->mStagingNetwork.ssidLen; + item.connected = false; + mExhausted = true; + + Network connectedNetwork; + CHIP_ERROR err = GetConnectedNetwork(connectedNetwork); + if (err == CHIP_NO_ERROR) + { + if (connectedNetwork.networkIDLen == item.networkIDLen && + memcmp(connectedNetwork.networkID, item.networkID, item.networkIDLen) == 0) + { + item.connected = true; + } + } + return true; +} + +} // namespace NetworkCommissioning +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/EFR32/NetworkCommissioningWiFiDriver.h b/src/platform/EFR32/NetworkCommissioningWiFiDriver.h new file mode 100644 index 00000000000000..6f411818b7e214 --- /dev/null +++ b/src/platform/EFR32/NetworkCommissioningWiFiDriver.h @@ -0,0 +1,179 @@ +/* + * + * Copyright (c) 2021 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 +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION +#include +#include + +namespace chip { +namespace DeviceLayer { +namespace NetworkCommissioning { + +namespace { +constexpr uint8_t kMaxWiFiNetworks = 1; +constexpr uint8_t kWiFiScanNetworksTimeOutSeconds = 10; +constexpr uint8_t kWiFiConnectNetworkTimeoutSeconds = 20; +} // namespace + +// class SlScanResponseIterator : public Iterator +// { +// public: +// SlScanResponseIterator(const size_t size, const wifi_ap_record_t * scanResults) : mSize(size), mpScanResults(scanResults) {} +// size_t Count() override { return mSize; } +// bool Next(WiFiScanResponse & item) override +// { +// if (mIternum >= mSize) +// { +// return false; +// } + +// item.security = mpScanResults[mIternum].authmode; +// item.ssidLen = +// strnlen(reinterpret_cast(mpScanResults[mIternum].ssid), +// chip::DeviceLayer::Internal::kMaxWiFiSSIDLength); +// item.channel = mpScanResults[mIternum].primary; +// item.wiFiBand = chip::DeviceLayer::NetworkCommissioning::WiFiBand::k2g4; +// item.rssi = mpScanResults[mIternum].rssi; +// memcpy(item.ssid, mpScanResults[mIternum].ssid, item.ssidLen); +// memcpy(item.bssid, mpScanResults[mIternum].bssid, 6); + +// mIternum++; +// return true; +// } +// void Release() override {} + +// private: +// const size_t mSize; +// const wifi_ap_record_t * mpScanResults; +// size_t mIternum = 0; +// }; + +template +class SlScanResponseIterator : public Iterator +{ +public: + SlScanResponseIterator(T * apScanResponse) : mpScanResponse(apScanResponse) {} + size_t Count() override { return itemCount; } + bool Next(T & item) override + { + if (mpScanResponse == nullptr || currentIterating >= itemCount) + { + return false; + } + item = mpScanResponse[currentIterating]; + currentIterating++; + return true; + } + void Release() override + { + itemCount = currentIterating = 0; + Platform::MemoryFree(mpScanResponse); + mpScanResponse = nullptr; + } + + void Add(T * pResponse) + { + size_t tempCount = itemCount + 1; + mpScanResponse = static_cast(Platform::MemoryRealloc(mpScanResponse, kItemSize * tempCount)); + if (mpScanResponse) + { + // first item at index. update after the copy. + memcpy(&(mpScanResponse[itemCount]), pResponse, kItemSize); + itemCount = tempCount; + } + } + +private: + size_t currentIterating = 0; + size_t itemCount = 0; + static constexpr size_t kItemSize = sizeof(T); + T * mpScanResponse; +}; + +class SlWiFiDriver final : public WiFiDriver +{ +public: + class WiFiNetworkIterator final : public NetworkIterator + { + public: + WiFiNetworkIterator(SlWiFiDriver * aDriver) : mDriver(aDriver) {} + size_t Count() override; + bool Next(Network & item) override; + void Release() override { delete this; } + ~WiFiNetworkIterator() = default; + + private: + SlWiFiDriver * mDriver; + bool mExhausted = false; + }; + + struct WiFiNetwork + { + char ssid[DeviceLayer::Internal::kMaxWiFiSSIDLength]; + uint8_t ssidLen = 0; + char credentials[DeviceLayer::Internal::kMaxWiFiKeyLength]; + uint8_t credentialsLen = 0; + }; + + // BaseDriver + NetworkIterator * GetNetworks() override { return new WiFiNetworkIterator(this); } + CHIP_ERROR Init() override; + + // WirelessDriver + uint8_t GetMaxNetworks() override { return kMaxWiFiNetworks; } + uint8_t GetScanNetworkTimeoutSeconds() override { return kWiFiScanNetworksTimeOutSeconds; } + uint8_t GetConnectNetworkTimeoutSeconds() override { return kWiFiConnectNetworkTimeoutSeconds; } + + CHIP_ERROR CommitConfiguration() override; + CHIP_ERROR RevertConfiguration() override; + + Status RemoveNetwork(ByteSpan networkId) override; + Status ReorderNetwork(ByteSpan networkId, uint8_t index) override; + void ConnectNetwork(ByteSpan networkId, ConnectCallback * callback) override; + + // WiFiDriver + Status AddOrUpdateNetwork(ByteSpan ssid, ByteSpan credentials) override; + void ScanNetworks(ByteSpan ssid, ScanCallback * callback) override; + + CHIP_ERROR ConnectWiFiNetwork(const char * ssid, uint8_t ssidLen, const char * key, uint8_t keyLen); + + uint8_t ConvertSecuritytype(uint8_t security); + + void OnConnectWiFiNetwork(); + static SlWiFiDriver & GetInstance() + { + static SlWiFiDriver instance; + return instance; + } + +private: + bool NetworkMatch(const WiFiNetwork & network, ByteSpan networkId); + bool StartScanWiFiNetworks(ByteSpan ssid); + static void OnScanWiFiNetworkDone(wfx_wifi_scan_result_t * aScanResult); + + WiFiNetworkIterator mWiFiIterator = WiFiNetworkIterator(this); + WiFiNetwork mSavedNetwork = {}; + WiFiNetwork mStagingNetwork = {}; + ScanCallback * mpScanCallback; + ConnectCallback * mpConnectCallback; +}; + +} // namespace NetworkCommissioning +} // namespace DeviceLayer +} // namespace chip +#endif diff --git a/src/platform/EFR32/ServiceProvisioning.cpp b/src/platform/EFR32/ServiceProvisioning.cpp deleted file mode 100644 index 494c03b7ec2a61..00000000000000 --- a/src/platform/EFR32/ServiceProvisioning.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * - * Copyright (c) 2020 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. - */ - -#include -#include -#include - -#include "wfx_host_events.h" -#include - -#include "ServiceProvisioning.h" - -using namespace ::chip::DeviceLayer; - -CHIP_ERROR SetWiFiStationProvisioning(const char * ssid, const char * key) -{ - ConnectivityMgr().SetWiFiStationMode(ConnectivityManager::kWiFiStationMode_Disabled); - - CHIP_ERROR err = CHIP_NO_ERROR; - wfx_wifi_provision_t wifiConfig; - - // Set the wifi configuration - memset(&wifiConfig, 0, sizeof(wifiConfig)); - memcpy(wifiConfig.ssid, ssid, std::min(strlen(ssid) + 1, sizeof(wifiConfig.ssid))); - memcpy(wifiConfig.passkey, key, std::min(strlen(key) + 1, sizeof(wifiConfig.passkey))); - wifiConfig.security = WFX_SEC_WPA2; /* Need something better ? Scan? */ - - // Configure the WFX WiFi interface. - wfx_set_wifi_provision(&wifiConfig); - /* Save into internal Keys */ - (void) Internal::EFR32Config::WriteConfigValueStr(Internal::EFR32Config::kConfigKey_WiFiSSID, (char *) ssid); - (void) Internal::EFR32Config::WriteConfigValueStr(Internal::EFR32Config::kConfigKey_WiFiPSK, key); - (void) Internal::EFR32Config::WriteConfigValueBin(Internal::EFR32Config::kConfigKey_WiFiSEC, &wifiConfig.security, - sizeof(wifiConfig.security)); - - ChipLogProgress(DeviceLayer, "SP WiFi STA provision set (SSID: %s)", wifiConfig.ssid); - - ConnectivityMgr().SetWiFiStationMode(ConnectivityManager::kWiFiStationMode_Disabled); - ConnectivityMgr().SetWiFiStationMode(ConnectivityManager::kWiFiStationMode_Enabled); - - return err; -} diff --git a/src/platform/EFR32/ServiceProvisioning.h b/src/platform/EFR32/ServiceProvisioning.h deleted file mode 100644 index 109ec4ae33ea6c..00000000000000 --- a/src/platform/EFR32/ServiceProvisioning.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * - * Copyright (c) 2020 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. - */ - -#ifndef _SERVICE_PROVISIONING_H -#define _SERVICE_PROVISIONING_H - -#include - -CHIP_ERROR SetWiFiStationProvisioning(const char * ssid, const char * key); - -#endif // _SERVICE_PROVISIONING_H diff --git a/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.h b/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.h index 3fc7b132ea30b9..be5ad934d7162e 100644 --- a/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.h +++ b/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.h @@ -59,9 +59,9 @@ class otScanResponseIterator : public Iterator } private: - size_t currentIterating = 0; - size_t itemCount = 0; - size_t kItemSize = sizeof(T); + size_t currentIterating = 0; + size_t itemCount = 0; + static constexpr size_t kItemSize = sizeof(T); T * mpScanResponse; }; diff --git a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.cpp b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.cpp index b35d586f821456..6312cfab08f1b1 100644 --- a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.cpp +++ b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.cpp @@ -97,8 +97,8 @@ void initNetworkCommissioningThreadDriver(void) #endif } -NetworkCommissioning::ThreadScanResponse * scanResult; -otScanResponseIterator mScanResponseIter(scanResult); +NetworkCommissioning::ThreadScanResponse * sScanResult; +otScanResponseIterator mScanResponseIter(sScanResult); } // namespace // Fully instantiate the generic implementation class in whatever compilation unit includes this file. template class GenericThreadStackManagerImpl_OpenThread; @@ -367,6 +367,10 @@ CHIP_ERROR GenericThreadStackManagerImpl_OpenThread::_StartThreadScan CHIP_ERROR err = MapOpenThreadError(otLinkActiveScan(mOTInst, 0, /* all channels */ 0, /* default value `kScanDurationDefault` = 300 ms. */ _OnNetworkScanFinished, this)); + if (err != CHIP_NO_ERROR) + { + mpScanCallback = nullptr; + } return err; } diff --git a/third_party/efr32_sdk/repo b/third_party/efr32_sdk/repo index 744316bcf0525f..4cf4906e3327ac 160000 --- a/third_party/efr32_sdk/repo +++ b/third_party/efr32_sdk/repo @@ -1 +1 @@ -Subproject commit 744316bcf0525fd6e07ea86969dd907c2cb10e5f +Subproject commit 4cf4906e3327ac5c5fccdf9c500a85987c489ae3