diff --git a/src/platform/Zephyr/wifi/ConnectivityManagerImplWiFi.cpp b/src/platform/Zephyr/wifi/ConnectivityManagerImplWiFi.cpp index 9b605c31560142..5bef79bb22fdc5 100644 --- a/src/platform/Zephyr/wifi/ConnectivityManagerImplWiFi.cpp +++ b/src/platform/Zephyr/wifi/ConnectivityManagerImplWiFi.cpp @@ -42,7 +42,7 @@ ConnectivityManager::WiFiStationMode ConnectivityManagerImplWiFi::_GetWiFiStatio { if (mStationMode != ConnectivityManager::WiFiStationMode::kWiFiStationMode_ApplicationControlled) { - mStationMode = (WiFiManager::StationStatus::DISABLED == WiFiManager::Instance().GetStationStatus()) + mStationMode = (WiFiManager::StationStatus::DISABLED == WiFiManager().Instance().GetStationStatus()) ? ConnectivityManager::WiFiStationMode::kWiFiStationMode_Disabled : ConnectivityManager::WiFiStationMode::kWiFiStationMode_Enabled; } @@ -60,7 +60,7 @@ CHIP_ERROR ConnectivityManagerImplWiFi::_SetWiFiStationMode(ConnectivityManager: bool ConnectivityManagerImplWiFi::_IsWiFiStationEnabled(void) { - return (WiFiManager::StationStatus::DISABLED <= WiFiManager::Instance().GetStationStatus()); + return (WiFiManager::StationStatus::DISABLED <= WiFiManager().Instance().GetStationStatus()); } bool ConnectivityManagerImplWiFi::_IsWiFiStationApplicationControlled(void) @@ -70,7 +70,7 @@ bool ConnectivityManagerImplWiFi::_IsWiFiStationApplicationControlled(void) bool ConnectivityManagerImplWiFi::_IsWiFiStationConnected(void) { - return (WiFiManager::StationStatus::CONNECTED == WiFiManager::Instance().GetStationStatus()); + return (WiFiManager::StationStatus::CONNECTED == WiFiManager().Instance().GetStationStatus()); } System::Clock::Timeout ConnectivityManagerImplWiFi::_GetWiFiStationReconnectInterval(void) @@ -88,14 +88,14 @@ bool ConnectivityManagerImplWiFi::_IsWiFiStationProvisioned(void) { // from Matter perspective `provisioned` means that the supplicant has been provided // with SSID and password (doesn't matter if valid or not) - return (WiFiManager::StationStatus::CONNECTING <= WiFiManager::Instance().GetStationStatus()); + return (WiFiManager::StationStatus::CONNECTING <= WiFiManager().Instance().GetStationStatus()); } void ConnectivityManagerImplWiFi::_ClearWiFiStationProvision(void) { if (_IsWiFiStationProvisioned()) { - if (CHIP_NO_ERROR != WiFiManager::Instance().ClearStationProvisioningData()) + if (CHIP_NO_ERROR != WiFiManager().Instance().ClearStationProvisioningData()) { ChipLogError(DeviceLayer, "Cannot clear WiFi station provisioning data"); } @@ -104,9 +104,9 @@ void ConnectivityManagerImplWiFi::_ClearWiFiStationProvision(void) bool ConnectivityManagerImplWiFi::_CanStartWiFiScan() { - return (WiFiManager::StationStatus::DISABLED != WiFiManager::Instance().GetStationStatus() && - WiFiManager::StationStatus::SCANNING != WiFiManager::Instance().GetStationStatus() && - WiFiManager::StationStatus::CONNECTING != WiFiManager::Instance().GetStationStatus()); + return (WiFiManager::StationStatus::DISABLED != WiFiManager().Instance().GetStationStatus() && + WiFiManager::StationStatus::SCANNING != WiFiManager().Instance().GetStationStatus() && + WiFiManager::StationStatus::CONNECTING != WiFiManager().Instance().GetStationStatus()); } void ConnectivityManagerImplWiFi::_OnWiFiStationProvisionChange() diff --git a/src/platform/Zephyr/wifi/WiFiManager.cpp b/src/platform/Zephyr/wifi/WiFiManager.cpp index bc0cb97ece44c4..11187a7cef1655 100644 --- a/src/platform/Zephyr/wifi/WiFiManager.cpp +++ b/src/platform/Zephyr/wifi/WiFiManager.cpp @@ -23,9 +23,10 @@ #include "WiFiManager.h" #include +#include +#include #include #include -#include #include #include @@ -49,21 +50,6 @@ namespace DeviceLayer { namespace { -app::Clusters::NetworkCommissioning::WiFiBandEnum ConvertBandEnum(uint8_t band) -{ - switch (band) - { - case WIFI_FREQ_BAND_2_4_GHZ: - return app::Clusters::NetworkCommissioning::WiFiBandEnum::k2g4; - case WIFI_FREQ_BAND_5_GHZ: - return app::Clusters::NetworkCommissioning::WiFiBandEnum::k5g; - case WIFI_FREQ_BAND_6_GHZ: - return app::Clusters::NetworkCommissioning::WiFiBandEnum::k6g; - default: - return app::Clusters::NetworkCommissioning::WiFiBandEnum::kUnknownEnumValue; - } -} - NetworkCommissioning::WiFiScanResponse ToScanResponse(const wifi_scan_result * result) { NetworkCommissioning::WiFiScanResponse response = {}; @@ -76,10 +62,9 @@ NetworkCommissioning::WiFiScanResponse ToScanResponse(const wifi_scan_result * r // TODO: Distinguish WPA versions response.security.Set(result->security == WIFI_SECURITY_TYPE_PSK ? NetworkCommissioning::WiFiSecurity::kWpaPersonal : NetworkCommissioning::WiFiSecurity::kUnencrypted); - response.channel = result->channel; - response.rssi = result->rssi; - response.ssidLen = result->ssid_length; - response.wiFiBand = ConvertBandEnum(result->band); + response.channel = result->channel; + response.rssi = result->rssi; + response.ssidLen = result->ssid_length; memcpy(response.ssid, result->ssid, result->ssid_length); // TODO: MAC/BSSID is not filled by the Wi-Fi driver memcpy(response.bssid, result->mac, result->mac_length); @@ -153,43 +138,57 @@ const Map { WIFI_STATE_GROUP_HANDSHAKE, WiFiManager::StationStatus::PROVISIONING }, { WIFI_STATE_COMPLETED, WiFiManager::StationStatus::FULLY_PROVISIONED } }); -const Map WiFiManager::sEventHandlerMap({ - { NET_EVENT_WIFI_SCAN_RESULT, WiFiManager::ScanResultHandler }, - { NET_EVENT_WIFI_SCAN_DONE, WiFiManager::ScanDoneHandler }, - { NET_EVENT_WIFI_CONNECT_RESULT, WiFiManager::ConnectHandler }, - { NET_EVENT_WIFI_DISCONNECT_RESULT, WiFiManager::DisconnectHandler }, - { NET_EVENT_WIFI_DISCONNECT_COMPLETE, WiFiManager::DisconnectHandler }, -}); +const Map + WiFiManager::sEventHandlerMap({ { NET_EVENT_WIFI_SCAN_RESULT, WiFiManager::ScanResultHandler }, + { NET_EVENT_WIFI_SCAN_DONE, WiFiManager::ScanDoneHandler }, + { NET_EVENT_WIFI_CONNECT_RESULT, WiFiManager::ConnectHandler }, + { NET_EVENT_WIFI_DISCONNECT_RESULT, WiFiManager::DisconnectHandler }, + { NET_EVENT_WIFI_DISCONNECT_COMPLETE, WiFiManager::DisconnectHandler } }); void WiFiManager::WifiMgmtEventHandler(net_mgmt_event_callback * cb, uint32_t mgmtEvent, net_if * iface) { - if (iface == Instance().mNetIf) + if (0 == strcmp(iface->if_dev->dev->name, InetUtils::GetInterface()->if_dev->dev->name)) { Platform::UniquePtr eventData(new uint8_t[cb->info_length]); VerifyOrReturn(eventData); memcpy(eventData.get(), cb->info, cb->info_length); - sEventHandlerMap[mgmtEvent](std::move(eventData), cb->info_length); - } -} - -void WiFiManager::IPv6MgmtEventHandler(net_mgmt_event_callback * cb, uint32_t mgmtEvent, net_if * iface) -{ - if (((mgmtEvent == NET_EVENT_IPV6_ADDR_ADD) || (mgmtEvent == NET_EVENT_IPV6_ADDR_DEL)) && cb->info) - { - IPv6AddressChangeHandler(cb->info); + sEventHandlerMap[mgmtEvent](std::move(eventData)); } } CHIP_ERROR WiFiManager::Init() { - mNetIf = InetUtils::GetWiFiInterface(); - VerifyOrReturnError(mNetIf != nullptr, INET_ERROR_UNKNOWN_INTERFACE); + // TODO: consider moving these to ConnectivityManagerImpl to be prepared for handling multiple interfaces on a single device. + Inet::UDPEndPointImplSockets::SetMulticastGroupHandler([](Inet::InterfaceId interfaceId, const Inet::IPAddress & address, + Inet::UDPEndPointImplSockets::MulticastOperation operation) { + const in6_addr addr = InetUtils::ToZephyrAddr(address); + net_if * iface = InetUtils::GetInterface(interfaceId); + VerifyOrReturnError(iface != nullptr, INET_ERROR_UNKNOWN_INTERFACE); + + if (operation == Inet::UDPEndPointImplSockets::MulticastOperation::kJoin) + { + net_if_mcast_addr * maddr = net_if_ipv6_maddr_add(iface, &addr); - net_mgmt_init_event_callback(&mWiFiMgmtClbk, WifiMgmtEventHandler, kWifiManagementEvents); - net_mgmt_init_event_callback(&mIPv6MgmtClbk, IPv6MgmtEventHandler, kIPv6ManagementEvents); + if (maddr && !net_if_ipv6_maddr_is_joined(maddr) && !net_ipv6_is_addr_mcast_link_all_nodes(&addr)) + { + net_if_ipv6_maddr_join(iface, maddr); + } + } + else if (operation == Inet::UDPEndPointImplSockets::MulticastOperation::kLeave) + { + VerifyOrReturnError(net_ipv6_is_addr_mcast_link_all_nodes(&addr) || net_if_ipv6_maddr_rm(iface, &addr), + CHIP_ERROR_INVALID_ADDRESS); + } + else + { + return CHIP_ERROR_INCORRECT_STATE; + } + return CHIP_NO_ERROR; + }); + + net_mgmt_init_event_callback(&mWiFiMgmtClbk, WifiMgmtEventHandler, kWifiManagementEvents); net_mgmt_add_event_callback(&mWiFiMgmtClbk); - net_mgmt_add_event_callback(&mIPv6MgmtClbk); ChipLogDetail(DeviceLayer, "WiFiManager has been initialized"); @@ -198,6 +197,9 @@ CHIP_ERROR WiFiManager::Init() CHIP_ERROR WiFiManager::Scan(const ByteSpan & ssid, ScanResultCallback resultCallback, ScanDoneCallback doneCallback, bool internalScan) { + net_if * iface = InetUtils::GetInterface(); + VerifyOrReturnError(nullptr != iface, CHIP_ERROR_INTERNAL); + mInternalScan = internalScan; mScanResultCallback = resultCallback; mScanDoneCallback = doneCallback; @@ -205,22 +207,17 @@ CHIP_ERROR WiFiManager::Scan(const ByteSpan & ssid, ScanResultCallback resultCal mWiFiState = WIFI_STATE_SCANNING; mSsidFound = false; - wifi_scan_params * scanParams{ nullptr }; - size_t scanParamsSize{ 0 }; - - if (!ssid.empty()) + /* If the ssid is not null, it means the scan must target a specific SSID, and only include this one in the scan + * result. To do so, we save the requested ssid and we will filter the scan results accordingly in the scan done + * handler. */ + if ((ssid.size() > 0) && (!mInternalScan)) { - /* We must assume that the ssid is handled as a NULL-terminated string. - Note that the mScanSsidBuffer is initialized with zeros. */ - VerifyOrReturnError(ssid.size() < sizeof(mScanSsidBuffer), CHIP_ERROR_INVALID_ARGUMENT); - memcpy(mScanSsidBuffer, ssid.data(), ssid.size()); - mScanSsidBuffer[ssid.size()] = 0; // indicate the end of ssid string - mScanParams.ssids[0] = mScanSsidBuffer; - mScanParams.ssids[1] = nullptr; // indicate the end of ssids list - scanParams = &mScanParams; - scanParamsSize = sizeof(*scanParams); + mNetworkToScan.Erase(); + memcpy(mNetworkToScan.ssid, ssid.data(), ssid.size()); + mNetworkToScan.ssidLen = ssid.size(); } - if (0 != net_mgmt(NET_REQUEST_WIFI_SCAN, mNetIf, scanParams, scanParamsSize)) + + if (0 != net_mgmt(NET_REQUEST_WIFI_SCAN, iface, NULL, 0)) { ChipLogError(DeviceLayer, "Scan request failed"); return CHIP_ERROR_INTERNAL; @@ -242,7 +239,9 @@ CHIP_ERROR WiFiManager::Connect(const ByteSpan & ssid, const ByteSpan & credenti { ChipLogDetail(DeviceLayer, "Connecting to WiFi network: %.*s", ssid.size(), ssid.data()); - mHandling = handling; + mHandling.mOnConnectionSuccess = handling.mOnConnectionSuccess; + mHandling.mOnConnectionFailed = handling.mOnConnectionFailed; + mHandling.mConnectionTimeout = handling.mConnectionTimeout; mWiFiState = WIFI_STATE_ASSOCIATING; @@ -259,8 +258,11 @@ CHIP_ERROR WiFiManager::Connect(const ByteSpan & ssid, const ByteSpan & credenti CHIP_ERROR WiFiManager::Disconnect() { + net_if * iface = InetUtils::GetInterface(); + VerifyOrReturnError(nullptr != iface, CHIP_ERROR_INTERNAL); + mApplicationDisconnectRequested = true; - int status = net_mgmt(NET_REQUEST_WIFI_DISCONNECT, mNetIf, NULL, 0); + int status = net_mgmt(NET_REQUEST_WIFI_DISCONNECT, iface, NULL, 0); if (status) { @@ -285,9 +287,11 @@ CHIP_ERROR WiFiManager::Disconnect() CHIP_ERROR WiFiManager::GetWiFiInfo(WiFiInfo & info) const { - wifi_iface_status status = { 0 }; + net_if * iface = InetUtils::GetInterface(); + VerifyOrReturnError(nullptr != iface, CHIP_ERROR_INTERNAL); + struct wifi_iface_status status = { 0 }; - if (net_mgmt(NET_REQUEST_WIFI_IFACE_STATUS, mNetIf, &status, sizeof(wifi_iface_status))) + if (net_mgmt(NET_REQUEST_WIFI_IFACE_STATUS, iface, &status, sizeof(struct wifi_iface_status))) { ChipLogError(DeviceLayer, "Status request failed"); return CHIP_ERROR_INTERNAL; @@ -312,31 +316,22 @@ CHIP_ERROR WiFiManager::GetWiFiInfo(WiFiInfo & info) const CHIP_ERROR WiFiManager::GetNetworkStatistics(NetworkStatistics & stats) const { net_stats_wifi data{}; - net_mgmt(NET_REQUEST_STATS_GET_WIFI, mNetIf, &data, sizeof(data)); + net_mgmt(NET_REQUEST_STATS_GET_WIFI, InetUtils::GetInterface(), &data, sizeof(data)); stats.mPacketMulticastRxCount = data.multicast.rx; stats.mPacketMulticastTxCount = data.multicast.tx; -#if CONFIG_CHIP_NXP_PLATFORM - /* Zephyr 3.6 doesn't support the unicast stat in net_stats_wifi struct */ - stats.mPacketUnicastRxCount = data.pkts.rx - data.multicast.rx - data.broadcast.rx; - stats.mPacketUnicastRxCount = data.pkts.tx - data.multicast.tx - data.broadcast.tx; -#else - stats.mPacketUnicastRxCount = data.unicast.rx; - stats.mPacketUnicastTxCount = data.unicast.tx; -#endif - stats.mBeaconsSuccessCount = data.sta_mgmt.beacons_rx; - stats.mBeaconsLostCount = data.sta_mgmt.beacons_miss; + stats.mPacketUnicastRxCount = data.pkts.rx - data.multicast.rx - data.broadcast.rx; + stats.mPacketUnicastTxCount = data.pkts.tx - data.multicast.tx - data.broadcast.tx; + stats.mBeaconsSuccessCount = data.sta_mgmt.beacons_rx; + stats.mBeaconsLostCount = data.sta_mgmt.beacons_miss; return CHIP_NO_ERROR; } -void WiFiManager::ScanResultHandler(Platform::UniquePtr data, size_t length) +void WiFiManager::ScanResultHandler(Platform::UniquePtr data) { - // Validate that input data size matches the expected one. - VerifyOrReturn(length == sizeof(wifi_scan_result)); - // Contrary to other handlers, offload accumulating of the scan results from the CHIP thread to the caller's thread - const wifi_scan_result * scanResult = reinterpret_cast(data.get()); + const struct wifi_scan_result * scanResult = reinterpret_cast(data.get()); if (Instance().mInternalScan && Instance().mWantedNetwork.GetSsidSpan().data_equal(ByteSpan(scanResult->ssid, scanResult->ssid_length))) @@ -373,33 +368,45 @@ void WiFiManager::ScanResultHandler(Platform::UniquePtr data, size_t le if (Instance().mScanResultCallback && !Instance().mInternalScan) { - Instance().mScanResultCallback(ToScanResponse(scanResult)); + /* Here we need to check if the scan is targeting a specific network and filter the scan result accordingly, + * to make sure only the targeted SSID is reported */ + if (Instance().mNetworkToScan.GetSsidSpan().size() == 0) + { + Instance().mScanResultCallback(ToScanResponse(scanResult)); + } + else if (Instance().mNetworkToScan.GetSsidSpan().data_equal(ByteSpan(scanResult->ssid, scanResult->ssid_length))) + { + Instance().mScanResultCallback(ToScanResponse(scanResult)); + } } } -void WiFiManager::ScanDoneHandler(Platform::UniquePtr data, size_t length) +void WiFiManager::ScanDoneHandler(Platform::UniquePtr data) { - // Validate that input data size matches the expected one. - VerifyOrReturn(length == sizeof(wifi_status)); - CHIP_ERROR err = SystemLayer().ScheduleLambda([capturedData = data.get()] { Platform::UniquePtr safePtr(capturedData); - uint8_t * rawData = safePtr.get(); - const wifi_status * status = reinterpret_cast(rawData); - ScanDoneStatus scanDoneStatus = status->status; + uint8_t * rawData = safePtr.get(); + const wifi_status * status = reinterpret_cast(rawData); + WiFiRequestStatus requestStatus = static_cast(status->status); + + /* Reset the specific network to scan */ + if (Instance().mNetworkToScan.GetSsidSpan().size() > 0) + { + Instance().mNetworkToScan.Erase(); + } - if (scanDoneStatus) + if (requestStatus == WiFiRequestStatus::FAILURE) { - ChipLogError(DeviceLayer, "Wi-Fi scan finalization failure (%d)", scanDoneStatus); + ChipLogError(DeviceLayer, "Wi-Fi scan finalization failure (%d)", status->status); } else { - ChipLogProgress(DeviceLayer, "Wi-Fi scan done"); + ChipLogProgress(DeviceLayer, "Wi-Fi scan done (%d)", status->status); } if (Instance().mScanDoneCallback && !Instance().mInternalScan) { - Instance().mScanDoneCallback(scanDoneStatus); + Instance().mScanDoneCallback(requestStatus); // restore the connection state from before the scan request was issued Instance().mWiFiState = Instance().mCachedWiFiState; return; @@ -408,7 +415,6 @@ void WiFiManager::ScanDoneHandler(Platform::UniquePtr data, size_t leng // Internal scan is supposed to be followed by a connection request if the SSID has been found if (Instance().mInternalScan) { - if (!Instance().mSsidFound) { ChipLogProgress(DeviceLayer, "No requested SSID found"); @@ -423,13 +429,12 @@ void WiFiManager::ScanDoneHandler(Platform::UniquePtr data, size_t leng net_if * iface = InetUtils::GetInterface(); VerifyOrReturn(nullptr != iface, CHIP_ERROR_INTERNAL); - if (net_mgmt(NET_REQUEST_WIFI_CONNECT, Instance().mNetIf, &(Instance().mWiFiParams.mParams), - sizeof(wifi_connect_req_params))) + if (net_mgmt(NET_REQUEST_WIFI_CONNECT, iface, &(Instance().mWiFiParams.mParams), sizeof(wifi_connect_req_params))) { ChipLogError(DeviceLayer, "Connection request failed"); - if (Instance().mHandling.mOnConnectionDone) + if (Instance().mHandling.mOnConnectionFailed) { - Instance().mHandling.mOnConnectionDone(WIFI_STATUS_CONN_FAIL); + Instance().mHandling.mOnConnectionFailed(); } Instance().mWiFiState = WIFI_STATE_DISCONNECTED; return; @@ -449,65 +454,38 @@ void WiFiManager::ScanDoneHandler(Platform::UniquePtr data, size_t leng void WiFiManager::SendRouterSolicitation(System::Layer * layer, void * param) { - net_if_start_rs(Instance().mNetIf); - Instance().mRouterSolicitationCounter++; - if (Instance().mRouterSolicitationCounter < kRouterSolicitationMaxCount) + net_if * iface = InetUtils::GetInterface(); + if (iface && iface->if_dev->link_addr.type == NET_LINK_ETHERNET) { - DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(kRouterSolicitationIntervalMs), SendRouterSolicitation, - nullptr); - } - else - { - Instance().mRouterSolicitationCounter = 0; + net_if_start_rs(iface); + Instance().mRouterSolicitationCounter++; + if (Instance().mRouterSolicitationCounter < kRouterSolicitationMaxCount) + { + DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(kRouterSolicitationIntervalMs), + SendRouterSolicitation, nullptr); + } + else + { + Instance().mRouterSolicitationCounter = 0; + } } } -void WiFiManager::ConnectHandler(Platform::UniquePtr data, size_t length) +void WiFiManager::ConnectHandler(Platform::UniquePtr data) { - using app::Clusters::WiFiNetworkDiagnostics::AssociationFailureCauseEnum; - - // Validate that input data size matches the expected one. - VerifyOrReturn(length == sizeof(wifi_status)); - CHIP_ERROR err = SystemLayer().ScheduleLambda([capturedData = data.get()] { Platform::UniquePtr safePtr(capturedData); - uint8_t * rawData = safePtr.get(); - const wifi_status * status = reinterpret_cast(rawData); - wifi_conn_status connStatus = status->conn_status; + uint8_t * rawData = safePtr.get(); + const wifi_status * status = reinterpret_cast(rawData); + WiFiRequestStatus requestStatus = static_cast(status->status); - if (connStatus) + if (requestStatus == WiFiRequestStatus::FAILURE || requestStatus == WiFiRequestStatus::TERMINATED) { ChipLogProgress(DeviceLayer, "Connection to WiFi network failed or was terminated by another request"); Instance().mWiFiState = WIFI_STATE_DISCONNECTED; - if (Instance().mHandling.mOnConnectionDone) - { - Instance().mHandling.mOnConnectionDone(connStatus); - } - - WiFiDiagnosticsDelegate * delegate = GetDiagnosticDataProvider().GetWiFiDiagnosticsDelegate(); - if (delegate) + if (Instance().mHandling.mOnConnectionFailed) { - uint16_t reason = Instance().GetLastDisconnectReason(); - uint8_t associationFailureCause; - - switch (connStatus) - { - case WIFI_STATUS_CONN_WRONG_PASSWORD: - associationFailureCause = to_underlying(AssociationFailureCauseEnum::kAuthenticationFailed); - break; - case WIFI_STATUS_CONN_FAIL: - case WIFI_STATUS_CONN_TIMEOUT: - associationFailureCause = to_underlying(AssociationFailureCauseEnum::kAssociationFailed); - break; - case WIFI_STATUS_CONN_AP_NOT_FOUND: - associationFailureCause = to_underlying(AssociationFailureCauseEnum::kSsidNotFound); - break; - default: - associationFailureCause = to_underlying(AssociationFailureCauseEnum::kUnknown); - break; - } - - delegate->OnAssociationFailureDetected(associationFailureCause, reason); + Instance().mHandling.mOnConnectionFailed(); } } else // The connection has been established successfully. @@ -519,9 +497,9 @@ void WiFiManager::ConnectHandler(Platform::UniquePtr data, size_t lengt ChipLogProgress(DeviceLayer, "Connected to WiFi network"); Instance().mWiFiState = WIFI_STATE_COMPLETED; - if (Instance().mHandling.mOnConnectionDone) + if (Instance().mHandling.mOnConnectionSuccess) { - Instance().mHandling.mOnConnectionDone(connStatus); + Instance().mHandling.mOnConnectionSuccess(); } Instance().PostConnectivityStatusChange(kConnectivity_Established); @@ -534,13 +512,6 @@ void WiFiManager::ConnectHandler(Platform::UniquePtr data, size_t lengt { ChipLogError(DeviceLayer, "Cannot post event [error: %s]", ErrorStr(error)); } - - WiFiDiagnosticsDelegate * delegate = GetDiagnosticDataProvider().GetWiFiDiagnosticsDelegate(); - if (delegate) - { - delegate->OnConnectionStatusChanged( - to_underlying(app::Clusters::WiFiNetworkDiagnostics::ConnectionStatusEnum::kConnected)); - } } // cleanup the provisioning data as it is configured per each connect request Instance().ClearStationProvisioningData(); @@ -553,74 +524,13 @@ void WiFiManager::ConnectHandler(Platform::UniquePtr data, size_t lengt } } -void WiFiManager::DisconnectHandler(Platform::UniquePtr data, size_t length) +void WiFiManager::DisconnectHandler(Platform::UniquePtr) { - // Validate that input data size matches the expected one. - VerifyOrReturn(length == sizeof(wifi_status)); - - CHIP_ERROR err = SystemLayer().ScheduleLambda([capturedData = data.get()] { - Platform::UniquePtr safePtr(capturedData); - uint8_t * rawData = safePtr.get(); - const wifi_status * status = reinterpret_cast(rawData); - uint16_t reason; - - switch (status->disconn_reason) - { - case WIFI_REASON_DISCONN_UNSPECIFIED: - reason = WLAN_REASON_UNSPECIFIED; - break; - case WIFI_REASON_DISCONN_USER_REQUEST: - reason = WLAN_REASON_DEAUTH_LEAVING; - break; - case WIFI_REASON_DISCONN_AP_LEAVING: - reason = WLAN_REASON_DEAUTH_LEAVING; - break; - case WIFI_REASON_DISCONN_INACTIVITY: - reason = WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY; - break; - default: - reason = WLAN_REASON_UNSPECIFIED; - break; - } - Instance().SetLastDisconnectReason(reason); - + SystemLayer().ScheduleLambda([] { ChipLogProgress(DeviceLayer, "WiFi station disconnected"); Instance().mWiFiState = WIFI_STATE_DISCONNECTED; Instance().PostConnectivityStatusChange(kConnectivity_Lost); - - WiFiDiagnosticsDelegate * delegate = GetDiagnosticDataProvider().GetWiFiDiagnosticsDelegate(); - if (delegate) - { - delegate->OnConnectionStatusChanged( - to_underlying(app::Clusters::WiFiNetworkDiagnostics::ConnectionStatusEnum::kNotConnected)); - delegate->OnDisconnectionDetected(reason); - } }); - - if (CHIP_NO_ERROR == err) - { - // the ownership has been transferred to the worker thread - release the buffer - data.release(); - } -} - -void WiFiManager::IPv6AddressChangeHandler(const void * data) -{ - const in6_addr * addr = reinterpret_cast(data); - - // Filter out link-local addresses that are not routable outside of a local network. - if (!net_ipv6_is_ll_addr(addr)) - { - // This is needed to send mDNS queries containing updated IPv6 addresses. - ChipDeviceEvent event; - event.Type = DeviceEventType::kDnssdRestartNeeded; - - CHIP_ERROR error = PlatformMgr().PostEvent(&event); - if (error != CHIP_NO_ERROR) - { - ChipLogError(DeviceLayer, "Cannot post event: %" CHIP_ERROR_FORMAT, error.Format()); - } - } } WiFiManager::StationStatus WiFiManager::GetStationStatus() const @@ -686,10 +596,11 @@ System::Clock::Milliseconds32 WiFiManager::CalculateNextRecoveryTime() CHIP_ERROR WiFiManager::SetLowPowerMode(bool onoff) { - VerifyOrReturnError(nullptr != mNetIf, CHIP_ERROR_INTERNAL); + net_if * iface = InetUtils::GetInterface(); + VerifyOrReturnError(nullptr != iface, CHIP_ERROR_INTERNAL); wifi_ps_config currentConfig{}; - if (net_mgmt(NET_REQUEST_WIFI_PS_CONFIG, mNetIf, ¤tConfig, sizeof(currentConfig))) + if (net_mgmt(NET_REQUEST_WIFI_PS_CONFIG, iface, ¤tConfig, sizeof(currentConfig))) { ChipLogError(DeviceLayer, "Get current low power mode config request failed"); return CHIP_ERROR_INTERNAL; @@ -699,7 +610,7 @@ CHIP_ERROR WiFiManager::SetLowPowerMode(bool onoff) (currentConfig.ps_params.enabled == WIFI_PS_DISABLED && onoff == true)) { wifi_ps_params params{ .enabled = onoff ? WIFI_PS_ENABLED : WIFI_PS_DISABLED }; - if (net_mgmt(NET_REQUEST_WIFI_PS, mNetIf, ¶ms, sizeof(params))) + if (net_mgmt(NET_REQUEST_WIFI_PS, iface, ¶ms, sizeof(params))) { ChipLogError(DeviceLayer, "Set low power mode request failed"); return CHIP_ERROR_INTERNAL; @@ -712,15 +623,5 @@ CHIP_ERROR WiFiManager::SetLowPowerMode(bool onoff) return CHIP_NO_ERROR; } -void WiFiManager::SetLastDisconnectReason(uint16_t reason) -{ - mLastDisconnectedReason = reason; -} - -uint16_t WiFiManager::GetLastDisconnectReason() -{ - return mLastDisconnectedReason; -} - } // namespace DeviceLayer } // namespace chip diff --git a/src/platform/Zephyr/wifi/WiFiManager.h b/src/platform/Zephyr/wifi/WiFiManager.h index 99bf777547a800..d48536fb3d0da3 100644 --- a/src/platform/Zephyr/wifi/WiFiManager.h +++ b/src/platform/Zephyr/wifi/WiFiManager.h @@ -88,16 +88,16 @@ class Map class WiFiManager { public: - /* No copy, nor move. */ - WiFiManager(const WiFiManager &) = delete; - WiFiManager & operator=(const WiFiManager &) = delete; - WiFiManager(WiFiManager &&) = delete; - WiFiManager & operator=(WiFiManager &&) = delete; + enum WiFiRequestStatus : int + { + SUCCESS = 0, + FAILURE = 1, + TERMINATED = 2 + }; - using ScanDoneStatus = decltype(wifi_status::status); using ScanResultCallback = void (*)(const NetworkCommissioning::WiFiScanResponse &); - using ScanDoneCallback = void (*)(const ScanDoneStatus &); - using ConnectionCallback = void (*)(const wifi_conn_status &); + using ScanDoneCallback = void (*)(WiFiRequestStatus); + using ConnectionCallback = void (*)(); enum class StationStatus : uint8_t { @@ -120,7 +120,8 @@ class WiFiManager struct ConnectionHandling { - ConnectionCallback mOnConnectionDone{}; + ConnectionCallback mOnConnectionSuccess{}; + ConnectionCallback mOnConnectionFailed{}; System::Clock::Seconds32 mConnectionTimeout{}; }; @@ -181,18 +182,12 @@ class WiFiManager CHIP_ERROR ClearStationProvisioningData(); CHIP_ERROR Disconnect(); CHIP_ERROR GetWiFiInfo(WiFiInfo & info) const; - const WiFiNetwork & GetWantedNetwork() const { return mWantedNetwork; } CHIP_ERROR GetNetworkStatistics(NetworkStatistics & stats) const; void AbortConnectionRecovery(); CHIP_ERROR SetLowPowerMode(bool onoff); - void SetLastDisconnectReason(uint16_t reason); - uint16_t GetLastDisconnectReason(); private: - using NetEventHandler = void (*)(Platform::UniquePtr, size_t); - - WiFiManager() = default; - ~WiFiManager() = default; + using NetEventHandler = void (*)(Platform::UniquePtr); struct ConnectionParams { @@ -203,18 +198,14 @@ class WiFiManager constexpr static uint32_t kWifiManagementEvents = NET_EVENT_WIFI_SCAN_RESULT | NET_EVENT_WIFI_SCAN_DONE | NET_EVENT_WIFI_CONNECT_RESULT | NET_EVENT_WIFI_DISCONNECT_RESULT | NET_EVENT_WIFI_IFACE_STATUS; - constexpr static uint32_t kIPv6ManagementEvents = NET_EVENT_IPV6_ADDR_ADD | NET_EVENT_IPV6_ADDR_DEL; - // Event handling static void WifiMgmtEventHandler(net_mgmt_event_callback * cb, uint32_t mgmtEvent, net_if * iface); - static void IPv6MgmtEventHandler(net_mgmt_event_callback * cb, uint32_t mgmtEvent, net_if * iface); - static void ScanResultHandler(Platform::UniquePtr data, size_t length); - static void ScanDoneHandler(Platform::UniquePtr data, size_t length); - static void ConnectHandler(Platform::UniquePtr data, size_t length); - static void DisconnectHandler(Platform::UniquePtr data, size_t length); + static void ScanResultHandler(Platform::UniquePtr data); + static void ScanDoneHandler(Platform::UniquePtr data); + static void ConnectHandler(Platform::UniquePtr data); + static void DisconnectHandler(Platform::UniquePtr data); static void PostConnectivityStatusChange(ConnectivityChange changeType); static void SendRouterSolicitation(System::Layer * layer, void * param); - static void IPv6AddressChangeHandler(const void * data); // Connection Recovery feature // This feature allows re-scanning and re-connecting the connection to the known network after @@ -229,25 +220,21 @@ class WiFiManager void ResetRecoveryTime(); System::Clock::Milliseconds32 CalculateNextRecoveryTime(); - net_if * mNetIf{ nullptr }; ConnectionParams mWiFiParams{}; - ConnectionHandling mHandling{}; - wifi_scan_params mScanParams{}; - char mScanSsidBuffer[DeviceLayer::Internal::kMaxWiFiSSIDLength + 1] = { 0 }; + ConnectionHandling mHandling; wifi_iface_state mWiFiState; wifi_iface_state mCachedWiFiState; net_mgmt_event_callback mWiFiMgmtClbk{}; - net_mgmt_event_callback mIPv6MgmtClbk{}; ScanResultCallback mScanResultCallback{ nullptr }; ScanDoneCallback mScanDoneCallback{ nullptr }; WiFiNetwork mWantedNetwork{}; + WiFiNetwork mNetworkToScan{}; bool mInternalScan{ false }; uint8_t mRouterSolicitationCounter = 0; bool mSsidFound{ false }; uint32_t mConnectionRecoveryCounter{ 0 }; uint32_t mConnectionRecoveryTimeMs{ kConnectionRecoveryMinIntervalMs }; bool mApplicationDisconnectRequested{ false }; - uint16_t mLastDisconnectedReason = WLAN_REASON_UNSPECIFIED; static const Map sStatusMap; static const Map sEventHandlerMap; diff --git a/src/platform/Zephyr/wifi/ZephyrWifiDriver.cpp b/src/platform/Zephyr/wifi/ZephyrWifiDriver.cpp index 7404a0272297be..53b7fa684a2213 100644 --- a/src/platform/Zephyr/wifi/ZephyrWifiDriver.cpp +++ b/src/platform/Zephyr/wifi/ZephyrWifiDriver.cpp @@ -17,13 +17,10 @@ #include "ZephyrWifiDriver.h" -#include - #include #include #include -#include #include using namespace ::chip; @@ -106,9 +103,8 @@ CHIP_ERROR ZephyrWifiDriver::Init(NetworkStatusChangeCallback * networkStatusCha if (mStagingNetwork.IsConfigured()) { - WiFiManager::ConnectionHandling handling{ [](const wifi_conn_status & connStatus) { - Instance().OnNetworkConnStatusChanged(connStatus); - }, + WiFiManager::ConnectionHandling handling{ [] { Instance().OnNetworkStatusChanged(Status::kSuccess); }, + [] { Instance().OnNetworkStatusChanged(Status::kUnknownError); }, System::Clock::Seconds32{ kWiFiConnectNetworkTimeoutSeconds } }; ReturnErrorOnFailure( WiFiManager::Instance().Connect(mStagingNetwork.GetSsidSpan(), mStagingNetwork.GetPassSpan(), handling)); @@ -117,11 +113,8 @@ CHIP_ERROR ZephyrWifiDriver::Init(NetworkStatusChangeCallback * networkStatusCha return CHIP_NO_ERROR; } -void ZephyrWifiDriver::OnNetworkConnStatusChanged(const wifi_conn_status & connStatus) +void ZephyrWifiDriver::OnNetworkStatusChanged(Status status) { - // TODO: check if we can report more accurate errors - Status status = connStatus ? Status::kUnknownError : Status::kSuccess; - if (status == Status::kSuccess) { ConnectivityMgr().SetWiFiStationMode(ConnectivityManager::kWiFiStationMode_Enabled); @@ -129,23 +122,7 @@ void ZephyrWifiDriver::OnNetworkConnStatusChanged(const wifi_conn_status & connS if (mpNetworkStatusChangeCallback) { - const uint8_t * ssid{}; - size_t ssidLen{}; - WiFiManager::WiFiInfo wifiInfo; - - if (CHIP_NO_ERROR == WiFiManager::Instance().GetWiFiInfo(wifiInfo)) - { - ssid = wifiInfo.mSsid; - ssidLen = wifiInfo.mSsidLen; - } - else - { - ssid = WiFiManager::Instance().GetWantedNetwork().ssid; - ssidLen = WiFiManager::Instance().GetWantedNetwork().ssidLen; - } - mpNetworkStatusChangeCallback->OnNetworkingStatusChange(status, MakeOptional(ByteSpan(ssid, ssidLen)), - connStatus ? MakeOptional(static_cast(connStatus)) - : NullOptional); + mpNetworkStatusChangeCallback->OnNetworkingStatusChange(status, NullOptional, NullOptional); } if (mpConnectCallback) @@ -181,15 +158,12 @@ CHIP_ERROR ZephyrWifiDriver::RevertConfiguration() // we are already connected to this network, so return prematurely return CHIP_NO_ERROR; } - - WiFiManager::Instance().Disconnect(); } if (mStagingNetwork.IsConfigured()) { - WiFiManager::ConnectionHandling handling{ [](const wifi_conn_status & connStatus) { - Instance().OnNetworkConnStatusChanged(connStatus); - }, + WiFiManager::ConnectionHandling handling{ [] { Instance().OnNetworkStatusChanged(Status::kSuccess); }, + [] { Instance().OnNetworkStatusChanged(Status::kUnknownError); }, System::Clock::Seconds32{ kWiFiConnectNetworkTimeoutSeconds } }; ReturnErrorOnFailure( WiFiManager::Instance().Connect(mStagingNetwork.GetSsidSpan(), mStagingNetwork.GetPassSpan(), handling)); @@ -243,9 +217,8 @@ void ZephyrWifiDriver::ConnectNetwork(ByteSpan networkId, ConnectCallback * call { Status status = Status::kSuccess; WiFiManager::StationStatus stationStatus; - WiFiManager::ConnectionHandling handling{ [](const wifi_conn_status & connStatus) { - Instance().OnNetworkConnStatusChanged(connStatus); - }, + WiFiManager::ConnectionHandling handling{ [] { Instance().OnNetworkStatusChanged(Status::kSuccess); }, + [] { Instance().OnNetworkStatusChanged(Status::kUnknownError); }, System::Clock::Seconds32{ kWiFiConnectNetworkTimeoutSeconds } }; VerifyOrExit(mpConnectCallback == nullptr, status = Status::kUnknownError); @@ -289,10 +262,11 @@ void ZephyrWifiDriver::LoadFromStorage() mStagingNetwork = network; } -void ZephyrWifiDriver::OnScanWiFiNetworkDone(const WiFiManager::ScanDoneStatus & status) +void ZephyrWifiDriver::OnScanWiFiNetworkDone(WiFiManager::WiFiRequestStatus status) { VerifyOrReturn(mScanCallback != nullptr); - mScanCallback->OnFinished(status ? Status::kUnknownError : Status::kSuccess, CharSpan(), &mScanResponseIterator); + mScanCallback->OnFinished(status == WiFiManager::WiFiRequestStatus::SUCCESS ? Status::kSuccess : Status::kUnknownError, + CharSpan(), &mScanResponseIterator); mScanCallback = nullptr; } @@ -306,7 +280,7 @@ void ZephyrWifiDriver::ScanNetworks(ByteSpan ssid, WiFiDriver::ScanCallback * ca mScanCallback = callback; CHIP_ERROR error = WiFiManager::Instance().Scan( ssid, [](const WiFiScanResponse & response) { Instance().OnScanWiFiNetworkResult(response); }, - [](const WiFiManager::ScanDoneStatus & status) { Instance().OnScanWiFiNetworkDone(status); }); + [](WiFiManager::WiFiRequestStatus status) { Instance().OnScanWiFiNetworkDone(status); }); if (error != CHIP_NO_ERROR) { @@ -315,13 +289,6 @@ void ZephyrWifiDriver::ScanNetworks(ByteSpan ssid, WiFiDriver::ScanCallback * ca } } -uint32_t ZephyrWifiDriver::GetSupportedWiFiBandsMask() const -{ - uint32_t bands = static_cast(1UL << chip::to_underlying(WiFiBandEnum::k2g4)); - bands |= static_cast(1UL << chip::to_underlying(WiFiBandEnum::k5g)); - return bands; -} - } // namespace NetworkCommissioning } // namespace DeviceLayer } // namespace chip diff --git a/src/platform/Zephyr/wifi/ZephyrWifiDriver.h b/src/platform/Zephyr/wifi/ZephyrWifiDriver.h index 414311a07ec4bf..9096aa408b69bd 100644 --- a/src/platform/Zephyr/wifi/ZephyrWifiDriver.h +++ b/src/platform/Zephyr/wifi/ZephyrWifiDriver.h @@ -25,9 +25,9 @@ namespace chip { namespace DeviceLayer { namespace NetworkCommissioning { -inline constexpr uint8_t kMaxWiFiNetworks = 1; -inline constexpr uint8_t kWiFiScanNetworksTimeOutSeconds = 10; -inline constexpr uint8_t kWiFiConnectNetworkTimeoutSeconds = 35; +constexpr uint8_t kMaxWiFiNetworks = 1; +constexpr uint8_t kWiFiScanNetworksTimeOutSeconds = 10; +constexpr uint8_t kWiFiConnectNetworkTimeoutSeconds = 35; class ZephyrWifiScanResponseIterator : public Iterator { @@ -48,8 +48,8 @@ class ZephyrWifiDriver final : public WiFiDriver public: // Define non-volatile storage keys for SSID and password. // The naming convention is aligned with DefaultStorageKeyAllocator class. - static constexpr char kSsidKey[] = "g/wi/s"; - static constexpr char kPassKey[] = "g/wi/p"; + static constexpr const char * kSsidKey = "g/wi/s"; + static constexpr const char * kPassKey = "g/wi/p"; class WiFiNetworkIterator final : public NetworkIterator { @@ -86,7 +86,6 @@ class ZephyrWifiDriver final : public WiFiDriver Status AddOrUpdateNetwork(ByteSpan ssid, ByteSpan credentials, MutableCharSpan & outDebugText, uint8_t & outNetworkIndex) override; void ScanNetworks(ByteSpan ssid, ScanCallback * callback) override; - uint32_t GetSupportedWiFiBandsMask() const override; static ZephyrWifiDriver & Instance() { @@ -94,9 +93,9 @@ class ZephyrWifiDriver final : public WiFiDriver return sInstance; } - void OnNetworkConnStatusChanged(const wifi_conn_status & connStatus); + void OnNetworkStatusChanged(Status status); void OnScanWiFiNetworkResult(const WiFiScanResponse & result); - void OnScanWiFiNetworkDone(const WiFiManager::ScanDoneStatus & status); + void OnScanWiFiNetworkDone(WiFiManager::WiFiRequestStatus status); private: void LoadFromStorage(); diff --git a/src/platform/nxp/zephyr/ConnectivityManagerImpl.cpp b/src/platform/nxp/zephyr/ConnectivityManagerImpl.cpp index 7025c33348d5c7..e47ee681a490d7 100644 --- a/src/platform/nxp/zephyr/ConnectivityManagerImpl.cpp +++ b/src/platform/nxp/zephyr/ConnectivityManagerImpl.cpp @@ -17,16 +17,11 @@ #include -#include -#include -#include #include -#include #include -#ifndef CONFIG_ARCH_POSIX -#include -#endif +#include +#include #include @@ -39,64 +34,15 @@ #endif #if CHIP_DEVICE_CONFIG_ENABLE_THREAD -#include #include #endif -using namespace ::chip::Inet; +using namespace ::chip; using namespace ::chip::DeviceLayer::Internal; namespace chip { namespace DeviceLayer { -namespace { -CHIP_ERROR JoinLeaveMulticastGroup(net_if * iface, const Inet::IPAddress & address, - UDPEndPointImplSockets::MulticastOperation operation) -{ -#if CHIP_DEVICE_CONFIG_ENABLE_THREAD - if (net_if_l2(iface) == &NET_L2_GET_NAME(OPENTHREAD)) - { - const otIp6Address otAddress = ToOpenThreadIP6Address(address); - const auto handler = operation == UDPEndPointImplSockets::MulticastOperation::kJoin ? otIp6SubscribeMulticastAddress - : otIp6UnsubscribeMulticastAddress; - otError error; - - ThreadStackMgr().LockThreadStack(); - error = handler(openthread_get_default_instance(), &otAddress); - ThreadStackMgr().UnlockThreadStack(); - - return MapOpenThreadError(error); - } -#endif - -#if CHIP_DEVICE_CONFIG_ENABLE_WIFI - // The following code should also be valid for other interface types, such as Ethernet, - // but they are not officially supported, so for now enable it for Wi-Fi only. - const in6_addr in6Addr = InetUtils::ToZephyrAddr(address); - - if (operation == UDPEndPointImplSockets::MulticastOperation::kJoin) - { - net_if_mcast_addr * maddr = net_if_ipv6_maddr_add(iface, &in6Addr); - - if (maddr && !net_if_ipv6_maddr_is_joined(maddr)) - { - net_if_ipv6_maddr_join(iface, maddr); - } - } - else if (operation == UDPEndPointImplSockets::MulticastOperation::kLeave) - { - VerifyOrReturnError(net_if_ipv6_maddr_rm(iface, &in6Addr), CHIP_ERROR_INVALID_ADDRESS); - } - else - { - return CHIP_ERROR_INCORRECT_STATE; - } -#endif - - return CHIP_NO_ERROR; -} -} // namespace - ConnectivityManagerImpl ConnectivityManagerImpl::sInstance; CHIP_ERROR ConnectivityManagerImpl::_Init() @@ -110,28 +56,6 @@ CHIP_ERROR ConnectivityManagerImpl::_Init() #elif CHIP_DEVICE_CONFIG_ENABLE_ETHERNET ReturnErrorOnFailure(InitEth()); #endif - -#if CHIP_DEVICE_CONFIG_ENABLE_THREAD || CHIP_DEVICE_CONFIG_ENABLE_WIFI - UDPEndPointImplSockets::SetMulticastGroupHandler( - [](InterfaceId interfaceId, const IPAddress & address, UDPEndPointImplSockets::MulticastOperation operation) { - if (interfaceId.IsPresent()) - { - net_if * iface = InetUtils::GetInterface(interfaceId); - VerifyOrReturnError(iface != nullptr, INET_ERROR_UNKNOWN_INTERFACE); - - return JoinLeaveMulticastGroup(iface, address, operation); - } - - // If the interface is not specified, join or leave the multicast group on all interfaces. - for (int i = 1; net_if * iface = net_if_get_by_index(i); i++) - { - ReturnErrorOnFailure(JoinLeaveMulticastGroup(iface, address, operation)); - } - - return CHIP_NO_ERROR; - }); -#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD || CHIP_DEVICE_CONFIG_ENABLE_WIFI - return CHIP_NO_ERROR; }