blob: 6cd45a048b4ea62e242e9a02c683903a52d69d3f [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/zap-generated/af-structs.h>
#include <app-common/zap-generated/callback.h>
#include <app-common/zap-generated/cluster-objects.h>
#include <app-common/zap-generated/ids/Clusters.h>
#include <app-common/zap-generated/ids/Commands.h>
#include <app/CommandHandler.h>
#include <app/InteractionModelEngine.h>
#include <app/util/util.h>
#include <lib/core/CHIPSafeCasts.h>
#include <lib/support/TypeTraits.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 AccountLogin {
void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPath & aCommandPath, 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 (aCommandPath.mCommandId)
{
case Commands::GetSetupPINResponse::Id: {
expectArgumentCount = 1;
chip::CharSpan setupPIN;
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(setupPIN);
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)
{
wasHandled =
emberAfAccountLoginClusterGetSetupPINResponseCallback(aCommandPath.mEndpointId, apCommandObj, setupPIN);
}
break;
}
default: {
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
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.Format(), TLVUnpackError.Format(), currentDecodeTagId);
// A command with no arguments would never write currentDecodeTagId. If
// progress logging is also disabled, it would look unused. Silence that
// warning.
UNUSED_VAR(currentDecodeTagId);
}
}
} // namespace AccountLogin
namespace ApplicationLauncher {
void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPath & aCommandPath, 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 (aCommandPath.mCommandId)
{
case Commands::HideAppResponse::Id: {
expectArgumentCount = 2;
uint8_t status;
chip::CharSpan data;
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(status);
break;
case 1:
TLVUnpackError = aDataTlv.Get(data);
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)
{
wasHandled =
emberAfApplicationLauncherClusterHideAppResponseCallback(aCommandPath.mEndpointId, apCommandObj, status, data);
}
break;
}
case Commands::LaunchAppResponse::Id: {
expectArgumentCount = 2;
uint8_t status;
chip::CharSpan data;
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(status);
break;
case 1:
TLVUnpackError = aDataTlv.Get(data);
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)
{
wasHandled = emberAfApplicationLauncherClusterLaunchAppResponseCallback(aCommandPath.mEndpointId, apCommandObj,
status, data);
}
break;
}
case Commands::StopAppResponse::Id: {
expectArgumentCount = 2;
uint8_t status;
chip::CharSpan data;
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(status);
break;
case 1:
TLVUnpackError = aDataTlv.Get(data);
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)
{
wasHandled =
emberAfApplicationLauncherClusterStopAppResponseCallback(aCommandPath.mEndpointId, apCommandObj, status, data);
}
break;
}
default: {
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
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.Format(), TLVUnpackError.Format(), currentDecodeTagId);
// A command with no arguments would never write currentDecodeTagId. If
// progress logging is also disabled, it would look unused. Silence that
// warning.
UNUSED_VAR(currentDecodeTagId);
}
}
} // namespace ApplicationLauncher
namespace Channel {
void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPath & aCommandPath, 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 (aCommandPath.mCommandId)
{
case Commands::ChangeChannelResponse::Id: {
expectArgumentCount = 2;
chip::app::Clusters::Channel::Structs::ChannelInfo::DecodableType channelMatch;
uint8_t errorType;
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:
// Not supported, just error out.
TLVUnpackError = CHIP_ERROR_UNEXPECTED_TLV_ELEMENT;
break;
case 1:
TLVUnpackError = aDataTlv.Get(errorType);
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)
{
wasHandled = emberAfChannelClusterChangeChannelResponseCallback(aCommandPath.mEndpointId, apCommandObj,
channelMatch, errorType);
}
break;
}
default: {
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
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.Format(), TLVUnpackError.Format(), currentDecodeTagId);
// A command with no arguments would never write currentDecodeTagId. If
// progress logging is also disabled, it would look unused. Silence that
// warning.
UNUSED_VAR(currentDecodeTagId);
}
}
} // namespace Channel
namespace ContentLauncher {
void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPath & aCommandPath, 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 (aCommandPath.mCommandId)
{
case Commands::LaunchContentResponse::Id: {
expectArgumentCount = 2;
uint8_t contentLaunchStatus;
chip::CharSpan data;
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(contentLaunchStatus);
break;
case 1:
TLVUnpackError = aDataTlv.Get(data);
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)
{
wasHandled = emberAfContentLauncherClusterLaunchContentResponseCallback(aCommandPath.mEndpointId, apCommandObj,
contentLaunchStatus, data);
}
break;
}
case Commands::LaunchURLResponse::Id: {
expectArgumentCount = 2;
uint8_t contentLaunchStatus;
chip::CharSpan data;
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(contentLaunchStatus);
break;
case 1:
TLVUnpackError = aDataTlv.Get(data);
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)
{
wasHandled = emberAfContentLauncherClusterLaunchURLResponseCallback(aCommandPath.mEndpointId, apCommandObj,
contentLaunchStatus, data);
}
break;
}
default: {
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
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.Format(), TLVUnpackError.Format(), currentDecodeTagId);
// A command with no arguments would never write currentDecodeTagId. If
// progress logging is also disabled, it would look unused. Silence that
// warning.
UNUSED_VAR(currentDecodeTagId);
}
}
} // namespace ContentLauncher
namespace DiagnosticLogs {
void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPath & aCommandPath, 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 (aCommandPath.mCommandId)
{
case Commands::RetrieveLogsResponse::Id: {
expectArgumentCount = 4;
uint8_t status;
chip::ByteSpan content;
uint32_t timeStamp;
uint32_t timeSinceBoot;
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(status);
break;
case 1:
TLVUnpackError = aDataTlv.Get(content);
break;
case 2:
TLVUnpackError = aDataTlv.Get(timeStamp);
break;
case 3:
TLVUnpackError = aDataTlv.Get(timeSinceBoot);
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)
{
wasHandled = emberAfDiagnosticLogsClusterRetrieveLogsResponseCallback(aCommandPath.mEndpointId, apCommandObj,
status, content, timeStamp, timeSinceBoot);
}
break;
}
default: {
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
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.Format(), TLVUnpackError.Format(), currentDecodeTagId);
// A command with no arguments would never write currentDecodeTagId. If
// progress logging is also disabled, it would look unused. Silence that
// warning.
UNUSED_VAR(currentDecodeTagId);
}
}
} // namespace DiagnosticLogs
namespace DoorLock {
void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPath & aCommandPath, 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 (aCommandPath.mCommandId)
{
case Commands::GetCredentialStatusResponse::Id: {
expectArgumentCount = 3;
bool credentialExists;
uint16_t userIndex;
uint16_t nextCredentialIndex;
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(credentialExists);
break;
case 1:
TLVUnpackError = aDataTlv.Get(userIndex);
break;
case 2:
TLVUnpackError = aDataTlv.Get(nextCredentialIndex);
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)
{
wasHandled = emberAfDoorLockClusterGetCredentialStatusResponseCallback(
aCommandPath.mEndpointId, apCommandObj, credentialExists, userIndex, nextCredentialIndex);
}
break;
}
case Commands::GetUserResponse::Id: {
expectArgumentCount = 10;
uint16_t userIndex;
chip::CharSpan userName;
uint32_t userUniqueId;
uint8_t userStatus;
uint8_t userType;
uint8_t credentialRule;
/* TYPE WARNING: array array defaults to */ uint8_t * credentials;
chip::FabricIndex creatorFabricIndex;
chip::FabricIndex lastModifiedFabricIndex;
uint16_t nextUserIndex;
bool argExists[10];
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 < 10)
{
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(userIndex);
break;
case 1:
TLVUnpackError = aDataTlv.Get(userName);
break;
case 2:
TLVUnpackError = aDataTlv.Get(userUniqueId);
break;
case 3:
TLVUnpackError = aDataTlv.Get(userStatus);
break;
case 4:
TLVUnpackError = aDataTlv.Get(userType);
break;
case 5:
TLVUnpackError = aDataTlv.Get(credentialRule);
break;
case 6:
// Just for compatibility, we will add array type support in IM later.
TLVUnpackError = aDataTlv.GetDataPtr(const_cast<const uint8_t *&>(credentials));
break;
case 7:
TLVUnpackError = aDataTlv.Get(creatorFabricIndex);
break;
case 8:
TLVUnpackError = aDataTlv.Get(lastModifiedFabricIndex);
break;
case 9:
TLVUnpackError = aDataTlv.Get(nextUserIndex);
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 && 10 == validArgumentCount)
{
wasHandled = emberAfDoorLockClusterGetUserResponseCallback(
aCommandPath.mEndpointId, apCommandObj, userIndex, userName, userUniqueId, userStatus, userType, credentialRule,
credentials, creatorFabricIndex, lastModifiedFabricIndex, nextUserIndex);
}
break;
}
case Commands::SetCredentialResponse::Id: {
expectArgumentCount = 3;
uint8_t status;
uint16_t userIndex;
uint16_t nextCredentialIndex;
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(status);
break;
case 1:
TLVUnpackError = aDataTlv.Get(userIndex);
break;
case 2:
TLVUnpackError = aDataTlv.Get(nextCredentialIndex);
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)
{
wasHandled = emberAfDoorLockClusterSetCredentialResponseCallback(aCommandPath.mEndpointId, apCommandObj, status,
userIndex, nextCredentialIndex);
}
break;
}
default: {
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
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.Format(), TLVUnpackError.Format(), currentDecodeTagId);
// A command with no arguments would never write currentDecodeTagId. If
// progress logging is also disabled, it would look unused. Silence that
// warning.
UNUSED_VAR(currentDecodeTagId);
}
}
} // namespace DoorLock
namespace GeneralCommissioning {
void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPath & aCommandPath, 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 (aCommandPath.mCommandId)
{
case Commands::ArmFailSafeResponse::Id: {
expectArgumentCount = 2;
uint8_t errorCode;
chip::CharSpan debugText;
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(errorCode);
break;
case 1:
TLVUnpackError = aDataTlv.Get(debugText);
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)
{
wasHandled = emberAfGeneralCommissioningClusterArmFailSafeResponseCallback(aCommandPath.mEndpointId, apCommandObj,
errorCode, debugText);
}
break;
}
case Commands::CommissioningCompleteResponse::Id: {
expectArgumentCount = 2;
uint8_t errorCode;
chip::CharSpan debugText;
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(errorCode);
break;
case 1:
TLVUnpackError = aDataTlv.Get(debugText);
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)
{
wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteResponseCallback(
aCommandPath.mEndpointId, apCommandObj, errorCode, debugText);
}
break;
}
case Commands::SetRegulatoryConfigResponse::Id: {
expectArgumentCount = 2;
uint8_t errorCode;
chip::CharSpan debugText;
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(errorCode);
break;
case 1:
TLVUnpackError = aDataTlv.Get(debugText);
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)
{
wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigResponseCallback(
aCommandPath.mEndpointId, apCommandObj, errorCode, debugText);
}
break;
}
default: {
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
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.Format(), TLVUnpackError.Format(), currentDecodeTagId);
// A command with no arguments would never write currentDecodeTagId. If
// progress logging is also disabled, it would look unused. Silence that
// warning.
UNUSED_VAR(currentDecodeTagId);
}
}
} // namespace GeneralCommissioning
namespace GroupKeyManagement {
void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPath & aCommandPath, 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 (aCommandPath.mCommandId)
{
case Commands::KeySetReadAllIndicesResponse::Id: {
expectArgumentCount = 1;
/* TYPE WARNING: array array defaults to */ uint8_t * groupKeySetIDs;
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:
// Just for compatibility, we will add array type support in IM later.
TLVUnpackError = aDataTlv.GetDataPtr(const_cast<const uint8_t *&>(groupKeySetIDs));
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)
{
wasHandled = emberAfGroupKeyManagementClusterKeySetReadAllIndicesResponseCallback(aCommandPath.mEndpointId,
apCommandObj, groupKeySetIDs);
}
break;
}
case Commands::KeySetReadResponse::Id: {
expectArgumentCount = 1;
chip::app::Clusters::GroupKeyManagement::Structs::GroupKeySet::DecodableType groupKeySet;
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:
// Not supported, just error out.
TLVUnpackError = CHIP_ERROR_UNEXPECTED_TLV_ELEMENT;
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)
{
wasHandled =
emberAfGroupKeyManagementClusterKeySetReadResponseCallback(aCommandPath.mEndpointId, apCommandObj, groupKeySet);
}
break;
}
default: {
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
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.Format(), TLVUnpackError.Format(), currentDecodeTagId);
// A command with no arguments would never write currentDecodeTagId. If
// progress logging is also disabled, it would look unused. Silence that
// warning.
UNUSED_VAR(currentDecodeTagId);
}
}
} // namespace GroupKeyManagement
namespace Groups {
void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPath & aCommandPath, 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 (aCommandPath.mCommandId)
{
case Commands::AddGroupResponse::Id: {
expectArgumentCount = 2;
uint8_t status;
uint16_t groupId;
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(status);
break;
case 1:
TLVUnpackError = aDataTlv.Get(groupId);
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)
{
wasHandled = emberAfGroupsClusterAddGroupResponseCallback(aCommandPath.mEndpointId, apCommandObj, status, groupId);
}
break;
}
case Commands::GetGroupMembershipResponse::Id: {
expectArgumentCount = 2;
uint8_t capacity;
/* TYPE WARNING: array array defaults to */ uint8_t * groupList;
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(capacity);
break;
case 1:
// Just for compatibility, we will add array type support in IM later.
TLVUnpackError = aDataTlv.GetDataPtr(const_cast<const uint8_t *&>(groupList));
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)
{
wasHandled = emberAfGroupsClusterGetGroupMembershipResponseCallback(aCommandPath.mEndpointId, apCommandObj,
capacity, groupList);
}
break;
}
case Commands::RemoveGroupResponse::Id: {
expectArgumentCount = 2;
uint8_t status;
uint16_t groupId;
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(status);
break;
case 1:
TLVUnpackError = aDataTlv.Get(groupId);
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)
{
wasHandled =
emberAfGroupsClusterRemoveGroupResponseCallback(aCommandPath.mEndpointId, apCommandObj, status, groupId);
}
break;
}
case Commands::ViewGroupResponse::Id: {
expectArgumentCount = 3;
uint8_t status;
uint16_t groupId;
chip::CharSpan groupName;
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(status);
break;
case 1:
TLVUnpackError = aDataTlv.Get(groupId);
break;
case 2:
TLVUnpackError = aDataTlv.Get(groupName);
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)
{
wasHandled = emberAfGroupsClusterViewGroupResponseCallback(aCommandPath.mEndpointId, apCommandObj, status, groupId,
groupName);
}
break;
}
default: {
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
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.Format(), TLVUnpackError.Format(), currentDecodeTagId);
// A command with no arguments would never write currentDecodeTagId. If
// progress logging is also disabled, it would look unused. Silence that
// warning.
UNUSED_VAR(currentDecodeTagId);
}
}
} // namespace Groups
namespace Identify {
void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPath & aCommandPath, 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 (aCommandPath.mCommandId)
{
case Commands::IdentifyQueryResponse::Id: {
expectArgumentCount = 1;
uint16_t timeout;
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(timeout);
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)
{
wasHandled = emberAfIdentifyClusterIdentifyQueryResponseCallback(aCommandPath.mEndpointId, apCommandObj, timeout);
}
break;
}
default: {
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
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.Format(), TLVUnpackError.Format(), currentDecodeTagId);
// A command with no arguments would never write currentDecodeTagId. If
// progress logging is also disabled, it would look unused. Silence that
// warning.
UNUSED_VAR(currentDecodeTagId);
}
}
} // namespace Identify
namespace KeypadInput {
void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPath & aCommandPath, 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 (aCommandPath.mCommandId)
{
case Commands::SendKeyResponse::Id: {
expectArgumentCount = 1;
uint8_t status;
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(status);
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)
{
wasHandled = emberAfKeypadInputClusterSendKeyResponseCallback(aCommandPath.mEndpointId, apCommandObj, status);
}
break;
}
default: {
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
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.Format(), TLVUnpackError.Format(), currentDecodeTagId);
// A command with no arguments would never write currentDecodeTagId. If
// progress logging is also disabled, it would look unused. Silence that
// warning.
UNUSED_VAR(currentDecodeTagId);
}
}
} // namespace KeypadInput
namespace MediaPlayback {
void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPath & aCommandPath, 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 (aCommandPath.mCommandId)
{
case Commands::MediaFastForwardResponse::Id: {
expectArgumentCount = 1;
uint8_t mediaPlaybackStatus;
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(mediaPlaybackStatus);
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)
{
wasHandled = emberAfMediaPlaybackClusterMediaFastForwardResponseCallback(aCommandPath.mEndpointId, apCommandObj,
mediaPlaybackStatus);
}
break;
}
case Commands::MediaNextResponse::Id: {
expectArgumentCount = 1;
uint8_t mediaPlaybackStatus;
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(mediaPlaybackStatus);
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)
{
wasHandled = emberAfMediaPlaybackClusterMediaNextResponseCallback(aCommandPath.mEndpointId, apCommandObj,
mediaPlaybackStatus);
}
break;
}
case Commands::MediaPauseResponse::Id: {
expectArgumentCount = 1;
uint8_t mediaPlaybackStatus;
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(mediaPlaybackStatus);
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)
{
wasHandled = emberAfMediaPlaybackClusterMediaPauseResponseCallback(aCommandPath.mEndpointId, apCommandObj,
mediaPlaybackStatus);
}
break;
}
case Commands::MediaPlayResponse::Id: {
expectArgumentCount = 1;
uint8_t mediaPlaybackStatus;
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(mediaPlaybackStatus);
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)
{
wasHandled = emberAfMediaPlaybackClusterMediaPlayResponseCallback(aCommandPath.mEndpointId, apCommandObj,
mediaPlaybackStatus);
}
break;
}
case Commands::MediaPreviousResponse::Id: {
expectArgumentCount = 1;
uint8_t mediaPlaybackStatus;
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(mediaPlaybackStatus);
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)
{
wasHandled = emberAfMediaPlaybackClusterMediaPreviousResponseCallback(aCommandPath.mEndpointId, apCommandObj,
mediaPlaybackStatus);
}
break;
}
case Commands::MediaRewindResponse::Id: {
expectArgumentCount = 1;
uint8_t mediaPlaybackStatus;
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(mediaPlaybackStatus);
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)
{
wasHandled = emberAfMediaPlaybackClusterMediaRewindResponseCallback(aCommandPath.mEndpointId, apCommandObj,
mediaPlaybackStatus);
}
break;
}
case Commands::MediaSeekResponse::Id: {
expectArgumentCount = 1;
uint8_t mediaPlaybackStatus;
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(mediaPlaybackStatus);
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)
{
wasHandled = emberAfMediaPlaybackClusterMediaSeekResponseCallback(aCommandPath.mEndpointId, apCommandObj,
mediaPlaybackStatus);
}
break;
}
case Commands::MediaSkipBackwardResponse::Id: {
expectArgumentCount = 1;
uint8_t mediaPlaybackStatus;
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(mediaPlaybackStatus);
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)
{
wasHandled = emberAfMediaPlaybackClusterMediaSkipBackwardResponseCallback(aCommandPath.mEndpointId, apCommandObj,
mediaPlaybackStatus);
}
break;
}
case Commands::MediaSkipForwardResponse::Id: {
expectArgumentCount = 1;
uint8_t mediaPlaybackStatus;
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(mediaPlaybackStatus);
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)
{
wasHandled = emberAfMediaPlaybackClusterMediaSkipForwardResponseCallback(aCommandPath.mEndpointId, apCommandObj,
mediaPlaybackStatus);
}
break;
}
case Commands::MediaStartOverResponse::Id: {
expectArgumentCount = 1;
uint8_t mediaPlaybackStatus;
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(mediaPlaybackStatus);
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)
{
wasHandled = emberAfMediaPlaybackClusterMediaStartOverResponseCallback(aCommandPath.mEndpointId, apCommandObj,
mediaPlaybackStatus);
}
break;
}
case Commands::MediaStopResponse::Id: {
expectArgumentCount = 1;
uint8_t mediaPlaybackStatus;
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(mediaPlaybackStatus);
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)
{
wasHandled = emberAfMediaPlaybackClusterMediaStopResponseCallback(aCommandPath.mEndpointId, apCommandObj,
mediaPlaybackStatus);
}
break;
}
default: {
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
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.Format(), TLVUnpackError.Format(), currentDecodeTagId);
// A command with no arguments would never write currentDecodeTagId. If
// progress logging is also disabled, it would look unused. Silence that
// warning.
UNUSED_VAR(currentDecodeTagId);
}
}
} // namespace MediaPlayback
namespace NetworkCommissioning {
void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPath & aCommandPath, 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 (aCommandPath.mCommandId)
{
case Commands::ConnectNetworkResponse::Id: {
expectArgumentCount = 3;
uint8_t NetworkingStatus;
chip::CharSpan DebugText;
int32_t ErrorValue;
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(NetworkingStatus);
break;
case 1:
TLVUnpackError = aDataTlv.Get(DebugText);
break;
case 2:
TLVUnpackError = aDataTlv.Get(ErrorValue);
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)
{
wasHandled = emberAfNetworkCommissioningClusterConnectNetworkResponseCallback(
aCommandPath.mEndpointId, apCommandObj, NetworkingStatus, DebugText, ErrorValue);
}
break;
}
case Commands::NetworkConfigResponse::Id: {
expectArgumentCount = 2;
uint8_t NetworkingStatus;
chip::CharSpan DebugText;
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(NetworkingStatus);
break;
case 1:
TLVUnpackError = aDataTlv.Get(DebugText);
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)
{
wasHandled = emberAfNetworkCommissioningClusterNetworkConfigResponseCallback(aCommandPath.mEndpointId, apCommandObj,
NetworkingStatus, DebugText);
}
break;
}
case Commands::ScanNetworksResponse::Id: {
expectArgumentCount = 4;
uint8_t NetworkingStatus;
chip::CharSpan DebugText;
/* TYPE WARNING: array array defaults to */ uint8_t * WiFiScanResults;
/* TYPE WARNING: array array defaults to */ uint8_t * ThreadScanResults;
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(NetworkingStatus);
break;
case 1:
TLVUnpackError = aDataTlv.Get(DebugText);
break;
case 2:
// Just for compatibility, we will add array type support in IM later.
TLVUnpackError = aDataTlv.GetDataPtr(const_cast<const uint8_t *&>(WiFiScanResults));
break;
case 3:
// Just for compatibility, we will add array type support in IM later.
TLVUnpackError = aDataTlv.GetDataPtr(const_cast<const uint8_t *&>(ThreadScanResults));
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)
{
wasHandled = emberAfNetworkCommissioningClusterScanNetworksResponseCallback(
aCommandPath.mEndpointId, apCommandObj, NetworkingStatus, DebugText, WiFiScanResults, ThreadScanResults);
}
break;
}
default: {
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
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.Format(), TLVUnpackError.Format(), currentDecodeTagId);
// A command with no arguments would never write currentDecodeTagId. If
// progress logging is also disabled, it would look unused. Silence that
// warning.
UNUSED_VAR(currentDecodeTagId);
}
}
} // namespace NetworkCommissioning
namespace OtaSoftwareUpdateProvider {
void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPath & aCommandPath, 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 (aCommandPath.mCommandId)
{
case Commands::ApplyUpdateResponse::Id: {
expectArgumentCount = 2;
uint8_t action;
uint32_t delayedActionTime;
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(action);
break;
case 1:
TLVUnpackError = aDataTlv.Get(delayedActionTime);
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)
{
wasHandled = emberAfOtaSoftwareUpdateProviderClusterApplyUpdateResponseCallback(
aCommandPath.mEndpointId, apCommandObj, action, delayedActionTime);
}
break;
}
case Commands::QueryImageResponse::Id: {
expectArgumentCount = 8;
uint8_t status;
uint32_t delayedActionTime;
chip::CharSpan imageURI;
uint32_t softwareVersion;
chip::CharSpan softwareVersionString;
chip::ByteSpan updateToken;
bool userConsentNeeded;
chip::ByteSpan metadataForRequestor;
bool argExists[8];
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 < 8)
{
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(status);
break;
case 1:
TLVUnpackError = aDataTlv.Get(delayedActionTime);
break;
case 2:
TLVUnpackError = aDataTlv.Get(imageURI);
break;
case 3:
TLVUnpackError = aDataTlv.Get(softwareVersion);
break;
case 4:
TLVUnpackError = aDataTlv.Get(softwareVersionString);
break;
case 5:
TLVUnpackError = aDataTlv.Get(updateToken);
break;
case 6:
TLVUnpackError = aDataTlv.Get(userConsentNeeded);
break;
case 7:
TLVUnpackError = aDataTlv.Get(metadataForRequestor);
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 && 8 == validArgumentCount)
{
wasHandled = emberAfOtaSoftwareUpdateProviderClusterQueryImageResponseCallback(
aCommandPath.mEndpointId, apCommandObj, status, delayedActionTime, imageURI, softwareVersion,
softwareVersionString, updateToken, userConsentNeeded, metadataForRequestor);
}
break;
}
default: {
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
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.Format(), TLVUnpackError.Format(), currentDecodeTagId);
// A command with no arguments would never write currentDecodeTagId. If
// progress logging is also disabled, it would look unused. Silence that
// warning.
UNUSED_VAR(currentDecodeTagId);
}
}
} // namespace OtaSoftwareUpdateProvider
namespace OperationalCredentials {
void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPath & aCommandPath, 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 (aCommandPath.mCommandId)
{
case Commands::AttestationResponse::Id: {
expectArgumentCount = 2;
chip::ByteSpan AttestationElements;
chip::ByteSpan Signature;
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(AttestationElements);
break;
case 1:
TLVUnpackError = aDataTlv.Get(Signature);
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)
{
wasHandled = emberAfOperationalCredentialsClusterAttestationResponseCallback(aCommandPath.mEndpointId, apCommandObj,
AttestationElements, Signature);
}
break;
}
case Commands::CertificateChainResponse::Id: {
expectArgumentCount = 1;
chip::ByteSpan Certificate;
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(Certificate);
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)
{
wasHandled = emberAfOperationalCredentialsClusterCertificateChainResponseCallback(aCommandPath.mEndpointId,
apCommandObj, Certificate);
}
break;
}
case Commands::NOCResponse::Id: {
expectArgumentCount = 3;
uint8_t StatusCode;
uint8_t FabricIndex;
chip::CharSpan DebugText;
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(StatusCode);
break;
case 1:
TLVUnpackError = aDataTlv.Get(FabricIndex);
break;
case 2:
TLVUnpackError = aDataTlv.Get(DebugText);
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)
{
wasHandled = emberAfOperationalCredentialsClusterNOCResponseCallback(aCommandPath.mEndpointId, apCommandObj,
StatusCode, FabricIndex, DebugText);
}
break;
}
case Commands::OpCSRResponse::Id: {
expectArgumentCount = 2;
chip::ByteSpan NOCSRElements;
chip::ByteSpan AttestationSignature;
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(NOCSRElements);
break;
case 1:
TLVUnpackError = aDataTlv.Get(AttestationSignature);
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)
{
wasHandled = emberAfOperationalCredentialsClusterOpCSRResponseCallback(aCommandPath.mEndpointId, apCommandObj,
NOCSRElements, AttestationSignature);
}
break;
}
default: {
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
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.Format(), TLVUnpackError.Format(), currentDecodeTagId);
// A command with no arguments would never write currentDecodeTagId. If
// progress logging is also disabled, it would look unused. Silence that
// warning.
UNUSED_VAR(currentDecodeTagId);
}
}
} // namespace OperationalCredentials
namespace Scenes {
void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPath & aCommandPath, 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 (aCommandPath.mCommandId)
{
case Commands::AddSceneResponse::Id: {
expectArgumentCount = 3;
uint8_t status;
uint16_t groupId;
uint8_t sceneId;
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(status);
break;
case 1:
TLVUnpackError = aDataTlv.Get(groupId);
break;
case 2:
TLVUnpackError = aDataTlv.Get(sceneId);
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)
{
wasHandled =
emberAfScenesClusterAddSceneResponseCallback(aCommandPath.mEndpointId, apCommandObj, status, groupId, sceneId);
}
break;
}
case Commands::GetSceneMembershipResponse::Id: {
expectArgumentCount = 5;
uint8_t status;
uint8_t capacity;
uint16_t groupId;
uint8_t sceneCount;
/* TYPE WARNING: array array defaults to */ uint8_t * sceneList;
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(status);
break;
case 1:
TLVUnpackError = aDataTlv.Get(capacity);
break;
case 2:
TLVUnpackError = aDataTlv.Get(groupId);
break;
case 3:
TLVUnpackError = aDataTlv.Get(sceneCount);
break;
case 4:
// Just for compatibility, we will add array type support in IM later.
TLVUnpackError = aDataTlv.GetDataPtr(const_cast<const uint8_t *&>(sceneList));
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)
{
wasHandled = emberAfScenesClusterGetSceneMembershipResponseCallback(aCommandPath.mEndpointId, apCommandObj, status,
capacity, groupId, sceneCount, sceneList);
}
break;
}
case Commands::RemoveAllScenesResponse::Id: {
expectArgumentCount = 2;
uint8_t status;
uint16_t groupId;
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(status);
break;
case 1:
TLVUnpackError = aDataTlv.Get(groupId);
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)
{
wasHandled =
emberAfScenesClusterRemoveAllScenesResponseCallback(aCommandPath.mEndpointId, apCommandObj, status, groupId);
}
break;
}
case Commands::RemoveSceneResponse::Id: {
expectArgumentCount = 3;
uint8_t status;
uint16_t groupId;
uint8_t sceneId;
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(status);
break;
case 1:
TLVUnpackError = aDataTlv.Get(groupId);
break;
case 2:
TLVUnpackError = aDataTlv.Get(sceneId);
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)
{
wasHandled = emberAfScenesClusterRemoveSceneResponseCallback(aCommandPath.mEndpointId, apCommandObj, status,
groupId, sceneId);
}
break;
}
case Commands::StoreSceneResponse::Id: {
expectArgumentCount = 3;
uint8_t status;
uint16_t groupId;
uint8_t sceneId;
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(status);
break;
case 1:
TLVUnpackError = aDataTlv.Get(groupId);
break;
case 2:
TLVUnpackError = aDataTlv.Get(sceneId);
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)
{
wasHandled = emberAfScenesClusterStoreSceneResponseCallback(aCommandPath.mEndpointId, apCommandObj, status, groupId,
sceneId);
}
break;
}
case Commands::ViewSceneResponse::Id: {
expectArgumentCount = 6;
uint8_t status;
uint16_t groupId;
uint8_t sceneId;
uint16_t transitionTime;
chip::CharSpan sceneName;
/* TYPE WARNING: array array defaults to */ uint8_t * extensionFieldSets;
bool argExists[6];
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 < 6)
{
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(status);
break;
case 1:
TLVUnpackError = aDataTlv.Get(groupId);
break;
case 2:
TLVUnpackError = aDataTlv.Get(sceneId);
break;
case 3:
TLVUnpackError = aDataTlv.Get(transitionTime);
break;
case 4:
TLVUnpackError = aDataTlv.Get(sceneName);
break;
case 5:
// Just for compatibility, we will add array type support in IM later.
TLVUnpackError = aDataTlv.GetDataPtr(const_cast<const uint8_t *&>(extensionFieldSets));
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 && 6 == validArgumentCount)
{
wasHandled = emberAfScenesClusterViewSceneResponseCallback(aCommandPath.mEndpointId, apCommandObj, status, groupId,
sceneId, transitionTime, sceneName, extensionFieldSets);
}
break;
}
default: {
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
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.Format(), TLVUnpackError.Format(), currentDecodeTagId);
// A command with no arguments would never write currentDecodeTagId. If
// progress logging is also disabled, it would look unused. Silence that
// warning.
UNUSED_VAR(currentDecodeTagId);
}
}
} // namespace Scenes
namespace TargetNavigator {
void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPath & aCommandPath, 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 (aCommandPath.mCommandId)
{
case Commands::NavigateTargetResponse::Id: {
expectArgumentCount = 2;
uint8_t status;
chip::CharSpan data;
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(status);
break;
case 1:
TLVUnpackError = aDataTlv.Get(data);
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)
{
wasHandled = emberAfTargetNavigatorClusterNavigateTargetResponseCallback(aCommandPath.mEndpointId, apCommandObj,
status, data);
}
break;
}
default: {
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
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.Format(), TLVUnpackError.Format(), currentDecodeTagId);
// A command with no arguments would never write currentDecodeTagId. If
// progress logging is also disabled, it would look unused. Silence that
// warning.
UNUSED_VAR(currentDecodeTagId);
}
}
} // namespace TargetNavigator
namespace TestCluster {
void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPath & aCommandPath, 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 (aCommandPath.mCommandId)
{
case Commands::BooleanResponse::Id: {
expectArgumentCount = 1;
bool value;
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(value);
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)
{
wasHandled = emberAfTestClusterClusterBooleanResponseCallback(aCommandPath.mEndpointId, apCommandObj, value);
}
break;
}
case Commands::SimpleStructResponse::Id: {
expectArgumentCount = 1;
chip::app::Clusters::TestCluster::Structs::SimpleStruct::DecodableType arg1;
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:
// Not supported, just error out.
TLVUnpackError = CHIP_ERROR_UNEXPECTED_TLV_ELEMENT;
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)
{
wasHandled = emberAfTestClusterClusterSimpleStructResponseCallback(aCommandPath.mEndpointId, apCommandObj, arg1);
}
break;
}
case Commands::TestAddArgumentsResponse::Id: {
expectArgumentCount = 1;
uint8_t returnValue;
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(returnValue);
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)
{
wasHandled =
emberAfTestClusterClusterTestAddArgumentsResponseCallback(aCommandPath.mEndpointId, apCommandObj, returnValue);
}
break;
}
case Commands::TestEnumsResponse::Id: {
expectArgumentCount = 2;
chip::VendorId arg1;
uint8_t arg2;
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(arg1);
break;
case 1:
TLVUnpackError = aDataTlv.Get(arg2);
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)
{
wasHandled = emberAfTestClusterClusterTestEnumsResponseCallback(aCommandPath.mEndpointId, apCommandObj, arg1, arg2);
}
break;
}
case Commands::TestListInt8UReverseResponse::Id: {
expectArgumentCount = 1;
/* TYPE WARNING: array array defaults to */ uint8_t * arg1;
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:
// Just for compatibility, we will add array type support in IM later.
TLVUnpackError = aDataTlv.GetDataPtr(const_cast<const uint8_t *&>(arg1));
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)
{
wasHandled =
emberAfTestClusterClusterTestListInt8UReverseResponseCallback(aCommandPath.mEndpointId, apCommandObj, arg1);
}
break;
}
case Commands::TestNullableOptionalResponse::Id: {
expectArgumentCount = 4;
bool wasPresent;
bool wasNull;
uint8_t value;
uint8_t originalValue;
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(wasPresent);
break;
case 1:
TLVUnpackError = aDataTlv.Get(wasNull);
break;
case 2:
TLVUnpackError = aDataTlv.Get(value);
break;
case 3:
TLVUnpackError = aDataTlv.Get(originalValue);
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)
{
wasHandled = emberAfTestClusterClusterTestNullableOptionalResponseCallback(
aCommandPath.mEndpointId, apCommandObj, wasPresent, wasNull, value, originalValue);
}
break;
}
case Commands::TestSpecificResponse::Id: {
expectArgumentCount = 1;
uint8_t returnValue;
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(returnValue);
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)
{
wasHandled =
emberAfTestClusterClusterTestSpecificResponseCallback(aCommandPath.mEndpointId, apCommandObj, returnValue);
}
break;
}
default: {
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
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.Format(), TLVUnpackError.Format(), currentDecodeTagId);
// A command with no arguments would never write currentDecodeTagId. If
// progress logging is also disabled, it would look unused. Silence that
// warning.
UNUSED_VAR(currentDecodeTagId);
}
}
} // namespace TestCluster
namespace Thermostat {
void DispatchClientCommand(CommandSender * apCommandObj, const ConcreteCommandPath & aCommandPath, 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 (aCommandPath.mCommandId)
{
case Commands::GetRelayStatusLogResponse::Id: {
expectArgumentCount = 6;
uint16_t timeOfDay;
uint16_t relayStatus;
int16_t localTemperature;
uint8_t humidityInPercentage;
int16_t setpoint;
uint16_t unreadEntries;
bool argExists[6];
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 < 6)
{
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(timeOfDay);
break;
case 1:
TLVUnpackError = aDataTlv.Get(relayStatus);
break;
case 2:
TLVUnpackError = aDataTlv.Get(localTemperature);
break;
case 3:
TLVUnpackError = aDataTlv.Get(humidityInPercentage);
break;
case 4:
TLVUnpackError = aDataTlv.Get(setpoint);
break;
case 5:
TLVUnpackError = aDataTlv.Get(unreadEntries);
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 && 6 == validArgumentCount)
{
wasHandled = emberAfThermostatClusterGetRelayStatusLogResponseCallback(
aCommandPath.mEndpointId, apCommandObj, timeOfDay, relayStatus, localTemperature, humidityInPercentage,
setpoint, unreadEntries);
}
break;
}
case Commands::GetWeeklyScheduleResponse::Id: {
expectArgumentCount = 4;
uint8_t numberOfTransitionsForSequence;
uint8_t dayOfWeekForSequence;
uint8_t modeForSequence;
/* TYPE WARNING: array array defaults to */ uint8_t * payload;
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(numberOfTransitionsForSequence);
break;
case 1:
TLVUnpackError = aDataTlv.Get(dayOfWeekForSequence);
break;
case 2:
TLVUnpackError = aDataTlv.Get(modeForSequence);
break;
case 3:
// Just for compatibility, we will add array type support in IM later.
TLVUnpackError = aDataTlv.GetDataPtr(const_cast<const uint8_t *&>(payload));
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)
{
wasHandled = emberAfThermostatClusterGetWeeklyScheduleResponseCallback(
aCommandPath.mEndpointId, apCommandObj, numberOfTransitionsForSequence, dayOfWeekForSequence, modeForSequence,
payload);
}
break;
}
default: {
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
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.Format(), TLVUnpackError.Format(), currentDecodeTagId);
// A command with no arguments would never write currentDecodeTagId. If
// progress logging is also disabled, it would look unused. Silence that
// warning.
UNUSED_VAR(currentDecodeTagId);
}
}
} // namespace Thermostat
} // namespace Clusters
void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aReader, CommandHandler * apCommandObj)
{
Compatibility::SetupEmberAfCommandHandler(apCommandObj, aCommandPath);
switch (aCommandPath.mClusterId)
{
default:
ChipLogError(Zcl, "Unknown cluster " ChipLogFormatMEI, ChipLogValueMEI(aCommandPath.mClusterId));
apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::UnsupportedCluster);
break;
}
Compatibility::ResetEmberAfObjects();
}
void DispatchSingleClusterResponseCommand(const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aReader,
CommandSender * apCommandObj)
{
Compatibility::SetupEmberAfCommandSender(apCommandObj, aCommandPath);
TLV::TLVType dataTlvType;
SuccessOrExit(aReader.EnterContainer(dataTlvType));
switch (aCommandPath.mClusterId)
{
case Clusters::AccountLogin::Id:
Clusters::AccountLogin::DispatchClientCommand(apCommandObj, aCommandPath, aReader);
break;
case Clusters::ApplicationLauncher::Id:
Clusters::ApplicationLauncher::DispatchClientCommand(apCommandObj, aCommandPath, aReader);
break;
case Clusters::Channel::Id:
Clusters::Channel::DispatchClientCommand(apCommandObj, aCommandPath, aReader);
break;
case Clusters::ContentLauncher::Id:
Clusters::ContentLauncher::DispatchClientCommand(apCommandObj, aCommandPath, aReader);
break;
case Clusters::DiagnosticLogs::Id:
Clusters::DiagnosticLogs::DispatchClientCommand(apCommandObj, aCommandPath, aReader);
break;
case Clusters::DoorLock::Id:
Clusters::DoorLock::DispatchClientCommand(apCommandObj, aCommandPath, aReader);
break;
case Clusters::GeneralCommissioning::Id:
Clusters::GeneralCommissioning::DispatchClientCommand(apCommandObj, aCommandPath, aReader);
break;
case Clusters::GroupKeyManagement::Id:
Clusters::GroupKeyManagement::DispatchClientCommand(apCommandObj, aCommandPath, aReader);
break;
case Clusters::Groups::Id:
Clusters::Groups::DispatchClientCommand(apCommandObj, aCommandPath, aReader);
break;
case Clusters::Identify::Id:
Clusters::Identify::DispatchClientCommand(apCommandObj, aCommandPath, aReader);
break;
case Clusters::KeypadInput::Id:
Clusters::KeypadInput::DispatchClientCommand(apCommandObj, aCommandPath, aReader);
break;
case Clusters::MediaPlayback::Id:
Clusters::MediaPlayback::DispatchClientCommand(apCommandObj, aCommandPath, aReader);
break;
case Clusters::NetworkCommissioning::Id:
Clusters::NetworkCommissioning::DispatchClientCommand(apCommandObj, aCommandPath, aReader);
break;
case Clusters::OtaSoftwareUpdateProvider::Id:
Clusters::OtaSoftwareUpdateProvider::DispatchClientCommand(apCommandObj, aCommandPath, aReader);
break;
case Clusters::OperationalCredentials::Id:
Clusters::OperationalCredentials::DispatchClientCommand(apCommandObj, aCommandPath, aReader);
break;
case Clusters::Scenes::Id:
Clusters::Scenes::DispatchClientCommand(apCommandObj, aCommandPath, aReader);
break;
case Clusters::TargetNavigator::Id:
Clusters::TargetNavigator::DispatchClientCommand(apCommandObj, aCommandPath, aReader);
break;
case Clusters::TestCluster::Id:
Clusters::TestCluster::DispatchClientCommand(apCommandObj, aCommandPath, aReader);
break;
case Clusters::Thermostat::Id:
Clusters::Thermostat::DispatchClientCommand(apCommandObj, aCommandPath, aReader);
break;
default:
ChipLogError(Zcl, "Unknown cluster " ChipLogFormatMEI, ChipLogValueMEI(aCommandPath.mClusterId));
break;
}
exit:
aReader.ExitContainer(dataTlvType);
Compatibility::ResetEmberAfObjects();
}
} // namespace app
} // namespace chip