[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