diff --git a/.github/workflows/examples-nrfconnect.yaml b/.github/workflows/examples-nrfconnect.yaml index 0ae8124f5a0cee..4f0efb889359c8 100644 --- a/.github/workflows/examples-nrfconnect.yaml +++ b/.github/workflows/examples-nrfconnect.yaml @@ -38,7 +38,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: connectedhomeip/chip-build-nrf-platform:0.6.44 + image: connectedhomeip/chip-build-nrf-platform:0.6.47 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" diff --git a/config/nrfconnect/.nrfconnect-recommended-revision b/config/nrfconnect/.nrfconnect-recommended-revision index a4b6ac3ded6d12..b1d18bc43f08ca 100644 --- a/config/nrfconnect/.nrfconnect-recommended-revision +++ b/config/nrfconnect/.nrfconnect-recommended-revision @@ -1 +1 @@ -v2.2.0 +v2.3.0 diff --git a/config/nrfconnect/chip-module/CMakeLists.txt b/config/nrfconnect/chip-module/CMakeLists.txt index c48d18c13bee02..4ef9feb7de4c26 100644 --- a/config/nrfconnect/chip-module/CMakeLists.txt +++ b/config/nrfconnect/chip-module/CMakeLists.txt @@ -114,6 +114,9 @@ if (CONFIG_NORDIC_SECURITY_BACKEND) zephyr_include_directories($) endif() list(APPEND CHIP_CFLAGS -DMBEDTLS_CONFIG_FILE=) +elseif(CONFIG_MBEDTLS) + zephyr_include_directories($) + zephyr_compile_definitions($) endif() if (CONFIG_NRF_802154_RADIO_DRIVER) diff --git a/config/nrfconnect/chip-module/Kconfig b/config/nrfconnect/chip-module/Kconfig index b0ab15b75a9f4e..390a99b1556e77 100644 --- a/config/nrfconnect/chip-module/Kconfig +++ b/config/nrfconnect/chip-module/Kconfig @@ -88,6 +88,9 @@ config CHIP_DEBUG_SYMBOLS help Enables building the application with debug symbols. +config CHIP_MALLOC_SYS_HEAP + default y if !ARCH_POSIX + config CHIP_FACTORY_DATA bool "Factory data provider" select ZCBOR diff --git a/config/nrfconnect/chip-module/Kconfig.defaults b/config/nrfconnect/chip-module/Kconfig.defaults index a2a26ca591bed9..bf7b494e7050d5 100644 --- a/config/nrfconnect/chip-module/Kconfig.defaults +++ b/config/nrfconnect/chip-module/Kconfig.defaults @@ -161,6 +161,11 @@ config BT_DEVICE_NAME_GATT_WRITABLE config CHIP_NFC_COMMISSIONING default y +# Disable not needed NFC callback to save flash +config NFC_THREAD_CALLBACK + bool + default n + config CHIP_OTA_REQUESTOR default y @@ -230,6 +235,9 @@ config NET_IF_MCAST_IPV6_ADDR_COUNT config NET_SOCKETS_POSIX_NAMES default n +config NET_SOCKETS_POLL_MAX + default 4 + config MBEDTLS_SSL_OUT_CONTENT_LEN default 900 @@ -247,6 +255,9 @@ config SHELL_STACK_SIZE config HEAP_MEM_POOL_SIZE default 200000 +config CHIP_MALLOC_SYS_HEAP_SIZE + default 28672 # 28 kB + endif @@ -368,6 +379,18 @@ config PSA_WANT_ALG_OFB # Disable not used shell modules +config SHELL_WILDCARD + default n + +config SHELL_VT100_COLORS + default n + +config SHELL_STATS + default n + +config KERNEL_SHELL + default n + config SENSOR_SHELL default n @@ -389,6 +412,18 @@ config CLOCK_CONTROL_NRF_SHELL config FLASH_SHELL default n +if MPSL_FEM + +config MPSL_FEM_NRF21540_RUNTIME_PA_GAIN_CONTROL + default y + +endif # MPSL_FEM + +config OPENTHREAD_DEFAULT_TX_POWER + default 20 if MPSL_FEM + default 3 if SOC_SERIES_NRF53X && !MPSL_FEM + default 8 if SOC_SERIES_NRF52X && !MPSL_FEM + # SoC series related configuration if SOC_SERIES_NRF52X diff --git a/config/nrfconnect/chip-module/Kconfig.features b/config/nrfconnect/chip-module/Kconfig.features index 1a1bf027267601..99d13e9d56aa59 100644 --- a/config/nrfconnect/chip-module/Kconfig.features +++ b/config/nrfconnect/chip-module/Kconfig.features @@ -98,6 +98,18 @@ config MCUMGR_SMP_BT_AUTHEN config MCUMGR_BUF_COUNT default 6 +config MCUMGR_MGMT_NOTIFICATION_HOOKS + bool + default y + +config MCUMGR_GRP_IMG_UPLOAD_CHECK_HOOK + bool + default y + +config MCUMGR_SMP_COMMAND_STATUS_HOOKS + bool + default y + # Increase BT MTU and RX buffer for big size DFU messages config BT_L2CAP_TX_MTU default 498 @@ -126,4 +138,37 @@ endif # SOC_SERIES_NRF53X endif # CHIP_DFU_OVER_BT_SMP +config CHIP_WIFI_CONNECTION_RECOVERY_MINIMUM_INTERVAL + int "Define the minimum connection recovery time interval in milliseconds" + depends on CHIP_WIFI + default 500 + help + Specifies the minimum connection recovery interval (in milliseconds). + +config CHIP_WIFI_CONNECTION_RECOVERY_MAXIMUM_INTERVAL + int "Define the maximum connection recovery time interval in milliseconds" + depends on CHIP_WIFI + default 3600000 # 1 hour + help + Specifies the maximum connection recovery interval (in milliseconds). + +config CHIP_WIFI_CONNECTION_RECOVERY_MAX_RETRIES_NUMBER + int "Define the maximum amount of connection recovery occurrences" + depends on CHIP_WIFI + default 0 + help + Specifies the maximum number of connection recovery attempts. + If set to 0, no limitation is applied and attempts + to recover the connection are performed indefinitely. + +config CHIP_WIFI_CONNECTION_RECOVERY_JITTER + int "Define the connection recovery jitter in milliseconds" + depends on CHIP_WIFI + default 2000 + help + Specifies the maximum connection recovery jitter interval (in milliseconds). + Once the wait time reaches the current maximum value (defined by CHIP_WIFI_CONNECTION_RECOVERY_MAXIMUM_INTERVAL), + a random jitter interval is added to it to avoid periodicity. The random jitter is selected + within range [-JITTER; +JITTER]. + endif # CHIP diff --git a/config/nrfconnect/chip-module/Kconfig.hci_rpmsg.defaults b/config/nrfconnect/chip-module/Kconfig.hci_rpmsg.defaults index 173766a44941c1..83290b2b492f28 100644 --- a/config/nrfconnect/chip-module/Kconfig.hci_rpmsg.defaults +++ b/config/nrfconnect/chip-module/Kconfig.hci_rpmsg.defaults @@ -63,10 +63,6 @@ config BT_HCI_RAW_RESERVE config BT_BUF_CMD_TX_COUNT default 10 -# Enable support for Wi-Fi and Bluetooth LE coexistance -config MPSL_CX - default y - config ASSERT default y diff --git a/config/nrfconnect/chip-module/make_gn_args.py b/config/nrfconnect/chip-module/make_gn_args.py index f30cd459a6e7d4..3c3f611c00b437 100755 --- a/config/nrfconnect/chip-module/make_gn_args.py +++ b/config/nrfconnect/chip-module/make_gn_args.py @@ -29,7 +29,11 @@ '-fno-reorder-functions', '-ffunction-sections', '-fdata-sections', - '-g*', + '-g', + '-g0', + '-g1', + '-g2', + '-g3', '-O*', '-W*', ] diff --git a/config/zephyr/Kconfig b/config/zephyr/Kconfig index 54717d7e3b80ca..b1edad054824c7 100644 --- a/config/zephyr/Kconfig +++ b/config/zephyr/Kconfig @@ -394,7 +394,7 @@ config CHIP_MALLOC_SYS_HEAP_OVERRIDE config CHIP_MALLOC_SYS_HEAP_SIZE int "Heap size used by memory allocator based on Zephyr sys_heap" - default 16384 # 16kB + default 12288 # 12kB help Provides a value that controls how much of the device RAM is reserved for the heap used by the memory allocation functions based on sys_heap from diff --git a/examples/all-clusters-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay b/examples/all-clusters-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay index 3fa8dace395131..86568566378149 100644 --- a/examples/all-clusters-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ b/examples/all-clusters-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -14,18 +14,12 @@ * limitations under the License. */ -#include - / { chosen { nordic,pm-ext-flash = &mx25r64; }; }; -&ipc0 { - zephyr,priority = <0 PRIO_COOP>; -}; - /* Disable unused peripherals to reduce power consumption */ &adc { status = "disabled"; diff --git a/examples/all-clusters-minimal-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay b/examples/all-clusters-minimal-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay index 3fa8dace395131..86568566378149 100644 --- a/examples/all-clusters-minimal-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ b/examples/all-clusters-minimal-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -14,18 +14,12 @@ * limitations under the License. */ -#include - / { chosen { nordic,pm-ext-flash = &mx25r64; }; }; -&ipc0 { - zephyr,priority = <0 PRIO_COOP>; -}; - /* Disable unused peripherals to reduce power consumption */ &adc { status = "disabled"; diff --git a/examples/light-switch-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay b/examples/light-switch-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay index 6f560e36368b6c..3063fbbcdee779 100644 --- a/examples/light-switch-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ b/examples/light-switch-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -14,14 +14,8 @@ * limitations under the License. */ -#include - / { chosen { nordic,pm-ext-flash = &mx25r64; }; }; - -&ipc0 { - zephyr,priority = <0 PRIO_COOP>; -}; diff --git a/examples/lighting-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay b/examples/lighting-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay index ae489254784606..240f0aaffa190f 100644 --- a/examples/lighting-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ b/examples/lighting-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -14,8 +14,6 @@ * limitations under the License. */ -#include - / { chosen { nordic,pm-ext-flash = &mx25r64; @@ -38,10 +36,6 @@ }; }; -&ipc0 { - zephyr,priority = <0 PRIO_COOP>; -}; - &pwm0 { pinctrl-0 = <&pwm0_default_alt>; pinctrl-1 = <&pwm0_sleep_alt>; diff --git a/examples/lock-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay b/examples/lock-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay index f9fe5b0fd9a950..7042eb46be3fad 100644 --- a/examples/lock-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ b/examples/lock-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -14,18 +14,12 @@ * limitations under the License. */ -#include - / { chosen { nordic,pm-ext-flash = &mx25r64; }; }; -&ipc0 { - zephyr,priority = <0 PRIO_COOP>; -}; - /* Disable unused peripherals to reduce power consumption */ &adc { status = "disabled"; diff --git a/examples/platform/nrfconnect/util/DFUOverSMP.cpp b/examples/platform/nrfconnect/util/DFUOverSMP.cpp index b1205f12c16c3d..1720a58edb5c73 100644 --- a/examples/platform/nrfconnect/util/DFUOverSMP.cpp +++ b/examples/platform/nrfconnect/util/DFUOverSMP.cpp @@ -27,11 +27,9 @@ #include -#include -#include -#include #include -#include +#include +#include using namespace ::chip; using namespace ::chip::DeviceLayer; @@ -42,6 +40,43 @@ constexpr uint16_t kAdvertisingIntervalMin = 400; constexpr uint16_t kAdvertisingIntervalMax = 500; constexpr uint8_t kAdvertisingFlags = BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR; +namespace { +int32_t UploadConfirmHandler(uint32_t event, int32_t rc, bool * abort_more, void * data, size_t data_size) +{ + const img_mgmt_upload_check & imgData = *static_cast(data); + IgnoreUnusedVariable(imgData); + + ChipLogProgress(SoftwareUpdate, "DFU over SMP progress: %u/%u B of image %u", static_cast(imgData.req->off), + static_cast(imgData.action->size), static_cast(imgData.req->image)); + + return MGMT_ERR_EOK; +} + +int32_t CommandHandler(uint32_t event, int32_t rc, bool * abort_more, void * data, size_t data_size) +{ + if (event == MGMT_EVT_OP_CMD_RECV) + { + GetFlashHandler().DoAction(ExternalFlashManager::Action::WAKE_UP); + } + else if (event == MGMT_EVT_OP_CMD_DONE) + { + GetFlashHandler().DoAction(ExternalFlashManager::Action::SLEEP); + } + + return MGMT_ERR_EOK; +} + +mgmt_callback sUploadCallback = { + .callback = UploadConfirmHandler, + .event_id = MGMT_EVT_OP_IMG_MGMT_DFU_CHUNK, +}; + +mgmt_callback sCommandCallback = { + .callback = CommandHandler, + .event_id = (MGMT_EVT_OP_CMD_RECV | MGMT_EVT_OP_CMD_DONE), +}; +} // namespace + DFUOverSMP DFUOverSMP::sDFUOverSMP; void DFUOverSMP::Init() @@ -68,28 +103,8 @@ void DFUOverSMP::Init() } }; - os_mgmt_register_group(); - img_mgmt_register_group(); - - img_mgmt_set_upload_cb([](const img_mgmt_upload_req req, const img_mgmt_upload_action action) { - ChipLogProgress(SoftwareUpdate, "DFU over SMP progress: %u/%u B of image %u", static_cast(req.off), - static_cast(action.size), static_cast(req.image)); - return 0; - }); - - mgmt_register_evt_cb([](uint8_t opcode, uint16_t group, uint8_t id, void * arg) { - switch (opcode) - { - case MGMT_EVT_OP_CMD_RECV: - GetFlashHandler().DoAction(ExternalFlashManager::Action::WAKE_UP); - break; - case MGMT_EVT_OP_CMD_DONE: - GetFlashHandler().DoAction(ExternalFlashManager::Action::SLEEP); - break; - default: - break; - } - }); + mgmt_callback_register(&sUploadCallback); + mgmt_callback_register(&sCommandCallback); } void DFUOverSMP::ConfirmNewImage() @@ -111,7 +126,6 @@ void DFUOverSMP::ConfirmNewImage() void DFUOverSMP::StartServer() { VerifyOrReturn(!mIsStarted, ChipLogProgress(SoftwareUpdate, "DFU over SMP was already started")); - smp_bt_register(); // Synchronize access to the advertising arbiter that normally runs on the CHIP thread. PlatformMgr().LockChipStack(); diff --git a/examples/pump-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay b/examples/pump-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay index e52b2072ec1b10..ca5ebd2d034af0 100644 --- a/examples/pump-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ b/examples/pump-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -14,15 +14,8 @@ * limitations under the License. */ -#include - / { chosen { nordic,pm-ext-flash = &mx25r64; }; }; - -&ipc0 { - zephyr,priority = <0 PRIO_COOP>; -}; - diff --git a/examples/pump-controller-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay b/examples/pump-controller-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay index e52b2072ec1b10..ca5ebd2d034af0 100644 --- a/examples/pump-controller-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ b/examples/pump-controller-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -14,15 +14,8 @@ * limitations under the License. */ -#include - / { chosen { nordic,pm-ext-flash = &mx25r64; }; }; - -&ipc0 { - zephyr,priority = <0 PRIO_COOP>; -}; - diff --git a/examples/window-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay b/examples/window-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay index d80b32f787a3cc..dad630c7c9aad9 100644 --- a/examples/window-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ b/examples/window-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -14,8 +14,6 @@ * limitations under the License. */ -#include - / { chosen { nordic,pm-ext-flash = &mx25r64; @@ -41,10 +39,6 @@ }; }; -&ipc0 { - zephyr,priority = <0 PRIO_COOP>; -}; - /* Disable unused peripherals to reduce power consumption */ &adc { status = "disabled"; diff --git a/src/platform/nrfconnect/DiagnosticDataProviderImplNrf.cpp b/src/platform/nrfconnect/DiagnosticDataProviderImplNrf.cpp index af6f39631250c4..8a058207581143 100644 --- a/src/platform/nrfconnect/DiagnosticDataProviderImplNrf.cpp +++ b/src/platform/nrfconnect/DiagnosticDataProviderImplNrf.cpp @@ -57,9 +57,7 @@ DiagnosticDataProviderImplNrf::GetWiFiSecurityType(app::Clusters::WiFiNetworkDia WiFiManager::WiFiInfo info; CHIP_ERROR err = WiFiManager::Instance().GetWiFiInfo(info); - // TODO: The values here are probably wrong. See - // https://github.com/project-chip/connectedhomeip/issues/25096 - securityType = static_cast(info.mSecurityType); + securityType = info.mSecurityType; return err; } @@ -87,34 +85,52 @@ CHIP_ERROR DiagnosticDataProviderImplNrf::GetWiFiRssi(int8_t & rssi) return err; } -// below will be implemented when the WiFi driver exposes Zephyr NET_STATISTICS API CHIP_ERROR DiagnosticDataProviderImplNrf::GetWiFiBeaconLostCount(uint32_t & beaconLostCount) { - return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; + WiFiManager::NetworkStatistics stats; + CHIP_ERROR err = WiFiManager::Instance().GetNetworkStatistics(stats); + beaconLostCount = stats.mBeaconsLostCount; + return err; } CHIP_ERROR DiagnosticDataProviderImplNrf::GetWiFiBeaconRxCount(uint32_t & beaconRxCount) { - return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; + WiFiManager::NetworkStatistics stats; + CHIP_ERROR err = WiFiManager::Instance().GetNetworkStatistics(stats); + beaconRxCount = stats.mBeaconsSuccessCount; + return err; } CHIP_ERROR DiagnosticDataProviderImplNrf::GetWiFiPacketMulticastRxCount(uint32_t & packetMulticastRxCount) { - return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; + WiFiManager::NetworkStatistics stats; + CHIP_ERROR err = WiFiManager::Instance().GetNetworkStatistics(stats); + packetMulticastRxCount = stats.mPacketMulticastRxCount; + return err; } + CHIP_ERROR DiagnosticDataProviderImplNrf::GetWiFiPacketMulticastTxCount(uint32_t & packetMulticastTxCount) { - return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; + WiFiManager::NetworkStatistics stats; + CHIP_ERROR err = WiFiManager::Instance().GetNetworkStatistics(stats); + packetMulticastTxCount = stats.mPacketMulticastTxCount; + return err; } CHIP_ERROR DiagnosticDataProviderImplNrf::GetWiFiPacketUnicastRxCount(uint32_t & packetUnicastRxCount) { - return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; + WiFiManager::NetworkStatistics stats; + CHIP_ERROR err = WiFiManager::Instance().GetNetworkStatistics(stats); + packetUnicastRxCount = stats.mPacketUnicastRxCount; + return err; } CHIP_ERROR DiagnosticDataProviderImplNrf::GetWiFiPacketUnicastTxCount(uint32_t & packetUnicastTxCount) { - return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; + WiFiManager::NetworkStatistics stats; + CHIP_ERROR err = WiFiManager::Instance().GetNetworkStatistics(stats); + packetUnicastTxCount = stats.mPacketUnicastTxCount; + return err; } CHIP_ERROR DiagnosticDataProviderImplNrf::GetWiFiCurrentMaxRate(uint64_t & currentMaxRate) diff --git a/src/platform/nrfconnect/wifi/NrfWiFiDriver.cpp b/src/platform/nrfconnect/wifi/NrfWiFiDriver.cpp index bfb284f3b84851..3df9b60c2157de 100644 --- a/src/platform/nrfconnect/wifi/NrfWiFiDriver.cpp +++ b/src/platform/nrfconnect/wifi/NrfWiFiDriver.cpp @@ -147,6 +147,10 @@ CHIP_ERROR NrfWiFiDriver::CommitConfiguration() CHIP_ERROR NrfWiFiDriver::RevertConfiguration() { + // Abort Connection Recovery if it is in progress during reverting configuration. + // This is needed to stop recovery process after failsafe timer expiring. + WiFiManager::Instance().AbortConnectionRecovery(); + LoadFromStorage(); if (WiFiManager::StationStatus::CONNECTING <= WiFiManager::Instance().GetStationStatus()) @@ -222,12 +226,13 @@ void NrfWiFiDriver::ConnectNetwork(ByteSpan networkId, ConnectCallback * callbac [] { Instance().OnNetworkStatusChanged(Status::kUnknownError); }, System::Clock::Seconds32{ kWiFiConnectNetworkTimeoutSeconds } }; + VerifyOrExit(mpConnectCallback == nullptr, status = Status::kUnknownError); + mpConnectCallback = callback; + VerifyOrExit(WiFiManager::StationStatus::CONNECTING != WiFiManager::Instance().GetStationStatus(), status = Status::kOtherConnectionFailure); VerifyOrExit(networkId.data_equal(mStagingNetwork.GetSsidSpan()), status = Status::kNetworkIDNotFound); - VerifyOrExit(mpConnectCallback == nullptr, status = Status::kUnknownError); - mpConnectCallback = callback; WiFiManager::Instance().Connect(mStagingNetwork.GetSsidSpan(), mStagingNetwork.GetPassSpan(), handling); exit: diff --git a/src/platform/nrfconnect/wifi/WiFiManager.cpp b/src/platform/nrfconnect/wifi/WiFiManager.cpp index 6a4585a57723f8..272dca72b20bb9 100644 --- a/src/platform/nrfconnect/wifi/WiFiManager.cpp +++ b/src/platform/nrfconnect/wifi/WiFiManager.cpp @@ -73,6 +73,57 @@ NetworkCommissioning::WiFiScanResponse ToScanResponse(const wifi_scan_result * r return response; } +// Matter expectations towards Wi-Fi version codes are unaligned with +// what wpa_supplicant provides. This function maps supplicant codes +// to the ones defined in the Matter spec (11.14.3.2. WiFiVersion enum) +uint8_t MapToMatterWiFiVersionCode(wifi_link_mode wifiVersion) +{ + using app::Clusters::WiFiNetworkDiagnostics::WiFiVersionEnum; + + if (wifiVersion < WIFI_1 || wifiVersion > WIFI_6E) + { + ChipLogError(DeviceLayer, "Unsupported Wi-Fi version detected"); + return static_cast(WiFiVersionEnum::kA); // let's return 'a' by default + } + + switch (wifiVersion) + { + case WIFI_1: + return static_cast(WiFiVersionEnum::kB); + case WIFI_2: + return static_cast(WiFiVersionEnum::kA); + case WIFI_6E: + return static_cast(WiFiVersionEnum::kAx); // treat as 802.11ax + default: + break; + } + + return (static_cast(wifiVersion) - 1); +} + +// Matter expectations towards Wi-Fi security type codes are unaligned with +// what wpa_supplicant provides. This function maps supplicant codes +// to the ones defined in the Matter spec (11.14.3.1. SecurityType enum) +app::Clusters::WiFiNetworkDiagnostics::SecurityTypeEnum MapToMatterSecurityType(wifi_security_type securityType) +{ + using app::Clusters::WiFiNetworkDiagnostics::SecurityTypeEnum; + + switch (securityType) + { + case WIFI_SECURITY_TYPE_NONE: + return SecurityTypeEnum::kNone; + case WIFI_SECURITY_TYPE_PSK: + case WIFI_SECURITY_TYPE_PSK_SHA256: + return SecurityTypeEnum::kWpa2; + case WIFI_SECURITY_TYPE_SAE: + return SecurityTypeEnum::kWpa3; + default: + break; + } + + return SecurityTypeEnum::kUnspecified; +} + } // namespace const Map @@ -100,20 +151,7 @@ void WiFiManager::WifiMgmtEventHandler(net_mgmt_event_callback * cb, uint32_t mg Platform::UniquePtr eventData(new uint8_t[cb->info_length]); VerifyOrReturn(eventData); memcpy(eventData.get(), cb->info, cb->info_length); - CHIP_ERROR status = SystemLayer().ScheduleLambda([data = eventData.get(), mgmtEvent]() { - if (data) - { - sEventHandlerMap[mgmtEvent](data); - // cleanup - delete[] data; - } - }); - - if (CHIP_NO_ERROR == status) - { - // the ownership has been transferred to the worker thread - release the buffer - eventData.release(); - } + sEventHandlerMap[mgmtEvent](std::move(eventData)); } } @@ -164,7 +202,9 @@ CHIP_ERROR WiFiManager::Scan(const ByteSpan & ssid, ScanResultCallback resultCal mInternalScan = internalScan; mScanResultCallback = resultCallback; mScanDoneCallback = doneCallback; + mCachedWiFiState = mWiFiState; mWiFiState = WIFI_STATE_SCANNING; + mSsidFound = false; if (net_mgmt(NET_REQUEST_WIFI_SCAN, iface, NULL, 0)) { @@ -250,8 +290,8 @@ CHIP_ERROR WiFiManager::GetWiFiInfo(WiFiInfo & info) const net_sprint_ll_addr_buf(reinterpret_cast(status.bssid), WIFI_MAC_ADDR_LEN, reinterpret_cast(mac_string_buf), sizeof(mac_string_buf)); info.mBssId = ByteSpan(mac_string_buf, sizeof(mac_string_buf)); - info.mSecurityType = static_cast(status.security); - info.mWiFiVersion = static_cast(status.link_mode); + info.mSecurityType = MapToMatterSecurityType(status.security); + info.mWiFiVersion = MapToMatterWiFiVersionCode(status.link_mode); info.mRssi = static_cast(status.rssi); info.mChannel = static_cast(status.channel); info.mSsidLen = status.ssid_len; @@ -265,23 +305,23 @@ CHIP_ERROR WiFiManager::GetWiFiInfo(WiFiInfo & info) const CHIP_ERROR WiFiManager::GetNetworkStatistics(NetworkStatistics & stats) const { - // TODO: below will not work (result will be all zeros) until - // the get_stats handler is implemented in WiFi driver - net_stats_eth data{}; - net_mgmt(NET_REQUEST_STATS_GET_ETHERNET, InetUtils::GetInterface(), &data, sizeof(data)); + net_stats_wifi data{}; + net_mgmt(NET_REQUEST_STATS_GET_WIFI, InetUtils::GetInterface(), &data, sizeof(data)); stats.mPacketMulticastRxCount = data.multicast.rx; stats.mPacketMulticastTxCount = data.multicast.tx; stats.mPacketUnicastRxCount = data.pkts.rx - data.multicast.rx - data.broadcast.rx; stats.mPacketUnicastTxCount = data.pkts.tx - data.multicast.tx - data.broadcast.tx; - stats.mOverruns = 0; // TODO: clarify if this can be queried from mgmt API (e.g. data.tx_dropped) + stats.mBeaconsSuccessCount = data.sta_mgmt.beacons_rx; + stats.mBeaconsLostCount = data.sta_mgmt.beacons_miss; return CHIP_NO_ERROR; } -void WiFiManager::ScanResultHandler(uint8_t * data) +void WiFiManager::ScanResultHandler(Platform::UniquePtr data) { - const struct wifi_scan_result * scanResult = reinterpret_cast(data); + // Contrary to other handlers, offload accumulating of the scan results from the CHIP thread to the caller's thread + const struct wifi_scan_result * scanResult = reinterpret_cast(data.get()); if (Instance().mInternalScan && Instance().mWantedNetwork.GetSsidSpan().data_equal(ByteSpan(scanResult->ssid, scanResult->ssid_length))) @@ -297,6 +337,7 @@ void WiFiManager::ScanResultHandler(uint8_t * data) Instance().mWiFiParams.mParams.security = scanResult->security <= WIFI_SECURITY_TYPE_MAX ? scanResult->security : WIFI_SECURITY_TYPE_PSK; Instance().mWiFiParams.mParams.psk_length = static_cast(Instance().mWantedNetwork.passLen); + Instance().mWiFiParams.mParams.mfp = (scanResult->mfp == WIFI_MFP_REQUIRED) ? WIFI_MFP_REQUIRED : WIFI_MFP_OPTIONAL; // If the security is none, WiFi driver expects the psk to be nullptr if (Instance().mWiFiParams.mParams.security == WIFI_SECURITY_TYPE_NONE) @@ -309,8 +350,9 @@ void WiFiManager::ScanResultHandler(uint8_t * data) } Instance().mWiFiParams.mParams.timeout = Instance().mHandling.mConnectionTimeout.count(); - Instance().mWiFiParams.mParams.channel = scanResult->channel; + Instance().mWiFiParams.mParams.channel = WIFI_CHANNEL_ANY; Instance().mWiFiParams.mRssi = scanResult->rssi; + Instance().mSsidFound = true; } } @@ -320,27 +362,45 @@ void WiFiManager::ScanResultHandler(uint8_t * data) } } -void WiFiManager::ScanDoneHandler(uint8_t * data) +void WiFiManager::ScanDoneHandler(Platform::UniquePtr data) { - const wifi_status * status = reinterpret_cast(data); - WiFiRequestStatus requestStatus = static_cast(status->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); + WiFiRequestStatus requestStatus = static_cast(status->status); - if (Instance().mScanDoneCallback && !Instance().mInternalScan) - { - Instance().mScanDoneCallback(requestStatus); - } + if (requestStatus == WiFiRequestStatus::FAILURE) + { + ChipLogError(DeviceLayer, "Wi-Fi scan finalization failure (%d)", status->status); + } + else + { + ChipLogProgress(DeviceLayer, "Wi-Fi scan done (%d)", status->status); + } - if (requestStatus == WiFiRequestStatus::FAILURE) - { - ChipLogDetail(DeviceLayer, "Scan request failed (%d)", status->status); - } - else - { - ChipLogDetail(DeviceLayer, "Scan request done (%d)", status->status); + if (Instance().mScanDoneCallback && !Instance().mInternalScan) + { + Instance().mScanDoneCallback(requestStatus); + // restore the connection state from before the scan request was issued + Instance().mWiFiState = Instance().mCachedWiFiState; + return; + } - // Internal scan is supposed to be followed by connection request + // Internal scan is supposed to be followed by a connection request if the SSID has been found if (Instance().mInternalScan) { + if (!Instance().mSsidFound && !Instance().mRecoveryTimerAborted) + { + ChipLogProgress(DeviceLayer, "No requested SSID found"); + auto currentTimeout = Instance().CalculateNextRecoveryTime(); + ChipLogProgress(DeviceLayer, "Starting connection recover: re-scanning... (next attempt in %d ms)", + currentTimeout.count()); + Instance().mRecoveryTimerAborted = false; + DeviceLayer::SystemLayer().StartTimer(currentTimeout, Recover, nullptr); + return; + } + Instance().mWiFiState = WIFI_STATE_ASSOCIATING; net_if * iface = InetUtils::GetInterface(); VerifyOrReturn(nullptr != iface, CHIP_ERROR_INTERNAL); @@ -352,12 +412,19 @@ void WiFiManager::ScanDoneHandler(uint8_t * data) { Instance().mHandling.mOnConnectionFailed(); } + Instance().mWiFiState = WIFI_STATE_DISCONNECTED; return; } - ChipLogError(DeviceLayer, "Connection to %*s requested", Instance().mWiFiParams.mParams.ssid_length, - Instance().mWiFiParams.mParams.ssid); + ChipLogProgress(DeviceLayer, "Connection to %*s requested", Instance().mWiFiParams.mParams.ssid_length, + Instance().mWiFiParams.mParams.ssid); Instance().mInternalScan = false; } + }); + + if (CHIP_NO_ERROR == err) + { + // the ownership has been transferred to the worker thread - release the buffer + data.release(); } } @@ -380,44 +447,70 @@ void WiFiManager::SendRouterSolicitation(System::Layer * layer, void * param) } } -void WiFiManager::ConnectHandler(uint8_t * data) +void WiFiManager::ConnectHandler(Platform::UniquePtr data) { - const wifi_status * status = reinterpret_cast(data); - WiFiRequestStatus requestStatus = static_cast(status->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); + WiFiRequestStatus requestStatus = static_cast(status->status); - if (requestStatus == WiFiRequestStatus::FAILURE || requestStatus == WiFiRequestStatus::TERMINATED) - { - ChipLogDetail(DeviceLayer, "Connection to WiFi network failed or was terminated by another request"); - Instance().mWiFiState = WIFI_STATE_DISCONNECTED; - if (Instance().mHandling.mOnConnectionFailed) + if (requestStatus == WiFiRequestStatus::FAILURE || requestStatus == WiFiRequestStatus::TERMINATED) { - Instance().mHandling.mOnConnectionFailed(); + ChipLogProgress(DeviceLayer, "Connection to WiFi network failed or was terminated by another request"); + Instance().mWiFiState = WIFI_STATE_DISCONNECTED; + if (Instance().mHandling.mOnConnectionFailed) + { + Instance().mHandling.mOnConnectionFailed(); + } } - } - else - { - // Workaround needed until sending Router Solicitation after connect will be done by the driver. - DeviceLayer::SystemLayer().StartTimer( - System::Clock::Milliseconds32(chip::Crypto::GetRandU16() % kMaxInitialRouterSolicitationDelayMs), - SendRouterSolicitation, nullptr); - - ChipLogDetail(DeviceLayer, "Connected to WiFi network"); - Instance().mWiFiState = WIFI_STATE_COMPLETED; - if (Instance().mHandling.mOnConnectionSuccess) + else // The connection has been established successfully. { - Instance().mHandling.mOnConnectionSuccess(); + // Workaround needed until sending Router Solicitation after connect will be done by the driver. + DeviceLayer::SystemLayer().StartTimer( + System::Clock::Milliseconds32(chip::Crypto::GetRandU16() % kMaxInitialRouterSolicitationDelayMs), + SendRouterSolicitation, nullptr); + + ChipLogProgress(DeviceLayer, "Connected to WiFi network"); + Instance().mWiFiState = WIFI_STATE_COMPLETED; + if (Instance().mHandling.mOnConnectionSuccess) + { + Instance().mHandling.mOnConnectionSuccess(); + } + Instance().PostConnectivityStatusChange(kConnectivity_Established); + + // Workaround needed to re-initialize mDNS server after Wi-Fi interface is operative + chip::DeviceLayer::ChipDeviceEvent event; + event.Type = chip::DeviceLayer::DeviceEventType::kDnssdInitialized; + + CHIP_ERROR error = chip::DeviceLayer::PlatformMgr().PostEvent(&event); + if (error != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Cannot post event [error: %s]", ErrorStr(error)); + } } - Instance().PostConnectivityStatusChange(kConnectivity_Established); + // Ensure fresh recovery for future connection requests. + Instance().ResetRecoveryTime(); + // cleanup the provisioning data as it is configured per each connect request + Instance().ClearStationProvisioningData(); + }); + + if (CHIP_NO_ERROR == err) + { + // the ownership has been transferred to the worker thread - release the buffer + data.release(); } - // cleanup the provisioning data as it is configured per each connect request - Instance().ClearStationProvisioningData(); } -void WiFiManager::DisconnectHandler(uint8_t * data) +void WiFiManager::DisconnectHandler(Platform::UniquePtr) { - ChipLogDetail(DeviceLayer, "WiFi station disconnected"); - Instance().mWiFiState = WIFI_STATE_DISCONNECTED; - Instance().PostConnectivityStatusChange(kConnectivity_Lost); + SystemLayer().ScheduleLambda([] { + ChipLogProgress(DeviceLayer, "WiFi station disconnected"); + Instance().mWiFiState = WIFI_STATE_DISCONNECTED; + Instance().PostConnectivityStatusChange(kConnectivity_Lost); + // Ensure fresh recovery for future connection requests. + Instance().ResetRecoveryTime(); + }); } WiFiManager::StationStatus WiFiManager::GetStationStatus() const @@ -433,5 +526,47 @@ void WiFiManager::PostConnectivityStatusChange(ConnectivityChange changeType) PlatformMgr().PostEventOrDie(&networkEvent); } +System::Clock::Milliseconds32 WiFiManager::CalculateNextRecoveryTime() +{ + if (mConnectionRecoveryTimeMs > kConnectionRecoveryMaxIntervalMs) + { + // Find the new random jitter value in range [-jitter, +jitter]. + int32_t jitter = chip::Crypto::GetRandU32() % (2 * jitter + 1) - jitter; + mConnectionRecoveryTimeMs = kConnectionRecoveryMaxIntervalMs + jitter; + return System::Clock::Milliseconds32(mConnectionRecoveryTimeMs); + } + else + { + uint32_t currentRecoveryTimeout = mConnectionRecoveryTimeMs; + mConnectionRecoveryTimeMs = mConnectionRecoveryTimeMs * 2; + return System::Clock::Milliseconds32(currentRecoveryTimeout); + } +} + +void WiFiManager::Recover(System::Layer *, void *) +{ + // If kConnectionRecoveryMaxOverallInterval has a non-zero value prevent endless re-scan. + if (0 != kConnectionRecoveryMaxRetries && (++Instance().mConnectionRecoveryCounter >= kConnectionRecoveryMaxRetries)) + { + Instance().AbortConnectionRecovery(); + return; + } + + Instance().Scan(Instance().mWantedNetwork.GetSsidSpan(), nullptr, nullptr, true /* internal scan */); +} + +void WiFiManager::ResetRecoveryTime() +{ + mConnectionRecoveryTimeMs = kConnectionRecoveryMinIntervalMs; + mConnectionRecoveryCounter = 0; +} + +void WiFiManager::AbortConnectionRecovery() +{ + DeviceLayer::SystemLayer().CancelTimer(Recover, nullptr); + Instance().ResetRecoveryTime(); + Instance().mRecoveryTimerAborted = true; +} + } // namespace DeviceLayer } // namespace chip diff --git a/src/platform/nrfconnect/wifi/WiFiManager.h b/src/platform/nrfconnect/wifi/WiFiManager.h index 99fd74f3cf8fb0..beed57575f3283 100644 --- a/src/platform/nrfconnect/wifi/WiFiManager.h +++ b/src/platform/nrfconnect/wifi/WiFiManager.h @@ -128,7 +128,7 @@ class WiFiManager struct WiFiInfo { ByteSpan mBssId{}; - uint8_t mSecurityType{}; + app::Clusters::WiFiNetworkDiagnostics::SecurityTypeEnum mSecurityType{}; uint8_t mWiFiVersion{}; uint16_t mChannel{}; int8_t mRssi{}; @@ -142,7 +142,8 @@ class WiFiManager uint32_t mPacketMulticastTxCount{}; uint32_t mPacketUnicastRxCount{}; uint32_t mPacketUnicastTxCount{}; - uint32_t mOverruns{}; + uint32_t mBeaconsSuccessCount{}; + uint32_t mBeaconsLostCount{}; }; struct WiFiNetwork @@ -168,6 +169,13 @@ class WiFiManager static constexpr uint16_t kRouterSolicitationIntervalMs = 4000; static constexpr uint16_t kMaxInitialRouterSolicitationDelayMs = 1000; static constexpr uint8_t kRouterSolicitationMaxCount = 3; + static constexpr uint32_t kConnectionRecoveryMinIntervalMs = CONFIG_CHIP_WIFI_CONNECTION_RECOVERY_MINIMUM_INTERVAL; + static constexpr uint32_t kConnectionRecoveryMaxIntervalMs = CONFIG_CHIP_WIFI_CONNECTION_RECOVERY_MAXIMUM_INTERVAL; + static constexpr uint32_t kConnectionRecoveryJitterMs = CONFIG_CHIP_WIFI_CONNECTION_RECOVERY_JITTER; + static constexpr uint32_t kConnectionRecoveryMaxRetries = CONFIG_CHIP_WIFI_CONNECTION_RECOVERY_MAX_RETRIES_NUMBER; + + static_assert(kConnectionRecoveryMinIntervalMs < kConnectionRecoveryMaxIntervalMs); + static_assert(kConnectionRecoveryJitterMs <= kConnectionRecoveryMaxIntervalMs); #if CHIP_DEVICE_CONFIG_ENABLE_SED static constexpr uint8_t kDefaultDTIMInterval = 3; @@ -183,9 +191,10 @@ class WiFiManager CHIP_ERROR Disconnect(); CHIP_ERROR GetWiFiInfo(WiFiInfo & info) const; CHIP_ERROR GetNetworkStatistics(NetworkStatistics & stats) const; + void AbortConnectionRecovery(); private: - using NetEventHandler = void (*)(uint8_t *); + using NetEventHandler = void (*)(Platform::UniquePtr); struct ConnectionParams { @@ -198,22 +207,41 @@ class WiFiManager // Event handling static void WifiMgmtEventHandler(net_mgmt_event_callback * cb, uint32_t mgmtEvent, net_if * iface); - static void ScanResultHandler(uint8_t * data); - static void ScanDoneHandler(uint8_t * data); - static void ConnectHandler(uint8_t * data); - static void DisconnectHandler(uint8_t * data); + static void 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); + // Connection Recovery feature + // This feature allows re-scanning and re-connecting the connection to the known network after + // a reboot or when a connection is lost. The following attempts will occur with increasing interval. + // The connection recovery interval starts from kConnectionRecoveryMinIntervalMs and is doubled + // with each occurrence until reaching kConnectionRecoveryMaxIntervalMs. + // When the connection recovery interval reaches the maximum value the randomized kConnectionRecoveryJitterMs + // from the range [-jitter, +jitter] is added to the value to avoid the periodicity. + // To avoid frequent recovery attempts when the signal to an access point is poor quality + // The connection recovery interval will be cleared after the defined delay in kConnectionRecoveryDelayToReset. + static void Recover(System::Layer * layer, void * param); + void ResetRecoveryTime(); + System::Clock::Milliseconds32 CalculateNextRecoveryTime(); + ConnectionParams mWiFiParams{}; ConnectionHandling mHandling; wifi_iface_state mWiFiState; + wifi_iface_state mCachedWiFiState; net_mgmt_event_callback mWiFiMgmtClbk{}; ScanResultCallback mScanResultCallback{ nullptr }; ScanDoneCallback mScanDoneCallback{ nullptr }; WiFiNetwork mWantedNetwork{}; bool mInternalScan{ false }; uint8_t mRouterSolicitationCounter = 0; + bool mSsidFound{ false }; + uint32_t mConnectionRecoveryCounter{ 0 }; + uint32_t mConnectionRecoveryTimeMs{ kConnectionRecoveryMinIntervalMs }; + bool mRecoveryTimerAborted{ false }; + static const Map sStatusMap; static const Map sEventHandlerMap; }; diff --git a/src/test_driver/nrfconnect/CMakeLists.txt b/src/test_driver/nrfconnect/CMakeLists.txt index 39648928a5dde2..750853ea25d214 100644 --- a/src/test_driver/nrfconnect/CMakeLists.txt +++ b/src/test_driver/nrfconnect/CMakeLists.txt @@ -42,9 +42,6 @@ set(CHIP_CFLAGS -DCHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF=0 -DCHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS=1 -I${CMAKE_CURRENT_SOURCE_DIR}/main/include - -DMBEDTLS_CONFIG_FILE= - -isystem$ENV{ZEPHYR_BASE}/modules/mbedtls/configs - -isystem$ENV{ZEPHYR_BASE}/../mbedtls/include ) # Load NCS/Zephyr build system diff --git a/src/test_driver/nrfconnect/main/runner.cpp b/src/test_driver/nrfconnect/main/runner.cpp index a44e09a3ebcae1..7cff68e0efcbc6 100644 --- a/src/test_driver/nrfconnect/main/runner.cpp +++ b/src/test_driver/nrfconnect/main/runner.cpp @@ -27,7 +27,7 @@ using namespace ::chip::DeviceLayer; LOG_MODULE_REGISTER(runner, CONFIG_MATTER_LOG_LEVEL); -void main(void) +extern "C" void main(void) { VerifyOrDie(settings_subsys_init() == 0);