[nrfconnect] Bump nRF Connect SDK to 2.2.0 (#24302)
* [nrfconnect] Bump nRF Connect SDK to 2.2.0
Change the recommended nRF Connect SDK version to v2.2.0.
* Start using Zephyr WiFi net_mgmt API and events
- replace wpa_supplicant API calls with generic Zephyr net_mgmt API
- use net events to manage WiFi connection
- refactoring of the whole platform/nrfconnect/wifi code
Signed-off-by: Marcin Kajor <marcin.kajor@nordicsemi.no>
* Implemented proper handling of WiFi security modes.
With the current net_mgmt API it is necessary to scan networks to get
the security mode supported by an AP which we want to connect with.
Also fixed the invalid handling of net_mgmt event life time.
Signed-off-by: Marcin Kajor <marcin.kajor@nordicsemi.no>
* Aligned Matter SDK to Zephyr 0.15.x revision.
These changes were implied the the recent Zephyr upmerge:
- updates of Zephyr include paths
- removal of disabling of gpio1 in board DTS overlays
- fix for the possible dangling pointer compilation error
after gcc got more picky about that (v10.3 vs. v12.1)
Signed-off-by: Marcin Kajor <marcin.kajor@nordicsemi.no>
* Increased the max number of BLE connections.
This is a workaround for the non-unreferenced BLE connection object
when restarting advertising in BLE disconnect callback.
Signed-off-by: Marcin Kajor <marcin.kajor@nordicsemi.no>
* WiFi fail-safe related fixes
Make sure the fail-safe works as expected with WiFi networking:
- disconnect when reverting the configuration
- always cleanup the provisioning data structures before connecting
to avoid dummy buffer overwriting and data length issues
Signed-off-by: Marcin Kajor <marcin.kajor@nordicsemi.no>
* Introduced a workaround to send Router Solicitation after connect
Router Solicitation is not sent after connecting to the Wi-Fi
network by the Wi-Fi driver, so in result Thread Border Router
doesn't send Router Advertisement to the device. As a workaround
sending RS was added in the Matter platform code.
* Forward the channel number and RSSI from WIFiManager.
We can now use this feature in spite of stats still
not being implemented.
Signed-off-by: Marcin Kajor <marcin.kajor@nordicsemi.no>
* Minor fixes for heap usage
Fix build with CHIP_MALLOC_SYS_HEAP Kconfig option that
replaces default malloc/free with alternatives based on
Zephyr's sys_heap.
Signed-off-by: Damian Krolik <damian.krolik@nordicsemi.no>
* Wi-Fi status handling fixes.
* Increase the SYSTEM_WORKQUEUE_STACK_SIZE to match supplicant needs
* Decrease the connection timeout to be lower than failsafe (35s)
* Adapt WiFiRequestStatus to follow supplicant implementation
* All of above makes the failsafe more robust
Signed-off-by: Marcin Kajor <marcin.kajor@nordicsemi.no>
* wifi: RevertConfiguration optimization.
Do not disconnect/reconnect to the already attached network.
Signed-off-by: Marcin Kajor <marcin.kajor@nordicsemi.no>
* Define _DEFAULT_SOURCE
This commit updates the chip-module build configurations to define
`_DEFAULT_SOURCE` when compiling Matter because it uses non-standard
functions that are only available when `_DEFAULT_SOURCE` is defined.
Note that this used to be not necessary only because of a quirk in the
way Newlib handles the feature test macro, which resulted in Newlib
defining `_DEFAULT_SOURCE` when compiling with `-std=gnu`.
For more details, refer to the issue zephyrproject-rtos/zephyr#52739.
* Align examples with samples included in nRF Connect SDK 2.2.0
* Update remaining Docker images to 0.6.27
* Restyled by clang-format
* Restyled by shellharden
Signed-off-by: Marcin Kajor <marcin.kajor@nordicsemi.no>
Signed-off-by: Damian Krolik <damian.krolik@nordicsemi.no>
Co-authored-by: Marcin Kajor <marcin.kajor@nordicsemi.no>
Co-authored-by: Kamil Kasperczyk <kamil.kasperczyk@nordicsemi.no>
Co-authored-by: Restyled.io <commits@restyled.io>
Co-authored-by: Andrei Litvin <andy314@gmail.com>
diff --git a/src/include/platform/internal/GenericPlatformManagerImpl_Zephyr.h b/src/include/platform/internal/GenericPlatformManagerImpl_Zephyr.h
index c3f1de4..88d98ec 100644
--- a/src/include/platform/internal/GenericPlatformManagerImpl_Zephyr.h
+++ b/src/include/platform/internal/GenericPlatformManagerImpl_Zephyr.h
@@ -27,7 +27,7 @@
#include <platform/internal/GenericPlatformManagerImpl.h>
#include <sys/select.h>
-#include <zephyr/zephyr.h>
+#include <zephyr/kernel.h>
namespace chip {
namespace DeviceLayer {
diff --git a/src/platform/Zephyr/BLEManagerImpl.cpp b/src/platform/Zephyr/BLEManagerImpl.cpp
index 88edbd3..d4639f8 100644
--- a/src/platform/Zephyr/BLEManagerImpl.cpp
+++ b/src/platform/Zephyr/BLEManagerImpl.cpp
@@ -37,11 +37,11 @@
#include <setup_payload/AdditionalDataPayloadGenerator.h>
#endif
-#include <bluetooth/addr.h>
-#include <bluetooth/gatt.h>
-#include <random/rand32.h>
-#include <sys/byteorder.h>
-#include <sys/util.h>
+#include <zephyr/bluetooth/addr.h>
+#include <zephyr/bluetooth/gatt.h>
+#include <zephyr/random/rand32.h>
+#include <zephyr/sys/byteorder.h>
+#include <zephyr/sys/util.h>
using namespace ::chip;
using namespace ::chip::Ble;
diff --git a/src/platform/Zephyr/BLEManagerImpl.h b/src/platform/Zephyr/BLEManagerImpl.h
index a99847c..fae4799 100644
--- a/src/platform/Zephyr/BLEManagerImpl.h
+++ b/src/platform/Zephyr/BLEManagerImpl.h
@@ -25,9 +25,9 @@
#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/conn.h>
-#include <bluetooth/gatt.h>
+#include <zephyr/bluetooth/bluetooth.h>
+#include <zephyr/bluetooth/conn.h>
+#include <zephyr/bluetooth/gatt.h>
#include <lib/support/logging/CHIPLogging.h>
diff --git a/src/platform/Zephyr/KeyValueStoreManagerImpl.h b/src/platform/Zephyr/KeyValueStoreManagerImpl.h
index 1d4ee7d..de8707f 100644
--- a/src/platform/Zephyr/KeyValueStoreManagerImpl.h
+++ b/src/platform/Zephyr/KeyValueStoreManagerImpl.h
@@ -24,7 +24,7 @@
#pragma once
-#include <zephyr/zephyr.h>
+#include <zephyr/kernel.h>
namespace chip {
namespace DeviceLayer {
diff --git a/src/platform/Zephyr/NFCManagerImpl.cpp b/src/platform/Zephyr/NFCManagerImpl.cpp
index 53856af..dd28457 100644
--- a/src/platform/Zephyr/NFCManagerImpl.cpp
+++ b/src/platform/Zephyr/NFCManagerImpl.cpp
@@ -26,7 +26,7 @@
#include <nfc/ndef/uri_msg.h>
#include <nfc/ndef/uri_rec.h>
#include <nfc_t2t_lib.h>
-#include <zephyr.h>
+#include <zephyr/kernel.h>
namespace chip {
namespace DeviceLayer {
diff --git a/src/platform/Zephyr/SysHeapMalloc.cpp b/src/platform/Zephyr/SysHeapMalloc.cpp
index e65ec8a..1a80fad 100644
--- a/src/platform/Zephyr/SysHeapMalloc.cpp
+++ b/src/platform/Zephyr/SysHeapMalloc.cpp
@@ -21,10 +21,10 @@
#include <system/SystemError.h>
extern "C" {
-#include <init.h>
-#include <sys/math_extras.h>
-#include <sys/mutex.h>
-#include <sys/sys_heap.h>
+#include <zephyr/init.h>
+#include <zephyr/sys/math_extras.h>
+#include <zephyr/sys/mutex.h>
+#include <zephyr/sys/sys_heap.h>
}
#include <cstdint>
@@ -131,7 +131,7 @@
LockGuard lockGuard;
ReturnErrorOnFailure(lockGuard.Error());
- sys_heap_runtime_stats sysHeapStats;
+ sys_memory_stats sysHeapStats;
ReturnErrorOnFailure(System::MapErrorZephyr(sys_heap_runtime_stats_get(&sHeap, &sysHeapStats)));
stats.free = sysHeapStats.free_bytes;
diff --git a/src/platform/Zephyr/SystemTimeSupport.cpp b/src/platform/Zephyr/SystemTimeSupport.cpp
index 90b63ad..c9ebdf7 100644
--- a/src/platform/Zephyr/SystemTimeSupport.cpp
+++ b/src/platform/Zephyr/SystemTimeSupport.cpp
@@ -26,7 +26,7 @@
#include <system/SystemError.h>
-#include <zephyr/zephyr.h>
+#include <zephyr/kernel.h>
#if !CHIP_SYSTEM_CONFIG_USE_POSIX_TIME_FUNCTS
diff --git a/src/platform/Zephyr/ThreadStackManagerImpl.h b/src/platform/Zephyr/ThreadStackManagerImpl.h
index 6600554..d9a9020 100644
--- a/src/platform/Zephyr/ThreadStackManagerImpl.h
+++ b/src/platform/Zephyr/ThreadStackManagerImpl.h
@@ -25,8 +25,8 @@
#include <platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.h>
+#include <zephyr/kernel.h>
#include <zephyr/net/openthread.h>
-#include <zephyr/zephyr.h>
#include <openthread/thread.h>
#if !CONFIG_SOC_SERIES_RISCV_TELINK_B91
diff --git a/src/platform/nrfconnect/DiagnosticDataProviderImplNrf.cpp b/src/platform/nrfconnect/DiagnosticDataProviderImplNrf.cpp
index 5f7bc1a..e7326ed 100644
--- a/src/platform/nrfconnect/DiagnosticDataProviderImplNrf.cpp
+++ b/src/platform/nrfconnect/DiagnosticDataProviderImplNrf.cpp
@@ -71,9 +71,7 @@
WiFiManager::WiFiInfo info;
CHIP_ERROR err = WiFiManager::Instance().GetWiFiInfo(info);
channelNumber = info.mChannel;
- (void) err;
- // above will return 0 until the wpa_supplicant driver API implementation is refined
- return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
+ return err;
}
CHIP_ERROR DiagnosticDataProviderImplNrf::GetWiFiRssi(int8_t & rssi)
@@ -81,9 +79,7 @@
WiFiManager::WiFiInfo info;
CHIP_ERROR err = WiFiManager::Instance().GetWiFiInfo(info);
rssi = info.mRssi;
- (void) err;
- // above will return -128 until the wpa_supplicant driver API implementation is refined
- return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
+ return err;
}
// below will be implemented when the WiFi driver exposes Zephyr NET_STATISTICS API
diff --git a/src/platform/nrfconnect/FactoryDataParser.c b/src/platform/nrfconnect/FactoryDataParser.c
index 1960188..85caee5 100644
--- a/src/platform/nrfconnect/FactoryDataParser.c
+++ b/src/platform/nrfconnect/FactoryDataParser.c
@@ -17,8 +17,8 @@
#include "FactoryDataParser.h"
-#include <logging/log.h>
#include <zcbor_decode.h>
+#include <zephyr/logging/log.h>
#include <ctype.h>
#include <string.h>
diff --git a/src/platform/nrfconnect/FactoryDataProvider.cpp b/src/platform/nrfconnect/FactoryDataProvider.cpp
index cd52046..200b8fa 100644
--- a/src/platform/nrfconnect/FactoryDataProvider.cpp
+++ b/src/platform/nrfconnect/FactoryDataProvider.cpp
@@ -24,7 +24,7 @@
#include <platform/Zephyr/ZephyrConfig.h>
#endif
-#include <logging/log.h>
+#include <zephyr/logging/log.h>
namespace chip {
namespace {
diff --git a/src/platform/nrfconnect/FactoryDataProvider.h b/src/platform/nrfconnect/FactoryDataProvider.h
index 3d46076..c551791 100644
--- a/src/platform/nrfconnect/FactoryDataProvider.h
+++ b/src/platform/nrfconnect/FactoryDataProvider.h
@@ -21,10 +21,10 @@
#include <platform/CommissionableDataProvider.h>
#include <platform/DeviceInstanceInfoProvider.h>
-#include <drivers/flash.h>
#include <fprotect.h>
#include <pm_config.h>
#include <system/SystemError.h>
+#include <zephyr/drivers/flash.h>
#include "FactoryDataParser.h"
diff --git a/src/platform/nrfconnect/OTAImageProcessorImpl.cpp b/src/platform/nrfconnect/OTAImageProcessorImpl.cpp
index 0daf01c..7448ffe 100644
--- a/src/platform/nrfconnect/OTAImageProcessorImpl.cpp
+++ b/src/platform/nrfconnect/OTAImageProcessorImpl.cpp
@@ -28,15 +28,15 @@
#if CONFIG_CHIP_CERTIFICATION_DECLARATION_STORAGE
#include <credentials/CertificationDeclaration.h>
#include <platform/Zephyr/ZephyrConfig.h>
-#include <settings/settings.h>
+#include <zephyr/settings/settings.h>
#endif
#include <dfu/dfu_multi_image.h>
#include <dfu/dfu_target.h>
#include <dfu/dfu_target_mcuboot.h>
-#include <dfu/mcuboot.h>
-#include <logging/log.h>
-#include <pm/device.h>
+#include <zephyr/dfu/mcuboot.h>
+#include <zephyr/logging/log.h>
+#include <zephyr/pm/device.h>
#if CONFIG_CHIP_CERTIFICATION_DECLARATION_STORAGE
// Cd globals are needed to be accessed from dfu image writer lambdas
diff --git a/src/platform/nrfconnect/wifi/ConnectivityManagerImplWiFi.cpp b/src/platform/nrfconnect/wifi/ConnectivityManagerImplWiFi.cpp
index 73e1630..b3bdede 100644
--- a/src/platform/nrfconnect/wifi/ConnectivityManagerImplWiFi.cpp
+++ b/src/platform/nrfconnect/wifi/ConnectivityManagerImplWiFi.cpp
@@ -52,27 +52,9 @@
CHIP_ERROR ConnectivityManagerImplWiFi::_SetWiFiStationMode(ConnectivityManager::WiFiStationMode aMode)
{
- VerifyOrReturnError(ConnectivityManager::WiFiStationMode::kWiFiStationMode_NotSupported != aMode,
- CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
+ VerifyOrReturnError(ConnectivityManager::WiFiStationMode::kWiFiStationMode_NotSupported != aMode, CHIP_ERROR_INVALID_ARGUMENT);
- if (aMode != mStationMode)
- {
- mStationMode = aMode;
- if (mStationMode != ConnectivityManager::WiFiStationMode::kWiFiStationMode_ApplicationControlled)
- {
- bool doEnable{ ConnectivityManager::WiFiStationMode::kWiFiStationMode_Enabled == mStationMode };
- // TODO: when the connection/disconnection callback API is provided
- // below calls should be used as a base of disconnect callback
- if (doEnable)
- {
- OnStationConnected();
- }
- else
- {
- OnStationDisconnected();
- }
- }
- }
+ mStationMode = aMode;
return CHIP_NO_ERROR;
}
@@ -89,7 +71,7 @@
bool ConnectivityManagerImplWiFi::_IsWiFiStationConnected(void)
{
- return (WiFiManager::StationStatus::FULLY_PROVISIONED == WiFiManager().Instance().GetStationStatus());
+ return (WiFiManager::StationStatus::CONNECTED == WiFiManager().Instance().GetStationStatus());
}
System::Clock::Timeout ConnectivityManagerImplWiFi::_GetWiFiStationReconnectInterval(void)
@@ -141,38 +123,6 @@
return CHIP_NO_ERROR;
}
-void ConnectivityManagerImplWiFi::OnStationConnected()
-{
- // ensure the station is connected
- if (_IsWiFiStationConnected())
- {
- ChipDeviceEvent connectEvent{};
- connectEvent.Type = DeviceEventType::kWiFiConnectivityChange;
- connectEvent.WiFiConnectivityChange.Result = kConnectivity_Established;
- PlatformMgr().PostEventOrDie(&connectEvent);
- }
- else
- {
- ChipLogError(DeviceLayer, "WiFi Station is not connected!");
- }
-}
-
-void ConnectivityManagerImplWiFi::OnStationDisconnected()
-{
- // ensure the station is disconnected
- if (WiFiManager::StationStatus::DISCONNECTED == WiFiManager().Instance().GetStationStatus())
- {
- ChipDeviceEvent disconnectEvent{};
- disconnectEvent.Type = DeviceEventType::kWiFiConnectivityChange;
- disconnectEvent.WiFiConnectivityChange.Result = kConnectivity_Lost;
- PlatformMgr().PostEventOrDie(&disconnectEvent);
- }
- else
- {
- ChipLogError(DeviceLayer, "WiFi Station is not disconnected!");
- }
-}
-
ConnectivityManager::WiFiAPMode ConnectivityManagerImplWiFi::_GetWiFiAPMode(void)
{
/* AP mode is unsupported */
diff --git a/src/platform/nrfconnect/wifi/ConnectivityManagerImplWiFi.h b/src/platform/nrfconnect/wifi/ConnectivityManagerImplWiFi.h
index 8198453..dfa6a05 100644
--- a/src/platform/nrfconnect/wifi/ConnectivityManagerImplWiFi.h
+++ b/src/platform/nrfconnect/wifi/ConnectivityManagerImplWiFi.h
@@ -54,8 +54,6 @@
bool _CanStartWiFiScan();
void _OnWiFiScanDone();
void _OnWiFiStationProvisionChange();
- void OnStationConnected();
- void OnStationDisconnected();
// Wi-Fi access point - not supported
ConnectivityManager::WiFiAPMode _GetWiFiAPMode(void);
diff --git a/src/platform/nrfconnect/wifi/NrfWiFiDriver.cpp b/src/platform/nrfconnect/wifi/NrfWiFiDriver.cpp
index 5092384..e8e5d10 100644
--- a/src/platform/nrfconnect/wifi/NrfWiFiDriver.cpp
+++ b/src/platform/nrfconnect/wifi/NrfWiFiDriver.cpp
@@ -17,7 +17,6 @@
#include "NrfWiFiDriver.h"
-#include "WiFiManager.h"
#include <platform/KeyValueStoreManager.h>
#include <lib/support/CodeUtils.h>
@@ -27,6 +26,7 @@
using namespace ::chip;
using namespace ::chip::DeviceLayer::Internal;
using namespace ::chip::DeviceLayer::PersistedStorage;
+using namespace ::chip::app::Clusters::NetworkCommissioning;
namespace chip {
namespace DeviceLayer {
@@ -105,7 +105,7 @@
{
WiFiManager::ConnectionHandling handling{ [] { Instance().OnNetworkStatusChanged(Status::kSuccess); },
[] { Instance().OnNetworkStatusChanged(Status::kUnknownError); },
- System::Clock::Timeout{ 40000 } };
+ System::Clock::Seconds32{ kWiFiConnectNetworkTimeoutSeconds } };
ReturnErrorOnFailure(
WiFiManager::Instance().Connect(mStagingNetwork.GetSsidSpan(), mStagingNetwork.GetPassSpan(), handling));
}
@@ -121,7 +121,15 @@
}
if (mpNetworkStatusChangeCallback)
+ {
mpNetworkStatusChangeCallback->OnNetworkingStatusChange(status, NullOptional, NullOptional);
+ }
+
+ if (mpConnectCallback)
+ {
+ mpConnectCallback->OnResult(status, CharSpan(), 0);
+ mpConnectCallback = nullptr;
+ }
}
void NrfWiFiDriver::Shutdown()
@@ -141,11 +149,24 @@
{
LoadFromStorage();
+ if (WiFiManager::StationStatus::CONNECTING <= WiFiManager::Instance().GetStationStatus())
+ {
+ WiFiManager::WiFiInfo wifiInfo;
+ ReturnErrorOnFailure(WiFiManager::Instance().GetWiFiInfo(wifiInfo));
+ if (mStagingNetwork.GetSsidSpan().data_equal(ByteSpan(wifiInfo.mSsid, wifiInfo.mSsidLen)))
+ {
+ // we are already connected to this network, so return prematurely
+ return CHIP_NO_ERROR;
+ }
+
+ WiFiManager::Instance().Disconnect();
+ }
+
if (mStagingNetwork.IsConfigured())
{
- WiFiManager::ConnectionHandling handling{ [] { Instance().OnConnectWiFiNetwork(); },
- [] { Instance().OnConnectWiFiNetworkFailed(); },
- System::Clock::Timeout{ 40000 } };
+ WiFiManager::ConnectionHandling handling{ [] { Instance().OnNetworkStatusChanged(Status::kSuccess); },
+ [] { Instance().OnNetworkStatusChanged(Status::kUnknownError); },
+ System::Clock::Seconds32{ kWiFiConnectNetworkTimeoutSeconds } };
ReturnErrorOnFailure(
WiFiManager::Instance().Connect(mStagingNetwork.GetSsidSpan(), mStagingNetwork.GetPassSpan(), handling));
}
@@ -163,6 +184,7 @@
VerifyOrReturnError(ssid.size() <= sizeof(mStagingNetwork.ssid), Status::kOutOfRange);
VerifyOrReturnError(credentials.size() <= sizeof(mStagingNetwork.pass), Status::kOutOfRange);
+ mStagingNetwork.Erase();
memcpy(mStagingNetwork.ssid, ssid.data(), ssid.size());
memcpy(mStagingNetwork.pass, credentials.data(), credentials.size());
mStagingNetwork.ssidLen = ssid.size();
@@ -196,9 +218,12 @@
void NrfWiFiDriver::ConnectNetwork(ByteSpan networkId, ConnectCallback * callback)
{
Status status = Status::kSuccess;
- WiFiManager::ConnectionHandling handling{ [] { Instance().OnConnectWiFiNetwork(); },
- [] { Instance().OnConnectWiFiNetworkFailed(); }, System::Clock::Timeout{ 40000 } };
+ WiFiManager::ConnectionHandling handling{ [] { Instance().OnNetworkStatusChanged(Status::kSuccess); },
+ [] { Instance().OnNetworkStatusChanged(Status::kUnknownError); },
+ System::Clock::Seconds32{ kWiFiConnectNetworkTimeoutSeconds } };
+ VerifyOrExit(WiFiManager::StationStatus::CONNECTING != WiFiManager::Instance().GetStationStatus(),
+ status = Status::kOtherConnectionFailure);
VerifyOrExit(networkId.data_equal(mStagingNetwork.GetSsidSpan()), status = Status::kNetworkIDNotFound);
VerifyOrExit(mpConnectCallback == nullptr, status = Status::kUnknownError);
@@ -206,43 +231,42 @@
WiFiManager::Instance().Connect(mStagingNetwork.GetSsidSpan(), mStagingNetwork.GetPassSpan(), handling);
exit:
- if (status != Status::kSuccess)
+ if (status != Status::kSuccess && mpConnectCallback)
{
- mpConnectCallback = nullptr;
- callback->OnResult(status, CharSpan(), 0);
- }
-}
-
-CHIP_ERROR GetConfiguredNetwork(Network & network)
-{
- return CHIP_NO_ERROR;
-}
-
-void NrfWiFiDriver::OnConnectWiFiNetwork()
-{
- ConnectivityMgr().SetWiFiStationMode(ConnectivityManager::kWiFiStationMode_Enabled);
-
- if (mpConnectCallback)
- {
- mpConnectCallback->OnResult(Status::kSuccess, CharSpan(), 0);
+ mpConnectCallback->OnResult(status, CharSpan(), 0);
mpConnectCallback = nullptr;
}
}
-void NrfWiFiDriver::OnConnectWiFiNetworkFailed()
+void NrfWiFiDriver::LoadFromStorage()
{
- if (mpConnectCallback)
- {
- mpConnectCallback->OnResult(Status::kNetworkNotFound, CharSpan(), 0);
- mpConnectCallback = nullptr;
- }
+ WiFiManager::WiFiNetwork network;
+
+ mStagingNetwork = {};
+ ReturnOnFailure(KeyValueStoreMgr().Get(kSsidKey, network.ssid, sizeof(network.ssid), &network.ssidLen));
+ ReturnOnFailure(KeyValueStoreMgr().Get(kPassKey, network.pass, sizeof(network.pass), &network.passLen));
+ mStagingNetwork = network;
+}
+
+void NrfWiFiDriver::OnScanWiFiNetworkDone(WiFiManager::WiFiRequestStatus status)
+{
+ VerifyOrReturn(mScanCallback != nullptr);
+ mScanCallback->OnFinished(status == WiFiManager::WiFiRequestStatus::SUCCESS ? Status::kSuccess : Status::kUnknownError,
+ CharSpan(), &mScanResponseIterator);
+ mScanCallback = nullptr;
+}
+
+void NrfWiFiDriver::OnScanWiFiNetworkResult(const WiFiScanResponse & response)
+{
+ mScanResponseIterator.Add(response);
}
void NrfWiFiDriver::ScanNetworks(ByteSpan ssid, WiFiDriver::ScanCallback * callback)
{
mScanCallback = callback;
CHIP_ERROR error = WiFiManager::Instance().Scan(
- ssid, [](int status, WiFiScanResponse * response) { Instance().OnScanWiFiNetworkDone(status, response); });
+ ssid, [](const WiFiScanResponse & response) { Instance().OnScanWiFiNetworkResult(response); },
+ [](WiFiManager::WiFiRequestStatus status) { Instance().OnScanWiFiNetworkDone(status); });
if (error != CHIP_NO_ERROR)
{
@@ -251,34 +275,6 @@
}
}
-void NrfWiFiDriver::OnScanWiFiNetworkDone(int status, WiFiScanResponse * response)
-{
- if (response != nullptr)
- {
- StackLock lock;
- VerifyOrReturn(mScanCallback != nullptr);
- mScanResponseIterator.Add(*response);
- return;
- }
-
- // Scan complete
- DeviceLayer::SystemLayer().ScheduleLambda([this, status]() {
- VerifyOrReturn(mScanCallback != nullptr);
- mScanCallback->OnFinished(status == 0 ? Status::kSuccess : Status::kUnknownError, CharSpan(), &mScanResponseIterator);
- mScanCallback = nullptr;
- });
-}
-
-void NrfWiFiDriver::LoadFromStorage()
-{
- WiFiNetwork network;
-
- mStagingNetwork = {};
- ReturnOnFailure(KeyValueStoreMgr().Get(kSsidKey, network.ssid, sizeof(network.ssid), &network.ssidLen));
- ReturnOnFailure(KeyValueStoreMgr().Get(kPassKey, network.pass, sizeof(network.pass), &network.passLen));
- mStagingNetwork = network;
-}
-
} // namespace NetworkCommissioning
} // namespace DeviceLayer
} // namespace chip
diff --git a/src/platform/nrfconnect/wifi/NrfWiFiDriver.h b/src/platform/nrfconnect/wifi/NrfWiFiDriver.h
index 880cce8..7b57607 100644
--- a/src/platform/nrfconnect/wifi/NrfWiFiDriver.h
+++ b/src/platform/nrfconnect/wifi/NrfWiFiDriver.h
@@ -16,6 +16,9 @@
*/
#pragma once
+
+#include "WiFiManager.h"
+
#include <platform/NetworkCommissioning.h>
namespace chip {
@@ -24,7 +27,7 @@
constexpr uint8_t kMaxWiFiNetworks = 1;
constexpr uint8_t kWiFiScanNetworksTimeOutSeconds = 10;
-constexpr uint8_t kWiFiConnectNetworkTimeoutSeconds = 120;
+constexpr uint8_t kWiFiConnectNetworkTimeoutSeconds = 35;
class NrfWiFiScanResponseIterator : public Iterator<WiFiScanResponse>
{
@@ -62,19 +65,6 @@
bool mExhausted{ false };
};
- struct WiFiNetwork
- {
- uint8_t ssid[DeviceLayer::Internal::kMaxWiFiSSIDLength];
- size_t ssidLen = 0;
- uint8_t pass[DeviceLayer::Internal::kMaxWiFiKeyLength];
- size_t passLen = 0;
-
- bool IsConfigured() const { return ssidLen > 0; }
- ByteSpan GetSsidSpan() const { return ByteSpan(ssid, ssidLen); }
- ByteSpan GetPassSpan() const { return ByteSpan(pass, passLen); }
- void Clear() { ssidLen = 0; }
- };
-
// BaseDriver
NetworkIterator * GetNetworks() override { return new WiFiNetworkIterator(this); }
CHIP_ERROR Init(NetworkStatusChangeCallback * networkStatusChangeCallback) override;
@@ -103,17 +93,16 @@
return sInstance;
}
- void OnConnectWiFiNetwork();
- void OnConnectWiFiNetworkFailed();
void OnNetworkStatusChanged(Status status);
- void OnScanWiFiNetworkDone(int status, WiFiScanResponse * result);
+ void OnScanWiFiNetworkResult(const WiFiScanResponse & result);
+ void OnScanWiFiNetworkDone(WiFiManager::WiFiRequestStatus status);
private:
void LoadFromStorage();
ConnectCallback * mpConnectCallback{ nullptr };
NetworkStatusChangeCallback * mpNetworkStatusChangeCallback{ nullptr };
- WiFiNetwork mStagingNetwork;
+ WiFiManager::WiFiNetwork mStagingNetwork;
NrfWiFiScanResponseIterator mScanResponseIterator;
ScanCallback * mScanCallback{ nullptr };
};
diff --git a/src/platform/nrfconnect/wifi/WiFiManager.cpp b/src/platform/nrfconnect/wifi/WiFiManager.cpp
index 7c2313f..a47655c 100644
--- a/src/platform/nrfconnect/wifi/WiFiManager.cpp
+++ b/src/platform/nrfconnect/wifi/WiFiManager.cpp
@@ -22,33 +22,35 @@
#include "WiFiManager.h"
+#include <crypto/RandUtils.h>
#include <inet/InetInterface.h>
#include <inet/UDPEndPointImplSockets.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/CHIPDeviceLayer.h>
#include <platform/Zephyr/InetUtils.h>
-#include <net/net_stats.h>
-#include <zephyr.h>
+#include <zephyr/kernel.h>
+#include <zephyr/net/net_event.h>
+#include <zephyr/net/net_if.h>
+#include <zephyr/net/net_stats.h>
extern "C" {
#include <common/defs.h>
#include <wpa_supplicant/config.h>
#include <wpa_supplicant/driver_i.h>
#include <wpa_supplicant/scan.h>
-#include <zephyr/net/wifi_mgmt.h>
+
+// extern function to obtain bssid from status buffer
+// It is defined in zephyr/subsys/net/ip/utils.c
+extern char * net_sprint_ll_addr_buf(const uint8_t * ll, uint8_t ll_len, char * buf, int buflen);
}
-extern struct wpa_global * global;
-
-static struct wpa_supplicant * wpa_s;
-
namespace chip {
namespace DeviceLayer {
namespace {
-NetworkCommissioning::WiFiScanResponse ToScanResponse(wifi_scan_result * result)
+NetworkCommissioning::WiFiScanResponse ToScanResponse(const wifi_scan_result * result)
{
NetworkCommissioning::WiFiScanResponse response = {};
@@ -73,49 +75,50 @@
} // namespace
-// These enums shall reflect the overall ordered disconnected->connected flow
-const Map<wpa_states, WiFiManager::StationStatus, 10>
- WiFiManager::sStatusMap({ { WPA_DISCONNECTED, WiFiManager::StationStatus::DISCONNECTED },
- { WPA_INTERFACE_DISABLED, WiFiManager::StationStatus::DISABLED },
- { WPA_INACTIVE, WiFiManager::StationStatus::DISABLED },
- { WPA_SCANNING, WiFiManager::StationStatus::SCANNING },
- { WPA_AUTHENTICATING, WiFiManager::StationStatus::CONNECTING },
- { WPA_ASSOCIATING, WiFiManager::StationStatus::CONNECTING },
- { WPA_ASSOCIATED, WiFiManager::StationStatus::CONNECTED },
- { WPA_4WAY_HANDSHAKE, WiFiManager::StationStatus::PROVISIONING },
- { WPA_GROUP_HANDSHAKE, WiFiManager::StationStatus::PROVISIONING },
- { WPA_COMPLETED, WiFiManager::StationStatus::FULLY_PROVISIONED } });
+const Map<wifi_iface_state, WiFiManager::StationStatus, 10>
+ WiFiManager::sStatusMap({ { WIFI_STATE_DISCONNECTED, WiFiManager::StationStatus::DISCONNECTED },
+ { WIFI_STATE_INTERFACE_DISABLED, WiFiManager::StationStatus::DISABLED },
+ { WIFI_STATE_INACTIVE, WiFiManager::StationStatus::DISABLED },
+ { WIFI_STATE_SCANNING, WiFiManager::StationStatus::SCANNING },
+ { WIFI_STATE_AUTHENTICATING, WiFiManager::StationStatus::CONNECTING },
+ { WIFI_STATE_ASSOCIATING, WiFiManager::StationStatus::CONNECTING },
+ { WIFI_STATE_ASSOCIATED, WiFiManager::StationStatus::CONNECTED },
+ { WIFI_STATE_4WAY_HANDSHAKE, WiFiManager::StationStatus::PROVISIONING },
+ { WIFI_STATE_GROUP_HANDSHAKE, WiFiManager::StationStatus::PROVISIONING },
+ { WIFI_STATE_COMPLETED, WiFiManager::StationStatus::FULLY_PROVISIONED } });
-// Map WiFi center frequency to the corresponding channel number
-const Map<uint16_t, uint8_t, 42> WiFiManager::sFreqChannelMap(
- { { 4915, 183 }, { 4920, 184 }, { 4925, 185 }, { 4935, 187 }, { 4940, 188 }, { 4945, 189 }, { 4960, 192 },
- { 4980, 196 }, { 5035, 7 }, { 5040, 8 }, { 5045, 9 }, { 5055, 11 }, { 5060, 12 }, { 5080, 16 },
- { 5170, 34 }, { 5180, 36 }, { 5190, 38 }, { 5200, 40 }, { 5210, 42 }, { 5220, 44 }, { 5230, 46 },
- { 5240, 48 }, { 5260, 52 }, { 5280, 56 }, { 5300, 60 }, { 5320, 64 }, { 5500, 100 }, { 5520, 104 },
- { 5540, 108 }, { 5560, 112 }, { 5580, 116 }, { 5600, 120 }, { 5620, 124 }, { 5640, 128 }, { 5660, 132 },
- { 5680, 136 }, { 5700, 140 }, { 5745, 149 }, { 5765, 153 }, { 5785, 157 }, { 5805, 161 }, { 5825, 165 } });
+const Map<uint32_t, WiFiManager::NetEventHandler, 4>
+ WiFiManager::sEventHandlerMap({ { NET_EVENT_WIFI_SCAN_RESULT, WiFiManager::ScanResultHandler },
+ { NET_EVENT_WIFI_SCAN_DONE, WiFiManager::ScanDoneHandler },
+ { NET_EVENT_WIFI_CONNECT_RESULT, WiFiManager::ConnectHandler },
+ { NET_EVENT_WIFI_DISCONNECT_RESULT, WiFiManager::DisconnectHandler } });
+
+void WiFiManager::WifiMgmtEventHandler(net_mgmt_event_callback * cb, uint32_t mgmtEvent, net_if * iface)
+{
+ if (0 == strcmp(iface->if_dev->dev->name, "wlan0"))
+ {
+ Platform::UniquePtr<uint8_t> eventData(new uint8_t[cb->info_length]);
+ VerifyOrReturn(eventData);
+ memcpy(eventData.get(), cb->info, cb->info_length);
+ CHIP_ERROR status = SystemLayer().ScheduleLambda([data = eventData.get(), mgmtEvent]() {
+ if (data)
+ {
+ sEventHandlerMap[mgmtEvent](data);
+ // cleanup
+ delete[] data;
+ }
+ });
+
+ if (CHIP_NO_ERROR == status)
+ {
+ // the ownership has been transferred to the worker thread - release the buffer
+ eventData.release();
+ }
+ }
+}
CHIP_ERROR WiFiManager::Init()
{
- // wpa_supplicant instance is initialized in dedicated supplicant thread, so wait until
- // the initialization is completed.
- // TODO: fix thread-safety of the solution.
- constexpr size_t kInitTimeoutMs = 5000;
- const int64_t initStartTime = k_uptime_get();
- // TODO: Handle multiple VIFs
- const char * ifname = "wlan0";
-
- while (!global || !(wpa_s = wpa_supplicant_get_iface(global, ifname)))
- {
- if (k_uptime_get() > initStartTime + kInitTimeoutMs)
- {
- ChipLogError(DeviceLayer, "wpa_supplicant is not initialized!");
- return CHIP_ERROR_INTERNAL;
- }
-
- k_msleep(200);
- }
-
// TODO: consider moving these to ConnectivityManagerImpl to be prepared for handling multiple interfaces on a single device.
Inet::UDPEndPointImplSockets::SetJoinMulticastGroupHandler([](Inet::InterfaceId interfaceId, const Inet::IPAddress & address) {
const in6_addr addr = InetUtils::ToZephyrAddr(address);
@@ -145,234 +148,114 @@
return CHIP_NO_ERROR;
});
- ChipLogDetail(DeviceLayer, "wpa_supplicant has been initialized");
+ net_mgmt_init_event_callback(&mWiFiMgmtClbk, WifiMgmtEventHandler, kWifiManagementEvents);
+ net_mgmt_add_event_callback(&mWiFiMgmtClbk);
+
+ ChipLogDetail(DeviceLayer, "WiFiManager has been initialized");
return CHIP_NO_ERROR;
}
-
-CHIP_ERROR WiFiManager::AddNetwork(const ByteSpan & ssid, const ByteSpan & credentials)
+CHIP_ERROR WiFiManager::Scan(const ByteSpan & ssid, ScanResultCallback resultCallback, ScanDoneCallback doneCallback,
+ bool internalScan)
{
- ChipLogDetail(DeviceLayer, "Adding WiFi network");
- mpWpaNetwork = wpa_supplicant_add_network(wpa_s);
- if (mpWpaNetwork)
+ net_if * iface = InetUtils::GetInterface();
+ VerifyOrReturnError(nullptr != iface, CHIP_ERROR_INTERNAL);
+
+ mInternalScan = internalScan;
+ mScanResultCallback = resultCallback;
+ mScanDoneCallback = doneCallback;
+ mWiFiState = WIFI_STATE_SCANNING;
+
+ if (net_mgmt(NET_REQUEST_WIFI_SCAN, iface, NULL, 0))
{
- static constexpr size_t kMaxSsidLen{ 32 };
- mpWpaNetwork->ssid = (u8 *) k_malloc(kMaxSsidLen);
-
- if (mpWpaNetwork->ssid)
- {
- memcpy(mpWpaNetwork->ssid, ssid.data(), ssid.size());
- mpWpaNetwork->ssid_len = ssid.size();
- mpWpaNetwork->key_mgmt = WPA_KEY_MGMT_NONE;
- mpWpaNetwork->disabled = 1;
- wpa_s->conf->filter_ssids = 1;
-
- return AddPsk(credentials);
- }
+ ChipLogError(DeviceLayer, "Scan request failed");
+ return CHIP_ERROR_INTERNAL;
}
- return CHIP_ERROR_INTERNAL;
-}
-
-CHIP_ERROR WiFiManager::Scan(const ByteSpan & ssid, ScanCallback callback)
-{
- const StationStatus stationStatus = GetStationStatus();
- VerifyOrReturnError(stationStatus != StationStatus::DISABLED && stationStatus != StationStatus::SCANNING &&
- stationStatus != StationStatus::CONNECTING,
- CHIP_ERROR_INCORRECT_STATE);
-
- net_if * const iface = InetUtils::GetInterface();
- VerifyOrReturnError(iface != nullptr, CHIP_ERROR_INTERNAL);
-
- const device * dev = net_if_get_device(iface);
- VerifyOrReturnError(dev != nullptr, CHIP_ERROR_INTERNAL);
-
- const net_wifi_mgmt_offload * ops = static_cast<const net_wifi_mgmt_offload *>(dev->api);
- VerifyOrReturnError(ops != nullptr, CHIP_ERROR_INTERNAL);
-
- mScanCallback = callback;
-
- // TODO: Use saner API once such exists.
- // TODO: Take 'ssid' into account.
- VerifyOrReturnError(ops->scan(dev,
- [](net_if *, int status, wifi_scan_result * result) {
- VerifyOrReturn(Instance().mScanCallback != nullptr);
- NetworkCommissioning::WiFiScanResponse response = ToScanResponse(result);
- Instance().mScanCallback(status, result != nullptr ? &response : nullptr);
- }) == 0,
- CHIP_ERROR_INTERNAL);
-
- return CHIP_NO_ERROR;
-}
-
-CHIP_ERROR WiFiManager::Connect(const ByteSpan & ssid, const ByteSpan & credentials, const ConnectionHandling & handling)
-{
- ChipLogDetail(DeviceLayer, "Connecting to WiFi network");
-
- mConnectionSuccessClbk = handling.mOnConnectionSuccess;
- mConnectionFailedClbk = handling.mOnConnectionFailed;
- mConnectionTimeoutMs = handling.mConnectionTimeoutMs;
-
- CHIP_ERROR err = AddNetwork(ssid, credentials);
- if (CHIP_NO_ERROR == err)
- {
- EnableStation(true);
- wpa_supplicant_select_network(wpa_s, mpWpaNetwork);
- WaitForConnectionAsync();
- }
- else
- {
- OnConnectionFailed();
- }
- return err;
-}
-
-void WiFiManager::OnConnectionSuccess()
-{
- if (mConnectionSuccessClbk)
- mConnectionSuccessClbk();
-}
-
-void WiFiManager::OnConnectionFailed()
-{
- if (mConnectionFailedClbk)
- mConnectionFailedClbk();
-}
-
-CHIP_ERROR WiFiManager::AddPsk(const ByteSpan & credentials)
-{
- mpWpaNetwork->key_mgmt = WPA_KEY_MGMT_PSK;
- str_clear_free(mpWpaNetwork->passphrase);
- mpWpaNetwork->passphrase = dup_binstr(credentials.data(), credentials.size());
-
- if (mpWpaNetwork->passphrase)
- {
- wpa_config_update_psk(mpWpaNetwork);
- return CHIP_NO_ERROR;
- }
-
- return CHIP_ERROR_INTERNAL;
-}
-
-WiFiManager::StationStatus WiFiManager::GetStationStatus() const
-{
- if (wpa_s)
- {
- return StatusFromWpaStatus(wpa_s->wpa_state);
- }
- else
- {
- ChipLogError(DeviceLayer, "wpa_supplicant is not initialized!");
- return StationStatus::NONE;
- }
-}
-
-WiFiManager::StationStatus WiFiManager::StatusFromWpaStatus(const wpa_states & status)
-{
- ChipLogDetail(DeviceLayer, "WPA internal status: %d", static_cast<int>(status));
- return WiFiManager::sStatusMap[status];
-}
-
-CHIP_ERROR WiFiManager::EnableStation(bool enable)
-{
- VerifyOrReturnError(nullptr != wpa_s && nullptr != mpWpaNetwork, CHIP_ERROR_INTERNAL);
- if (enable)
- {
- wpa_supplicant_enable_network(wpa_s, mpWpaNetwork);
- }
- else
- {
- wpa_supplicant_disable_network(wpa_s, mpWpaNetwork);
- }
+ ChipLogDetail(DeviceLayer, "WiFi scanning started...");
return CHIP_NO_ERROR;
}
CHIP_ERROR WiFiManager::ClearStationProvisioningData()
{
- VerifyOrReturnError(nullptr != wpa_s && nullptr != mpWpaNetwork, CHIP_ERROR_INTERNAL);
- wpa_supplicant_cancel_scan(wpa_s);
- wpa_clear_keys(wpa_s, mpWpaNetwork->bssid);
- str_clear_free(mpWpaNetwork->passphrase);
- wpa_config_update_psk(mpWpaNetwork);
- wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
-
+ mWiFiParams.mRssi = std::numeric_limits<int8_t>::min();
+ memset(&mWiFiParams.mParams, 0, sizeof(mWiFiParams.mParams));
return CHIP_NO_ERROR;
}
-CHIP_ERROR WiFiManager::DisconnectStation()
+CHIP_ERROR WiFiManager::Connect(const ByteSpan & ssid, const ByteSpan & credentials, const ConnectionHandling & handling)
{
- VerifyOrReturnError(nullptr != wpa_s, CHIP_ERROR_INTERNAL);
- wpa_supplicant_cancel_scan(wpa_s);
- wpas_request_disconnection(wpa_s);
+ ChipLogDetail(DeviceLayer, "Connecting to WiFi network: %*s", ssid.size(), ssid.data());
- return CHIP_NO_ERROR;
+ mHandling.mOnConnectionSuccess = handling.mOnConnectionSuccess;
+ mHandling.mOnConnectionFailed = handling.mOnConnectionFailed;
+ mHandling.mConnectionTimeout = handling.mConnectionTimeout;
+
+ mWiFiState = WIFI_STATE_ASSOCIATING;
+
+ // Store SSID and credentials and perform the scan to detect the security mode supported by the AP.
+ // Zephyr WiFi connect request will be issued in the callback when we have the SSID match.
+ mWantedNetwork.Erase();
+ memcpy(mWantedNetwork.ssid, ssid.data(), ssid.size());
+ memcpy(mWantedNetwork.pass, credentials.data(), credentials.size());
+ mWantedNetwork.ssidLen = ssid.size();
+ mWantedNetwork.passLen = credentials.size();
+
+ return Scan(ssid, nullptr, nullptr, true /* internal scan */);
}
-void WiFiManager::WaitForConnectionAsync()
+CHIP_ERROR WiFiManager::Disconnect()
{
- chip::DeviceLayer::SystemLayer().StartTimer(
- static_cast<System::Clock::Timeout>(1000), [](System::Layer *, void *) { Instance().PollTimerCallback(); }, nullptr);
-}
+ net_if * iface = InetUtils::GetInterface();
+ VerifyOrReturnError(nullptr != iface, CHIP_ERROR_INTERNAL);
-void WiFiManager::PollTimerCallback()
-{
- const uint32_t kMaxRetriesNumber{ mConnectionTimeoutMs.count() / 1000 };
- static uint32_t retriesNumber{ 0 };
+ int status = net_mgmt(NET_REQUEST_WIFI_DISCONNECT, iface, NULL, 0);
- if (WiFiManager::StationStatus::FULLY_PROVISIONED == GetStationStatus())
+ if (status)
{
- retriesNumber = 0;
- OnConnectionSuccess();
- }
- else
- {
- if (retriesNumber++ < kMaxRetriesNumber)
+ if (status == -EALREADY)
{
- // wait more time
- WaitForConnectionAsync();
+ ChipLogDetail(DeviceLayer, "Already disconnected");
}
else
{
- // connection timeout
- retriesNumber = 0;
- OnConnectionFailed();
+ ChipLogDetail(DeviceLayer, "Disconnect request failed");
+ return CHIP_ERROR_INTERNAL;
}
}
+ else
+ {
+ ChipLogDetail(DeviceLayer, "Disconnect requested");
+ }
+
+ return CHIP_NO_ERROR;
}
CHIP_ERROR WiFiManager::GetWiFiInfo(WiFiInfo & info) const
{
- VerifyOrReturnError(nullptr != wpa_s, CHIP_ERROR_INTERNAL);
- VerifyOrReturnError(nullptr != mpWpaNetwork, CHIP_ERROR_INTERNAL);
+ net_if * iface = InetUtils::GetInterface();
+ VerifyOrReturnError(nullptr != iface, CHIP_ERROR_INTERNAL);
+ struct wifi_iface_status status = { 0 };
- static uint8_t sBssid[ETH_ALEN];
- if (WiFiManager::StationStatus::CONNECTED <= GetStationStatus())
+ if (net_mgmt(NET_REQUEST_WIFI_IFACE_STATUS, iface, &status, sizeof(struct wifi_iface_status)))
{
- memcpy(sBssid, wpa_s->bssid, ETH_ALEN);
- info.mBssId = ByteSpan(sBssid, ETH_ALEN);
- info.mSecurityType = GetSecurityType();
- // TODO: this should reflect the real connection compliance
- // i.e. the AP might support WiFi 5 only even though the station
- // is WiFi 6 ready (so the connection is WiFi 5 effectively).
- // For now just return what the station supports.
- info.mWiFiVersion = EMBER_ZCL_WI_FI_VERSION_TYPE_AX;
+ ChipLogError(DeviceLayer, "Status request failed");
+ return CHIP_ERROR_INTERNAL;
+ }
- wpa_signal_info signalInfo{};
- if (0 == wpa_drv_signal_poll(wpa_s, &signalInfo))
- {
- info.mRssi = signalInfo.current_signal; // dBm
- info.mChannel = FrequencyToChannel(signalInfo.frequency);
- }
- else
- {
- // this values should be nullable according to the Matter spec
- info.mRssi = std::numeric_limits<decltype(info.mRssi)>::min();
- info.mChannel = std::numeric_limits<decltype(info.mChannel)>::min();
- }
-
- memcpy(info.mSsid, mpWpaNetwork->ssid, mpWpaNetwork->ssid_len);
- info.mSsidLen = mpWpaNetwork->ssid_len;
+ if (status.state >= WIFI_STATE_ASSOCIATED)
+ {
+ uint8_t mac_string_buf[sizeof("xx:xx:xx:xx:xx:xx")];
+ net_sprint_ll_addr_buf(reinterpret_cast<const uint8_t *>(status.bssid), WIFI_MAC_ADDR_LEN,
+ reinterpret_cast<char *>(mac_string_buf), sizeof(mac_string_buf));
+ info.mBssId = ByteSpan(mac_string_buf, sizeof(mac_string_buf));
+ info.mSecurityType = static_cast<uint8_t>(status.security);
+ info.mWiFiVersion = static_cast<uint8_t>(status.link_mode);
+ info.mRssi = status.rssi;
+ info.mChannel = status.channel;
+ info.mSsidLen = status.ssid_len;
+ memcpy(info.mSsid, status.ssid, status.ssid_len);
return CHIP_NO_ERROR;
}
@@ -380,53 +263,6 @@
return CHIP_ERROR_INTERNAL;
}
-uint8_t WiFiManager::GetSecurityType() const
-{
- VerifyOrReturnValue(nullptr != mpWpaNetwork, EMBER_ZCL_SECURITY_TYPE_UNSPECIFIED);
-
- if ((mpWpaNetwork->key_mgmt & WPA_KEY_MGMT_NONE) || !wpa_key_mgmt_wpa_any(mpWpaNetwork->key_mgmt))
- {
- return EMBER_ZCL_SECURITY_TYPE_NONE;
- }
- else if (wpa_key_mgmt_wpa_psk_no_sae(mpWpaNetwork->key_mgmt))
- {
- return (mpWpaNetwork->pairwise_cipher & (WPA_CIPHER_TKIP | WPA_CIPHER_CCMP)) ? EMBER_ZCL_SECURITY_TYPE_WPA2
- : EMBER_ZCL_SECURITY_TYPE_WPA3;
- }
- else if (wpa_key_mgmt_sae(mpWpaNetwork->key_mgmt))
- {
- return EMBER_ZCL_SECURITY_TYPE_WPA3;
- }
- else
- {
- return EMBER_ZCL_SECURITY_TYPE_WEP;
- }
-
- return EMBER_ZCL_SECURITY_TYPE_UNSPECIFIED;
-}
-
-uint8_t WiFiManager::FrequencyToChannel(uint16_t freq)
-{
- static constexpr uint16_t k24MinFreq{ 2401 };
- static constexpr uint16_t k24MaxFreq{ 2484 };
- static constexpr uint8_t k24FreqConstDiff{ 5 };
-
- if (freq >= k24MinFreq && freq < k24MaxFreq)
- {
- return static_cast<uint8_t>((freq - k24MinFreq) / k24FreqConstDiff + 1);
- }
- else if (freq == k24MaxFreq)
- {
- return 14;
- }
- else if (freq > k24MaxFreq)
- {
- // assume we are in 5GH band
- return sFreqChannelMap[freq];
- }
- return 0;
-}
-
CHIP_ERROR WiFiManager::GetNetworkStatistics(NetworkStatistics & stats) const
{
// TODO: below will not work (result will be all zeros) until
@@ -443,5 +279,159 @@
return CHIP_NO_ERROR;
}
+void WiFiManager::ScanResultHandler(uint8_t * data)
+{
+ const struct wifi_scan_result * scanResult = reinterpret_cast<const struct wifi_scan_result *>(data);
+
+ if (Instance().mInternalScan &&
+ Instance().mWantedNetwork.GetSsidSpan().data_equal(ByteSpan(scanResult->ssid, scanResult->ssid_length)))
+ {
+ // Prepare the connection parameters
+ // In case there are many networks with the same SSID choose the one with the best RSSI
+ if (scanResult->rssi > Instance().mWiFiParams.mRssi)
+ {
+ Instance().ClearStationProvisioningData();
+ Instance().mWiFiParams.mParams.ssid_length = Instance().mWantedNetwork.ssidLen;
+ Instance().mWiFiParams.mParams.ssid = Instance().mWantedNetwork.ssid;
+ // Fallback to the WIFI_SECURITY_TYPE_PSK if the security is unknown
+ Instance().mWiFiParams.mParams.security =
+ scanResult->security <= WIFI_SECURITY_TYPE_MAX ? scanResult->security : WIFI_SECURITY_TYPE_PSK;
+ Instance().mWiFiParams.mParams.psk_length = Instance().mWantedNetwork.passLen;
+
+ // If the security is none, WiFi driver expects the psk to be nullptr
+ if (Instance().mWiFiParams.mParams.security == WIFI_SECURITY_TYPE_NONE)
+ {
+ Instance().mWiFiParams.mParams.psk = nullptr;
+ }
+ else
+ {
+ Instance().mWiFiParams.mParams.psk = Instance().mWantedNetwork.pass;
+ }
+
+ Instance().mWiFiParams.mParams.timeout = Instance().mHandling.mConnectionTimeout.count();
+ Instance().mWiFiParams.mParams.channel = scanResult->channel;
+ Instance().mWiFiParams.mRssi = scanResult->rssi;
+ }
+ }
+
+ if (Instance().mScanResultCallback && !Instance().mInternalScan)
+ {
+ Instance().mScanResultCallback(ToScanResponse(scanResult));
+ }
+}
+
+void WiFiManager::ScanDoneHandler(uint8_t * data)
+{
+ const wifi_status * status = reinterpret_cast<const wifi_status *>(data);
+ WiFiRequestStatus requestStatus = static_cast<WiFiRequestStatus>(status->status);
+
+ if (Instance().mScanDoneCallback && !Instance().mInternalScan)
+ {
+ Instance().mScanDoneCallback(requestStatus);
+ }
+
+ if (requestStatus == WiFiRequestStatus::FAILURE)
+ {
+ ChipLogDetail(DeviceLayer, "Scan request failed (%d)", status->status);
+ }
+ else
+ {
+ ChipLogDetail(DeviceLayer, "Scan request done (%d)", status->status);
+
+ // Internal scan is supposed to be followed by connection request
+ if (Instance().mInternalScan)
+ {
+ Instance().mWiFiState = WIFI_STATE_ASSOCIATING;
+ net_if * iface = InetUtils::GetInterface();
+ VerifyOrReturn(nullptr != iface, CHIP_ERROR_INTERNAL);
+
+ if (net_mgmt(NET_REQUEST_WIFI_CONNECT, iface, &(Instance().mWiFiParams.mParams), sizeof(wifi_connect_req_params)))
+ {
+ ChipLogError(DeviceLayer, "Connection request failed");
+ if (Instance().mHandling.mOnConnectionFailed)
+ {
+ Instance().mHandling.mOnConnectionFailed();
+ }
+ return;
+ }
+ ChipLogError(DeviceLayer, "Connection to %*s requested", Instance().mWiFiParams.mParams.ssid_length,
+ Instance().mWiFiParams.mParams.ssid);
+ Instance().mInternalScan = false;
+ }
+ }
+}
+
+void WiFiManager::SendRouterSolicitation(System::Layer * layer, void * param)
+{
+ net_if * iface = InetUtils::GetInterface();
+ if (iface && iface->if_dev->link_addr.type == NET_LINK_ETHERNET)
+ {
+ net_if_start_rs(iface);
+ Instance().mRouterSolicitationCounter++;
+ if (Instance().mRouterSolicitationCounter < kRouterSolicitationMaxCount)
+ {
+ DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(kRouterSolicitationIntervalMs),
+ SendRouterSolicitation, nullptr);
+ }
+ else
+ {
+ Instance().mRouterSolicitationCounter = 0;
+ }
+ }
+}
+
+void WiFiManager::ConnectHandler(uint8_t * data)
+{
+ const wifi_status * status = reinterpret_cast<const wifi_status *>(data);
+ WiFiRequestStatus requestStatus = static_cast<WiFiRequestStatus>(status->status);
+
+ if (requestStatus == WiFiRequestStatus::FAILURE || requestStatus == WiFiRequestStatus::TERMINATED)
+ {
+ ChipLogDetail(DeviceLayer, "Connection to WiFi network failed or was terminated by another request");
+ Instance().mWiFiState = WIFI_STATE_DISCONNECTED;
+ if (Instance().mHandling.mOnConnectionFailed)
+ {
+ Instance().mHandling.mOnConnectionFailed();
+ }
+ }
+ else
+ {
+ // Workaround needed until sending Router Solicitation after connect will be done by the driver.
+ DeviceLayer::SystemLayer().StartTimer(
+ System::Clock::Milliseconds32(chip::Crypto::GetRandU16() % kMaxInitialRouterSolicitationDelayMs),
+ SendRouterSolicitation, nullptr);
+
+ ChipLogDetail(DeviceLayer, "Connected to WiFi network");
+ Instance().mWiFiState = WIFI_STATE_COMPLETED;
+ if (Instance().mHandling.mOnConnectionSuccess)
+ {
+ Instance().mHandling.mOnConnectionSuccess();
+ }
+ Instance().PostConnectivityStatusChange(kConnectivity_Established);
+ }
+ // cleanup the provisioning data as it is configured per each connect request
+ Instance().ClearStationProvisioningData();
+}
+
+void WiFiManager::DisconnectHandler(uint8_t * data)
+{
+ ChipLogDetail(DeviceLayer, "WiFi station disconnected");
+ Instance().mWiFiState = WIFI_STATE_DISCONNECTED;
+ Instance().PostConnectivityStatusChange(kConnectivity_Lost);
+}
+
+WiFiManager::StationStatus WiFiManager::GetStationStatus() const
+{
+ return WiFiManager::sStatusMap[mWiFiState];
+}
+
+void WiFiManager::PostConnectivityStatusChange(ConnectivityChange changeType)
+{
+ ChipDeviceEvent networkEvent{};
+ networkEvent.Type = DeviceEventType::kWiFiConnectivityChange;
+ networkEvent.WiFiConnectivityChange.Result = changeType;
+ PlatformMgr().PostEventOrDie(&networkEvent);
+}
+
} // namespace DeviceLayer
} // namespace chip
diff --git a/src/platform/nrfconnect/wifi/WiFiManager.h b/src/platform/nrfconnect/wifi/WiFiManager.h
index b068cd9..920df4d 100644
--- a/src/platform/nrfconnect/wifi/WiFiManager.h
+++ b/src/platform/nrfconnect/wifi/WiFiManager.h
@@ -24,10 +24,12 @@
#include <lib/core/CHIPError.h>
#include <lib/support/Span.h>
+#include <platform/CHIPDeviceLayer.h>
#include <platform/NetworkCommissioning.h>
#include <system/SystemLayer.h>
-#include <net/net_if.h>
+#include <zephyr/net/net_if.h>
+#include <zephyr/net/wifi_mgmt.h>
extern "C" {
#include <src/utils/common.h>
@@ -85,9 +87,18 @@
class WiFiManager
{
+public:
+ enum WiFiRequestStatus : int
+ {
+ SUCCESS = 0,
+ FAILURE = 1,
+ TERMINATED = 2
+ };
+
+ using ScanResultCallback = void (*)(const NetworkCommissioning::WiFiScanResponse &);
+ using ScanDoneCallback = void (*)(WiFiRequestStatus);
using ConnectionCallback = void (*)();
-public:
enum class StationStatus : uint8_t
{
NONE,
@@ -97,7 +108,8 @@
CONNECTING,
CONNECTED,
PROVISIONING,
- FULLY_PROVISIONED
+ FULLY_PROVISIONED,
+ UNKNOWN
};
static WiFiManager & Instance()
@@ -106,13 +118,11 @@
return sInstance;
}
- using ScanCallback = void (*)(int /* status */, NetworkCommissioning::WiFiScanResponse *);
-
struct ConnectionHandling
{
ConnectionCallback mOnConnectionSuccess{};
ConnectionCallback mOnConnectionFailed{};
- System::Clock::Timeout mConnectionTimeoutMs{};
+ System::Clock::Seconds32 mConnectionTimeout{};
};
struct WiFiInfo
@@ -135,36 +145,72 @@
uint32_t mOverruns{};
};
+ struct WiFiNetwork
+ {
+ uint8_t ssid[DeviceLayer::Internal::kMaxWiFiSSIDLength];
+ size_t ssidLen = 0;
+ uint8_t pass[DeviceLayer::Internal::kMaxWiFiKeyLength];
+ size_t passLen = 0;
+
+ bool IsConfigured() const { return ssidLen > 0; }
+ ByteSpan GetSsidSpan() const { return ByteSpan(ssid, ssidLen); }
+ ByteSpan GetPassSpan() const { return ByteSpan(pass, passLen); }
+ void Clear() { ssidLen = 0; }
+ void Erase()
+ {
+ memset(ssid, 0, DeviceLayer::Internal::kMaxWiFiSSIDLength);
+ memset(pass, 0, DeviceLayer::Internal::kMaxWiFiKeyLength);
+ ssidLen = 0;
+ passLen = 0;
+ }
+ };
+
+ static constexpr uint16_t kRouterSolicitationIntervalMs = 4000;
+ static constexpr uint16_t kMaxInitialRouterSolicitationDelayMs = 1000;
+ static constexpr uint8_t kRouterSolicitationMaxCount = 3;
+
CHIP_ERROR Init();
- CHIP_ERROR Scan(const ByteSpan & ssid, ScanCallback callback);
+ CHIP_ERROR Scan(const ByteSpan & ssid, ScanResultCallback resultCallback, ScanDoneCallback doneCallback,
+ bool internalScan = false);
CHIP_ERROR Connect(const ByteSpan & ssid, const ByteSpan & credentials, const ConnectionHandling & handling);
StationStatus GetStationStatus() const;
CHIP_ERROR ClearStationProvisioningData();
- CHIP_ERROR DisconnectStation();
+ CHIP_ERROR Disconnect();
CHIP_ERROR GetWiFiInfo(WiFiInfo & info) const;
CHIP_ERROR GetNetworkStatistics(NetworkStatistics & stats) const;
private:
- CHIP_ERROR AddPsk(const ByteSpan & credentials);
- CHIP_ERROR EnableStation(bool enable);
- CHIP_ERROR AddNetwork(const ByteSpan & ssid, const ByteSpan & credentials);
- void PollTimerCallback();
- void WaitForConnectionAsync();
- void OnConnectionSuccess();
- void OnConnectionFailed();
- uint8_t GetSecurityType() const;
+ using NetEventHandler = void (*)(uint8_t *);
- WpaNetwork * mpWpaNetwork{ nullptr };
- ConnectionCallback mConnectionSuccessClbk;
- ConnectionCallback mConnectionFailedClbk;
- System::Clock::Timeout mConnectionTimeoutMs;
- ScanCallback mScanCallback{ nullptr };
+ struct ConnectionParams
+ {
+ wifi_connect_req_params mParams;
+ int8_t mRssi{ std::numeric_limits<int8_t>::min() };
+ };
- static uint8_t FrequencyToChannel(uint16_t freq);
- static StationStatus StatusFromWpaStatus(const wpa_states & status);
+ constexpr static uint32_t kWifiManagementEvents = NET_EVENT_WIFI_SCAN_RESULT | NET_EVENT_WIFI_SCAN_DONE |
+ NET_EVENT_WIFI_CONNECT_RESULT | NET_EVENT_WIFI_DISCONNECT_RESULT | NET_EVENT_WIFI_IFACE_STATUS;
- static const Map<wpa_states, StationStatus, 10> sStatusMap;
- static const Map<uint16_t, uint8_t, 42> sFreqChannelMap;
+ // Event handling
+ static void WifiMgmtEventHandler(net_mgmt_event_callback * cb, uint32_t mgmtEvent, net_if * iface);
+ static void ScanResultHandler(uint8_t * data);
+ static void ScanDoneHandler(uint8_t * data);
+ static void ConnectHandler(uint8_t * data);
+ static void DisconnectHandler(uint8_t * data);
+ static void PostConnectivityStatusChange(ConnectivityChange changeType);
+ static void SendRouterSolicitation(System::Layer * layer, void * param);
+
+ ConnectionParams mWiFiParams{};
+ ConnectionHandling mHandling;
+ wifi_iface_state mWiFiState;
+ net_mgmt_event_callback mWiFiMgmtClbk{};
+ ScanResultCallback mScanResultCallback{ nullptr };
+ ScanDoneCallback mScanDoneCallback{ nullptr };
+ WiFiNetwork mWantedNetwork{};
+ bool mInternalScan{ false };
+ uint8_t mRouterSolicitationCounter = 0;
+ static const Map<wifi_iface_state, StationStatus, 10> sStatusMap;
+ static const Map<uint32_t, NetEventHandler, 4> sEventHandlerMap;
};
} // namespace DeviceLayer
diff --git a/src/test_driver/nrfconnect/main/runner.cpp b/src/test_driver/nrfconnect/main/runner.cpp
index b7654f7..a44e09a 100644
--- a/src/test_driver/nrfconnect/main/runner.cpp
+++ b/src/test_driver/nrfconnect/main/runner.cpp
@@ -19,8 +19,8 @@
#include <lib/support/UnitTestRegistration.h>
#include <platform/CHIPDeviceLayer.h>
-#include <logging/log.h>
-#include <settings/settings.h>
+#include <zephyr/logging/log.h>
+#include <zephyr/settings/settings.h>
using namespace ::chip;
using namespace ::chip::DeviceLayer;