blob: 40b8e84443ce4e511bb07559131e09b1ce2eff26 [file] [log] [blame]
/**
*
* Copyright (c) 2021 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <app-common/zap-generated/cluster-objects.h>
#include <app/CommandHandler.h>
#include <app/CommandHandlerInterface.h>
#include <app/ConcreteCommandPath.h>
#include <app/clusters/diagnostic-logs-server/diagnostic-logs-server.h>
#include <app/util/af.h>
#include <lib/support/BytesCircularBuffer.h>
#include <array>
CHIP_ERROR DiagnosticLogsCommandHandler::PushLog(const chip::ByteSpan & payload)
{
chip::System::Clock::Milliseconds32 now = chip::System::SystemClock().GetMonotonicTimestamp();
uint32_t timeMs = now.count();
chip::ByteSpan payloadTime(reinterpret_cast<uint8_t *>(&timeMs), sizeof(timeMs));
return mBuffer.Push(payloadTime, payload);
}
void DiagnosticLogsCommandHandler::InvokeCommand(HandlerContext & handlerContext)
{
HandleCommand<chip::app::Clusters::DiagnosticLogs::Commands::RetrieveLogsRequest::DecodableType>(
handlerContext, [&](auto & _u, auto & payload) {
if (payload.requestedProtocol == chip::app::Clusters::DiagnosticLogs::LogsTransferProtocol::kUnknownEnumValue)
{
handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath,
chip::Protocols::InteractionModel::Status::InvalidCommand);
return;
}
switch (payload.intent)
{
case chip::app::Clusters::DiagnosticLogs::LogsIntent::kEndUserSupport: {
chip::app::Clusters::DiagnosticLogs::Commands::RetrieveLogsResponse::Type response;
if (mBuffer.IsEmpty())
{
response.status = chip::app::Clusters::DiagnosticLogs::LogsStatus::kNoLogs;
handlerContext.mCommandHandler.AddResponse(handlerContext.mRequestPath, response);
break;
}
size_t logSize = mBuffer.GetFrontSize();
chip::System::Clock::Milliseconds32::rep timeMs;
VerifyOrDie(logSize > sizeof(timeMs));
std::unique_ptr<uint8_t, decltype(&chip::Platform::MemoryFree)> buf(
reinterpret_cast<uint8_t *>(chip::Platform::MemoryAlloc(logSize)), &chip::Platform::MemoryFree);
if (!buf)
{
response.status = chip::app::Clusters::DiagnosticLogs::LogsStatus::kBusy;
handlerContext.mCommandHandler.AddResponse(handlerContext.mRequestPath, response);
break;
}
// The entry is | time (4 bytes) | content (var size) |
chip::MutableByteSpan entry(buf.get(), logSize);
CHIP_ERROR err = mBuffer.ReadFront(entry);
VerifyOrDie(err == CHIP_NO_ERROR);
timeMs = *reinterpret_cast<decltype(timeMs) *>(buf.get());
response.status = chip::app::Clusters::DiagnosticLogs::LogsStatus::kSuccess;
response.content = chip::ByteSpan(buf.get() + sizeof(timeMs), logSize - sizeof(timeMs));
response.timeStamp = timeMs;
handlerContext.mCommandHandler.AddResponse(handlerContext.mRequestPath, response);
}
break;
case chip::app::Clusters::DiagnosticLogs::LogsIntent::kNetworkDiag: {
chip::app::Clusters::DiagnosticLogs::Commands::RetrieveLogsResponse::Type response;
response.status = chip::app::Clusters::DiagnosticLogs::LogsStatus::kNoLogs;
handlerContext.mCommandHandler.AddResponse(handlerContext.mRequestPath, response);
}
break;
case chip::app::Clusters::DiagnosticLogs::LogsIntent::kCrashLogs: {
chip::app::Clusters::DiagnosticLogs::Commands::RetrieveLogsResponse::Type response;
response.status = chip::app::Clusters::DiagnosticLogs::LogsStatus::kNoLogs;
handlerContext.mCommandHandler.AddResponse(handlerContext.mRequestPath, response);
}
break;
case chip::app::Clusters::DiagnosticLogs::LogsIntent::kUnknownEnumValue: {
handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath,
chip::Protocols::InteractionModel::Status::InvalidCommand);
break;
}
}
});
}
bool emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback(
chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath,
const chip::app::Clusters::DiagnosticLogs::Commands::RetrieveLogsRequest::DecodableType & commandData)
{
// TODO: Shouldn't the default "no-op" impl return some sort of error?
EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS;
emberAfSendImmediateDefaultResponse(status);
return true;
}
void MatterDiagnosticLogsPluginServerInitCallback() {}