[Mbed] Fix network commissioning - add network commissioning driver (#15041)
* Add Network Commisioning Driver implementation
Add WiFi Driver
* Improve Mbed WiFi driver - move all WiFi interface code from ConnectivityManagerImpl
* Use Mbed Wifi driver in NetworkProvisioningDelegateImpl class
* Wifi interface separation from ConnectivityManagerImpl class
Create ConnectivityManagerImpl_WiFi class
Remove deprecated functions calling
* Changes restyle
* Add data model included indicator to platform config
* Add CONFIG_CHIP_DATA_MODEL flag to all Mbed examples
Passing config data model flag to gn build
Fix Wifi driver initialization for no data model examples
* Move connect callback calling to OnNetworkConnected handler
diff --git a/src/platform/BUILD.gn b/src/platform/BUILD.gn
index 0b4eb60..a7449b9 100644
--- a/src/platform/BUILD.gn
+++ b/src/platform/BUILD.gn
@@ -65,6 +65,9 @@
# todo: below operates are not work without root permission
# pthread_attr_setschedpolicy in GenericPlatformManagerImpl_POSIX.cpp
chip_device_config_run_as_root = current_os != "android"
+
+ # Indication that the CHIP data model is included
+ chip_enable_data_model = false
}
if (chip_stack_lock_tracking == "auto") {
@@ -200,6 +203,8 @@
defines += [
"CHIP_DEVICE_LAYER_TARGET_MBED=1",
"CHIP_DEVICE_LAYER_TARGET=mbed",
+ "CHIP_DEVICE_CONFIG_ENABLE_WIFI=${chip_enable_wifi}",
+ "CHIP_DEVICE_ENABLE_DATA_MODEL=${chip_enable_data_model}",
]
} else if (chip_device_platform == "fake") {
defines += [
diff --git a/src/platform/mbed/BUILD.gn b/src/platform/mbed/BUILD.gn
index 7484cff..1e13e2c 100644
--- a/src/platform/mbed/BUILD.gn
+++ b/src/platform/mbed/BUILD.gn
@@ -35,6 +35,7 @@
"Logging.cpp",
"MbedConfig.cpp",
"MbedEventTimeout.cpp",
+ "NetworkCommissioningDriver.h",
"PlatformManagerImpl.cpp",
"SystemTimeSupport.cpp",
"arch.c",
@@ -42,8 +43,10 @@
public_deps = [ "${chip_root}/src/platform:platform_base" ]
- if (chip_enable_openthread && chip_mdns == "platform") {
- sources += [ "../OpenThread/DnssdImpl.cpp" ]
- public_deps += [ "${chip_root}/src/lib/dnssd:platform_header" ]
+ if (chip_enable_wifi) {
+ sources += [
+ "ConnectivityManagerImpl_WiFi.cpp",
+ "NetworkCommissioningWiFiDriver.cpp",
+ ]
}
}
diff --git a/src/platform/mbed/ConnectivityManagerImpl.cpp b/src/platform/mbed/ConnectivityManagerImpl.cpp
index 854699c..646b56f 100644
--- a/src/platform/mbed/ConnectivityManagerImpl.cpp
+++ b/src/platform/mbed/ConnectivityManagerImpl.cpp
@@ -18,445 +18,71 @@
*/
/* this file behaves like a config.h, comes first */
-#include <net_common.h>
#include <platform/internal/CHIPDeviceLayerInternal.h>
#include <platform/ConnectivityManager.h>
+
#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
#include <platform/internal/GenericConnectivityManagerImpl_BLE.cpp>
#endif
-#include <platform/internal/GenericConnectivityManagerImpl_WiFi.cpp>
-#include <lib/support/CodeUtils.h>
-#include <lib/support/logging/CHIPLogging.h>
-#include <platform/internal/BLEManager.h>
-
-#include <type_traits>
-
-#if !CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION
-#error "WiFi Station support must be enabled when building for mbed"
+#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
+#include <platform/internal/GenericConnectivityManagerImpl_Thread.cpp>
#endif
-using namespace ::chip;
-using namespace ::chip::Inet;
-using namespace ::chip::System;
-using namespace ::chip::DeviceLayer::Internal;
+#if CHIP_DEVICE_CONFIG_ENABLE_WIFI
+#include <platform/internal/GenericConnectivityManagerImpl_WiFi.cpp>
+#endif
namespace chip {
namespace DeviceLayer {
ConnectivityManagerImpl ConnectivityManagerImpl::sInstance;
-ConnectivityManager::WiFiStationMode ConnectivityManagerImpl::_GetWiFiStationMode(void)
-{
- return mWiFiStationMode;
-}
-
-bool ConnectivityManagerImpl::_IsWiFiStationEnabled(void)
-{
- return GetWiFiStationMode() == kWiFiStationMode_Enabled;
-}
-
-bool ConnectivityManagerImpl::_IsWiFiStationApplicationControlled(void)
-{
- return mWiFiStationMode == kWiFiStationMode_ApplicationControlled;
-}
-
-CHIP_ERROR ConnectivityManagerImpl::_SetWiFiStationMode(WiFiStationMode val)
-{
- CHIP_ERROR err = CHIP_NO_ERROR;
-
- VerifyOrExit(val != kWiFiStationMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT);
-
- if (mWiFiStationMode != val)
- {
- ChipLogDetail(DeviceLayer, "WiFi station mode change: %s -> %s", WiFiStationModeToStr(mWiFiStationMode),
- WiFiStationModeToStr(val));
- }
-
- mWiFiStationMode = val;
-
-exit:
- return err;
-}
-
-bool ConnectivityManagerImpl::_IsWiFiStationConnected(void)
-{
- return mWiFiStationState == kWiFiStationState_Connected;
-}
-
-bool ConnectivityManagerImpl::_IsWiFiStationProvisioned(void)
-{
- return mIsProvisioned;
-}
-
-CHIP_ERROR ConnectivityManagerImpl::_SetWiFiAPMode(WiFiAPMode val)
-{
- CHIP_ERROR err = CHIP_NO_ERROR;
-
- VerifyOrExit(val != kWiFiAPMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT);
-
- if (mWiFiAPMode != val)
- {
- ChipLogDetail(DeviceLayer, "WiFi AP mode change: %s -> %s", WiFiAPModeToStr(mWiFiAPMode), WiFiAPModeToStr(val));
- }
-
- mWiFiAPMode = val;
-
-exit:
- return err;
-}
-
// ==================== ConnectivityManager Platform Internal Methods ====================
-
CHIP_ERROR ConnectivityManagerImpl::_Init()
{
CHIP_ERROR err = CHIP_NO_ERROR;
- mWiFiStationMode = kWiFiStationMode_NotSupported;
- mWiFiStationState = kWiFiStationState_NotConnected;
- mIsProvisioned = false;
- mIp4Address = IPAddress::Any;
- mIp6Address = IPAddress::Any;
- mWiFiAPMode = kWiFiAPMode_NotSupported;
- mWiFiStationReconnectInterval = System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_WIFI_STATION_RECONNECT_INTERVAL);
- mWiFiAPIdleTimeout = System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_WIFI_AP_IDLE_TIMEOUT);
- mSecurityType = NSAPI_SECURITY_WPA_WPA2;
-
- auto net_if = get_mbed_net_if();
- if (net_if == nullptr)
- {
- ChipLogError(DeviceLayer, "No network interface available");
- return CHIP_ERROR_NOT_IMPLEMENTED;
- }
-
- if (net_if->wifiInterface() != nullptr)
- {
- mWiFiInterface = net_if->wifiInterface();
- mWiFiStationMode = kWiFiStationMode_Enabled;
-
- // TODO: Add to user documentation that add_event_listener must be used
- // To add more listener to the interface
- mWiFiInterface->add_event_listener([this](nsapi_event_t event, intptr_t data) {
- PlatformMgrImpl().mQueue.call([this, event, data] {
- PlatformMgr().LockChipStack();
- OnInterfaceEvent(event, data);
- PlatformMgr().UnlockChipStack();
- });
- });
-
- mWiFiInterface->set_blocking(false);
- }
- return err;
-}
-
-CHIP_ERROR ConnectivityManagerImpl::_SetWiFiStationReconnectInterval(System::Clock::Timeout val)
-{
- CHIP_ERROR err = CHIP_NO_ERROR;
-
- if (mWiFiStationReconnectInterval != val)
- {
- ChipLogProgress(DeviceLayer, "WiFi station reconnect interval change: %lu ms -> %lu ms",
- System::Clock::Milliseconds32(mWiFiStationReconnectInterval).count(),
- System::Clock::Milliseconds32(val).count());
- }
-
- mWiFiStationReconnectInterval = val;
-
+#if CHIP_DEVICE_CONFIG_ENABLE_WIFI
+ err = InitWiFi();
+#endif
return err;
}
void ConnectivityManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event)
{
- // This is for internal use, state change is handled by platform middleware
+#if CHIP_DEVICE_CONFIG_ENABLE_WIFI
+ OnWiFiPlatformEvent(event);
+#endif
}
-void ConnectivityManagerImpl::_ProcessInterfaceChange(nsapi_connection_status_t new_status)
+CHIP_ERROR ConnectivityManagerImpl::PostEvent(const ChipDeviceEvent * event, bool die)
{
- switch (new_status)
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ if (die)
{
- case NSAPI_STATUS_LOCAL_UP:
- ChipLogDetail(DeviceLayer, "Connection status - LOCAL_UP");
- OnStationConnected();
- break;
- case NSAPI_STATUS_GLOBAL_UP:
- ChipLogDetail(DeviceLayer, "Connection status - GLOBAL_UP");
- OnStationConnected();
- break;
- case NSAPI_STATUS_DISCONNECTED:
- ChipLogDetail(DeviceLayer, "Connection status - DISCONNECTED");
- OnStationDisconnected();
- break;
- case NSAPI_STATUS_CONNECTING:
- ChipLogDetail(DeviceLayer, "Connection status - CONNECTING");
- OnStationConnecting();
- break;
- default:
- ChipLogDetail(DeviceLayer, "Unknown connection status: 0x%08X", new_status);
- break;
- }
-}
-
-void ConnectivityManagerImpl::OnInterfaceEvent(nsapi_event_t event, intptr_t data)
-{
- if (event == NSAPI_EVENT_CONNECTION_STATUS_CHANGE)
- {
- _ProcessInterfaceChange((nsapi_connection_status_t) data);
- }
-}
-
-CHIP_ERROR ConnectivityManagerImpl::ProvisionWiFiNetwork(const char * ssid, const char * key)
-{
- // Validate the interface is available
- if (!mWiFiInterface)
- {
- ChipLogError(DeviceLayer, "WiFi interface not supported");
- return CHIP_ERROR_INCORRECT_STATE;
- }
-
- // Set WiFi credentials
- auto error = mWiFiInterface->set_credentials(ssid, key, mSecurityType);
- if (error)
- {
- ChipLogError(DeviceLayer, "Set WiFi credentials failed %d", error);
- return CHIP_ERROR_INTERNAL;
- }
-
- mIsProvisioned = true;
-
- PlatformMgr().ScheduleWork(OnWiFiStationChange, 0);
-
- return CHIP_NO_ERROR;
-}
-
-void ConnectivityManagerImpl::_ClearWiFiStationProvision(void)
-{
- // Validate the interface is available
- if (!mWiFiInterface)
- {
- ChipLogError(DeviceLayer, "WiFi interface not supported");
- return;
- }
-
- // Reset credentials
- auto error = mWiFiInterface->set_credentials("ssid", NULL, NSAPI_SECURITY_NONE);
- if (error)
- {
- ChipLogError(DeviceLayer, "Reset WiFi credentials failed %d", error);
- return;
- }
-
- mIsProvisioned = false;
-
- PlatformMgr().ScheduleWork(OnWiFiStationChange, 0);
-}
-
-CHIP_ERROR ConnectivityManagerImpl::OnStationConnected()
-{
- // Update WiFi station state and propagate it if necessary
- if (mWiFiStationState != kWiFiStationState_Connected)
- {
- mWiFiStationState = kWiFiStationState_Connected;
- ChipDeviceEvent event;
- event.Type = DeviceEventType::kWiFiConnectivityChange;
- event.WiFiConnectivityChange.Result = kConnectivity_Established;
- ReturnErrorOnFailure(PlatformMgr().PostEvent(&event));
- ChipLogProgress(DeviceLayer, "Event - StationConnected");
- }
-
- // Update IP address
- SocketAddress address;
- auto error = mWiFiInterface->get_ip_address(&address);
- if (error != NSAPI_ERROR_OK)
- {
- if (mIp4Address != IPAddress::Any)
- {
- // Unnexpected change, forward to the application
- mIp4Address = IPAddress::Any;
- ChipDeviceEvent event;
- event.Type = DeviceEventType::kInternetConnectivityChange;
- event.InternetConnectivityChange.IPv4 = kConnectivity_Lost;
- event.InternetConnectivityChange.IPv6 = kConnectivity_NoChange;
- ReturnErrorOnFailure(PlatformMgr().PostEvent(&event));
- ChipLogError(DeviceLayer, "Unnexpected loss of Ip4 address");
- }
-
- if (mIp6Address != IPAddress::Any)
- {
- // Unnexpected change, forward to the application
- mIp6Address = IPAddress::Any;
- ChipDeviceEvent event;
- event.Type = DeviceEventType::kInternetConnectivityChange;
- event.InternetConnectivityChange.IPv4 = kConnectivity_NoChange;
- event.InternetConnectivityChange.IPv6 = kConnectivity_Lost;
- ReturnErrorOnFailure(PlatformMgr().PostEvent(&event));
- ChipLogError(DeviceLayer, "Unnexpected loss of Ip6 address");
- }
+ PlatformMgr().PostEventOrDie(event);
}
else
{
- IPAddress addr;
- if (address.get_ip_version() == NSAPI_IPv4)
- {
- if (IPAddress::FromString(address.get_ip_address(), addr) && addr != mIp4Address)
- {
- mIp4Address = addr;
- ChipDeviceEvent event;
- event.Type = DeviceEventType::kInternetConnectivityChange;
- event.InternetConnectivityChange.IPv4 = kConnectivity_Established;
- event.InternetConnectivityChange.IPv6 = kConnectivity_NoChange;
- ReturnErrorOnFailure(PlatformMgr().PostEvent(&event));
- ChipLogProgress(DeviceLayer, "New Ip4 address set: %s", address.get_ip_address());
- }
-
- error = mWiFiInterface->get_ipv6_link_local_address(&address);
- if (error)
- {
- if (mIp6Address != IPAddress::Any)
- {
- // Unnexpected change, forward to the application
- mIp6Address = IPAddress::Any;
- ChipDeviceEvent event;
- event.Type = DeviceEventType::kInternetConnectivityChange;
- event.InternetConnectivityChange.IPv4 = kConnectivity_NoChange;
- event.InternetConnectivityChange.IPv6 = kConnectivity_Lost;
- ReturnErrorOnFailure(PlatformMgr().PostEvent(&event));
- ChipLogError(DeviceLayer, "Unnexpected loss of Ip6 address");
- }
- }
- else
- {
- if (IPAddress::FromString(address.get_ip_address(), addr) && addr != mIp6Address)
- {
- mIp6Address = addr;
- ChipDeviceEvent event;
- event.Type = DeviceEventType::kInternetConnectivityChange;
- event.InternetConnectivityChange.IPv4 = kConnectivity_NoChange;
- event.InternetConnectivityChange.IPv6 = kConnectivity_Established;
- ReturnErrorOnFailure(PlatformMgr().PostEvent(&event));
- ChipLogProgress(DeviceLayer, "New Ip6 address set %s", address.get_ip_address());
- }
- }
- }
- else
- {
- if (IPAddress::FromString(address.get_ip_address(), addr) && addr != mIp6Address)
- {
- mIp6Address = addr;
- ChipDeviceEvent event;
- event.Type = DeviceEventType::kInternetConnectivityChange;
- event.InternetConnectivityChange.IPv4 = kConnectivity_NoChange;
- event.InternetConnectivityChange.IPv6 = kConnectivity_Established;
- ReturnErrorOnFailure(PlatformMgr().PostEvent(&event));
- ChipLogProgress(DeviceLayer, "New Ip6 address set %s", address.get_ip_address());
- }
- }
+ err = PlatformMgr().PostEvent(event);
}
- return CHIP_NO_ERROR;
+ return err;
+}
+void ConnectivityManagerImpl::AddTask(AsyncWorkFunct workFunct, intptr_t arg)
+{
+ PlatformMgr().ScheduleWork(workFunct, arg);
}
-CHIP_ERROR ConnectivityManagerImpl::OnStationDisconnected()
+void ConnectivityManagerImpl::AddQueueEvent(void (*func)(nsapi_event_t, intptr_t), nsapi_event_t event, intptr_t data)
{
- ChipLogDetail(DeviceLayer, "OnStationDisconnected");
-
- // Update WiFi station state and propagate it if necessary
- if (mWiFiStationState != kWiFiStationState_NotConnected)
- {
- mWiFiStationState = kWiFiStationState_NotConnected;
- ChipDeviceEvent event;
- event.Type = DeviceEventType::kWiFiConnectivityChange;
- event.WiFiConnectivityChange.Result = kConnectivity_Lost;
- ReturnErrorOnFailure(PlatformMgr().PostEvent(&event));
- ChipLogProgress(DeviceLayer, "Event - StationDisconnected");
- }
-
- // Update IPv4 address
- if (mIp4Address != IPAddress::Any)
- {
- // Unnexpected change, forward to the application
- mIp4Address = IPAddress::Any;
- ChipDeviceEvent event;
- event.Type = DeviceEventType::kInternetConnectivityChange;
- event.InternetConnectivityChange.IPv4 = kConnectivity_Lost;
- event.InternetConnectivityChange.IPv6 = kConnectivity_NoChange;
- ReturnErrorOnFailure(PlatformMgr().PostEvent(&event));
- ChipLogError(DeviceLayer, "Loss of Ip4 address");
- }
-
- if (mIp6Address != IPAddress::Any)
- {
- // Unnexpected change, forward to the application
- mIp6Address = IPAddress::Any;
- ChipDeviceEvent event;
- event.Type = DeviceEventType::kInternetConnectivityChange;
- event.InternetConnectivityChange.IPv4 = kConnectivity_NoChange;
- event.InternetConnectivityChange.IPv6 = kConnectivity_Lost;
- ReturnErrorOnFailure(PlatformMgr().PostEvent(&event));
- ChipLogError(DeviceLayer, "Loss of Ip6 address");
- }
-
- return CHIP_NO_ERROR;
-}
-
-CHIP_ERROR ConnectivityManagerImpl::OnStationConnecting()
-{
- ChipLogDetail(DeviceLayer, "OnStationConnecting");
-
- // Update WiFi station state and propagate it if necessary
- if (mWiFiStationState != kWiFiStationState_Connected)
- {
- mWiFiStationState = kWiFiStationState_Connecting;
- }
- return CHIP_NO_ERROR;
-}
-
-void ConnectivityManagerImpl::ExecuteStationChange()
-{
- nsapi_error_t error;
- if ((mWiFiStationMode == kWiFiStationMode_Enabled) && IsWiFiStationProvisioned() &&
- mWiFiStationState != kWiFiStationState_Connected)
- {
- // Connect the interface with network
- error = mWiFiInterface->connect();
- if (error)
- {
- ChipLogError(DeviceLayer, "Network connection failed %d", error);
- }
- }
-
- if ((mWiFiStationMode == kWiFiStationMode_Enabled) && !IsWiFiStationProvisioned() &&
- mWiFiStationState == kWiFiStationState_Connected)
- {
- // Connect the interface with network
- error = mWiFiInterface->disconnect();
- if (error)
- {
- ChipLogError(DeviceLayer, "Network disconnect failed %d", error);
- }
- }
-}
-
-void ConnectivityManagerImpl::OnWiFiStationChange(intptr_t arg)
-{
- sInstance.ExecuteStationChange();
-}
-
-const char * ConnectivityManagerImpl::status2str(nsapi_connection_status_t status)
-{
- switch (status)
- {
- case NSAPI_STATUS_LOCAL_UP:
- return "Network local UP";
- case NSAPI_STATUS_GLOBAL_UP:
- return "Network global UP";
- case NSAPI_STATUS_DISCONNECTED:
- return "Network disconnected";
- case NSAPI_STATUS_CONNECTING:
- return "Network connecting";
- default:
- return "Unknown";
- }
+ PlatformMgrImpl().mQueue.call([func, event, data] {
+ PlatformMgr().LockChipStack();
+ (*func)(event, data);
+ PlatformMgr().UnlockChipStack();
+ });
}
} // namespace DeviceLayer
diff --git a/src/platform/mbed/ConnectivityManagerImpl.h b/src/platform/mbed/ConnectivityManagerImpl.h
index cabdeae..9926592 100644
--- a/src/platform/mbed/ConnectivityManagerImpl.h
+++ b/src/platform/mbed/ConnectivityManagerImpl.h
@@ -20,22 +20,26 @@
#include <platform/CHIPDeviceConfig.h>
#include <platform/ConnectivityManager.h>
-#include <platform/internal/DeviceNetworkInfo.h>
#include <platform/internal/GenericConnectivityManagerImpl.h>
+
+#if CHIP_DEVICE_CONFIG_ENABLE_WIFI
+#include <netsocket/WiFiInterface.h>
#include <platform/internal/GenericConnectivityManagerImpl_WiFi.h>
+#else
+#include <platform/internal/GenericConnectivityManagerImpl_NoWiFi.h>
+#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI
+
#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
#include <platform/internal/GenericConnectivityManagerImpl_BLE.h>
#else
#include <platform/internal/GenericConnectivityManagerImpl_NoBLE.h>
-#endif
+#endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
+
#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
#include <platform/internal/GenericConnectivityManagerImpl_Thread.h>
#else
#include <platform/internal/GenericConnectivityManagerImpl_NoThread.h>
-#endif
-#include <inet/IPAddress.h>
-#include <lib/support/logging/CHIPLogging.h>
-#include <netsocket/WiFiInterface.h>
+#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD
namespace chip {
namespace DeviceLayer {
@@ -45,78 +49,80 @@
*/
class ConnectivityManagerImpl final : public ConnectivityManager,
public Internal::GenericConnectivityManagerImpl<ConnectivityManagerImpl>,
+#if CHIP_DEVICE_CONFIG_ENABLE_WIFI
public Internal::GenericConnectivityManagerImpl_WiFi<ConnectivityManagerImpl>,
-
+#else
+ public Internal::GenericConnectivityManagerImpl_NoWiFi<ConnectivityManagerImpl>,
+#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI
#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
public Internal::GenericConnectivityManagerImpl_BLE<ConnectivityManagerImpl>,
#else
public Internal::GenericConnectivityManagerImpl_NoBLE<ConnectivityManagerImpl>,
-#endif
+#endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
public Internal::GenericConnectivityManagerImpl_Thread<ConnectivityManagerImpl>,
#else
public Internal::GenericConnectivityManagerImpl_NoThread<ConnectivityManagerImpl>
-#endif
+#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD
{
// Allow the ConnectivityManager interface class to delegate method calls to
// the implementation methods provided by this class.
friend class ConnectivityManager;
-public:
- CHIP_ERROR ProvisionWiFiNetwork(const char * ssid, const char * key);
- void StartWiFiManagement() {}
-
private:
- // ===== Members that implement the ConnectivityManager abstract interface.
CHIP_ERROR _Init(void);
- void _ProcessInterfaceChange(nsapi_connection_status_t new_status);
- void OnInterfaceEvent(nsapi_event_t event, intptr_t data);
- WiFiStationMode _GetWiFiStationMode(void);
- CHIP_ERROR _SetWiFiStationMode(WiFiStationMode val);
-
- WiFiAPMode _GetWiFiAPMode(void);
-
- System::Clock::Timeout _GetWiFiStationReconnectInterval(void);
- CHIP_ERROR _SetWiFiStationReconnectInterval(System::Clock::Timeout val);
- bool _IsWiFiStationConnected(void);
- bool _IsWiFiStationEnabled(void);
- bool _IsWiFiStationProvisioned(void);
- void _ClearWiFiStationProvision(void);
- bool _IsWiFiStationApplicationControlled(void);
- CHIP_ERROR _SetWiFiAPMode(WiFiAPMode val);
void _OnPlatformEvent(const ChipDeviceEvent * event);
- CHIP_ERROR OnStationConnected();
- CHIP_ERROR OnStationDisconnected();
- CHIP_ERROR OnStationConnecting();
- const char * status2str(nsapi_connection_status_t sec);
- ::chip::DeviceLayer::Internal::WiFiAuthSecurityType NsapiToNetworkSecurity(nsapi_security_t nsapi_security);
+#if CHIP_DEVICE_CONFIG_ENABLE_WIFI
+private:
+ CHIP_ERROR InitWiFi(void);
+ void OnWiFiPlatformEvent(const ChipDeviceEvent * event);
- void ExecuteStationChange(void);
- static void OnWiFiStationChange(intptr_t arg);
+ WiFiStationMode _GetWiFiStationMode();
+ CHIP_ERROR _SetWiFiStationMode(WiFiStationMode val);
+ bool _IsWiFiStationEnabled();
+ bool _IsWiFiStationApplicationControlled();
+ System::Clock::Timeout _GetWiFiStationReconnectInterval();
+ CHIP_ERROR _SetWiFiStationReconnectInterval(System::Clock::Timeout val);
+ bool _IsWiFiStationProvisioned();
+ bool _IsWiFiStationConnected(void);
+ void _ClearWiFiStationProvision();
+
// ===== Members for internal use by the following friends.
+ WiFiStationMode mWiFiStationMode = kWiFiStationMode_NotSupported;
+ WiFiStationState mWiFiStationState = kWiFiStationState_NotConnected;
+ System::Clock::Timeout mWiFiStationReconnectInterval =
+ System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_WIFI_STATION_RECONNECT_INTERVAL);
+ bool mIsProvisioned = false;
+#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI
+
friend ConnectivityManager & ConnectivityMgr(void);
friend ConnectivityManagerImpl & ConnectivityMgrImpl(void);
static ConnectivityManagerImpl sInstance;
- WiFiStationMode mWiFiStationMode = kWiFiStationMode_NotSupported;
- WiFiStationState mWiFiStationState = kWiFiStationState_NotConnected;
- WiFiAPMode mWiFiAPMode = kWiFiAPMode_NotSupported;
- System::Clock::Timeout mWiFiStationReconnectInterval =
- System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_WIFI_STATION_RECONNECT_INTERVAL);
- System::Clock::Timeout mWiFiAPIdleTimeout = System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_WIFI_AP_IDLE_TIMEOUT);
- WiFiInterface * mWiFiInterface = nullptr;
- nsapi_security_t mSecurityType = NSAPI_SECURITY_WPA_WPA2;
- bool mIsProvisioned = false;
- Inet::IPAddress mIp4Address = Inet::IPAddress::Any;
- Inet::IPAddress mIp6Address = Inet::IPAddress::Any;
+
+public:
+ CHIP_ERROR PostEvent(const ChipDeviceEvent * event, bool die);
+ void AddTask(AsyncWorkFunct workFunct, intptr_t arg);
+ void AddQueueEvent(void (*func)(nsapi_event_t, intptr_t), nsapi_event_t event, intptr_t data);
};
-inline ConnectivityManager::WiFiAPMode ConnectivityManagerImpl::_GetWiFiAPMode(void)
+#if CHIP_DEVICE_CONFIG_ENABLE_WIFI
+inline ConnectivityManager::WiFiStationMode ConnectivityManagerImpl::_GetWiFiStationMode(void)
{
- return mWiFiAPMode;
+ return mWiFiStationMode;
+}
+
+inline bool ConnectivityManagerImpl::_IsWiFiStationEnabled(void)
+{
+ return mWiFiStationMode == kWiFiStationMode_Enabled;
+}
+
+inline bool ConnectivityManagerImpl::_IsWiFiStationApplicationControlled(void)
+{
+ return mWiFiStationMode == kWiFiStationMode_ApplicationControlled;
}
inline System::Clock::Timeout ConnectivityManagerImpl::_GetWiFiStationReconnectInterval(void)
@@ -124,6 +130,18 @@
return mWiFiStationReconnectInterval;
}
+inline bool ConnectivityManagerImpl::_IsWiFiStationProvisioned(void)
+{
+ return mIsProvisioned;
+}
+
+inline bool ConnectivityManagerImpl::_IsWiFiStationConnected(void)
+{
+ return mWiFiStationState == kWiFiStationState_Connected;
+}
+
+#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI
+
/**
* Returns the public interface of the ConnectivityManager singleton object.
*
diff --git a/src/platform/mbed/ConnectivityManagerImpl_WiFi.cpp b/src/platform/mbed/ConnectivityManagerImpl_WiFi.cpp
new file mode 100644
index 0000000..57aca8b
--- /dev/null
+++ b/src/platform/mbed/ConnectivityManagerImpl_WiFi.cpp
@@ -0,0 +1,171 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2018 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * 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 <platform/ConnectivityManager.h>
+#include <platform/internal/CHIPDeviceLayerInternal.h>
+#include <platform/mbed/ConnectivityManagerImpl.h>
+#include <platform/mbed/NetworkCommissioningDriver.h>
+
+#include <platform/internal/GenericConnectivityManagerImpl_WiFi.cpp>
+
+#include <app/clusters/network-commissioning/network-commissioning.h>
+
+#include <lib/support/CodeUtils.h>
+#include <lib/support/logging/CHIPLogging.h>
+
+using namespace ::chip;
+using namespace ::chip::Inet;
+using namespace ::chip::System;
+using namespace ::chip::DeviceLayer;
+using namespace ::chip::DeviceLayer::Internal;
+
+namespace chip {
+namespace DeviceLayer {
+
+#if CHIP_DEVICE_ENABLE_DATA_MODEL
+namespace {
+app::Clusters::NetworkCommissioning::Instance
+ sWiFiNetworkCommissioningInstance(0 /* Endpoint Id */, &(NetworkCommissioning::WiFiDriverImpl::GetInstance()));
+} // namespace
+#endif // CHIP_DEVICE_ENABLE_DATA_MODEL
+
+CHIP_ERROR ConnectivityManagerImpl::InitWiFi()
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ NetworkCommissioning::NetworkIterator * networks;
+
+ mWiFiStationState = kWiFiStationState_NotConnected;
+
+ mWiFiStationReconnectInterval = System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_WIFI_STATION_RECONNECT_INTERVAL);
+#if CHIP_DEVICE_ENABLE_DATA_MODEL
+ err = sWiFiNetworkCommissioningInstance.Init();
+#else
+ err = NetworkCommissioning::WiFiDriverImpl::GetInstance().Init();
+#endif
+ VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(DeviceLayer, "WiFi driver init failed: %s", chip::ErrorStr(err)));
+
+ mWiFiStationMode = kWiFiStationMode_Enabled;
+ networks = NetworkCommissioning::WiFiDriverImpl::GetInstance().GetNetworks();
+ if (networks != nullptr && networks->Count() > 0)
+ {
+ mIsProvisioned = true;
+ }
+ else
+ {
+ mIsProvisioned = false;
+ }
+ if (networks != nullptr)
+ {
+ networks->Release();
+ }
+exit:
+ return err;
+}
+
+void ConnectivityManagerImpl::OnWiFiPlatformEvent(const ChipDeviceEvent * event)
+{
+ if (event->Type == DeviceEventType::kWiFiConnectivityChange)
+ {
+ switch (event->WiFiConnectivityChange.Result)
+ {
+ case kConnectivity_NoChange:
+ mWiFiStationState = kWiFiStationState_Connecting;
+ break;
+ case kConnectivity_Established:
+ ChipLogProgress(DeviceLayer, "WiFi station connected");
+ mWiFiStationState = kWiFiStationState_Connected;
+ break;
+ case kConnectivity_Lost:
+ ChipLogProgress(DeviceLayer, "WiFi station disconnected");
+ mWiFiStationState = kWiFiStationState_NotConnected;
+ break;
+ }
+ }
+}
+
+CHIP_ERROR ConnectivityManagerImpl::_SetWiFiStationMode(WiFiStationMode val)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ VerifyOrExit(val != kWiFiStationMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT);
+
+ if (mWiFiStationMode != val)
+ {
+ ChipLogProgress(DeviceLayer, "WiFi station mode change: %s -> %s", WiFiStationModeToStr(mWiFiStationMode),
+ WiFiStationModeToStr(val));
+
+ mWiFiStationMode = val;
+
+ if (mWiFiStationMode != kWiFiStationMode_ApplicationControlled)
+ {
+ if (mWiFiStationMode == kWiFiStationMode_Enabled)
+ {
+ NetworkCommissioning::WiFiDriverImpl::GetInstance().Init();
+ }
+ else if (mWiFiStationMode == kWiFiStationMode_Disabled)
+ {
+ NetworkCommissioning::WiFiDriverImpl::GetInstance().Shutdown();
+ }
+ }
+ }
+
+exit:
+ return err;
+}
+
+CHIP_ERROR ConnectivityManagerImpl::_SetWiFiStationReconnectInterval(System::Clock::Timeout val)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ if (mWiFiStationReconnectInterval != val)
+ {
+ ChipLogProgress(DeviceLayer, "WiFi station reconnect interval change: %lu ms -> %lu ms",
+ System::Clock::Milliseconds32(mWiFiStationReconnectInterval).count(),
+ System::Clock::Milliseconds32(val).count());
+ }
+
+ mWiFiStationReconnectInterval = val;
+
+ return err;
+}
+
+void ConnectivityManagerImpl::_ClearWiFiStationProvision(void)
+{
+ if (mWiFiStationMode != kWiFiStationMode_ApplicationControlled)
+ {
+ auto networks = NetworkCommissioning::WiFiDriverImpl::GetInstance().GetNetworks();
+ NetworkCommissioning::Network network;
+ for (; networks != nullptr && networks->Next(network);)
+ {
+ if (network.connected)
+ {
+ NetworkCommissioning::WiFiDriverImpl::GetInstance().DisconnectNetwork(
+ ByteSpan(network.networkID, network.networkIDLen));
+ }
+ NetworkCommissioning::WiFiDriverImpl::GetInstance().RemoveNetwork(ByteSpan(network.networkID, network.networkIDLen));
+ }
+ if (networks != nullptr)
+ {
+ networks->Release();
+ }
+ }
+}
+
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/mbed/DeviceNetworkProvisioningDelegateImpl.cpp b/src/platform/mbed/DeviceNetworkProvisioningDelegateImpl.cpp
index 194be66..282c9cd 100644
--- a/src/platform/mbed/DeviceNetworkProvisioningDelegateImpl.cpp
+++ b/src/platform/mbed/DeviceNetworkProvisioningDelegateImpl.cpp
@@ -15,26 +15,37 @@
* limitations under the License.
*/
-#include <lib/support/ErrorStr.h>
#include <lib/support/logging/CHIPLogging.h>
#include "DeviceNetworkProvisioningDelegateImpl.h"
+#include "NetworkCommissioningDriver.h"
+
+using namespace ::chip::DeviceLayer::NetworkCommissioning;
namespace chip {
namespace DeviceLayer {
CHIP_ERROR DeviceNetworkProvisioningDelegateImpl::_ProvisionWiFiNetwork(const char * ssid, const char * key)
{
- CHIP_ERROR err = CHIP_NO_ERROR;
-
- ChipLogProgress(NetworkProvisioning, "MbedNetworkProvisioningDelegate: SSID: %s", ssid);
- err = ConnectivityMgrImpl().ProvisionWiFiNetwork(ssid, key);
- if (err != CHIP_NO_ERROR)
+#if CHIP_DEVICE_CONFIG_ENABLE_WIFI
+ auto err = WiFiDriverImpl::GetInstance().AddOrUpdateNetwork(ByteSpan(Uint8::from_const_char(ssid), strlen(ssid)),
+ ByteSpan(Uint8::from_const_char(key), strlen(key)));
+ if (err != Status::kSuccess)
{
- ChipLogError(NetworkProvisioning, "Failed to connect to WiFi network: %s", chip::ErrorStr(err));
+ ChipLogError(NetworkProvisioning, "Failed to add WiFi network: 0x%" PRIx16, int(err));
+ return CHIP_ERROR_INTERNAL;
}
+ NetworkCommissioning::WiFiDriverImpl::GetInstance().ConnectNetwork(ByteSpan(Uint8::from_const_char(ssid), strlen(ssid)),
+ nullptr);
+ return CHIP_NO_ERROR;
+#else
+ return CHIP_ERROR_NOT_IMPLEMENTED;
+#endif
+}
- return err;
+CHIP_ERROR DeviceNetworkProvisioningDelegateImpl::_ProvisionThreadNetwork(ByteSpan threadData)
+{
+ return CHIP_ERROR_NOT_IMPLEMENTED;
}
} // namespace DeviceLayer
diff --git a/src/platform/mbed/DeviceNetworkProvisioningDelegateImpl.h b/src/platform/mbed/DeviceNetworkProvisioningDelegateImpl.h
index 6e89a78..1026994 100644
--- a/src/platform/mbed/DeviceNetworkProvisioningDelegateImpl.h
+++ b/src/platform/mbed/DeviceNetworkProvisioningDelegateImpl.h
@@ -36,7 +36,7 @@
friend class GenericDeviceNetworkProvisioningDelegateImpl<DeviceNetworkProvisioningDelegateImpl>;
CHIP_ERROR _ProvisionWiFiNetwork(const char * ssid, const char * passwd);
- CHIP_ERROR _ProvisionThreadNetwork(ByteSpan threadData) { return CHIP_ERROR_NOT_IMPLEMENTED; }
+ CHIP_ERROR _ProvisionThreadNetwork(ByteSpan threadData);
};
} // namespace DeviceLayer
diff --git a/src/platform/mbed/NetworkCommissioningDriver.h b/src/platform/mbed/NetworkCommissioningDriver.h
new file mode 100644
index 0000000..1a374f5
--- /dev/null
+++ b/src/platform/mbed/NetworkCommissioningDriver.h
@@ -0,0 +1,156 @@
+/*
+ *
+ * Copyright (c) 2022 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 <inet/IPAddress.h>
+#include <platform/NetworkCommissioning.h>
+
+namespace chip {
+namespace DeviceLayer {
+namespace NetworkCommissioning {
+
+#if CHIP_DEVICE_CONFIG_ENABLE_WIFI
+
+#include <netsocket/WiFiInterface.h>
+
+namespace {
+constexpr uint8_t kMaxWiFiNetworks = 1;
+constexpr uint8_t kWiFiScanNetworksTimeOutSeconds = 10;
+constexpr uint8_t kWiFiConnectNetworkTimeoutSeconds = 20;
+} // namespace
+
+class MbedScanResponseIterator : public Iterator<WiFiScanResponse>
+{
+public:
+ MbedScanResponseIterator(const size_t size, const WiFiAccessPoint * scanResults) : mSize(size), mScanResults(scanResults) {}
+ size_t Count() override { return mSize; }
+ bool Next(WiFiScanResponse & item) override
+ {
+ if (mIternum >= mSize)
+ {
+ return false;
+ }
+
+ item.security = mScanResults[mIternum].get_security();
+ item.ssidLen = strnlen(reinterpret_cast<const char *>(mScanResults[mIternum].get_ssid()),
+ chip::DeviceLayer::Internal::kMaxWiFiSSIDLength);
+ item.channel = mScanResults[mIternum].get_channel();
+ item.wiFiBand = chip::DeviceLayer::NetworkCommissioning::WiFiBand::k2g4;
+ item.rssi = mScanResults[mIternum].get_rssi();
+ memcpy(item.ssid, mScanResults[mIternum].get_ssid(), item.ssidLen);
+ memcpy(item.bssid, mScanResults[mIternum].get_bssid(), 6);
+
+ mIternum++;
+ return true;
+ }
+ void Release() override {}
+
+private:
+ const size_t mSize;
+ const WiFiAccessPoint * mScanResults;
+ size_t mIternum = 0;
+};
+
+class WiFiDriverImpl final : public WiFiDriver
+{
+public:
+ class WiFiNetworkIterator final : public NetworkIterator
+ {
+ public:
+ WiFiNetworkIterator(WiFiDriverImpl * aDriver) : mDriver(aDriver) {}
+ size_t Count() override;
+ bool Next(Network & item) override;
+ void Release() override { delete this; }
+ ~WiFiNetworkIterator() = default;
+
+ private:
+ WiFiDriverImpl * 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;
+ CHIP_ERROR Shutdown() 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;
+ void DisconnectNetwork(ByteSpan networkId);
+
+ // WiFiDriver
+ Status AddOrUpdateNetwork(ByteSpan ssid, ByteSpan credentials) override;
+ void ScanNetworks(ByteSpan ssid, ScanCallback * callback) override;
+
+ static WiFiDriverImpl & GetInstance()
+ {
+ static WiFiDriverImpl instance;
+ return instance;
+ }
+
+private:
+ bool NetworkMatch(const WiFiNetwork & network, ByteSpan networkId);
+
+ static void OnScanNetwork(intptr_t arg);
+ void ExecuteScanNetwork(void);
+
+ static void OnConnectNetwork(intptr_t arg);
+ void ExecuteConnectNetwork(void);
+
+ static void OnWiFiInterfaceEvent(nsapi_event_t event, intptr_t data);
+ void ExecuteWiFiInterfaceChange(nsapi_connection_status_t new_status);
+
+ void OnNetworkConnected();
+ void OnNetworkDisconnected();
+ void OnNetworkConnecting();
+
+ chip::DeviceLayer::Internal::WiFiAuthSecurityType NsapiToNetworkSecurity(nsapi_security_t nsapi_security);
+
+ WiFiNetworkIterator mWiFiIterator = WiFiNetworkIterator(this);
+ WiFiNetwork mSavedNetwork;
+ WiFiNetwork mStagingNetwork;
+ ScanCallback * mScanCallback;
+ ConnectCallback * mConnectCallback;
+ char mScanSSID[DeviceLayer::Internal::kMaxWiFiSSIDLength];
+ bool mScanSpecific = false;
+
+ WiFiInterface * mWiFiInterface = nullptr;
+ nsapi_security_t mSecurityType = NSAPI_SECURITY_NONE;
+ Inet::IPAddress mIp4Address = Inet::IPAddress::Any;
+ Inet::IPAddress mIp6Address = Inet::IPAddress::Any;
+};
+#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI
+} // namespace NetworkCommissioning
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/mbed/NetworkCommissioningWiFiDriver.cpp b/src/platform/mbed/NetworkCommissioningWiFiDriver.cpp
new file mode 100644
index 0000000..f6918e6
--- /dev/null
+++ b/src/platform/mbed/NetworkCommissioningWiFiDriver.cpp
@@ -0,0 +1,595 @@
+/*
+ *
+ * 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 <platform/CHIPDeviceLayer.h>
+#include <platform/mbed/NetworkCommissioningDriver.h>
+
+#include <net_common.h>
+#include <netsocket/WiFiInterface.h>
+
+using namespace ::chip::Inet;
+using namespace ::chip::DeviceLayer;
+using namespace ::chip::DeviceLayer::Internal;
+
+namespace chip {
+namespace DeviceLayer {
+namespace NetworkCommissioning {
+
+namespace {
+constexpr char kWiFiSSIDKeyName[] = "wifi-ssid";
+constexpr char kWiFiCredentialsKeyName[] = "wifi-pass";
+} // namespace
+
+CHIP_ERROR WiFiDriverImpl::Init()
+{
+ size_t ssidLen = 0;
+ size_t credentialsLen = 0;
+
+ mSecurityType = NSAPI_SECURITY_WPA_WPA2;
+
+ auto net_if = get_mbed_net_if();
+ if (net_if == nullptr)
+ {
+ ChipLogError(DeviceLayer, "No network interface available");
+ return CHIP_ERROR_NOT_IMPLEMENTED;
+ }
+
+ if (net_if->wifiInterface() != nullptr)
+ {
+ mWiFiInterface = net_if->wifiInterface();
+ // To add more listener to the interface
+ mWiFiInterface->add_event_listener(
+ [this](nsapi_event_t event, intptr_t data) { ConnectivityMgrImpl().AddQueueEvent(OnWiFiInterfaceEvent, event, data); });
+
+ mWiFiInterface->set_blocking(false);
+ }
+
+ mScanCallback = nullptr;
+ mConnectCallback = nullptr;
+ mScanSpecific = false;
+
+ mIp4Address = IPAddress::Any;
+ mIp6Address = IPAddress::Any;
+
+ auto err = PersistedStorage::KeyValueStoreMgr().Get(kWiFiSSIDKeyName, mSavedNetwork.ssid, sizeof(mSavedNetwork.ssid), &ssidLen);
+ if (err == CHIP_NO_ERROR)
+ {
+ mSavedNetwork.ssidLen = ssidLen;
+ }
+
+ err = PersistedStorage::KeyValueStoreMgr().Get(kWiFiCredentialsKeyName, mSavedNetwork.credentials,
+ sizeof(mSavedNetwork.credentials), &credentialsLen);
+ if (err == CHIP_NO_ERROR)
+ {
+ mSavedNetwork.credentialsLen = credentialsLen;
+ }
+
+ if (mSavedNetwork.ssidLen != 0 && mSavedNetwork.credentialsLen != 0)
+ {
+ mStagingNetwork = mSavedNetwork;
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR WiFiDriverImpl::Shutdown()
+{
+ Network network;
+ auto networks = GetNetworks();
+ for (; networks != nullptr && networks->Next(network);)
+ {
+ if (network.connected)
+ {
+ DisconnectNetwork(ByteSpan(network.networkID, network.networkIDLen));
+ }
+ }
+ if (networks != nullptr)
+ {
+ networks->Release();
+ }
+ mScanCallback = nullptr;
+ mConnectCallback = nullptr;
+ mScanSpecific = false;
+ mWiFiInterface = nullptr;
+ mIp4Address = IPAddress::Any;
+ mIp6Address = IPAddress::Any;
+ mSecurityType = NSAPI_SECURITY_NONE;
+ memset(mScanSSID, 0, sizeof(mScanSSID));
+ mStagingNetwork.ssidLen = 0;
+ mStagingNetwork.credentialsLen = 0;
+ mSavedNetwork.ssidLen = 0;
+ mSavedNetwork.credentialsLen = 0;
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR WiFiDriverImpl::CommitConfiguration()
+{
+ ReturnErrorOnFailure(PersistedStorage::KeyValueStoreMgr().Put(kWiFiSSIDKeyName, mStagingNetwork.ssid, mStagingNetwork.ssidLen));
+ ReturnErrorOnFailure(PersistedStorage::KeyValueStoreMgr().Put(kWiFiCredentialsKeyName, mStagingNetwork.credentials,
+ mStagingNetwork.credentialsLen));
+ mSavedNetwork = mStagingNetwork;
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR WiFiDriverImpl::RevertConfiguration()
+{
+ mStagingNetwork = mSavedNetwork;
+ return CHIP_NO_ERROR;
+}
+
+bool WiFiDriverImpl::NetworkMatch(const WiFiNetwork & network, ByteSpan networkId)
+{
+ return networkId.size() == network.ssidLen && memcmp(networkId.data(), network.ssid, network.ssidLen) == 0;
+}
+
+Status WiFiDriverImpl::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);
+
+ memcpy(mStagingNetwork.credentials, credentials.data(), credentials.size());
+ mStagingNetwork.credentialsLen = static_cast<decltype(mStagingNetwork.credentialsLen)>(credentials.size());
+
+ memcpy(mStagingNetwork.ssid, ssid.data(), ssid.size());
+ mStagingNetwork.ssidLen = static_cast<decltype(mStagingNetwork.ssidLen)>(ssid.size());
+
+ return Status::kSuccess;
+}
+
+Status WiFiDriverImpl::RemoveNetwork(ByteSpan networkId)
+{
+ VerifyOrReturnError(NetworkMatch(mStagingNetwork, networkId), Status::kNetworkIDNotFound);
+
+ // Use empty ssid for representing invalid network
+ mStagingNetwork.ssidLen = 0;
+ return Status::kSuccess;
+}
+
+Status WiFiDriverImpl::ReorderNetwork(ByteSpan networkId, uint8_t index)
+{
+ // Only one network is supported now
+ VerifyOrReturnError(index == 0, Status::kOutOfRange);
+ VerifyOrReturnError(NetworkMatch(mStagingNetwork, networkId), Status::kNetworkIDNotFound);
+ return Status::kSuccess;
+}
+
+void WiFiDriverImpl::ExecuteWiFiInterfaceChange(nsapi_connection_status_t status)
+{
+
+ switch (status)
+ {
+ case NSAPI_STATUS_LOCAL_UP:
+ ChipLogDetail(DeviceLayer, "Connection status - LOCAL_UP");
+ OnNetworkConnected();
+ break;
+ case NSAPI_STATUS_GLOBAL_UP:
+ ChipLogDetail(DeviceLayer, "Connection status - GLOBAL_UP");
+ OnNetworkConnected();
+ break;
+ case NSAPI_STATUS_DISCONNECTED:
+ ChipLogDetail(DeviceLayer, "Connection status - DISCONNECTED");
+ OnNetworkDisconnected();
+ break;
+ case NSAPI_STATUS_CONNECTING:
+ ChipLogDetail(DeviceLayer, "Connection status - CONNECTING");
+ OnNetworkConnecting();
+ break;
+ default:
+ ChipLogDetail(DeviceLayer, "Unknown connection status: 0x%08X", status);
+ break;
+ }
+}
+
+void WiFiDriverImpl::OnWiFiInterfaceEvent(nsapi_event_t event, intptr_t data)
+{
+ if (event == NSAPI_EVENT_CONNECTION_STATUS_CHANGE)
+ {
+ GetInstance().ExecuteWiFiInterfaceChange((nsapi_connection_status_t) data);
+ }
+}
+
+void WiFiDriverImpl::ExecuteConnectNetwork()
+{
+ const char * ssid = mStagingNetwork.ssid;
+ const char * key = mStagingNetwork.credentials;
+
+ // Set WiFi credentials
+ auto error = mWiFiInterface->set_credentials(ssid, key, mSecurityType);
+ if (error)
+ {
+ ChipLogError(DeviceLayer, "Set WiFi credentials failed %d", error);
+ if (mConnectCallback)
+ {
+ mConnectCallback->OnResult(Status::kUnknownError, CharSpan(), 0);
+ mConnectCallback = nullptr;
+ }
+ return;
+ }
+
+ // Connect Wifi network
+ error = mWiFiInterface->connect();
+ if (error)
+ {
+ ChipLogError(DeviceLayer, "Connect WiFi network failed %d", error);
+ if (mConnectCallback)
+ {
+ mConnectCallback->OnResult(Status::kOtherConnectionFailure, CharSpan(), 0);
+ mConnectCallback = nullptr;
+ }
+ return;
+ }
+}
+
+void WiFiDriverImpl::OnConnectNetwork(intptr_t arg)
+{
+ GetInstance().ExecuteConnectNetwork();
+}
+
+void WiFiDriverImpl::ConnectNetwork(ByteSpan networkId, ConnectCallback * callback)
+{
+ Status status = Status::kSuccess;
+
+ VerifyOrExit(mWiFiInterface != nullptr, status = Status::kUnknownError);
+ VerifyOrExit(NetworkMatch(mStagingNetwork, networkId), status = Status::kNetworkIDNotFound);
+ VerifyOrExit(mConnectCallback == nullptr, status = Status::kUnknownError);
+ ChipLogProgress(NetworkProvisioning, "Mbed WiFi driver connect network: SSID: %.*s", static_cast<int>(networkId.size()),
+ networkId.data());
+ mConnectCallback = callback;
+ ConnectivityMgrImpl().AddTask(OnConnectNetwork, 0);
+exit:
+ if (status != Status::kSuccess)
+ {
+ ChipLogError(DeviceLayer, "Connect WiFi network failed: 0x%" PRIx16, int(status));
+ if (callback)
+ {
+ callback->OnResult(status, CharSpan(), 0);
+ }
+ }
+}
+
+void WiFiDriverImpl::DisconnectNetwork(ByteSpan networkId)
+{
+ Status status = Status::kSuccess;
+
+ VerifyOrReturn(mWiFiInterface != nullptr, ChipLogError(DeviceLayer, "Wifi network not available"));
+ VerifyOrReturn(NetworkMatch(mStagingNetwork, networkId), ChipLogError(DeviceLayer, "Network not found"));
+ ChipLogProgress(NetworkProvisioning, "Mbed WiFi driver disconnect network: SSID: %.*s", static_cast<int>(networkId.size()),
+ networkId.data());
+
+ // Disconnect Wifi network
+ auto error = mWiFiInterface->disconnect();
+ if (error)
+ {
+ ChipLogError(DeviceLayer, "Disconnect WiFi network failed %d", error);
+ }
+}
+
+void WiFiDriverImpl::ExecuteScanNetwork()
+{
+ uint16_t ap_number, ap_index = 0;
+ WiFiAccessPoint * ap_buffer;
+ MbedScanResponseIterator * scan_resp_iter;
+
+ // Get APs number
+ ap_number = mWiFiInterface->scan(nullptr, 0);
+ if (!ap_number)
+ {
+ ChipLogProgress(DeviceLayer, "No AP found");
+ if (mScanCallback)
+ {
+ mScanCallback->OnFinished(Status::kUnknownError, CharSpan(), nullptr);
+ }
+ goto exit;
+ }
+
+ ap_buffer = new WiFiAccessPoint[ap_number];
+ if (ap_buffer == nullptr)
+ {
+ ChipLogError(DeviceLayer, "Can't malloc memory for AP list");
+ if (mScanCallback)
+ {
+ mScanCallback->OnFinished(Status::kUnknownError, CharSpan(), nullptr);
+ }
+ goto exit;
+ }
+
+ // Get APs details
+ if (mWiFiInterface->scan(ap_buffer, ap_number) < 0)
+ {
+ if (mScanSpecific)
+ {
+ while (ap_index < ap_number)
+ {
+ if (strcmp(ap_buffer->get_ssid(), mScanSSID) == 0)
+ {
+ break;
+ }
+ ap_buffer++;
+ ap_index++;
+ }
+ if (ap_index == ap_number)
+ {
+ ChipLogError(DeviceLayer, "Specific AP not found");
+ if (mScanCallback)
+ {
+ mScanCallback->OnFinished(Status::kNetworkNotFound, CharSpan(), nullptr);
+ }
+ goto exit;
+ }
+ ap_number = 1;
+ }
+ scan_resp_iter = new MbedScanResponseIterator(ap_number, ap_buffer);
+ if (mScanCallback)
+ {
+ mScanCallback->OnFinished(Status::kSuccess, CharSpan(), scan_resp_iter);
+ }
+ }
+ else
+ {
+ ChipLogError(DeviceLayer, "Scan Wifi AP failed");
+ if (mScanCallback)
+ {
+ mScanCallback->OnFinished(Status::kUnknownError, CharSpan(), nullptr);
+ }
+ goto exit;
+ }
+
+exit:
+ if (ap_buffer)
+ {
+ delete[] ap_buffer;
+ }
+ mScanCallback = nullptr;
+ mScanSpecific = false;
+}
+
+void WiFiDriverImpl::OnScanNetwork(intptr_t arg)
+{
+ GetInstance().ExecuteScanNetwork();
+}
+
+void WiFiDriverImpl::ScanNetworks(ByteSpan ssid, WiFiDriver::ScanCallback * callback)
+{
+ Status status = Status::kSuccess;
+
+ VerifyOrExit(mWiFiInterface != nullptr, status = Status::kUnknownError);
+
+ if (ssid.data())
+ {
+ memset(mScanSSID, 0, sizeof(mScanSSID));
+ memcpy(mScanSSID, ssid.data(), ssid.size());
+ mScanSpecific = true;
+ }
+ mScanCallback = callback;
+ ConnectivityMgrImpl().AddTask(OnScanNetwork, 0);
+
+exit:
+ if (status != Status::kSuccess)
+ {
+ ChipLogError(DeviceLayer, "Scan WiFi networks failed: 0x%" PRIx16, int(status));
+ if (callback)
+ {
+ callback->OnFinished(status, CharSpan(), nullptr);
+ }
+ }
+}
+
+size_t WiFiDriverImpl::WiFiNetworkIterator::Count()
+{
+ return mDriver->mStagingNetwork.ssidLen == 0 ? 0 : 1;
+}
+
+bool WiFiDriverImpl::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 = get_mbed_net_if()->wifiInterface()->get_connection_status() == NSAPI_STATUS_LOCAL_UP ||
+ get_mbed_net_if()->wifiInterface()->get_connection_status() == NSAPI_STATUS_GLOBAL_UP;
+ mExhausted = true;
+
+ return true;
+}
+
+void WiFiDriverImpl::OnNetworkConnected()
+{
+ ChipLogDetail(DeviceLayer, "OnNetworkConnected");
+
+ if (mConnectCallback)
+ {
+ mConnectCallback->OnResult(Status::kSuccess, CharSpan(), 0);
+ mConnectCallback = nullptr;
+ }
+
+ ChipDeviceEvent event;
+ event.Type = DeviceEventType::kWiFiConnectivityChange;
+ event.WiFiConnectivityChange.Result = kConnectivity_Established;
+ ConnectivityMgrImpl().PostEvent(&event, true);
+
+ // Update IP address
+ SocketAddress address;
+ auto error = mWiFiInterface->get_ip_address(&address);
+ if (error != NSAPI_ERROR_OK)
+ {
+ if (mIp4Address != IPAddress::Any)
+ {
+ // Unexpected change, forward to the application
+ mIp4Address = IPAddress::Any;
+ ChipDeviceEvent event;
+ event.Type = DeviceEventType::kInternetConnectivityChange;
+ event.InternetConnectivityChange.IPv4 = kConnectivity_Lost;
+ event.InternetConnectivityChange.IPv6 = kConnectivity_NoChange;
+ ConnectivityMgrImpl().PostEvent(&event, true);
+ ChipLogError(DeviceLayer, "Unexpected loss of Ip4 address");
+ }
+
+ if (mIp6Address != IPAddress::Any)
+ {
+ // Unexpected change, forward to the application
+ mIp6Address = IPAddress::Any;
+ ChipDeviceEvent event;
+ event.Type = DeviceEventType::kInternetConnectivityChange;
+ event.InternetConnectivityChange.IPv4 = kConnectivity_NoChange;
+ event.InternetConnectivityChange.IPv6 = kConnectivity_Lost;
+ ConnectivityMgrImpl().PostEvent(&event, true);
+ ChipLogError(DeviceLayer, "Unexpected loss of Ip6 address");
+ }
+ }
+ else
+ {
+ IPAddress addr;
+ if (address.get_ip_version() == NSAPI_IPv4)
+ {
+ if (IPAddress::FromString(address.get_ip_address(), addr) && addr != mIp4Address)
+ {
+ mIp4Address = addr;
+ ChipDeviceEvent event;
+ event.Type = DeviceEventType::kInternetConnectivityChange;
+ event.InternetConnectivityChange.IPv4 = kConnectivity_Established;
+ event.InternetConnectivityChange.IPv6 = kConnectivity_NoChange;
+ ConnectivityMgrImpl().PostEvent(&event, true);
+ ChipLogProgress(DeviceLayer, "New Ip4 address set: %s", address.get_ip_address());
+ }
+
+ error = mWiFiInterface->get_ipv6_link_local_address(&address);
+ if (error)
+ {
+ if (mIp6Address != IPAddress::Any)
+ {
+ // Unexpected change, forward to the application
+ mIp6Address = IPAddress::Any;
+ ChipDeviceEvent event;
+ event.Type = DeviceEventType::kInternetConnectivityChange;
+ event.InternetConnectivityChange.IPv4 = kConnectivity_NoChange;
+ event.InternetConnectivityChange.IPv6 = kConnectivity_Lost;
+ ConnectivityMgrImpl().PostEvent(&event, true);
+ ChipLogError(DeviceLayer, "Unexpected loss of Ip6 address");
+ }
+ }
+ else
+ {
+ if (IPAddress::FromString(address.get_ip_address(), addr) && addr != mIp6Address)
+ {
+ mIp6Address = addr;
+ ChipDeviceEvent event;
+ event.Type = DeviceEventType::kInternetConnectivityChange;
+ event.InternetConnectivityChange.IPv4 = kConnectivity_NoChange;
+ event.InternetConnectivityChange.IPv6 = kConnectivity_Established;
+ ConnectivityMgrImpl().PostEvent(&event, true);
+ ChipLogProgress(DeviceLayer, "New Ip6 address set %s", address.get_ip_address());
+ }
+ }
+ }
+ else
+ {
+ if (IPAddress::FromString(address.get_ip_address(), addr) && addr != mIp6Address)
+ {
+ mIp6Address = addr;
+ ChipDeviceEvent event;
+ event.Type = DeviceEventType::kInternetConnectivityChange;
+ event.InternetConnectivityChange.IPv4 = kConnectivity_NoChange;
+ event.InternetConnectivityChange.IPv6 = kConnectivity_Established;
+ ConnectivityMgrImpl().PostEvent(&event, true);
+ ChipLogProgress(DeviceLayer, "New Ip6 address set %s", address.get_ip_address());
+ }
+ }
+ }
+}
+
+void WiFiDriverImpl::OnNetworkDisconnected()
+{
+ ChipLogDetail(DeviceLayer, "OnStationDisconnected");
+
+ ChipDeviceEvent event;
+ event.Type = DeviceEventType::kWiFiConnectivityChange;
+ event.WiFiConnectivityChange.Result = kConnectivity_Lost;
+ ConnectivityMgrImpl().PostEvent(&event, true);
+
+ // Update IPv4 address
+ if (mIp4Address != IPAddress::Any)
+ {
+ // Unexpected change, forward to the application
+ mIp4Address = IPAddress::Any;
+ ChipDeviceEvent event;
+ event.Type = DeviceEventType::kInternetConnectivityChange;
+ event.InternetConnectivityChange.IPv4 = kConnectivity_Lost;
+ event.InternetConnectivityChange.IPv6 = kConnectivity_NoChange;
+ ConnectivityMgrImpl().PostEvent(&event, true);
+ ChipLogError(DeviceLayer, "Loss of Ip4 address");
+ }
+
+ if (mIp6Address != IPAddress::Any)
+ {
+ // Unexpected change, forward to the application
+ mIp6Address = IPAddress::Any;
+ ChipDeviceEvent event;
+ event.Type = DeviceEventType::kInternetConnectivityChange;
+ event.InternetConnectivityChange.IPv4 = kConnectivity_NoChange;
+ event.InternetConnectivityChange.IPv6 = kConnectivity_Lost;
+ ConnectivityMgrImpl().PostEvent(&event, true);
+ ChipLogError(DeviceLayer, "Loss of Ip6 address");
+ }
+}
+
+void WiFiDriverImpl::OnNetworkConnecting()
+{
+ ChipLogDetail(DeviceLayer, "OnNetworkConnecting");
+
+ ChipDeviceEvent event;
+ event.Type = DeviceEventType::kWiFiConnectivityChange;
+ event.WiFiConnectivityChange.Result = kConnectivity_NoChange;
+ ConnectivityMgrImpl().PostEvent(&event, true);
+}
+
+WiFiAuthSecurityType WiFiDriverImpl::NsapiToNetworkSecurity(nsapi_security_t nsapi_security)
+{
+ switch (nsapi_security)
+ {
+ case NSAPI_SECURITY_NONE:
+ return kWiFiSecurityType_None;
+ case NSAPI_SECURITY_WEP:
+ return kWiFiSecurityType_WEP;
+ case NSAPI_SECURITY_WPA:
+ return kWiFiSecurityType_WPAPersonal;
+ case NSAPI_SECURITY_WPA2:
+ return kWiFiSecurityType_WPA2Personal;
+ case NSAPI_SECURITY_WPA_WPA2:
+ return kWiFiSecurityType_WPA2MixedPersonal;
+ case NSAPI_SECURITY_WPA2_ENT:
+ return kWiFiSecurityType_WPA2Enterprise;
+ case NSAPI_SECURITY_WPA3:
+ return kWiFiSecurityType_WPA3Personal;
+ case NSAPI_SECURITY_WPA3_WPA2:
+ return kWiFiSecurityType_WPA3MixedPersonal;
+ case NSAPI_SECURITY_PAP:
+ case NSAPI_SECURITY_CHAP:
+ case NSAPI_SECURITY_EAP_TLS:
+ case NSAPI_SECURITY_PEAP:
+ case NSAPI_SECURITY_UNKNOWN:
+ default:
+ return kWiFiSecurityType_NotSpecified;
+ }
+}
+
+} // namespace NetworkCommissioning
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/test_driver/mbed/unit_tests/config.in b/src/test_driver/mbed/unit_tests/config.in
index 11e0c0f..a05daae 100644
--- a/src/test_driver/mbed/unit_tests/config.in
+++ b/src/test_driver/mbed/unit_tests/config.in
@@ -2,3 +2,4 @@
CONFIG_CHIP_WITH_EXTERNAL_MBEDTLS=y
CONFIG_CHIP_PROJECT_CONFIG=main/include/CHIPProjectConfig.h
CONFIG_MBED_BSD_SOCKET_TRACE=n
+CONFIG_CHIP_DATA_MODEL=n
\ No newline at end of file