blob: 8fde99d23a1489242deac09d782dba277bf0a67c [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.
*/
// THIS FILE IS GENERATED BY ZAP
#include <cinttypes>
#include <cstdint>
#include "app/common/gen/af-structs.h"
#include "app/common/gen/cluster-id.h"
#include "app/common/gen/command-id.h"
#include "app/util/util.h"
#include "callback.h"
#include <app/InteractionModelEngine.h>
// Currently we need some work to keep compatible with ember lib.
#include <app/util/ember-compatibility-functions.h>
namespace chip {
namespace app {
// Cluster specific command parsing
namespace clusters {
namespace DiagnosticLogs {
void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv)
{
// We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV
// When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error.
// Any error value TLVUnpackError means we have received an illegal value.
// The following variables are used for all commands to save code size.
CHIP_ERROR TLVError = CHIP_NO_ERROR;
CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
uint32_t validArgumentCount = 0;
uint32_t expectArgumentCount = 0;
uint32_t currentDecodeTagId = 0;
bool wasHandled = false;
{
switch (aCommandId)
{
case ZCL_RETRIEVE_LOGS_REQUEST_COMMAND_ID: {
expectArgumentCount = 3;
uint8_t intent;
uint8_t requestedProtocol;
chip::ByteSpan transferFileDesignator;
bool argExists[3];
memset(argExists, 0, sizeof argExists);
while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
// Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element.
// Skip this element if it is not a ContextTag, not consider it as an error if other values are valid.
if (!TLV::IsContextTag(aDataTlv.GetTag()))
{
continue;
}
currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag());
if (currentDecodeTagId < 3)
{
if (argExists[currentDecodeTagId])
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
else
{
argExists[currentDecodeTagId] = true;
validArgumentCount++;
}
}
switch (currentDecodeTagId)
{
case 0:
TLVUnpackError = aDataTlv.Get(intent);
break;
case 1:
TLVUnpackError = aDataTlv.Get(requestedProtocol);
break;
case 2: {
const uint8_t * data = nullptr;
TLVUnpackError = aDataTlv.GetDataPtr(data);
transferFileDesignator = chip::ByteSpan(data, aDataTlv.GetLength());
}
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback(apCommandObj, intent, requestedProtocol,
transferFileDesignator);
}
break;
}
default: {
// Unrecognized command ID, error status will apply.
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
Protocols::SecureChannel::Id,
Protocols::InteractionModel::ProtocolCode::UnsupportedCommand);
ChipLogError(Zcl, "Unknown command %" PRIx32 " for cluster %" PRIx32, aCommandId, ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID);
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand);
ChipLogProgress(Zcl,
"Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT
", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32,
validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
}
}
} // namespace DiagnosticLogs
namespace GeneralCommissioning {
void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv)
{
// We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV
// When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error.
// Any error value TLVUnpackError means we have received an illegal value.
// The following variables are used for all commands to save code size.
CHIP_ERROR TLVError = CHIP_NO_ERROR;
CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
uint32_t validArgumentCount = 0;
uint32_t expectArgumentCount = 0;
uint32_t currentDecodeTagId = 0;
bool wasHandled = false;
{
switch (aCommandId)
{
case ZCL_ARM_FAIL_SAFE_COMMAND_ID: {
expectArgumentCount = 3;
uint16_t expiryLengthSeconds;
uint64_t breadcrumb;
uint32_t timeoutMs;
bool argExists[3];
memset(argExists, 0, sizeof argExists);
while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
// Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element.
// Skip this element if it is not a ContextTag, not consider it as an error if other values are valid.
if (!TLV::IsContextTag(aDataTlv.GetTag()))
{
continue;
}
currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag());
if (currentDecodeTagId < 3)
{
if (argExists[currentDecodeTagId])
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
else
{
argExists[currentDecodeTagId] = true;
validArgumentCount++;
}
}
switch (currentDecodeTagId)
{
case 0:
TLVUnpackError = aDataTlv.Get(expiryLengthSeconds);
break;
case 1:
TLVUnpackError = aDataTlv.Get(breadcrumb);
break;
case 2:
TLVUnpackError = aDataTlv.Get(timeoutMs);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled =
emberAfGeneralCommissioningClusterArmFailSafeCallback(apCommandObj, expiryLengthSeconds, breadcrumb, timeoutMs);
}
break;
}
case ZCL_COMMISSIONING_COMPLETE_COMMAND_ID: {
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj);
break;
}
case ZCL_SET_REGULATORY_CONFIG_COMMAND_ID: {
expectArgumentCount = 4;
uint8_t location;
const uint8_t * countryCode;
uint64_t breadcrumb;
uint32_t timeoutMs;
bool argExists[4];
memset(argExists, 0, sizeof argExists);
while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
// Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element.
// Skip this element if it is not a ContextTag, not consider it as an error if other values are valid.
if (!TLV::IsContextTag(aDataTlv.GetTag()))
{
continue;
}
currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag());
if (currentDecodeTagId < 4)
{
if (argExists[currentDecodeTagId])
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
else
{
argExists[currentDecodeTagId] = true;
validArgumentCount++;
}
}
switch (currentDecodeTagId)
{
case 0:
TLVUnpackError = aDataTlv.Get(location);
break;
case 1:
// TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
TLVUnpackError = aDataTlv.GetDataPtr(countryCode);
break;
case 2:
TLVUnpackError = aDataTlv.Get(breadcrumb);
break;
case 3:
TLVUnpackError = aDataTlv.Get(timeoutMs);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback(
apCommandObj, location, const_cast<uint8_t *>(countryCode), breadcrumb, timeoutMs);
}
break;
}
default: {
// Unrecognized command ID, error status will apply.
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_GENERAL_COMMISSIONING_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
Protocols::SecureChannel::Id,
Protocols::InteractionModel::ProtocolCode::UnsupportedCommand);
ChipLogError(Zcl, "Unknown command %" PRIx32 " for cluster %" PRIx32, aCommandId, ZCL_GENERAL_COMMISSIONING_CLUSTER_ID);
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_GENERAL_COMMISSIONING_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand);
ChipLogProgress(Zcl,
"Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT
", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32,
validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
}
}
} // namespace GeneralCommissioning
namespace LevelControl {
void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv)
{
// We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV
// When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error.
// Any error value TLVUnpackError means we have received an illegal value.
// The following variables are used for all commands to save code size.
CHIP_ERROR TLVError = CHIP_NO_ERROR;
CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
uint32_t validArgumentCount = 0;
uint32_t expectArgumentCount = 0;
uint32_t currentDecodeTagId = 0;
bool wasHandled = false;
{
switch (aCommandId)
{
case ZCL_MOVE_COMMAND_ID: {
expectArgumentCount = 4;
uint8_t moveMode;
uint8_t rate;
uint8_t optionMask;
uint8_t optionOverride;
bool argExists[4];
memset(argExists, 0, sizeof argExists);
while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
// Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element.
// Skip this element if it is not a ContextTag, not consider it as an error if other values are valid.
if (!TLV::IsContextTag(aDataTlv.GetTag()))
{
continue;
}
currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag());
if (currentDecodeTagId < 4)
{
if (argExists[currentDecodeTagId])
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
else
{
argExists[currentDecodeTagId] = true;
validArgumentCount++;
}
}
switch (currentDecodeTagId)
{
case 0:
TLVUnpackError = aDataTlv.Get(moveMode);
break;
case 1:
TLVUnpackError = aDataTlv.Get(rate);
break;
case 2:
TLVUnpackError = aDataTlv.Get(optionMask);
break;
case 3:
TLVUnpackError = aDataTlv.Get(optionOverride);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfLevelControlClusterMoveCallback(apCommandObj, moveMode, rate, optionMask, optionOverride);
}
break;
}
case ZCL_MOVE_TO_LEVEL_COMMAND_ID: {
expectArgumentCount = 4;
uint8_t level;
uint16_t transitionTime;
uint8_t optionMask;
uint8_t optionOverride;
bool argExists[4];
memset(argExists, 0, sizeof argExists);
while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
// Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element.
// Skip this element if it is not a ContextTag, not consider it as an error if other values are valid.
if (!TLV::IsContextTag(aDataTlv.GetTag()))
{
continue;
}
currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag());
if (currentDecodeTagId < 4)
{
if (argExists[currentDecodeTagId])
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
else
{
argExists[currentDecodeTagId] = true;
validArgumentCount++;
}
}
switch (currentDecodeTagId)
{
case 0:
TLVUnpackError = aDataTlv.Get(level);
break;
case 1:
TLVUnpackError = aDataTlv.Get(transitionTime);
break;
case 2:
TLVUnpackError = aDataTlv.Get(optionMask);
break;
case 3:
TLVUnpackError = aDataTlv.Get(optionOverride);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled =
emberAfLevelControlClusterMoveToLevelCallback(apCommandObj, level, transitionTime, optionMask, optionOverride);
}
break;
}
case ZCL_MOVE_TO_LEVEL_WITH_ON_OFF_COMMAND_ID: {
expectArgumentCount = 2;
uint8_t level;
uint16_t transitionTime;
bool argExists[2];
memset(argExists, 0, sizeof argExists);
while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
// Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element.
// Skip this element if it is not a ContextTag, not consider it as an error if other values are valid.
if (!TLV::IsContextTag(aDataTlv.GetTag()))
{
continue;
}
currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag());
if (currentDecodeTagId < 2)
{
if (argExists[currentDecodeTagId])
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
else
{
argExists[currentDecodeTagId] = true;
validArgumentCount++;
}
}
switch (currentDecodeTagId)
{
case 0:
TLVUnpackError = aDataTlv.Get(level);
break;
case 1:
TLVUnpackError = aDataTlv.Get(transitionTime);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfLevelControlClusterMoveToLevelWithOnOffCallback(apCommandObj, level, transitionTime);
}
break;
}
case ZCL_MOVE_WITH_ON_OFF_COMMAND_ID: {
expectArgumentCount = 2;
uint8_t moveMode;
uint8_t rate;
bool argExists[2];
memset(argExists, 0, sizeof argExists);
while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
// Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element.
// Skip this element if it is not a ContextTag, not consider it as an error if other values are valid.
if (!TLV::IsContextTag(aDataTlv.GetTag()))
{
continue;
}
currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag());
if (currentDecodeTagId < 2)
{
if (argExists[currentDecodeTagId])
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
else
{
argExists[currentDecodeTagId] = true;
validArgumentCount++;
}
}
switch (currentDecodeTagId)
{
case 0:
TLVUnpackError = aDataTlv.Get(moveMode);
break;
case 1:
TLVUnpackError = aDataTlv.Get(rate);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfLevelControlClusterMoveWithOnOffCallback(apCommandObj, moveMode, rate);
}
break;
}
case ZCL_STEP_COMMAND_ID: {
expectArgumentCount = 5;
uint8_t stepMode;
uint8_t stepSize;
uint16_t transitionTime;
uint8_t optionMask;
uint8_t optionOverride;
bool argExists[5];
memset(argExists, 0, sizeof argExists);
while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
// Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element.
// Skip this element if it is not a ContextTag, not consider it as an error if other values are valid.
if (!TLV::IsContextTag(aDataTlv.GetTag()))
{
continue;
}
currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag());
if (currentDecodeTagId < 5)
{
if (argExists[currentDecodeTagId])
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
else
{
argExists[currentDecodeTagId] = true;
validArgumentCount++;
}
}
switch (currentDecodeTagId)
{
case 0:
TLVUnpackError = aDataTlv.Get(stepMode);
break;
case 1:
TLVUnpackError = aDataTlv.Get(stepSize);
break;
case 2:
TLVUnpackError = aDataTlv.Get(transitionTime);
break;
case 3:
TLVUnpackError = aDataTlv.Get(optionMask);
break;
case 4:
TLVUnpackError = aDataTlv.Get(optionOverride);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfLevelControlClusterStepCallback(apCommandObj, stepMode, stepSize, transitionTime, optionMask,
optionOverride);
}
break;
}
case ZCL_STEP_WITH_ON_OFF_COMMAND_ID: {
expectArgumentCount = 3;
uint8_t stepMode;
uint8_t stepSize;
uint16_t transitionTime;
bool argExists[3];
memset(argExists, 0, sizeof argExists);
while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
// Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element.
// Skip this element if it is not a ContextTag, not consider it as an error if other values are valid.
if (!TLV::IsContextTag(aDataTlv.GetTag()))
{
continue;
}
currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag());
if (currentDecodeTagId < 3)
{
if (argExists[currentDecodeTagId])
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
else
{
argExists[currentDecodeTagId] = true;
validArgumentCount++;
}
}
switch (currentDecodeTagId)
{
case 0:
TLVUnpackError = aDataTlv.Get(stepMode);
break;
case 1:
TLVUnpackError = aDataTlv.Get(stepSize);
break;
case 2:
TLVUnpackError = aDataTlv.Get(transitionTime);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfLevelControlClusterStepWithOnOffCallback(apCommandObj, stepMode, stepSize, transitionTime);
}
break;
}
case ZCL_STOP_COMMAND_ID: {
expectArgumentCount = 2;
uint8_t optionMask;
uint8_t optionOverride;
bool argExists[2];
memset(argExists, 0, sizeof argExists);
while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
// Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element.
// Skip this element if it is not a ContextTag, not consider it as an error if other values are valid.
if (!TLV::IsContextTag(aDataTlv.GetTag()))
{
continue;
}
currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag());
if (currentDecodeTagId < 2)
{
if (argExists[currentDecodeTagId])
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
else
{
argExists[currentDecodeTagId] = true;
validArgumentCount++;
}
}
switch (currentDecodeTagId)
{
case 0:
TLVUnpackError = aDataTlv.Get(optionMask);
break;
case 1:
TLVUnpackError = aDataTlv.Get(optionOverride);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfLevelControlClusterStopCallback(apCommandObj, optionMask, optionOverride);
}
break;
}
case ZCL_STOP_WITH_ON_OFF_COMMAND_ID: {
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfLevelControlClusterStopWithOnOffCallback(apCommandObj);
break;
}
default: {
// Unrecognized command ID, error status will apply.
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_LEVEL_CONTROL_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
Protocols::SecureChannel::Id,
Protocols::InteractionModel::ProtocolCode::UnsupportedCommand);
ChipLogError(Zcl, "Unknown command %" PRIx32 " for cluster %" PRIx32, aCommandId, ZCL_LEVEL_CONTROL_CLUSTER_ID);
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_LEVEL_CONTROL_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand);
ChipLogProgress(Zcl,
"Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT
", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32,
validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
}
}
} // namespace LevelControl
namespace NetworkCommissioning {
void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv)
{
// We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV
// When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error.
// Any error value TLVUnpackError means we have received an illegal value.
// The following variables are used for all commands to save code size.
CHIP_ERROR TLVError = CHIP_NO_ERROR;
CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
uint32_t validArgumentCount = 0;
uint32_t expectArgumentCount = 0;
uint32_t currentDecodeTagId = 0;
bool wasHandled = false;
{
switch (aCommandId)
{
case ZCL_ADD_THREAD_NETWORK_COMMAND_ID: {
expectArgumentCount = 3;
chip::ByteSpan operationalDataset;
uint64_t breadcrumb;
uint32_t timeoutMs;
bool argExists[3];
memset(argExists, 0, sizeof argExists);
while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
// Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element.
// Skip this element if it is not a ContextTag, not consider it as an error if other values are valid.
if (!TLV::IsContextTag(aDataTlv.GetTag()))
{
continue;
}
currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag());
if (currentDecodeTagId < 3)
{
if (argExists[currentDecodeTagId])
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
else
{
argExists[currentDecodeTagId] = true;
validArgumentCount++;
}
}
switch (currentDecodeTagId)
{
case 0: {
const uint8_t * data = nullptr;
TLVUnpackError = aDataTlv.GetDataPtr(data);
operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength());
}
break;
case 1:
TLVUnpackError = aDataTlv.Get(breadcrumb);
break;
case 2:
TLVUnpackError = aDataTlv.Get(timeoutMs);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfNetworkCommissioningClusterAddThreadNetworkCallback(apCommandObj, operationalDataset,
breadcrumb, timeoutMs);
}
break;
}
case ZCL_ADD_WI_FI_NETWORK_COMMAND_ID: {
expectArgumentCount = 4;
chip::ByteSpan ssid;
chip::ByteSpan credentials;
uint64_t breadcrumb;
uint32_t timeoutMs;
bool argExists[4];
memset(argExists, 0, sizeof argExists);
while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
// Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element.
// Skip this element if it is not a ContextTag, not consider it as an error if other values are valid.
if (!TLV::IsContextTag(aDataTlv.GetTag()))
{
continue;
}
currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag());
if (currentDecodeTagId < 4)
{
if (argExists[currentDecodeTagId])
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
else
{
argExists[currentDecodeTagId] = true;
validArgumentCount++;
}
}
switch (currentDecodeTagId)
{
case 0: {
const uint8_t * data = nullptr;
TLVUnpackError = aDataTlv.GetDataPtr(data);
ssid = chip::ByteSpan(data, aDataTlv.GetLength());
}
break;
case 1: {
const uint8_t * data = nullptr;
TLVUnpackError = aDataTlv.GetDataPtr(data);
credentials = chip::ByteSpan(data, aDataTlv.GetLength());
}
break;
case 2:
TLVUnpackError = aDataTlv.Get(breadcrumb);
break;
case 3:
TLVUnpackError = aDataTlv.Get(timeoutMs);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfNetworkCommissioningClusterAddWiFiNetworkCallback(apCommandObj, ssid, credentials, breadcrumb,
timeoutMs);
}
break;
}
case ZCL_DISABLE_NETWORK_COMMAND_ID: {
expectArgumentCount = 3;
chip::ByteSpan networkID;
uint64_t breadcrumb;
uint32_t timeoutMs;
bool argExists[3];
memset(argExists, 0, sizeof argExists);
while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
// Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element.
// Skip this element if it is not a ContextTag, not consider it as an error if other values are valid.
if (!TLV::IsContextTag(aDataTlv.GetTag()))
{
continue;
}
currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag());
if (currentDecodeTagId < 3)
{
if (argExists[currentDecodeTagId])
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
else
{
argExists[currentDecodeTagId] = true;
validArgumentCount++;
}
}
switch (currentDecodeTagId)
{
case 0: {
const uint8_t * data = nullptr;
TLVUnpackError = aDataTlv.GetDataPtr(data);
networkID = chip::ByteSpan(data, aDataTlv.GetLength());
}
break;
case 1:
TLVUnpackError = aDataTlv.Get(breadcrumb);
break;
case 2:
TLVUnpackError = aDataTlv.Get(timeoutMs);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled =
emberAfNetworkCommissioningClusterDisableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs);
}
break;
}
case ZCL_ENABLE_NETWORK_COMMAND_ID: {
expectArgumentCount = 3;
chip::ByteSpan networkID;
uint64_t breadcrumb;
uint32_t timeoutMs;
bool argExists[3];
memset(argExists, 0, sizeof argExists);
while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
// Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element.
// Skip this element if it is not a ContextTag, not consider it as an error if other values are valid.
if (!TLV::IsContextTag(aDataTlv.GetTag()))
{
continue;
}
currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag());
if (currentDecodeTagId < 3)
{
if (argExists[currentDecodeTagId])
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
else
{
argExists[currentDecodeTagId] = true;
validArgumentCount++;
}
}
switch (currentDecodeTagId)
{
case 0: {
const uint8_t * data = nullptr;
TLVUnpackError = aDataTlv.GetDataPtr(data);
networkID = chip::ByteSpan(data, aDataTlv.GetLength());
}
break;
case 1:
TLVUnpackError = aDataTlv.Get(breadcrumb);
break;
case 2:
TLVUnpackError = aDataTlv.Get(timeoutMs);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled =
emberAfNetworkCommissioningClusterEnableNetworkCallback(apCommandObj, networkID, breadcrumb, timeoutMs);
}
break;
}
case ZCL_GET_LAST_NETWORK_COMMISSIONING_RESULT_COMMAND_ID: {
expectArgumentCount = 1;
uint32_t timeoutMs;
bool argExists[1];
memset(argExists, 0, sizeof argExists);
while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
// Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element.
// Skip this element if it is not a ContextTag, not consider it as an error if other values are valid.
if (!TLV::IsContextTag(aDataTlv.GetTag()))
{
continue;
}
currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag());
if (currentDecodeTagId < 1)
{
if (argExists[currentDecodeTagId])
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
else
{
argExists[currentDecodeTagId] = true;
validArgumentCount++;
}
}
switch (currentDecodeTagId)
{
case 0:
TLVUnpackError = aDataTlv.Get(timeoutMs);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback(apCommandObj, timeoutMs);
}
break;
}
case ZCL_REMOVE_NETWORK_COMMAND_ID: {
expectArgumentCount = 3;
chip::ByteSpan NetworkID;
uint64_t Breadcrumb;
uint32_t TimeoutMs;
bool argExists[3];
memset(argExists, 0, sizeof argExists);
while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
// Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element.
// Skip this element if it is not a ContextTag, not consider it as an error if other values are valid.
if (!TLV::IsContextTag(aDataTlv.GetTag()))
{
continue;
}
currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag());
if (currentDecodeTagId < 3)
{
if (argExists[currentDecodeTagId])
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
else
{
argExists[currentDecodeTagId] = true;
validArgumentCount++;
}
}
switch (currentDecodeTagId)
{
case 0: {
const uint8_t * data = nullptr;
TLVUnpackError = aDataTlv.GetDataPtr(data);
NetworkID = chip::ByteSpan(data, aDataTlv.GetLength());
}
break;
case 1:
TLVUnpackError = aDataTlv.Get(Breadcrumb);
break;
case 2:
TLVUnpackError = aDataTlv.Get(TimeoutMs);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled =
emberAfNetworkCommissioningClusterRemoveNetworkCallback(apCommandObj, NetworkID, Breadcrumb, TimeoutMs);
}
break;
}
case ZCL_SCAN_NETWORKS_COMMAND_ID: {
expectArgumentCount = 3;
chip::ByteSpan ssid;
uint64_t breadcrumb;
uint32_t timeoutMs;
bool argExists[3];
memset(argExists, 0, sizeof argExists);
while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
// Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element.
// Skip this element if it is not a ContextTag, not consider it as an error if other values are valid.
if (!TLV::IsContextTag(aDataTlv.GetTag()))
{
continue;
}
currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag());
if (currentDecodeTagId < 3)
{
if (argExists[currentDecodeTagId])
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
else
{
argExists[currentDecodeTagId] = true;
validArgumentCount++;
}
}
switch (currentDecodeTagId)
{
case 0: {
const uint8_t * data = nullptr;
TLVUnpackError = aDataTlv.GetDataPtr(data);
ssid = chip::ByteSpan(data, aDataTlv.GetLength());
}
break;
case 1:
TLVUnpackError = aDataTlv.Get(breadcrumb);
break;
case 2:
TLVUnpackError = aDataTlv.Get(timeoutMs);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfNetworkCommissioningClusterScanNetworksCallback(apCommandObj, ssid, breadcrumb, timeoutMs);
}
break;
}
case ZCL_UPDATE_THREAD_NETWORK_COMMAND_ID: {
expectArgumentCount = 3;
chip::ByteSpan operationalDataset;
uint64_t breadcrumb;
uint32_t timeoutMs;
bool argExists[3];
memset(argExists, 0, sizeof argExists);
while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
// Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element.
// Skip this element if it is not a ContextTag, not consider it as an error if other values are valid.
if (!TLV::IsContextTag(aDataTlv.GetTag()))
{
continue;
}
currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag());
if (currentDecodeTagId < 3)
{
if (argExists[currentDecodeTagId])
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
else
{
argExists[currentDecodeTagId] = true;
validArgumentCount++;
}
}
switch (currentDecodeTagId)
{
case 0: {
const uint8_t * data = nullptr;
TLVUnpackError = aDataTlv.GetDataPtr(data);
operationalDataset = chip::ByteSpan(data, aDataTlv.GetLength());
}
break;
case 1:
TLVUnpackError = aDataTlv.Get(breadcrumb);
break;
case 2:
TLVUnpackError = aDataTlv.Get(timeoutMs);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfNetworkCommissioningClusterUpdateThreadNetworkCallback(apCommandObj, operationalDataset,
breadcrumb, timeoutMs);
}
break;
}
case ZCL_UPDATE_WI_FI_NETWORK_COMMAND_ID: {
expectArgumentCount = 4;
chip::ByteSpan ssid;
chip::ByteSpan credentials;
uint64_t breadcrumb;
uint32_t timeoutMs;
bool argExists[4];
memset(argExists, 0, sizeof argExists);
while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
// Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element.
// Skip this element if it is not a ContextTag, not consider it as an error if other values are valid.
if (!TLV::IsContextTag(aDataTlv.GetTag()))
{
continue;
}
currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag());
if (currentDecodeTagId < 4)
{
if (argExists[currentDecodeTagId])
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
else
{
argExists[currentDecodeTagId] = true;
validArgumentCount++;
}
}
switch (currentDecodeTagId)
{
case 0: {
const uint8_t * data = nullptr;
TLVUnpackError = aDataTlv.GetDataPtr(data);
ssid = chip::ByteSpan(data, aDataTlv.GetLength());
}
break;
case 1: {
const uint8_t * data = nullptr;
TLVUnpackError = aDataTlv.GetDataPtr(data);
credentials = chip::ByteSpan(data, aDataTlv.GetLength());
}
break;
case 2:
TLVUnpackError = aDataTlv.Get(breadcrumb);
break;
case 3:
TLVUnpackError = aDataTlv.Get(timeoutMs);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback(apCommandObj, ssid, credentials,
breadcrumb, timeoutMs);
}
break;
}
default: {
// Unrecognized command ID, error status will apply.
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_NETWORK_COMMISSIONING_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
Protocols::SecureChannel::Id,
Protocols::InteractionModel::ProtocolCode::UnsupportedCommand);
ChipLogError(Zcl, "Unknown command %" PRIx32 " for cluster %" PRIx32, aCommandId, ZCL_NETWORK_COMMISSIONING_CLUSTER_ID);
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_NETWORK_COMMISSIONING_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand);
ChipLogProgress(Zcl,
"Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT
", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32,
validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
}
}
} // namespace NetworkCommissioning
namespace OnOff {
void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv)
{
// We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV
// When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error.
// Any error value TLVUnpackError means we have received an illegal value.
// The following variables are used for all commands to save code size.
CHIP_ERROR TLVError = CHIP_NO_ERROR;
CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
uint32_t validArgumentCount = 0;
uint32_t expectArgumentCount = 0;
uint32_t currentDecodeTagId = 0;
bool wasHandled = false;
{
switch (aCommandId)
{
case ZCL_OFF_COMMAND_ID: {
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfOnOffClusterOffCallback(apCommandObj);
break;
}
case ZCL_ON_COMMAND_ID: {
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfOnOffClusterOnCallback(apCommandObj);
break;
}
case ZCL_TOGGLE_COMMAND_ID: {
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfOnOffClusterToggleCallback(apCommandObj);
break;
}
default: {
// Unrecognized command ID, error status will apply.
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_ON_OFF_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
Protocols::SecureChannel::Id,
Protocols::InteractionModel::ProtocolCode::UnsupportedCommand);
ChipLogError(Zcl, "Unknown command %" PRIx32 " for cluster %" PRIx32, aCommandId, ZCL_ON_OFF_CLUSTER_ID);
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_ON_OFF_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand);
ChipLogProgress(Zcl,
"Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT
", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32,
validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
}
}
} // namespace OnOff
namespace OperationalCredentials {
void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv)
{
// We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV
// When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error.
// Any error value TLVUnpackError means we have received an illegal value.
// The following variables are used for all commands to save code size.
CHIP_ERROR TLVError = CHIP_NO_ERROR;
CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
uint32_t validArgumentCount = 0;
uint32_t expectArgumentCount = 0;
uint32_t currentDecodeTagId = 0;
bool wasHandled = false;
{
switch (aCommandId)
{
case ZCL_ADD_OP_CERT_COMMAND_ID: {
expectArgumentCount = 4;
chip::ByteSpan NOCArray;
chip::ByteSpan IPKValue;
chip::NodeId CaseAdminNode;
uint16_t AdminVendorId;
bool argExists[4];
memset(argExists, 0, sizeof argExists);
while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
// Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element.
// Skip this element if it is not a ContextTag, not consider it as an error if other values are valid.
if (!TLV::IsContextTag(aDataTlv.GetTag()))
{
continue;
}
currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag());
if (currentDecodeTagId < 4)
{
if (argExists[currentDecodeTagId])
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
else
{
argExists[currentDecodeTagId] = true;
validArgumentCount++;
}
}
switch (currentDecodeTagId)
{
case 0: {
const uint8_t * data = nullptr;
TLVUnpackError = aDataTlv.GetDataPtr(data);
NOCArray = chip::ByteSpan(data, aDataTlv.GetLength());
}
break;
case 1: {
const uint8_t * data = nullptr;
TLVUnpackError = aDataTlv.GetDataPtr(data);
IPKValue = chip::ByteSpan(data, aDataTlv.GetLength());
}
break;
case 2:
TLVUnpackError = aDataTlv.Get(CaseAdminNode);
break;
case 3:
TLVUnpackError = aDataTlv.Get(AdminVendorId);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfOperationalCredentialsClusterAddOpCertCallback(apCommandObj, NOCArray, IPKValue, CaseAdminNode,
AdminVendorId);
}
break;
}
case ZCL_ADD_TRUSTED_ROOT_CERTIFICATE_COMMAND_ID: {
expectArgumentCount = 1;
chip::ByteSpan RootCertificate;
bool argExists[1];
memset(argExists, 0, sizeof argExists);
while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
// Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element.
// Skip this element if it is not a ContextTag, not consider it as an error if other values are valid.
if (!TLV::IsContextTag(aDataTlv.GetTag()))
{
continue;
}
currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag());
if (currentDecodeTagId < 1)
{
if (argExists[currentDecodeTagId])
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
else
{
argExists[currentDecodeTagId] = true;
validArgumentCount++;
}
}
switch (currentDecodeTagId)
{
case 0: {
const uint8_t * data = nullptr;
TLVUnpackError = aDataTlv.GetDataPtr(data);
RootCertificate = chip::ByteSpan(data, aDataTlv.GetLength());
}
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfOperationalCredentialsClusterAddTrustedRootCertificateCallback(apCommandObj, RootCertificate);
}
break;
}
case ZCL_OP_CSR_REQUEST_COMMAND_ID: {
expectArgumentCount = 1;
chip::ByteSpan CSRNonce;
bool argExists[1];
memset(argExists, 0, sizeof argExists);
while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
// Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element.
// Skip this element if it is not a ContextTag, not consider it as an error if other values are valid.
if (!TLV::IsContextTag(aDataTlv.GetTag()))
{
continue;
}
currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag());
if (currentDecodeTagId < 1)
{
if (argExists[currentDecodeTagId])
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
else
{
argExists[currentDecodeTagId] = true;
validArgumentCount++;
}
}
switch (currentDecodeTagId)
{
case 0: {
const uint8_t * data = nullptr;
TLVUnpackError = aDataTlv.GetDataPtr(data);
CSRNonce = chip::ByteSpan(data, aDataTlv.GetLength());
}
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfOperationalCredentialsClusterOpCSRRequestCallback(apCommandObj, CSRNonce);
}
break;
}
case ZCL_REMOVE_ALL_FABRICS_COMMAND_ID: {
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfOperationalCredentialsClusterRemoveAllFabricsCallback(apCommandObj);
break;
}
case ZCL_REMOVE_FABRIC_COMMAND_ID: {
expectArgumentCount = 3;
chip::FabricId FabricId;
chip::NodeId NodeId;
uint16_t VendorId;
bool argExists[3];
memset(argExists, 0, sizeof argExists);
while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
// Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element.
// Skip this element if it is not a ContextTag, not consider it as an error if other values are valid.
if (!TLV::IsContextTag(aDataTlv.GetTag()))
{
continue;
}
currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag());
if (currentDecodeTagId < 3)
{
if (argExists[currentDecodeTagId])
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
else
{
argExists[currentDecodeTagId] = true;
validArgumentCount++;
}
}
switch (currentDecodeTagId)
{
case 0:
TLVUnpackError = aDataTlv.Get(FabricId);
break;
case 1:
TLVUnpackError = aDataTlv.Get(NodeId);
break;
case 2:
TLVUnpackError = aDataTlv.Get(VendorId);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfOperationalCredentialsClusterRemoveFabricCallback(apCommandObj, FabricId, NodeId, VendorId);
}
break;
}
case ZCL_REMOVE_TRUSTED_ROOT_CERTIFICATE_COMMAND_ID: {
expectArgumentCount = 1;
chip::ByteSpan TrustedRootIdentifier;
bool argExists[1];
memset(argExists, 0, sizeof argExists);
while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
// Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element.
// Skip this element if it is not a ContextTag, not consider it as an error if other values are valid.
if (!TLV::IsContextTag(aDataTlv.GetTag()))
{
continue;
}
currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag());
if (currentDecodeTagId < 1)
{
if (argExists[currentDecodeTagId])
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
else
{
argExists[currentDecodeTagId] = true;
validArgumentCount++;
}
}
switch (currentDecodeTagId)
{
case 0: {
const uint8_t * data = nullptr;
TLVUnpackError = aDataTlv.GetDataPtr(data);
TrustedRootIdentifier = chip::ByteSpan(data, aDataTlv.GetLength());
}
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled =
emberAfOperationalCredentialsClusterRemoveTrustedRootCertificateCallback(apCommandObj, TrustedRootIdentifier);
}
break;
}
case ZCL_SET_FABRIC_COMMAND_ID: {
expectArgumentCount = 1;
uint16_t VendorId;
bool argExists[1];
memset(argExists, 0, sizeof argExists);
while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
// Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element.
// Skip this element if it is not a ContextTag, not consider it as an error if other values are valid.
if (!TLV::IsContextTag(aDataTlv.GetTag()))
{
continue;
}
currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag());
if (currentDecodeTagId < 1)
{
if (argExists[currentDecodeTagId])
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
else
{
argExists[currentDecodeTagId] = true;
validArgumentCount++;
}
}
switch (currentDecodeTagId)
{
case 0:
TLVUnpackError = aDataTlv.Get(VendorId);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfOperationalCredentialsClusterSetFabricCallback(apCommandObj, VendorId);
}
break;
}
case ZCL_UPDATE_FABRIC_LABEL_COMMAND_ID: {
expectArgumentCount = 1;
const uint8_t * Label;
bool argExists[1];
memset(argExists, 0, sizeof argExists);
while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
// Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element.
// Skip this element if it is not a ContextTag, not consider it as an error if other values are valid.
if (!TLV::IsContextTag(aDataTlv.GetTag()))
{
continue;
}
currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag());
if (currentDecodeTagId < 1)
{
if (argExists[currentDecodeTagId])
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
else
{
argExists[currentDecodeTagId] = true;
validArgumentCount++;
}
}
switch (currentDecodeTagId)
{
case 0:
// TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
TLVUnpackError = aDataTlv.GetDataPtr(Label);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled =
emberAfOperationalCredentialsClusterUpdateFabricLabelCallback(apCommandObj, const_cast<uint8_t *>(Label));
}
break;
}
default: {
// Unrecognized command ID, error status will apply.
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_OPERATIONAL_CREDENTIALS_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
Protocols::SecureChannel::Id,
Protocols::InteractionModel::ProtocolCode::UnsupportedCommand);
ChipLogError(Zcl, "Unknown command %" PRIx32 " for cluster %" PRIx32, aCommandId,
ZCL_OPERATIONAL_CREDENTIALS_CLUSTER_ID);
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_OPERATIONAL_CREDENTIALS_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand);
ChipLogProgress(Zcl,
"Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT
", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32,
validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
}
}
} // namespace OperationalCredentials
} // namespace clusters
void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aCommandId, chip::EndpointId aEndPointId,
chip::TLV::TLVReader & aReader, Command * apCommandObj)
{
ChipLogDetail(Zcl, "Received Cluster Command: Cluster=%" PRIx32 " Command=%" PRIx32 " Endpoint=%" PRIx16, aClusterId,
aCommandId, aEndPointId);
Compatibility::SetupEmberAfObjects(apCommandObj, aClusterId, aCommandId, aEndPointId);
TLV::TLVType dataTlvType;
SuccessOrExit(aReader.EnterContainer(dataTlvType));
switch (aClusterId)
{
case ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID:
clusters::DiagnosticLogs::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader);
break;
case ZCL_GENERAL_COMMISSIONING_CLUSTER_ID:
clusters::GeneralCommissioning::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader);
break;
case ZCL_LEVEL_CONTROL_CLUSTER_ID:
clusters::LevelControl::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader);
break;
case ZCL_NETWORK_COMMISSIONING_CLUSTER_ID:
clusters::NetworkCommissioning::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader);
break;
case ZCL_ON_OFF_CLUSTER_ID:
clusters::OnOff::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader);
break;
case ZCL_OPERATIONAL_CREDENTIALS_CLUSTER_ID:
clusters::OperationalCredentials::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader);
break;
default:
// Unrecognized cluster ID, error status will apply.
chip::app::CommandPathParams returnStatusParam = { aEndPointId,
0, // GroupId
aClusterId, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand);
ChipLogError(Zcl, "Unknown cluster %" PRIx32, aClusterId);
break;
}
exit:
Compatibility::ResetEmberAfObjects();
aReader.ExitContainer(dataTlvType);
}
} // namespace app
} // namespace chip