blob: 90e3f8767133973d159a08064a191fa244a6ae9c [file] [log] [blame]
/*
*
* Copyright (c) 2020-2022 Project CHIP Authors
* Copyright (c) 2020 Nest Labs, Inc.
* Copyright 2023-2024 NXP
* 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.
*/
/* this file behaves like a config.h, comes first */
#include <platform/internal/CHIPDeviceLayerInternal.h>
#include "NetworkCommissioningDriver.h"
#include <lib/support/CodeUtils.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/ConnectivityManager.h>
#include <platform/DiagnosticDataProvider.h>
#include <platform/internal/BLEManager.h>
#include <platform/internal/GenericConnectivityManagerImpl_UDP.ipp>
#if INET_CONFIG_ENABLE_TCP_ENDPOINT
#include <platform/internal/GenericConnectivityManagerImpl_TCP.ipp>
#endif
#if CHIP_SYSTEM_CONFIG_USE_LWIP
#include <lwip/dns.h>
#include <lwip/ip_addr.h>
#include <lwip/nd6.h>
#include <lwip/netif.h>
#endif
#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
#include <platform/internal/GenericConnectivityManagerImpl_BLE.ipp>
#endif
#if CHIP_DEVICE_CONFIG_ENABLE_WPA
extern "C" {
#include "wlan.h"
#include "wm_net.h"
}
#include <platform/internal/GenericConnectivityManagerImpl_WiFi.ipp>
#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
#include <openthread/mdns.h>
#include "border_agent.h"
#include "br_rtos_manager.h"
#include "infra_if.h"
#endif /* CHIP_DEVICE_CONFIG_ENABLE_THREAD */
#endif /* CHIP_DEVICE_CONFIG_ENABLE_WPA */
#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
#include "ConnectivityManagerImpl.h"
#include <platform/internal/GenericConnectivityManagerImpl_Thread.ipp>
#endif /* CHIP_DEVICE_CONFIG_ENABLE_THREAD */
using namespace ::chip;
using namespace ::chip::Inet;
using namespace ::chip::System;
using namespace ::chip::DeviceLayer::Internal;
using namespace ::chip::DeviceLayer::DeviceEventType;
#if !SDK_2_16_100
// Table 9-50 "Status codes" of IEEE 802.11-2020: Unspecified failure
// Temporary default status code before SDK API to map wlan_event_reason to IEEE Status codes
#define WLAN_REFUSED_REASON_UNSPECIFIED 1
#endif
namespace chip {
namespace DeviceLayer {
ConnectivityManagerImpl ConnectivityManagerImpl::sInstance;
#if CHIP_DEVICE_CONFIG_ENABLE_WPA
netif_ext_callback_t ConnectivityManagerImpl::sNetifCallback;
#endif /* CHIP_DEVICE_CONFIG_ENABLE_WPA */
CHIP_ERROR ConnectivityManagerImpl::_Init()
{
CHIP_ERROR err = CHIP_NO_ERROR;
mWiFiStationMode = kWiFiStationMode_Disabled;
mWiFiStationState = kWiFiStationState_NotConnected;
mWiFiStationReconnectIntervalMS = CHIP_DEVICE_CONFIG_WIFI_STATION_RECONNECT_INTERVAL;
// Initialize the generic base classes that require it.
#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
GenericConnectivityManagerImpl_Thread<ConnectivityManagerImpl>::_Init();
#endif
SuccessOrExit(err);
exit:
return err;
}
void ConnectivityManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event)
{
// Forward the event to the generic base classes as needed.
#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
GenericConnectivityManagerImpl_Thread<ConnectivityManagerImpl>::_OnPlatformEvent(event);
#endif
#if CHIP_DEVICE_CONFIG_ENABLE_WPA
if (event->Type == kPlatformNxpWlanEvent)
{
ProcessWlanEvent(event->Platform.WlanEventReason);
}
else if (event->Type == kPlatformNxpIpChangeEvent)
{
UpdateInternetConnectivityState();
}
else if (event->Type == kPlatformNxpStartWlanConnectEvent)
{
bool is_wlan_added = false;
struct wlan_network searchedNetwork = { 0 };
/* If network was added before on a previous connection call or other API, do not add it again */
if (wlan_get_network_byname(event->Platform.pNetworkDataEvent->name, &searchedNetwork) != WM_SUCCESS)
{
if (wlan_add_network(event->Platform.pNetworkDataEvent) == WM_SUCCESS)
{
ChipLogProgress(DeviceLayer, "Added WLAN \"%s\"", event->Platform.pNetworkDataEvent->name);
is_wlan_added = true;
}
}
else
{
/* In case network was added before, signal that it is added and that connection can start */
is_wlan_added = true;
}
/* At this point, the network details should be registered in the wlan driver */
if (is_wlan_added == true)
{
_SetWiFiStationState(kWiFiStationState_Connecting);
ChipLogProgress(DeviceLayer, "WLAN connecting to network.name = \"%s\"", event->Platform.pNetworkDataEvent->name);
#if WIFI_DFS_OPTIMIZATION
/* Skip DFS (Dynamic Frequency Selection) channels during scan, DFS is used to avoid interferences */
wlan_connect_opt(event->Platform.pNetworkDataEvent->name, true);
#else
wlan_connect(event->Platform.pNetworkDataEvent->name);
#endif
}
if (event->Platform.pNetworkDataEvent != NULL)
{
free(event->Platform.pNetworkDataEvent);
}
}
else if (event->Type == kPlatformNxpScanWiFiNetworkDoneEvent)
{
NetworkCommissioning::NXPWiFiDriver::GetInstance().ScanWiFINetworkDoneFromMatterTaskContext(
event->Platform.ScanWiFiNetworkCount);
}
else if (event->Type == kPlatformNxpStartWlanInitWaitTimerEvent)
{
DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(kWlanInitWaitMs), ConnectNetworkTimerHandler,
(void *) event->Platform.pNetworkDataEvent);
}
#endif
}
#if CHIP_DEVICE_CONFIG_ENABLE_WPA
ConnectivityManager::WiFiStationMode ConnectivityManagerImpl::_GetWiFiStationMode()
{
return mWiFiStationMode;
}
CHIP_ERROR ConnectivityManagerImpl::_SetWiFiStationMode(ConnectivityManager::WiFiStationMode val)
{
CHIP_ERROR err = CHIP_NO_ERROR;
VerifyOrExit(val != ConnectivityManager::kWiFiStationMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT);
if (mWiFiStationMode != val)
{
ChipLogProgress(DeviceLayer, "WiFi station mode change: %s -> %s", WiFiStationModeToStr(mWiFiStationMode),
WiFiStationModeToStr(val));
}
mWiFiStationMode = val;
exit:
return err;
}
void ConnectivityManagerImpl::_SetWiFiStationState(ConnectivityManager::WiFiStationState val)
{
if (mWiFiStationState != val)
{
ChipLogProgress(DeviceLayer, "WiFi station state change: %s -> %s", WiFiStationStateToStr(mWiFiStationState),
WiFiStationStateToStr(val));
}
mWiFiStationState = val;
}
CHIP_ERROR ConnectivityManagerImpl::_SetWiFiAPMode(WiFiAPMode val)
{
CHIP_ERROR err = CHIP_NO_ERROR;
VerifyOrExit(val != kWiFiAPMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT);
if (mWiFiAPMode != val)
{
ChipLogProgress(DeviceLayer, "WiFi AP mode change: %s -> %s", WiFiAPModeToStr(mWiFiAPMode), WiFiAPModeToStr(val));
}
mWiFiAPMode = val;
exit:
return err;
}
bool ConnectivityManagerImpl::_IsWiFiStationEnabled()
{
return GetWiFiStationMode() == kWiFiStationMode_Enabled;
}
bool ConnectivityManagerImpl::_IsWiFiStationConnected()
{
return (mWiFiStationState == kWiFiStationState_Connected);
}
bool ConnectivityManagerImpl::_IsWiFiStationApplicationControlled()
{
return mWiFiStationMode == ConnectivityManager::kWiFiStationMode_ApplicationControlled;
}
void ConnectivityManagerImpl::ProcessWlanEvent(enum wlan_event_reason wlanEvent)
{
WiFiDiagnosticsDelegate * delegate = GetDiagnosticDataProvider().GetWiFiDiagnosticsDelegate();
uint8_t associationFailureCause =
chip::to_underlying(chip::app::Clusters::WiFiNetworkDiagnostics::AssociationFailureCauseEnum::kUnknown);
#if SDK_2_16_100
uint16_t wlan_status_code = wlan_get_status_code(wlanEvent);
#else
uint16_t wlan_status_code = WLAN_REFUSED_REASON_UNSPECIFIED;
#endif
#if CHIP_DETAIL_LOGGING
enum wlan_connection_state state;
int result;
result = wlan_get_connection_state(&state);
if (result == WM_SUCCESS)
{
ChipLogDetail(DeviceLayer, "WLAN event: %d, WLAN connection state: %d", wlanEvent, state);
}
else
{
ChipLogDetail(DeviceLayer, "WLAN event: %d, WLAN connection state: unknown", wlanEvent);
}
#endif /* CHIP_DETAIL_LOGGING */
switch (wlanEvent)
{
case WLAN_REASON_SUCCESS:
ChipLogProgress(DeviceLayer, "Connected to WLAN network = %d", is_sta_ipv6_connected());
if (sInstance._GetWiFiStationState() == kWiFiStationState_Connecting)
{
sInstance._SetWiFiStationState(kWiFiStationState_Connecting_Succeeded);
sInstance._SetWiFiStationState(kWiFiStationState_Connected);
NetworkCommissioning::NXPWiFiDriver::GetInstance().OnConnectWiFiNetwork(NetworkCommissioning::Status::kSuccess,
CharSpan(), wlanEvent);
sInstance.OnStationConnected();
}
break;
case WLAN_REASON_AUTH_SUCCESS:
ChipLogProgress(DeviceLayer, "Associated to WLAN network");
break;
case WLAN_REASON_CONNECT_FAILED:
ChipLogError(DeviceLayer, "WLAN (re)connect failed");
sInstance._SetWiFiStationState(kWiFiStationState_NotConnected);
associationFailureCause =
chip::to_underlying(chip::app::Clusters::WiFiNetworkDiagnostics::AssociationFailureCauseEnum::kAssociationFailed);
if (delegate)
{
delegate->OnAssociationFailureDetected(associationFailureCause, wlan_status_code);
}
UpdateInternetConnectivityState();
break;
case WLAN_REASON_NETWORK_NOT_FOUND:
ChipLogError(DeviceLayer, "WLAN network not found");
NetworkCommissioning::NXPWiFiDriver::GetInstance().OnConnectWiFiNetwork(NetworkCommissioning::Status::kNetworkNotFound,
CharSpan(), wlanEvent);
associationFailureCause =
chip::to_underlying(chip::app::Clusters::WiFiNetworkDiagnostics::AssociationFailureCauseEnum::kSsidNotFound);
if (delegate)
{
delegate->OnAssociationFailureDetected(associationFailureCause, wlan_status_code);
}
break;
case WLAN_REASON_NETWORK_AUTH_FAILED:
ChipLogError(DeviceLayer, "Authentication to WLAN network failed");
NetworkCommissioning::NXPWiFiDriver::GetInstance().OnConnectWiFiNetwork(NetworkCommissioning::Status::kAuthFailure,
CharSpan(), wlanEvent);
ChipLogError(DeviceLayer, "Authentication to WLAN network failed end");
associationFailureCause =
chip::to_underlying(chip::app::Clusters::WiFiNetworkDiagnostics::AssociationFailureCauseEnum::kAuthenticationFailed);
if (delegate)
{
delegate->OnAssociationFailureDetected(associationFailureCause, wlan_status_code);
}
break;
case WLAN_REASON_LINK_LOST:
ChipLogError(DeviceLayer, "WLAN link lost");
if (sInstance._GetWiFiStationState() == kWiFiStationState_Connected)
{
sInstance._SetWiFiStationState(kWiFiStationState_NotConnected);
sInstance.OnStationDisconnected();
if (delegate)
{
delegate->OnAssociationFailureDetected(associationFailureCause, wlan_status_code);
}
}
break;
case WLAN_REASON_USER_DISCONNECT:
ChipLogProgress(DeviceLayer, "Disconnected from WLAN network");
sInstance._SetWiFiStationState(kWiFiStationState_NotConnected);
sInstance.OnStationDisconnected();
if (delegate)
{
delegate->OnAssociationFailureDetected(associationFailureCause, wlan_status_code);
}
break;
case WLAN_REASON_INITIALIZED:
sInstance._SetWiFiStationState(kWiFiStationState_NotConnected);
sInstance._SetWiFiStationMode(kWiFiStationMode_Enabled);
break;
default:
break;
}
}
int ConnectivityManagerImpl::_WlanEventCallback(enum wlan_event_reason wlanEvent, void * data)
{
ChipDeviceEvent event;
event.Type = DeviceEventType::kPlatformNxpWlanEvent;
event.Platform.WlanEventReason = wlanEvent;
(void) PlatformMgr().PostEvent(&event);
return 0;
}
void ConnectivityManagerImpl::OnStationConnected()
{
ChipDeviceEvent event;
event.Type = DeviceEventType::kWiFiConnectivityChange;
event.WiFiConnectivityChange.Result = kConnectivity_Established;
(void) PlatformMgr().PostEvent(&event);
/* Update the connectivity state in case the connected event has been received after getting an IP addr */
UpdateInternetConnectivityState();
WiFiDiagnosticsDelegate * delegate = GetDiagnosticDataProvider().GetWiFiDiagnosticsDelegate();
if (delegate)
{
delegate->OnConnectionStatusChanged(
chip::to_underlying(chip::app::Clusters::WiFiNetworkDiagnostics::ConnectionStatusEnum::kConnected));
}
}
void ConnectivityManagerImpl::OnStationDisconnected()
{
ChipDeviceEvent event;
event.Type = DeviceEventType::kWiFiConnectivityChange;
event.WiFiConnectivityChange.Result = kConnectivity_Lost;
(void) PlatformMgr().PostEvent(&event);
WiFiDiagnosticsDelegate * delegate = GetDiagnosticDataProvider().GetWiFiDiagnosticsDelegate();
if (delegate)
{
delegate->OnConnectionStatusChanged(
chip::to_underlying(chip::app::Clusters::WiFiNetworkDiagnostics::ConnectionStatusEnum::kNotConnected));
}
/* Update the connectivity state in case the connected event has been received after getting an IP addr */
UpdateInternetConnectivityState();
}
void ConnectivityManagerImpl::UpdateInternetConnectivityState()
{
bool haveIPv4Conn = false;
bool haveIPv6Conn = false;
const bool hadIPv4Conn = mFlags.Has(ConnectivityFlags::kHaveIPv4InternetConnectivity);
const bool hadIPv6Conn = mFlags.Has(ConnectivityFlags::kHaveIPv6InternetConnectivity);
const ip_addr_t * addr4;
const ip6_addr_t * addr6;
CHIP_ERROR err;
ChipDeviceEvent event;
// If the WiFi station is currently in the connected state...
if (_IsWiFiStationConnected())
{
// Get the LwIP netif for the WiFi station interface.
struct netif * netif = static_cast<struct netif *>(net_get_mlan_handle());
// If the WiFi station interface is up...
if ((netif != nullptr) && netif_is_up(netif) && netif_is_link_up(netif))
{
#if INET_CONFIG_ENABLE_IPV4
// Check if a DNS server is currently configured. If so...
ip_addr_t dnsServerAddr = *dns_getserver(0);
if (!ip_addr_isany_val(dnsServerAddr))
{
// If the station interface has been assigned an IPv4 address, and has
// an IPv4 gateway, then presume that the device has IPv4 Internet
// connectivity.
if (!ip4_addr_isany_val(*netif_ip4_addr(netif)) && !ip4_addr_isany_val(*netif_ip4_gw(netif)))
{
haveIPv4Conn = true;
addr4 = &netif->ip_addr;
}
}
#endif
// Search among the IPv6 addresses assigned to the interface for an
// address that is in the valid state. Search goes backwards because
// the link-local address is in the first slot and we prefer to report
// other than the link-local address value if there are multiple addresses.
for (int i = (LWIP_IPV6_NUM_ADDRESSES - 1); i >= 0; i--)
{
if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)))
{
haveIPv6Conn = true;
addr6 = netif_ip6_addr(netif, i);
break;
}
}
}
}
// Update the current state.
mFlags.Set(ConnectivityFlags::kHaveIPv4InternetConnectivity, haveIPv4Conn)
.Set(ConnectivityFlags::kHaveIPv6InternetConnectivity, haveIPv6Conn);
if (haveIPv4Conn != hadIPv4Conn)
{
/* Check if the */
event.Type = DeviceEventType::kInternetConnectivityChange;
event.InternetConnectivityChange.IPv4 = GetConnectivityChange(hadIPv4Conn, haveIPv4Conn);
event.InternetConnectivityChange.IPv6 = kConnectivity_NoChange;
if (haveIPv4Conn)
{
event.InternetConnectivityChange.ipAddress = IPAddress(*addr4);
}
err = PlatformMgr().PostEvent(&event);
VerifyOrDie(err == CHIP_NO_ERROR);
ChipLogProgress(DeviceLayer, "%s Internet connectivity %s", "IPv4", (haveIPv4Conn) ? "ESTABLISHED" : "LOST");
}
if (haveIPv6Conn != hadIPv6Conn)
{
event.Type = DeviceEventType::kInternetConnectivityChange;
event.InternetConnectivityChange.IPv4 = kConnectivity_NoChange;
event.InternetConnectivityChange.IPv6 = GetConnectivityChange(hadIPv6Conn, haveIPv6Conn);
#if CHIP_ENABLE_OPENTHREAD
// In case of boot, start the Border Router services including MDNS Server, otherwise inform of link state change
// The posted event will signal the application to restart the Matter mDNS server instance
bool bLinkState = event.InternetConnectivityChange.IPv6 == kConnectivity_Established ? true : false;
BrHandleStateChange(bLinkState);
#endif
if (haveIPv6Conn)
{
event.InternetConnectivityChange.ipAddress = IPAddress(*addr6);
}
err = PlatformMgr().PostEvent(&event);
VerifyOrDie(err == CHIP_NO_ERROR);
ChipLogProgress(DeviceLayer, "%s Internet connectivity %s", "IPv6", (haveIPv6Conn) ? "ESTABLISHED" : "LOST");
}
#if CHIP_ENABLE_OPENTHREAD
if (haveIPv6Conn && UpdateIp6AddrList())
{
UpdateMdnsHost();
}
#endif
}
void ConnectivityManagerImpl::_NetifExtCallback(struct netif * netif, netif_nsc_reason_t reason,
const netif_ext_callback_args_t * args)
{
struct netif * station_netif;
ChipDeviceEvent event;
ChipLogDetail(DeviceLayer, "_NetifExtCallback: netif=%p, reason=0x%04x", netif, reason);
station_netif = static_cast<struct netif *>(net_get_mlan_handle());
if (netif == station_netif)
{
event.Type = DeviceEventType::kPlatformNxpIpChangeEvent;
(void) PlatformMgr().PostEvent(&event);
}
}
void ConnectivityManagerImpl::StartWiFiManagement()
{
struct netif * netif = nullptr;
int32_t result;
LOCK_TCPIP_CORE();
netif = static_cast<struct netif *>(net_get_mlan_handle());
if (netif != nullptr)
{
memset(&ConnectivityManagerImpl::sNetifCallback, 0, sizeof(ConnectivityManagerImpl::sNetifCallback));
netif_add_ext_callback(&ConnectivityManagerImpl::sNetifCallback, &_NetifExtCallback);
}
UNLOCK_TCPIP_CORE();
result = wlan_start(_WlanEventCallback);
if (result != WM_SUCCESS)
{
ChipLogError(DeviceLayer, "Failed to start WLAN Connection Manager");
chipDie();
}
}
#if CHIP_ENABLE_OPENTHREAD
void ConnectivityManagerImpl::BrHandleStateChange(bool bLinkState)
{
if (mBorderRouterInit == false)
{
if (bLinkState)
{
struct netif * extNetIfPtr = static_cast<struct netif *>(net_get_mlan_handle());
struct netif * thrNetIfPtr = ThreadStackMgrImpl().ThreadNetIf();
otInstance * thrInstancePtr;
// Need to wait for the wifi to be connected because the mlan netif can be !=null but not initialized
// properly. If the thread netif is !=null it means that it was fully initialized
// Lock OT task ?
if ((thrNetIfPtr) && (mWiFiStationState == kWiFiStationState_Connected))
{
// Initalize internal interface variables, these can be used by other modules like the DNSSD Impl to
// get the underlying IP interface
Inet::InterfaceId tmpExtIf(extNetIfPtr);
Inet::InterfaceId tmpThrIf(thrNetIfPtr);
mExternalNetIf = tmpExtIf;
mThreadNetIf = tmpThrIf;
mBorderRouterInit = true;
// Check if OT instance is init
thrInstancePtr = ThreadStackMgrImpl().OTInstance();
BrInitPlatform(thrInstancePtr, extNetIfPtr, thrNetIfPtr);
BrInitServices();
UpdateIp6AddrList();
UpdateMdnsHost();
BorderAgentInit(thrInstancePtr, mHostname);
}
}
}
else
{
InfraIfLinkState(bLinkState);
}
}
void ConnectivityManagerImpl::UpdateMdnsHost()
{
CHIP_ERROR err = CHIP_NO_ERROR;
otMdnsHost mdnsHost;
if (strlen(mHostname) == 0)
{
uint8_t macBuffer[ConfigurationManager::kPrimaryMACAddressLength];
MutableByteSpan mac(macBuffer);
err = DeviceLayer::ConfigurationMgr().GetPrimaryMACAddress(mac);
SuccessOrExit(err);
chip::Dnssd::MakeHostName(mHostname, sizeof(mHostname), mac);
}
mdnsHost.mAddresses = mIp6AddrList;
mdnsHost.mAddressesLength = mIp6AddrNum;
mdnsHost.mHostName = mHostname;
mdnsHost.mInfraIfIndex = netif_get_index(mExternalNetIf.GetPlatformInterface());
// Allways use ID 0 for host
otMdnsRegisterHost(ThreadStackMgrImpl().OTInstance(), &mdnsHost, 0, nullptr);
exit:
return;
}
bool ConnectivityManagerImpl::UpdateIp6AddrList()
{
const ip6_addr_t * addr6 = nullptr;
bool bAddrChange = false;
uint32_t newIp6AddrNum = 0;
struct netif * extNetIfPtr = mExternalNetIf.GetPlatformInterface();
uint32_t lwipIterator, addrListIterator;
for (lwipIterator = 0; lwipIterator < LWIP_IPV6_NUM_ADDRESSES; lwipIterator++)
{
if (ip6_addr_ispreferred(netif_ip6_addr_state(extNetIfPtr, lwipIterator)) && (mIp6AddrNum <= kMaxIp6Addr))
{
addr6 = netif_ip6_addr(extNetIfPtr, lwipIterator);
for (addrListIterator = 0; addrListIterator < kMaxIp6Addr; addrListIterator++)
{
if (0 == memcmp(&mIp6AddrList[addrListIterator].mFields.m32, addr6->addr, sizeof(Inet::IPAddress)))
{
break;
}
}
if (addrListIterator == kMaxIp6Addr)
{
bAddrChange |= true;
}
memcpy(&mIp6AddrList[newIp6AddrNum++].mFields.m32, addr6->addr, sizeof(Inet::IPAddress));
}
}
bAddrChange |= (newIp6AddrNum != mIp6AddrNum) ? true : false;
mIp6AddrNum = newIp6AddrNum;
return bAddrChange;
}
Inet::InterfaceId ConnectivityManagerImpl::GetThreadInterface()
{
return sInstance.mThreadNetIf;
}
Inet::InterfaceId ConnectivityManagerImpl::GetExternalInterface()
{
return sInstance.mExternalNetIf;
}
#endif // CHIP_ENABLE_OPENTHREAD
#endif // CHIP_DEVICE_CONFIG_ENABLE_WPA
CHIP_ERROR ConnectivityManagerImpl::ProvisionWiFiNetwork(const char * ssid, uint8_t ssidLen, const char * key, uint8_t keyLen)
{
#if CHIP_DEVICE_CONFIG_ENABLE_WPA
CHIP_ERROR ret = CHIP_NO_ERROR;
struct wlan_network * pNetworkData = (struct wlan_network *) malloc(sizeof(struct wlan_network));
VerifyOrExit(pNetworkData != NULL, ret = CHIP_ERROR_NO_MEMORY);
VerifyOrExit(ssidLen <= IEEEtypes_SSID_SIZE, ret = CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrExit(mWiFiStationState != kWiFiStationState_Connecting, ret = CHIP_ERROR_BUSY);
// Need to enable the WIFI interface here when Thread is enabled as a secondary network interface. We don't want to enable
// WIFI from the init phase anymore and we will only do it in case the commissioner is provisioning the device with
// the WIFI credentials.
if (mWifiManagerInit == false)
{
StartWiFiManagement();
mWifiManagerInit = true;
}
memset(pNetworkData, 0, sizeof(struct wlan_network));
if (ssidLen < WLAN_NETWORK_NAME_MAX_LENGTH)
{
memcpy(pNetworkData->name, ssid, ssidLen);
pNetworkData->name[ssidLen] = '\0';
}
else
{
memcpy(pNetworkData->name, ssid, WLAN_NETWORK_NAME_MAX_LENGTH);
pNetworkData->name[WLAN_NETWORK_NAME_MAX_LENGTH] = '\0';
}
memcpy(pNetworkData->ssid, ssid, ssidLen);
pNetworkData->ip.ipv4.addr_type = ADDR_TYPE_DHCP;
pNetworkData->ssid_specific = 1;
pNetworkData->security.type = WLAN_SECURITY_NONE;
if (keyLen > 0)
{
pNetworkData->security.type = WLAN_SECURITY_WILDCARD;
memcpy(pNetworkData->security.psk, key, keyLen);
pNetworkData->security.psk_len = keyLen;
}
ConnectNetworkTimerHandler(NULL, (void *) pNetworkData);
exit:
return ret;
#else
return CHIP_ERROR_NOT_IMPLEMENTED;
#endif
}
#if CHIP_DEVICE_CONFIG_ENABLE_WPA
void ConnectivityManagerImpl::ConnectNetworkTimerHandler(::chip::System::Layer * aLayer, void * context)
{
ChipDeviceEvent event;
/*
* Make sure to have the Wi-Fi station enabled before scheduling a connect event .
* Otherwise start a new timer to check again the status later.
*/
if (ConnectivityMgr().IsWiFiStationEnabled())
{
/* Post an event to start the connection asynchronously in the Matter task context */
event.Type = DeviceEventType::kPlatformNxpStartWlanConnectEvent;
event.Platform.pNetworkDataEvent = (struct wlan_network *) context;
(void) PlatformMgr().PostEvent(&event);
}
else
{
/* Post an event to start a delay timer asynchronously in the Matter task context */
event.Type = DeviceEventType::kPlatformNxpStartWlanInitWaitTimerEvent;
event.Platform.pNetworkDataEvent = (struct wlan_network *) context;
(void) PlatformMgr().PostEvent(&event);
}
}
/* Can be used to disconnect from WiFi network.
*/
CHIP_ERROR ConnectivityManagerImpl::_DisconnectNetwork(void)
{
int ret = 0;
CHIP_ERROR err = CHIP_NO_ERROR;
if (ConnectivityMgrImpl().IsWiFiStationConnected())
{
ChipLogProgress(NetworkProvisioning, "Disconnecting from WiFi network.");
ret = wlan_disconnect();
if (ret != WM_SUCCESS)
{
ChipLogError(NetworkProvisioning, "Failed to disconnect from network with error: %u", (uint8_t) ret);
err = CHIP_ERROR_UNEXPECTED_EVENT;
}
}
else
{
ChipLogError(NetworkProvisioning, "Error: WiFi not connected!");
err = CHIP_ERROR_INCORRECT_STATE;
}
return err;
}
#if CHIP_CONFIG_ENABLE_ICD_SERVER
CHIP_ERROR ConnectivityManagerImpl::_SetPollingInterval(System::Clock::Milliseconds32 pollingInterval)
{
/*
* ToDo: Call API to put device into sleep
*/
return CHIP_NO_ERROR;
}
#endif // CHIP_CONFIG_ENABLE_ICD_SERVER
#endif
} // namespace DeviceLayer
} // namespace chip