blob: 2e990ae8e4204a88dfcf43884a0fcbc59b7769b8 [file] [log] [blame]
/*
*
* Copyright (c) 2021 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// THIS FILE IS GENERATED BY ZAP
#include <cinttypes>
#include <cstdint>
#include "app/common/gen/af-structs.h"
#include "app/common/gen/cluster-id.h"
#include "app/common/gen/command-id.h"
#include "app/util/util.h"
#include "callback.h"
#include <app/InteractionModelEngine.h>
// Currently we need some work to keep compatible with ember lib.
#include <app/util/ember-compatibility-functions.h>
namespace chip {
namespace app {
// Cluster specific command parsing
namespace clusters {
namespace AccountLogin {
void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv)
{
// We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV
// When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error.
// Any error value TLVUnpackError means we have received an illegal value.
// The following variables are used for all commands to save code size.
CHIP_ERROR TLVError = CHIP_NO_ERROR;
CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
uint32_t validArgumentCount = 0;
uint32_t expectArgumentCount = 0;
uint32_t currentDecodeTagId = 0;
bool wasHandled = false;
{
switch (aCommandId)
{
case ZCL_GET_SETUP_PIN_RESPONSE_COMMAND_ID: {
expectArgumentCount = 1;
const uint8_t * 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:
// TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
TLVUnpackError = aDataTlv.GetDataPtr(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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfAccountLoginClusterGetSetupPINResponseCallback(apCommandObj, const_cast<uint8_t *>(setupPIN));
}
break;
}
default: {
// Unrecognized command ID, error status will apply.
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_ACCOUNT_LOGIN_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
Protocols::SecureChannel::Id,
Protocols::InteractionModel::ProtocolCode::UnsupportedCommand);
ChipLogError(Zcl, "Unknown command %" PRIx32 " for cluster %" PRIx32, aCommandId, ZCL_ACCOUNT_LOGIN_CLUSTER_ID);
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_ACCOUNT_LOGIN_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand);
ChipLogProgress(Zcl,
"Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" PRIu32
", UnpackError=%" PRIu32 " (last decoded tag = %" PRIu32,
validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
}
}
} // namespace AccountLogin
namespace ApplicationLauncher {
void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv)
{
// We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV
// When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error.
// Any error value TLVUnpackError means we have received an illegal value.
// The following variables are used for all commands to save code size.
CHIP_ERROR TLVError = CHIP_NO_ERROR;
CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
uint32_t validArgumentCount = 0;
uint32_t expectArgumentCount = 0;
uint32_t currentDecodeTagId = 0;
bool wasHandled = false;
{
switch (aCommandId)
{
case ZCL_LAUNCH_APP_RESPONSE_COMMAND_ID: {
expectArgumentCount = 2;
uint8_t status;
const uint8_t * 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:
// TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
TLVUnpackError = aDataTlv.GetDataPtr(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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled =
emberAfApplicationLauncherClusterLaunchAppResponseCallback(apCommandObj, status, const_cast<uint8_t *>(data));
}
break;
}
default: {
// Unrecognized command ID, error status will apply.
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_APPLICATION_LAUNCHER_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
Protocols::SecureChannel::Id,
Protocols::InteractionModel::ProtocolCode::UnsupportedCommand);
ChipLogError(Zcl, "Unknown command %" PRIx32 " for cluster %" PRIx32, aCommandId, ZCL_APPLICATION_LAUNCHER_CLUSTER_ID);
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_APPLICATION_LAUNCHER_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand);
ChipLogProgress(Zcl,
"Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" PRIu32
", UnpackError=%" PRIu32 " (last decoded tag = %" PRIu32,
validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
}
}
} // namespace ApplicationLauncher
namespace ContentLauncher {
void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv)
{
// We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV
// When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error.
// Any error value TLVUnpackError means we have received an illegal value.
// The following variables are used for all commands to save code size.
CHIP_ERROR TLVError = CHIP_NO_ERROR;
CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
uint32_t validArgumentCount = 0;
uint32_t expectArgumentCount = 0;
uint32_t currentDecodeTagId = 0;
bool wasHandled = false;
{
switch (aCommandId)
{
case ZCL_LAUNCH_CONTENT_RESPONSE_COMMAND_ID: {
expectArgumentCount = 2;
const uint8_t * data;
uint8_t contentLaunchStatus;
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:
// TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
TLVUnpackError = aDataTlv.GetDataPtr(data);
break;
case 1:
TLVUnpackError = aDataTlv.Get(contentLaunchStatus);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfContentLauncherClusterLaunchContentResponseCallback(apCommandObj, const_cast<uint8_t *>(data),
contentLaunchStatus);
}
break;
}
case ZCL_LAUNCH_URL_RESPONSE_COMMAND_ID: {
expectArgumentCount = 2;
const uint8_t * data;
uint8_t contentLaunchStatus;
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:
// TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
TLVUnpackError = aDataTlv.GetDataPtr(data);
break;
case 1:
TLVUnpackError = aDataTlv.Get(contentLaunchStatus);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfContentLauncherClusterLaunchURLResponseCallback(apCommandObj, const_cast<uint8_t *>(data),
contentLaunchStatus);
}
break;
}
default: {
// Unrecognized command ID, error status will apply.
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_CONTENT_LAUNCH_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
Protocols::SecureChannel::Id,
Protocols::InteractionModel::ProtocolCode::UnsupportedCommand);
ChipLogError(Zcl, "Unknown command %" PRIx32 " for cluster %" PRIx32, aCommandId, ZCL_CONTENT_LAUNCH_CLUSTER_ID);
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_CONTENT_LAUNCH_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand);
ChipLogProgress(Zcl,
"Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" PRIu32
", UnpackError=%" PRIu32 " (last decoded tag = %" PRIu32,
validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
}
}
} // namespace ContentLauncher
namespace DoorLock {
void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv)
{
// We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV
// When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error.
// Any error value TLVUnpackError means we have received an illegal value.
// The following variables are used for all commands to save code size.
CHIP_ERROR TLVError = CHIP_NO_ERROR;
CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
uint32_t validArgumentCount = 0;
uint32_t expectArgumentCount = 0;
uint32_t currentDecodeTagId = 0;
bool wasHandled = false;
{
switch (aCommandId)
{
case ZCL_CLEAR_ALL_PINS_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfDoorLockClusterClearAllPinsResponseCallback(apCommandObj, status);
}
break;
}
case ZCL_CLEAR_ALL_RFIDS_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfDoorLockClusterClearAllRfidsResponseCallback(apCommandObj, status);
}
break;
}
case ZCL_CLEAR_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfDoorLockClusterClearHolidayScheduleResponseCallback(apCommandObj, status);
}
break;
}
case ZCL_CLEAR_PIN_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfDoorLockClusterClearPinResponseCallback(apCommandObj, status);
}
break;
}
case ZCL_CLEAR_RFID_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfDoorLockClusterClearRfidResponseCallback(apCommandObj, status);
}
break;
}
case ZCL_CLEAR_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfDoorLockClusterClearWeekdayScheduleResponseCallback(apCommandObj, status);
}
break;
}
case ZCL_CLEAR_YEARDAY_SCHEDULE_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfDoorLockClusterClearYeardayScheduleResponseCallback(apCommandObj, status);
}
break;
}
case ZCL_GET_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_ID: {
expectArgumentCount = 5;
uint8_t scheduleId;
uint8_t status;
uint32_t localStartTime;
uint32_t localEndTime;
uint8_t operatingModeDuringHoliday;
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(scheduleId);
break;
case 1:
TLVUnpackError = aDataTlv.Get(status);
break;
case 2:
TLVUnpackError = aDataTlv.Get(localStartTime);
break;
case 3:
TLVUnpackError = aDataTlv.Get(localEndTime);
break;
case 4:
TLVUnpackError = aDataTlv.Get(operatingModeDuringHoliday);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfDoorLockClusterGetHolidayScheduleResponseCallback(
apCommandObj, scheduleId, status, localStartTime, localEndTime, operatingModeDuringHoliday);
}
break;
}
case ZCL_GET_LOG_RECORD_RESPONSE_COMMAND_ID: {
expectArgumentCount = 7;
uint16_t logEntryId;
uint32_t timestamp;
uint8_t eventType;
uint8_t source;
uint8_t eventIdOrAlarmCode;
uint16_t userId;
const uint8_t * pin;
bool argExists[7];
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 < 7)
{
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(logEntryId);
break;
case 1:
TLVUnpackError = aDataTlv.Get(timestamp);
break;
case 2:
TLVUnpackError = aDataTlv.Get(eventType);
break;
case 3:
TLVUnpackError = aDataTlv.Get(source);
break;
case 4:
TLVUnpackError = aDataTlv.Get(eventIdOrAlarmCode);
break;
case 5:
TLVUnpackError = aDataTlv.Get(userId);
break;
case 6:
// TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
TLVUnpackError = aDataTlv.GetDataPtr(pin);
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 && 7 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfDoorLockClusterGetLogRecordResponseCallback(
apCommandObj, logEntryId, timestamp, eventType, source, eventIdOrAlarmCode, userId, const_cast<uint8_t *>(pin));
}
break;
}
case ZCL_GET_PIN_RESPONSE_COMMAND_ID: {
expectArgumentCount = 4;
uint16_t userId;
uint8_t userStatus;
uint8_t userType;
const uint8_t * pin;
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(userId);
break;
case 1:
TLVUnpackError = aDataTlv.Get(userStatus);
break;
case 2:
TLVUnpackError = aDataTlv.Get(userType);
break;
case 3:
// TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
TLVUnpackError = aDataTlv.GetDataPtr(pin);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfDoorLockClusterGetPinResponseCallback(apCommandObj, userId, userStatus, userType,
const_cast<uint8_t *>(pin));
}
break;
}
case ZCL_GET_RFID_RESPONSE_COMMAND_ID: {
expectArgumentCount = 4;
uint16_t userId;
uint8_t userStatus;
uint8_t userType;
const uint8_t * rfid;
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(userId);
break;
case 1:
TLVUnpackError = aDataTlv.Get(userStatus);
break;
case 2:
TLVUnpackError = aDataTlv.Get(userType);
break;
case 3:
// TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
TLVUnpackError = aDataTlv.GetDataPtr(rfid);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 4 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfDoorLockClusterGetRfidResponseCallback(apCommandObj, userId, userStatus, userType,
const_cast<uint8_t *>(rfid));
}
break;
}
case ZCL_GET_USER_TYPE_RESPONSE_COMMAND_ID: {
expectArgumentCount = 2;
uint16_t userId;
uint8_t userType;
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(userId);
break;
case 1:
TLVUnpackError = aDataTlv.Get(userType);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 2 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfDoorLockClusterGetUserTypeResponseCallback(apCommandObj, userId, userType);
}
break;
}
case ZCL_GET_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_ID: {
expectArgumentCount = 8;
uint8_t scheduleId;
uint16_t userId;
uint8_t status;
uint8_t daysMask;
uint8_t startHour;
uint8_t startMinute;
uint8_t endHour;
uint8_t endMinute;
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(scheduleId);
break;
case 1:
TLVUnpackError = aDataTlv.Get(userId);
break;
case 2:
TLVUnpackError = aDataTlv.Get(status);
break;
case 3:
TLVUnpackError = aDataTlv.Get(daysMask);
break;
case 4:
TLVUnpackError = aDataTlv.Get(startHour);
break;
case 5:
TLVUnpackError = aDataTlv.Get(startMinute);
break;
case 6:
TLVUnpackError = aDataTlv.Get(endHour);
break;
case 7:
TLVUnpackError = aDataTlv.Get(endMinute);
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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfDoorLockClusterGetWeekdayScheduleResponseCallback(
apCommandObj, scheduleId, userId, status, daysMask, startHour, startMinute, endHour, endMinute);
}
break;
}
case ZCL_GET_YEARDAY_SCHEDULE_RESPONSE_COMMAND_ID: {
expectArgumentCount = 5;
uint8_t scheduleId;
uint16_t userId;
uint8_t status;
uint32_t localStartTime;
uint32_t localEndTime;
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(scheduleId);
break;
case 1:
TLVUnpackError = aDataTlv.Get(userId);
break;
case 2:
TLVUnpackError = aDataTlv.Get(status);
break;
case 3:
TLVUnpackError = aDataTlv.Get(localStartTime);
break;
case 4:
TLVUnpackError = aDataTlv.Get(localEndTime);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 5 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfDoorLockClusterGetYeardayScheduleResponseCallback(apCommandObj, scheduleId, userId, status,
localStartTime, localEndTime);
}
break;
}
case ZCL_LOCK_DOOR_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfDoorLockClusterLockDoorResponseCallback(apCommandObj, status);
}
break;
}
case ZCL_SET_HOLIDAY_SCHEDULE_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfDoorLockClusterSetHolidayScheduleResponseCallback(apCommandObj, status);
}
break;
}
case ZCL_SET_PIN_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfDoorLockClusterSetPinResponseCallback(apCommandObj, status);
}
break;
}
case ZCL_SET_RFID_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfDoorLockClusterSetRfidResponseCallback(apCommandObj, status);
}
break;
}
case ZCL_SET_USER_TYPE_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfDoorLockClusterSetUserTypeResponseCallback(apCommandObj, status);
}
break;
}
case ZCL_SET_WEEKDAY_SCHEDULE_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfDoorLockClusterSetWeekdayScheduleResponseCallback(apCommandObj, status);
}
break;
}
case ZCL_SET_YEARDAY_SCHEDULE_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfDoorLockClusterSetYeardayScheduleResponseCallback(apCommandObj, status);
}
break;
}
case ZCL_UNLOCK_DOOR_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfDoorLockClusterUnlockDoorResponseCallback(apCommandObj, status);
}
break;
}
case ZCL_UNLOCK_WITH_TIMEOUT_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfDoorLockClusterUnlockWithTimeoutResponseCallback(apCommandObj, status);
}
break;
}
default: {
// Unrecognized command ID, error status will apply.
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_DOOR_LOCK_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
Protocols::SecureChannel::Id,
Protocols::InteractionModel::ProtocolCode::UnsupportedCommand);
ChipLogError(Zcl, "Unknown command %" PRIx32 " for cluster %" PRIx32, aCommandId, ZCL_DOOR_LOCK_CLUSTER_ID);
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_DOOR_LOCK_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand);
ChipLogProgress(Zcl,
"Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" PRIu32
", UnpackError=%" PRIu32 " (last decoded tag = %" PRIu32,
validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
}
}
} // namespace DoorLock
namespace GeneralCommissioning {
void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv)
{
// We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV
// When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error.
// Any error value TLVUnpackError means we have received an illegal value.
// The following variables are used for all commands to save code size.
CHIP_ERROR TLVError = CHIP_NO_ERROR;
CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
uint32_t validArgumentCount = 0;
uint32_t expectArgumentCount = 0;
uint32_t currentDecodeTagId = 0;
bool wasHandled = false;
{
switch (aCommandId)
{
case ZCL_ARM_FAIL_SAFE_RESPONSE_COMMAND_ID: {
expectArgumentCount = 2;
uint8_t errorCode;
const uint8_t * 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:
// TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
TLVUnpackError = aDataTlv.GetDataPtr(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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfGeneralCommissioningClusterArmFailSafeResponseCallback(apCommandObj, errorCode,
const_cast<uint8_t *>(debugText));
}
break;
}
case ZCL_COMMISSIONING_COMPLETE_RESPONSE_COMMAND_ID: {
expectArgumentCount = 2;
uint8_t errorCode;
const uint8_t * 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:
// TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
TLVUnpackError = aDataTlv.GetDataPtr(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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteResponseCallback(
apCommandObj, errorCode, const_cast<uint8_t *>(debugText));
}
break;
}
case ZCL_SET_REGULATORY_CONFIG_RESPONSE_COMMAND_ID: {
expectArgumentCount = 2;
uint8_t errorCode;
const uint8_t * 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:
// TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
TLVUnpackError = aDataTlv.GetDataPtr(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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigResponseCallback(
apCommandObj, errorCode, const_cast<uint8_t *>(debugText));
}
break;
}
default: {
// Unrecognized command ID, error status will apply.
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_GENERAL_COMMISSIONING_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
Protocols::SecureChannel::Id,
Protocols::InteractionModel::ProtocolCode::UnsupportedCommand);
ChipLogError(Zcl, "Unknown command %" PRIx32 " for cluster %" PRIx32, aCommandId, ZCL_GENERAL_COMMISSIONING_CLUSTER_ID);
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_GENERAL_COMMISSIONING_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand);
ChipLogProgress(Zcl,
"Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" PRIu32
", UnpackError=%" PRIu32 " (last decoded tag = %" PRIu32,
validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
}
}
} // namespace GeneralCommissioning
namespace Groups {
void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv)
{
// We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV
// When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error.
// Any error value TLVUnpackError means we have received an illegal value.
// The following variables are used for all commands to save code size.
CHIP_ERROR TLVError = CHIP_NO_ERROR;
CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
uint32_t validArgumentCount = 0;
uint32_t expectArgumentCount = 0;
uint32_t currentDecodeTagId = 0;
bool wasHandled = false;
{
switch (aCommandId)
{
case ZCL_ADD_GROUP_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfGroupsClusterAddGroupResponseCallback(apCommandObj, status, groupId);
}
break;
}
case ZCL_GET_GROUP_MEMBERSHIP_RESPONSE_COMMAND_ID: {
expectArgumentCount = 3;
uint8_t capacity;
uint8_t groupCount;
/* TYPE WARNING: array array defaults to */ uint8_t * groupList;
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(capacity);
break;
case 1:
TLVUnpackError = aDataTlv.Get(groupCount);
break;
case 2:
// 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 && 3 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfGroupsClusterGetGroupMembershipResponseCallback(apCommandObj, capacity, groupCount, groupList);
}
break;
}
case ZCL_REMOVE_GROUP_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfGroupsClusterRemoveGroupResponseCallback(apCommandObj, status, groupId);
}
break;
}
case ZCL_VIEW_GROUP_RESPONSE_COMMAND_ID: {
expectArgumentCount = 3;
uint8_t status;
uint16_t groupId;
const uint8_t * 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:
// TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
TLVUnpackError = aDataTlv.GetDataPtr(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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled =
emberAfGroupsClusterViewGroupResponseCallback(apCommandObj, status, groupId, const_cast<uint8_t *>(groupName));
}
break;
}
default: {
// Unrecognized command ID, error status will apply.
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_GROUPS_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
Protocols::SecureChannel::Id,
Protocols::InteractionModel::ProtocolCode::UnsupportedCommand);
ChipLogError(Zcl, "Unknown command %" PRIx32 " for cluster %" PRIx32, aCommandId, ZCL_GROUPS_CLUSTER_ID);
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_GROUPS_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand);
ChipLogProgress(Zcl,
"Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" PRIu32
", UnpackError=%" PRIu32 " (last decoded tag = %" PRIu32,
validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
}
}
} // namespace Groups
namespace Identify {
void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv)
{
// We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV
// When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error.
// Any error value TLVUnpackError means we have received an illegal value.
// The following variables are used for all commands to save code size.
CHIP_ERROR TLVError = CHIP_NO_ERROR;
CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
uint32_t validArgumentCount = 0;
uint32_t expectArgumentCount = 0;
uint32_t currentDecodeTagId = 0;
bool wasHandled = false;
{
switch (aCommandId)
{
case ZCL_IDENTIFY_QUERY_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfIdentifyClusterIdentifyQueryResponseCallback(apCommandObj, timeout);
}
break;
}
default: {
// Unrecognized command ID, error status will apply.
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_IDENTIFY_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
Protocols::SecureChannel::Id,
Protocols::InteractionModel::ProtocolCode::UnsupportedCommand);
ChipLogError(Zcl, "Unknown command %" PRIx32 " for cluster %" PRIx32, aCommandId, ZCL_IDENTIFY_CLUSTER_ID);
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_IDENTIFY_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand);
ChipLogProgress(Zcl,
"Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" PRIu32
", UnpackError=%" PRIu32 " (last decoded tag = %" PRIu32,
validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
}
}
} // namespace Identify
namespace KeypadInput {
void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv)
{
// We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV
// When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error.
// Any error value TLVUnpackError means we have received an illegal value.
// The following variables are used for all commands to save code size.
CHIP_ERROR TLVError = CHIP_NO_ERROR;
CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
uint32_t validArgumentCount = 0;
uint32_t expectArgumentCount = 0;
uint32_t currentDecodeTagId = 0;
bool wasHandled = false;
{
switch (aCommandId)
{
case ZCL_SEND_KEY_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfKeypadInputClusterSendKeyResponseCallback(apCommandObj, status);
}
break;
}
default: {
// Unrecognized command ID, error status will apply.
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_KEYPAD_INPUT_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
Protocols::SecureChannel::Id,
Protocols::InteractionModel::ProtocolCode::UnsupportedCommand);
ChipLogError(Zcl, "Unknown command %" PRIx32 " for cluster %" PRIx32, aCommandId, ZCL_KEYPAD_INPUT_CLUSTER_ID);
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_KEYPAD_INPUT_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand);
ChipLogProgress(Zcl,
"Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" PRIu32
", UnpackError=%" PRIu32 " (last decoded tag = %" PRIu32,
validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
}
}
} // namespace KeypadInput
namespace MediaPlayback {
void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv)
{
// We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV
// When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error.
// Any error value TLVUnpackError means we have received an illegal value.
// The following variables are used for all commands to save code size.
CHIP_ERROR TLVError = CHIP_NO_ERROR;
CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
uint32_t validArgumentCount = 0;
uint32_t expectArgumentCount = 0;
uint32_t currentDecodeTagId = 0;
bool wasHandled = false;
{
switch (aCommandId)
{
case ZCL_MEDIA_FAST_FORWARD_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfMediaPlaybackClusterMediaFastForwardResponseCallback(apCommandObj, mediaPlaybackStatus);
}
break;
}
case ZCL_MEDIA_NEXT_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfMediaPlaybackClusterMediaNextResponseCallback(apCommandObj, mediaPlaybackStatus);
}
break;
}
case ZCL_MEDIA_PAUSE_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfMediaPlaybackClusterMediaPauseResponseCallback(apCommandObj, mediaPlaybackStatus);
}
break;
}
case ZCL_MEDIA_PLAY_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfMediaPlaybackClusterMediaPlayResponseCallback(apCommandObj, mediaPlaybackStatus);
}
break;
}
case ZCL_MEDIA_PREVIOUS_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfMediaPlaybackClusterMediaPreviousResponseCallback(apCommandObj, mediaPlaybackStatus);
}
break;
}
case ZCL_MEDIA_REWIND_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfMediaPlaybackClusterMediaRewindResponseCallback(apCommandObj, mediaPlaybackStatus);
}
break;
}
case ZCL_MEDIA_SKIP_BACKWARD_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfMediaPlaybackClusterMediaSkipBackwardResponseCallback(apCommandObj, mediaPlaybackStatus);
}
break;
}
case ZCL_MEDIA_SKIP_FORWARD_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfMediaPlaybackClusterMediaSkipForwardResponseCallback(apCommandObj, mediaPlaybackStatus);
}
break;
}
case ZCL_MEDIA_SKIP_SEEK_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfMediaPlaybackClusterMediaSkipSeekResponseCallback(apCommandObj, mediaPlaybackStatus);
}
break;
}
case ZCL_MEDIA_START_OVER_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfMediaPlaybackClusterMediaStartOverResponseCallback(apCommandObj, mediaPlaybackStatus);
}
break;
}
case ZCL_MEDIA_STOP_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfMediaPlaybackClusterMediaStopResponseCallback(apCommandObj, mediaPlaybackStatus);
}
break;
}
default: {
// Unrecognized command ID, error status will apply.
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_MEDIA_PLAYBACK_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
Protocols::SecureChannel::Id,
Protocols::InteractionModel::ProtocolCode::UnsupportedCommand);
ChipLogError(Zcl, "Unknown command %" PRIx32 " for cluster %" PRIx32, aCommandId, ZCL_MEDIA_PLAYBACK_CLUSTER_ID);
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_MEDIA_PLAYBACK_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand);
ChipLogProgress(Zcl,
"Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" PRIu32
", UnpackError=%" PRIu32 " (last decoded tag = %" PRIu32,
validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
}
}
} // namespace MediaPlayback
namespace NetworkCommissioning {
void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv)
{
// We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV
// When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error.
// Any error value TLVUnpackError means we have received an illegal value.
// The following variables are used for all commands to save code size.
CHIP_ERROR TLVError = CHIP_NO_ERROR;
CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
uint32_t validArgumentCount = 0;
uint32_t expectArgumentCount = 0;
uint32_t currentDecodeTagId = 0;
bool wasHandled = false;
{
switch (aCommandId)
{
case ZCL_ADD_THREAD_NETWORK_RESPONSE_COMMAND_ID: {
expectArgumentCount = 2;
uint8_t errorCode;
const uint8_t * 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:
// TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
TLVUnpackError = aDataTlv.GetDataPtr(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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfNetworkCommissioningClusterAddThreadNetworkResponseCallback(apCommandObj, errorCode,
const_cast<uint8_t *>(debugText));
}
break;
}
case ZCL_ADD_WI_FI_NETWORK_RESPONSE_COMMAND_ID: {
expectArgumentCount = 2;
uint8_t errorCode;
const uint8_t * 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:
// TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
TLVUnpackError = aDataTlv.GetDataPtr(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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfNetworkCommissioningClusterAddWiFiNetworkResponseCallback(apCommandObj, errorCode,
const_cast<uint8_t *>(debugText));
}
break;
}
case ZCL_DISABLE_NETWORK_RESPONSE_COMMAND_ID: {
expectArgumentCount = 2;
uint8_t errorCode;
const uint8_t * 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:
// TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
TLVUnpackError = aDataTlv.GetDataPtr(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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfNetworkCommissioningClusterDisableNetworkResponseCallback(apCommandObj, errorCode,
const_cast<uint8_t *>(debugText));
}
break;
}
case ZCL_ENABLE_NETWORK_RESPONSE_COMMAND_ID: {
expectArgumentCount = 2;
uint8_t errorCode;
const uint8_t * 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:
// TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
TLVUnpackError = aDataTlv.GetDataPtr(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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfNetworkCommissioningClusterEnableNetworkResponseCallback(apCommandObj, errorCode,
const_cast<uint8_t *>(debugText));
}
break;
}
case ZCL_REMOVE_NETWORK_RESPONSE_COMMAND_ID: {
expectArgumentCount = 2;
uint8_t errorCode;
const uint8_t * 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:
// TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
TLVUnpackError = aDataTlv.GetDataPtr(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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfNetworkCommissioningClusterRemoveNetworkResponseCallback(apCommandObj, errorCode,
const_cast<uint8_t *>(debugText));
}
break;
}
case ZCL_SCAN_NETWORKS_RESPONSE_COMMAND_ID: {
expectArgumentCount = 4;
uint8_t errorCode;
const uint8_t * 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(errorCode);
break;
case 1:
// TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
TLVUnpackError = aDataTlv.GetDataPtr(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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfNetworkCommissioningClusterScanNetworksResponseCallback(
apCommandObj, errorCode, const_cast<uint8_t *>(debugText), wifiScanResults, threadScanResults);
}
break;
}
case ZCL_UPDATE_THREAD_NETWORK_RESPONSE_COMMAND_ID: {
expectArgumentCount = 2;
uint8_t errorCode;
const uint8_t * 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:
// TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
TLVUnpackError = aDataTlv.GetDataPtr(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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfNetworkCommissioningClusterUpdateThreadNetworkResponseCallback(
apCommandObj, errorCode, const_cast<uint8_t *>(debugText));
}
break;
}
case ZCL_UPDATE_WI_FI_NETWORK_RESPONSE_COMMAND_ID: {
expectArgumentCount = 2;
uint8_t errorCode;
const uint8_t * 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:
// TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
TLVUnpackError = aDataTlv.GetDataPtr(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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfNetworkCommissioningClusterUpdateWiFiNetworkResponseCallback(apCommandObj, errorCode,
const_cast<uint8_t *>(debugText));
}
break;
}
default: {
// Unrecognized command ID, error status will apply.
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_NETWORK_COMMISSIONING_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
Protocols::SecureChannel::Id,
Protocols::InteractionModel::ProtocolCode::UnsupportedCommand);
ChipLogError(Zcl, "Unknown command %" PRIx32 " for cluster %" PRIx32, aCommandId, ZCL_NETWORK_COMMISSIONING_CLUSTER_ID);
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_NETWORK_COMMISSIONING_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand);
ChipLogProgress(Zcl,
"Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" PRIu32
", UnpackError=%" PRIu32 " (last decoded tag = %" PRIu32,
validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
}
}
} // namespace NetworkCommissioning
namespace OtaSoftwareUpdateProvider {
void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv)
{
// We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV
// When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error.
// Any error value TLVUnpackError means we have received an illegal value.
// The following variables are used for all commands to save code size.
CHIP_ERROR TLVError = CHIP_NO_ERROR;
CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
uint32_t validArgumentCount = 0;
uint32_t expectArgumentCount = 0;
uint32_t currentDecodeTagId = 0;
bool wasHandled = false;
{
switch (aCommandId)
{
case ZCL_APPLY_UPDATE_REQUEST_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfOtaSoftwareUpdateProviderClusterApplyUpdateRequestResponseCallback(apCommandObj, action,
delayedActionTime);
}
break;
}
case ZCL_QUERY_IMAGE_RESPONSE_COMMAND_ID: {
expectArgumentCount = 7;
uint8_t status;
uint32_t delayedActionTime;
const uint8_t * imageURI;
uint32_t softwareVersion;
chip::ByteSpan updateToken;
uint8_t userConsentNeeded;
chip::ByteSpan metadataForRequestor;
bool argExists[7];
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 < 7)
{
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:
// TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
TLVUnpackError = aDataTlv.GetDataPtr(imageURI);
break;
case 3:
TLVUnpackError = aDataTlv.Get(softwareVersion);
break;
case 4: {
const uint8_t * data = nullptr;
TLVUnpackError = aDataTlv.GetDataPtr(data);
updateToken = chip::ByteSpan(data, aDataTlv.GetLength());
}
break;
case 5:
TLVUnpackError = aDataTlv.Get(userConsentNeeded);
break;
case 6: {
const uint8_t * data = nullptr;
TLVUnpackError = aDataTlv.GetDataPtr(data);
metadataForRequestor = chip::ByteSpan(data, aDataTlv.GetLength());
}
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 7 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfOtaSoftwareUpdateProviderClusterQueryImageResponseCallback(
apCommandObj, status, delayedActionTime, const_cast<uint8_t *>(imageURI), softwareVersion, updateToken,
userConsentNeeded, metadataForRequestor);
}
break;
}
default: {
// Unrecognized command ID, error status will apply.
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_OTA_PROVIDER_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
Protocols::SecureChannel::Id,
Protocols::InteractionModel::ProtocolCode::UnsupportedCommand);
ChipLogError(Zcl, "Unknown command %" PRIx32 " for cluster %" PRIx32, aCommandId, ZCL_OTA_PROVIDER_CLUSTER_ID);
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_OTA_PROVIDER_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand);
ChipLogProgress(Zcl,
"Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" PRIu32
", UnpackError=%" PRIu32 " (last decoded tag = %" PRIu32,
validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
}
}
} // namespace OtaSoftwareUpdateProvider
namespace OperationalCredentials {
void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv)
{
// We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV
// When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error.
// Any error value TLVUnpackError means we have received an illegal value.
// The following variables are used for all commands to save code size.
CHIP_ERROR TLVError = CHIP_NO_ERROR;
CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
uint32_t validArgumentCount = 0;
uint32_t expectArgumentCount = 0;
uint32_t currentDecodeTagId = 0;
bool wasHandled = false;
{
switch (aCommandId)
{
case ZCL_OP_CSR_RESPONSE_COMMAND_ID: {
expectArgumentCount = 6;
chip::ByteSpan CSR;
chip::ByteSpan CSRNonce;
chip::ByteSpan VendorReserved1;
chip::ByteSpan VendorReserved2;
chip::ByteSpan VendorReserved3;
chip::ByteSpan Signature;
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: {
const uint8_t * data = nullptr;
TLVUnpackError = aDataTlv.GetDataPtr(data);
CSR = chip::ByteSpan(data, aDataTlv.GetLength());
}
break;
case 1: {
const uint8_t * data = nullptr;
TLVUnpackError = aDataTlv.GetDataPtr(data);
CSRNonce = chip::ByteSpan(data, aDataTlv.GetLength());
}
break;
case 2: {
const uint8_t * data = nullptr;
TLVUnpackError = aDataTlv.GetDataPtr(data);
VendorReserved1 = chip::ByteSpan(data, aDataTlv.GetLength());
}
break;
case 3: {
const uint8_t * data = nullptr;
TLVUnpackError = aDataTlv.GetDataPtr(data);
VendorReserved2 = chip::ByteSpan(data, aDataTlv.GetLength());
}
break;
case 4: {
const uint8_t * data = nullptr;
TLVUnpackError = aDataTlv.GetDataPtr(data);
VendorReserved3 = chip::ByteSpan(data, aDataTlv.GetLength());
}
break;
case 5: {
const uint8_t * data = nullptr;
TLVUnpackError = aDataTlv.GetDataPtr(data);
Signature = chip::ByteSpan(data, aDataTlv.GetLength());
}
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfOperationalCredentialsClusterOpCSRResponseCallback(apCommandObj, CSR, CSRNonce, VendorReserved1,
VendorReserved2, VendorReserved3, Signature);
}
break;
}
case ZCL_OP_CERT_RESPONSE_COMMAND_ID: {
expectArgumentCount = 3;
uint8_t StatusCode;
uint64_t FabricIndex;
const uint8_t * 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:
// TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
TLVUnpackError = aDataTlv.GetDataPtr(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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfOperationalCredentialsClusterOpCertResponseCallback(apCommandObj, StatusCode, FabricIndex,
const_cast<uint8_t *>(DebugText));
}
break;
}
case ZCL_SET_FABRIC_RESPONSE_COMMAND_ID: {
expectArgumentCount = 1;
chip::FabricId FabricId;
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(FabricId);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}
if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfOperationalCredentialsClusterSetFabricResponseCallback(apCommandObj, FabricId);
}
break;
}
default: {
// Unrecognized command ID, error status will apply.
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_OPERATIONAL_CREDENTIALS_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
Protocols::SecureChannel::Id,
Protocols::InteractionModel::ProtocolCode::UnsupportedCommand);
ChipLogError(Zcl, "Unknown command %" PRIx32 " for cluster %" PRIx32, aCommandId,
ZCL_OPERATIONAL_CREDENTIALS_CLUSTER_ID);
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_OPERATIONAL_CREDENTIALS_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand);
ChipLogProgress(Zcl,
"Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" PRIu32
", UnpackError=%" PRIu32 " (last decoded tag = %" PRIu32,
validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
}
}
} // namespace OperationalCredentials
namespace Scenes {
void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv)
{
// We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV
// When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error.
// Any error value TLVUnpackError means we have received an illegal value.
// The following variables are used for all commands to save code size.
CHIP_ERROR TLVError = CHIP_NO_ERROR;
CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
uint32_t validArgumentCount = 0;
uint32_t expectArgumentCount = 0;
uint32_t currentDecodeTagId = 0;
bool wasHandled = false;
{
switch (aCommandId)
{
case ZCL_ADD_SCENE_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfScenesClusterAddSceneResponseCallback(apCommandObj, status, groupId, sceneId);
}
break;
}
case ZCL_GET_SCENE_MEMBERSHIP_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfScenesClusterGetSceneMembershipResponseCallback(apCommandObj, status, capacity, groupId,
sceneCount, sceneList);
}
break;
}
case ZCL_REMOVE_ALL_SCENES_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfScenesClusterRemoveAllScenesResponseCallback(apCommandObj, status, groupId);
}
break;
}
case ZCL_REMOVE_SCENE_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfScenesClusterRemoveSceneResponseCallback(apCommandObj, status, groupId, sceneId);
}
break;
}
case ZCL_STORE_SCENE_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfScenesClusterStoreSceneResponseCallback(apCommandObj, status, groupId, sceneId);
}
break;
}
case ZCL_VIEW_SCENE_RESPONSE_COMMAND_ID: {
expectArgumentCount = 6;
uint8_t status;
uint16_t groupId;
uint8_t sceneId;
uint16_t transitionTime;
const uint8_t * 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:
// TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
TLVUnpackError = aDataTlv.GetDataPtr(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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfScenesClusterViewSceneResponseCallback(apCommandObj, status, groupId, sceneId, transitionTime,
const_cast<uint8_t *>(sceneName), extensionFieldSets);
}
break;
}
default: {
// Unrecognized command ID, error status will apply.
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_SCENES_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
Protocols::SecureChannel::Id,
Protocols::InteractionModel::ProtocolCode::UnsupportedCommand);
ChipLogError(Zcl, "Unknown command %" PRIx32 " for cluster %" PRIx32, aCommandId, ZCL_SCENES_CLUSTER_ID);
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_SCENES_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand);
ChipLogProgress(Zcl,
"Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" PRIu32
", UnpackError=%" PRIu32 " (last decoded tag = %" PRIu32,
validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
}
}
} // namespace Scenes
namespace TvChannel {
void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv)
{
// We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV
// When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error.
// Any error value TLVUnpackError means we have received an illegal value.
// The following variables are used for all commands to save code size.
CHIP_ERROR TLVError = CHIP_NO_ERROR;
CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
uint32_t validArgumentCount = 0;
uint32_t expectArgumentCount = 0;
uint32_t currentDecodeTagId = 0;
bool wasHandled = false;
{
switch (aCommandId)
{
case ZCL_CHANGE_CHANNEL_RESPONSE_COMMAND_ID: {
expectArgumentCount = 2;
/* TYPE WARNING: array array defaults to */ uint8_t * 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:
// Just for compatibility, we will add array type support in IM later.
TLVUnpackError = aDataTlv.GetDataPtr(const_cast<const uint8_t *&>(ChannelMatch));
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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfTvChannelClusterChangeChannelResponseCallback(apCommandObj, ChannelMatch, ErrorType);
}
break;
}
default: {
// Unrecognized command ID, error status will apply.
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_TV_CHANNEL_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
Protocols::SecureChannel::Id,
Protocols::InteractionModel::ProtocolCode::UnsupportedCommand);
ChipLogError(Zcl, "Unknown command %" PRIx32 " for cluster %" PRIx32, aCommandId, ZCL_TV_CHANNEL_CLUSTER_ID);
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_TV_CHANNEL_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand);
ChipLogProgress(Zcl,
"Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" PRIu32
", UnpackError=%" PRIu32 " (last decoded tag = %" PRIu32,
validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
}
}
} // namespace TvChannel
namespace TargetNavigator {
void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv)
{
// We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV
// When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error.
// Any error value TLVUnpackError means we have received an illegal value.
// The following variables are used for all commands to save code size.
CHIP_ERROR TLVError = CHIP_NO_ERROR;
CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
uint32_t validArgumentCount = 0;
uint32_t expectArgumentCount = 0;
uint32_t currentDecodeTagId = 0;
bool wasHandled = false;
{
switch (aCommandId)
{
case ZCL_NAVIGATE_TARGET_RESPONSE_COMMAND_ID: {
expectArgumentCount = 2;
uint8_t status;
const uint8_t * 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:
// TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
TLVUnpackError = aDataTlv.GetDataPtr(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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled =
emberAfTargetNavigatorClusterNavigateTargetResponseCallback(apCommandObj, status, const_cast<uint8_t *>(data));
}
break;
}
default: {
// Unrecognized command ID, error status will apply.
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_TARGET_NAVIGATOR_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
Protocols::SecureChannel::Id,
Protocols::InteractionModel::ProtocolCode::UnsupportedCommand);
ChipLogError(Zcl, "Unknown command %" PRIx32 " for cluster %" PRIx32, aCommandId, ZCL_TARGET_NAVIGATOR_CLUSTER_ID);
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_TARGET_NAVIGATOR_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand);
ChipLogProgress(Zcl,
"Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" PRIu32
", UnpackError=%" PRIu32 " (last decoded tag = %" PRIu32,
validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
}
}
} // namespace TargetNavigator
namespace TestCluster {
void DispatchClientCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv)
{
// We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV
// When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error.
// Any error value TLVUnpackError means we have received an illegal value.
// The following variables are used for all commands to save code size.
CHIP_ERROR TLVError = CHIP_NO_ERROR;
CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
uint32_t validArgumentCount = 0;
uint32_t expectArgumentCount = 0;
uint32_t currentDecodeTagId = 0;
bool wasHandled = false;
{
switch (aCommandId)
{
case ZCL_TEST_SPECIFIC_RESPONSE_COMMAND_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)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
wasHandled = emberAfTestClusterClusterTestSpecificResponseCallback(apCommandObj, returnValue);
}
break;
}
default: {
// Unrecognized command ID, error status will apply.
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_TEST_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
Protocols::SecureChannel::Id,
Protocols::InteractionModel::ProtocolCode::UnsupportedCommand);
ChipLogError(Zcl, "Unknown command %" PRIx32 " for cluster %" PRIx32, aCommandId, ZCL_TEST_CLUSTER_ID);
return;
}
}
}
if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
ZCL_TEST_CLUSTER_ID, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand);
ChipLogProgress(Zcl,
"Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" PRIu32
", UnpackError=%" PRIu32 " (last decoded tag = %" PRIu32,
validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId);
}
}
} // namespace TestCluster
} // namespace clusters
void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aCommandId, chip::EndpointId aEndPointId,
chip::TLV::TLVReader & aReader, Command * apCommandObj)
{
ChipLogDetail(Zcl, "Received Cluster Command: Cluster=%" PRIx32 " Command=%" PRIx32 " Endpoint=%" PRIx16, aClusterId,
aCommandId, aEndPointId);
Compatibility::SetupEmberAfObjects(apCommandObj, aClusterId, aCommandId, aEndPointId);
TLV::TLVType dataTlvType;
SuccessOrExit(aReader.EnterContainer(dataTlvType));
switch (aClusterId)
{
case ZCL_ACCOUNT_LOGIN_CLUSTER_ID:
clusters::AccountLogin::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
break;
case ZCL_APPLICATION_LAUNCHER_CLUSTER_ID:
clusters::ApplicationLauncher::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
break;
case ZCL_CONTENT_LAUNCH_CLUSTER_ID:
clusters::ContentLauncher::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
break;
case ZCL_DOOR_LOCK_CLUSTER_ID:
clusters::DoorLock::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
break;
case ZCL_GENERAL_COMMISSIONING_CLUSTER_ID:
clusters::GeneralCommissioning::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
break;
case ZCL_GROUPS_CLUSTER_ID:
clusters::Groups::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
break;
case ZCL_IDENTIFY_CLUSTER_ID:
clusters::Identify::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
break;
case ZCL_KEYPAD_INPUT_CLUSTER_ID:
clusters::KeypadInput::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
break;
case ZCL_MEDIA_PLAYBACK_CLUSTER_ID:
clusters::MediaPlayback::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
break;
case ZCL_NETWORK_COMMISSIONING_CLUSTER_ID:
clusters::NetworkCommissioning::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
break;
case ZCL_OTA_PROVIDER_CLUSTER_ID:
clusters::OtaSoftwareUpdateProvider::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
break;
case ZCL_OPERATIONAL_CREDENTIALS_CLUSTER_ID:
clusters::OperationalCredentials::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
break;
case ZCL_SCENES_CLUSTER_ID:
clusters::Scenes::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
break;
case ZCL_TV_CHANNEL_CLUSTER_ID:
clusters::TvChannel::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
break;
case ZCL_TARGET_NAVIGATOR_CLUSTER_ID:
clusters::TargetNavigator::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
break;
case ZCL_TEST_CLUSTER_ID:
clusters::TestCluster::DispatchClientCommand(apCommandObj, aCommandId, aEndPointId, aReader);
break;
default:
// Unrecognized cluster ID, error status will apply.
chip::app::CommandPathParams returnStatusParam = { aEndPointId,
0, // GroupId
aClusterId, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand);
ChipLogError(Zcl, "Unknown cluster %" PRIx32, aClusterId);
break;
}
exit:
Compatibility::ResetEmberAfObjects();
aReader.ExitContainer(dataTlvType);
}
} // namespace app
} // namespace chip