diff --git a/config/nrfconnect/app/sample-defaults.conf b/config/nrfconnect/app/sample-defaults.conf index 829ef8ef29c880..93ac000214ad8b 100644 --- a/config/nrfconnect/app/sample-defaults.conf +++ b/config/nrfconnect/app/sample-defaults.conf @@ -25,6 +25,9 @@ CONFIG_ASSERT=y CONFIG_HW_STACK_PROTECTION=y CONFIG_SHELL=y +# Enable getting reboot reasons information +CONFIG_HWINFO=y + # Generic networking options CONFIG_NETWORKING=y CONFIG_NET_SOCKETS=y diff --git a/src/app/clusters/general_diagnostics_server/general_diagnostics_server.cpp b/src/app/clusters/general_diagnostics_server/general_diagnostics_server.cpp index 96734482b78c1a..820a2ac4b8d322 100644 --- a/src/app/clusters/general_diagnostics_server/general_diagnostics_server.cpp +++ b/src/app/clusters/general_diagnostics_server/general_diagnostics_server.cpp @@ -35,6 +35,13 @@ using chip::DeviceLayer::ConnectivityMgr; using chip::DeviceLayer::DiagnosticDataProvider; using chip::DeviceLayer::GetDiagnosticDataProvider; +static_assert(sizeof(DiagnosticDataProvider::BootReasonType) == sizeof(EmberAfBootReasonType), + "BootReasonType size doesn't match EmberAfBootReasonType size"); +static_assert(static_cast(DiagnosticDataProvider::BootReasonType::Unspecified) == EMBER_ZCL_BOOT_REASON_TYPE_UNSPECIFIED && + static_cast(DiagnosticDataProvider::BootReasonType::SoftwareReset) == + EMBER_ZCL_BOOT_REASON_TYPE_SOFTWARE_RESET, + "BootReasonType and EmberAfBootReasonType values does not match."); + namespace { class GeneralDiagosticsAttrAccess : public AttributeAccessInterface diff --git a/src/include/platform/DiagnosticDataProvider.h b/src/include/platform/DiagnosticDataProvider.h index e02a96201db182..eaba40996cd2e9 100644 --- a/src/include/platform/DiagnosticDataProvider.h +++ b/src/include/platform/DiagnosticDataProvider.h @@ -131,6 +131,17 @@ class WiFiDiagnosticsDelegate class DiagnosticDataProvider { public: + enum BootReasonType : uint8_t + { + Unspecified = 0, + PowerOnReboot = 1, + BrownOutReset = 2, + SoftwareWatchdogReset = 3, + HardwareWatchdogReset = 4, + SoftwareUpdateCompleted = 5, + SoftwareReset = 6, + }; + void SetGeneralDiagnosticsDelegate(GeneralDiagnosticsDelegate * delegate) { mGeneralDiagnosticsDelegate = delegate; } GeneralDiagnosticsDelegate * GetGeneralDiagnosticsDelegate() const { return mGeneralDiagnosticsDelegate; } diff --git a/src/inet/InetInterface.cpp b/src/inet/InetInterface.cpp index 4b648b7ec2853b..a69f7b6281ef37 100644 --- a/src/inet/InetInterface.cpp +++ b/src/inet/InetInterface.cpp @@ -165,6 +165,16 @@ bool InterfaceIterator::HasBroadcastAddress() return HasCurrent() && (mCurNetif->flags & NETIF_FLAG_BROADCAST) != 0; } +CHIP_ERROR InterfaceIterator::GetInterfaceType(InterfaceType & type) +{ + return CHIP_ERROR_NOT_IMPLEMENTED; +} + +CHIP_ERROR InterfaceIterator::GetHardwareAddress(uint8_t * addressBuffer, uint8_t & addressSize, uint8_t addressBufferSize) +{ + return CHIP_ERROR_NOT_IMPLEMENTED; +} + bool InterfaceAddressIterator::HasCurrent() { return mIntfIter.HasCurrent() && ((mCurAddrIndex != kBeforeStartIndex) || Next()); @@ -619,6 +629,16 @@ short InterfaceIterator::GetFlags() return mIntfFlags; } +CHIP_ERROR InterfaceIterator::GetInterfaceType(InterfaceType & type) +{ + return CHIP_ERROR_NOT_IMPLEMENTED; +} + +CHIP_ERROR InterfaceIterator::GetHardwareAddress(uint8_t * addressBuffer, uint8_t & addressSize, uint8_t addressBufferSize) +{ + return CHIP_ERROR_NOT_IMPLEMENTED; +} + InterfaceAddressIterator::InterfaceAddressIterator() { mAddrsList = nullptr; @@ -850,6 +870,52 @@ bool InterfaceIterator::HasBroadcastAddress() return HasCurrent() && INET_CONFIG_ENABLE_IPV4; } +CHIP_ERROR InterfaceIterator::GetInterfaceType(InterfaceType & type) +{ + VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE); + + const net_linkaddr * linkAddr = net_if_get_link_addr(mCurrentInterface); + if (!linkAddr) + return CHIP_ERROR_INCORRECT_STATE; + + // Do not consider other than WiFi and Thread for now. + if (linkAddr->type == NET_LINK_IEEE802154) + { + type = InterfaceType::Thread; + } + // Zephyr doesn't define WiFi address type, so it shares the same type as Ethernet. + else if (linkAddr->type == NET_LINK_ETHERNET) + { + type = InterfaceType::WiFi; + } + else + { + type = InterfaceType::Unknown; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR InterfaceIterator::GetHardwareAddress(uint8_t * addressBuffer, uint8_t & addressSize, uint8_t addressBufferSize) +{ + VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE); + + if (!addressBuffer) + return CHIP_ERROR_INVALID_ARGUMENT; + + const net_linkaddr * linkAddr = net_if_get_link_addr(mCurrentInterface); + if (!linkAddr) + return CHIP_ERROR_INCORRECT_STATE; + + if (linkAddr->len > addressBufferSize) + return CHIP_ERROR_BUFFER_TOO_SMALL; + + addressSize = linkAddr->len; + memcpy(addressBuffer, linkAddr->addr, linkAddr->len); + + return CHIP_NO_ERROR; +} + InterfaceAddressIterator::InterfaceAddressIterator() = default; bool InterfaceAddressIterator::HasCurrent() diff --git a/src/inet/InetInterface.h b/src/inet/InetInterface.h index 29a9b76bf9c878..34638c3ea50e43 100644 --- a/src/inet/InetInterface.h +++ b/src/inet/InetInterface.h @@ -58,6 +58,18 @@ namespace Inet { class IPAddress; class IPPrefix; +/** + * Data type describing interface type. + */ +enum class InterfaceType +{ + Unknown = 0, + WiFi = 1, + Ethernet = 2, + Cellular = 3, + Thread = 4, +}; + /** * Indicator for system network interfaces. */ @@ -299,6 +311,22 @@ class InterfaceIterator */ bool HasBroadcastAddress(); + /** + * Get the interface type of the current network interface. + * + * @param[out] type Object to save the interface type. + */ + CHIP_ERROR GetInterfaceType(InterfaceType & type); + + /** + * Get the hardware address of the current network interface + * + * @param[out] addressBuffer Region of memory to write the hardware address. + * @param[out] addressSize Size of the address saved to a buffer. + * @param[in] addressBufferSize Maximum size of a buffer to save data. + */ + CHIP_ERROR GetHardwareAddress(uint8_t * addressBuffer, uint8_t & addressSize, uint8_t addressBufferSize); + protected: #if CHIP_SYSTEM_CONFIG_USE_LWIP struct netif * mCurNetif; diff --git a/src/inet/tests/TestInetEndPoint.cpp b/src/inet/tests/TestInetEndPoint.cpp index 4af7590d883253..0fab309d824c66 100644 --- a/src/inet/tests/TestInetEndPoint.cpp +++ b/src/inet/tests/TestInetEndPoint.cpp @@ -126,6 +126,12 @@ static void TestInetInterface(nlTestSuite * inSuite, void * inContext) InterfaceId intId; IPAddress addr; IPPrefix addrWithPrefix; + InterfaceType intType; + // 64 bit IEEE MAC address + const uint8_t kMaxHardwareAddressSize = 8; + uint8_t intHwAddress[kMaxHardwareAddressSize]; + uint8_t intHwAddressSize; + CHIP_ERROR err; #ifndef __MBED__ @@ -165,13 +171,36 @@ static void TestInetInterface(nlTestSuite * inSuite, void * inContext) intId.GetLinkLocalAddr(&addr); InterfaceId::MatchLocalIPv6Subnet(addr); + + // Not all platforms support getting interface type and hardware address + err = intIterator.GetInterfaceType(intType); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR || err == CHIP_ERROR_NOT_IMPLEMENTED); + + err = intIterator.GetHardwareAddress(intHwAddress, intHwAddressSize, sizeof(intHwAddress)); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR || err == CHIP_ERROR_NOT_IMPLEMENTED); + if (err == CHIP_NO_ERROR) + { + NL_TEST_ASSERT(inSuite, intHwAddressSize == 6 || intHwAddressSize == 8); + NL_TEST_ASSERT(inSuite, + intIterator.GetHardwareAddress(nullptr, intHwAddressSize, sizeof(intHwAddress)) == + CHIP_ERROR_INVALID_ARGUMENT); + NL_TEST_ASSERT(inSuite, + intIterator.GetHardwareAddress(intHwAddress, intHwAddressSize, 4) == CHIP_ERROR_BUFFER_TOO_SMALL); + } } + NL_TEST_ASSERT(inSuite, !intIterator.Next()); NL_TEST_ASSERT(inSuite, intIterator.GetInterfaceId() == InterfaceId::Null()); NL_TEST_ASSERT(inSuite, intIterator.GetInterfaceName(intName, sizeof(intName)) == CHIP_ERROR_INCORRECT_STATE); NL_TEST_ASSERT(inSuite, !intIterator.SupportsMulticast()); NL_TEST_ASSERT(inSuite, !intIterator.HasBroadcastAddress()); + // Not all platforms support getting interface type and hardware address + err = intIterator.GetInterfaceType(intType); + NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INCORRECT_STATE || err == CHIP_ERROR_NOT_IMPLEMENTED); + err = intIterator.GetHardwareAddress(intHwAddress, intHwAddressSize, sizeof(intHwAddress)); + NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INCORRECT_STATE || err == CHIP_ERROR_NOT_IMPLEMENTED); + printf(" Addresses:\n"); for (; addrIterator.HasCurrent(); addrIterator.Next()) { diff --git a/src/platform/Ameba/ConfigurationManagerImpl.cpp b/src/platform/Ameba/ConfigurationManagerImpl.cpp index ad0c2f4fde70ed..aa6434c21c85c3 100644 --- a/src/platform/Ameba/ConfigurationManagerImpl.cpp +++ b/src/platform/Ameba/ConfigurationManagerImpl.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -79,7 +80,7 @@ CHIP_ERROR ConfigurationManagerImpl::Init() if (!AmebaConfig::ConfigValueExists(AmebaConfig::kCounterKey_BootReason)) { - err = StoreBootReason(EMBER_ZCL_BOOT_REASON_TYPE_UNSPECIFIED); + err = StoreBootReason(DiagnosticDataProvider::BootReasonType::Unspecified); SuccessOrExit(err); } diff --git a/src/platform/EFR32/ConfigurationManagerImpl.cpp b/src/platform/EFR32/ConfigurationManagerImpl.cpp index 711e4540191241..24407f7342ea12 100644 --- a/src/platform/EFR32/ConfigurationManagerImpl.cpp +++ b/src/platform/EFR32/ConfigurationManagerImpl.cpp @@ -27,6 +27,7 @@ #include #include +#include #include #include "em_rmu.h" @@ -106,50 +107,50 @@ uint32_t ConfigurationManagerImpl::GetBootReason(void) #if defined(_SILICON_LABS_32B_SERIES_1) if (rebootCause & RMU_RSTCAUSE_PORST || rebootCause & RMU_RSTCAUSE_EXTRST) // PowerOn or External pin reset { - matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_POWER_ON_REBOOT; + matterBootCause = DiagnosticDataProvider::BootReasonType::PowerOnReboot; } else if (rebootCause & RMU_RSTCAUSE_AVDDBOD || rebootCause & RMU_RSTCAUSE_DVDDBOD || rebootCause & RMU_RSTCAUSE_DECBOD) { - matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_BROWN_OUT_RESET; + matterBootCause = DiagnosticDataProvider::BootReasonType::BrownOutReset; } else if (rebootCause & RMU_RSTCAUSE_SYSREQRST) { - matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_SOFTWARE_RESET; + matterBootCause = DiagnosticDataProvider::BootReasonType::SoftwareReset; } else if (rebootCause & RMU_RSTCAUSE_WDOGRST) { - matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_SOFTWARE_WATCHDOG_RESET; + matterBootCause = DiagnosticDataProvider::BootReasonType::SoftwareWatchdogReset; } else { - matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_UNSPECIFIED; + matterBootCause = DiagnosticDataProvider::BootReasonType::Unspecified; } // Not tracked HARDWARE_WATCHDOG_RESET && SOFTWARE_UPDATE_COMPLETED #elif defined(_SILICON_LABS_32B_SERIES_2) if (rebootCause & EMU_RSTCAUSE_POR || rebootCause & EMU_RSTCAUSE_PIN) // PowerOn or External pin reset { - matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_POWER_ON_REBOOT; + matterBootCause = DiagnosticDataProvider::BootReasonType::PowerOnReboot; } else if (rebootCause & EMU_RSTCAUSE_AVDDBOD || rebootCause & EMU_RSTCAUSE_DVDDBOD || rebootCause & EMU_RSTCAUSE_DECBOD || rebootCause & EMU_RSTCAUSE_VREGIN || rebootCause & EMU_RSTCAUSE_IOVDD0BOD || rebootCause & EMU_RSTCAUSE_DVDDLEBOD) { - matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_BROWN_OUT_RESET; + matterBootCause = DiagnosticDataProvider::BootReasonType::BrownOutReset; } else if (rebootCause & EMU_RSTCAUSE_SYSREQ) { - matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_SOFTWARE_RESET; + matterBootCause = DiagnosticDataProvider::BootReasonType::SoftwareReset; } else if (rebootCause & EMU_RSTCAUSE_WDOG0 || rebootCause & EMU_RSTCAUSE_WDOG1) { - matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_SOFTWARE_WATCHDOG_RESET; + matterBootCause = DiagnosticDataProvider::BootReasonType::SoftwareWatchdogReset; } else { - matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_UNSPECIFIED; + matterBootCause = DiagnosticDataProvider::BootReasonType::Unspecified; } // Not tracked HARDWARE_WATCHDOG_RESET && SOFTWARE_UPDATE_COMPLETED #else - matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_UNSPECIFIED; + matterBootCause = DiagnosticDataProvider::BootReasonType::Unspecified; #endif return matterBootCause; diff --git a/src/platform/ESP32/DiagnosticDataProviderImpl.cpp b/src/platform/ESP32/DiagnosticDataProviderImpl.cpp index f97e2a6459c005..82396710972711 100644 --- a/src/platform/ESP32/DiagnosticDataProviderImpl.cpp +++ b/src/platform/ESP32/DiagnosticDataProviderImpl.cpp @@ -167,28 +167,28 @@ CHIP_ERROR DiagnosticDataProviderImpl::GetTotalOperationalHours(uint32_t & total CHIP_ERROR DiagnosticDataProviderImpl::GetBootReason(uint8_t & bootReason) { - bootReason = EMBER_ZCL_BOOT_REASON_TYPE_UNSPECIFIED; + bootReason = BootReasonType::Unspecified; uint8_t reason; reason = static_cast(esp_reset_reason()); if (reason == ESP_RST_UNKNOWN) { - bootReason = EMBER_ZCL_BOOT_REASON_TYPE_UNSPECIFIED; + bootReason = BootReasonType::Unspecified; } else if (reason == ESP_RST_POWERON) { - bootReason = EMBER_ZCL_BOOT_REASON_TYPE_POWER_ON_REBOOT; + bootReason = BootReasonType::PowerOnReboot; } else if (reason == ESP_RST_BROWNOUT) { - bootReason = EMBER_ZCL_BOOT_REASON_TYPE_BROWN_OUT_RESET; + bootReason = BootReasonType::BrownOutReset; } else if (reason == ESP_RST_SW) { - bootReason = EMBER_ZCL_BOOT_REASON_TYPE_SOFTWARE_RESET; + bootReason = BootReasonType::SoftwareReset; } else if (reason == ESP_RST_INT_WDT) { - bootReason = EMBER_ZCL_BOOT_REASON_TYPE_SOFTWARE_WATCHDOG_RESET; + bootReason = BootReasonType::SoftwareWatchdogReset; /* Reboot can be due to hardware or software watchdog*/ } return CHIP_NO_ERROR; diff --git a/src/platform/Linux/ConfigurationManagerImpl.cpp b/src/platform/Linux/ConfigurationManagerImpl.cpp index 56b7394a85856f..94d5654d784098 100644 --- a/src/platform/Linux/ConfigurationManagerImpl.cpp +++ b/src/platform/Linux/ConfigurationManagerImpl.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -87,7 +88,7 @@ CHIP_ERROR ConfigurationManagerImpl::Init() if (!PosixConfig::ConfigValueExists(PosixConfig::kCounterKey_BootReason)) { - err = StoreBootReason(EMBER_ZCL_BOOT_REASON_TYPE_UNSPECIFIED); + err = StoreBootReason(DiagnosticDataProvider::BootReasonType::Unspecified); SuccessOrExit(err); } diff --git a/src/platform/Linux/PlatformManagerImpl.cpp b/src/platform/Linux/PlatformManagerImpl.cpp index 76ac2fa9679f55..5273b814f159ca 100644 --- a/src/platform/Linux/PlatformManagerImpl.cpp +++ b/src/platform/Linux/PlatformManagerImpl.cpp @@ -63,27 +63,27 @@ void SignalHandler(int signum) switch (signum) { case SIGINT: - ConfigurationMgr().StoreBootReason(EMBER_ZCL_BOOT_REASON_TYPE_SOFTWARE_RESET); + ConfigurationMgr().StoreBootReason(DiagnosticDataProvider::BootReasonType::SoftwareReset); err = CHIP_ERROR_REBOOT_SIGNAL_RECEIVED; break; case SIGHUP: - ConfigurationMgr().StoreBootReason(EMBER_ZCL_BOOT_REASON_TYPE_BROWN_OUT_RESET); + ConfigurationMgr().StoreBootReason(DiagnosticDataProvider::BootReasonType::BrownOutReset); err = CHIP_ERROR_REBOOT_SIGNAL_RECEIVED; break; case SIGTERM: - ConfigurationMgr().StoreBootReason(EMBER_ZCL_BOOT_REASON_TYPE_POWER_ON_REBOOT); + ConfigurationMgr().StoreBootReason(DiagnosticDataProvider::BootReasonType::PowerOnReboot); err = CHIP_ERROR_REBOOT_SIGNAL_RECEIVED; break; case SIGUSR1: - ConfigurationMgr().StoreBootReason(EMBER_ZCL_BOOT_REASON_TYPE_HARDWARE_WATCHDOG_RESET); + ConfigurationMgr().StoreBootReason(DiagnosticDataProvider::BootReasonType::HardwareWatchdogReset); err = CHIP_ERROR_REBOOT_SIGNAL_RECEIVED; break; case SIGUSR2: - ConfigurationMgr().StoreBootReason(EMBER_ZCL_BOOT_REASON_TYPE_SOFTWARE_WATCHDOG_RESET); + ConfigurationMgr().StoreBootReason(DiagnosticDataProvider::BootReasonType::SoftwareWatchdogReset); err = CHIP_ERROR_REBOOT_SIGNAL_RECEIVED; break; case SIGTSTP: - ConfigurationMgr().StoreBootReason(EMBER_ZCL_BOOT_REASON_TYPE_SOFTWARE_UPDATE_COMPLETED); + ConfigurationMgr().StoreBootReason(DiagnosticDataProvider::BootReasonType::SoftwareUpdateCompleted); err = CHIP_ERROR_REBOOT_SIGNAL_RECEIVED; break; case SIGTRAP: diff --git a/src/platform/P6/DiagnosticDataProviderImpl.cpp b/src/platform/P6/DiagnosticDataProviderImpl.cpp index 3187f917a11784..3cefb86d46453c 100644 --- a/src/platform/P6/DiagnosticDataProviderImpl.cpp +++ b/src/platform/P6/DiagnosticDataProviderImpl.cpp @@ -119,23 +119,23 @@ CHIP_ERROR DiagnosticDataProviderImpl::GetBootReason(uint8_t & bootReason) cyhal_reset_reason_t reset_reason = cyhal_system_get_reset_reason(); if (reset_reason == CYHAL_SYSTEM_RESET_NONE) { - bootReason = EMBER_ZCL_BOOT_REASON_TYPE_POWER_ON_REBOOT; + bootReason = BootReasonType::PowerOnReboot; } else if (reset_reason == CYHAL_SYSTEM_RESET_WDT) { - bootReason = EMBER_ZCL_BOOT_REASON_TYPE_SOFTWARE_WATCHDOG_RESET; + bootReason = BootReasonType::SoftwareWatchdogReset; } else if (reset_reason == CYHAL_SYSTEM_RESET_SOFT) { - bootReason = EMBER_ZCL_BOOT_REASON_TYPE_SOFTWARE_RESET; + bootReason = BootReasonType::SoftwareReset; } else if (reset_reason == CYHAL_SYSTEM_RESET_HIB_WAKEUP) { - bootReason = EMBER_ZCL_BOOT_REASON_TYPE_HARDWARE_WATCHDOG_RESET; + bootReason = BootReasonType::HardwareWatchdogReset; } else { - bootReason = EMBER_ZCL_BOOT_REASON_TYPE_UNSPECIFIED; + bootReason = BootReasonType::Unspecified; } return CHIP_NO_ERROR; } diff --git a/src/platform/Zephyr/ConfigurationManagerImpl.cpp b/src/platform/Zephyr/ConfigurationManagerImpl.cpp index 068b3117f69dbc..7c4f7ab9b095ba 100644 --- a/src/platform/Zephyr/ConfigurationManagerImpl.cpp +++ b/src/platform/Zephyr/ConfigurationManagerImpl.cpp @@ -52,6 +52,7 @@ ConfigurationManagerImpl & ConfigurationManagerImpl::GetDefaultInstance() CHIP_ERROR ConfigurationManagerImpl::Init() { CHIP_ERROR err; + uint32_t rebootCount; bool failSafeArmed; // Initialize the generic implementation base class. @@ -71,6 +72,22 @@ CHIP_ERROR ConfigurationManagerImpl::Init() } #endif // CHIP_DEVICE_CONFIG_ENABLE_FACTORY_PROVISIONING + if (ZephyrConfig::ConfigValueExists(ZephyrConfig::kCounterKey_RebootCount)) + { + err = GetRebootCount(rebootCount); + SuccessOrExit(err); + + // Do not increment reboot count if the value is going to overflow UINT16. + err = StoreRebootCount(rebootCount < UINT16_MAX ? rebootCount + 1 : rebootCount); + SuccessOrExit(err); + } + else + { + // The first boot after factory reset of the Node. + err = StoreRebootCount(1); + SuccessOrExit(err); + } + // If the fail-safe was armed when the device last shutdown, initiate a factory reset. if (GetFailSafeArmed(failSafeArmed) == CHIP_NO_ERROR && failSafeArmed) { @@ -84,6 +101,16 @@ CHIP_ERROR ConfigurationManagerImpl::Init() return err; } +CHIP_ERROR ConfigurationManagerImpl::GetRebootCount(uint32_t & rebootCount) +{ + return ReadConfigValue(ZephyrConfig::kCounterKey_RebootCount, rebootCount); +} + +CHIP_ERROR ConfigurationManagerImpl::StoreRebootCount(uint32_t rebootCount) +{ + return WriteConfigValue(ZephyrConfig::kCounterKey_RebootCount, rebootCount); +} + void ConfigurationManagerImpl::InitiateFactoryReset() { PlatformMgr().ScheduleWork(DoFactoryReset); diff --git a/src/platform/Zephyr/ConfigurationManagerImpl.h b/src/platform/Zephyr/ConfigurationManagerImpl.h index a9f0346c906a24..bcca062af99771 100644 --- a/src/platform/Zephyr/ConfigurationManagerImpl.h +++ b/src/platform/Zephyr/ConfigurationManagerImpl.h @@ -36,6 +36,8 @@ namespace DeviceLayer { class ConfigurationManagerImpl : public Internal::GenericConfigurationManagerImpl { public: + CHIP_ERROR GetRebootCount(uint32_t & rebootCount) override; + CHIP_ERROR StoreRebootCount(uint32_t rebootCount) override; // This returns an instance of this class. static ConfigurationManagerImpl & GetDefaultInstance(); diff --git a/src/platform/Zephyr/DiagnosticDataProviderImpl.cpp b/src/platform/Zephyr/DiagnosticDataProviderImpl.cpp index 7ac6665dcbdd26..e627bb5a0d7296 100644 --- a/src/platform/Zephyr/DiagnosticDataProviderImpl.cpp +++ b/src/platform/Zephyr/DiagnosticDataProviderImpl.cpp @@ -27,6 +27,8 @@ #include #include +#include + #include namespace chip { @@ -74,5 +76,130 @@ CHIP_ERROR DiagnosticDataProviderImpl::GetCurrentHeapHighWatermark(uint64_t & cu #endif } +CHIP_ERROR DiagnosticDataProviderImpl::GetRebootCount(uint16_t & rebootCount) +{ + uint32_t count = 0; + CHIP_ERROR err = ConfigurationMgr().GetRebootCount(count); + + if (err == CHIP_NO_ERROR) + { + // If the value overflows, return UINT16 max value to provide best-effort number. + rebootCount = static_cast(count <= UINT16_MAX ? count : UINT16_MAX); + } + + return err; +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetBootReason(uint8_t & bootReason) +{ +#if CONFIG_HWINFO + uint32_t reason = 0; + + CHIP_ERROR err = CHIP_NO_ERROR; + + if (hwinfo_get_reset_cause(&reason) != 0) + { + return CHIP_ERROR_INCORRECT_STATE; + } + + if (reason & (RESET_POR | RESET_PIN)) + { + bootReason = BootReasonType::PowerOnReboot; + } + else if (reason & RESET_WATCHDOG) + { + bootReason = BootReasonType::SoftwareWatchdogReset; + } + else if (reason & RESET_BROWNOUT) + { + bootReason = BootReasonType::BrownOutReset; + } + else if (reason & (RESET_SOFTWARE | RESET_CPU_LOCKUP | RESET_DEBUG)) + { + bootReason = BootReasonType::SoftwareReset; + } + else + { + bootReason = BootReasonType::Unspecified; + } + + return err; +#else + return CHIP_ERROR_NOT_IMPLEMENTED; +#endif +} + +CHIP_ERROR DiagnosticDataProviderImpl::GetNetworkInterfaces(NetworkInterface ** netifpp) +{ +#if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF + NetworkInterface * head = NULL; + + for (Inet::InterfaceIterator interfaceIterator; interfaceIterator.HasCurrent(); interfaceIterator.Next()) + { + NetworkInterface * ifp = new NetworkInterface(); + + interfaceIterator.GetInterfaceName(ifp->Name, Inet::InterfaceId::kMaxIfNameLength); + ifp->name = CharSpan(ifp->Name, strlen(ifp->Name)); + ifp->fabricConnected = true; + Inet::InterfaceType interfaceType; + if (interfaceIterator.GetInterfaceType(interfaceType) == CHIP_NO_ERROR) + { + switch (interfaceType) + { + case Inet::InterfaceType::Unknown: + ifp->type = EMBER_ZCL_INTERFACE_TYPE_UNSPECIFIED; + break; + case Inet::InterfaceType::WiFi: + ifp->type = EMBER_ZCL_INTERFACE_TYPE_WI_FI; + break; + case Inet::InterfaceType::Ethernet: + ifp->type = EMBER_ZCL_INTERFACE_TYPE_ETHERNET; + break; + case Inet::InterfaceType::Thread: + ifp->type = EMBER_ZCL_INTERFACE_TYPE_THREAD; + break; + case Inet::InterfaceType::Cellular: + ifp->type = EMBER_ZCL_INTERFACE_TYPE_CELLULAR; + break; + } + } + else + { + ChipLogError(DeviceLayer, "Failed to get interface type"); + } + + ifp->offPremiseServicesReachableIPv4 = false; + ifp->offPremiseServicesReachableIPv6 = false; + + uint8_t addressSize; + if (interfaceIterator.GetHardwareAddress(ifp->MacAddress, addressSize, sizeof(ifp->MacAddress)) != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Failed to get network hardware address"); + } + else + { + ifp->hardwareAddress = ByteSpan(ifp->MacAddress, addressSize); + } + + head = ifp; + } + + *netifpp = head; + return CHIP_NO_ERROR; +#else + return CHIP_ERROR_NOT_IMPLEMENTED; +#endif +} + +void DiagnosticDataProviderImpl::ReleaseNetworkInterfaces(NetworkInterface * netifp) +{ + while (netifp) + { + NetworkInterface * del = netifp; + netifp = netifp->Next; + delete del; + } +} + } // namespace DeviceLayer } // namespace chip diff --git a/src/platform/Zephyr/DiagnosticDataProviderImpl.h b/src/platform/Zephyr/DiagnosticDataProviderImpl.h index 6505cf5eedff17..36eeef68422879 100644 --- a/src/platform/Zephyr/DiagnosticDataProviderImpl.h +++ b/src/platform/Zephyr/DiagnosticDataProviderImpl.h @@ -42,6 +42,11 @@ class DiagnosticDataProviderImpl : public DiagnosticDataProvider CHIP_ERROR GetCurrentHeapFree(uint64_t & currentHeapFree) override; CHIP_ERROR GetCurrentHeapUsed(uint64_t & currentHeapUsed) override; CHIP_ERROR GetCurrentHeapHighWatermark(uint64_t & currentHeapHighWatermark) override; + + CHIP_ERROR GetRebootCount(uint16_t & rebootCount) override; + CHIP_ERROR GetBootReason(uint8_t & bootReason) override; + CHIP_ERROR GetNetworkInterfaces(NetworkInterface ** netifpp) override; + void ReleaseNetworkInterfaces(NetworkInterface * netifp) override; }; } // namespace DeviceLayer diff --git a/src/platform/Zephyr/ZephyrConfig.cpp b/src/platform/Zephyr/ZephyrConfig.cpp index dadeabba34adc8..9bdbccb80d7c79 100644 --- a/src/platform/Zephyr/ZephyrConfig.cpp +++ b/src/platform/Zephyr/ZephyrConfig.cpp @@ -71,6 +71,11 @@ const ZephyrConfig::Key ZephyrConfig::kConfigKey_FailSafeArmed = CONFIG_KEY const ZephyrConfig::Key ZephyrConfig::kConfigKey_RegulatoryLocation = CONFIG_KEY(NAMESPACE_CONFIG "regulatory-location"); const ZephyrConfig::Key ZephyrConfig::kConfigKey_CountryCode = CONFIG_KEY(NAMESPACE_CONFIG "country-code"); const ZephyrConfig::Key ZephyrConfig::kConfigKey_Breadcrumb = CONFIG_KEY(NAMESPACE_CONFIG "breadcrumb"); + +// Keys stored in the counters namespace +const ZephyrConfig::Key ZephyrConfig::kCounterKey_RebootCount = CONFIG_KEY(NAMESPACE_COUNTERS "reboot-count"); +const ZephyrConfig::Key ZephyrConfig::kCounterKey_BootReason = CONFIG_KEY(NAMESPACE_COUNTERS "boot-reason"); + namespace { constexpr const char * sAllResettableConfigKeys[] = { diff --git a/src/platform/Zephyr/ZephyrConfig.h b/src/platform/Zephyr/ZephyrConfig.h index 0c3b038fa63c68..a43d3bfc368be6 100644 --- a/src/platform/Zephyr/ZephyrConfig.h +++ b/src/platform/Zephyr/ZephyrConfig.h @@ -63,6 +63,8 @@ class ZephyrConfig static const Key kConfigKey_RegulatoryLocation; static const Key kConfigKey_CountryCode; static const Key kConfigKey_Breadcrumb; + static const Key kCounterKey_RebootCount; + static const Key kCounterKey_BootReason; static CHIP_ERROR Init(void);