diff --git a/applications/matter_weather_station/prj.conf b/applications/matter_weather_station/prj.conf index feb76469e78e..cdb2ba531e49 100644 --- a/applications/matter_weather_station/prj.conf +++ b/applications/matter_weather_station/prj.conf @@ -80,7 +80,6 @@ CONFIG_MINIMAL_LIBC=y # Enable Diagnostic Logs feature CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS=y CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_CRASH_LOGS=y -CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_SAVE_CRASH_TO_SETTINGS=y CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_REMOVE_CRASH_AFTER_READ=y # Enable test event triggers for diagnostic logs testing purposes. diff --git a/applications/matter_weather_station/prj_release.conf b/applications/matter_weather_station/prj_release.conf index e22ed5f3a04b..27fc16d832b1 100644 --- a/applications/matter_weather_station/prj_release.conf +++ b/applications/matter_weather_station/prj_release.conf @@ -75,7 +75,6 @@ CONFIG_NCS_SAMPLE_MATTER_WATCHDOG=y # Enable Diagnostic Logs feature CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS=y CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_CRASH_LOGS=y -CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_SAVE_CRASH_TO_SETTINGS=y CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_REMOVE_CRASH_AFTER_READ=y # Enable test event triggers for diagnostic logs testing purposes. diff --git a/doc/nrf/protocols/matter/getting_started/advanced_kconfigs.rst b/doc/nrf/protocols/matter/getting_started/advanced_kconfigs.rst index d5c447d0148c..4a1ae9becec6 100644 --- a/doc/nrf/protocols/matter/getting_started/advanced_kconfigs.rst +++ b/doc/nrf/protocols/matter/getting_started/advanced_kconfigs.rst @@ -251,11 +251,6 @@ Only the latest crash data will be stored in the device's memory, meaning that i After receiving the read request from the Matter controller, the device reads the crash data and creates human readable logs at runtime. The device sends converted logs to the Matter controller as a response. -By default, the :ref:`ug_matter_diagnostic_logs_snippet` enables copying the crash data to Zephyr's settings storage at the first boot after a crash. -This operation allows the device to keep crash data even if a power breakdown occurs, but it will use some space within the settings storage partition and you need to take it into account while setting the partition size. -If the new crash data is the same as the previous one, the entry will not be updated. -You can disable saving crash data to the settings storage by setting the :kconfig:option:`CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_SAVE_CRASH_TO_SETTINGS` Kconfig option to ``n``. - After the crash data is successfully read, it will be removed and further read attempts will notify the user that there is no available data to read. To keep the crash log in the memory after reading it, set the :kconfig:option:`CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_REMOVE_CRASH_AFTER_READ` Kconfig option to ``n``. @@ -272,7 +267,6 @@ The snippet sets the following kconfig options: * :kconfig:option:`CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS` to ``y``. * :kconfig:option:`CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_CRASH_LOGS` to ``y``. - * :kconfig:option:`CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_SAVE_CRASH_TO_SETTINGS` to ``y``. * :kconfig:option:`CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_REMOVE_CRASH_AFTER_READ` to ``y``. To use the snippet when building a sample, add ``-S diagnostic-logs`` to the west arguments list. diff --git a/samples/matter/common/snippets/diagnostic-logs/diagnostic_logs.conf b/samples/matter/common/snippets/diagnostic-logs/diagnostic_logs.conf index e79cf170e023..4493ca0c9d62 100644 --- a/samples/matter/common/snippets/diagnostic-logs/diagnostic_logs.conf +++ b/samples/matter/common/snippets/diagnostic-logs/diagnostic_logs.conf @@ -6,7 +6,6 @@ CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS=y CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_CRASH_LOGS=y -CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_SAVE_CRASH_TO_SETTINGS=y CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_REMOVE_CRASH_AFTER_READ=y # Enable test event triggers for diagnostic logs testing purposes. diff --git a/samples/matter/common/src/diagnostic/Kconfig b/samples/matter/common/src/diagnostic/Kconfig index feab206cd2a6..9f84549209bc 100644 --- a/samples/matter/common/src/diagnostic/Kconfig +++ b/samples/matter/common/src/diagnostic/Kconfig @@ -6,7 +6,7 @@ menuconfig NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS bool "Enable diagnostics logs support" - select CHIP_ENABLE_BDX_LOG_TRANSFER + imply CHIP_ENABLE_BDX_LOG_TRANSFER help Provides support for diagnostics logs. Diagnostics logs allow the Matter controller to read end-user, network and crash logs from the Matter device. @@ -40,14 +40,6 @@ config NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_REMOVE_CRASH_AFTER_READ Removes the last crash data after reading it by Matter controller. Disable this option to read the last crash multiple times. -config NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_SAVE_CRASH_TO_SETTINGS - bool "Save crash logs to settings storage" - select NCS_SAMPLE_MATTER_PERSISTENT_STORAGE - help - Saves crash logs to settings storage at the boot time if there is an entry in the retention memory. - If this option is disabled crash logs will be saved only in the retention memory and can be lost - during physical power down. - endif # NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_CRASH_LOGS config NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_TEST diff --git a/samples/matter/common/src/diagnostic/diagnostic_logs_crash.cpp b/samples/matter/common/src/diagnostic/diagnostic_logs_crash.cpp index 235222af4948..e671b550832a 100644 --- a/samples/matter/common/src/diagnostic/diagnostic_logs_crash.cpp +++ b/samples/matter/common/src/diagnostic/diagnostic_logs_crash.cpp @@ -10,7 +10,16 @@ #include #include +#include +#include + using namespace Nrf; +using namespace chip; + +namespace +{ +const struct device *kCrashDataMem = DEVICE_DT_GET(DT_NODELABEL(crash_retention)); +} // namespace #define Verify(expr, value) \ do { \ @@ -127,6 +136,70 @@ bool CrashData::Collect(const char *format, ...) return true; } +void CrashData::ClearState() +{ + mLastLine = 0; +} + +CHIP_ERROR CrashData::LoadCrashData() +{ + int ret = retention_is_valid(kCrashDataMem); + VerifyOrReturnError(ret == 1, CHIP_ERROR_NOT_FOUND); + ret = retention_read(kCrashDataMem, 0, reinterpret_cast(GetDescription()), + sizeof(*GetDescription())); + VerifyOrReturnError(0 == ret, System::MapErrorZephyr(ret)); + + return CHIP_NO_ERROR; +} + +size_t CrashData::GetLogsSize() +{ + size_t outSize = 0; + + VerifyOrExit(CHIP_NO_ERROR == LoadCrashData(), ); + outSize = CalculateSize(); + +exit: + /* Size calculation requires collecting all logs to get the summarized size. Clear state after that to start + * exact log collection from the beginning when requested. */ + ClearState(); + + return outSize; +} + +CHIP_ERROR CrashData::GetLogs(chip::MutableByteSpan &outBuffer, bool &outIsEndOfLog) +{ + size_t convertedSize = 0; + CHIP_ERROR err = LoadCrashData(); + VerifyOrExit(CHIP_NO_ERROR == err, ); + + convertedSize = + ProcessConversionToLog(reinterpret_cast(outBuffer.data()), outBuffer.size(), outIsEndOfLog); + outBuffer.reduce_size(convertedSize); + + ChipLogDetail(Zcl, "Getting log with size %zu. Is end of log: %s", convertedSize, + outIsEndOfLog ? "true" : "false"); + +exit: + /* If it is the end of the log message we can clear the state, otherwise, we need to keep Esf data for + * the following bunch */ + if (outIsEndOfLog || convertedSize == 0 || err != CHIP_NO_ERROR) { + ClearState(); + } + + return err; +} + +CHIP_ERROR CrashData::FinishLogs() +{ +#ifdef CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_REMOVE_CRASH_AFTER_READ + int ret = retention_clear(kCrashDataMem); + VerifyOrReturnError(0 == ret, System::MapErrorZephyr(ret)); +#endif /* CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_REMOVE_CRASH_AFTER_READ */ + + return CHIP_NO_ERROR; +} + extern "C" { /* The actual code of the z_fatal_error function assigned as __real_ for linker wrapping purpose. diff --git a/samples/matter/common/src/diagnostic/diagnostic_logs_crash.h b/samples/matter/common/src/diagnostic/diagnostic_logs_crash.h index 287d7276938d..e99d4bcf4808 100644 --- a/samples/matter/common/src/diagnostic/diagnostic_logs_crash.h +++ b/samples/matter/common/src/diagnostic/diagnostic_logs_crash.h @@ -6,9 +6,16 @@ #pragma once +#include +#include + +#include "diagnostic_logs_provider.h" + #include #include +using namespace chip; + namespace Nrf { struct CrashDescription { @@ -46,10 +53,25 @@ static_assert(DT_REG_SIZE(DT_NODELABEL(crash_retention)) - 4 > sizeof(CrashDescr * MultithreadDump converts the information about the the thread from which the error occurred. Can be disabled using CONFIG_MULTITHREADING. */ -class CrashData { +class CrashData : public Nrf::Matter::DiagnosticLogsIntentIface { public: constexpr static size_t MaxSingleDumpSize = 100; + CHIP_ERROR GetLogs(chip::MutableByteSpan &outBuffer, bool &outIsEndOfLog) override; + CHIP_ERROR FinishLogs() override; + size_t GetLogsSize() override; + +private: + /* The source is obtained based on values from ARM Cortex vector table set in the ICSR register. */ + enum FaultSource { + HardFault = 3, + MemManageFault = 4, + BusFault = 5, + UsageFault = 6, + SecureFault = 7, + DebugMonitor = 12 + }; + /** * @brief Convert CrashDat to output string buffer that will contain a crash message. * @@ -81,17 +103,6 @@ class CrashData { */ size_t CalculateSize(); -private: - /* The source is obtained based on values from ARM Cortex vector table set in the ICSR register. */ - enum FaultSource { - HardFault = 3, - MemManageFault = 4, - BusFault = 5, - UsageFault = 6, - SecureFault = 7, - DebugMonitor = 12 - }; - const char *FaultSourceToStr(uint32_t source); bool Collect(const char *format, ...); @@ -99,6 +110,9 @@ class CrashData { bool BasicDump(); bool ReasonDump(); + CHIP_ERROR LoadCrashData(); + void ClearState(); + /* Actual crash data to be filled */ CrashDescription mDescription = {}; diff --git a/samples/matter/common/src/diagnostic/diagnostic_logs_provider.cpp b/samples/matter/common/src/diagnostic/diagnostic_logs_provider.cpp index 59b55c8051bf..0ee948e7a045 100644 --- a/samples/matter/common/src/diagnostic/diagnostic_logs_provider.cpp +++ b/samples/matter/common/src/diagnostic/diagnostic_logs_provider.cpp @@ -11,7 +11,7 @@ #endif #ifdef CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_CRASH_LOGS -#include +#include "diagnostic_logs_crash.h" #endif #include "diagnostic_logs_provider.h" @@ -25,9 +25,6 @@ using namespace Nrf::Matter; namespace { -#ifdef CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_CRASH_LOGS -const struct device *kCrashDataMem = DEVICE_DT_GET(DT_NODELABEL(crash_retention)); -#endif /* CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_CRASH_LOGS */ bool IsValidIntent(IntentEnum intent) { @@ -54,6 +51,45 @@ const char *GetIntentStr(IntentEnum intent) } /* namespace */ +void IntentData::Clear() +{ + if (!mIntentImpl) { + return; + } + + switch (mIntent) { + case chip::app::Clusters::DiagnosticLogs::IntentEnum::kCrashLogs: +#ifdef CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_CRASH_LOGS + chip::Platform::Delete(reinterpret_cast(mIntentImpl)); + break; +#endif /* CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_CRASH_LOGS */ + case chip::app::Clusters::DiagnosticLogs::IntentEnum::kNetworkDiag: + case chip::app::Clusters::DiagnosticLogs::IntentEnum::kEndUserSupport: + default: + break; + } +} + +CHIP_ERROR DiagnosticLogProvider::SetIntentImplementation(IntentEnum intent, IntentData &intentData) +{ + switch (intent) { + case IntentEnum::kCrashLogs: +#ifdef CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_CRASH_LOGS + intentData.mIntentImpl = Platform::New(); + if (!intentData.mIntentImpl) { + return CHIP_ERROR_NO_MEMORY; + } + break; +#endif /* CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_CRASH_LOGS */ + case IntentEnum::kNetworkDiag: + case IntentEnum::kEndUserSupport: + default: + intentData.mIntentImpl = nullptr; + break; + } + return CHIP_NO_ERROR; +} + CHIP_ERROR DiagnosticLogProvider::StartLogCollection(IntentEnum intent, LogSessionHandle &outHandle, Optional &outTimeStamp, Optional &outTimeSinceBoot) @@ -63,7 +99,13 @@ CHIP_ERROR DiagnosticLogProvider::StartLogCollection(IntentEnum intent, LogSessi uint16_t freeSlot = mIntentMap.GetFirstFreeSlot(); VerifyOrReturnError(freeSlot < kMaxLogSessionHandle, CHIP_ERROR_NO_MEMORY); - mIntentMap.Insert(freeSlot, std::move(intent)); + IntentData intentData; + intentData.mIntent = intent; + CHIP_ERROR err = SetIntentImplementation(intent, intentData); + + VerifyOrReturnError(err == CHIP_NO_ERROR, err); + + mIntentMap.Insert(freeSlot, std::move(intentData)); outHandle = freeSlot; ChipLogDetail(Zcl, "Starting Log collection for %s with session handle %d", GetIntentStr(intent), outHandle); @@ -78,36 +120,40 @@ CHIP_ERROR DiagnosticLogProvider::EndLogCollection(LogSessionHandle sessionHandl CHIP_ERROR err = CHIP_NO_ERROR; - IntentEnum intent = mIntentMap[sessionHandle]; - - /* Old intent is no needed anymore*/ - mIntentMap.Erase(sessionHandle); - /* Do the specific action for the removing intent */ - switch (intent) { + switch (mIntentMap[sessionHandle].mIntent) { case IntentEnum::kEndUserSupport: #ifndef CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_TEST /* TODO: add support for End User Intent */ - return CHIP_ERROR_NOT_IMPLEMENTED; + err = CHIP_ERROR_NOT_IMPLEMENTED; + break; #endif /* CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_TEST */ case IntentEnum::kNetworkDiag: #ifndef CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_TEST /* TODO: add support for Network Diagnostics */ - return CHIP_ERROR_NOT_IMPLEMENTED; + err = CHIP_ERROR_NOT_IMPLEMENTED; + break; #endif /* CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_TEST */ case IntentEnum::kCrashLogs: #ifdef CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_CRASH_LOGS - err = FinishCrashLogs(); + if (mIntentMap[sessionHandle].mIntentImpl) { + err = mIntentMap[sessionHandle].mIntentImpl->FinishLogs(); + } break; #else - return CHIP_ERROR_NOT_IMPLEMENTED; + err = CHIP_ERROR_NOT_IMPLEMENTED; + break; #endif /* CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_CRASH_LOGS */ default: - return CHIP_ERROR_INVALID_ARGUMENT; + err = CHIP_ERROR_INVALID_ARGUMENT; + break; } ChipLogDetail(Zcl, "Ending Log collection for %s with session handle %d", - GetIntentStr(mIntentMap[sessionHandle]), sessionHandle); + GetIntentStr(mIntentMap[sessionHandle].mIntent), sessionHandle); + + /* Old intent is not needed anymore*/ + mIntentMap.Erase(sessionHandle); return err; } @@ -120,7 +166,7 @@ CHIP_ERROR DiagnosticLogProvider::CollectLog(LogSessionHandle sessionHandle, Mut VerifyOrReturnError(sessionHandle < kMaxLogSessionHandle, CHIP_ERROR_NO_MEMORY); VerifyOrReturnError(mIntentMap.Contains(sessionHandle), CHIP_ERROR_INTERNAL); - switch (mIntentMap[sessionHandle]) { + switch (mIntentMap[sessionHandle].mIntent) { case IntentEnum::kEndUserSupport: #ifndef CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_TEST /* TODO: add support for End User Intent */ @@ -128,14 +174,14 @@ CHIP_ERROR DiagnosticLogProvider::CollectLog(LogSessionHandle sessionHandle, Mut #endif /* CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_TEST */ case IntentEnum::kNetworkDiag: #ifdef CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_TEST - err = GetTestingLogs(mIntentMap[sessionHandle], outBuffer, outIsEndOfLog); + err = GetTestingLogs(mIntentMap[sessionHandle].mIntent, outBuffer, outIsEndOfLog); break; #endif /* CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_TEST */ /* TODO: add support for Network Diag Intent */ return CHIP_ERROR_NOT_IMPLEMENTED; case IntentEnum::kCrashLogs: #ifdef CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_CRASH_LOGS - err = GetCrashLogs(outBuffer, outIsEndOfLog); + err = mIntentMap[sessionHandle].mIntentImpl->GetLogs(outBuffer, outIsEndOfLog); break; #else return CHIP_ERROR_NOT_IMPLEMENTED; @@ -164,9 +210,11 @@ size_t DiagnosticLogProvider::GetSizeForIntent(IntentEnum intent) /* TODO: add support for Network Diag Intent */ break; #ifdef CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_CRASH_LOGS - case IntentEnum::kCrashLogs: - logSize = GetCrashLogsSize(); + case IntentEnum::kCrashLogs: { + Platform::UniquePtr crashData(Platform::New()); + logSize = crashData->GetLogsSize(); break; + } #endif /* CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_CRASH_LOGS */ default: break; @@ -202,10 +250,6 @@ CHIP_ERROR DiagnosticLogProvider::GetLogForIntent(IntentEnum intent, MutableByte CHIP_ERROR DiagnosticLogProvider::Init() { -#ifdef CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_SAVE_CRASH_TO_SETTINGS - ReturnErrorOnFailure(MoveCrashLogsToNVS()); -#endif - return CHIP_NO_ERROR; } @@ -216,133 +260,6 @@ void emberAfDiagnosticLogsClusterInitCallback(chip::EndpointId endpoint) DiagnosticLogsServer::Instance().SetDiagnosticLogsProviderDelegate(endpoint, &logProvider); } -#ifdef CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_CRASH_LOGS - -CHIP_ERROR DiagnosticLogProvider::LoadCrashData(CrashData *crashData) -{ - VerifyOrReturnError(crashData, CHIP_ERROR_INVALID_ARGUMENT); - -#ifdef CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_SAVE_CRASH_TO_SETTINGS - VerifyOrReturnError(Nrf::GetPersistentStorage().NonSecureHasEntry(&mCrashLogsStorageNode), - CHIP_ERROR_NOT_FOUND); - size_t outSize = 0; - VerifyOrReturnError(Nrf::GetPersistentStorage().NonSecureLoad( - &mCrashLogsStorageNode, reinterpret_cast(crashData->GetDescription()), - sizeof(*crashData->GetDescription()), outSize), - CHIP_ERROR_INTERNAL); - VerifyOrReturnError(outSize == sizeof(*crashData->GetDescription()), CHIP_ERROR_INTERNAL); -#else - int ret = retention_is_valid(kCrashDataMem); - VerifyOrReturnError(ret == 1, CHIP_ERROR_NOT_FOUND); - ret = retention_read(kCrashDataMem, 0, reinterpret_cast(crashData->GetDescription()), - sizeof(*crashData->GetDescription())); - VerifyOrReturnError(0 == ret, System::MapErrorZephyr(ret)); -#endif /* CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_SAVE_CRASH_TO_SETTINGS */ - - return CHIP_NO_ERROR; -} - -size_t DiagnosticLogProvider::GetCrashLogsSize() -{ - CrashData *crashData = Platform::New(); - if (!crashData) { - return 0; - } - - size_t outSize = 0; - - VerifyOrExit(CHIP_NO_ERROR == LoadCrashData(crashData), ); - - outSize = crashData->CalculateSize(); - -exit: - Platform::Delete(crashData); - - return outSize; -} - -CHIP_ERROR DiagnosticLogProvider::GetCrashLogs(chip::MutableByteSpan &outBuffer, bool &outIsEndOfLog) -{ - size_t convertedSize = 0; - CHIP_ERROR err = CHIP_NO_ERROR; - - /* if mCrashData is not Null then it means that it is the following data bunch */ - if (!mCrashData) { - /* mCrashData is not initialized, so this is the first bunch - allocate the memory */ - mCrashData = Platform::New(); - if (!mCrashData) { - return CHIP_ERROR_NO_MEMORY; - } - err = LoadCrashData(mCrashData); - VerifyOrExit(CHIP_NO_ERROR == err, ); - } - - convertedSize = mCrashData->ProcessConversionToLog(reinterpret_cast(outBuffer.data()), outBuffer.size(), - outIsEndOfLog); - outBuffer.reduce_size(convertedSize); - - ChipLogDetail(Zcl, "Getting log with size %zu. Is end of log: %s", convertedSize, - outIsEndOfLog ? "true" : "false"); - -exit: - /* If it is the end of the log message we can release allocated memory, otherwise, we need to keep Esf data for - * the following bunch */ - if (outIsEndOfLog || convertedSize == 0 || err != CHIP_NO_ERROR) { - Platform::Delete(mCrashData); - mCrashData = nullptr; - } - - return err; -} - -CHIP_ERROR DiagnosticLogProvider::FinishCrashLogs() -{ -#ifdef CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_REMOVE_CRASH_AFTER_READ -#ifdef CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_SAVE_CRASH_TO_SETTINGS - VerifyOrReturnError(Nrf::GetPersistentStorage().NonSecureRemove(&mCrashLogsStorageNode), CHIP_ERROR_INTERNAL); -#endif /* CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_SAVE_CRASH_TO_SETTINGS */ - int ret = retention_clear(kCrashDataMem); - VerifyOrReturnError(0 == ret, System::MapErrorZephyr(ret)); -#endif /* CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_REMOVE_CRASH_AFTER_READ */ - - return CHIP_NO_ERROR; -} - -#ifdef CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_SAVE_CRASH_TO_SETTINGS -CHIP_ERROR DiagnosticLogProvider::MoveCrashLogsToNVS() -{ - /* Check if something is in the retained memory */ - CrashDescription description; - if (1 == retention_is_valid(kCrashDataMem)) { - int ret = retention_read(kCrashDataMem, 0, reinterpret_cast(&description), - sizeof(description)); - VerifyOrReturnError(0 == ret, System::MapErrorZephyr(ret)); - /* Check whether the entry already exists */ - CrashDescription descriptionToCompare; - size_t outSize = 0; - if (Nrf::GetPersistentStorage().NonSecureHasEntry(&mCrashLogsStorageNode)) { - VerifyOrReturnError(Nrf::GetPersistentStorage().NonSecureLoad( - &mCrashLogsStorageNode, - reinterpret_cast(&descriptionToCompare), - sizeof(descriptionToCompare), outSize), - CHIP_ERROR_READ_FAILED); - if (0 == memcmp(&descriptionToCompare, &description, sizeof(description))) { - ret = retention_clear(kCrashDataMem); - VerifyOrReturnError(0 == ret, System::MapErrorZephyr(ret)); - return CHIP_NO_ERROR; - } - } - - VerifyOrReturnError(Nrf::GetPersistentStorage().NonSecureStore(&mCrashLogsStorageNode, &description, - sizeof(description)), - CHIP_ERROR_WRITE_FAILED); - } - - return CHIP_NO_ERROR; -} -#endif /* CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_SAVE_CRASH_TO_SETTINGS */ -#endif /* CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_CRASH_LOGS */ - #ifdef CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_TEST bool DiagnosticLogProvider::StoreTestingLog(IntentEnum intent, char *text, size_t textSize) @@ -412,7 +329,7 @@ CHIP_ERROR DiagnosticLogProvider::GetTestingLogs(IntentEnum intent, chip::Mutabl } ChipLogDetail(Zcl, "Sending %zu B of logs, left bytes: %zu, is the end of logs: %d", sizeToRead, - *currentBufferSize, outIsEndOfLog); + *currentBufferSize, outIsEndOfLog); outBuffer.reduce_size(sizeToRead); diff --git a/samples/matter/common/src/diagnostic/diagnostic_logs_provider.h b/samples/matter/common/src/diagnostic/diagnostic_logs_provider.h index c996c161f385..db0372033368 100644 --- a/samples/matter/common/src/diagnostic/diagnostic_logs_provider.h +++ b/samples/matter/common/src/diagnostic/diagnostic_logs_provider.h @@ -6,12 +6,6 @@ #pragma once -#ifdef CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_CRASH_LOGS -#include "diagnostic_logs_crash.h" -#include -#endif - -#include "persistent_storage/persistent_storage.h" #include "util/finite_map.h" #include @@ -20,6 +14,74 @@ namespace Nrf::Matter { +class DiagnosticLogsIntentIface { +public: + /** + * @brief Get the captured logs size. + * + * @return size of captured logs in bytes + */ + virtual size_t GetLogsSize() = 0; + + /** + * @brief Get the captured logs. + * + * @param outBuffer output buffer to store the logs + * @param outIsEndOfLog flag informing whether the stored data is complete log or one of the few chunks + * + * @return size of captured logs in bytes + */ + virtual CHIP_ERROR GetLogs(chip::MutableByteSpan &outBuffer, bool &outIsEndOfLog) = 0; + + /** + * @brief Finish the log capturing. This method is used to perform potential clean up after session. + */ + virtual CHIP_ERROR FinishLogs() = 0; +}; + +struct IntentData { + chip::app::Clusters::DiagnosticLogs::IntentEnum mIntent = + chip::app::Clusters::DiagnosticLogs::IntentEnum::kUnknownEnumValue; + DiagnosticLogsIntentIface *mIntentImpl = nullptr; + + IntentData() {} + + /* Disable copy semantics and implement move, bool and == semantics according to the FiniteMap + * requirements. */ + IntentData(const IntentData &other) = delete; + IntentData &operator=(const IntentData &other) = delete; + + IntentData(IntentData &&other) + { + mIntent = other.mIntent; + mIntentImpl = other.mIntentImpl; + /* Nullptr the copied data to prevent from deleting it by the source. */ + other.mIntentImpl = nullptr; + } + + IntentData &operator=(IntentData &&other) + { + if (this != &other) { + Clear(); + mIntent = other.mIntent; + mIntentImpl = other.mIntentImpl; + /* Nullptr the copied data to prevent from deleting it by the source. */ + other.mIntentImpl = nullptr; + } + return *this; + } + + operator bool() const { return true; } + bool operator==(const IntentData &other) + { + return mIntent == other.mIntent && mIntentImpl == other.mIntentImpl; + } + + void Clear(); + + ~IntentData() { Clear(); } +}; + class DiagnosticLogProvider : public chip::app::Clusters::DiagnosticLogs::DiagnosticLogsProviderDelegate { public: /** @@ -36,9 +98,6 @@ class DiagnosticLogProvider : public chip::app::Clusters::DiagnosticLogs::Diagno /** * @brief Initialize the diagnostic log provider module * - * @note This method moves the crash log from the retained memory to the settings NVS if the - CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_SAVE_CRASH_TO_SETTINGS option is set. - * * @retval CHIP_ERROR_READ_FAILED if the NVS storage contains a crash log entry, but it cannot be loaded. * @retval CHIP_ERROR_WRITE_FAILED if a new crash data could not be stored in the NVS storage. * @retval other CHIP_ERROR values that come from internal methods. @@ -77,30 +136,10 @@ class DiagnosticLogProvider : public chip::app::Clusters::DiagnosticLogs::Diagno DiagnosticLogProvider(DiagnosticLogProvider &&) = delete; DiagnosticLogProvider &operator=(DiagnosticLogProvider &&) = delete; - /* Crash logs */ -#ifdef CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_CRASH_LOGS - CHIP_ERROR LoadCrashData(CrashData *crashData); - CHIP_ERROR GetCrashLogs(chip::MutableByteSpan &outBuffer, bool &outIsEndOfLog); - CHIP_ERROR FinishCrashLogs(); - size_t GetCrashLogsSize(); - -#ifdef CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_SAVE_CRASH_TO_SETTINGS - DiagnosticLogProvider() - : mDiagnosticLogsStorageNode("dl", strlen("dl")), - mCrashLogsStorageNode("cl", strlen("cl"), &mDiagnosticLogsStorageNode) - { - } - CHIP_ERROR MoveCrashLogsToNVS(); - - Nrf::PersistentStorageNode mDiagnosticLogsStorageNode; - Nrf::PersistentStorageNode mCrashLogsStorageNode; -#endif - Nrf::CrashData *mCrashData = nullptr; -#endif - -#ifndef CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_SAVE_CRASH_TO_SETTINGS DiagnosticLogProvider() = default; -#endif + + CHIP_ERROR SetIntentImplementation(chip::app::Clusters::DiagnosticLogs::IntentEnum intent, + IntentData &intentData); #ifdef CONFIG_NCS_SAMPLE_MATTER_DIAGNOSTIC_LOGS_TEST size_t GetTestingLogsSize(chip::app::Clusters::DiagnosticLogs::IntentEnum intent); @@ -116,7 +155,8 @@ class DiagnosticLogProvider : public chip::app::Clusters::DiagnosticLogs::Diagno size_t mReadNetworkLogsOffset = 0; #endif - Nrf::FiniteMap mIntentMap; + Nrf::FiniteMap + mIntentMap; }; } /* namespace Nrf::Matter */